clash-prelude 1.6.2 → 1.6.3
raw patch · 36 files changed
+787/−616 lines, 36 filesdep ~hedgehogdep ~tasty-hedgehogPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hedgehog, tasty-hedgehog
API changes (from Hackage documentation)
+ Clash.Class.BitPack.Internal: xToBV :: KnownNat n => BitVector n -> BitVector n
+ Clash.Explicit.BlockRam: blockRam1# :: forall n dom a. (KnownDomain dom, HasCallStack, NFDataX a) => Clock dom -> Enable dom -> SNat n -> a -> Signal dom Int -> Signal dom Bool -> Signal dom Int -> Signal dom a -> Signal dom a
+ Clash.Explicit.BlockRam: blockRamU# :: forall n dom a. (KnownDomain dom, HasCallStack, NFDataX a) => Clock dom -> Enable dom -> SNat n -> Signal dom Int -> Signal dom Bool -> Signal dom Int -> Signal dom a -> Signal dom a
+ Clash.Num.Overflowing: fromOverflowing :: Overflowing a -> a
+ Clash.Num.Overflowing: hasOverflowed :: Overflowing a -> Bool
Files
- CHANGELOG.md +15/−1
- clash-prelude.cabal +4/−3
- src/Clash/Class/AutoReg/Internal.hs +4/−3
- src/Clash/Class/BitPack/Internal.hs +10/−4
- src/Clash/Explicit/BlockRam.hs +174/−162
- src/Clash/Explicit/BlockRam/Blob.hs +15/−15
- src/Clash/Explicit/BlockRam/File.hs +54/−51
- src/Clash/Explicit/Mealy.hs +2/−2
- src/Clash/Explicit/Moore.hs +2/−2
- src/Clash/Explicit/Prelude.hs +4/−4
- src/Clash/Explicit/Prelude/Safe.hs +3/−3
- src/Clash/Explicit/RAM.hs +15/−15
- src/Clash/Explicit/ROM.hs +16/−16
- src/Clash/Explicit/ROM/Blob.hs +4/−4
- src/Clash/Explicit/ROM/File.hs +39/−36
- src/Clash/Intel/ClockGen.hs +121/−23
- src/Clash/Num/Overflowing.hs +11/−1
- src/Clash/Prelude.hs +4/−4
- src/Clash/Prelude/BlockRam.hs +80/−81
- src/Clash/Prelude/BlockRam/Blob.hs +11/−11
- src/Clash/Prelude/BlockRam/File.hs +38/−38
- src/Clash/Prelude/Mealy.hs +2/−2
- src/Clash/Prelude/Moore.hs +2/−2
- src/Clash/Prelude/RAM.hs +6/−6
- src/Clash/Prelude/ROM.hs +28/−28
- src/Clash/Prelude/ROM/Blob.hs +5/−5
- src/Clash/Prelude/ROM/File.hs +53/−49
- src/Clash/Signal/Trace.hs +1/−1
- tests/Clash/Tests/AsyncFIFOSynchronizer.hs +2/−2
- tests/Clash/Tests/BitVector.hs +8/−8
- tests/Clash/Tests/BlockRam/Blob.hs +2/−2
- tests/Clash/Tests/Counter.hs +7/−7
- tests/Clash/Tests/Fixed.hs +9/−9
- tests/Clash/Tests/Laws/SaturatingNum.hs +4/−4
- tests/Clash/Tests/NumNewtypes.hs +12/−12
- tests/Test/Tasty/Hedgehog/Extra.hs +20/−0
CHANGELOG.md view
@@ -1,6 +1,20 @@ # Changelog for the Clash project+## 1.6.3 *Apr 7th 2022*+Fixed:+ * Handle `~ISUNDEFINED` hole in black boxes for `BitVector` and for product types. This means that with `-fclash-aggressive-x-optimization-blackboxes`, resets are now omitted for _undefined_ reset values of such types as well. [#2117](https://github.com/clash-lang/clash-compiler/issues/2117)+ * The `alteraPll` primitive was unusable since commit `d325557750` (release v1.4.0), it now works again. [#2136](https://github.com/clash-lang/clash-compiler/pull/2136)+ * Simulation/Synthesis mismatch for X-exception to undefined bitvector conversion [#2154](https://github.com/clash-lang/clash-compiler/issues/2154)+ * The VHDL blackbox for `Signed.fromInteger` can now handle any `Netlist Expr` as input [#2149](https://github.com/clash-lang/clash-compiler/issues/2149)+ * Clash no longer escapes extended identifiers when rendering SDC files. [#2142](https://github.com/clash-lang/clash-compiler/pull/2142)+ * The types defined in `clash-prelude-hedgehog` now come with `Show` instances [#2133](https://github.com/clash-lang/clash-compiler/issues/2133)+ * Extreme values are now generated from the input range instead of the type's bounds [#2138](https://github.com/clash-lang/clash-compiler/issues/2138) -## 1.6.2 *Fed 25th 2022*+Internal change:+ * Clash now always generates non-extended identifiers for port names, so that generated names play nicer with different vendor tools. [#2142](https://github.com/clash-lang/clash-compiler/pull/2142)+ * Top entity name available in netlist context. Top entity name used in generated name for include files. [#2146](https://github.com/clash-lang/clash-compiler/pull/2146)+++## 1.6.2 *Feb 25th 2022* Fixed: * Clash now compiles for users of Clang - i.e., all macOS users. * The `trueDualPortBlockRam` model did not accurately simulate concurrent active ports, thus causing a Haskell/HDL simulation mismatch for `asyncFIFOSynchronizer`.
clash-prelude.cabal view
@@ -1,6 +1,6 @@ Cabal-version: 2.2 Name: clash-prelude-Version: 1.6.2+Version: 1.6.3 Synopsis: Clash: a functional hardware description language - Prelude library Description: Clash is a functional hardware description language that borrows both its@@ -393,11 +393,11 @@ base, bytestring, deepseq,- hedgehog >= 1.0.3 && < 1.1,+ hedgehog >= 1.0.3 && < 1.2, hint >= 0.7 && < 0.10, quickcheck-classes-base >= 0.6 && < 1.0, tasty >= 1.2 && < 1.5,- tasty-hedgehog,+ tasty-hedgehog >= 1.2.0, tasty-hunit, tasty-th, tasty-quickcheck,@@ -433,6 +433,7 @@ Hedgehog.Extra Test.Tasty.HUnit.Extra+ Test.Tasty.Hedgehog.Extra Test.QuickCheck.Extra benchmark benchmark-clash-prelude
src/Clash/Class/AutoReg/Internal.hs view
@@ -1,7 +1,7 @@ {-| Copyright : (C) 2019 , Google Inc.,- 2021 , QBayLogic B.V.- 2021 , Myrtle.ai+ 2021-2022, QBayLogic B.V.,+ 2021-2022, Myrtle.ai License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -107,7 +107,7 @@ class NFDataX a => AutoReg a where -- | For documentation see class 'AutoReg'. --- -- This is version with explicit clock/reset/enable,+ -- This is the version with explicit clock\/reset\/enable inputs, -- "Clash.Prelude" exports an implicit version of this: 'Clash.Prelude.autoReg' autoReg :: (HasCallStack, KnownDomain dom)@@ -389,6 +389,7 @@ [VarT _] -> False -- gets copied by "filter isOk" above [ConT _] -> False -- we can just drop constraints like: "AutoReg Bool => ..." [LitT _] -> False -- or "KnownNat 4 =>"+ [TupleT 0] -> False -- handle Unit () [_] -> error ( "Error while deriveAutoReg: don't know how to handle: " ++ pprint cls ++ " (" ++ pprint tys ++ ")" ) _ -> False -- see [NOTE: MultiParamTypeClasses]
src/Clash/Class/BitPack/Internal.hs view
@@ -1,7 +1,8 @@ {-| Copyright : (C) 2013-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2021, QBayLogic B.V.+ 2021, QBayLogic B.V.,+ 2022, Google Inc. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -142,10 +143,15 @@ => (a -> BitVector n) -> a -> BitVector n-packXWith f x =- unsafeDupablePerformIO (catch (f <$> evaluate x)+packXWith f = xToBV . f+{-# INLINE packXWith #-}++xToBV :: KnownNat n => BitVector n -> BitVector n+xToBV x =+ unsafeDupablePerformIO (catch (evaluate x) (\(XException _) -> return undefined#))-{-# NOINLINE packXWith #-}+{-# NOINLINE xToBV #-}+{-# ANN xToBV hasBlackBox #-} -- | Pack both arguments to a 'BitVector' and use -- 'Clash.Sized.Internal.BitVector.isLike#' to compare them. This is a more
src/Clash/Explicit/BlockRam.hs view
@@ -6,13 +6,13 @@ License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -BlockRAM primitives+Block RAM primitives = Using RAMs #usingrams# We will show a rather elaborate example on how you can, and why you might want-to use 'blockRam's. We will build a \"small\" CPU+Memory+Program ROM where we-will slowly evolve to using blockRams. Note that the code is /not/ meant as a+to use block RAMs. We will build a \"small\" CPU + Memory + Program ROM where we+will slowly evolve to using block RAMs. Note that the code is /not/ meant as a de-facto standard on how to do CPU design in Clash. We start with the definition of the Instructions, Register names and machine@@ -36,7 +36,7 @@ | Load MemAddr Reg | Store Reg MemAddr | Nop- deriving (Eq,Show)+ deriving (Eq, Show) data Reg = Zero@@ -46,10 +46,10 @@ | RegC | RegD | RegE- deriving (Eq,Show,Enum)+ deriving (Eq, Show, Enum, Generic, NFDataX) data Operator = Add | Sub | Incr | Imm | CmpGt- deriving (Eq,Show)+ deriving (Eq, Show) data MachCode = MachCode@@ -63,53 +63,60 @@ , jmpM :: Maybe Value } -nullCode = MachCode { inputX = Zero, inputY = Zero, result = Zero, aluCode = Imm- , ldReg = Zero, rdAddr = 0, wrAddrM = Nothing- , jmpM = Nothing- }+nullCode =+ MachCode+ { inputX = Zero+ , inputY = Zero+ , result = Zero+ , aluCode = Imm+ , ldReg = Zero+ , rdAddr = 0+ , wrAddrM = Nothing+ , jmpM = Nothing+ } @ Next we define the CPU and its ALU: @ cpu- :: Vec 7 Value- -- ^ Register bank- -> (Value,Instruction)- -- ^ (Memory output, Current instruction)+ :: Vec 7 Value -- ^ Register bank+ -> (Value,Instruction) -- ^ (Memory output, Current instruction) -> ( Vec 7 Value , (MemAddr, Maybe (MemAddr,Value), InstrAddr) )-cpu regbank (memOut,instr) = (regbank',(rdAddr,(,aluOut) '<$>' wrAddrM,fromIntegral ipntr))- where- -- Current instruction pointer- ipntr = regbank 'Clash.Sized.Vector.!!' PC+cpu regbank (memOut, instr) =+ (regbank', (rdAddr, (,aluOut) '<$>' wrAddrM, fromIntegral ipntr))+ where+ -- Current instruction pointer+ ipntr = regbank 'Clash.Sized.Vector.!!' PC - -- Decoder- (MachCode {..}) = case instr of- Compute op rx ry res -> nullCode {inputX=rx,inputY=ry,result=res,aluCode=op}- Branch cr a -> nullCode {inputX=cr,jmpM=Just a}- Jump a -> nullCode {aluCode=Incr,jmpM=Just a}- Load a r -> nullCode {ldReg=r,rdAddr=a}- Store r a -> nullCode {inputX=r,wrAddrM=Just a}- Nop -> nullCode+ -- Decoder+ (MachCode {..}) = case instr of+ Compute op rx ry res -> nullCode {inputX=rx,inputY=ry,result=res,aluCode=op}+ Branch cr a -> nullCode {inputX=cr,jmpM=Just a}+ Jump a -> nullCode {aluCode=Incr,jmpM=Just a}+ Load a r -> nullCode {ldReg=r,rdAddr=a}+ Store r a -> nullCode {inputX=r,wrAddrM=Just a}+ Nop -> nullCode - -- ALU- regX = regbank 'Clash.Sized.Vector.!!' inputX- regY = regbank 'Clash.Sized.Vector.!!' inputY- aluOut = alu aluCode regX regY+ -- ALU+ regX = regbank 'Clash.Sized.Vector.!!' inputX+ regY = regbank 'Clash.Sized.Vector.!!' inputY+ aluOut = alu aluCode regX regY - -- next instruction- nextPC = case jmpM of- Just a | aluOut /= 0 -> ipntr + a- _ -> ipntr + 1+ -- next instruction+ nextPC =+ case jmpM of+ Just a | aluOut /= 0 -> ipntr + a+ _ -> ipntr + 1 - -- update registers- regbank' = 'Clash.Sized.Vector.replace' Zero 0- $ 'Clash.Sized.Vector.replace' PC nextPC- $ 'Clash.Sized.Vector.replace' result aluOut- $ 'Clash.Sized.Vector.replace' ldReg memOut- $ regbank+ -- update registers+ regbank' = 'Clash.Sized.Vector.replace' Zero 0+ $ 'Clash.Sized.Vector.replace' PC nextPC+ $ 'Clash.Sized.Vector.replace' result aluOut+ $ 'Clash.Sized.Vector.replace' ldReg memOut+ $ regbank alu Add x y = x + y alu Sub x y = x - y@@ -132,14 +139,16 @@ -- ^ (write address, data in) -> Signal dom Value -- ^ data out-dataMem clk rst en rd wrM = 'Clash.Explicit.Mealy.mealy' clk rst en dataMemT ('Clash.Sized.Vector.replicate' d32 0) (bundle (rd,wrM))- where- dataMemT mem (rd,wrM) = (mem',dout)- where- dout = mem 'Clash.Sized.Vector.!!' rd- mem' = case wrM of- Just (wr,din) -> 'Clash.Sized.Vector.replace' wr din mem- _ -> mem+dataMem clk rst en rd wrM =+ 'Clash.Explicit.Mealy.mealy' clk rst en dataMemT ('Clash.Sized.Vector.replicate' d32 0) (bundle (rd,wrM))+ where+ dataMemT mem (rd,wrM) = (mem',dout)+ where+ dout = mem 'Clash.Sized.Vector.!!' rd+ mem' =+ case wrM of+ Just (wr,din) -> 'Clash.Sized.Vector.replace' wr din mem+ _ -> mem @ And then connect everything:@@ -154,10 +163,10 @@ -> Enable dom -> Signal dom Value system instrs clk rst en = memOut- where- memOut = dataMem clk rst en rdAddr dout- (rdAddr,dout,ipntr) = 'Clash.Explicit.Mealy.mealyB' clk rst en cpu ('Clash.Sized.Vector.replicate' d7 0) (memOut,instr)- instr = 'Clash.Explicit.Prelude.asyncRom' instrs '<$>' ipntr+ where+ memOut = dataMem clk rst en rdAddr dout+ (rdAddr,dout,ipntr) = 'Clash.Explicit.Mealy.mealyB' clk rst en cpu ('Clash.Sized.Vector.replicate' d7 0) (memOut,instr)+ instr = 'Clash.Explicit.Prelude.asyncRom' instrs '<$>' ipntr @ Create a simple program that calculates the GCD of 4 and 6:@@ -224,10 +233,10 @@ -> Enable dom -> Signal dom Value system2 instrs clk rst en = memOut- where- memOut = 'Clash.Explicit.RAM.asyncRam' clk clk en d32 rdAddr dout- (rdAddr,dout,ipntr) = 'Clash.Explicit.Prelude.mealyB' clk rst en cpu ('Clash.Sized.Vector.replicate' d7 0) (memOut,instr)- instr = 'Clash.Prelude.ROM.asyncRom' instrs '<$>' ipntr+ where+ memOut = 'Clash.Explicit.RAM.asyncRam' clk clk en d32 rdAddr dout+ (rdAddr,dout,ipntr) = 'Clash.Explicit.Prelude.mealyB' clk rst en cpu ('Clash.Sized.Vector.replicate' d7 0) (memOut,instr)+ instr = 'Clash.Prelude.ROM.asyncRom' instrs '<$>' ipntr @ Again, we can simulate our system and see that it works. This time however,@@ -247,62 +256,61 @@ Finally we get to using 'blockRam'. On FPGAs, 'Clash.Prelude.RAM.asyncRam' will be implemented in terms of LUTs, and therefore take up logic resources. FPGAs-also have large(r) memory structures called /Block RAMs/, which are preferred,+also have large(r) memory structures called /block RAMs/, which are preferred, especially as the memories we need for our application get bigger. The-'blockRam' function will be translated to such a /Block RAM/.+'blockRam' function will be translated to such a /block RAM/. -One important aspect of Block RAMs have a /synchronous/ read port, meaning that,-unlike the behavior of 'Clash.Prelude.RAM.asyncRam', given a read address @r@-at time @t@, the value @v@ in the RAM at address @r@ is only available at time-@t+1@.+One important aspect of block RAMs is that they have a /synchronous/ read port,+meaning unlike an 'Clash.Prelude.RAM.asyncRam', the result of a read command+given at time @t@ is output at time @t + 1@. For us that means we need to change the design of our CPU. Right now, upon a load instruction we generate a read address for the memory, and the value at-that read address is immediately available to be put in the register bank.-Because we will be using a BlockRAM, the value is delayed until the next cycle.-We hence need to also delay the register address to which the memory address-is loaded:+that read address is immediately available to be put in the register bank. We+will be using a block RAM, so the value is delayed until the next cycle. Thus,+we will also need to delay the register address to which the memory address is+loaded: @ cpu2- :: (Vec 7 Value,Reg)- -- ^ (Register bank, Load reg addr)- -> (Value,Instruction)- -- ^ (Memory output, Current instruction)- -> ( (Vec 7 Value,Reg)+ :: (Vec 7 Value,Reg) -- ^ (Register bank, Load reg addr)+ -> (Value,Instruction) -- ^ (Memory output, Current instruction)+ -> ( (Vec 7 Value, Reg) , (MemAddr, Maybe (MemAddr,Value), InstrAddr) )-cpu2 (regbank,ldRegD) (memOut,instr) = ((regbank',ldRegD'),(rdAddr,(,aluOut) '<$>' wrAddrM,fromIntegral ipntr))- where- -- Current instruction pointer- ipntr = regbank 'Clash.Sized.Vector.!!' PC+cpu2 (regbank, ldRegD) (memOut, instr) =+ ((regbank', ldRegD'), (rdAddr, (,aluOut) '<$>' wrAddrM, fromIntegral ipntr))+ where+ -- Current instruction pointer+ ipntr = regbank 'Clash.Sized.Vector.!!' PC - -- Decoder- (MachCode {..}) = case instr of- Compute op rx ry res -> nullCode {inputX=rx,inputY=ry,result=res,aluCode=op}- Branch cr a -> nullCode {inputX=cr,jmpM=Just a}- Jump a -> nullCode {aluCode=Incr,jmpM=Just a}- Load a r -> nullCode {ldReg=r,rdAddr=a}- Store r a -> nullCode {inputX=r,wrAddrM=Just a}- Nop -> nullCode+ -- Decoder+ (MachCode {..}) = case instr of+ Compute op rx ry res -> nullCode {inputX=rx,inputY=ry,result=res,aluCode=op}+ Branch cr a -> nullCode {inputX=cr,jmpM=Just a}+ Jump a -> nullCode {aluCode=Incr,jmpM=Just a}+ Load a r -> nullCode {ldReg=r,rdAddr=a}+ Store r a -> nullCode {inputX=r,wrAddrM=Just a}+ Nop -> nullCode - -- ALU- regX = regbank 'Clash.Sized.Vector.!!' inputX- regY = regbank 'Clash.Sized.Vector.!!' inputY- aluOut = alu aluCode regX regY+ -- ALU+ regX = regbank 'Clash.Sized.Vector.!!' inputX+ regY = regbank 'Clash.Sized.Vector.!!' inputY+ aluOut = alu aluCode regX regY - -- next instruction- nextPC = case jmpM of- Just a | aluOut /= 0 -> ipntr + a- _ -> ipntr + 1+ -- next instruction+ nextPC =+ case jmpM of+ Just a | aluOut /= 0 -> ipntr + a+ _ -> ipntr + 1 - -- update registers- ldRegD' = ldReg -- Delay the ldReg by 1 cycle- regbank' = 'Clash.Sized.Vector.replace' Zero 0- $ 'Clash.Sized.Vector.replace' PC nextPC- $ 'Clash.Sized.Vector.replace' result aluOut- $ 'Clash.Sized.Vector.replace' ldRegD memOut- $ regbank+ -- update registers+ ldRegD' = ldReg -- Delay the ldReg by 1 cycle+ regbank' = 'Clash.Sized.Vector.replace' Zero 0+ $ 'Clash.Sized.Vector.replace' PC nextPC+ $ 'Clash.Sized.Vector.replace' result aluOut+ $ 'Clash.Sized.Vector.replace' ldRegD memOut+ $ regbank @ We can now finally instantiate our system with a 'blockRam':@@ -317,17 +325,17 @@ -> Enable dom -> Signal dom Value system3 instrs clk rst en = memOut- where- memOut = 'blockRam' clk en (replicate d32 0) rdAddr dout- (rdAddr,dout,ipntr) = 'Clash.Explicit.Prelude.mealyB' clk rst en cpu2 (('Clash.Sized.Vector.replicate' d7 0),Zero) (memOut,instr)- instr = 'Clash.Explicit.Prelude.asyncRom' instrs '<$>' ipntr+ where+ memOut = 'blockRam' clk en (replicate d32 0) rdAddr dout+ (rdAddr,dout,ipntr) = 'Clash.Explicit.Prelude.mealyB' clk rst en cpu2 (('Clash.Sized.Vector.replicate' d7 0),Zero) (memOut,instr)+ instr = 'Clash.Explicit.Prelude.asyncRom' instrs '<$>' ipntr @ We are, however, not done. We will also need to update our program. The reason being that values that we try to load in our registers won't be loaded into the register until the next cycle. This is a problem when the next instruction-immediately depended on this memory value. In our case, this was only the case-when the loaded the value @6@, which was stored at address @1@, into @RegB@.+immediately depends on this memory value. In our example, this was only the case+when we loaded the value @6@, which was stored at address @1@, into @RegB@. Our updated program is thus: @@@ -394,7 +402,7 @@ {-# OPTIONS_GHC -fno-cpr-anal #-} module Clash.Explicit.BlockRam- ( -- * BlockRAM synchronized to the system clock+ ( -- * Block RAM synchronized to an arbitrary clock blockRam , blockRamPow2 , blockRamU@@ -408,6 +416,8 @@ , RamOp(..) -- * Internal , blockRam#+ , blockRamU#+ , blockRam1# , trueDualPortBlockRam# ) where@@ -729,12 +739,24 @@ -} --- | Create a blockRAM with space for @n@ elements+-- | Create a block RAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'XException' --+-- === See also:+--+-- * See "Clash.Explicit.BlockRam#usingrams" for more information on how to use a+-- block RAM.+-- * Use the adapter 'readNew' for obtaining write-before-read semantics like+-- this: @'readNew' clk rst en ('blockRam' clk inits) rd wrM@.+-- * A large 'Vec' for the initial content may be too inefficient, depending+-- on how it is constructed. See 'Clash.Explicit.BlockRam.File.blockRamFile' and+-- 'Clash.Explicit.BlockRam.Blob.blockRamBlob' for different approaches that+-- scale well.+--+-- === __Example__ -- @ -- bram40 -- :: 'Clock' dom@@ -744,16 +766,6 @@ -- -> 'Signal' dom 'Clash.Sized.BitVector.Bit' -- bram40 clk en = 'blockRam' clk en ('Clash.Sized.Vector.replicate' d40 1) -- @------ Additional helpful information:------ * See "Clash.Explicit.BlockRam#usingrams" for more information on how to use a--- Block RAM.--- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @'readNew' clk rst ('blockRam' clk inits) rd wrM@.--- * A large 'Vec' for the initial content might be too inefficient, depending--- on how it is constructed. See 'Clash.Explicit.BlockRam.File.blockRamFile' and--- 'Clash.Explicit.BlockRam.Blob.blockRamBlob' for different approaches that--- scale well. blockRam :: ( KnownDomain dom , HasCallStack@@ -762,17 +774,17 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> Vec n a- -- ^ Initial content of the BRAM, also determines the size, @n@, of the BRAM.+ -- ^ Initial content of the BRAM, also determines the size, @n@, of the BRAM --- -- __NB__: __MUST__ be a constant.+ -- __NB__: __MUST__ be a constant -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRam = \clk gen content rd wrM -> let en = isJust <$> wrM (wr,din) = unbundle (fromJustX <$> wrM)@@ -780,12 +792,24 @@ (blockRam# clk gen content (fromEnum <$> rd) en (fromEnum <$> wr) din) {-# INLINE blockRam #-} --- | Create a blockRAM with space for 2^@n@ elements+-- | Create a block RAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'XException' --+-- === See also:+--+-- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a+-- block RAM.+-- * Use the adapter 'readNew' for obtaining write-before-read semantics like+-- this: @'readNew' clk rst en ('blockRamPow2' clk inits) rd wrM@.+-- * A large 'Vec' for the initial content may be too inefficient, depending+-- on how it is constructed. See 'Clash.Explicit.BlockRam.File.blockRamFilePow2'+-- and 'Clash.Explicit.BlockRam.Blob.blockRamBlobPow2' for different approaches+-- that scale well.+--+-- === __Example__ -- @ -- bram32 -- :: 'Clock' dom@@ -795,16 +819,6 @@ -- -> 'Signal' dom 'Clash.Sized.BitVector.Bit' -- bram32 clk en = 'blockRamPow2' clk en ('Clash.Sized.Vector.replicate' d32 1) -- @------ Additional helpful information:------ * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.--- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @'readNew' clk rst ('blockRamPow2' clk inits) rd wrM@.--- * A large 'Vec' for the initial content might be too inefficient, depending--- on how it is constructed. See 'Clash.Explicit.BlockRam.File.blockRamFilePow2'--- and 'Clash.Explicit.BlockRam.Blob.blockRamBlobPow2' for different approaches--- that scale well. blockRamPow2 :: ( KnownDomain dom , HasCallStack@@ -813,18 +827,17 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> Vec (2^n) a -- ^ Initial content of the BRAM --- -- __NB__: __MUST__ be a constant.+ -- __NB__: __MUST__ be a constant -> Signal dom (Unsigned n) -- ^ Read address @r@ -> Signal dom (Maybe (Unsigned n, a)) -- ^ (Write address @w@, value to write) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous- -- clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamPow2 = \clk en cnt rd wrM -> withFrozenCallStack (blockRam clk en cnt rd wrM) {-# INLINE blockRamPow2 #-}@@ -833,8 +846,8 @@ ClearOnReset :: ResetStrategy 'True NoClearOnReset :: ResetStrategy 'False --- | Version of blockram that has no default values set. May be cleared to an--- arbitrary state using a reset function.+-- | A version of 'blockRam' that has no default values set. May be cleared to+-- an arbitrary state using a reset function. blockRamU :: forall n dom a r addr . ( KnownDomain dom@@ -845,24 +858,24 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Reset dom- -- ^ 'Reset' line to listen to. Needs to be held at least /n/ cycles in order+ -- ^ 'Reset' line. This needs to be asserted for at least /n/ cycles in order -- for the BRAM to be reset to its initial state. -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> ResetStrategy r -- ^ Whether to clear BRAM on asserted reset ('ClearOnReset') or- -- not ('NoClearOnReset'). Reset needs to be asserted at least /n/ cycles to- -- clear the BRAM.+ -- not ('NoClearOnReset'). The reset needs to be asserted for at least /n/+ -- cycles to clear the BRAM. -> SNat n -- ^ Number of elements in BRAM -> (Index n -> a)- -- ^ If applicable (see 'ResetStrategy' argument), reset BRAM using this function.+ -- ^ If applicable (see 'ResetStrategy' argument), reset BRAM using this function -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamU clk rst0 en rstStrategy n@SNat initF rd0 mw0 = case rstStrategy of ClearOnReset ->@@ -900,7 +913,7 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global Enable+ -- ^ 'Enable' line -> SNat n -- ^ Number of elements in BRAM -> Signal dom Int@@ -912,7 +925,7 @@ -> Signal dom a -- ^ Value to write (at address @w@) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamU# clk en SNat = -- TODO: Generalize to single BRAM primitive taking an initialization function blockRam#@@ -924,8 +937,8 @@ {-# NOINLINE blockRamU# #-} {-# ANN blockRamU# hasBlackBox #-} --- | Version of blockram that is initialized with the same value on all--- memory positions.+-- | A version of 'blockRam' that is initialized with the same value on all+-- memory positions blockRam1 :: forall n dom a r addr . ( KnownDomain dom@@ -936,14 +949,14 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Reset dom- -- ^ 'Reset' line to listen to. Needs to be held at least /n/ cycles in order+ -- ^ 'Reset' line. This needs to be asserted for at least /n/ cycles in order -- for the BRAM to be reset to its initial state. -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> ResetStrategy r -- ^ Whether to clear BRAM on asserted reset ('ClearOnReset') or- -- not ('NoClearOnReset'). Reset needs to be asserted at least /n/ cycles to- -- clear the BRAM.+ -- not ('NoClearOnReset'). The reset needs to be asserted for at least /n/+ -- cycles to clear the BRAM. -> SNat n -- ^ Number of elements in BRAM -> a@@ -953,7 +966,7 @@ -> Signal dom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRam1 clk rst0 en rstStrategy n@SNat a rd0 mw0 = case rstStrategy of ClearOnReset ->@@ -991,7 +1004,7 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global Enable+ -- ^ 'Enable' line -> SNat n -- ^ Number of elements in BRAM -> a@@ -1005,7 +1018,7 @@ -> Signal dom a -- ^ Value to write (at address @w@) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRam1# clk en n a = -- TODO: Generalize to single BRAM primitive taking an initialization function blockRam# clk en (replicate n a)@@ -1021,12 +1034,11 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> Vec n a- -- ^ Initial content of the BRAM, also- -- determines the size, @n@, of the BRAM.+ -- ^ Initial content of the BRAM, also determines the size, @n@, of the BRAM --- -- __NB__: __MUST__ be a constant.+ -- __NB__: __MUST__ be a constant -> Signal dom Int -- ^ Read address @r@ -> Signal dom Bool@@ -1036,7 +1048,7 @@ -> Signal dom a -- ^ Value to write (at address @w@) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRam# (Clock _) gen content = \rd wen waS wd -> runST $ do ramStart <- newListArray (0,szI-1) contentL -- start benchmark only@@ -1108,7 +1120,7 @@ {-# ANN blockRam# hasBlackBox #-} {-# NOINLINE blockRam# #-} --- | Create read-after-write blockRAM from a read-before-write one+-- | Create a read-after-write block RAM from a read-before-write one readNew :: ( KnownDomain dom , NFDataX a@@ -1117,13 +1129,13 @@ -> Reset dom -> Enable dom -> (Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a)- -- ^ The @ram@ component+ -- ^ The BRAM component -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, a)) -- ^ (Write address @w@, value to write) -> Signal dom a- -- ^ Value of the @ram@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle readNew clk rst en ram rdAddr wrM = mux wasSame wasWritten $ ram rdAddr wrM where readNewT rd (Just (wr, wrdata)) = (wr == rd, wrdata) readNewT _ Nothing = (False , undefined)
src/Clash/Explicit/BlockRam/Blob.hs view
@@ -5,7 +5,7 @@ = Efficient bundling of initial RAM content with the compiled code -Leveraging Template Haskell, the initial content for the blockRAM components in+Leveraging Template Haskell, the initial content for the block RAM components in this module is stored alongside the compiled Haskell code. It covers use cases where passing the initial content as a 'Clash.Sized.Vector.Vec' turns out to be problematically slow.@@ -25,7 +25,7 @@ {-# OPTIONS_HADDOCK show-extensions #-} module Clash.Explicit.BlockRam.Blob- ( -- * BlockRAMs initialized with a 'MemBlob'+ ( -- * Block RAMs initialized with a 'MemBlob' blockRamBlob , blockRamBlobPow2 -- * Creating and inspecting 'MemBlob'@@ -71,17 +71,17 @@ -- >>> :m -Prelude -- >>> import Clash.Explicit.Prelude --- | Create a blockRAM with space for @n@ elements+-- | Create a block RAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' -- ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.+-- block RAM. -- * Use the adapter 'Clash.Explicit.BlockRam.readNew' for obtaining -- write-before-read semantics like this: @'Clash.Explicit.BlockRam.readNew' -- clk rst en ('blockRamBlob' clk en content) rd wrM@.@@ -95,7 +95,7 @@ -> Enable dom -- ^ 'Enable' line -> MemBlob n m- -- ^ Initial content of the RAM, also determines the size, @n@, of the RAM+ -- ^ Initial content of the BRAM, also determines the size, @n@, of the BRAM -- -- __NB__: __MUST__ be a constant -> Signal dom addr@@ -103,23 +103,23 @@ -> Signal dom (Maybe (addr, BitVector m)) -- ^ (write address @w@, value to write) -> Signal dom (BitVector m)- -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamBlob = \clk gen content rd wrM -> let en = isJust <$> wrM (wr,din) = unbundle (fromJustX <$> wrM) in blockRamBlob# clk gen content (fromEnum <$> rd) en (fromEnum <$> wr) din {-# INLINE blockRamBlob #-} --- | Create a blockRAM with space for 2^@n@ elements+-- | Create a block RAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.+-- block RAM. -- * Use the adapter 'Clash.Explicit.BlockRam.readNew' for obtaining -- write-before-read semantics like this: @'Clash.Explicit.BlockRam.readNew' -- clk rst en ('blockRamBlobPow2' clk en content) rd wrM@.@@ -133,7 +133,7 @@ -> Enable dom -- ^ 'Enable' line -> MemBlob (2^n) m- -- ^ Initial content of the RAM, also determines the size, 2^@n@, of the RAM+ -- ^ Initial content of the BRAM, also determines the size, 2^@n@, of the BRAM -- -- __NB__: __MUST__ be a constant -> Signal dom (Unsigned n)@@ -141,11 +141,11 @@ -> Signal dom (Maybe (Unsigned n, BitVector m)) -- ^ (write address @w@, value to write) -> Signal dom (BitVector m)- -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamBlobPow2 = blockRamBlob {-# INLINE blockRamBlobPow2 #-} --- | BlockRAM primitive+-- | blockRAMBlob primitive blockRamBlob# :: forall dom m n . KnownDomain dom@@ -154,7 +154,7 @@ -> Enable dom -- ^ 'Enable' line -> MemBlob n m- -- ^ Initial content of the RAM, also determines the size, @n@, of the RAM+ -- ^ Initial content of the BRAM, also determines the size, @n@, of the BRAM -- -- __NB__: __MUST__ be a constant -> Signal dom Int@@ -166,7 +166,7 @@ -> Signal dom (BitVector m) -- ^ Value to write (at address @w@) -> Signal dom (BitVector m)- -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamBlob# !_ gen content@MemBlob{} = \rd wen waS wd -> runST $ do bvList <- unsafeIOToST (unpackMemBlob0 content) ramStart <- newListArray (0,szI-1) bvList
src/Clash/Explicit/BlockRam/File.hs view
@@ -6,9 +6,9 @@ License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -= Initializing a BlockRAM with a data file #usingramfiles#+= Initializing a block RAM with a data file #usingramfiles# -BlockRAM primitives that can be initialized with a data file. The BNF grammar+Block RAM primitives that can be initialized with a data file. The BNF grammar for this data file is simple: @@@ -19,7 +19,7 @@ @ Consecutive @LINE@s correspond to consecutive memory addresses starting at @0@.-For example, a data file @memory.bin@ containing the 9-bit unsigned number+For example, a data file @memory.bin@ containing the 9-bit unsigned numbers @7@ to @13@ looks like: @@@ -38,17 +38,18 @@ writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13]) @ -We can instantiate a BlockRAM using the content of the above file like so:+We can instantiate a block RAM using the contents of the file above like so: @-f :: Clock dom+f :: KnownDomain dom+ => Clock dom -> Enable dom -> Signal dom (Unsigned 3) -> Signal dom (Unsigned 9)-f clk ena rd = 'Clash.Class.BitPack.unpack' '<$>' 'blockRamFile' clk ena d7 \"memory.bin\" rd (signal Nothing)+f clk en rd = 'Clash.Class.BitPack.unpack' '<$>' 'blockRamFile' clk en d7 \"memory.bin\" rd (signal Nothing) @ -In the example above, we basically treat the BlockRAM as an synchronous ROM.+In the example above, we basically treat the block RAM as a synchronous ROM. We can see that it works as expected: @@@ -61,11 +62,12 @@ number, and a 3-bit signed number: @-g :: Clock dom+g :: KnownDomain dom+ => Clock dom -> Enable dom -> Signal dom (Unsigned 3) -> Signal dom (Unsigned 6,Signed 3)-g clk ena rd = 'Clash.Class.BitPack.unpack' '<$>' 'blockRamFile' clk ena d7 \"memory.bin\" rd (signal Nothing)+g clk en rd = 'Clash.Class.BitPack.unpack' '<$>' 'blockRamFile' clk en d7 \"memory.bin\" rd (signal Nothing) @ And then we would see:@@ -91,7 +93,7 @@ {-# OPTIONS_GHC -fno-cpr-anal #-} module Clash.Explicit.BlockRam.File- ( -- * BlockRAM synchronized to an arbitrary clock+ ( -- * Block RAM synchronized to an arbitrary clock blockRamFile , blockRamFilePow2 -- * Producing files@@ -138,7 +140,7 @@ -- >>> import Clash.Prelude.BlockRam.File --- | Create a blockRAM with space for 2^@n@ elements+-- | Create a block RAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an@@ -147,22 +149,23 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.+-- block RAM. -- * Use the adapter 'Clash.Explicit.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Explicit.BlockRam.readNew' clk rst en (blockRamFilePow2' clk en file) rd wrM@. -- * See "Clash.Explicit.BlockRam.File#usingramfiles" for more information on how--- to instantiate a Block RAM with the contents of a data file.+-- to instantiate a block RAM with the contents of a data file. -- * See 'memFile' for creating a data file with Clash. -- * See "Clash.Explicit.Fixed#creatingdatafiles" for more ideas on how to -- create your own data files.@@ -172,20 +175,20 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> FilePath- -- ^ File describing the initial content of the blockRAM+ -- ^ File describing the initial content of the BRAM -> Signal dom (Unsigned n) -- ^ Read address @r@ -> Signal dom (Maybe (Unsigned n, BitVector m)) -- ^ (write address @w@, value to write) -> Signal dom (BitVector m)- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamFilePow2 = \clk en file rd wrM -> withFrozenCallStack (blockRamFile clk en (pow2SNat (SNat @n)) file rd wrM) {-# INLINE blockRamFilePow2 #-} --- | Create a blockRAM with space for @n@ elements+-- | Create a block RAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an@@ -194,22 +197,23 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Explicit.BlockRam#usingrams" for more information on how to use a--- Block RAM.+-- block RAM. -- * Use the adapter 'Clash.Explicit.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Explicit.BlockRam.readNew' clk rst en ('blockRamFile' clk en size file) rd wrM@. -- * See "Clash.Explicit.BlockRam.File#usingramfiles" for more information on how--- to instantiate a Block RAM with the contents of a data file.+-- to instantiate a block RAM with the contents of a data file. -- * See 'memFile' for creating a data file with Clash. -- * See "Clash.Sized.Fixed#creatingdatafiles" for more ideas on how to create -- your own data files.@@ -218,18 +222,17 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> SNat n- -- ^ Size of the blockRAM+ -- ^ Size of the BRAM -> FilePath- -- ^ File describing the initial content of the blockRAM+ -- ^ File describing the initial content of the BRAM -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, BitVector m)) -- ^ (write address @w@, value to write) -> Signal dom (BitVector m)- -- ^ Value of the @blockRAM@ at address @r@ from the previous- -- clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamFile = \clk gen sz file rd wrM -> let en = isJust <$> wrM (wr,din) = unbundle (fromJustX <$> wrM)@@ -237,9 +240,9 @@ (blockRamFile# clk gen sz file (fromEnum <$> rd) en (fromEnum <$> wr) din) {-# INLINE blockRamFile #-} --- | Convert data to the String contents of a memory file.+-- | Convert data to the 'String' contents of a memory file. ----- * __NB:__ Not synthesizable+-- * __NB__: Not synthesizable -- * The following document the several ways to instantiate components with -- files: --@@ -277,12 +280,12 @@ , Foldable f , HasCallStack) => Maybe Bit- -- ^ Value to map don't care bits to. Nothing means throwing an error on+ -- ^ Value to map don't care bits to. 'Nothing' means throwing an error on -- don't care bits. -> f a- -- ^ Values to convert.+ -- ^ Values to convert -> String- -- ^ Contents of the memory file.+ -- ^ Contents of the memory file memFile care = foldr (\e -> showsBV $ pack e) "" where showsBV :: BitVector (BitSize a) -> String -> String@@ -318,11 +321,11 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> SNat n- -- ^ Size of the blockRAM+ -- ^ Size of the BRAM -> FilePath- -- ^ File describing the initial content of the blockRAM+ -- ^ File describing the initial content of the BRAM -> Signal dom Int -- ^ Read address @r@ -> Signal dom Bool@@ -332,7 +335,7 @@ -> Signal dom (BitVector m) -- ^ Value to write (at address @w@) -> Signal dom (BitVector m)- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamFile# (Clock _) ena sz file = \rd wen waS wd -> runST $ do ramStart <- newArray_ (0,szI) unsafeIOToST (withFile file ReadMode (\h ->
src/Clash/Explicit/Mealy.hs view
@@ -80,8 +80,8 @@ -- -> 'Signal' dom Int -- dualMac clk rst en (a,b) (x,y) = s1 + s2 -- where--- s1 = 'mealy' clk rst en mac 0 ('bundle' (a,x))--- s2 = 'mealy' clk rst en mac 0 ('bundle' (b,y))+-- s1 = 'mealy' clk rst en macT 0 ('bundle' (a,x))+-- s2 = 'mealy' clk rst en macT 0 ('bundle' (b,y)) -- @ mealy :: ( KnownDomain dom
src/Clash/Explicit/Moore.hs view
@@ -72,8 +72,8 @@ -- -> 'Signal' dom Int -- dualMac clk rst en (a,b) (x,y) = s1 + s2 -- where--- s1 = 'moore' clk rst en mac id 0 ('bundle' (a,x))--- s2 = 'moore' clk rst en mac id 0 ('bundle' (b,y))+-- s1 = 'moore' clk rst en macT id 0 ('bundle' (a,x))+-- s2 = 'moore' clk rst en macT id 0 ('bundle' (b,y)) -- @ moore :: ( KnownDomain dom
src/Clash/Explicit/Prelude.hs view
@@ -45,13 +45,13 @@ -- * RAM primitives with a combinational read port , asyncRam , asyncRamPow2- -- * BlockRAM primitives+ -- * Block RAM primitives , blockRam , blockRamPow2 , blockRamU , blockRam1 , ResetStrategy(..)- -- ** BlockRAM primitives initialized with a 'MemBlob'+ -- ** Block RAM primitives initialized with a 'MemBlob' , blockRamBlob , blockRamBlobPow2 -- *** Creating and inspecting 'MemBlob'@@ -59,10 +59,10 @@ , createMemBlob , memBlobTH , unpackMemBlob- -- ** BlockRAM primitives initialized with a data file+ -- ** Block RAM primitives initialized with a data file , blockRamFile , blockRamFilePow2- -- ** BlockRAM read/write conflict resolution+ -- ** Block RAM read/write conflict resolution , readNew -- ** True dual-port block RAM , trueDualPortBlockRam
src/Clash/Explicit/Prelude/Safe.hs view
@@ -42,10 +42,10 @@ -- * RAM primitives with a combinational read port , asyncRam , asyncRamPow2- -- * BlockRAM primitives+ -- * Block RAM primitives , blockRam , blockRamPow2- -- ** BlockRAM primitives initialized with a 'MemBlob'+ -- ** Block RAM primitives initialized with a 'MemBlob' , blockRamBlob , blockRamBlobPow2 -- *** Creating and inspecting 'MemBlob'@@ -53,7 +53,7 @@ , createMemBlob , memBlobTH , unpackMemBlob- -- ** BlockRAM read/write conflict resolution+ -- ** Block RAM read/write conflict resolution , readNew -- ** True dual-port block RAM , trueDualPortBlockRam
src/Clash/Explicit/RAM.hs view
@@ -49,7 +49,7 @@ -- * __NB__: Initial content of the RAM is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a -- RAM.@@ -62,17 +62,17 @@ , NFDataX a ) => Clock wdom- -- ^ 'Clock' to which to synchronize the write port of the RAM+ -- ^ 'Clock' to which the write port of the RAM is synchronized -> Clock rdom- -- ^ 'Clock' to which the read address signal, @r@, is synchronized+ -- ^ 'Clock' to which the read address signal, @r@, is synchronized -> Enable wdom- -- ^ Global enable+ -- ^ 'Enable' line for the write port -> Signal rdom (Unsigned n) -- ^ Read address @r@ -> Signal wdom (Maybe (Unsigned n, a)) -- ^ (write address @w@, value to write) -> Signal rdom a- -- ^ Value of the @RAM@ at address @r@+ -- ^ Value of the RAM at address @r@ asyncRamPow2 = \wclk rclk en rd wrM -> withFrozenCallStack (asyncRam wclk rclk en (pow2SNat (SNat @n)) rd wrM) {-# INLINE asyncRamPow2 #-}@@ -83,7 +83,7 @@ -- * __NB__: Initial content of the RAM is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Explicit.BlockRam#usingrams" for more information on how to use a -- RAM.@@ -95,11 +95,11 @@ , NFDataX a ) => Clock wdom- -- ^ 'Clock' to which to synchronize the write port of the RAM+ -- ^ 'Clock' to which the write port of the RAM is synchronized -> Clock rdom- -- ^ 'Clock' to which the read address signal, @r@, is synchronized to+ -- ^ 'Clock' to which the read address signal, @r@, is synchronized -> Enable wdom- -- ^ Global enable+ -- ^ 'Enable' line for the write port -> SNat n -- ^ Size @n@ of the RAM -> Signal rdom addr@@ -107,7 +107,7 @@ -> Signal wdom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal rdom a- -- ^ Value of the @RAM@ at address @r@+ -- ^ Value of the RAM at address @r@ asyncRam = \wclk rclk gen sz rd wrM -> let en = isJust <$> wrM (wr,din) = unbundle (fromJustX <$> wrM)@@ -124,11 +124,11 @@ , NFDataX a ) => Clock wdom- -- ^ 'Clock' to which to synchronize the write port of the RAM+ -- ^ 'Clock' to which the write port of the RAM is synchronized -> Clock rdom- -- ^ 'Clock' to which the read address signal, @r@, is synchronized+ -- ^ 'Clock' to which the read address signal, @r@, is synchronized -> Enable wdom- -- ^ Global enable+ -- ^ 'Enable' line for the write port -> SNat n -- ^ Size @n@ of the RAM -> Signal rdom Int@@ -140,12 +140,12 @@ -> Signal wdom a -- ^ Value to write (at address @w@) -> Signal rdom a- -- ^ Value of the @RAM@ at address @r@+ -- ^ Value of the RAM at address @r@ asyncRam# !_ !_ en sz rd we wr din = dout where ramI = Seq.replicate szI- (withFrozenCallStack (errorX "asyncRam#: initial value undefined"))+ (withFrozenCallStack (errorX "asyncRam: initial value undefined")) en0 = fromEnable (andEnable en we) dout = if rPeriod == wPeriod then goSingle ramI rd en0 wr din
src/Clash/Explicit/ROM.hs view
@@ -46,11 +46,11 @@ -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Explicit.BlockRam#usingrams"--- for ideas on how to use ROMs and RAMs--- * A large 'Vec' for the content might be too inefficient, depending on how it+-- for ideas on how to use ROMs and RAMs.+-- * A large 'Vec' for the content may be too inefficient, depending on how it -- is constructed. See 'Clash.Explicit.ROM.File.romFilePow2' and -- 'Clash.Explicit.ROM.Blob.romBlobPow2' for different approaches that scale -- well.@@ -59,15 +59,15 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> Vec (2^n) a -- ^ ROM content --- -- __NB:__ must be a constant+ -- __NB__: __MUST__ be a constant -> Signal dom (Unsigned n)- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom a- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ from the previous clock cycle romPow2 = rom {-# INLINE romPow2 #-} @@ -77,11 +77,11 @@ -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Explicit.BlockRam#usingrams"--- for ideas on how to use ROMs and RAMs--- * A large 'Vec' for the content might be too inefficient, depending on how it+-- for ideas on how to use ROMs and RAMs.+-- * A large 'Vec' for the content may be too inefficient, depending on how it -- is constructed. See 'Clash.Explicit.ROM.File.romFile' and -- 'Clash.Explicit.ROM.Blob.romBlob' for different approaches that scale well. rom@@ -89,15 +89,15 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> Vec n a -- ^ ROM content, also determines the size, @n@, of the ROM --- -- __NB:__ must be a constant+ -- __NB__: __MUST__ be a constant -> Signal dom addr- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom a- -- ^ The value of the ROM at address @rd@ from the previous clock cycle+ -- ^ The value of the ROM at address @r@ from the previous clock cycle rom = \clk en content rd -> rom# clk en content (fromEnum <$> rd) {-# INLINE rom #-} @@ -108,11 +108,11 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> Vec n a -- ^ ROM content, also determines the size, @n@, of the ROM --- -- __NB:__ must be a constant+ -- __NB__: __MUST__ be a constant -> Signal dom Int -- ^ Read address @rd@ -> Signal dom a
src/Clash/Explicit/ROM/Blob.hs view
@@ -57,10 +57,10 @@ -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and--- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs+-- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs. romBlob :: forall dom addr m n . ( KnownDomain dom@@ -87,10 +87,10 @@ -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and--- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs+-- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs. romBlobPow2 :: forall dom m n . ( KnownDomain dom
src/Clash/Explicit/ROM/File.hs view
@@ -18,7 +18,7 @@ @ Consecutive @LINE@s correspond to consecutive memory addresses starting at @0@.-For example, a data file @memory.bin@ containing the 9-bit unsigned number+For example, a data file @memory.bin@ containing the 9-bit unsigned numbers @7@ to @13@ looks like: @@@ -37,15 +37,16 @@ writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13]) @ -We can instantiate a synchronous ROM using the content of the above file like+We can instantiate a synchronous ROM using the contents of the file above like so: @-f :: Clock dom+f :: KnownDomain dom+ => Clock dom -> Enable dom -> Signal dom (Unsigned 3) -> Signal dom (Unsigned 9)-f clk ena rd = 'Clash.Class.BitPack.unpack' '<$>' 'romFile' clk ena d7 \"memory.bin\" rd+f clk en rd = 'Clash.Class.BitPack.unpack' '<$>' 'romFile' clk en d7 \"memory.bin\" rd @ And see that it works as expected:@@ -60,11 +61,11 @@ number, and a 3-bit signed number: @-g :: Clock dom- -> Enable dom+g :: KnownDomain dom+ => Clock dom -> Signal dom (Unsigned 3) -> Signal dom (Unsigned 6,Signed 3)-g clk ena rd = 'Clash.Class.BitPack.unpack' '<$>' 'romFile' clk ena d7 \"memory.bin\" rd+g clk en rd = 'Clash.Class.BitPack.unpack' '<$>' 'romFile' clk en d7 \"memory.bin\" rd @ And then we would see:@@ -116,16 +117,17 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Explicit.ROM.File#usingromfiles" for more information on how -- to instantiate a ROM with the contents of a data file.@@ -138,14 +140,13 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> FilePath- -- ^ File describing the content of- -- the ROM+ -- ^ File describing the content of the ROM -> Signal dom (Unsigned n)- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom (BitVector m)- -- ^ The value of the ROM at address @rd@ from the previous clock cycle+ -- ^ The value of the ROM at address @r@ from the previous clock cycle romFilePow2 = \clk en -> romFile clk en (pow2SNat (SNat @n)) {-# INLINE romFilePow2 #-} @@ -158,19 +159,21 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Explicit.ROM.File#usingromfiles" for more information on how -- to instantiate a ROM with the contents of a data file.+-- * See 'memFile' for creating a data file with Clash. -- * See "Clash.Sized.Fixed#creatingdatafiles" for ideas on how to create your -- own data files. romFile@@ -178,15 +181,15 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> SNat n -- ^ Size of the ROM -> FilePath -- ^ File describing the content of the ROM -> Signal dom addr- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom (BitVector m)- -- ^ The value of the ROM at address @rd@ from the previous clock cycle+ -- ^ The value of the ROM at address @r@ from the previous clock cycle romFile = \clk en sz file rd -> romFile# clk en sz file (fromEnum <$> rd) {-# INLINE romFile #-} @@ -197,15 +200,15 @@ => Clock dom -- ^ 'Clock' to synchronize to -> Enable dom- -- ^ Global enable+ -- ^ 'Enable' line -> SNat n -- ^ Size of the ROM -> FilePath -- ^ File describing the content of the ROM -> Signal dom Int- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom (BitVector m)- -- ^ The value of the ROM at address @rd@ from the previous clock cycle+ -- ^ The value of the ROM at address @r@ from the previous clock cycle romFile# clk en sz file rd = delay clk en (deepErrorX "First value of romFile is undefined") (safeAt <$> rd)
src/Clash/Intel/ClockGen.hs view
@@ -6,6 +6,23 @@ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> PLL and other clock-related components for Intel (Altera) FPGAs++A PLL generates a stable clock signal for your circuit at a selectable+frequency.++If you haven't determined the frequency you want the circuit to run at, the+predefined 100 MHz domain `Clash.Signal.System` can be a good starting point.+The datasheet for your FPGA specifies lower and upper limits, but the true+maximum frequency is determined by your circuit. The 'altpll' and 'alteraPll'+components below show an example for when the oscillator connected to the FPGA+runs at 50 MHz. If the oscillator runs at 100 MHz, change @DomInput@ to:++@+'Clash.Signal.createDomain' 'Clash.Signal.vSystem'{vName=\"DomInput\", vPeriod=10000}+@++We suggest you always use a PLL even if your oscillator runs at the frequency+you want to run your circuit at. -} {-# LANGUAGE FlexibleContexts #-}@@ -31,28 +48,66 @@ -- -- * 1 reference clock -- * 1 output clock--- * a reset port--- * a locked port+-- * a reset input port+-- * a locked output port ----- You must use type applications to specify the output clock domain, e.g.:+-- The PLL lock output is asserted when the clock is stable, and is usually+-- connected to reset circuitry to keep the circuit in reset while the clock is+-- still stabilizing. --+-- See also the [ALTPLL (Phase-Locked Loop) IP Core User Guide](https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_altpll.pdf)+--+-- === Example+--+-- ==== Using a PLL+--+-- When the oscillator connected to the FPGA runs at 50 MHz and the external+-- reset signal is /active low/, this will generate a 100 MHz clock for the+-- @'Clash.Signal.System'@ domain:+-- -- @--- -- outputs a clock running at 100 MHz--- altpll @@"50MHzDom" @@"100MHzDom" (SSymbol @@"altpll50to100") clk50 rst+-- 'Clash.Signal.createDomain' 'Clash.Signal.vSystem'{vName=\"DomInput\", vPeriod=20000}+--+-- topEntity+-- :: 'Clock' DomInput+-- -> 'Signal' DomInput 'Bool'+-- -> [...]+-- topEntity clkInp rstInp = [...]+-- where+-- (clk, pllStable) =+-- 'altpll' \@'Clash.Signal.System' ('SSymbol' \@\"altpll50to100\") clkInp+-- ('Clash.Signal.unsafeFromLowPolarity' rstInp)+-- rst = 'Clash.Signal.resetSynchronizer' clk ('Clash.Signal.unsafeFromLowPolarity' pllStable) -- @ ----- See also the [ALTPLL (Phase-Locked Loop) IP Core User Guide](https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_altpll.pdf)+-- 'Clash.Signal.resetSynchronizer' will keep the reset asserted when+-- @pllStable@ is 'False', hence the use of+-- @'Clash.Signal.unsafeFromLowPolarity' pllStable@. Your circuit will have+-- signals of type @'Signal' 'Clash.Signal.System'@ and all the clocks and+-- resets of your components will be the @clk@ and @rst@ signals generated here+-- (modulo local resets, which will be based on @rst@ or never asserted at all+-- if the component doesn't need a reset).+--+-- ==== Specifying the output frequency+--+-- If you don't have a top-level type signature specifying the output clock+-- domain, you can use type applications to specify it, e.g.:+--+-- @+-- 'Clash.Signal.createDomain' 'Clash.Signal.vSystem'{vName=\"Dom100MHz\", vPeriod=10000}+--+-- -- outputs a clock running at 100 MHz+-- (clk100, pllLocked) = 'altpll' \@Dom100MHz ('SSymbol' \@\"altpll50to100\") clk50 rst50+-- @ altpll :: forall domOut domIn name . (KnownDomain domIn, KnownDomain domOut) => SSymbol name- -- ^ Name of the component instance.- --- -- Instantiate as follows:+ -- ^ Name of the component instance --- -- > SSymbol @"altPLL50"+ -- Instantiate as follows: @(SSymbol \@\"altpll50\")@ -> Clock domIn- -- ^ Free running clock (i.e. a clock pin connected to a crystal)+ -- ^ Free running clock (e.g. a clock pin connected to a crystal oscillator) -> Reset domIn -- ^ Reset for the PLL -> (Clock domOut, Signal domOut Bool)@@ -72,32 +127,75 @@ -- * a reset input port -- * a locked output port ----- The number of output clocks depend this function's inferred result type. An--- instance with a single and double output clock can be instantiated using:+-- The PLL lock output is asserted when the clocks are stable, and is usually+-- connected to reset circuitry to keep the circuit in reset while the clocks+-- are still stabilizing. --+-- See also the [Altera Phase-Locked Loop (Altera PLL) IP Core User Guide](https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/altera_pll.pdf)+--+-- === Specifying outputs+--+-- The number of output clocks depends on this function's inferred result type.+-- An instance with a single output clock can be instantiated using:+-- -- @--- (outClk, pllLocked) = alteraPll clk rst+-- 'Clash.Signal.createDomain' 'Clash.Signal.vSystem'{vName=\"Dom100MHz\", vPeriod=10000}+--+-- (clk100 :: 'Clock' Dom100MHz, pllLocked) =+-- 'alteraPll' ('SSymbol' \@\"alterapll50to100\") clk50 rst50 -- @ ----- and+-- An instance with two clocks can be instantiated using -- -- @--- (outClk1, outClk2, pllLocked) = alteraPll clk rst+-- 'Clash.Signal.createDomain' 'Clash.Signal.vSystem'{vName=\"Dom100MHz\", vPeriod=10000}+-- 'Clash.Signal.createDomain' 'Clash.Signal.vSystem'{vName=\"Dom150MHz\", vPeriod='Clash.Signal.hzToPeriod' 150e6}+--+-- (clk100 :: 'Clock' Dom100MHz, clk150 :: 'Clock' Dom150MHz, pllLocked) =+-- 'alteraPll' ('SSymbol' \@\"alterapllmulti\") clk50 rst50 -- @ ----- respectively.+-- and so on up to 16 clocks. ----- See also the [Altera Phase-Locked Loop (Altera PLL) IP Core User Guide](https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/altera_pll.pdf)+-- If you don't have a top-level type signature specifying the output clock+-- domains, you can specify them using a pattern type signature, as shown here.+--+-- === Example+--+-- When the oscillator connected to the FPGA runs at 50 MHz and the external+-- reset signal is /active low/, this will generate a 100 MHz clock for the+-- @'Clash.Signal.System'@ domain:+--+-- @+-- 'Clash.Signal.createDomain' 'Clash.Signal.vSystem'{vName=\"DomInput\", vPeriod=20000}+--+-- topEntity+-- :: 'Clock' DomInput+-- -> 'Signal' DomInput 'Bool'+-- -> [...]+-- topEntity clkInp rstInp = [...]+-- where+-- (clk :: 'Clock' 'Clash.Signal.System', pllStable :: 'Signal' 'Clash.Signal.System' 'Bool')+-- 'alteraPll' ('SSymbol' \@\"alterapll50to100\") clkInp+-- ('Clash.Signal.unsafeFromLowPolarity' rstInp)+-- rst = 'Clash.Signal.resetSynchronizer' clk ('Clash.Signal.unsafeFromLowPolarity' pllStable)+-- @+--+-- 'Clash.Signal.resetSynchronizer' will keep the reset asserted when+-- @pllStable@ is 'False', hence the use of+-- @'Clash.Signal.unsafeFromLowPolarity' pllStable@. Your circuit will have+-- signals of type @'Signal' 'Clash.Signal.System'@ and all the clocks and+-- resets of your components will be the @clk@ and @rst@ signals generated here+-- (modulo local resets, which will be based on @rst@ or never asserted at all+-- if the component doesn't need a reset). alteraPll :: (Clocks t, KnownDomain domIn, ClocksCxt t) => SSymbol name- -- ^ Name of the component instance.- --- -- Instantiate as follows:+ -- ^ Name of the component instance --- -- > SSymbol @"alteraPLL50"+ -- Instantiate as follows: @(SSymbol \@\"alterapll50\")@ -> Clock domIn- -- ^ Free running clock (i.e. a clock pin connected to a crystal)+ -- ^ Free running clock (e.g. a clock pin connected to a crystal oscillator) -> Reset domIn -- ^ Reset for the PLL -> t
src/Clash/Num/Overflowing.hs view
@@ -1,10 +1,18 @@+{-|+Copyright : (C) 2021-2022, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+-}+ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} module Clash.Num.Overflowing- ( Overflowing(fromOverflowing, hasOverflowed)+ ( Overflowing+ , fromOverflowing+ , hasOverflowed , toOverflowing , clearOverflow ) where@@ -31,7 +39,9 @@ -- data Overflowing a = Overflowing { fromOverflowing :: a+ -- ^ Retrieve the value , hasOverflowed :: Bool+ -- ^ 'True' when a computation has overflowed } deriving stock (Generic, Show) deriving anyclass (Binary, Hashable, NFData, NFDataX, ShowX)
src/Clash/Prelude.hs view
@@ -73,13 +73,13 @@ -- * RAM primitives with a combinational read port , asyncRam , asyncRamPow2- -- * BlockRAM primitives+ -- * Block RAM primitives , blockRam , blockRamPow2 , blockRamU , blockRam1 , E.ResetStrategy(..)- -- ** BlockRAM primitives initialized with a 'MemBlob'+ -- ** Block RAM primitives initialized with a 'MemBlob' , blockRamBlob , blockRamBlobPow2 -- *** Creating and inspecting 'MemBlob'@@ -87,10 +87,10 @@ , createMemBlob , memBlobTH , unpackMemBlob- -- ** BlockRAM primitives initialized with a data file+ -- ** Block RAM primitives initialized with a data file , blockRamFile , blockRamFilePow2- -- ** BlockRAM read/write conflict resolution+ -- ** Block RAM read/write conflict resolution , readNew -- ** True dual-port block RAM , trueDualPortBlockRam
src/Clash/Prelude/BlockRam.hs view
@@ -6,20 +6,20 @@ License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -BlockRAM primitives+Block RAM primitives = Using RAMs #usingrams# We will show a rather elaborate example on how you can, and why you might want-to use 'blockRam's. We will build a \"small\" CPU+Memory+Program ROM where we-will slowly evolve to using blockRams. Note that the code is /not/ meant as a-de-facto standard on how to do CPU design in Clash.+to use 'blockRam's. We will build a \"small\" CPU + Memory + Program ROM where+we will slowly evolve to using 'blockRam's. Note that the code is /not/ meant as+a de-facto standard on how to do CPU design in Clash. We start with the definition of the Instructions, Register names and machine codes: @-{\-\# LANGUAGE RecordWildCards, TupleSections, DeriveAnyClass, TypeApplications \#-\}+{\-\# LANGUAGE RecordWildCards, TupleSections, DeriveAnyClass \#-\} module CPU where @@ -79,11 +79,12 @@ Next we define the CPU and its ALU: @-cpu :: Vec 7 Value -- ^ Register bank- -> (Value,Instruction) -- ^ (Memory output, Current instruction)- -> ( Vec 7 Value- , (MemAddr, Maybe (MemAddr,Value), InstrAddr)- )+cpu+ :: Vec 7 Value -- ^ Register bank+ -> (Value,Instruction) -- ^ (Memory output, Current instruction)+ -> ( Vec 7 Value+ , (MemAddr, Maybe (MemAddr,Value), InstrAddr)+ ) cpu regbank (memOut, instr) = (regbank', (rdAddr, (,aluOut) 'Prelude.<$>' wrAddrM, fromIntegral ipntr)) where@@ -157,10 +158,10 @@ => Vec n Instruction -> Signal dom Value system instrs = memOut- where- memOut = dataMem rdAddr dout- (rdAddr, dout, ipntr) = 'Clash.Prelude.Mealy.mealyB' cpu ('Clash.Sized.Vector.replicate' d7 0) (memOut,instr)- instr = 'Clash.Prelude.ROM.asyncRom' instrs 'Prelude.<$>' ipntr+ where+ memOut = dataMem rdAddr dout+ (rdAddr, dout, ipntr) = 'Clash.Prelude.Mealy.mealyB' cpu ('Clash.Sized.Vector.replicate' d7 0) (memOut,instr)+ instr = 'Clash.Prelude.ROM.asyncRom' instrs 'Prelude.<$>' ipntr @ Create a simple program that calculates the GCD of 4 and 6:@@ -224,10 +225,10 @@ => Vec n Instruction -> Signal dom Value system2 instrs = memOut- where- memOut = 'Clash.Prelude.RAM.asyncRam' d32 rdAddr dout- (rdAddr,dout,ipntr) = 'Clash.Prelude.mealyB' cpu ('Clash.Sized.Vector.replicate' d7 0) (memOut,instr)- instr = 'Clash.Prelude.ROM.asyncRom' instrs 'Prelude.<$>' ipntr+ where+ memOut = 'Clash.Prelude.RAM.asyncRam' d32 rdAddr dout+ (rdAddr,dout,ipntr) = 'Clash.Prelude.mealyB' cpu ('Clash.Sized.Vector.replicate' d7 0) (memOut,instr)+ instr = 'Clash.Prelude.ROM.asyncRom' instrs 'Prelude.<$>' ipntr @ Again, we can simulate our system and see that it works. This time however,@@ -235,7 +236,7 @@ 'Clash.Prelude.RAM.asyncRam' is /undefined/, and consequently, the first few output samples are also /undefined/. We use the utility function 'Clash.XException.printX' to conveniently filter out the undefinedness and-replace it with the string @\"undefined\"@ in the few leading outputs.+replace it with the string @\"undefined\"@ in the first few leading outputs. @ >>> printX $ sampleN @System 32 (system2 prog)@@ -247,30 +248,28 @@ Finally we get to using 'blockRam'. On FPGAs, 'Clash.Prelude.RAM.asyncRam' will be implemented in terms of LUTs, and therefore take up logic resources. FPGAs-also have large(r) memory structures called /Block RAMs/, which are preferred,+also have large(r) memory structures called /block RAMs/, which are preferred, especially as the memories we need for our application get bigger. The-'blockRam' function will be translated to such a /Block RAM/.+'blockRam' function will be translated to such a /block RAM/. -One important aspect of Block RAMs have a /synchronous/ read port, meaning that,-unlike the behavior of 'Clash.Prelude.RAM.asyncRam', given a read address @r@-at time @t@, the value @v@ in the RAM at address @r@ is only available at time-@t+1@.+One important aspect of block RAMs is that they have a /synchronous/ read port,+meaning that, unlike the behavior of 'Clash.Prelude.RAM.asyncRam', given a read+address @r@ at time @t@, the value @v@ in the RAM at address @r@ is only+available at time @t+1@. For us that means we need to change the design of our CPU. Right now, upon a load instruction we generate a read address for the memory, and the value at that read address is immediately available to be put in the register bank.-Because we will be using a BlockRAM, the value is delayed until the next cycle.-We hence need to also delay the register address to which the memory address-is loaded:+Because we will be using a block RAM, the value is delayed until the next cycle.+Thus, we will need to also delay the register address to which the memory+address is loaded: @ cpu2- :: (Vec 7 Value,Reg)- -- ^ (Register bank, Load reg addr)- -> (Value, Instruction)- -- ^ (Memory output, Current instruction)- -> ( (Vec 7 Value,Reg)- , (MemAddr, Maybe (MemAddr, Value), InstrAddr)+ :: (Vec 7 Value,Reg) -- ^ (Register bank, Load reg addr)+ -> (Value,Instruction) -- ^ (Memory output, Current instruction)+ -> ( (Vec 7 Value, Reg)+ , (MemAddr, Maybe (MemAddr,Value), InstrAddr) ) cpu2 (regbank,ldRegD) (memOut,instr) = ((regbank', ldRegD'), (rdAddr, (,aluOut) 'Prelude.<$>' wrAddrM, fromIntegral ipntr))@@ -316,17 +315,17 @@ => Vec n Instruction -> Signal dom Value system3 instrs = memOut- where- memOut = 'blockRam' (replicate d32 0) rdAddr dout- (rdAddr,dout,ipntr) = 'Clash.Prelude.mealyB' cpu2 (('Clash.Sized.Vector.replicate' d7 0),Zero) (memOut,instr)- instr = 'Clash.Prelude.ROM.asyncRom' instrs 'Prelude.<$>' ipntr+ where+ memOut = 'blockRam' (replicate d32 0) rdAddr dout+ (rdAddr,dout,ipntr) = 'Clash.Prelude.mealyB' cpu2 (('Clash.Sized.Vector.replicate' d7 0),Zero) (memOut,instr)+ instr = 'Clash.Prelude.ROM.asyncRom' instrs 'Prelude.<$>' ipntr @ We are, however, not done. We will also need to update our program. The reason being that values that we try to load in our registers won't be loaded into the register until the next cycle. This is a problem when the next instruction-immediately depended on this memory value. In our case, this was only the case-when the loaded the value @6@, which was stored at address @1@, into @RegB@.+immediately depends on this memory value. In our case, this was only the case+when we loaded the value @6@, which was stored at address @1@, into @RegB@. Our updated program is thus: @@@ -685,12 +684,23 @@ -} --- | Create a blockRAM with space for @n@ elements.+-- | Create a block RAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' --+-- === See also:+--+-- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a+-- Block RAM.+-- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @'readNew' ('blockRam' inits) rd wrM@.+-- * A large 'Vec' for the initial content may be too inefficient, depending+-- on how it is constructed. See 'Clash.Prelude.BlockRam.File.blockRamFile' and+-- 'Clash.Prelude.BlockRam.Blob.blockRamBlob' for different approaches that+-- scale well.+--+-- === __Example__ -- @ -- bram40 -- :: 'HiddenClock' dom@@ -699,16 +709,6 @@ -- -> 'Signal' dom 'Clash.Sized.BitVector.Bit' -- bram40 = 'blockRam' ('Clash.Sized.Vector.replicate' d40 1) -- @------ Additional helpful information:------ * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.--- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @readNew (blockRam inits) rd wrM@.--- * A large 'Vec' for the initial content might be too inefficient, depending--- on how it is constructed. See 'Clash.Prelude.BlockRam.File.blockRamFile' and--- 'Clash.Prelude.BlockRam.Blob.blockRamBlob' for different approaches that--- scale well. blockRam :: ( HasCallStack , HiddenClock dom@@ -717,22 +717,21 @@ , Enum addr ) => Vec n a- -- ^ Initial content of the BRAM, also determines the size, @n@, of the BRAM.+ -- ^ Initial content of the BRAM, also determines the size, @n@, of the BRAM --- -- __NB__: __MUST__ be a constant.+ -- __NB__: __MUST__ be a constant -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock- -- cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRam = \cnt rd wrM -> withFrozenCallStack (hideEnable (hideClock E.blockRam) cnt rd wrM) {-# INLINE blockRam #-} --- | Version of blockram that has no default values set. May be cleared to a--- arbitrary state using a reset function.+-- | A version of 'blockRam' that has no default values set. May be cleared to+-- an arbitrary state using a reset function. blockRamU :: forall n dom a r addr . ( HasCallStack@@ -742,25 +741,25 @@ , 1 <= n ) => E.ResetStrategy r -- ^ Whether to clear BRAM on asserted reset ('Clash.Explicit.BlockRam.ClearOnReset')- -- or not ('Clash.Explicit.BlockRam.NoClearOnReset'). Reset needs to be- -- asserted at least /n/ cycles to clear the BRAM.+ -- or not ('Clash.Explicit.BlockRam.NoClearOnReset'). The reset needs to be+ -- asserted for at least /n/ cycles to clear the BRAM. -> SNat n -- ^ Number of elements in BRAM -> (Index n -> a)- -- ^ If applicable (see first argument), reset BRAM using this function.+ -- ^ If applicable (see first argument), reset BRAM using this function -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamU = \rstStrategy cnt initF rd wrM -> withFrozenCallStack (hideClockResetEnable E.blockRamU) rstStrategy cnt initF rd wrM {-# INLINE blockRamU #-} --- | Version of blockram that is initialized with the same value on all--- memory positions.+-- | A version of 'blockRam' that is initialized with the same value on all+-- memory positions blockRam1 :: forall n dom a r addr . ( HasCallStack@@ -770,8 +769,8 @@ , 1 <= n ) => E.ResetStrategy r -- ^ Whether to clear BRAM on asserted reset ('Clash.Explicit.BlockRam.ClearOnReset')- -- or not ('Clash.Explicit.BlockRam.NoClearOnReset'). Reset needs to be- -- asserted at least /n/ cycles to clear the BRAM.+ -- or not ('Clash.Explicit.BlockRam.NoClearOnReset'). The reset needs to be+ -- asserted for at least /n/ cycles to clear the BRAM. -> SNat n -- ^ Number of elements in BRAM -> a@@ -781,18 +780,29 @@ -> Signal dom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal dom a- -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRam1 = \rstStrategy cnt initValue rd wrM -> withFrozenCallStack (hideClockResetEnable E.blockRam1) rstStrategy cnt initValue rd wrM {-# INLINE blockRam1 #-} --- | Create a blockRAM with space for 2^@n@ elements+-- | Create a block RAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' --+-- === See also:+--+-- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a+-- block RAM.+-- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @'readNew' ('blockRamPow2' inits) rd wrM@.+-- * A large 'Vec' for the initial content may be too inefficient, depending+-- on how it is constructed. See 'Clash.Prelude.BlockRam.File.blockRamFilePow2'+-- and 'Clash.Prelude.BlockRam.Blob.blockRamBlobPow2' for different approaches+-- that scale well.+--+-- === __Example__ -- @ -- bram32 -- :: 'HiddenClock' dom@@ -801,16 +811,6 @@ -- -> 'Signal' dom 'Clash.Sized.BitVector.Bit' -- bram32 = 'blockRamPow2' ('Clash.Sized.Vector.replicate' d32 1) -- @------ Additional helpful information:------ * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.--- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @readNew (blockRamPow2 inits) rd wrM@.--- * A large 'Vec' for the initial content might be too inefficient, depending--- on how it is constructed. See 'Clash.Prelude.BlockRam.File.blockRamFilePow2'--- and 'Clash.Prelude.BlockRam.Blob.blockRamBlobPow2' for different approaches--- that scale well. blockRamPow2 :: ( HasCallStack , HiddenClock dom@@ -833,9 +833,8 @@ (hideEnable (hideClock E.blockRamPow2) cnt rd wrM) {-# INLINE blockRamPow2 #-} --- | Create read-after-write blockRAM from a read-before-write one (synchronized to system clock)+-- | Create a read-after-write block RAM from a read-before-write one ----- >>> import Clash.Prelude -- >>> :t readNew (blockRam (0 :> 1 :> Nil)) -- readNew (blockRam (0 :> 1 :> Nil)) -- :: ...@@ -849,13 +848,13 @@ , NFDataX a , Eq addr ) => (Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a)- -- ^ The @ram@ component+ -- ^ The BRAM component -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, a)) -- ^ (Write address @w@, value to write) -> Signal dom a- -- ^ Value of the @ram@ at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle readNew = hideClockResetEnable E.readNew {-# INLINE readNew #-}
src/Clash/Prelude/BlockRam/Blob.hs view
@@ -5,7 +5,7 @@ = Efficient bundling of initial RAM content with the compiled code -Leveraging Template Haskell, the initial content for the blockRAM components in+Leveraging Template Haskell, the initial content for the block RAM components in this module is stored alongside the compiled Haskell code. It covers use cases where passing the initial content as a 'Clash.Sized.Vector.Vec' turns out to be problematically slow.@@ -41,17 +41,17 @@ import Clash.Sized.BitVector (BitVector) import Clash.Sized.Unsigned (Unsigned) --- | Create a blockRAM with space for @n@ elements+-- | Create a block RAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' -- ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.+-- block RAM. -- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining -- write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew' -- ('blockRamBlob' content) rd wrM@.@@ -62,7 +62,7 @@ , Enum addr ) => E.MemBlob n m- -- ^ Initial content of the RAM, also determines the size, @n@, of the RAM+ -- ^ Initial content of the BRAM, also determines the size, @n@, of the BRAM -- -- __NB__: __MUST__ be a constant -> Signal dom addr@@ -70,20 +70,20 @@ -> Signal dom (Maybe (addr, BitVector m)) -- ^ (write address @w@, value to write) -> Signal dom (BitVector m)- -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamBlob = hideEnable (hideClock E.blockRamBlob) {-# INLINE blockRamBlob #-} --- | Create a blockRAM with space for 2^@n@ elements+-- | Create a block RAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.+-- block RAM. -- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining -- write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew' -- ('blockRamBlobPow2' content) rd wrM@.@@ -94,7 +94,7 @@ , KnownNat n ) => E.MemBlob (2^n) m- -- ^ Initial content of the RAM, also determines the size, 2^@n@, of the RAM+ -- ^ Initial content of the BRAM, also determines the size, 2^@n@, of the BRAM -- -- __NB__: __MUST__ be a constant -> Signal dom (Unsigned n)@@ -102,6 +102,6 @@ -> Signal dom (Maybe (Unsigned n, BitVector m)) -- ^ (write address @w@, value to write) -> Signal dom (BitVector m)- -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamBlobPow2 = hideEnable (hideClock E.blockRamBlobPow2) {-# INLINE blockRamBlobPow2 #-}
src/Clash/Prelude/BlockRam/File.hs view
@@ -2,13 +2,13 @@ Copyright : (C) 2015-2016, University of Twente, 2019 , Myrtle Software Ltd, 2017 , Google Inc.,- 2021 , QBayLogic B.V.+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -= Initializing a BlockRAM with a data file #usingramfiles#+= Initializing a block RAM with a data file #usingramfiles# -BlockRAM primitives that can be initialized with a data file. The BNF grammar+Block RAM primitives that can be initialized with a data file. The BNF grammar for this data file is simple: @@@ -19,7 +19,7 @@ @ Consecutive @LINE@s correspond to consecutive memory addresses starting at @0@.-For example, a data file @memory.bin@ containing the 9-bit unsigned number+For example, a data file @memory.bin@ containing the 9-bit unsigned numbers @7@ to @13@ looks like: @@@ -38,7 +38,7 @@ writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13]) @ -We can instantiate a BlockRAM using the content of the above file like so:+We can instantiate a block RAM using the contents of the file above like so: @ f :: (HiddenClock dom, HiddenEnable dom)@@ -47,7 +47,7 @@ f rd = 'Clash.Class.BitPack.unpack' '<$>' 'blockRamFile' d7 \"memory.bin\" rd (pure Nothing) @ -In the example above, we basically treat the BlockRAM as an synchronous ROM.+In the example above, we basically treat the block RAM as a synchronous ROM. We can see that it works as expected: @@@ -84,7 +84,7 @@ {-# OPTIONS_HADDOCK show-extensions #-} module Clash.Prelude.BlockRam.File- ( -- * BlockRAM synchronized to an arbitrary clock+ ( -- * Block RAM synchronized to an arbitrary clock blockRamFile , blockRamFilePow2 -- * Producing files@@ -103,7 +103,7 @@ import Clash.Sized.BitVector (BitVector) import Clash.Sized.Unsigned (Unsigned) --- | Create a blockRAM with space for 2^@n@ elements+-- | Create a block RAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an@@ -112,22 +112,23 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.+-- block RAM. -- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew' ('blockRamFilePow2' file) rd wrM@. -- * See "Clash.Prelude.BlockRam.File#usingramfiles" for more information on how--- to instantiate a Block RAM with the contents of a data file.+-- to instantiate a block RAM with the contents of a data file. -- * See "Clash.Sized.Fixed#creatingdatafiles" for ideas on how to create your -- own data files. blockRamFilePow2@@ -138,19 +139,18 @@ , HiddenEnable dom , HasCallStack ) => FilePath- -- ^ File describing the initial content of the blockRAM+ -- ^ File describing the initial content of the BRAM -> Signal dom (Unsigned n) -- ^ Read address @r@ -> Signal dom (Maybe (Unsigned n, BitVector m)) -- ^ (write address @w@, value to write) -> Signal dom (BitVector m)- -- ^ Value of the @blockRAM@ at address @r@ from the previous- -- clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamFilePow2 = \fp rd wrM -> withFrozenCallStack (hideEnable (hideClock E.blockRamFilePow2) fp rd wrM) {-# INLINE blockRamFilePow2 #-} --- | Create a blockRAM with space for @n@ elements+-- | Create a block RAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an@@ -159,22 +159,23 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a--- Block RAM.+-- block RAM. -- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew' ('blockRamFile' size file) rd wrM@. -- * See "Clash.Prelude.BlockRam.File#usingramfiles" for more information on how--- to instantiate a Block RAM with the contents of a data file.+-- to instantiate a block RAM with the contents of a data file. -- * See "Clash.Sized.Fixed#creatingdatafiles" for ideas on how to create your -- own data files. blockRamFile@@ -184,16 +185,15 @@ , HiddenEnable dom , HasCallStack ) => SNat n- -- ^ Size of the blockRAM+ -- ^ Size of the BRAM -> FilePath- -- ^ File describing the initial content of the blockRAM+ -- ^ File describing the initial content of the BRAM -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, BitVector m)) -- ^ (write address @w@, value to write) -> Signal dom (BitVector m)- -- ^ Value of the @blockRAM@ at address @r@ from the previous- -- clock cycle+ -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamFile = \sz fp rd wrM -> withFrozenCallStack (hideEnable (hideClock E.blockRamFile) sz fp rd wrM) {-# INLINE blockRamFile #-}
src/Clash/Prelude/Mealy.hs view
@@ -71,8 +71,8 @@ -- -> 'Signal' dom Int -- dualMac (a,b) (x,y) = s1 + s2 -- where--- s1 = 'mealy' mac 0 ('Clash.Signal.bundle' (a,x))--- s2 = 'mealy' mac 0 ('Clash.Signal.bundle' (b,y))+-- s1 = 'mealy' macT 0 ('Clash.Signal.bundle' (a,x))+-- s2 = 'mealy' macT 0 ('Clash.Signal.bundle' (b,y)) -- @ mealy :: ( HiddenClockResetEnable dom
src/Clash/Prelude/Moore.hs view
@@ -74,8 +74,8 @@ -- -> 'Signal' dom Int -- dualMac (a,b) (x,y) = s1 + s2 -- where--- s1 = 'moore' mac id 0 ('Clash.Signal.bundle' (a,x))--- s2 = 'moore' mac id 0 ('Clash.Signal.bundle' (b,y))+-- s1 = 'moore' macT id 0 ('Clash.Signal.bundle' (a,x))+-- s2 = 'moore' macT id 0 ('Clash.Signal.bundle' (b,y)) -- @ moore :: ( HiddenClockResetEnable dom
src/Clash/Prelude/RAM.hs view
@@ -6,7 +6,7 @@ License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -RAM primitives with a combinational read port.+RAM primitives with a combinational read port -} {-# LANGUAGE CPP #-}@@ -34,12 +34,12 @@ import Clash.XException (NFDataX) --- | Create a RAM with space for @n@ elements.+-- | Create a RAM with space for @n@ elements -- -- * __NB__: Initial content of the RAM is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a -- RAM.@@ -57,7 +57,7 @@ -> Signal dom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal dom a- -- ^ Value of the @RAM@ at address @r@+ -- ^ Value of the RAM at address @r@ asyncRam = \sz rd wrM -> withFrozenCallStack (hideEnable (\en -> hideClock (\clk -> E.asyncRam clk clk en sz rd wrM))) {-# INLINE asyncRam #-}@@ -67,7 +67,7 @@ -- * __NB__: Initial content of the RAM is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a -- RAM.@@ -83,7 +83,7 @@ -> Signal dom (Maybe (Unsigned n, a)) -- ^ (write address @w@, value to write) -> Signal dom a- -- ^ Value of the @RAM@ at address @r@+ -- ^ Value of the RAM at address @r@ asyncRamPow2 = \rd wrM -> withFrozenCallStack (hideEnable (\en -> (hideClock (\clk -> E.asyncRamPow2 clk clk en rd wrM)))) {-# INLINE asyncRamPow2 #-}
src/Clash/Prelude/ROM.hs view
@@ -45,11 +45,11 @@ -- | An asynchronous/combinational ROM with space for @n@ elements ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Prelude.BlockRam#usingrams"--- for ideas on how to use ROMs and RAMs--- * A large 'Vec' for the content might be too inefficient, depending on how it+-- for ideas on how to use ROMs and RAMs.+-- * A large 'Vec' for the content may be too inefficient, depending on how it -- is constructed. See 'Clash.Prelude.ROM.File.asyncRomFile' and -- 'Clash.Prelude.ROM.Blob.asyncRomBlob' for different approaches that scale -- well.@@ -58,21 +58,21 @@ => Vec n a -- ^ ROM content, also determines the size, @n@, of the ROM --- -- __NB:__ must be a constant+ -- __NB__: __MUST__ be a constant -> addr- -- ^ Read address @rd@+ -- ^ Read address @r@ -> a- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ asyncRom = \content rd -> asyncRom# content (fromEnum rd) {-# INLINE asyncRom #-} -- | An asynchronous/combinational ROM with space for 2^@n@ elements ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Prelude.BlockRam#usingrams"--- for ideas on how to use ROMs and RAMs--- * A large 'Vec' for the content might be too inefficient, depending on how it+-- for ideas on how to use ROMs and RAMs.+-- * A large 'Vec' for the content may be too inefficient, depending on how it -- is constructed. See 'Clash.Prelude.ROM.File.asyncRomFilePow2' and -- 'Clash.Prelude.ROM.Blob.asyncRomBlobPow2' for different approaches that scale -- well.@@ -81,25 +81,25 @@ => Vec (2^n) a -- ^ ROM content --- -- __NB:__ must be a constant+ -- __NB__: __MUST__ be a constant -> Unsigned n- -- ^ Read address @rd@+ -- ^ Read address @r@ -> a- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ asyncRomPow2 = asyncRom {-# INLINE asyncRomPow2 #-} --- | asyncROM primitive+-- | asyncRom primitive asyncRom# :: forall n a . KnownNat n => Vec n a -- ^ ROM content, also determines the size, @n@, of the ROM --- -- __NB:__ must be a constant+ -- __NB__: __MUST__ be a constant -> Int- -- ^ Read address @rd@+ -- ^ Read address @r@ -> a- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ asyncRom# content = safeAt where szI = length content@@ -122,11 +122,11 @@ -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Prelude.BlockRam#usingrams"--- for ideas on how to use ROMs and RAMs--- * A large 'Vec' for the content might be too inefficient, depending on how it+-- for ideas on how to use ROMs and RAMs.+-- * A large 'Vec' for the content may be too inefficient, depending on how it -- is constructed. See 'Clash.Prelude.ROM.File.romFile' and -- 'Clash.Prelude.ROM.Blob.romBlob' for different approaches that scale well. rom@@ -139,11 +139,11 @@ => Vec n a -- ^ ROM content, also determines the size, @n@, of the ROM --- -- __NB:__ must be a constant+ -- __NB__: __MUST__ be a constant -> Signal dom (Unsigned m)- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom a- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ from the previous clock cycle rom = hideEnable (hideClock E.rom) {-# INLINE rom #-} @@ -153,11 +153,11 @@ -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Prelude.BlockRam#usingrams"--- for ideas on how to use ROMs and RAMs--- * A large 'Vec' for the content might be too inefficient, depending on how it+-- for ideas on how to use ROMs and RAMs.+-- * A large 'Vec' for the content may be too inefficient, depending on how it -- is constructed. See 'Clash.Prelude.ROM.File.romFilePow2' and -- 'Clash.Prelude.ROM.Blob.romBlobPow2' for different approaches that scale -- well.@@ -170,10 +170,10 @@ => Vec (2^n) a -- ^ ROM content --- -- __NB:__ must be a constant+ -- __NB__: __MUST__ be a constant -> Signal dom (Unsigned n)- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom a- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ from the previous clock cycle romPow2 = hideEnable (hideClock E.romPow2) {-# INLINE romPow2 #-}
src/Clash/Prelude/ROM/Blob.hs view
@@ -57,7 +57,7 @@ -- | An asynchronous/combinational ROM with space for @n@ elements ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and -- "Clash.Prelude.BlockRam#usingrams" for ideas on how to use ROMs and RAMs.@@ -76,7 +76,7 @@ -- | An asynchronous/combinational ROM with space for 2^@n@ elements ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and -- "Clash.Prelude.BlockRam#usingrams" for ideas on how to use ROMs and RAMs.@@ -93,7 +93,7 @@ asyncRomBlobPow2 = asyncRomBlob {-# INLINE asyncRomBlobPow2 #-} --- | asyncROM primitive+-- | asyncRomBlob primitive asyncRomBlob# :: forall m n . MemBlob n m@@ -126,7 +126,7 @@ -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and -- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs.@@ -153,7 +153,7 @@ -- * __NB__: Initial output value is /undefined/, reading it will throw an -- 'Clash.XException.XException' ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and -- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs.
src/Clash/Prelude/ROM/File.hs view
@@ -18,7 +18,7 @@ @ Consecutive @LINE@s correspond to consecutive memory addresses starting at @0@.-For example, a data file @memory.bin@ containing the 9-bit unsigned number+For example, a data file @memory.bin@ containing the 9-bit unsigned numbers @7@ to @13@ looks like: @@@ -37,7 +37,7 @@ writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13]) @ -We can instantiate a synchronous ROM using the content of the above file like+We can instantiate a synchronous ROM using the contents of the file above like so: @@@ -112,16 +112,17 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.ROM.File#usingromfiles" for more information on how -- to instantiate a ROM with the contents of a data file.@@ -155,9 +156,9 @@ -> FilePath -- ^ File describing the content of the ROM -> addr- -- ^ Read address @rd@+ -- ^ Read address @r@ -> BitVector m- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ asyncRomFile sz file = asyncRomFile# sz file . fromEnum -- Leave 'asyncRomFile#' eta-reduced, see Note [Eta-reduction and unsafePerformIO initMem] {-# INLINE asyncRomFile #-}@@ -196,16 +197,17 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.ROM.File#usingromfiles" for more information on how -- to instantiate a ROM with the contents of a data file.@@ -231,13 +233,13 @@ => FilePath -- ^ File describing the content of the ROM -> Unsigned n- -- ^ Read address @rd@+ -- ^ Read address @r@ -> BitVector m- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ asyncRomFilePow2 = asyncRomFile (pow2SNat (SNat @n)) {-# INLINE asyncRomFilePow2 #-} --- | asyncROMFile primitive+-- | asyncRomFile primitive asyncRomFile# :: KnownNat m => SNat n@@ -245,9 +247,9 @@ -> FilePath -- ^ File describing the content of the ROM -> Int- -- ^ Read address @rd@+ -- ^ Read address @r@ -> BitVector m- -- ^ The value of the ROM at address @rd@+ -- ^ The value of the ROM at address @r@ asyncRomFile# sz file = (content !) -- Leave "(content !)" eta-reduced, see where -- Note [Eta-reduction and unsafePerformIO initMem] mem = unsafePerformIO (initMem file)@@ -265,16 +267,17 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.ROM.File#usingromfiles" for more information on how -- to instantiate a ROM with the contents of a data file.@@ -292,9 +295,9 @@ -> FilePath -- ^ File describing the content of the ROM -> Signal dom addr- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom (BitVector m)- -- ^ The value of the ROM at address @rd@ from the previous clock cycle+ -- ^ The value of the ROM at address @r@ from the previous clock cycle romFile = hideEnable (hideClock E.romFile) {-# INLINE romFile #-} @@ -307,16 +310,17 @@ -- code-generation backends and hardware targets. Please check the support table -- below: ----- @--- | VHDL | Verilog | SystemVerilog |--- ===============+==========+==========+===============+--- Altera/Quartus | Broken | Works | Works |--- Xilinx/ISE | Works | Works | Works |--- ASIC | Untested | Untested | Untested |--- ===============+==========+==========+===============+--- @+-- +----------------+----------+----------+---------------++-- | | VHDL | Verilog | SystemVerilog |+-- +================+==========+==========+===============++-- | Altera/Quartus | Broken | Works | Works |+-- +----------------+----------+----------+---------------++-- | Xilinx/ISE | Works | Works | Works |+-- +----------------+----------+----------+---------------++-- | ASIC | Untested | Untested | Untested |+-- +----------------+----------+----------+---------------+ ----- Additional helpful information:+-- === See also: -- -- * See "Clash.Prelude.ROM.File#usingromfiles" for more information on how -- to instantiate a ROM with the contents of a data file.@@ -332,8 +336,8 @@ => FilePath -- ^ File describing the content of the ROM -> Signal dom (Unsigned n)- -- ^ Read address @rd@+ -- ^ Read address @r@ -> Signal dom (BitVector m)- -- ^ The value of the ROM at address @rd@ from the previous clock cycle+ -- ^ The value of the ROM at address @r@ from the previous clock cycle romFilePow2 = hideEnable (hideClock E.romFilePow2) {-# INLINE romFilePow2 #-}
src/Clash/Signal/Trace.hs view
@@ -262,7 +262,7 @@ -- an error. -- -- __NB__ Works correctly when creating VCD files from traced signal in--- multi-clock circuits. However 'traceSignal1' might be more convinient to+-- multi-clock circuits. However 'traceSignal1' might be more convenient to -- use when the domain of your circuit is polymorphic. traceVecSignal :: forall dom a n
tests/Clash/Tests/AsyncFIFOSynchronizer.hs view
@@ -14,7 +14,7 @@ import qualified Hedgehog.Range as Range import qualified Hedgehog.Gen as Gen import Test.Tasty-import Test.Tasty.Hedgehog+import Test.Tasty.Hedgehog.Extra import Test.Tasty.HUnit import Clash.Explicit.Prelude@@ -1149,5 +1149,5 @@ , testCase "Test 5.7 Write" test5W7 , testCase "Test 6.7 Read" test6R7 , testCase "Test 6.7 Write" test6W7- , testProperty "Functional test" $ forAllNamedTestProperties fifoFunctionalTestCombinations+ , testPropertyXXX "Functional test" $ forAllNamedTestProperties fifoFunctionalTestCombinations ]
tests/Clash/Tests/BitVector.hs view
@@ -19,7 +19,7 @@ import Test.Tasty import Test.Tasty.HUnit -import qualified Test.Tasty.Hedgehog as H+import qualified Test.Tasty.Hedgehog.Extra as H import qualified Test.Tasty.QuickCheck as Q import Clash.Prelude@@ -97,13 +97,13 @@ , testCase "minBound :: BitVector 0" $ minBound @(BitVector 0) @?= 0 ] , testGroup "MSB"- [ H.testProperty "msb @(BitVector 1)" (msbTest @1)- , H.testProperty "msb @(BitVector 2)" (msbTest @2)- , H.testProperty "msb @(BitVector 3)" (msbTest @3)- , H.testProperty "msb @(BitVector 37)" (msbTest @37)- , H.testProperty "msb @(BitVector 64)" (msbTest @64)- , H.testProperty "msb @(BitVector 128)" (msbTest @128)- , H.testProperty "msb @(BitVector 129)" (msbTest @129)+ [ H.testPropertyXXX "msb @(BitVector 1)" (msbTest @1)+ , H.testPropertyXXX "msb @(BitVector 2)" (msbTest @2)+ , H.testPropertyXXX "msb @(BitVector 3)" (msbTest @3)+ , H.testPropertyXXX "msb @(BitVector 37)" (msbTest @37)+ , H.testPropertyXXX "msb @(BitVector 64)" (msbTest @64)+ , H.testPropertyXXX "msb @(BitVector 128)" (msbTest @128)+ , H.testPropertyXXX "msb @(BitVector 129)" (msbTest @129) ] , testGroup "show" [ testCase "show0" $ show @(BitVector 0) 0b0 @?= "0"
tests/Clash/Tests/BlockRam/Blob.hs view
@@ -8,7 +8,7 @@ import qualified Hedgehog.Range as Range import Numeric.Natural import Test.Tasty-import Test.Tasty.Hedgehog+import Test.Tasty.Hedgehog.Extra import Clash.Explicit.BlockRam.Internal (packAsNats, unpackNats) @@ -32,5 +32,5 @@ tests :: TestTree tests = testGroup "BlockRam" [ testGroup "Blob"- [ testProperty "Round trip" roundTripProperty ]+ [ testPropertyXXX "Round trip" roundTripProperty ] ]
tests/Clash/Tests/Counter.hs view
@@ -16,7 +16,7 @@ import qualified Hedgehog.Range as Range import Test.Tasty-import qualified Test.Tasty.Hedgehog as H+import qualified Test.Tasty.Hedgehog.Extra as H import Test.Tasty.HUnit genUnsigned :: SNat n -> H.Gen (Unsigned n)@@ -86,12 +86,12 @@ tests :: TestTree tests = testGroup "All"- [ H.testProperty "packSuccTest @2 @2" (packSuccTest2 @2 @2 Proxy Proxy)- , H.testProperty "packSuccTest @3 @2" (packSuccTest2 @3 @2 Proxy Proxy)- , H.testProperty "packSuccTest2 @129 @5" (packSuccTest2 @129 @5 Proxy Proxy)- , H.testProperty "packPredTest @2 @2" (packPredTest2 @2 @2 Proxy Proxy)- , H.testProperty "packPredTest @3 @2" (packPredTest2 @3 @2 Proxy Proxy)- , H.testProperty "packPredTest2 @129 @5" (packPredTest2 @129 @5 Proxy Proxy)+ [ H.testPropertyXXX "packSuccTest @2 @2" (packSuccTest2 @2 @2 Proxy Proxy)+ , H.testPropertyXXX "packSuccTest @3 @2" (packSuccTest2 @3 @2 Proxy Proxy)+ , H.testPropertyXXX "packSuccTest2 @129 @5" (packSuccTest2 @129 @5 Proxy Proxy)+ , H.testPropertyXXX "packPredTest @2 @2" (packPredTest2 @2 @2 Proxy Proxy)+ , H.testPropertyXXX "packPredTest @3 @2" (packPredTest2 @3 @2 Proxy Proxy)+ , H.testPropertyXXX "packPredTest2 @129 @5" (packPredTest2 @129 @5 Proxy Proxy) , quadTest (Proxy @(Signed 5)) , quadTest (Proxy @(Signed 5, Signed 5))
tests/Clash/Tests/Fixed.hs view
@@ -10,7 +10,7 @@ import Data.Proxy (Proxy(..)) import Test.Tasty-import Test.Tasty.Hedgehog+import Test.Tasty.Hedgehog.Extra import Clash.Class.Num import Clash.Sized.Fixed (Fixed(..), FracFixedC, NumFixedC, SFixed, UFixed)@@ -123,8 +123,8 @@ => Gen a -> [TestTree] saturatingNumLaws genA =- [ testProperty "satSucc" $ satSuccProperty genA- , testProperty "satPred" $ satPredProperty genA+ [ testPropertyXXX "satSucc" $ satSuccProperty genA+ , testPropertyXXX "satPred" $ satPredProperty genA ] testSaturationLaws@@ -462,12 +462,12 @@ => Proxy f -> [TestTree] enumProperties pf =- [ testProperty "pred" $ predProperty pf- , testProperty "succ" $ succProperty pf- , testProperty "enumFrom" $ enumFromProperty pf- , testProperty "enumFromThen" $ enumFromThenProperty pf- , testProperty "enumFromTo" $ enumFromToProperty pf- , testProperty "enumFromThenTo" $ enumFromThenToProperty pf+ [ testPropertyXXX "pred" $ predProperty pf+ , testPropertyXXX "succ" $ succProperty pf+ , testPropertyXXX "enumFrom" $ enumFromProperty pf+ , testPropertyXXX "enumFromThen" $ enumFromThenProperty pf+ , testPropertyXXX "enumFromTo" $ enumFromToProperty pf+ , testPropertyXXX "enumFromThenTo" $ enumFromThenToProperty pf ] testEnumProperties
tests/Clash/Tests/Laws/SaturatingNum.hs view
@@ -7,7 +7,7 @@ module Clash.Tests.Laws.SaturatingNum (tests) where import Test.Tasty-import Test.Tasty.Hedgehog+import Test.Tasty.Hedgehog.Extra import Test.Tasty.HUnit import Test.Tasty.HUnit.Extra @@ -111,9 +111,9 @@ ] else []) <>- [ testProperty "satAddTotal" (isTotal satAdd genA)- , testProperty "satSubTotal" (isTotal satSub genA)- , testProperty "satMulTotal" (isTotal satMul genA)+ [ testPropertyXXX "satAddTotal" (isTotal satAdd genA)+ , testPropertyXXX "satSubTotal" (isTotal satSub genA)+ , testPropertyXXX "satMulTotal" (isTotal satMul genA) ] testSaturationLaws ::
tests/Clash/Tests/NumNewtypes.hs view
@@ -15,7 +15,7 @@ import Hedgehog.Extra import Hedgehog.Internal.Exception (tryEvaluate) import Test.Tasty-import Test.Tasty.Hedgehog+import Test.Tasty.Hedgehog.Extra import Clash.Class.Num import Clash.Num.Erroring@@ -64,17 +64,17 @@ -> TestTree testIntegral name mode gen = testGroup name- [ testProperty "Addition" $ checkIntegral2 mode gen (+)- , testProperty "Subtraction" $ checkIntegral2 mode gen (-)- , testProperty "Multiplication" $ checkIntegral2 mode gen (*)- , testProperty "Negation" $ checkIntegral mode gen negate- , testProperty "Absolute" $ checkIntegral mode gen abs- , testProperty "Successor" $ checkIntegral mode gen succ- , testProperty "Predecessor" $ checkIntegral mode gen pred- , testProperty "Division" $ checkIntegral2 mode gen div- , testProperty "Modulo" $ checkIntegral2 mode gen mod- , testProperty "Quotient" $ checkIntegral2 mode gen quot- , testProperty "Remainder" $ checkIntegral2 mode gen rem+ [ testPropertyXXX "Addition" $ checkIntegral2 mode gen (+)+ , testPropertyXXX "Subtraction" $ checkIntegral2 mode gen (-)+ , testPropertyXXX "Multiplication" $ checkIntegral2 mode gen (*)+ , testPropertyXXX "Negation" $ checkIntegral mode gen negate+ , testPropertyXXX "Absolute" $ checkIntegral mode gen abs+ , testPropertyXXX "Successor" $ checkIntegral mode gen succ+ , testPropertyXXX "Predecessor" $ checkIntegral mode gen pred+ , testPropertyXXX "Division" $ checkIntegral2 mode gen div+ , testPropertyXXX "Modulo" $ checkIntegral2 mode gen mod+ , testPropertyXXX "Quotient" $ checkIntegral2 mode gen quot+ , testPropertyXXX "Remainder" $ checkIntegral2 mode gen rem ] data Mode :: (Type -> Type) -> Type where
+ tests/Test/Tasty/Hedgehog/Extra.hs view
@@ -0,0 +1,20 @@+{-|+Copyright : (C) 2022, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++Convenience functions \"missing\" in "Test.Tasty.Hedgehog"+-}++module Test.Tasty.Hedgehog.Extra (testPropertyXXX) where++import Data.String (IsString(fromString))+import Hedgehog (Property)+import Test.Tasty (TestName, TestTree)+import Test.Tasty.Hedgehog (testPropertyNamed)++-- | 'Test.Tasty.Hedgehog.testProperty' has been deprecated in favor of+-- 'testPropertyNamed', but we've written our test cases in such a way that using+-- it correctly is hard. To prevent deprecation warnings, we apply this workaround.+testPropertyXXX :: TestName -> Property -> TestTree+testPropertyXXX nm prop = testPropertyNamed nm (fromString nm) prop