From c83a157c64b4392b1d82698495dc954a38a05223 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 9 Apr 2017 11:59:09 +0200 Subject: [PATCH] IBusCachedPlugin with twoStage config is now compatible with syncronous regfile --- src/main/scala/SpinalRiscv/Pipeline.scala | 5 +++ .../SpinalRiscv/Plugin/IBusCachedPlugin.scala | 33 +++++++++----- .../SpinalRiscv/Plugin/IBusSimplePlugin.scala | 1 + .../SpinalRiscv/Plugin/RegFilePlugin.scala | 6 ++- src/main/scala/SpinalRiscv/Services.scala | 2 +- src/main/scala/SpinalRiscv/TopLevel.scala | 2 +- src/main/scala/SpinalRiscv/VexRiscv.scala | 1 + src/test/cpp/testA/fail.gtkw | 44 ++++++++++++++----- 8 files changed, 69 insertions(+), 25 deletions(-) diff --git a/src/main/scala/SpinalRiscv/Pipeline.scala b/src/main/scala/SpinalRiscv/Pipeline.scala index 9e36e5d..e54fe35 100644 --- a/src/main/scala/SpinalRiscv/Pipeline.scala +++ b/src/main/scala/SpinalRiscv/Pipeline.scala @@ -23,6 +23,11 @@ trait Pipeline { filtered.head.asInstanceOf[T] } + def serviceExist[T](clazz : Class[T]) = { + val filtered = plugins.filter(o => clazz.isAssignableFrom(o.getClass)) + filtered.length != 0 + } + def build(): Unit ={ plugins.foreach(_.setup(this.asInstanceOf[T])) diff --git a/src/main/scala/SpinalRiscv/Plugin/IBusCachedPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/IBusCachedPlugin.scala index 97d623a..7a7a792 100644 --- a/src/main/scala/SpinalRiscv/Plugin/IBusCachedPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/IBusCachedPlugin.scala @@ -20,10 +20,12 @@ case class InstructionCacheConfig( cacheSize : Int, -class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv]{ +class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv] { import config._ var iBus : InstructionCacheMemBus = null + + object IBUS_ACCESS_ERROR extends Stageable(Bool) var decodeExceptionPort : Flow[ExceptionCause] = null override def setup(pipeline: VexRiscv): Unit = { @@ -55,8 +57,11 @@ class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv] cache.io.cpu.fetch.isStuck := fetch.arbitration.isStuck if(!twoStageLogic) cache.io.cpu.fetch.isStuckByOthers := fetch.arbitration.isStuckByOthers cache.io.cpu.fetch.address := fetch.output(PC) - if(!twoStageLogic) fetch.arbitration.haltIt setWhen(cache.io.cpu.fetch.haltIt) - if(!twoStageLogic) fetch.insert(INSTRUCTION) := cache.io.cpu.fetch.data + if(!twoStageLogic) { + 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)) + } cache.io.flush.cmd.valid := False @@ -66,6 +71,7 @@ class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv] cache.io.cpu.decode.isStuck := decode.arbitration.isStuck 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 } @@ -99,7 +105,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 = if(!p.twoStageLogic) Bits(32 bit) else null + 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 error = if(!p.twoStageLogic && p.catchAccessFault) Bool else null override def asMaster(): Unit = { @@ -116,11 +122,12 @@ case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle val isStuck = Bool val address = UInt(p.addressWidth bit) val data = Bits(32 bit) + val dataAnticipated = Bits(32 bits) val error = if(p.catchAccessFault) Bool else null override def asMaster(): Unit = { out(isValid, isStuck, address) - in(haltIt, data) + in(haltIt, data, dataAnticipated) if(p.catchAccessFault) in(error) } } @@ -398,24 +405,30 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ 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 := fetchInstructionValue + decodeInstructionReg := decodeInstructionRegIn + io.cpu.decode.dataAnticipated := decodeInstructionRegIn }.elsewhen(loadedWord.valid && (loadedWord.address >> 2) === (io.cpu.decode.address >> 2)){ decodeInstructionValid := True - decodeInstructionReg := loadedWord.data + decodeInstructionReg := decodeInstructionRegIn + io.cpu.decode.dataAnticipated := decodeInstructionRegIn } - io.cpu.decode.haltIt := io.cpu.decode.isValid && !decodeInstructionValid - io.cpu.decode.data := decodeInstructionReg + io.cpu.decode.haltIt := io.cpu.decode.isValid && !decodeInstructionValid + io.cpu.decode.data := decodeInstructionReg + lineLoader.requestIn.valid := io.cpu.decode.isValid && !decodeInstructionValid lineLoader.requestIn.addr := io.cpu.decode.address - } io.flush.cmd.ready := !(lineLoader.request.valid || io.cpu.fetch.isValid) diff --git a/src/main/scala/SpinalRiscv/Plugin/IBusSimplePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/IBusSimplePlugin.scala index 561962f..6edbf7b 100644 --- a/src/main/scala/SpinalRiscv/Plugin/IBusSimplePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/IBusSimplePlugin.scala @@ -60,6 +60,7 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean) fetch.insert(INSTRUCTION) := iBus.rsp.inst 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)) if(catchAccessFault){ decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR) diff --git a/src/main/scala/SpinalRiscv/Plugin/RegFilePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/RegFilePlugin.scala index 15d087f..30ac01b 100644 --- a/src/main/scala/SpinalRiscv/Plugin/RegFilePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/RegFilePlugin.scala @@ -1,9 +1,11 @@ package SpinalRiscv.Plugin -import SpinalRiscv.{Stageable, DecoderService, Riscv, VexRiscv} +import SpinalRiscv._ import spinal.core._ import spinal.lib._ +import scala.collection.mutable + trait RegFileReadKind object ASYNC extends RegFileReadKind @@ -41,7 +43,7 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals //read register file val srcInstruction = regFileReadyKind match{ case `ASYNC` => input(INSTRUCTION) - case `SYNC` => Mux(arbitration.isStuck,input(INSTRUCTION),fetch.output(INSTRUCTION)) + case `SYNC` => input(INSTRUCTION_ANTICIPATED) } val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt diff --git a/src/main/scala/SpinalRiscv/Services.scala b/src/main/scala/SpinalRiscv/Services.scala index d122e26..6d6ec83 100644 --- a/src/main/scala/SpinalRiscv/Services.scala +++ b/src/main/scala/SpinalRiscv/Services.scala @@ -20,4 +20,4 @@ case class ExceptionCause() extends Bundle{ trait ExceptionService{ def newExceptionPort(stage : Stage, priority : Int = 0) : Flow[ExceptionCause] -} \ No newline at end of file +} diff --git a/src/main/scala/SpinalRiscv/TopLevel.scala b/src/main/scala/SpinalRiscv/TopLevel.scala index 6c38fe7..01980c8 100644 --- a/src/main/scala/SpinalRiscv/TopLevel.scala +++ b/src/main/scala/SpinalRiscv/TopLevel.scala @@ -239,7 +239,7 @@ object TopLevel { catchIllegalInstruction = false ), new RegFilePlugin( - regFileReadyKind = Plugin.ASYNC, + regFileReadyKind = Plugin.SYNC, zeroBoot = false ), new IntAluPlugin, diff --git a/src/main/scala/SpinalRiscv/VexRiscv.scala b/src/main/scala/SpinalRiscv/VexRiscv.scala index 443c33b..aa24a03 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_ANTICIPATED extends Stageable(Bits(32 bits)) object LEGAL_INSTRUCTION extends Stageable(Bool) object REGFILE_WRITE_VALID extends Stageable(Bool) object REGFILE_WRITE_DATA extends Stageable(Bits(32 bits)) diff --git a/src/test/cpp/testA/fail.gtkw b/src/test/cpp/testA/fail.gtkw index d97694c..4930b64 100644 --- a/src/test/cpp/testA/fail.gtkw +++ b/src/test/cpp/testA/fail.gtkw @@ -1,19 +1,19 @@ [*] [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Sat Apr 8 15:08:01 2017 +[*] Sun Apr 9 09:10:08 2017 [*] -[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/rv32ui-p-simple.vcd" -[dumpfile_mtime] "Sat Apr 8 15:02:54 2017" -[dumpfile_size] 95378 +[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 [savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/fail.gtkw" -[timestart] 211 +[timestart] 274 [size] 1776 953 -[pos] -1 -1 -*-4.422177 320 -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 -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 [treeopen] TOP. [treeopen] TOP.VexRiscv. [sst_width] 201 -[signals_width] 397 +[signals_width] 453 [sst_expanded] 1 [sst_vpaned_height] 279 @800200 @@ -31,19 +31,18 @@ TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isValid TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isStuck @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 -@29 TOP.VexRiscv.instructionCache_1.io_cpu_decode_haltIt -@28 TOP.VexRiscv.instructionCache_1.io_cpu_decode_isStuck @22 TOP.VexRiscv.instructionCache_1.io_cpu_decode_address[31:0] -TOP.VexRiscv.instructionCache_1.io_cpu_decode_instruction[31:0] +TOP.VexRiscv.instructionCache_1.io_cpu_decode_data[31:0] @1000200 -decode @800200 @@ -61,5 +60,28 @@ TOP.VexRiscv.instructionCache_1.io_mem_rsp_valid -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 +@28 +TOP.VexRiscv.decode_arbitration_isStuck +@22 +TOP.VexRiscv.decode_PC[31:0] +TOP.VexRiscv.decode_REG1[31:0] +TOP.VexRiscv.decode_REG2[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] [pattern_trace] 1 [pattern_trace] 0