packages feed

clash-lib 1.8.4 → 1.8.5

raw patch · 25 files changed

+220/−74 lines, 25 filesdep ~clash-preludePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: clash-prelude

API changes (from Hackage documentation)

+ Clash.Core.Subst: acmpTerm :: Term -> Term -> Ordering
+ Clash.Core.Term: Attributes :: Type -> Term -> TickInfo
+ Clash.Driver.Types: [opt_ghcDebugLevel] :: ClashOpts -> Int
+ Clash.Netlist.Types: [_localAttrs] :: NetlistEnv -> [Attr Text]
+ Clash.Netlist.Types: [_peEvaluator] :: NetlistEnv -> Evaluator
+ Clash.Netlist.Types: localAttrs :: Lens' NetlistEnv [Attr Text]
+ Clash.Netlist.Types: peEvaluator :: Lens' NetlistEnv Evaluator
- Clash.Driver.Types: ClashOpts :: Bool -> Int -> Int -> Word -> Word -> Word -> DebugOpts -> Bool -> Bool -> Bool -> OverridingBool -> Int -> Maybe String -> HdlSyn -> Bool -> [FilePath] -> Maybe Text -> Bool -> Bool -> PreserveCase -> Bool -> Maybe (Maybe Int) -> Bool -> Bool -> Bool -> Word -> Bool -> Bool -> Period -> ClashOpts
+ Clash.Driver.Types: ClashOpts :: Bool -> Int -> Int -> Word -> Word -> Word -> DebugOpts -> Int -> Bool -> Bool -> Bool -> OverridingBool -> Int -> Maybe String -> HdlSyn -> Bool -> [FilePath] -> Maybe Text -> Bool -> Bool -> PreserveCase -> Bool -> Maybe (Maybe Int) -> Bool -> Bool -> Bool -> Word -> Bool -> Bool -> Period -> ClashOpts
- Clash.Netlist: genNetlist :: ClashEnv -> Bool -> BindingMap -> VarEnv TopEntityT -> VarEnv Identifier -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Bool -> SomeBackend -> IdentifierSet -> FilePath -> Maybe Text -> Id -> IO (Component, ComponentMap, IdentifierSet)
+ Clash.Netlist: genNetlist :: ClashEnv -> Evaluator -> Bool -> BindingMap -> VarEnv TopEntityT -> VarEnv Identifier -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Bool -> SomeBackend -> IdentifierSet -> FilePath -> Maybe Text -> Id -> IO (Component, ComponentMap, IdentifierSet)
- Clash.Netlist: runNetlistMonad :: ClashEnv -> Bool -> BindingMap -> VarEnv TopEntityT -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Bool -> SomeBackend -> IdentifierSet -> FilePath -> VarEnv Identifier -> NetlistMonad a -> IO (a, NetlistState)
+ Clash.Netlist: runNetlistMonad :: ClashEnv -> Evaluator -> Bool -> BindingMap -> VarEnv TopEntityT -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Bool -> SomeBackend -> IdentifierSet -> FilePath -> VarEnv Identifier -> NetlistMonad a -> IO (a, NetlistState)
- Clash.Netlist.Types: NetlistEnv :: ClashEnv -> Text -> Text -> Maybe Text -> NetlistEnv
+ Clash.Netlist.Types: NetlistEnv :: ClashEnv -> Text -> Text -> Maybe Text -> [Attr Text] -> Evaluator -> NetlistEnv
- Clash.Rewrite.Types: bindings :: forall extra_a4GHC. Lens' (RewriteState extra_a4GHC) BindingMap
+ Clash.Rewrite.Types: bindings :: forall extra_a4HGd. Lens' (RewriteState extra_a4HGd) BindingMap
- Clash.Rewrite.Types: curFun :: forall extra_a4GHC. Lens' (RewriteState extra_a4GHC) (Id, SrcSpan)
+ Clash.Rewrite.Types: curFun :: forall extra_a4HGd. Lens' (RewriteState extra_a4HGd) (Id, SrcSpan)
- Clash.Rewrite.Types: extra :: forall extra_a4GHC extra_a4GSV. Lens (RewriteState extra_a4GHC) (RewriteState extra_a4GSV) extra_a4GHC extra_a4GSV
+ Clash.Rewrite.Types: extra :: forall extra_a4HGd extra_a4HRw. Lens (RewriteState extra_a4HGd) (RewriteState extra_a4HRw) extra_a4HGd extra_a4HRw
- Clash.Rewrite.Types: globalHeap :: forall extra_a4GHC. Lens' (RewriteState extra_a4GHC) PrimHeap
+ Clash.Rewrite.Types: globalHeap :: forall extra_a4HGd. Lens' (RewriteState extra_a4HGd) PrimHeap
- Clash.Rewrite.Types: nameCounter :: forall extra_a4GHC. Lens' (RewriteState extra_a4GHC) Int
+ Clash.Rewrite.Types: nameCounter :: forall extra_a4HGd. Lens' (RewriteState extra_a4HGd) Int
- Clash.Rewrite.Types: transformCounter :: forall extra_a4GHC. Lens' (RewriteState extra_a4GHC) Word
+ Clash.Rewrite.Types: transformCounter :: forall extra_a4HGd. Lens' (RewriteState extra_a4HGd) Word
- Clash.Rewrite.Types: transformCounters :: forall extra_a4GHC. Lens' (RewriteState extra_a4GHC) (HashMap Text Word)
+ Clash.Rewrite.Types: transformCounters :: forall extra_a4HGd. Lens' (RewriteState extra_a4HGd) (HashMap Text Word)
- Clash.Rewrite.Types: uniqSupply :: forall extra_a4GHC. Lens' (RewriteState extra_a4GHC) Supply
+ Clash.Rewrite.Types: uniqSupply :: forall extra_a4HGd. Lens' (RewriteState extra_a4HGd) Supply
- Clash.Rewrite.Types: workFreeBinders :: forall extra_a4GHC. Lens' (RewriteState extra_a4GHC) (VarEnv Bool)
+ Clash.Rewrite.Types: workFreeBinders :: forall extra_a4HGd. Lens' (RewriteState extra_a4HGd) (VarEnv Bool)

