diff options
Diffstat (limited to 'VexRiscv/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala')
-rw-r--r-- | VexRiscv/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/VexRiscv/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala b/VexRiscv/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala new file mode 100644 index 0000000..9b08f68 --- /dev/null +++ b/VexRiscv/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala @@ -0,0 +1,179 @@ +package vexriscv + +import spinal.core._ +import spinal.lib.bus.bmb.{Bmb, BmbAccessCapabilities, BmbAccessParameter, BmbImplicitDebugDecoder, BmbInterconnectGenerator, BmbInvalidationParameter, BmbParameter} +import spinal.lib.bus.misc.AddressMapping +import spinal.lib.com.jtag.{Jtag, JtagTapInstructionCtrl} +import spinal.lib.generator._ +import spinal.lib.{sexport, slave} +import vexriscv.plugin._ +import spinal.core.fiber._ + +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: BmbInterconnectGenerator = null) extends Area { + 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.sync(0) + + val iBus, dBus = Handle[Bmb] + + val externalInterrupt = Handle[Bool] + val externalSupervisorInterrupt = Handle[Bool] + val timerInterrupt = Handle[Bool] + val softwareInterrupt = Handle[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.rework{ + this.debugClockDomain.load(debugCd.outputClockDomain) + val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH) + debugAskReset.loadNothing() + withDebug.load(DEBUG_JTAG) + } + + def enableJtagInstructionCtrl(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator) : Unit = debugCd.rework{ + this.debugClockDomain.load(debugCd.outputClockDomain) + val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH) + debugAskReset.loadNothing() + withDebug.load(DEBUG_JTAG_CTRL) + } + + def enableDebugBus(debugCd : ClockDomainResetGenerator, resetCd : ClockDomainResetGenerator) : Unit = debugCd.rework{ + this.debugClockDomain.load(debugCd.outputClockDomain) + val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH) + debugAskReset.loadNothing() + withDebug.load(DEBUG_BUS) + } + + val debugBmbAccessSource = Handle[BmbAccessCapabilities] + val debugBmbAccessRequirements = Handle[BmbAccessParameter] + def enableDebugBmb(debugCd : Handle[ClockDomain], resetCd : ClockDomainResetGenerator, mapping : AddressMapping)(implicit debugMaster : BmbImplicitDebugDecoder = null) : Unit = debugCd.on{ + this.debugClockDomain.load(debugCd) + val resetBridge = resetCd.asyncReset(debugReset, ResetSensitivity.HIGH) + debugAskReset.loadNothing() + withDebug.load(DEBUG_BMB) + val slaveModel = debugCd on interconnectSmp.addSlave( + accessSource = debugBmbAccessSource, + accessCapabilities = debugBmbAccessSource.derivate(DebugExtensionBus.getBmbAccessParameter(_)), + accessRequirements = debugBmbAccessRequirements, + bus = debugBmb, + mapping = mapping + ) + debugBmb.derivatedFrom(debugBmbAccessRequirements)(Bmb(_)) + if(debugMaster != null) interconnectSmp.addConnection(debugMaster.bus, debugBmb) + } + + val jtag = Handle(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 = Handle(new Area { + withDebug.get != DEBUG_NONE generate new Area { + config.add(new DebugPlugin(debugClockDomain, hardwareBreakpointCount)) + } + + val cpu = new VexRiscv(config) + def doExport(value : => Any, postfix : String) = { + sexport(Handle(value).setCompositeName(VexRiscvBmbGenerator.this, postfix)) + } + + doExport(cpu.plugins.exists(_.isInstanceOf[CfuPlugin]), "cfu") + doExport(cpu.plugins.exists(_.isInstanceOf[FpuPlugin]), "fpu") + 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()) + doExport(plugin.config.wayCount, "icacheWays") + doExport(plugin.config.cacheSize, "icacheSize") + doExport(plugin.config.bytePerLine, "bytesPerLine") + } + case plugin: DBusCachedPlugin => { + dBus.load(plugin.dBus.toBmb()) + doExport(plugin.config.wayCount, "dcacheWays") + doExport(plugin.config.cacheSize, "dcacheSize") + doExport(plugin.config.bytePerLine, "bytesPerLine") + } + case plugin: MmuPlugin => { + doExport(true, "mmu") + } + case plugin: StaticMemoryTranslatorPlugin => { + doExport(false, "mmu") + } + case plugin: CsrPlugin => { + doExport(plugin.config.supervisorGen, "supervisor") + 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, 0) + case DEBUG_BUS => debugBus <> plugin.io.bus + case DEBUG_BMB => debugBmb >> plugin.io.bus.fromBmb() + } + } + case _ => + } + }) + + + logic.soon(debugReset) + + 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 _ => + } + } + } + + val invalidationSource = Handle[BmbInvalidationParameter] + val invalidationRequirements = Handle[BmbInvalidationParameter] + if(interconnectSmp != null){ + interconnectSmp.addMaster(accessRequirements = parameterGenerator.iBusParameter.derivate(_.access), bus = iBus) + interconnectSmp.addMaster( + accessRequirements = parameterGenerator.dBusParameter.derivate(_.access), + invalidationSource = invalidationSource, + invalidationCapabilities = invalidationSource, + invalidationRequirements = invalidationRequirements, + bus = dBus + ) + } + +} |