mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
Fix Instruction Data cache exceptions
Pass all tests including CSR/FreeRTOS
This commit is contained in:
parent
ca1bc9cf69
commit
4d6a6fbb02
7 changed files with 81 additions and 53 deletions
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue