SmpCluster now with proper jtag and plic

This commit is contained in:
Dolu1990 2020-06-12 16:18:41 +02:00
parent 2e8a059c77
commit b0cd88c462
3 changed files with 172 additions and 51 deletions

View File

@ -6,8 +6,10 @@ import spinal.core.sim.{onSimEnd, simSuccess}
import spinal.lib._
import spinal.lib.bus.bmb.sim.BmbMemoryAgent
import spinal.lib.bus.bmb.{Bmb, BmbArbiter, BmbDecoder, BmbExclusiveMonitor, BmbInvalidateMonitor, BmbParameter}
import spinal.lib.com.jtag.Jtag
import spinal.lib.bus.misc.SizeMapping
import spinal.lib.com.jtag.{Jtag, JtagTapInstructionCtrl}
import spinal.lib.com.jtag.sim.JtagTcp
import spinal.lib.system.debugger.SystemDebuggerConfig
import vexriscv.ip.{DataCacheAck, DataCacheConfig, DataCacheMemBus, InstructionCache, InstructionCacheConfig}
import vexriscv.plugin.{BranchPlugin, CsrAccess, CsrPlugin, CsrPluginConfig, DBusCachedPlugin, DBusSimplePlugin, DYNAMIC_TARGET, DebugPlugin, DecoderSimplePlugin, FullBarrelShifterPlugin, HazardSimplePlugin, IBusCachedPlugin, IBusSimplePlugin, IntAluPlugin, MmuPlugin, MmuPortConfig, MulDivIterativePlugin, MulPlugin, RegFilePlugin, STATIC, SrcPlugin, YamlPlugin}
import vexriscv.{Riscv, VexRiscv, VexRiscvConfig, plugin}
@ -38,21 +40,23 @@ case class VexRiscvSmpCluster(p : VexRiscvSmpClusterParameter,
val externalInterrupts = in Bits(p.cpuConfigs.size bits)
val softwareInterrupts = in Bits(p.cpuConfigs.size bits)
val externalSupervisorInterrupts = in Bits(p.cpuConfigs.size bits)
val jtag = slave(Jtag())
val debugBus = slave(Bmb(SystemDebuggerConfig().getBmbParameter.copy(addressWidth = 20)))
val debugReset = out Bool()
val time = in UInt(64 bits)
}
io.debugReset := False
val cpus = for((cpuConfig, cpuId) <- p.cpuConfigs.zipWithIndex) yield new Area{
var iBus : Bmb = null
var dBus : Bmb = null
var debug : Bmb = null
cpuConfig.plugins.foreach {
case plugin: DebugPlugin => debugClockDomain{
plugin.debugClockDomain = debugClockDomain
}
case _ =>
}
if(cpuId == 0) cpuConfig.plugins += new DebugPlugin(debugClockDomain)
cpuConfig.plugins += new DebugPlugin(debugClockDomain)
val core = new VexRiscv(cpuConfig)
core.plugins.foreach {
case plugin: IBusCachedPlugin => iBus = plugin.iBus.toBmb()
@ -65,8 +69,8 @@ case class VexRiscvSmpCluster(p : VexRiscvSmpClusterParameter,
if (plugin.utime != null) plugin.utime := io.time
}
case plugin: DebugPlugin => debugClockDomain{
io.debugReset := RegNext(plugin.io.resetOut)
io.jtag <> plugin.io.bus.fromJtag()
io.debugReset setWhen(RegNext(plugin.io.resetOut))
debug = plugin.io.bus.fromBmb()
}
case _ =>
}
@ -97,19 +101,18 @@ case class VexRiscvSmpCluster(p : VexRiscvSmpClusterParameter,
io.dMem << invalidateMonitor.io.output
// val iBusArbiter = BmbArbiter(
// p = iBusArbiterParameter,
// portCount = cpus.size,
// pendingRspMax = 64,
// lowerFirstPriority = false,
// inputsWithInv = cpus.map(_ => true),
// inputsWithSync = cpus.map(_ => true),
// pendingInvMax = 16
// )
//
// (iBusArbiter.io.inputs, cpus).zipped.foreach(_ << _.iBus)
// io.iMem << iBusArbiter.io.output
(io.iMems, cpus).zipped.foreach(_ << _.iBus)
val debug = debugClockDomain on new Area{
val arbiter = BmbDecoder(
p = io.debugBus.p,
mappings = List.tabulate(p.cpuConfigs.size)(i => SizeMapping(0x00000 + i*0x1000, 0x1000)),
capabilities = List.fill(p.cpuConfigs.size)(io.debugBus.p),
pendingMax = 2
)
arbiter.io.input << io.debugBus
(arbiter.io.outputs, cpus.map(_.debug)).zipped.foreach(_ >> _)
}
}
@ -417,10 +420,7 @@ object VexRiscvSmpClusterTestInfrastructure{
import spinal.core.sim._
dut.clockDomain.forkStimulus(10)
dut.debugClockDomain.forkStimulus(10)
// JtagTcp(dut.io.jtag, 100)
dut.io.jtag.tck #= false
dut.io.jtag.tdi #= false
dut.io.jtag.tms #= false
dut.io.debugBus.cmd.valid #= false
}
}

View File

@ -3,13 +3,15 @@ package vexriscv.demo.smp
import spinal.core._
import spinal.lib.bus.bmb._
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig, WishboneSlaveFactory}
import spinal.lib.com.jtag.Jtag
import spinal.lib.com.jtag.{Jtag, JtagTapInstructionCtrl}
import spinal.lib._
import spinal.lib.bus.bmb.sim.{BmbMemoryMultiPort, BmbMemoryTester}
import spinal.lib.bus.misc.{AddressMapping, DefaultMapping, SizeMapping}
import spinal.lib.eda.bench.Bench
import spinal.lib.misc.Clint
import spinal.lib.misc.plic.{PlicGatewayActiveHigh, PlicMapper, PlicMapping, PlicTarget}
import spinal.lib.sim.{SimData, SparseMemory, StreamDriver, StreamMonitor, StreamReadyRandomizer}
import spinal.lib.system.debugger.{JtagBridgeNoTap, SystemDebugger, SystemDebuggerConfig}
import vexriscv.demo.smp.VexRiscvLitexSmpClusterOpenSbi.{cpuCount, parameter}
import vexriscv.demo.smp.VexRiscvSmpClusterGen.vexRiscvConfig
import vexriscv.{VexRiscv, VexRiscvConfig}
@ -25,7 +27,8 @@ case class VexRiscvLitexSmpClusterParameter( cluster : VexRiscvSmpClusterParamet
//addAttribute("""mark_debug = "true"""")
case class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter,
debugClockDomain : ClockDomain) extends Component{
debugClockDomain : ClockDomain,
jtagClockDomain : ClockDomain) extends Component{
val peripheralWishboneConfig = WishboneConfig(
addressWidth = 30,
@ -41,9 +44,9 @@ case class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter,
val iMem = master(LiteDramNative(p.liteDram))
val peripheral = master(Wishbone(peripheralWishboneConfig))
val clint = slave(Wishbone(Clint.getWisboneConfig()))
val externalInterrupts = in Bits(p.cluster.cpuConfigs.size bits)
val externalSupervisorInterrupts = in Bits(p.cluster.cpuConfigs.size bits)
val jtag = slave(Jtag())
val plic = slave(Wishbone(WishboneConfig(addressWidth = 20, dataWidth = 32)))
val interrupts = in Bits(32 bits)
val jtagInstruction = slave(JtagTapInstructionCtrl())
val debugReset = out Bool()
}
val cpuCount = p.cluster.cpuConfigs.size
@ -51,14 +54,25 @@ case class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter,
clint.driveFrom(WishboneSlaveFactory(io.clint))
val cluster = VexRiscvSmpCluster(p.cluster, debugClockDomain)
cluster.io.externalInterrupts <> io.externalInterrupts
cluster.io.externalSupervisorInterrupts <> io.externalSupervisorInterrupts
cluster.io.jtag <> io.jtag
cluster.io.debugReset <> io.debugReset
cluster.io.timerInterrupts <> B(clint.harts.map(_.timerInterrupt))
cluster.io.softwareInterrupts <> B(clint.harts.map(_.softwareInterrupt))
cluster.io.time := clint.time
val debug = debugClockDomain on new Area{
val jtagConfig = SystemDebuggerConfig()
val jtagBridge = new JtagBridgeNoTap(
c = jtagConfig,
jtagClockDomain = jtagClockDomain
)
jtagBridge.io.ctrl << io.jtagInstruction
val debugger = new SystemDebugger(jtagConfig)
debugger.io.remote <> jtagBridge.io.remote
cluster.io.debugBus << debugger.io.mem.toBmb()
}
val dBusDecoder = BmbDecoderOutOfOrder(
p = cluster.io.dMem.p,
mappings = Seq(DefaultMapping, p.liteDramMapping),
@ -114,9 +128,39 @@ case class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter,
val peripheralWishbone = peripheralArbiter.io.output.pipelined(cmdValid = true).toWishbone()
io.peripheral << peripheralWishbone
val plic = new Area{
val priorityWidth = 2
val gateways = for(i <- 1 until 32) yield PlicGatewayActiveHigh(
source = io.interrupts(i),
id = i,
priorityWidth = priorityWidth
)
val bus = WishboneSlaveFactory(io.plic)
val targets = for(i <- 0 until cpuCount) yield new Area{
val machine = PlicTarget(
gateways = gateways,
priorityWidth = priorityWidth
)
val supervisor = PlicTarget(
gateways = gateways,
priorityWidth = priorityWidth
)
cluster.io.externalInterrupts(i) := machine.iep
cluster.io.externalSupervisorInterrupts(i) := supervisor.iep
}
val bridge = PlicMapper(bus, PlicMapping.sifive)(
gateways = gateways,
targets = targets.flatMap(t => List(t.machine, t.supervisor))
)
}
}
//ifconfig eth0 192.168.0.50 netmask 255.255.255.0 up
object VexRiscvLitexSmpClusterGen extends App {
for(cpuCount <- List(1,2,4,8)) {
def parameter = VexRiscvLitexSmpClusterParameter(
@ -136,7 +180,8 @@ object VexRiscvLitexSmpClusterGen extends App {
def dutGen = {
val toplevel = VexRiscvLitexSmpCluster(
p = parameter,
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn"))
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn")),
jtagClockDomain = ClockDomain.external("jtag", withReset = false)
)
toplevel
}
@ -175,7 +220,8 @@ object VexRiscvLitexSmpClusterOpenSbi extends App{
def dutGen = {
val top = VexRiscvLitexSmpCluster(
p = parameter,
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn"))
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn")),
jtagClockDomain = ClockDomain.external("jtag", withReset = false)
)
top.rework{
top.io.clint.setAsDirectionLess.allowDirectionLessIo
@ -216,8 +262,7 @@ object VexRiscvLitexSmpClusterOpenSbi extends App{
dut.io.iMem.simSlave(ram, dut.clockDomain)
dut.io.dMem.simSlave(ram, dut.clockDomain, dut.dMemBridge.unburstified)
dut.io.externalInterrupts #= 0
dut.io.externalSupervisorInterrupts #= 0
dut.io.interrupts #= 0
dut.clockDomain.onFallingEdges{
if(dut.io.peripheral.CYC.toBoolean){

View File

@ -3,13 +3,19 @@ package vexriscv.demo.smp
import spinal.core._
import spinal.lib.bus.bmb._
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig, WishboneSlaveFactory}
import spinal.lib.com.jtag.Jtag
import spinal.lib.com.jtag.{Jtag, JtagTap, JtagTapInstructionCtrl}
import spinal.lib._
import spinal.lib.blackbox.xilinx.s7.BSCANE2
import spinal.lib.bus.bmb.sim.{BmbMemoryMultiPort, BmbMemoryTester}
import spinal.lib.bus.misc.{AddressMapping, DefaultMapping, SizeMapping}
import spinal.lib.com.jtag.sim.JtagTcp
import spinal.lib.com.jtag.xilinx.Bscane2BmbMaster
import spinal.lib.eda.bench.Bench
import spinal.lib.misc.Clint
import spinal.lib.misc.plic.{PlicGatewayActiveHigh, PlicMapper, PlicMapping, PlicTarget}
import spinal.lib.sim.{SimData, SparseMemory, StreamDriver, StreamMonitor, StreamReadyRandomizer}
import spinal.lib.system.debugger.{JtagBridgeNoTap, SystemDebugger, SystemDebuggerConfig}
import sun.jvm.hotspot.oops.DataLayout
import vexriscv.demo.smp.VexRiscvLitexSmpMpClusterOpenSbi.{cpuCount, parameter}
import vexriscv.demo.smp.VexRiscvSmpClusterGen.vexRiscvConfig
import vexriscv.{VexRiscv, VexRiscvConfig}
@ -24,8 +30,9 @@ case class VexRiscvLitexSmpMpClusterParameter( cluster : VexRiscvSmpClusterParam
liteDramMapping : AddressMapping)
//addAttribute("""mark_debug = "true"""")
case class VexRiscvLitexSmpMpCluster(p : VexRiscvLitexSmpMpClusterParameter,
debugClockDomain : ClockDomain) extends Component{
class VexRiscvLitexSmpMpCluster(val p : VexRiscvLitexSmpMpClusterParameter,
val debugClockDomain : ClockDomain,
val jtagClockDomain : ClockDomain) extends Component{
val peripheralWishboneConfig = WishboneConfig(
addressWidth = 30,
@ -43,23 +50,48 @@ case class VexRiscvLitexSmpMpCluster(p : VexRiscvLitexSmpMpClusterParameter,
val iMem = Vec(master(LiteDramNative(p.liteDram)), cpuCount)
val peripheral = master(Wishbone(peripheralWishboneConfig))
val clint = slave(Wishbone(Clint.getWisboneConfig()))
val externalInterrupts = in Bits(p.cluster.cpuConfigs.size bits)
val externalSupervisorInterrupts = in Bits(p.cluster.cpuConfigs.size bits)
val jtag = slave(Jtag())
val plic = slave(Wishbone(WishboneConfig(addressWidth = 20, dataWidth = 32)))
val interrupts = in Bits(32 bits)
val jtagInstruction = slave(JtagTapInstructionCtrl())
val debugReset = out Bool()
}
val clint = Clint(cpuCount)
clint.driveFrom(WishboneSlaveFactory(io.clint))
val cluster = VexRiscvSmpCluster(p.cluster, debugClockDomain)
cluster.io.externalInterrupts <> io.externalInterrupts
cluster.io.externalSupervisorInterrupts <> io.externalSupervisorInterrupts
cluster.io.jtag <> io.jtag
cluster.io.debugReset <> io.debugReset
cluster.io.timerInterrupts <> B(clint.harts.map(_.timerInterrupt))
cluster.io.softwareInterrupts <> B(clint.harts.map(_.softwareInterrupt))
cluster.io.time := clint.time
val debug = debugClockDomain on new Area{
val jtagConfig = SystemDebuggerConfig()
val jtagBridge = new JtagBridgeNoTap(jtagConfig, jtagClockDomain)
jtagBridge.io.ctrl << io.jtagInstruction
val debugger = new SystemDebugger(jtagConfig)
debugger.io.remote <> jtagBridge.io.remote
cluster.io.debugBus << debugger.io.mem.toBmb()
// io.jtagInstruction.allowDirectionLessIo.setAsDirectionLess
// val bridge = Bscane2BmbMaster(1)
// cluster.io.debugBus << bridge.io.bmb
// val bscane2 = BSCANE2(usedId)
// val jtagClockDomain = ClockDomain(bscane2.TCK)
//
// val jtagBridge = new JtagBridgeNoTap(jtagConfig, jtagClockDomain)
// jtagBridge.io.ctrl << bscane2.toJtagTapInstructionCtrl()
//
// val debugger = new SystemDebugger(jtagConfig)
// debugger.io.remote <> jtagBridge.io.remote
//
// io.bmb << debugger.io.mem.toBmb()
}
val dBusDecoder = BmbDecoderOutOfOrder(
p = cluster.io.dMem.p,
mappings = Seq(DefaultMapping, p.liteDramMapping),
@ -116,6 +148,38 @@ case class VexRiscvLitexSmpMpCluster(p : VexRiscvLitexSmpMpClusterParameter,
val dMemBridge = for(id <- 0 until cpuCount) yield {
io.dMem(id).fromBmb(dBusDemux.io.outputs(id), wdataFifoSize = 32, rdataFifoSize = 32)
}
val plic = new Area{
val priorityWidth = 2
val gateways = for(i <- 1 until 32) yield PlicGatewayActiveHigh(
source = io.interrupts(i),
id = i,
priorityWidth = priorityWidth
)
val bus = WishboneSlaveFactory(io.plic)
val targets = for(i <- 0 until cpuCount) yield new Area{
val machine = PlicTarget(
gateways = gateways,
priorityWidth = priorityWidth
)
val supervisor = PlicTarget(
gateways = gateways,
priorityWidth = priorityWidth
)
cluster.io.externalInterrupts(i) := machine.iep
cluster.io.externalSupervisorInterrupts(i) := supervisor.iep
}
val bridge = PlicMapper(bus, PlicMapping.sifive)(
gateways = gateways,
targets = targets.flatMap(t => List(t.machine, t.supervisor))
)
}
//
// io.dMem.foreach(_.cmd.valid.addAttribute("""mark_debug = "true""""))
// io.dMem.foreach(_.cmd.ready.addAttribute("""mark_debug = "true""""))
@ -145,9 +209,10 @@ object VexRiscvLitexSmpMpClusterGen extends App {
)
def dutGen = {
val toplevel = VexRiscvLitexSmpMpCluster(
val toplevel = new VexRiscvLitexSmpMpCluster(
p = parameter,
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn"))
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn")),
jtagClockDomain = ClockDomain.external("jtag", withReset = false)
)
toplevel
}
@ -185,10 +250,20 @@ object VexRiscvLitexSmpMpClusterOpenSbi extends App{
)
def dutGen = {
val top = VexRiscvLitexSmpMpCluster(
val top = new VexRiscvLitexSmpMpCluster(
p = parameter,
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn"))
)
debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn")),
jtagClockDomain = ClockDomain.external("jtag", withReset = false)
){
io.jtagInstruction.allowDirectionLessIo.setAsDirectionLess
val jtag = slave(Jtag())
jtagClockDomain.readClockWire.setAsDirectionLess() := jtag.tck
val jtagLogic = jtagClockDomain on new Area{
val tap = new JtagTap(jtag, 4)
val idcodeArea = tap.idcode(B"x10001FFF")(1)
val wrapper = tap.map(io.jtagInstruction, instructionId = 2)
}
}
top.rework{
top.io.clint.setAsDirectionLess.allowDirectionLessIo
top.io.peripheral.setAsDirectionLess.allowDirectionLessIo.simPublic()
@ -217,6 +292,7 @@ object VexRiscvLitexSmpMpClusterOpenSbi extends App{
dut.debugClockDomain.resetSim #= false
}
JtagTcp(dut.jtag, 10*20)
val ram = SparseMemory()
ram.loadBin(0x80000000l, "../opensbi/build/platform/spinal/vexriscv/sim/smp/firmware/fw_jump.bin")
@ -229,8 +305,8 @@ object VexRiscvLitexSmpMpClusterOpenSbi extends App{
dut.io.dMem(id).simSlave(ram, dut.clockDomain)
}
dut.io.externalInterrupts #= 0
dut.io.externalSupervisorInterrupts #= 0
dut.io.interrupts #= 0
// val stdin = mutable.Queue[Byte]()
// def stdInPush(str : String) = stdin ++= str.toCharArray.map(_.toByte)
@ -272,7 +348,7 @@ object VexRiscvLitexSmpMpClusterOpenSbi extends App{
fork{
val at = 0
val duration = 0
val duration = 1000
while(simTime() < at*1000000l) {
disableSimWave()
sleep(100000 * 10)