Instruction cache is now able to catch bus errors

This commit is contained in:
Charles Papon 2017-03-30 17:34:24 +02:00
parent 95585b4d9a
commit 19fe998a52
4 changed files with 125 additions and 88 deletions

View File

@ -11,7 +11,8 @@ case class InstructionCacheConfig( cacheSize : Int,
wrappedMemAccess : Boolean, wrappedMemAccess : Boolean,
addressWidth : Int, addressWidth : Int,
cpuDataWidth : Int, cpuDataWidth : Int,
memDataWidth : Int){ memDataWidth : Int,
catchAccessFault : Boolean){
def burstSize = bytePerLine*8/memDataWidth def burstSize = bytePerLine*8/memDataWidth
} }
@ -36,9 +37,6 @@ class IBusCachedPlugin(catchAccessFault : Boolean, cacheConfig : InstructionCach
import pipeline._ import pipeline._
import pipeline.config._ import pipeline.config._
assert(catchAccessFault == false) //unimplemented
val cache = new InstructionCache(cacheConfig) val cache = new InstructionCache(cacheConfig)
iBus = master(new InstructionCacheMemBus(cacheConfig)).setName("iBus") iBus = master(new InstructionCacheMemBus(cacheConfig)).setName("iBus")
iBus <> cache.io.mem iBus <> cache.io.mem
@ -59,13 +57,14 @@ class IBusCachedPlugin(catchAccessFault : Boolean, cacheConfig : InstructionCach
cache.io.flush.cmd.valid := False cache.io.flush.cmd.valid := False
// fetch.insert(IBUS_ACCESS_ERROR) := iRsp.error
// if(catchAccessFault){ if(catchAccessFault){
// decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR) fetch.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.rsp.error
// decodeExceptionPort.code := 1
// decodeExceptionPort.badAddr := decode.input(PC) decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR)
// } decodeExceptionPort.code := 1
decodeExceptionPort.badAddr := decode.input(PC)
}
} }
} }
@ -89,10 +88,12 @@ case class InstructionCacheCpuRsp(p : InstructionCacheConfig) extends Bundle wit
val isStuck = Bool val isStuck = Bool
val address = UInt(p.addressWidth bit) val address = UInt(p.addressWidth bit)
val data = Bits(32 bit) val data = Bits(32 bit)
val error = if(p.catchAccessFault) Bool else null
override def asMaster(): Unit = { override def asMaster(): Unit = {
out(isValid, isStuck, address) out(isValid, isStuck, address)
in(haltIt, data) in(haltIt, data)
if(p.catchAccessFault) in(error)
} }
} }
@ -107,12 +108,24 @@ case class InstructionCacheCpuBus(p : InstructionCacheConfig) extends Bundle wit
} }
} }
case class InstructionCacheTranslationBus(p : InstructionCacheConfig) extends Bundle with IMasterSlave{
val virtualAddress = UInt(32 bits)
val physicalAddress = UInt(32 bits)
val error = if(p.catchAccessFault) Bool else null
override def asMaster(): Unit = {
out(virtualAddress)
in(physicalAddress)
if(p.catchAccessFault) in(error)
}
}
case class InstructionCacheMemCmd(p : InstructionCacheConfig) extends Bundle{ case class InstructionCacheMemCmd(p : InstructionCacheConfig) extends Bundle{
val address = UInt(p.addressWidth bit) val address = UInt(p.addressWidth bit)
} }
case class InstructionCacheMemRsp(p : InstructionCacheConfig) extends Bundle{ case class InstructionCacheMemRsp(p : InstructionCacheConfig) extends Bundle{
val data = Bits(32 bit) val data = Bits(32 bit)
val error = if(p.catchAccessFault) Bool else null
} }
case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle with IMasterSlave{ case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle with IMasterSlave{
@ -141,6 +154,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
assert(cpuDataWidth == memDataWidth) assert(cpuDataWidth == memDataWidth)
val io = new Bundle{ val io = new Bundle{
val flush = slave(InstructionCacheFlushBus()) val flush = slave(InstructionCacheFlushBus())
// val translator = master(InstructionCacheTranslationBus(p))
val cpu = slave(InstructionCacheCpuBus(p)) val cpu = slave(InstructionCacheCpuBus(p))
val mem = master(InstructionCacheMemBus(p)) val mem = master(InstructionCacheMemBus(p))
} }
@ -158,16 +172,22 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
val tagRange = addressWidth-1 downto log2Up(wayLineCount*bytePerLine) val tagRange = addressWidth-1 downto log2Up(wayLineCount*bytePerLine)
val lineRange = tagRange.low-1 downto log2Up(bytePerLine) val lineRange = tagRange.low-1 downto log2Up(bytePerLine)
val wordRange = log2Up(bytePerLine)-1 downto log2Up(bytePerWord) val wordRange = log2Up(bytePerLine)-1 downto log2Up(bytePerWord)
val tagLineRange = tagRange.high downto lineRange.low
class LineInfo extends Bundle{
class LineInfo() extends Bundle{
val valid = Bool val valid = Bool
val error = if(catchAccessFault) Bool else null
val address = UInt(tagRange.length bit) val address = UInt(tagRange.length bit)
} }
// class LineWord extends Bundle{
// val data = Bits(wordWidth bits)
// val error = Bool
// }
val ways = Array.fill(wayCount)(new Area{ val ways = Array.fill(wayCount)(new Area{
val tags = Mem(new LineInfo(),wayLineCount) val tags = Mem(new LineInfo(),wayLineCount)
val datas = Mem(Bits(wordWidth bit),wayWordCount) val datas = Mem(Bits(wordWidth bits),wayWordCount)
}) })
@ -175,7 +195,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
val lineLoader = new Area{ val lineLoader = new Area{
val requestIn = Stream(wrap(new Bundle{ val requestIn = Stream(wrap(new Bundle{
val addr = UInt(addressWidth bit) val addr = UInt(addressWidth bits)
})) }))
@ -204,46 +224,61 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.flush.rsp := flushCounter.msb.rise && flushFromInterface io.flush.rsp := flushCounter.msb.rise && flushFromInterface
val lineInfoWrite = new LineInfo() val loadingWithErrorReg = if(catchAccessFault) RegInit(False) else null
lineInfoWrite.valid := flushCounter.msb val loadingWithError = if(catchAccessFault) loadingWithErrorReg else null
lineInfoWrite.address := requestIn.addr(tagRange) if(catchAccessFault) loadingWithErrorReg := loadingWithError
when(requestIn.fire || !flushCounter.msb){
val tagsAddress = Mux(flushCounter.msb,requestIn.addr(lineRange),flushCounter(flushCounter.high-1 downto 0))
ways(0).tags(tagsAddress) := lineInfoWrite //TODO
}
val request = requestIn.haltWhen(!io.mem.cmd.ready).stage() val request = requestIn.haltWhen(!io.mem.cmd.ready).stage()
val lineInfoWrite = new LineInfo()
lineInfoWrite.valid := flushCounter.msb
lineInfoWrite.address := request.addr(tagRange)
if(catchAccessFault) lineInfoWrite.error := loadingWithError
io.mem.cmd.valid := requestIn.valid && !request.isStall io.mem.cmd.valid := requestIn.valid && !request.isStall
val wordIndex = Reg(UInt(log2Up(wordPerLine) bit)) val wordIndex = Reg(UInt(log2Up(wordPerLine) bit))
val loadedWordsNext = Bits(wordPerLine bit) val loadedWordsNext = Bits(wordPerLine bit)
val loadedWords = RegNext(loadedWordsNext) val loadedWords = RegNext(loadedWordsNext)
val loadedWordsReadable = RegNext(loadedWords) val loadedWordsReadable = RegNext(loadedWords)
loadedWordsNext := loadedWords loadedWordsNext := loadedWords
when(io.mem.rsp.fire){ when(io.mem.rsp.valid){
wordIndex := wordIndex + 1 wordIndex := wordIndex + 1
loadedWordsNext(wordIndex) := True loadedWordsNext(wordIndex) := True
ways(0).datas(request.addr(lineRange) @@ wordIndex) := io.mem.rsp.data //TODO ways(0).datas(request.addr(lineRange) @@ wordIndex) := io.mem.rsp.data //TODO
if(catchAccessFault) loadingWithError setWhen io.mem.rsp.error
} }
val memRspLast = loadedWordsNext === B(loadedWordsNext.range -> true)
val readyDelay = Reg(UInt(1 bit)) val readyDelay = Reg(UInt(1 bit))
when(loadedWordsNext === B(loadedWordsNext.range -> true)){ when(memRspLast){
readyDelay := readyDelay + 1 readyDelay := readyDelay + 1
} }
request.ready := readyDelay === 1 request.ready := readyDelay === 1
when((request.valid && memRspLast) || !flushCounter.msb){
val tagsAddress = Mux(flushCounter.msb,request.addr(lineRange),flushCounter(flushCounter.high-1 downto 0))
ways(0).tags(tagsAddress) := lineInfoWrite //TODO
}
when(requestIn.ready){ when(requestIn.ready){
wordIndex := io.mem.cmd.address(wordRange) wordIndex := io.mem.cmd.address(wordRange)
loadedWords := 0 loadedWords := 0
loadedWordsReadable := 0 loadedWordsReadable := 0
readyDelay := 0 readyDelay := 0
if(catchAccessFault) loadingWithErrorReg := False
} }
} }
val task = new Area{ val task = new Area{
val waysHitValid = False val waysHitValid = False
val waysHitError = Bool.assignDontCare()
val waysHitWord = Bits(wordWidth bit) val waysHitWord = Bits(wordWidth bit)
waysHitWord.assignDontCare() // waysHitWord.assignDontCare()
val waysRead = for(way <- ways) yield new Area{ val waysRead = for(way <- ways) yield new Area{
val readAddress = Mux(io.cpu.rsp.isStuck,io.cpu.rsp.address,io.cpu.cmd.address) val readAddress = Mux(io.cpu.rsp.isStuck,io.cpu.rsp.address,io.cpu.cmd.address)
@ -254,18 +289,25 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
// val data = way.datas.readAsync(readAddress(lineRange.high downto wordRange.low)) // val data = way.datas.readAsync(readAddress(lineRange.high downto wordRange.low))
// way.tags.add(new AttributeString("ramstyle","no_rw_check")) // way.tags.add(new AttributeString("ramstyle","no_rw_check"))
// way.datas.add(new AttributeString("ramstyle","no_rw_check")) // way.datas.add(new AttributeString("ramstyle","no_rw_check"))
waysHitWord := data //Not applicable to multi way
when(tag.valid && tag.address === io.cpu.rsp.address(tagRange)) { when(tag.valid && tag.address === io.cpu.rsp.address(tagRange)) {
waysHitValid := True waysHitValid := True
waysHitWord := data if(catchAccessFault) waysHitError := tag.error
}
when(lineLoader.request.valid && lineLoader.request.addr(lineRange) === io.cpu.rsp.address(lineRange)){
waysHitValid := False //Not applicable to multi way
} }
} }
val loaderHitValid = lineLoader.request.valid && lineLoader.request.addr(tagRange) === io.cpu.rsp.address(tagRange)
val loaderHitValid = lineLoader.request.valid && lineLoader.request.addr(tagLineRange) === io.cpu.rsp.address(tagLineRange)
val loaderHitReady = lineLoader.loadedWordsReadable(io.cpu.rsp.address(wordRange)) val loaderHitReady = lineLoader.loadedWordsReadable(io.cpu.rsp.address(wordRange))
io.cpu.rsp.haltIt := io.cpu.rsp.isValid && !( waysHitValid && !(loaderHitValid && !loaderHitReady)) io.cpu.rsp.haltIt := io.cpu.rsp.isValid && !(waysHitValid || (loaderHitValid && loaderHitReady))
io.cpu.rsp.data := waysHitWord //TODO io.cpu.rsp.data := waysHitWord //TODO
if(catchAccessFault) io.cpu.rsp.error := (waysHitValid && waysHitError) || (loaderHitValid && loaderHitReady && lineLoader.loadingWithErrorReg)
lineLoader.requestIn.valid := io.cpu.rsp.isValid && ! waysHitValid lineLoader.requestIn.valid := io.cpu.rsp.isValid && ! waysHitValid
lineLoader.requestIn.addr := io.cpu.rsp.address lineLoader.requestIn.addr := io.cpu.rsp.address
} }
@ -274,30 +316,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
} }
object InstructionCacheMain{ object InstructionCacheMain{
class TopLevel extends Component{
implicit val p = InstructionCacheConfig(
cacheSize =4096,
bytePerLine =32,
wayCount = 1,
wrappedMemAccess = true,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32)
// val io = new Bundle{
// val cpu = slave(InstructionCacheCpuBus())
// val mem = master(InstructionCacheMemBus())
// }
val cache = new InstructionCache(p)
// cache.io.cpu.cmd <-< io.cpu.cmd
// cache.io.mem.cmd >-> io.mem.cmd
// cache.io.mem.rsp <-< io.mem.rsp
// cache.io.cpu.rsp >-> io.cpu.rsp
// when(cache.io.cpu.rsp.valid){
// cache.io.cpu.cmd.valid := RegNext(cache.io.cpu.cmd.valid)
// cache.io.cpu.cmd.address := RegNext(cache.io.cpu.cmd.address)
// }
}
def main(args: Array[String]) { def main(args: Array[String]) {
implicit val p = InstructionCacheConfig( implicit val p = InstructionCacheConfig(
cacheSize =4096, cacheSize =4096,
@ -306,7 +325,8 @@ object InstructionCacheMain{
wrappedMemAccess = true, wrappedMemAccess = true,
addressWidth = 32, addressWidth = 32,
cpuDataWidth = 32, cpuDataWidth = 32,
memDataWidth = 32) memDataWidth = 32,
catchAccessFault = true)
// val io = new Bundle{ // val io = new Bundle{
// val cpu = slave(InstructionCacheCpuBus()) // val cpu = slave(InstructionCacheCpuBus())
// val mem = master(InstructionCacheMemBus()) // val mem = master(InstructionCacheMemBus())

View File

@ -84,7 +84,7 @@ object TopLevel {
// catchAccessFault = true // catchAccessFault = true
// ), // ),
new IBusCachedPlugin( new IBusCachedPlugin(
catchAccessFault = false, catchAccessFault = true,//DUPLICATION
cacheConfig = InstructionCacheConfig( cacheConfig = InstructionCacheConfig(
cacheSize =4096, cacheSize =4096,
bytePerLine =32, bytePerLine =32,
@ -92,7 +92,8 @@ object TopLevel {
wrappedMemAccess = true, wrappedMemAccess = true,
addressWidth = 32, addressWidth = 32,
cpuDataWidth = 32, cpuDataWidth = 32,
memDataWidth = 32 memDataWidth = 32,
catchAccessFault = true //DUPLICATION
) )
), ),
new DecoderSimplePlugin( new DecoderSimplePlugin(
@ -156,7 +157,9 @@ object TopLevel {
// ) // )
val toplevel = new VexRiscv(config) val toplevel = new VexRiscv(config)
toplevel.decode.input(config.INSTRUCTION).addAttribute("verilator public")
toplevel.decode.input(config.PC).addAttribute("verilator public")
toplevel.decode.arbitration.isValid.addAttribute("verilator public")
// toplevel.service(classOf[DecoderSimplePlugin]).bench(toplevel) // toplevel.service(classOf[DecoderSimplePlugin]).bench(toplevel)
toplevel toplevel

View File

@ -1,45 +1,50 @@
[*] [*]
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
[*] Sat Mar 25 22:06:00 2017 [*] Thu Mar 30 15:00:10 2017
[*] [*]
[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/dhrystoneO3.vcd" [dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/dhrystoneO3.vcd"
[dumpfile_mtime] "Sat Mar 25 22:05:31 2017" [dumpfile_mtime] "Thu Mar 30 14:59:57 2017"
[dumpfile_size] 414222144 [dumpfile_size] 1227579722
[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/fail.gtkw" [savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/fail.gtkw"
[timestart] 60961 [timestart] 555551
[size] 1000 600 [size] 1776 953
[pos] -1 -1 [pos] -1 -1
*-7.000000 61271 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 *-2.000000 555567 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] TOP. [treeopen] TOP.
[sst_width] 201 [treeopen] TOP.VexRiscv.
[signals_width] 571 [sst_width] 378
[signals_width] 418
[sst_expanded] 1 [sst_expanded] 1
[sst_vpaned_height] 155 [sst_vpaned_height] 279
@28 @28
TOP.VexRiscv.decode_EXCEPTION TOP.VexRiscv.clk
TOP.VexRiscv.execute_EXCEPTION TOP.VexRiscv.decode_arbitration_isValid
TOP.VexRiscv.memory_EXCEPTION
TOP.VexRiscv.writeBack_EXCEPTION
TOP.VexRiscv.execute_arbitration_isValid
TOP.VexRiscv.execute_MEMORY_ENABLE
@22 @22
TOP.VexRiscv.execute_PC[31:0] TOP.VexRiscv.decode_PC[31:0]
TOP.VexRiscv.RegFilePlugin_regFile(8)[31:0] TOP.VexRiscv.decode_INSTRUCTION[31:0]
@28 @28
TOP.VexRiscv.writeBack_arbitration_isValid TOP.VexRiscv.decode_LEGAL_INSTRUCTION
@23
TOP.VexRiscv.writeBack_PC[31:0]
@28
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_valid
@22 @22
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_address[4:0] TOP.VexRiscv.instructionCache_1.io_cpu_cmd_address[31:0]
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_data[31:0]
TOP.VexRiscv.dCmd_payload_address[31:0]
TOP.VexRiscv.dCmd_payload_data[31:0]
@28 @28
TOP.VexRiscv.dCmd_payload_size[1:0] TOP.VexRiscv.instructionCache_1.io_cpu_cmd_haltIt
TOP.VexRiscv.dCmd_payload_wr @22
TOP.VexRiscv.dCmd_ready TOP.VexRiscv.instructionCache_1.io_cpu_rsp_address[31:0]
TOP.VexRiscv.dCmd_valid TOP.VexRiscv.instructionCache_1.io_cpu_rsp_data[31:0]
@28
TOP.VexRiscv.instructionCache_1.io_cpu_rsp_haltIt
TOP.VexRiscv.instructionCache_1.io_cpu_rsp_isStuck
TOP.VexRiscv.instructionCache_1.io_cpu_rsp_isValid
TOP.VexRiscv.instructionCache_1.task_loaderHitReady
@29
TOP.VexRiscv.instructionCache_1.task_loaderHitValid
@28
TOP.VexRiscv.instructionCache_1.task_waysHitValid
@22
TOP.VexRiscv.instructionCache_1.task_waysHitWord[31:0]
TOP.VexRiscv.instructionCache_1.lineLoader_request_payload_addr[31:0]
@28
TOP.VexRiscv.instructionCache_1.lineLoader_request_ready
TOP.VexRiscv.instructionCache_1.lineLoader_request_valid
[pattern_trace] 1 [pattern_trace] 1
[pattern_trace] 0 [pattern_trace] 0

View File

@ -342,6 +342,14 @@ public:
} }
for(SimElement* simElement : simElements) simElement->preCycle(); for(SimElement* simElement : simElements) simElement->preCycle();
if(top->VexRiscv->decode_arbitration_isValid){
uint32_t expectedData;
bool dummy;
iBusAccess(top->VexRiscv->decode_PC, &expectedData, &dummy);
assertEq(top->VexRiscv->decode_INSTRUCTION,expectedData);
}
checks(); checks();
top->clk = 1; top->clk = 1;
top->eval(); top->eval();
@ -459,10 +467,11 @@ public:
} }
virtual void postCycle(){ virtual void postCycle(){
bool dummy; bool error;
top->iBus_rsp_valid = 0; top->iBus_rsp_valid = 0;
if(pendingCount != 0 && (!ws->iStall || VL_RANDOM_I(8) < 100)){ if(pendingCount != 0 && (!ws->iStall || VL_RANDOM_I(8) < 100)){
ws->iBusAccess(address,&top->iBus_rsp_payload_data,&dummy); ws->iBusAccess(address,&top->iBus_rsp_payload_data,&error);
top->iBus_rsp_payload_error = error;
pendingCount--; pendingCount--;
address = (address & ~0x1F) + ((address + 4) & 0x1F); address = (address & ~0x1F) + ((address + 4) & 0x1F);
top->iBus_rsp_valid = 1; top->iBus_rsp_valid = 1;