Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exposing Simulation-only behavior in Chisel3

Tags:

chisel

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?

like image 405
Chris Avatar asked Mar 07 '26 21:03

Chris


2 Answers

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 ifdefs). Support for instantiating a module via a bind is expected soon-ish.

like image 100
seldridge Avatar answered Mar 09 '26 11:03

seldridge


In chiseltest we provide a simple expose feature that allows you to make arbitrary signals from your design available as outputs in your toplevel. If you want to use this only for simulation, the trick is to make a simulation toplevel module that just wraps your design under test and adds all necessary expose statements. Have a look at this small example.

like image 29
Kevin Laeufer Avatar answered Mar 09 '26 11:03

Kevin Laeufer