您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

3.9KB

Rendering your circuit

This system is very WIP, and is therefore pretty janktastic. The general idea of the circuit renderer is that you create a vector drawing of your circuit with special labels for the circuit state you want to render. The only svg program I have tested this with is inkscape, and I recommend against using other drawing programs.

As an example we will use a very simple circuit: /sindre/Chisel-intro/src/commit/45e921c3ff7f4b56aebeedccca003b745419347b/Images/inkscape.jpg

This circuit has a register, and we want to see how its state evolves, thus we add a label. The name of the register is "Reg_A", which will be replaced by the actual value as the circuit is simulated. We indicate this by adding "_field" as a postfix.

Next we make a test for our circuit

class Adder() extends Module {
  val io = IO(
    new Bundle {
      val reg_a = Output(UInt(32.W))
    }
  )

  val reg_a = RegInit(0.U(8.W))
  reg_a := reg_a + 1.U

  io.reg_a := reg_a
}

Next we create a test, using an extension of PeekPokeTester

class AdderTester(c: Adder) extends PeekPokeTesterLogger(c)  {
  //                                ^^^^^^^^^^^^^^^^^^^^^^^ This is an extension of the regular peek poke tester


  // Tells us which signals should be logged
  override def ioLoggers = List(c.io)

  for(ii <- 0 until 10){
    step(1)
  }

  // Writes the log to disk
  writeLog
}

When the addertester is run it will record the state of c.io for every timestep and store it. When testing is done, calling writeLog will search for an SVG whose name matches the tested device in the resources folder. For adder this corresponds to src/test/resources/svgs/Adder.svg The svg is loaded, and every value with the _field postfix is replaced with the recorded value sharing its name. In the simple adder circuit the only value in io is reg_a which matches Reg_A_field.

By running testOnly Ex0.SVGSpec 10 svg files will be created, showing the state of the circuit for every step

You can now see the output svgs in the svgOutputs folder.

/sindre/Chisel-intro/src/commit/45e921c3ff7f4b56aebeedccca003b745419347b/Images/simulatedAdder.png
The simulated adders

If you want to view them as pngs and you have inkscape installed you can run ./convert.sh to get png output instead.

For a more fully fledged example take a look at src/test/scala/SVGNestedSpec.scala

which can be run with testOnly Ex0.SVGSNestedSpec

Should I use this? What's the approach?

The time invested in drawing a circuit, laying out fields etc is likely not worth it. However, for the 5-stage RISCV pipeline the answer is definitely a yes! In order to get a feel for this approach I recommend trying to debug the matrix multiplier unit (last exercise) with this approach. To do so you need to do the following steps:

(Or you could repurpose the SVGSNestedSpec)

Draw the circuit in inkscape

You can add as much detail as you want here, the only thing the parser looks for is text fields that are postfixed with "_field" The fields I would be interested in are the row and column counters, and the dot product accumulator state. Save the svg as /src/test/resources/svgs/MatMul.svg

Wire the debug IO

The peek poke logger can only observe the top level IO modules, so the signals you want to record must be made available. This approach is shown in the chisel introduction.

Create the test runner

Your tester should extend PeekPokeTesterLogger. In your test you need to override the ioLoggers function to record the ports you want to monitor (typically io, maybe a special debug port)

At the end of your test add writeLog in order to actually write the svgs

Run your test

If everything goes smooth you can now take a look at the SVG output, or if you have inkscape render it as an svg