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:
Charles Papon 2017-08-10 20:56:54 +02:00
parent 37f2674d5b
commit aa477b2b1c
6 changed files with 90 additions and 83 deletions

View File

@ -34,6 +34,9 @@ trait InterruptionInhibitor{
def inhibateInterrupts() : Unit
}
trait ExceptionInhibitor{
def inhibateException() : Unit
}
case class MemoryTranslatorCmd() extends Bundle{
val isValid = Bool

View File

@ -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
),

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()
}
}
}}
}
}