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
This commit is contained in:
parent
37f2674d5b
commit
aa477b2b1c
|
@ -34,6 +34,9 @@ trait InterruptionInhibitor{
|
|||
def inhibateInterrupts() : Unit
|
||||
}
|
||||
|
||||
trait ExceptionInhibitor{
|
||||
def inhibateException() : Unit
|
||||
}
|
||||
|
||||
case class MemoryTranslatorCmd() extends Bundle{
|
||||
val isValid = Bool
|
||||
|
|
|
@ -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
|
||||
),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue