Copyright | (C) 2013-2016 University of Twente 2017-2019 Myrtle Software Ltd 2017 Google Inc. 2021-2022 QBayLogic B.V. |
---|---|
License | BSD2 (see the file LICENSE) |
Maintainer | QBayLogic B.V. <devops@qbaylogic.com> |
Safe Haskell | Unsafe |
Language | Haskell2010 |
Extensions |
|
Clash is a functional hardware description language that borrows both its syntax and semantics from the functional programming language Haskell. The merits of using a functional language to describe hardware comes from the fact that combinational circuits can be directly modeled as mathematical functions and that functional languages lend themselves very well at describing and (de-)composing mathematical functions.
This package provides:
- Prelude library containing datatypes and functions for circuit design
To use the library:
- Import Clash.Prelude; by default clock and reset lines are implicitly routed for all the components found in Clash.Prelude. You can read more about implicit clock and reset lines in Clash.Signal
- Alternatively, if you want to explicitly route clock and reset ports, for more straightforward multi-clock designs, you can import the Clash.Explicit.Prelude module. Note that you should not import Clash.Prelude and Clash.Explicit.Prelude at the same time as they have overlapping definitions.
For now, Clash.Prelude is also the best starting point for exploring the library. A preliminary version of a tutorial can be found in Clash.Tutorial. Some circuit examples can be found in Clash.Examples.
Synopsis
- mealy :: (HiddenClockResetEnable dom, NFDataX s) => (s -> i -> (s, o)) -> s -> Signal dom i -> Signal dom o
- mealyB :: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) => (s -> i -> (s, o)) -> s -> Unbundled dom i -> Unbundled dom o
- (<^>) :: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) => (s -> i -> (s, o)) -> s -> Unbundled dom i -> Unbundled dom o
- moore :: (HiddenClockResetEnable dom, NFDataX s) => (s -> i -> s) -> (s -> o) -> s -> Signal dom i -> Signal dom o
- mooreB :: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) => (s -> i -> s) -> (s -> o) -> s -> Unbundled dom i -> Unbundled dom o
- registerB :: (HiddenClockResetEnable dom, NFDataX a, Bundle a) => a -> Unbundled dom a -> Unbundled dom a
- asyncRom :: (KnownNat n, Enum addr) => Vec n a -> addr -> a
- asyncRomPow2 :: KnownNat n => Vec (2 ^ n) a -> Unsigned n -> a
- rom :: forall dom n m a. (NFDataX a, KnownNat n, KnownNat m, HiddenClock dom, HiddenEnable dom) => Vec n a -> Signal dom (Unsigned m) -> Signal dom a
- romPow2 :: forall dom n a. (KnownNat n, NFDataX a, HiddenClock dom, HiddenEnable dom) => Vec (2 ^ n) a -> Signal dom (Unsigned n) -> Signal dom a
- asyncRomBlob :: Enum addr => MemBlob n m -> addr -> BitVector m
- asyncRomBlobPow2 :: KnownNat n => MemBlob (2 ^ n) m -> Unsigned n -> BitVector m
- romBlob :: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) => MemBlob n m -> Signal dom addr -> Signal dom (BitVector m)
- romBlobPow2 :: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) => MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
- asyncRomFile :: (KnownNat m, Enum addr) => SNat n -> FilePath -> addr -> BitVector m
- asyncRomFilePow2 :: forall n m. (KnownNat m, KnownNat n) => FilePath -> Unsigned n -> BitVector m
- romFile :: (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom, Enum addr) => SNat n -> FilePath -> Signal dom addr -> Signal dom (BitVector m)
- romFilePow2 :: forall n m dom. (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom) => FilePath -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
- asyncRam :: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- asyncRamPow2 :: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) => Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
- blockRam :: (HasCallStack, HiddenClock dom, HiddenEnable dom, NFDataX a, Enum addr) => Vec n a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- blockRamPow2 :: (HasCallStack, HiddenClock dom, HiddenEnable dom, NFDataX a, KnownNat n) => Vec (2 ^ n) a -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
- blockRamU :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, 1 <= n) => ResetStrategy r -> SNat n -> (Index n -> a) -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- blockRam1 :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, 1 <= n) => ResetStrategy r -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- data ResetStrategy (r :: Bool) where
- blockRamBlob :: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) => MemBlob n m -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
- blockRamBlobPow2 :: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) => MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
- data MemBlob (n :: Nat) (m :: Nat)
- createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
- memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
- unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
- blockRamFile :: (KnownNat m, Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) => SNat n -> FilePath -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
- blockRamFilePow2 :: forall dom n m. (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) => FilePath -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
- readNew :: (HiddenClockResetEnable dom, NFDataX a, Eq addr) => (Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a) -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- trueDualPortBlockRam :: forall nAddrs dom a. (HasCallStack, KnownNat nAddrs, HiddenClock dom, NFDataX a) => Signal dom (RamOp nAddrs a) -> Signal dom (RamOp nAddrs a) -> (Signal dom a, Signal dom a)
- data RamOp n a
- window :: (HiddenClockResetEnable dom, KnownNat n, Default a, NFDataX a) => Signal dom a -> Vec (n + 1) (Signal dom a)
- windowD :: (HiddenClockResetEnable dom, KnownNat n, Default a, NFDataX a) => Signal dom a -> Vec (n + 1) (Signal dom a)
- isRising :: (HiddenClockResetEnable dom, NFDataX a, Bounded a, Eq a) => a -> Signal dom a -> Signal dom Bool
- isFalling :: (HiddenClockResetEnable dom, NFDataX a, Bounded a, Eq a) => a -> Signal dom a -> Signal dom Bool
- riseEvery :: HiddenClockResetEnable dom => SNat n -> Signal dom Bool
- oscillate :: HiddenClockResetEnable dom => Bool -> SNat n -> Signal dom Bool
- traceSignal1 :: (BitPack a, NFDataX a, Typeable a) => String -> Signal dom a -> Signal dom a
- traceVecSignal1 :: (KnownNat n, BitPack a, NFDataX a, Typeable a) => String -> Signal dom (Vec (n + 1) a) -> Signal dom (Vec (n + 1) a)
- traceSignal :: forall dom a. (KnownDomain dom, BitPack a, NFDataX a, Typeable a) => String -> Signal dom a -> Signal dom a
- traceVecSignal :: forall dom a n. (KnownDomain dom, KnownNat n, BitPack a, NFDataX a, Typeable a) => String -> Signal dom (Vec (n + 1) a) -> Signal dom (Vec (n + 1) a)
- dumpVCD :: NFDataX a => (Int, Int) -> Signal dom a -> [String] -> IO (Either String Text)
- data Reset (dom :: Domain)
- data Clock (dom :: Domain)
- data Enable dom
- data Signal (dom :: Domain) a
- type Domain = Symbol
- data VDomainConfiguration = VDomainConfiguration {}
- type XilinxSystem = "XilinxSystem" :: Domain
- type IntelSystem = "IntelSystem" :: Domain
- type System = "System" :: Domain
- class KnownSymbol dom => KnownDomain (dom :: Domain) where
- type KnownConf dom :: DomainConfiguration
- knownDomain :: SDomainConfiguration dom (KnownConf dom)
- type KnownConfiguration dom conf = (KnownDomain dom, KnownConf dom ~ conf)
- data SDomainConfiguration (dom :: Domain) (conf :: DomainConfiguration) where
- SDomainConfiguration :: SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
- type DomainResetPolarity (dom :: Domain) = DomainConfigurationResetPolarity (KnownConf dom)
- type DomainInitBehavior (dom :: Domain) = DomainConfigurationInitBehavior (KnownConf dom)
- type DomainResetKind (dom :: Domain) = DomainConfigurationResetKind (KnownConf dom)
- type DomainActiveEdge (dom :: Domain) = DomainConfigurationActiveEdge (KnownConf dom)
- type DomainPeriod (dom :: Domain) = DomainConfigurationPeriod (KnownConf dom)
- data DomainConfiguration = DomainConfiguration {}
- data SInitBehavior (init :: InitBehavior) where
- data InitBehavior
- data SResetPolarity (polarity :: ResetPolarity) where
- data ResetPolarity
- data SResetKind (resetKind :: ResetKind) where
- data ResetKind
- data SActiveEdge (edge :: ActiveEdge) where
- data ActiveEdge
- vSystem :: VDomainConfiguration
- vIntelSystem :: VDomainConfiguration
- vXilinxSystem :: VDomainConfiguration
- vDomain :: SDomainConfiguration dom conf -> VDomainConfiguration
- createDomain :: VDomainConfiguration -> Q [Dec]
- sameDomain :: forall (domA :: Domain) (domB :: Domain). (KnownDomain domA, KnownDomain domB) => Maybe (domA :~: domB)
- fromEnable :: Enable dom -> Signal dom Bool
- toEnable :: Signal dom Bool -> Enable dom
- enableGen :: Enable dom
- clockGen :: KnownDomain dom => Clock dom
- resetGen :: forall dom. KnownDomain dom => Reset dom
- resetGenN :: forall dom n. (KnownDomain dom, 1 <= n) => SNat n -> Reset dom
- unsafeToHighPolarity :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool
- unsafeToLowPolarity :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool
- unsafeFromReset :: Reset dom -> Signal dom Bool
- unsafeToReset :: Signal dom Bool -> Reset dom
- unsafeFromHighPolarity :: forall dom. KnownDomain dom => Signal dom Bool -> Reset dom
- unsafeFromLowPolarity :: forall dom. KnownDomain dom => Signal dom Bool -> Reset dom
- (.||.) :: Applicative f => f Bool -> f Bool -> f Bool
- (.&&.) :: Applicative f => f Bool -> f Bool -> f Bool
- mux :: Applicative f => f Bool -> f a -> f a -> f a
- (.==.) :: (Eq a, Applicative f) => f a -> f a -> f Bool
- (./=.) :: (Eq a, Applicative f) => f a -> f a -> f Bool
- (.<.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
- (.<=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
- (.>.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
- (.>=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
- fromList :: NFDataX a => [a] -> Signal dom a
- fromList_lazy :: [a] -> Signal dom a
- hzToPeriod :: HasCallStack => Ratio Natural -> Natural
- periodToHz :: Natural -> Ratio Natural
- clockPeriod :: forall dom period. (KnownDomain dom, DomainPeriod dom ~ period) => SNat period
- activeEdge :: forall dom edge. (KnownDomain dom, DomainActiveEdge dom ~ edge) => SActiveEdge edge
- resetKind :: forall dom sync. (KnownDomain dom, DomainResetKind dom ~ sync) => SResetKind sync
- initBehavior :: forall dom init. (KnownDomain dom, DomainInitBehavior dom ~ init) => SInitBehavior init
- resetPolarity :: forall dom polarity. (KnownDomain dom, DomainResetPolarity dom ~ polarity) => SResetPolarity polarity
- knownVDomain :: forall dom. KnownDomain dom => VDomainConfiguration
- class Bundle a where
- data TaggedEmptyTuple (dom :: Domain) = TaggedEmptyTuple
- data EmptyTuple = EmptyTuple
- data BiSignalOut (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)
- data BiSignalIn (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)
- data BiSignalDefault
- readFromBiSignal :: (HasCallStack, BitPack a) => BiSignalIn ds d (BitSize a) -> Signal d a
- mergeBiSignalOuts :: (HasCallStack, KnownNat n) => Vec n (BiSignalOut defaultState dom m) -> BiSignalOut defaultState dom m
- writeToBiSignal :: (HasCallStack, BitPack a) => BiSignalIn ds d (BitSize a) -> Signal d (Maybe a) -> BiSignalOut ds d (BitSize a)
- veryUnsafeToBiSignalIn :: (HasCallStack, KnownNat n, Given (SBiSignalDefault ds)) => BiSignalOut ds d n -> BiSignalIn ds d n
- systemClockGen :: Clock System
- systemResetGen :: Reset System
- resetSynchronizer :: forall dom. KnownDomain dom => Clock dom -> Reset dom -> Reset dom
- resetGlitchFilter :: forall dom glitchlessPeriod n. (KnownDomain dom, glitchlessPeriod ~ (n + 1)) => SNat glitchlessPeriod -> Clock dom -> Reset dom -> Reset dom
- type SystemClockResetEnable = (Hidden (HiddenClockName System) (Clock System), Hidden (HiddenResetName System) (Reset System), Hidden (HiddenEnableName System) (Enable System))
- type HiddenClockResetEnable dom = (HiddenClock dom, HiddenReset dom, HiddenEnable dom)
- type HiddenEnable dom = (Hidden (HiddenEnableName dom) (Enable dom), KnownDomain dom)
- type HiddenReset dom = (Hidden (HiddenResetName dom) (Reset dom), KnownDomain dom)
- type HiddenClock dom = (Hidden (HiddenClockName dom) (Clock dom), KnownDomain dom)
- exposeClock :: forall dom r. (HiddenClock dom => r) -> KnownDomain dom => Clock dom -> r
- hideClock :: forall dom r. HiddenClock dom => (Clock dom -> r) -> r
- withClock :: forall dom r. KnownDomain dom => Clock dom -> (HiddenClock dom => r) -> r
- hasClock :: forall dom. HiddenClock dom => Clock dom
- exposeReset :: forall dom r. (HiddenReset dom => r) -> KnownDomain dom => Reset dom -> r
- hideReset :: forall dom r. HiddenReset dom => (Reset dom -> r) -> r
- withReset :: forall dom r. KnownDomain dom => Reset dom -> (HiddenReset dom => r) -> r
- hasReset :: forall dom. HiddenReset dom => Reset dom
- exposeEnable :: forall dom r. (HiddenEnable dom => r) -> KnownDomain dom => Enable dom -> r
- hideEnable :: forall dom r. HiddenEnable dom => (Enable dom -> r) -> r
- withEnable :: forall dom r. KnownDomain dom => Enable dom -> (HiddenEnable dom => r) -> r
- hasEnable :: forall dom. HiddenEnable dom => Enable dom
- andEnable :: forall dom r. HiddenEnable dom => Signal dom Bool -> (HiddenEnable dom => r) -> r
- exposeClockResetEnable :: forall dom r. (HiddenClockResetEnable dom => r) -> KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> r
- hideClockResetEnable :: forall dom r. HiddenClockResetEnable dom => (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> r) -> r
- withClockResetEnable :: forall dom r. KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> (HiddenClockResetEnable dom => r) -> r
- dflipflop :: forall dom a. (HiddenClock dom, NFDataX a) => Signal dom a -> Signal dom a
- delay :: forall dom a. (NFDataX a, HiddenClock dom, HiddenEnable dom) => a -> Signal dom a -> Signal dom a
- delayMaybe :: forall dom a. (NFDataX a, HiddenClock dom, HiddenEnable dom) => a -> Signal dom (Maybe a) -> Signal dom a
- delayEn :: forall dom a. (NFDataX a, HiddenClock dom, HiddenEnable dom) => a -> Signal dom Bool -> Signal dom a -> Signal dom a
- register :: forall dom a. (HiddenClockResetEnable dom, NFDataX a) => a -> Signal dom a -> Signal dom a
- regMaybe :: forall dom a. (HiddenClockResetEnable dom, NFDataX a) => a -> Signal dom (Maybe a) -> Signal dom a
- regEn :: forall dom a. (HiddenClockResetEnable dom, NFDataX a) => a -> Signal dom Bool -> Signal dom a -> Signal dom a
- sample :: forall dom a. (KnownDomain dom, NFDataX a) => (HiddenClockResetEnable dom => Signal dom a) -> [a]
- sampleN :: forall dom a. (KnownDomain dom, NFDataX a) => Int -> (HiddenClockResetEnable dom => Signal dom a) -> [a]
- sampleWithReset :: forall dom a m. (KnownDomain dom, NFDataX a, 1 <= m) => SNat m -> (HiddenClockResetEnable dom => Signal dom a) -> [a]
- sampleWithResetN :: forall dom a m. (KnownDomain dom, NFDataX a, 1 <= m) => SNat m -> Int -> (HiddenClockResetEnable dom => Signal dom a) -> [a]
- sample_lazy :: forall dom a. KnownDomain dom => (HiddenClockResetEnable dom => Signal dom a) -> [a]
- sampleN_lazy :: forall dom a. KnownDomain dom => Int -> (HiddenClockResetEnable dom => Signal dom a) -> [a]
- simulate :: forall dom a b. (KnownDomain dom, NFDataX a, NFDataX b) => (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) -> [a] -> [b]
- simulateN :: forall dom a b. (KnownDomain dom, NFDataX a, NFDataX b) => Int -> (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) -> [a] -> [b]
- simulateWithReset :: forall dom a b m. (KnownDomain dom, NFDataX a, NFDataX b, 1 <= m) => SNat m -> a -> (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) -> [a] -> [b]
- simulateWithResetN :: forall dom a b m. (KnownDomain dom, NFDataX a, NFDataX b, 1 <= m) => SNat m -> a -> Int -> (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) -> [a] -> [b]
- simulate_lazy :: forall dom a b. KnownDomain dom => (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) -> [a] -> [b]
- simulateB :: forall dom a b. (KnownDomain dom, Bundle a, Bundle b, NFDataX a, NFDataX b) => (HiddenClockResetEnable dom => Unbundled dom a -> Unbundled dom b) -> [a] -> [b]
- simulateB_lazy :: forall dom a b. (KnownDomain dom, Bundle a, Bundle b) => (HiddenClockResetEnable dom => Unbundled dom a -> Unbundled dom b) -> [a] -> [b]
- runUntil :: forall dom a. (KnownDomain dom, NFDataX a, ShowX a) => (a -> Bool) -> (HiddenClockResetEnable dom => Signal dom a) -> IO ()
- testFor :: KnownDomain dom => Int -> (HiddenClockResetEnable dom => Signal dom Bool) -> Property
- holdReset :: forall dom m. HiddenClockResetEnable dom => SNat m -> Reset dom
- fromListWithReset :: forall dom a. (HiddenReset dom, NFDataX a) => a -> [a] -> Signal dom a
- signalAutomaton :: forall dom a b. KnownDomain dom => (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) -> Automaton (->) a b
- module Clash.Signal.Delayed
- module Clash.Sized.BitVector
- module Clash.Sized.Signed
- module Clash.Sized.Unsigned
- module Clash.Sized.Index
- module Clash.Sized.Fixed
- data Vec :: Nat -> Type -> Type where
- foldl :: (b -> a -> b) -> b -> Vec n a -> b
- foldr :: (a -> b -> b) -> b -> Vec n a -> b
- map :: (a -> b) -> Vec n a -> Vec n b
- bv2v :: KnownNat n => BitVector n -> Vec n Bit
- data VCons (a :: Type) (f :: TyFun Nat Type) :: Type
- traverse# :: forall a f b n. Applicative f => (a -> f b) -> Vec n a -> f (Vec n b)
- singleton :: a -> Vec 1 a
- head :: Vec (n + 1) a -> a
- tail :: Vec (n + 1) a -> Vec n a
- last :: Vec (n + 1) a -> a
- init :: Vec (n + 1) a -> Vec n a
- shiftInAt0 :: KnownNat n => Vec n a -> Vec m a -> (Vec n a, Vec m a)
- shiftInAtN :: KnownNat m => Vec n a -> Vec m a -> (Vec n a, Vec m a)
- (+>>) :: KnownNat n => a -> Vec n a -> Vec n a
- (<<+) :: Vec n a -> a -> Vec n a
- shiftOutFrom0 :: (Default a, KnownNat m) => SNat m -> Vec (m + n) a -> (Vec (m + n) a, Vec m a)
- shiftOutFromN :: (Default a, KnownNat n) => SNat m -> Vec (m + n) a -> (Vec (m + n) a, Vec m a)
- (++) :: Vec n a -> Vec m a -> Vec (n + m) a
- splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a)
- splitAtI :: KnownNat m => Vec (m + n) a -> (Vec m a, Vec n a)
- concat :: Vec n (Vec m a) -> Vec (n * m) a
- concatMap :: (a -> Vec m b) -> Vec n a -> Vec (n * m) b
- unconcat :: KnownNat n => SNat m -> Vec (n * m) a -> Vec n (Vec m a)
- unconcatI :: (KnownNat n, KnownNat m) => Vec (n * m) a -> Vec n (Vec m a)
- merge :: KnownNat n => Vec n a -> Vec n a -> Vec (2 * n) a
- reverse :: Vec n a -> Vec n a
- imap :: forall n a b. KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b
- izipWith :: KnownNat n => (Index n -> a -> b -> c) -> Vec n a -> Vec n b -> Vec n c
- ifoldr :: KnownNat n => (Index n -> a -> b -> b) -> b -> Vec n a -> b
- ifoldl :: KnownNat n => (a -> Index n -> b -> a) -> a -> Vec n b -> a
- indices :: KnownNat n => SNat n -> Vec n (Index n)
- indicesI :: KnownNat n => Vec n (Index n)
- findIndex :: KnownNat n => (a -> Bool) -> Vec n a -> Maybe (Index n)
- elemIndex :: (KnownNat n, Eq a) => a -> Vec n a -> Maybe (Index n)
- zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c
- zipWith3 :: (a -> b -> c -> d) -> Vec n a -> Vec n b -> Vec n c -> Vec n d
- zipWith4 :: (a -> b -> c -> d -> e) -> Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e
- zipWith5 :: (a -> b -> c -> d -> e -> f) -> Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f
- zipWith6 :: (a -> b -> c -> d -> e -> f -> g) -> Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f -> Vec n g
- zipWith7 :: (a -> b -> c -> d -> e -> f -> g -> h) -> Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f -> Vec n g -> Vec n h
- foldr1 :: (a -> a -> a) -> Vec (n + 1) a -> a
- foldl1 :: (a -> a -> a) -> Vec (n + 1) a -> a
- fold :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> a
- scanl :: (b -> a -> b) -> b -> Vec n a -> Vec (n + 1) b
- postscanl :: (b -> a -> b) -> b -> Vec n a -> Vec n b
- scanr :: (a -> b -> b) -> b -> Vec n a -> Vec (n + 1) b
- postscanr :: (a -> b -> b) -> b -> Vec n a -> Vec n b
- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> Vec n x -> (acc, Vec n y)
- mapAccumR :: (acc -> x -> (acc, y)) -> acc -> Vec n x -> (acc, Vec n y)
- zip :: Vec n a -> Vec n b -> Vec n (a, b)
- zip3 :: Vec n a -> Vec n b -> Vec n c -> Vec n (a, b, c)
- zip4 :: Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n (a, b, c, d)
- zip5 :: Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n (a, b, c, d, e)
- zip6 :: Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f -> Vec n (a, b, c, d, e, f)
- zip7 :: Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f -> Vec n g -> Vec n (a, b, c, d, e, f, g)
- unzip :: Vec n (a, b) -> (Vec n a, Vec n b)
- unzip3 :: Vec n (a, b, c) -> (Vec n a, Vec n b, Vec n c)
- unzip4 :: Vec n (a, b, c, d) -> (Vec n a, Vec n b, Vec n c, Vec n d)
- unzip5 :: Vec n (a, b, c, d, e) -> (Vec n a, Vec n b, Vec n c, Vec n d, Vec n e)
- unzip6 :: Vec n (a, b, c, d, e, f) -> (Vec n a, Vec n b, Vec n c, Vec n d, Vec n e, Vec n f)
- unzip7 :: Vec n (a, b, c, d, e, f, g) -> (Vec n a, Vec n b, Vec n c, Vec n d, Vec n e, Vec n f, Vec n g)
- (!!) :: (KnownNat n, Enum i) => Vec n a -> i -> a
- length :: KnownNat n => Vec n a -> Int
- replace :: (KnownNat n, Enum i) => i -> a -> Vec n a -> Vec n a
- take :: SNat m -> Vec (m + n) a -> Vec m a
- takeI :: KnownNat m => Vec (m + n) a -> Vec m a
- drop :: SNat m -> Vec (m + n) a -> Vec n a
- dropI :: KnownNat m => Vec (m + n) a -> Vec n a
- at :: SNat m -> Vec (m + (n + 1)) a -> a
- select :: CmpNat (i + s) (s * n) ~ 'GT => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
- selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
- replicate :: SNat n -> a -> Vec n a
- repeat :: KnownNat n => a -> Vec n a
- iterate :: SNat n -> (a -> a) -> a -> Vec n a
- iterateI :: forall n a. KnownNat n => (a -> a) -> a -> Vec n a
- unfoldr :: SNat n -> (s -> (a, s)) -> s -> Vec n a
- unfoldrI :: KnownNat n => (s -> (a, s)) -> s -> Vec n a
- generate :: SNat n -> (a -> a) -> a -> Vec n a
- generateI :: KnownNat n => (a -> a) -> a -> Vec n a
- transpose :: KnownNat n => Vec m (Vec n a) -> Vec n (Vec m a)
- stencil1d :: KnownNat n => SNat (stX + 1) -> (Vec (stX + 1) a -> b) -> Vec ((stX + n) + 1) a -> Vec (n + 1) b
- stencil2d :: (KnownNat n, KnownNat m) => SNat (stY + 1) -> SNat (stX + 1) -> (Vec (stY + 1) (Vec (stX + 1) a) -> b) -> Vec ((stY + m) + 1) (Vec ((stX + n) + 1) a) -> Vec (m + 1) (Vec (n + 1) b)
- windows1d :: KnownNat n => SNat (stX + 1) -> Vec ((stX + n) + 1) a -> Vec (n + 1) (Vec (stX + 1) a)
- windows2d :: (KnownNat n, KnownNat m) => SNat (stY + 1) -> SNat (stX + 1) -> Vec ((stY + m) + 1) (Vec ((stX + n) + 1) a) -> Vec (m + 1) (Vec (n + 1) (Vec (stY + 1) (Vec (stX + 1) a)))
- permute :: (Enum i, KnownNat n, KnownNat m) => (a -> a -> a) -> Vec n a -> Vec m i -> Vec (m + k) a -> Vec n a
- backpermute :: (Enum i, KnownNat n) => Vec n a -> Vec m i -> Vec m a
- scatter :: (Enum i, KnownNat n, KnownNat m) => Vec n a -> Vec m i -> Vec (m + k) a -> Vec n a
- gather :: (Enum i, KnownNat n) => Vec n a -> Vec m i -> Vec m a
- interleave :: (KnownNat n, KnownNat d) => SNat d -> Vec (n * d) a -> Vec (d * n) a
- rotateLeft :: (Enum i, KnownNat n) => Vec n a -> i -> Vec n a
- rotateRight :: (Enum i, KnownNat n) => Vec n a -> i -> Vec n a
- rotateLeftS :: KnownNat n => Vec n a -> SNat d -> Vec n a
- rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a
- toList :: Vec n a -> [a]
- listToVecTH :: Lift a => [a] -> ExpQ
- asNatProxy :: Vec n a -> Proxy n
- lengthS :: KnownNat n => Vec n a -> SNat n
- lazyV :: KnownNat n => Vec n a -> Vec n a
- dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall l. SNat l -> a -> (p @@ l) -> p @@ (l + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
- dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall l. SNat l -> (p @@ l) -> (p @@ l) -> p @@ (l + 1)) -> Vec (2 ^ k) a -> p @@ k
- vfold :: forall k a b. KnownNat k => (forall l. SNat l -> a -> Vec l b -> Vec (l + 1) b) -> Vec k a -> Vec k b
- smap :: forall k a b. KnownNat k => (forall l. SNat l -> a -> b) -> Vec k a -> Vec k b
- concatBitVector# :: forall n m. (KnownNat n, KnownNat m) => Vec n (BitVector m) -> BitVector (n * m)
- unconcatBitVector# :: forall n m. (KnownNat n, KnownNat m) => BitVector (n * m) -> Vec n (BitVector m)
- v2bv :: KnownNat n => Vec n Bit -> BitVector n
- seqV :: KnownNat n => Vec n a -> b -> b
- forceV :: KnownNat n => Vec n a -> Vec n a
- seqVX :: KnownNat n => Vec n a -> b -> b
- forceVX :: KnownNat n => Vec n a -> Vec n a
- module Clash.Sized.RTree
- module Clash.Annotations.TopEntity
- class Generic a
- class Generic1 (f :: k -> Type)
- module GHC.TypeLits
- module GHC.TypeLits.Extra
- module Clash.Promoted.Nat
- module Clash.Promoted.Nat.Literals
- module Clash.Promoted.Nat.TH
- module Clash.Promoted.Symbol
- class Lift (t :: TYPE r) where
- class NFDataX a => AutoReg a
- autoReg :: (HasCallStack, HiddenClockResetEnable dom, AutoReg a) => a -> Signal dom a -> Signal dom a
- deriveAutoReg :: Name -> DecsQ
- module Clash.Class.BitPack
- module Clash.Class.Exp
- module Clash.Class.Num
- module Clash.Class.Parity
- module Clash.Class.Resize
- module Control.Applicative
- module Data.Bits
- module Data.Default.Class
- type Type = Type
- data Constraint
- module Clash.XException
- module Clash.NamedTypes
- module Clash.Hidden
- module Clash.Magic
- module Clash.HaskellPrelude
Creating synchronous sequential circuits
:: (HiddenClockResetEnable dom, NFDataX s) | |
=> (s -> i -> (s, o)) | Transfer function in mealy machine form: |
-> s | Initial state |
-> Signal dom i -> Signal dom o | Synchronous sequential function with input and output matching that of the mealy machine |
Create a synchronous function from a combinational function describing a mealy machine
macT :: Int -- Current state -> (Int,Int) -- Input -> (Int,Int) -- (Updated state, output) macT s (x,y) = (s',s) where s' = x * y + s mac :: HiddenClockResetEnable dom =>Signal
dom (Int, Int) ->Signal
dom Int mac =mealy
macT 0
>>>
simulate @System mac [(0,0),(1,1),(2,2),(3,3),(4,4)]
[0,0,1,5,14... ...
Synchronous sequential functions can be composed just like their combinational counterpart:
dualMac :: HiddenClockResetEnable dom => (Signal
dom Int,Signal
dom Int) -> (Signal
dom Int,Signal
dom Int) ->Signal
dom Int dualMac (a,b) (x,y) = s1 + s2 where s1 =mealy
macT 0 (bundle
(a,x)) s2 =mealy
macT 0 (bundle
(b,y))
:: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) | |
=> (s -> i -> (s, o)) | Transfer function in mealy machine form: |
-> s | Initial state |
-> Unbundled dom i -> Unbundled dom o | Synchronous sequential function with input and output matching that of the mealy machine |
A version of mealy
that does automatic Bundle
ing
Given a function f
of type:
f :: Int -> (Bool, Int) -> (Int, (Int, Bool))
When we want to make compositions of f
in g
using mealy
, we have to
write:
g a b c = (b1,b2,i2) where (i1,b1) =unbundle
(mealy
f 0 (bundle
(a,b))) (i2,b2) =unbundle
(mealy
f 3 (bundle
(c,i1)))
Using mealyB
however we can write:
g a b c = (b1,b2,i2) where (i1,b1) =mealyB
f 0 (a,b) (i2,b2) =mealyB
f 3 (c,i1)
:: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) | |
=> (s -> i -> (s, o)) | Transfer function in mealy machine form: |
-> s | Initial state |
-> Unbundled dom i -> Unbundled dom o | Synchronous sequential function with input and output matching that of the mealy machine |
Infix version of mealyB
:: (HiddenClockResetEnable dom, NFDataX s) | |
=> (s -> i -> s) | Transfer function in moore machine form: |
-> (s -> o) | Output function in moore machine form: |
-> s | Initial state |
-> Signal dom i -> Signal dom o | Synchronous sequential function with input and output matching that of the moore machine |
Create a synchronous function from a combinational function describing a moore machine
macT :: Int -- Current state -> (Int,Int) -- Input -> Int -- Updated state macT s (x,y) = x * y + s mac :: HiddenClockResetEnable dom =>Signal
dom (Int, Int) ->Signal
dom Int mac =moore
mac id 0
>>>
simulate @System mac [(0,0),(1,1),(2,2),(3,3),(4,4)]
[0,0,1,5,14,30,... ...
Synchronous sequential functions can be composed just like their combinational counterpart:
dualMac :: HiddenClockResetEnable dom => (Signal
dom Int,Signal
dom Int) -> (Signal
dom Int,Signal
dom Int) ->Signal
dom Int dualMac (a,b) (x,y) = s1 + s2 where s1 =moore
macT id 0 (bundle
(a,x)) s2 =moore
macT id 0 (bundle
(b,y))
:: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) | |
=> (s -> i -> s) | Transfer function in moore machine form: |
-> (s -> o) | Output function in moore machine form: |
-> s | Initial state |
-> Unbundled dom i -> Unbundled dom o | Synchronous sequential function with input and output matching that of the moore machine |
A version of moore
that does automatic Bundle
ing
Given a functions t
and o
of types:
t :: Int -> (Bool, Int) -> Int o :: Int -> (Int, Bool)
When we want to make compositions of t
and o
in g
using moore
, we have to
write:
g a b c = (b1,b2,i2) where (i1,b1) =unbundle
(moore
t o 0 (bundle
(a,b))) (i2,b2) =unbundle
(moore
t o 3 (bundle
(c,i1)))
Using mooreB
however we can write:
g a b c = (b1,b2,i2) where (i1,b1) =mooreB
t o 0 (a,b) (i2,b2) =mooreB
t o 3 (c,i1)
registerB :: (HiddenClockResetEnable dom, NFDataX a, Bundle a) => a -> Unbundled dom a -> Unbundled dom a infixr 3 Source #
Create a register
function for product-type like signals (e.g. '(Signal a, Signal b)')
rP :: HiddenClockResetEnable dom => (Signal dom Int, Signal dom Int) -> (Signal dom Int, Signal dom Int) rP = registerB (8,8)
>>>
simulateB @System rP [(1,1),(2,2),(3,3)] :: [(Int,Int)]
[(8,8),(1,1),(2,2),(3,3)... ...
ROMs
:: (KnownNat n, Enum addr) | |
=> Vec n a | ROM content, also determines the size, NB: MUST be a constant |
-> addr | Read address |
-> a | The value of the ROM at address |
An asynchronous/combinational ROM with space for n
elements
See also:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam 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. SeeasyncRomFile
andasyncRomBlob
for different approaches that scale well.
:: KnownNat n | |
=> Vec (2 ^ n) a | ROM content NB: MUST be a constant |
-> Unsigned n | Read address |
-> a | The value of the ROM at address |
An asynchronous/combinational ROM with space for 2^n
elements
See also:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam 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. SeeasyncRomFilePow2
andasyncRomBlobPow2
for different approaches that scale well.
:: forall dom n m a. (NFDataX a, KnownNat n, KnownNat m, HiddenClock dom, HiddenEnable dom) | |
=> Vec n a | ROM content, also determines the size, NB: MUST be a constant |
-> Signal dom (Unsigned m) | Read address |
-> Signal dom a | The value of the ROM at address |
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, reading it will throw an
XException
See also:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam 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. SeeromFile
andromBlob
for different approaches that scale well.
:: forall dom n a. (KnownNat n, NFDataX a, HiddenClock dom, HiddenEnable dom) | |
=> Vec (2 ^ n) a | ROM content NB: MUST be a constant |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom a | The value of the ROM at address |
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, reading it will throw an
XException
See also:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam 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. SeeromFilePow2
andromBlobPow2
for different approaches that scale well.
ROMs defined by a MemBlob
:: Enum addr | |
=> MemBlob n m | ROM content, also determines the size, NB: MUST be a constant |
-> addr | Read address |
-> BitVector m | The value of the ROM at address |
An asynchronous/combinational ROM with space for n
elements
See also:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam for ideas on how to use ROMs and RAMs.
:: KnownNat n | |
=> MemBlob (2 ^ n) m | ROM content, also determines the size, 2^ NB: MUST be a constant |
-> Unsigned n | Read address |
-> BitVector m | The value of the ROM at address |
An asynchronous/combinational ROM with space for 2^n
elements
See also:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam for ideas on how to use ROMs and RAMs.
:: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) | |
=> MemBlob n m | ROM content, also determines the size, NB: MUST be a constant |
-> Signal dom addr | Read address |
-> Signal dom (BitVector m) | The value of the ROM at address |
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, reading it will throw an
XException
See also:
- See Clash.Sized.Fixed and Clash.Explicit.BlockRam for ideas on how to use ROMs and RAMs.
:: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) | |
=> MemBlob (2 ^ n) m | ROM content, also determines the size, 2^ NB: MUST be a constant |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (BitVector m) | The value of the ROM at address |
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, reading it will throw an
XException
See also:
- See Clash.Sized.Fixed and Clash.Explicit.BlockRam for ideas on how to use ROMs and RAMs.
ROMs defined by a data file
:: (KnownNat m, Enum addr) | |
=> SNat n | Size of the ROM |
-> FilePath | File describing the content of the ROM |
-> addr | Read address |
-> BitVector m | The value of the ROM at address |
An asynchronous/combinational ROM with space for n
elements
- NB: This function might not work for specific combinations of 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 |
See also:
- See Clash.Prelude.ROM.File for more information on how to instantiate a ROM with the contents of a data file.
- See Clash.Sized.Fixed for ideas on how to create your own data files.
When you notice that
asyncRomFile
is significantly slowing down your simulation, give it a monomorphic type signature. So instead of leaving the type to be inferred:myRomData = asyncRomFile d512 "memory.bin"
or giving it a polymorphic type signature:
myRomData :: Enum addr => addr -> BitVector 16 myRomData = asyncRomFile d512 "memory.bin"
you should give it a monomorphic type signature:
myRomData :: Unsigned 9 -> BitVector 16 myRomData = asyncRomFile d512 "memory.bin"
:: forall n m. (KnownNat m, KnownNat n) | |
=> FilePath | File describing the content of the ROM |
-> Unsigned n | Read address |
-> BitVector m | The value of the ROM at address |
An asynchronous/combinational ROM with space for 2^n
elements
- NB: This function might not work for specific combinations of 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 |
See also:
- See Clash.Prelude.ROM.File for more information on how to instantiate a ROM with the contents of a data file.
- See Clash.Sized.Fixed for ideas on how to create your own data files.
When you notice that
asyncRomFilePow2
is significantly slowing down your simulation, give it a monomorphic type signature. So instead of leaving the type to be inferred:myRomData = asyncRomFilePow2 "memory.bin"
you should give it a monomorphic type signature:
myRomData :: Unsigned 9 -> BitVector 16 myRomData = asyncRomFilePow2 "memory.bin"
:: (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom, Enum addr) | |
=> SNat n | Size of the ROM |
-> FilePath | File describing the content of the ROM |
-> Signal dom addr | Read address |
-> Signal dom (BitVector m) | The value of the ROM at address |
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, reading it will throw an
XException
- NB: This function might not work for specific combinations of 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 |
See also:
- See Clash.Prelude.ROM.File for more information on how to instantiate a ROM with the contents of a data file.
- See Clash.Sized.Fixed for ideas on how to create your own data files.
:: forall n m dom. (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom) | |
=> FilePath | File describing the content of the ROM |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (BitVector m) | The value of the ROM at address |
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, reading it will throw an
XException
- NB: This function might not work for specific combinations of 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 |
See also:
- See Clash.Prelude.ROM.File for more information on how to instantiate a ROM with the contents of a data file.
- See Clash.Sized.Fixed for ideas on how to create your own data files.
RAM primitives with a combinational read port
:: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) | |
=> SNat n | Size |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (write address |
-> Signal dom a | Value of the RAM at address |
Create a RAM with space for n
elements
- NB: Initial content of the RAM is undefined, reading it will throw an
XException
See also:
- See Clash.Prelude.BlockRam for more information on how to use a RAM.
:: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) | |
=> Signal dom (Unsigned n) | Read address |
-> Signal dom (Maybe (Unsigned n, a)) | (write address |
-> Signal dom a | Value of the RAM at address |
Create a RAM with space for 2^n
elements
- NB: Initial content of the RAM is undefined, reading it will throw an
XException
See also:
- See Clash.Prelude.BlockRam for more information on how to use a RAM.
Block RAM primitives
:: (HasCallStack, HiddenClock dom, HiddenEnable dom, NFDataX a, Enum addr) | |
=> Vec n a | Initial content of the BRAM, also determines the size, NB: MUST be a constant |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (write address |
-> Signal dom a | Value of the BRAM at address |
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.Prelude.BlockRam 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. SeeblockRamFile
andblockRamBlob
for different approaches that scale well.
Example
:: (HasCallStack, HiddenClock dom, HiddenEnable dom, NFDataX a, KnownNat n) | |
=> Vec (2 ^ n) a | Initial content of the BRAM NB: MUST be a constant. |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (Maybe (Unsigned n, a)) | (write address |
-> Signal dom a | Value of the |
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 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. SeeblockRamFilePow2
andblockRamBlobPow2
for different approaches that scale well.
Example
bram32 ::HiddenClock
dom =>Signal
dom (Unsigned
5) ->Signal
dom (Maybe (Unsigned
5,Bit
)) ->Signal
domBit
bram32 =blockRamPow2
(replicate
d32 1)
:: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, 1 <= n) | |
=> ResetStrategy r | Whether to clear BRAM on asserted reset ( |
-> SNat n | Number of elements in BRAM |
-> (Index n -> a) | If applicable (see first argument), reset BRAM using this function |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (write address |
-> Signal dom a | Value of the BRAM at address |
A version of blockRam
that has no default values set. May be cleared to
an arbitrary state using a reset function.
:: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, 1 <= n) | |
=> ResetStrategy r | Whether to clear BRAM on asserted reset ( |
-> SNat n | Number of elements in BRAM |
-> a | Initial content of the BRAM (replicated n times) |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (write address |
-> Signal dom a | Value of the BRAM at address |
A version of blockRam
that is initialized with the same value on all
memory positions
data ResetStrategy (r :: Bool) where Source #
Block RAM primitives initialized with a MemBlob
:: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) | |
=> MemBlob n m | Initial content of the BRAM, also determines the size, NB: MUST be a constant |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, BitVector m)) | (write address |
-> Signal dom (BitVector m) | Value of the BRAM at address |
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.Prelude.BlockRam for more information on how to use a block RAM.
- Use the adapter
readNew
for obtaining write-before-read semantics like this:
.readNew
(blockRamBlob
content) rd wrM
:: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) | |
=> MemBlob (2 ^ n) m | Initial content of the BRAM, also determines the size, 2^ NB: MUST be a constant |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (Maybe (Unsigned n, BitVector m)) | (write address |
-> Signal dom (BitVector m) | Value of the BRAM at address |
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 for more information on how to use a block RAM.
- Use the adapter
readNew
for obtaining write-before-read semantics like this:
.readNew
(blockRamBlobPow2
content) rd wrM
Creating and inspecting MemBlob
data MemBlob (n :: Nat) (m :: Nat) Source #
Efficient storage of memory content
It holds n
words of
.BitVector
m
:: forall a f. (Foldable f, BitPack a) | |
=> String | Name of the binding to generate |
-> Maybe Bit | Value to map don't care bits to. |
-> f a | The content for the |
-> DecsQ |
Create a MemBlob
binding from a list of values
Since this uses Template Haskell, nothing in the arguments given to
createMemBlob
can refer to something defined in the same module.
Example
createMemBlob
"content"Nothing
[15 :: Unsigned 8 .. 17] ram clk en =blockRamBlob
clk en content
The Maybe
datatype has don't care bits, where the actual value
does not matter. But the bits need a defined value in the memory. Either 0 or
1 can be used, and both are valid representations of the data.
>>>
import qualified Prelude as P
>>>
let es = [ Nothing, Just (7 :: Unsigned 8), Just 8 ]
>>>
:{
createMemBlob "content0" (Just 0) es createMemBlob "content1" (Just 1) es x = 1 :}
>>>
let pr = mapM_ (putStrLn . show)
>>>
pr $ P.map pack es
0b0_...._.... 0b1_0000_0111 0b1_0000_1000>>>
pr $ unpackMemBlob content0
0b0_0000_0000 0b1_0000_0111 0b1_0000_1000>>>
pr $ unpackMemBlob content1
0b0_1111_1111 0b1_0000_0111 0b1_0000_1000>>>
:{
createMemBlob "contentN" Nothing es x = 1 :} <interactive>:...: error: packBVs: cannot convert don't care values. Please specify a mapping to a definite value.
Note how we hinted to clashi
that our multi-line command was a list of
declarations by including a dummy declaration x = 1
. Without this trick,
clashi
would expect an expression and the Template Haskell would not work.
:: forall a f. (Foldable f, BitPack a) | |
=> Maybe Bit | Value to map don't care bits to. |
-> f a | The content for the |
-> ExpQ |
Create a MemBlob
from a list of values
Since this uses Template Haskell, nothing in the arguments given to
memBlobTH
can refer to something defined in the same module.
Example
ram clk en = blockRamBlob
clk en $(memBlobTH Nothing [15 :: Unsigned 8 .. 17])
The Maybe
datatype has don't care bits, where the actual value
does not matter. But the bits need a defined value in the memory. Either 0 or
1 can be used, and both are valid representations of the data.
>>>
import qualified Prelude as P
>>>
let es = [ Nothing, Just (7 :: Unsigned 8), Just 8 ]
>>>
content0 = $(memBlobTH (Just 0) es)
>>>
content1 = $(memBlobTH (Just 1) es)
>>>
let pr = mapM_ (putStrLn . show)
>>>
pr $ P.map pack es
0b0_...._.... 0b1_0000_0111 0b1_0000_1000>>>
pr $ unpackMemBlob content0
0b0_0000_0000 0b1_0000_0111 0b1_0000_1000>>>
pr $ unpackMemBlob content1
0b0_1111_1111 0b1_0000_0111 0b1_0000_1000>>>
$(memBlobTH Nothing es)
<interactive>:...: error: • packBVs: cannot convert don't care values. Please specify a mapping to a definite value. • In the untyped splice: $(memBlobTH Nothing es)
unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m] Source #
Convert a MemBlob
back to a list
NB: Not synthesizable
Block RAM primitives initialized with a data file
:: (KnownNat m, Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) | |
=> SNat n | Size of the BRAM |
-> FilePath | File describing the initial content of the BRAM |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, BitVector m)) | (write address |
-> Signal dom (BitVector m) | Value of the BRAM at address |
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
- NB: This function might not work for specific combinations of 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 |
See also:
- See Clash.Prelude.BlockRam for more information on how to use a block RAM.
- Use the adapter
readNew
for obtaining write-before-read semantics like this:
.readNew
(blockRamFile
size file) rd wrM - See Clash.Prelude.BlockRam.File for more information on how to instantiate a block RAM with the contents of a data file.
- See Clash.Sized.Fixed for ideas on how to create your own data files.
:: forall dom n m. (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) | |
=> FilePath | File describing the initial content of the BRAM |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (Maybe (Unsigned n, BitVector m)) | (write address |
-> Signal dom (BitVector m) | Value of the BRAM at address |
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
- NB: This function might not work for specific combinations of 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 |
See also:
- See Clash.Prelude.BlockRam for more information on how to use a block RAM.
- Use the adapter
readNew
for obtaining write-before-read semantics like this:
.readNew
(blockRamFilePow2
file) rd wrM - See Clash.Prelude.BlockRam.File for more information on how to instantiate a block RAM with the contents of a data file.
- See Clash.Sized.Fixed for ideas on how to create your own data files.
Block RAM read/write conflict resolution
:: (HiddenClockResetEnable dom, NFDataX a, Eq addr) | |
=> (Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a) | The BRAM component |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (Write address |
-> Signal dom a | Value of the BRAM at address |
Create a read-after-write block RAM from a read-before-write one
>>>
:t readNew (blockRam (0 :> 1 :> Nil))
readNew (blockRam (0 :> 1 :> Nil)) :: ... ... ... ... ... => Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
True dual-port block RAM
:: forall nAddrs dom a. (HasCallStack, KnownNat nAddrs, HiddenClock dom, NFDataX a) | |
=> Signal dom (RamOp nAddrs a) | RAM operation for port A |
-> Signal dom (RamOp nAddrs a) | RAM operation for port B |
-> (Signal dom a, Signal dom a) | Outputs data on next cycle. When writing, the data written will be echoed. When reading, the read data is returned. |
Produces vendor-agnostic HDL that will be inferred as a true dual-port block RAM
Any value that is being written on a particular port is also the value that will be read on that port, i.e. the same-port read/write behavior is: WriteFirst. For mixed-port read/write, when port A writes to the address port B reads from, the output of port B is undefined, and vice versa.
Port operation
Instances
Show a => Show (RamOp n a) Source # | |
Generic (RamOp n a) Source # | |
NFDataX a => NFDataX (RamOp n a) Source # | |
Defined in Clash.Explicit.BlockRam | |
type Rep (RamOp n a) Source # | |
Defined in Clash.Explicit.BlockRam type Rep (RamOp n a) = D1 ('MetaData "RamOp" "Clash.Explicit.BlockRam" "clash-prelude-1.6.6-inplace" 'False) (C1 ('MetaCons "RamRead" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Index n))) :+: (C1 ('MetaCons "RamWrite" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Index n)) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 a)) :+: C1 ('MetaCons "RamNoOp" 'PrefixI 'False) (U1 :: Type -> Type))) |
Utility functions
:: (HiddenClockResetEnable dom, KnownNat n, Default a, NFDataX a) | |
=> Signal dom a | Signal to create a window over |
-> Vec (n + 1) (Signal dom a) | Window of at least size 1 |
Give a window over a Signal
window4 :: HiddenClockResetEnable dom => Signal dom Int -> Vec 4 (Signal dom Int) window4 = window
>>>
simulateB @System window4 [1::Int,2,3,4,5] :: [Vec 4 Int]
[1 :> 0 :> 0 :> 0 :> Nil,2 :> 1 :> 0 :> 0 :> Nil,3 :> 2 :> 1 :> 0 :> Nil,4 :> 3 :> 2 :> 1 :> Nil,5 :> 4 :> 3 :> 2 :> Nil,... ...
:: (HiddenClockResetEnable dom, KnownNat n, Default a, NFDataX a) | |
=> Signal dom a | Signal to create a window over |
-> Vec (n + 1) (Signal dom a) | Window of at least size 1 |
Give a delayed window over a Signal
windowD3 :: HiddenClockResetEnable dom => Signal dom Int -> Vec 3 (Signal dom Int) windowD3 = windowD
>>>
simulateB @System windowD3 [1::Int,2,3,4] :: [Vec 3 Int]
[0 :> 0 :> 0 :> Nil,1 :> 0 :> 0 :> Nil,2 :> 1 :> 0 :> Nil,3 :> 2 :> 1 :> Nil,4 :> 3 :> 2 :> Nil,... ...
riseEvery :: HiddenClockResetEnable dom => SNat n -> Signal dom Bool Source #
Give a pulse every n
clock cycles. This is a useful helper function when
combined with functions like
or regEn
,
in order to delay a register by a known amount.mux
To be precise: the given signal will be
for the next False
n-1
cycles,
followed by a single
value:True
>>>
Prelude.last (sampleN @System 1025 (riseEvery d1024)) == True
True>>>
Prelude.or (sampleN @System 1024 (riseEvery d1024)) == False
True
For example, to update a counter once every 10 million cycles:
counter =regEn
0 (riseEvery
(SNat
::SNat
10000000)) (counter + 1)
oscillate :: HiddenClockResetEnable dom => Bool -> SNat n -> Signal dom Bool Source #
Oscillate a
for a given number of cycles. This is a convenient
function when combined with something like Bool
, as it allows you to
easily hold a register value for a given number of cycles. The input regEn
determines what the initial value is.Bool
To oscillate on an interval of 5 cycles:
>>>
sampleN @System 11 (oscillate False d5)
[False,False,False,False,False,False,True,True,True,True,True]
To oscillate between
and True
:False
>>>
sampleN @System 11 (oscillate False d1)
[False,False,True,False,True,False,True,False,True,False,True]
An alternative definition for the above could be:
>>>
let osc' = register False (not <$> osc')
>>>
sampleN @System 200 (oscillate False d1) == sampleN @System 200 osc'
True
Tracing
Simple
:: (BitPack a, NFDataX a, Typeable a) | |
=> String | Name of signal in the VCD output |
-> Signal dom a | Signal to trace |
-> Signal dom a |
Trace a single signal. Will emit an error if a signal with the same name was previously registered.
NB associates the traced signal with a clock period of 1, which
results in incorrect VCD files when working with circuits that have
multiple clocks. Use traceSignal
when working with circuits that have
multiple clocks.
:: (KnownNat n, BitPack a, NFDataX a, Typeable a) | |
=> String | Name of signal in debugging output. Will be appended by _0, _1, ..., _n. |
-> Signal dom (Vec (n + 1) a) | Signal to trace |
-> Signal dom (Vec (n + 1) a) |
Trace a single vector signal: each element in the vector will show up as a different trace. If the trace name already exists, this function will emit an error.
NB associates the traced signal with a clock period of 1, which
results in incorrect VCD files when working with circuits that have
multiple clocks. Use traceSignal
when working with circuits that have
multiple clocks.
Tracing in a multi-clock environment
:: forall dom a. (KnownDomain dom, BitPack a, NFDataX a, Typeable a) | |
=> String | Name of signal in the VCD output |
-> Signal dom a | Signal to trace |
-> Signal dom a |
Trace a single signal. Will emit an error if a signal with the same name was previously registered.
NB Works correctly when creating VCD files from traced signal in
multi-clock circuits. However traceSignal1
might be more convenient to
use when the domain of your circuit is polymorphic.
:: forall dom a n. (KnownDomain dom, KnownNat n, BitPack a, NFDataX a, Typeable a) | |
=> String | Name of signal in debugging output. Will be appended by _0, _1, ..., _n. |
-> Signal dom (Vec (n + 1) a) | Signal to trace |
-> Signal dom (Vec (n + 1) a) |
Trace a single vector signal: each element in the vector will show up as a different trace. If the trace name already exists, this function will emit an error.
NB Works correctly when creating VCD files from traced signal in
multi-clock circuits. However traceSignal1
might be more convenient to
use when the domain of your circuit is polymorphic.
VCD dump functions
:: NFDataX a | |
=> (Int, Int) | (offset, number of samples) |
-> Signal dom a | (One of) the outputs of the circuit containing the traces |
-> [String] | The names of the traces you definitely want to be dumped in the VCD file |
-> IO (Either String Text) |
Produce a four-state VCD (Value Change Dump) according to IEEE 1364-{1995,2001}. This function fails if a trace name contains either non-printable or non-VCD characters.
Due to lazy evaluation, the created VCD files might not contain all the traces you were expecting. You therefore have to provide a list of names you definately want to be dumped in the VCD file.
For example:
vcd <- dumpVCD (0, 100) cntrOut ["main", "sub"]
Evaluates cntrOut long enough in order for to guarantee that the main
,
and sub
traces end up in the generated VCD file.
Exported modules
Synchronous signals
data Reset (dom :: Domain) Source #
A reset signal belonging to a domain called dom.
The underlying representation of resets is Bool
.
data Clock (dom :: Domain) Source #
A clock signal belonging to a domain named dom.
Instances
A signal of booleans, indicating whether a component is enabled. No special meaning is implied, it's up to the component itself to decide how to respond to its enable line. It is used throughout Clash as a global enable signal.
data Signal (dom :: Domain) a Source #
Clash has synchronous Signal
s in the form of:
Signal
(dom ::Domain
) a
Where a is the type of the value of the Signal
, for example Int or Bool,
and dom is the clock- (and reset-) domain to which the memory elements
manipulating these Signal
s belong.
The type-parameter, dom, is of the kind Domain
- a simple string. That
string refers to a single synthesis domain. A synthesis domain describes the
behavior of certain aspects of memory elements in it.
- NB: "Bad things"™ happen when you actually use a clock period of
0
, so do not do that! - NB: You should be judicious using a clock with period of
1
as you can never create a clock that goes any faster! - NB: For the best compatibility make sure your period is divisible by 2, because some VHDL simulators don't support fractions of picoseconds.
- NB: Whether
System
has good defaults depends on your target platform. Check outIntelSystem
andXilinxSystem
too!
Signals have the type role
>>>
:i Signal
type role Signal nominal representational ...
as it is safe to coerce the underlying value of a signal, but not safe to coerce a signal between different synthesis domains.
See the module documentation of Clash.Signal for more information about domains.
Instances
data VDomainConfiguration Source #
Same as SDomainConfiguration but allows for easy updates through record update syntax.
Should be used in combination with vDomain
and createDomain
. Example:
createDomain (knownVDomain @System){vName="System10", vPeriod=10}
This duplicates the settings in the System
domain, replaces the name and
period, and creates an instance for it. As most users often want to update
the system domain, a shortcut is available in the form:
createDomain vSystem{vName="System10", vPeriod=10}
VDomainConfiguration | |
|
Instances
type XilinxSystem = "XilinxSystem" :: Domain Source #
A clock (and reset) dom with clocks running at 100 MHz. Memory elements respond to the rising edge of the clock, and synchronously to changes in reset signals. It has defined initial values, and active-high resets.
See module documentation of Clash.Explicit.Signal for more information on how to create custom synthesis domains.
type IntelSystem = "IntelSystem" :: Domain Source #
A clock (and reset) dom with clocks running at 100 MHz. Memory elements respond to the rising edge of the clock, and asynchronously to changes in reset signals. It has defined initial values, and active-high resets.
See module documentation of Clash.Explicit.Signal for more information on how to create custom synthesis domains.
type System = "System" :: Domain Source #
A clock (and reset) dom with clocks running at 100 MHz. Memory elements respond to the rising edge of the clock, and asynchronously to changes in reset signals. It has defined initial values, and active-high resets.
See module documentation of Clash.Explicit.Signal for more information on how to create custom synthesis domains.
class KnownSymbol dom => KnownDomain (dom :: Domain) where Source #
A KnownDomain
constraint indicates that a circuit's behavior depends on
some properties of a domain. See DomainConfiguration
for more information.
type KnownConf dom :: DomainConfiguration Source #
knownDomain :: SDomainConfiguration dom (KnownConf dom) Source #
Returns SDomainConfiguration
corresponding to an instance's DomainConfiguration
.
Example usage:
>>>
knownDomain @System
SDomainConfiguration (SSymbol @"System") (SNat @10000) SRising SAsynchronous SDefined SActiveHigh
Instances
KnownDomain XilinxSystem Source # | System instance with defaults set for Xilinx FPGAs |
Defined in Clash.Signal.Internal type KnownConf XilinxSystem :: DomainConfiguration Source # | |
KnownDomain IntelSystem Source # | System instance with defaults set for Intel FPGAs |
Defined in Clash.Signal.Internal type KnownConf IntelSystem :: DomainConfiguration Source # | |
KnownDomain System Source # | A clock (and reset) dom with clocks running at 100 MHz |
Defined in Clash.Signal.Internal type KnownConf System :: DomainConfiguration Source # |
type KnownConfiguration dom conf = (KnownDomain dom, KnownConf dom ~ conf) Source #
data SDomainConfiguration (dom :: Domain) (conf :: DomainConfiguration) where Source #
Singleton version of DomainConfiguration
SDomainConfiguration :: SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity) |
Instances
Show (SDomainConfiguration dom conf) Source # | |
Defined in Clash.Signal.Internal showsPrec :: Int -> SDomainConfiguration dom conf -> ShowS # show :: SDomainConfiguration dom conf -> String # showList :: [SDomainConfiguration dom conf] -> ShowS # |
type DomainResetPolarity (dom :: Domain) = DomainConfigurationResetPolarity (KnownConf dom) Source #
Convenience type to help to extract the reset polarity from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainResetPolarity dom ~ 'ActiveHigh) => ...
type DomainInitBehavior (dom :: Domain) = DomainConfigurationInitBehavior (KnownConf dom) Source #
Convenience type to help to extract the initial value behavior from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainInitBehavior dom ~ 'Defined) => ...
type DomainResetKind (dom :: Domain) = DomainConfigurationResetKind (KnownConf dom) Source #
Convenience type to help to extract the reset synchronicity from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainResetKind dom ~ 'Synchronous) => ...
type DomainActiveEdge (dom :: Domain) = DomainConfigurationActiveEdge (KnownConf dom) Source #
Convenience type to help to extract the active edge from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainActiveEdge dom ~ 'Rising) => ...
type DomainPeriod (dom :: Domain) = DomainConfigurationPeriod (KnownConf dom) Source #
Convenience type to help to extract a period from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainPeriod dom ~ 6000) => ...
data DomainConfiguration Source #
A domain with a name (Domain
). Configures the behavior of various aspects
of a circuits. See the documentation of this record's field types for more
information on the options.
See module documentation of Clash.Explicit.Signal for more information on how to create custom synthesis domains.
DomainConfiguration | |
|
data SInitBehavior (init :: InitBehavior) where Source #
Instances
Show (SInitBehavior init) Source # | |
Defined in Clash.Signal.Internal showsPrec :: Int -> SInitBehavior init -> ShowS # show :: SInitBehavior init -> String # showList :: [SInitBehavior init] -> ShowS # |
data InitBehavior Source #
Unknown | Power up value of memory elements is unknown. |
Defined | If applicable, power up value of a memory element is defined. Applies to
|
Instances
data SResetPolarity (polarity :: ResetPolarity) where Source #
Singleton version of ResetPolarity
Instances
Show (SResetPolarity polarity) Source # | |
Defined in Clash.Signal.Internal showsPrec :: Int -> SResetPolarity polarity -> ShowS # show :: SResetPolarity polarity -> String # showList :: [SResetPolarity polarity] -> ShowS # |
data ResetPolarity Source #
Determines the value for which a reset line is considered "active"
ActiveHigh | Reset is considered active if underlying signal is |
ActiveLow | Reset is considered active if underlying signal is |
Instances
data SResetKind (resetKind :: ResetKind) where Source #
Singleton version of ResetKind
Instances
Show (SResetKind reset) Source # | |
Defined in Clash.Signal.Internal showsPrec :: Int -> SResetKind reset -> ShowS # show :: SResetKind reset -> String # showList :: [SResetKind reset] -> ShowS # |
Asynchronous | Elements respond asynchronously to changes in their reset input. This means that they do not wait for the next active clock edge, but respond immediately instead. Common on Intel FPGA platforms. |
Synchronous | Elements respond synchronously to changes in their reset input. This means that changes in their reset input won't take effect until the next active clock edge. Common on Xilinx FPGA platforms. |
Instances
Eq ResetKind Source # | |
Data ResetKind Source # | |
Defined in Clash.Signal.Internal gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ResetKind -> c ResetKind # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ResetKind # toConstr :: ResetKind -> Constr # dataTypeOf :: ResetKind -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c ResetKind) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ResetKind) # gmapT :: (forall b. Data b => b -> b) -> ResetKind -> ResetKind # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ResetKind -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ResetKind -> r # gmapQ :: (forall d. Data d => d -> u) -> ResetKind -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> ResetKind -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> ResetKind -> m ResetKind # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ResetKind -> m ResetKind # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ResetKind -> m ResetKind # | |
Ord ResetKind Source # | |
Defined in Clash.Signal.Internal | |
Read ResetKind Source # | |
Show ResetKind Source # | |
Generic ResetKind Source # | |
NFData ResetKind Source # | |
Defined in Clash.Signal.Internal | |
Hashable ResetKind Source # | |
Defined in Clash.Signal.Internal | |
type Rep ResetKind Source # | |
data SActiveEdge (edge :: ActiveEdge) where Source #
Singleton version of ActiveEdge
SRising :: SActiveEdge 'Rising | |
SFalling :: SActiveEdge 'Falling |
Instances
Show (SActiveEdge edge) Source # | |
Defined in Clash.Signal.Internal showsPrec :: Int -> SActiveEdge edge -> ShowS # show :: SActiveEdge edge -> String # showList :: [SActiveEdge edge] -> ShowS # |
data ActiveEdge Source #
Determines clock edge memory elements are sensitive to. Not yet implemented.
Rising | Elements are sensitive to the rising edge (low-to-high) of the clock. |
Falling | Elements are sensitive to the falling edge (high-to-low) of the clock. |
Instances
vSystem :: VDomainConfiguration Source #
Convenience value to allow easy "subclassing" of System domain. Should
be used in combination with createDomain
. For example, if you just want to
change the period but leave all other settings intact use:
createDomain vSystem{vName="System10", vPeriod=10}
vIntelSystem :: VDomainConfiguration Source #
Convenience value to allow easy "subclassing" of IntelSystem domain. Should
be used in combination with createDomain
. For example, if you just want to
change the period but leave all other settings intact use:
createDomain vIntelSystem{vName="Intel10", vPeriod=10}
vXilinxSystem :: VDomainConfiguration Source #
Convenience value to allow easy "subclassing" of XilinxSystem domain. Should
be used in combination with createDomain
. For example, if you just want to
change the period but leave all other settings intact use:
createDomain vXilinxSystem{vName="Xilinx10", vPeriod=10}
vDomain :: SDomainConfiguration dom conf -> VDomainConfiguration Source #
Convert SDomainConfiguration
to VDomainConfiguration
. Should be used in combination with
createDomain
only.
createDomain :: VDomainConfiguration -> Q [Dec] Source #
Convenience method to express new domains in terms of others.
createDomain (knownVDomain @System){vName="System10", vPeriod=10}
This duplicates the settings in the System domain, replaces the name and period, and creates an instance for it. As most users often want to update the system domain, a shortcut is available in the form:
createDomain vSystem{vName="System10", vPeriod=10}
The function will create two extra identifiers. The first:
type System10 = ..
You can use that as the dom to Clocks/Resets/Enables/Signals. For example:
Signal System10 Int
. Additionally, it will create a VDomainConfiguration
that you can
use in later calls to createDomain
:
vSystem10 = knownVDomain @System10
It will also make System10
an instance of KnownDomain
.
If either identifier is already in scope it will not be generated a second time. Note: This can be useful for example when documenting a new domain:
-- | Here is some documentation for CustomDomain type CustomDomain = ("CustomDomain" :: Domain) -- | Here is some documentation for vCustomDomain createDomain vSystem{vName="CustomDomain"}
sameDomain :: forall (domA :: Domain) (domB :: Domain). (KnownDomain domA, KnownDomain domB) => Maybe (domA :~: domB) Source #
We either get evidence that this function was instantiated with the same domains, or Nothing.
fromEnable :: Enable dom -> Signal dom Bool Source #
Convert Enable
construct to its underlying representation: a signal of
bools.
clockGen :: KnownDomain dom => Clock dom Source #
Clock generator for simulations. Do not use this clock generator for
the testBench function, use tbClockGen
instead.
To be used like:
clkSystem = clockGen @System
See DomainConfiguration
for more information on how to use synthesis domains.
resetGen :: forall dom. KnownDomain dom => Reset dom Source #
:: forall dom n. (KnownDomain dom, 1 <= n) | |
=> SNat n | Number of initial cycles to hold reset high |
-> Reset dom |
Generate reset that's asserted for the first n cycles.
To be used like:
rstSystem5 = resetGen System (SNat
5)
Example usage:
>>>
sampleN 7 (unsafeToHighPolarity (resetGenN @System (SNat @3)))
[True,True,True,False,False,False,False]
unsafeToHighPolarity :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool Source #
Convert a reset to an active high reset. Has no effect if reset is already an active high reset. Is unsafe because it can introduce:
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
unsafeToLowPolarity :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool Source #
Convert a reset to an active low reset. Has no effect if reset is already an active low reset. It is unsafe because it can introduce:
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
unsafeFromReset :: Reset dom -> Signal dom Bool Source #
unsafeFromReset
is unsafe because it can introduce:
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
NB: You probably want to use unsafeToLowPolarity
or
unsafeToHighPolarity
.
unsafeToReset :: Signal dom Bool -> Reset dom Source #
unsafeToReset
is unsafe. For asynchronous resets it is unsafe
because it can introduce combinatorial loops. In case of synchronous resets
it can lead to meta-stability
issues in the presence of asynchronous resets.
NB: You probably want to use unsafeFromLowPolarity
or
unsafeFromHighPolarity
.
unsafeFromHighPolarity Source #
:: forall dom. KnownDomain dom | |
=> Signal dom Bool | Reset signal that's |
-> Reset dom |
Interpret a signal of bools as an active high reset and convert it to a reset signal corresponding to the domain's setting.
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
unsafeFromLowPolarity Source #
:: forall dom. KnownDomain dom | |
=> Signal dom Bool | Reset signal that's |
-> Reset dom |
Interpret a signal of bools as an active low reset and convert it to a reset signal corresponding to the domain's setting.
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
mux :: Applicative f => f Bool -> f a -> f a -> f a Source #
fromList :: NFDataX a => [a] -> Signal dom a Source #
Create a Signal
from a list
Every element in the list will correspond to a value of the signal for one clock cycle.
>>>
sampleN 2 (fromList [1,2,3,4,5])
[1,2]
NB: This function is not synthesizable
fromList_lazy :: [a] -> Signal dom a Source #
Create a Signal
from a list
Every element in the list will correspond to a value of the signal for one clock cycle.
>>>
sampleN 2 (fromList [1,2,3,4,5] :: Signal System Int)
[1,2]
NB: This function is not synthesizable
hzToPeriod :: HasCallStack => Ratio Natural -> Natural Source #
Calculate the period, in ps, given a frequency in Hz
i.e. to calculate the clock period for a circuit to run at 240 MHz we get
>>>
hzToPeriod 240e6
4166
NB: This function is not synthesizable
NB: This function is lossy. I.e., periodToHz . hzToPeriod /= id.
periodToHz :: Natural -> Ratio Natural Source #
Calculate the frequence in Hz, given the period in ps
i.e. to calculate the clock frequency of a clock with a period of 5000 ps:
>>>
periodToHz 5000
200000000 % 1
NB: This function is not synthesizable
clockPeriod :: forall dom period. (KnownDomain dom, DomainPeriod dom ~ period) => SNat period Source #
Get the clock period from a KnownDomain context
activeEdge :: forall dom edge. (KnownDomain dom, DomainActiveEdge dom ~ edge) => SActiveEdge edge Source #
Get ActiveEdge
from a KnownDomain context. Example usage:
f :: forall dom . KnownDomain dom => .... f a b c = case activeEdge @dom of SRising -> foo SFalling -> bar
resetKind :: forall dom sync. (KnownDomain dom, DomainResetKind dom ~ sync) => SResetKind sync Source #
Get ResetKind
from a KnownDomain context. Example usage:
f :: forall dom . KnownDomain dom => .... f a b c = case resetKind @dom of SAsynchronous -> foo SSynchronous -> bar
initBehavior :: forall dom init. (KnownDomain dom, DomainInitBehavior dom ~ init) => SInitBehavior init Source #
Get InitBehavior
from a KnownDomain context. Example usage:
f :: forall dom . KnownDomain dom => .... f a b c = case initBehavior @dom of SDefined -> foo SUnknown -> bar
resetPolarity :: forall dom polarity. (KnownDomain dom, DomainResetPolarity dom ~ polarity) => SResetPolarity polarity Source #
Get ResetPolarity
from a KnownDomain context. Example usage:
f :: forall dom . KnownDomain dom => .... f a b c = case resetPolarity @dom of SActiveHigh -> foo SActiveLow -> bar
knownVDomain :: forall dom. KnownDomain dom => VDomainConfiguration Source #
Like 'knownDomain but yields a VDomainConfiguration
. Should only be used
in combination with createDomain
.
Isomorphism between a Signal
of a product type (e.g. a tuple) and a
product type of Signal
s.
Instances of Bundle
must satisfy the following laws:
bundle
.unbundle
=id
unbundle
.bundle
=id
By default, bundle
and unbundle
, are defined as the identity, that is,
writing:
data D = A | B instance Bundle D
is the same as:
data D = A | B instance Bundle D where typeUnbundled
clk D =Signal
clk Dbundle
s = sunbundle
s = s
For custom product types you'll have to write the instance manually:
data Pair a b = MkPair { getA :: a, getB :: b } instance Bundle (Pair a b) where type Unbundled dom (Pair a b) = Pair (Signal dom a) (Signal dom b) -- bundle :: Pair (Signal dom a) (Signal dom b) -> Signal dom (Pair a b) bundle (MkPair as bs) = MkPair $ as * bs -- unbundle :: Signal dom (Pair a b) -> Pair (Signal dom a) (Signal dom b) unbundle pairs = MkPair (getA $ pairs) (getB $ pairs)
Nothing
bundle :: Unbundled dom a -> Signal dom a Source #
Example:
bundle :: (Signal
dom a,Signal
dom b) ->Signal
dom (a,b)
However:
bundle ::Signal
domBit
->Signal
domBit
Instances
Bundle Bool Source # | |
Bundle Double Source # | |
Bundle Float Source # | |
Bundle Int Source # | |
Bundle Integer Source # | |
Bundle () Source # | |
Bundle Bit Source # | |
Bundle EmptyTuple Source # | See commit 94b0bff5
and documentation for |
Defined in Clash.Signal.Bundle type Unbundled dom EmptyTuple = (res :: Type) Source # bundle :: forall (dom :: Domain). Unbundled dom EmptyTuple -> Signal dom EmptyTuple Source # unbundle :: forall (dom :: Domain). Signal dom EmptyTuple -> Unbundled dom EmptyTuple Source # | |
Bundle (Maybe a) Source # | |
Bundle (BitVector n) Source # | |
Bundle (Index n) Source # | |
Bundle (Unsigned n) Source # | |
Bundle (Signed n) Source # | |
Bundle (Either a b) Source # | |
Bundle (a1, a2) Source # | |
KnownNat n => Bundle (Vec n a) Source # | |
KnownNat d => Bundle (RTree d a) Source # | |
Bundle (a1, a2, a3) Source # | N.B.: The documentation only shows instances up to 3-tuples. By
default, instances up to and including 12-tuples will exist. If the flag
|
Bundle (Fixed rep int frac) Source # | |
Defined in Clash.Signal.Bundle | |
Bundle ((f :*: g) a) Source # | |
data TaggedEmptyTuple (dom :: Domain) Source #
Helper type to emulate the "old" behavior of Bundle's unit instance. I.e.,
the instance for Bundle ()
used to be defined as:
class Bundle () where bundle :: () -> Signal dom () unbundle :: Signal dom () -> ()
In order to have sensible type inference, the Bundle
class specifies that
the argument type of bundle
should uniquely identify the result type, and
vice versa for unbundle
. The type signatures in the snippet above don't
though, as ()
doesn't uniquely map to a specific domain. In other words,
domain
should occur in both the argument and result of both functions.
TaggedEmptyTuple
tackles this by carrying the domain in its type. The
bundle
and unbundle
instance now looks like:
class Bundle EmptyTuple where bundle :: TaggedEmptyTuple dom -> Signal dom EmptyTuple unbundle :: Signal dom EmptyTuple -> TaggedEmptyTuple dom
dom
is now mentioned both the argument and result for both bundle
and
unbundle
.
data EmptyTuple Source #
See TaggedEmptyTuple
Instances
Bundle EmptyTuple Source # | See commit 94b0bff5
and documentation for |
Defined in Clash.Signal.Bundle type Unbundled dom EmptyTuple = (res :: Type) Source # bundle :: forall (dom :: Domain). Unbundled dom EmptyTuple -> Signal dom EmptyTuple Source # unbundle :: forall (dom :: Domain). Signal dom EmptyTuple -> Unbundled dom EmptyTuple Source # | |
Bundle EmptyTuple Source # | See commit 94b0bff5
and documentation for |
Defined in Clash.Signal.Delayed.Bundle type Unbundled dom d EmptyTuple = (res :: Type) Source # bundle :: forall (dom :: Domain) (d :: Nat). Unbundled dom d EmptyTuple -> DSignal dom d EmptyTuple Source # unbundle :: forall (dom :: Domain) (d :: Nat). DSignal dom d EmptyTuple -> Unbundled dom d EmptyTuple Source # | |
type Unbundled dom EmptyTuple Source # | |
Defined in Clash.Signal.Bundle | |
type Unbundled dom d EmptyTuple Source # | |
Defined in Clash.Signal.Delayed.Bundle |
data BiSignalOut (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat) Source #
The out part of an inout port
Wraps (multiple) writing signals. The semantics are such that only one of the signals may write at a single time step.
BiSignalOut has the type role
>>>
:i BiSignalOut
type role BiSignalOut nominal nominal nominal ...
as it is not safe to coerce the default behaviour, synthesis domain or width of the data in the signal.
Instances
Semigroup (BiSignalOut defaultState dom n) Source # | NB Not synthesizable |
Defined in Clash.Signal.BiSignal (<>) :: BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n # sconcat :: NonEmpty (BiSignalOut defaultState dom n) -> BiSignalOut defaultState dom n # stimes :: Integral b => b -> BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n # | |
Monoid (BiSignalOut defaultState dom n) Source # | Monoid instance to support concatenating NB Not synthesizable |
Defined in Clash.Signal.BiSignal mempty :: BiSignalOut defaultState dom n # mappend :: BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n # mconcat :: [BiSignalOut defaultState dom n] -> BiSignalOut defaultState dom n # | |
type HasDomain dom1 (BiSignalOut ds dom2 n) Source # | |
Defined in Clash.Signal.BiSignal | |
type TryDomain t (BiSignalOut ds dom n) Source # | |
Defined in Clash.Signal.BiSignal |
data BiSignalIn (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat) Source #
The in part of an inout port. BiSignalIn has the type role
>>>
:i BiSignalIn
type role BiSignalIn nominal nominal nominal ...
as it is not safe to coerce the default behaviour, synthesis domain or width of the data in the signal.
data BiSignalDefault Source #
Used to specify the default behavior of a "BiSignal", i.e. what value is read when no value is being written to it.
PullUp | inout port behaves as if connected to a pull-up resistor |
PullDown | inout port behaves as if connected to a pull-down resistor |
Floating | inout port behaves as if is floating. Reading a floating "BiSignal" value in simulation will yield an errorX (undefined value). |
Instances
Show BiSignalDefault Source # | |
Defined in Clash.Signal.BiSignal showsPrec :: Int -> BiSignalDefault -> ShowS # show :: BiSignalDefault -> String # showList :: [BiSignalDefault] -> ShowS # |
:: (HasCallStack, BitPack a) | |
=> BiSignalIn ds d (BitSize a) | A |
-> Signal d a |
Read the value from an inout port
mergeBiSignalOuts :: (HasCallStack, KnownNat n) => Vec n (BiSignalOut defaultState dom m) -> BiSignalOut defaultState dom m Source #
Combine several inout signals into one.
:: (HasCallStack, BitPack a) | |
=> BiSignalIn ds d (BitSize a) | |
-> Signal d (Maybe a) | Value to write
|
-> BiSignalOut ds d (BitSize a) |
Write to an inout port
veryUnsafeToBiSignalIn :: (HasCallStack, KnownNat n, Given (SBiSignalDefault ds)) => BiSignalOut ds d n -> BiSignalIn ds d n Source #
Converts the out
part of a BiSignal to an in
part. In simulation it
checks whether multiple components are writing and will error accordingly.
Make sure this is only called ONCE for every BiSignal.
systemClockGen :: Clock System Source #
Clock generator for the System
clock domain.
NB: should only be used for simulation, and not for the testBench
function. For the testBench function, used tbSystemClockGen
systemResetGen :: Reset System Source #
Reset generator for the System
clock domain.
NB: should only be used for simulation or the testBench function.
Example
topEntity :: Vec 2 (Vec 3 (Unsigned 8)) -> Vec 6 (Unsigned 8)
topEntity = concat
testBench :: Signal System Bool
testBench = done
where
testInput = pure ((1 :> 2 :> 3 :> Nil) :> (4 :> 5 :> 6 :> Nil) :> Nil)
expectedOutput = outputVerifier' ((1:>2:>3:>4:>5:>6:>Nil):>Nil)
done = exposeClockResetEnable (expectedOutput (topEntity $ testInput)) clk rst
clk = tbSystemClockGen (not <$> done)
rst = systemResetGen
resetSynchronizer :: forall dom. KnownDomain dom => Clock dom -> Reset dom -> Reset dom Source #
The resetSynchronizer will synchronize an incoming reset according to whether the domain is synchronous or asynchronous.
For asynchronous resets this synchronizer ensures the reset will only 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,
resetSynchronizer
ensures that de-assertion of a reset happens
synchronously. Assertion of the reset remains asynchronous.
Note that asynchronous assertion does not induce meta-stability in the component whose reset is asserted. However, when a component "A" in another clock or reset domain depends on the value of a component "B" being reset, then asynchronous assertion of the reset of component "B" can induce meta-stability in component "A". To prevent this from happening you need to use a proper synchronizer, for example one of the synchronizers in Clash.Explicit.Synchronizer.
For synchronous resets this function ensures that the reset is asserted and de-asserted synchronously. Both the assertion and de-assertion of the reset are delayed by two cycles.
Example 1
The circuit below detects a rising bit (i.e., a transition from 0 to 1) in a
given argument. It takes a reset that is not synchronized to any of the other
incoming signals and synchronizes it using resetSynchronizer
.
topEntity
:: Clock System
-> Reset System
-> Signal System Bit
-> Signal System (BitVector 8)
topEntity clk asyncRst key1 =
withClockResetEnable clk rst enableGen leds
where
rst = resetSynchronizer
clk asyncRst
key1R = isRising 1 key1
leds = mealy blinkerT (1, False, 0) key1R
Example 2
Similar to Example 1 this circuit detects a rising bit (i.e., a transition from 0 to 1) in a given argument. It takes a clock that is not stable yet and a reset singal that is not synchronized to any other signals. It stabalizes the clock and then synchronizes the reset signal.
topEntity
:: Clock System
-> Reset System
-> Signal System Bit
-> Signal System (BitVector 8)
topEntity clk rst key1 =
let (pllOut,pllStable) = altpll (SSymbol @"altpll50") clk rst
rstSync = resetSynchronizer
pllOut (unsafeToHighPolarity pllStable)
in exposeClockResetEnable leds pllOut rstSync enableGen
where
key1R = isRising 1 key1
leds = mealy blinkerT (1, False, 0) key1R
Implementation details
resetSynchronizer
implements the following circuit for asynchronous domains:
rst --------------------------------------+ | | +----v----+ +----v----+ deasserted | | | | ---------------> +-------> +--------> | | | | +---|> | +---|> | | | | | | | | +---------+ | +---------+ clk | | -----------------------------+
This corresponds to figure 3d at https://www.embedded.com/asynchronous-reset-synchronization-and-distribution-challenges-and-solutions/
For synchronous domains two sequential dflipflops are used:
+---------+ +---------+ rst | | | | ---------------> +-------> +--------> | | | | +---|> | +---|> | | | | | | | | +---------+ | +---------+ clk | | -----------------------------+
:: forall dom glitchlessPeriod n. (KnownDomain dom, glitchlessPeriod ~ (n + 1)) | |
=> SNat glitchlessPeriod | Consider a reset signal to be properly asserted after having seen the reset asserted for glitchlessPeriod cycles straight. |
-> Clock dom | |
-> Reset dom | |
-> Reset dom |
Filter glitches from reset signals by only triggering a reset after it has been asserted for glitchlessPeriod cycles. It will then stay asserted for as long as the given reset was asserted consecutively.
If synthesized on a domain with initial values, resetGlitchFilter
will
output an asserted reset for glitchlessPeriod cycles (plus any cycles added
by the given reset). If initial values can't be used, it will only output
defined reset values after glitchlessPeriod cycles.
Example 1
>>>
let sampleResetN n = sampleN n . unsafeToHighPolarity
>>>
let resetFromList = unsafeFromHighPolarity . fromList
>>>
let rst = resetFromList [True, True, False, False, True, False, False, True, True, False, True]
>>>
sampleResetN 12 (resetGlitchFilter d2 systemClockGen rst)
[True,True,True,True,False,False,False,False,False,True,True,False]
type SystemClockResetEnable = (Hidden (HiddenClockName System) (Clock System), Hidden (HiddenResetName System) (Reset System), Hidden (HiddenEnableName System) (Enable System)) Source #
A constraint that indicates the component needs a Clock
, a Reset
,
and an Enable
belonging to the System
domain.
Click here to read more about hidden clocks, resets, and enables
type HiddenClockResetEnable dom = (HiddenClock dom, HiddenReset dom, HiddenEnable dom) Source #
A constraint that indicates the component needs a Clock
, a Reset
,
and an Enable
belonging to the same dom
.
Click here to read more about hidden clocks, resets, and enables
type HiddenEnable dom = (Hidden (HiddenEnableName dom) (Enable dom), KnownDomain dom) Source #
A constraint that indicates the component needs an Enable
Click here to read more about hidden clocks, resets, and enables
type HiddenReset dom = (Hidden (HiddenResetName dom) (Reset dom), KnownDomain dom) Source #
A constraint that indicates the component needs a Reset
Click here to read more about hidden clocks, resets, and enables
type HiddenClock dom = (Hidden (HiddenClockName dom) (Clock dom), KnownDomain dom) Source #
A constraint that indicates the component has a hidden Clock
Click here to read more about hidden clocks, resets, and enables
:: forall dom r. (HiddenClock dom => r) | The component with a hidden clock |
-> KnownDomain dom => Clock dom -> r | The component with its clock argument exposed |
Expose a hidden Clock
argument of a component, so it can be applied
explicitly.
Click here to read more about hidden clocks, resets, and enables
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
sig = exposeClock reg clockGen
>>>
sampleN @System 10 sig
[5,5,6,7,8,9,10,11,12,13]
Force exposeClock
to work on System
(hence sampleN
not needing an explicit
domain later):
>>>
reg = register 5 (reg + 1)
>>>
sig = exposeClock @System reg clockGen
>>>
sampleN 10 sig
[5,5,6,7,8,9,10,11,12,13]
:: forall dom r. HiddenClock dom | |
=> (Clock dom -> r) | Function whose clock argument you want to hide |
-> r |
Hide the Clock
argument of a component, so it can be routed implicitly.
Click here to read more about hidden clocks, resets, and enables
:: forall dom r. KnownDomain dom | |
=> Clock dom | The |
-> (HiddenClock dom => r) | The function with a hidden |
-> r |
Connect an explicit Clock
to a function with a hidden Clock
.
Click here to read more about hidden clocks, resets, and enables
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
sig = withClock clockGen reg
>>>
sampleN @System 10 sig
[5,5,6,7,8,9,10,11,12,13]
Force withClock
to work on System
(hence sampleN
not needing an explicit
domain later):
>>>
reg = register 5 (reg + 1)
>>>
sig = withClock @System clockGen reg
>>>
sampleN 10 sig
[5,5,6,7,8,9,10,11,12,13]
hasClock :: forall dom. HiddenClock dom => Clock dom Source #
Connect a hidden Clock
to an argument where a normal Clock
argument
was expected.
Click here to read more about hidden clocks, resets, and enables
:: forall dom r. (HiddenReset dom => r) | The component with a hidden reset |
-> KnownDomain dom => Reset dom -> r | The component with its reset argument exposed |
Expose a hidden Reset
argument of a component, so it can be applied
explicitly.
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
sig = exposeReset reg resetGen
>>>
sampleN @System 10 sig
[5,5,6,7,8,9,10,11,12,13]
Force exposeReset
to work on System
(hence sampleN
not needing an explicit
domain later):
>>>
reg = register 5 (reg + 1)
>>>
sig = exposeReset @System reg resetGen
>>>
sampleN 10 sig
[5,5,6,7,8,9,10,11,12,13]
:: forall dom r. HiddenReset dom | |
=> (Reset dom -> r) | Component whose reset argument you want to hide |
-> r |
Hide the Reset
argument of a component, so it can be routed implicitly.
Click here to read more about hidden clocks, resets, and enables
:: forall dom r. KnownDomain dom | |
=> Reset dom | The |
-> (HiddenReset dom => r) | The function with a hidden |
-> r |
Connect an explicit Reset
to a function with a hidden Reset
.
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
sig = withReset resetGen reg
>>>
sampleN @System 10 sig
[5,5,6,7,8,9,10,11,12,13]
Force withReset
to work on System
(hence sampleN
not needing an explicit
domain later):
>>>
reg = register 5 (reg + 1)
>>>
sig = withReset @System resetGen reg
>>>
sampleN 10 sig
[5,5,6,7,8,9,10,11,12,13]
hasReset :: forall dom. HiddenReset dom => Reset dom Source #
Connect a hidden Reset
to an argument where a normal Reset
argument
was expected.
Click here to read more about hidden clocks, resets, and enables
:: forall dom r. (HiddenEnable dom => r) | The component with a hidden enable |
-> KnownDomain dom => Enable dom -> r | The component with its enable argument exposed |
Expose a hidden Enable
argument of a component, so it can be applied
explicitly.
Click here to read more about hidden clocks, resets, and enables
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
sig = exposeEnable reg enableGen
>>>
sampleN @System 10 sig
[5,5,6,7,8,9,10,11,12,13]
Force exposeEnable
to work on System
(hence sampleN
not needing an
explicit domain later):
>>>
reg = register 5 (reg + 1)
>>>
sig = exposeEnable @System reg enableGen
>>>
sampleN 10 sig
[5,5,6,7,8,9,10,11,12,13]
:: forall dom r. HiddenEnable dom | |
=> (Enable dom -> r) | Component whose enable argument you want to hide |
-> r |
Hide the Enable
argument of a component, so it can be routed implicitly.
Click here to read more about hidden clocks, resets, and enables
:: forall dom r. KnownDomain dom | |
=> Enable dom | The |
-> (HiddenEnable dom => r) | The function with a hidden |
-> r |
Connect an explicit Enable
to a function with a hidden Enable
.
Click here to read more about hidden clocks, resets, and enables
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
sig = withEnable enableGen reg
>>>
sampleN @System 10 sig
[5,5,6,7,8,9,10,11,12,13]
Force withEnable
to work on System
(hence sampleN
not needing an explicit
domain later):
>>>
reg = register 5 (reg + 1)
>>>
sig = withEnable @System enableGen reg
>>>
sampleN 10 sig
[5,5,6,7,8,9,10,11,12,13]
hasEnable :: forall dom. HiddenEnable dom => Enable dom Source #
Connect a hidden Enable
to an argument where a normal Enable
argument
was expected.
Click here to read more about hidden clocks, resets, and enables
:: forall dom r. HiddenEnable dom | |
=> Signal dom Bool | The signal to AND with |
-> (HiddenEnable dom => r) | The component whose enable is modified |
-> r |
Merge enable signal with signal of bools by applying the boolean AND operation.
NB: The component given to andEnable
as an argument needs an explicit type signature.
Please read Monomorphism restriction leads to surprising
behavior.
The component whose enable is modified will only be enabled when both the
encompassing HiddenEnable
and the Signal
dom
Bool
are asserted.
Click here to read more about hidden clocks, resets, and enables
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
f en = andEnable en reg
>>>
sampleN @System 10 (f (riseEvery d2))
[5,5,5,6,6,7,7,8,8,9]
Force andEnable
to work on System
(hence sampleN
not needing an explicit
domain later):
>>>
reg = register 5 (reg + 1)
>>>
f en = andEnable @System en reg
>>>
sampleN 10 (f (riseEvery d2))
[5,5,5,6,6,7,7,8,8,9]
exposeClockResetEnable Source #
:: forall dom r. (HiddenClockResetEnable dom => r) | The component with hidden clock, reset, and enable arguments |
-> KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> r | The component with its clock, reset, and enable arguments exposed |
Expose hidden Clock
, Reset
, and Enable
arguments of a component, so
they can be applied explicitly.
Click here to read more about hidden clocks, resets, and enables
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
sig = exposeClockResetEnable reg clockGen resetGen enableGen
>>>
sampleN @System 10 sig
[5,5,6,7,8,9,10,11,12,13]
Force exposeClockResetEnable
to work on System
(hence sampleN
not needing
an explicit domain later):
>>>
reg = register 5 (reg + 1)
>>>
sig = exposeClockResetEnable @System reg clockGen resetGen enableGen
>>>
sampleN 10 sig
[5,5,6,7,8,9,10,11,12,13]
Usage in a testbench context:
topEntity :: Vec 2 (Vec 3 (Unsigned 8)) -> Vec 6 (Unsigned 8) topEntity = concat testBench :: Signal System Bool testBench = done where testInput = pure ((1 :> 2 :> 3 :> Nil) :> (4 :> 5 :> 6 :> Nil) :> Nil) expectedOutput = outputVerifier' ((1:>2:>3:>4:>5:>6:>Nil):>Nil) done = exposeClockResetEnable (expectedOutput (topEntity <$> testInput)) clk rst en clk = tbSystemClockGen (not <$> done) rst = systemResetGen en = enableGen
:: forall dom r. HiddenClockResetEnable dom | |
=> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> r) | Component whose clock, reset, and enable argument you want to hide |
-> r |
Hide the Clock
, Reset
, and Enable
arguments of a component, so they
can be routed implicitly.
Click here to read more about hidden clocks, resets, and enables
:: forall dom r. KnownDomain dom | |
=> Clock dom | The |
-> Reset dom | The |
-> Enable dom | The |
-> (HiddenClockResetEnable dom => r) | The function with a hidden |
-> r |
Connect an explicit Clock
, Reset
, and Enable
to a function with a
hidden Clock
, Reset
, and Enable
.
Click here to read more about hidden clocks, resets, and enables
Example
Usage with a polymorphic domain:
>>>
reg = register 5 (reg + 1)
>>>
sig = withClockResetEnable clockGen resetGen enableGen reg
>>>
sampleN @System 10 sig
[5,5,6,7,8,9,10,11,12,13]
Force withClockResetEnable
to work on System
(hence sampleN
not needing
an explicit domain later):
>>>
reg = register 5 (reg + 1)
>>>
sig = withClockResetEnable @System clockGen resetGen enableGen reg
>>>
sampleN 10 sig
[5,5,6,7,8,9,10,11,12,13]
dflipflop :: forall dom a. (HiddenClock dom, NFDataX a) => Signal dom a -> Signal dom a Source #
Special version of delay
that doesn't take enable signals of any kind.
Initial value will be undefined.
:: forall dom a. (NFDataX a, HiddenClock dom, HiddenEnable dom) | |
=> a | Initial value |
-> Signal dom a | Signal to delay |
-> Signal dom a |
:: forall dom a. (NFDataX a, HiddenClock dom, HiddenEnable dom) | |
=> a | Initial value |
-> Signal dom (Maybe a) | |
-> Signal dom a |
:: forall dom a. (NFDataX a, HiddenClock dom, HiddenEnable dom) | |
=> a | Initial value |
-> Signal dom Bool | Enable |
-> Signal dom a | |
-> Signal dom a |
Version of delay
that only updates when its second argument is asserted.
>>>
let input = fromList [1,2,3,4,5,6,7::Int]
>>>
let enable = fromList [True,True,False,False,True,True,True]
>>>
sampleN @System 7 (delayEn 0 enable input)
[0,1,2,2,2,5,6]
:: forall dom a. (HiddenClockResetEnable dom, NFDataX a) | |
=> a | Reset value. |
-> Signal dom a | |
-> Signal dom a |
:: forall dom a. (HiddenClockResetEnable dom, NFDataX a) | |
=> a | Reset value. |
-> Signal dom (Maybe a) | |
-> Signal dom a |
Version of register
that only updates its content when its second
argument is a Just
value. So given:
sometimes1 = s where s =register
Nothing (switch<$>
s) switch Nothing = Just 1 switch _ = Nothing countSometimes = s where s =regMaybe
0 (plusM (pure
<$>
s) sometimes1) plusM =liftA2
(liftA2 (+))
We get:
>>>
sampleN @System 9 sometimes1
[Nothing,Nothing,Just 1,Nothing,Just 1,Nothing,Just 1,Nothing,Just 1]>>>
sampleN @System 9 countSometimes
[0,0,0,1,1,2,2,3,3]
:: forall dom a. (HiddenClockResetEnable dom, NFDataX a) | |
=> a | Reset value. |
-> Signal dom Bool | |
-> Signal dom a | |
-> Signal dom a |
Version of register
that only updates its content when its second argument
is asserted. So given:
oscillate =register
False (not
<$>
oscillate) count =regEn
0 oscillate (count + 1)
We get:
>>>
sampleN @System 9 oscillate
[False,False,True,False,True,False,True,False,True]>>>
sampleN @System 9 count
[0,0,0,1,1,2,2,3,3]
:: forall dom a. (KnownDomain dom, NFDataX a) | |
=> (HiddenClockResetEnable dom => Signal dom a) |
|
-> [a] |
Get an infinite list of samples from a Signal
The elements in the list correspond to the values of the Signal
at consecutive clock cycles
sample s == [s0, s1, s2, s3, ...
If the given component has not yet been given a clock, reset, or enable
line, sample
will supply them. The reset will be asserted for a single
cycle. sample
will not drop the value produced by the circuit while
the reset was asserted. If you want this, or if you want more than a
single cycle reset, consider using sampleWithReset
.
NB: This function is not synthesizable
:: forall dom a. (KnownDomain dom, NFDataX a) | |
=> Int | Number of samples to produce |
-> (HiddenClockResetEnable dom => Signal dom a) |
|
-> [a] |
Get a list of n samples from a Signal
The elements in the list correspond to the values of the Signal
at consecutive clock cycles
sampleN @System 3 s == [s0, s1, s2]
If the given component has not yet been given a clock, reset, or enable
line, sampleN
will supply them. The reset will be asserted for a single
cycle. sampleN
will not drop the value produced by the circuit while
the reset was asserted. If you want this, or if you want more than a
single cycle reset, consider using sampleWithResetN
.
NB: This function is not synthesizable
:: forall dom a m. (KnownDomain dom, NFDataX a, 1 <= m) | |
=> SNat m | Number of cycles to assert the reset |
-> (HiddenClockResetEnable dom => Signal dom a) |
|
-> [a] |
Get an infinite list of samples from a Signal
, while asserting the reset
line for m clock cycles. sampleWithReset
does not return the first m
cycles, i.e., when the reset is asserted.
NB: This function is not synthesizable
:: forall dom a m. (KnownDomain dom, NFDataX a, 1 <= m) | |
=> SNat m | Number of cycles to assert the reset |
-> Int | Number of samples to produce |
-> (HiddenClockResetEnable dom => Signal dom a) |
|
-> [a] |
Get a list of n samples from a Signal
, while asserting the reset line
for m clock cycles. sampleWithReset
does not return the first m cycles,
i.e., while the reset is asserted.
NB: This function is not synthesizable
:: forall dom a. KnownDomain dom | |
=> (HiddenClockResetEnable dom => Signal dom a) |
|
-> [a] |
Lazily get an infinite list of samples from a Signal
The elements in the list correspond to the values of the Signal
at consecutive clock cycles
sample s == [s0, s1, s2, s3, ...
If the given component has not yet been given a clock, reset, or enable
line, sample_lazy
will supply them. The reset will be asserted for a
single cycle. sample_lazy
will not drop the value produced by the
circuit while the reset was asserted.
NB: This function is not synthesizable
:: forall dom a. KnownDomain dom | |
=> Int | |
-> (HiddenClockResetEnable dom => Signal dom a) |
|
-> [a] |
Lazily get a list of n samples from a Signal
The elements in the list correspond to the values of the Signal
at consecutive clock cycles
sampleN @System 3 s == [s0, s1, s2]
If the given component has not yet been given a clock, reset, or enable
line, sampleN_lazy
will supply them. The reset will be asserted for a
single cycle. sampleN_lazy
will not drop the value produced by the
circuit while the reset was asserted.
NB: This function is not synthesizable
:: forall dom a b. (KnownDomain dom, NFDataX a, NFDataX b) | |
=> (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) | Circuit to simulate, whose source potentially has a hidden clock, reset, and/or enable. |
-> [a] | |
-> [b] |
Simulate a (
) function given a list of samples
of type aSignal
a -> Signal
b
>>>
simulate @System (register 8) [1, 2, 3]
[8,1,2,3... ...
Where System
denotes the domain to simulate on. The reset line is
asserted for a single cycle. The first value is therefore supplied twice to
the circuit: once while reset is high, and once directly after. The first
output value (the value produced while the reset is asserted) is dropped.
If you only want to simulate a finite number of samples, see simulateN
. If
you need the reset line to be asserted for more than one cycle or if you
need a custom reset value, see simulateWithReset
and simulateWithResetN
.
NB: This function is not synthesizable
:: forall dom a b. (KnownDomain dom, NFDataX a, NFDataX b) | |
=> Int | Number of cycles to simulate (excluding cycle spent in reset) |
-> (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) |
|
-> [a] | |
-> [b] |
Same as simulate
, but only sample the first Int output values.
NB: This function is not synthesizable
:: forall dom a b m. (KnownDomain dom, NFDataX a, NFDataX b, 1 <= m) | |
=> SNat m | Number of cycles to assert the reset |
-> a | Reset value |
-> (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) |
|
-> [a] | |
-> [b] |
Same as simulate
, but with the reset line asserted for n cycles. Similar
to simulate
, simulateWithReset
will drop the output values produced while
the reset is asserted. While the reset is asserted, the reset value a is
supplied to the circuit.
:: forall dom a b m. (KnownDomain dom, NFDataX a, NFDataX b, 1 <= m) | |
=> SNat m | Number of cycles to assert the reset |
-> a | Reset value |
-> Int | Number of cycles to simulate (excluding cycles spent in reset) |
-> (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) |
|
-> [a] | |
-> [b] |
Same as simulateWithReset
, but only sample the first Int output values.
:: forall dom a b. KnownDomain dom | |
=> (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) | Function we want to simulate, whose components potentially have a hidden clock (and reset) |
-> [a] | |
-> [b] |
:: forall dom a b. (KnownDomain dom, Bundle a, Bundle b, NFDataX a, NFDataX b) | |
=> (HiddenClockResetEnable dom => Unbundled dom a -> Unbundled dom b) | Function we want to simulate, whose components potentially have a hidden clock (and reset) |
-> [a] | |
-> [b] |
:: forall dom a b. (KnownDomain dom, Bundle a, Bundle b) | |
=> (HiddenClockResetEnable dom => Unbundled dom a -> Unbundled dom b) | Function we want to simulate, whose components potentially have a hidden clock (and reset) |
-> [a] | |
-> [b] |
:: forall dom a. (KnownDomain dom, NFDataX a, ShowX a) | |
=> (a -> Bool) | Condition checking function, should return |
-> (HiddenClockResetEnable dom => Signal dom a) |
|
-> IO () |
Simulate a component until it matches a condition
If the given component has not yet been given a clock, reset, or enable
line, runUntil
will supply them. The reset will be asserted for a single
cycle.
It prints a message of the form
Signal sampled for N cycles until value X
NB: This function is not synthesizable
Example with test bench
A common usage is with a test bench using
outputVerifier
.
NB: Since this uses assert
, when using
clashi
, read the note at Clash.Explicit.Testbench.
import Clash.Prelude import Clash.Explicit.Testbench topEntity ::Signal
System
Int ->Signal
System
Int topEntity = id testBench ::Signal
System
Bool testBench = done where testInput =stimuliGenerator
clk rst $(listToVecTH
[1 :: Int .. 10]) expectedOutput =outputVerifier'
clk rst $(listToVecTH
$ [1 :: Int .. 9]<>
[42]) done = expectedOutput $ topEntity testInput clk =tbSystemClockGen
(not <$> done) rst =systemResetGen
> runUntil id testBench cycle(<Clock: System>): 10, outputVerifier expected value: 42, not equal to actual value: 10 Signal sampled for 11 cycles until value True
When you need to verify multiple test benches, the following invocations come in handy:
> mapM_
(runUntil id) [ testBenchA, testBenchB ]
or when the test benches are in different clock domains:
testBenchA :: Signal DomA Bool testBenchB :: Signal DomB Bool
> sequence_
[ runUntil id testBenchA, runUntil id testBenchB ]
:: KnownDomain dom | |
=> Int | The number of cycles we want to test for |
-> (HiddenClockResetEnable dom => Signal dom Bool) |
|
-> Property |
testFor n s
tests the signal s for n cycles.
NB: This function is not synthesizable
:: forall dom m. HiddenClockResetEnable dom | |
=> SNat m | Hold for m cycles, counting from the moment the incoming reset signal becomes deasserted. |
-> Reset dom |
Hold reset for a number of cycles relative to an implicit reset signal.
Example:
>>>
sampleN @System 8 (unsafeToHighPolarity (holdReset (SNat @2)))
[True,True,True,False,False,False,False,False]
holdReset
holds the reset for an additional 2 clock cycles for a total
of 3 clock cycles where the reset is asserted.
fromListWithReset :: forall dom a. (HiddenReset dom, NFDataX a) => a -> [a] -> Signal dom a Source #
Like fromList
, but resets on reset and has a defined reset value.
>>>
let rst = unsafeFromHighPolarity (fromList [True, True, False, False, True, False])
>>>
let res = withReset rst (fromListWithReset Nothing [Just 'a', Just 'b', Just 'c'])
>>>
sampleN @System 6 res
[Nothing,Nothing,Just 'a',Just 'b',Nothing,Just 'a']
NB: This function is not synthesizable
signalAutomaton :: forall dom a b. KnownDomain dom => (HiddenClockResetEnable dom => Signal dom a -> Signal dom b) -> Automaton (->) a b Source #
module Clash.Signal.Delayed
Datatypes
Bit vectors
module Clash.Sized.BitVector
Arbitrary-width numbers
module Clash.Sized.Signed
module Clash.Sized.Unsigned
module Clash.Sized.Index
Fixed point numbers
module Clash.Sized.Fixed
Fixed size vectors
data Vec :: Nat -> Type -> Type where Source #
Fixed size vectors.
pattern (:>) :: a -> Vec n a -> Vec (n + 1) a infixr 5 | Add an element to the head of a vector.
Can be used as a pattern:
Also in conjunctions with (
|
pattern (:<) :: Vec n a -> a -> Vec (n + 1) a infixl 5 | Add an element to the tail of a vector.
Can be used as a pattern:
Also in conjunctions with (
|
Instances
Lift a => Lift (Vec n a :: Type) Source # | |
Functor (Vec n) Source # | |
KnownNat n => Applicative (Vec n) Source # | |
(KnownNat n, 1 <= n) => Foldable (Vec n) Source # | |
Defined in Clash.Sized.Vector fold :: Monoid m => Vec n m -> m # foldMap :: Monoid m => (a -> m) -> Vec n a -> m # foldMap' :: Monoid m => (a -> m) -> Vec n a -> m # foldr :: (a -> b -> b) -> b -> Vec n a -> b # foldr' :: (a -> b -> b) -> b -> Vec n a -> b # foldl :: (b -> a -> b) -> b -> Vec n a -> b # foldl' :: (b -> a -> b) -> b -> Vec n a -> b # foldr1 :: (a -> a -> a) -> Vec n a -> a # foldl1 :: (a -> a -> a) -> Vec n a -> a # elem :: Eq a => a -> Vec n a -> Bool # maximum :: Ord a => Vec n a -> a # minimum :: Ord a => Vec n a -> a # | |
(KnownNat n, 1 <= n) => Traversable (Vec n) Source # | |
(KnownNat n, Eq a) => Eq (Vec n a) Source # | |
(KnownNat n, Typeable a, Data a) => Data (Vec n a) Source # | |
Defined in Clash.Sized.Vector gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Vec n a -> c (Vec n a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Vec n a) # toConstr :: Vec n a -> Constr # dataTypeOf :: Vec n a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Vec n a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Vec n a)) # gmapT :: (forall b. Data b => b -> b) -> Vec n a -> Vec n a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Vec n a -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Vec n a -> r # gmapQ :: (forall d. Data d => d -> u) -> Vec n a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Vec n a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Vec n a -> m (Vec n a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Vec n a -> m (Vec n a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Vec n a -> m (Vec n a) # | |
(KnownNat n, Ord a) => Ord (Vec n a) Source # | |
Show a => Show (Vec n a) Source # | |
KnownNat n => Generic (Vec n a) Source # | In many cases, this Generic instance only allows generic functions/instances over vectors of at least size 1, due to the n-1 in the Rep (Vec n a) definition. We'll have to wait for things like https://ryanglscott.github.io/2018/02/11/how-to-derive-generic-for-some-gadts/ before we can work around this limitation |
(KnownNat n, Semigroup a) => Semigroup (Vec n a) Source # | |
(KnownNat n, Monoid a) => Monoid (Vec n a) Source # | |
(KnownNat n, Arbitrary a) => Arbitrary (Vec n a) Source # | |
CoArbitrary a => CoArbitrary (Vec n a) Source # | |
Defined in Clash.Sized.Vector coarbitrary :: Vec n a -> Gen b -> Gen b # | |
(Default a, KnownNat n) => Default (Vec n a) Source # | |
Defined in Clash.Sized.Vector | |
NFData a => NFData (Vec n a) Source # | |
Defined in Clash.Sized.Vector | |
KnownNat n => Ixed (Vec n a) Source # | |
Defined in Clash.Sized.Vector | |
(NFDataX a, KnownNat n) => NFDataX (Vec n a) Source # | |
Defined in Clash.Sized.Vector | |
ShowX a => ShowX (Vec n a) Source # | |
(KnownNat n, BitPack a) => BitPack (Vec n a) Source # | |
KnownNat n => Bundle (Vec n a) Source # | |
KnownNat n => Bundle (Vec n a) Source # | |
Defined in Clash.Signal.Delayed.Bundle | |
(KnownNat n, AutoReg a) => AutoReg (Vec n a) Source # | |
Defined in Clash.Class.AutoReg.Internal | |
(LockStep en a, KnownNat n) => LockStep (Vec n en) (Vec n a) Source # | |
type Unbundled t d (Vec n a) Source # | |
Defined in Clash.Signal.Delayed.Bundle | |
type HasDomain dom (Vec n a) Source # | |
Defined in Clash.Class.HasDomain.HasSpecificDomain | |
type Unbundled t (Vec n a) Source # | |
Defined in Clash.Signal.Bundle | |
type TryDomain t (Vec n a) Source # | |
Defined in Clash.Class.HasDomain.HasSingleDomain | |
type Rep (Vec n a) Source # | |
Defined in Clash.Sized.Vector type Rep (Vec n a) = D1 ('MetaData "Vec" "Clash.Data.Vector" "clash-prelude" 'False) (C1 ('MetaCons "Nil" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Cons" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 a) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Vec (n - 1) a)))) | |
type Index (Vec n a) Source # | |
Defined in Clash.Sized.Vector | |
type IxValue (Vec n a) Source # | |
Defined in Clash.Sized.Vector | |
type BitSize (Vec n a) Source # | |
Defined in Clash.Sized.Vector |
foldl :: (b -> a -> b) -> b -> Vec n a -> b Source #
foldl
, applied to a binary operator, a starting value (typically
the left-identity of the operator), and a vector, reduces the vector
using the binary operator, from left to right:
foldl f z (x1 :> x2 :> ... :> xn :> Nil) == (...((z `f` x1) `f` x2) `f`...) `f` xn foldl f z Nil == z
>>>
foldl (/) 1 (5 :> 4 :> 3 :> 2 :> Nil)
8.333333333333333e-3
"foldl
f z xs
" corresponds to the following circuit layout:
NB: "
produces a linear structure, which has a depth, or
delay, of O(foldl
f z xs"
). Use length
xsfold
if your binary operator f
is
associative, as "
produces a structure with a depth of
O(log_2(fold
f xs"
)).length
xs
foldr :: (a -> b -> b) -> b -> Vec n a -> b Source #
foldr
, applied to a binary operator, a starting value (typically
the right-identity of the operator), and a vector, reduces the vector
using the binary operator, from right to left:
foldr f z (x1 :> ... :> xn1 :> xn :> Nil) == x1 `f` (... (xn1 `f` (xn `f` z))...) foldr r z Nil == z
>>>
foldr (/) 1 (5 :> 4 :> 3 :> 2 :> Nil)
1.875
"foldr
f z xs
" corresponds to the following circuit layout:
NB: "
produces a linear structure, which has a depth, or
delay, of O(foldr
f z xs"
). Use length
xsfold
if your binary operator f
is
associative, as "
produces a structure with a depth of
O(log_2(fold
f xs"
)).length
xs
map :: (a -> b) -> Vec n a -> Vec n b Source #
"map
f xs
" is the vector obtained by applying f to each element
of xs, i.e.,
map f (x1 :> x2 :> ... :> xn :> Nil) == (f x1 :> f x2 :> ... :> f xn :> Nil)
and corresponds to the following circuit layout:
data VCons (a :: Type) (f :: TyFun Nat Type) :: Type Source #
head :: Vec (n + 1) a -> a Source #
Extract the first element of a vector
>>>
head (1:>2:>3:>Nil)
1
>>>
head Nil
<interactive>:... • Couldn't match type ‘1’ with ‘0’ Expected type: Vec (0 + 1) a Actual type: Vec 0 a • In the first argument of ‘head’, namely ‘Nil’ In the expression: head Nil In an equation for ‘it’: it = head Nil
tail :: Vec (n + 1) a -> Vec n a Source #
Extract the elements after the head of a vector
>>>
tail (1:>2:>3:>Nil)
2 :> 3 :> Nil
>>>
tail Nil
<interactive>:... • Couldn't match type ‘1’ with ‘0’ Expected type: Vec (0 + 1) a Actual type: Vec 0 a • In the first argument of ‘tail’, namely ‘Nil’ In the expression: tail Nil In an equation for ‘it’: it = tail Nil
last :: Vec (n + 1) a -> a Source #
Extract the last element of a vector
>>>
last (1:>2:>3:>Nil)
3
>>>
last Nil
<interactive>:... • Couldn't match type ‘1’ with ‘0’ Expected type: Vec (0 + 1) a Actual type: Vec 0 a • In the first argument of ‘last’, namely ‘Nil’ In the expression: last Nil In an equation for ‘it’: it = last Nil
init :: Vec (n + 1) a -> Vec n a Source #
Extract all the elements of a vector except the last element
>>>
init (1:>2:>3:>Nil)
1 :> 2 :> Nil
>>>
init Nil
<interactive>:... • Couldn't match type ‘1’ with ‘0’ Expected type: Vec (0 + 1) a Actual type: Vec 0 a • In the first argument of ‘init’, namely ‘Nil’ In the expression: init Nil In an equation for ‘it’: it = init Nil
:: KnownNat n | |
=> Vec n a | The old vector |
-> Vec m a | The elements to shift in at the head |
-> (Vec n a, Vec m a) | (The new vector, shifted out elements) |
Shift in elements to the head of a vector, bumping out elements at the tail. The result is a tuple containing:
- The new vector
- The shifted out elements
>>>
shiftInAt0 (1 :> 2 :> 3 :> 4 :> Nil) ((-1) :> 0 :> Nil)
(-1 :> 0 :> 1 :> 2 :> Nil,3 :> 4 :> Nil)>>>
shiftInAt0 (1 :> Nil) ((-1) :> 0 :> Nil)
(-1 :> Nil,0 :> 1 :> Nil)
:: KnownNat m | |
=> Vec n a | The old vector |
-> Vec m a | The elements to shift in at the tail |
-> (Vec n a, Vec m a) | (The new vector, shifted out elements) |
Shift in element to the tail of a vector, bumping out elements at the head. The result is a tuple containing:
- The new vector
- The shifted out elements
>>>
shiftInAtN (1 :> 2 :> 3 :> 4 :> Nil) (5 :> 6 :> Nil)
(3 :> 4 :> 5 :> 6 :> Nil,1 :> 2 :> Nil)>>>
shiftInAtN (1 :> Nil) (2 :> 3 :> Nil)
(3 :> Nil,1 :> 2 :> Nil)
(+>>) :: KnownNat n => a -> Vec n a -> Vec n a infixr 4 Source #
Add an element to the head of a vector, and extract all but the last element.
>>>
1 +>> (3:>4:>5:>Nil)
1 :> 3 :> 4 :> Nil>>>
1 +>> Nil
Nil
(<<+) :: Vec n a -> a -> Vec n a infixl 4 Source #
Add an element to the tail of a vector, and extract all but the first element.
>>>
(3:>4:>5:>Nil) <<+ 1
4 :> 5 :> 1 :> Nil>>>
Nil <<+ 1
Nil
:: (Default a, KnownNat m) | |
=> SNat m |
|
-> Vec (m + n) a | The old vector |
-> (Vec (m + n) a, Vec m a) | (The new vector, shifted out elements) |
Shift m elements out from the head of a vector, filling up the tail with
Default
values. The result is a tuple containing:
- The new vector
- The shifted out values
>>>
shiftOutFrom0 d2 ((1 :> 2 :> 3 :> 4 :> 5 :> Nil) :: Vec 5 Integer)
(3 :> 4 :> 5 :> 0 :> 0 :> Nil,1 :> 2 :> Nil)
:: (Default a, KnownNat n) | |
=> SNat m |
|
-> Vec (m + n) a | The old vector |
-> (Vec (m + n) a, Vec m a) | (The new vector, shifted out elements) |
Shift m elements out from the tail of a vector, filling up the head with
Default
values. The result is a tuple containing:
- The new vector
- The shifted out values
>>>
shiftOutFromN d2 ((1 :> 2 :> 3 :> 4 :> 5 :> Nil) :: Vec 5 Integer)
(0 :> 0 :> 1 :> 2 :> 3 :> Nil,4 :> 5 :> Nil)
(++) :: Vec n a -> Vec m a -> Vec (n + m) a infixr 5 Source #
Append two vectors.
>>>
(1:>2:>3:>Nil) ++ (7:>8:>Nil)
1 :> 2 :> 3 :> 7 :> 8 :> Nil
splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a) Source #
Split a vector into two vectors at the given point.
>>>
splitAt (SNat :: SNat 3) (1:>2:>3:>7:>8:>Nil)
(1 :> 2 :> 3 :> Nil,7 :> 8 :> Nil)>>>
splitAt d3 (1:>2:>3:>7:>8:>Nil)
(1 :> 2 :> 3 :> Nil,7 :> 8 :> Nil)
splitAtI :: KnownNat m => Vec (m + n) a -> (Vec m a, Vec n a) Source #
Split a vector into two vectors where the length of the two is determined by the context.
>>>
splitAtI (1:>2:>3:>7:>8:>Nil) :: (Vec 2 Int, Vec 3 Int)
(1 :> 2 :> Nil,3 :> 7 :> 8 :> Nil)
concat :: Vec n (Vec m a) -> Vec (n * m) a Source #
Concatenate a vector of vectors.
>>>
concat ((1:>2:>3:>Nil) :> (4:>5:>6:>Nil) :> (7:>8:>9:>Nil) :> (10:>11:>12:>Nil) :> Nil)
1 :> 2 :> 3 :> 4 :> 5 :> 6 :> 7 :> 8 :> 9 :> 10 :> 11 :> 12 :> Nil
concatMap :: (a -> Vec m b) -> Vec n a -> Vec (n * m) b Source #
Map a function over all the elements of a vector and concatentate the resulting vectors.
>>>
concatMap (replicate d3) (1:>2:>3:>Nil)
1 :> 1 :> 1 :> 2 :> 2 :> 2 :> 3 :> 3 :> 3 :> Nil
unconcat :: KnownNat n => SNat m -> Vec (n * m) a -> Vec n (Vec m a) Source #
Split a vector of (n * m) elements into a vector of "vectors of length m", where the length m is given.
>>>
unconcat d4 (1:>2:>3:>4:>5:>6:>7:>8:>9:>10:>11:>12:>Nil)
(1 :> 2 :> 3 :> 4 :> Nil) :> (5 :> 6 :> 7 :> 8 :> Nil) :> (9 :> 10 :> 11 :> 12 :> Nil) :> Nil
unconcatI :: (KnownNat n, KnownNat m) => Vec (n * m) a -> Vec n (Vec m a) Source #
Split a vector of (n * m) elements into a vector of "vectors of length m", where the length m is determined by the context.
>>>
unconcatI (1:>2:>3:>4:>5:>6:>7:>8:>9:>10:>11:>12:>Nil) :: Vec 2 (Vec 6 Int)
(1 :> 2 :> 3 :> 4 :> 5 :> 6 :> Nil) :> (7 :> 8 :> 9 :> 10 :> 11 :> 12 :> Nil) :> Nil
merge :: KnownNat n => Vec n a -> Vec n a -> Vec (2 * n) a Source #
Merge two vectors, alternating their elements, i.e.,
>>>
merge (1 :> 2 :> 3 :> 4 :> Nil) (5 :> 6 :> 7 :> 8 :> Nil)
1 :> 5 :> 2 :> 6 :> 3 :> 7 :> 4 :> 8 :> Nil
reverse :: Vec n a -> Vec n a Source #
The elements in a vector in reverse order.
>>>
reverse (1:>2:>3:>4:>Nil)
4 :> 3 :> 2 :> 1 :> Nil
imap :: forall n a b. KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b Source #
Apply a function of every element of a vector and its index.
>>>
:t imap (+) (2 :> 2 :> 2 :> 2 :> Nil)
imap (+) (2 :> 2 :> 2 :> 2 :> Nil) :: Vec 4 (Index 4)>>>
imap (+) (2 :> 2 :> 2 :> 2 :> Nil)
2 :> 3 :> *** Exception: X: Clash.Sized.Index: result 4 is out of bounds: [0..3] ...>>>
imap (\i a -> extend (bitCoerce i) + a) (2 :> 2 :> 2 :> 2 :> Nil) :: Vec 4 (Unsigned 8)
2 :> 3 :> 4 :> 5 :> Nil
"imap
f xs
" corresponds to the following circuit layout:
izipWith :: KnownNat n => (Index n -> a -> b -> c) -> Vec n a -> Vec n b -> Vec n c Source #
Zip two vectors with a functions that also takes the elements' indices.
>>>
izipWith (\i a b -> i + a + b) (2 :> 2 :> Nil) (3 :> 3:> Nil)
*** Exception: X: Clash.Sized.Index: result 3 is out of bounds: [0..1] ...>>>
izipWith (\i a b -> extend (bitCoerce i) + a + b) (2 :> 2 :> Nil) (3 :> 3 :> Nil) :: Vec 2 (Unsigned 8)
5 :> 6 :> Nil
"imap
f xs
" corresponds to the following circuit layout:
NB: izipWith
is strict in its second argument, and lazy in its
third. This matters when izipWith
is used in a recursive setting. See
lazyV
for more information.
ifoldr :: KnownNat n => (Index n -> a -> b -> b) -> b -> Vec n a -> b Source #
Right fold (function applied to each element and its index)
>>>
let findLeftmost x xs = ifoldr (\i a b -> if a == x then Just i else b) Nothing xs
>>>
findLeftmost 3 (1:>3:>2:>4:>3:>5:>6:>Nil)
Just 1>>>
findLeftmost 8 (1:>3:>2:>4:>3:>5:>6:>Nil)
Nothing
"ifoldr
f z xs
" corresponds to the following circuit layout:
ifoldl :: KnownNat n => (a -> Index n -> b -> a) -> a -> Vec n b -> a Source #
Left fold (function applied to each element and its index)
>>>
let findRightmost x xs = ifoldl (\a i b -> if b == x then Just i else a) Nothing xs
>>>
findRightmost 3 (1:>3:>2:>4:>3:>5:>6:>Nil)
Just 4>>>
findRightmost 8 (1:>3:>2:>4:>3:>5:>6:>Nil)
Nothing
"ifoldl
f z xs
" corresponds to the following circuit layout:
indices :: KnownNat n => SNat n -> Vec n (Index n) Source #
Generate a vector of indices.
>>>
indices d4
0 :> 1 :> 2 :> 3 :> Nil
indicesI :: KnownNat n => Vec n (Index n) Source #
Generate a vector of indices, where the length of the vector is determined by the context.
>>>
indicesI :: Vec 4 (Index 4)
0 :> 1 :> 2 :> 3 :> Nil
zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c Source #
zipWith
generalizes zip
by zipping with the function given
as the first argument, instead of a tupling function.
For example, "zipWith
(+)
" applied to two vectors produces the
vector of corresponding sums.
zipWith f (x1 :> x2 :> ... xn :> Nil) (y1 :> y2 :> ... :> yn :> Nil) == (f x1 y1 :> f x2 y2 :> ... :> f xn yn :> Nil)
"zipWith
f xs ys
" corresponds to the following circuit layout:
NB: zipWith
is strict in its second argument, and lazy in its
third. This matters when zipWith
is used in a recursive setting. See
lazyV
for more information.
zipWith3 :: (a -> b -> c -> d) -> Vec n a -> Vec n b -> Vec n c -> Vec n d Source #
zipWith3
generalizes zip3
by zipping with the function given
as the first argument, instead of a tupling function.
zipWith3 f (x1 :> x2 :> ... xn :> Nil) (y1 :> y2 :> ... :> yn :> Nil) (z1 :> z2 :> ... :> zn :> Nil) == (f x1 y1 z1 :> f x2 y2 z2 :> ... :> f xn yn zn :> Nil)
"zipWith3
f xs ys zs
" corresponds to the following circuit layout:
NB: zipWith3
is strict in its second argument, and lazy in its
third and fourth. This matters when zipWith3
is used in a recursive setting.
See lazyV
for more information.
zipWith5 :: (a -> b -> c -> d -> e -> f) -> Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f Source #
zipWith6 :: (a -> b -> c -> d -> e -> f -> g) -> Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f -> Vec n g Source #
zipWith7 :: (a -> b -> c -> d -> e -> f -> g -> h) -> Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f -> Vec n g -> Vec n h Source #
foldr1 :: (a -> a -> a) -> Vec (n + 1) a -> a Source #
foldr1
is a variant of foldr
that has no starting value argument,
and thus must be applied to non-empty vectors.
foldr1 f (x1 :> ... :> xn2 :> xn1 :> xn :> Nil) == x1 `f` (... (xn2 `f` (xn1 `f` xn))...) foldr1 f (x1 :> Nil) == x1 foldr1 f Nil == TYPE ERROR
>>>
foldr1 (/) (5 :> 4 :> 3 :> 2 :> 1 :> Nil)
1.875
"foldr1
f xs
" corresponds to the following circuit layout:
NB: "
produces a linear structure, which has a depth,
or delay, of O(foldr1
f z xs"
). Use length
xsfold
if your binary operator f
is
associative, as "
produces a structure with a depth of
O(log_2(fold
f xs"
)).length
xs
foldl1 :: (a -> a -> a) -> Vec (n + 1) a -> a Source #
foldl1
is a variant of foldl
that has no starting value argument,
and thus must be applied to non-empty vectors.
foldl1 f (x1 :> x2 :> x3 :> ... :> xn :> Nil) == (...((x1 `f` x2) `f` x3) `f`...) `f` xn foldl1 f (x1 :> Nil) == x1 foldl1 f Nil == TYPE ERROR
>>>
foldl1 (/) (1 :> 5 :> 4 :> 3 :> 2 :> Nil)
8.333333333333333e-3
"foldl1
f xs
" corresponds to the following circuit layout:
NB: "
produces a linear structure, which has a depth,
or delay, of O(foldl1
f z xs"
). Use length
xsfold
if your binary operator f
is
associative, as "
produces a structure with a depth of
O(log_2(fold
f xs"
)).length
xs
fold :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> a Source #
fold
is a variant of foldr1
and foldl1
, but instead of reducing from
right to left, or left to right, it reduces a vector using a tree-like
structure. The depth, or delay, of the structure produced by
"
", is hence fold
f xsO(log_2(
, and not
length
xs))O(
.length
xs)
NB: The binary operator "f
" in "
" must be associative.fold
f xs
fold f (x1 :> x2 :> ... :> xn1 :> xn :> Nil) == ((x1 `f` x2) `f` ...) `f` (... `f` (xn1 `f` xn)) fold f (x1 :> Nil) == x1 fold f Nil == TYPE ERROR
>>>
fold (+) (5 :> 4 :> 3 :> 2 :> 1 :> Nil)
15
"fold
f xs
" corresponds to the following circuit layout:
scanl :: (b -> a -> b) -> b -> Vec n a -> Vec (n + 1) b Source #
scanl
is similar to foldl
, but returns a vector of successive reduced
values from the left:
scanl f z (x1 :> x2 :> ... :> Nil) == z :> (z `f` x1) :> ((z `f` x1) `f` x2) :> ... :> Nil
>>>
scanl (+) 0 (5 :> 4 :> 3 :> 2 :> Nil)
0 :> 5 :> 9 :> 12 :> 14 :> Nil
"scanl
f z xs
" corresponds to the following circuit layout:
NB:
last (scanl f z xs) == foldl f z xs
- For a different trade-off between circuit size and logic depth for associative operators, see Clash.Sized.RTree
scanr :: (a -> b -> b) -> b -> Vec n a -> Vec (n + 1) b Source #
scanr
is similar to foldr
, but returns a vector of successive reduced
values from the right:
scanr f z (... :> xn1 :> xn :> Nil) == ... :> (xn1 `f` (xn `f` z)) :> (xn `f` z) :> z :> Nil
>>>
scanr (+) 0 (5 :> 4 :> 3 :> 2 :> Nil)
14 :> 9 :> 5 :> 2 :> 0 :> Nil
"scanr
f z xs
" corresponds to the following circuit layout:
NB:
head (scanr f z xs) == foldr f z xs
- For a different trade-off between circuit size and logic depth for associative operators, see Clash.Sized.RTree
mapAccumL :: (acc -> x -> (acc, y)) -> acc -> Vec n x -> (acc, Vec n y) Source #
The mapAccumL
function behaves like a combination of map
and foldl
;
it applies a function to each element of a vector, passing an accumulating
parameter from left to right, and returning a final value of this accumulator
together with the new vector.
>>>
mapAccumL (\acc x -> (acc + x,acc + 1)) 0 (1 :> 2 :> 3 :> 4 :> Nil)
(10,1 :> 2 :> 4 :> 7 :> Nil)
"mapAccumL
f acc xs
" corresponds to the following circuit layout:
mapAccumR :: (acc -> x -> (acc, y)) -> acc -> Vec n x -> (acc, Vec n y) Source #
The mapAccumR
function behaves like a combination of map
and foldr
;
it applies a function to each element of a vector, passing an accumulating
parameter from right to left, and returning a final value of this accumulator
together with the new vector.
>>>
mapAccumR (\acc x -> (acc + x,acc + 1)) 0 (1 :> 2 :> 3 :> 4 :> Nil)
(10,10 :> 8 :> 5 :> 1 :> Nil)
"mapAccumR
f acc xs
" corresponds to the following circuit layout:
zip :: Vec n a -> Vec n b -> Vec n (a, b) Source #
zip
takes two vectors and returns a vector of corresponding pairs.
>>>
zip (1:>2:>3:>4:>Nil) (4:>3:>2:>1:>Nil)
(1,4) :> (2,3) :> (3,2) :> (4,1) :> Nil
zip3 :: Vec n a -> Vec n b -> Vec n c -> Vec n (a, b, c) Source #
zip3
takes three vectors and returns a vector of corresponding triplets.
>>>
zip3 (1:>2:>3:>4:>Nil) (4:>3:>2:>1:>Nil) (5:>6:>7:>8:>Nil)
(1,4,5) :> (2,3,6) :> (3,2,7) :> (4,1,8) :> Nil
zip6 :: Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f -> Vec n (a, b, c, d, e, f) Source #
zip7 :: Vec n a -> Vec n b -> Vec n c -> Vec n d -> Vec n e -> Vec n f -> Vec n g -> Vec n (a, b, c, d, e, f, g) Source #
unzip :: Vec n (a, b) -> (Vec n a, Vec n b) Source #
unzip
transforms a vector of pairs into a vector of first components
and a vector of second components.
>>>
unzip ((1,4):>(2,3):>(3,2):>(4,1):>Nil)
(1 :> 2 :> 3 :> 4 :> Nil,4 :> 3 :> 2 :> 1 :> Nil)
unzip3 :: Vec n (a, b, c) -> (Vec n a, Vec n b, Vec n c) Source #
unzip3
transforms a vector of triplets into a vector of first components,
a vector of second components, and a vector of third components.
>>>
unzip3 ((1,4,5):>(2,3,6):>(3,2,7):>(4,1,8):>Nil)
(1 :> 2 :> 3 :> 4 :> Nil,4 :> 3 :> 2 :> 1 :> Nil,5 :> 6 :> 7 :> 8 :> Nil)
unzip6 :: Vec n (a, b, c, d, e, f) -> (Vec n a, Vec n b, Vec n c, Vec n d, Vec n e, Vec n f) Source #
unzip7 :: Vec n (a, b, c, d, e, f, g) -> (Vec n a, Vec n b, Vec n c, Vec n d, Vec n e, Vec n f, Vec n g) Source #
(!!) :: (KnownNat n, Enum i) => Vec n a -> i -> a Source #
"xs
!!
n
" returns the n'th element of xs.
NB: vector elements have an ASCENDING subscript starting from 0 and
ending at
.length
- 1
>>>
(1:>2:>3:>4:>5:>Nil) !! 4
5>>>
(1:>2:>3:>4:>5:>Nil) !! (length (1:>2:>3:>4:>5:>Nil) - 1)
5>>>
(1:>2:>3:>4:>5:>Nil) !! 1
2>>>
(1:>2:>3:>4:>5:>Nil) !! 14
*** Exception: Clash.Sized.Vector.(!!): index 14 is larger than maximum index 4 ...
replace :: (KnownNat n, Enum i) => i -> a -> Vec n a -> Vec n a Source #
"replace
n a xs
" returns the vector xs where the n'th element is
replaced by a.
NB: vector elements have an ASCENDING subscript starting from 0 and
ending at
.length
- 1
>>>
replace 3 7 (1:>2:>3:>4:>5:>Nil)
1 :> 2 :> 3 :> 7 :> 5 :> Nil>>>
replace 0 7 (1:>2:>3:>4:>5:>Nil)
7 :> 2 :> 3 :> 4 :> 5 :> Nil>>>
replace 9 7 (1:>2:>3:>4:>5:>Nil)
1 :> 2 :> 3 :> 4 :> 5 :> *** Exception: Clash.Sized.Vector.replace: index 9 is larger than maximum index 4 ...
take :: SNat m -> Vec (m + n) a -> Vec m a Source #
"take
n xs
" returns the n-length prefix of xs.
>>>
take (SNat :: SNat 3) (1:>2:>3:>4:>5:>Nil)
1 :> 2 :> 3 :> Nil>>>
take d3 (1:>2:>3:>4:>5:>Nil)
1 :> 2 :> 3 :> Nil>>>
take d0 (1:>2:>Nil)
Nil
>>>
take d4 (1:>2:>Nil)
<interactive>:... • Couldn't match type ‘4 + n0’ with ‘2’ Expected type: Vec (4 + n0) a Actual type: Vec (1 + 1) a The type variable ‘n0’ is ambiguous • In the second argument of ‘take’, namely ‘(1 :> 2 :> Nil)’ In the expression: take d4 (1 :> 2 :> Nil) In an equation for ‘it’: it = take d4 (1 :> 2 :> Nil)
takeI :: KnownNat m => Vec (m + n) a -> Vec m a Source #
"takeI
xs
" returns the prefix of xs as demanded by the context.
>>>
takeI (1:>2:>3:>4:>5:>Nil) :: Vec 2 Int
1 :> 2 :> Nil
drop :: SNat m -> Vec (m + n) a -> Vec n a Source #
"drop
n xs
" returns the suffix of xs after the first n elements.
>>>
drop (SNat :: SNat 3) (1:>2:>3:>4:>5:>Nil)
4 :> 5 :> Nil>>>
drop d3 (1:>2:>3:>4:>5:>Nil)
4 :> 5 :> Nil>>>
drop d0 (1:>2:>Nil)
1 :> 2 :> Nil>>>
drop d4 (1:>2:>Nil)
<interactive>:...: error: • Couldn't match...type ‘4 + n0... The type variable ‘n0’ is ambiguous • In the first argument of ‘print’, namely ‘it’ In a stmt of an interactive GHCi command: print it
dropI :: KnownNat m => Vec (m + n) a -> Vec n a Source #
"dropI
xs
" returns the suffix of xs as demanded by the context.
>>>
dropI (1:>2:>3:>4:>5:>Nil) :: Vec 2 Int
4 :> 5 :> Nil
select :: CmpNat (i + s) (s * n) ~ 'GT => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a Source #
"select
f s n xs
" selects n elements with step-size s and
offset f
from xs.
>>>
select (SNat :: SNat 1) (SNat :: SNat 2) (SNat :: SNat 3) (1:>2:>3:>4:>5:>6:>7:>8:>Nil)
2 :> 4 :> 6 :> Nil>>>
select d1 d2 d3 (1:>2:>3:>4:>5:>6:>7:>8:>Nil)
2 :> 4 :> 6 :> Nil
selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a Source #
"selectI
f s xs
" selects as many elements as demanded by the context
with step-size s and offset f from xs.
>>>
selectI d1 d2 (1:>2:>3:>4:>5:>6:>7:>8:>Nil) :: Vec 2 Int
2 :> 4 :> Nil
replicate :: SNat n -> a -> Vec n a Source #
"replicate
n a
" returns a vector that has n copies of a.
>>>
replicate (SNat :: SNat 3) 6
6 :> 6 :> 6 :> Nil>>>
replicate d3 6
6 :> 6 :> 6 :> Nil
repeat :: KnownNat n => a -> Vec n a Source #
"repeat
a
" creates a vector with as many copies of a as demanded
by the context.
>>>
repeat 6 :: Vec 5 Int
6 :> 6 :> 6 :> 6 :> 6 :> Nil
iterate :: SNat n -> (a -> a) -> a -> Vec n a Source #
"iterate
n f x
" returns a vector starting with x followed by
n repeated applications of f to x.
iterate (SNat :: SNat 4) f x == (x :> f x :> f (f x) :> f (f (f x)) :> Nil) iterate d4 f x == (x :> f x :> f (f x) :> f (f (f x)) :> Nil)
>>>
iterate d4 (+1) 1
1 :> 2 :> 3 :> 4 :> Nil
"iterate
n f z
" corresponds to the following circuit layout:
unfoldr :: SNat n -> (s -> (a, s)) -> s -> Vec n a Source #
"unfoldr
n f s
" builds a vector of length n
from a seed value s
,
where every element a
is created by successive calls of f
on s
. Unlike
unfoldr
from Data.List the generating function f
cannot
dictate the length of the resulting vector, it must be statically known.
a simple use of unfoldr
:
>>>
unfoldr d10 (\s -> (s,s-1)) 10
10 :> 9 :> 8 :> 7 :> 6 :> 5 :> 4 :> 3 :> 2 :> 1 :> Nil
unfoldrI :: KnownNat n => (s -> (a, s)) -> s -> Vec n a Source #
"unfoldrI
f s
" builds a vector from a seed value s
, where every
element a
is created by successive calls of f
on s
; the length of the
vector is inferred from the context. Unlike unfoldr
from
Data.List the generating function f
cannot dictate the length of the
resulting vector, it must be statically known.
a simple use of unfoldrI
:
>>>
unfoldrI (\s -> (s,s-1)) 10 :: Vec 10 Int
10 :> 9 :> 8 :> 7 :> 6 :> 5 :> 4 :> 3 :> 2 :> 1 :> Nil
generate :: SNat n -> (a -> a) -> a -> Vec n a Source #
"generate
n f x
" returns a vector with n
repeated applications of
f
to x
.
generate (SNat :: SNat 4) f x == (f x :> f (f x) :> f (f (f x)) :> f (f (f (f x))) :> Nil) generate d4 f x == (f x :> f (f x) :> f (f (f x)) :> f (f (f (f x))) :> Nil)
>>>
generate d4 (+1) 1
2 :> 3 :> 4 :> 5 :> Nil
"generate
n f z
" corresponds to the following circuit layout:
transpose :: KnownNat n => Vec m (Vec n a) -> Vec n (Vec m a) Source #
Transpose a matrix: go from row-major to column-major
>>>
let xss = (1:>2:>Nil):>(3:>4:>Nil):>(5:>6:>Nil):>Nil
>>>
xss
(1 :> 2 :> Nil) :> (3 :> 4 :> Nil) :> (5 :> 6 :> Nil) :> Nil>>>
transpose xss
(1 :> 3 :> 5 :> Nil) :> (2 :> 4 :> 6 :> Nil) :> Nil
:: KnownNat n | |
=> SNat (stX + 1) | Windows length stX, at least size 1 |
-> (Vec (stX + 1) a -> b) | The stencil (function) |
-> Vec ((stX + n) + 1) a | |
-> Vec (n + 1) b |
1-dimensional stencil computations
"stencil1d
stX f xs
", where xs has stX + n elements, applies the
stencil computation f on: n + 1 overlapping (1D) windows of length stX,
drawn from xs. The resulting vector has n + 1 elements.
>>>
let xs = (1:>2:>3:>4:>5:>6:>Nil)
>>>
:t xs
xs :: Num a => Vec 6 a>>>
:t stencil1d d2 sum xs
stencil1d d2 sum xs :: Num b => Vec 5 b>>>
stencil1d d2 sum xs
3 :> 5 :> 7 :> 9 :> 11 :> Nil
:: (KnownNat n, KnownNat m) | |
=> SNat (stY + 1) | Window hight stY, at least size 1 |
-> SNat (stX + 1) | Window width stX, at least size 1 |
-> (Vec (stY + 1) (Vec (stX + 1) a) -> b) | The stencil (function) |
-> Vec ((stY + m) + 1) (Vec ((stX + n) + 1) a) | |
-> Vec (m + 1) (Vec (n + 1) b) |
2-dimensional stencil computations
"stencil2d
stY stX f xss
", where xss is a matrix of stY + m rows
of stX + n elements, applies the stencil computation f on:
(m + 1) * (n + 1) overlapping (2D) windows of stY rows of stX elements,
drawn from xss. The result matrix has m + 1 rows of n + 1 elements.
>>>
let xss = ((1:>2:>3:>4:>Nil):>(5:>6:>7:>8:>Nil):>(9:>10:>11:>12:>Nil):>(13:>14:>15:>16:>Nil):>Nil)
>>>
:t xss
xss :: Num a => Vec 4 (Vec 4 a)>>>
:t stencil2d d2 d2 (sum . map sum) xss
stencil2d d2 d2 (sum . map sum) xss :: Num b => Vec 3 (Vec 3 b)>>>
stencil2d d2 d2 (sum . map sum) xss
(14 :> 18 :> 22 :> Nil) :> (30 :> 34 :> 38 :> Nil) :> (46 :> 50 :> 54 :> Nil) :> Nil
:: KnownNat n | |
=> SNat (stX + 1) | Length of the window, at least size 1 |
-> Vec ((stX + n) + 1) a | |
-> Vec (n + 1) (Vec (stX + 1) a) |
"windows1d
stX xs
", where the vector xs has stX + n elements,
returns a vector of n + 1 overlapping (1D) windows of xs of length stX.
>>>
let xs = (1:>2:>3:>4:>5:>6:>Nil)
>>>
:t xs
xs :: Num a => Vec 6 a>>>
:t windows1d d2 xs
windows1d d2 xs :: Num a => Vec 5 (Vec 2 a)>>>
windows1d d2 xs
(1 :> 2 :> Nil) :> (2 :> 3 :> Nil) :> (3 :> 4 :> Nil) :> (4 :> 5 :> Nil) :> (5 :> 6 :> Nil) :> Nil
:: (KnownNat n, KnownNat m) | |
=> SNat (stY + 1) | Window hight stY, at least size 1 |
-> SNat (stX + 1) | Window width stX, at least size 1 |
-> Vec ((stY + m) + 1) (Vec ((stX + n) + 1) a) | |
-> Vec (m + 1) (Vec (n + 1) (Vec (stY + 1) (Vec (stX + 1) a))) |
"windows2d
stY stX xss
", where matrix xss has stY + m rows of
stX + n, returns a matrix of m+1 rows of n+1 elements. The elements
of this new matrix are the overlapping (2D) windows of xss, where every
window has stY rows of stX elements.
>>>
let xss = ((1:>2:>3:>4:>Nil):>(5:>6:>7:>8:>Nil):>(9:>10:>11:>12:>Nil):>(13:>14:>15:>16:>Nil):>Nil)
>>>
:t xss
xss :: Num a => Vec 4 (Vec 4 a)>>>
:t windows2d d2 d2 xss
windows2d d2 d2 xss :: Num a => Vec 3 (Vec 3 (Vec 2 (Vec 2 a)))>>>
windows2d d2 d2 xss
(((1 :> 2 :> Nil) :> (5 :> 6 :> Nil) :> Nil) :> ((2 :> 3 :> Nil) :> (6 :> 7 :> Nil) :> Nil) :> ((3 :> 4 :> Nil) :> (7 :> 8 :> Nil) :> Nil) :> Nil) :> (((5 :> 6 :> Nil) :> (9 :> 10 :> Nil) :> Nil) :> ((6 :> 7 :> Nil) :> (10 :> 11 :> Nil) :> Nil) :> ((7 :> 8 :> Nil) :> (11 :> 12 :> Nil) :> Nil) :> Nil) :> (((9 :> 10 :> Nil) :> (13 :> 14 :> Nil) :> Nil) :> ((10 :> 11 :> Nil) :> (14 :> 15 :> Nil) :> Nil) :> ((11 :> 12 :> Nil) :> (15 :> 16 :> Nil) :> Nil) :> Nil) :> Nil
:: (Enum i, KnownNat n, KnownNat m) | |
=> (a -> a -> a) | Combination function, f |
-> Vec n a | Default values, def |
-> Vec m i | Index mapping, is |
-> Vec (m + k) a | Vector to be permuted, xs |
-> Vec n a |
Forward permutation specified by an index mapping, ix. The result vector is initialized by the given defaults, def, and an further values that are permuted into the result are added to the current value using the given combination function, f.
The combination function must be associative and commutative.
Backwards permutation specified by an index mapping, is, from the destination vector specifying which element of the source vector xs to read.
"backpermute
xs is
" is equivalent to "map
(xs
".!!
) is
For example:
>>>
let input = 1:>9:>6:>4:>4:>2:>0:>1:>2:>Nil
>>>
let from = 1:>3:>7:>2:>5:>3:>Nil
>>>
backpermute input from
9 :> 4 :> 1 :> 6 :> 2 :> 4 :> Nil
:: (Enum i, KnownNat n, KnownNat m) | |
=> Vec n a | Default values, def |
-> Vec m i | Index mapping, is |
-> Vec (m + k) a | Vector to be scattered, xs |
-> Vec n a |
Copy elements from the source vector, xs, to the destination vector according to an index mapping is. This is a forward permute operation where a to vector encodes an input to output index mapping. Output elements for indices that are not mapped assume the value in the default vector def.
For example:
>>>
let defVec = 0:>0:>0:>0:>0:>0:>0:>0:>0:>Nil
>>>
let to = 1:>3:>7:>2:>5:>8:>Nil
>>>
let input = 1:>9:>6:>4:>4:>2:>5:>Nil
>>>
scatter defVec to input
0 :> 1 :> 4 :> 9 :> 0 :> 4 :> 0 :> 6 :> 2 :> Nil
NB: If the same index appears in the index mapping more than once, the latest mapping is chosen.
Backwards permutation specified by an index mapping, is, from the destination vector specifying which element of the source vector xs to read.
"gather
xs is
" is equivalent to "map
(xs
".!!
) is
For example:
>>>
let input = 1:>9:>6:>4:>4:>2:>0:>1:>2:>Nil
>>>
let from = 1:>3:>7:>2:>5:>3:>Nil
>>>
gather input from
9 :> 4 :> 1 :> 6 :> 2 :> 4 :> Nil
"interleave
d xs
" creates a vector:
<x_0,x_d,x_(2d),...,x_1,x_(d+1),x_(2d+1),...,x_(d-1),x_(2d-1),x_(3d-1)>
>>>
let xs = 1 :> 2 :> 3 :> 4 :> 5 :> 6 :> 7 :> 8 :> 9 :> Nil
>>>
interleave d3 xs
1 :> 4 :> 7 :> 2 :> 5 :> 8 :> 3 :> 6 :> 9 :> Nil
rotateLeft :: (Enum i, KnownNat n) => Vec n a -> i -> Vec n a Source #
Dynamically rotate a Vec
tor to the left:
>>>
let xs = 1 :> 2 :> 3 :> 4 :> Nil
>>>
rotateLeft xs 1
2 :> 3 :> 4 :> 1 :> Nil>>>
rotateLeft xs 2
3 :> 4 :> 1 :> 2 :> Nil>>>
rotateLeft xs (-1)
4 :> 1 :> 2 :> 3 :> Nil
NB: use rotateLeftS
if you want to rotate left by a static amount.
rotateRight :: (Enum i, KnownNat n) => Vec n a -> i -> Vec n a Source #
Dynamically rotate a Vec
tor to the right:
>>>
let xs = 1 :> 2 :> 3 :> 4 :> Nil
>>>
rotateRight xs 1
4 :> 1 :> 2 :> 3 :> Nil>>>
rotateRight xs 2
3 :> 4 :> 1 :> 2 :> Nil>>>
rotateRight xs (-1)
2 :> 3 :> 4 :> 1 :> Nil
NB: use rotateRightS
if you want to rotate right by a static amount.
rotateLeftS :: KnownNat n => Vec n a -> SNat d -> Vec n a Source #
Statically rotate a Vec
tor to the left:
>>>
let xs = 1 :> 2 :> 3 :> 4 :> Nil
>>>
rotateLeftS xs d1
2 :> 3 :> 4 :> 1 :> Nil
NB: use rotateLeft
if you want to rotate left by a dynamic amount.
rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a Source #
Statically rotate a Vec
tor to the right:
>>>
let xs = 1 :> 2 :> 3 :> 4 :> Nil
>>>
rotateRightS xs d1
4 :> 1 :> 2 :> 3 :> Nil
NB: use rotateRight
if you want to rotate right by a dynamic amount.
toList :: Vec n a -> [a] Source #
Convert a vector to a list.
>>>
toList (1:>2:>3:>Nil)
[1,2,3]
NB: this function is not synthesizable
listToVecTH :: Lift a => [a] -> ExpQ Source #
Create a vector literal from a list literal.
$(listToVecTH [1::Signed 8,2,3,4,5]) == (8:>2:>3:>4:>5:>Nil) :: Vec 5 (Signed 8)
>>>
[1 :: Signed 8,2,3,4,5]
[1,2,3,4,5]>>>
$(listToVecTH [1::Signed 8,2,3,4,5])
1 :> 2 :> 3 :> 4 :> 5 :> Nil
lazyV :: KnownNat n => Vec n a -> Vec n a Source #
What you should use when your vector functions are too strict in their arguments.
doctests setup
>>>
let compareSwapL a b = if a < b then (a,b) else (b,a)
>>>
:{
let sortVL :: (Ord a, KnownNat (n + 1)) => Vec ((n + 1) + 1) a -> Vec ((n + 1) + 1) a sortVL xs = map fst sorted :< (snd (last sorted)) where lefts = head xs :> map snd (init sorted) rights = tail xs sorted = zipWith compareSwapL (lazyV lefts) rights :}
>>>
:{
let sortV_flip xs = map fst sorted :< (snd (last sorted)) where lefts = head xs :> map snd (init sorted) rights = tail xs sorted = zipWith (flip compareSwapL) rights lefts :}
Example usage
For example:
-- Bubble sort for 1 iteration sortV xs =map
fst sorted:<
(snd (last
sorted)) where lefts =head
xs :>map
snd (init
sorted) rights =tail
xs sorted =zipWith
compareSwapL lefts rights -- Compare and swap compareSwapL a b = if a < b then (a,b) else (b,a)
Will not terminate because zipWith
is too strict in its second argument.
In this case, adding lazyV
on zipWith
s second argument:
sortVL xs =map
fst sorted:<
(snd (last
sorted)) where lefts =head
xs :> map snd (init
sorted) rights =tail
xs sorted =zipWith
compareSwapL (lazyV
lefts) rights
Results in a successful computation:
>>>
sortVL (4 :> 1 :> 2 :> 3 :> Nil)
1 :> 2 :> 3 :> 4 :> Nil
NB: There is also a solution using flip
, but it slightly obfuscates the
meaning of the code:
sortV_flip xs =map
fst sorted:<
(snd (last
sorted)) where lefts =head
xs :>map
snd (init
sorted) rights =tail
xs sorted =zipWith
(flip
compareSwapL) rights lefts
>>>
sortV_flip (4 :> 1 :> 2 :> 3 :> Nil)
1 :> 2 :> 3 :> 4 :> Nil
:: forall p k a. KnownNat k | |
=> Proxy (p :: TyFun Nat Type -> Type) | The motive |
-> (forall l. SNat l -> a -> (p @@ l) -> p @@ (l + 1)) | Function to fold. NB: The |
-> (p @@ 0) | Initial element |
-> Vec k a | Vector to fold over |
-> p @@ k |
A dependently typed fold.
doctests setup
>>>
:seti -fplugin GHC.TypeLits.Normalise
>>>
import Data.Singletons (Apply, Proxy (..), TyFun)
>>>
data Append (m :: Nat) (a :: Type) (f :: TyFun Nat Type) :: Type
>>>
type instance Apply (Append m a) l = Vec (l + m) a
>>>
let append' xs ys = dfold (Proxy :: Proxy (Append m a)) (const (:>)) ys xs
Example usage
Using lists, we can define append (a.k.a. Data.List.
++
) in
terms of Data.List.
foldr
:
>>>
import qualified Data.List
>>>
let append xs ys = Data.List.foldr (:) ys xs
>>>
append [1,2] [3,4]
[1,2,3,4]
However, when we try to do the same for Vec
, by defining append' in terms
of Clash.Sized.Vector.
foldr
:
append' xs ys = foldr
(:>) ys xs
we get a type error:
>>> let append' xs ys = foldr (:>) ys xs <interactive>:... • Occurs check: cannot construct the infinite type: ... ~ ... + 1 Expected type: a -> Vec ... a -> Vec ... a Actual type: a -> Vec ... a -> Vec (... + 1) a • In the first argument of ‘foldr’, namely ‘(:>)’ In the expression: foldr (:>) ys xs In an equation for ‘append'’: append' xs ys = foldr (:>) ys xs • Relevant bindings include ys :: Vec ... a (bound at ...) append' :: Vec n a -> Vec ... a -> Vec ... a (bound at ...)
The reason is that the type of foldr
is:
>>>
:t foldr
foldr :: (a -> b -> b) -> b -> Vec n a -> b
While the type of (:>
) is:
>>>
:t (:>)
(:>) :: a -> Vec n a -> Vec (n + 1) a
We thus need a fold
function that can handle the growing vector type:
dfold
. Compared to foldr
, dfold
takes an extra parameter, called the
motive, that allows the folded function to have an argument and result type
that depends on the current length of the vector. Using dfold
, we can
now correctly define append':
import Data.Singletons import Data.Proxy data Append (m :: Nat) (a :: Type) (f ::TyFun
Nat Type) :: Type type instanceApply
(Append m a) l =Vec
(l + m) a append' xs ys =dfold
(Proxy :: Proxy (Append m a)) (const (:>
)) ys xs
We now see that append' has the appropriate type:
>>>
:t append'
append' :: KnownNat k => Vec k a -> Vec m a -> Vec (k + m) a
And that it works:
>>>
append' (1 :> 2 :> Nil) (3 :> 4 :> Nil)
1 :> 2 :> 3 :> 4 :> Nil
NB: "
" creates a linear structure, which has a depth,
or delay, of O(dfold
m f z xs
). Look at length
xsdtfold
for a dependently typed
fold that produces a structure with a depth of O(log_2(
)).length
xs
:: forall p k a. KnownNat k | |
=> Proxy (p :: TyFun Nat Type -> Type) | The motive |
-> (a -> p @@ 0) | Function to apply to every element |
-> (forall l. SNat l -> (p @@ l) -> (p @@ l) -> p @@ (l + 1)) | Function to combine results. NB: The |
-> Vec (2 ^ k) a | Vector to fold over. NB: Must have a length that is a power of 2. |
-> p @@ k |
A combination of dfold
and fold
: a dependently typed fold that
reduces a vector in a tree-like structure.
doctests setup
>>>
:seti -XUndecidableInstances
>>>
import Data.Singletons (Apply, Proxy (..), TyFun)
>>>
data IIndex (f :: TyFun Nat Type) :: Type
>>>
type instance Apply IIndex l = Index ((2^l)+1)
>>>
:{
let populationCount' :: (KnownNat k, KnownNat (2^k)) => BitVector (2^k) -> Index ((2^k)+1) populationCount' bv = dtfold (Proxy @IIndex) fromIntegral (\_ x y -> add x y) (bv2v bv) :}
Example usage
As an example of when you might want to use dtfold
we will build a
population counter: a circuit that counts the number of bits set to '1' in
a BitVector
. Given a vector of n bits, we only need we need a data type
that can represent the number n: Index
(n+1)
. Index
k
has a range
of [0 .. k-1]
(using ceil(log2(k))
bits), hence we need Index
n+1
.
As an initial attempt we will use sum
, because it gives a nice (log2(n)
)
tree-structure of adders:
populationCount :: (KnownNat (n+1), KnownNat (n+2)) =>BitVector
(n+1) ->Index
(n+2) populationCount = sum . map fromIntegral .bv2v
The "problem" with this description is that all adders have the same bit-width, i.e. all adders are of the type:
(+) ::Index
(n+2) ->Index
(n+2) ->Index
(n+2).
This is a "problem" because we could have a more efficient structure: one where each layer of adders is precisely wide enough to count the number of bits at that layer. That is, at height d we want the adder to be of type:
Index
((2^d)+1) ->Index
((2^d)+1) ->Index
((2^(d+1))+1)
We have such an adder in the form of the add
function, as
defined in the instance ExtendingNum
instance of Index
.
However, we cannot simply use fold
to create a tree-structure of
add
es:
>>>
:{
let populationCount' :: (KnownNat (n+1), KnownNat (n+2)) => BitVector (n+1) -> Index (n+2) populationCount' = fold add . map fromIntegral . bv2v :} <interactive>:... • Couldn't match type ‘((n + 2) + (n + 2)) - 1’ with ‘n + 2’ Expected type: Index (n + 2) -> Index (n + 2) -> Index (n + 2) Actual type: Index (n + 2) -> Index (n + 2) -> AResult (Index (n + 2)) (Index (n + 2)) • In the first argument of ‘fold’, namely ‘add’ In the first argument of ‘(.)’, namely ‘fold add’ In the expression: fold add . map fromIntegral . bv2v • Relevant bindings include populationCount' :: BitVector (n + 1) -> Index (n + 2) (bound at ...)
because fold
expects a function of type "a -> a -> a
", i.e. a function
where the arguments and result all have exactly the same type.
In order to accommodate the type of our add
, where the
result is larger than the arguments, we must use a dependently typed fold in
the form of dtfold
:
{-# LANGUAGE UndecidableInstances #-} import Data.Singletons import Data.Proxy data IIndex (f ::TyFun
Nat Type) :: Type type instanceApply
IIndex l =Index
((2^l)+1) populationCount' :: (KnownNat k, KnownNat (2^k)) => BitVector (2^k) -> Index ((2^k)+1) populationCount' bv =dtfold
(Proxy @IIndex) fromIntegral (\_ x y ->add
x y) (bv2v
bv)
And we can test that it works:
>>>
:t populationCount' (7 :: BitVector 16)
populationCount' (7 :: BitVector 16) :: Index 17>>>
populationCount' (7 :: BitVector 16)
3
Some final remarks:
- By using
dtfold
instead offold
, we had to restrict ourBitVector
argument to have bit-width that is a power of 2. - Even though our original populationCount function specified a structure where all adders had the same width. Most VHDL/(System)Verilog synthesis tools will create a more efficient circuit, i.e. one where the adders have an increasing bit-width for every layer, from the VHDL/(System)Verilog produced by the Clash compiler.
NB: The depth, or delay, of the structure produced by
"
" is O(log_2(dtfold
m f g xs
)).length
xs
vfold :: forall k a b. KnownNat k => (forall l. SNat l -> a -> Vec l b -> Vec (l + 1) b) -> Vec k a -> Vec k b Source #
Specialised version of dfold
that builds a triangular computational
structure.
doctests setup
>>>
let compareSwap a b = if a > b then (a,b) else (b,a)
>>>
let insert y xs = let (y',xs') = mapAccumL compareSwap y xs in xs' :< y'
>>>
let insertionSort = vfold (const insert)
Example usage
compareSwap a b = if a > b then (a,b) else (b,a) insert y xs = let (y',xs') =mapAccumL
compareSwap y xs in xs':<
y' insertionSort =vfold
(const insert)
Builds a triangular structure of compare and swaps to sort a row.
>>>
insertionSort (7 :> 3 :> 9 :> 1 :> Nil)
1 :> 3 :> 7 :> 9 :> Nil
The circuit layout of insertionSort
, build using vfold
, is:
smap :: forall k a b. KnownNat k => (forall l. SNat l -> a -> b) -> Vec k a -> Vec k b Source #
Apply a function to every element of a vector and the element's position
(as an SNat
value) in the vector.
>>>
let rotateMatrix = smap (flip rotateRightS)
>>>
let xss = (1:>2:>3:>Nil):>(1:>2:>3:>Nil):>(1:>2:>3:>Nil):>Nil
>>>
xss
(1 :> 2 :> 3 :> Nil) :> (1 :> 2 :> 3 :> Nil) :> (1 :> 2 :> 3 :> Nil) :> Nil>>>
rotateMatrix xss
(1 :> 2 :> 3 :> Nil) :> (3 :> 1 :> 2 :> Nil) :> (2 :> 3 :> 1 :> Nil) :> Nil
concatBitVector# :: forall n m. (KnownNat n, KnownNat m) => Vec n (BitVector m) -> BitVector (n * m) Source #
unconcatBitVector# :: forall n m. (KnownNat n, KnownNat m) => BitVector (n * m) -> Vec n (BitVector m) Source #
seqV :: KnownNat n => Vec n a -> b -> b infixr 0 Source #
Evaluate all elements of a vector to WHNF, returning the second argument
seqVX :: KnownNat n => Vec n a -> b -> b infixr 0 Source #
Evaluate all elements of a vector to WHNF, returning the second argument.
Does not propagate XException
s.
forceVX :: KnownNat n => Vec n a -> Vec n a Source #
Evaluate all elements of a vector to WHNF. Does not propagate
XException
s.
Perfect depth trees
module Clash.Sized.RTree
Annotations
module Clash.Annotations.TopEntity
Generics type-classes
Representable types of kind *
.
This class is derivable in GHC with the DeriveGeneric
flag on.
A Generic
instance must satisfy the following laws:
from
.to
≡id
to
.from
≡id
Instances
class Generic1 (f :: k -> Type) #
Representable types of kind * -> *
(or kind k -> *
, when PolyKinds
is enabled).
This class is derivable in GHC with the DeriveGeneric
flag on.
A Generic1
instance must satisfy the following laws:
from1
.to1
≡id
to1
.from1
≡id
Instances
Generic1 (V1 :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (U1 :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (Proxy :: k -> Type) | Since: base-4.6.0.0 |
Generic1 (Alt f :: k -> Type) | Since: base-4.8.0.0 |
Generic1 (Ap f :: k -> Type) | Since: base-4.12.0.0 |
Generic1 (Const a :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (URec (Ptr ()) :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (URec Char :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (URec Double :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (URec Float :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (URec Int :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (URec Word :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (Rec1 f :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (Sum f g :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (Product f g :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (K1 i c :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (f :+: g :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (f :*: g :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (WrappedBifunctor p a :: k1 -> Type) | |
Defined in Data.Bifunctor.Wrapped type Rep1 (WrappedBifunctor p a) :: k -> Type # from1 :: forall (a0 :: k). WrappedBifunctor p a a0 -> Rep1 (WrappedBifunctor p a) a0 # to1 :: forall (a0 :: k). Rep1 (WrappedBifunctor p a) a0 -> WrappedBifunctor p a a0 # | |
Generic1 (Joker g a :: k1 -> Type) | |
Generic1 (Clown f a :: k1 -> Type) | |
Functor f => Generic1 (Compose f g :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (M1 i c f :: k -> Type) | Since: base-4.9.0.0 |
Functor f => Generic1 (f :.: g :: k -> Type) | Since: base-4.9.0.0 |
Generic1 (Sum p q a :: k1 -> Type) | |
Generic1 (Product f g a :: k1 -> Type) | |
Functor f => Generic1 (Tannen f p a :: k2 -> Type) | |
Functor (p (f a)) => Generic1 (Biff p f g a :: k3 -> Type) | |
Generic1 [] | Since: base-4.6.0.0 |
Generic1 Maybe | Since: base-4.6.0.0 |
Generic1 Par1 | Since: base-4.9.0.0 |
Generic1 Solo | |
Generic1 Complex | Since: base-4.9.0.0 |
Generic1 Min | Since: base-4.9.0.0 |
Generic1 Max | Since: base-4.9.0.0 |
Generic1 First | Since: base-4.9.0.0 |
Generic1 Last | Since: base-4.9.0.0 |
Generic1 WrappedMonoid | Since: base-4.9.0.0 |
Defined in Data.Semigroup type Rep1 WrappedMonoid :: k -> Type # from1 :: forall (a :: k). WrappedMonoid a -> Rep1 WrappedMonoid a # to1 :: forall (a :: k). Rep1 WrappedMonoid a -> WrappedMonoid a # | |
Generic1 Option | Since: base-4.9.0.0 |
Generic1 ZipList | Since: base-4.7.0.0 |
Generic1 Identity | Since: base-4.8.0.0 |
Generic1 First | Since: base-4.7.0.0 |
Generic1 Last | Since: base-4.7.0.0 |
Generic1 Dual | Since: base-4.7.0.0 |
Generic1 Sum | Since: base-4.7.0.0 |
Generic1 Product | Since: base-4.7.0.0 |
Generic1 Down | Since: base-4.12.0.0 |
Generic1 NonEmpty | Since: base-4.6.0.0 |
Generic1 Tree | Since: containers-0.5.8 |
Generic1 FingerTree | Since: containers-0.6.1 |
Defined in Data.Sequence.Internal type Rep1 FingerTree :: k -> Type # from1 :: forall (a :: k). FingerTree a -> Rep1 FingerTree a # to1 :: forall (a :: k). Rep1 FingerTree a -> FingerTree a # | |
Generic1 Digit | Since: containers-0.6.1 |
Generic1 Node | Since: containers-0.6.1 |
Generic1 Elem | Since: containers-0.6.1 |
Generic1 ViewL | Since: containers-0.5.8 |
Generic1 ViewR | Since: containers-0.5.8 |
Generic1 Maybe | |
Generic1 (Either a :: Type -> Type) | Since: base-4.6.0.0 |
Generic1 ((,) a :: Type -> Type) | Since: base-4.6.0.0 |
Generic1 (Arg a :: Type -> Type) | Since: base-4.9.0.0 |
Generic1 (WrappedMonad m :: Type -> Type) | Since: base-4.7.0.0 |
Defined in Control.Applicative type Rep1 (WrappedMonad m) :: k -> Type # from1 :: forall (a :: k). WrappedMonad m a -> Rep1 (WrappedMonad m) a # to1 :: forall (a :: k). Rep1 (WrappedMonad m) a -> WrappedMonad m a # | |
Functor f => Generic1 (Free f :: Type -> Type) | |
Functor f => Generic1 (Cofree f :: Type -> Type) | |
Generic1 (ListF a :: Type -> Type) | |
Generic1 (NonEmptyF a :: Type -> Type) | |
Generic1 (TreeF a :: Type -> Type) | |
Generic1 (Pair a :: Type -> Type) | |
Generic1 (These a :: Type -> Type) | |
Generic1 (Either a :: Type -> Type) | |
Generic1 (These a :: Type -> Type) | |
Generic1 ((,,) a b :: Type -> Type) | Since: base-4.6.0.0 |
Generic1 (Kleisli m a :: Type -> Type) | Since: base-4.14.0.0 |
Generic1 (WrappedArrow a b :: Type -> Type) | Since: base-4.7.0.0 |
Defined in Control.Applicative type Rep1 (WrappedArrow a b) :: k -> Type # from1 :: forall (a0 :: k). WrappedArrow a b a0 -> Rep1 (WrappedArrow a b) a0 # to1 :: forall (a0 :: k). Rep1 (WrappedArrow a b) a0 -> WrappedArrow a b a0 # | |
Generic1 (FreeF f a :: Type -> Type) | |
Generic1 (CofreeF f a :: Type -> Type) | |
Generic1 (Tagged s :: Type -> Type) | |
Generic1 ((,,,) a b c :: Type -> Type) | Since: base-4.6.0.0 |
Generic1 ((,,,,) a b c d :: Type -> Type) | Since: base-4.6.0.0 |
Generic1 ((,,,,,) a b c d e :: Type -> Type) | Since: base-4.6.0.0 |
Generic1 ((,,,,,,) a b c d e f :: Type -> Type) | Since: base-4.6.0.0 |
Type-level natural numbers
module GHC.TypeLits
module GHC.TypeLits.Extra
module Clash.Promoted.Nat
module Clash.Promoted.Nat.Literals
module Clash.Promoted.Nat.TH
Type-level strings
module Clash.Promoted.Symbol
Template Haskell
class Lift (t :: TYPE r) where #
A Lift
instance can have any of its values turned into a Template
Haskell expression. This is needed when a value used within a Template
Haskell quotation is bound outside the Oxford brackets ([| ... |]
or
[|| ... ||]
) but not at the top level. As an example:
add1 :: Int -> Q (TExp Int) add1 x = [|| x + 1 ||]
Template Haskell has no way of knowing what value x
will take on at
splice-time, so it requires the type of x
to be an instance of Lift
.
A Lift
instance must satisfy $(lift x) ≡ x
and $$(liftTyped x) ≡ x
for all x
, where $(...)
and $$(...)
are Template Haskell splices.
It is additionally expected that
.lift
x ≡ unTypeQ
(liftTyped
x)
Lift
instances can be derived automatically by use of the -XDeriveLift
GHC language extension:
{-# LANGUAGE DeriveLift #-} module Foo where import Language.Haskell.TH.Syntax data Bar a = Bar1 a (Bar a) | Bar2 String deriving Lift
Levity-polymorphic since template-haskell-2.16.0.0.
Turn a value into a Template Haskell expression, suitable for use in a splice.
liftTyped :: t -> Q (TExp t) #
Turn a value into a Template Haskell typed expression, suitable for use in a typed splice.
Since: template-haskell-2.16.0.0
Instances
Lift Bool | |
Lift Char | |
Lift Double | |
Lift Float | |
Lift Int | |
Lift Int8 | |
Lift Int16 | |
Lift Int32 | |
Lift Int64 | |
Lift Integer | |
Lift Natural | |
Lift Word | |
Lift Word8 | |
Lift Word16 | |
Lift Word32 | |
Lift Word64 | |
Lift () | |
Lift Void | Since: template-haskell-2.15.0.0 |
Lift ByteArray | |
Lift Half | |
Lift ConstrRepr Source # | |
Defined in Clash.Annotations.BitRepresentation lift :: ConstrRepr -> Q Exp # liftTyped :: ConstrRepr -> Q (TExp ConstrRepr) # | |
Lift DataReprAnn Source # | |
Defined in Clash.Annotations.BitRepresentation lift :: DataReprAnn -> Q Exp # liftTyped :: DataReprAnn -> Q (TExp DataReprAnn) # | |
Lift Bit Source # | |
Lift PortName Source # | |
Lift TopEntity Source # | |
Lift Int# | Since: template-haskell-2.16.0.0 |
Lift Char# | Since: template-haskell-2.16.0.0 |
Lift Word# | Since: template-haskell-2.16.0.0 |
Lift Addr# | Produces an Since: template-haskell-2.16.0.0 |
Lift Float# | Since: template-haskell-2.16.0.0 |
Lift Double# | Since: template-haskell-2.16.0.0 |
Lift a => Lift ([a] :: Type) | |
Lift a => Lift (Maybe a :: Type) | |
Integral a => Lift (Ratio a :: Type) | |
Lift a => Lift (NonEmpty a :: Type) | Since: template-haskell-2.15.0.0 |
Lift a => Lift (HashSet a :: Type) | Since: unordered-containers-0.2.17.0 |
Lift (PrimArray a :: Type) | |
Lift a => Lift (SmallArray a :: Type) | |
Defined in Data.Primitive.SmallArray lift :: SmallArray a -> Q Exp # liftTyped :: SmallArray a -> Q (TExp (SmallArray a)) # | |
Lift a => Lift (Array a :: Type) | |
KnownSymbol s => Lift (SSymbol s :: Type) Source # | |
KnownNat n => Lift (BitVector n :: Type) Source # | |
KnownNat n => Lift (Index n :: Type) Source # | |
Lift (SNat n :: Type) Source # | |
KnownNat n => Lift (Unsigned n :: Type) Source # | |
KnownNat n => Lift (Signed n :: Type) Source # | |
(Lift a, Lift b) => Lift (Either a b :: Type) | |
(Lift a, Lift b) => Lift ((a, b) :: Type) | |
(Lift k, Lift v) => Lift (HashMap k v :: Type) | Since: unordered-containers-0.2.17.0 |
(Lift k, Lift v) => Lift (Leaf k v :: Type) | Since: unordered-containers-0.2.17.0 |
Lift a => Lift (Vec n a :: Type) Source # | |
Lift a => Lift (Signal dom a :: Type) Source # | |
Lift a => Lift (RTree d a :: Type) Source # | |
(Lift a, Lift b, Lift c) => Lift ((a, b, c) :: Type) | |
Lift a => Lift (DSignal dom delay a :: Type) Source # | |
(Lift (rep (int + frac)), KnownNat frac, KnownNat int, Typeable rep) => Lift (Fixed rep int frac :: Type) Source # | |
(Lift a, Lift b, Lift c, Lift d) => Lift ((a, b, c, d) :: Type) | |
(Lift a, Lift b, Lift c, Lift d, Lift e) => Lift ((a, b, c, d, e) :: Type) | |
(Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) => Lift ((a, b, c, d, e, f) :: Type) | |
(Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) => Lift ((a, b, c, d, e, f, g) :: Type) | |
Lift (# #) | Since: template-haskell-2.16.0.0 |
Lift a => Lift ((# a #) :: TYPE ('TupleRep '['LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b) => Lift ((# a, b #) :: TYPE ('TupleRep '['LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b) => Lift ((# a | b #) :: TYPE ('SumRep '['LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c) => Lift ((# a, b, c #) :: TYPE ('TupleRep '['LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c) => Lift ((# a | b | c #) :: TYPE ('SumRep '['LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c, Lift d) => Lift ((# a, b, c, d #) :: TYPE ('TupleRep '['LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c, Lift d) => Lift ((# a | b | c | d #) :: TYPE ('SumRep '['LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c, Lift d, Lift e) => Lift ((# a, b, c, d, e #) :: TYPE ('TupleRep '['LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c, Lift d, Lift e) => Lift ((# a | b | c | d | e #) :: TYPE ('SumRep '['LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) => Lift ((# a, b, c, d, e, f #) :: TYPE ('TupleRep '['LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) => Lift ((# a | b | c | d | e | f #) :: TYPE ('SumRep '['LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) => Lift ((# a, b, c, d, e, f, g #) :: TYPE ('TupleRep '['LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
(Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) => Lift ((# a | b | c | d | e | f | g #) :: TYPE ('SumRep '['LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep, 'LiftedRep])) | Since: template-haskell-2.16.0.0 |
Type classes
Clash
class NFDataX a => AutoReg a Source #
autoReg
is a "smart" version of register
. It does two things:
- It splits product types over their fields. For example, given a 3-tuple, the corresponding HDL will end up with three instances of a register (or more if the three fields can be split up similarly).
- Given a data type where a constructor indicates (parts) of the data will (not) be updated a given cycle, it will split the data in two parts. The first part will contain the "always interesting" parts (the constructor bits). The second holds the "potentially uninteresting" data (the rest). Both parts will be stored in separate registers. The register holding the "potentially uninteresting" part will only be enabled if the constructor bits indicate they're interesting.
The most important example of this is Maybe
. Consider Maybe (Signed 16)
;
when viewed as bits, a Nothing
would look like:
>>>
pack @(Maybe (Signed 16)) Nothing
0b0_...._...._...._....
and Just
>>>
pack @(Maybe (Signed 16)) (Just 3)
0b1_0000_0000_0000_0011
In the first case, Nothing, we don't particularly care about updating the
register holding the Signed 16
field, as they'll be unknown anyway. We
can therefore deassert its enable line.
Making Clash lay it out like this increases the chances of synthesis tools clock gating the registers, saving energy.
This version of autoReg
will split the given data type up recursively. For
example, given a :: Maybe (Maybe Int, Maybe Int)
, a total of five registers
will be rendered. Both the "interesting" and "uninteresting" enable lines of
the inner Maybe types will be controlled by the outer one, in addition to
the inner parts controlling their "uninteresting" parts as described in (2).
The default implementation is just register
. If you don't need or want
the special features of AutoReg, you can use that by writing an empty instance.
data MyDataType = ... instance AutoReg MyDataType
If you have a product type you can use deriveAutoReg
to derive an instance.
Instances
autoReg :: (HasCallStack, HiddenClockResetEnable dom, AutoReg a) => a -> Signal dom a -> Signal dom a Source #
Implicit version of autoReg
deriveAutoReg :: Name -> DecsQ Source #
Automatically derives an AutoReg
instance for a product type
Usage:
data Pair a b = MkPair { getA :: a, getB :: b } deriving (Generic, NFDataX) data Tup3 a b c = MkTup3 { getAB :: Pair a b, getC :: c } deriving (Generic, NFDataX) deriveAutoReg ''Pair deriveAutoReg ''Tup3
NB: Because of the way template haskell works the order here matters,
if you try to deriveAutoReg ''Tup3
before Pair
it will complain
about missing an instance AutoReg (Pair a b)
.
module Clash.Class.BitPack
module Clash.Class.Exp
module Clash.Class.Num
module Clash.Class.Parity
module Clash.Class.Resize
Other
module Control.Applicative
module Data.Bits
module Data.Default.Class
data Constraint #
The kind of constraints, like Show a
Exceptions
module Clash.XException
Named types
module Clash.NamedTypes
Hidden arguments
module Clash.Hidden
Magic
module Clash.Magic
Haskell Prelude
Clash.Prelude re-exports most of the Haskell Prelude with the exception of
those functions that the Clash API defines to work on Vec
from
Clash.Sized.Vector instead of on lists as the Haskell Prelude does.
In addition, for the odd
and even
functions a type class called Parity
is available at
Clash.Class.Parity.
module Clash.HaskellPrelude