Litex SoC add coherent DMA master
This commit is contained in:
parent
32539dfe6d
commit
c51e25f8c4
|
@ -4,12 +4,13 @@ import spinal.core.SpinalVerilog
|
|||
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
||||
import vexriscv.plugin.{BranchPlugin, CsrPlugin, CsrPluginConfig, DBusSimplePlugin, DecoderSimplePlugin, DivPlugin, FullBarrelShifterPlugin, HazardSimplePlugin, IBusSimplePlugin, IntAluPlugin, LightShifterPlugin, MulPlugin, MulSimplePlugin, NONE, RegFilePlugin, SrcPlugin, YamlPlugin}
|
||||
|
||||
object GenTwoStage extends App{
|
||||
object GenTwoThreeStage extends App{
|
||||
def cpu(withMulDiv : Boolean,
|
||||
bypass : Boolean,
|
||||
barrielShifter : Boolean) = new VexRiscv(
|
||||
barrielShifter : Boolean,
|
||||
withMemoryStage : Boolean) = new VexRiscv(
|
||||
config = VexRiscvConfig(
|
||||
withMemoryStage = false,
|
||||
withMemoryStage = withMemoryStage,
|
||||
withWriteBackStage = false,
|
||||
plugins = List(
|
||||
new IBusSimplePlugin(
|
||||
|
@ -42,8 +43,8 @@ object GenTwoStage extends App{
|
|||
),
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = bypass,
|
||||
bypassMemory = false,
|
||||
bypassWriteBack = false,
|
||||
bypassMemory = bypass,
|
||||
bypassWriteBack = bypass,
|
||||
bypassWriteBackBuffer = bypass,
|
||||
pessimisticUseSrc = false,
|
||||
pessimisticWriteRegFile = false,
|
||||
|
@ -67,5 +68,5 @@ object GenTwoStage extends App{
|
|||
)
|
||||
)
|
||||
|
||||
SpinalVerilog(cpu(false,false,false))
|
||||
SpinalVerilog(cpu(true,true,true,true))
|
||||
}
|
|
@ -108,104 +108,6 @@ class VexRiscvSmpClusterWithPeripherals(p : VexRiscvSmpClusterParameter) extends
|
|||
}
|
||||
|
||||
|
||||
|
||||
//case class VexRiscvSmpCluster(p : VexRiscvSmpClusterParameter,
|
||||
// debugClockDomain : ClockDomain) extends Component{
|
||||
// val dBusParameter = p.cpuConfigs.head.plugins.find(_.isInstanceOf[DBusCachedPlugin]).get.asInstanceOf[DBusCachedPlugin].config.getBmbParameter()
|
||||
// val dBusArbiterParameter = dBusParameter.copy(sourceWidth = log2Up(p.cpuConfigs.size))
|
||||
// val exclusiveMonitorParameter = dBusArbiterParameter
|
||||
// val invalidateMonitorParameter = BmbExclusiveMonitor.outputParameter(exclusiveMonitorParameter)
|
||||
// val dMemParameter = BmbInvalidateMonitor.outputParameter(invalidateMonitorParameter)
|
||||
//
|
||||
// val iBusParameter = p.cpuConfigs.head.plugins.find(_.isInstanceOf[IBusCachedPlugin]).get.asInstanceOf[IBusCachedPlugin].config.getBmbParameter()
|
||||
// val iBusArbiterParameter = iBusParameter//.copy(sourceWidth = log2Up(p.cpuConfigs.size))
|
||||
// val iMemParameter = iBusArbiterParameter
|
||||
//
|
||||
// val io = new Bundle {
|
||||
// val dMem = master(Bmb(dMemParameter))
|
||||
//// val iMem = master(Bmb(iMemParameter))
|
||||
// val iMems = Vec(master(Bmb(iMemParameter)), p.cpuConfigs.size)
|
||||
// val timerInterrupts = in Bits(p.cpuConfigs.size bits)
|
||||
// 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 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 _ =>
|
||||
// }
|
||||
// cpuConfig.plugins += new DebugPlugin(debugClockDomain)
|
||||
// val core = new VexRiscv(cpuConfig)
|
||||
// core.plugins.foreach {
|
||||
// case plugin: IBusCachedPlugin => iBus = plugin.iBus.toBmb()
|
||||
// case plugin: DBusCachedPlugin => dBus = plugin.dBus.toBmb().pipelined(cmdValid = true)
|
||||
// case plugin: CsrPlugin => {
|
||||
// plugin.softwareInterrupt := io.softwareInterrupts(cpuId)
|
||||
// plugin.externalInterrupt := io.externalInterrupts(cpuId)
|
||||
// plugin.timerInterrupt := io.timerInterrupts(cpuId)
|
||||
// if (plugin.config.supervisorGen) plugin.externalInterruptS := io.externalSupervisorInterrupts(cpuId)
|
||||
// if (plugin.utime != null) plugin.utime := io.time
|
||||
// }
|
||||
// case plugin: DebugPlugin => debugClockDomain{
|
||||
// io.debugReset setWhen(RegNext(plugin.io.resetOut))
|
||||
// debug = plugin.io.bus.fromBmb()
|
||||
// }
|
||||
// case _ =>
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val dBusArbiter = BmbArbiter(
|
||||
// p = dBusArbiterParameter,
|
||||
// portCount = cpus.size,
|
||||
// lowerFirstPriority = false,
|
||||
// inputsWithInv = cpus.map(_ => true),
|
||||
// inputsWithSync = cpus.map(_ => true),
|
||||
// pendingInvMax = 16
|
||||
// )
|
||||
//
|
||||
// (dBusArbiter.io.inputs, cpus).zipped.foreach(_ << _.dBus.pipelined(invValid = true, ackValid = true, syncValid = true))
|
||||
//
|
||||
// val exclusiveMonitor = BmbExclusiveMonitor(
|
||||
// inputParameter = exclusiveMonitorParameter,
|
||||
// pendingWriteMax = 64
|
||||
// )
|
||||
// exclusiveMonitor.io.input << dBusArbiter.io.output.pipelined(cmdValid = true, cmdReady = true, rspValid = true)
|
||||
//
|
||||
// val invalidateMonitor = BmbInvalidateMonitor(
|
||||
// inputParameter = invalidateMonitorParameter,
|
||||
// pendingInvMax = 16
|
||||
// )
|
||||
// invalidateMonitor.io.input << exclusiveMonitor.io.output
|
||||
//
|
||||
// io.dMem << invalidateMonitor.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(_ >> _)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//
|
||||
//
|
||||
object VexRiscvSmpClusterGen {
|
||||
def vexRiscvConfig(hartId : Int,
|
||||
ioRange : UInt => Bool = (x => x(31 downto 28) === 0xF),
|
||||
|
@ -222,7 +124,7 @@ object VexRiscvSmpClusterGen {
|
|||
new IBusCachedPlugin(
|
||||
resetVector = resetVector,
|
||||
compressedGen = false,
|
||||
prediction = STATIC,
|
||||
prediction = vexriscv.plugin.NONE,
|
||||
historyRamSizeLog2 = 9,
|
||||
relaxPredictorAddress = true,
|
||||
injectorStage = false,
|
||||
|
@ -309,7 +211,7 @@ object VexRiscvSmpClusterGen {
|
|||
),
|
||||
new CsrPlugin(CsrPluginConfig.openSbi(mhartid = hartId, misa = Riscv.misaToInt("imas")).copy(utimeAccess = CsrAccess.READ_ONLY)),
|
||||
new BranchPlugin(
|
||||
earlyBranch = false,
|
||||
earlyBranch = true,
|
||||
catchAddressMisaligned = true,
|
||||
fenceiGenAsAJump = false
|
||||
),
|
||||
|
@ -318,6 +220,8 @@ object VexRiscvSmpClusterGen {
|
|||
)
|
||||
config
|
||||
}
|
||||
|
||||
|
||||
// def vexRiscvCluster(cpuCount : Int, resetVector : Long = 0x80000000l) = VexRiscvSmpCluster(
|
||||
// debugClockDomain = ClockDomain.current.copy(reset = Bool().setName("debugResetIn")),
|
||||
// p = VexRiscvSmpClusterParameter(
|
||||
|
|
|
@ -3,8 +3,10 @@ package vexriscv.demo.smp
|
|||
import spinal.core._
|
||||
import spinal.lib.bus.bmb._
|
||||
import spinal.lib.bus.misc.{AddressMapping, DefaultMapping, SizeMapping}
|
||||
import spinal.lib.bus.wishbone.{WishboneConfig, WishboneToBmbGenerator}
|
||||
import spinal.lib.sim.SparseMemory
|
||||
import vexriscv.demo.smp.VexRiscvSmpClusterGen.vexRiscvConfig
|
||||
import vexriscv.plugin.DBusCachedPlugin
|
||||
|
||||
|
||||
case class VexRiscvLitexSmpClusterParameter( cluster : VexRiscvSmpClusterParameter,
|
||||
|
@ -27,6 +29,17 @@ class VexRiscvLitexSmpCluster(p : VexRiscvLitexSmpClusterParameter) extends VexR
|
|||
dBridge.liteDramParameter.load(p.liteDram)
|
||||
iBridge.liteDramParameter.load(p.liteDram)
|
||||
|
||||
// Coherent DMA interface
|
||||
val dmaBridge = WishboneToBmbGenerator()
|
||||
val dmaWishbone = dmaBridge.produceIo(dmaBridge.logic.io.input)
|
||||
val dmaDataWidth = p.cluster.cpuConfigs.head.find(classOf[DBusCachedPlugin]).get.config.memDataWidth
|
||||
dmaBridge.config.load(WishboneConfig(
|
||||
addressWidth = 32-log2Up(dmaDataWidth/8),
|
||||
dataWidth = p.cluster.cpuConfigs.head.find(classOf[DBusCachedPlugin]).get.config.memDataWidth,
|
||||
useSTALL = true
|
||||
))
|
||||
interconnect.addConnection(dmaBridge.bmb, exclusiveMonitor.input)
|
||||
|
||||
// Interconnect pipelining (FMax)
|
||||
for(core <- cores) {
|
||||
interconnect.setPipelining(core.cpu.dBus)(cmdValid = true, cmdReady = true, rspValid = true)
|
||||
|
|
|
@ -1,33 +1,73 @@
|
|||
//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, 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}
|
||||
//import vexriscv.plugin.{CsrPlugin, DBusCachedPlugin, DebugPlugin, IBusCachedPlugin}
|
||||
//
|
||||
//import scala.collection.mutable
|
||||
//import scala.util.Random
|
||||
//
|
||||
//
|
||||
//case class VexRiscvLitexSmpMpClusterParameter( 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.bus.wishbone.{WishboneConfig, WishboneToBmbGenerator}
|
||||
import spinal.lib.sim.SparseMemory
|
||||
import vexriscv.demo.smp.VexRiscvSmpClusterGen.vexRiscvConfig
|
||||
|
||||
case class VexRiscvLitexSmpMpClusterParameter( cluster : VexRiscvSmpClusterParameter,
|
||||
liteDram : LiteDramNativeParameter,
|
||||
liteDramMapping : AddressMapping)
|
||||
|
||||
class VexRiscvLitexSmpMpCluster(p : VexRiscvLitexSmpMpClusterParameter) 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 VexRiscvLitexSmpMpClusterGen extends App {
|
||||
for(cpuCount <- List(1,2,4,8)) {
|
||||
def parameter = VexRiscvLitexSmpMpClusterParameter(
|
||||
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 VexRiscvLitexSmpMpCluster(
|
||||
p = parameter
|
||||
).toComponent()
|
||||
toplevel
|
||||
}
|
||||
|
||||
val genConfig = SpinalConfig().addStandardMemBlackboxing(blackboxByteEnables)
|
||||
// genConfig.generateVerilog(Bench.compressIo(dutGen))
|
||||
genConfig.generateVerilog(dutGen.setDefinitionName(s"VexRiscvLitexSmpMpCluster_${cpuCount}c"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
////addAttribute("""mark_debug = "true"""")
|
||||
//class VexRiscvLitexSmpMpCluster(val p : VexRiscvLitexSmpMpClusterParameter,
|
||||
|
|
Loading…
Reference in New Issue