clash-prelude-0.99.3: CAES Language for Synchronous Hardware - Prelude library

Copyright(C) 2013-2016 University of Twente
2017 Myrtle Software Ltd Google Inc.
LicenseBSD2 (see the file LICENSE)
MaintainerChristiaan Baaij <christiaan.baaij@gmail.com>
Safe HaskellUnsafe
LanguageHaskell2010
Extensions
  • Cpp
  • MonoLocalBinds
  • TemplateHaskell
  • TemplateHaskellQuotes
  • ScopedTypeVariables
  • TypeFamilies
  • GADTs
  • GADTSyntax
  • DataKinds
  • DeriveGeneric
  • DeriveAnyClass
  • TypeSynonymInstances
  • FlexibleInstances
  • ConstrainedClassMethods
  • MultiParamTypeClasses
  • MagicHash
  • KindSignatures
  • ExplicitNamespaces
  • ExplicitForAll

Clash.Signal.Internal

Contents

Description

 
Synopsis

Datatypes

data Domain Source #

A domain with a name (Symbol) and a clock period (Nat) in ps

Constructors

Dom 

data Signal (domain :: Domain) a Source #

CλaSH has synchronous Signals in the form of:

Signal (domain :: Domain) a

Where a is the type of the value of the Signal, for example Int or Bool, and domain is the clock- (and reset-) domain to which the memory elements manipulating these Signals belong.

The type-parameter, domain, is of the kind Domain which has types of the following shape:

data Domain = Dom { domainName :: Symbol, clkPeriod :: Nat }

Where domainName is a type-level string (Symbol) representing the name of the clock- (and reset-) domain, and clkPeriod is a type-level natural number (Nat) representing the clock period (in ps) of the clock lines in the clock-domain.

  • 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!

Constructors

a :- (Signal domain a) infixr 5

The constructor, (:-), is not synthesisable.

Instances
Functor (Signal domain) Source # 
Instance details

Methods

fmap :: (a -> b) -> Signal domain a -> Signal domain b #

(<$) :: a -> Signal domain b -> Signal domain a #

Applicative (Signal domain) Source # 
Instance details

Methods

pure :: a -> Signal domain a #

(<*>) :: Signal domain (a -> b) -> Signal domain a -> Signal domain b #

liftA2 :: (a -> b -> c) -> Signal domain a -> Signal domain b -> Signal domain c #

(*>) :: Signal domain a -> Signal domain b -> Signal domain b #

(<*) :: Signal domain a -> Signal domain b -> Signal domain a #

Foldable (Signal domain) Source #

NB: Not synthesisable

NB: In "foldr f z s":

  • The function f should be lazy in its second argument.
  • The z element will never be used.
Instance details

Methods

fold :: Monoid m => Signal domain m -> m #

foldMap :: Monoid m => (a -> m) -> Signal domain a -> m #

foldr :: (a -> b -> b) -> b -> Signal domain a -> b #

foldr' :: (a -> b -> b) -> b -> Signal domain a -> b #

foldl :: (b -> a -> b) -> b -> Signal domain a -> b #

foldl' :: (b -> a -> b) -> b -> Signal domain a -> b #

foldr1 :: (a -> a -> a) -> Signal domain a -> a #

foldl1 :: (a -> a -> a) -> Signal domain a -> a #

toList :: Signal domain a -> [a] #

null :: Signal domain a -> Bool #

length :: Signal domain a -> Int #

elem :: Eq a => a -> Signal domain a -> Bool #

maximum :: Ord a => Signal domain a -> a #

minimum :: Ord a => Signal domain a -> a #

sum :: Num a => Signal domain a -> a #

product :: Num a => Signal domain a -> a #

Traversable (Signal domain) Source # 
Instance details

Methods

traverse :: Applicative f => (a -> f b) -> Signal domain a -> f (Signal domain b) #

sequenceA :: Applicative f => Signal domain (f a) -> f (Signal domain a) #

