-
Notifications
You must be signed in to change notification settings - Fork 22
Timed Assertions
The idea behind Timed assertions is to use the notion of a delay, as defined in the TimedCross, to consider arbitrary assertion conditions with an added timing factor. This could allow one to test the correctness of a design's timing, which is harder to do with regular assertions and stepping.
There are two types of Timed Assertions: AssertTimed and ExpectTimed. These two objects allow the user to check an assertion condition with a certain delay, defined using a delayType.
The delay types are the same as the one used in the TimedCross, but have a different meaning:
-
NoDelay: Using this turns the timed assertion into a normal assertion. -
Always: Checks that the argument condition is true at every cycle during the next given number of cycles. -
Eventually: Checks that the argument condition is true at least once within the next given number of cycles. -
Exactly: Checks that the argument condition will be true in exactly a given number of cycles. -
Never: Checks that the argument condition is never true in the next given number of cycles.
These delays can be used in two different ways: with AssertTimed or with ExpectTimed.
This object functions as a regular software assert, but with an added delay.
AssertTimed[T <: Module](dut: T, cond: => Boolean, errorMsg: String)(delayType: DelayType): TesterThreadListThis object works given a DUT, and arbitrary condition (hopefully on the dut ports) and an error message in case the assertion doesn't pass. It then also takes in a delay with is given as described above.
The object works using ChiselTest's expect method. It is thus more suitable for hardware assertions.
ExpectTimed[T <: Module](dut: T, port: Data, expectedVal: UInt, message: String)(delayType: DelayType): TesterThreadListThe idea is the same as the AssertTimed object, except that here we ask for a port and an expected value rather than an arbitrary condition. In this case the delays work like and assertion where the condition is dut.io.port.peek() === expectedVal.
Note that the return type for both objects is
TesterThreadList. This is because the timing aspect works by forking off into a new thread where the clock stepping can be done without modifying the timing of the test suite. One thus needs tojoin()the result of the timed assertion into the main thread in order for it to work.
Here is an example of how to used AssertTimed and ExpectTimed:
AssertTimed(dut, dut.io.aEvEqC.peek().litValue() == 1, "a eventually isn't c")(Eventually(11)).join()
//And the same thing but with expect
ExpectTimed(dut, dut.io.aEvEqC, 1.U, "aEqb expected timing is wrong")(Exactly(6)).join()Both Timed assertion objects have a simplified syntax, which is inspired by the syntax used by ScalaTest. These are perfectly equivalent and function based on the delay type rather than the assertion type:
//For Timed Assertions
eventually(2, "aEqb expected timing is wrong") { dut.io.a.peek() === dut.io.b.peek() }
exact(2, "aEqb expected timing is wrong") { dut.io.a.peek() === dut.io.b.peek() }
always(2, "aEqb expected timing is wrong") { dut.io.a.peek() === dut.io.b.peek() }
never(2, "aEqb expected timing is wrong") { dut.io.a.peek() === dut.io.b.peek() }
//For exepect
eventually(2, "aEqb expected timing is wrong") { dut.io.aEqb expected 1.U }
exact(2, "aEqb expected timing is wrong") { dut.io.aEqb expected 1.U }
always(2, "aEqb expected timing is wrong") { dut.io.aEqb expected 1.U }
never(2, "aEqb expected timing is wrong") { dut.io.aEqb expected 1.U }The expected method is what differentiates the use of AssertTimed from ExpectTimed. We highly recommend using this syntax over the direct apply method call, since it removes any risk of using illegal predicates or forgetting to join() the thread.
Note that for this new syntax to work, the user needs to define an implicit dut somewhere in his test suite:
implicit val _dut : T = dut
This was the only page on Timed Assertions. Return home.