@@ -34,12 +34,13 @@ module Clash.XException
3434 -- * Printing 'X' exceptions as \"X\"
3535 , ShowX (.. ), showsX , printX , showsPrecXWith
3636 -- * Strict evaluation
37- , seqX , forceX , deepseqX , rwhnfX , defaultSeqX
37+ , seqX , forceX , deepseqX , rwhnfX , defaultSeqX , hwSeqX
3838 -- * Structured undefined / deep evaluation with undefined values
3939 , NFDataX (rnfX , deepErrorX , hasUndefined , ensureSpine )
4040 )
4141where
4242
43+ import Clash.Annotations.Primitive (hasBlackBox )
4344import Clash.CPP (maxTupleSize )
4445import Clash.XException.TH
4546import Control.Exception (Exception , catch , evaluate , throw )
@@ -111,6 +112,25 @@ seqX a b = unsafeDupablePerformIO
111112{-# NOINLINE seqX #-}
112113infixr 0 `seqX`
113114
115+ -- | Like 'seqX' in simulation, but will force its first argument to be rendered
116+ -- in HDL. This is useful for components that need to be rendered in hardware,
117+ -- but otherwise have no meaning in simulation. An example of such a component
118+ -- would be an ILA: a component monitoring an internal signal of a design. The
119+ -- output of such a component (typically a unit) can be passed as the first
120+ -- argument to 'hwSeqX' to ensure the ILA ends up in the generated HDL.
121+ --
122+ -- __NB__: the result of 'hwSeqX' must (indirectly) be used at the very top of
123+ -- a design. If it's not, Clash will remove it like it does for any other unused
124+ -- circuit parts.
125+ --
126+ -- __NB__: Make sure the blackbox for the component with zero-width results
127+ -- uses 'Clash.Netlist.BlackBox.Types.RenderVoid'
128+ hwSeqX :: a -> b -> b
129+ hwSeqX = seqX
130+ {-# NOINLINE hwSeqX #-}
131+ {-# ANN hwSeqX hasBlackBox #-}
132+ infixr 0 `hwSeqX`
133+
114134-- | Evaluate a value with given function, returning 'Nothing' if it throws
115135-- 'XException'.
116136--
0 commit comments