mapM :: Monad m => (a -> m b) -> Signal domain a -> m (Signal domain b) #

sequence :: Monad m => Signal domain (m a) -> m (Signal domain a) #

Fractional a => Fractional (Signal domain a) Source # 
Instance details

Methods

(/) :: Signal domain a -> Signal domain a -> Signal domain a #

recip :: Signal domain a -> Signal domain a #

fromRational :: Rational -> Signal domain a #

Num a => Num (Signal domain a) Source # 
Instance details

Methods

(+) :: Signal domain a -> Signal domain a -> Signal domain a #

(-) :: Signal domain a -> Signal domain a -> Signal domain a #

(*) :: Signal domain a -> Signal domain a -> Signal domain a #

negate :: Signal domain a -> Signal domain a #

abs :: Signal domain a -> Signal domain a #

signum :: Signal domain a -> Signal domain a #

fromInteger :: Integer -> Signal domain a #

Show a => Show (Signal domain a) Source # 
Instance details

Methods

showsPrec :: Int -> Signal domain a -> ShowS #

show :: Signal domain a -> String #

showList :: [Signal domain a] -> ShowS #

Lift a => Lift (Signal domain a) Source # 
Instance details

Methods

lift :: Signal domain a -> Q Exp #

Arbitrary a => Arbitrary (Signal domain a) Source # 
Instance details

Methods

arbitrary :: Gen (Signal domain a) #

shrink :: Signal domain a -> [Signal domain a] #

CoArbitrary a => CoArbitrary (Signal domain a) Source # 
Instance details

Methods

coarbitrary :: Signal domain a -> Gen b -> Gen b #

Default a => Default (Signal domain a) Source # 
Instance details

Methods

def :: Signal domain a #

Clocks

data Clock (domain :: Domain) (gated :: ClockKind) where Source #

A clock signal belonging to a domain

Constructors

Clock :: domain ~ Dom name period => SSymbol name -> SNat period -> Clock domain Source 
GatedClock :: domain ~ Dom name period => SSymbol name -> SNat period -> Signal domain Bool -> Clock domain Gated 
Instances
Show (Clock domain gated) Source # 
Instance details

Methods

showsPrec :: Int -> Clock domain gated -> ShowS #

show :: Clock domain gated -> String #

showList :: [Clock domain gated] -> ShowS #

data ClockKind Source #

Distinction between gated and ungated clocks

Constructors

Source

A clock signal coming straight from the clock source

Gated

A clock signal that has been gated

Instances
Eq ClockKind Source # 
Instance details
Ord ClockKind Source # 
Instance details
Show ClockKind Source # 
Instance details
Generic ClockKind Source # 
Instance details

Associated Types

type Rep ClockKind :: * -> * #

NFData ClockKind Source # 
Instance details

Methods

rnf :: ClockKind -> () #

type Rep ClockKind Source # 
Instance details
type Rep ClockKind = D1 (MetaData "ClockKind" "Clash.Signal.Internal" "clash-prelude-0.99.3-inplace" False) (C1 (MetaCons "Source" PrefixI False) (U1 :: * -> *) :+: C1 (MetaCons "Gated" PrefixI False) (U1 :: * -> *))

clockPeriod :: Num a => Clock domain gated -> a Source #

Get the clock period of a Clock (in ps) as a Num

clockEnable :: Clock domain gated -> Maybe (Signal domain Bool) Source #

If the clock is gated, return Just the enable signal, Nothing otherwise

Clock gating

clockGate :: Clock domain gated -> Signal domain Bool -> Clock domain Gated Source #

Clock gating primitive

Resets

data Reset (domain :: Domain) (synchronous :: ResetKind) where Source #

A reset signal belonging to a domain.

The underlying representation of resets is Bool. Note that all components in the clash-prelude package have an active-high reset port, i.e., the component is reset when the reset port is True.

Constructors

Sync :: Signal domain Bool -> Reset domain Synchronous 
Async :: Signal domain Bool -> Reset domain Asynchronous 

