diff --git a/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala index 9134b2a..d6d730d 100644 --- a/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala @@ -128,7 +128,7 @@ class BranchPlugin(earlyBranch : Boolean, stages(indexOf(branchStage) - 1).arbitration.flushAll := True } - if(catchAddressMisaligned) { + if(catchAddressMisaligned) { //TODO conflict with instruction cache two stage branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0 branchExceptionPort.code := 0 branchExceptionPort.badAddr := jumpInterface.payload @@ -180,7 +180,7 @@ class BranchPlugin(earlyBranch : Boolean, } if(catchAddressMisaligned) { - predictionExceptionPort.valid := input(PREDICTION_HAD_BRANCHED) && arbitration.isValid && predictionJumpInterface.payload(1 downto 0) =/= 0 + predictionExceptionPort.valid := input(INSTRUCTION_READY) && input(PREDICTION_HAD_BRANCHED) && arbitration.isValid && predictionJumpInterface.payload(1 downto 0) =/= 0 predictionExceptionPort.code := 0 predictionExceptionPort.badAddr := predictionJumpInterface.payload } @@ -236,7 +236,7 @@ class BranchPlugin(earlyBranch : Boolean, } if(catchAddressMisaligned) { - branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0 + branchExceptionPort.valid := input(INSTRUCTION_READY) && arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0 branchExceptionPort.code := 0 branchExceptionPort.badAddr := jumpInterface.payload } diff --git a/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala index 9b69e27..dd2ed88 100644 --- a/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala @@ -131,7 +131,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean) extends Plugin[VexR if(catchIllegalInstruction){ - decodeExceptionPort.valid := arbitration.isValid && arbitration.haltIt && !input(LEGAL_INSTRUCTION) //HalitIt to alow decoder stage to wait valid data from 2 stages cache cache + 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.code := 2 decodeExceptionPort.badAddr.assignDontCare() } diff --git a/src/main/scala/SpinalRiscv/Plugin/HazardSimplePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/HazardSimplePlugin.scala index 8b8f489..477f55e 100644 --- a/src/main/scala/SpinalRiscv/Plugin/HazardSimplePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/HazardSimplePlugin.scala @@ -82,11 +82,13 @@ class HazardSimplePlugin(bypassExecute : Boolean, trackHazardWithStage(execute ,bypassExecute ,BYPASSABLE_EXECUTE_STAGE) - when(decode.input(INSTRUCTION)(rs1Range) === 0 || (if(pessimisticUseSrc) False else !decode.input(REG1_USE))){ - src0Hazard := False - } - when(decode.input(INSTRUCTION)(rs2Range) === 0 || (if(pessimisticUseSrc) False else !decode.input(REG2_USE))){ - src1Hazard := False + if(!pessimisticUseSrc) { + when(!decode.input(REG1_USE)) { + src0Hazard := False + } + when(!decode.input(REG2_USE)) { + src1Hazard := False + } } when(decode.arbitration.isValid && (src0Hazard || src1Hazard)){ diff --git a/src/main/scala/SpinalRiscv/Plugin/IBusCachedPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/IBusCachedPlugin.scala index 7a7a792..fdd130c 100644 --- a/src/main/scala/SpinalRiscv/Plugin/IBusCachedPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/IBusCachedPlugin.scala @@ -61,6 +61,7 @@ class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv] fetch.arbitration.haltIt setWhen (cache.io.cpu.fetch.haltIt) fetch.insert(INSTRUCTION) := cache.io.cpu.fetch.data decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION)) + decode.insert(INSTRUCTION_READY) := True } cache.io.flush.cmd.valid := False @@ -72,11 +73,13 @@ class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv] cache.io.cpu.decode.address := decode.input(PC) decode.insert(INSTRUCTION) := cache.io.cpu.decode.data decode.insert(INSTRUCTION_ANTICIPATED) := cache.io.cpu.decode.dataAnticipated + decode.insert(INSTRUCTION_READY) := !cache.io.cpu.decode.haltIt } if(catchAccessFault){ - if(!twoStageLogic) fetch.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.fetch.error + if(!twoStageLogic) fetch.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.fetch.error + if( twoStageLogic) decode.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.decode.error decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR) decodeExceptionPort.code := 1 @@ -105,7 +108,7 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w val isStuck = Bool val isStuckByOthers = if(!p.twoStageLogic) Bool else null val address = UInt(p.addressWidth bit) - val data = Bits(32 bit) //If twoStageLogic == true, this signal is acurate only when there is the cache doesn't stall decode (Used for Sync regfile) + val data = if(!p.twoStageLogic) Bits(32 bit) else null val error = if(!p.twoStageLogic && p.catchAccessFault) Bool else null override def asMaster(): Unit = { @@ -209,13 +212,26 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ val lineRange = tagRange.low-1 downto log2Up(bytePerLine) val wordRange = log2Up(bytePerLine)-1 downto log2Up(bytePerWord) val tagLineRange = tagRange.high downto lineRange.low + val lineWordRange = lineRange.high downto wordRange.low class LineInfo extends Bundle{ val valid = Bool + val loading = Bool val error = if(catchAccessFault) Bool else null val address = UInt(tagRange.length bit) } + class LineInfoWithHit extends LineInfo{ + val hit = Bool + } + + def LineInfoWithHit(lineInfo : LineInfo, testTag : UInt) = { + val ret = new LineInfoWithHit() + ret.assignSomeByName(lineInfo) + ret.hit := lineInfo.valid && lineInfo.address === testTag + ret + } + val ways = Array.fill(wayCount)(new Area{ val tags = Mem(new LineInfo(),wayLineCount) @@ -232,7 +248,6 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ - val flushCounter = Reg(UInt(log2Up(wayLineCount) + 1 bit)) init(0) when(!flushCounter.msb){ io.cpu.prefetch.haltIt := True @@ -260,10 +275,6 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ val request = requestIn.stage() - val lineInfoWrite = new LineInfo() - lineInfoWrite.valid := flushCounter.msb - lineInfoWrite.address := request.addr(tagRange) - if(catchAccessFault) lineInfoWrite.error := loadingWithError //Send memory requests val memCmdSended = RegInit(False) setWhen(io.mem.cmd.fire) @@ -279,10 +290,10 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ val loadedWordsReadable = RegNext(loadedWords) loadedWordsNext := loadedWords - val waysWritePort = ways(0).datas.writePort //Not multi ways - waysWritePort.valid := io.mem.rsp.valid - waysWritePort.address := request.addr(lineRange) @@ wordIndex - waysWritePort.data := io.mem.rsp.data + val waysDatasWritePort = ways(0).datas.writePort //Not multi ways + waysDatasWritePort.valid := io.mem.rsp.valid + waysDatasWritePort.address := request.addr(lineRange) @@ wordIndex + waysDatasWritePort.data := io.mem.rsp.data when(io.mem.rsp.valid){ wordIndex := wordIndex + 1 loadedWordsNext(wordIndex) := True @@ -297,11 +308,14 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ } request.ready := readyDelay === 1 + val waysTagsWritePort = ways(0).tags.writePort //not multi way + waysTagsWritePort.valid := io.mem.rsp.valid || !flushCounter.msb + waysTagsWritePort.address := Mux(flushCounter.msb,request.addr(lineRange),flushCounter(flushCounter.high-1 downto 0)) + waysTagsWritePort.data.valid := flushCounter.msb + waysTagsWritePort.data.address := request.addr(tagRange) + waysTagsWritePort.data.loading := !memRspLast + if(catchAccessFault) waysTagsWritePort.data.error := loadingWithError - 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){ memCmdSended := False @@ -321,9 +335,9 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ val waysRead = for(way <- ways) yield new Area{ val readAddress = Mux(io.cpu.fetch.isStuck,io.cpu.fetch.address,io.cpu.prefetch.address) //TODO FMAX val tag = if(asyncTagMemory) - way.tags.readAsync(io.cpu.fetch.address(lineRange)) + way.tags.readAsync(io.cpu.fetch.address(lineRange),writeFirst) else - way.tags.readSync(readAddress(lineRange)) + way.tags.readSync(readAddress(lineRange),readUnderWrite = readFirst) val data = way.datas.readSync(readAddress(lineRange.high downto wordRange.low)) waysHitWord := data //Not applicable to multi way @@ -332,102 +346,128 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ if(catchAccessFault) waysHitError := tag.error } - when(lineLoader.request.valid && lineLoader.request.addr(lineRange) === io.cpu.fetch.address(lineRange)){ - waysHitValid := False //Not applicable to multi way - } +// when(lineLoader.request.valid && lineLoader.request.addr(lineRange) === io.cpu.fetch.address(lineRange)){ +// waysHitValid := False //Not applicable to multi way +// } } - val loaderHitValid = lineLoader.request.valid && lineLoader.request.addr(tagLineRange) === io.cpu.fetch.address(tagLineRange) - val loaderHitReady = lineLoader.loadedWordsReadable(io.cpu.fetch.address(wordRange)) + val hit = waysHitValid && !(waysRead(0).tag.loading && !(if(asyncTagMemory) lineLoader.loadedWords else RegNext(lineLoader.loadedWords))(io.cpu.fetch.address(wordRange))) + io.cpu.fetch.haltIt := io.cpu.fetch.isValid && !hit + io.cpu.fetch.data := waysHitWord + if(catchAccessFault) io.cpu.fetch.error := waysRead(0).tag.error + lineLoader.requestIn.valid := io.cpu.fetch.isValid && !hit //TODO avoid duplicated request + lineLoader.requestIn.addr := io.cpu.fetch.address - - io.cpu.fetch.haltIt := io.cpu.fetch.isValid && !(waysHitValid || (loaderHitValid && loaderHitReady)) - io.cpu.fetch.data := waysHitWord //TODO - if(catchAccessFault) io.cpu.fetch.error := (waysHitValid && waysHitError) || (loaderHitValid && loaderHitReady && lineLoader.loadingWithErrorReg) - lineLoader.requestIn.valid := io.cpu.fetch.isValid && !io.cpu.fetch.isStuckByOthers && !waysHitValid - lineLoader.requestIn.addr := io.cpu.fetch.address + // val loaderHitValid = lineLoader.request.valid && lineLoader.request.addr(tagLineRange) === io.cpu.fetch.address(tagLineRange) +// val loaderHitReady = lineLoader.loadedWordsReadable(io.cpu.fetch.address(wordRange)) +// +// +// io.cpu.fetch.haltIt := io.cpu.fetch.isValid && !(waysHitValid || (loaderHitValid && loaderHitReady)) +// io.cpu.fetch.data := waysHitWord //TODO +// if(catchAccessFault) io.cpu.fetch.error := (waysHitValid && waysHitError) || (loaderHitValid && loaderHitReady && lineLoader.loadingWithErrorReg) +// lineLoader.requestIn.valid := io.cpu.fetch.isValid && !io.cpu.fetch.isStuckByOthers && !waysHitValid +// lineLoader.requestIn.addr := io.cpu.fetch.address } else new Area{ - val waysHitValid = False - val waysHitError = Bool.assignDontCare() - val waysHitWord = Bits(wordWidth bit) + //Long readValidPath +// def writeFirstMemWrap[T <: Data](readValid : Bool, readAddress : UInt, lastAddress : UInt, readData : T,writeValid : Bool, writeAddress : UInt, writeData : T) : T = { +// val hit = writeValid && (readValid ? readAddress | lastAddress) === writeAddress +// val overrideValid = RegInit(False) clearWhen(readValid) setWhen(hit) +// val overrideValue = RegNextWhen(writeData,hit) +// overrideValid ? overrideValue | readData +// } - val waysRead = for(way <- ways) yield new Area{ + //shot readValid path + def writeFirstMemWrap[T <: Data](readValid : Bool, readLastAddress : UInt, readData : T,writeValid : Bool, writeAddress : UInt, writeData : T) : T = { + val writeSample = readValid || (writeValid && writeAddress === readLastAddress) + val writeValidReg = RegNextWhen(writeValid,writeSample) + val writeAddressReg = RegNextWhen(writeAddress,writeSample) + val writeDataReg = RegNextWhen(writeData,writeSample) + (writeValidReg && writeAddressReg === readLastAddress) ? writeDataReg | readData + } + + //Long sample path +// def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,lastAddress : UInt, readData : T, writeValid : Bool, writeAddress : UInt, writeData : T) : (T,T) = { +// val hit = writeValid && (sample ? sampleAddress | lastAddress) === writeAddress +// val bypass = hit ? writeData | readData +// val reg = RegNextWhen(bypass,sample || hit) +// (reg,bypass) +// } + + //Short sample path + def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, readData : T, writeValid : Bool, writeAddress : UInt, writeData : T) = { + val preWrite = (writeValid && sampleAddress === writeAddress) + val postWrite = (writeValid && sampleLastAddress === writeAddress) + val bypass = (!sample || preWrite) ? writeData | readData + val regEn = sample || postWrite + val reg = RegNextWhen(bypass,regEn) + (reg,bypass,regEn,preWrite,postWrite) + } +// def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, readData : T, writeValid : Bool, writeAddress : UInt, writeData : T) = { +// val bypass = (!sample || (writeValid && sampleAddress === writeAddress)) ? writeData | readData +// val regEn = sample || (writeValid && sampleLastAddress === writeAddress) +// val reg = RegNextWhen(bypass,regEn) +// (reg,bypass,regEn,False,False) +// } + require(wayCount == 1) + val memRead = new Area{ + val way = ways(0) val tag = if(asyncTagMemory) - way.tags.readAsync(io.cpu.fetch.address(lineRange)) + way.tags.readAsync(io.cpu.fetch.address(lineRange),writeFirst) else - way.tags.readSync(io.cpu.prefetch.address(lineRange),enable = !io.cpu.fetch.isStuck) + writeFirstMemWrap( + readValid = !io.cpu.fetch.isStuck, +// readAddress = io.cpu.prefetch.address(lineRange), + readLastAddress = io.cpu.fetch.address(lineRange), + readData = way.tags.readSync(io.cpu.prefetch.address(lineRange),enable = !io.cpu.fetch.isStuck), + writeValid = lineLoader.waysTagsWritePort.valid, + writeAddress = lineLoader.waysTagsWritePort.address, + writeData = lineLoader.waysTagsWritePort.data + ) - val data = way.datas.readSync(io.cpu.prefetch.address(lineRange.high downto wordRange.low),enable = !io.cpu.fetch.isStuck) - waysHitWord := data //Not applicable to multi way - when(tag.valid && tag.address === io.cpu.fetch.address(tagRange)) { - waysHitValid := True - if(catchAccessFault) waysHitError := tag.error - } - - when(lineLoader.request.valid && lineLoader.request.addr(lineRange) === io.cpu.fetch.address(lineRange)){ - waysHitValid := False //Not applicable to multi way - } + val data = writeFirstMemWrap( + readValid = !io.cpu.fetch.isStuck, +// readAddress = io.cpu.prefetch.address(lineWordRange), + readLastAddress = io.cpu.fetch.address(lineWordRange), + readData = way.datas.readSync(io.cpu.prefetch.address(lineWordRange),enable = !io.cpu.fetch.isStuck), + writeValid = lineLoader.waysDatasWritePort.valid, + writeAddress = lineLoader.waysDatasWritePort.address, + writeData = lineLoader.waysDatasWritePort.data + ) } + val tag = writeFirstRegWrap( + sample = !io.cpu.decode.isStuck, + sampleAddress = io.cpu.fetch.address(lineRange), + sampleLastAddress = io.cpu.decode.address(lineRange), + readData = LineInfoWithHit(memRead.tag,io.cpu.fetch.address(tagRange)), + writeValid = lineLoader.waysTagsWritePort.valid, + writeAddress = lineLoader.waysTagsWritePort.address, + writeData = LineInfoWithHit(lineLoader.waysTagsWritePort.data,io.cpu.fetch.address(tagRange)) //TODO wrong address src + )._1 - val loadedWord = new Area{ - val valid = RegNext(lineLoader.waysWritePort.valid) - val address = RegNext(lineLoader.request.addr(tagLineRange) @@ lineLoader.wordIndex @@ U"00") - val data = RegNext(lineLoader.waysWritePort.data) - val wasLoaded = RegNext(lineLoader.loadedWords) - } + val (data,dataRegIn,dataRegEn,dataPreWrite,dataPostWrite) = writeFirstRegWrap( + sample = !io.cpu.decode.isStuck, + sampleAddress = io.cpu.fetch.address(lineWordRange), + sampleLastAddress = io.cpu.decode.address(lineWordRange), + readData = memRead.data, + writeValid = lineLoader.waysDatasWritePort.valid, + writeAddress = lineLoader.waysDatasWritePort.address, + writeData = lineLoader.waysDatasWritePort.data + ) + val hit = tag.valid && tag.address === io.cpu.decode.address(tagRange) && !(tag.loading && !lineLoader.loadedWords(io.cpu.decode.address(wordRange))) +// val hit = tag.hit && !(tag.loading && !lineLoader.loadedWords(io.cpu.decode.address(wordRange))) - val fetchInstructionValid = Bool - val fetchInstructionValue = Bits(32 bits) - val fetchInstructionValidReg = Reg(Bool) - val fetchInstructionValueReg = Reg(Bits(32 bits)) + io.cpu.decode.haltIt := io.cpu.decode.isValid && !hit //TODO PERF not halit it when removed, Should probably be applyed in many other places + io.cpu.decode.data := data +// io.cpu.decode.dataAnticipated := dataRegEn ? dataRegIn | data + 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 - when(fetchInstructionValidReg){ - fetchInstructionValid := True - fetchInstructionValue := fetchInstructionValueReg - }.elsewhen(loadedWord.valid && (loadedWord.address >> 2) === (io.cpu.fetch.address >> 2)){ - fetchInstructionValid := True - fetchInstructionValue := loadedWord.data - } otherwise{ - fetchInstructionValid := waysHitValid || (loadedWord.address(tagLineRange) === io.cpu.fetch.address(tagLineRange) && loadedWord.wasLoaded(io.cpu.fetch.address(wordRange))) - fetchInstructionValue := waysHitWord //Not multi way (wasloaded) - } - - - when(io.cpu.fetch.isStuck){ - fetchInstructionValidReg := fetchInstructionValid - fetchInstructionValueReg := fetchInstructionValue - } otherwise { - fetchInstructionValidReg := False - } - - io.cpu.fetch.data := fetchInstructionValue - - - val decodeInstructionValid = Reg(Bool) - val decodeInstructionReg = Reg(Bits(32 bits)) - val decodeInstructionRegIn = (!io.cpu.decode.isStuck) ? fetchInstructionValue | loadedWord.data - - io.cpu.decode.dataAnticipated := decodeInstructionReg - when(!io.cpu.decode.isStuck){ - decodeInstructionValid := fetchInstructionValid - decodeInstructionReg := decodeInstructionRegIn - io.cpu.decode.dataAnticipated := decodeInstructionRegIn - }.elsewhen(loadedWord.valid && (loadedWord.address >> 2) === (io.cpu.decode.address >> 2)){ - decodeInstructionValid := True - decodeInstructionReg := decodeInstructionRegIn - io.cpu.decode.dataAnticipated := decodeInstructionRegIn - } - - io.cpu.decode.haltIt := io.cpu.decode.isValid && !decodeInstructionValid - io.cpu.decode.data := decodeInstructionReg - - - lineLoader.requestIn.valid := io.cpu.decode.isValid && !decodeInstructionValid + lineLoader.requestIn.valid := io.cpu.decode.isValid && !hit //TODO avoid duplicated request lineLoader.requestIn.addr := io.cpu.decode.address } diff --git a/src/main/scala/SpinalRiscv/Plugin/IBusSimplePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/IBusSimplePlugin.scala index 6edbf7b..ec0f4d1 100644 --- a/src/main/scala/SpinalRiscv/Plugin/IBusSimplePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/IBusSimplePlugin.scala @@ -61,6 +61,7 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean) fetch.insert(IBUS_ACCESS_ERROR) := iBus.rsp.error fetch.arbitration.haltIt setWhen(fetch.arbitration.isValid && !iBus.rsp.ready) decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION)) + decode.insert(INSTRUCTION_READY) := True if(catchAccessFault){ decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR) diff --git a/src/main/scala/SpinalRiscv/TopLevel.scala b/src/main/scala/SpinalRiscv/TopLevel.scala index 01980c8..092fdc8 100644 --- a/src/main/scala/SpinalRiscv/TopLevel.scala +++ b/src/main/scala/SpinalRiscv/TopLevel.scala @@ -79,22 +79,24 @@ object TopLevel { configFull.plugins ++= List( new PcManagerSimplePlugin(0x00000000l, false), - new IBusSimplePlugin( - interfaceKeepData = true, - catchAccessFault = true - ), -// new IBusCachedPlugin( -// config = InstructionCacheConfig( -// cacheSize =4096, -// bytePerLine =32, -// wayCount = 1, -// wrappedMemAccess = true, -// addressWidth = 32, -// cpuDataWidth = 32, -// memDataWidth = 32, -// 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, + catchAccessFault = true, + asyncTagMemory = false, + twoStageLogic = true + ) + ), new DBusSimplePlugin( catchAddressMisaligned = true, catchAccessFault = true @@ -269,9 +271,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) diff --git a/src/main/scala/SpinalRiscv/VexRiscv.scala b/src/main/scala/SpinalRiscv/VexRiscv.scala index aa24a03..53533e0 100644 --- a/src/main/scala/SpinalRiscv/VexRiscv.scala +++ b/src/main/scala/SpinalRiscv/VexRiscv.scala @@ -19,6 +19,7 @@ case class VexRiscvConfig(pcWidth : Int){ object PC extends Stageable(UInt(pcWidth bits)) object PC_CALC_WITHOUT_JUMP extends Stageable(UInt(pcWidth bits)) object INSTRUCTION extends Stageable(Bits(32 bits)) + object INSTRUCTION_READY extends Stageable(Bool) object INSTRUCTION_ANTICIPATED extends Stageable(Bits(32 bits)) object LEGAL_INSTRUCTION extends Stageable(Bool) object REGFILE_WRITE_VALID extends Stageable(Bool) diff --git a/src/test/cpp/testA/fail.gtkw b/src/test/cpp/testA/fail.gtkw index 4930b64..8baef35 100644 --- a/src/test/cpp/testA/fail.gtkw +++ b/src/test/cpp/testA/fail.gtkw @@ -1,52 +1,66 @@ [*] [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Sun Apr 9 09:10:08 2017 +[*] Wed Apr 12 17:13:59 2017 [*] -[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/rv32ui-p-addi.vcd" -[dumpfile_mtime] "Sun Apr 9 09:08:48 2017" -[dumpfile_size] 136439 +[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/dhrystoneO3.vcd" +[dumpfile_mtime] "Wed Apr 12 17:05:50 2017" +[dumpfile_size] 476292557 [savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/fail.gtkw" -[timestart] 274 +[timestart] 602234 [size] 1776 953 -[pos] -775 -353 -*-2.774728 284 -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 +[pos] -775 -1 +*-3.626630 602285 -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.VexRiscv. [sst_width] 201 -[signals_width] 453 +[signals_width] 518 [sst_expanded] 1 [sst_vpaned_height] 279 -@800200 --prefetch -@28 -TOP.VexRiscv.instructionCache_1.io_cpu_prefetch_haltIt @22 TOP.VexRiscv.instructionCache_1.io_cpu_prefetch_address[31:0] -@1000200 --prefetch -@800200 --fetch @28 -TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isValid -TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isStuck +TOP.VexRiscv.instructionCache_1.io_cpu_prefetch_haltIt +@800200 +-Fetch @22 TOP.VexRiscv.instructionCache_1.io_cpu_fetch_address[31:0] -TOP.VexRiscv.instructionCache_1.io_cpu_fetch_data[31:0] -@1000200 --fetch -@800200 --decode @28 -TOP.VexRiscv.instructionCache_1.io_cpu_decode_isValid -TOP.VexRiscv.instructionCache_1.io_cpu_decode_haltIt -TOP.VexRiscv.instructionCache_1.io_cpu_decode_isStuck +TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isStuck +TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isValid +@1000200 +-Fetch +@800200 +-Decode @22 TOP.VexRiscv.instructionCache_1.io_cpu_decode_address[31:0] TOP.VexRiscv.instructionCache_1.io_cpu_decode_data[31:0] +@28 +TOP.VexRiscv.instructionCache_1.io_cpu_decode_haltIt +TOP.VexRiscv.instructionCache_1.io_cpu_decode_isStuck +TOP.VexRiscv.instructionCache_1.io_cpu_decode_isValid @1000200 --decode +-Decode @800200 --ibus +-Task +@22 +TOP.VexRiscv.instructionCache_1.task_memRead_data[31:0] +TOP.VexRiscv.instructionCache_1.task_memRead_tag_address[19:0] +@28 +TOP.VexRiscv.instructionCache_1.task_memRead_tag_valid +@22 +TOP.VexRiscv.instructionCache_1.task_tag_address[19:0] +@28 +TOP.VexRiscv.instructionCache_1.task_tag_valid +@22 +TOP.VexRiscv.instructionCache_1.task_dataRegIn[31:0] +TOP.VexRiscv.instructionCache_1.task_data[31:0] +@29 +TOP.VexRiscv.instructionCache_1.task_cacheHit +@28 +TOP.VexRiscv.instructionCache_1.task_hit +TOP.VexRiscv.instructionCache_1.task_loaderHit +@1000200 +-Task @22 TOP.VexRiscv.instructionCache_1.io_mem_cmd_payload_address[31:0] @28 @@ -56,32 +70,16 @@ TOP.VexRiscv.instructionCache_1.io_mem_cmd_valid TOP.VexRiscv.instructionCache_1.io_mem_rsp_payload_data[31:0] @28 TOP.VexRiscv.instructionCache_1.io_mem_rsp_valid -@1000200 --ibus -@28 -TOP.VexRiscv.instructionCache_1.clk @22 -TOP.VexRiscv.instructionCache_1.io_cpu_fetch_data[31:0] -TOP.VexRiscv.decode_RegFilePlugin_srcInstruction[31:0] -TOP.VexRiscv.instructionCache_1.io_cpu_decode_data[31:0] -@29 -TOP.VexRiscv.decode_arbitration_isValid +TOP.VexRiscv.instructionCache_1.lineLoader_waysDatasWritePort_payload_address[9:0] +TOP.VexRiscv.instructionCache_1.lineLoader_waysDatasWritePort_payload_data[31:0] @28 -TOP.VexRiscv.decode_arbitration_isStuck +TOP.VexRiscv.instructionCache_1.lineLoader_waysDatasWritePort_valid +TOP.VexRiscv.clk @22 -TOP.VexRiscv.decode_PC[31:0] -TOP.VexRiscv.decode_REG1[31:0] -TOP.VexRiscv.decode_REG2[31:0] +TOP.VexRiscv.instructionCache_1.lineLoader_request_payload_addr[31:0] @28 -TOP.VexRiscv.decode_REG1_USE -TOP.VexRiscv.decode_REG2_USE -TOP.VexRiscv.decode_arbitration_isValid -TOP.VexRiscv.decode_arbitration_isStuck -@22 -TOP.VexRiscv.decode_RegFilePlugin_regFileReadAddress1[4:0] -TOP.VexRiscv.decode_RegFilePlugin_regFileReadAddress2[4:0] -TOP.VexRiscv.decode_RegFilePlugin_rs1Data[31:0] -TOP.VexRiscv.decode_RegFilePlugin_rs2Data[31:0] -TOP.VexRiscv.decode_RegFilePlugin_srcInstruction[31:0] +TOP.VexRiscv.instructionCache_1.lineLoader_request_ready +TOP.VexRiscv.instructionCache_1.lineLoader_request_valid [pattern_trace] 1 [pattern_trace] 0 diff --git a/src/test/cpp/testA/main.cpp b/src/test/cpp/testA/main.cpp index 45ce64d..ac13883 100644 --- a/src/test/cpp/testA/main.cpp +++ b/src/test/cpp/testA/main.cpp @@ -681,11 +681,12 @@ public: #endif class Dhrystone : public Workspace{ public: - - Dhrystone(string name,bool iStall, bool dStall) : Workspace(name) { + string hexName; + Dhrystone(string name,string hexName,bool iStall, bool dStall) : Workspace(name) { setIStall(iStall); setDStall(dStall); - loadHex("../../resources/hex/" + name + ".hex"); + loadHex("../../resources/hex/" + hexName + ".hex"); + this->hexName = hexName; } virtual void checks(){ @@ -693,7 +694,7 @@ public: } virtual void pass(){ - FILE *refFile = fopen((name + ".logRef").c_str(), "r"); + FILE *refFile = fopen((hexName + ".logRef").c_str(), "r"); fseek(refFile, 0, SEEK_END); uint32_t refSize = ftell(refFile); fseek(refFile, 0, SEEK_SET); @@ -828,10 +829,10 @@ int main(int argc, char **argv, char **env) { #ifdef DHRYSTONE // Dhrystone("dhrystoneO3",false,false).run(0.05e6); - Dhrystone("dhrystoneO3",true,true).run(1.1e6); - Dhrystone("dhrystoneO3M",true,true).run(1.5e6); - Dhrystone("dhrystoneO3",false,false).run(1.5e6); - Dhrystone("dhrystoneO3M",false,false).run(1.2e6); + Dhrystone("dhrystoneO3_Stall","dhrystoneO3",true,true).run(1.1e6); + Dhrystone("dhrystoneO3M_Stall","dhrystoneO3M",true,true).run(1.5e6); + Dhrystone("dhrystoneO3","dhrystoneO3",false,false).run(1.5e6); + Dhrystone("dhrystoneO3M","dhrystoneO3M",false,false).run(1.2e6); // Dhrystone("dhrystoneO3ML",false,false).run(8e6); // Dhrystone("dhrystoneO3MLL",false,false).run(80e6); diff --git a/src/test/cpp/testA/makefile b/src/test/cpp/testA/makefile index 90eeaa4..364e0f5 100644 --- a/src/test/cpp/testA/makefile +++ b/src/test/cpp/testA/makefile @@ -1,4 +1,4 @@ -IBUS=IBUS_SIMPLE +IBUS=IBUS_CACHED DBUS=DBUS_SIMPLE TRACE=no TRACE_START=0