packages feed

clash-prelude 0.5 → 0.5.0.1

raw patch · 9 files changed

+383/−80 lines, 9 files

Files

README.md view
@@ -1,2 +1,2 @@ = WARNING =-Only works with GHC-7.8 (http://www.haskell.org/ghc/dist/7.8.1-rc2/)!+Only works with GHC-7.8.* (http://www.haskell.org/ghc/download_ghc_7_8_2)!
clash-prelude.cabal view
@@ -1,5 +1,5 @@ Name:                 clash-prelude-Version:              0.5+Version:              0.5.0.1 Synopsis:             CAES Language for Synchronous Hardware - Prelude library Description:   CλaSH (pronounced ‘clash’) is a functional hardware description language that@@ -16,6 +16,7 @@   To use the library:   .   * Import "CLaSH.Prelude"+  .   * Additionally import "CLaSH.Prelude.Explicit" if you want to design     explicitly clocked circuits in a multi-clock setting   .
src/CLaSH/Bit.hs view
@@ -11,8 +11,8 @@ import Language.Haskell.TH.Lift  -- | Two-level logic-data Bit = H -- ^ High-         | L -- ^ Low+data Bit = L -- ^ Low+         | H -- ^ High  instance Eq Bit where   (==) = eqBit
src/CLaSH/Prelude.hs view
@@ -180,10 +180,12 @@ registerP i = unpack Prelude.. register i Prelude.. pack  {-# NOINLINE blockRam #-}--- | Create a blockRAM with space for @n@ elements+-- | Create a blockRAM with space for @n@ elements. --+-- NB: Read value is delayed by 1 cycle+-- -- > bram40 :: Signal (Unsigned 6) -> Signal (Unsigned 6) -> Signal Bool -> Signal a -> Signal a--- > bram40 = blockRam d50+-- > bram40 = blockRam d40 blockRam :: forall n m a . (KnownNat n, KnownNat m, Pack a, Default a)          => SNat n              -- ^ Size @n@ of the blockram          -> Signal (Unsigned m) -- ^ Write address @w@@@ -204,11 +206,13 @@              | otherwise = ram         o'               = ram ! r -{-# DEPRECATED blockRamC "'Comp' is deprecated, use 'blockRam' instead" #-}+{-# DEPRECATED blockRamC "'Comp' is deprecated and will be removed in version 0.6, use 'blockRam' instead" #-} -- | Create a blockRAM with space for @n@ elements --+-- NB: Read value is delayed by 1 cycle+-- -- > bramC40 :: Comp (Unsigned 6, Unsigned 6, Bool, a) a--- > bramC40 = blockRamC d50+-- > bramC40 = blockRamC d40 blockRamC :: (KnownNat n, KnownNat m, Pack a, Default a)           => SNat n -- ^ Size @n@ of the blockram           -> Comp (Unsigned m, Unsigned m, Bool, a) a@@ -217,6 +221,8 @@ {-# INLINABLE blockRamPow2 #-} -- | Create a blockRAM with space for 2^@n@ elements --+-- NB: Read value is delayed by 1 cycle+-- -- > bram32 :: Signal (Unsigned 5) -> Signal (Unsigned 5) -> Signal Bool -> Signal a -> Signal a -- > bram32 = blockRamPow2 d32 blockRamPow2 :: (KnownNat n, KnownNat (2^n), Pack a, Default a)@@ -228,9 +234,11 @@              -> Signal a            -- ^ Value of the 'blockRAM' at address @r@ from the previous clock cycle blockRamPow2 = blockRam -{-# DEPRECATED blockRamPow2C "'Comp' is deprecated, use 'blockRamPow2' instead" #-}+{-# DEPRECATED blockRamPow2C "'Comp' is deprecated and will be removed in version 0.6, use 'blockRamPow2' instead" #-} -- | Create a blockRAM with space for 2^@n@ elements --+-- NB: Read value is delayed by 1 cycle+-- -- > bramC32 :: Comp (Unsigned 5, Unsigned 5, Bool, a) a -- > bramC32 = blockRamPow2C d32 blockRamPow2C :: (KnownNat n, KnownNat (2^n), Pack a, Default a)@@ -238,7 +246,7 @@               -> Comp (Unsigned n, Unsigned n, Bool, a) a blockRamPow2C n = C ((\(wr,rd,en,din) -> blockRamPow2 n wr rd en din) Prelude.. unpack) -{-# DEPRECATED Comp "Use 'Applicative' interface and ('<^>') instead" #-}+{-# DEPRECATED Comp "Will be removed in version 0.6. Use 'Applicative' interface and ('<^>') instead" #-} -- | 'Comp'onent: an 'Arrow' interface to synchronous sequential functions newtype Comp  a b = C { asFunction :: Signal a -> Signal b } @@ -258,7 +266,7 @@       simpleLoop g b = let ~(c,d) = g (b,d)                        in c -{-# DEPRECATED registerC "'Comp' is deprecated, use 'register' instead" #-}+{-# DEPRECATED registerC "'Comp' is deprecated and will be removed in version 0.6, use 'register' instead" #-} -- | Create a 'register' 'Comp'onent -- -- > rC :: Comp (Int,Int) (Int,Int)@@ -269,7 +277,7 @@ registerC :: a -> Comp a a registerC = C Prelude.. register -{-# DEPRECATED simulateC "'Comp' is deprecated, use 'simulate' instead" #-}+{-# DEPRECATED simulateC "'Comp' is deprecated and will be removed in version 0.6, use 'simulate' instead" #-} -- | Simulate a 'Comp'onent given a list of samples -- -- >>> simulateC (registerC 8) [1, 2, 3, ...@@ -277,7 +285,7 @@ simulateC :: Comp a b -> [a] -> [b] simulateC f = simulate (asFunction f) -{-# DEPRECATED (^^^) "Use 'Applicative' interface and ('<^>') instead" #-}+{-# DEPRECATED (^^^) "Will be removed in version 0.6. Use 'Applicative' interface and ('<^>') instead" #-} {-# INLINABLE (^^^) #-} -- | Create a synchronous 'Comp'onent from a combinational function describing -- a mealy machine
src/CLaSH/Prelude/Explicit.hs view
@@ -104,7 +104,7 @@ cregisterP :: CPack a => Clock clk -> a -> CSignalP clk a -> CSignalP clk a cregisterP clk i = cunpack clk Prelude.. cregister clk i Prelude.. cpack clk -{-# DEPRECATED CComp "Use 'Applicative' interface and 'sync' instead" #-}+{-# DEPRECATED CComp "Will be removed in version 0.6. Use 'Applicative' interface and 'sync' instead" #-} -- | 'CComp'onent: an 'Arrow' interface to explicitly clocked synchronous -- sequential functions newtype CComp t a b = CC { asCFunction :: CSignal t a -> CSignal t b }@@ -127,7 +127,7 @@       simpleLoop g b = let ~(c,d) = g (b,d)                        in c -{-# DEPRECATED syncA "Use 'Applicative' interface and 'sync' instead" #-}+{-# DEPRECATED syncA "Will be removed in version 0.6. Use 'Applicative' interface and 'sync' instead" #-} {-# INLINABLE syncA #-} -- | Create a synchronous 'CComp'onent from a combinational function describing -- a mealy machine@@ -162,7 +162,7 @@                                 s      = cregister clk sI s'                             in  o -{-# DEPRECATED cregisterC "'CComp' is deprecated, use 'cregister' instead" #-}+{-# DEPRECATED cregisterC "'CComp' is deprecated and will be removed in version 0.6, use 'cregister' instead" #-} -- | Create a 'cregister' 'CComp'onent -- -- > clk100 = Clock d100@@ -175,7 +175,7 @@ cregisterC :: Clock clk -> a -> CComp clk a a cregisterC clk = CC Prelude.. cregister clk -{-# DEPRECATED csimulateC "'CComp' is deprecated, use 'csimulate' instead" #-}+{-# DEPRECATED csimulateC "'CComp' is deprecated and will be removed in version 0.6, use 'csimulate' instead" #-} -- | Simulate a 'Comp'onent given a list of samples -- -- > clk100 = Clock d100@@ -187,11 +187,13 @@ {-# NOINLINE cblockRam #-} -- | Create a blockRAM with space for @n@ elements --+-- NB: Read value is delayed by 1 cycle+-- -- > clk100 = Clock d100 -- > -- > bram40 :: CSignal 100 (Unsigned 6) -> CSignal 100 (Unsigned 6) -- >        -> CSignal 100 Bool -> CSignal 100 a -> 100 CSignal a--- > bram40 = cblockRam clk100 d50+-- > bram40 = cblockRam clk100 d40 cblockRam :: forall n m a clk . (KnownNat n, KnownNat m, CPack a, Default a)           => Clock clk                -- ^ 'Clock' to synchronize to           -> SNat n                   -- ^ Size @n@ of the blockram@@ -213,13 +215,15 @@              | otherwise = ram         o'               = ram ! r -{-# DEPRECATED blockRamCC "'CComp' is deprecated, use 'cblockRam' instead" #-}+{-# DEPRECATED blockRamCC "'CComp' is deprecated and will be removed in version 0.6, use 'cblockRam' instead" #-} -- | Create a blockRAM with space for @n@ elements --+-- NB: Read value is delayed by 1 cycle+-- -- > clk100 = Clock 100 -- > -- > bramC40 :: CComp 100 (Unsigned 6, Unsigned 6, Bool, a) a--- > bramC40 = blockRamCC clk100 d50+-- > bramC40 = blockRamCC clk100 d40 blockRamCC :: (KnownNat n, KnownNat m, CPack a, Default a)            => Clock clk -- ^ 'Clock' to synchronize to            -> SNat n    -- ^ Size @n@ of the blockram@@ -229,6 +233,8 @@ {-# INLINABLE cblockRamPow2 #-} -- | Create a blockRAM with space for 2^@n@ elements --+-- NB: Read value is delayed by 1 cycle+-- -- > bram32 :: Signal (Unsigned 5) -> Signal (Unsigned 5) -> Signal Bool -> Signal a -> Signal a -- > bram32 = cblockRamPow2 d32 cblockRamPow2 :: (KnownNat n, KnownNat (2^n), CPack a, Default a)@@ -241,8 +247,10 @@               -> CSignal clk a            -- ^ Value of the 'blockRAM' at address @r@ from the previous clock cycle cblockRamPow2 = cblockRam -{-# DEPRECATED blockRamPow2CC "'CComp' is deprecated, use 'cblockRamPow2' instead" #-}+{-# DEPRECATED blockRamPow2CC "'CComp' is deprecated and will be removed in version 0.6, use 'cblockRamPow2' instead" #-} -- | Create a blockRAM with space for 2^@n@ elements+--+-- NB: Read value is delayed by 1 cycle -- -- > clk100 = Clock d100 -- >
src/CLaSH/Signal/Explicit.hs view
@@ -115,6 +115,13 @@  -- | Isomorphism between a @'CSignal' clk@ of a product type (e.g. a tuple) and a -- product type of @'CSignal' clk@'s+--+-- Instances of 'CPack' must satisfy the following laws:+--+-- @+-- cpack clk . cunpack clk = 'id'+-- cunpack clk . cpack clk = 'id'+-- @ class CPack a where   type CSignalP (clk :: Nat) a   type CSignalP clk a = CSignal clk a
src/CLaSH/Signal/Implicit.hs view
@@ -79,7 +79,14 @@ simulate f = sample . f . fromList  -- | Isomorphism between a 'Signal' of a product type (e.g. a tuple) and a--- product type of 'Signal's+-- product type of 'Signal's.+--+-- Instances of 'Pack' must satisfy the following laws:+--+-- @+-- pack . unpack = 'id'+-- unpack . pack = 'id'+-- @ class Pack a where   type SignalP a   -- | Example:
src/CLaSH/Sized/Vector.hs view
@@ -385,7 +385,7 @@ vindex_integer :: KnownNat n => Vec n a -> Integer -> a vindex_integer xs i = case vindexM_integer xs (maxIndex xs - i) of     Just a  -> a-    Nothing -> error "index out of bounds"+    Nothing -> error ("(!): Index " ++ show i ++ " is out of bounds 0 and " ++ show (maxIndex xs))  {-# INLINEABLE (!) #-} -- | Vector index (subscript) operator, descending from 'maxIndex', where the@@ -430,7 +430,7 @@ vreplace_integer :: KnownNat n => Vec n a -> Integer -> a -> Vec n a vreplace_integer xs i a = case vreplaceM_integer xs (maxIndex xs - i) a of   Just ys -> ys-  Nothing -> error "index out of bounds"+  Nothing -> error ("vreplace: Index " ++ show i ++ " is out of bounds 0 and " ++ show (maxIndex xs))  {-# INLINEABLE vreplace #-} -- | Replace an element of a vector at the given index (subscript).@@ -649,12 +649,12 @@ -- > compareSwapL a b = if a < b then (a,b) -- >                             else (b,a) ----- Will not terminate because 'vzipWith' is too strict in its left argument:+-- Will not terminate because 'vzipWith' is too strict in its second argument: -- -- >>> sortV (4 :> 1 :> 2 :> 3 :> Nil) -- <*** Exception: <<loop>> ----- In this case, adding 'lazyV' on 'vzipWith's left argument:+-- In this case, adding 'lazyV' on 'vzipWith's second argument: -- -- > sortVL xs = vmap fst sorted <: (snd (vlast sorted)) -- >  where
src/CLaSH/Tutorial.hs view
@@ -35,6 +35,9 @@   -- * Composition of sequential circuits   -- $composition_sequential +  -- * Advanced: VHDL primitives+  -- $vhdlprimitives+   -- * Conclusion   -- $conclusion @@ -43,19 +46,27 @@    -- * Unsupported Haskell features   -- $unsupported++  -- * CλaSH vs Lava+  -- $vslava   ) where  import CLaSH.Prelude import CLaSH.Prelude.Explicit+import Data.Char+import Data.Int+import GHC.Word + {- $introduction CλaSH (pronounced ‘clash’) is a functional hardware description language that borrows both its syntax and semantics from the functional programming language Haskell. The merits of using a functional language to describe hardware comes from the fact that combinational circuits can be directly modeled as mathematical functions and that functional languages lend themselves very well-at describing and (de-)composing mathematical functions.+at describing and (de-)composing mathematical functions. The CλaSH compiler+transforms these high-level descriptions to low-level synthesizable VHDL.  Although we say that CλaSH borrows the semantics of Haskell, that statement should be taken with a grain of salt. What we mean to say is that the CλaSH@@ -65,13 +76,13 @@ consequences on how we view /recursive/ functions: structurally, a recursive function would denote an /infinitely/ deep / structured component, something that cannot be turned into an actual circuit (See also <#unsupported Unsupported Haskell features>).-Of course there are variants of recursion that cab be completely unfolded at+Of course there are variants of recursion that could be completely unfolded at compile-time with a finite amount of steps and hence could be converted to a realisable circuit. Sadly, this last feature is missing in the current version of the compiler. -On the other hand, Haskell's by-default non-strict evaluation corresponds very-well to the simulation of the feedback loops which are ubiquitous in digital+On the other hand, Haskell's by-default non-strict evaluation works very well+for the simulation of the feedback loops, which are ubiquitous in digital circuits. That is, when we take our structural view to circuit descriptions, value-recursion corresponds directly to a feedback loop: @@ -81,10 +92,10 @@     s = register 0 (s + 1) @ -Over time, you will get a better feeling of what exact the consequences are of-taking a \structural\ view on circuit descriptions. What is always important to+Over time, you will get a better feeling for the consequences of taking a+/structural/ view on circuit descriptions. What is always important to remember is that every applied functions results in an instantiated component,-and also that the compiler will never infer / invent more logic than what is+and also that the compiler will /never/ infer / invent more logic than what is specified in the circuit description.  With that out of the way, let us continue with installing CλaSH and building@@ -93,9 +104,9 @@  {- $installation The CλaSH compiler and Prelude library for circuit design only work with the-<http://haskell.org/ghc GHC> Haskell compiler version 7.8.1 and up.+<http://haskell.org/ghc GHC> Haskell compiler version 7.8.* and up. -  (1) Install __GHC (version 7.8.1 or higher)__+  (1) Install __GHC (version 7.8.* or higher)__        * Download and install <http://www.haskell.org/ghc/download GHC for your platform>.         Unix user can use @./configure prefix=\<LOCATION\>@ to set the installation@@ -105,12 +116,12 @@    (2) Install __Cabal__ -      * Windows:+      * Windows and OS X Mavericks:            * Download the binary for <http://www.haskell.org/cabal/download.html cabal-install>           * Put the binary in a location mentioned in your @PATH@ -      * Unix:+      * Other Unix systems:            * Download the sources for <http://hackage.haskell.org/package/cabal-install cabal-install>           * Unpack (@tar xf@) the archive and @cd@ to the directory@@ -129,7 +140,7 @@       * Run @clash --interactive FIR.hs@       * Execute, in the interpreter, the @:vhdl@ command.       * Exit the interpreter using @:q@-      * Examin the VHDL code in the @vhdl@ directory+      * Examine the VHDL code in the @vhdl@ directory  -} @@ -173,28 +184,28 @@ and accumulates them. Before we describe any logic, we must first create the file we will be working on and input some preliminaries: -  * Create the file:+* Create the file: -      @-      MAC.hs-      @+    @+    MAC.hs+    @ -  * Write on the first line the module header:+* Write on the first line the module header: -      @-      module MAC where-      @+    @+    module MAC where+    @ -      Module names must always start with a __C__apital letter. Also make sure that-      the file name corresponds to the module name.+    Module names must always start with a __C__apital letter. Also make sure that+    the file name corresponds to the module name. -  * Add the import statement for the CλaSH prelude library:+* Add the import statement for the CλaSH prelude library: -      @-      import CLaSH.Prelude-      @+    @+    import CLaSH.Prelude+    @ -      This imports all the necessary functions and datatypes for circuit description.+    This imports all the necessary functions and datatypes for circuit description.  We can now finally start describing the logic of our circuit, starting with just the multiplication and addition:@@ -214,7 +225,7 @@ We can also examine the inferred type of @ma@ in the interpreter:  >>> :t ma-ma :: Num a => a -> a -> a+ma :: Num a => a -> (a, a) -> a  Talking about /types/ also brings us to one of the most important parts of this tutorial: /types/ and /synchronous sequential logic/. Especially how we can@@ -336,7 +347,7 @@ type instance SignalP (a,b) = (Signal a, Signal b) @ -'SignalP' is an <http://www.haskell.org/ghc/docs/latest/html/users_guide/type-families.html#assoc-decl associcated type family>+'SignalP' is an <http://www.haskell.org/ghc/docs/latest/html/users_guide/type-families.html#assoc-decl associated type family> belonging to the 'Pack' <http://en.wikipedia.org/wiki/Type_class type class>, which, together with 'pack' and 'unpack' defines the isomorphism between a product type of 'Signal's and a 'Signal' of a product type. That is, while@@ -442,7 +453,7 @@ topEntity :: SignalP a -> SignalP b @ -Where @a@ and @b@ are placeholders for monomorphics types: the 'topEntity' is+Where @a@ and @b@ are placeholders for monomorphic types: the 'topEntity' is not allowed to be polymorphic. So given the above type for the 'topEntity', the type of 'testInput' should be: @@ -505,16 +516,18 @@  This concludes the main part of this section on \"Your first circuit\", read on for alternative specifications for the same 'mac' circuit, or just skip to the-next section where we will describe another DSP classic: an FIR filter structure.+next section where we will describe another DSP classic: an FIR filter+structure. -}  {- $mac5-* __'Num' instance__:+* __'Num' instance for 'Signal'__: -    @'Signal' a@ is also also considered a 'Num'eric type as long as @a@ is also.-    This means that we can also use the standard numeric operators, such as ('*')-    and ('+'), directly on signals. An alternative specification of the 'mac'-    circuit will also use the 'register' function directly:+    @'Signal' a@ is also also considered a 'Num'eric type as long as the value+    type /a/ is also 'Num'eric.  This means that we can also use the standard+    numeric operators, such as ('*') and ('+'), directly on signals. An+    alternative specification of the 'mac' circuit will also use the 'register'+    function directly:      @     macN (x,y) = acc@@ -522,11 +535,12 @@         acc = register 0 (acc + x * y)     @ -* __'Applicative' interface__:+* __'Applicative' instance for 'Signal'__:      We can also mix the combinational 'ma' function, with the sequential     'register' function, by lifting the 'ma' function to the sequential 'Signal'-    domain using the operators of the 'Applicative' type class:+    domain using the operators ('<$>' and '<*>') of the 'Applicative' type+    class:      @     macA (x,y) = acc@@ -537,7 +551,8 @@  * __<http://hackage.haskell.org/package/mtl/docs/Control-Monad-State-Lazy.html#t:State State> Monad__ -    We can also implement the original 'macT' function as a <http://hackage.haskell.org/package/mtl/docs/Control-Monad-State-Lazy.html#t:State State>+    We can also implement the original 'macT' function as a+    @<http://hackage.haskell.org/package/mtl/docs/Control-Monad-State-Lazy.html#t:State State>@     monadic computation. First we must an extra import statement, right after     the import of "CLaSH.Prelude": @@ -558,6 +573,10 @@     position of the arguments and result:      @+    asStateM :: (Pack o, Pack i)+             => (i -> State s o)+             -> s+             -> (SignalP i -> SignalP o)     asStateM f i = g \<^\> i       where         g s x = let (o,s') = runState (f x) s@@ -655,22 +674,196 @@ @  Here we can finally see the advantage of having the '<^>' return a function-of type @'SignalP' i -> 'SignalP' o@:+of type: @('SignalP' i -> 'SignalP' o)@ (instead of:+@('Signal' i -> 'Signal' o)@):    * We can use normal pattern matching to get parts of the result, and,   * We can use normal tuple-constructors to build the input values for the     circuits. -} +{- $vhdlprimitives+There are times when you already have an existing piece of IP, or there are+times where you need the VHDL to have a specific shape so that the VHDL+synthesis tool can infer a specific component. In these specific cases you can+resort to defining your own VHDL primitives. Actually, most of the primitives+in CλaSH are specified in the same way as you will read about in this section.+There are perhaps 10 (at most) functions which are truly hard-coded into the+CλaSH compiler. You can take a look at the files in+<http://github.com/christiaanb/clash2/tree/master/primitives>+if you want to know which functions are defined as \"regular\" primitives. The+compiler looks for primitives in two locations:++* The official install location: e.g.+  @$CABAL_DIR\/share\/\<GHC_VERSION\>\/clash-ghc\-<VERSION\>\/primitives@+* The current directory (the location given by @pwd@)++Where redefined primitives in the current directory will overwrite those in+the official install location. For now, files containing primitive definitions+must end in the @.json@ file-extension.++CλaSH differentiates between two types of primitives, /expression/ primitives+and /declaration/ primitives, corresponding to whether the primitive is a VHDL+/expression/ or a VHDL /declaration/. We will first explore /expression/+primitives, using 'Signed' multiplication ('*') as an example. The+"CLaSH.Sized.Signed" module specifies multiplication as follows:++@+{\-# NOINLINE timesS #-\}+timesS :: KnownNat n => Signed n -> Signed n -> Signed n+timesS (S a) (S b) = fromIntegerS_inlineable (a * b)+@++For which the /expression/ primitive is:++@+{ \"BlackBox\" :+  { "name"      : "CLaSH.Sized.Signed.timesS"+  , "templateE" : "resize(~ARG[1] * ~ARG[2], ~LIT[0])"+  }+}+@++The @name@ of the primitive is the /fully qualified/ name of the function you+are creating the primitive for. Because we are creating an /expression/+primitive we define a @template__E__@ field. As the name suggest, it is a VHDL+/template/, meaning that the compiler must fill in the holes heralded by the+tilde (~). Here:++  * @~ARG[1]@ denotes the second argument given to the @timesS@ function, which+    corresponds to the LHS of the ('*') operator.+  * @~ARG[2]@ denotes the third argument given to the @timesS@ function, which+    corresponds to the RHS of the ('*') operator.+  * @~LIT[0]@ denotes the first argument given to the @timesS@ function, with+    the extra condition that it must be a @LIT@eral. If for some reason this+    first argument does not turn out to be a literal then the compiler will+    raise an error. This first arguments corresponds to the \"@'KnownNat' n@\"+    class constraint.++An extensive list with all of the template holes will be given the end of this+section. What we immediately notice is that class constraints are counted as+normal arguments in the primitive definition. This is because these class+constraints are actually represented by ordinary record types, with fields+corresponding to the methods of the type class. In the above case, 'KnownNat'+is actually just like a @newtype@ wrapper for 'Integer'.++The second kind of primitive that we will explore is the /declaration/ primitive.+We will use 'blockRam' as an example, for which the Haskell/CλaSH code is:++@+{\-# NOINLINE blockRam #-\}+-- | Create a blockRAM with space for \@n\@ elements+--+-- NB: Read value is delayed by 1 cycle+--+-- > bram40 :: Signal (Unsigned 6) -> Signal (Unsigned 6) -> Signal Bool -> Signal a -> Signal a+-- > bram40 = blockRam d40+blockRam :: forall n m a . (KnownNat n, KnownNat m, Pack a, Default a)+         => SNat n              -- ^ Size \@n\@ of the blockram+         -> Signal (Unsigned m) -- ^ Write address \@w\@+         -> Signal (Unsigned m) -- ^ Read address \@r\@+         -> Signal Bool         -- ^ Write enable+         -> Signal a            -- ^ Value to write (at address \@w\@)+         -> Signal a            -- ^ Value of the 'blockRAM' at address \@r\@ from the previous clock cycle+blockRam n wr rd en din = pack $ (bram' \<^\> binit) (wr,rd,en,din)+  where+    binit :: (Vec n a,a)+    binit = (vcopy n def,def)++    bram' :: (Vec n a,a) -> (Unsigned m, Unsigned m, Bool, a)+          -> (((Vec n a),a),a)+    bram' (ram,o) (w,r,e,d) = ((ram',o'),o)+      where+        ram' | e         = vreplace ram w d+             | otherwise = ram+        o'               = ram ! r+@++And for which the /definition/ primitive is:++@+{ \"BlackBox\" :+  { "name"      : "CLaSH.Prelude.blockRam"+  , "templateD" :+"~SYM[0]_block : block+  type ram_array is array (natural range <>) of ~TYP[8];+  signal ~SYM[1] : ram_array((~ARG[0]-1) downto 0) := (others => ~ARG[3]); -- ram+  signal ~SYM[2] : ~TYP[8]; -- inp+  signal ~SYM[3] : ~TYP[8] := ~ARG[3]; -- outp+begin+  ~SYM[2] <= ~ARG[8];++  process(~CLKO)+  begin+    if rising_edge(~CLKO) then+      if ~ARG[7] then+        ~SYM[1](to_integer(~ARG[5])) <= ~SYM[2];+      end if;+      ~SYM[3] <= ~SYM[1](to_integer(~ARG[6]));+    end if;+  end process;++  ~RESULT <= ~SYM[3];+end block;"+  }+}+@++Again, the @name@ of the primitive is the fully qualified name of the function+you are creating the primitive for. Because we are creating a /declaration/+primitive we define a @template__D__@ field. Instead of discussing what the+individual template holes mean in the above context, we will instead just give+a general listing of the available template holes:++* @~RESULT@: VHDL signal to which the result of a primitive must be assigned+  to. NB: Only used in a /definition/ primitive.+* @~ARG[N]@: @(N+1)@'th argument to the function.+* @~LIT[N]@: @(N+1)@'th argument to the function An extra condition that must+  hold is that this @(N+1)@'th argument is an (integer) literal.+* @~CLK[N]@: Clock signal to which the @(N+1)@'th argument is synchronized to.+* @~CLKO@: Clock signal to which the result is synchronized to.+* @~RST[N]@: Asynchronous reset signal to the clock to which the @(N+1)@'th+  argument is synchronized to.+* @~RSTO@: Asynchronous reset signal to the clock to which the result is+  synchronized to.+* @~TYP[N]@: VHDL type of the @(N+1)@'th argument.+* @~TYPO@: VHDL type of the result.+* @~TYPM[N]@: VHDL type/name/ of the @(N+1)@'th argument; used in /type/+  /qualification/.+* @~TYPM@: VHDL type/name/ of the result; used in /type qualification/.+* @~DEF[N]@: Default value for the VHDL type of the @(N+1)@'th argument. NB:+  Does not correspond per se to the value of 'def' of the 'Default' type class+  for the Haskell type.+* @~DEFO@: Default value for the VHDL type of the result. NB: Does not+  correspond per se to the value of the 'def' of the 'Default' type class for+  the Haskell type.+* @~SYM[N]@: Randomly generated, but unique, symbol. Multiple occurrences of+  @~SYM[N]@ in the same primitive definition all refer to the same random, but+  unique, symbol.++Some final remarks to end this section: VHDL primitives are there to instruct the+CλaSH compiler to use the given VHDL template, instead of trying to do normal+synthesis. As a consequence you can use constructs inside the Haskell+definitions that are normally not synthesizable by the CλaSH compiler. However,+VHDL primitives do not give us /co-simulation/: where you would be able to+simulate VHDL and Haskell in a /single/ environment. If you still want to+simulate your design in Haskell, you will have to describe, in a cycle- and+bit-accurate way, the behaviour of that (potentially complex) IP you are trying+to include in your design.++Perhaps in the future, someone will figure out how to connect the two simulation+worlds, using e.g. VHDL's foreign function interface VHPI.+-}+ {- $conclusion For now, this is the end of this tutorial. We will be adding updates over time,-so check back from time to time. For now we recommend that you continue with-exploring the "CLaSH.Prelude" module however, and like that hopefully get a feel-of what CλaSH is capable of.+so check back from time to time. For now, we recommend that you continue with+exploring the "CLaSH.Prelude" module, and get a better understanding of the+capabilities of CλaSH in the process. -}  {- $errorsandsolutions-A list often encountered errors and their solutions:+A list of often encountered errors and their solutions:  * __Type error: Couldn't match expected type ‘Signal (a,b)’ with actual type__   __‘(Signal a, Signal b)’__:@@ -701,7 +894,7 @@   __ actual type ‘Signal (a,b)’__:      Product types (to which tuples belong) of signals and signals of product-    types are __isomorphic__ due to synchronisity principle, but are not+    types are __isomorphic__ due to synchronicity principle, but are not     (structurally) equal. Use the 'unpack' function to convert from a signal     type to the product type. So if your code which gives the error looks like: @@ -722,31 +915,54 @@      NB: Use 'cunpack' when you are using explicitly clocked 'CSignal's +* __CLaSH.Netlist(..): Not in normal form: \<REASON\>: \<EXPR\>__:++    A function could not be transformed into the expected normal form. This+    usually means one of the following:++    * The @topEntity@ has residual polymorphism.+    * The @topEntity@ has higher-order arguments, or a higher-order result.+    * You are using types which cannot be represented in hardware.++    The solution for all the above listed reasons is quite simple: remove them.+    That is, make sure that the @topEntity@ is completely monomorphic and+    first-order. Also remove any variables and constants/literals that have a+    non-representable type, see <#unsupported Unsupported Haskell features> to+    find out which types are not representable.+ * __CLaSH.Normalize(94): Expr belonging to bndr: \<FUNCTION\> remains__   __recursive after normalization__:      * If you actually wrote a recursive function, rewrite it to a non-recursive-      one :-)+      one using e.g. one of the higher-order functions in "CLaSH.Sized.Vector" :-)      * You defined a recursively defined value, but left it polymorphic:      @     topEntity x y = acc-    where-      acc = register 3 (x*y + acc)+      where+        acc = register 3 (acc + x * y)     @      The above function, works for any number-like type. This means that @acc@ is     a recursively defined __polymorphic__ value. Adding a monomorphic type-    annotation makes the error go away.+    annotation makes the error go away:      @     topEntity :: Signal (Signed 8) -> Signal (Signed 8) -> Signal (Signed 8)     topEntity x y = acc-    where-      acc = register 3 (x*y + acc)+      where+        acc = register 3 (acc + x * y)     @ +    Or, alternatively:++    @+    topEntity x y = acc+      where+        acc = register (3 :: Signed 8) (acc + x * y)+    @+ * __CLaSH.Normalize.Transformations(155): InlineNonRep: \<FUNCTION\> already__   __inlined 100 times in:\<FUNCTION\>, \<TYPE\>__: @@ -781,12 +997,12 @@                                 else (b,a)     @ -    Will not terminate because 'vzipWith' is too strict in its left argument:+    Will not terminate because 'vzipWith' is too strict in its second argument:      >>> sortV (4 :> 1 :> 2 :> 3 :> Nil)     <*** Exception: <<loop>> -    In this case, adding 'lazyV' on 'vzipWith's left argument:+    In this case, adding 'lazyV' on 'vzipWith's second argument:      @     sortVL xs = vmap fst sorted <: (snd (vlast sorted))@@ -855,6 +1071,62 @@    [@Floating point types@] -    There is no support for the 'Float' and 'Double' type, if you need numbers+    There is no support for the 'Float' and 'Double' types, if you need numbers     with a /fractional/ part you can use the 'Fixed' point type.++  [@Other primitive types@]++    Most primitive types are not supported, with the exception of 'Int',+    @<http://hackage.haskell.org/package/ghc-prim/docs/GHC-Prim.html#t:Int-35- Int#>@,+    and 'Integer'. This means that types such as: 'Word', 'Word8', 'Int8', 'Char',+    @<http://hackage.haskell.org/package/array/docs/Data-Array.html#t:Array Array>@,+    etc. cannot to translated to hardware.++    The translations of 'Int',+    @<http://hackage.haskell.org/package/ghc-prim/docs/GHC-Prim.html#t:Int-35- Int#>@,+    and 'Integer' are also incorrect: they are translated to the VHDL @integer@+    type, which can only represent 32-bit integer values. Use these types with+    due diligence.++  [@Side-effects: 'IO', <http://hackage.haskell.org/package/base/docs/Control-Monad-ST.html#t:ST ST>, etc.@]++    There is no support for side-effecting computations such as those in the+    'IO' or @<http://hackage.haskell.org/package/base/docs/Control-Monad-ST.html#t:ST ST>@+    monad. There is also no support for Haskell's+    <http://www.haskell.org/haskellwiki/Foreign_Function_Interface FFI>.+-}++{- $vslava+In Haskell land the most well-known way of describing digital circuits is the+Lava family of languages:++* <http://hackage.haskell.org/package/chalmers-lava2000 Chalmers Lava>+* <http://hackage.haskell.org/package/xilinx-lava Xilinx Lava>+* <http://hackage.haskell.org/package/york-lava York Lava>+* <http://hackage.haskell.org/package/kansas-lava Kansas Lava>++The big difference between CλaSH and Lava is that CλaSH uses a \"standard\"+compiler (static analysis) approach towards synthesis, where Lava is an+embedded domain specific language. One downside of static analysis vs. the+embedded language approach is already clearly visible: synthesis of recursive+descriptions does not come for \"free\". This will be implemented in CλaSH in+due time, but that doesn't help the circuit designer right now. As already+mentioned earlier, the lack of support for recursive functions is amortized by+the built-in support for the higher-order in "CLaSH.Sized.Vector".++The big upside of CλaSH and its static analysis approach is that CλaSH can+do synthesis of \"normal\" functions: there is no forced encasing datatype (often+called /Signal/ in Lava) on all the arguments and results of a synthesizable+function. This enables the following features not available to Lava:++* Automatic synthesis for user-defined ADTs+* Synthesis of all choice constructs (pattern matching, guards, etc.)+* 'Applicative' instance for the 'Signal' type+* Working with \"normal\" functions permits the use of e.g. the+  <http://hackage.haskell.org/package/mtl/docs/Control-Monad-State-Lazy.html#t:State State>+  monad to describe the functionality of a circuit.++Although there are Lava alternatives to some of the above features (e.g.+first-class patterns to replace pattern matching) they are not as \"beautiful\"+and / or easy to use as the standard Haskell features. -}