Search code examples
scalasbtchisel

Is it possible to test chisel Reg() in console?


To test Chisel code, I launch a console sbt then scala in the directory of my project where is the file build.sbt. I can import chisel3 library :

$ cd myproject
$ sbt
sbt:myproject> console
scala> import chisel3._
import chisel3._

Then I can test some chisel code for data type for example :

scala> val plop = "b01010101".U(20.W)
plop: chisel3.UInt = UInt<20>(85)

But I can test Reg() or other Module() elements :

scala> val plopReg = RegInit(23.U(24.W))
java.lang.IllegalArgumentException: requirement failed: must be inside Builder context
  at scala.Predef$.require(Predef.scala:281)
  at chisel3.internal.Builder$.dynamicContext(Builder.scala:232)
  at chisel3.internal.Builder$.currentClock(Builder.scala:308)
  at chisel3.internal.Builder$.forcedClock(Builder.scala:318)
  at chisel3.RegInit$.apply(Reg.scala:155)
  at chisel3.RegInit$.apply(Reg.scala:173)
  ... 36 elided

Is there a tips to test these chisel element in console ? Or is it mandatory to write a file code source ?


Solution

  • What's going on here is that UInt is a Chisel type while Reg is a hardware type.

    You can play with hardware types only inside a module. I often do something like the following to play with them on the console:

    import chisel3._
    import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
    import chisel3.util.Cat
    
    import firrtl.EmittedCircuitAnnotation
    
    class Foo extends MultiIOModule {
      val in = IO(Input(Bool()))
      val out = IO(Output(Bool()))
    
      val tmp = RegNext(~in)
    
      out := tmp
    }
    
    val args = Array(
      "-X", "verilog",
      "-E", "high",
      "-E", "middle",
      "-E", "low",
      "-E", "verilog")
    
    (new ChiselStage).execute(args, Seq(ChiselGeneratorAnnotation(() => new Foo)))
    

    You can then look at the various outputs inside your chisel3 top-level directory.

    More Information

    What's going on, specifically, is that UInt (and things like it) are factory methods that generate classes (technically UInt is really an object that extends UIntFactory). When you do UInt(4.W), that's constructing a new UInt. You should be able to construct new classes anywhere you want which is why this works on the console.

    However, when you do Reg(UInt(4.W)) that's interacting with global mutable state used during the elaboration process to associate a register with a specific module. This global mutable state is stored inside the Builder. The error that you get is coming from the Builder where you've tried to use its methods without first being inside a module.