I want to expose certain signals only during simulation (for performance monitoring purposes, etc...) that can be used during the debug process for various purposes. I could use the dontTouch
annotation to ensure that the counter, which is necessarily eliminated by DCE, is preserved in simulation and visible in the final waveform, but this would mean that the component would also be preserved during synthesis.
Chisel3 generates 'ifndef SYNTHESIS
verilog macros for cases of VerificationStatement
(e.g. $printf
, $stop
, ...). Is there a way for a user to more generally use the 'ifndef SYNTHESIS
macro within their designs or would I need to write my own FIRRTL/CIRCT annotations/passes to provide this functionality?
An alternative approach would be to probe the internals of the design from the testbench. This uses a new feature of Chisel 6 (BoringUtils.tapAndRead
) to create cross-module references.
Here's a small example:
//> using scala "2.13.10"
//> using repository "https://s01.oss.sonatype.org/content/repositories/snapshots"
//> using lib "org.chipsalliance::chisel::6.0.0-M1+3-35860474-SNAPSHOT"
//> using plugin "org.chipsalliance:::chisel-plugin::6.0.0-M1+3-35860474-SNAPSHOT"
//> using options "-unchecked", "-deprecation", "-language:reflectiveCalls", "-feature", "-Xcheckinit", "-Ywarn-dead-code", "-Ywarn-unused", "-Ymacro-annotations"
import chisel3._
import chisel3.util.experimental.BoringUtils
import circt.stage.ChiselStage
class Bar extends RawModule {
val b = WireInit(Bool(), DontCare)
dontTouch(b)
}
class Foo extends RawModule {
val bar = Module(new Bar)
val a = WireInit(Bool(), BoringUtils.tapAndRead(bar.b))
dontTouch(a)
}
object Main extends App {
println(ChiselStage.emitSystemVerilog(new Foo))
}
Running this (scala-cli Foo.scala
) produces the following Verilog:
module Bar();
wire b = 1'h0;
endmodule
module Foo();
wire a = Foo.bar.b;
Bar bar ();
endmodule
You could also do this by creating a "debug module" inside Bar
with all the signals you want. This module can then be excluded from synthesis. There is no great mechanism to exclude a module from synthesis (either via emitting it as a Verilog bind
to a specific bind file or with ifdef
s). Support for instantiating a module via a bind
is expected soon-ish.