Fix Instruction Data cache exceptions

Pass all tests including CSR/FreeRTOS
This commit is contained in:
Charles Papon 2017-05-07 12:51:47 +02:00
parent ca1bc9cf69
commit 4d6a6fbb02
7 changed files with 81 additions and 53 deletions

View file

@ -96,11 +96,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
U(1) -> input(REG2)(15 downto 0) ## input(REG2)(15 downto 0),
default -> input(REG2)(31 downto 0)
)
cache.io.cpu.execute.args.mask := (size.mux (
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) << cache.io.cpu.execute.args.address(1 downto 0)).resized
cache.io.cpu.execute.args.size := size
cache.io.cpu.execute.args.forceUncachedAccess := False // cache.io.cpu.execute.args.address(31 downto 28) === 0xF
cache.io.cpu.execute.args.kind := DataCacheCpuCmdKind.MEMORY
cache.io.cpu.execute.args.clean := False
@ -130,12 +126,15 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
if(catchSomething) {
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess
exceptionBus.badAddr := cache.io.cpu.writeBack.badAddr
exceptionBus.code := 13
when(cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.accessError){
when(cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError){
exceptionBus.code := (input(INSTRUCTION)(5) ? U(7) | U(5)).resized
}
when(cache.io.cpu.writeBack.unalignedAccess){
exceptionBus.code := (input(INSTRUCTION)(5) ? U(6) | U(4)).resized
}
}
arbitration.haltIt.setWhen(cache.io.cpu.writeBack.haltIt)
@ -259,7 +258,7 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
val wr = Bool
val address = UInt(p.addressWidth bit)
val data = Bits(p.cpuDataWidth bit)
val mask = Bits(p.cpuDataWidth/8 bit)
val size = UInt(2 bits)
val forceUncachedAccess = Bool
val clean, invalidate, way = Bool
// val all = Bool //Address should be zero when "all" is used
@ -571,6 +570,12 @@ class DataCache(p : DataCacheConfig) extends Component{
val victimNotSent = RegInit(False) clearWhen(victim.requestIn.ready) setWhen(!io.cpu.memory.isStuck)
val loadingNotDone = RegInit(False) clearWhen(loaderReady) setWhen(!io.cpu.memory.isStuck)
val writeMask = request.size.mux (
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) |<< mmuRsp.physicalAddress(1 downto 0)
io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid
io.cpu.writeBack.mmuMiss := False
io.cpu.writeBack.illegalAccess := False
@ -618,7 +623,7 @@ class DataCache(p : DataCacheConfig) extends Component{
}
is(MEMORY) {
val illegal = if(catchIllegal) (request.wr && !mmuRsp.allowWrite) || (!request.wr && !mmuRsp.allowRead) else False
val unaligned = if(catchUnaligned) ((request.mask === 0xF && mmuRsp.physicalAddress(1 downto 0) =/= 0) || ((request.mask === 0x3 || request.mask === 0xC) && mmuRsp.physicalAddress(0) =/= False)) else False
val unaligned = if(catchUnaligned) ((request.size === 2 && mmuRsp.physicalAddress(1 downto 0) =/= 0) || (request.size === 1 && mmuRsp.physicalAddress(0 downto 0) =/= 0)) else False
io.cpu.writeBack.illegalAccess := illegal
io.cpu.writeBack.unalignedAccess := unaligned
when((Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) && !illegal && !unaligned) {
@ -628,7 +633,7 @@ class DataCache(p : DataCacheConfig) extends Component{
//Avoid mixing memory request while victim is pending
io.mem.cmd.wr := request.wr
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
io.mem.cmd.mask := request.mask
io.mem.cmd.mask := writeMask
io.mem.cmd.data := request.data
io.mem.cmd.length := 1
@ -646,7 +651,7 @@ class DataCache(p : DataCacheConfig) extends Component{
dataWriteCmd.valid := request.wr
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
dataWriteCmd.data := request.data
dataWriteCmd.mask := request.mask
dataWriteCmd.mask := writeMask
tagsWriteCmd.valid := (!loadingNotDone) || request.wr
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
@ -667,7 +672,7 @@ class DataCache(p : DataCacheConfig) extends Component{
assert(!(io.cpu.writeBack.isValid && !io.cpu.writeBack.haltIt && io.cpu.writeBack.isStuck), "writeBack stuck by another plugin is not allowed")
io.cpu.writeBack.data := request.forceUncachedAccess ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
io.cpu.writeBack.data := (request.forceUncachedAccess || mmuRsp.isIoAccess) ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
}
//The whole life of a loading task, the corresponding manager request is present

View file

@ -131,7 +131,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean) extends Plugin[VexR
if(catchIllegalInstruction){
decodeExceptionPort.valid := arbitration.isValid && arbitration.haltIt && input(INSTRUCTION_READY) && !input(LEGAL_INSTRUCTION) //HalitIt to alow decoder stage to wait valid data from 2 stages cache cache
decodeExceptionPort.valid := arbitration.isValid && input(INSTRUCTION_READY) && !input(LEGAL_INSTRUCTION) // ?? HalitIt to alow decoder stage to wait valid data from 2 stages cache cache ??
decodeExceptionPort.code := 2
decodeExceptionPort.badAddr.assignDontCare()
}

View file

@ -12,12 +12,13 @@ case class InstructionCacheConfig( cacheSize : Int,
addressWidth : Int,
cpuDataWidth : Int,
memDataWidth : Int,
catchIllegalAccess : Boolean,
catchAccessFault : Boolean,
catchMemoryTranslationMiss : Boolean,
asyncTagMemory : Boolean,
twoStageLogic : Boolean){
def burstSize = bytePerLine*8/memDataWidth
def catchSomething = catchAccessFault || catchMemoryTranslationMiss
def catchSomething = catchAccessFault || catchMemoryTranslationMiss || catchIllegalAccess
}
@ -102,8 +103,9 @@ class IBusCachedPlugin(config : InstructionCacheConfig, askMemoryTranslation : B
val accessFault = if(catchAccessFault) decode.input(IBUS_ACCESS_ERROR) else False
val mmuMiss = if(catchMemoryTranslationMiss) cache.io.cpu.decode.mmuMiss else False
val illegalAccess = if(catchIllegalAccess) cache.io.cpu.decode.illegalAccess else False
decodeExceptionPort.valid := decode.arbitration.isValid && (accessFault || mmuMiss)
decodeExceptionPort.valid := decode.arbitration.isValid && (accessFault || mmuMiss || illegalAccess)
decodeExceptionPort.code := mmuMiss ? U(14) | 1
decodeExceptionPort.badAddr := decode.input(PC)
}
@ -152,11 +154,12 @@ case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle
val dataAnticipated = Bits(32 bits)
val error = if(p.catchAccessFault) Bool else null
val mmuMiss = if(p.catchMemoryTranslationMiss) Bool else null
val illegalAccess = if(p.catchIllegalAccess) Bool else null
override def asMaster(): Unit = {
out(isValid, isStuck, address)
in(haltIt, data, dataAnticipated)
inWithNull(error,mmuMiss)
inWithNull(error,mmuMiss,illegalAccess)
}
}
@ -177,7 +180,7 @@ case class InstructionCacheMemCmd(p : InstructionCacheConfig) extends Bundle{
}
case class InstructionCacheMemRsp(p : InstructionCacheConfig) extends Bundle{
val data = Bits(32 bit)
val error = if(p.catchAccessFault) Bool else null
val error = Bool
}
case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle with IMasterSlave{
@ -281,8 +284,11 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.flush.rsp := flushCounter.msb.rise && flushFromInterface
val loadingWithErrorReg = if(catchAccessFault) RegInit(False) else null
val loadingWithError = if(catchAccessFault) loadingWithErrorReg else null
if(catchAccessFault) loadingWithErrorReg := loadingWithError
val loadingWithError = if(catchAccessFault) Bool else null
if(catchAccessFault) {
loadingWithError := loadingWithErrorReg
loadingWithErrorReg := loadingWithError
}
@ -470,6 +476,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.decode.dataAnticipated := io.cpu.decode.isStuck ? Mux(dataPostWrite,lineLoader.waysDatasWritePort.data,data) | Mux(dataPreWrite,lineLoader.waysDatasWritePort.data,memRead.data)
if(catchAccessFault) io.cpu.decode.error := tag.error
if(catchMemoryTranslationMiss) io.cpu.decode.mmuMiss := mmuRsp.miss
if(catchIllegalAccess) io.cpu.decode.illegalAccess := !mmuRsp.miss && !mmuRsp.allowExecute
lineLoader.requestIn.valid := io.cpu.decode.isValid && !hit && !mmuRsp.miss//TODO avoid duplicated request
lineLoader.requestIn.addr := mmuRsp.physicalAddress

View file

@ -304,13 +304,13 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
)
mcause.interrupt := interrupt
mcause.exceptionCode := interrupt.mux(
True -> ((mip.MEIP && mie.MEIE) ? U(11) | ((mip.MSIP && mie.MSIE) ? U(3) | U(7))),
False -> (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.code else U(0))
)
when(RegNext(exception)){
mbadaddr := (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.badAddr else U(0))
}
mcause.exceptionCode := ((mip.MEIP && mie.MEIE) ? U(11) | ((mip.MSIP && mie.MSIE) ? U(3) | U(7)))
}
when(RegNext(exception)){
mbadaddr := (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.badAddr else U(0))
mcause.exceptionCode := (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.code else U(0))
}

View file

@ -99,24 +99,30 @@ object TopLevel {
val configFull = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(0x00000000l, false),
new IBusSimplePlugin(
interfaceKeepData = true,
catchAccessFault = true
// new IBusSimplePlugin(
// interfaceKeepData = true,
// 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 IBusCachedPlugin(
// config = InstructionCacheConfig(
// cacheSize = 4096,
// bytePerLine =32,
// wayCount = 1,
// wrappedMemAccess = true,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchAccessFault = true,
// asyncTagMemory = false,
// twoStageLogic = true
// )
// ),
// new DBusSimplePlugin(
// catchAddressMisaligned = true,
// catchAccessFault = true
@ -132,9 +138,18 @@ object TopLevel {
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = false
catchMemoryTranslationMiss = true
),
askMemoryTranslation = true,
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 6
)
),
new MemoryTranslatorPlugin(
tlbSize = 32,
virtualRange = _(31 downto 28) === 0xC,
ioRange = _(31 downto 28) === 0xF
),
new DecoderSimplePlugin(
catchIllegalInstruction = true
),
@ -237,7 +252,8 @@ object TopLevel {
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchAccessFault = false,
catchIllegalAccess = true,
catchAccessFault = true,
catchMemoryTranslationMiss = true,
asyncTagMemory = false,
twoStageLogic = true
@ -324,9 +340,9 @@ object TopLevel {
)
)
// val toplevel = new VexRiscv(configFull)
val toplevel = new VexRiscv(configFull)
// val toplevel = new VexRiscv(configLight)
val toplevel = new VexRiscv(configTest)
// val toplevel = new VexRiscv(configTest)
toplevel.decode.input(toplevel.config.INSTRUCTION).addAttribute(Verilator.public)
toplevel.decode.input(toplevel.config.PC).addAttribute(Verilator.public)
toplevel.decode.arbitration.isValid.addAttribute(Verilator.public)

View file

@ -332,6 +332,7 @@ public:
// dump variables into VCD file and toggle clock
dump(i);
//top->eval();
top->clk = 0;
top->eval();
@ -360,6 +361,7 @@ public:
}
checks();
//top->eval();
top->clk = 1;
top->eval();
@ -469,9 +471,7 @@ public:
top->iBus_rsp_valid = 0;
if(pendingCount != 0 && (!ws->iStall || VL_RANDOM_I(7) < 100)){
ws->iBusAccess(address,&top->iBus_rsp_payload_data,&error);
#ifdef CSR
top->iBus_rsp_payload_error = error;
#endif
pendingCount--;
address = (address & ~0x1F) + ((address + 4) & 0x1F);
top->iBus_rsp_valid = 1;
@ -833,8 +833,8 @@ int main(int argc, char **argv, char **env) {
#ifdef CSR
uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u ,
8,6,9,6,10,4,11,4, 12,13,0, 14,2, 15,5,16,5,17,1 };
redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).run(4e3);)
8,6,9,6,10,4,11,4, 12,13,0, 14,2, 15,5,16,17,1 };
redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).noInstructionReadCheck()->run(4e3);)
#endif
#ifdef MMU
uint32_t mmuRef[] = {1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5,

View file

@ -2,10 +2,10 @@ IBUS=IBUS_CACHED
DBUS=DBUS_CACHED
TRACE=no
TRACE_START=0
CSR=no
CSR=yes
MMU=yes
DHRYSTONE=yes
FREE_RTOS=no
FREE_RTOS=yes
REDO=10
REF=no
TRACE_WITH_TIME=no