-
Notifications
You must be signed in to change notification settings - Fork 623
[chiselsim] Unified peek/poke/expect API for all Data types, include Records and Vecs #4824
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I think this looks really good. Sorry for the delay on reviewing, I'm not super familiar with the PeekPokeAPI so had to look over it again so I could review 😅
I don't want to sandbag so feel free to push back, but my only real complaint is a nit that the tests are a big big rather than being split into small pieces for like each type being tested. Would it be too much trouble to split those up?
it("should peek and poke various data types correctly") { | ||
val numTests = 100 | ||
simulate(new TestPeekPokeEnum(w)) { dut => | ||
assert(w == dut.io.in.bits.a.getWidth) | ||
val vecDim = dut.vecDim | ||
val truncationMask = (BigInt(1) << w) - 1 | ||
for { | ||
_ <- 0 until numTests | ||
a = BigInt(w, rand) | ||
b = BigInt(w, rand) | ||
v1 = Seq.fill(vecDim)(BigInt(w, rand)) | ||
v2 = Seq.fill(vecDim)(BigInt(w, rand)) | ||
op <- TestOp.all | ||
} { | ||
|
||
dut.io.in.bits.poke( | ||
chiselTypeOf(dut.io.in.bits).Lit( | ||
_.a -> a.U, | ||
_.b -> b.U, | ||
_.v1 -> Vec.Lit(v1.map(_.U(w.W)): _*), | ||
_.v2 -> Vec.Lit(v2.map(_.U(w.W)): _*) | ||
) | ||
) | ||
dut.io.in.valid.poke(true) | ||
dut.io.op.poke(op) | ||
dut.clock.step() | ||
dut.io.in.valid.poke(false) | ||
|
||
val peekedOp = dut.io.op.peek() | ||
assert(peekedOp.litValue == op.litValue) | ||
assert(peekedOp.toString.contains(TestOp.getClass.getSimpleName.stripSuffix("$"))) | ||
|
||
val expected = op match { | ||
case TestOp.Add => a + b | ||
case TestOp.Sub => a - b | ||
case TestOp.Mul => a * b | ||
case _ => throw new Exception("Invalid operation") | ||
} | ||
val expectedCmp = a.compare(b) match { | ||
case -1 => dut.CmpResult.LT | ||
case 0 => dut.CmpResult.EQ | ||
case 1 => dut.CmpResult.GT | ||
} | ||
|
||
dut.io.out.valid.expect(true.B) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to split this into a bunch of smaller tests of just individual types? Having the peeks and pokes of all types together kind of muddles what's being tested a bit.
dut.io.in.bits.poke( | ||
chiselTypeOf(dut.io.in.bits).Lit( | ||
_.a -> 1.U, | ||
_.b -> 2.U, | ||
_.v1 -> Vec.Lit(Seq.fill(vecDim)(3.U(w.W)): _*), | ||
_.v2 -> Vec.Lit(Seq.fill(vecDim)(4.U(w.W)): _*) | ||
) | ||
) | ||
dut.io.in.valid.poke(true) | ||
dut.io.op.poke(TestOp.Add) | ||
dut.clock.step() | ||
|
||
dut.io.out.bits.c.expect(5.U) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is just testing that the expectation is correct, could the rest of the test be simpler?
Hi @jackkoenig, |
The other issue is the ability to extend for the multi-threaded version of |
be more flexible with the provided lit Vec
more concise, and matches the previous message tested in ChiselSimSpec
lengths are checked to match, elements are themselves checked when being individually poked
+ Refactor PeekPokeTestModule to its own file
- Use implicit functions inside the trait - Better error messages for expect on Vec
All those |
This PR changes the "testable" implicit classes in
PeekPokeAPI
to allow for a unifiedpeek()
,poke()
, andexpect
API for all data types, including Records, Vecs, Enums, and nested aggregates.This unified API would be very helpful when developing higher-level test abstractions, such as enqueue/deque over clocked Decoupled interfaces.
This is a step towards adding some useful features and ergonomic APIs similar to those provided by
chiseltest
(#4209 included a rough PoC for integrating some of these features).The code does not look very pretty, but I could not figure out a cleaner way to make it work. Also, there is some repeated code.
I'd greatly appreciate comments and ideas for an alternative approach or other improvements.
Note: The previous (existing) implementation of
expect[T]()
seems incorrect. In addition to mistakingly using the same type name,T
for the different method type parameter, the comparison uses object equality (!=
).For the implemented
Element
values, the observed value is tuned into a Chisel object using theencode()
method. Since the objects are not the same, the comparison would always fail, even when the value is expected. Seems the previous tests did not cover this, but using the tests in this PR, I get false failures with the previousexpect
+encode
:Contributor Checklist
docs/src
?Type of Improvement
Feature
Desired Merge Strategy
Release Notes
Reviewer Checklist (only modified by reviewer)
3.6.x
,5.x
, or6.x
depending on impact, API modification or big change:7.0
)?Enable auto-merge (squash)
and clean up the commit message.Create a merge commit
.