Skip to content

Commit c0a6120

Browse files
committed
Allow blackbox templates to get domain info from Clock,Reset,Enable,etc
You can now use ~PERIOD, ~ISSYNC, ~ISINITDEFINED and ~ACTIVEEDGE on arguments of type Clock,Reset,Enable,ClockN and DiffClock.
1 parent 4ba5f60 commit c0a6120

File tree

3 files changed

+83
-52
lines changed

3 files changed

+83
-52
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ADDED: You can now use ~PERIOD, ~ISSYNC, ~ISINITDEFINED and ~ACTIVEEDGE
2+
on arguments of type Clock,Reset,Enable,ClockN and DiffClock.

clash-lib/src/Clash/Netlist/BlackBox/Util.hs

Lines changed: 77 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ import Text.Read (readEither)
5757
import Text.Trifecta.Result hiding (Err)
5858

5959
import Clash.Backend
60-
(Backend (..), Usage (..), AggressiveXOptBB(..), RenderEnums(..))
60+
(Backend (..), DomainMap, Usage (..), AggressiveXOptBB(..), RenderEnums(..))
6161
import Clash.Netlist.BlackBox.Parser
6262
import Clash.Netlist.BlackBox.Types
6363
import Clash.Netlist.Types
6464
(BlackBoxContext (..), Expr (..), HWType (..), Literal (..), Modifier (..),
6565
Declaration(BlackBoxD))
6666
import qualified Clash.Netlist.Id as Id
6767
import qualified Clash.Netlist.Types as N
68-
import Clash.Netlist.Util (typeSize, isVoid, stripVoid)
68+
import Clash.Netlist.Util (typeSize, isVoid, stripAttributes, stripVoid)
6969
import Clash.Signal.Internal
7070
(ResetKind(..), ResetPolarity(..), InitBehavior(..), VDomainConfiguration (..))
7171
import Clash.Util
@@ -493,20 +493,20 @@ renderElem b (IF c t f) = do
493493
syn <- hdlSyn
494494
enums <- renderEnums
495495
xOpt <- aggressiveXOptBB
496-
let c' = check (coerce xOpt) iw hdl syn enums c
496+
c' <- check (coerce xOpt) iw hdl syn enums c
497497
if c' > 0 then renderTemplate b t else renderTemplate b f
498498
where
499-
check :: Bool -> Int -> HDL -> HdlSyn -> RenderEnums -> Element -> Int
499+
check :: Backend backend => Bool -> Int -> HDL -> HdlSyn -> RenderEnums -> Element -> State backend Int
500500
check xOpt iw hdl syn enums c' = case c' of
501-
(Size e) -> typeSize (lineToType b [e])
502-
(Length e) -> case lineToType b [e] of
501+
(Size e) -> pure $ typeSize (lineToType b [e])
502+
(Length e) -> pure $ case lineToType b [e] of
503503
(Vector n _) -> n
504504
Void (Just (Vector n _)) -> n
505505
(MemBlob n _) -> n
506506
Void (Just (MemBlob n _)) -> n
507507
_ -> 0 -- HACK: So we can test in splitAt if one of the
508508
-- vectors in the tuple had a zero length
509-
(Lit n) -> case bbInputs b !! n of
509+
(Lit n) -> pure $ case bbInputs b !! n of
510510
(l,_,_)
511511
| Literal _ l' <- l ->
512512
case l' of
@@ -534,16 +534,16 @@ renderElem b (IF c t f) = do
534534
, [Literal _ (NumLit j)] <- extractLiterals bbCtx
535535
-> fromInteger j
536536
k -> error $ $(curLoc) ++ ("IF: LIT must be a numeric lit:" ++ show k)
537-
(Depth e) -> case lineToType b [e] of
537+
(Depth e) -> pure $ case lineToType b [e] of
538538
(RTree n _) -> n
539539
_ -> error $ $(curLoc) ++ "IF: treedepth of non-tree type"
540-
IW64 -> if iw == 64 then 1 else 0
541-
(HdlSyn s) -> if s == syn then 1 else 0
542-
(IsVar n) -> let (e,_,_) = bbInputs b !! n
540+
IW64 -> pure $ if iw == 64 then 1 else 0
541+
(HdlSyn s) -> pure $ if s == syn then 1 else 0
542+
(IsVar n) -> pure $ let (e,_,_) = bbInputs b !! n
543543
in case e of
544544
Identifier _ Nothing -> 1
545545
_ -> 0
546-
(IsLit n) -> let (e,_,_) = bbInputs b !! n
546+
(IsLit n) -> pure $ let (e,_,_) = bbInputs b !! n
547547
in case e of
548548
DataCon {} -> 1
549549
Literal {} -> 1
@@ -557,13 +557,13 @@ renderElem b (IF c t f) = do
557557
RenderEnums True -> 1
558558
RenderEnums False -> 0
559559
isScalar _ _ = 0
560-
in isScalar hdl ty
560+
in pure $ isScalar hdl ty
561561

562-
(IsUndefined n) ->
562+
(IsUndefined n) -> pure $
563563
let (e, _, _) = bbInputs b !! n
564564
in if xOpt && checkUndefined e then 1 else 0
565565

566-
(IsActiveEnable n) ->
566+
(IsActiveEnable n) -> pure $
567567
let (e, ty, _) = bbInputs b !! n in
568568
case ty of
569569
Enable _ ->
@@ -585,52 +585,81 @@ renderElem b (IF c t f) = do
585585
_ ->
586586
error $ $(curLoc) ++ "IsActiveEnable: Expected Bool or Enable, not: " ++ show ty
587587

588-
(ActiveEdge edgeRequested n) ->
589-
let (_, ty, _) = bbInputs b !! n in
590-
case stripVoid ty of
591-
KnownDomain _ _ edgeActual _ _ _ ->
588+
(ActiveEdge edgeRequested n) -> do
589+
let (_, ty, _) = bbInputs b !! n
590+
domConf <- getDomainConf ty
591+
case domConf of
592+
VDomainConfiguration _ _ edgeActual _ _ _ -> pure $
592593
if edgeRequested == edgeActual then 1 else 0
593-
_ ->
594-
error $ $(curLoc) ++ "ActiveEdge: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty
595-
596-
(IsSync n) ->
597-
let (_, ty, _) = bbInputs b !! n in
598-
case stripVoid ty of
599-
KnownDomain _ _ _ Synchronous _ _ -> 1
600-
KnownDomain _ _ _ Asynchronous _ _ -> 0
601-
_ -> error $ $(curLoc) ++ "IsSync: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty
602-
603-
(IsInitDefined n) ->
604-
let (_, ty, _) = bbInputs b !! n in
605-
case stripVoid ty of
606-
KnownDomain _ _ _ _ Defined _ -> 1
607-
KnownDomain _ _ _ _ Unknown _ -> 0
608-
_ -> error $ $(curLoc) ++ "IsInitDefined: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty
609-
610-
(IsActiveHigh n) ->
611-
let (_, ty, _) = bbInputs b !! n in
612-
case stripVoid ty of
613-
KnownDomain _ _ _ _ _ ActiveHigh -> 1
614-
KnownDomain _ _ _ _ _ ActiveLow -> 0
615-
_ -> error $ $(curLoc) ++ "IsActiveHigh: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty
616-
617-
(StrCmp [Text t1] n) ->
594+
595+
(IsSync n) -> do
596+
let (_, ty, _) = bbInputs b !! n
597+
domConf <- getDomainConf ty
598+
case domConf of
599+
VDomainConfiguration _ _ _ Synchronous _ _ -> pure 1
600+
VDomainConfiguration _ _ _ Asynchronous _ _ -> pure 0
601+
602+
(IsInitDefined n) -> do
603+
let (_, ty, _) = bbInputs b !! n
604+
domConf <- getDomainConf ty
605+
case domConf of
606+
VDomainConfiguration _ _ _ _ Defined _ -> pure 1
607+
VDomainConfiguration _ _ _ _ Unknown _ -> pure 0
608+
609+
(IsActiveHigh n) -> do
610+
let (_, ty, _) = bbInputs b !! n
611+
domConf <- getDomainConf ty
612+
case domConf of
613+
VDomainConfiguration _ _ _ _ _ ActiveHigh -> pure 1
614+
VDomainConfiguration _ _ _ _ _ ActiveLow -> pure 0
615+
616+
(StrCmp [Text t1] n) -> pure $
618617
let (e,_,_) = bbInputs b !! n
619618
in case exprToString e of
620619
Just t2
621620
| t1 == Text.pack t2 -> 1
622621
| otherwise -> 0
623622
Nothing -> error $ $(curLoc) ++ "Expected a string literal: " ++ show e
624-
(And es) -> if all (/=0) (map (check xOpt iw hdl syn enums) es)
623+
(And es) -> do
624+
es' <- mapM (check xOpt iw hdl syn enums) es
625+
pure $ if all (/=0) es'
625626
then 1
626627
else 0
627-
CmpLE e1 e2 -> if check xOpt iw hdl syn enums e1 <= check xOpt iw hdl syn enums e2
628-
then 1
629-
else 0
628+
CmpLE e1 e2 -> do
629+
v1 <- check xOpt iw hdl syn enums e1
630+
v2 <- check xOpt iw hdl syn enums e2
631+
if v1 <= v2
632+
then pure 1
633+
else pure 0
630634
_ -> error $ $(curLoc) ++ "IF: condition must be: SIZE, LENGTH, LIT, DEPTH, IW64, VIVADO, OTHERSYN, ISVAR, ISLIT, ISUNDEFINED, ISACTIVEENABLE, ACTIVEEDGE, ISSYNC, ISINITDEFINED, ISACTIVEHIGH, STRCMP, AND, ISSCALAR or CMPLE."
631635
++ "\nGot: " ++ show c'
632636
renderElem b e = fmap const (renderTag b e)
633637

638+
getDomainConf :: (Backend backend, HasCallStack) => HWType -> State backend VDomainConfiguration
639+
getDomainConf = generalGetDomainConf domainConfigurations
640+
641+
generalGetDomainConf
642+
:: forall m. (Monad m, HasCallStack)
643+
=> (m DomainMap) -- ^ a way to get the `DomainMap`
644+
-> HWType -> m VDomainConfiguration
645+
generalGetDomainConf getDomainMap ty = case (snd . stripAttributes . stripVoid) ty of
646+
KnownDomain dom period activeEdge resetKind initBehavior resetPolarity ->
647+
pure $ VDomainConfiguration (Data.Text.unpack dom) (fromIntegral period) activeEdge resetKind initBehavior resetPolarity
648+
649+
Clock dom -> go dom
650+
ClockN dom -> go dom
651+
Reset dom -> go dom
652+
Enable dom -> go dom
653+
Product _DiffClock _ [Clock dom,_clkN] -> go dom
654+
t -> error $ "Don't know how to get a Domain out of HWType: " <> show t
655+
where
656+
go :: HasCallStack => N.DomainName -> m VDomainConfiguration
657+
go dom = do
658+
doms <- getDomainMap
659+
case HashMap.lookup dom doms of
660+
Nothing -> error $ "Can't find domain " <> show dom <> ". Please report an issue at https://github.com/clash-lang/clash-compiler/issues."
661+
Just conf -> pure conf
662+
634663
parseFail :: Text -> BlackBoxTemplate
635664
parseFail t = case runParse t of
636665
Failure errInfo ->

clash-prelude/src/Clash/Tutorial.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,16 +1290,16 @@ a general listing of the available template holes:
12901290
* @~TAG[N]@: Name of given domain. Errors when called on an argument which is not
12911291
a 'KnownDomain', 'Reset', or 'Clock'.
12921292
* @~PERIOD[N]@: Clock period of given domain. Errors when called on an argument
1293-
which is not a 'KnownDomain' or 'KnownConf'.
1293+
which is not a 'Clock', 'Reset', 'KnownDomain' or 'KnownConf'.
12941294
* @~ISACTIVEENABLE[N]@: Is the @(N+1)@'th argument a an Enable line NOT set to a
12951295
constant True. Can be used instead of deprecated (and removed) template tag
12961296
* @~ISSYNC[N]@: Does synthesis domain at the @(N+1)@'th argument have synchronous resets. Errors
1297-
when called on an argument which is not a 'KnownDomain' or 'KnownConf'.
1297+
when called on an argument which is not a 'Reset', 'Clock', 'Enable', 'KnownDomain' or 'KnownConf'.
12981298
* @~ISINITDEFINED[N]@: Does synthesis domain at the @(N+1)@'th argument have defined initial
1299-
values. Errors when called on an argument which is not a 'KnownDomain' or 'KnownConf'.
1299+
values. Errors when called on an argument which is not a 'Clock', 'Reset', 'Enable', 'KnownDomain' or 'KnownConf'.
13001300
* @~ACTIVEEDGE[edge][N]@: Does synthesis domain at the @(N+1)@'th argument respond to
13011301
/edge/. /edge/ must be one of 'Falling' or 'Rising'. Errors when called on an
1302-
argument which is not a 'KnownDomain' or 'KnownConf'.
1302+
argument which is not a 'Clock', 'Reset', 'Enable', 'KnownDomain' or 'KnownConf'.
13031303
* @~AND[\<HOLE1\>,\<HOLE2\>,..]@: Logically /and/ the conditions in the @\<HOLE\>@'s
13041304
* @~VAR[\<NAME\>][N]@: Like @~ARG[N]@ but binds the argument to a variable named NAME.
13051305
The @\<NAME\>@ can be left blank, then clash will come up with a (unique) name.

0 commit comments

Comments
 (0)