From aa477b2b1c81d65f0978b91ba8efc96cb99f7d32 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Thu, 10 Aug 2017 20:56:54 +0200 Subject: [PATCH] DebugPlugin now prevent the CPU catching exception when debug instruction are pushed Fix DataCache locking when loading mem read rsp transaction has the flag set Briey : Now the debug module reset the whole AXI system instead of only the CPU Now in debug, you can access unmapped memory without crashing the CPU --- src/main/scala/vexriscv/Services.scala | 3 + src/main/scala/vexriscv/TestsWorkspace.scala | 98 +++++++++---------- src/main/scala/vexriscv/demo/Briey.scala | 53 +++++----- src/main/scala/vexriscv/ip/DataCache.scala | 6 +- .../scala/vexriscv/plugin/CsrPlugin.scala | 8 +- .../scala/vexriscv/plugin/DebugPlugin.scala | 5 + 6 files changed, 90 insertions(+), 83 deletions(-) diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index d0c8280..5d6e371 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -34,6 +34,9 @@ trait InterruptionInhibitor{ def inhibateInterrupts() : Unit } +trait ExceptionInhibitor{ + def inhibateException() : Unit +} case class MemoryTranslatorCmd() extends Bundle{ val isValid = Bool diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index 99a379d..44a5150 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -35,61 +35,61 @@ object TestsWorkspace { resetVector = 0x00000000l, relaxedPcCalculation = false ), - new IBusSimplePlugin( - interfaceKeepData = false, - catchAccessFault = true - ), -// new IBusCachedPlugin( -// config = InstructionCacheConfig( -// cacheSize = 4096, -// bytePerLine =32, -// wayCount = 1, -// wrappedMemAccess = true, -// addressWidth = 32, -// cpuDataWidth = 32, -// memDataWidth = 32, -// catchIllegalAccess = true, -// catchAccessFault = true, -// catchMemoryTranslationMiss = true, -// asyncTagMemory = false, -// twoStageLogic = true -// ), -// askMemoryTranslation = true, -// memoryTranslatorPortConfig = MemoryTranslatorPortConfig( -// portTlbSize = 4 -// ) +// new IBusSimplePlugin( +// interfaceKeepData = false, +// catchAccessFault = true // ), - new DBusSimplePlugin( - catchAddressMisaligned = true, - catchAccessFault = true, - earlyInjection = false + new IBusCachedPlugin( + config = InstructionCacheConfig( + cacheSize = 4096, + bytePerLine =32, + wayCount = 1, + wrappedMemAccess = true, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchIllegalAccess = true, + catchAccessFault = true, + catchMemoryTranslationMiss = true, + asyncTagMemory = false, + twoStageLogic = true + ), + askMemoryTranslation = true, + memoryTranslatorPortConfig = MemoryTranslatorPortConfig( + portTlbSize = 4 + ) ), -// new DBusCachedPlugin( -// config = new DataCacheConfig( -// cacheSize = 4096, -// bytePerLine = 32, -// wayCount = 1, -// addressWidth = 32, -// cpuDataWidth = 32, -// memDataWidth = 32, -// catchAccessError = true, -// catchIllegal = true, -// catchUnaligned = true, -// catchMemoryTranslationMiss = true -// ), -//// memoryTranslatorPortConfig = null -// memoryTranslatorPortConfig = MemoryTranslatorPortConfig( -// portTlbSize = 6 -// ) +// new DBusSimplePlugin( +// catchAddressMisaligned = true, +// catchAccessFault = true, +// earlyInjection = false // ), + new DBusCachedPlugin( + config = new DataCacheConfig( + cacheSize = 4096, + bytePerLine = 32, + wayCount = 1, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchAccessError = true, + catchIllegal = true, + catchUnaligned = true, + catchMemoryTranslationMiss = true + ), +// memoryTranslatorPortConfig = null + memoryTranslatorPortConfig = MemoryTranslatorPortConfig( + portTlbSize = 6 + ) + ), // new StaticMemoryTranslatorPlugin( // ioRange = _(31 downto 28) === 0xF // ), -// new MemoryTranslatorPlugin( -// tlbSize = 32, -// virtualRange = _(31 downto 28) === 0xC, -// ioRange = _(31 downto 28) === 0xF -// ), + new MemoryTranslatorPlugin( + tlbSize = 32, + virtualRange = _(31 downto 28) === 0xC, + ioRange = _(31 downto 28) === 0xF + ), new DecoderSimplePlugin( catchIllegalInstruction = true ), diff --git a/src/main/scala/vexriscv/demo/Briey.scala b/src/main/scala/vexriscv/demo/Briey.scala index 818daad..c64650a 100644 --- a/src/main/scala/vexriscv/demo/Briey.scala +++ b/src/main/scala/vexriscv/demo/Briey.scala @@ -50,7 +50,7 @@ object BrieyConfig{ new PcManagerSimplePlugin(0x00000000l, false), // new IBusSimplePlugin( // interfaceKeepData = false, - // catchAccessFault = false + // catchAccessFault = true // ), new IBusCachedPlugin( config = InstructionCacheConfig( @@ -196,29 +196,24 @@ class Briey(config: BrieyConfig) extends Component{ ) val resetCtrl = new ClockingArea(resetCtrlClockDomain) { - val axiResetUnbuffered = False - val coreResetUnbuffered = False + val systemResetUnbuffered = False +// val coreResetUnbuffered = False //Implement an counter to keep the reset axiResetOrder high 64 cycles // Also this counter will automaticly do a reset when the system boot. - val axiResetCounter = Reg(UInt(6 bits)) init(0) - when(axiResetCounter =/= U(axiResetCounter.range -> true)){ - axiResetCounter := axiResetCounter + 1 - axiResetUnbuffered := True + val systemResetCounter = Reg(UInt(6 bits)) init(0) + when(systemResetCounter =/= U(systemResetCounter.range -> true)){ + systemResetCounter := systemResetCounter + 1 + systemResetUnbuffered := True } when(BufferCC(io.asyncReset)){ - axiResetCounter := 0 - } - - //When an axiResetOrder happen, the core reset will as well - when(axiResetUnbuffered){ - coreResetUnbuffered := True + systemResetCounter := 0 } //Create all reset used later in the design - val axiReset = RegNext(axiResetUnbuffered) - val coreReset = RegNext(coreResetUnbuffered) - val vgaReset = BufferCC(axiResetUnbuffered) + val systemReset = RegNext(systemResetUnbuffered) + val axiReset = RegNext(systemResetUnbuffered) + val vgaReset = BufferCC(axiReset) } val axiClockDomain = ClockDomain( @@ -227,9 +222,10 @@ class Briey(config: BrieyConfig) extends Component{ frequency = FixedFrequency(axiFrequency) //The frequency information is used by the SDRAM controller ) - val coreClockDomain = ClockDomain( + val debugClockDomain = ClockDomain( clock = io.axiClk, - reset = resetCtrl.coreReset + reset = resetCtrl.systemReset, + frequency = FixedFrequency(axiFrequency) ) val vgaClockDomain = ClockDomain( @@ -284,16 +280,15 @@ class Briey(config: BrieyConfig) extends Component{ - val core = new ClockingArea(coreClockDomain){ - val configLight = VexRiscvConfig( - plugins = cpuPlugins += new DebugPlugin(axiClockDomain) + val core = new Area{ + val config = VexRiscvConfig( + plugins = cpuPlugins += new DebugPlugin(debugClockDomain) ) - val cpu = new VexRiscv(configLight) + val cpu = new VexRiscv(config) var iBus : Axi4ReadOnly = null var dBus : Axi4Shared = null - var debugBus : DebugExtensionBus = null - for(plugin <- configLight.plugins) plugin match{ + for(plugin <- config.plugins) plugin match{ case plugin : IBusSimplePlugin => iBus = plugin.iBus.toAxi4ReadOnly() case plugin : IBusCachedPlugin => iBus = plugin.iBus.toAxi4ReadOnly() case plugin : DBusSimplePlugin => dBus = plugin.dBus.toAxi4Shared() @@ -302,9 +297,9 @@ class Briey(config: BrieyConfig) extends Component{ plugin.externalInterrupt := BufferCC(io.coreInterrupt) plugin.timerInterrupt := timerCtrl.io.interrupt } - case plugin : DebugPlugin => { - resetCtrl.coreResetUnbuffered setWhen(plugin.io.resetOut) - debugBus = plugin.io.bus + case plugin : DebugPlugin => debugClockDomain{ + resetCtrl.axiReset setWhen(RegNext(plugin.io.resetOut)) + io.jtag <> plugin.io.bus.fromJtag() } case _ => } @@ -356,7 +351,7 @@ class Briey(config: BrieyConfig) extends Component{ cpu.sharedCmd >> crossbar.sharedCmd cpu.writeData >> crossbar.writeData cpu.writeRsp << crossbar.writeRsp - cpu.readRsp <-< crossbar.readRsp + cpu.readRsp <-< crossbar.readRsp //Data cache directly use read responses without buffering, so pipeline it for FMax }) axiCrossbar.build() @@ -372,8 +367,6 @@ class Briey(config: BrieyConfig) extends Component{ vgaCtrl.io.apb -> (0x30000, 4 kB) ) ) - - io.jtag <> core.debugBus.fromJtag() } io.gpioA <> axi.gpioACtrl.io.gpio diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index f927047..288b1f5 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -536,11 +536,15 @@ class DataCache(p : DataCacheConfig) extends Component{ default -> B"1111" ) |<< mmuRsp.physicalAddress(1 downto 0) + val hadMemRspErrorReg = RegInit(False) + val hadMemRspError = (io.mem.rsp.valid && io.mem.rsp.error) || hadMemRspErrorReg + hadMemRspErrorReg := hadMemRspError && io.cpu.writeBack.haltIt + io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid io.cpu.writeBack.mmuMiss := False io.cpu.writeBack.illegalAccess := False io.cpu.writeBack.unalignedAccess := False - io.cpu.writeBack.accessError := (if(catchAccessError) io.mem.rsp.valid && io.mem.rsp.error else False) + io.cpu.writeBack.accessError := (if(catchAccessError) hadMemRspError && !io.cpu.writeBack.haltIt else False) io.cpu.writeBack.badAddr := request.address //Evict the cache after reset logics diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index ee2a5b7..4c3c310 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -140,7 +140,7 @@ case class CsrMapping(){ -class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor{ +class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor{ import config._ import CsrAccess._ @@ -172,7 +172,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio object IS_CSR extends Stageable(Bool) var allowInterrupts : Bool = null - + var allowException : Bool = null override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ @@ -230,9 +230,11 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio selfException = newExceptionPort(pipeline.execute) allowInterrupts = True + allowException = True } def inhibateInterrupts() : Unit = allowInterrupts := False + def inhibateException() : Unit = allowException := False def isUser(stage : Stage) : Bool = privilege === 0 @@ -385,7 +387,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio val interrupt = ((mip.MSIP && mie.MSIE) || (mip.MEIP && mie.MEIE) || (mip.MTIP && mie.MTIE)) && mstatus.MIE && allowInterrupts - val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last else False + val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last && allowException else False val writeBackWfi = if(wfiGen) writeBack.arbitration.isValid && writeBack.input(ENV_CTRL) === EnvCtrlEnum.WFI else False //Interrupt/Exception entry logic diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 4534d68..56fd577 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -201,6 +201,11 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] { service(classOf[InterruptionInhibitor]).inhibateInterrupts() } } + if(serviceExist(classOf[ExceptionInhibitor])) { + when(haltIt) { + service(classOf[ExceptionInhibitor]).inhibateException() + } + } }} } }