Chisel code conversion

So I have a theoretical question about chisel code conversion.

I know Chisel is actually a collection of Scala definitions, so it compiles to Java bytecodes, which in turn gets run in the JVM and, like magic, spits out the equivalent Verilog description and even the C ++ description for more older versions of Chisel.

The point is, I couldn't figure out how this "magic" works. I am assuming the code conversion from Chisel to Verilog / C ++ is based on Scala reflection. But I am not sure about this as I could not find anything related to this topic.

So, is it about reflection? If so, is it our runtime compile time? Can someone please give me the key?

Many thanks.

+3


source to share


2 answers


Basically, the writing driller writes a Scala program to create the schema. What you are describing is a bit like a high level synthesis, which is very different from a bit. Instead of mapping Scala (or Java) primitives to hardware, Chisel executes Scala code to build a hardware AST , which is then compiled for Verilog.

I'll try to make it clearer with an annotated example.



// The body of a Scala class is the default constructor
// MyModule default constructor has a single Int argument
// Superclass Module is a chisel3 Class that begins construction of a hardware module
// Implicit clock and reset inputs are added by the Module constructor
class MyModule(width: Int) extends Module {
  // io is a required field for subclasses of Module
  // new Bundle creates an instance of an anonymous subclass of Chisel Bundle (like a struct)
  // When executing the function IO(...), Chisel adds ports to the Module based on the Bundle object
  val io = IO(new Bundle {
    val in = Input(UInt(width.W)) // Input port with width defined by parameter
    val out = Output(UInt()) // Output port with width inferred by Chisel
  }) 

  // A Scala println that will print at elaboration time each time this Module is instantiated
  // This does NOT create a node in the Module AST
  println(s"Constructing MyModule with width $width")

  // Adds a register declaration node to the Module AST
  // This counter register resets to the value of input port io.in
  // The implicit clock and reset inputs feed into this node
  val counter = RegInit(io.in)

  // Adds an addition node to the hardware AST with operands counter and 1
  val inc = counter + 1.U // + is overloaded, this is actually a Chisel function call

  // Connects the output of the addition node to the "next" value of counter
  counter := inc

  // Adds a printf node to the Module AST that will print at simulation time
  // The value of counter feeds into this node
  printf("counter = %d\n", counter) 
}

      

+2


source


This is also a question that interests me. I think "build hardware AST" is programmed and compiled as * .class. When classes are generated, since firrtl. After you execute this class the rtl is generated, it feels like a built-in toolchain. But I cannot tell you how to do it. Wish someone told more.



0


source







All Articles