Got VexRiscvSmpLitexCluster refractoring to work
This commit is contained in:
parent
0da94ac66f
commit
32539dfe6d
|
@ -0,0 +1,156 @@
|
|||
package vexriscv
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib.bus.bmb.{Bmb, BmbAccessCapabilities, BmbAccessParameter, BmbImplicitDebugDecoder, BmbParameter, BmbSmpInterconnectGenerator}
|
||||
import spinal.lib.bus.misc.AddressMapping
|
||||
import spinal.lib.com.jtag.{Jtag, JtagTapInstructionCtrl}
|
||||
import spinal.lib.generator._
|
||||
import spinal.lib.slave
|
||||
import vexriscv.plugin._
|
||||
|
||||
|
||||
object VexRiscvBmbGenerator{
|
||||
val DEBUG_NONE = 0
|
||||
val DEBUG_JTAG = 1
|
||||
val DEBUG_JTAG_CTRL = 2
|
||||
val DEBUG_BUS = 3
|
||||
val DEBUG_BMB = 4
|
||||
}
|
||||
|
||||
case class VexRiscvBmbGenerator()(implicit interconnectSmp: BmbSmpInterconnectGenerator = null) extends Generator {
|
||||
import VexRiscvBmbGenerator._
|
||||
|
||||
val config = Handle[VexRiscvConfig]
|
||||
val withDebug = Handle[Int]
|
||||
val debugClockDomain = Handle[ClockDomain]
|
||||
val debugReset = Handle[Bool]
|
||||
val debugAskReset = Handle[() => Unit]
|
||||
val hardwareBreakpointCount = Handle(0)
|
||||
|
||||
val iBus, dBus = product[Bmb]
|
||||
|
||||
val externalInterrupt = product[Bool]
|
||||
val externalSupervisorInterrupt = product[Bool]
|
||||
val timerInterrupt = product[Bool]
|
||||
val softwareInterrupt = product[Bool]
|
||||
|
||||
def setTimerInterrupt(that: Handle[Bool]) = Dependable(that, timerInterrupt){timerInterrupt := that}
|
||||
def setSoftwareInterrupt(that: Handle[Bool]) = Dependable(that, softwareInterrupt){softwareInterrupt := that}
|
||||
|
||||
|
||||
def disableDebug() = {
|
||||
withDebug.load(DEBUG_NONE)
|
||||
}
|
||||
|
||||
def enableJtag(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator) : Unit = debugCd{
|
||||
this.debugClockDomain.merge(debugCd.outputClockDomain)
|
||||
val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH)
|
||||
debugAskReset.load(null)
|
||||
withDebug.load(DEBUG_JTAG)
|
||||
}
|
||||
|
||||
def enableJtagInstructionCtrl(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator) : Unit = debugCd{
|
||||
this.debugClockDomain.merge(debugCd.outputClockDomain)
|
||||
val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH)
|
||||
debugAskReset.load(null)
|
||||
withDebug.load(DEBUG_JTAG_CTRL)
|
||||
dependencies += jtagClockDomain
|
||||
}
|
||||
|
||||
def enableDebugBus(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator) : Unit = debugCd{
|
||||
this.debugClockDomain.merge(debugCd.outputClockDomain)
|
||||
val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH)
|
||||
debugAskReset.load(null)
|
||||
withDebug.load(DEBUG_BUS)
|
||||
}
|
||||
|
||||
val debugBmbAccessSource = Handle[BmbAccessCapabilities]
|
||||
val debugBmbAccessRequirements = Handle[BmbAccessParameter]
|
||||
def enableDebugBmb(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator, mapping : AddressMapping)(implicit debugMaster : BmbImplicitDebugDecoder = null) : Unit = debugCd{
|
||||
this.debugClockDomain.merge(debugCd.outputClockDomain)
|
||||
val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH)
|
||||
debugAskReset.load(null)
|
||||
withDebug.load(DEBUG_BMB)
|
||||
val slaveModel = interconnectSmp.addSlave(
|
||||
accessSource = debugBmbAccessSource,
|
||||
accessCapabilities = debugBmbAccessSource.derivate(DebugExtensionBus.getBmbAccessParameter(_)),
|
||||
accessRequirements = debugBmbAccessRequirements,
|
||||
bus = debugBmb,
|
||||
mapping = mapping
|
||||
)
|
||||
slaveModel.onClockDomain(debugCd.outputClockDomain)
|
||||
debugBmb.derivatedFrom(debugBmbAccessRequirements)(Bmb(_))
|
||||
if(debugMaster != null) interconnectSmp.addConnection(debugMaster.bus, debugBmb)
|
||||
dependencies += debugBmb
|
||||
}
|
||||
|
||||
|
||||
dependencies ++= List(config)
|
||||
dependencies += Dependable(withDebug) {
|
||||
if (withDebug.get != DEBUG_NONE) {
|
||||
dependencies ++= List(debugClockDomain, debugAskReset)
|
||||
}
|
||||
}
|
||||
|
||||
val jtag = add task (withDebug.get == DEBUG_JTAG generate slave(Jtag()))
|
||||
val jtagInstructionCtrl = withDebug.produce(withDebug.get == DEBUG_JTAG_CTRL generate JtagTapInstructionCtrl())
|
||||
val debugBus = withDebug.produce(withDebug.get == DEBUG_BUS generate DebugExtensionBus())
|
||||
val debugBmb = Handle[Bmb]
|
||||
val jtagClockDomain = Handle[ClockDomain]
|
||||
|
||||
val logic = add task new Area {
|
||||
withDebug.get != DEBUG_NONE generate new Area {
|
||||
config.add(new DebugPlugin(debugClockDomain, hardwareBreakpointCount))
|
||||
}
|
||||
|
||||
val cpu = new VexRiscv(config)
|
||||
for (plugin <- cpu.plugins) plugin match {
|
||||
case plugin: IBusSimplePlugin => iBus.load(plugin.iBus.toBmb())
|
||||
case plugin: DBusSimplePlugin => dBus.load(plugin.dBus.toBmb())
|
||||
case plugin: IBusCachedPlugin => iBus.load(plugin.iBus.toBmb())
|
||||
case plugin: DBusCachedPlugin => dBus.load(plugin.dBus.toBmb())
|
||||
case plugin: CsrPlugin => {
|
||||
externalInterrupt load plugin.externalInterrupt
|
||||
timerInterrupt load plugin.timerInterrupt
|
||||
softwareInterrupt load plugin.softwareInterrupt
|
||||
if (plugin.config.supervisorGen) externalSupervisorInterrupt load plugin.externalInterruptS
|
||||
}
|
||||
case plugin: DebugPlugin => plugin.debugClockDomain {
|
||||
if(debugAskReset.get != null) when(RegNext(plugin.io.resetOut)) {
|
||||
debugAskReset.get()
|
||||
} else {
|
||||
debugReset.load(RegNext(plugin.io.resetOut))
|
||||
}
|
||||
|
||||
withDebug.get match {
|
||||
case DEBUG_JTAG => jtag <> plugin.io.bus.fromJtag()
|
||||
case DEBUG_JTAG_CTRL => jtagInstructionCtrl <> plugin.io.bus.fromJtagInstructionCtrl(jtagClockDomain)
|
||||
case DEBUG_BUS => debugBus <> plugin.io.bus
|
||||
case DEBUG_BMB => debugBmb >> plugin.io.bus.fromBmb()
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
val parameterGenerator = new Generator {
|
||||
val iBusParameter, dBusParameter = product[BmbParameter]
|
||||
dependencies += config
|
||||
|
||||
add task {
|
||||
for (plugin <- config.plugins) plugin match {
|
||||
case plugin: IBusSimplePlugin => iBusParameter.load(IBusSimpleBus.getBmbParameter())
|
||||
case plugin: DBusSimplePlugin => dBusParameter.load(DBusSimpleBus.getBmbParameter())
|
||||
case plugin: IBusCachedPlugin => iBusParameter.load(plugin.config.getBmbParameter())
|
||||
case plugin: DBusCachedPlugin => dBusParameter.load(plugin.config.getBmbParameter())
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(interconnectSmp != null){
|
||||
interconnectSmp.addMaster(accessRequirements = parameterGenerator.iBusParameter.derivate(_.access), bus = iBus)
|
||||
interconnectSmp.addMaster(accessRequirements = parameterGenerator.dBusParameter.derivate(_.access), bus = dBus)
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ 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.generator.{Generator, Handle}
|
||||
import spinal.lib.misc.Clint
|
||||
import spinal.lib.sim.{SimData, SparseMemory, StreamDriver, StreamMonitor, StreamReadyRandomizer}
|
||||
import vexriscv.{VexRiscv, VexRiscvConfig}
|
||||
|
@ -244,4 +245,44 @@ object BmbToLiteDramTester extends App{
|
|||
val tester = new BmbMemoryTester(dut.io.input, dut.clockDomain, rspCounterTarget = 3000)
|
||||
dut.io.output.simSlave(tester.memory.memory, dut.clockDomain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case class BmbToLiteDramGenerator(mapping : AddressMapping)(implicit interconnect : BmbSmpInterconnectGenerator) extends Generator{
|
||||
val liteDramParameter = createDependency[LiteDramNativeParameter]
|
||||
val bmb = produce(logic.io.input)
|
||||
val dram = produceIo(logic.io.output)
|
||||
|
||||
val accessSource = Handle[BmbAccessCapabilities]
|
||||
val accessRequirements = createDependency[BmbAccessParameter]
|
||||
interconnect.addSlave(
|
||||
accessSource = accessSource,
|
||||
accessCapabilities = accessSource,
|
||||
accessRequirements = accessRequirements,
|
||||
bus = bmb,
|
||||
mapping = mapping
|
||||
)
|
||||
val logic = add task BmbToLiteDram(
|
||||
bmbParameter = accessRequirements.toBmbParameter(),
|
||||
liteDramParameter = liteDramParameter,
|
||||
wdataFifoSize = 32,
|
||||
rdataFifoSize = 32
|
||||
)
|
||||
}
|
||||
|
||||
case class BmbToWishboneGenerator(mapping : AddressMapping)(implicit interconnect : BmbSmpInterconnectGenerator) extends Generator{
|
||||
val bmb = produce(logic.io.input)
|
||||
val wishbone = produce(logic.io.output)
|
||||
|
||||
val accessSource = Handle[BmbAccessCapabilities]
|
||||
val accessRequirements = createDependency[BmbAccessParameter]
|
||||
interconnect.addSlave(
|
||||
accessSource = accessSource,
|
||||
accessCapabilities = accessSource,
|
||||
accessRequirements = accessRequirements,
|
||||
bus = bmb,
|
||||
mapping = mapping
|
||||
)
|
||||
val logic = add task BmbToWishbone(
|
||||
p = accessRequirements.toBmbParameter()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,21 +5,110 @@ import spinal.core._
|
|||
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.bus.misc.SizeMapping
|
||||
import spinal.lib.com.jtag.{Jtag, JtagTapInstructionCtrl}
|
||||
import spinal.lib.bus.bmb._
|
||||
import spinal.lib.bus.misc.{DefaultMapping, SizeMapping}
|
||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig, WishboneToBmb, WishboneToBmbGenerator}
|
||||
import spinal.lib.com.jtag.{Jtag, JtagInstructionDebuggerGenerator, JtagTapInstructionCtrl}
|
||||
import spinal.lib.com.jtag.sim.JtagTcp
|
||||
import spinal.lib.com.jtag.xilinx.Bscane2BmbMasterGenerator
|
||||
import spinal.lib.generator.Handle
|
||||
import spinal.lib.misc.plic.PlicMapping
|
||||
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}
|
||||
import vexriscv.{Riscv, VexRiscv, VexRiscvBmbGenerator, VexRiscvConfig, plugin}
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import spinal.lib.generator._
|
||||
|
||||
case class VexRiscvSmpClusterParameter( cpuConfigs : Seq[VexRiscvConfig])
|
||||
|
||||
class VexRiscvSmpClusterBase(p : VexRiscvSmpClusterParameter) extends Generator{
|
||||
val cpuCount = p.cpuConfigs.size
|
||||
|
||||
val debugCd = ClockDomainResetGenerator()
|
||||
debugCd.holdDuration.load(4095)
|
||||
debugCd.makeExternal()
|
||||
|
||||
val systemCd = ClockDomainResetGenerator()
|
||||
systemCd.holdDuration.load(63)
|
||||
systemCd.setInput(debugCd)
|
||||
|
||||
this.onClockDomain(systemCd.outputClockDomain)
|
||||
|
||||
implicit val interconnect = BmbSmpInterconnectGenerator()
|
||||
|
||||
val debugBridge = JtagInstructionDebuggerGenerator() onClockDomain(debugCd.outputClockDomain)
|
||||
debugBridge.jtagClockDomain.load(ClockDomain.external("jtag", withReset = false))
|
||||
|
||||
val debugPort = debugBridge.produceIo(debugBridge.logic.jtagBridge.io.ctrl)
|
||||
|
||||
val exclusiveMonitor = BmbExclusiveMonitorGenerator()
|
||||
val invalidationMonitor = BmbInvalidateMonitorGenerator()
|
||||
interconnect.addConnection(exclusiveMonitor.output, invalidationMonitor.input)
|
||||
interconnect.masters(invalidationMonitor.output).withOutOfOrderDecoder()
|
||||
|
||||
val cores = for(cpuId <- 0 until cpuCount) yield new Area{
|
||||
val cpu = VexRiscvBmbGenerator()
|
||||
cpu.config.load(p.cpuConfigs(cpuId))
|
||||
interconnect.addConnection(
|
||||
cpu.dBus -> List(exclusiveMonitor.input)
|
||||
)
|
||||
cpu.enableDebugBmb(
|
||||
debugCd = debugCd,
|
||||
resetCd = systemCd,
|
||||
mapping = SizeMapping(cpuId*0x1000, 0x1000)
|
||||
)
|
||||
interconnect.addConnection(debugBridge.bmb, cpu.debugBmb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class VexRiscvSmpClusterWithPeripherals(p : VexRiscvSmpClusterParameter) extends VexRiscvSmpClusterBase(p) {
|
||||
val peripheralBridge = BmbToWishboneGenerator(DefaultMapping)
|
||||
val peripheral = peripheralBridge.produceIo(peripheralBridge.logic.io.output)
|
||||
interconnect.slaves(peripheralBridge.bmb).forceAccessSourceDataWidth(32)
|
||||
|
||||
val plic = BmbPlicGenerator(0)
|
||||
plic.priorityWidth.load(2)
|
||||
plic.mapping.load(PlicMapping.sifive)
|
||||
|
||||
val plicWishboneBridge = WishboneToBmbGenerator()
|
||||
val plicWishbone = plicWishboneBridge.produceIo(plicWishboneBridge.logic.io.input)
|
||||
plicWishboneBridge.config.load(WishboneConfig(20, 32))
|
||||
interconnect.addConnection(plicWishboneBridge.bmb, plic.bus)
|
||||
|
||||
val clint = BmbClintGenerator(0)
|
||||
|
||||
val clintWishboneBridge = WishboneToBmbGenerator()
|
||||
val clintWishbone = clintWishboneBridge.produceIo(clintWishboneBridge.logic.io.input)
|
||||
clintWishboneBridge.config.load(WishboneConfig(14, 32))
|
||||
interconnect.addConnection(clintWishboneBridge.bmb, clint.bus)
|
||||
|
||||
val interrupts = add task (in Bits(32 bits))
|
||||
for(i <- 1 to 31) yield plic.addInterrupt(interrupts.derivate(_.apply(i)), i)
|
||||
|
||||
for ((core, cpuId) <- cores.zipWithIndex) {
|
||||
core.cpu.setTimerInterrupt(clint.timerInterrupt(cpuId))
|
||||
core.cpu.setSoftwareInterrupt(clint.softwareInterrupt(cpuId))
|
||||
plic.priorityWidth.load(2)
|
||||
plic.mapping.load(PlicMapping.sifive)
|
||||
plic.addTarget(core.cpu.externalInterrupt)
|
||||
plic.addTarget(core.cpu.externalSupervisorInterrupt)
|
||||
List(clint.logic, core.cpu.logic).produce {
|
||||
for (plugin <- core.cpu.config.plugins) plugin match {
|
||||
case plugin: CsrPlugin if plugin.utime != null => plugin.utime := clint.logic.io.time
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clint.cpuCount.load(cpuCount)
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
//case class VexRiscvSmpClusterParameter( cpuConfigs : Seq[VexRiscvConfig])
|
||||
//
|
||||
//case class VexRiscvSmpCluster(p : VexRiscvSmpClusterParameter,
|
||||
// debugClockDomain : ClockDomain) extends Component{
|
||||
// val dBusParameter = p.cpuConfigs.head.plugins.find(_.isInstanceOf[DBusCachedPlugin]).get.asInstanceOf[DBusCachedPlugin].config.getBmbParameter()
|
||||
|
|
|
@ -1,305 +1,150 @@
|
|||
//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, 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}
|
||||
//import vexriscv.plugin.{CsrPlugin, DBusCachedPlugin, DebugPlugin, IBusCachedPlugin}
|
||||
//
|
||||
//import scala.collection.mutable
|
||||
//import scala.util.Random
|
||||
//
|
||||
//
|
||||
//case class VexRiscvLitexSmpClusterParameter( cluster : VexRiscvSmpClusterParameter,
|
||||
// liteDram : LiteDramNativeParameter,
|
||||
// liteDramMapping : AddressMapping)
|
||||
//
|
||||
package vexriscv.demo.smp
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib.bus.bmb._
|
||||
import spinal.lib.bus.misc.{AddressMapping, DefaultMapping, SizeMapping}
|
||||
import spinal.lib.sim.SparseMemory
|
||||
import vexriscv.demo.smp.VexRiscvSmpClusterGen.vexRiscvConfig
|
||||
|
||||
|
||||
case class VexRiscvLitexSmpClusterParameter( cluster : VexRiscvSmpClusterParameter,
|
||||
liteDram : LiteDramNativeParameter,
|
||||
liteDramMapping : AddressMapping)
|
||||
|
||||
|
||||
class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter) extends VexRiscvSmpClusterWithPeripherals(p.cluster) {
|
||||
val iArbiter = BmbSmpBridgeGenerator()
|
||||
val iBridge = BmbToLiteDramGenerator(p.liteDramMapping)
|
||||
val dBridge = BmbToLiteDramGenerator(p.liteDramMapping)
|
||||
|
||||
for(core <- cores) interconnect.addConnection(core.cpu.iBus -> List(iArbiter.bmb))
|
||||
interconnect.addConnection(
|
||||
iArbiter.bmb -> List(iBridge.bmb, peripheralBridge.bmb),
|
||||
invalidationMonitor.output -> List(dBridge.bmb, peripheralBridge.bmb)
|
||||
)
|
||||
interconnect.masters(invalidationMonitor.output).withOutOfOrderDecoder()
|
||||
|
||||
dBridge.liteDramParameter.load(p.liteDram)
|
||||
iBridge.liteDramParameter.load(p.liteDram)
|
||||
|
||||
// Interconnect pipelining (FMax)
|
||||
for(core <- cores) {
|
||||
interconnect.setPipelining(core.cpu.dBus)(cmdValid = true, cmdReady = true, rspValid = true)
|
||||
interconnect.setPipelining(core.cpu.iBus)(cmdHalfRate = true, rspValid = true)
|
||||
interconnect.setPipelining(iArbiter.bmb)(cmdHalfRate = true, rspValid = true)
|
||||
}
|
||||
interconnect.setPipelining(invalidationMonitor.output)(cmdValid = true, cmdReady = true, rspValid = true)
|
||||
interconnect.setPipelining(peripheralBridge.bmb)(cmdHalfRate = true, rspValid = true)
|
||||
}
|
||||
|
||||
|
||||
object VexRiscvLitexSmpClusterGen extends App {
|
||||
for(cpuCount <- List(1,2,4,8)) {
|
||||
def parameter = VexRiscvLitexSmpClusterParameter(
|
||||
cluster = VexRiscvSmpClusterParameter(
|
||||
cpuConfigs = List.tabulate(cpuCount) { hartId =>
|
||||
vexRiscvConfig(
|
||||
hartId = hartId,
|
||||
ioRange = address => address.msb,
|
||||
resetVector = 0
|
||||
)
|
||||
}
|
||||
),
|
||||
liteDram = LiteDramNativeParameter(addressWidth = 32, dataWidth = 128),
|
||||
liteDramMapping = SizeMapping(0x40000000l, 0x40000000l)
|
||||
)
|
||||
|
||||
def dutGen = {
|
||||
val toplevel = new VexRiscvLitexSmpCluster(
|
||||
p = parameter
|
||||
).toComponent()
|
||||
toplevel
|
||||
}
|
||||
|
||||
val genConfig = SpinalConfig().addStandardMemBlackboxing(blackboxByteEnables)
|
||||
// genConfig.generateVerilog(Bench.compressIo(dutGen))
|
||||
genConfig.generateVerilog(dutGen.setDefinitionName(s"VexRiscvLitexSmpCluster_${cpuCount}c"))
|
||||
}
|
||||
}
|
||||
|
||||
////addAttribute("""mark_debug = "true"""")
|
||||
//case class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter,
|
||||
// debugClockDomain : ClockDomain,
|
||||
// jtagClockDomain : ClockDomain) extends Component{
|
||||
//
|
||||
// val peripheralWishboneConfig = WishboneConfig(
|
||||
// addressWidth = 30,
|
||||
// dataWidth = 32,
|
||||
// selWidth = 4,
|
||||
// useERR = true,
|
||||
// useBTE = true,
|
||||
// useCTI = true
|
||||
// )
|
||||
//
|
||||
// val io = new Bundle {
|
||||
// val dMem = master(LiteDramNative(p.liteDram))
|
||||
// val iMem = master(LiteDramNative(p.liteDram))
|
||||
// val peripheral = master(Wishbone(peripheralWishboneConfig))
|
||||
// val clint = slave(Wishbone(Clint.getWisboneConfig()))
|
||||
// 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
|
||||
// val clint = Clint(cpuCount)
|
||||
// clint.driveFrom(WishboneSlaveFactory(io.clint))
|
||||
//
|
||||
// val cluster = VexRiscvSmpCluster(p.cluster, debugClockDomain)
|
||||
// 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),
|
||||
// capabilities = Seq(cluster.io.dMem.p, cluster.io.dMem.p),
|
||||
// pendingRspTransactionMax = 32
|
||||
// )
|
||||
//// val dBusDecoder = BmbDecoderOut(
|
||||
//// p = cluster.io.dMem.p,
|
||||
//// mappings = Seq(DefaultMapping, p.liteDramMapping),
|
||||
//// capabilities = Seq(cluster.io.dMem.p, cluster.io.dMem.p),
|
||||
//// pendingMax = 31
|
||||
//// )
|
||||
// dBusDecoder.io.input << cluster.io.dMem.pipelined(cmdValid = true, cmdReady = true, rspValid = true)
|
||||
// val dMemBridge = io.dMem.fromBmb(dBusDecoder.io.outputs(1), wdataFifoSize = 32, rdataFifoSize = 32)
|
||||
//
|
||||
// val iBusArbiterParameter = cluster.iBusParameter.copy(sourceWidth = log2Up(cpuCount))
|
||||
// val iBusArbiter = BmbArbiter(
|
||||
// p = iBusArbiterParameter,
|
||||
// portCount = cpuCount,
|
||||
// lowerFirstPriority = false
|
||||
// )
|
||||
//
|
||||
// (iBusArbiter.io.inputs, cluster.io.iMems).zipped.foreach(_ << _.pipelined(cmdHalfRate = true, rspValid = true))
|
||||
//
|
||||
// val iBusDecoder = BmbDecoder(
|
||||
// p = iBusArbiter.io.output.p,
|
||||
// mappings = Seq(DefaultMapping, p.liteDramMapping),
|
||||
// capabilities = Seq(iBusArbiterParameter, iBusArbiterParameter),
|
||||
// pendingMax = 15
|
||||
// )
|
||||
// iBusDecoder.io.input << iBusArbiter.io.output.pipelined(cmdValid = true)
|
||||
//
|
||||
// val iMem = LiteDramNative(p.liteDram)
|
||||
// io.iMem.fromBmb(iBusDecoder.io.outputs(1), wdataFifoSize = 0, rdataFifoSize = 32)
|
||||
//
|
||||
//
|
||||
// val iBusDecoderToPeripheral = iBusDecoder.io.outputs(0).resize(dataWidth = 32).pipelined(cmdHalfRate = true, rspValid = true)
|
||||
// val dBusDecoderToPeripheral = dBusDecoder.io.outputs(0).resize(dataWidth = 32).pipelined(cmdHalfRate = true, rspValid = true)
|
||||
//
|
||||
// val peripheralAccessLength = Math.max(iBusDecoder.io.outputs(0).p.lengthWidth, dBusDecoder.io.outputs(0).p.lengthWidth)
|
||||
// val peripheralArbiter = BmbArbiter(
|
||||
// p = dBusDecoder.io.outputs(0).p.copy(
|
||||
// sourceWidth = List(iBusDecoderToPeripheral, dBusDecoderToPeripheral).map(_.p.sourceWidth).max + 1,
|
||||
// contextWidth = List(iBusDecoderToPeripheral, dBusDecoderToPeripheral).map(_.p.contextWidth).max,
|
||||
// lengthWidth = peripheralAccessLength,
|
||||
// dataWidth = 32
|
||||
// ),
|
||||
// portCount = 2,
|
||||
// lowerFirstPriority = true
|
||||
// )
|
||||
// peripheralArbiter.io.inputs(0) << iBusDecoderToPeripheral
|
||||
// peripheralArbiter.io.inputs(1) << dBusDecoderToPeripheral
|
||||
//
|
||||
// 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))
|
||||
// )
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//object VexRiscvLitexSmpClusterGen extends App {
|
||||
// for(cpuCount <- List(1,2,4,8)) {
|
||||
// def parameter = VexRiscvLitexSmpClusterParameter(
|
||||
// cluster = VexRiscvSmpClusterParameter(
|
||||
// cpuConfigs = List.tabulate(cpuCount) { hartId =>
|
||||
// vexRiscvConfig(
|
||||
// hartId = hartId,
|
||||
// ioRange = address => address.msb,
|
||||
// resetVector = 0
|
||||
// )
|
||||
// }
|
||||
// ),
|
||||
// liteDram = LiteDramNativeParameter(addressWidth = 32, dataWidth = 128),
|
||||
// liteDramMapping = SizeMapping(0x40000000l, 0x40000000l)
|
||||
// )
|
||||
//
|
||||
// def dutGen = {
|
||||
// val toplevel = VexRiscvLitexSmpCluster(
|
||||
// p = parameter,
|
||||
// debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn")),
|
||||
// jtagClockDomain = ClockDomain.external("jtag", withReset = false)
|
||||
// )
|
||||
// toplevel
|
||||
// }
|
||||
//
|
||||
// val genConfig = SpinalConfig().addStandardMemBlackboxing(blackboxByteEnables)
|
||||
// // genConfig.generateVerilog(Bench.compressIo(dutGen))
|
||||
// genConfig.generateVerilog(dutGen.setDefinitionName(s"VexRiscvLitexSmpCluster_${cpuCount}c"))
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
//
|
||||
//object VexRiscvLitexSmpClusterOpenSbi extends App{
|
||||
// import spinal.core.sim._
|
||||
//
|
||||
// val simConfig = SimConfig
|
||||
// simConfig.withWave
|
||||
// simConfig.allOptimisation
|
||||
//
|
||||
// val cpuCount = 2
|
||||
//
|
||||
// def parameter = VexRiscvLitexSmpClusterParameter(
|
||||
// cluster = VexRiscvSmpClusterParameter(
|
||||
// cpuConfigs = List.tabulate(cpuCount) { hartId =>
|
||||
// vexRiscvConfig(
|
||||
// hartId = hartId,
|
||||
// ioRange = address => address(31 downto 28) === 0xF,
|
||||
// resetVector = 0x80000000l
|
||||
// )
|
||||
// }
|
||||
// ),
|
||||
// liteDram = LiteDramNativeParameter(addressWidth = 32, dataWidth = 128),
|
||||
// liteDramMapping = SizeMapping(0x80000000l, 0x70000000l)
|
||||
// )
|
||||
//
|
||||
// def dutGen = {
|
||||
// val top = VexRiscvLitexSmpCluster(
|
||||
// p = parameter,
|
||||
// debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn")),
|
||||
// jtagClockDomain = ClockDomain.external("jtag", withReset = false)
|
||||
// )
|
||||
// top.rework{
|
||||
// top.io.clint.setAsDirectionLess.allowDirectionLessIo
|
||||
// top.io.peripheral.setAsDirectionLess.allowDirectionLessIo.simPublic()
|
||||
//
|
||||
// val hit = (top.io.peripheral.ADR <<2 >= 0xF0010000l && top.io.peripheral.ADR<<2 < 0xF0020000l)
|
||||
// top.io.clint.CYC := top.io.peripheral.CYC && hit
|
||||
// top.io.clint.STB := top.io.peripheral.STB
|
||||
// top.io.clint.WE := top.io.peripheral.WE
|
||||
// top.io.clint.ADR := top.io.peripheral.ADR.resized
|
||||
// top.io.clint.DAT_MOSI := top.io.peripheral.DAT_MOSI
|
||||
// top.io.peripheral.DAT_MISO := top.io.clint.DAT_MISO
|
||||
// top.io.peripheral.ACK := top.io.peripheral.CYC && (!hit || top.io.clint.ACK)
|
||||
// top.io.peripheral.ERR := False
|
||||
//
|
||||
object VexRiscvLitexSmpClusterOpenSbi extends App{
|
||||
import spinal.core.sim._
|
||||
|
||||
val simConfig = SimConfig
|
||||
simConfig.withWave
|
||||
simConfig.allOptimisation
|
||||
|
||||
val cpuCount = 2
|
||||
|
||||
def parameter = VexRiscvLitexSmpClusterParameter(
|
||||
cluster = VexRiscvSmpClusterParameter(
|
||||
cpuConfigs = List.tabulate(cpuCount) { hartId =>
|
||||
vexRiscvConfig(
|
||||
hartId = hartId,
|
||||
ioRange = address => address(31 downto 28) === 0xF,
|
||||
resetVector = 0x80000000l
|
||||
)
|
||||
}
|
||||
),
|
||||
liteDram = LiteDramNativeParameter(addressWidth = 32, dataWidth = 128),
|
||||
liteDramMapping = SizeMapping(0x80000000l, 0x70000000l)
|
||||
)
|
||||
|
||||
def dutGen = {
|
||||
val top = new VexRiscvLitexSmpCluster(
|
||||
p = parameter
|
||||
).toComponent()
|
||||
top.rework{
|
||||
top.clintWishbone.setAsDirectionLess.allowDirectionLessIo
|
||||
top.peripheral.setAsDirectionLess.allowDirectionLessIo.simPublic()
|
||||
|
||||
val hit = (top.peripheral.ADR <<2 >= 0xF0010000l && top.peripheral.ADR<<2 < 0xF0020000l)
|
||||
top.clintWishbone.CYC := top.peripheral.CYC && hit
|
||||
top.clintWishbone.STB := top.peripheral.STB
|
||||
top.clintWishbone.WE := top.peripheral.WE
|
||||
top.clintWishbone.ADR := top.peripheral.ADR.resized
|
||||
top.clintWishbone.DAT_MOSI := top.peripheral.DAT_MOSI
|
||||
top.peripheral.DAT_MISO := top.clintWishbone.DAT_MISO
|
||||
top.peripheral.ACK := top.peripheral.CYC && (!hit || top.clintWishbone.ACK)
|
||||
top.peripheral.ERR := False
|
||||
|
||||
// top.dMemBridge.unburstified.cmd.simPublic()
|
||||
// }
|
||||
// top
|
||||
// }
|
||||
// simConfig.compile(dutGen).doSimUntilVoid(seed = 42){dut =>
|
||||
// dut.clockDomain.forkStimulus(10)
|
||||
// fork {
|
||||
// dut.debugClockDomain.resetSim #= false
|
||||
// sleep (0)
|
||||
// dut.debugClockDomain.resetSim #= true
|
||||
// sleep (10)
|
||||
// dut.debugClockDomain.resetSim #= false
|
||||
// }
|
||||
//
|
||||
//
|
||||
// val ram = SparseMemory()
|
||||
// ram.loadBin(0x80000000l, "../opensbi/build/platform/spinal/vexriscv/sim/smp/firmware/fw_jump.bin")
|
||||
// ram.loadBin(0xC0000000l, "../buildroot/output/images/Image")
|
||||
// ram.loadBin(0xC1000000l, "../buildroot/output/images/dtb")
|
||||
// ram.loadBin(0xC2000000l, "../buildroot/output/images/rootfs.cpio")
|
||||
//
|
||||
//
|
||||
// dut.io.iMem.simSlave(ram, dut.clockDomain)
|
||||
// dut.io.dMem.simSlave(ram, dut.clockDomain, dut.dMemBridge.unburstified)
|
||||
//
|
||||
// dut.io.interrupts #= 0
|
||||
//
|
||||
// dut.clockDomain.onFallingEdges{
|
||||
// if(dut.io.peripheral.CYC.toBoolean){
|
||||
// (dut.io.peripheral.ADR.toLong << 2) match {
|
||||
// case 0xF0000000l => print(dut.io.peripheral.DAT_MOSI.toLong.toChar)
|
||||
// case 0xF0000004l => dut.io.peripheral.DAT_MISO #= (if(System.in.available() != 0) System.in.read() else 0xFFFFFFFFl)
|
||||
// case _ =>
|
||||
// }
|
||||
//// println(f"${dut.io.peripheral.ADR.toLong}%x")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//// fork{
|
||||
//// disableSimWave()
|
||||
//// val atMs = 3790
|
||||
//// val durationMs = 5
|
||||
//// sleep(atMs*1000000l)
|
||||
//// enableSimWave()
|
||||
//// println("** enableSimWave **")
|
||||
//// sleep(durationMs*1000000l)
|
||||
//// println("** disableSimWave **")
|
||||
//// while(true) {
|
||||
//// disableSimWave()
|
||||
//// sleep(100000 * 10)
|
||||
//// enableSimWave()
|
||||
//// sleep( 100 * 10)
|
||||
//// }
|
||||
//// // simSuccess()
|
||||
//// }
|
||||
//
|
||||
// fork{
|
||||
// while(true) {
|
||||
// disableSimWave()
|
||||
// sleep(100000 * 10)
|
||||
// enableSimWave()
|
||||
// sleep( 100 * 10)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
top
|
||||
}
|
||||
simConfig.compile(dutGen).doSimUntilVoid(seed = 42){dut =>
|
||||
dut.debugCd.inputClockDomain.get.forkStimulus(10)
|
||||
|
||||
val ram = SparseMemory()
|
||||
ram.loadBin(0x80000000l, "../opensbi/build/platform/spinal/vexriscv/sim/smp/firmware/fw_jump.bin")
|
||||
ram.loadBin(0xC0000000l, "../buildroot/output/images/Image")
|
||||
ram.loadBin(0xC1000000l, "../buildroot/output/images/dtb")
|
||||
ram.loadBin(0xC2000000l, "../buildroot/output/images/rootfs.cpio")
|
||||
|
||||
|
||||
dut.iBridge.dram.simSlave(ram, dut.debugCd.inputClockDomain)
|
||||
dut.dBridge.dram.simSlave(ram, dut.debugCd.inputClockDomain/*, dut.dMemBridge.unburstified*/)
|
||||
|
||||
dut.interrupts.get #= 0
|
||||
|
||||
dut.debugCd.inputClockDomain.get.onFallingEdges{
|
||||
if(dut.peripheral.CYC.toBoolean){
|
||||
(dut.peripheral.ADR.toLong << 2) match {
|
||||
case 0xF0000000l => print(dut.peripheral.DAT_MOSI.toLong.toChar)
|
||||
case 0xF0000004l => dut.peripheral.DAT_MISO #= (if(System.in.available() != 0) System.in.read() else 0xFFFFFFFFl)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fork{
|
||||
while(true) {
|
||||
disableSimWave()
|
||||
sleep(100000 * 10)
|
||||
enableSimWave()
|
||||
sleep( 100 * 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue