Skip to content

Commit

Permalink
MicroSoc cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Dolu1990 committed Oct 28, 2024
1 parent 946f8f9 commit 11ee99e
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 72 deletions.
149 changes: 83 additions & 66 deletions src/main/scala/vexiiriscv/soc/demo/MicroSoc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import spinal.lib.bus.tilelink.fabric.Node
import spinal.lib.com.uart.TilelinkUartFiber
import spinal.lib.com.uart.sim.{UartDecoder, UartEncoder}
import spinal.lib.cpu.riscv.RiscvHart
import spinal.lib.cpu.riscv.debug.DebugModuleFiber
import spinal.lib.cpu.riscv.debug.{DebugModuleFiber, DebugModuleSocFiber}
import spinal.lib.eda.bench.Rtl
import spinal.lib.misc.{Elf, PathTracer, TilelinkClintFiber}
import spinal.lib.misc.plic.TilelinkPlicFiber
Expand All @@ -26,89 +26,99 @@ import vexiiriscv.test.VexiiRiscvProbe
import java.io.File
import scala.collection.mutable.ArrayBuffer

// This class will carry all the parameter of the SoC
class MicroSocParam {
var withJtagTap = true
var withJtagInstruction = false

def withDebug = withJtagTap || withJtagInstruction
}

class DebugModuleSocFiber(withJtagInstruction : Boolean) extends Area{
val tck = withJtagInstruction generate in(Bool())
val dm = new DebugModuleFiber()
val tap = (!withJtagInstruction) generate dm.withJtagTap()
val instruction = (withJtagInstruction) generate ClockDomain(tck)(dm.withJtagInstruction())
var ramBytes = 16 KiB
val vexii = new ParamSimple()
var demoPeripheral = Option.empty[PeripheralDemoParam]
val socCtrl = new SocCtrlParam()

// Provide some sane default
vexii.fetchForkAt = 1
vexii.lsuPmaAt = 1
vexii.lsuForkAt = 1
vexii.relaxedBranch = true
socCtrl.withJtagTap = true

// This is a command line parser utility, so you can customize the SoC using command line arguments to feed parameters
def addOptions(parser: scopt.OptionParser[Unit]): Unit = {
import parser._
vexii.addOptions(parser)
socCtrl.addOptions(parser)
opt[Int]("ram-bytes") action { (v, c) => ramBytes = v }
opt[Int]("demo-peripheral") action { (v, c) => demoPeripheral = Some(new PeripheralDemoParam(
ledWidth = v
))}
}

def bindHart(cpu: RiscvHart) = {
dm.bindHart(cpu)
def legalize(): Unit = {
vexii.privParam.withDebug = socCtrl.withDebug
}
}

class MicroSoc(p : MicroSocParam) extends Component {
val asyncReset = in Bool()
val cd100 = ClockDomain.external("cd100", withReset = false, frequency = FixedFrequency(100 MHz))

val debugResetCtrl = cd100(new ResetCtrlFiber().addAsyncReset(asyncReset, HIGH))
val mainResetCtrl = cd100(new ResetCtrlFiber().addAsyncReset(debugResetCtrl))

val debug = p.withDebug generate debugResetCtrl.cd(new DebugModuleSocFiber(p.withJtagInstruction){
mainResetCtrl.addSyncRelaxedReset(dm.ndmreset, HIGH)
})

// Lets define our SoC toplevel
class MicroSoc(p : MicroSocParam) extends Component {
// socCtrl will provide clocking, reset controllers and debugModule (through jtag) to our SoC
val socCtrl = new SocCtrl(p.socCtrl)

val main = mainResetCtrl.cd on new Area {
val sharedBus = tilelink.fabric.Node()
val system = new ClockingArea(socCtrl.system.cd) {
// Let's define our main tilelink bus on which the CPU, RAM and peripheral "portal" will be plugged later.
val mainBus = tilelink.fabric.Node()

val param = new ParamSimple()
param.fetchForkAt = 1
param.lsuPmaAt = 1
param.lsuForkAt = 1
param.relaxedBranch = true
param.privParam.withDebug = p.withDebug

val plugins = param.plugins()
val cpu = new TilelinkVexiiRiscvFiber(plugins)
sharedBus << cpu.buses
cpu.dBus.setDownConnection(a = StreamPipe.S2M)
if(p.withDebug) debug.bindHart(cpu)
val cpu = new TilelinkVexiiRiscvFiber(p.vexii.plugins())
if(p.socCtrl.withDebug) socCtrl.debugModule.bindHart(cpu)
mainBus << cpu.buses
cpu.dBus.setDownConnection(a = StreamPipe.S2M) // Let's add a bit of pipelining on the cpu.dBus to increase FMax

val ram = new tilelink.fabric.RamFiber(16 KiB)
ram.up at 0x80000000l of sharedBus
val ram = new tilelink.fabric.RamFiber(p.ramBytes)
ram.up at 0x80000000l of mainBus

// Handle all the IO / Peripheral things
val peripheral = new Area {
val busXlen = Node().forceDataWidth(param.xlen)
busXlen << sharedBus
// Some peripheral may require to have an access as big as the CPU XLEN, so, lets define a bus which ensure it.
val busXlen = Node()
busXlen.forceDataWidth(p.vexii.xlen)
busXlen << mainBus
busXlen.setUpConnection(a = StreamPipe.HALF, d = StreamPipe.HALF)

val bus32 = Node().forceDataWidth(32)
// Most peripheral will work with a 32 bits data bus.
val bus32 = Node()
bus32.forceDataWidth(32)
bus32 << busXlen

// The clint is a regular RISC-V timer peripheral
val clint = new TilelinkClintFiber()
clint.node at 0x10010000 of busXlen

// The clint is a regular RISC-V interrupt controller
val plic = new TilelinkPlicFiber()
plic.node at 0x10C00000 of bus32

val uart = new TilelinkUartFiber()
uart.node at 0x10001000 of bus32
plic.mapUpInterrupt(1, uart.interrupt)

val demo = p.demoPeripheral.map(new PeripheralDemoFiber(_){
node at 0x10002000 of bus32
plic.mapUpInterrupt(2, interrupt)
})

val cpuPlic = cpu.bind(plic)
val cpuClint = cpu.bind(clint)
}
}
}

object MicroSocGen extends App{
val report = SpinalVerilog{
val p = new MicroSocParam()
new MicroSoc(p)
}
val p = new MicroSocParam()

// val h = report.toplevel.main.cpu.logic.core.host
// val path = PathTracer.impl(h[SrcPlugin].logic.addsub.rs2Patched, h[TrapPlugin].logic.harts(0).trap.pending.state.tval)
// println(path.report)
assert(new scopt.OptionParser[Unit]("MicroSoc") {
p.addOptions(this)
}.parse(args, Unit).nonEmpty)
p.legalize()

val report = SpinalVerilog(new MicroSoc(p))
}

object MicroSocSynt extends App{
Expand All @@ -117,7 +127,7 @@ object MicroSocSynt extends App{
rtls += Rtl(SpinalVerilog{
val p = new MicroSocParam()
new MicroSoc(p) {
cd100.readClockWire.setName("clk")
socCtrl.systemClk.setName("clk")
setDefinitionName("MicroSoc")
}
})
Expand All @@ -133,66 +143,73 @@ object MicroSocSynt extends App{
/**
* To connect with openocd jtag :
* - src/openocd -f $VEXIIRISCV/src/main/tcl/openocd/vexiiriscv_sim.tcl
*/

object MicroSocSim extends App{
var traceKonata = false
var withRvlsCheck = false
var elf: Elf = null
var elf: File = null
val sim = SimConfig
sim.withTimeSpec(1 ns, 1 ps)
val p = new MicroSocParam()

assert(new scopt.OptionParser[Unit]("VexiiRiscv") {
help("help").text("prints this usage text")
opt[String]("load-elf") action { (v, c) => elf = new Elf(new File(v), 32) }
opt[String]("load-elf") action { (v, c) => elf = new File(v) }
opt[Unit]("trace-konata") action { (v, c) => traceKonata = true }
opt[Unit]("check-rvls") action { (v, c) => withRvlsCheck = true }
p.addOptions(this)
sim.addOptions(this)
}.parse(args, Unit).nonEmpty)


sim.compile(new MicroSoc(p){
hardFork{
main.ram.thread.logic.mem.simPublic()
Fiber patch{
system.ram.thread.logic.mem.simPublic()
}
}).doSimUntilVoid("test", seed = 42){dut =>
dut.cd100.forkStimulus()
dut.asyncReset #= true
delayed(100 ns)(dut.asyncReset #= false)
dut.socCtrl.systemClkCd.forkStimulus()
dut.socCtrl.asyncReset #= true
delayed(100 ns)(dut.socCtrl.asyncReset #= false)

val uartBaudPeriod = hzToLong(115200 Hz)
val uartTx = UartDecoder(
uartPin = dut.main.peripheral.uart.logic.uart.txd,
uartPin = dut.system.peripheral.uart.logic.uart.txd,
baudPeriod = uartBaudPeriod
)
val uartRx = UartEncoder(
uartPin = dut.main.peripheral.uart.logic.uart.rxd,
uartPin = dut.system.peripheral.uart.logic.uart.rxd,
baudPeriod = uartBaudPeriod
)

val konata = traceKonata.option(
new vexiiriscv.test.konata.Backend(new File(currentTestPath, "konata.log")).spinalSimFlusher(hzToLong(1000 Hz))
)
val probe = new VexiiRiscvProbe(
cpu = dut.main.cpu.logic.core,
cpu = dut.system.cpu.logic.core,
kb = konata
)

if (withRvlsCheck) probe.add(new RvlsBackend(new File(currentTestPath)).spinalSimFlusher(hzToLong(1000 Hz)))

probe.autoRegions()

if(p.withJtagTap) {
if(p.socCtrl.withJtagTap) {
probe.checkLiveness = false
spinal.lib.com.jtag.sim.JtagRemote(dut.debug.tap.jtag, hzToLong(dut.cd100.frequency.getValue)*4)
spinal.lib.com.jtag.sim.JtagRemote(dut.socCtrl.debugModule.tap.jtag, hzToLong(p.socCtrl.systemFrequency)*4)
}


if(elf != null) {
elf.load(dut.main.ram.thread.logic.mem, 0x80000000l)
probe.backends.foreach(_.loadElf(0, elf.f))
new Elf(elf, p.vexii.xlen).load(dut.system.ram.thread.logic.mem, 0x80000000l)
probe.backends.foreach(_.loadElf(0, elf))
}
}
}




// val h = report.toplevel.main.cpu.logic.core.host
// val path = PathTracer.impl(h[SrcPlugin].logic.addsub.rs2Patched, h[TrapPlugin].logic.harts(0).trap.pending.state.tval)
// println(path.report)
5 changes: 2 additions & 3 deletions src/main/scala/vexiiriscv/soc/litex/Soc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import spinal.lib.bus.tilelink.{coherent, fabric}
import spinal.lib.bus.tilelink.fabric.Node
import spinal.lib.com.eth.sg.{MacSgFiber, MacSgFiberSpec, MacSgParam}
import spinal.lib.com.jtag.sim.JtagRemote
import spinal.lib.cpu.riscv.debug.DebugModuleFiber
import spinal.lib.cpu.riscv.debug.{DebugModuleFiber, DebugModuleSocFiber}
import spinal.lib.eda.bench.{Bench, Rtl}
import spinal.lib.graphic.YcbcrConfig
import spinal.lib.graphic.vga.{TilelinkVgaCtrlFiber, TilelinkVgaCtrlSpec, Vga, VgaRgbToYcbcr, VgaYcbcrPix2}
Expand All @@ -34,7 +34,6 @@ import vexiiriscv.misc.PrivilegedPlugin
import vexiiriscv.prediction.GSharePlugin
import vexiiriscv.schedule.DispatchPlugin
import vexiiriscv.soc.TilelinkVexiiRiscvFiber
import vexiiriscv.soc.demo.DebugModuleSocFiber

import java.awt.{Dimension, Graphics}
import java.awt.image.BufferedImage
Expand Down Expand Up @@ -421,7 +420,7 @@ class Soc(c : SocConfig) extends Component {
}

val debugReset = c.withDebug generate in.Bool()
val debug = c.withDebug generate ClockDomain(cpuCd.clock, debugReset)(new DebugModuleSocFiber(withJtagInstruction) {
val debug = c.withDebug generate ClockDomain(cpuCd.clock, debugReset)(new DebugModuleSocFiber(withJtagTap, withJtagInstruction) {
out(dm.ndmreset)
system.vexiis.foreach(bindHart)
})
Expand Down
5 changes: 2 additions & 3 deletions src/main/scala/vexiiriscv/tester/TilelinkTestBench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import spinal.lib.bus.tilelink.sim.{Checker, MemoryAgent}
import spinal.lib.com.uart.TilelinkUartFiber
import spinal.lib.com.uart.sim.{UartDecoder, UartEncoder}
import spinal.lib.cpu.riscv.RiscvHart
import spinal.lib.cpu.riscv.debug.DebugModuleFiber
import spinal.lib.cpu.riscv.debug.{DebugModuleFiber, DebugModuleSocFiber}
import spinal.lib.eda.bench.Rtl
import spinal.lib.misc.{Elf, PathTracer, TilelinkClintFiber}
import spinal.lib.misc.plic.TilelinkPlicFiber
Expand All @@ -29,7 +29,6 @@ import vexiiriscv.ParamSimple
import vexiiriscv.execute.SrcPlugin
import vexiiriscv.misc.TrapPlugin
import vexiiriscv.soc.TilelinkVexiiRiscvFiber
import vexiiriscv.soc.demo.DebugModuleSocFiber
import vexiiriscv.soc.demo.MicroSocSim.args
import vexiiriscv.test.{PeripheralEmulator, VexiiRiscvProbe}

Expand Down Expand Up @@ -58,7 +57,7 @@ class TlTbTop(p : TlTbParam) extends Component {
val debugResetCtrl = cd100(new ResetCtrlFiber().addAsyncReset(asyncReset, HIGH))
val mainResetCtrl = cd100(new ResetCtrlFiber().addAsyncReset(debugResetCtrl))

val debug = p.withDebug generate debugResetCtrl.cd(new DebugModuleSocFiber(p.withJtagInstruction){
val debug = p.withDebug generate debugResetCtrl.cd(new DebugModuleSocFiber(p.withJtagTap, p.withJtagInstruction){
mainResetCtrl.addSyncRelaxedReset(dm.ndmreset, HIGH)
})

Expand Down

0 comments on commit 11ee99e

Please sign in to comment.