diff --git a/README.md b/README.md index cc2743a..dcce4e0 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,15 @@ MuraxFast bypassed stages (0.55 DMIPS/Mhz) -> There is some scripts to generate the SoC and call the icestorm toolchain there : scripts/Murax/ +Note that now a toplevel simulation testbench with the same feature + a GUI is implemented with SpinalSim. You can find it in src/test/scala/vexriscv/MuraxSim.scala. + +To run it : + +```sh +#This will generate the Murax RTL + run its testbench. You need Verilator 3.9xx installated. +sbt "test:runMain vexriscv.MuraxSim" +``` + ## Build the RISC-V GCC In fact, now you can find some prebuild GCC :
diff --git a/src/test/scala/vexriscv/MuraxSim.scala b/src/test/scala/vexriscv/MuraxSim.scala index 5cc2637..375f8dd 100644 --- a/src/test/scala/vexriscv/MuraxSim.scala +++ b/src/test/scala/vexriscv/MuraxSim.scala @@ -1,21 +1,27 @@ package vexriscv +import java.awt +import java.awt.event.{ActionEvent, ActionListener} + import spinal.sim._ import spinal.core._ import spinal.core.sim._ import vexriscv.demo.{Murax, MuraxConfig} -import java.awt.Graphics -import javax.swing.{JFrame, JPanel} +import java.awt.{Color, Dimension, Graphics, GridLayout} +import javax.annotation.processing.SupportedSourceVersion +import javax.swing.{BoxLayout, JButton, JFrame, JPanel} import spinal.lib.com.jtag.sim.JtagTcp import spinal.lib.com.uart.sim.{UartDecoder, UartEncoder} +import scala.collection.mutable + object MuraxSim { def main(args: Array[String]): Unit = { -// def config = MuraxConfig.default.copy(onChipRamSize = 256 kB) - def config = MuraxConfig.default.copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex") + def config = MuraxConfig.default.copy(onChipRamSize = 256 kB) +// def config = MuraxConfig.default.copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex") SimConfig.allOptimisation.compile(new Murax(config)).doSimUntilVoid{dut => val mainClkPeriod = (1e12/dut.config.coreFrequency.toDouble).toLong @@ -25,7 +31,7 @@ object MuraxSim { val clockDomain = ClockDomain(dut.io.mainClk, dut.io.asyncReset) clockDomain.forkStimulus(mainClkPeriod) -// clockDomain.forkSimSpeedPrinter() +// clockDomain.forkSimSpeedPrinter(2) val tcpJtag = JtagTcp( jtag = dut.io.jtag, @@ -43,28 +49,56 @@ object MuraxSim { ) - val leds = fork{ + val guiThread = fork{ + val guiToSim = mutable.Queue[Any]() + var ledsValue = 0l val ledsFrame = new JFrame{ - setContentPane(new DrawPane()); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - setSize(400, 400); - setVisible(true); - - //create a component that you can actually draw on. - class DrawPane extends JPanel{ + setLayout(new BoxLayout(getContentPane, BoxLayout.Y_AXIS)) + add(new JPanel{ + val ledDiameter = 20 + val blackThickness = 2 override def paintComponent(g : Graphics) : Unit = { for(i <- 0 to 7) { - if (((ledsValue >> i) & 1) != 0) { - g.fillRect(20*i, 20, 20, 20) + g.setColor(Color.BLACK) + val x = i*ledDiameter + 1 + g.fillOval(x,1,ledDiameter,ledDiameter); + if (((ledsValue >> (7-i)) & 1) != 0) { + g.setColor(Color.GREEN.darker()) + g.fillOval(x+blackThickness,3,ledDiameter-blackThickness*2,ledDiameter-blackThickness*2); } } + g.setColor(Color.BLACK) } - } + this.setPreferredSize(new Dimension(ledDiameter*8+2, ledDiameter+2)) + }) + add(new JButton("Reset"){ + addActionListener(new ActionListener { + override def actionPerformed(actionEvent: ActionEvent): Unit = { + println("ASYNC RESET") + guiToSim.enqueue("asyncReset") + } + }) + setAlignmentX(awt.Component.CENTER_ALIGNMENT) + }) + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) + pack() + setVisible(true) + } while(true){ - sleep(mainClkPeriod*100000) + sleep(mainClkPeriod*50000) + + val dummy = if(guiToSim.nonEmpty){ + val request = guiToSim.dequeue() + if(request == "asyncReset"){ + dut.io.asyncReset #= true + sleep(mainClkPeriod*32) + dut.io.asyncReset #= false + } + } + ledsValue = dut.io.gpioA.write.toLong ledsFrame.repaint() }