-
Notifications
You must be signed in to change notification settings - Fork 650
ChiselTest Compatibility Layer for Chisel 7 #5221
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
Open
EhsanKhodadad
wants to merge
8
commits into
chipsalliance:main
Choose a base branch
from
EhsanKhodadad:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 4 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
5f9d6c2
ChiselTest Compatibility Layer for Chisel 7
EhsanKhodadad bb9ae1d
Update docs/src/appendix/migrating-from-chiseltest.md
EhsanKhodadad fd2f9ce
vcd generation added
EhsanKhodadad 569f32d
format
EhsanKhodadad 3b7f389
Chisel test compatibility layer:
EhsanKhodadad 788e2b6
Update src/main/scala/chiseltest/formal/package.scala
jackkoenig 59fb618
Fix mdoc
jackkoenig 108f637
Meant invisible, not silent
jackkoenig File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,244 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package chiseltest | ||
|
|
||
| import chisel3._ | ||
| import chisel3.simulator.EphemeralSimulator._ | ||
| import chisel3.simulator.ChiselSim | ||
| import svsim._ | ||
| import svsim.verilator.Backend.CompilationSettings.{TraceKind, TraceStyle} | ||
| import scala.language.implicitConversions | ||
|
|
||
| /** | ||
| * ChiselTest-compatible API that delegates to ChiselSim (Chisel 7) | ||
| * | ||
| * This trait provides the ChiselTest API that users are familiar with from Chisel 6, | ||
| * but internally uses ChiselSim from Chisel 7 to perform the actual testing. | ||
| * | ||
| * VCD GENERATION SUPPORT: | ||
| * This compatibility layer supports VCD generation when WriteVcdAnnotation is used. | ||
| * VCD files are generated in: build/chiselsim/<timestamp>/workdir-verilator/trace.vcd | ||
| * | ||
| * AUTOMATIC RESET FEATURE: | ||
| * By default, this trait automatically resets the module before running tests, | ||
| * mimicking ChiselTest's behavior from Chisel 6. | ||
| * | ||
| * To disable auto-reset or customize the reset duration: | ||
| * {{{ | ||
| * class MyTest extends AnyFlatSpec with ChiselScalatestTester { | ||
| * override def autoResetEnabled: Boolean = false // Disable auto-reset | ||
| * override def resetCycles: Int = 5 // Or change duration | ||
| * } | ||
| * }}} | ||
| * | ||
| * Example usage with VCD: | ||
| * {{{ | ||
| * import chiseltest._ | ||
| * import org.scalatest.flatspec.AnyFlatSpec | ||
| * | ||
| * class MyModuleSpec extends AnyFlatSpec with ChiselScalatestTester { | ||
| * behavior of "MyModule" | ||
| * | ||
| * it should "generate waveforms" in { | ||
| * test(new MyModule).withAnnotations(Seq(WriteVcdAnnotation)) { dut => | ||
| * dut.io.in.poke(42.U) | ||
| * dut.clock.step() | ||
| * dut.io.out.expect(42.U) | ||
| * } | ||
| * // VCD file: build/chiselsim/<timestamp>/workdir-verilator/trace.vcd | ||
| * } | ||
| * } | ||
| * }}} | ||
| */ | ||
| trait ChiselScalatestTester { | ||
|
|
||
| /** | ||
| * Enable automatic reset before each test. | ||
| * Override this to disable auto-reset if needed. | ||
| */ | ||
| def autoResetEnabled: Boolean = false | ||
|
|
||
| /** | ||
| * Number of clock cycles to assert reset. | ||
| * Override this to change reset duration. | ||
| */ | ||
| def resetCycles: Int = 1 | ||
|
|
||
| /** | ||
| * Test a module with the given stimulus | ||
| * | ||
| * This method provides the ChiselTest interface. | ||
| * | ||
| * @param dutGen A generator function that creates the device under test | ||
| * @tparam T The type of module being tested | ||
| */ | ||
| def test[T <: Module](dutGen: => T): TestBuilder[T] = | ||
| new TestBuilder(dutGen, autoResetEnabled, resetCycles) | ||
|
|
||
| /** | ||
| * Builder class to support .withAnnotations() chaining | ||
| * | ||
| * @param dutGen Generator for the device under test | ||
| * @param autoReset Whether automatic reset is enabled | ||
| * @param resetCyc Number of reset cycles to apply | ||
| */ | ||
| class TestBuilder[T <: Module](dutGen: => T, autoReset: Boolean, resetCyc: Int) { | ||
|
|
||
| /** | ||
| * Attach ChiselTest-style annotations before running the test. | ||
| * | ||
| * @param annotations Annotation list (for example WriteVcdAnnotation) | ||
| * @return A runner that executes the test with the provided annotations | ||
| */ | ||
| def withAnnotations(annotations: Seq[Any]): TestRunner[T] = { | ||
| new TestRunner(dutGen, autoReset, resetCyc, annotations) | ||
| } | ||
|
|
||
| /** | ||
| * Run the test body without explicit annotations. | ||
| * | ||
| * @param body User-defined test body operating on the DUT instance | ||
| */ | ||
| // Allow direct execution without annotations | ||
| def apply(body: T => Unit): Unit = { | ||
| val chiselSim = new ChiselSim {} | ||
| chiselSim.simulate(dutGen) { dut => | ||
| if (autoReset) { | ||
| applyReset(dut, resetCyc) | ||
| } | ||
| body(dut) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Runner class that executes the test with VCD support | ||
| * | ||
| * @param dutGen Generator for the device under test | ||
| * @param autoReset Whether automatic reset is enabled | ||
| * @param resetCyc Number of reset cycles to apply | ||
| * @param annotations Annotation list used to configure execution behavior | ||
| */ | ||
| class TestRunner[T <: Module](dutGen: => T, autoReset: Boolean, resetCyc: Int, annotations: Seq[Any] = Seq()) { | ||
|
|
||
| /** | ||
| * Execute the configured test run. | ||
| * | ||
| * @param body User-defined test body operating on the DUT instance | ||
| */ | ||
| def apply(body: T => Unit): Unit = { | ||
| // Check if WriteVcdAnnotation is present | ||
| val hasVcd = annotations.exists { | ||
| case _: chiseltest.WriteVcdAnnotation.type => true | ||
| case _ => false | ||
| } | ||
|
|
||
| val chiselSim = new ChiselSim {} | ||
|
|
||
| if (hasVcd) { | ||
| println("[ChiselTest Compat] WriteVcdAnnotation detected, enabling VCD trace generation...") | ||
|
|
||
| // Create backend modification to enable VCD tracing | ||
| implicit val backendMod: BackendSettingsModifications = | ||
| (settings: Backend.Settings) => | ||
| settings match { | ||
| case vs: verilator.Backend.CompilationSettings => | ||
| val vcdStyle = TraceStyle( | ||
| kind = TraceKind.Vcd, | ||
| traceUnderscore = false, | ||
| traceStructs = true, | ||
| traceParams = true, | ||
| maxWidth = None, | ||
| maxArraySize = None, | ||
| traceDepth = None | ||
| ) | ||
| vs.withTraceStyle(Some(vcdStyle)) | ||
| case other => other | ||
| } | ||
|
|
||
| // Simulate with VCD enabled | ||
| chiselSim.simulate(dutGen) { dut => | ||
| chiselSim.enableWaves() | ||
|
|
||
| if (autoReset) { | ||
| applyReset(dut, resetCyc) | ||
| } | ||
| body(dut) | ||
| } | ||
| } else { | ||
| // Simulate without VCD | ||
| chiselSim.simulate(dutGen) { dut => | ||
| if (autoReset) { | ||
| applyReset(dut, resetCyc) | ||
| } | ||
| body(dut) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Apply reset sequence to the DUT | ||
| * | ||
| * @param dut Device under test | ||
| * @param cycles Number of cycles reset stays asserted | ||
| */ | ||
| private def applyReset[T <: Module](dut: T, cycles: Int): Unit = { | ||
| toTestableReset(dut.reset).poke(true.B) | ||
| toTestableClock(dut.clock).step(cycles) | ||
| toTestableReset(dut.reset).poke(false.B) | ||
| } | ||
| } | ||
|
|
||
| /** Enhanced Data operations compatible with ChiselTest API */ | ||
| object ChiselTestCompat { | ||
| import chisel3.simulator.EphemeralSimulator._ | ||
|
|
||
| /** | ||
| * Implicit class to add ChiselTest-style operations to Data types | ||
| */ | ||
| implicit class testableData[T <: Data](val x: T) extends AnyVal { | ||
|
jackkoenig marked this conversation as resolved.
Outdated
|
||
|
|
||
| /** | ||
| * Poke a value onto a port | ||
| * | ||
| * @param value The value to drive on the target signal | ||
| */ | ||
| def poke(value: T): Unit = { | ||
| toTestableData(x).poke(value) | ||
| } | ||
|
|
||
| /** | ||
| * Peek the current value of a port | ||
| * | ||
| * @return The current sampled value of the target signal | ||
| */ | ||
| def peek(): T = { | ||
| toTestableData(x).peek() | ||
| } | ||
|
|
||
| /** | ||
| * Assert that a port has an expected value | ||
| * | ||
| * @param expected The value expected on the target signal | ||
| */ | ||
| def expect(expected: T): Unit = { | ||
| toTestableData(x).expect(expected) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Implicit class to add ChiselTest-style operations to Clock types | ||
| */ | ||
| implicit class testableClock(val clock: Clock) extends AnyVal { | ||
|
|
||
| /** | ||
| * Step the clock forward by a number of cycles | ||
| * | ||
| * @param cycles Number of clock cycles to advance (default: 1) | ||
| */ | ||
| def step(cycles: Int = 1): Unit = { | ||
| toTestableClock(clock).step(cycles) | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package chiseltest | ||
|
|
||
| /** | ||
| * DecoupledDriver provides utility functions for testing Decoupled interfaces | ||
| * | ||
| * This is compatible with ChiselTest's DecoupledDriver but implemented using ChiselSim. | ||
| * | ||
| * The actual implementation is in the package object as implicit conversions. | ||
| * Import chiseltest._ or chiseltest.DecoupledDriver._ to use these methods. | ||
| * | ||
| * Example: | ||
| * {{{ | ||
| * import chiseltest._ | ||
| * | ||
| * test(new QueueModule) { dut => | ||
| * dut.io.in.enqueueNow(42.U) | ||
| * dut.io.out.expectDequeueNow(42.U) | ||
| * } | ||
| * }}} | ||
| */ | ||
| object DecoupledDriver { | ||
| // For compatibility with imports like: import chiseltest.DecoupledDriver._ | ||
| // The actual implicit classes are defined in the package object | ||
| } | ||
|
jackkoenig marked this conversation as resolved.
Outdated
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.