Files

CHANGELOG.md view
@@ -1,5 +1,25 @@ # Changelog for the Clash project +## 1.8.5 *Mar 24th, 2026*++Added:+* `Clash.Annotation.SynthesisAtrributes.annotateReg`, a function to add synthesis attributes (e.g. `ASYNC_REG`) to register declarations in the HDL generated by the Clash compiler.+  [#3093](https://github.com/clash-lang/clash-compiler/pull/3093)+* `registerSyncReset` [#3115](https://github.com/clash-lang/clash-compiler/issues/3115)++Fixed:+* The `Clash.Explicit.Verification.check` blackbox now correctly uses the given clock line, not assuming any longer that it is already bound to an identifier in the first place. [#2907](https://github.com/clash-lang/clash-compiler/issues/2907)+* The type of string literals passed to the `Clash.Explicit.Verification.check` blackbox now matches with the input provided via `Clash.Explicit.Verification.name`. [#2908](https://github.com/clash-lang/clash-compiler/issues/2908)+* `toInteger`, `toEnum`, and `fromEnum` now correctly sign extend when using Verilog backend. [#2729](https://github.com/clash-lang/clash-compiler/issues/2729).+* `dumpVCD` now properly aligns the first clock edges in multi-domain designs. [#3075](https://github.com/clash-lang/clash-compiler/issues/3075)+* Removed the limit on the number of traces in `dumpVCD`. Also removed unnecessary double newlines after 1-bit signals. [#3082](https://github.com/clash-lang/clash-compiler/issues/3082)+* In Clash simulation, `pack` for `Vec` and `RTree` had all bits undefined when the spine of the value had an `XException`. Now, those elements with defined bits will output those defined bits. In HDL, this was already the case. Example: consider `xs = 1 :> undefined :> Nil :: Vec 2 (Unsigned 4)` and `ys = 1 :> undefined :: Vec 2 (Unsigned 4)`. `xs` merely has an undefined element, but `ys` has an undefined spine: it is a `:>` constructor that is undefined. `pack ys` used to be `0b...._....` but is now `0b0001_....`, just as `pack xs` already was.+  [#3114](https://github.com/clash-lang/clash-compiler/pull/3114)+* Clash drops cached normalization result. [#3109](https://github.com/clash-lang/clash-compiler/issues/3109)+* Fix `holdReset` glitch behavior for asynchronous resets and wrong hold cycles for sync resets. [#3115](https://github.com/clash-lang/clash-compiler/issues/3115)+* Do not emit source locations if `-g` is not passed to clash [#3132](https://github.com/clash-lang/clash-compiler/issues/3132)+* `clash-ghc`: Remove `Opt_LlvmTBAA` from unwanted flags [#2508](https://github.com/clash-lang/clash-compiler/issues/2823)+ ## 1.8.4 *Nov 6th 2025*  Changed:@@ -314,7 +334,7 @@ Added:   * `Clash.Class.Counter`: a class that defines a odometer-style supercounter. [#1763](https://github.com/clash-lang/clash-compiler/pull/1763)   * `isLike` function for BitPack types. [#1774](https://github.com/clash-lang/clash-compiler/pull/1774)-  * 'seqErrorX' for catching both `XException` and `ErrorCall`. [#1774](https://github.com/clash-lang/clash-compiler/pull/1774)+  * 'seqErrorX' for catching both `XException` and `ErrorCall`. [#1839](https://github.com/clash-lang/clash-compiler/pull/1839)   * `Clash.Explicit.BlockRam.File.memFile`, a function for creating the contents of the data files this blockRAM uses. Can also be imported from `Clash.Prelude.BlockRam.File`, `Clash.Prelude.ROM.File` and `Clash.Explicit.ROM.File`. [#1840](https://github.com/clash-lang/clash-compiler/pull/1840)   * Support for Yosys compatible SVA to `Clash.Verification`. This enables formal verification using SymbiYosis for Verilog and SystemVerilog. [#1798](https://github.com/clash-lang/clash-compiler/pull/1798)   * `Clash.Explicit.Signal.Delayed.forward`, a function that can be used to retime a `DSignal` into the future without applying any logic. [#1882](https://github.com/clash-lang/clash-compiler/pull/1882)
clash-lib.cabal view
@@ -1,6 +1,6 @@ Cabal-version:        2.2 Name:                 clash-lib-Version:              1.8.4+Version:              1.8.5 Synopsis:             Clash: a functional hardware description language - As a library Description:   Clash is a functional hardware description language that borrows both its@@ -151,7 +151,7 @@                       base16-bytestring       >= 0.1.1    && < 1.1,                       binary                  >= 0.8.5    && < 0.11,                       bytestring              >= 0.10.0.2 && < 0.13,-                      clash-prelude           == 1.8.4,+                      clash-prelude           == 1.8.5,                       containers              >= 0.5.0.0  && < 0.8,                       cryptohash-sha256       >= 0.11     && < 0.12,                       data-binary-ieee754     >= 0.4.4    && < 0.6,@@ -380,7 +380,7 @@     build-depends:       base,       clash-lib,-      doctest-parallel >= 0.2 && < 0.4,+      doctest-parallel >= 0.2 && < 0.5,       filepath  test-suite unittests
+ prims/common/Clash_Annotations_SynthesisAttributes.primitives.yaml view
@@ -0,0 +1,3 @@+- Primitive:+    name: Clash.Annotations.SynthesisAttributes.annotateReg+    primType: Function
prims/commonverilog/Clash_Sized_Internal_Signed.primitives.yaml view
@@ -44,7 +44,7 @@     type: 'fromEnum# :: KnownNat       n => Signed n -> Int'     template: ~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$signed(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])-      {1'b0}},~VAR[i][1]})~FI~ELSE~SIZE[~TYPO]'sd0~FI+      {~VAR[i][1][~SIZE[~TYP[1]]-1]}},~VAR[i][1]})~FI~ELSE~SIZE[~TYPO]'sd0~FI     workInfo: Never - BlackBox:     name: Clash.Sized.Internal.Signed.size#@@ -118,7 +118,7 @@     type: 'toEnum# :: KnownNat       n => Int -> Signed n'     template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$signed(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])-      {1'b0}},~VAR[i][1]})~FI+      {~VAR[i][1][~SIZE[~TYP[1]]-1]}},~VAR[i][1]})~FI     workInfo: Never - BlackBox:     name: Clash.Sized.Internal.Signed.plus#
prims/systemverilog/Clash_Signal_Internal.primitives.yaml view
@@ -94,7 +94,7 @@         => Signal dom Bool     -- ARG[1]         -> Clock dom     template: |--      // tbClockGen begin+      // ~IF~ISACTIVEENABLE[1]~THENtbClockGen~ELSEclockGen~FI begin       // pragma translate_off       // 1 = 0.1ps       localparam ~GENSYM[half_period][0] = (~PERIOD[0]0 / 2);
prims/verilog/Clash_Signal_Internal.primitives.yaml view
@@ -93,7 +93,7 @@         => Signal dom Bool     -- ARG[1]         -> Clock dom     template: |--      // tbClockGen begin+      // ~IF~ISACTIVEENABLE[1]~THENtbClockGen~ELSEclockGen~FI begin       // pragma translate_off       reg ~TYPO ~GENSYM[clk][0];       // 1 = 0.1ps
prims/vhdl/Clash_Signal_Internal.primitives.yaml view
@@ -141,7 +141,7 @@         => Signal dom Bool     -- ARG[1]         -> Clock dom     template: |--      -- tbClockGen begin+      -- ~IF~ISACTIVEENABLE[1]~THENtbClockGen~ELSEclockGen~FI begin       -- pragma translate_off       ~GENSYM[clkGen][0] : process is         constant ~GENSYM[half_periodH][1] : time := ~PERIOD[0]000 fs / 2;
src/Clash/Core/EqSolver.hs view
@@ -92,7 +92,7 @@             []  -- | Solve equations supported by @normalizeAdd@. See documentation of--- @TypeEqSolution@ to understand the return value.+-- 'TypeEqSolution' to understand the return value. solveAdd   :: VarSet   -> (Type, Type)@@ -134,7 +134,7 @@   lhsLit _                 _                 = Nothing  -- | Tests for nonsencical patterns due to types being "absurd". See--- @isAbsurdEq@ for more info.+-- 'isAbsurdEq' for more info. isAbsurdPat   :: TyConMap   -> Pat@@ -152,7 +152,7 @@     DataPat _dc extNms _ids -> mkVarSet extNms     _ -> emptyVarSet --- | Determines if an "equation" obtained through @patEqs@ or @typeEq@ is+-- | Determines if an "equation" obtained through 'patEqs' or 'typeEq' is -- absurd. That is, it tests if two types that are definitely not equal are -- asserted to be equal OR if the computation of the types yield some absurd -- (intermediate) result such as -1.
src/Clash/Core/Evaluator/Types.hs view
@@ -80,10 +80,10 @@ -- define partial evaluation. In this implementation, it consists of two types -- of function: -----   * steps, which applies the reduction realtion to the current term+--   * steps, which applies the reduction relation to the current term --   * unwindings, which pop the stack and evaluate the stack frame ----- Variants of these functions also exist for evalauting primitive operations.+-- Variants of these functions also exist for evaluating primitive operations. -- This is because there may be multiple frontends to the compiler which can -- reuse a common step and unwind, but have different primitives. --
src/Clash/Core/FreeVars.hs view
@@ -281,6 +281,8 @@    goTick inLocalScope = \case     NameMod m ty -> NameMod m <$> typeFreeVars' interesting inLocalScope f ty+    Attributes ty tm -> Attributes <$> typeFreeVars' interesting inLocalScope f ty+                                   <*> go inLocalScope tm     tick         -> pure tick  -- | Get the free variables of an expression and count the number of occurrences
src/Clash/Core/Pretty.hs view
@@ -246,7 +246,7 @@   pprPrec _ = pure . pretty  instance PrettyPrec Type where-  pprPrec _ t = annotate (AnnSyntax Type) <$> pprType t+  pprPrec _ t = pprType t  instance ClashPretty Type where   clashPretty = fromPpr@@ -265,7 +265,7 @@         name <- pprPrec prec dc         ty <- pprType (dcType dc) -        pure (name <+> dcolon <+> ty)+        pure (name <> annotate (AnnSyntax Type) (space <> dcolon <+> ty))      AlgTyCon _ nm kn _ (NewTyCon dc _) _ -> do       name <- pprPrec prec nm@@ -275,7 +275,7 @@       conName <- pprPrec prec (dcName dc)       conType <- pprType (dcType dc) -      pure (vsep [newtype_ <+> decl, conName <+> dcolon <+> conType])+      pure (vsep [newtype_ <+> decl, conName <> annotate (AnnSyntax Type) (space <> dcolon <+> conType)])      PromotedDataCon _ _ _ _ dc ->       fmap ("promoted" <+>) (pprPrec prec dc)@@ -313,7 +313,7 @@     Var x           -> do       v <- pprPrec prec (varName x)       s <- pprPrecIdScope x-      pure (v <> brackets s)+      pure (v <> annotate (AnnSyntax Unique) (brackets s))     Data dc         -> pprPrec prec dc     Literal l       -> pprPrec prec l     Prim p          -> pprPrecPrim prec (primName p)@@ -341,6 +341,7 @@   pprPrec prec (NameMod SetName t)    = ("<setName>" <>) <$> pprPrec prec t   pprPrec _    DeDup                  = pure "<deDup>"   pprPrec _    NoDeDup                = pure "<noDeDup>"+  pprPrec prec (Attributes _ attrs)   = ("<attributes>" <>) <$> pprPrec prec attrs  instance PrettyPrec SrcSpan where   pprPrec _ sp = return ("<src>"<>pretty (GHC.showSDocUnsafe (GHC.ppr sp)))
src/Clash/Core/Subst.hs view
@@ -56,6 +56,7 @@     -- * Alpha equivalence   , aeqType   , aeqTerm+  , acmpTerm     -- * Structural equivalence   , eqTerm   , eqType@@ -584,6 +585,7 @@   goTick (NameMod m ty) = NameMod m (substTy subst ty)   goTick t@DeDup        = t   goTick t@NoDeDup      = t+  goTick (Attributes ty tm) = Attributes (substTy subst ty) (go tm)  -- | Substitute within a case-alternative substAlt
src/Clash/Core/Subst.hs-boot view
@@ -3,6 +3,7 @@ module Clash.Core.Subst where  import GHC.Stack (HasCallStack)+import {-# SOURCE #-} Clash.Core.Term (Term) import {-# SOURCE #-} Clash.Core.Type (Type) import Clash.Core.Var (TyVar) @@ -20,3 +21,7 @@  instance Eq Type instance Ord Type++acmpTerm :: Term -> Term -> Ordering++instance Eq Term
src/Clash/Core/Term.hs view
@@ -81,7 +81,7 @@ import Clash.Core.DataCon                      (DataCon) import Clash.Core.Literal                      (Literal) import Clash.Core.Name                         (Name (..))-import {-# SOURCE #-} Clash.Core.Subst         () -- instance Eq/Ord Type+import {-# SOURCE #-} Clash.Core.Subst         (acmpTerm) -- instance Eq/Ord Type, Eq Term import {-# SOURCE #-} Clash.Core.Type          (Type) import Clash.Core.Var                          (Var, Id, TyVar) import Clash.Util                              (curLoc, thenCompare)@@ -124,19 +124,25 @@   | NoDeDup   -- ^ Do not deduplicate, i.e. /keep/, an expression inside a case-alternative;   -- do not try to share expressions between multiple branches.+  | Attributes Type Term+  -- ^ Synthesis attributes brough into scope by+  -- 'Clash.Annotations.SynthesisAttributes.annotateReg'   deriving (Eq, Show, Generic, NFData, Binary)  instance Ord TickInfo where   compare (SrcSpan s1) (SrcSpan s2) = leftmost_smallest s1 s2   compare (NameMod m1 t1) (NameMod m2 t2) =     compare m1 m2 `thenCompare` compare t1 t2+  compare (Attributes t1 a1) (Attributes t2 a2) =+    compare t1 t2 `thenCompare` acmpTerm a1 a2   compare t1 t2 = compare (getRank t1) (getRank t2)     where       getRank :: TickInfo -> Word-      getRank SrcSpan{} = 0-      getRank NameMod{} = 1-      getRank DeDup     = 2-      getRank NoDeDup   = 3+      getRank SrcSpan{}     = 0+      getRank NameMod{}     = 1+      getRank DeDup         = 2+      getRank NoDeDup       = 3+      getRank Attributes {} = 4  -- | Tag to indicate which instance/register name modifier was used data NameMod
src/Clash/Core/TermLiteral.hs view
@@ -129,6 +129,7 @@ instance TermLiteral Integer where   termToData (Tick _ e) = termToData e   termToData (Literal (IntegerLiteral n)) = Right n+  termToData (collectArgs -> (_, [Left (Literal (IntLiteral n))])) = Right n   termToData (collectArgs -> (_, [Left (Literal (IntegerLiteral n))])) = Right n   termToData t = Left t 
src/Clash/Driver.hs view
@@ -458,7 +458,7 @@       (topComponent, netlist) <- modifyMVar seenV $ \seen -> do         (topComponent, netlist, seen') <-           -- TODO My word, this has far too many arguments.-          genNetlist env isTb transformedBindings topEntityMap compNames+          genNetlist env peEval isTb transformedBindings topEntityMap compNames             typeTrans ite (SomeBackend hdlState') seen hdlDir prefixM topEntity          pure (seen', (topComponent, netlist))
src/Clash/Driver/Types.hs view
@@ -2,8 +2,8 @@   Copyright  :  (C) 2013-2016, University of Twente,                     2016-2017, Myrtle Software Ltd,                     2017     , QBayLogic, Google Inc.,-                    2020-2022, QBayLogic,                     2022     , Google Inc.,+                    2020-2026, QBayLogic,   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -322,6 +322,11 @@   -- Command line flag: -fclash-evaluator-fuel-limit   , opt_debug :: DebugOpts   -- ^ Options which control debugging. See 'DebugOpts'.+  , opt_ghcDebugLevel :: Int+  -- ^ What the GHC debug level is (i.e. @-g<N>@).+  --+  -- Clash uses this to decide whether to emit source-location information in+  -- generated HDL.   , opt_cachehdl :: Bool   -- ^ Reuse previously generated output from Clash. Only caches topentities.   --@@ -411,6 +416,7 @@   , opt_inlineConstantLimit = 0   , opt_evaluatorFuelLimit  = 20   , opt_debug               = debugNone+  , opt_ghcDebugLevel       = 0   , opt_cachehdl            = True   , opt_clear               = False   , opt_primWarn            = True
src/Clash/Netlist.hs view
@@ -2,8 +2,8 @@   Copyright   :  (C) 2012-2016, University of Twente,                      2016-2017, Myrtle Software Ltd,                      2017-2018, Google Inc.,-                     2021-2024, QBayLogic B.V.-                     2022     , Google Inc.+                     2022     , Google Inc.,+                     2021-2026, QBayLogic B.V.   License     :  BSD2 (see the file LICENSE)   Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com> @@ -84,11 +84,13 @@ import           Clash.Primitives.Types           as P import           Clash.Util import qualified Clash.Util.Interpolate           as I+import Clash.Core.PartialEval (Evaluator)  -- | Generate a hierarchical netlist out of a set of global binders with -- @topEntity@ at the top. genNetlist   :: ClashEnv+  -> Evaluator   -> Bool   -- ^ Whether this we're compiling a testbench (suppresses certain warnings)   -> BindingMap@@ -113,9 +115,9 @@   -> Id   -- ^ Name of the @topEntity@   -> IO (Component, ComponentMap, IdentifierSet)-genNetlist env isTb globals tops topNames typeTrans ite be seen0 dir prefixM topEntity = do+genNetlist env eval isTb globals tops topNames typeTrans ite be seen0 dir prefixM topEntity = do   ((_meta, topComponent), s) <--    runNetlistMonad env isTb globals tops typeTrans ite be seen1 dir componentNames_+    runNetlistMonad env eval isTb globals tops typeTrans ite be seen1 dir componentNames_       $ genComponent topEntity   return (topComponent, _components s, seen1)  where@@ -125,6 +127,7 @@ -- | Run a NetlistMonad action in a given environment runNetlistMonad   :: ClashEnv+  -> Evaluator   -> Bool   -- ^ Whether this we're compiling a testbench (suppresses certain warnings)   -> BindingMap@@ -147,8 +150,8 @@   -> NetlistMonad a   -- ^ Action to run   -> IO (a, NetlistState)-runNetlistMonad env isTb s tops typeTrans ite be seenIds_ dir componentNames_-  = flip runReaderT (NetlistEnv env "" "" Nothing)+runNetlistMonad env eval isTb s tops typeTrans ite be seenIds_ dir componentNames_+  = flip runReaderT (NetlistEnv env "" "" Nothing [] eval)   . flip runStateT s'   . runNetlist   where@@ -308,16 +311,33 @@       return (ComponentMeta wereVoids sp ids u, component)  mkNetDecl :: (Id, Term) -> NetlistMonad [Declaration]-mkNetDecl (id_,tm) = preserveVarEnv $ do-  hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (coreTypeOf id_)+mkNetDecl (id_,tm) | (_,_,ticks) <- collectArgsTicks tm = preserveVarEnv $ withTicks ticks $ \_ -> do +  lAttrs <- Lens.view localAttrs+  hwTy0 <- unsafeCoreTypeToHWTypeM' $(curLoc) (coreTypeOf id_)+  let hwTy = case hwTy0 of+        Annotated attrs hty0 -> Annotated (attrs ++ lAttrs) hty0+        hty0 -> annotated lAttrs hty0++  -- GHC starts including sources notes on any debug level greater than 0+  -- we copy this behaviour here.+  emitLocs <- (>0) . opt_ghcDebugLevel <$> Lens.view clashOpts+  let+    srcNote =+      if emitLocs then+        addSrcNote $ case tm of+          Tick (SrcSpan s) _ -> s+          _ -> nameLoc (varName id_)+      else+        Nothing+   if | not (shouldRenderDecl hwTy tm) -> return []      | (Prim pInfo@PrimInfo{primMultiResult=MultiResult}, args) <- collectArgs tm ->-          multiDecls pInfo args-     | otherwise -> pure <$> singleDecl hwTy+          multiDecls srcNote pInfo args+     | otherwise -> pure <$> singleDecl srcNote hwTy    where-    multiDecls pInfo args0 = do+    multiDecls srcNote pInfo args0 = do       tcm <- Lens.view tcCache       resInits0 <- getResInits (id_, tm)       let@@ -331,7 +351,7 @@       hwTys <- mapM (unsafeCoreTypeToHWTypeM' $(curLoc)) (mpi_resultTypes mpInfo)       pure (zipWith3 netdecl res hwTys resInits1) -    singleDecl hwTy = do+    singleDecl srcNote hwTy = do       rIM <- listToMaybe <$> getResInits (id_, tm)       return (NetDecl' srcNote (Id.unsafeFromCoreId id_) hwTy rIM) @@ -339,10 +359,6 @@       | isGoodSrcSpan loc = Just (StrictText.pack (showSDocUnsafe (ppr loc)))       | otherwise = Nothing -    srcNote = addSrcNote $ case tm of-      Tick (SrcSpan s) _ -> s-      _ -> nameLoc (varName id_)-     isMultiPrimSelect :: Term -> Bool     isMultiPrimSelect t = case collectArgs t of       (Prim (primName -> "c$multiPrimSelect"), _) -> True@@ -356,16 +372,16 @@      -- Set the initialization value of a signal when a primitive wants to set it     getResInits :: (Id, Term) -> NetlistMonad [Expr]-    getResInits (i,collectArgsTicks -> (k,args0,ticks)) = case k of+    getResInits (i,collectArgs -> (k,args0)) = case k of       Prim p -> extractPrimWarnOrFail (primName p) >>= go p       _ -> return []      where-      go pInfo (BlackBox {resultInits=nmDs, multiResult=True}) = withTicks ticks $ \_ -> do+      go pInfo (BlackBox {resultInits=nmDs, multiResult=True}) = do         tcm <- Lens.view tcCache         let (args1, res) = splitMultiPrimArgs (multiPrimInfo' tcm pInfo) args0         (bbCtx, _) <- mkBlackBoxContext (primName pInfo) Concurrent res args1         mapM (go' (primName pInfo) bbCtx) nmDs-      go pInfo (BlackBox {resultInits=nmDs}) = withTicks ticks $ \_ -> do+      go pInfo (BlackBox {resultInits=nmDs}) = do         (bbCtx, _) <- mkBlackBoxContext (primName pInfo) Concurrent [i] args0         mapM (go' (primName pInfo) bbCtx) nmDs       go _ _ = pure []
src/Clash/Netlist/Types.hs view
@@ -75,6 +75,7 @@ import Clash.Annotations.TopEntity          (TopEntity) import Clash.Backend                        (Backend, HasUsageMap (..)) import Clash.Core.HasType+import Clash.Core.PartialEval               (Evaluator) import Clash.Core.Type                      (Type) import Clash.Core.Var                       (Id) import Clash.Core.TyCon                     (TyConMap)@@ -282,6 +283,11 @@   -- ^ Postfix for instance/register names   , _setName :: Maybe Text   -- ^ (Maybe) user given instance/register name+  , _localAttrs :: [Attr Text]+  -- ^ Synthesis attributes brough into scope by+  -- 'Clash.Annotations.SynthesisAttributes.annotateReg'+  , _peEvaluator :: Evaluator+  -- ^ Evaluator to evaluate a term to Normal Form   }  data ComponentMeta = ComponentMeta
src/Clash/Netlist/Util.hs view
@@ -55,6 +55,7 @@ import           Data.Maybe   (catMaybes, fromMaybe, isNothing, mapMaybe, isJust, listToMaybe, maybeToList) import           Text.Printf             (printf)+import           Data.Proxy import           Data.Text               (Text) import qualified Data.Text               as Text import           Data.Text.Extra         (showt)@@ -68,6 +69,8 @@ #endif  import           GHC.Stack               (HasCallStack)+import           GHC.TypeLits (someNatVal)+import           GHC.TypeNats (SomeNat(..))  #if MIN_VERSION_ghc(9,0,0) import           GHC.Utils.Monad         (zipWith3M)@@ -90,11 +93,12 @@ import           Clash.Core.DataCon      (DataCon (..)) import           Clash.Core.EqSolver     (typeEq) import           Clash.Core.FreeVars     (typeFreeVars, typeFreeVars')-import           Clash.Core.HasFreeVars  (elemFreeVars)+import           Clash.Core.HasFreeVars  (elemFreeVars, isClosed) import           Clash.Core.HasType import qualified Clash.Core.Literal      as C import           Clash.Core.Name-  (Name (..), appendToName, nameOcc)+  (Name (..), appendToName, mkUnsafeSystemName, nameOcc)+import           Clash.Core.PartialEval import           Clash.Core.Pretty       (showPpr) import           Clash.Core.Subst   (Subst (..), extendIdSubst, extendIdSubstList, extendInScopeId,@@ -103,16 +107,18 @@   (primMultiResult, MultiPrimInfo(..), Alt, LetBinding, Pat (..), Term (..), TickInfo (..), NameMod (..),    IsMultiPrim (..), collectArgsTicks, collectTicks, collectBndrs, PrimInfo(primName), mkTicks, stripTicks) import           Clash.Core.TermInfo+import           Clash.Core.TermLiteral (termToDataError) import           Clash.Core.TyCon   (TyCon (FunTyCon), TyConName, TyConMap, tyConDataCons) import           Clash.Core.Type-  (Type (..), TyVar, TypeView (..), coreView1, normalizeType, splitTyConAppM, tyView)+  (LitTy (..), Type (..), TyVar, TypeView (..), coreView, coreView1, normalizeType,+   splitTyConAppM, tyView) import           Clash.Core.Util   (substArgTys, tyLitShow) import           Clash.Core.Var   (Id, Var (..), mkLocalId, modifyVarName) import           Clash.Core.VarEnv-  (InScopeSet, extendInScopeSetList, uniqAway, lookupVarEnv)+  (InScopeSet, extendInScopeSetList, uniqAway, lookupVarEnv, emptyInScopeSet) import qualified Clash.Data.UniqMap as UniqMap import {-# SOURCE #-} Clash.Netlist.BlackBox import {-# SOURCE #-} Clash.Netlist.BlackBox.Util@@ -121,8 +127,10 @@ import qualified Clash.Netlist.Id as Id import           Clash.Netlist.Types     as HW import           Clash.Primitives.Types+import qualified Clash.Sized.Vector as V import           Clash.Util import qualified Clash.Util.Interpolate  as I+import Clash.Util.Supply  hmFindWithDefault :: (Eq k, Hashable k) => v -> k -> HashMap k v -> v #if MIN_VERSION_unordered_containers(0,2,11)@@ -220,8 +228,7 @@   :: String   -> Type   -> NetlistMonad HWType-unsafeCoreTypeToHWTypeM' loc ty =-  stripFiltered <$> unsafeCoreTypeToHWTypeM loc ty+unsafeCoreTypeToHWTypeM' loc ty = stripFiltered <$> unsafeCoreTypeToHWTypeM loc ty  -- | Converts a Core type to a HWType within the NetlistMonad; errors on failure unsafeCoreTypeToHWTypeM@@ -1881,6 +1888,56 @@   go decls (SrcSpan sp:ticks) =     go (TickDecl (Comment (Text.pack (showSDocUnsafe (ppr sp)))):decls) ticks +  go decls (Attributes ty attrs0:ticks) = do+    -- We have 'Term', `attrs0`, that represents a value of type `Vec n (Attr String)`.+    -- We want to convert this to an actual value of type `Vec n (Attr String)`, for+    -- which we will use `termToDataError`.+    --+    -- The `termToDataError` only works well for completely evaluated literals.+    -- Sometimes we end up with a term which hasn't been complete beta-reduced, e.g.+    -- `(/\b.Nil 0 b (0~0)) Bool` which represents a value of type `Vec 0 Bool`, for+    -- which `termToDataError` would create an error-value.+    --+    -- To ensure that we only pass literals to `termToDataError` we first evaluate+    -- `attrs0` to Normal Form (NF) using the partial evaluators.+    tcm <- Lens.view tcCache+    case coreView tcm ty of+      LitTy (NumTy n)+        | Just (SomeNat (Proxy :: Proxy n)) <- someNatVal n+        -> if isClosed attrs0 then do+            -- Step 1. Evaluate to normal form+            nm <- Lens.use bindings+            ids <- State.liftIO newSupply+            eval <- Lens.view peEvaluator+            let attrsTy = inferCoreTypeOf tcm attrs0+                -- Safe to use `mkUnsafeSystemName` here, because attrs0 has no+                -- free variables (it's closed), meaning there can be no shadowing+                attrsName = mkUnsafeSystemName "attrs" 0+                attrsId = mkLocalId attrsTy attrsName++                genv = mkGlobalEnv nm tcm emptyInScopeSet ids 20 mempty 0+            -- Force attributes term to Normal Form so that it is a simple literal+            -- that is understood by `termToDataError`.+            (attrs1,_) <- State.liftIO (nf eval genv True attrsId attrs0)++            -- Step 2. Create data from the term+            case termToDataError attrs1 of+              Left msg -> error msg+              Right attrs2 ->+                -- Step 3. Finally add the attributes to the environment.+                let attrs3 = fmap (fmap Text.pack) attrs2+                in local (\env -> env {_localAttrs = V.toList @n attrs3}) (go decls ticks)+           else+            error errFV+      _ -> error errNoNum+   where+    errHeader = "ERROR: cannot add attribues: " <> showPpr attrs0+    errNoNum  = unlines [errHeader+                         ,"REASON: Internal length is not a literal" <> showPpr ty]+    errFV     = unlines [errHeader+                         ,"REASON: attributes mentions variables" <> showPpr attrs0+                         ]+   go decls (NameMod m nm0:ticks) = do     tcm <- Lens.view tcCache     case runExcept (tyLitShow tcm nm0) of@@ -1904,7 +1961,7 @@   :: Text   -> NetlistMonad Text affixName nm0 = do-  NetlistEnv _ pre suf _ <- ask+  NetlistEnv _ pre suf _ _ _ <- ask   let nm1 = if Text.null pre then nm0 else pre <> "_" <> nm0       nm2 = if Text.null suf then nm1 else nm1 <> "_" <> suf   return nm2
src/Clash/Normalize.hs view
@@ -18,7 +18,7 @@  import           Control.Exception                (throw) import qualified Control.Lens                     as Lens-import           Control.Monad                    (when)+import           Control.Monad                    ((>=>), when) import           Control.Monad.State.Strict       (State) import           Data.Default                     (def) import           Data.Either                      (lefts,partitionEithers)@@ -143,11 +143,24 @@ normalize   :: [Id]   -> NormalizeSession BindingMap-normalize []  = return emptyVarEnv-normalize top = do-  (new,topNormalized) <- unzip <$> mapM normalize' top-  newNormalized <- normalize (concat new)-  return (unionVarEnv (mkVarEnv topNormalized) newNormalized)+normalize = go >=> unionWithCache+ where+  go []  = return emptyVarEnv+  go top = do+    (new,topNormalized) <- unzip <$> mapM normalize' top+    newNormalized <- normalize (concat new)+    return (unionVarEnv (mkVarEnv topNormalized) newNormalized)++  unionWithCache :: BindingMap -> NormalizeSession BindingMap+  unionWithCache env = do+    cache <- Lens.use (extra.normalized)+    -- We need to include the cache in our final result, forgetting to do so+    -- leads to https://github.com/clash-lang/clash-compiler/issues/3109+    --+    -- On the other hand, just returning the cache as our final result could+    -- not be enough, because normalize' might return a non-normalized binder+    -- that is later picked up and cleaned up by flattenCallTree.+    return (unionVarEnv cache env)  normalize' :: Id -> NormalizeSession ([Id], (Id, Binding Term)) normalize' nm = do
src/Clash/Normalize/Transformations/Cast.hs view
@@ -47,11 +47,11 @@ -- -- The reason d'etre for this transformation is that we hope to end up with -- and expression where two casts are "back-to-back" after which we can--- eliminate them in 'eliminateCastCast'.+-- eliminate them in 'elimCastCast'. argCastSpec :: HasCallStack => NormRewrite argCastSpec ctx e@(App f (stripTicks -> Cast e' _ _))  -- Don't specialise when the arguments are casts-of-casts, these casts-of-casts- -- will be eliminated by 'eliminateCastCast' during the normalization of the+ -- will be eliminated by 'elimCastCast' during the normalization of the  -- "current" function. We thus prevent the unnecessary introduction of a  -- specialized version of 'f'.  | not (isCast e')
src/Clash/Primitives/Sized/Signed.hs view
@@ -3,7 +3,7 @@   License     :  BSD2 (see the file LICENSE)   Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com> -  VHDL Blackbox implementations for "Clash.Sized.Internal.Signed.toInteger#".+  VHDL Blackbox implementations for 'Clash.Sized.Internal.Signed.fromInteger#'. -}  {-# LANGUAGE OverloadedStrings #-}
src/Clash/Primitives/Sized/ToInteger.hs view
@@ -153,7 +153,7 @@     _ -> case hty of       BitVector {} -> "~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[bv][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]]) {1'b0}},~VAR[bv][1]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"       Index {}     -> "~IF~SIZE[~TYP[0]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[0]]]~THEN$unsigned(~VAR[i][0][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[i][0]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"-      Signed {}    -> "~IF~SIZE[~TYP[0]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[0]]]~THEN$signed(~VAR[i][0][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[i][0]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"+      Signed {}    -> "~IF~SIZE[~TYP[0]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[0]]]~THEN$signed(~VAR[i][0][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {~VAR[i][0][~SIZE[~TYP[0]]-1]}},~VAR[i][0]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"       Unsigned {}  -> "~IF~SIZE[~TYP[0]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[0]]]~THEN$unsigned(~VAR[i][0][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[i][0]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"       _            -> error "internal error" 
src/Clash/Primitives/Verification.hs view
@@ -1,3 +1,11 @@+{-|+  Copyright  :  (C) 2019     , Myrtle Software Ltd+                    2021     , Ellie Hermaszewska+                    2020-2025, QBayLogic B.V.+  License    :  BSD2 (see the file LICENSE)+  Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}+ {-# LANGUAGE OverloadedStrings #-}  module Clash.Primitives.Verification (checkBBF) where@@ -11,14 +19,14 @@ import           Data.Maybe                      (listToMaybe) import           Data.Monoid                     (Ap(getAp)) import           Data.Text.Prettyprint.Doc.Extra (Doc)-import qualified Data.Text                       as Text+import           Data.Text                       (Text) import           GHC.Stack                       (HasCallStack)  import           Clash.Annotations.Primitive     (HDL(..)) import           Clash.Backend   (Backend, blockDecl, hdlKind) import           Clash.Core.HasType-import           Clash.Core.Term                 (Term(Var), varToId)+import           Clash.Core.Term                 (Term(Var)) import           Clash.Core.TermLiteral          (termToDataError) import           Clash.Util                      (indexNote) import           Clash.Netlist                   (mkExpr)@@ -41,10 +49,11 @@   case litArgs of     Left err -> pure (Left err)     Right (propName, renderAs, cvProperty0) -> do+      clkBind <- bindMaybe (Just "clk") (indexNote "clk" (lefts args) clkArg)       cvProperty1 <- mapM (uncurry bindMaybe) cvProperty0       let decls = concatMap snd cvProperty1           cvProperty2 = fmap fst cvProperty1-      pure (Right (meta, bb (checkTF decls (clkExpr, clkId) propName renderAs cvProperty2)))+      pure (Right (meta, bb (checkTF decls clkBind propName renderAs cvProperty2)))  where   -- TODO: Improve error handling; currently errors don't indicate what   -- TODO: blackbox generated them.@@ -55,8 +64,6 @@     :< renderAsArg     :< propArg     :< _ = ((0 :: Int)...)-  (Id.unsafeFromCoreId -> clkId) = varToId (indexNote "clk" (lefts args) clkArg)-  clkExpr = Identifier clkId Nothing    litArgs = do     propName <- termToDataError (indexNote "propName" (lefts args) propNameArg)@@ -68,7 +75,7 @@   meta = emptyBlackBoxMeta {bbKind=TDecl, bbRenderVoid=RenderVoid}    bindMaybe-    :: Maybe String+    :: Maybe Text     -- ^ Hint for new identifier     -> Term     -- ^ Term to bind. Does not bind if it's already a reference to a signal@@ -78,7 +85,7 @@   bindMaybe Nothing t = bindMaybe (Just "s") t   bindMaybe (Just nm) t = do     tcm <- Lens.view tcCache-    newId <- Id.make (Text.pack nm)+    newId <- Id.make nm     (expr0, decls) <- mkExpr False Concurrent (NetlistId newId (inferCoreTypeOf tcm t)) t     assn <- contAssign newId expr0     pure@@ -91,8 +98,8 @@  checkTF   :: [Declaration]-  -> (Expr, Identifier)-  -> Text.Text+  -> (Identifier, [Declaration])+  -> Text   -> RenderAs   -> Property' Identifier   -> TemplateFunction@@ -104,20 +111,21 @@    . (HasCallStack, Backend s)   => [Declaration]   -- ^ Extra decls needed-  -> (Expr, Identifier)+  -> (Identifier, [Declaration])   -- ^ Clock-  -> Text.Text+  -> Text   -- ^ Prop name   -> RenderAs   -> Property' Identifier   -> BlackBoxContext   -> State s Doc-checkTF' decls (clk, clkId) propName renderAs prop bbCtx = do+checkTF' decls (clkId, clkDecls) propName renderAs prop bbCtx = do   blockName <- Id.makeBasic (propName <> "_block")-  getAp (blockDecl blockName (renderedPslProperty : decls))+  getAp (blockDecl blockName (clkDecls <> (renderedPslProperty : decls)))   where   hdl = hdlKind (undefined :: s)+  clk = Identifier clkId Nothing    edge =     case bbInputs bbCtx of