We can't put Clash.Annotations.SynthesisAttributes on a top entity output when the output is a tuple. Specifying SynthesisAttributes on output tuple elements causes them to silently disappear from the output. But something like a tuple is necessary to have outputs with multiple clock domains, so this is a rather significant omission.
Example
So for example I'd like to do
type PinAttr loc =
[ 'StringAttr "chip_pin" loc
, 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
]
properTopEntity
:: Clock Input `Annotate` PinAttr "R8"
-> Reset Input `Annotate` PinAttr "J15"
-> ( Signal DomA Bit `Annotate` PinAttr "D1"
, Signal DomB Bit `Annotate` PinAttr "A11"
, Signal DomC Bit `Annotate` PinAttr "B13"
, Signal DomD Bit `Annotate` PinAttr "A13"
, Signal DomE Bit `Annotate` PinAttr "A15"
)
in the following code, but I have to jump through weird hoops and write topEntity instead:
MultiBlinker.hs
```haskell
{-# OPTIONS_GHC -Wno-orphans #-}
module MultiBlinker where
import Clash.Explicit.Prelude
import Clash.Intel.ClockGen
import Clash.Annotations.SynthesisAttributes
createDomain vSystem{vName="Input", vPeriod=20000, vResetPolarity=ActiveLow}
createDomain vSystem{vName="DomA", vPeriod=9000}
createDomain vSystem{vName="DomB", vPeriod=11000}
createDomain vSystem{vName="DomC", vPeriod=13000}
createDomain vSystem{vName="DomD", vPeriod=15000}
createDomain vSystem{vName="DomE", vPeriod=17000}
type PinAttr loc =
[ 'StringAttr "chip_pin" loc
, 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\""
]
{-# ANN topEntity
(Synthesize
{ t_name = "blinker"
, t_inputs = [ PortName "CLOCK_50"
, PortName "KEY0"
]
, t_output = PortName "LED"
}) #-}
topEntity
:: Clock Input `Annotate` PinAttr "R8"
-> Reset Input `Annotate` PinAttr "J15"
-> Signal DomA (BitVector 5) `Annotate` PinAttr "D1, A11, B13, A13, A15"
topEntity clkIn rstIn =
pack <$> bundle
( ledA
, syn ledB
, syn ledC
, syn ledD
, syn ledE
)
where
(ledA, ledB, ledC, ledD, ledE) = properTopEntity clkIn rstIn
syn :: KnownDomain domIn => Signal domIn a -> Signal DomA a
syn = unsafeSynchronizer undefined undefined
{-# OPAQUE topEntity #-}
properTopEntity
:: Clock Input `Annotate` PinAttr "R8"
-> Reset Input `Annotate` PinAttr "J15"
-> ( Signal DomA Bit `Annotate` PinAttr "D1"
, Signal DomB Bit `Annotate` PinAttr "A11"
, Signal DomC Bit `Annotate` PinAttr "B13"
, Signal DomD Bit `Annotate` PinAttr "A13"
, Signal DomE Bit `Annotate` PinAttr "A15"
)
properTopEntity clkIn rstIn =
( blink clkA rstA
, blink clkB rstB
, blink clkC rstC
, blink clkD rstD
, blink clkE rstE
)
where
blink clk rst =
let
cnt = register clk rst enableGen (0 :: Unsigned 26) $ cnt + 1
in msb <$> cnt
(clkA, rstA, clkB, rstB, clkC, rstC, clkD, rstD, clkE, rstE) =
altpllSync clkIn rstIn
```
We can't put
Clash.Annotations.SynthesisAttributes
on a top entity output when the output is a tuple. SpecifyingSynthesisAttributes
on output tuple elements causes them to silently disappear from the output. But something like a tuple is necessary to have outputs with multiple clock domains, so this is a rather significant omission.Example
So for example I'd like to do
in the following code, but I have to jump through weird hoops and write
topEntity
instead:MultiBlinker.hs
```haskell {-# OPTIONS_GHC -Wno-orphans #-} module MultiBlinker where import Clash.Explicit.Prelude import Clash.Intel.ClockGen import Clash.Annotations.SynthesisAttributes createDomain vSystem{vName="Input", vPeriod=20000, vResetPolarity=ActiveLow} createDomain vSystem{vName="DomA", vPeriod=9000} createDomain vSystem{vName="DomB", vPeriod=11000} createDomain vSystem{vName="DomC", vPeriod=13000} createDomain vSystem{vName="DomD", vPeriod=15000} createDomain vSystem{vName="DomE", vPeriod=17000} type PinAttr loc = [ 'StringAttr "chip_pin" loc , 'StringAttr "altera_attribute" "-name IO_STANDARD \"3.3-V LVTTL\"" ] {-# ANN topEntity (Synthesize { t_name = "blinker" , t_inputs = [ PortName "CLOCK_50" , PortName "KEY0" ] , t_output = PortName "LED" }) #-} topEntity :: Clock Input `Annotate` PinAttr "R8" -> Reset Input `Annotate` PinAttr "J15" -> Signal DomA (BitVector 5) `Annotate` PinAttr "D1, A11, B13, A13, A15" topEntity clkIn rstIn = pack <$> bundle ( ledA , syn ledB , syn ledC , syn ledD , syn ledE ) where (ledA, ledB, ledC, ledD, ledE) = properTopEntity clkIn rstIn syn :: KnownDomain domIn => Signal domIn a -> Signal DomA a syn = unsafeSynchronizer undefined undefined {-# OPAQUE topEntity #-} properTopEntity :: Clock Input `Annotate` PinAttr "R8" -> Reset Input `Annotate` PinAttr "J15" -> ( Signal DomA Bit `Annotate` PinAttr "D1" , Signal DomB Bit `Annotate` PinAttr "A11" , Signal DomC Bit `Annotate` PinAttr "B13" , Signal DomD Bit `Annotate` PinAttr "A13" , Signal DomE Bit `Annotate` PinAttr "A15" ) properTopEntity clkIn rstIn = ( blink clkA rstA , blink clkB rstB , blink clkC rstC , blink clkD rstD , blink clkE rstE ) where blink clk rst = let cnt = register clk rst enableGen (0 :: Unsigned 26) $ cnt + 1 in msb <$> cnt (clkA, rstA, clkB, rstB, clkC, rstC, clkD, rstD, clkE, rstE) = altpllSync clkIn rstIn ```