data ResetKind Source #

The "kind" of reset

Given a situation where a reset is asserted, and then de-asserted at the active flank of the clock, we can observe the difference between a synchronous reset and an asynchronous reset:

Synchronous reset

registerS
  :: Clock domain gated -> Reset domain Synchronous
  -> Signal domain Int -> Signal domain Int
registerS = register
>>> printX (sampleN 4 (registerS (clockGen @System) (syncResetGen @System) 0 (fromList [1,2,3])))
[X,0,2,3]

Asynchronous reset

registerA
  :: Clock domain gated -> Reset domain Asynchronous
  -> Signal domain Int -> Signal domain Int
registerA = register
>>> sampleN 4 (registerA (clockGen @System) (asyncResetGen @System) 0 (fromList [1,2,3]))
[0,1,2,3]

Constructors

Synchronous

Components with a synchronous reset port produce the reset value when:

  • The reset is asserted during the active flank of the clock to which the component is synchronized.
Asynchronous

Components with an asynchronous reset port produce the reset value when:

  • Immediately when the reset is asserted.
Instances
Eq ResetKind Source # 
Instance details
Ord ResetKind Source # 
Instance details
Show ResetKind Source # 
Instance details
Generic ResetKind Source # 
Instance details

Associated Types

type Rep ResetKind :: * -> * #

NFData ResetKind Source # 
Instance details

Methods

rnf :: ResetKind -> () #

type Rep ResetKind Source # 
Instance details
type Rep ResetKind = D1 (MetaData "ResetKind" "Clash.Signal.Internal" "clash-prelude-0.99.3-inplace" False) (C1 (MetaCons "Synchronous" PrefixI False) (U1 :: * -> *) :+: C1 (MetaCons "Asynchronous" PrefixI False) (U1 :: * -> *))

unsafeFromAsyncReset :: Reset domain Asynchronous -> Signal domain Bool Source #

unsafeFromAsyncReset is unsafe because it can introduce:

unsafeToAsyncReset :: Signal domain Bool -> Reset domain Asynchronous Source #

unsafeToAsyncReset is unsafe because it can introduce:

  • combinational loops

Example

Expand
resetSynchronizer
  :: Clock domain gated
  -> Reset domain 'Asynchronous
  -> Reset domain 'Asynchronous
resetSynchronizer clk rst  =
  let r1 = register clk rst True (pure False)
      r2 = register clk rst True r1
  in  unsafeToAsyncReset r2

fromSyncReset :: Reset domain Synchronous -> Signal domain Bool Source #

It is safe to treat synchronous resets as Bool signals

unsafeToSyncReset :: Signal domain Bool -> Reset domain Synchronous Source #

unsafeToSyncReset is unsafe because:

  • It can lead to meta-stability issues in the presence of asynchronous resets.

Basic circuits

delay# :: HasCallStack => Clock domain gated -> Signal domain a -> Signal domain a Source #

register# :: HasCallStack => Clock domain gated -> Reset domain synchronous -> a -> Signal domain a -> Signal domain a Source #

mux :: Applicative f => f Bool -> f a -> f a -> f a Source #

The above type is a generalisation for:

mux :: Signal Bool -> Signal a -> Signal a -> Signal a

A multiplexer. Given "mux b t f", output t when b is True, and f when b is False.

Simulation and testbench functions

clockGen :: (domain ~ Dom nm period, KnownSymbol nm, KnownNat period) => Clock domain Source Source #

Clock generator for simulations. Do not use this clock generator for for the testBench function, use tbClockGen instead.

To be used like:

type DomA = Dom "A" 1000
clkA = clockGen @DomA

tbClockGen :: (domain ~ Dom nm period, KnownSymbol nm, KnownNat period) => Signal domain Bool -> Clock domain Source Source #

Clock generator to be used in the testBench function.

To be used like:

type DomA = Dom "A" 1000
clkA en = clockGen @DomA en

Example

Expand
type DomA1 = Dom "A" 1 -- fast, twice as fast as slow
type DomB2 = Dom "B" 2 -- slow

topEntity
  :: Clock DomA1 Source
  -> Reset DomA1 Asynchronous
  -> Clock DomB2 Source
  -> Signal DomA1 (Unsigned 8)
  -> Signal DomB2 (Unsigned 8, Unsigned 8)
topEntity clk1 rst1 clk2 i =
  let h = register clk1 rst1 0 (register clk1 rst1 0 i)
      l = register clk1 rst1 0 i
  in  unsafeSynchronizer clk1 clk2 (bundle (h,l))

testBench
  :: Signal DomB2 Bool
testBench = done
  where
    testInput      = stimuliGenerator clkA1 rstA1 $(listToVecTH [1::Unsigned 8,2,3,4,5,6,7,8])
    expectedOutput = outputVerifier   clkB2 rstB2 $(listToVecTH [(0,0) :: (Unsigned 8, Unsigned 8),(1,2),(3,4),(5,6),(7,8)])
    done           = expectedOutput (topEntity clkA1 rstA1 clkB2 testInput)
    done'          = not <$> done
    clkA1          = tbClockGen @DomA1 (unsafeSynchronizer clkB2 clkA1 done')
    clkB2          = tbClockGen @DomB2 done'
    rstA1          = asyncResetGen @DomA1
    rstB2          = asyncResetGen @DomB2

asyncResetGen :: Reset domain Asynchronous Source #

Asynchronous reset generator, for simulations and the testBench function.

To be used like:

type DomA = Dom "A" 1000
rstA = asyncResetGen @DomA

NB: Can only be used for components with an active-high reset port, which all clash-prelude components are.

Example

Expand
type Dom2 = Dom "dom" 2
type Dom7 = Dom "dom" 7
type Dom9 = Dom "dom" 9

topEntity
  :: Clock Dom2 Source
  -> Clock Dom7 Source
  -> Clock Dom9 Source
  -> Signal Dom7 Integer
  -> Signal Dom9 Integer
topEntity clk2 clk7 clk9 i = delay clk9 (unsafeSynchronizer clk2 clk9 (delay clk2 (unsafeSynchronizer clk7 clk2 (delay clk7 i))))
{--}

testBench
  :: Signal Dom9 Bool
testBench = done
  where
    testInput      = stimuliGenerator clk7 rst7 $(listToVecTH [(1::Integer)..10])
    expectedOutput = outputVerifier   clk9 rst9
                        ((undefined :> undefined :> Nil) ++ $(listToVecTH ([2,3,4,5,7,8,9,10]::[Integer])))
    done           = expectedOutput (topEntity clk2 clk7 clk9 testInput)
    done'          = not <$> done
    clk2           = tbClockGen @Dom2 (unsafeSynchronizer clk9 clk2 done')
    clk7           = tbClockGen @Dom7 (unsafeSynchronizer clk9 clk7 done')
    clk9           = tbClockGen @Dom9 done'
    rst7           = asyncResetGen @Dom7
    rst9           = asyncResetGen @Dom9

syncResetGen :: (domain ~ Dom n clkPeriod, KnownNat clkPeriod) => Reset domain Synchronous Source #

Synchronous reset generator, for simulations and the testBench function.

To be used like:

type DomA = Dom "A" 1000
rstA = syncResetGen @DomA

NB: Can only be used for components with an active-high reset port, which all clash-prelude components are.

Boolean connectives

(.&&.) :: Applicative f => f Bool -> f Bool -> f Bool infixr 3 Source #

The above type is a generalisation for:

(.&&.) :: Signal Bool -> Signal Bool -> Signal Bool

It is a version of (&&) that returns a Signal of Bool

(.||.) :: Applicative f => f Bool -> f Bool -> f Bool infixr 2 Source #

The above type is a generalisation for:

(.||.) :: Signal Bool -> Signal Bool -> Signal Bool

It is a version of (||) that returns a Signal of Bool

Simulation functions (not synthesisable)

simulate :: (NFData a, NFData b) => (Signal domain1 a -> Signal domain2 b) -> [a] -> [b] Source #

Simulate a (Signal a -> Signal b) function given a list of samples of type a

>>> simulate (register systemClockGen systemResetGen 8) [1, 2, 3]
[8,1,2,3...
...

NB: This function is not synthesisable

lazy version

simulate_lazy :: (Signal domain1 a -> Signal domain2 b) -> [a] -> [b] Source #

Simulate a (Signal a -> Signal b) function given a list of samples of type a

>>> simulate (register systemClockGen systemResetGen 8) [1, 2, 3]
[8,1,2,3...
...

NB: This function is not synthesisable

List <-> Signal conversion (not synthesisable)

sample :: (Foldable f, NFData a) => f a -> [a] Source #

The above type is a generalisation for:

sample :: Signal 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, ...

NB: This function is not synthesisable

sampleN :: (Foldable f, NFData a) => Int -> f a -> [a] Source #

The above type is a generalisation for:

sampleN :: Int -> Signal 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 3 s == [s0, s1, s2]

NB: This function is not synthesisable

fromList :: NFData a => [a] -> Signal domain 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 synthesisable

lazy versions

sample_lazy :: Foldable f => f a -> [a] Source #

The above type is a generalisation for:

sample :: Signal 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, ...

NB: This function is not synthesisable

sampleN_lazy :: Foldable f => Int -> f a -> [a] Source #

The above type is a generalisation for:

sampleN :: Int -> Signal 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 3 s == [s0, s1, s2]

NB: This function is not synthesisable

fromList_lazy :: [a] -> Signal domain 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 synthesisable

QuickCheck combinators

testFor :: Foldable f => Int -> f Bool -> Property Source #

The above type is a generalisation for:

testFor :: Int -> Signal Bool -> Property

testFor n s tests the signal s for n cycles.

Type classes

Eq-like

(.==.) :: (Eq a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.==.) :: Eq a => Signal a -> Signal a -> Signal Bool

It is a version of (==) that returns a Signal of Bool

(./=.) :: (Eq a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(./=.) :: Eq a => Signal a -> Signal a -> Signal Bool

It is a version of (/=) that returns a Signal of Bool

Ord-like

(.<.) :: (Ord a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.<.) :: Ord a => Signal a -> Signal a -> Signal Bool

It is a version of (<) that returns a Signal of Bool

(.<=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.<=.) :: Ord a => Signal a -> Signal a -> Signal Bool

It is a version of (<=) that returns a Signal of Bool

(.>=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.>=.) :: Ord a => Signal a -> Signal a -> Signal Bool

It is a version of (>=) that returns a Signal of Bool

(.>.) :: (Ord a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.>.) :: Ord a => Signal a -> Signal a -> Signal Bool

It is a version of (>) that returns a Signal of Bool

Functor

mapSignal# :: (a -> b) -> Signal domain a -> Signal domain b Source #

Applicative

signal# :: a -> Signal domain a Source #

appSignal# :: Signal domain (a -> b) -> Signal domain a -> Signal domain b Source #

Foldable

foldr# :: (a -> b -> b) -> b -> Signal domain a -> b Source #

NB: Not synthesisable

NB: In "foldr# f z s":

  • The function f should be lazy in its second argument.
  • The z element will never be used.

Traversable

traverse# :: Applicative f => (a -> f b) -> Signal domain a -> f (Signal domain b) Source #

EXTREMELY EXPERIMENTAL

joinSignal# :: Signal domain (Signal domain a) -> Signal domain a Source #

WARNING: EXTREMELY EXPERIMENTAL

The circuit semantics of this operation are unclear and/or non-existent. There is a good reason there is no Monad instance for Signal'.

Is currently treated as id by the Clash compiler.