clash-prelude 1.4.6 → 1.4.7
raw patch · 27 files changed
+436/−245 lines, 27 filesdep +extradep ~ghc-bignumdep ~hashabledep ~textPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: extra
Dependency ranges changed: ghc-bignum, hashable, text, time
API changes (from Hackage documentation)
+ Clash.Annotations.Primitive: instance GHC.Classes.Eq Clash.Annotations.Primitive.Primitive
+ Clash.Annotations.Primitive: instance GHC.Classes.Eq Clash.Annotations.Primitive.PrimitiveWarning
+ Clash.Annotations.Primitive: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Annotations.Primitive.PrimitiveGuard a)
- Clash.Explicit.RAM: asyncRam# :: (HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom Int -> Signal wdom Bool -> Signal wdom Int -> Signal wdom a -> Signal rdom a
+ Clash.Explicit.RAM: asyncRam# :: forall wdom rdom n a. (HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom Int -> Signal wdom Bool -> Signal wdom Int -> Signal wdom a -> Signal rdom a
- Clash.Sized.Internal.BitVector: undefError :: (HasCallStack, KnownNat n) => String -> [BitVector n] -> a
+ Clash.Sized.Internal.BitVector: undefError :: KnownNat n => String -> [BitVector n] -> a
Files
- CHANGELOG.md +15/−0
- clash-prelude.cabal +10/−6
- src/Clash/Annotations/Primitive.hs +5/−3
- src/Clash/Examples/Internal.hs +1/−1
- src/Clash/Explicit/BlockRam.hs +21/−14
- src/Clash/Explicit/BlockRam/File.hs +16/−7
- src/Clash/Explicit/RAM.hs +55/−24
- src/Clash/Explicit/ROM.hs +9/−6
- src/Clash/Explicit/ROM/File.hs +7/−4
- src/Clash/Explicit/Reset.hs +1/−1
- src/Clash/Intel/ClockGen.hs +4/−0
- src/Clash/Prelude/BlockRam.hs +13/−10
- src/Clash/Prelude/BlockRam/File.hs +7/−4
- src/Clash/Prelude/RAM.hs +7/−4
- src/Clash/Prelude/ROM.hs +8/−6
- src/Clash/Prelude/ROM/File.hs +8/−5
- src/Clash/Signal/Bundle/Internal.hs +3/−7
- src/Clash/Signal/Internal.hs +1/−1
- src/Clash/Sized/Internal/BitVector.hs +6/−6
- src/Clash/Sized/Internal/BitVector.hs-boot +1/−2
- src/Clash/Sized/RTree.hs +1/−1
- src/Clash/Sized/Vector.hs +3/−3
- src/Clash/Tutorial.hs +60/−124
- src/Clash/XException.hs +6/−6
- tests/Clash/Tests/BlockRam.hs +52/−0
- tests/Clash/Tests/Ram.hs +112/−0
- tests/unittests.hs +4/−0
CHANGELOG.md view
@@ -1,4 +1,19 @@ # Changelog for the Clash project+## 1.4.7 *Jan 30th 2022*+Fixed:+ * Clash now shows days in time strings for compile runs which take longer than a day [#1989](https://github.com/clash-lang/clash-compiler/compare/issue-1989).+ * Types defined in the package head are no longer qualified in the package body when rendering VHDL [#1996](https://github.com/clash-lang/clash-compiler/issues/1996).+ * `asyncRam` with different read and write clocks no longer produce the wrong results in Haskell simulation. [#2031](https://github.com/clash-lang/clash-compiler/pull/2031)+ * `Clash.Explicit.RAM.asyncRam#` Haskell simulation incorrectly treated an _undefined_ write enable as asserted. It now causes an _undefined_ value to be written instead. This problem did not propagate to the other `asyncRam` functions, where the same condition would simultaneously lead to an undefined write address, which would be handled correctly. This problem also only affects Haskell simulation, not the generated HDL. [#2031](https://github.com/clash-lang/clash-compiler/pull/2031)+ * `Clash.Explicit.BlockRam.blockRam#` and `Clash.Explicit.BlockRam.File.blockRamFile#` Haskell simulation incorrectly treated an _undefined_ write enable as asserted. It now causes an _undefined_ value to be written instead. This problem did not propagate to the other `blockRam` functions, where the same condition would simultaneously lead to an undefined write address, which would be handled correctly. This problem also only affects Haskell simulation, not the generated HDL.([#2054](https://github.com/clash-lang/clash-compiler/pull/2054))++Internal changes:+ * Removed instances of `Hashable Term` and `Hashable Type` [#1986](https://github.com/clash-lang/clash-compiler/pull/1986)+ * Added structural equality on `Term` (`Clash.Core.Subst.eqTerm`) and `Type` (`Clash.Core.Subst.eqType`)++Internal fixes:+ * Enable used to be a `Bool` in the Blackbox DSL, so we could use `boolToBit`. However it now has its own type in the DSL (`Enable domainName`), so we've added a new conversion function in order to convert it to a Bool.+ ## 1.4.6 *Oct 26th 2021*
clash-prelude.cabal view
@@ -1,6 +1,6 @@ Cabal-version: 2.2 Name: clash-prelude-Version: 1.4.6+Version: 1.4.7 Synopsis: Clash: a functional hardware description language - Prelude library Description: Clash is a functional hardware description language that borrows both its@@ -50,7 +50,8 @@ Maintainer: QBayLogic B.V. <devops@qbaylogic.com> Copyright: Copyright © 2013-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2017-2019, QBayLogic B.V., Google Inc.+ 2017-2019, QBayLogic B.V., Google Inc.,+ 2020-2022, QBayLogic B.V. Category: Hardware Build-type: Custom @@ -318,11 +319,12 @@ data-binary-ieee754 >= 0.4.4 && < 0.6, data-default-class >= 0.1.2 && < 0.2, deepseq >= 1.4.1.0 && < 1.5,+ extra >= 1.6.17 && < 1.8, ghc-prim >= 0.5.1.0 && < 0.8, ghc-typelits-extra >= 0.4 && < 0.5, ghc-typelits-knownnat >= 0.7.2 && < 0.8, ghc-typelits-natnormalise >= 0.7.2 && < 0.8,- hashable >= 1.2.1.0 && < 1.4,+ hashable >= 1.2.1.0 && < 1.5, half >= 0.2.2.3 && < 1.0, interpolate >= 0.2 && < 0.3, lens >= 4.10 && < 5.1.0,@@ -334,16 +336,16 @@ th-abstraction >= 0.2.10 && < 0.5.0, th-lift >= 0.7.0 && < 0.9, th-orphans >= 0.13.1 && < 1.0,- text >= 0.11.3.1 && < 1.3,+ text >= 0.11.3.1 && < 2.1, text-show >= 3.7 && < 3.10,- time >= 1.8 && < 1.13,+ time >= 1.8 && < 1.14, transformers >= 0.5.2.0 && < 0.7, type-errors >= 0.2.0.0 && < 0.3, uniplate >= 1.6.12 && < 1.7, vector >= 0.11 && < 1.0 if impl(ghc >= 9.0.0)- Build-Depends: ghc-bignum >= 1.0 && < 1.1+ Build-Depends: ghc-bignum >= 1.0 && < 1.3 else Build-Depends: integer-gmp >= 1.0.1.0 && < 2.0 if flag(large-tuples)@@ -402,11 +404,13 @@ Clash.Tests.AutoReg Clash.Tests.BitPack Clash.Tests.BitVector+ Clash.Tests.BlockRam Clash.Tests.DerivingDataRepr Clash.Tests.DerivingDataReprTypes Clash.Tests.Fixed Clash.Tests.FixedExhaustive Clash.Tests.NFDataX+ Clash.Tests.Ram Clash.Tests.Reset Clash.Tests.Resize Clash.Tests.Signal
src/Clash/Annotations/Primitive.hs view
@@ -272,7 +272,7 @@ -- ^ Description of a primitive for a given 'HDL's in a file at 'FilePath' | InlinePrimitive [HDL] String -- ^ Description of a primitive for a given 'HDL's as an inline 'String'- deriving (Show, Read, Data, Generic, NFData, Hashable)+ deriving (Show, Read, Data, Generic, NFData, Hashable, Eq) -- | Primitive guard to mark a value as either not translatable or as having a -- blackbox with an optional extra warning. Helps Clash generate better error@@ -287,7 +287,9 @@ | HasBlackBox [PrimitiveWarning] a -- ^ Marks a value as having a blackbox. Clash will error if it hasn't found -- a blackbox.- deriving (Show, Read, Data, Generic, NFData, Hashable, Functor, Foldable, Traversable, Binary)+ deriving+ ( Show, Read, Data, Generic, NFData, Hashable, Functor, Foldable+ , Traversable, Binary, Eq ) -- | Warning that will be emitted on instantiating a guarded value. data PrimitiveWarning@@ -296,7 +298,7 @@ -- instantiated in a non-testbench context. | WarnAlways String -- ^ Always emit warning upon primitive instantiation.- deriving (Show, Read, Data, Generic, NFData, Hashable, Binary)+ deriving (Show, Read, Data, Generic, NFData, Hashable, Binary, Eq) -- | Extract primitive definition from a PrimitiveGuard. Will yield Nothing -- for guards of value 'DontTranslate'.
src/Clash/Examples/Internal.hs view
@@ -105,7 +105,7 @@ s = register 0 (mux upDown (s + 1) (s - 1)) lfsrF' :: BitVector 16 -> BitVector 16-lfsrF' s = pack feedback ++# slice d15 d1 s+lfsrF' s = pack feedback ++# slice (SNat @15) d1 s where feedback = s!5 `xor` s!3 `xor` s!2 `xor` s!0
src/Clash/Explicit/BlockRam.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2013-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> BlockRAM primitives @@ -234,7 +235,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 "X" in the few leading outputs.+replace it with the string @\"undefined\"@ in the first few leading outputs. @ >>> printX $ sampleN 32 $ system2 prog systemClockGen resetGen enableGen@@ -364,7 +365,7 @@ When we simulate our system we see that it works. This time again, we need to disregard the first sample, because the initial output of a 'blockRam' is /undefined/. We use the utility function 'Clash.XException.printX'-to conveniently filter out the undefinedness and replace it with the string "X".+to conveniently filter out the undefinedness and replace it with the string @\"undefined\"@. @ >>> printX $ sampleN 34 $ system3 prog2 systemClockGen resetGen enableGen@@ -695,7 +696,8 @@ -- | Create a blockRAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is /undefined/+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- @ -- bram40@@ -741,7 +743,8 @@ -- | Create a blockRAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is /undefined/+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- @ -- bram32@@ -768,9 +771,7 @@ -> Enable dom -- ^ Global enable -> Vec (2^n) a- -- ^ Initial content of the BRAM, also- -- determines the size, @2^n@, of- -- the BRAM.+ -- ^ Initial content of the BRAM -- -- __NB__: __MUST__ be a constant. -> Signal dom (Unsigned n)@@ -788,7 +789,7 @@ ClearOnReset :: ResetStrategy 'True NoClearOnReset :: ResetStrategy 'False --- | Version of blockram that has no default values set. May be cleared to 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@@ -811,7 +812,7 @@ -> SNat n -- ^ Number of elements in BRAM -> (Index n -> a)- -- ^ If applicable (see first 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))@@ -1006,10 +1007,16 @@ upd ram we waddr d = case maybeIsX we of Nothing -> case maybeIsX waddr of- Nothing -> fmap (const (seq waddr d)) ram- Just wa -> Seq.update wa d ram+ Nothing -> -- Put the XException from `waddr` as the value in all+ -- locations of `ram`.+ seq waddr d <$ ram+ Just wa -> -- Put the XException from `we` as the value at address+ -- `waddr`.+ Seq.update wa (seq we d) ram Just True -> case maybeIsX waddr of- Nothing -> fmap (const (seq waddr d)) ram+ Nothing -> -- Put the XException from `waddr` as the value in all+ -- locations of `ram`.+ seq waddr d <$ ram Just wa -> Seq.update wa d ram _ -> ram {-# ANN blockRam# hasBlackBox #-}
src/Clash/Explicit/BlockRam/File.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2015-2016, University of Twente, 2017 , Google Inc.- 2019 , Myrtle Software Ltd+ 2019 , Myrtle Software Ltd,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> = Initializing a BlockRAM with a data file #usingramfiles# @@ -113,7 +114,8 @@ -- | Create a blockRAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:@@ -158,7 +160,8 @@ -- | Create a blockRAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:@@ -252,10 +255,16 @@ upd ram we waddr d = case maybeIsX we of Nothing -> case maybeIsX waddr of- Nothing -> fmap (const (seq waddr d)) ram- Just wa -> Seq.update wa d ram+ Nothing -> -- Put the XException from `waddr` as the value in all+ -- locations of `ram`.+ seq waddr d <$ ram+ Just wa -> -- Put the XException from `we` as the value at address+ -- `waddr`.+ Seq.update wa (seq we d) ram Just True -> case maybeIsX waddr of- Nothing -> fmap (const (seq waddr d)) ram+ Nothing -> -- Put the XException from `waddr` as the value in all+ -- locations of `ram`.+ seq waddr d <$ ram Just wa -> Seq.update wa d ram _ -> ram
src/Clash/Explicit/RAM.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2015-2016, University of Twente, 2017 , Google Inc.- 2019 , Myrtle Software Ltd+ 2019 , Myrtle Software Ltd,+ 2022 , QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> RAM primitives with a combinational read port. -}@@ -34,16 +35,17 @@ import GHC.TypeLits (KnownNat) import qualified Data.Sequence as Seq -import Clash.Explicit.Signal- (unbundle, unsafeSynchronizer, KnownDomain, enable)+import Clash.Explicit.Signal (unbundle, KnownDomain, enable) import Clash.Promoted.Nat (SNat (..), snatToNum, pow2SNat) import Clash.Signal.Internal (Clock (..), Signal (..), Enable, fromEnable)+import Clash.Signal.Internal.Ambiguous (clockPeriod) import Clash.Sized.Unsigned (Unsigned)-import Clash.XException (errorX, maybeIsX, fromJustX)+import Clash.XException (errorX, maybeIsX, fromJustX, seqX) -- | Create a RAM with space for 2^@n@ elements ----- * __NB__: Initial content of the RAM is 'undefined'+-- * __NB__: Initial content of the RAM is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- Additional helpful information: --@@ -75,7 +77,8 @@ -- | Create a RAM with space for @n@ elements ----- * __NB__: Initial content of the RAM is 'undefined'+-- * __NB__: Initial content of the RAM is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- Additional helpful information: --@@ -110,7 +113,8 @@ -- | RAM primitive asyncRam#- :: ( HasCallStack+ :: forall wdom rdom n a+ . ( HasCallStack , KnownDomain wdom , KnownDomain rdom ) => Clock wdom@@ -131,29 +135,56 @@ -- ^ Value to write (at address @w@) -> Signal rdom a -- ^ Value of the @RAM@ at address @r@-asyncRam# wclk rclk en sz rd we wr din =- unsafeSynchronizer wclk rclk dout+asyncRam# !_ !_ en sz rd we wr din = dout where- rd' = unsafeSynchronizer rclk wclk rd ramI = Seq.replicate- (snatToNum sz)+ szI (withFrozenCallStack (errorX "asyncRam#: initial value undefined"))- en' = fromEnable (enable en we)- dout = go ramI rd' en' wr din+ en0 = fromEnable (enable en we)+ dout = if rPeriod == wPeriod+ then goSingle ramI rd en0 wr din+ else go 0 ramI rd en0 wr din+ rPeriod = snatToNum (clockPeriod @rdom) :: Int+ wPeriod = snatToNum (clockPeriod @wdom) :: Int+ szI = snatToNum sz :: Int - go :: Seq.Seq a -> Signal wdom Int -> Signal wdom Bool- -> Signal wdom Int -> Signal wdom a -> Signal wdom a- go !ram (r :- rs) (e :- es) (w :- ws) (d :- ds) =- let ram' = upd ram e (fromEnum w) d+ goSingle :: Seq.Seq a -> Signal rdom Int -> Signal wdom Bool+ -> Signal wdom Int -> Signal wdom a -> Signal rdom a+ goSingle !ram (r :- rs) ~(e :- es) wt@(~(w :- ws)) dt@(~(d :- ds)) =+ let ram0 = upd ram e w d o = ram `Seq.index` r- in o :- go ram' rs es ws ds+ in o :- (wt `seq` dt `seq` goSingle ram0 rs es ws ds) - upd ram we' waddr d = case maybeIsX we' of+ -- Given+ -- tR = absolute time of next active edge of read clock+ -- tW = absolute time of next active edge of write clock+ -- relTime is defined as relTime = tW - tR+ --+ -- Put differently, relative time 0 points at the next active edge of the+ -- read clock, and relTime points at the next active edge of the write+ -- clock.+ go :: Int -> Seq.Seq a -> Signal rdom Int -> Signal wdom Bool+ -> Signal wdom Int -> Signal wdom a -> Signal rdom a+ go relTime !ram rt@(~(r :- rs)) et@(~(e :- es)) wt@(~(w :- ws))+ dt@(~(d :- ds))+ | relTime < 0 = let ram0 = upd ram e w d+ in wt `seq` dt `seq`+ go (relTime + wPeriod) ram0 rt es ws ds+ | otherwise = let o = ram `Seq.index` r+ in o :- go (relTime - rPeriod) ram rs et wt dt++ upd ram we0 waddr d = case maybeIsX we0 of Nothing -> case maybeIsX waddr of- Nothing -> fmap (const (seq waddr d)) ram- Just wa -> Seq.update wa d ram+ Nothing -> -- Put the XException from `waddr` as the value in all+ -- locations of `ram`.+ seq waddr d <$ ram+ Just wa -> -- Put the XException from `we` as the value at address+ -- `waddr`.+ Seq.update wa (seq we0 d) ram Just True -> case maybeIsX waddr of- Nothing -> fmap (const (seq waddr d)) ram- Just wa -> Seq.update wa d ram+ Nothing -> -- Put the XException from `waddr` as the value in all+ -- locations of `ram`.+ seq waddr d <$ ram+ Just wa -> d `seqX` Seq.update wa d ram _ -> ram {-# NOINLINE asyncRam# #-}
src/Clash/Explicit/ROM.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2015-2016, University of Twente, 2017 , Google Inc.- 2019 , Myrtle Software Ltd+ 2019 , Myrtle Software Ltd,+ 2022 , QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> ROMs -}@@ -40,7 +41,8 @@ -- | A ROM with a synchronous read port, with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- Additional helpful information: --@@ -66,7 +68,8 @@ -- | A ROM with a synchronous read port, with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- Additional helpful information: --@@ -79,7 +82,7 @@ -> Enable dom -- ^ Global enable -> Vec n a- -- ^ ROM content+ -- ^ ROM content, also determines the size, @n@, of the ROM -- -- __NB:__ must be a constant -> Signal dom addr@@ -98,7 +101,7 @@ -> Enable dom -- ^ Global enable -> Vec n a- -- ^ ROM content+ -- ^ ROM content, also determines the size, @n@, of the ROM -- -- __NB:__ must be a constant -> Signal dom Int
src/Clash/Explicit/ROM/File.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2015-2016, University of Twente, 2017 , Google Inc.- 2019 , Myrtle Software Ltd.+ 2019 , Myrtle Software Ltd.,+ 2022 , QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> = Initializing a ROM with a data file #usingromfiles# @@ -99,7 +100,8 @@ -- | A ROM with a synchronous read port, with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:@@ -139,7 +141,8 @@ -- | A ROM with a synchronous read port, with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:
src/Clash/Explicit/Reset.hs view
@@ -64,7 +64,7 @@ -- be de-asserted synchronously but it can still be asserted asynchronously. -- The reset assert is immediate, but reset de-assertion is delayed by two -- cycles.-+-- -- Normally, asynchronous resets can be both asynchronously asserted and -- de-asserted. Asynchronous de-assertion can induce meta-stability in the -- component which is being reset. To ensure this doesn't happen,
src/Clash/Intel/ClockGen.hs view
@@ -38,6 +38,8 @@ -- -- outputs a clock running at 100 MHz -- altpll @@"50MHzDom" @@"100MHzDom" (SSymbol @@"altpll50to100") clk50 rst -- @+--+-- 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) altpll :: forall domOut domIn name . (KnownDomain domIn, KnownDomain domOut)@@ -81,6 +83,8 @@ -- @ -- -- respectively.+--+-- 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) alteraPll :: (Clocks t, KnownDomain domIn, ClocksCxt t) => SSymbol name
src/Clash/Prelude/BlockRam.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2013-2016, University of Twente, 2016-2019, Myrtle Software Ltd,- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> BlockRAM primitives @@ -231,10 +232,10 @@ Again, we can simulate our system and see that it works. This time however, we need to disregard the first few output samples, because the initial content of an-'Clash.Prelude.RAM.asyncRam' is 'Clash.XException.undefined', and consequently, the first few-output samples are also 'Clash.XException.undefined'. We use the utility function+'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 "X" in the few leading outputs.+replace it with the string @\"undefined\"@ in the few leading outputs. @ >>> printX $ sampleN @System 32 (system2 prog)@@ -362,8 +363,8 @@ When we simulate our system we see that it works. This time again, we need to disregard the first sample, because the initial output of a-'blockRam' is 'Clash.XException.undefined'. We use the utility function 'Clash.XException.printX'-to conveniently filter out the undefinedness and replace it with the string "X".+'blockRam' is /undefined/. We use the utility function 'Clash.XException.printX'+to conveniently filter out the undefinedness and replace it with the string @\"undefined\"@. @ >>> printX $ sampleN @System 34 (system3 prog2)@@ -673,7 +674,8 @@ -- | Create a blockRAM with space for @n@ elements. -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'Clash.XException.undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- @ -- bram40@@ -770,7 +772,8 @@ -- | Create a blockRAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'Clash.XException.undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- @ -- bram32@@ -794,7 +797,7 @@ , KnownNat n ) => Vec (2^n) a- -- ^ Initial content of the BRAM, also determines the size, @2^n@, of the BRAM.+ -- ^ Initial content of the BRAM -- -- __NB__: __MUST__ be a constant. -> Signal dom (Unsigned n)
src/Clash/Prelude/BlockRam/File.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2015-2016, University of Twente, 2019 , Myrtle Software Ltd- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2022 , QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> = Initializing a BlockRAM with a data file #usingramfiles# @@ -97,7 +98,8 @@ -- | Create a blockRAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:@@ -143,7 +145,8 @@ -- | Create a blockRAM with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:
src/Clash/Prelude/RAM.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2015-2016, University of Twente, 2017-2019, Myrtle Software Ltd- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> RAM primitives with a combinational read port. -}@@ -34,7 +35,8 @@ -- | Create a RAM with space for @n@ elements. ----- * __NB__: Initial content of the RAM is 'undefined'+-- * __NB__: Initial content of the RAM is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- Additional helpful information: --@@ -60,7 +62,8 @@ -- | Create a RAM with space for 2^@n@ elements ----- * __NB__: Initial content of the RAM is 'undefined'+-- * __NB__: Initial content of the RAM is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- Additional helpful information: --
src/Clash/Prelude/ROM.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2015-2016, University of Twente, 2017 , Google Inc.- 2019 , Myrtle Software Ltd+ 2019 , Myrtle Software Ltd,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> ROMs -}@@ -48,7 +49,7 @@ asyncRom :: (KnownNat n, Enum addr) => Vec n a- -- ^ ROM content+ -- ^ ROM content, also determines the size, @n@, of the ROM -- -- __NB:__ must be a constant -> addr@@ -81,7 +82,7 @@ asyncRom# :: KnownNat n => Vec n a- -- ^ ROM content+ -- ^ ROM content, also determines the size, @n@, of the ROM -- -- __NB:__ must be a constant -> Int@@ -111,7 +112,7 @@ , HiddenClock dom , HiddenEnable dom ) => Vec n a- -- ^ ROM content+ -- ^ ROM content, also determines the size, @n@, of the ROM -- -- __NB:__ must be a constant -> Signal dom (Unsigned m)@@ -124,7 +125,8 @@ -- | A ROM with a synchronous read port, with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- Additional helpful information: --
src/Clash/Prelude/ROM/File.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2015-2016, University of Twente, 2017 , Google Inc.- 2019 , Myrtle Software Ltd+ 2019 , Myrtle Software Ltd,+ 2022 , QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> = Initializing a ROM with a data file #usingromfiles# @@ -149,7 +150,7 @@ -> BitVector m -- ^ The value of the ROM at address @rd@ asyncRomFile sz file = asyncRomFile# sz file . fromEnum--- Leave 'asyncRom' eta-reduced, see Note [Eta-reduction and unsafePerformIO initMem]+-- Leave 'asyncRomFile#' eta-reduced, see Note [Eta-reduction and unsafePerformIO initMem] {-# INLINE asyncRomFile #-} -- Note [Eta-reduction and unsafePerformIO initMem]@@ -248,7 +249,8 @@ -- | A ROM with a synchronous read port, with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:@@ -289,7 +291,8 @@ -- | A ROM with a synchronous read port, with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:
src/Clash/Signal/Bundle/Internal.hs view
@@ -1,9 +1,9 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE TemplateHaskell #-} -module Clash.Signal.Bundle.Internal where+module Clash.Signal.Bundle.Internal (deriveBundleTuples, idPrimitive) where -import Control.Monad (liftM)+import Control.Monad.Extra (concatMapM) import Clash.Annotations.Primitive (Primitive(InlinePrimitive)) import Clash.CPP (maxTupleSize) import Clash.Signal.Internal (Signal((:-)))@@ -20,10 +20,6 @@ ipJson = "[{\"Primitive\": {\"name\": \"" ++ show nm ++ "\", \"primType\": \"Function\"}}]" ip = InlinePrimitive [minBound..maxBound] ipJson --- | Monadic version of concatMap-concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]-concatMapM f xs = liftM concat (mapM f xs)- -- | Contruct all the tuple instances for Bundle. deriveBundleTuples :: Name@@ -162,7 +158,7 @@ , unbundleSig, unbundleF, unbundlePrimAnn, unbundleNoInlineAnn ] -mkFunTys :: Foldable t => t Type -> Type -> Type+mkFunTys :: Foldable t => t TH.Type -> TH.Type -> TH.Type mkFunTys args res= foldl' go res args where go l r = AppT (AppT ArrowT l) r
src/Clash/Signal/Internal.hs view
@@ -854,7 +854,7 @@ clockTag (Clock dom) = dom -- | Clock generator for simulations. Do __not__ use this clock generator for--- for the /testBench/ function, use 'Clash.Explicit.Testbench.tbClockGen' instead.+-- the /testBench/ function, use 'Clash.Explicit.Testbench.tbClockGen' instead. -- -- To be used like: --
src/Clash/Sized/Internal/BitVector.hs view
@@ -153,7 +153,7 @@ import GHC.Natural (naturalToInteger) #endif import GHC.Prim (dataToTag#)-import GHC.Stack (HasCallStack, withFrozenCallStack)+import GHC.Stack (withFrozenCallStack) import GHC.TypeLits (KnownNat, Nat, type (+), type (-)) #if MIN_VERSION_base(4,15,0) import GHC.TypeNats (natVal)@@ -1179,35 +1179,35 @@ -- error for infix operator-undefErrorI :: (HasCallStack, KnownNat m, KnownNat n) => String -> BitVector m -> BitVector n -> a+undefErrorI :: (KnownNat m, KnownNat n) => String -> BitVector m -> BitVector n -> a undefErrorI op bv1 bv2 = withFrozenCallStack $ errorX $ "Clash.Sized.BitVector." ++ op ++ " called with (partially) undefined arguments: " ++ show bv1 ++ " " ++ op ++" " ++ show bv2 -- error for prefix operator/function-undefErrorP :: (HasCallStack, KnownNat m, KnownNat n) => String -> BitVector m -> BitVector n -> a+undefErrorP :: (KnownNat m, KnownNat n) => String -> BitVector m -> BitVector n -> a undefErrorP op bv1 bv2 = withFrozenCallStack $ errorX $ "Clash.Sized.BitVector." ++ op ++ " called with (partially) undefined arguments: " ++ show bv1 ++ " " ++ show bv2 -- error for prefix operator/function-undefErrorP3 :: (HasCallStack, KnownNat m, KnownNat n, KnownNat o) => String -> BitVector m -> BitVector n -> BitVector o -> a+undefErrorP3 :: (KnownNat m, KnownNat n, KnownNat o) => String -> BitVector m -> BitVector n -> BitVector o -> a undefErrorP3 op bv1 bv2 bv3 = withFrozenCallStack $ errorX $ "Clash.Sized.BitVector." ++ op ++ " called with (partially) undefined arguments: " ++ show bv1 ++ " " ++ show bv2 ++ " " ++ show bv3 -- error for unary operator/function-undefErrorU :: (HasCallStack, KnownNat n) => String -> BitVector n -> a+undefErrorU :: KnownNat n => String -> BitVector n -> a -- undefErrorU op bv1 = undefError ("Clash.Sized.BitVector." ++ op) [bv1] undefErrorU op bv1 = withFrozenCallStack $ errorX $ "Clash.Sized.BitVector." ++ op ++ " called with (partially) undefined argument: " ++ show bv1 -undefError :: (HasCallStack, KnownNat n) => String -> [BitVector n] -> a+undefError :: KnownNat n => String -> [BitVector n] -> a undefError op bvs = withFrozenCallStack $ errorX $ op ++ " called with (partially) undefined arguments: "
src/Clash/Sized/Internal/BitVector.hs-boot view
@@ -10,11 +10,10 @@ module Clash.Sized.Internal.BitVector where import GHC.TypeLits (KnownNat,Nat)-import GHC.Stack (HasCallStack) import Data.Kind (Type) type role BitVector nominal data BitVector :: Nat -> Type data Bit -undefError :: (HasCallStack, KnownNat n) => String -> [BitVector n] -> a+undefError :: KnownNat n => String -> [BitVector n] -> a
src/Clash/Sized/RTree.hs view
@@ -336,7 +336,7 @@ import Data.Singletons import Data.Proxy -data IIndex (f :: 'TyFun' Nat *) :: *+data IIndex (f :: 'TyFun' Nat Type) :: Type type instance 'Apply' IIndex l = 'Index' ((2^l)+1) populationCount' :: (KnownNat k, KnownNat (2^k))
src/Clash/Sized/Vector.hs view
@@ -2130,7 +2130,7 @@ -- import Data.Singletons -- import Data.Proxy ----- data Append (m :: Nat) (a :: *) (f :: 'TyFun' Nat *) :: *+-- data Append (m :: Nat) (a :: Type) (f :: 'TyFun' Nat Type) :: Type -- type instance 'Apply' (Append m a) l = 'Vec' (l + m) a -- -- append' xs ys = 'dfold' (Proxy :: Proxy (Append m a)) (const (':>')) ys xs@@ -2164,7 +2164,7 @@ where go :: SNat n -> Vec n a -> (p @@ n) go _ Nil = z- go s (y `Cons` (ys :: Vec z a)) =+ go s (y `Cons` ys) = let s' = s `subSNat` d1 in f s' y (go s' ys) {-# NOINLINE dfold #-}@@ -2260,7 +2260,7 @@ import Data.Singletons import Data.Proxy -data IIndex (f :: 'TyFun' Nat *) :: *+data IIndex (f :: 'TyFun' Nat Type) :: Type type instance 'Apply' IIndex l = 'Index' ((2^l)+1) populationCount' :: (KnownNat k, KnownNat (2^k))
src/Clash/Tutorial.hs view
@@ -906,24 +906,24 @@ import "Clash.Intel.ClockGen" 'createDomain' vSystem{vName=\"DomInput\", vPeriod=20000}-'createDomain' vSystem{vName=\"Dom50\", vPeriod=50000}+'createDomain' vSystem{vName=\"Dom100\", vPeriod=10000} topEntity :: Clock DomInput -> Signal DomInput Bool- -> Signal Dom50 Bit- -> Signal Dom50 (BitVector 8)+ -> Signal Dom100 Bit+ -> Signal Dom100 (BitVector 8) topEntity clk rst = 'exposeClockResetEnable' ('mealy' blinkerT (1,False,0) . Clash.Prelude.isRising 1) pllOut rstSync 'enableGen' where- (pllOut,pllStable) = 'Clash.Intel.ClockGen.altpll' \@Dom50 (SSymbol \@\"altpll50\") clk ('Clash.Signal.unsafeFromLowPolarity' rst)+ (pllOut,pllStable) = 'Clash.Intel.ClockGen.altpll' \@Dom100 (SSymbol \@\"altpll100\") clk ('Clash.Signal.unsafeFromLowPolarity' rst) rstSync = 'Clash.Signal.resetSynchronizer' pllOut ('Clash.Signal.unsafeFromLowPolarity' pllStable) enableGen blinkerT (leds,mode,cntr) key1R = ((leds',mode',cntr'),leds) where- -- clock frequency = 50e6 (50 MHz)+ -- clock frequency = 100e6 (100 MHz) -- led update rate = 333e-3 (every 333ms)- cnt_max = 16650000 :: ('Index' 16650001) -- 50e6 * 333e-3+ cnt_max = 'maxBound' :: ('Index' 33300000) -- 100e6 * 333e-3 cntr' | cntr == cnt_max = 0 | otherwise = cntr + 1@@ -946,17 +946,17 @@ use IEEE.MATH_REAL.ALL; use std.textio.all; use work.all;-use work.blinker_types.all;+use work.Blinker_topEntity_types.all; -entity topentity is+entity topEntity is port(-- clock- clk : in blinker_types.clk_dominput;- rst : in boolean;- x : in std_logic;- leds : out std_logic_vector(7 downto 0));+ clk : in Blinker_topEntity_types.clk_DomInput;+ rst : in boolean;+ x : in std_logic;+ result : out std_logic_vector(7 downto 0)); end; -architecture structural of topentity is+architecture structural of topEntity is ... end; @@@ -1458,7 +1458,7 @@ Clash supports designs multiple /clock/ (and /reset/) domains, though perhaps in a slightly limited form. What is possible is: -* Create clock primitives, such as PPLs, which have an accompanying HDL primitive+* Create clock primitives, such as PLLs, which have an accompanying HDL primitive (described <#primitives later on> in this tutorial). * Explicitly assign clocks to memory primitives. * Synchronize between differently-clocked parts of your design in a type-safe@@ -1514,7 +1514,7 @@ What this means is that when Clash converts your design to VHDL/(System)Verilog, you end up with a top-level module/entity with multiple clock and reset ports for the different clock domains. If you're targeting an FPGA, you can use e.g. a-<https://www.altera.com/literature/ug/ug_altpll.pdf PPL> or+<https://www.altera.com/literature/ug/ug_altpll.pdf PLL> or <http://www.xilinx.com/support/documentation/user_guides/ug472_7Series_Clocking.pdf MMCM> to provide the clock signals. @@ -2176,7 +2176,7 @@ @ x =- case 'resetKind' @@'System' of+ case 'resetKind' @'System' of SAsynchronous -> \'a\' SSynchronous -> \'b\' @@@ -2393,41 +2393,41 @@ import Clash.Prelude import Clash.Explicit.Testbench -dotp :: SaturatingNum a- => Vec (n + 1) a- -> Vec (n + 1) a+dotp :: 'SaturatingNum' a+ => 'Vec' (n + 1) a+ -> 'Vec' (n + 1) a -> a-dotp as bs = fold boundedAdd (zipWith boundedMul as bs)+dotp as bs = 'fold' 'boundedAdd' ('zipWith' 'boundedMul' as bs) fir- :: ( HiddenClockResetEnable dom- , Default a- , KnownNat n- , SaturatingNum a- , NFDataX a )- => Vec (n + 1) a -> Signal dom a -> Signal dom a+ :: ( 'HiddenClockResetEnable' dom+ , 'KnownNat' n+ , 'SaturatingNum' a+ , 'NFDataX' a+ , 'Default' a )+ => 'Vec' (n + 1) a -> 'Signal' dom a -> 'Signal' dom a fir coeffs x_t = y_t where- y_t = dotp coeffs \<$\> bundle xs- xs = window x_t+ y_t = dotp coeffs \<$\> 'bundle' xs+ xs = 'window' x_t topEntity- :: Clock System- -> Reset System- -> Enable System- -> Signal System (Signed 16)- -> Signal System (Signed 16)-topEntity = exposeClockResetEnable (fir (2:>3:>(-2):>8:>Nil))+ :: 'Clock' 'System'+ -> 'Reset' 'System'+ -> 'Enable' 'System'+ -> 'Signal' 'System' ('Signed' 16)+ -> 'Signal' 'System' ('Signed' 16)+topEntity = 'exposeClockResetEnable' (fir (2:>3:>(-2):>8:>'Nil')) {\-\# NOINLINE topEntity \#-\} -testBench :: Signal System Bool+testBench :: 'Signal' 'System' 'Bool' testBench = done where- testInput = stimuliGenerator clk rst (2:>3:>(-2):>8:>Nil)- expectedOutput = outputVerifier' clk rst (4:>12:>1:>20:>Nil)- done = expectedOutput (topEntity clk rst enableGen testInput)- clk = tbSystemClockGen (not \<$\> done)- rst = systemResetGen+ testInput = 'stimuliGenerator' clk rst (2:>3:>(-2):>8:>'Nil')+ expectedOutput = 'outputVerifier'' clk rst (4:>12:>1:>20:>'Nil')+ done = expectedOutput (topEntity clk rst 'enableGen' testInput)+ clk = 'tbSystemClockGen' (not \<$\> done)+ rst = 'systemResetGen' @ ==== Blinker circuit@@ -2487,102 +2487,38 @@ @ module Blinker where -import Clash.Prelude-import Clash.Intel.ClockGen--data LedMode- = Rotate- -- ^ After some period, rotate active led to the left- | Complement- -- ^ After some period, turn on all disable LEDs, and vice versa- deriving (Generic, 'NFDataX')---- Define a synthesis domain with a clock with a period of 20000 /ps/.-'createDomain' 'vSystem'{vName=\"Input\", vPeriod=20000}+import "Clash.Signal"+import "Clash.Prelude"+import "Clash.Intel.ClockGen" --- Define a synthesis domain with a clock with a period of 50000 /ps/.-'createDomain' 'vSystem'{vName=\"Dom50\", vPeriod=50000}+'createDomain' vSystem{vName=\"DomInput\", vPeriod=20000}+'createDomain' vSystem{vName=\"Dom100\", vPeriod=10000} -{\-\# ANN topEntity- ('Synthesize'- { t_name = \"blinker\"- , t_inputs = [ PortName \"CLOCK_50\"- , PortName \"KEY0\"- , PortName \"KEY1\"- ]- , t_output = PortName \"LED\"- }) \#-\} topEntity- :: Clock Input- -- ^ Incoming clock- -> Signal Input Bool- -- ^ Reset signal, straight from KEY0- -> Signal Dom50 Bit- -- ^ Mode choice, straight from KEY1. See \'LedMode\'.- -> Signal Dom50 (BitVector 8)- -- ^ Output containing 8 bits, corresponding to 8 LEDs-topEntity clk20 rstBtn modeBtn =- exposeClockResetEnable- (mealy blinkerT initialStateBlinkerT . isRising 1)- clk50- rstSync- en- modeBtn- where- -- | Enable line for subcomponents: we'll keep it always running- en = enableGen-- -- Start with the first LED turned on, in rotate mode, with the counter on zero- initialStateBlinkerT = (1, Rotate, 0)-- -- Signal coming from the reset button is low when pressed, and high when- -- not pressed. We convert this signal to the polarity of our domain with- -- 'unsafeFromLowPolarity'.- rst = 'Clash.Signal.unsafeFromLowPolarity' rstBtn-- -- Instantiate a PLL: this stabilizes the incoming clock signal and indicates- -- when the signal is stable. We're also using it to transform an incoming- -- clock signal running at 20 MHz to a clock signal running at 50 MHz.- (clk50, pllStable) =- altpll- \@Dom50- (SSymbol \@\"altpll50\")- clk20- rst-- -- Synchronize reset to clock signal coming from PLL. We want the reset to- -- remain active while the PLL is NOT stable, hence the conversion with- -- 'unsafeFromLowPolarity'- rstSync =- 'Clash.Signal.resetSynchronizer'- clk50- (unsafeFromLowPolarity pllStable)- en--flipMode :: LedMode -> LedMode-flipMode Rotate = Complement-flipMode Complement = Rotate+ :: Clock DomInput+ -> Signal DomInput Bool+ -> Signal Dom100 Bit+ -> Signal Dom100 (BitVector 8)+topEntity clk rst =+ 'exposeClockResetEnable' ('mealy' blinkerT (1,False,0) . Clash.Prelude.isRising 1) pllOut rstSync 'enableGen'+ where+ (pllOut,pllStable) = 'Clash.Intel.ClockGen.altpll' \@Dom100 (SSymbol \@\"altpll100\") clk ('Clash.Signal.unsafeFromLowPolarity' rst)+ rstSync = 'Clash.Signal.resetSynchronizer' pllOut ('Clash.Signal.unsafeFromLowPolarity' pllStable) -blinkerT- :: (BitVector 8, LedMode, Index 16650001)- -> Bool- -> ((BitVector 8, LedMode, Index 16650001), BitVector 8)-blinkerT (leds, mode, cntr) key1R = ((leds', mode', cntr'), leds)+blinkerT (leds,mode,cntr) key1R = ((leds',mode',cntr'),leds) where- -- clock frequency = 50e6 (50 MHz)+ -- clock frequency = 100e6 (100 MHz) -- led update rate = 333e-3 (every 333ms)- cnt_max = 16650000 :: Index 16650001 -- 50e6 * 333e-3+ cnt_max = 'maxBound' :: ('Index' 33300000) -- 100e6 * 333e-3 cntr' | cntr == cnt_max = 0 | otherwise = cntr + 1 - mode' | key1R = flipMode mode+ mode' | key1R = not mode | otherwise = mode - leds' | cntr == 0 =- case mode of- Rotate -> rotateL leds 1- Complement -> complement leds+ leds' | cntr == 0 = if mode then complement leds+ else rotateL leds 1 | otherwise = leds @ -}
src/Clash/XException.hs view
@@ -252,11 +252,11 @@ -- | Fully evaluate a value, returning 'Nothing' if it throws 'XException'. ----- > maybeX 42 = Just 42--- > maybeX (XException msg) = Nothing--- > maybeX (3, XException msg) = Nothing--- > maybeX (3, _|_) = _|_--- > maybeX _|_ = _|_+-- > maybeHasX 42 = Just 42+-- > maybeHasX (XException msg) = Nothing+-- > maybeHasX (3, XException msg) = Nothing+-- > maybeHasX (3, _|_) = _|_+-- > maybeHasX _|_ = _|_ -- maybeHasX :: NFData a => a -> Maybe a maybeHasX = maybeX hasX@@ -296,7 +296,7 @@ -- > isX 42 = Right 42 -- > isX (XException msg) = Left msg -- > isX (3, XException msg) = Right (3, XException msg)--- > isX (3, _|_) = (3, _|_)+-- > isX (3, _|_) = Right (3, _|_) -- > isX _|_ = _|_ isX :: a -> Either String a isX a =
+ tests/Clash/Tests/BlockRam.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE NoImplicitPrelude #-}++module Clash.Tests.BlockRam (tests) where++import qualified Data.List as List+import Test.Tasty+import Test.Tasty.HUnit++import qualified Clash.Explicit.Prelude as E+import Clash.Explicit.BlockRam (blockRam#)+import Clash.Prelude++primRam+ :: Signal System Int+ -> Signal System Bool+ -> Signal System Int+ -> Signal System Int+ -> Signal System (Maybe Int)+primRam rd we wr din =+ maybeIsX <$> blockRam# clockGen enableGen (0 :> 1 :> Nil) rd we wr din++type PrimSamples = [(Int, Bool, Int, Int, Maybe Int)]++undefEn :: PrimSamples++-- Undefined enable:+-- The written-to address should read 'undefined', but other addresses+-- should still have their data.++-- rd enable waddr wdata dout++undefEn = [ ( 0, undefined, 0 , 2 , Nothing)+ , ( 0, False , 0 , 3 , Just 0 )+ , ( 1, False , 0 , 3 , Nothing)+ , ( 1, False , 0 , 3 , Just 1 )+ ]++primRamAssertion+ :: PrimSamples+ -> Assertion+primRamAssertion samples = actual @?= expectedOutput+ where+ (rd, we, wr, din, expectedOutput) = List.unzip5 samples+ actual = E.sampleN (List.length samples) $ primRam (fromList rd)+ (fromList we)+ (fromList wr)+ (fromList din)++tests :: TestTree+tests = testGroup "BlockRam"+ [ testCase "Undefined enable" $ primRamAssertion undefEn+ ]
+ tests/Clash/Tests/Ram.hs view
@@ -0,0 +1,112 @@+-- Assert correct behavior:+--+-- Undefined enable:+-- The written-to address should read 'undefined', but other addresses+-- should still have their data.+--+-- Undefined write address:+-- All addresses should read 'undefined'.+--+-- Undefined write data:+-- The written-to address should read 'undefined', but other addresses+-- should still have their data.+--+-- Deasserted enable+-- It shouldn't matter that other write inputs are 'undefined'.+--+-- Deasserted enable, OOB address+-- It shouldn't matter that it is out of bounds.+--+-- Read address strictness+-- If the read result is not used, out-of-bounds read address shouldn't+-- matter (equivalent to issue #1458).++{-# LANGUAGE NoImplicitPrelude #-}++module Clash.Tests.Ram (tests) where++import qualified Data.List as L+import Test.Tasty+import Test.Tasty.HUnit++import Clash.Explicit.Prelude+import Clash.Explicit.RAM++type Ram = ( Signal System Int+ -> Signal System Bool+ -> Signal System Int+ -> Signal System Int+ -> Signal System (Maybe Int)+ )++ram :: Ram+ram rd we wr din =+ maybeIsX <$> asyncRam# clockGen clockGen enableGen d2 rd we wr din++maskOobRead :: Ram+maskOobRead rd we wr din =+ maybeIsX <$> mux (rd .<. 2) ram0 (pure 4)+ where+ ram0 = asyncRam# clockGen clockGen enableGen d2 rd we wr din++type Samples = [(Int, Bool, Int, Int, Maybe Int)]++initMem, undefEn, undefWAddr, undefWData, enFalse, enFalseOobWAddr,+ oobRAddrStrict+ :: Samples++-- rd enable waddr wdata dout+initMem = [ ( 0, True , 0 , 0 , Nothing)+ , ( 0, True , 1 , 1 , Just 0 )+ ]++undefEn = initMem <> [ ( 0, undefined, 0 , 2 , Just 0 )+ , ( 0, False , 0 , 3 , Nothing)+ , ( 1, False , 0 , 3 , Just 1 )+ ]++undefWAddr = initMem <> [ ( 0, True , undefined, 2 , Just 0 )+ , ( 0, False , 0 , 3 , Nothing)+ , ( 1, False , 0 , 3 , Nothing)+ ]++undefWData = initMem <> [ ( 0, True , 0 , undefined, Just 0 )+ , ( 0, False , 0 , 3 , Nothing)+ , ( 1, False , 0 , 3 , Just 1 )+ ]++enFalse = initMem <> [ ( 0, False , undefined, undefined, Just 0)+ , ( 0, False , undefined, undefined, Just 0)+ , ( 1, False , undefined, undefined, Just 1)+ ]++enFalseOobWAddr = initMem <> [ ( 0, False , 255 , 2 , Just 0 )+ , ( 0, False , 0 , 3 , Just 0 )+ , ( 1, False , 0 , 3 , Just 1 )+ ]++oobRAddrStrict = initMem <> [ ( 1, False , 0 , 3 , Just 1 )+ , ( 2, False , 0 , 3 , Just 4 )+ , ( 0, False , 0 , 3 , Just 0 )+ ]++ramAssertion+ :: Ram+ -> Samples+ -> Assertion+ramAssertion ram0 samples = actual @?= expectedOutput+ where+ (rd, we, wr, din, expectedOutput) = L.unzip5 samples+ actual = sampleN (L.length samples) $ ram0 (fromList rd)+ (fromList we)+ (fromList wr)+ (fromList din)+tests :: TestTree+tests = testGroup "Ram"+ [ testCase "Undefined enable" $ ramAssertion ram undefEn+ , testCase "Undefined write address" $ ramAssertion ram undefWAddr+ , testCase "Undefined write data" $ ramAssertion ram undefWData+ , testCase "Deasserted enable" $ ramAssertion ram enFalse+ , testCase "Deasserted enable, OOB address" $ ramAssertion ram enFalseOobWAddr+ , testCase "Read address strictness" $ ramAssertion maskOobRead oobRAddrStrict+ ]
tests/unittests.hs view
@@ -5,10 +5,12 @@ import qualified Clash.Tests.AutoReg import qualified Clash.Tests.BitPack import qualified Clash.Tests.BitVector+import qualified Clash.Tests.BlockRam import qualified Clash.Tests.DerivingDataRepr import qualified Clash.Tests.Fixed import qualified Clash.Tests.FixedExhaustive import qualified Clash.Tests.NFDataX+import qualified Clash.Tests.Ram import qualified Clash.Tests.Reset import qualified Clash.Tests.Resize import qualified Clash.Tests.Signal@@ -25,10 +27,12 @@ [ Clash.Tests.AutoReg.tests , Clash.Tests.BitPack.tests , Clash.Tests.BitVector.tests+ , Clash.Tests.BlockRam.tests , Clash.Tests.DerivingDataRepr.tests , Clash.Tests.Fixed.tests , Clash.Tests.FixedExhaustive.tests , Clash.Tests.NFDataX.tests+ , Clash.Tests.Ram.tests , Clash.Tests.Reset.tests , Clash.Tests.Resize.tests , Clash.Tests.Signal.tests