Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assert HDL does not use Eq #2245

Open
DigitalBrains1 opened this issue Jun 17, 2022 · 0 comments
Open

assert HDL does not use Eq #2245

DigitalBrains1 opened this issue Jun 17, 2022 · 0 comments
Labels

Comments

@DigitalBrains1
Copy link
Member

DigitalBrains1 commented Jun 17, 2022

As can already be seen from the type signature:

assert
  :: (KnownDomain dom, Eq a, ShowX a)
  => Clock dom
  -> Reset dom
  -> String
  -- ^ Additional message
  -> Signal dom a
  -- ^ Checked value
  -> Signal dom a
  -- ^ Expected value
  -> Signal dom b
  -- ^ Return value
  -> Signal dom b

assert uses Eq in Haskell simulation. However, the black boxes use a different equality test:

VHDL:

            assert (toSLV(~SYM[2]) = toSLV(~SYM[3])) report [...]

Verilog/SystemVerilog:

        if (~ARG[6] !== ~ARG[7]) begin

This will clearly go wrong for custom Eq classes. It just so happens I'll be using a custom Eq class soonish in the work on Xilinx floating point IP: for instance for the exponential operator, the result has an accuracy of within one unit in the last place (ULP / LSB), so a test bench will need to check whether the result is at most one ULP different from the "exact" result. With the current assert, this will lead to different behaviour of Haskell simulation and HDL simulation.

My suggestion is a structure overhaul:

  • Lift the machinery for the test in assertBitVector to isLike#, making isLike and isLike# not synthesisable, but generates HDL usable in HDL simulation.
  • Make a new assertWith with a black box and the type sig:
    assertWith
      :: (KnownDomain dom, ShowX a)
      => Clock dom
      -> Reset dom
      -> String
      -- ^ Additional message
      -> Signal dom Bool
      -- ^ 'False' when assertion fails
      -> Signal dom a
      -- ^ Checked value, for formatting failure message
      -> Signal dom a
      -- ^ Expected value, for formatting failure message
      -> Signal dom b
      -- ^ Return value
      -> Signal dom b
    The checked and expected signals are only still there to format the assertion failure messages, which are the same as before. The assert itself now checks the truth value of the Bool signal.
  • Redefine assert and assertBitVector as:
    assert clk rst msg checked expected returned = assertWith clk rst msg (checked .==. expected) checked expected returned
    assertBitVector clk rst msg checked expected returned = assertWith clk rst msg (liftA2 islike# checked expected) checked expected returned
    (I could have taken isLike but isLike# is faster, no pack).

While I'm in there, I can also fix another bug that I will mention here but not make a separate issue for. There is a disparity between Haskell and HDL simulation when assert is used with BitVectors with undefined bits, even without a custom Eq. The following test bench:

module CmpAssert where

import Clash.Explicit.Prelude
import Clash.Explicit.Testbench

topEntity ::
  BitVector 4 ->
  BitVector 4
topEntity = id
{-# NOINLINE topEntity #-}

testBench
  :: Signal System Bool
testBench = done
 where
  inp = stimuliGenerator clk rst (singleton $(bLit "1.0."))
  expectedOutput = outputVerifier' clk rst (singleton $(bLit "1.0."))
  done = expectedOutput (fmap topEntity inp)
  clk = tbClockGen (not <$> done)
  rst = resetGen
{-# NOINLINE testBench #-}

fails in Haskell:

>>> runUntil id testBench

cycle(<Clock: System>): 0, outputVerifier
expected value: 0b1.0., not equal to actual value: 0b1.0.

cycle(<Clock: System>): 1, outputVerifier
expected value: 0b1.0., not equal to actual value: 0b1.0.
Signal sampled for 2 cycles until value True

but succeeds in HDL.

Are there any objections to or suggestions for the structure overhaul?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants