* 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: [[./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 #+begin_src scala 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 } #+end_src Next we create a test, using an extension of PeekPokeTester #+begin_src scala 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 } #+end_src 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][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/][svgOutputs]] folder. #+CAPTION: The simulated adders [[./Images/simulatedAdder.png]] 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][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