ftr
ftr

Reputation: 33

Access Chisel Module Variables at emitVerilog

I have a Chisel module, that has lots of submodules. The top module is configured with a set of parameters. The submodules have their configuration too; based on the input parameters and some hardcoded values.

Depending on all these configurations, I calculate e.g. the expected latency of the module. But, I cannot calculate it just by looking at the input parameters. Encoding all submodule information, and their hardcoded values into the input parameters would be horrible.

As a solution, I can print the latency when executing the emitVerilog function within myModuleDriver. However, I do not want to print it, I want the myModuleDriver to write the latency value to a file together with input parameters.

I provide an example piece of code. Simply, I want to access latency from myModule, when executing the myModuleDriver. Is there a way to do it from emitVerilog, or some other way?

import chisel3._
import chisel3.stage.ChiselStage

class myModule(
  val params: ParameterSet = new ParameterSet(...)
) extends Module {

  // inputs
  // outputs

  // submodule declarations; based on input params and some hardcoded internal parameters

  val latency = submoduleA.latency + submoduleB.latency
  println(s"latency: $latency")

  // output is available after given latency
}

object myModuleDriver extends App {

  val params = new ParameterSet(...)
  
  (new ChiselStage).emitVerilog(new myModule(params))


  write(params, myModule(params).latency) ????
}

Yet I could not find any solution.

Upvotes: 3

Views: 102

Answers (1)

Jack Koenig
Jack Koenig

Reputation: 6065

Certain things about the software architecture of Chisel make us a bit hesitant to return the elaborated Module object itself. There are a lot of things that feel like they should "work" on the returned object that do not, so the built-in APIs don't return the object. I would like to change this architecture but it's a lot of otherwise unimportant work so it tends to float on the backlog.

All this being said, your desire to capture calculated values is totally reasonable. There is a hacky way to do this. Fortunately, it looks nasty enough that I think any use of it is sufficient warning to the user to tread lightly with what they do with the returned module object.

You can try the following:

object myModuleDriver extends App {

  val params = new ParameterSet(...)

  // Capture the elaborated Module object at your own risk
  var elaboratedResult: myModule = null
  
  (new ChiselStage).emitVerilog {
    elaboratedResult = new myModule(params)
    elaboratedResult
  }

  write(params, elaboratedResult.latency) ????
}

Another option is you could pass a mutable data structure (like a Map or a class with var fields) and mutate it during elaboration. If params were mutable you could store latency in it and access it that way.

Upvotes: 0

Related Questions