From 38a573a48c6b17c6f41294ec811cc711f550f3bb Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 3 Feb 2020 13:35:55 +0100 Subject: [PATCH 01/51] Update build.sbt --- build.sbt | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sbt b/build.sbt index ccb19f1..27bcb19 100644 --- a/build.sbt +++ b/build.sbt @@ -6,6 +6,7 @@ lazy val root = (project in file(".")). scalaVersion := "2.11.12", version := "2.0.0" )), + scalacOptions += s"-Xplugin:${new File("../SpinalHDL/idslplugin/target/scala-2.11/spinalhdl-idsl-plugin_2.11-1.3.9.jar").getAbsolutePath}", libraryDependencies ++= Seq( // "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.6", // "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.6", From 10da093422368de055b08dd3433e27b906c1521d Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Thu, 6 Feb 2020 21:07:40 +0100 Subject: [PATCH 02/51] Fix sbt --- build.sbt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.sbt b/build.sbt index 27bcb19..ac8feba 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,3 @@ - lazy val root = (project in file(".")). settings( inThisBuild(List( @@ -6,7 +5,8 @@ lazy val root = (project in file(".")). scalaVersion := "2.11.12", version := "2.0.0" )), - scalacOptions += s"-Xplugin:${new File("../SpinalHDL/idslplugin/target/scala-2.11/spinalhdl-idsl-plugin_2.11-1.3.9.jar").getAbsolutePath}", + scalacOptions += s"-Xplugin:${new File(baseDirectory.value + "/../SpinalHDL/idslplugin/target/scala-2.11/spinalhdl-idsl-plugin_2.11-1.3.9.jar")}", + scalacOptions += s"-Xplugin-require:idsl-plugin", libraryDependencies ++= Seq( // "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.6", // "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.6", @@ -14,10 +14,10 @@ lazy val root = (project in file(".")). "org.yaml" % "snakeyaml" % "1.8" ), name := "VexRiscv" - ).dependsOn(spinalHdlSim,spinalHdlCore,spinalHdlLib) + ).dependsOn(spinalHdlIdslPlugin, spinalHdlSim,spinalHdlCore,spinalHdlLib) +lazy val spinalHdlIdslPlugin = ProjectRef(file("../SpinalHDL"), "idslplugin") lazy val spinalHdlSim = ProjectRef(file("../SpinalHDL"), "sim") lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "core") lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "lib") - fork := true \ No newline at end of file From 6edab1eb34eeed9943b586f5a203dbf1756b908b Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 15 Feb 2020 00:24:33 +0100 Subject: [PATCH 03/51] Add SMP spec draft --- doc/smp/smp.md | 155 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 doc/smp/smp.md diff --git a/doc/smp/smp.md b/doc/smp/smp.md new file mode 100644 index 0000000..596b6a3 --- /dev/null +++ b/doc/smp/smp.md @@ -0,0 +1,155 @@ +# Coherent interface specification + +Features : +- 3 buses (write, read, probe) composed of 7 streams +- Two data paths (read + write), but allow dirty/clean sharing by reusing the write data path +- Allow multi level coherent interconnect +- No ordering, but provide barrier + + +## Memory copy flags + +| Name | Description | +|---------------|-------------| +| Valid/Invalid | Line loaded or not | +| Shared/Unique | shared => multiple copy of the cache line in different caches, unique => no other caches has a copy of the line | +| Owner/Lodger | invited => copy of the line, but no other responsibility, invited => the given cache is responsible to write back dirty data and answer probes with the data | +| Clean/Dirty | clean => match main memory, dirty => main memory need updates | + +All combination of those cache flag are valid. But if a cache line is invalid, the other flags have no meaning. + +Later in the spec, memory copy state can be described as : + +- VSOC for (Valid, Shared, Owner, Clean) +- V-OC for (Valid, Shared or Unique, Owner, Clean) +- !V-OC for NOT (Valid, Shared or Unique, Owner, Clean) + +## buses + +One full interface is composed of 3 buses +- write (M -> S) +- read (M -> S) +- probe (M <- S) + +### Read bus + +Composed of 3 stream : + +| Name | Direction | Description | +|---------|-----------|----------| +| readCmd | M -> S | Emit memory read and cache management commands | +| readRsp | M <- S | Return some data and/or a status from readCmd | +| readAck | M -> S | Return ACK from readRsp | + +### Write bus + +Composed of 2 stream : + +| Name | Direction | Description | +|---------|-----------|----------| +| writeCmd | M -> S | Emit memory writes and cache management commands | +| writeRsp | M <- S | Return a status from writeCmd | + +### Probe bus + +| Name | Direction | Description | +|----------|-----------|----------| +| probeCmd | M <- S | Used for cache management | +| probeRsp | M -> S | Acknowledgment | + +## Transactions + +This chapter define transactions moving over the 3 previously defined buses. + +### Read commands + +Emitted on the readCmd channel (master -> slave) + +| Command | Initial state | Description | Usage example | +|-------------|---------------|----------|------| +| readShared | I--- | Get a memory copy as V--- | Want to read a uncached address | +| readUnique | I--- | Get a memory copy as VUO- | Want to write a uncached address | +| readOnce | I--- | Get a memory copy without coherency tracking | Instruction cache read | +| makeInvalid | VS-- | Make other memory copy as I--- and make yourself VUO- | Want to write into a shared line | +| readBarrier | N/A | Ensure that the visibility of the memory operations of this channel do not cross the barrier | ISA fence | + +makeInvalid should be designed with care. There is a few corner cases : +- While a master has a inflight makeInvalid, a probe can change its state. +- Multi level coherent interconnect should be careful to properly move the ownership and not lose dirty data + +I'm not sure yet if we should add some barrier transactions to enforce + +### Read responses + +Emitted on the readRsp channel (master <- slave) + +success, abort, error, data shared/unique clean/dirty owner/notOwner + +| Responses | From command | Description | +|-----------|---------------|----------| +| success | makeInvalid, readBarrier | - | +| abort | makeInvalid | A concurrent makeInvalid toke over | +| error | readShared, readUnique, readOnce | Bad address | +| readData | readShared, readUnique, readOnce | Data + coherency flags (V???) | + +### Read ack + +Emitted on the readAck channel (master -> slave), it carry no information, just a notification that the master received the read response + +| Name | From command | Description | +|--------------|---------------|----------| +| readSuccess | * | - | + +### Write commands + +Write commands can be emitted on the writeCmd channel (master -> slave) + +| Name | Initial state | Description | Usage example | +|--------------|---------------|----------|----------| +| writeInvalid | V-O- | Write the memory copy and update it status to I--- | Need to free the dirty cache line | +| writeShare | V-O- | Write the memory copy but keep it as VSO- | A probe makeShared asked it | +| evict | V---, !V-OD | Notify the interconnect that the cache line is now I--- | Need to free a clean cache line | +| writeBarrier | N/A | Ensure that the visibility of the memory operations of this channel do not cross the barrier | ISA fence | + +### Write responses + +Emitted on the writeRsp channel (master <- slave), it carry no information, just a notification that the corresponding command is done. + +| Name | From command | Description | +|--------------|---------------|----------| +| writeSuccess | * | - | + +### Probe commands + +Probe commands can be emitted on the probeCmd channel (slave -> master) + +| Name | Description | Usage example | +|-------------|-------------|---------------| +| makeInvalid | Make the memory copy I--- | Another cache want to make his shared copy unique to write it | +| makeShared | Make the memory copy VS-- | Another cache want to read a memory block, so unique copy need to be shared | + +Both makeInvalid and makeShared could result into one of the following probeSuccess, writeInvalid, writeShare. + +To help the slave matching the writeInvalid and writeShare generated from a probe, those request are tagged with a matching ID. + +### Probe responses + +Emitted on the probeRsp channel (master -> slave), it carry no information, just a notification that the corresponding command is done. + +| Name | From command | Description | +|--------------|---------------|----------| +| probeSuccess | * | - | + + +## Channel interlocking + +There is the streams priority (top => high priority, bottom => low priority ) +- writeCmd, writeRsp, readRsp, readAck, probeRsp. Nothing should realy block them excepted bandwidth +- probeCmd. Can be blocked by inflight/generated writes +- readCmd. Can be blocked by inflight/generated probes + +In other words : + +Masters can wait the completion of inflight writes before answering probes. +Slaves can emit probes and wait their completion before answering reads. +Slaves can wait on readAck incomming from generated readRsp before at all times From f1959ff830d3d9f711fb079dc3fea157d7bde58a Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 15 Feb 2020 00:26:11 +0100 Subject: [PATCH 04/51] smp spec typo --- doc/smp/smp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/smp/smp.md b/doc/smp/smp.md index 596b6a3..c335f1f 100644 --- a/doc/smp/smp.md +++ b/doc/smp/smp.md @@ -13,7 +13,7 @@ Features : |---------------|-------------| | Valid/Invalid | Line loaded or not | | Shared/Unique | shared => multiple copy of the cache line in different caches, unique => no other caches has a copy of the line | -| Owner/Lodger | invited => copy of the line, but no other responsibility, invited => the given cache is responsible to write back dirty data and answer probes with the data | +| Owner/Lodger | lodger => copy of the line, but no other responsibility, owner => the given cache is responsible to write back dirty data and answer probes with the data | | Clean/Dirty | clean => match main memory, dirty => main memory need updates | All combination of those cache flag are valid. But if a cache line is invalid, the other flags have no meaning. From d241f3562501bed750f958b116a40cf453be7021 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 15 Feb 2020 10:10:04 +0100 Subject: [PATCH 05/51] Remove usages of implicit string to B/U/S --- src/main/scala/vexriscv/ip/DataCache.scala | 6 +++--- src/main/scala/vexriscv/plugin/BranchPlugin.scala | 6 +++--- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 10 +++++----- src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala | 2 +- src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala | 6 +++--- src/main/scala/vexriscv/plugin/Misc.scala | 4 ++-- .../scala/vexriscv/plugin/MulDivIterativePlugin.scala | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index 838489d..eaed1d0 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -259,7 +259,7 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave val cmdBridge = Stream (DataCacheMemCmd(p)) val isBurst = cmdBridge.length =/= 0 cmdBridge.valid := cmd.valid - cmdBridge.address := (isBurst ? (cmd.address(31 downto widthOf(counter) + 2) @@ counter @@ "00") | (cmd.address(31 downto 2) @@ "00")) + cmdBridge.address := (isBurst ? (cmd.address(31 downto widthOf(counter) + 2) @@ counter @@ U"00") | (cmd.address(31 downto 2) @@ U"00")) cmdBridge.wr := cmd.wr cmdBridge.mask := cmd.mask cmdBridge.data := cmd.data @@ -278,8 +278,8 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave bus.ADR := cmdBridge.address >> 2 bus.CTI := Mux(isBurst, cmdBridge.last ? B"111" | B"010", B"000") - bus.BTE := "00" - bus.SEL := cmdBridge.wr ? cmdBridge.mask | "1111" + bus.BTE := B"00" + bus.SEL := cmdBridge.wr ? cmdBridge.mask | B"1111" bus.WE := cmdBridge.wr bus.DAT_MOSI := cmdBridge.data diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index 77f72b8..e90a1fc 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -197,7 +197,7 @@ class BranchPlugin(earlyBranch : Boolean, ).asUInt val branchAdder = branch_src1 + branch_src2 - insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0" + insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ U"0" } //Apply branchs (JAL,JALR, Bxx) @@ -274,7 +274,7 @@ class BranchPlugin(earlyBranch : Boolean, } } val branchAdder = branch_src1 + branch_src2 - insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0" + insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ U"0" } @@ -341,7 +341,7 @@ class BranchPlugin(earlyBranch : Boolean, ).asUInt val branchAdder = branch_src1 + input(BRANCH_SRC2) - insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0" + insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ U"0" insert(NEXT_PC) := input(PC) + (if(pipeline(RVC_GEN)) ((input(IS_RVC)) ? U(2) | U(4)) else 4) insert(TARGET_MISSMATCH) := decode.input(PC) =/= input(BRANCH_CALC) } diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 8759df5..98dfbaa 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -775,8 +775,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep var privilegs = if (supervisorGen) List(1, 3) else List(3) val targetPrivilege = if(pipelinedInterrupt) Reg(UInt(2 bits)) else UInt(2 bits).assignDontCare() val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]() - if (supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01") - privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11") + if (supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === U"01") || privilege < U"01") + privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < U"11") while (privilegs.nonEmpty) { val p = privilegs.head when(privilegeAllowInterrupts(p)) { @@ -844,7 +844,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep fetcher.haltIt() //Avoid having the fetch confused by the incomming privilege switch jumpInterface.valid := True - jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") ) + jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ U"00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ U"00") | ((xtvec.base + trapCause) @@ U"00") ) lastStage.arbitration.flushNext := True if(privilegeGen) privilegeReg := targetPrivilege @@ -917,8 +917,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep val imm = IMM(input(INSTRUCTION)) insert(CSR_WRITE_OPCODE) := ! ( - (input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0) - || (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0) + (input(INSTRUCTION)(14 downto 13) === B"01" && input(INSTRUCTION)(rs1Range) === 0) + || (input(INSTRUCTION)(14 downto 13) === B"11" && imm.z === 0) ) insert(CSR_READ_OPCODE) := input(INSTRUCTION)(13 downto 7) =/= B"0100000" } diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index a7b2194..8ef10b2 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -211,7 +211,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, if (catchSomething) { decodeExceptionPort.valid := False decodeExceptionPort.code.assignDontCare() - decodeExceptionPort.badAddr := cacheRsp.pc(31 downto 2) @@ "00" + decodeExceptionPort.badAddr := cacheRsp.pc(31 downto 2) @@ U"00" } when(cacheRsp.isValid && cacheRsp.mmuRefilling && !issueDetected) { diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index fa74f6c..7936f17 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -316,7 +316,7 @@ class IBusSimplePlugin( resetVector : BigInt, mmuBus.cmd.bypassTranslation := False mmuBus.end := cmdForkStage.output.fire || fetcherflushIt - cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00" + cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ U"00" //do not emit memory request if MMU miss when(mmuBus.rsp.exception || mmuBus.rsp.refilling){ @@ -333,7 +333,7 @@ class IBusSimplePlugin( resetVector : BigInt, } val mmuLess = (mmuBus == null) generate new Area{ - cmd.pc := cmdForkStage.input.payload(31 downto 2) @@ "00" + cmd.pc := cmdForkStage.input.payload(31 downto 2) @@ U"00" } val rspJoin = new Area { @@ -389,7 +389,7 @@ class IBusSimplePlugin( resetVector : BigInt, if(catchSomething){ decodeExceptionPort.code.assignDontCare() - decodeExceptionPort.badAddr := join.pc(31 downto 2) @@ "00" + decodeExceptionPort.badAddr := join.pc(31 downto 2) @@ U"00" if(catchAccessFault) when(join.valid && join.rsp.error){ decodeExceptionPort.code := 1 diff --git a/src/main/scala/vexriscv/plugin/Misc.scala b/src/main/scala/vexriscv/plugin/Misc.scala index b8ddd8e..8f68e4e 100644 --- a/src/main/scala/vexriscv/plugin/Misc.scala +++ b/src/main/scala/vexriscv/plugin/Misc.scala @@ -50,7 +50,7 @@ object RvcDecompressor{ ret := (i(11 downto 7) === 2) ? addi16sp | lui } is(12){ - val isImmediate = i(11 downto 10) =/= "11" + val isImmediate = i(11 downto 10) =/= B"11" val isShift = !i(11) val func3 = i(11 downto 10).mux( 0 -> B"101", @@ -64,7 +64,7 @@ object RvcDecompressor{ ) ) val msbs = Mux( - sel = i(11 downto 10) === "10", + sel = i(11 downto 10) === B"10", whenTrue = B((6 downto 0) -> i(12)), //andi whenFalse = B"0" ## (i(11 downto 10) === B"01" || (i(11 downto 10) === B"11" && i(6 downto 5) === B"00")) ## B"00000" ) diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index 6820f8e..eafa4da 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -167,7 +167,7 @@ class MulDivIterativePlugin(genMul : Boolean = true, } if(dhrystoneOpt) { - execute.insert(FAST_DIV_VALID) := execute.input(IS_DIV) && execute.input(INSTRUCTION)(13 downto 12) === "00" && !execute.input(RS1).msb && !execute.input(RS2).msb && execute.input(RS1).asUInt < 16 && execute.input(RS2).asUInt < 16 && execute.input(RS2) =/= 0 + execute.insert(FAST_DIV_VALID) := execute.input(IS_DIV) && execute.input(INSTRUCTION)(13 downto 12) === B"00" && !execute.input(RS1).msb && !execute.input(RS2).msb && execute.input(RS1).asUInt < 16 && execute.input(RS2).asUInt < 16 && execute.input(RS2) =/= 0 execute.insert(FAST_DIV_VALUE) := (0 to 15).flatMap(n => (0 to 15).map(d => U(if (d == 0) 0 else n / d, 4 bits))).read(U(execute.input(RS1)(3 downto 0)) @@ U(execute.input(RS2)(3 downto 0))) //(U(execute.input(RS1)(3 downto 0)) / U(execute.input(RS2)(3 downto 0)) when(execute.input(FAST_DIV_VALID)) { execute.output(IS_DIV) := False From 3d34d754a9b5adc2e173eb12e79da9cb11c74abd Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 15 Feb 2020 10:10:04 +0100 Subject: [PATCH 06/51] Remove usages of implicit string to B/U/S --- src/main/scala/vexriscv/ip/DataCache.scala | 6 +++--- src/main/scala/vexriscv/plugin/BranchPlugin.scala | 6 +++--- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 10 +++++----- src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala | 2 +- src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala | 6 +++--- src/main/scala/vexriscv/plugin/Misc.scala | 4 ++-- .../scala/vexriscv/plugin/MulDivIterativePlugin.scala | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index 838489d..eaed1d0 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -259,7 +259,7 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave val cmdBridge = Stream (DataCacheMemCmd(p)) val isBurst = cmdBridge.length =/= 0 cmdBridge.valid := cmd.valid - cmdBridge.address := (isBurst ? (cmd.address(31 downto widthOf(counter) + 2) @@ counter @@ "00") | (cmd.address(31 downto 2) @@ "00")) + cmdBridge.address := (isBurst ? (cmd.address(31 downto widthOf(counter) + 2) @@ counter @@ U"00") | (cmd.address(31 downto 2) @@ U"00")) cmdBridge.wr := cmd.wr cmdBridge.mask := cmd.mask cmdBridge.data := cmd.data @@ -278,8 +278,8 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave bus.ADR := cmdBridge.address >> 2 bus.CTI := Mux(isBurst, cmdBridge.last ? B"111" | B"010", B"000") - bus.BTE := "00" - bus.SEL := cmdBridge.wr ? cmdBridge.mask | "1111" + bus.BTE := B"00" + bus.SEL := cmdBridge.wr ? cmdBridge.mask | B"1111" bus.WE := cmdBridge.wr bus.DAT_MOSI := cmdBridge.data diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index 77f72b8..e90a1fc 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -197,7 +197,7 @@ class BranchPlugin(earlyBranch : Boolean, ).asUInt val branchAdder = branch_src1 + branch_src2 - insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0" + insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ U"0" } //Apply branchs (JAL,JALR, Bxx) @@ -274,7 +274,7 @@ class BranchPlugin(earlyBranch : Boolean, } } val branchAdder = branch_src1 + branch_src2 - insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0" + insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ U"0" } @@ -341,7 +341,7 @@ class BranchPlugin(earlyBranch : Boolean, ).asUInt val branchAdder = branch_src1 + input(BRANCH_SRC2) - insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0" + insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ U"0" insert(NEXT_PC) := input(PC) + (if(pipeline(RVC_GEN)) ((input(IS_RVC)) ? U(2) | U(4)) else 4) insert(TARGET_MISSMATCH) := decode.input(PC) =/= input(BRANCH_CALC) } diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 8759df5..98dfbaa 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -775,8 +775,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep var privilegs = if (supervisorGen) List(1, 3) else List(3) val targetPrivilege = if(pipelinedInterrupt) Reg(UInt(2 bits)) else UInt(2 bits).assignDontCare() val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]() - if (supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01") - privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11") + if (supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === U"01") || privilege < U"01") + privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < U"11") while (privilegs.nonEmpty) { val p = privilegs.head when(privilegeAllowInterrupts(p)) { @@ -844,7 +844,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep fetcher.haltIt() //Avoid having the fetch confused by the incomming privilege switch jumpInterface.valid := True - jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") ) + jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ U"00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ U"00") | ((xtvec.base + trapCause) @@ U"00") ) lastStage.arbitration.flushNext := True if(privilegeGen) privilegeReg := targetPrivilege @@ -917,8 +917,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep val imm = IMM(input(INSTRUCTION)) insert(CSR_WRITE_OPCODE) := ! ( - (input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0) - || (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0) + (input(INSTRUCTION)(14 downto 13) === B"01" && input(INSTRUCTION)(rs1Range) === 0) + || (input(INSTRUCTION)(14 downto 13) === B"11" && imm.z === 0) ) insert(CSR_READ_OPCODE) := input(INSTRUCTION)(13 downto 7) =/= B"0100000" } diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index a7b2194..8ef10b2 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -211,7 +211,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, if (catchSomething) { decodeExceptionPort.valid := False decodeExceptionPort.code.assignDontCare() - decodeExceptionPort.badAddr := cacheRsp.pc(31 downto 2) @@ "00" + decodeExceptionPort.badAddr := cacheRsp.pc(31 downto 2) @@ U"00" } when(cacheRsp.isValid && cacheRsp.mmuRefilling && !issueDetected) { diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index fa74f6c..7936f17 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -316,7 +316,7 @@ class IBusSimplePlugin( resetVector : BigInt, mmuBus.cmd.bypassTranslation := False mmuBus.end := cmdForkStage.output.fire || fetcherflushIt - cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00" + cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ U"00" //do not emit memory request if MMU miss when(mmuBus.rsp.exception || mmuBus.rsp.refilling){ @@ -333,7 +333,7 @@ class IBusSimplePlugin( resetVector : BigInt, } val mmuLess = (mmuBus == null) generate new Area{ - cmd.pc := cmdForkStage.input.payload(31 downto 2) @@ "00" + cmd.pc := cmdForkStage.input.payload(31 downto 2) @@ U"00" } val rspJoin = new Area { @@ -389,7 +389,7 @@ class IBusSimplePlugin( resetVector : BigInt, if(catchSomething){ decodeExceptionPort.code.assignDontCare() - decodeExceptionPort.badAddr := join.pc(31 downto 2) @@ "00" + decodeExceptionPort.badAddr := join.pc(31 downto 2) @@ U"00" if(catchAccessFault) when(join.valid && join.rsp.error){ decodeExceptionPort.code := 1 diff --git a/src/main/scala/vexriscv/plugin/Misc.scala b/src/main/scala/vexriscv/plugin/Misc.scala index b8ddd8e..8f68e4e 100644 --- a/src/main/scala/vexriscv/plugin/Misc.scala +++ b/src/main/scala/vexriscv/plugin/Misc.scala @@ -50,7 +50,7 @@ object RvcDecompressor{ ret := (i(11 downto 7) === 2) ? addi16sp | lui } is(12){ - val isImmediate = i(11 downto 10) =/= "11" + val isImmediate = i(11 downto 10) =/= B"11" val isShift = !i(11) val func3 = i(11 downto 10).mux( 0 -> B"101", @@ -64,7 +64,7 @@ object RvcDecompressor{ ) ) val msbs = Mux( - sel = i(11 downto 10) === "10", + sel = i(11 downto 10) === B"10", whenTrue = B((6 downto 0) -> i(12)), //andi whenFalse = B"0" ## (i(11 downto 10) === B"01" || (i(11 downto 10) === B"11" && i(6 downto 5) === B"00")) ## B"00000" ) diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index 6820f8e..eafa4da 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -167,7 +167,7 @@ class MulDivIterativePlugin(genMul : Boolean = true, } if(dhrystoneOpt) { - execute.insert(FAST_DIV_VALID) := execute.input(IS_DIV) && execute.input(INSTRUCTION)(13 downto 12) === "00" && !execute.input(RS1).msb && !execute.input(RS2).msb && execute.input(RS1).asUInt < 16 && execute.input(RS2).asUInt < 16 && execute.input(RS2) =/= 0 + execute.insert(FAST_DIV_VALID) := execute.input(IS_DIV) && execute.input(INSTRUCTION)(13 downto 12) === B"00" && !execute.input(RS1).msb && !execute.input(RS2).msb && execute.input(RS1).asUInt < 16 && execute.input(RS2).asUInt < 16 && execute.input(RS2) =/= 0 execute.insert(FAST_DIV_VALUE) := (0 to 15).flatMap(n => (0 to 15).map(d => U(if (d == 0) 0 else n / d, 4 bits))).read(U(execute.input(RS1)(3 downto 0)) @@ U(execute.input(RS2)(3 downto 0))) //(U(execute.input(RS1)(3 downto 0)) / U(execute.input(RS2)(3 downto 0)) when(execute.input(FAST_DIV_VALID)) { execute.output(IS_DIV) := False From 29f85a7ae2d50b349ae527acecd7439b8afc0ba5 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 16 Feb 2020 18:44:10 +0100 Subject: [PATCH 07/51] Remove INSTRUCTION_READY Add proper Fetcher.ibusRsp.flush prediction are disabled yet much is broken for sure, WIP --- src/main/scala/vexriscv/VexRiscv.scala | 1 - .../vexriscv/plugin/DecoderSimplePlugin.scala | 2 +- src/main/scala/vexriscv/plugin/Fetcher.scala | 478 +++++++++--------- .../vexriscv/plugin/IBusCachedPlugin.scala | 11 +- .../vexriscv/plugin/IBusSimplePlugin.scala | 1 + 5 files changed, 237 insertions(+), 256 deletions(-) diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala index 1e38791..3350dc9 100644 --- a/src/main/scala/vexriscv/VexRiscv.scala +++ b/src/main/scala/vexriscv/VexRiscv.scala @@ -36,7 +36,6 @@ case class VexRiscvConfig(){ object PC extends Stageable(UInt(32 bits)) object PC_CALC_WITHOUT_JUMP extends Stageable(UInt(32 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/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala index a1076e7..e88a98c 100644 --- a/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala @@ -172,7 +172,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, } if(catchIllegalInstruction){ - 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.valid := arbitration.isValid && !input(LEGAL_INSTRUCTION) // ?? HalitIt to alow decoder stage to wait valid data from 2 stages cache cache ?? decodeExceptionPort.code := 2 decodeExceptionPort.badAddr := input(INSTRUCTION).asUInt } diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 8aa351e..1fefe1a 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -67,29 +67,42 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pipeline(RVC_GEN) = compressedGen - prediction match { - case NONE => - case STATIC | DYNAMIC => { - predictionJumpInterface = createJumpInterface(pipeline.decode) - decodePrediction = pipeline.service(classOf[PredictionInterface]).askDecodePrediction() - } - case DYNAMIC_TARGET => { - fetchPrediction = pipeline.service(classOf[PredictionInterface]).askFetchPrediction() - if(compressedGen && cmdToRspStageCount > 1){ - dynamicTargetFailureCorrection = createJumpInterface(pipeline.decode) - } - } - } +// prediction match { +// case NONE => +// case STATIC | DYNAMIC => { +// predictionJumpInterface = createJumpInterface(pipeline.decode) +// decodePrediction = pipeline.service(classOf[PredictionInterface]).askDecodePrediction() +// } +// case DYNAMIC_TARGET => { +// fetchPrediction = pipeline.service(classOf[PredictionInterface]).askFetchPrediction() +// if(compressedGen && cmdToRspStageCount > 1){ +// dynamicTargetFailureCorrection = createJumpInterface(pipeline.decode) +// } +// } +// } pcValids = Vec(Bool, pipeline.stages.size) } + object IBUS_RSP + object DECOMPRESSOR + object INJECTOR_M2S + + def isDrivingDecode(s : Any): Boolean = { + if(injectorStage) return s == INJECTOR_M2S + if(compressedGen) return s == DECOMPRESSOR + s == IBUS_RSP + } + + def getFlushAt(s : Any, lastCond : Boolean = true): Bool = { + if(isDrivingDecode(s) && lastCond) pipeline.decode.arbitration.isRemoved else fetcherflushIt + } class FetchArea(pipeline : VexRiscv) extends Area { import pipeline._ import pipeline.config._ - //JumpService hardware implementation + //Arbitrate jump requests into pcLoad val jump = new Area { val sortedByStage = jumpInfos.sortWith((a, b) => { (pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage)) || @@ -117,25 +130,25 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val booted = RegNext(True) init (False) val inc = RegInit(False) clearWhen(corrected || pcRegPropagate) setWhen(output.fire) clearWhen(!output.valid && output.ready) val pc = pcReg + (inc ## B"00").asUInt - val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) +// val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) if(compressedGen) when(inc) { pc(1) := False } - if(predictionPcLoad != null) { - when(predictionPcLoad.valid) { - corrected := True - pc := predictionPcLoad.payload - } - } +// if(predictionPcLoad != null) { +// when(predictionPcLoad.valid) { +// corrected := True +// pc := predictionPcLoad.payload +// } +// } when(jump.pcLoad.valid) { corrected := True pc := jump.pcLoad.payload } - when(booted && (output.ready || fetcherflushIt || pcRegPropagate)){ + when(booted && (output.ready || corrected || pcRegPropagate)){ pcReg := pc } @@ -160,12 +173,12 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pcReg := pcPlus } - val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) - if(prediction == DYNAMIC_TARGET) { - when(predictionPcLoad.valid) { - pcReg := predictionPcLoad.payload - } - } +// val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) +// if(prediction == DYNAMIC_TARGET) { +// when(predictionPcLoad.valid) { +// pcReg := predictionPcLoad.payload +// } +// } //application of the selected jump request when(jump.pcLoad.valid && (!decode.arbitration.isStuck || decode.arbitration.isRemoved)) { @@ -177,27 +190,18 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, case class FetchRsp() extends Bundle { val pc = UInt(32 bits) val rsp = IBusSimpleRsp() - val isRvc = Bool + val isRvc = Bool() } val iBusRsp = new Area { -// val input = Stream(UInt(32 bits)) -// val inputPipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount) -// val inputPipelineHalt = Vec(False, cmdToRspStageCount-1) -// for(i <- 0 until cmdToRspStageCount) { -// inputPipeline(i) << {i match { -// case 0 => input.m2sPipeWithFlush(flush, false, collapsBubble = false) -// case _ => inputPipeline(i-1).haltWhen(inputPipelineHalt(i-1)).m2sPipeWithFlush(flush,collapsBubble = false) -// }} -// } - -// val stages = Array.fill(cmdToRspStageCount)(Stream(UInt(32 bits))) + val fetchFlush = False val stages = Array.fill(cmdToRspStageCount + 1)(new Bundle { val input = Stream(UInt(32 bits)) val output = Stream(UInt(32 bits)) - val halt = Bool - val inputSample = Bool + val halt = Bool() + val inputSample = Bool() + val flush = Bool() }) stages(0).input << fetchPc.output @@ -207,29 +211,18 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, s.output << s.input.haltWhen(s.halt) } + stages.head.flush := getFlushAt(IBUS_RSP, stages.head == stages.last) || fetchFlush for((s,sNext) <- (stages, stages.tail).zipped) { + sNext.flush := getFlushAt(IBUS_RSP, sNext == stages.last) || fetchFlush if(s == stages.head && pcRegReusedForSecondStage) { - sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(fetcherflushIt, s != stages.head, collapsBubble = false)) + sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(sNext.flush, s != stages.head, collapsBubble = false)) sNext.input.payload := fetchPc.pcReg fetchPc.pcRegPropagate setWhen(sNext.input.ready) } else { - sNext.input << s.output.m2sPipeWithFlush(fetcherflushIt, s != stages.head, collapsBubble = false) + sNext.input << s.output.m2sPipeWithFlush(sNext.flush, s != stages.head, collapsBubble = false) } } -// -// val pipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount + 1) -// val halts = Vec(False, cmdToRspStageCount) -// for(i <- 0 until cmdToRspStageCount + 1) { -// pipeline(i) << {i match { -// case 0 => pipeline(0) << fetchPc.output.haltWhen(halts(i)) -// case 1 => pipeline(1).m2sPipeWithFlush(flush, false, collapsBubble = false) -// case _ => inputPipeline(i-1).haltWhen(inputPipelineHalt(i-1)).m2sPipeWithFlush(flush,collapsBubble = false) -// }} -// } - - // ... - val readyForError = True val output = Stream(FetchRsp()) incomingInstruction setWhen(stages.tail.map(_.input.valid).reduce(_ || _)) @@ -253,7 +246,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, output.pc := input.pc output.isRvc := isRvc output.rsp.inst := isRvc ? decompressed | raw -// input.ready := (bufferValid ? (!isRvc && output.ready) | (input.pc(1) || output.ready)) input.ready := !output.valid || !(!output.ready || (isRvc && !input.pc(1) && input.rsp.inst(16, 2 bits) =/= 3) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3)) addPrePopTask(() => { when(!input.ready && output.fire && !fetcherflushIt /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) { @@ -286,7 +278,8 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, incomingInstruction setWhen (inputBeforeStage.valid) } val decodeInput = (if (injectorStage) { - val decodeInput = inputBeforeStage.m2sPipeWithFlush(fetcherflushIt, collapsBubble = false) + val flushStage = getFlushAt(INJECTOR_M2S) + val decodeInput = inputBeforeStage.m2sPipeWithFlush(flushStage, collapsBubble = false) decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst) iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer incomingInstruction setWhen (decodeInput.valid) @@ -323,13 +316,10 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pcValids := Vec(valids.takeRight(stages.size)) } - val decodeRemoved = RegInit(False) setWhen(decode.arbitration.isRemoved) clearWhen(fetcherflushIt) //!decode.arbitration.isStuck || decode.arbitration.isFlushed - decodeInput.ready := !decode.arbitration.isStuck - decode.arbitration.isValid := decodeInput.valid && !decodeRemoved + decode.arbitration.isValid := decodeInput.valid decode.insert(PC) := (if (decodePcGen) decodePc.pcReg else decodeInput.pc) decode.insert(INSTRUCTION) := decodeInput.rsp.inst - decode.insert(INSTRUCTION_READY) := True if (compressedGen) decode.insert(IS_RVC) := decodeInput.isRvc if (injectionPort != null) { @@ -401,11 +391,11 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, else decode.input(PC) + 4) - if(decodePc != null && decodePc.predictionPcLoad != null){ - when(decodePc.predictionPcLoad.valid){ - decode.insert(FORMAL_PC_NEXT) := decodePc.predictionPcLoad.payload - } - } +// if(decodePc != null && decodePc.predictionPcLoad != null){ +// when(decodePc.predictionPcLoad.valid){ +// decode.insert(FORMAL_PC_NEXT) := decodePc.predictionPcLoad.payload +// } +// } jumpInfos.foreach(info => { when(info.interface.valid) { @@ -429,182 +419,182 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, (ifGen(compressedGen)(decompressorContext), injectorContextWire) } - val predictor = prediction match { - case NONE => - case STATIC | DYNAMIC => { - def historyWidth = 2 - val dynamic = ifGen(prediction == DYNAMIC) (new Area { - case class BranchPredictorLine() extends Bundle{ - val history = SInt(historyWidth bits) - } - - val historyCache = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) - val historyWrite = historyCache.writePort - val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) - val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(0).input.payload >> 2).resized - - case class DynamicContext() extends Bundle{ - val hazard = Bool - val line = BranchPredictorLine() - } - val fetchContext = DynamicContext() - fetchContext.hazard := hazard - fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) - - object PREDICTION_CONTEXT extends Stageable(DynamicContext()) - decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2 - val decodeContextPrediction = decode.input(PREDICTION_CONTEXT).line.history.msb - - val branchStage = decodePrediction.stage - val branchContext = branchStage.input(PREDICTION_CONTEXT) - val moreJump = decodePrediction.rsp.wasWrong ^ branchContext.line.history.msb - - historyWrite.address := branchStage.input(PC)(2, historyRamSizeLog2 bits) + (if(pipeline(RVC_GEN)) - ((!branchStage.input(IS_RVC) && branchStage.input(PC)(1)) ? U(1) | U(0)) - else - U(0)) - - historyWrite.data.history := branchContext.line.history + (moreJump ? S(-1) | S(1)) - val sat = (branchContext.line.history === (moreJump ? S(branchContext.line.history.minValue) | S(branchContext.line.history.maxValue))) - historyWrite.valid := !branchContext.hazard && branchStage.arbitration.isFiring && branchStage.input(BRANCH_CTRL) === BranchCtrlEnum.B && !sat - }) - - - val imm = IMM(decode.input(INSTRUCTION)) - - val conditionalBranchPrediction = prediction match { - case STATIC => imm.b_sext.msb - case DYNAMIC => dynamic.decodeContextPrediction - } - - decodePrediction.cmd.hadBranch := decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (decode.input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction) - - val noPredictionOnMissaligned = (!pipeline(RVC_GEN)) generate new Area{ - val missaligned = decode.input(BRANCH_CTRL).mux( - BranchCtrlEnum.JAL -> imm.j_sext(1), - default -> imm.b_sext(1) - ) - decodePrediction.cmd.hadBranch clearWhen(missaligned) - } - - //TODO no more fireing depedancies - predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch //TODO OH Doublon de priorité - predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt - if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) - - when(predictionJumpInterface.valid && decode.arbitration.isFiring){ - flushIt() - } - } - case DYNAMIC_TARGET => new Area{ -// assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air") - - case class BranchPredictorLine() extends Bundle{ - val source = Bits(30 - historyRamSizeLog2 bits) - val branchWish = UInt(2 bits) - val target = UInt(32 bits) - val unaligned = ifGen(compressedGen)(Bool) - } - - val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) - val historyWrite = history.writePort - - val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) - val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True) - - //Avoid stoping instruction fetch in the middle patch - if(compressedGen && cmdToRspStageCount == 1){ - hit clearWhen(!decompressor.output.valid) - } - - //Avoid write to read hazard - val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) - val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized - //TODO improve predictionPcLoad way of doing things - fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.valid //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1)) - fetchPc.predictionPcLoad.payload := line.target - - case class PredictionResult() extends Bundle{ - val hazard = Bool - val hit = Bool - val line = BranchPredictorLine() - } - - val fetchContext = PredictionResult() - fetchContext.hazard := hazard - fetchContext.hit := hit - fetchContext.line := line - - val (decompressorContext, injectorContext) = stage1ToInjectorPipe(fetchContext) - if(compressedGen) { - //prediction hit on the right instruction into words - decompressorContext.hit clearWhen(decompressorContext.line.unaligned && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.input.pc(1)))) - - // if(compressedGen) injectorContext.hit clearWhen(decodePc.pcReg(1) =/= injectorContext.line.unaligned) - - decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire - decodePc.predictionPcLoad.payload := injectorContext.line.target - - - when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){ - decompressor.bufferValid := False - decompressor.input.ready := True - } - } - - object PREDICTION_CONTEXT extends Stageable(PredictionResult()) - pipeline.decode.insert(PREDICTION_CONTEXT) := injectorContext - val branchStage = fetchPrediction.stage - val branchContext = branchStage.input(PREDICTION_CONTEXT) - - fetchPrediction.cmd.hadBranch := branchContext.hit && !branchContext.hazard && branchContext.line.branchWish.msb - fetchPrediction.cmd.targetPc := branchContext.line.target - - - historyWrite.valid := False - historyWrite.address := fetchPrediction.rsp.sourceLastWord(2, historyRamSizeLog2 bits) - historyWrite.data.source := fetchPrediction.rsp.sourceLastWord.asBits >> 2 + historyRamSizeLog2 - historyWrite.data.target := fetchPrediction.rsp.finalPc - if(compressedGen) historyWrite.data.unaligned := !fetchPrediction.stage.input(PC)(1) ^ fetchPrediction.stage.input(IS_RVC) - - when(fetchPrediction.rsp.wasRight) { - historyWrite.valid := branchContext.hit - historyWrite.data.branchWish := branchContext.line.branchWish + (branchContext.line.branchWish === 2).asUInt - (branchContext.line.branchWish === 1).asUInt - } otherwise { - when(branchContext.hit) { - historyWrite.valid := True - historyWrite.data.branchWish := branchContext.line.branchWish - (branchContext.line.branchWish.msb).asUInt + (!branchContext.line.branchWish.msb).asUInt - } otherwise { - historyWrite.valid := True - historyWrite.data.branchWish := "10" - } - } - - historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring) - - - - val predictionFailure = ifGen(compressedGen && cmdToRspStageCount > 1)(new Area{ - val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) - val unalignedWordIssue = decompressor.bufferFill && decompressor.input.rsp.inst(17 downto 16) === 3 && predictionBranch - val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt) - val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) - val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid - - dynamicTargetFailureCorrection.valid := False - dynamicTargetFailureCorrection.payload := decode.input(PC) - when(injectorFailure || bypassFailure){ - historyWrite.valid := True - historyWrite.address := (decode.input(PC) >> 2).resized - historyWrite.data.branchWish := 0 - - decode.arbitration.isValid := False - decode.arbitration.flushNext := True - dynamicTargetFailureCorrection.valid := True - } - }) - } - } +// val predictor = prediction match { +// case NONE => +// case STATIC | DYNAMIC => { +// def historyWidth = 2 +// val dynamic = ifGen(prediction == DYNAMIC) (new Area { +// case class BranchPredictorLine() extends Bundle{ +// val history = SInt(historyWidth bits) +// } +// +// val historyCache = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) +// val historyWrite = historyCache.writePort +// val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) +// val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(0).input.payload >> 2).resized +// +// case class DynamicContext() extends Bundle{ +// val hazard = Bool +// val line = BranchPredictorLine() +// } +// val fetchContext = DynamicContext() +// fetchContext.hazard := hazard +// fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) +// +// object PREDICTION_CONTEXT extends Stageable(DynamicContext()) +// decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2 +// val decodeContextPrediction = decode.input(PREDICTION_CONTEXT).line.history.msb +// +// val branchStage = decodePrediction.stage +// val branchContext = branchStage.input(PREDICTION_CONTEXT) +// val moreJump = decodePrediction.rsp.wasWrong ^ branchContext.line.history.msb +// +// historyWrite.address := branchStage.input(PC)(2, historyRamSizeLog2 bits) + (if(pipeline(RVC_GEN)) +// ((!branchStage.input(IS_RVC) && branchStage.input(PC)(1)) ? U(1) | U(0)) +// else +// U(0)) +// +// historyWrite.data.history := branchContext.line.history + (moreJump ? S(-1) | S(1)) +// val sat = (branchContext.line.history === (moreJump ? S(branchContext.line.history.minValue) | S(branchContext.line.history.maxValue))) +// historyWrite.valid := !branchContext.hazard && branchStage.arbitration.isFiring && branchStage.input(BRANCH_CTRL) === BranchCtrlEnum.B && !sat +// }) +// +// +// val imm = IMM(decode.input(INSTRUCTION)) +// +// val conditionalBranchPrediction = prediction match { +// case STATIC => imm.b_sext.msb +// case DYNAMIC => dynamic.decodeContextPrediction +// } +// +// decodePrediction.cmd.hadBranch := decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (decode.input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction) +// +// val noPredictionOnMissaligned = (!pipeline(RVC_GEN)) generate new Area{ +// val missaligned = decode.input(BRANCH_CTRL).mux( +// BranchCtrlEnum.JAL -> imm.j_sext(1), +// default -> imm.b_sext(1) +// ) +// decodePrediction.cmd.hadBranch clearWhen(missaligned) +// } +// +// //TODO no more fireing depedancies +// predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch //TODO OH Doublon de priorité +// predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt +// if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) +// +// when(predictionJumpInterface.valid && decode.arbitration.isFiring){ +// flushIt() +// } +// } +// case DYNAMIC_TARGET => new Area{ +//// assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air") +// +// case class BranchPredictorLine() extends Bundle{ +// val source = Bits(30 - historyRamSizeLog2 bits) +// val branchWish = UInt(2 bits) +// val target = UInt(32 bits) +// val unaligned = ifGen(compressedGen)(Bool) +// } +// +// val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) +// val historyWrite = history.writePort +// +// val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) +// val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True) +// +// //Avoid stoping instruction fetch in the middle patch +// if(compressedGen && cmdToRspStageCount == 1){ +// hit clearWhen(!decompressor.output.valid) +// } +// +// //Avoid write to read hazard +// val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) +// val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized +// //TODO improve predictionPcLoad way of doing things +// fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.valid //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1)) +// fetchPc.predictionPcLoad.payload := line.target +// +// case class PredictionResult() extends Bundle{ +// val hazard = Bool +// val hit = Bool +// val line = BranchPredictorLine() +// } +// +// val fetchContext = PredictionResult() +// fetchContext.hazard := hazard +// fetchContext.hit := hit +// fetchContext.line := line +// +// val (decompressorContext, injectorContext) = stage1ToInjectorPipe(fetchContext) +// if(compressedGen) { +// //prediction hit on the right instruction into words +// decompressorContext.hit clearWhen(decompressorContext.line.unaligned && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.input.pc(1)))) +// +// // if(compressedGen) injectorContext.hit clearWhen(decodePc.pcReg(1) =/= injectorContext.line.unaligned) +// +// decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire +// decodePc.predictionPcLoad.payload := injectorContext.line.target +// +// +// when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){ +// decompressor.bufferValid := False +// decompressor.input.ready := True +// } +// } +// +// object PREDICTION_CONTEXT extends Stageable(PredictionResult()) +// pipeline.decode.insert(PREDICTION_CONTEXT) := injectorContext +// val branchStage = fetchPrediction.stage +// val branchContext = branchStage.input(PREDICTION_CONTEXT) +// +// fetchPrediction.cmd.hadBranch := branchContext.hit && !branchContext.hazard && branchContext.line.branchWish.msb +// fetchPrediction.cmd.targetPc := branchContext.line.target +// +// +// historyWrite.valid := False +// historyWrite.address := fetchPrediction.rsp.sourceLastWord(2, historyRamSizeLog2 bits) +// historyWrite.data.source := fetchPrediction.rsp.sourceLastWord.asBits >> 2 + historyRamSizeLog2 +// historyWrite.data.target := fetchPrediction.rsp.finalPc +// if(compressedGen) historyWrite.data.unaligned := !fetchPrediction.stage.input(PC)(1) ^ fetchPrediction.stage.input(IS_RVC) +// +// when(fetchPrediction.rsp.wasRight) { +// historyWrite.valid := branchContext.hit +// historyWrite.data.branchWish := branchContext.line.branchWish + (branchContext.line.branchWish === 2).asUInt - (branchContext.line.branchWish === 1).asUInt +// } otherwise { +// when(branchContext.hit) { +// historyWrite.valid := True +// historyWrite.data.branchWish := branchContext.line.branchWish - (branchContext.line.branchWish.msb).asUInt + (!branchContext.line.branchWish.msb).asUInt +// } otherwise { +// historyWrite.valid := True +// historyWrite.data.branchWish := "10" +// } +// } +// +// historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring) +// +// +// +// val predictionFailure = ifGen(compressedGen && cmdToRspStageCount > 1)(new Area{ +// val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) +// val unalignedWordIssue = decompressor.bufferFill && decompressor.input.rsp.inst(17 downto 16) === 3 && predictionBranch +// val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt) +// val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) +// val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid +// +// dynamicTargetFailureCorrection.valid := False +// dynamicTargetFailureCorrection.payload := decode.input(PC) +// when(injectorFailure || bypassFailure){ +// historyWrite.valid := True +// historyWrite.address := (decode.input(PC) >> 2).resized +// historyWrite.data.branchWish := 0 +// +// decode.arbitration.isValid := False +// decode.arbitration.flushNext := True +// dynamicTargetFailureCorrection.valid := True +// } +// }) +// } +// } def stageXToIBusRsp[T <: Data](stage : Any, input : T): (T) ={ iBusRsp.stages.dropWhile(_ != stage).tail.foldLeft(input)((data,stage) => RegNextWhen(data, stage.output.ready)) diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index a7b2194..953ef24 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -237,19 +237,10 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, decodeExceptionPort.code := 1 } - when(!iBusRsp.readyForError){ - redoFetch := False - cache.io.cpu.fill.valid := False - } -// when(pipeline.stages.map(_.arbitration.flushIt).orR){ -// cache.io.cpu.fill.valid := False -// } - - redoBranch.valid := redoFetch redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc) - decode.arbitration.flushNext setWhen(redoBranch.valid) + iBusRsp.fetchFlush setWhen(redoBranch.valid) cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt) diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index fa74f6c..c866a4a 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -384,6 +384,7 @@ class IBusSimplePlugin( resetVector : BigInt, decode.arbitration.flushIt setWhen(redoBranch.valid) decode.arbitration.flushNext setWhen(redoBranch.valid) + ??? } From 8be50b8e3d3c7f3f049ba3d3e10ce1021c5713a4 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 17 Feb 2020 12:50:12 +0100 Subject: [PATCH 08/51] IBusFetcher now support proper iBusRsp.redo/flush --- src/main/scala/vexriscv/demo/Linux.scala | 4 ++-- src/main/scala/vexriscv/plugin/Fetcher.scala | 14 ++++++++++---- .../scala/vexriscv/plugin/IBusCachedPlugin.scala | 12 +++++------- .../scala/vexriscv/plugin/IBusSimplePlugin.scala | 14 +++++--------- src/test/scala/vexriscv/DhrystoneBench.scala | 4 ++-- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/main/scala/vexriscv/demo/Linux.scala b/src/main/scala/vexriscv/demo/Linux.scala index 906b5b2..c13ef12 100644 --- a/src/main/scala/vexriscv/demo/Linux.scala +++ b/src/main/scala/vexriscv/demo/Linux.scala @@ -272,7 +272,7 @@ object LinuxGen { // wfiGenAsNop = true, // ucycleAccess = CsrAccess.NONE // )), -// new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), + new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new BranchPlugin( earlyBranch = false, catchAddressMisaligned = true, @@ -310,7 +310,7 @@ object LinuxGen { // } // } - SpinalConfig(mergeAsyncProcess = true, anonymSignalPrefix = "_zz").generateVerilog { + SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "_zz").generateVerilog { val toplevel = new VexRiscv(configFull( diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 1fefe1a..79b8b07 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -21,7 +21,8 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val prediction : BranchPrediction, val historyRamSizeLog2 : Int, val injectorStage : Boolean, - val relaxPredictorAddress : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{ + val relaxPredictorAddress : Boolean, + val fetchRedoGen : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{ var prefetchExceptionPort : Flow[ExceptionCause] = null var decodePrediction : DecodePredictionBus = null var fetchPrediction : FetchPredictionBus = null @@ -131,11 +132,16 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val inc = RegInit(False) clearWhen(corrected || pcRegPropagate) setWhen(output.fire) clearWhen(!output.valid && output.ready) val pc = pcReg + (inc ## B"00").asUInt // val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) + val redo = fetchRedoGen generate Flow(UInt(32 bits)) if(compressedGen) when(inc) { pc(1) := False } + if(fetchRedoGen) when(redo.valid){ + corrected := True + pc := redo.payload + } // if(predictionPcLoad != null) { // when(predictionPcLoad.valid) { // corrected := True @@ -147,7 +153,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pc := jump.pcLoad.payload } - when(booted && (output.ready || corrected || pcRegPropagate)){ pcReg := pc } @@ -231,6 +236,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val decompressor = ifGen(decodePcGen)(new Area{ def input = iBusRsp.output val output = Stream(FetchRsp()) + val flush = getFlushAt(DECOMPRESSOR) val bufferValid = RegInit(False) val bufferData = Reg(Bits(16 bits)) @@ -248,7 +254,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, output.rsp.inst := isRvc ? decompressed | raw input.ready := !output.valid || !(!output.ready || (isRvc && !input.pc(1) && input.rsp.inst(16, 2 bits) =/= 3) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3)) addPrePopTask(() => { - when(!input.ready && output.fire && !fetcherflushIt /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) { + when(!input.ready && output.fire && !flush /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) { input.pc.getDrivingReg(1) := True } }) @@ -264,7 +270,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } bufferData := input.rsp.inst(31 downto 16) } - bufferValid.clearWhen(fetcherflushIt) + bufferValid.clearWhen(flush) iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3) }) diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 06ffa0a..537cb0f 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -46,7 +46,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, prediction = prediction, historyRamSizeLog2 = historyRamSizeLog2, injectorStage = (!config.twoCycleCache && !withoutInjectorStage) || injectorStage, - relaxPredictorAddress = relaxPredictorAddress){ + relaxPredictorAddress = relaxPredictorAddress, + fetchRedoGen = true){ import config._ assert(isPow2(cacheSize)) @@ -86,9 +87,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, FLUSH_ALL -> True )) - - redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.decode, priority = 1) //Priority 1 will win against branch predictor - if(catchSomething) { val exceptionService = pipeline.service(classOf[ExceptionService]) decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1) @@ -238,9 +236,9 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, } - redoBranch.valid := redoFetch - redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc) - iBusRsp.fetchFlush setWhen(redoBranch.valid) + fetchPc.redo.valid := redoFetch + fetchPc.redo.payload := iBusRsp.stages.last.input.payload + iBusRsp.fetchFlush setWhen(redoFetch) cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt) diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 0be4275..aa4fcb6 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -245,13 +245,13 @@ class IBusSimplePlugin( resetVector : BigInt, prediction = prediction, historyRamSizeLog2 = historyRamSizeLog2, injectorStage = injectorStage, - relaxPredictorAddress = relaxPredictorAddress){ + relaxPredictorAddress = relaxPredictorAddress, + fetchRedoGen = memoryTranslatorPortConfig != null){ var iBus : IBusSimpleBus = null var decodeExceptionPort : Flow[ExceptionCause] = null val catchSomething = memoryTranslatorPortConfig != null || catchAccessFault var mmuBus : MemoryTranslatorBus = null - var redoBranch : Flow[UInt] = null if(rspHoldValue) assert(busLatencyMin <= 1) @@ -268,7 +268,6 @@ class IBusSimplePlugin( resetVector : BigInt, if(memoryTranslatorPortConfig != null) { mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_INSTRUCTION, memoryTranslatorPortConfig) - redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.decode, priority = 1) //Priority 1 will win against branch predictor } } @@ -379,12 +378,9 @@ class IBusSimplePlugin( resetVector : BigInt, if(memoryTranslatorPortConfig != null){ redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling) - redoBranch.valid := redoRequired && iBusRsp.readyForError - redoBranch.payload := decode.input(PC) - - decode.arbitration.flushIt setWhen(redoBranch.valid) - decode.arbitration.flushNext setWhen(redoBranch.valid) - ??? + fetchPc.redo.valid := redoRequired && iBusRsp.readyForError + fetchPc.redo.payload := decode.input(PC) + iBusRsp.fetchFlush setWhen(fetchPc.redo.valid) } diff --git a/src/test/scala/vexriscv/DhrystoneBench.scala b/src/test/scala/vexriscv/DhrystoneBench.scala index 1034aed..d23c4e1 100644 --- a/src/test/scala/vexriscv/DhrystoneBench.scala +++ b/src/test/scala/vexriscv/DhrystoneBench.scala @@ -102,9 +102,9 @@ class DhrystoneBench extends FunSuite{ getDmips( name = "GenLinuxBalenced", gen = LinuxGen.main(Array.fill[String](0)("")), - testCmd = "make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes MMU=no CSR=yes CSR_SKIP_TEST=yes DEBUG_PLUGIN=no COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes REDO=10 TRACE=no COREMARK=yes LINUX_REGRESSION=no" + testCmd = "make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes MMU=no CSR=yes CSR_SKIP_TEST=yes COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes REDO=10 TRACE=no COREMARK=yes LINUX_REGRESSION=no" ) - + //make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yess SUPERVISOR=yes CSR=yes COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes REDO=1 TRACE=no LINUX_REGRESSION=yes SEED=42 test("final_report") { From 9e75e2cb58967f9142fe812dcef3968b55296e38 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 17 Feb 2020 14:36:08 +0100 Subject: [PATCH 09/51] IBusFetcher disable pcRegReusedForSecondStage when using fetch prediction. Fix some fetch flush DYNAMIC_PREDICTION start to work again --- src/main/scala/vexriscv/plugin/Fetcher.scala | 424 +++++++++--------- .../vexriscv/plugin/IBusCachedPlugin.scala | 2 +- .../vexriscv/plugin/IBusSimplePlugin.scala | 2 +- src/main/scala/vexriscv/plugin/Misc.scala | 7 +- 4 files changed, 218 insertions(+), 217 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 79b8b07..eae5461 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -16,7 +16,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val decodePcGen : Boolean, val compressedGen : Boolean, val cmdToRspStageCount : Int, - val pcRegReusedForSecondStage : Boolean, + val allowPcRegReusedForSecondStage : Boolean, val injectorReadyCutGen : Boolean, val prediction : BranchPrediction, val historyRamSizeLog2 : Int, @@ -43,7 +43,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, injectionPort = Stream(Bits(32 bits)) injectionPort } - + def pcRegReusedForSecondStage = allowPcRegReusedForSecondStage && prediction != DYNAMIC_TARGET var predictionJumpInterface : Flow[UInt] = null override def haltIt(): Unit = fetcherHalt := True @@ -68,19 +68,19 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pipeline(RVC_GEN) = compressedGen -// prediction match { -// case NONE => -// case STATIC | DYNAMIC => { -// predictionJumpInterface = createJumpInterface(pipeline.decode) -// decodePrediction = pipeline.service(classOf[PredictionInterface]).askDecodePrediction() -// } -// case DYNAMIC_TARGET => { -// fetchPrediction = pipeline.service(classOf[PredictionInterface]).askFetchPrediction() -// if(compressedGen && cmdToRspStageCount > 1){ -// dynamicTargetFailureCorrection = createJumpInterface(pipeline.decode) -// } -// } -// } + prediction match { + case NONE => + case STATIC | DYNAMIC => { + predictionJumpInterface = createJumpInterface(pipeline.decode) + decodePrediction = pipeline.service(classOf[PredictionInterface]).askDecodePrediction() + } + case DYNAMIC_TARGET => { + fetchPrediction = pipeline.service(classOf[PredictionInterface]).askFetchPrediction() + if(compressedGen && cmdToRspStageCount > 1){ + dynamicTargetFailureCorrection = createJumpInterface(pipeline.decode) + } + } + } pcValids = Vec(Bool, pipeline.stages.size) } @@ -131,7 +131,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val booted = RegNext(True) init (False) val inc = RegInit(False) clearWhen(corrected || pcRegPropagate) setWhen(output.fire) clearWhen(!output.valid && output.ready) val pc = pcReg + (inc ## B"00").asUInt -// val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) + val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) val redo = fetchRedoGen generate Flow(UInt(32 bits)) if(compressedGen) when(inc) { @@ -142,12 +142,12 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, corrected := True pc := redo.payload } -// if(predictionPcLoad != null) { -// when(predictionPcLoad.valid) { -// corrected := True -// pc := predictionPcLoad.payload -// } -// } + if(predictionPcLoad != null) { + when(predictionPcLoad.valid) { + corrected := True + pc := predictionPcLoad.payload + } + } when(jump.pcLoad.valid) { corrected := True pc := jump.pcLoad.payload @@ -178,12 +178,12 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pcReg := pcPlus } -// val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) -// if(prediction == DYNAMIC_TARGET) { -// when(predictionPcLoad.valid) { -// pcReg := predictionPcLoad.payload -// } -// } + val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) + if(prediction == DYNAMIC_TARGET) { + when(predictionPcLoad.valid) { + pcReg := predictionPcLoad.payload + } + } //application of the selected jump request when(jump.pcLoad.valid && (!decode.arbitration.isStuck || decode.arbitration.isRemoved)) { @@ -205,26 +205,25 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val input = Stream(UInt(32 bits)) val output = Stream(UInt(32 bits)) val halt = Bool() - val inputSample = Bool() val flush = Bool() }) stages(0).input << fetchPc.output - stages(0).inputSample := True for(s <- stages) { s.halt := False s.output << s.input.haltWhen(s.halt) } - stages.head.flush := getFlushAt(IBUS_RSP, stages.head == stages.last) || fetchFlush + stages.head.flush := False //getFlushAt(IBUS_RSP, stages.head == stages.last) || fetchFlush for((s,sNext) <- (stages, stages.tail).zipped) { + val discardInputOnFlush = s != stages.head sNext.flush := getFlushAt(IBUS_RSP, sNext == stages.last) || fetchFlush if(s == stages.head && pcRegReusedForSecondStage) { - sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(sNext.flush, s != stages.head, collapsBubble = false)) + sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(sNext.flush, false, collapsBubble = false, flushInput = s.flush)) sNext.input.payload := fetchPc.pcReg fetchPc.pcRegPropagate setWhen(sNext.input.ready) } else { - sNext.input << s.output.m2sPipeWithFlush(sNext.flush, s != stages.head, collapsBubble = false) + sNext.input << s.output.m2sPipeWithFlush(sNext.flush, false, collapsBubble = false, flushInput = s.flush) } } @@ -234,7 +233,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } val decompressor = ifGen(decodePcGen)(new Area{ - def input = iBusRsp.output + val input = iBusRsp.output.clearValidWhen(iBusRsp.stages.last.flush) val output = Stream(FetchRsp()) val flush = getFlushAt(DECOMPRESSOR) @@ -285,7 +284,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } val decodeInput = (if (injectorStage) { val flushStage = getFlushAt(INJECTOR_M2S) - val decodeInput = inputBeforeStage.m2sPipeWithFlush(flushStage, collapsBubble = false) + val decodeInput = inputBeforeStage.m2sPipeWithFlush(flushStage, false, collapsBubble = false, flushInput = fetcherflushIt) decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst) iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer incomingInstruction setWhen (decodeInput.valid) @@ -397,11 +396,11 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, else decode.input(PC) + 4) -// if(decodePc != null && decodePc.predictionPcLoad != null){ -// when(decodePc.predictionPcLoad.valid){ -// decode.insert(FORMAL_PC_NEXT) := decodePc.predictionPcLoad.payload -// } -// } + if(decodePc != null && decodePc.predictionPcLoad != null){ + when(decodePc.predictionPcLoad.valid){ + decode.insert(FORMAL_PC_NEXT) := decodePc.predictionPcLoad.payload + } + } jumpInfos.foreach(info => { when(info.interface.valid) { @@ -425,182 +424,181 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, (ifGen(compressedGen)(decompressorContext), injectorContextWire) } -// val predictor = prediction match { -// case NONE => -// case STATIC | DYNAMIC => { -// def historyWidth = 2 -// val dynamic = ifGen(prediction == DYNAMIC) (new Area { -// case class BranchPredictorLine() extends Bundle{ -// val history = SInt(historyWidth bits) -// } -// -// val historyCache = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) -// val historyWrite = historyCache.writePort -// val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) -// val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(0).input.payload >> 2).resized -// -// case class DynamicContext() extends Bundle{ -// val hazard = Bool -// val line = BranchPredictorLine() -// } -// val fetchContext = DynamicContext() -// fetchContext.hazard := hazard -// fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) -// -// object PREDICTION_CONTEXT extends Stageable(DynamicContext()) -// decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2 -// val decodeContextPrediction = decode.input(PREDICTION_CONTEXT).line.history.msb -// -// val branchStage = decodePrediction.stage -// val branchContext = branchStage.input(PREDICTION_CONTEXT) -// val moreJump = decodePrediction.rsp.wasWrong ^ branchContext.line.history.msb -// -// historyWrite.address := branchStage.input(PC)(2, historyRamSizeLog2 bits) + (if(pipeline(RVC_GEN)) -// ((!branchStage.input(IS_RVC) && branchStage.input(PC)(1)) ? U(1) | U(0)) -// else -// U(0)) -// -// historyWrite.data.history := branchContext.line.history + (moreJump ? S(-1) | S(1)) -// val sat = (branchContext.line.history === (moreJump ? S(branchContext.line.history.minValue) | S(branchContext.line.history.maxValue))) -// historyWrite.valid := !branchContext.hazard && branchStage.arbitration.isFiring && branchStage.input(BRANCH_CTRL) === BranchCtrlEnum.B && !sat -// }) -// -// -// val imm = IMM(decode.input(INSTRUCTION)) -// -// val conditionalBranchPrediction = prediction match { -// case STATIC => imm.b_sext.msb -// case DYNAMIC => dynamic.decodeContextPrediction -// } -// -// decodePrediction.cmd.hadBranch := decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (decode.input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction) -// -// val noPredictionOnMissaligned = (!pipeline(RVC_GEN)) generate new Area{ -// val missaligned = decode.input(BRANCH_CTRL).mux( -// BranchCtrlEnum.JAL -> imm.j_sext(1), -// default -> imm.b_sext(1) -// ) -// decodePrediction.cmd.hadBranch clearWhen(missaligned) -// } -// -// //TODO no more fireing depedancies -// predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch //TODO OH Doublon de priorité -// predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt -// if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) -// -// when(predictionJumpInterface.valid && decode.arbitration.isFiring){ -// flushIt() -// } -// } -// case DYNAMIC_TARGET => new Area{ -//// assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air") -// -// case class BranchPredictorLine() extends Bundle{ -// val source = Bits(30 - historyRamSizeLog2 bits) -// val branchWish = UInt(2 bits) -// val target = UInt(32 bits) -// val unaligned = ifGen(compressedGen)(Bool) -// } -// -// val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) -// val historyWrite = history.writePort -// -// val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) -// val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True) -// -// //Avoid stoping instruction fetch in the middle patch + val predictor = prediction match { + case NONE => + case STATIC | DYNAMIC => { + def historyWidth = 2 + val dynamic = ifGen(prediction == DYNAMIC) (new Area { + case class BranchPredictorLine() extends Bundle{ + val history = SInt(historyWidth bits) + } + + val historyCache = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) + val historyWrite = historyCache.writePort + val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) + val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(0).input.payload >> 2).resized + + case class DynamicContext() extends Bundle{ + val hazard = Bool + val line = BranchPredictorLine() + } + val fetchContext = DynamicContext() + fetchContext.hazard := hazard + fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) + + object PREDICTION_CONTEXT extends Stageable(DynamicContext()) + decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2 + val decodeContextPrediction = decode.input(PREDICTION_CONTEXT).line.history.msb + + val branchStage = decodePrediction.stage + val branchContext = branchStage.input(PREDICTION_CONTEXT) + val moreJump = decodePrediction.rsp.wasWrong ^ branchContext.line.history.msb + + historyWrite.address := branchStage.input(PC)(2, historyRamSizeLog2 bits) + (if(pipeline(RVC_GEN)) + ((!branchStage.input(IS_RVC) && branchStage.input(PC)(1)) ? U(1) | U(0)) + else + U(0)) + + historyWrite.data.history := branchContext.line.history + (moreJump ? S(-1) | S(1)) + val sat = (branchContext.line.history === (moreJump ? S(branchContext.line.history.minValue) | S(branchContext.line.history.maxValue))) + historyWrite.valid := !branchContext.hazard && branchStage.arbitration.isFiring && branchStage.input(BRANCH_CTRL) === BranchCtrlEnum.B && !sat + }) + + + val imm = IMM(decode.input(INSTRUCTION)) + + val conditionalBranchPrediction = prediction match { + case STATIC => imm.b_sext.msb + case DYNAMIC => dynamic.decodeContextPrediction + } + + decodePrediction.cmd.hadBranch := decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (decode.input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction) + + val noPredictionOnMissaligned = (!pipeline(RVC_GEN)) generate new Area{ + val missaligned = decode.input(BRANCH_CTRL).mux( + BranchCtrlEnum.JAL -> imm.j_sext(1), + default -> imm.b_sext(1) + ) + decodePrediction.cmd.hadBranch clearWhen(missaligned) + } + + //TODO no more fireing depedancies + predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch //TODO OH Doublon de priorité + predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt + if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) + + when(predictionJumpInterface.valid && decode.arbitration.isFiring){ + flushIt() + } + } + case DYNAMIC_TARGET => new Area{ +// assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air") + + case class BranchPredictorLine() extends Bundle{ + val source = Bits(30 - historyRamSizeLog2 bits) + val branchWish = UInt(2 bits) + val target = UInt(32 bits) + val unaligned = ifGen(compressedGen)(Bool) + } + + val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) + val historyWrite = history.writePort + + //Avoid write to read hazard + val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) + val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized + val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready) + val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True) + + //Avoid stoping instruction fetch in the middle patch // if(compressedGen && cmdToRspStageCount == 1){ // hit clearWhen(!decompressor.output.valid) // } -// -// //Avoid write to read hazard -// val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) -// val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized -// //TODO improve predictionPcLoad way of doing things -// fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.valid //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1)) -// fetchPc.predictionPcLoad.payload := line.target -// -// case class PredictionResult() extends Bundle{ -// val hazard = Bool -// val hit = Bool -// val line = BranchPredictorLine() -// } -// -// val fetchContext = PredictionResult() -// fetchContext.hazard := hazard -// fetchContext.hit := hit -// fetchContext.line := line -// -// val (decompressorContext, injectorContext) = stage1ToInjectorPipe(fetchContext) -// if(compressedGen) { -// //prediction hit on the right instruction into words -// decompressorContext.hit clearWhen(decompressorContext.line.unaligned && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.input.pc(1)))) -// -// // if(compressedGen) injectorContext.hit clearWhen(decodePc.pcReg(1) =/= injectorContext.line.unaligned) -// -// decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire -// decodePc.predictionPcLoad.payload := injectorContext.line.target -// -// -// when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){ -// decompressor.bufferValid := False -// decompressor.input.ready := True -// } -// } -// -// object PREDICTION_CONTEXT extends Stageable(PredictionResult()) -// pipeline.decode.insert(PREDICTION_CONTEXT) := injectorContext -// val branchStage = fetchPrediction.stage -// val branchContext = branchStage.input(PREDICTION_CONTEXT) -// -// fetchPrediction.cmd.hadBranch := branchContext.hit && !branchContext.hazard && branchContext.line.branchWish.msb -// fetchPrediction.cmd.targetPc := branchContext.line.target -// -// -// historyWrite.valid := False -// historyWrite.address := fetchPrediction.rsp.sourceLastWord(2, historyRamSizeLog2 bits) -// historyWrite.data.source := fetchPrediction.rsp.sourceLastWord.asBits >> 2 + historyRamSizeLog2 -// historyWrite.data.target := fetchPrediction.rsp.finalPc -// if(compressedGen) historyWrite.data.unaligned := !fetchPrediction.stage.input(PC)(1) ^ fetchPrediction.stage.input(IS_RVC) -// -// when(fetchPrediction.rsp.wasRight) { -// historyWrite.valid := branchContext.hit -// historyWrite.data.branchWish := branchContext.line.branchWish + (branchContext.line.branchWish === 2).asUInt - (branchContext.line.branchWish === 1).asUInt -// } otherwise { -// when(branchContext.hit) { -// historyWrite.valid := True -// historyWrite.data.branchWish := branchContext.line.branchWish - (branchContext.line.branchWish.msb).asUInt + (!branchContext.line.branchWish.msb).asUInt -// } otherwise { -// historyWrite.valid := True -// historyWrite.data.branchWish := "10" -// } -// } -// -// historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring) -// -// -// -// val predictionFailure = ifGen(compressedGen && cmdToRspStageCount > 1)(new Area{ -// val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) -// val unalignedWordIssue = decompressor.bufferFill && decompressor.input.rsp.inst(17 downto 16) === 3 && predictionBranch -// val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt) -// val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) -// val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid -// -// dynamicTargetFailureCorrection.valid := False -// dynamicTargetFailureCorrection.payload := decode.input(PC) -// when(injectorFailure || bypassFailure){ -// historyWrite.valid := True -// historyWrite.address := (decode.input(PC) >> 2).resized -// historyWrite.data.branchWish := 0 -// -// decode.arbitration.isValid := False -// decode.arbitration.flushNext := True -// dynamicTargetFailureCorrection.valid := True -// } -// }) -// } -// } + + fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).input.valid + fetchPc.predictionPcLoad.payload := line.target + + case class PredictionResult() extends Bundle{ + val hazard = Bool + val hit = Bool + val line = BranchPredictorLine() + } + + val fetchContext = PredictionResult() + fetchContext.hazard := hazard + fetchContext.hit := hit + fetchContext.line := line + + val (decompressorContext, injectorContext) = stage1ToInjectorPipe(fetchContext) + if(compressedGen) { + //prediction hit on the right instruction into words + decompressorContext.hit clearWhen(decompressorContext.line.unaligned && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.input.pc(1)))) + + // if(compressedGen) injectorContext.hit clearWhen(decodePc.pcReg(1) =/= injectorContext.line.unaligned) + + decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire + decodePc.predictionPcLoad.payload := injectorContext.line.target + + + when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){ + decompressor.bufferValid := False + decompressor.input.ready := True + } + } + + object PREDICTION_CONTEXT extends Stageable(PredictionResult()) + pipeline.decode.insert(PREDICTION_CONTEXT) := injectorContext + val branchStage = fetchPrediction.stage + val branchContext = branchStage.input(PREDICTION_CONTEXT) + + fetchPrediction.cmd.hadBranch := branchContext.hit && !branchContext.hazard && branchContext.line.branchWish.msb + fetchPrediction.cmd.targetPc := branchContext.line.target + + + historyWrite.valid := False + historyWrite.address := fetchPrediction.rsp.sourceLastWord(2, historyRamSizeLog2 bits) + historyWrite.data.source := fetchPrediction.rsp.sourceLastWord.asBits >> 2 + historyRamSizeLog2 + historyWrite.data.target := fetchPrediction.rsp.finalPc + if(compressedGen) historyWrite.data.unaligned := !fetchPrediction.stage.input(PC)(1) ^ fetchPrediction.stage.input(IS_RVC) + + when(fetchPrediction.rsp.wasRight) { + historyWrite.valid := branchContext.hit + historyWrite.data.branchWish := branchContext.line.branchWish + (branchContext.line.branchWish === 2).asUInt - (branchContext.line.branchWish === 1).asUInt + } otherwise { + when(branchContext.hit) { + historyWrite.valid := True + historyWrite.data.branchWish := branchContext.line.branchWish - (branchContext.line.branchWish.msb).asUInt + (!branchContext.line.branchWish.msb).asUInt + } otherwise { + historyWrite.valid := True + historyWrite.data.branchWish := "10" + } + } + + historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring) + + + + val predictionFailure = ifGen(compressedGen && cmdToRspStageCount > 1)(new Area{ + val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) + val unalignedWordIssue = decompressor.bufferFill && decompressor.input.rsp.inst(17 downto 16) === 3 && predictionBranch + val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt) + val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) + val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid + + dynamicTargetFailureCorrection.valid := False + dynamicTargetFailureCorrection.payload := decode.input(PC) + when(injectorFailure || bypassFailure){ + historyWrite.valid := True + historyWrite.address := (decode.input(PC) >> 2).resized + historyWrite.data.branchWish := 0 + + decode.arbitration.isValid := False + decode.arbitration.flushNext := True + dynamicTargetFailureCorrection.valid := True + } + }) + } + } def stageXToIBusRsp[T <: Data](stage : Any, input : T): (T) ={ iBusRsp.stages.dropWhile(_ != stage).tail.foldLeft(input)((data,stage) => RegNextWhen(data, stage.output.ready)) diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 537cb0f..4a63364 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -41,7 +41,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, decodePcGen = compressedGen, compressedGen = compressedGen, cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1) + (if(relaxedPcCalculation) 1 else 0), - pcRegReusedForSecondStage = true, + allowPcRegReusedForSecondStage = true, injectorReadyCutGen = false, prediction = prediction, historyRamSizeLog2 = historyRamSizeLog2, diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index aa4fcb6..c14ac30 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -240,7 +240,7 @@ class IBusSimplePlugin( resetVector : BigInt, decodePcGen = compressedGen, compressedGen = compressedGen, cmdToRspStageCount = busLatencyMin + (if(cmdForkOnSecondStage) 1 else 0), - pcRegReusedForSecondStage = !(cmdForkOnSecondStage && cmdForkPersistence), + allowPcRegReusedForSecondStage = !(cmdForkOnSecondStage && cmdForkPersistence), injectorReadyCutGen = false, prediction = prediction, historyRamSizeLog2 = historyRamSizeLog2, diff --git a/src/main/scala/vexriscv/plugin/Misc.scala b/src/main/scala/vexriscv/plugin/Misc.scala index 8f68e4e..60c1682 100644 --- a/src/main/scala/vexriscv/plugin/Misc.scala +++ b/src/main/scala/vexriscv/plugin/Misc.scala @@ -122,7 +122,7 @@ object StreamForkVex{ object StreamVexPimper{ implicit class StreamFlushPimper[T <: Data](pimped : Stream[T]){ - def m2sPipeWithFlush(flush : Bool, discardInput : Boolean = true, collapsBubble : Boolean = true): Stream[T] = { + def m2sPipeWithFlush(flush : Bool, discardInput : Boolean = true, collapsBubble : Boolean = true, flushInput : Bool = null): Stream[T] = { val ret = cloneOf(pimped) val rValid = RegInit(False) @@ -132,7 +132,10 @@ object StreamVexPimper{ pimped.ready := (Bool(collapsBubble) && !ret.valid) || ret.ready when(pimped.ready) { - rValid := pimped.valid + if(flushInput == null) + rValid := pimped.valid + else + rValid := pimped.valid && !flushInput rData := pimped.payload } From e23295f06e00ba7296748b5213bbe6cb7d2ee2e0 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 17 Feb 2020 19:29:41 +0100 Subject: [PATCH 10/51] Fix Fetcher pcValid pipeline --- src/main/scala/vexriscv/plugin/Fetcher.scala | 35 +++++++++----------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index eae5461..0ba19e0 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -133,24 +133,27 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val pc = pcReg + (inc ## B"00").asUInt val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) val redo = fetchRedoGen generate Flow(UInt(32 bits)) + val flushed = False if(compressedGen) when(inc) { pc(1) := False } - if(fetchRedoGen) when(redo.valid){ - corrected := True - pc := redo.payload - } if(predictionPcLoad != null) { when(predictionPcLoad.valid) { corrected := True pc := predictionPcLoad.payload } } + if(fetchRedoGen) when(redo.valid){ + corrected := True + pc := redo.payload + flushed := True + } when(jump.pcLoad.valid) { corrected := True pc := jump.pcLoad.payload + flushed := True } when(booted && (output.ready || corrected || pcRegPropagate)){ @@ -166,6 +169,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val decodePc = ifGen(decodePcGen)(new Area { //PC calculation without Jump + val flushed = False val pcReg = Reg(UInt(32 bits)) init(if(resetVector != null) resetVector else externalResetVector) addAttribute(Verilator.public) val pcPlus = if(compressedGen) pcReg + ((decode.input(IS_RVC)) ? U(2) | U(4)) @@ -188,6 +192,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, //application of the selected jump request when(jump.pcLoad.valid && (!decode.arbitration.isStuck || decode.arbitration.isRemoved)) { pcReg := jump.pcLoad.payload + flushed := True } }) @@ -296,16 +301,16 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, if(!decodePcGen) iBusRsp.readyForError.clearWhen(!pcValid(decode)) //Need to wait a valid PC on the decode stage, as it is use to fill CSR xEPC - def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = { + def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean, flush : Bool) : Seq[Bool] = { stucks.scanLeft(input)((i, stuck) => { val reg = RegInit(False) - if(!relaxedInput) when(fetcherflushIt) { + if(!relaxedInput) when(flush) { reg := False } when(!stuck) { reg := i } - if(relaxedInput || i != input) when(fetcherflushIt) { + if(relaxedInput || i != input) when(flush) { reg := False } reg @@ -314,10 +319,10 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val stagesFromExecute = stages.dropWhile(_ != execute).toList val nextPcCalc = if (decodePcGen) new Area{ - val valids = pcUpdatedGen(True, False :: stagesFromExecute.map(_.arbitration.isStuck), true) + val valids = pcUpdatedGen(True, False :: stagesFromExecute.map(_.arbitration.isStuck), true, decodePc.flushed) pcValids := Vec(valids.takeRight(stages.size)) } else new Area{ - val valids = pcUpdatedGen(True, iBusRsp.stages.tail.map(!_.input.ready) ++ (if (injectorStage) List(!decodeInput.ready) else Nil) ++ stagesFromExecute.map(_.arbitration.isStuck), false) + val valids = pcUpdatedGen(True, iBusRsp.stages.tail.map(!_.input.ready) ++ (if (injectorStage) List(!decodeInput.ready) else Nil) ++ stagesFromExecute.map(_.arbitration.isStuck), false, fetchPc.flushed) pcValids := Vec(valids.takeRight(stages.size)) } @@ -508,12 +513,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready) - val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True) - - //Avoid stoping instruction fetch in the middle patch -// if(compressedGen && cmdToRspStageCount == 1){ -// hit clearWhen(!decompressor.output.valid) -// } + val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).input.valid fetchPc.predictionPcLoad.payload := line.target @@ -534,12 +534,9 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, //prediction hit on the right instruction into words decompressorContext.hit clearWhen(decompressorContext.line.unaligned && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.input.pc(1)))) - // if(compressedGen) injectorContext.hit clearWhen(decodePc.pcReg(1) =/= injectorContext.line.unaligned) - decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire decodePc.predictionPcLoad.payload := injectorContext.line.target - when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){ decompressor.bufferValid := False decompressor.input.ready := True @@ -584,7 +581,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt) val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid - + ??? dynamicTargetFailureCorrection.valid := False dynamicTargetFailureCorrection.payload := decode.input(PC) when(injectorFailure || bypassFailure){ From 0e0a568743a9fa9b1023a4387e183d4237e1c72d Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 17 Feb 2020 21:43:02 +0100 Subject: [PATCH 11/51] Apply DYNAMIC_TARGET correction all the time --- src/main/scala/vexriscv/plugin/Fetcher.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 0ba19e0..255efc2 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -76,7 +76,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } case DYNAMIC_TARGET => { fetchPrediction = pipeline.service(classOf[PredictionInterface]).askFetchPrediction() - if(compressedGen && cmdToRspStageCount > 1){ + if(compressedGen){ dynamicTargetFailureCorrection = createJumpInterface(pipeline.decode) } } @@ -575,13 +575,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, - val predictionFailure = ifGen(compressedGen && cmdToRspStageCount > 1)(new Area{ + val predictionFailure = ifGen(compressedGen)(new Area{ val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) val unalignedWordIssue = decompressor.bufferFill && decompressor.input.rsp.inst(17 downto 16) === 3 && predictionBranch val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt) val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid - ??? + dynamicTargetFailureCorrection.valid := False dynamicTargetFailureCorrection.payload := decode.input(PC) when(injectorFailure || bypassFailure){ From e0cd9a6e067e6e42f385a87af9f439f8314290f0 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 17 Feb 2020 22:45:34 +0100 Subject: [PATCH 12/51] clean iBusRsp redo --- src/main/scala/vexriscv/plugin/Fetcher.scala | 16 ++++++---------- .../scala/vexriscv/plugin/IBusCachedPlugin.scala | 8 +++----- .../scala/vexriscv/plugin/IBusSimplePlugin.scala | 10 ++++------ 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 255efc2..f933ab9 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -76,9 +76,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } case DYNAMIC_TARGET => { fetchPrediction = pipeline.service(classOf[PredictionInterface]).askFetchPrediction() - if(compressedGen){ - dynamicTargetFailureCorrection = createJumpInterface(pipeline.decode) - } } } @@ -205,7 +202,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val iBusRsp = new Area { - val fetchFlush = False + val redoFetch = False val stages = Array.fill(cmdToRspStageCount + 1)(new Bundle { val input = Stream(UInt(32 bits)) val output = Stream(UInt(32 bits)) @@ -219,10 +216,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, s.output << s.input.haltWhen(s.halt) } + fetchPc.redo.valid := redoFetch + fetchPc.redo.payload := stages.last.input.payload + stages.head.flush := False //getFlushAt(IBUS_RSP, stages.head == stages.last) || fetchFlush for((s,sNext) <- (stages, stages.tail).zipped) { val discardInputOnFlush = s != stages.head - sNext.flush := getFlushAt(IBUS_RSP, sNext == stages.last) || fetchFlush + sNext.flush := getFlushAt(IBUS_RSP, sNext == stages.last) || redoFetch if(s == stages.head && pcRegReusedForSecondStage) { sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(sNext.flush, false, collapsBubble = false, flushInput = s.flush)) sNext.input.payload := fetchPc.pcReg @@ -582,16 +582,12 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid - dynamicTargetFailureCorrection.valid := False - dynamicTargetFailureCorrection.payload := decode.input(PC) when(injectorFailure || bypassFailure){ historyWrite.valid := True historyWrite.address := (decode.input(PC) >> 2).resized historyWrite.data.branchWish := 0 - decode.arbitration.isValid := False - decode.arbitration.flushNext := True - dynamicTargetFailureCorrection.valid := True + iBusRsp.redoFetch := True } }) } diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 4a63364..f018bb3 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -59,7 +59,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, var iBus : InstructionCacheMemBus = null var mmuBus : MemoryTranslatorBus = null var privilegeService : PrivilegeService = null - var redoBranch : Flow[UInt] = null var decodeExceptionPort : Flow[ExceptionCause] = null val tightlyCoupledPorts = ArrayBuffer[TightlyCoupledPort]() def tightlyGen = tightlyCoupledPorts.nonEmpty @@ -235,10 +234,9 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, decodeExceptionPort.code := 1 } - - fetchPc.redo.valid := redoFetch - fetchPc.redo.payload := iBusRsp.stages.last.input.payload - iBusRsp.fetchFlush setWhen(redoFetch) + when(redoFetch) { + iBusRsp.redoFetch := True + } cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt) diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index c14ac30..319634d 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -369,18 +369,16 @@ class IBusSimplePlugin( resetVector : BigInt, val join = Stream(FetchRsp()) val exceptionDetected = False - val redoRequired = False join.valid := stages.last.output.valid && rspBufferOutput.valid join.payload := fetchRsp stages.last.output.ready := stages.last.output.valid ? join.fire | join.ready rspBufferOutput.ready := join.fire - output << join.haltWhen(exceptionDetected || redoRequired) + output << join.haltWhen(exceptionDetected) if(memoryTranslatorPortConfig != null){ - redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling) - fetchPc.redo.valid := redoRequired && iBusRsp.readyForError - fetchPc.redo.payload := decode.input(PC) - iBusRsp.fetchFlush setWhen(fetchPc.redo.valid) + when(stages.last.input.valid && mmu.joinCtx.refilling) { + iBusRsp.redoFetch := True + } } From 53a29e35e9a05a3f08247367c3cba96cf73615a9 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 17 Feb 2020 23:27:17 +0100 Subject: [PATCH 13/51] fix deleg external interrupt propagation time failure --- src/test/cpp/raw/deleg/build/deleg.asm | 1198 ++++++++++++++---------- src/test/cpp/raw/deleg/build/deleg.hex | 290 +++--- src/test/cpp/raw/deleg/src/crt.S | 17 + 3 files changed, 891 insertions(+), 614 deletions(-) diff --git a/src/test/cpp/raw/deleg/build/deleg.asm b/src/test/cpp/raw/deleg/build/deleg.asm index 9e3098f..e64c374 100644 --- a/src/test/cpp/raw/deleg/build/deleg.asm +++ b/src/test/cpp/raw/deleg/build/deleg.asm @@ -6,536 +6,744 @@ Disassembly of section .crt_section: 80000000 <_start>: 80000000: 00100e93 li t4,1 -80000004: 00000097 auipc ra,0x0 -80000008: 6fc08093 addi ra,ra,1788 # 80000700 +80000004: 00001097 auipc ra,0x1 +80000008: a3c08093 addi ra,ra,-1476 # 80000a40 8000000c: 30509073 csrw mtvec,ra -80000010: 00000097 auipc ra,0x0 -80000014: 72808093 addi ra,ra,1832 # 80000738 +80000010: 00001097 auipc ra,0x1 +80000014: a6808093 addi ra,ra,-1432 # 80000a78 80000018: 10509073 csrw stvec,ra 8000001c: f00110b7 lui ra,0xf0011 80000020: 00000113 li sp,0 -80000024: 0020a023 sw sp,0(ra) # f0011000 +80000024: 0020a023 sw sp,0(ra) # f0011000 +80000028: 00000013 nop +8000002c: 00000013 nop +80000030: 00000013 nop +80000034: 00000013 nop +80000038: 00000013 nop +8000003c: 00000013 nop +80000040: 00000013 nop +80000044: 00000013 nop -80000028 : -80000028: 00100e13 li t3,1 -8000002c: 00000f17 auipc t5,0x0 -80000030: 00cf0f13 addi t5,t5,12 # 80000038 -80000034: 00000073 ecall +80000048 : +80000048: 00100e13 li t3,1 +8000004c: 00000f17 auipc t5,0x0 +80000050: 00cf0f13 addi t5,t5,12 # 80000058 +80000054: 00000073 ecall -80000038 : -80000038: 00200e13 li t3,2 -8000003c: 000020b7 lui ra,0x2 -80000040: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -80000044: 00000113 li sp,0 -80000048: 3000b073 csrc mstatus,ra -8000004c: 30012073 csrs mstatus,sp -80000050: 00000097 auipc ra,0x0 -80000054: 01408093 addi ra,ra,20 # 80000064 -80000058: 34109073 csrw mepc,ra -8000005c: 30200073 mret -80000060: 6880006f j 800006e8 -80000064: 00000f17 auipc t5,0x0 -80000068: 024f0f13 addi t5,t5,36 # 80000088 -8000006c: 00000073 ecall -80000070: 6780006f j 800006e8 +80000058 : +80000058: 00200e13 li t3,2 +8000005c: 000020b7 lui ra,0x2 +80000060: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +80000064: 00000113 li sp,0 +80000068: 3000b073 csrc mstatus,ra +8000006c: 30012073 csrs mstatus,sp +80000070: 00000097 auipc ra,0x0 +80000074: 01408093 addi ra,ra,20 # 80000084 +80000078: 34109073 csrw mepc,ra +8000007c: 30200073 mret +80000080: 1a90006f j 80000a28 +80000084: 00000f17 auipc t5,0x0 +80000088: 024f0f13 addi t5,t5,36 # 800000a8 +8000008c: 00000073 ecall +80000090: 1990006f j 80000a28 -80000074 : -80000074: 00300e13 li t3,3 -80000078: 00000f17 auipc t5,0x0 -8000007c: 010f0f13 addi t5,t5,16 # 80000088 -80000080: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> -80000084: 6640006f j 800006e8 +80000094 : +80000094: 00300e13 li t3,3 +80000098: 00000f17 auipc t5,0x0 +8000009c: 010f0f13 addi t5,t5,16 # 800000a8 +800000a0: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> +800000a4: 1850006f j 80000a28 -80000088 : -80000088: 00400e13 li t3,4 -8000008c: 000020b7 lui ra,0x2 -80000090: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -80000094: 00001137 lui sp,0x1 -80000098: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> -8000009c: 3000b073 csrc mstatus,ra -800000a0: 30012073 csrs mstatus,sp -800000a4: 00000097 auipc ra,0x0 -800000a8: 01408093 addi ra,ra,20 # 800000b8 -800000ac: 34109073 csrw mepc,ra -800000b0: 30200073 mret -800000b4: 6340006f j 800006e8 -800000b8: 00000f17 auipc t5,0x0 -800000bc: 010f0f13 addi t5,t5,16 # 800000c8 -800000c0: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> -800000c4: 6240006f j 800006e8 +800000a8 : +800000a8: 00400e13 li t3,4 +800000ac: 000020b7 lui ra,0x2 +800000b0: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +800000b4: 00001137 lui sp,0x1 +800000b8: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> +800000bc: 3000b073 csrc mstatus,ra +800000c0: 30012073 csrs mstatus,sp +800000c4: 00000097 auipc ra,0x0 +800000c8: 01408093 addi ra,ra,20 # 800000d8 +800000cc: 34109073 csrw mepc,ra +800000d0: 30200073 mret +800000d4: 1550006f j 80000a28 +800000d8: 00000f17 auipc t5,0x0 +800000dc: 010f0f13 addi t5,t5,16 # 800000e8 +800000e0: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> +800000e4: 1450006f j 80000a28 -800000c8 : -800000c8: 00500e13 li t3,5 -800000cc: 000020b7 lui ra,0x2 -800000d0: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -800000d4: 00000113 li sp,0 -800000d8: 3000b073 csrc mstatus,ra -800000dc: 30012073 csrs mstatus,sp -800000e0: 00000097 auipc ra,0x0 -800000e4: 01408093 addi ra,ra,20 # 800000f4 -800000e8: 34109073 csrw mepc,ra -800000ec: 30200073 mret -800000f0: 5f80006f j 800006e8 -800000f4: 00000f17 auipc t5,0x0 -800000f8: 010f0f13 addi t5,t5,16 # 80000104 -800000fc: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> -80000100: 5e80006f j 800006e8 - -80000104 : -80000104: 00600e13 li t3,6 -80000108: 01000093 li ra,16 -8000010c: 30209073 csrw medeleg,ra - -80000110 : -80000110: 00700e13 li t3,7 +800000e8 : +800000e8: 00500e13 li t3,5 +800000ec: 000020b7 lui ra,0x2 +800000f0: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +800000f4: 00000113 li sp,0 +800000f8: 3000b073 csrc mstatus,ra +800000fc: 30012073 csrs mstatus,sp +80000100: 00000097 auipc ra,0x0 +80000104: 01408093 addi ra,ra,20 # 80000114 +80000108: 34109073 csrw mepc,ra +8000010c: 30200073 mret +80000110: 1190006f j 80000a28 80000114: 00000f17 auipc t5,0x0 -80000118: 010f0f13 addi t5,t5,16 # 80000124 +80000118: 010f0f13 addi t5,t5,16 # 80000124 8000011c: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> -80000120: 5c80006f j 800006e8 +80000120: 1090006f j 80000a28 -80000124 : -80000124: 00800e13 li t3,8 -80000128: 00000f17 auipc t5,0x0 -8000012c: 03cf0f13 addi t5,t5,60 # 80000164 -80000130: 000020b7 lui ra,0x2 -80000134: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -80000138: 00001137 lui sp,0x1 -8000013c: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> -80000140: 3000b073 csrc mstatus,ra -80000144: 30012073 csrs mstatus,sp -80000148: 00000097 auipc ra,0x0 -8000014c: 01408093 addi ra,ra,20 # 8000015c -80000150: 34109073 csrw mepc,ra -80000154: 30200073 mret -80000158: 5900006f j 800006e8 -8000015c: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> -80000160: 5880006f j 800006e8 +80000124 : +80000124: 00600e13 li t3,6 +80000128: 01000093 li ra,16 +8000012c: 30209073 csrw medeleg,ra -80000164 : -80000164: 00900e13 li t3,9 -80000168: 00000f17 auipc t5,0x0 -8000016c: 038f0f13 addi t5,t5,56 # 800001a0 -80000170: 000020b7 lui ra,0x2 -80000174: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -80000178: 00000113 li sp,0 -8000017c: 3000b073 csrc mstatus,ra -80000180: 30012073 csrs mstatus,sp -80000184: 00000097 auipc ra,0x0 -80000188: 01408093 addi ra,ra,20 # 80000198 -8000018c: 34109073 csrw mepc,ra -80000190: 30200073 mret -80000194: 5540006f j 800006e8 -80000198: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> -8000019c: 54c0006f j 800006e8 +80000130 : +80000130: 00700e13 li t3,7 +80000134: 00000f17 auipc t5,0x0 +80000138: 010f0f13 addi t5,t5,16 # 80000144 +8000013c: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> +80000140: 0e90006f j 80000a28 -800001a0 : -800001a0: 00a00e13 li t3,10 -800001a4: 00000f17 auipc t5,0x0 -800001a8: 03cf0f13 addi t5,t5,60 # 800001e0 -800001ac: f00110b7 lui ra,0xf0011 -800001b0: 00000113 li sp,0 -800001b4: 0020a023 sw sp,0(ra) # f0011000 -800001b8: 00800093 li ra,8 -800001bc: 30009073 csrw mstatus,ra -800001c0: 000010b7 lui ra,0x1 -800001c4: 80008093 addi ra,ra,-2048 # 800 <_start-0x7ffff800> -800001c8: 30409073 csrw mie,ra +80000144 : +80000144: 00800e13 li t3,8 +80000148: 00000f17 auipc t5,0x0 +8000014c: 03cf0f13 addi t5,t5,60 # 80000184 +80000150: 000020b7 lui ra,0x2 +80000154: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +80000158: 00001137 lui sp,0x1 +8000015c: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> +80000160: 3000b073 csrc mstatus,ra +80000164: 30012073 csrs mstatus,sp +80000168: 00000097 auipc ra,0x0 +8000016c: 01408093 addi ra,ra,20 # 8000017c +80000170: 34109073 csrw mepc,ra +80000174: 30200073 mret +80000178: 0b10006f j 80000a28 +8000017c: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> +80000180: 0a90006f j 80000a28 + +80000184 : +80000184: 00900e13 li t3,9 +80000188: 00000f17 auipc t5,0x0 +8000018c: 038f0f13 addi t5,t5,56 # 800001c0 +80000190: 000020b7 lui ra,0x2 +80000194: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +80000198: 00000113 li sp,0 +8000019c: 3000b073 csrc mstatus,ra +800001a0: 30012073 csrs mstatus,sp +800001a4: 00000097 auipc ra,0x0 +800001a8: 01408093 addi ra,ra,20 # 800001b8 +800001ac: 34109073 csrw mepc,ra +800001b0: 30200073 mret +800001b4: 0750006f j 80000a28 +800001b8: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff> +800001bc: 06d0006f j 80000a28 + +800001c0 : +800001c0: 00a00e13 li t3,10 +800001c4: 00000f17 auipc t5,0x0 +800001c8: 07cf0f13 addi t5,t5,124 # 80000240 800001cc: f00110b7 lui ra,0xf0011 -800001d0: 00100113 li sp,1 -800001d4: 0020a023 sw sp,0(ra) # f0011000 -800001d8: 10500073 wfi -800001dc: 50c0006f j 800006e8 - -800001e0 : -800001e0: 00b00e13 li t3,11 -800001e4: 00000f17 auipc t5,0x0 -800001e8: 068f0f13 addi t5,t5,104 # 8000024c -800001ec: f00110b7 lui ra,0xf0011 -800001f0: 00000113 li sp,0 -800001f4: 0020a023 sw sp,0(ra) # f0011000 +800001d0: 00000113 li sp,0 +800001d4: 0020a023 sw sp,0(ra) # f0011000 +800001d8: 00000013 nop +800001dc: 00000013 nop +800001e0: 00000013 nop +800001e4: 00000013 nop +800001e8: 00000013 nop +800001ec: 00000013 nop +800001f0: 00000013 nop +800001f4: 00000013 nop 800001f8: 00800093 li ra,8 800001fc: 30009073 csrw mstatus,ra 80000200: 000010b7 lui ra,0x1 80000204: 80008093 addi ra,ra,-2048 # 800 <_start-0x7ffff800> 80000208: 30409073 csrw mie,ra -8000020c: 000020b7 lui ra,0x2 -80000210: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -80000214: 00001137 lui sp,0x1 -80000218: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> -8000021c: 3000b073 csrc mstatus,ra -80000220: 30012073 csrs mstatus,sp -80000224: 00000097 auipc ra,0x0 -80000228: 01408093 addi ra,ra,20 # 80000238 -8000022c: 34109073 csrw mepc,ra -80000230: 30200073 mret -80000234: 4b40006f j 800006e8 -80000238: f00110b7 lui ra,0xf0011 -8000023c: 00100113 li sp,1 -80000240: 0020a023 sw sp,0(ra) # f0011000 -80000244: 10500073 wfi -80000248: 4a00006f j 800006e8 +8000020c: f00110b7 lui ra,0xf0011 +80000210: 00100113 li sp,1 +80000214: 0020a023 sw sp,0(ra) # f0011000 +80000218: 00000013 nop +8000021c: 00000013 nop +80000220: 00000013 nop +80000224: 00000013 nop +80000228: 00000013 nop +8000022c: 00000013 nop +80000230: 00000013 nop +80000234: 00000013 nop +80000238: 10500073 wfi +8000023c: 7ec0006f j 80000a28 -8000024c : -8000024c: 00c00e13 li t3,12 -80000250: 00000f17 auipc t5,0x0 -80000254: 064f0f13 addi t5,t5,100 # 800002b4 -80000258: f00110b7 lui ra,0xf0011 -8000025c: 00000113 li sp,0 -80000260: 0020a023 sw sp,0(ra) # f0011000 -80000264: 00800093 li ra,8 -80000268: 30009073 csrw mstatus,ra -8000026c: 000010b7 lui ra,0x1 -80000270: 80008093 addi ra,ra,-2048 # 800 <_start-0x7ffff800> -80000274: 30409073 csrw mie,ra -80000278: 000020b7 lui ra,0x2 -8000027c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -80000280: 00000113 li sp,0 -80000284: 3000b073 csrc mstatus,ra -80000288: 30012073 csrs mstatus,sp -8000028c: 00000097 auipc ra,0x0 -80000290: 01408093 addi ra,ra,20 # 800002a0 -80000294: 34109073 csrw mepc,ra -80000298: 30200073 mret -8000029c: 44c0006f j 800006e8 -800002a0: f00110b7 lui ra,0xf0011 -800002a4: 00100113 li sp,1 -800002a8: 0020a023 sw sp,0(ra) # f0011000 -800002ac: 10500073 wfi -800002b0: 4380006f j 800006e8 +80000240 : +80000240: 00b00e13 li t3,11 +80000244: 00000f17 auipc t5,0x0 +80000248: 0a8f0f13 addi t5,t5,168 # 800002ec +8000024c: f00110b7 lui ra,0xf0011 +80000250: 00000113 li sp,0 +80000254: 0020a023 sw sp,0(ra) # f0011000 +80000258: 00000013 nop +8000025c: 00000013 nop +80000260: 00000013 nop +80000264: 00000013 nop +80000268: 00000013 nop +8000026c: 00000013 nop +80000270: 00000013 nop +80000274: 00000013 nop +80000278: 00800093 li ra,8 +8000027c: 30009073 csrw mstatus,ra +80000280: 000010b7 lui ra,0x1 +80000284: 80008093 addi ra,ra,-2048 # 800 <_start-0x7ffff800> +80000288: 30409073 csrw mie,ra +8000028c: 000020b7 lui ra,0x2 +80000290: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +80000294: 00001137 lui sp,0x1 +80000298: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> +8000029c: 3000b073 csrc mstatus,ra +800002a0: 30012073 csrs mstatus,sp +800002a4: 00000097 auipc ra,0x0 +800002a8: 01408093 addi ra,ra,20 # 800002b8 +800002ac: 34109073 csrw mepc,ra +800002b0: 30200073 mret +800002b4: 7740006f j 80000a28 +800002b8: f00110b7 lui ra,0xf0011 +800002bc: 00100113 li sp,1 +800002c0: 0020a023 sw sp,0(ra) # f0011000 +800002c4: 00000013 nop +800002c8: 00000013 nop +800002cc: 00000013 nop +800002d0: 00000013 nop +800002d4: 00000013 nop +800002d8: 00000013 nop +800002dc: 00000013 nop +800002e0: 00000013 nop +800002e4: 10500073 wfi +800002e8: 7400006f j 80000a28 -800002b4 : -800002b4: 00200093 li ra,2 -800002b8: 10009073 csrw sstatus,ra -800002bc: 00e00e13 li t3,14 -800002c0: 00000f17 auipc t5,0x0 -800002c4: 040f0f13 addi t5,t5,64 # 80000300 -800002c8: f00120b7 lui ra,0xf0012 -800002cc: 00000113 li sp,0 -800002d0: 0020a023 sw sp,0(ra) # f0012000 -800002d4: 00200093 li ra,2 -800002d8: 30009073 csrw mstatus,ra -800002dc: 20000093 li ra,512 -800002e0: 30409073 csrw mie,ra -800002e4: 00000e93 li t4,0 -800002e8: f00120b7 lui ra,0xf0012 -800002ec: 00100113 li sp,1 -800002f0: 0020a023 sw sp,0(ra) # f0012000 -800002f4: 06400093 li ra,100 -800002f8: fff08093 addi ra,ra,-1 -800002fc: fe104ee3 bgtz ra,800002f8 +800002ec : +800002ec: 00c00e13 li t3,12 +800002f0: 00000f17 auipc t5,0x0 +800002f4: 0a4f0f13 addi t5,t5,164 # 80000394 +800002f8: f00110b7 lui ra,0xf0011 +800002fc: 00000113 li sp,0 +80000300: 0020a023 sw sp,0(ra) # f0011000 +80000304: 00000013 nop +80000308: 00000013 nop +8000030c: 00000013 nop +80000310: 00000013 nop +80000314: 00000013 nop +80000318: 00000013 nop +8000031c: 00000013 nop +80000320: 00000013 nop +80000324: 00800093 li ra,8 +80000328: 30009073 csrw mstatus,ra +8000032c: 000010b7 lui ra,0x1 +80000330: 80008093 addi ra,ra,-2048 # 800 <_start-0x7ffff800> +80000334: 30409073 csrw mie,ra +80000338: 000020b7 lui ra,0x2 +8000033c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +80000340: 00000113 li sp,0 +80000344: 3000b073 csrc mstatus,ra +80000348: 30012073 csrs mstatus,sp +8000034c: 00000097 auipc ra,0x0 +80000350: 01408093 addi ra,ra,20 # 80000360 +80000354: 34109073 csrw mepc,ra +80000358: 30200073 mret +8000035c: 6cc0006f j 80000a28 +80000360: f00110b7 lui ra,0xf0011 +80000364: 00100113 li sp,1 +80000368: 0020a023 sw sp,0(ra) # f0011000 +8000036c: 00000013 nop +80000370: 00000013 nop +80000374: 00000013 nop +80000378: 00000013 nop +8000037c: 00000013 nop +80000380: 00000013 nop +80000384: 00000013 nop +80000388: 00000013 nop +8000038c: 10500073 wfi +80000390: 6980006f j 80000a28 -80000300 : -80000300: 00f00e13 li t3,15 -80000304: 00000f17 auipc t5,0x0 -80000308: 068f0f13 addi t5,t5,104 # 8000036c -8000030c: f00120b7 lui ra,0xf0012 -80000310: 00000113 li sp,0 -80000314: 0020a023 sw sp,0(ra) # f0012000 -80000318: 00200093 li ra,2 -8000031c: 30009073 csrw mstatus,ra -80000320: 20000093 li ra,512 -80000324: 30409073 csrw mie,ra -80000328: 000020b7 lui ra,0x2 -8000032c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -80000330: 00001137 lui sp,0x1 -80000334: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> -80000338: 3000b073 csrc mstatus,ra -8000033c: 30012073 csrs mstatus,sp -80000340: 00000097 auipc ra,0x0 -80000344: 01408093 addi ra,ra,20 # 80000354 -80000348: 34109073 csrw mepc,ra -8000034c: 30200073 mret -80000350: 3980006f j 800006e8 -80000354: 00100e93 li t4,1 -80000358: f00120b7 lui ra,0xf0012 -8000035c: 00100113 li sp,1 -80000360: 0020a023 sw sp,0(ra) # f0012000 -80000364: 10500073 wfi -80000368: 3800006f j 800006e8 +80000394 : +80000394: 00200093 li ra,2 +80000398: 10009073 csrw sstatus,ra +8000039c: 00e00e13 li t3,14 +800003a0: 00000f17 auipc t5,0x0 +800003a4: 080f0f13 addi t5,t5,128 # 80000420 +800003a8: f00120b7 lui ra,0xf0012 +800003ac: 00000113 li sp,0 +800003b0: 0020a023 sw sp,0(ra) # f0012000 +800003b4: 00000013 nop +800003b8: 00000013 nop +800003bc: 00000013 nop +800003c0: 00000013 nop +800003c4: 00000013 nop +800003c8: 00000013 nop +800003cc: 00000013 nop +800003d0: 00000013 nop +800003d4: 00200093 li ra,2 +800003d8: 30009073 csrw mstatus,ra +800003dc: 20000093 li ra,512 +800003e0: 30409073 csrw mie,ra +800003e4: 00000e93 li t4,0 +800003e8: f00120b7 lui ra,0xf0012 +800003ec: 00100113 li sp,1 +800003f0: 0020a023 sw sp,0(ra) # f0012000 +800003f4: 00000013 nop +800003f8: 00000013 nop +800003fc: 00000013 nop +80000400: 00000013 nop +80000404: 00000013 nop +80000408: 00000013 nop +8000040c: 00000013 nop +80000410: 00000013 nop +80000414: 06400093 li ra,100 +80000418: fff08093 addi ra,ra,-1 +8000041c: fe104ee3 bgtz ra,80000418 -8000036c : -8000036c: 01000e13 li t3,16 -80000370: 00000f17 auipc t5,0x0 -80000374: 060f0f13 addi t5,t5,96 # 800003d0 -80000378: f00120b7 lui ra,0xf0012 -8000037c: 00000113 li sp,0 -80000380: 0020a023 sw sp,0(ra) # f0012000 -80000384: 00200093 li ra,2 -80000388: 30009073 csrw mstatus,ra -8000038c: 20000093 li ra,512 -80000390: 30409073 csrw mie,ra -80000394: 000020b7 lui ra,0x2 -80000398: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -8000039c: 00000113 li sp,0 -800003a0: 3000b073 csrc mstatus,ra -800003a4: 30012073 csrs mstatus,sp -800003a8: 00000097 auipc ra,0x0 -800003ac: 01408093 addi ra,ra,20 # 800003bc -800003b0: 34109073 csrw mepc,ra -800003b4: 30200073 mret -800003b8: 3300006f j 800006e8 -800003bc: f00120b7 lui ra,0xf0012 -800003c0: 00100113 li sp,1 -800003c4: 0020a023 sw sp,0(ra) # f0012000 -800003c8: 10500073 wfi -800003cc: 31c0006f j 800006e8 +80000420 : +80000420: 00f00e13 li t3,15 +80000424: 00000f17 auipc t5,0x0 +80000428: 0a8f0f13 addi t5,t5,168 # 800004cc +8000042c: f00120b7 lui ra,0xf0012 +80000430: 00000113 li sp,0 +80000434: 0020a023 sw sp,0(ra) # f0012000 +80000438: 00000013 nop +8000043c: 00000013 nop +80000440: 00000013 nop +80000444: 00000013 nop +80000448: 00000013 nop +8000044c: 00000013 nop +80000450: 00000013 nop +80000454: 00000013 nop +80000458: 00200093 li ra,2 +8000045c: 30009073 csrw mstatus,ra +80000460: 20000093 li ra,512 +80000464: 30409073 csrw mie,ra +80000468: 000020b7 lui ra,0x2 +8000046c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +80000470: 00001137 lui sp,0x1 +80000474: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> +80000478: 3000b073 csrc mstatus,ra +8000047c: 30012073 csrs mstatus,sp +80000480: 00000097 auipc ra,0x0 +80000484: 01408093 addi ra,ra,20 # 80000494 +80000488: 34109073 csrw mepc,ra +8000048c: 30200073 mret +80000490: 5980006f j 80000a28 +80000494: 00100e93 li t4,1 +80000498: f00120b7 lui ra,0xf0012 +8000049c: 00100113 li sp,1 +800004a0: 0020a023 sw sp,0(ra) # f0012000 +800004a4: 00000013 nop +800004a8: 00000013 nop +800004ac: 00000013 nop +800004b0: 00000013 nop +800004b4: 00000013 nop +800004b8: 00000013 nop +800004bc: 00000013 nop +800004c0: 00000013 nop +800004c4: 10500073 wfi +800004c8: 5600006f j 80000a28 -800003d0 : -800003d0: 01100e13 li t3,17 -800003d4: 20000093 li ra,512 -800003d8: 30309073 csrw mideleg,ra -800003dc: 00000f17 auipc t5,0x0 -800003e0: 040f0f13 addi t5,t5,64 # 8000041c -800003e4: f00120b7 lui ra,0xf0012 -800003e8: 00000113 li sp,0 -800003ec: 0020a023 sw sp,0(ra) # f0012000 -800003f0: 00200093 li ra,2 -800003f4: 30009073 csrw mstatus,ra -800003f8: 20000093 li ra,512 -800003fc: 30409073 csrw mie,ra -80000400: 00000e93 li t4,0 -80000404: f00120b7 lui ra,0xf0012 -80000408: 00100113 li sp,1 -8000040c: 0020a023 sw sp,0(ra) # f0012000 -80000410: 06400093 li ra,100 -80000414: fff08093 addi ra,ra,-1 -80000418: fe104ee3 bgtz ra,80000414 - -8000041c : -8000041c: 01200e13 li t3,18 -80000420: 00000f17 auipc t5,0x0 -80000424: 068f0f13 addi t5,t5,104 # 80000488 -80000428: f00120b7 lui ra,0xf0012 -8000042c: 00000113 li sp,0 -80000430: 0020a023 sw sp,0(ra) # f0012000 -80000434: 00200093 li ra,2 -80000438: 30009073 csrw mstatus,ra -8000043c: 20000093 li ra,512 -80000440: 30409073 csrw mie,ra -80000444: 000020b7 lui ra,0x2 -80000448: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -8000044c: 00001137 lui sp,0x1 -80000450: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> -80000454: 3000b073 csrc mstatus,ra -80000458: 30012073 csrs mstatus,sp -8000045c: 00000097 auipc ra,0x0 -80000460: 01408093 addi ra,ra,20 # 80000470 -80000464: 34109073 csrw mepc,ra -80000468: 30200073 mret -8000046c: 27c0006f j 800006e8 -80000470: 00100e93 li t4,1 -80000474: f00120b7 lui ra,0xf0012 -80000478: 00100113 li sp,1 -8000047c: 0020a023 sw sp,0(ra) # f0012000 -80000480: 10500073 wfi -80000484: 2640006f j 800006e8 - -80000488 : -80000488: 01300e13 li t3,19 -8000048c: 00000f17 auipc t5,0x0 -80000490: 060f0f13 addi t5,t5,96 # 800004ec -80000494: f00120b7 lui ra,0xf0012 -80000498: 00000113 li sp,0 -8000049c: 0020a023 sw sp,0(ra) # f0012000 -800004a0: 00200093 li ra,2 -800004a4: 30009073 csrw mstatus,ra -800004a8: 20000093 li ra,512 -800004ac: 30409073 csrw mie,ra -800004b0: 000020b7 lui ra,0x2 -800004b4: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -800004b8: 00000113 li sp,0 -800004bc: 3000b073 csrc mstatus,ra -800004c0: 30012073 csrs mstatus,sp -800004c4: 00000097 auipc ra,0x0 -800004c8: 01408093 addi ra,ra,20 # 800004d8 -800004cc: 34109073 csrw mepc,ra -800004d0: 30200073 mret -800004d4: 2140006f j 800006e8 +800004cc : +800004cc: 01000e13 li t3,16 +800004d0: 00000f17 auipc t5,0x0 +800004d4: 0a0f0f13 addi t5,t5,160 # 80000570 800004d8: f00120b7 lui ra,0xf0012 -800004dc: 00100113 li sp,1 -800004e0: 0020a023 sw sp,0(ra) # f0012000 -800004e4: 10500073 wfi -800004e8: 2000006f j 800006e8 - -800004ec : -800004ec: f00120b7 lui ra,0xf0012 -800004f0: 00000113 li sp,0 -800004f4: 0020a023 sw sp,0(ra) # f0012000 -800004f8: 01400e13 li t3,20 -800004fc: 00000f17 auipc t5,0x0 -80000500: 030f0f13 addi t5,t5,48 # 8000052c +800004dc: 00000113 li sp,0 +800004e0: 0020a023 sw sp,0(ra) # f0012000 +800004e4: 00000013 nop +800004e8: 00000013 nop +800004ec: 00000013 nop +800004f0: 00000013 nop +800004f4: 00000013 nop +800004f8: 00000013 nop +800004fc: 00000013 nop +80000500: 00000013 nop 80000504: 00200093 li ra,2 80000508: 30009073 csrw mstatus,ra 8000050c: 20000093 li ra,512 80000510: 30409073 csrw mie,ra -80000514: 00000e93 li t4,0 -80000518: 20000093 li ra,512 -8000051c: 1440a073 csrs sip,ra -80000520: 06400093 li ra,100 -80000524: fff08093 addi ra,ra,-1 -80000528: fe104ee3 bgtz ra,80000524 +80000514: 000020b7 lui ra,0x2 +80000518: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +8000051c: 00000113 li sp,0 +80000520: 3000b073 csrc mstatus,ra +80000524: 30012073 csrs mstatus,sp +80000528: 00000097 auipc ra,0x0 +8000052c: 01408093 addi ra,ra,20 # 8000053c +80000530: 34109073 csrw mepc,ra +80000534: 30200073 mret +80000538: 4f00006f j 80000a28 +8000053c: f00120b7 lui ra,0xf0012 +80000540: 00100113 li sp,1 +80000544: 0020a023 sw sp,0(ra) # f0012000 +80000548: 00000013 nop +8000054c: 00000013 nop +80000550: 00000013 nop +80000554: 00000013 nop +80000558: 00000013 nop +8000055c: 00000013 nop +80000560: 00000013 nop +80000564: 00000013 nop +80000568: 10500073 wfi +8000056c: 4bc0006f j 80000a28 -8000052c : -8000052c: 01500e13 li t3,21 -80000530: 00000f17 auipc t5,0x0 -80000534: 060f0f13 addi t5,t5,96 # 80000590 -80000538: 20000093 li ra,512 -8000053c: 1440b073 csrc sip,ra -80000540: 00200093 li ra,2 -80000544: 30009073 csrw mstatus,ra -80000548: 20000093 li ra,512 -8000054c: 30409073 csrw mie,ra -80000550: 000020b7 lui ra,0x2 -80000554: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -80000558: 00001137 lui sp,0x1 -8000055c: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> -80000560: 3000b073 csrc mstatus,ra -80000564: 30012073 csrs mstatus,sp -80000568: 00000097 auipc ra,0x0 -8000056c: 01408093 addi ra,ra,20 # 8000057c -80000570: 34109073 csrw mepc,ra -80000574: 30200073 mret -80000578: 1700006f j 800006e8 -8000057c: 00100e93 li t4,1 -80000580: 20000093 li ra,512 -80000584: 1440a073 csrs sip,ra -80000588: 10500073 wfi -8000058c: 15c0006f j 800006e8 +80000570 : +80000570: 01100e13 li t3,17 +80000574: 20000093 li ra,512 +80000578: 30309073 csrw mideleg,ra +8000057c: 00000f17 auipc t5,0x0 +80000580: 080f0f13 addi t5,t5,128 # 800005fc +80000584: f00120b7 lui ra,0xf0012 +80000588: 00000113 li sp,0 +8000058c: 0020a023 sw sp,0(ra) # f0012000 +80000590: 00000013 nop +80000594: 00000013 nop +80000598: 00000013 nop +8000059c: 00000013 nop +800005a0: 00000013 nop +800005a4: 00000013 nop +800005a8: 00000013 nop +800005ac: 00000013 nop +800005b0: 00200093 li ra,2 +800005b4: 30009073 csrw mstatus,ra +800005b8: 20000093 li ra,512 +800005bc: 30409073 csrw mie,ra +800005c0: 00000e93 li t4,0 +800005c4: f00120b7 lui ra,0xf0012 +800005c8: 00100113 li sp,1 +800005cc: 0020a023 sw sp,0(ra) # f0012000 +800005d0: 00000013 nop +800005d4: 00000013 nop +800005d8: 00000013 nop +800005dc: 00000013 nop +800005e0: 00000013 nop +800005e4: 00000013 nop +800005e8: 00000013 nop +800005ec: 00000013 nop +800005f0: 06400093 li ra,100 +800005f4: fff08093 addi ra,ra,-1 +800005f8: fe104ee3 bgtz ra,800005f4 -80000590 : -80000590: 01600e13 li t3,22 -80000594: 00000f17 auipc t5,0x0 -80000598: 058f0f13 addi t5,t5,88 # 800005ec -8000059c: 20000093 li ra,512 -800005a0: 1440b073 csrc sip,ra -800005a4: 00200093 li ra,2 -800005a8: 30009073 csrw mstatus,ra -800005ac: 20000093 li ra,512 -800005b0: 30409073 csrw mie,ra -800005b4: 20000093 li ra,512 -800005b8: 1440a073 csrs sip,ra -800005bc: 000020b7 lui ra,0x2 -800005c0: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -800005c4: 00000113 li sp,0 -800005c8: 3000b073 csrc mstatus,ra -800005cc: 30012073 csrs mstatus,sp -800005d0: 00000097 auipc ra,0x0 -800005d4: 01408093 addi ra,ra,20 # 800005e4 -800005d8: 34109073 csrw mepc,ra -800005dc: 30200073 mret -800005e0: 1080006f j 800006e8 -800005e4: 10500073 wfi -800005e8: 1000006f j 800006e8 +800005fc : +800005fc: 01200e13 li t3,18 +80000600: 00000f17 auipc t5,0x0 +80000604: 0a8f0f13 addi t5,t5,168 # 800006a8 +80000608: f00120b7 lui ra,0xf0012 +8000060c: 00000113 li sp,0 +80000610: 0020a023 sw sp,0(ra) # f0012000 +80000614: 00000013 nop +80000618: 00000013 nop +8000061c: 00000013 nop +80000620: 00000013 nop +80000624: 00000013 nop +80000628: 00000013 nop +8000062c: 00000013 nop +80000630: 00000013 nop +80000634: 00200093 li ra,2 +80000638: 30009073 csrw mstatus,ra +8000063c: 20000093 li ra,512 +80000640: 30409073 csrw mie,ra +80000644: 000020b7 lui ra,0x2 +80000648: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +8000064c: 00001137 lui sp,0x1 +80000650: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> +80000654: 3000b073 csrc mstatus,ra +80000658: 30012073 csrs mstatus,sp +8000065c: 00000097 auipc ra,0x0 +80000660: 01408093 addi ra,ra,20 # 80000670 +80000664: 34109073 csrw mepc,ra +80000668: 30200073 mret +8000066c: 3bc0006f j 80000a28 +80000670: 00100e93 li t4,1 +80000674: f00120b7 lui ra,0xf0012 +80000678: 00100113 li sp,1 +8000067c: 0020a023 sw sp,0(ra) # f0012000 +80000680: 00000013 nop +80000684: 00000013 nop +80000688: 00000013 nop +8000068c: 00000013 nop +80000690: 00000013 nop +80000694: 00000013 nop +80000698: 00000013 nop +8000069c: 00000013 nop +800006a0: 10500073 wfi +800006a4: 3840006f j 80000a28 -800005ec : -800005ec: 01700e13 li t3,23 -800005f0: 00000e93 li t4,0 -800005f4: f00120b7 lui ra,0xf0012 -800005f8: 00000113 li sp,0 -800005fc: 0020a023 sw sp,0(ra) # f0012000 -80000600: 20000093 li ra,512 -80000604: 1440b073 csrc sip,ra -80000608: 344021f3 csrr gp,mip -8000060c: f00120b7 lui ra,0xf0012 -80000610: 00100113 li sp,1 -80000614: 0020a023 sw sp,0(ra) # f0012000 -80000618: 20000093 li ra,512 -8000061c: 1440b073 csrc sip,ra -80000620: 344021f3 csrr gp,mip -80000624: f00120b7 lui ra,0xf0012 -80000628: 00000113 li sp,0 -8000062c: 0020a023 sw sp,0(ra) # f0012000 -80000630: 20000093 li ra,512 -80000634: 1440b073 csrc sip,ra -80000638: 344021f3 csrr gp,mip -8000063c: f00120b7 lui ra,0xf0012 -80000640: 00000113 li sp,0 -80000644: 0020a023 sw sp,0(ra) # f0012000 -80000648: 20000093 li ra,512 -8000064c: 1440a073 csrs sip,ra -80000650: 344021f3 csrr gp,mip -80000654: f00120b7 lui ra,0xf0012 -80000658: 00100113 li sp,1 -8000065c: 0020a023 sw sp,0(ra) # f0012000 -80000660: 20000093 li ra,512 -80000664: 1440a073 csrs sip,ra -80000668: 344021f3 csrr gp,mip -8000066c: f00120b7 lui ra,0xf0012 -80000670: 00000113 li sp,0 -80000674: 0020a023 sw sp,0(ra) # f0012000 +800006a8 : +800006a8: 01300e13 li t3,19 +800006ac: 00000f17 auipc t5,0x0 +800006b0: 0a0f0f13 addi t5,t5,160 # 8000074c +800006b4: f00120b7 lui ra,0xf0012 +800006b8: 00000113 li sp,0 +800006bc: 0020a023 sw sp,0(ra) # f0012000 +800006c0: 00000013 nop +800006c4: 00000013 nop +800006c8: 00000013 nop +800006cc: 00000013 nop +800006d0: 00000013 nop +800006d4: 00000013 nop +800006d8: 00000013 nop +800006dc: 00000013 nop +800006e0: 00200093 li ra,2 +800006e4: 30009073 csrw mstatus,ra +800006e8: 20000093 li ra,512 +800006ec: 30409073 csrw mie,ra +800006f0: 000020b7 lui ra,0x2 +800006f4: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +800006f8: 00000113 li sp,0 +800006fc: 3000b073 csrc mstatus,ra +80000700: 30012073 csrs mstatus,sp +80000704: 00000097 auipc ra,0x0 +80000708: 01408093 addi ra,ra,20 # 80000718 +8000070c: 34109073 csrw mepc,ra +80000710: 30200073 mret +80000714: 3140006f j 80000a28 +80000718: f00120b7 lui ra,0xf0012 +8000071c: 00100113 li sp,1 +80000720: 0020a023 sw sp,0(ra) # f0012000 +80000724: 00000013 nop +80000728: 00000013 nop +8000072c: 00000013 nop +80000730: 00000013 nop +80000734: 00000013 nop +80000738: 00000013 nop +8000073c: 00000013 nop +80000740: 00000013 nop +80000744: 10500073 wfi +80000748: 2e00006f j 80000a28 -80000678 : -80000678: 01800e13 li t3,24 -8000067c: 00200093 li ra,2 -80000680: 3040a073 csrs mie,ra -80000684: 3440a073 csrs mip,ra -80000688: 3000a073 csrs mstatus,ra -8000068c: 00100e93 li t4,1 -80000690: 00000f17 auipc t5,0x0 -80000694: 03cf0f13 addi t5,t5,60 # 800006cc -80000698: 000020b7 lui ra,0x2 -8000069c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -800006a0: 00001137 lui sp,0x1 -800006a4: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> -800006a8: 3000b073 csrc mstatus,ra -800006ac: 30012073 csrs mstatus,sp -800006b0: 00000097 auipc ra,0x0 -800006b4: 01408093 addi ra,ra,20 # 800006c4 -800006b8: 34109073 csrw mepc,ra -800006bc: 30200073 mret -800006c0: 0280006f j 800006e8 - -800006c4 : -800006c4: 10500073 wfi -800006c8: 0200006f j 800006e8 - -800006cc : -800006cc: 01900e13 li t3,25 -800006d0: 00000f17 auipc t5,0x0 -800006d4: 014f0f13 addi t5,t5,20 # 800006e4 -800006d8: 30046073 csrsi mstatus,8 -800006dc: 10500073 wfi -800006e0: 0080006f j 800006e8 - -800006e4 : -800006e4: 0100006f j 800006f4 - -800006e8 : -800006e8: f0100137 lui sp,0xf0100 -800006ec: f2410113 addi sp,sp,-220 # f00fff24 -800006f0: 01c12023 sw t3,0(sp) - -800006f4 : -800006f4: f0100137 lui sp,0xf0100 -800006f8: f2010113 addi sp,sp,-224 # f00fff20 -800006fc: 00012023 sw zero,0(sp) - -80000700 : -80000700: fe0e84e3 beqz t4,800006e8 -80000704: 342020f3 csrr ra,mcause -80000708: 341020f3 csrr ra,mepc -8000070c: 300020f3 csrr ra,mstatus -80000710: 343020f3 csrr ra,mtval -80000714: 08000093 li ra,128 -80000718: 3000b073 csrc mstatus,ra -8000071c: 00200093 li ra,2 -80000720: fc1e8ae3 beq t4,ra,800006f4 -80000724: 000020b7 lui ra,0x2 -80000728: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> -8000072c: 3000a073 csrs mstatus,ra -80000730: 341f1073 csrw mepc,t5 -80000734: 30200073 mret - -80000738 : -80000738: fa0e88e3 beqz t4,800006e8 -8000073c: 142020f3 csrr ra,scause -80000740: 141020f3 csrr ra,sepc -80000744: 100020f3 csrr ra,sstatus -80000748: 143020f3 csrr ra,stval -8000074c: 00000073 ecall -80000750: 00000013 nop -80000754: 00000013 nop +8000074c : +8000074c: f00120b7 lui ra,0xf0012 +80000750: 00000113 li sp,0 +80000754: 0020a023 sw sp,0(ra) # f0012000 80000758: 00000013 nop 8000075c: 00000013 nop 80000760: 00000013 nop 80000764: 00000013 nop +80000768: 00000013 nop +8000076c: 00000013 nop +80000770: 00000013 nop +80000774: 00000013 nop +80000778: 01400e13 li t3,20 +8000077c: 00000f17 auipc t5,0x0 +80000780: 030f0f13 addi t5,t5,48 # 800007ac +80000784: 00200093 li ra,2 +80000788: 30009073 csrw mstatus,ra +8000078c: 20000093 li ra,512 +80000790: 30409073 csrw mie,ra +80000794: 00000e93 li t4,0 +80000798: 20000093 li ra,512 +8000079c: 1440a073 csrs sip,ra +800007a0: 06400093 li ra,100 +800007a4: fff08093 addi ra,ra,-1 +800007a8: fe104ee3 bgtz ra,800007a4 + +800007ac : +800007ac: 01500e13 li t3,21 +800007b0: 00000f17 auipc t5,0x0 +800007b4: 060f0f13 addi t5,t5,96 # 80000810 +800007b8: 20000093 li ra,512 +800007bc: 1440b073 csrc sip,ra +800007c0: 00200093 li ra,2 +800007c4: 30009073 csrw mstatus,ra +800007c8: 20000093 li ra,512 +800007cc: 30409073 csrw mie,ra +800007d0: 000020b7 lui ra,0x2 +800007d4: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +800007d8: 00001137 lui sp,0x1 +800007dc: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> +800007e0: 3000b073 csrc mstatus,ra +800007e4: 30012073 csrs mstatus,sp +800007e8: 00000097 auipc ra,0x0 +800007ec: 01408093 addi ra,ra,20 # 800007fc +800007f0: 34109073 csrw mepc,ra +800007f4: 30200073 mret +800007f8: 2300006f j 80000a28 +800007fc: 00100e93 li t4,1 +80000800: 20000093 li ra,512 +80000804: 1440a073 csrs sip,ra +80000808: 10500073 wfi +8000080c: 21c0006f j 80000a28 + +80000810 : +80000810: 01600e13 li t3,22 +80000814: 00000f17 auipc t5,0x0 +80000818: 058f0f13 addi t5,t5,88 # 8000086c +8000081c: 20000093 li ra,512 +80000820: 1440b073 csrc sip,ra +80000824: 00200093 li ra,2 +80000828: 30009073 csrw mstatus,ra +8000082c: 20000093 li ra,512 +80000830: 30409073 csrw mie,ra +80000834: 20000093 li ra,512 +80000838: 1440a073 csrs sip,ra +8000083c: 000020b7 lui ra,0x2 +80000840: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +80000844: 00000113 li sp,0 +80000848: 3000b073 csrc mstatus,ra +8000084c: 30012073 csrs mstatus,sp +80000850: 00000097 auipc ra,0x0 +80000854: 01408093 addi ra,ra,20 # 80000864 +80000858: 34109073 csrw mepc,ra +8000085c: 30200073 mret +80000860: 1c80006f j 80000a28 +80000864: 10500073 wfi +80000868: 1c00006f j 80000a28 + +8000086c : +8000086c: 01700e13 li t3,23 +80000870: 00000e93 li t4,0 +80000874: f00120b7 lui ra,0xf0012 +80000878: 00000113 li sp,0 +8000087c: 0020a023 sw sp,0(ra) # f0012000 +80000880: 00000013 nop +80000884: 00000013 nop +80000888: 00000013 nop +8000088c: 00000013 nop +80000890: 00000013 nop +80000894: 00000013 nop +80000898: 00000013 nop +8000089c: 00000013 nop +800008a0: 20000093 li ra,512 +800008a4: 1440b073 csrc sip,ra +800008a8: 344021f3 csrr gp,mip +800008ac: f00120b7 lui ra,0xf0012 +800008b0: 00100113 li sp,1 +800008b4: 0020a023 sw sp,0(ra) # f0012000 +800008b8: 00000013 nop +800008bc: 00000013 nop +800008c0: 00000013 nop +800008c4: 00000013 nop +800008c8: 00000013 nop +800008cc: 00000013 nop +800008d0: 00000013 nop +800008d4: 00000013 nop +800008d8: 20000093 li ra,512 +800008dc: 1440b073 csrc sip,ra +800008e0: 344021f3 csrr gp,mip +800008e4: f00120b7 lui ra,0xf0012 +800008e8: 00000113 li sp,0 +800008ec: 0020a023 sw sp,0(ra) # f0012000 +800008f0: 00000013 nop +800008f4: 00000013 nop +800008f8: 00000013 nop +800008fc: 00000013 nop +80000900: 00000013 nop +80000904: 00000013 nop +80000908: 00000013 nop +8000090c: 00000013 nop +80000910: 20000093 li ra,512 +80000914: 1440b073 csrc sip,ra +80000918: 344021f3 csrr gp,mip +8000091c: f00120b7 lui ra,0xf0012 +80000920: 00000113 li sp,0 +80000924: 0020a023 sw sp,0(ra) # f0012000 +80000928: 00000013 nop +8000092c: 00000013 nop +80000930: 00000013 nop +80000934: 00000013 nop +80000938: 00000013 nop +8000093c: 00000013 nop +80000940: 00000013 nop +80000944: 00000013 nop +80000948: 20000093 li ra,512 +8000094c: 1440a073 csrs sip,ra +80000950: 344021f3 csrr gp,mip +80000954: f00120b7 lui ra,0xf0012 +80000958: 00100113 li sp,1 +8000095c: 0020a023 sw sp,0(ra) # f0012000 +80000960: 00000013 nop +80000964: 00000013 nop +80000968: 00000013 nop +8000096c: 00000013 nop +80000970: 00000013 nop +80000974: 00000013 nop +80000978: 00000013 nop +8000097c: 00000013 nop +80000980: 20000093 li ra,512 +80000984: 1440a073 csrs sip,ra +80000988: 344021f3 csrr gp,mip +8000098c: f00120b7 lui ra,0xf0012 +80000990: 00000113 li sp,0 +80000994: 0020a023 sw sp,0(ra) # f0012000 +80000998: 00000013 nop +8000099c: 00000013 nop +800009a0: 00000013 nop +800009a4: 00000013 nop +800009a8: 00000013 nop +800009ac: 00000013 nop +800009b0: 00000013 nop +800009b4: 00000013 nop + +800009b8 : +800009b8: 01800e13 li t3,24 +800009bc: 00200093 li ra,2 +800009c0: 3040a073 csrs mie,ra +800009c4: 3440a073 csrs mip,ra +800009c8: 3000a073 csrs mstatus,ra +800009cc: 00100e93 li t4,1 +800009d0: 00000f17 auipc t5,0x0 +800009d4: 03cf0f13 addi t5,t5,60 # 80000a0c +800009d8: 000020b7 lui ra,0x2 +800009dc: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +800009e0: 00001137 lui sp,0x1 +800009e4: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800> +800009e8: 3000b073 csrc mstatus,ra +800009ec: 30012073 csrs mstatus,sp +800009f0: 00000097 auipc ra,0x0 +800009f4: 01408093 addi ra,ra,20 # 80000a04 +800009f8: 34109073 csrw mepc,ra +800009fc: 30200073 mret +80000a00: 0280006f j 80000a28 + +80000a04 : +80000a04: 10500073 wfi +80000a08: 0200006f j 80000a28 + +80000a0c : +80000a0c: 01900e13 li t3,25 +80000a10: 00000f17 auipc t5,0x0 +80000a14: 014f0f13 addi t5,t5,20 # 80000a24 +80000a18: 30046073 csrsi mstatus,8 +80000a1c: 10500073 wfi +80000a20: 0080006f j 80000a28 + +80000a24 : +80000a24: 0100006f j 80000a34 + +80000a28 : +80000a28: f0100137 lui sp,0xf0100 +80000a2c: f2410113 addi sp,sp,-220 # f00fff24 +80000a30: 01c12023 sw t3,0(sp) + +80000a34 : +80000a34: f0100137 lui sp,0xf0100 +80000a38: f2010113 addi sp,sp,-224 # f00fff20 +80000a3c: 00012023 sw zero,0(sp) + +80000a40 : +80000a40: fe0e84e3 beqz t4,80000a28 +80000a44: 342020f3 csrr ra,mcause +80000a48: 341020f3 csrr ra,mepc +80000a4c: 300020f3 csrr ra,mstatus +80000a50: 343020f3 csrr ra,mbadaddr +80000a54: 08000093 li ra,128 +80000a58: 3000b073 csrc mstatus,ra +80000a5c: 00200093 li ra,2 +80000a60: fc1e8ae3 beq t4,ra,80000a34 +80000a64: 000020b7 lui ra,0x2 +80000a68: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800> +80000a6c: 3000a073 csrs mstatus,ra +80000a70: 341f1073 csrw mepc,t5 +80000a74: 30200073 mret + +80000a78 : +80000a78: fa0e88e3 beqz t4,80000a28 +80000a7c: 142020f3 csrr ra,scause +80000a80: 141020f3 csrr ra,sepc +80000a84: 100020f3 csrr ra,sstatus +80000a88: 143020f3 csrr ra,sbadaddr +80000a8c: 00000073 ecall +80000a90: 00000013 nop +80000a94: 00000013 nop +80000a98: 00000013 nop +80000a9c: 00000013 nop +80000aa0: 00000013 nop +80000aa4: 00000013 nop diff --git a/src/test/cpp/raw/deleg/build/deleg.hex b/src/test/cpp/raw/deleg/build/deleg.hex index ba5fc06..9290e85 100644 --- a/src/test/cpp/raw/deleg/build/deleg.hex +++ b/src/test/cpp/raw/deleg/build/deleg.hex @@ -1,122 +1,174 @@ :0200000480007A -:10000000930E1000970000009380C06F73905030E3 -:10001000970000009380807273905010B71001F029 -:100020001301000023A02000130E1000170F000082 -:10003000130FCF0073000000130E2000B720000044 -:10004000938000801301000073B0003073200130F2 -:1000500097000000938040017390103473002030AB -:100060006F008068170F0000130F4F02730000002D -:100070006F008067130E3000170F0000130F0F0181 -:10008000832010006F004066130E4000B720000070 -:1000900093800080371100001301018073B000309D -:1000A000732001309700000093804001739010345A -:1000B000730020306F004063170F0000130F0F0113 -:1000C000832010006F004062130E5000B720000024 -:1000D000938000801301000073B000307320013062 -:1000E000970000009380400173901034730020301B -:1000F0006F00805F170F0000130F0F0183201000A7 -:100100006F00805E130E600093000001739020303A -:10011000130E7000170F0000130F0F018320100043 -:100120006F00805C130E8000170F0000130FCF03C9 -:10013000B720000093800080371100001301018078 -:1001400073B00030732001309700000093804001AD -:1001500073901034730020306F000059832010001A -:100160006F008058130E9000170F0000130F8F03BD -:10017000B7200000938000801301000073B00030AE -:100180007320013097000000938040017390103479 -:10019000730020306F004055832010006F00C05462 -:1001A000130EA000170F0000130FCF03B71001F0BC -:1001B0001301000023A02000930080007390003002 -:1001C000B71000009380008073904030B71001F0AA -:1001D0001301100023A02000730050106F00C050C6 -:1001E000130EB000170F0000130F8F06B71001F0A9 -:1001F0001301000023A020009300800073900030C2 -:10020000B71000009380008073904030B72000004A -:1002100093800080371100001301018073B000301B -:1002200073200130970000009380400173901034D8 -:10023000730020306F00404BB71001F01301100025 -:1002400023A02000730050106F00004A130EC0005E -:10025000170F0000130F4F06B71001F01301000035 -:1002600023A020009300800073900030B71000009E -:100270009380008073904030B7200000938000800E -:100280001301000073B000307320013097000000AC -:100290009380400173901034730020306F00C0448D -:1002A000B71001F01301100023A0200073005010BC -:1002B0006F0080439300200073900010130EE00045 -:1002C000170F0000130F0F04B72001F013010000F7 -:1002D00023A02000930020007390003093000020A2 -:1002E00073904030930E0000B72001F0130110000E -:1002F00023A02000930040069380F0FFE34E10FE01 -:10030000130EF000170F0000130F8F06B72001F037 -:100310001301000023A02000930020007390003000 -:100320009300002073904030B7200000938000803D -:10033000371100001301018073B0003073200130C9 -:1003400097000000938040017390103473002030B8 -:100350006F008039930E1000B72001F013011000D8 -:1003600023A02000730050106F000038130E00010E -:10037000170F0000130F0F06B72001F01301000044 -:1003800023A02000930020007390003093000020F1 -:1003900073904030B720000093800080130100006C -:1003A00073B000307320013097000000938040014B -:1003B00073901034730020306F000033B72001F0C9 -:1003C0001301100023A02000730050106F00C031F3 -:1003D000130E10019300002073903030170F0000AF -:1003E000130F0F04B72001F01301000023A0200019 -:1003F00093002000739000309300002073904030F1 -:10040000930E0000B72001F01301100023A020007C -:10041000930040069380F0FFE34E10FE130E200180 -:10042000170F0000130F8F06B72001F01301000013 -:1004300023A0200093002000739000309300002040 -:1004400073904030B7200000938000803711000087 -:100450001301018073B00030732001309700000059 -:100460009380400173901034730020306F00C027D8 -:10047000930E1000B72001F01301100023A02000FC -:10048000730050106F004026130E3001170F00004C -:10049000130F0F06B72001F01301000023A0200066 -:1004A0009300200073900030930000207390403040 -:1004B000B7200000938000801301000073B000306B -:1004C0007320013097000000938040017390103436 -:1004D000730020306F004021B72001F0130110009D -:1004E00023A02000730050106F000020B72001F0FF -:1004F0001301000023A02000130E4001170F00007D -:10050000130F0F039300200073900030930000201E -:1005100073904030930E00009300002073A04014AD -:10052000930040069380F0FFE34E10FE130E50013F -:10053000170F0000130F0F069300002073B0401434 -:10054000930020007390003093000020739040309F -:10055000B720000093800080371100001301018054 -:1005600073B0003073200130970000009380400189 -:1005700073901034730020306F000017930E10003A -:100580009300002073A04014730050106F00C0153A -:10059000130E6001170F0000130F8F05930000204A -:1005A00073B040149300200073900030930000203B -:1005B000739040309300002073A04014B7200000D7 -:1005C000938000801301000073B00030732001306D -:1005D0009700000093804001739010347300203026 -:1005E0006F008010730050106F000010130E700128 -:1005F000930E0000B72001F01301000023A020009B -:100600009300002073B04014F3214034B72001F070 -:100610001301100023A020009300002073B04014A9 -:10062000F3214034B72001F01301000023A0200083 -:100630009300002073B04014F3214034B72001F040 -:100640001301000023A020009300002073A0401499 -:10065000F3214034B72001F01301100023A0200043 -:100660009300002073A04014F3214034B72001F020 -:100670001301000023A02000130E8001930020002E -:1006800073A0403073A0403473A00030930E10006C -:10069000170F0000130FCF03B720000093800080D6 -:1006A000371100001301018073B000307320013056 -:1006B0009700000093804001739010347300203045 -:1006C0006F008002730050106F000002130E900143 -:1006D000170F0000130F4F017360043073005010A8 -:1006E0006F0080006F000001370110F0130141F22C -:1006F0002320C101370110F0130101F22320010072 -:10070000E3840EFEF3202034F3201034F320003075 -:10071000F32030349300000873B0003093002000C1 -:10072000E38A1EFCB72000009380008073A0003095 -:1007300073101F3473002030E3880EFAF320201466 -:10074000F3201014F3200010F32030147300000085 -:10075000130000001300000013000000130000004D -:0807600013000000130000006B +:10000000930E1000971000009380C0A3739050309F +:1000100097100000938080A673905010B71001F0E5 +:100020001301000023A020001300000013000000B3 +:100030001300000013000000130000001300000074 +:100040001300000013000000130E1000170F000033 +:10005000130FCF0073000000130E2000B720000024 +:10006000938000801301000073B0003073200130D2 +:10007000970000009380400173901034730020308B +:100080006F00901A170F0000130F4F02730000004B +:100090006F009019130E3000170F0000130F0F019F +:1000A000832010006F005018130E4000B72000008E +:1000B00093800080371100001301018073B000307D +:1000C000732001309700000093804001739010343A +:1000D000730020306F005015170F0000130F0F0131 +:1000E000832010006F005014130E5000B720000042 +:1000F000938000801301000073B000307320013042 +:1001000097000000938040017390103473002030FA +:100110006F009011170F0000130F0F0183201000C4 +:100120006F009010130E6000930000017390203058 +:10013000130E7000170F0000130F0F018320100023 +:100140006F00900E130E8000170F0000130FCF03E7 +:10015000B720000093800080371100001301018058 +:1001600073B000307320013097000000938040018D +:1001700073901034730020306F00100B8320100038 +:100180006F00900A130E9000170F0000130F8F03DB +:10019000B7200000938000801301000073B000308E +:1001A0007320013097000000938040017390103459 +:1001B000730020306F005007832010006F00D006BE +:1001C000130EA000170F0000130FCF07B71001F098 +:1001D0001301000023A02000130000001300000002 +:1001E00013000000130000001300000013000000C3 +:1001F0001300000013000000930080007390003093 +:10020000B71000009380008073904030B71001F069 +:100210001301100023A020001300000013000000B1 +:100220001300000013000000130000001300000082 +:100230001300000013000000730050106F00C07E18 +:10024000130EB000170F0000130F8F0AB71001F044 +:100250001301000023A02000130000001300000081 +:100260001300000013000000130000001300000042 +:100270001300000013000000930080007390003012 +:10028000B71000009380008073904030B7200000CA +:1002900093800080371100001301018073B000309B +:1002A0007320013097000000938040017390103458 +:1002B000730020306F004077B71001F01301100079 +:1002C00023A0200013000000130000001300000012 +:1002D00013000000130000001300000013000000D2 +:1002E00013000000730050106F000074130EC00064 +:1002F000170F0000130F4F0AB71001F01301000091 +:1003000023A02000130000001300000013000000D1 +:100310001300000013000000130000001300000091 +:10032000130000009300800073900030B7100000AD +:100330009380008073904030B7200000938000804D +:100340001301000073B000307320013097000000EB +:100350009380400173901034730020306F00C06CA4 +:10036000B71001F01301100023A0200013000000BB +:100370001300000013000000130000001300000031 +:100380001300000013000000130000007300501061 +:100390006F0080699300200073900010130EE0003E +:1003A000170F0000130F0F08B72001F01301000012 +:1003B00023A0200013000000130000001300000021 +:1003C00013000000130000001300000013000000E1 +:1003D0001300000093002000739000309300002071 +:1003E00073904030930E0000B72001F0130110000D +:1003F00023A02000130000001300000013000000E1 +:1004000013000000130000001300000013000000A0 +:1004100013000000930040069380F0FFE34E10FEAF +:10042000130EF000170F0000130F8F0AB72001F012 +:100430001301000023A0200013000000130000009F +:100440001300000013000000130000001300000060 +:100450001300000013000000930020007390003090 +:100460009300002073904030B720000093800080FC +:10047000371100001301018073B000307320013088 +:100480009700000093804001739010347300203077 +:100490006F008059930E1000B72001F01301100077 +:1004A00023A0200013000000130000001300000030 +:1004B00013000000130000001300000013000000F0 +:1004C00013000000730050106F000056130E00015F +:1004D000170F0000130F0F0AB72001F013010000DF +:1004E00023A02000130000001300000013000000F0 +:1004F00013000000130000001300000013000000B0 +:10050000130000009300200073900030930000203F +:1005100073904030B72000009380008013010000EA +:1005200073B00030732001309700000093804001C9 +:1005300073901034730020306F00004FB72001F02B +:100540001301100023A0200013000000130000007E +:10055000130000001300000013000000130000004F +:100560001300000013000000730050106F00C04B18 +:10057000130E10019300002073903030170F00000D +:10058000130F0F08B72001F01301000023A0200073 +:10059000130000001300000013000000130000000F +:1005A00013000000130000001300000013000000FF +:1005B000930020007390003093000020739040302F +:1005C000930E0000B72001F01301100023A02000BB +:1005D00013000000130000001300000013000000CF +:1005E00013000000130000001300000013000000BF +:1005F000930040069380F0FFE34E10FE130E20019F +:10060000170F0000130F8F0AB72001F0130100002D +:1006100023A02000130000001300000013000000BE +:10062000130000001300000013000000130000007E +:10063000130000009300200073900030930000200E +:1006400073904030B7200000938000803711000085 +:100650001301018073B00030732001309700000057 +:100660009380400173901034730020306F00C03BC2 +:10067000930E1000B72001F01301100023A02000FA +:10068000130000001300000013000000130000001E +:10069000130000001300000013000000130000000E +:1006A000730050106F004038130E3001170F000018 +:1006B000130F0F0AB72001F01301000023A0200040 +:1006C00013000000130000001300000013000000DE +:1006D00013000000130000001300000013000000CE +:1006E00093002000739000309300002073904030FE +:1006F000B7200000938000801301000073B0003029 +:1007000073200130970000009380400173901034F3 +:10071000730020306F004031B72001F0130110004A +:1007200023A02000130000001300000013000000AD +:10073000130000001300000013000000130000006D +:1007400013000000730050106F00002EB72001F05E +:100750001301000023A0200013000000130000007C +:10076000130000001300000013000000130000003D +:100770001300000013000000130E4001170F0000CB +:10078000130F0F039300200073900030930000209C +:1007900073904030930E00009300002073A040142B +:1007A000930040069380F0FFE34E10FE130E5001BD +:1007B000170F0000130F0F069300002073B04014B2 +:1007C000930020007390003093000020739040301D +:1007D000B7200000938000803711000013010180D2 +:1007E00073B0003073200130970000009380400107 +:1007F00073901034730020306F000023930E1000AC +:100800009300002073A04014730050106F00C021AB +:10081000130E6001170F0000130F8F0593000020C7 +:1008200073B04014930020007390003093000020B8 +:10083000739040309300002073A04014B720000054 +:10084000938000801301000073B0003073200130EA +:1008500097000000938040017390103473002030A3 +:100860006F00801C730050106F00001C130E70018D +:10087000930E0000B72001F01301000023A0200018 +:10088000130000001300000013000000130000001C +:10089000130000001300000013000000130000000C +:1008A0009300002073B04014F3214034B72001F0CE +:1008B0001301100023A0200013000000130000000B +:1008C00013000000130000001300000013000000DC +:1008D00013000000130000009300002073B04014C8 +:1008E000F3214034B72001F01301000023A02000C1 +:1008F00013000000130000001300000013000000AC +:10090000130000001300000013000000130000009B +:100910009300002073B04014F3214034B72001F05D +:100920001301000023A020001300000013000000AA +:10093000130000001300000013000000130000006B +:1009400013000000130000009300002073A0401467 +:10095000F3214034B72001F01301100023A0200040 +:10096000130000001300000013000000130000003B +:10097000130000001300000013000000130000002B +:100980009300002073A04014F3214034B72001F0FD +:100990001301000023A0200013000000130000003A +:1009A00013000000130000001300000013000000FB +:1009B0001300000013000000130E800193002000BC +:1009C00073A0403073A0403473A00030930E100029 +:1009D000170F0000130FCF03B72000009380008093 +:1009E000371100001301018073B000307320013013 +:1009F0009700000093804001739010347300203002 +:100A00006F008002730050106F000002130E9001FF +:100A1000170F0000130F4F01736004307300501064 +:100A20006F0080006F000001370110F0130141F2E8 +:100A30002320C101370110F0130101F2232001002E +:100A4000E3840EFEF3202034F3201034F320003032 +:100A5000F32030349300000873B00030930020007E +:100A6000E38A1EFCB72000009380008073A0003052 +:100A700073101F3473002030E3880EFAF320201423 +:100A8000F3201014F3200010F32030147300000042 +:100A9000130000001300000013000000130000000A +:080AA000130000001300000028 :040000058000000077 :00000001FF diff --git a/src/test/cpp/raw/deleg/src/crt.S b/src/test/cpp/raw/deleg/src/crt.S index 86dd58f..f88d13f 100644 --- a/src/test/cpp/raw/deleg/src/crt.S +++ b/src/test/cpp/raw/deleg/src/crt.S @@ -10,11 +10,28 @@ li x1, 0xF0011000; \ li x2, value; \ sw x2, 0(x1); \ + nop; \ + nop; \ + nop; \ + nop; \ + nop; \ + nop; \ + nop; \ + nop; \ + #define externalInterruptS(value) \ li x1, 0xF0012000; \ li x2, value; \ sw x2, 0(x1); \ + nop; \ + nop; \ + nop; \ + nop; \ + nop; \ + nop; \ + nop; \ + nop; \ From f63c4db469926ee4b8ba84f13749893052c5d237 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Tue, 18 Feb 2020 00:59:39 +0100 Subject: [PATCH 14/51] Fix CsrPlugin pipeline liberator --- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 98dfbaa..7d98bb9 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -808,17 +808,29 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep //Used to make the pipeline empty softly (for interrupts) val pipelineLiberator = new Area{ - when(interrupt.valid && allowInterrupts){ - decode.arbitration.haltByOther := decode.arbitration.isValid + val pcValids = Vec(RegInit(False), stagesFromExecute.length) + val active = interrupt.valid && allowInterrupts && decode.arbitration.isValid + when(active){ + decode.arbitration.haltByOther := True + for((stage, reg, previous) <- (stagesFromExecute, pcValids, True :: pcValids.toList).zipped){ + when(!stage.arbitration.isStuck){ + reg := previous + } + } + } + when(!active || decode.arbitration.isRemoved) { + pcValids.foreach(_ := False) } - val done = !stagesFromExecute.map(_.arbitration.isValid).orR && fetcher.pcValid(mepcCaptureStage) +// val pcValids = for(stage <- stagesFromExecute) yield RegInit(False) clearWhen(!started) setWhen(!stage.arbitration.isValid) + val done = CombInit(pcValids.last) if(exceptionPortCtrl != null) done.clearWhen(exceptionPortCtrl.exceptionValidsRegs.tail.orR) } //Interrupt/Exception entry logic val interruptJump = Bool.addTag(Verilator.public) interruptJump := interrupt.valid && pipelineLiberator.done && allowInterrupts + if(pipelinedInterrupt) interrupt.valid clearWhen(interruptJump) //avoid double fireing val hadException = RegNext(exception) init(False) pipelineLiberator.done.clearWhen(hadException) From a7440426fd6fd8c1b80b816a0c63a70ed4412e9d Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Tue, 18 Feb 2020 01:00:11 +0100 Subject: [PATCH 15/51] Fix FetchPlugin redo gen condition Fix injectorFailure reset --- src/main/scala/vexriscv/plugin/Fetcher.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index f933ab9..065f01f 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -129,7 +129,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val inc = RegInit(False) clearWhen(corrected || pcRegPropagate) setWhen(output.fire) clearWhen(!output.valid && output.ready) val pc = pcReg + (inc ## B"00").asUInt val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) - val redo = fetchRedoGen generate Flow(UInt(32 bits)) + val redo = (fetchRedoGen || prediction == DYNAMIC_TARGET) generate Flow(UInt(32 bits)) val flushed = False if(compressedGen) when(inc) { @@ -142,7 +142,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pc := predictionPcLoad.payload } } - if(fetchRedoGen) when(redo.valid){ + if(redo != null) when(redo.valid){ corrected := True pc := redo.payload flushed := True @@ -216,8 +216,10 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, s.output << s.input.haltWhen(s.halt) } - fetchPc.redo.valid := redoFetch - fetchPc.redo.payload := stages.last.input.payload + if(fetchPc.redo != null) { + fetchPc.redo.valid := redoFetch + fetchPc.redo.payload := stages.last.input.payload + } stages.head.flush := False //getFlushAt(IBUS_RSP, stages.head == stages.last) || fetchFlush for((s,sNext) <- (stages, stages.tail).zipped) { @@ -579,7 +581,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) val unalignedWordIssue = decompressor.bufferFill && decompressor.input.rsp.inst(17 downto 16) === 3 && predictionBranch val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt) - val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) + val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready, init=False) val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid when(injectorFailure || bypassFailure){ From a684d5e4d172e649a388e9d33b4e4e03c4754883 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Wed, 19 Feb 2020 01:20:52 +0100 Subject: [PATCH 16/51] Rework/clean decompressor logic --- src/main/scala/vexriscv/plugin/Fetcher.scala | 37 ++++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 065f01f..5c2c5dd 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -43,7 +43,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, injectionPort = Stream(Bits(32 bits)) injectionPort } - def pcRegReusedForSecondStage = allowPcRegReusedForSecondStage && prediction != DYNAMIC_TARGET + def pcRegReusedForSecondStage = allowPcRegReusedForSecondStage && prediction != DYNAMIC_TARGET //TODO might not be required for DYNAMIC_TARGET var predictionJumpInterface : Flow[UInt] = null override def haltIt(): Unit = fetcherHalt := True @@ -253,32 +253,31 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, whenFalse = input.rsp.inst(31 downto 16) ## (input.pc(1) ? input.rsp.inst(31 downto 16) | input.rsp.inst(15 downto 0)) ) val isRvc = raw(1 downto 0) =/= 3 + val isBufferRvc = bufferData(1 downto 0) =/= 3 val decompressed = RvcDecompressor(raw(15 downto 0)) - output.valid := (isRvc ? (bufferValid || input.valid) | (input.valid && (bufferValid || !input.pc(1)))) + output.valid := bufferValid ? (isBufferRvc || input.valid) | (input.valid && (!input.pc(1) || input.rsp.inst(17 downto 16) =/= 3)) output.pc := input.pc output.isRvc := isRvc output.rsp.inst := isRvc ? decompressed | raw - input.ready := !output.valid || !(!output.ready || (isRvc && !input.pc(1) && input.rsp.inst(16, 2 bits) =/= 3) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3)) - addPrePopTask(() => { - when(!input.ready && output.fire && !flush /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) { - input.pc.getDrivingReg(1) := True - } - }) + input.ready := output.ready && !(bufferValid && isBufferRvc) - bufferValid clearWhen(output.fire) val bufferFill = False - when(input.fire){ - when(!(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1) && output.ready)) { - bufferValid := True - bufferFill := True - } otherwise { - bufferValid := False - } - bufferData := input.rsp.inst(31 downto 16) + when(output.ready && (isBufferRvc || input.valid)){ + bufferValid := False } + when(output.ready && input.valid){ + bufferData := input.rsp.inst(31 downto 16) + when((!bufferValid && !input.pc(1) && input.rsp.inst(1 downto 0) =/= 3) || (bufferValid && !isBufferRvc) || (input.pc(1) && input.rsp.inst(17 downto 16) === 3)){ + bufferFill := True + bufferValid := True + } + } + bufferValid.clearWhen(flush) - iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending - incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3) + when(bufferValid && isBufferRvc){ + iBusRsp.readyForError := False + incomingInstruction := True + } }) From 59508d5b5736848eae2eed229d01b7566dbcf8d1 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Thu, 20 Feb 2020 02:27:57 +0100 Subject: [PATCH 17/51] Fix target branch prediction for RVC, all default configs pass dhrystone --- src/main/scala/vexriscv/plugin/Fetcher.scala | 56 +++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 5c2c5dd..3106e99 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -247,36 +247,42 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val bufferValid = RegInit(False) val bufferData = Reg(Bits(16 bits)) + + val isInputLowRvc = input.rsp.inst(1 downto 0) =/= 3 + val isInputHighRvc = input.rsp.inst(17 downto 16) =/= 3 + val doubleRvc = iBusRsp.stages.last.input.valid && !bufferValid && isInputLowRvc && isInputHighRvc && !input.pc(1) + val throw2BytesReg = RegInit(False) + val throw2Bytes = throw2BytesReg || input.pc(1) + val unaligned = throw2Bytes || bufferValid + def aligned = !unaligned val raw = Mux( sel = bufferValid, whenTrue = input.rsp.inst(15 downto 0) ## bufferData, - whenFalse = input.rsp.inst(31 downto 16) ## (input.pc(1) ? input.rsp.inst(31 downto 16) | input.rsp.inst(15 downto 0)) + whenFalse = input.rsp.inst(31 downto 16) ## (throw2Bytes ? input.rsp.inst(31 downto 16) | input.rsp.inst(15 downto 0)) ) val isRvc = raw(1 downto 0) =/= 3 - val isBufferRvc = bufferData(1 downto 0) =/= 3 val decompressed = RvcDecompressor(raw(15 downto 0)) - output.valid := bufferValid ? (isBufferRvc || input.valid) | (input.valid && (!input.pc(1) || input.rsp.inst(17 downto 16) =/= 3)) + output.valid := input.valid && !(throw2Bytes && !bufferValid && !isInputHighRvc) output.pc := input.pc output.isRvc := isRvc output.rsp.inst := isRvc ? decompressed | raw - input.ready := output.ready && !(bufferValid && isBufferRvc) + input.ready := output.ready && (!iBusRsp.stages.last.input.valid || (!(bufferValid && isInputHighRvc) && !(aligned && isInputLowRvc && isInputHighRvc))) - val bufferFill = False - when(output.ready && (isBufferRvc || input.valid)){ + when(output.fire){ + throw2BytesReg := (aligned && isInputLowRvc && isInputHighRvc) || (bufferValid && isInputHighRvc) + } + val bufferFill = (aligned && isInputLowRvc && !isInputHighRvc) || (bufferValid && !isInputHighRvc) || (throw2Bytes && !isRvc && !isInputHighRvc) + when(output.ready && input.valid){ bufferValid := False } when(output.ready && input.valid){ bufferData := input.rsp.inst(31 downto 16) - when((!bufferValid && !input.pc(1) && input.rsp.inst(1 downto 0) =/= 3) || (bufferValid && !isBufferRvc) || (input.pc(1) && input.rsp.inst(17 downto 16) === 3)){ - bufferFill := True - bufferValid := True - } + bufferValid setWhen(bufferFill) } - bufferValid.clearWhen(flush) - when(bufferValid && isBufferRvc){ - iBusRsp.readyForError := False - incomingInstruction := True + when(flush){ + throw2BytesReg := False + bufferValid := False } }) @@ -504,7 +510,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val source = Bits(30 - historyRamSizeLog2 bits) val branchWish = UInt(2 bits) val target = UInt(32 bits) - val unaligned = ifGen(compressedGen)(Bool) + val last2Bytes = ifGen(compressedGen)(Bool) } val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) @@ -515,6 +521,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready) val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) + if(compressedGen) hit clearWhen(!line.last2Bytes && iBusRsp.stages(1).input.payload(1)) fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).input.valid fetchPc.predictionPcLoad.payload := line.target @@ -533,14 +540,16 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val (decompressorContext, injectorContext) = stage1ToInjectorPipe(fetchContext) if(compressedGen) { //prediction hit on the right instruction into words - decompressorContext.hit clearWhen(decompressorContext.line.unaligned && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.input.pc(1)))) + decompressorContext.hit clearWhen(decompressorContext.line.last2Bytes && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.throw2Bytes))) decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire decodePc.predictionPcLoad.payload := injectorContext.line.target + //Clean the RVC buffer when a prediction was made when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){ decompressor.bufferValid := False - decompressor.input.ready := True + decompressor.throw2BytesReg := False + decompressor.input.ready := True //Drop the remaining byte if any } } @@ -557,7 +566,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, historyWrite.address := fetchPrediction.rsp.sourceLastWord(2, historyRamSizeLog2 bits) historyWrite.data.source := fetchPrediction.rsp.sourceLastWord.asBits >> 2 + historyRamSizeLog2 historyWrite.data.target := fetchPrediction.rsp.finalPc - if(compressedGen) historyWrite.data.unaligned := !fetchPrediction.stage.input(PC)(1) ^ fetchPrediction.stage.input(IS_RVC) + if(compressedGen) historyWrite.data.last2Bytes := fetchPrediction.stage.input(PC)(1) && fetchPrediction.stage.input(IS_RVC) when(fetchPrediction.rsp.wasRight) { historyWrite.valid := branchContext.hit @@ -574,18 +583,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring) - - val predictionFailure = ifGen(compressedGen)(new Area{ val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) - val unalignedWordIssue = decompressor.bufferFill && decompressor.input.rsp.inst(17 downto 16) === 3 && predictionBranch - val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt) - val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready, init=False) - val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid + val unalignedWordIssue = iBusRsp.output.valid && predictionBranch && decompressor.throw2Bytes && !decompressor.isInputHighRvc - when(injectorFailure || bypassFailure){ + when(unalignedWordIssue){ historyWrite.valid := True - historyWrite.address := (decode.input(PC) >> 2).resized + historyWrite.address := (iBusRsp.stages(1).input.payload >> 2).resized historyWrite.data.branchWish := 0 iBusRsp.redoFetch := True From 32fade50e54609d8406f32222d92cafdf44b6211 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 21 Feb 2020 02:03:29 +0100 Subject: [PATCH 18/51] Fix fetcher decompressor when driving decode stage --- src/main/scala/vexriscv/plugin/Fetcher.scala | 20 +++++++++---------- .../vexriscv/plugin/IBusSimplePlugin.scala | 3 ++- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 3106e99..0c61fa1 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -88,8 +88,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, def isDrivingDecode(s : Any): Boolean = { if(injectorStage) return s == INJECTOR_M2S - if(compressedGen) return s == DECOMPRESSOR - s == IBUS_RSP + s == IBUS_RSP || s == DECOMPRESSOR } def getFlushAt(s : Any, lastCond : Boolean = true): Bool = { @@ -240,9 +239,11 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } val decompressor = ifGen(decodePcGen)(new Area{ - val input = iBusRsp.output.clearValidWhen(iBusRsp.stages.last.flush) + val input = iBusRsp.output.clearValidWhen(iBusRsp.redoFetch) val output = Stream(FetchRsp()) val flush = getFlushAt(DECOMPRESSOR) + val flushNext = if(isDrivingDecode(DECOMPRESSOR)) decode.arbitration.flushNext else False + val consumeCurrent = if(isDrivingDecode(DECOMPRESSOR)) flushNext && output.ready else False val bufferValid = RegInit(False) val bufferData = Reg(Bits(16 bits)) @@ -250,7 +251,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val isInputLowRvc = input.rsp.inst(1 downto 0) =/= 3 val isInputHighRvc = input.rsp.inst(17 downto 16) =/= 3 - val doubleRvc = iBusRsp.stages.last.input.valid && !bufferValid && isInputLowRvc && isInputHighRvc && !input.pc(1) val throw2BytesReg = RegInit(False) val throw2Bytes = throw2BytesReg || input.pc(1) val unaligned = throw2Bytes || bufferValid @@ -266,7 +266,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, output.pc := input.pc output.isRvc := isRvc output.rsp.inst := isRvc ? decompressed | raw - input.ready := output.ready && (!iBusRsp.stages.last.input.valid || (!(bufferValid && isInputHighRvc) && !(aligned && isInputLowRvc && isInputHighRvc))) + input.ready := output.ready && (!iBusRsp.stages.last.input.valid || flushNext || (!(bufferValid && isInputHighRvc) && !(aligned && isInputLowRvc && isInputHighRvc))) when(output.fire){ throw2BytesReg := (aligned && isInputLowRvc && isInputHighRvc) || (bufferValid && isInputHighRvc) @@ -280,7 +280,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, bufferValid setWhen(bufferFill) } - when(flush){ + when(flush || consumeCurrent){ throw2BytesReg := False bufferValid := False } @@ -495,13 +495,11 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } //TODO no more fireing depedancies - predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch //TODO OH Doublon de priorité + predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt - if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) + decode.arbitration.flushNext setWhen(predictionJumpInterface.valid) - when(predictionJumpInterface.valid && decode.arbitration.isFiring){ - flushIt() - } + if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) } case DYNAMIC_TARGET => new Area{ // assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air") diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 319634d..8681b9c 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -352,7 +352,8 @@ class IBusSimplePlugin( resetVector : BigInt, val rspBuffer = if(!rspHoldValue) new Area{ val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0)) c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream - c.io.flush := fetcherflushIt + c.io.flush := iBusRsp.stages.last.flush + if(compressedGen) c.io.flush setWhen(decompressor.consumeCurrent) rspBufferOutput << c.io.pop } else new Area{ val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream From befc54a444b7ddbe61c4d456c8a2981fd40d221f Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 21 Feb 2020 13:28:29 +0100 Subject: [PATCH 19/51] No more Fetcher flush() API as it can now be done via the decoder.flushNext --- src/main/scala/vexriscv/Services.scala | 1 - src/main/scala/vexriscv/ip/InstructionCache.scala | 2 +- src/main/scala/vexriscv/plugin/DebugPlugin.scala | 1 - src/main/scala/vexriscv/plugin/Fetcher.scala | 15 +++++++-------- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index 09cd098..4b0aeca 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -13,7 +13,6 @@ trait JumpService{ trait IBusFetcher{ def haltIt() : Unit - def flushIt() : Unit def incoming() : Bool def pcValid(stage : Stage) : Bool def getInjectionPort() : Stream[Bits] diff --git a/src/main/scala/vexriscv/ip/InstructionCache.scala b/src/main/scala/vexriscv/ip/InstructionCache.scala index 0a809c6..4df0f79 100644 --- a/src/main/scala/vexriscv/ip/InstructionCache.scala +++ b/src/main/scala/vexriscv/ip/InstructionCache.scala @@ -114,7 +114,7 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w val mmuBus = MemoryTranslatorBus() val physicalAddress = UInt(p.addressWidth bits) val cacheMiss, error, mmuRefilling, mmuException, isUser = ifGen(!p.twoCycleCache)(Bool) - val haltIt = Bool + val haltIt = Bool() //Used to wait on the MMU rsp busy override def asMaster(): Unit = { out(isValid, isStuck, isRemoved, pc) diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 1b0084b..a1051d7 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -201,7 +201,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount : execute.arbitration.haltByOther := True busReadDataReg := execute.input(PC).asBits when(stagesFromExecute.tail.map(_.arbitration.isValid).orR === False){ - iBusFetcher.flushIt() iBusFetcher.haltIt() execute.arbitration.flushIt := True execute.arbitration.flushNext := True diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 0c61fa1..ec40773 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -32,7 +32,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, // assert(!(cmdToRspStageCount == 1 && !injectorStage)) assert(!(compressedGen && !decodePcGen)) var fetcherHalt : Bool = null - var fetcherflushIt : Bool = null var pcValids : Vec[Bool] = null def pcValid(stage : Stage) = pcValids(pipeline.indexOf(stage)) var incomingInstruction : Bool = null @@ -47,8 +46,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, var predictionJumpInterface : Flow[UInt] = null override def haltIt(): Unit = fetcherHalt := True - override def flushIt(): Unit = fetcherflushIt := True - case class JumpInfo(interface : Flow[UInt], stage: Stage, priority : Int) val jumpInfos = ArrayBuffer[JumpInfo]() override def createJumpInterface(stage: Stage, priority : Int = 0): Flow[UInt] = { @@ -62,7 +59,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, // var decodeExceptionPort : Flow[ExceptionCause] = null override def setup(pipeline: VexRiscv): Unit = { fetcherHalt = False - fetcherflushIt = False incomingInstruction = False if(resetVector == null) externalResetVector = in(UInt(32 bits).setName("externalResetVector")) @@ -91,13 +87,16 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, s == IBUS_RSP || s == DECOMPRESSOR } - def getFlushAt(s : Any, lastCond : Boolean = true): Bool = { - if(isDrivingDecode(s) && lastCond) pipeline.decode.arbitration.isRemoved else fetcherflushIt - } + class FetchArea(pipeline : VexRiscv) extends Area { import pipeline._ import pipeline.config._ + val fetcherflushIt = stages.map(_.arbitration.flushNext).orR + + def getFlushAt(s : Any, lastCond : Boolean = true): Bool = { + if(isDrivingDecode(s) && lastCond) pipeline.decode.arbitration.isRemoved else fetcherflushIt + } //Arbitrate jump requests into pcLoad val jump = new Area { @@ -113,7 +112,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs) } - fetcherflushIt setWhen(stages.map(_.arbitration.flushNext).orR) + //The fetchPC pcReg can also be use for the second stage of the fetch //When the fetcherHalt is set and the pipeline isn't stalled,, the pc is propagated to to the pcReg, which allow From 4ad1215873c993db456dbc817c7f1dd6bd9ff0a9 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 21 Feb 2020 13:28:42 +0100 Subject: [PATCH 20/51] Fix iBusSimplePlugin MMU integration --- .../vexriscv/plugin/IBusSimplePlugin.scala | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 8681b9c..b2f1083 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -317,15 +317,16 @@ class IBusSimplePlugin( resetVector : BigInt, cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ U"00" - //do not emit memory request if MMU miss - when(mmuBus.rsp.exception || mmuBus.rsp.refilling){ - cmdForkStage.halt := False - cmd.valid := False - } - - when(mmuBus.busy){ - cmdForkStage.input.valid := False - cmdForkStage.input.ready := False + //do not emit memory request if MMU had issues + when(cmdForkStage.input.valid) { + when(mmuBus.rsp.refilling) { + cmdForkStage.halt := True + cmd.valid := False + } + when(mmuBus.rsp.exception) { + cmdForkStage.halt := False + cmd.valid := False + } } val joinCtx = stageXToIBusRsp(cmdForkStage, mmuBus.rsp) @@ -354,6 +355,7 @@ class IBusSimplePlugin( resetVector : BigInt, c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream c.io.flush := iBusRsp.stages.last.flush if(compressedGen) c.io.flush setWhen(decompressor.consumeCurrent) + if(!compressedGen && isDrivingDecode(IBUS_RSP)) c.io.flush setWhen(decode.arbitration.flushNext && iBusRsp.output.ready) rspBufferOutput << c.io.pop } else new Area{ val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream From 41008551c16afaa3c1781db3f4623d01df5079d0 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 21 Feb 2020 20:01:35 +0100 Subject: [PATCH 21/51] CsrPlugin redo interface do not need next pc calculation --- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 7d98bb9..8366b55 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -447,9 +447,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep if(supervisorGen) { - redoInterface = pcManagerService.createJumpInterface(pipeline.execute) - redoInterface.valid := False - redoInterface.payload.assignDontCare() + redoInterface = pcManagerService.createJumpInterface(pipeline.execute, -1) } exceptionPendings = Vec(Bool, pipeline.stages.length) @@ -643,10 +641,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep satpAccess(CSR.SATP, 31 -> satp.MODE, 22 -> satp.ASID, 0 -> satp.PPN) - if(supervisorGen) onWrite(CSR.SATP){ - execute.arbitration.flushNext := True - redoInterface.valid := True - redoInterface.payload := execute.input(PC) + 4 + if(supervisorGen) { + redoInterface.valid := False + redoInterface.payload := decode.input(PC) + onWrite(CSR.SATP){ + execute.arbitration.flushNext := True + redoInterface.valid := True + } } } } From 5ea0b57d1b277ee9ff20c2ed8490e72477e605fa Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 22 Feb 2020 11:53:47 +0100 Subject: [PATCH 22/51] Fix BRANCH_TARGET with RVC patch --- src/main/scala/vexriscv/plugin/Fetcher.scala | 50 +++++++++---------- .../vexriscv/TestIndividualFeatures.scala | 6 +-- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index ec40773..4b76336 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -421,18 +421,15 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } } - def stage1ToInjectorPipe[T <: Data](input : T): (T,T) ={ + def stage1ToInjectorPipe[T <: Data](input : T): (T, T, T) ={ val iBusRspContext = iBusRsp.stages.drop(1).dropRight(1).foldLeft(input)((data,stage) => RegNextWhen(data, stage.output.ready)) -// val decompressorContext = ifGen(compressedGen)(new Area{ -// val lastContext = RegNextWhen(iBusRspContext, decompressor.input.fire) -// val output = decompressor.bufferValid ? lastContext | iBusRspContext -// }) - val decompressorContext = cloneOf(input) - decompressorContext := iBusRspContext - val injectorContext = Delay(if(compressedGen) decompressorContext else iBusRspContext, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) + + val iBusRspContextOutput = cloneOf(input) + iBusRspContextOutput := iBusRspContext + val injectorContext = Delay(iBusRspContextOutput, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) val injectorContextWire = cloneOf(input) //Allow combinatorial override injectorContextWire := injectorContext - (ifGen(compressedGen)(decompressorContext), injectorContextWire) + (iBusRspContext, iBusRspContextOutput, injectorContextWire) } val predictor = prediction match { @@ -458,7 +455,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) object PREDICTION_CONTEXT extends Stageable(DynamicContext()) - decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2 + decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._3 val decodeContextPrediction = decode.input(PREDICTION_CONTEXT).line.history.msb val branchStage = decodePrediction.stage @@ -534,21 +531,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, fetchContext.hit := hit fetchContext.line := line - val (decompressorContext, injectorContext) = stage1ToInjectorPipe(fetchContext) - if(compressedGen) { - //prediction hit on the right instruction into words - decompressorContext.hit clearWhen(decompressorContext.line.last2Bytes && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.throw2Bytes))) - - decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire - decodePc.predictionPcLoad.payload := injectorContext.line.target - - //Clean the RVC buffer when a prediction was made - when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){ - decompressor.bufferValid := False - decompressor.throw2BytesReg := False - decompressor.input.ready := True //Drop the remaining byte if any - } - } + val (decompressorContext, decompressorContextOutput, injectorContext) = stage1ToInjectorPipe(fetchContext) object PREDICTION_CONTEXT extends Stageable(PredictionResult()) pipeline.decode.insert(PREDICTION_CONTEXT) := injectorContext @@ -580,7 +563,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring) - val predictionFailure = ifGen(compressedGen)(new Area{ + val compressor = compressedGen generate new Area{ val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) val unalignedWordIssue = iBusRsp.output.valid && predictionBranch && decompressor.throw2Bytes && !decompressor.isInputHighRvc @@ -591,7 +574,20 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, iBusRsp.redoFetch := True } - }) + + //Do not trigger prediction hit when it is one for the upper RVC word and we aren't there yet + decompressorContextOutput.hit clearWhen(decompressorContext.line.last2Bytes && !decompressor.throw2Bytes) + + decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire + decodePc.predictionPcLoad.payload := injectorContext.line.target + + //Clean the RVC buffer when a prediction was made + when(decompressorContext.line.branchWish.msb && decompressorContextOutput.hit && !decompressorContext.hazard && decompressor.output.fire){ + decompressor.bufferValid := False + decompressor.throw2BytesReg := False + decompressor.input.ready := True //Drop the remaining byte if any + } + } } } diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 005f335..7f00d1f 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -620,7 +620,7 @@ class TestIndividualFeatures extends FunSuite { test(prefix + name + "_test") { println("START TEST " + prefix + name) val debug = true - val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${sys.env.getOrElse("VEXRISCV_REGRESSION_COREMARK", "yes")} THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", 1)} ") + s" SEED=${testSeed} " + val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${sys.env.getOrElse("VEXRISCV_REGRESSION_COREMARK", "yes")} THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", 1)} ") + s" SEED=${testSeed} " val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ") println(testCmd) val str = doCmd(testCmd) @@ -633,8 +633,8 @@ class TestIndividualFeatures extends FunSuite { // // val testId = Some(mutable.HashSet(3,4,9,11,13,16,18,19,20,21)) // val testId = Some(mutable.HashSet(11)) -// val testId = Some(mutable.HashSet(4, 11)) -// val seed = 6592877339343561798l +// val testId = Some(mutable.HashSet(6)) +// val seed = 9095713085965080531l val rand = new Random(seed) From 01e5112680cd437cca7151bd13bf220fc85e1ec9 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 23 Feb 2020 10:44:44 +0100 Subject: [PATCH 23/51] Fetcher RVC ensure redo keep PC(1) Fix BranchTarget RVC inibition --- src/main/scala/vexriscv/plugin/Fetcher.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 4b76336..4200982 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -247,7 +247,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val bufferValid = RegInit(False) val bufferData = Reg(Bits(16 bits)) - val isInputLowRvc = input.rsp.inst(1 downto 0) =/= 3 val isInputHighRvc = input.rsp.inst(17 downto 16) =/= 3 val throw2BytesReg = RegInit(False) @@ -283,6 +282,10 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, throw2BytesReg := False bufferValid := False } + + if(fetchPc.redo != null) { + fetchPc.redo.payload(1) setWhen(throw2BytesReg) + } }) @@ -576,7 +579,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } //Do not trigger prediction hit when it is one for the upper RVC word and we aren't there yet - decompressorContextOutput.hit clearWhen(decompressorContext.line.last2Bytes && !decompressor.throw2Bytes) + decompressorContextOutput.hit clearWhen(decompressorContext.line.last2Bytes && (decompressor.bufferValid || (!decompressor.throw2Bytes && decompressor.isInputLowRvc))) decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire decodePc.predictionPcLoad.payload := injectorContext.line.target From c8016e90a4987a30b6fde5e435626760ddf4b322 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 23 Feb 2020 20:25:31 +0100 Subject: [PATCH 24/51] MulPlugin now add KEEP attribute on RS1 and RS2 to force Vivado to not retime it with the DSP --- src/main/scala/vexriscv/plugin/MulPlugin.scala | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/scala/vexriscv/plugin/MulPlugin.scala b/src/main/scala/vexriscv/plugin/MulPlugin.scala index 96db3e9..efe3ba0 100644 --- a/src/main/scala/vexriscv/plugin/MulPlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulPlugin.scala @@ -2,6 +2,7 @@ package vexriscv.plugin import vexriscv._ import vexriscv.VexRiscv import spinal.core._ +import spinal.lib.KeepAttribute //Input buffer generaly avoid the FPGA synthesis to duplicate reg inside the DSP cell, which could stress timings quite much. class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv]{ @@ -94,6 +95,12 @@ class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv]{ insert(MUL_LH) := aSLow * bHigh insert(MUL_HL) := aHigh * bSLow insert(MUL_HH) := aHigh * bHigh + + Component.current.afterElaboration{ + //Avoid synthesis tools to retime RS1 RS2 from execute stage to decode stage leading to bad timings (ex : Vivado, even if retiming is disabled) + KeepAttribute(input(RS1).getDrivingReg) + KeepAttribute(input(RS2).getDrivingReg) + } } //First aggregation of partial multiplication From 67d2071a32c88b822c0d601757d2e1c3aade3d9a Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 23 Feb 2020 23:17:02 +0100 Subject: [PATCH 25/51] typo --- src/main/scala/vexriscv/demo/SynthesisBench.scala | 2 +- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index 08a7d72..503ef37 100644 --- a/src/main/scala/vexriscv/demo/SynthesisBench.scala +++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala @@ -121,7 +121,7 @@ object VexRiscvSynthesisBench { ) ++ IcestormStdTargets().take(1) // val targets = IcestormStdTargets() - Bench(rtls, targets, "/media/miaou/HD/linux/tmp") + Bench(rtls, targets, "/media/miaou/HD/linux/tmp/") } } diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 8366b55..6e0c41b 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -686,7 +686,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep //Aggregate all exception port and remove required instructions - val exceptionPortCtrl = if(exceptionPortsInfos.nonEmpty) new Area{ + val exceptionPortCtrl = exceptionPortsInfos.nonEmpty generate new Area{ val firstStageIndexWithExceptionPort = exceptionPortsInfos.map(i => indexOf(i.stage)).min val exceptionValids = Vec(stages.map(s => Bool().setPartialName(s.getName()))) val exceptionValidsRegs = Vec(stages.map(s => Reg(Bool).init(False).setPartialName(s.getName()))).allowUnsetRegToAvoidLatch @@ -763,7 +763,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep //Avoid the PC register of the last stage to change durring an exception handleing (Used to fill Xepc) stages.last.dontSample.getOrElseUpdate(PC, ArrayBuffer[Bool]()) += exceptionValids.last exceptionPendings := exceptionValidsRegs - } else null + } From fad09e805f3470abc14f57cffa380860cc89a4c7 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 23 Feb 2020 23:18:27 +0100 Subject: [PATCH 26/51] Add Fetcher.predictionBuffer option to pipeline BRANCH_TARGET, higher FMax, about 1 ns critical path gain on Arty7 => 5 ns --- src/main/scala/vexriscv/plugin/Fetcher.scala | 54 +++++++++++++------ .../vexriscv/plugin/IBusCachedPlugin.scala | 6 ++- .../vexriscv/plugin/IBusSimplePlugin.scala | 6 ++- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 4200982..cac8789 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -22,7 +22,8 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val historyRamSizeLog2 : Int, val injectorStage : Boolean, val relaxPredictorAddress : Boolean, - val fetchRedoGen : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{ + val fetchRedoGen : Boolean, + val predictionBuffer : Boolean = true) extends Plugin[VexRiscv] with JumpService with IBusFetcher{ var prefetchExceptionPort : Flow[ExceptionCause] = null var decodePrediction : DecodePredictionBus = null var fetchPrediction : FetchPredictionBus = null @@ -121,10 +122,12 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, //PC calculation without Jump val output = Stream(UInt(32 bits)) val pcReg = Reg(UInt(32 bits)) init(if(resetVector != null) resetVector else externalResetVector) addAttribute(Verilator.public) - val corrected = False + val correction = False + val correctionReg = RegInit(False) setWhen(correction) clearWhen(output.fire) + val corrected = correction || correctionReg val pcRegPropagate = False val booted = RegNext(True) init (False) - val inc = RegInit(False) clearWhen(corrected || pcRegPropagate) setWhen(output.fire) clearWhen(!output.valid && output.ready) + val inc = RegInit(False) clearWhen(correction || pcRegPropagate) setWhen(output.fire) clearWhen(!output.valid && output.ready) val pc = pcReg + (inc ## B"00").asUInt val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) val redo = (fetchRedoGen || prediction == DYNAMIC_TARGET) generate Flow(UInt(32 bits)) @@ -136,22 +139,22 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, if(predictionPcLoad != null) { when(predictionPcLoad.valid) { - corrected := True + correction := True pc := predictionPcLoad.payload } } if(redo != null) when(redo.valid){ - corrected := True + correction := True pc := redo.payload flushed := True } when(jump.pcLoad.valid) { - corrected := True + correction := True pc := jump.pcLoad.payload flushed := True } - when(booted && (output.ready || corrected || pcRegPropagate)){ + when(booted && (output.ready || correction || pcRegPropagate)){ pcReg := pc } @@ -506,17 +509,36 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, case class BranchPredictorLine() extends Bundle{ val source = Bits(30 - historyRamSizeLog2 bits) val branchWish = UInt(2 bits) - val target = UInt(32 bits) val last2Bytes = ifGen(compressedGen)(Bool) + val target = UInt(32 bits) } val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) - val historyWrite = history.writePort + val historyWriteDelayPatched = history.writePort + val historyWrite = cloneOf(historyWriteDelayPatched) + historyWriteDelayPatched.valid := historyWrite.valid + historyWriteDelayPatched.address := (if(predictionBuffer) historyWrite.address - 1 else historyWrite.address) + historyWriteDelayPatched.data := historyWrite.data + + + val writeLast = RegNextWhen(historyWriteDelayPatched, iBusRsp.stages(0).output.ready) //Avoid write to read hazard - val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) - val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized - val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready) + val buffer = predictionBuffer generate new Area{ + val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready) + val pcCorrected = RegNextWhen(fetchPc.corrected, iBusRsp.stages(0).input.ready) + val hazard = (writeLast.valid && writeLast.address === (iBusRsp.stages(1).input.payload >> 2).resized) + } + + val (line, hazard) = predictionBuffer match { + case true => + (RegNextWhen(buffer.line, iBusRsp.stages(0).output.ready), + RegNextWhen(buffer.hazard, iBusRsp.stages(0).output.ready) || buffer.pcCorrected) + case false => + (history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, + iBusRsp.stages(0).output.ready), writeLast.valid && writeLast.address === (iBusRsp.stages(1).input.payload >> 2).resized) + } + val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) if(compressedGen) hit clearWhen(!line.last2Bytes && iBusRsp.stages(1).input.payload(1)) @@ -534,7 +556,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, fetchContext.hit := hit fetchContext.line := line - val (decompressorContext, decompressorContextOutput, injectorContext) = stage1ToInjectorPipe(fetchContext) + val (iBusRspContext, iBusRspContextOutput, injectorContext) = stage1ToInjectorPipe(fetchContext) object PREDICTION_CONTEXT extends Stageable(PredictionResult()) pipeline.decode.insert(PREDICTION_CONTEXT) := injectorContext @@ -567,7 +589,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring) val compressor = compressedGen generate new Area{ - val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1) + val predictionBranch = iBusRspContext.hit && !iBusRspContext.hazard && iBusRspContext.line.branchWish(1) val unalignedWordIssue = iBusRsp.output.valid && predictionBranch && decompressor.throw2Bytes && !decompressor.isInputHighRvc when(unalignedWordIssue){ @@ -579,13 +601,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } //Do not trigger prediction hit when it is one for the upper RVC word and we aren't there yet - decompressorContextOutput.hit clearWhen(decompressorContext.line.last2Bytes && (decompressor.bufferValid || (!decompressor.throw2Bytes && decompressor.isInputLowRvc))) + iBusRspContextOutput.hit clearWhen(iBusRspContext.line.last2Bytes && (decompressor.bufferValid || (!decompressor.throw2Bytes && decompressor.isInputLowRvc))) decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire decodePc.predictionPcLoad.payload := injectorContext.line.target //Clean the RVC buffer when a prediction was made - when(decompressorContext.line.branchWish.msb && decompressorContextOutput.hit && !decompressorContext.hazard && decompressor.output.fire){ + when(iBusRspContext.line.branchWish.msb && iBusRspContextOutput.hit && !iBusRspContext.hazard && decompressor.output.fire){ decompressor.bufferValid := False decompressor.throw2BytesReg := False decompressor.input.ready := True //Drop the remaining byte if any diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index f018bb3..1f59a33 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -35,7 +35,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, memoryTranslatorPortConfig : Any = null, injectorStage : Boolean = false, withoutInjectorStage : Boolean = false, - relaxPredictorAddress : Boolean = true) extends IBusFetcherImpl( + relaxPredictorAddress : Boolean = true, + predictionBuffer : Boolean = true) extends IBusFetcherImpl( resetVector = resetVector, keepPcPlus4 = keepPcPlus4, decodePcGen = compressedGen, @@ -47,7 +48,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, historyRamSizeLog2 = historyRamSizeLog2, injectorStage = (!config.twoCycleCache && !withoutInjectorStage) || injectorStage, relaxPredictorAddress = relaxPredictorAddress, - fetchRedoGen = true){ + fetchRedoGen = true, + predictionBuffer = predictionBuffer){ import config._ assert(isPow2(cacheSize)) diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index b2f1083..56ad76f 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -233,7 +233,8 @@ class IBusSimplePlugin( resetVector : BigInt, val rspHoldValue : Boolean = false, val singleInstructionPipeline : Boolean = false, val memoryTranslatorPortConfig : Any = null, - relaxPredictorAddress : Boolean = true + relaxPredictorAddress : Boolean = true, + predictionBuffer : Boolean = true ) extends IBusFetcherImpl( resetVector = resetVector, keepPcPlus4 = keepPcPlus4, @@ -246,7 +247,8 @@ class IBusSimplePlugin( resetVector : BigInt, historyRamSizeLog2 = historyRamSizeLog2, injectorStage = injectorStage, relaxPredictorAddress = relaxPredictorAddress, - fetchRedoGen = memoryTranslatorPortConfig != null){ + fetchRedoGen = memoryTranslatorPortConfig != null, + predictionBuffer = predictionBuffer){ var iBus : IBusSimpleBus = null var decodeExceptionPort : Flow[ExceptionCause] = null From 485b4a5838e1c9b0b5bd1c76b900dc85731012c8 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 23 Feb 2020 23:52:43 +0100 Subject: [PATCH 27/51] Improve maxPerf configs --- src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala | 8 ++++---- src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala | 2 +- src/main/scala/vexriscv/demo/SynthesisBench.scala | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala b/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala index 28843d8..6c892f0 100644 --- a/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala +++ b/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala @@ -20,7 +20,7 @@ object GenFullNoMmuMaxPerf extends App{ prediction = DYNAMIC_TARGET, historyRamSizeLog2 = 8, config = InstructionCacheConfig( - cacheSize = 4096*4, + cacheSize = 4096*2, bytePerLine =32, wayCount = 1, addressWidth = 32, @@ -29,13 +29,13 @@ object GenFullNoMmuMaxPerf extends App{ catchIllegalAccess = true, catchAccessFault = true, asyncTagMemory = false, - twoCycleRam = true, + twoCycleRam = false, twoCycleCache = true ) ), new DBusCachedPlugin( config = new DataCacheConfig( - cacheSize = 4096*4, + cacheSize = 4096*2, bytePerLine = 32, wayCount = 1, addressWidth = 32, @@ -76,7 +76,7 @@ object GenFullNoMmuMaxPerf extends App{ new CsrPlugin(CsrPluginConfig.small), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new BranchPlugin( - earlyBranch = true, + earlyBranch = false, catchAddressMisaligned = true ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala b/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala index 89dffe0..9bca107 100644 --- a/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala +++ b/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala @@ -56,7 +56,7 @@ object GenNoCacheNoMmuMaxPerf extends App{ new CsrPlugin(CsrPluginConfig.small), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new BranchPlugin( - earlyBranch = true, + earlyBranch = false, catchAddressMisaligned = true ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index 503ef37..4df6f5e 100644 --- a/src/main/scala/vexriscv/demo/SynthesisBench.scala +++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala @@ -96,7 +96,7 @@ object VexRiscvSynthesisBench { } val full = new Rtl { - override def getName(): String = "VexRiscv full" + override def getName(): String = "VexRiscv full with MMU" override def getRtlPath(): String = "VexRiscvFull.v" SpinalVerilog(wrap(GenFull.cpu()).setDefinitionName(getRtlPath().split("\\.").head)) } From 999a868c1412796c0a230bc2802449055ece990a Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 24 Feb 2020 00:07:14 +0100 Subject: [PATCH 28/51] Update readme VexRiscv perf numbers --- README.md | 59 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index d0deb16..f60369b 100644 --- a/README.md +++ b/README.md @@ -65,55 +65,54 @@ dhrystone binaries which fit inside a 4KB I$ and 4KB D$ (I already had this case The CPU configurations used below can be found in the `src/scala/vexriscv/demo` directory. ``` -VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) -> - Artix 7 -> 233 Mhz 494 LUT 505 FF - Cyclone V -> 193 Mhz 347 ALMs - Cyclone IV -> 179 Mhz 730 LUT 494 FF +VexRiscv small (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) -> + Artix 7 -> 239 Mhz 494 LUT 505 FF + Cyclone V -> 189 Mhz 345 ALMs + Cyclone IV -> 179 Mhz 730 LUT 494 FF iCE40 -> 92 Mhz 1130 LC -VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) -> - Artix 7 -> 232 Mhz 538 LUT 562 FF - Cyclone V -> 189 Mhz 387 ALMs - Cyclone IV -> 175 Mhz 829 LUT 550 FF +VexRiscv small (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) -> + Artix 7 -> 238 Mhz 552 LUT 562 FF + Cyclone V -> 192 Mhz 390 ALMs + Cyclone IV -> 172 Mhz 832 LUT 551 FF iCE40 -> 85 Mhz 1292 LC VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) -> - Artix 7 -> 226 Mhz 689 LUT 531 FF - Cyclone V -> 145 Mhz 499 ALMs - Cyclone IV -> 150 Mhz 1,111 LUT 525 FF + Artix 7 -> 225 Mhz 699 LUT 532 FF + Cyclone V -> 144 Mhz 493 ALMs + Cyclone IV -> 148 Mhz 1,111 LUT 526 FF iCE40 -> 63 Mhz 1596 LC VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) -> - Artix 7 -> 230 Mhz 734 LUT 564 FF + Artix 7 -> 225 Mhz 719 LUT 566 FF Cyclone V -> 145 Mhz 511 ALMs - Cyclone IV -> 144 Mhz 1,145 LUT 531 FF + Cyclone IV -> 150 Mhz 1,138 LUT 532 FF iCE40 -> 66 Mhz 1680 LC VexRiscv full no cache (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 219 Mhz 1537 LUT 977 FF - Cyclone V -> 139 Mhz 958 ALMs - Cyclone IV -> 135 Mhz 2,011 LUT 968 FF + Artix 7 -> 219 Mhz 1486 LUT 975 FF + Cyclone V -> 149 Mhz 943 ALMs + Cyclone IV -> 138 Mhz 2,013 LUT 966 FF VexRiscv full (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 193 Mhz 1706 LUT 1172 FF - Cyclone V -> 144 Mhz 1,128 ALMs - Cyclone IV -> 133 Mhz 2,298 LUT 1,096 FF + Artix 7 -> 204 Mhz 1661 LUT 1172 FF + Cyclone V -> 143 Mhz 1,118 ALMs + Cyclone IV -> 133 Mhz 2,278 LUT 1,061 FF -VexRiscv full max dmips/mhz -> (RV32IM, 1.44 DMIPS/Mhz 2.70 Coremark/Mhz,, 16KB-I$,16KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) -> - Artix 7 -> 140 Mhz 1767 LUT 1128 FF - Cyclone V -> 90 Mhz 1,089 ALMs - Cyclone IV -> 79 Mhz 2,336 LUT 1,048 FF +VexRiscv full max perf (HZ*IPC) -> (RV32IM, 1.38 DMIPS/Mhz 2.57 Coremark/Mhz, 8KB-I$,8KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) -> + Artix 7 -> 199 Mhz 1739 LUT 1229 FF + Cyclone V -> 132 Mhz 1,129 ALMs + Cyclone IV -> 126 Mhz 2,345 LUT 1,114 FF VexRiscv full with MMU (RV32IM, 1.24 DMIPS/Mhz 2.35 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) -> - Artix 7 -> 161 Mhz 1985 LUT 1585 FF - Cyclone V -> 124 Mhz 1,319 ALMs - Cyclone IV -> 122 Mhz 2,710 LUT 1,501 FF + Artix 7 -> 167 Mhz 1927 LUT 1553 FF + Cyclone V -> 128 Mhz 1,302 ALMs + Cyclone IV -> 125 Mhz 2,685 LUT 1,466 FF VexRiscv linux balanced (RV32IMA, 1.21 DMIPS/Mhz 2.27 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, catch exceptions, static branch, MMU, Supervisor, Compatible with mainstream linux) -> - Artix 7 -> 170 Mhz 2530 LUT 2013 FF - Cyclone V -> 125 Mhz 1,618 ALMs - Cyclone IV -> 116 Mhz 3,314 LUT 2,016 FF - + Artix 7 -> 179 Mhz 2685 LUT 2177 FF + Cyclone V -> 136 Mhz 1,666 ALMs + Cyclone IV -> 123 Mhz 3,350 LUT 2,059 FF ``` The following configuration results in 1.44 DMIPS/MHz: From 76d063f20ab94d6be2463b88861aef737cd79f1e Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 24 Feb 2020 22:43:08 +0100 Subject: [PATCH 29/51] Fix MulPlugin keep attribute --- src/main/scala/vexriscv/plugin/MulPlugin.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/MulPlugin.scala b/src/main/scala/vexriscv/plugin/MulPlugin.scala index efe3ba0..31714e8 100644 --- a/src/main/scala/vexriscv/plugin/MulPlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulPlugin.scala @@ -98,8 +98,8 @@ class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv]{ Component.current.afterElaboration{ //Avoid synthesis tools to retime RS1 RS2 from execute stage to decode stage leading to bad timings (ex : Vivado, even if retiming is disabled) - KeepAttribute(input(RS1).getDrivingReg) - KeepAttribute(input(RS2).getDrivingReg) + KeepAttribute(input(RS1)) + KeepAttribute(input(RS2)) } } From 492310e6fa66e9d8a47a48ea6dc406fde961dcf8 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 28 Feb 2020 17:21:59 +0100 Subject: [PATCH 30/51] DBusCachedPlugin fix noWriteBack redo priority --- .../scala/vexriscv/plugin/DBusCachedPlugin.scala | 2 +- src/main/scala/vexriscv/plugin/Fetcher.scala | 4 ++-- .../scala/vexriscv/plugin/IBusSimplePlugin.scala | 2 +- .../scala/vexriscv/TestIndividualFeatures.scala | 14 ++++++++------ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index f0eaa81..fd45dd8 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -145,7 +145,7 @@ class DBusCachedPlugin(val config : DataCacheConfig, decoderService.add(FENCE, Nil) mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig) - redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.writeBack != null) pipeline.writeBack else pipeline.execute) + redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.writeBack != null) pipeline.writeBack else pipeline.memory) if(catchSomething) exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(if(pipeline.writeBack == null) pipeline.memory else pipeline.writeBack) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index cac8789..8463238 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -159,7 +159,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } pc(0) := False - if(!pipeline(RVC_GEN)) pc(1) := False + if(!compressedGen) pc(1) := False output.valid := !fetcherHalt && booted output.payload := pc @@ -590,7 +590,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val compressor = compressedGen generate new Area{ val predictionBranch = iBusRspContext.hit && !iBusRspContext.hazard && iBusRspContext.line.branchWish(1) - val unalignedWordIssue = iBusRsp.output.valid && predictionBranch && decompressor.throw2Bytes && !decompressor.isInputHighRvc + val unalignedWordIssue = iBusRsp.output.valid && predictionBranch && iBusRspContext.line.last2Bytes && Mux(decompressor.unaligned, !decompressor.isInputHighRvc, decompressor.isInputLowRvc && !decompressor.isInputHighRvc) when(unalignedWordIssue){ historyWrite.valid := True diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 56ad76f..ed5cbb4 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -343,7 +343,7 @@ class IBusSimplePlugin( resetVector : BigInt, //Manage flush for iBus transactions in flight val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0) discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt - when(fetcherflushIt) { + when(iBusRsp.stages.last.flush) { if(secondStagePersistence) discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt else diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 7f00d1f..3ed94a0 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -628,13 +628,15 @@ class TestIndividualFeatures extends FunSuite { } } - val testId : Option[mutable.HashSet[Int]] = None - val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong -// + var testId : Option[mutable.HashSet[Int]] = None + var seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextInt(1000000000).toString).toLong + // val testId = Some(mutable.HashSet(3,4,9,11,13,16,18,19,20,21)) -// val testId = Some(mutable.HashSet(11)) -// val testId = Some(mutable.HashSet(6)) -// val seed = 9095713085965080531l +// val testId = Some(mutable.HashSet(15)) +// seed = -7374992264756372315l +// testId = Some(mutable.HashSet(1,2,6,14,15,16,19)) +// testId = Some(mutable.HashSet(1,2,6,14)) +// testId = Some(mutable.HashSet(1)) val rand = new Random(seed) From c94d8f1c6c1896fd35e1e5779f69566a9f09bb28 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 28 Feb 2020 17:23:44 +0100 Subject: [PATCH 31/51] Fetcher and IBusSimplePlugin flush reworked --- src/main/scala/vexriscv/plugin/Fetcher.scala | 21 +++-- .../vexriscv/plugin/IBusCachedPlugin.scala | 2 +- .../vexriscv/plugin/IBusSimplePlugin.scala | 88 +++++++++---------- 3 files changed, 55 insertions(+), 56 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 8463238..1de5021 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -93,10 +93,10 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, class FetchArea(pipeline : VexRiscv) extends Area { import pipeline._ import pipeline.config._ - val fetcherflushIt = stages.map(_.arbitration.flushNext).orR + val externalFlush = stages.map(_.arbitration.flushNext).orR def getFlushAt(s : Any, lastCond : Boolean = true): Bool = { - if(isDrivingDecode(s) && lastCond) pipeline.decode.arbitration.isRemoved else fetcherflushIt + if(isDrivingDecode(s) && lastCond) pipeline.decode.arbitration.isRemoved else externalFlush } //Arbitrate jump requests into pcLoad @@ -208,7 +208,6 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val input = Stream(UInt(32 bits)) val output = Stream(UInt(32 bits)) val halt = Bool() - val flush = Bool() }) stages(0).input << fetchPc.output @@ -222,16 +221,16 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, fetchPc.redo.payload := stages.last.input.payload } - stages.head.flush := False //getFlushAt(IBUS_RSP, stages.head == stages.last) || fetchFlush + val flush = (if(isDrivingDecode(IBUS_RSP)) pipeline.decode.arbitration.isRemoved || decode.arbitration.flushNext && !decode.arbitration.isStuck else externalFlush) || redoFetch for((s,sNext) <- (stages, stages.tail).zipped) { - val discardInputOnFlush = s != stages.head - sNext.flush := getFlushAt(IBUS_RSP, sNext == stages.last) || redoFetch + val sFlushed = if(s != stages.head) flush else False + val sNextFlushed = flush if(s == stages.head && pcRegReusedForSecondStage) { - sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(sNext.flush, false, collapsBubble = false, flushInput = s.flush)) + sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(sNextFlushed, false, collapsBubble = false, flushInput = sFlushed)) sNext.input.payload := fetchPc.pcReg fetchPc.pcRegPropagate setWhen(sNext.input.ready) } else { - sNext.input << s.output.m2sPipeWithFlush(sNext.flush, false, collapsBubble = false, flushInput = s.flush) + sNext.input << s.output.m2sPipeWithFlush(sNextFlushed, false, collapsBubble = false, flushInput = sFlushed) } } @@ -294,14 +293,14 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that val injector = new Area { - val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(fetcherflushIt)) + val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(externalFlush)) if (injectorReadyCutGen) { iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe incomingInstruction setWhen (inputBeforeStage.valid) } val decodeInput = (if (injectorStage) { val flushStage = getFlushAt(INJECTOR_M2S) - val decodeInput = inputBeforeStage.m2sPipeWithFlush(flushStage, false, collapsBubble = false, flushInput = fetcherflushIt) + val decodeInput = inputBeforeStage.m2sPipeWithFlush(flushStage, false, collapsBubble = false, flushInput = externalFlush) decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst) iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer incomingInstruction setWhen (decodeInput.valid) @@ -458,7 +457,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } val fetchContext = DynamicContext() fetchContext.hazard := hazard - fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) + fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || externalFlush) object PREDICTION_CONTEXT extends Stageable(DynamicContext()) decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._3 diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 1f59a33..642fcbb 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -156,7 +156,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt) - cache.io.cpu.fetch.isRemoved := fetcherflushIt + cache.io.cpu.fetch.isRemoved := externalFlush } diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index ed5cbb4..b8bc978 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -255,7 +255,9 @@ class IBusSimplePlugin( resetVector : BigInt, val catchSomething = memoryTranslatorPortConfig != null || catchAccessFault var mmuBus : MemoryTranslatorBus = null - if(rspHoldValue) assert(busLatencyMin <= 1) +// if(rspHoldValue) assert(busLatencyMin <= 1) + assert(!rspHoldValue, "rspHoldValue not supported yet") + assert(!singleInstructionPipeline) override def setup(pipeline: VexRiscv): Unit = { super.setup(pipeline) @@ -283,9 +285,12 @@ class IBusSimplePlugin( resetVector : BigInt, iBus.cmd << (if(cmdWithS2mPipe) cmd.s2mPipe() else cmd) //Avoid sending to many iBus cmd - val pendingCmd = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0) - val pendingCmdNext = pendingCmd + cmd.fire.asUInt - iBus.rsp.fire.asUInt - pendingCmd := pendingCmdNext + val pending = new Area{ + val inc, dec = Bool() + val value = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0) + val next = value + U(inc) - U(dec) + value := next + } val secondStagePersistence = cmdForkPersistence && cmdForkOnSecondStage && !cmdWithS2mPipe def cmdForkStage = if(!secondStagePersistence) iBusRsp.stages(if(cmdForkOnSecondStage) 1 else 0) else iBusRsp.stages(1) @@ -293,29 +298,30 @@ class IBusSimplePlugin( resetVector : BigInt, val cmdFork = if(!secondStagePersistence) new Area { //This implementation keep the cmd on the bus until it's executed or the the pipeline is flushed def stage = cmdForkStage - stage.halt setWhen(stage.input.valid && (!cmd.valid || !cmd.ready)) - if(singleInstructionPipeline) { - cmd.valid := stage.input.valid && pendingCmd =/= pendingMax && !stages.map(_.arbitration.isValid).orR - assert(injectorStage == false) - assert(iBusRsp.stages.dropWhile(_ != stage).length <= 2) - }else { - cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax - } + val canEmit = stage.output.ready && pending.value =/= pendingMax + stage.halt setWhen(stage.input.valid && (!canEmit || !cmd.ready)) + cmd.valid := stage.input.valid && canEmit + pending.inc := cmd.fire } else new Area{ //This implementation keep the cmd on the bus until it's executed, even if the pipeline is flushed def stage = cmdForkStage - val pendingFull = pendingCmd === pendingMax - val cmdKeep = RegInit(False) setWhen(cmd.valid) clearWhen(cmd.ready) + val pendingFull = pending.value === pendingMax + val enterTheMarket = Bool() + val cmdKeep = RegInit(False) setWhen(enterTheMarket) clearWhen(cmd.ready) val cmdFired = RegInit(False) setWhen(cmd.fire) clearWhen(stage.input.ready) - stage.halt setWhen(cmd.isStall || (pendingFull && !cmdFired)) - cmd.valid := (stage.input.valid || cmdKeep) && !pendingFull && !cmdFired + enterTheMarket := stage.input.valid && !pendingFull && !cmdFired && !cmdKeep +// stage.halt setWhen(cmd.isStall || (pendingFull && !cmdFired)) //(cmd.isStall) + stage.halt setWhen(pendingFull && !cmdFired && !cmdKeep) + stage.halt setWhen(!cmd.ready && !cmdFired) + cmd.valid := enterTheMarket || cmdKeep + pending.inc := enterTheMarket } val mmu = (mmuBus != null) generate new Area { mmuBus.cmd.isValid := cmdForkStage.input.valid mmuBus.cmd.virtualAddress := cmdForkStage.input.payload mmuBus.cmd.bypassTranslation := False - mmuBus.end := cmdForkStage.output.fire || fetcherflushIt + mmuBus.end := cmdForkStage.output.fire || externalFlush cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ U"00" @@ -341,43 +347,37 @@ class IBusSimplePlugin( resetVector : BigInt, val rspJoin = new Area { import iBusRsp._ //Manage flush for iBus transactions in flight - val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0) - discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt - when(iBusRsp.stages.last.flush) { - if(secondStagePersistence) - discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt - else - discardCounter := (if(cmdForkOnSecondStage) pendingCmdNext else pendingCmd - iBus.rsp.fire.asUInt) - } - - val rspBufferOutput = Stream(IBusSimpleRsp()) - - val rspBuffer = if(!rspHoldValue) new Area{ + val rspBuffer = new Area { + val output = Stream(IBusSimpleRsp()) val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0)) - c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream - c.io.flush := iBusRsp.stages.last.flush - if(compressedGen) c.io.flush setWhen(decompressor.consumeCurrent) - if(!compressedGen && isDrivingDecode(IBUS_RSP)) c.io.flush setWhen(decode.arbitration.flushNext && iBusRsp.output.ready) - rspBufferOutput << c.io.pop - } else new Area{ - val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream - val validReg = RegInit(False) setWhen(rspStream.valid) clearWhen(rspBufferOutput.ready) - rspBufferOutput << rspStream - rspBufferOutput.valid setWhen(validReg) + val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0) + discardCounter := discardCounter - (c.io.pop.valid && discardCounter =/= 0).asUInt + when(iBusRsp.flush) { + discardCounter := (if(cmdForkOnSecondStage) pending.next else pending.value - U(pending.dec)) + } + + c.io.push << iBus.rsp.toStream +// if(compressedGen) c.io.flush setWhen(decompressor.consumeCurrent) +// if(!compressedGen && isDrivingDecode(IBUS_RSP)) c.io.flush setWhen(decode.arbitration.flushNext && iBusRsp.output.ready) + val flush = discardCounter =/= 0 || iBusRsp.flush + output.valid := c.io.pop.valid && discardCounter === 0 + output.payload := c.io.pop.payload + c.io.pop.ready := output.ready || flush + + pending.dec := c.io.pop.fire // iBus.rsp.valid && flush || c.io.pop.valid && output.ready instead to avoid unecessary dependancies ? } val fetchRsp = FetchRsp() fetchRsp.pc := stages.last.output.payload - fetchRsp.rsp := rspBufferOutput.payload - fetchRsp.rsp.error.clearWhen(!rspBufferOutput.valid) //Avoid interference with instruction injection from the debug plugin - + fetchRsp.rsp := rspBuffer.output.payload + fetchRsp.rsp.error.clearWhen(!rspBuffer.output.valid) //Avoid interference with instruction injection from the debug plugin val join = Stream(FetchRsp()) val exceptionDetected = False - join.valid := stages.last.output.valid && rspBufferOutput.valid + join.valid := stages.last.output.valid && rspBuffer.output.valid join.payload := fetchRsp stages.last.output.ready := stages.last.output.valid ? join.fire | join.ready - rspBufferOutput.ready := join.fire + rspBuffer.output.ready := join.fire output << join.haltWhen(exceptionDetected) if(memoryTranslatorPortConfig != null){ From 25d880f6c7f30fea5e6f3393eba9b2360ab71fa1 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 28 Feb 2020 18:20:08 +0100 Subject: [PATCH 32/51] Fix synthesis bench --- src/main/scala/vexriscv/demo/SynthesisBench.scala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index 4df6f5e..91c1e5f 100644 --- a/src/main/scala/vexriscv/demo/SynthesisBench.scala +++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala @@ -4,8 +4,9 @@ import spinal.core._ import spinal.lib._ import spinal.lib.eda.bench._ import spinal.lib.eda.icestorm.IcestormStdTargets +import spinal.lib.io.InOutWrapper import vexriscv.VexRiscv -import vexriscv.plugin.{DecoderSimplePlugin} +import vexriscv.plugin.DecoderSimplePlugin import scala.collection.mutable.ArrayBuffer import scala.util.Random @@ -132,7 +133,7 @@ object BrieySynthesisBench { override def getName(): String = "Briey" override def getRtlPath(): String = "Briey.v" SpinalVerilog({ - val briey = new Briey(BrieyConfig.default).setDefinitionName(getRtlPath().split("\\.").head) + val briey = InOutWrapper(new Briey(BrieyConfig.default).setDefinitionName(getRtlPath().split("\\.").head)) briey.io.axiClk.setName("clk") briey }) @@ -161,7 +162,7 @@ object MuraxSynthesisBench { override def getName(): String = "Murax" override def getRtlPath(): String = "Murax.v" SpinalVerilog({ - val murax = new Murax(MuraxConfig.default.copy(gpioWidth = 8)).setDefinitionName(getRtlPath().split("\\.").head) + val murax = InOutWrapper(new Murax(MuraxConfig.default.copy(gpioWidth = 8)).setDefinitionName(getRtlPath().split("\\.").head)) murax.io.mainClk.setName("clk") murax }) @@ -172,7 +173,7 @@ object MuraxSynthesisBench { override def getName(): String = "MuraxFast" override def getRtlPath(): String = "MuraxFast.v" SpinalVerilog({ - val murax = new Murax(MuraxConfig.fast.copy(gpioWidth = 8)).setDefinitionName(getRtlPath().split("\\.").head) + val murax = InOutWrapper(new Murax(MuraxConfig.fast.copy(gpioWidth = 8)).setDefinitionName(getRtlPath().split("\\.").head)) murax.io.mainClk.setName("clk") murax }) From 559260020b4dda3c5532fc281ae302936ed6baa3 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sun, 1 Mar 2020 13:02:08 +0100 Subject: [PATCH 33/51] Improve testing infrastructure with more options and better readme https://github.com/litex-hub/linux-on-litex-vexriscv/issues/112 --- README.md | 45 ++++++++--- .../vexriscv/TestIndividualFeatures.scala | 76 +++++++++++-------- 2 files changed, 80 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index d0deb16..d76a040 100644 --- a/README.md +++ b/README.md @@ -186,24 +186,47 @@ NOTES: [![Build Status](https://travis-ci.org/SpinalHDL/VexRiscv.svg?branch=master)](https://travis-ci.org/SpinalHDL/VexRiscv) -To run tests (need the verilator simulator), go in the src/test/cpp/regression folder and run : +To run tests (need the java, scala, verilator), just do : ```sh -# To test the GenFull CPU -# (Don't worry about the CSR test not passing, basicaly the GenFull isn't the truly full version of the CPU, some CSR features are disable in it) -make clean run - -# To test the GenSmallest CPU -make clean run IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no +export VEXRISCV_REGRESSION_SEED=42 +export VEXRISCV_REGRESSION_TEST_ID= +sbt "testOnly vexriscv.TestIndividualFeatures" ``` -The self-test includes: -- ISA tests from https://github.com/riscv/riscv-tests/tree/master/isa +This will generate random VexRiscv configuration and test them with: +- ISA tests from https://github.com/riscv/riscv-tests/tree/master/isa and https://github.com/riscv/riscv-compliance - Dhrystone benchmark -- 24 FreeRTOS tests +- Coremark benchmark +- Zephyr os +- Buildroot/Linux os - Some handwritten tests to check the CSR, debug module and MMU plugins -You can enable FreeRTOS tests by adding `FREERTOS=yes` to the command line, but it will take time to run. Also, it uses THREAD_COUNT host CPU threads to run multiple regression in parallel. +You can rerun some specific test by setting VEXRISCV_REGRESSION_TEST_ID by their id. For instance, if you want to rerun : +- test_id_5_test_IBus_CachedS1024W1BPL32Relaxvexriscv.plugin.DYNAMIC_DBus_CachedS8192W2BPL16_MulDiv_MulDivFpga_Shift_FullLate_Branch_Late_Hazard_BypassAll_RegFile_SyncDR_Src__Csr_AllNoException_Decoder__Debug_None_DBus_NoMmu +- test_id_9_test_IBus_Simple1S2InjStagevexriscv.plugin.STATIC_DBus_SimpleLate_MulDiv_MulDivFpgaSimple_Shift_FullEarly_Branch_Late_Hazard_Interlock_RegFile_AsyncER_Src_AddSubExecute_Csr_None_Decoder__Debug_None_DBus_NoMmu + +then : + +``` +export VEXRISCV_REGRESSION_TEST_ID=5,9 +``` + +Also there is a few environnement variable that you can use to modulate the random generation : + +| Parameters | range | description | +| ------------------------------------------- | ------------------ | ----------- | +| VEXRISCV_REGRESSION_SEED | Int | Seed used to generate the random configurations | +| VEXRISCV_REGRESSION_TEST_ID | \[Int\[,\Int\]\*\] | Random configuration that should be keeped and tested | +| VEXRISCV_REGRESSION_CONFIG_COUNT | Int | Number of random configurations | +| VEXRISCV_REGRESSION_CONFIG_RVC_RATE | 0.0-1.0 | Chance to generate a RVC config | +| VEXRISCV_REGRESSION_CONFIG_LINUX_RATE | 0.0-1.0 | Chance to generate a linux ready config | +| VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE | 0.0-1.0 | Chance to generate a machine mode OS ready config | +| VEXRISCV_REGRESSION_LINUX_REGRESSION | yes/no | Enable the linux test | +| VEXRISCV_REGRESSION_COREMARK | yes/no | Enable the Coremark test | +| VEXRISCV_REGRESSION_ZEPHYR_COUNT | Int | Number of zephyr tests to run on capable configs | +| VEXRISCV_REGRESSION_CONFIG_DEMW_RATE | 0.0-1.0 | Chance to generate a config with writeback stage | +| VEXRISCV_REGRESSION_CONFIG_DEM_RATE | 0.0-1.0 | Chance to generate a config with memory stage | ## Interactive debug of the simulated CPU via GDB OpenOCD and Verilator It's as described to run tests, but you just have to add `DEBUG_PLUGIN_EXTERNAL=yes` in the make arguments. diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 005f335..6605cb5 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -3,7 +3,7 @@ package vexriscv import java.io.File import org.apache.commons.io.FileUtils -import org.scalatest.FunSuite +import org.scalatest.{BeforeAndAfterAll, FunSuite, ParallelTestExecution} import spinal.core._ import vexriscv.demo._ import vexriscv.ip.{DataCacheConfig, InstructionCacheConfig} @@ -313,7 +313,7 @@ class SrcDimension extends VexRiscvDimension("Src") { } -class IBusDimension extends VexRiscvDimension("IBus") { +class IBusDimension(rvcRate : Double) extends VexRiscvDimension("IBus") { override def randomPositionImpl(universes: Seq[ConfigUniverse], r: Random) = { @@ -322,7 +322,7 @@ class IBusDimension extends VexRiscvDimension("IBus") { if(r.nextDouble() < 0.5){ val latency = r.nextInt(5) + 1 - val compressed = r.nextBoolean() + val compressed = r.nextDouble() < rvcRate val injectorStage = r.nextBoolean() || latency == 1 val prediction = random(r, List(NONE, STATIC, DYNAMIC, DYNAMIC_TARGET)) val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) @@ -345,7 +345,7 @@ class IBusDimension extends VexRiscvDimension("IBus") { } } else { val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) - val compressed = r.nextBoolean() + val compressed = r.nextDouble() < rvcRate val tighlyCoupled = r.nextBoolean() && !catchAll // val tighlyCoupled = false val prediction = random(r, List(NONE, STATIC, DYNAMIC, DYNAMIC_TARGET)) @@ -497,14 +497,14 @@ class MmuDimension extends VexRiscvDimension("DBus") { trait CatchAllPosition -class CsrDimension(freertos : String, zephyr : String) extends VexRiscvDimension("Csr") { +class CsrDimension(freertos : String, zephyr : String, linux : String) extends VexRiscvDimension("Csr") { override def randomPositionImpl(universes: Seq[ConfigUniverse], r: Random) = { val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) val supervisor = universes.contains(VexRiscvUniverse.SUPERVISOR) if(supervisor){ new VexRiscvPosition("Supervisor") with CatchAllPosition{ override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.linuxFull(0x80000020l)) - override def testParam = s"FREERTOS=$freertos ZEPHYR=$zephyr LINUX_REGRESSION=${sys.env.getOrElse("VEXRISCV_REGRESSION_LINUX_REGRESSION", "yes")} SUPERVISOR=yes" + override def testParam = s"FREERTOS=$freertos ZEPHYR=$zephyr LINUX_REGRESSION=$linux SUPERVISOR=yes" } } else if(catchAll){ new VexRiscvPosition("MachineOs") with CatchAllPosition{ @@ -554,10 +554,35 @@ class DecoderDimension extends VexRiscvDimension("Decoder") { } - +//class TesterPlay extends FunSuite with ParallelTestExecution { +// def createTest(name : String): Unit ={ +// test(name){ +// for(i <- 0 to 4) { +// println(s"$name $i") +// Thread.sleep(2000) +// } +// } +// } +// List("a", "b","c").foreach(createTest) +//} class TestIndividualFeatures extends FunSuite { + val testCount = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_COUNT", "100").toInt + val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong + val testId : Set[Int] = sys.env.get("VEXRISCV_REGRESSION_TEST_ID") match { + case Some(x) if x != "" => x.split(',').map(_.toInt).toSet + case _ => (0 until testCount).toSet + } + val rvcRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_RVC_RATE", "0.5").toDouble + val linuxRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_LINUX_RATE", "0.3").toDouble + val machineOsRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE", "0.5").toDouble + val linuxRegression = sys.env.getOrElse("VEXRISCV_REGRESSION_LINUX_REGRESSION", "yes") + val coremarkRegression = sys.env.getOrElse("VEXRISCV_REGRESSION_COREMARK", "yes") + val zephyrCount = sys.env.getOrElse("VEXRISCV_REGRESSION_ZEPHYR_COUNT", "4") + val demwRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble + val demRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEM_RATE", "0.5").toDouble + def doCmd(cmd: String): String = { val stdOut = new StringBuilder() class Logger extends ProcessLogger { @@ -578,7 +603,7 @@ class TestIndividualFeatures extends FunSuite { val dimensions = List( - new IBusDimension, + new IBusDimension(rvcRate), new DBusDimension, new MulDivDimension, new ShiftDimension, @@ -586,7 +611,7 @@ class TestIndividualFeatures extends FunSuite { new HazardDimension, new RegFileDimension, new SrcDimension, - new CsrDimension(/*sys.env.getOrElse("VEXRISCV_REGRESSION_FREERTOS_COUNT", "1")*/ "0", sys.env.getOrElse("VEXRISCV_REGRESSION_ZEPHYR_COUNT", "4")), //Freertos old port software is broken + new CsrDimension(/*sys.env.getOrElse("VEXRISCV_REGRESSION_FREERTOS_COUNT", "1")*/ "0", zephyrCount, linuxRegression), //Freertos old port software is broken new DecoderDimension, new DebugDimension, new MmuDimension @@ -612,15 +637,15 @@ class TestIndividualFeatures extends FunSuite { } val name = (if(noMemory) "noMemoryStage_" else "") + (if(noWriteback) "noWritebackStage_" else "") + positionsToApply.map(d => d.dimension.name + "_" + d.name).mkString("_") - test(prefix + name + "_gen") { + test(prefix + "gen_" + name) { gen } - test(prefix + name + "_test") { + test(prefix + "test_" + name) { println("START TEST " + prefix + name) val debug = true - val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${sys.env.getOrElse("VEXRISCV_REGRESSION_COREMARK", "yes")} THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", 1)} ") + s" SEED=${testSeed} " + val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=1000000000000l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${coremarkRegression} THREAD_COUNT=1 ") + s" SEED=${testSeed} " val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ") println(testCmd) val str = doCmd(testCmd) @@ -628,42 +653,33 @@ class TestIndividualFeatures extends FunSuite { } } - val testId : Option[mutable.HashSet[Int]] = None - val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong -// -// val testId = Some(mutable.HashSet(3,4,9,11,13,16,18,19,20,21)) -// val testId = Some(mutable.HashSet(11)) -// val testId = Some(mutable.HashSet(4, 11)) -// val seed = 6592877339343561798l - - val rand = new Random(seed) test("Info"){ println(s"MAIN_SEED=$seed") } println(s"Seed=$seed") - for(i <- 0 until sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_COUNT", "100").toInt){ + for(i <- 0 until testCount){ var positions : List[VexRiscvPosition] = null var universe = mutable.HashSet[VexRiscvUniverse]() if(rand.nextDouble() < 0.5) universe += VexRiscvUniverse.EXECUTE_RF - if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_LINUX_RATE", "0.3").toDouble > rand.nextDouble()) { + if(linuxRate > rand.nextDouble()) { universe += VexRiscvUniverse.CATCH_ALL universe += VexRiscvUniverse.MMU universe += VexRiscvUniverse.FORCE_MULDIV universe += VexRiscvUniverse.SUPERVISOR - if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble < rand.nextDouble()){ + if(demwRate < rand.nextDouble()){ universe += VexRiscvUniverse.NO_WRITEBACK } } else { - if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE", "0.5").toDouble > rand.nextDouble()) { + if(machineOsRate > rand.nextDouble()) { universe += VexRiscvUniverse.CATCH_ALL - if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble < rand.nextDouble()){ + if(demwRate < rand.nextDouble()){ universe += VexRiscvUniverse.NO_WRITEBACK } } - if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble > rand.nextDouble()){ - }else if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEM_RATE", "0.5").toDouble > rand.nextDouble()){ + if(demwRate > rand.nextDouble()){ + }else if(demRate > rand.nextDouble()){ universe += VexRiscvUniverse.NO_WRITEBACK } else { universe += VexRiscvUniverse.NO_WRITEBACK @@ -676,8 +692,8 @@ class TestIndividualFeatures extends FunSuite { }while(!positions.forall(_.isCompatibleWith(positions))) val testSeed = rand.nextInt() - if(testId.isEmpty || testId.get.contains(i)) - doTest(positions," random_" + i + "_", testSeed, universe) + if(testId.contains(i)) + doTest(positions," test_id_" + i + "_", testSeed, universe) Hack.dCounter += 1 } } \ No newline at end of file From 02545b9beae0e1420d38f7b8001dde98f4585445 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sun, 1 Mar 2020 13:03:40 +0100 Subject: [PATCH 34/51] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d76a040..76f511b 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ NOTES: [![Build Status](https://travis-ci.org/SpinalHDL/VexRiscv.svg?branch=master)](https://travis-ci.org/SpinalHDL/VexRiscv) -To run tests (need the java, scala, verilator), just do : +To run tests (need java, scala, verilator), just do : ```sh export VEXRISCV_REGRESSION_SEED=42 From ea5464ea26c4151b6218ac53ed6fc5bba4c96e77 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sun, 1 Mar 2020 21:40:53 +0100 Subject: [PATCH 35/51] TestIndividualFeatures is now multithreaded --- src/test/cpp/regression/main.cpp | 58 +++--- src/test/cpp/regression/makefile | 15 +- .../vexriscv/TestIndividualFeatures.scala | 166 +++++++++++++----- 3 files changed, 160 insertions(+), 79 deletions(-) diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index 75f06bd..d983e8e 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -2805,7 +2805,7 @@ public: uint32_t regFileWriteRefIndex = 0; TestA() : WorkspaceRegression("testA") { - loadHex("../../resources/hex/testA.hex"); + loadHex(string(REGRESSION_PATH) + "../../resources/hex/testA.hex"); } virtual void checks(){ @@ -2831,7 +2831,7 @@ public: TestX28(string name, uint32_t *ref, uint32_t refSize) : WorkspaceRegression(name) { this->ref = ref; this->refSize = refSize; - loadHex("../../resources/hex/" + name + ".hex"); + loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".hex"); } virtual void checks(){ @@ -2851,7 +2851,7 @@ public: class RiscvTest : public WorkspaceRegression{ public: RiscvTest(string name) : WorkspaceRegression(name) { - loadHex("../../resources/hex/" + name + ".hex"); + loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".hex"); bootAt(0x800000bcu); } @@ -2899,7 +2899,7 @@ public: setIStall(iStall); setDStall(dStall); withRiscvRef(); - loadHex("../../resources/hex/" + hexName + ".hex"); + loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + hexName + ".hex"); this->hexName = hexName; } @@ -2942,7 +2942,7 @@ public: int out32Counter = 0; Compliance(string name) : WorkspaceRegression(name) { withRiscvRef(); - loadHex("../../resources/hex/" + name + ".elf.hex"); + loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".elf.hex"); out32.open (name + ".out32"); this->name = name; } @@ -2963,7 +2963,7 @@ public: virtual void pass(){ - FILE *refFile = fopen((string("../../resources/ref/") + name + ".reference_output").c_str(), "r"); + FILE *refFile = fopen((string(REGRESSION_PATH) + string("../../resources/ref/") + name + ".reference_output").c_str(), "r"); fseek(refFile, 0, SEEK_END); uint32_t refSize = ftell(refFile); fseek(refFile, 0, SEEK_SET); @@ -3152,7 +3152,7 @@ public: DebugPluginTest() : WorkspaceRegression("DebugPluginTest") { - loadHex("../../resources/hex/debugPlugin.hex"); + loadHex(string(REGRESSION_PATH) + "../../resources/hex/debugPlugin.hex"); pthread_create(&clientThreadId, NULL, &clientThreadWrapper, this); } @@ -3837,17 +3837,17 @@ int main(int argc, char **argv, char **env) { // #endif #ifdef IBUS_CACHED - redo(REDO,WorkspaceRegression("icache").withRiscvRef()->loadHex("../raw/icache/build/icache.hex")->bootAt(0x80000000u)->run(50e3);); + redo(REDO,WorkspaceRegression("icache").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/icache/build/icache.hex")->bootAt(0x80000000u)->run(50e3);); #endif #ifdef DBUS_CACHED - redo(REDO,WorkspaceRegression("dcache").loadHex("../raw/dcache/build/dcache.hex")->bootAt(0x80000000u)->run(2500e3);); + redo(REDO,WorkspaceRegression("dcache").loadHex(string(REGRESSION_PATH) + "../raw/dcache/build/dcache.hex")->bootAt(0x80000000u)->run(2500e3);); #endif #ifdef MMU - redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3);); + redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3);); #endif #ifdef SUPERVISOR - redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3);); + redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3);); #endif #ifdef DEBUG_PLUGIN @@ -3858,20 +3858,20 @@ int main(int argc, char **argv, char **env) { #endif #ifdef CUSTOM_SIMD_ADD - redo(REDO,WorkspaceRegression("custom_simd_add").loadHex("../custom/simd_add/build/custom_simd_add.hex")->bootAt(0x00000000u)->run(50e3);); + redo(REDO,WorkspaceRegression("custom_simd_add").loadHex(string(REGRESSION_PATH) + "../custom/simd_add/build/custom_simd_add.hex")->bootAt(0x00000000u)->run(50e3);); #endif #ifdef CUSTOM_CSR - redo(REDO,WorkspaceRegression("custom_csr").loadHex("../custom/custom_csr/build/custom_csr.hex")->bootAt(0x00000000u)->run(50e3);); + redo(REDO,WorkspaceRegression("custom_csr").loadHex(string(REGRESSION_PATH) + "../custom/custom_csr/build/custom_csr.hex")->bootAt(0x00000000u)->run(50e3);); #endif #ifdef LRSC - redo(REDO,WorkspaceRegression("lrsc").withRiscvRef()->loadHex("../raw/lrsc/build/lrsc.hex")->bootAt(0x00000000u)->run(10e3);); + redo(REDO,WorkspaceRegression("lrsc").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/lrsc/build/lrsc.hex")->bootAt(0x00000000u)->run(10e3);); #endif #ifdef AMO - redo(REDO,WorkspaceRegression("amo").withRiscvRef()->loadHex("../raw/amo/build/amo.hex")->bootAt(0x00000000u)->run(10e3);); + redo(REDO,WorkspaceRegression("amo").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/amo/build/amo.hex")->bootAt(0x00000000u)->run(10e3);); #endif #ifdef DHRYSTONE @@ -3910,7 +3910,7 @@ int main(int argc, char **argv, char **env) { if(withStall == -1) break; #endif WorkspaceRegression("coremark_" + rv + (withStall > 0 ? "_stall" : "_nostall")).withRiscvRef() - ->loadBin("../../resources/bin/coremark_" + rv + ".bin", 0x80000000) + ->loadBin(string(REGRESSION_PATH) + "../../resources/bin/coremark_" + rv + ".bin", 0x80000000) ->bootAt(0x80000000) ->setIStall(withStall > 0) ->setDStall(withStall > 0) @@ -3930,17 +3930,17 @@ int main(int argc, char **argv, char **env) { /*for(int redo = 0;redo < 4;redo++)*/{ for(const string &name : freeRtosTests){ - tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O0").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32i_O0.hex")->bootAt(0x80000000u)->run(4e6*15);}); - tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32i_O3.hex")->bootAt(0x80000000u)->run(4e6*15);}); + tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O0").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32i_O0.hex")->bootAt(0x80000000u)->run(4e6*15);}); + tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32i_O3.hex")->bootAt(0x80000000u)->run(4e6*15);}); #ifdef COMPRESSED -// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O0").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32ic_O0.hex")->bootAt(0x80000000u)->run(5e6*15);}); - tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32ic_O3.hex")->bootAt(0x80000000u)->run(4e6*15);}); +// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O0").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32ic_O0.hex")->bootAt(0x80000000u)->run(5e6*15);}); + tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32ic_O3.hex")->bootAt(0x80000000u)->run(4e6*15);}); #endif #if defined(MUL) && defined(DIV) // #ifdef COMPRESSED -// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32imac_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32imac_O3.hex")->bootAt(0x80000000u)->run(4e6*15);}); +// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32imac_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32imac_O3.hex")->bootAt(0x80000000u)->run(4e6*15);}); // #else - tasks.push_back([=]() { WorkspaceRegression(name + "_rv32im_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32im_O3.hex")->bootAt(0x80000000u)->run(4e6*15);}); + tasks.push_back([=]() { WorkspaceRegression(name + "_rv32im_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32im_O3.hex")->bootAt(0x80000000u)->run(4e6*15);}); // #endif #endif } @@ -3967,12 +3967,12 @@ int main(int argc, char **argv, char **env) { /*for(int redo = 0;redo < 4;redo++)*/{ for(const string &name : zephyrTests){ #ifdef COMPRESSED - tasks.push_back([=]() { ZephyrRegression(name + "_rv32ic").withRiscvRef()->loadHex("../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32ic.hex")->bootAt(0x80000000u)->run(180e6);}); + tasks.push_back([=]() { ZephyrRegression(name + "_rv32ic").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32ic.hex")->bootAt(0x80000000u)->run(180e6);}); #else - tasks.push_back([=]() { ZephyrRegression(name + "_rv32i").withRiscvRef()->loadHex("../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32i.hex")->bootAt(0x80000000u)->run(180e6);}); + tasks.push_back([=]() { ZephyrRegression(name + "_rv32i").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32i.hex")->bootAt(0x80000000u)->run(180e6);}); #endif #if defined(MUL) && defined(DIV) - tasks.push_back([=]() { ZephyrRegression(name + "_rv32im").withRiscvRef()->loadHex("../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32im.hex")->bootAt(0x80000000u)->run(180e6);}); + tasks.push_back([=]() { ZephyrRegression(name + "_rv32im").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32im.hex")->bootAt(0x80000000u)->run(180e6);}); #endif } } @@ -3993,10 +3993,10 @@ int main(int argc, char **argv, char **env) { LinuxRegression soc("linux"); #ifndef DEBUG_PLUGIN_EXTERNAL soc.withRiscvRef(); - soc.loadBin(EMULATOR, 0x80000000); - soc.loadBin(VMLINUX, 0xC0000000); - soc.loadBin(DTB, 0xC3000000); - soc.loadBin(RAMDISK, 0xC2000000); + soc.loadBin(string(REGRESSION_PATH) + EMULATOR, 0x80000000); + soc.loadBin(string(REGRESSION_PATH) + VMLINUX, 0xC0000000); + soc.loadBin(string(REGRESSION_PATH) + DTB, 0xC3000000); + soc.loadBin(string(REGRESSION_PATH) + RAMDISK, 0xC2000000); #endif //soc.setIStall(true); //soc.setDStall(true); diff --git a/src/test/cpp/regression/makefile b/src/test/cpp/regression/makefile index ad05707..61fe9d1 100644 --- a/src/test/cpp/regression/makefile +++ b/src/test/cpp/regression/makefile @@ -1,5 +1,6 @@ DEBUG?=no - +REGRESSION_PATH?=./ +VEXRISCV_FILE?=../../../../VexRiscv.v IBUS?=CACHED IBUS_TC?=no DBUS?=CACHED @@ -38,6 +39,7 @@ STOP_ON_ERROR?=no COREMARK=no WITH_USER_IO?=no +ADDCFLAGS += -CFLAGS -DREGRESSION_PATH='\"$(REGRESSION_PATH)/\"' ADDCFLAGS += -CFLAGS -DIBUS_${IBUS} ADDCFLAGS += -CFLAGS -DDBUS_${DBUS} ADDCFLAGS += -CFLAGS -DREDO=${REDO} @@ -107,11 +109,11 @@ endif -ifneq ($(shell grep timerInterrupt ../../../../VexRiscv.v -w),) +ifneq ($(shell grep timerInterrupt ${VEXRISCV_FILE} -w),) ADDCFLAGS += -CFLAGS -DTIMER_INTERRUPT endif -ifneq ($(shell grep externalInterrupt ../../../../VexRiscv.v -w),) +ifneq ($(shell grep externalInterrupt ${VEXRISCV_FILE} -w),) ifneq ($(EXTERNAL_INTERRUPT),no) ADDCFLAGS += -CFLAGS -DEXTERNAL_INTERRUPT endif @@ -267,10 +269,9 @@ all: clean run run: compile ./obj_dir/VVexRiscv -verilate: ../../../../VexRiscv.v - rm -f VexRiscv.v*.bin - cp ../../../../VexRiscv.v*.bin . | true - verilator -cc ../../../../VexRiscv.v -O3 -CFLAGS -std=c++11 -LDFLAGS -pthread ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-UNOPTFLAT -Wno-WIDTH --x-assign unique --exe main.cpp +verilate: ${VEXRISCV_FILE} + cp ${VEXRISCV_FILE}*.bin . | true + verilator -cc ${VEXRISCV_FILE} -O3 -CFLAGS -std=c++11 -LDFLAGS -pthread ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-UNOPTFLAT -Wno-WIDTH --x-assign unique --exe main.cpp compile: verilate make -j${THREAD_COUNT} -C obj_dir/ -f VVexRiscv.mk VVexRiscv diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 6605cb5..047c719 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -1,9 +1,10 @@ package vexriscv -import java.io.File +import java.io.{File, OutputStream} +import java.util.concurrent.TimeUnit import org.apache.commons.io.FileUtils -import org.scalatest.{BeforeAndAfterAll, FunSuite, ParallelTestExecution} +import org.scalatest.{BeforeAndAfterAll, FunSuite, ParallelTestExecution, Tag, Transformer} import spinal.core._ import vexriscv.demo._ import vexriscv.ip.{DataCacheConfig, InstructionCacheConfig} @@ -11,6 +12,8 @@ import vexriscv.plugin._ import scala.collection.mutable import scala.collection.mutable.ArrayBuffer +import scala.concurrent.duration.Duration +import scala.concurrent.{Await, ExecutionContext, Future} import scala.sys.process._ import scala.util.Random @@ -534,6 +537,7 @@ class DebugDimension extends VexRiscvDimension("Debug") { }, new VexRiscvPosition("Enable") { override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))) + override def testParam = "CONCURRENT_OS_EXECUTIONS=yes" } )) } @@ -553,21 +557,80 @@ class DecoderDimension extends VexRiscvDimension("Decoder") { } } +object PlayFuture extends App{ + implicit val ec = ExecutionContext.global + val x = for(i <- 0 until 160) yield Future { + print(s"$i ") + Thread.sleep(1000) + } -//class TesterPlay extends FunSuite with ParallelTestExecution { -// def createTest(name : String): Unit ={ -// test(name){ -// for(i <- 0 to 4) { -// println(s"$name $i") -// Thread.sleep(2000) -// } -// } -// } -// List("a", "b","c").foreach(createTest) -//} + Thread.sleep(8000) +} + +class MultithreadedFunSuite extends FunSuite { + implicit val ec = ExecutionContext.global + class Job(body : => Unit){ + val originalOutput = Console.out + val buffer = mutable.Queue[Char]() + var bufferEnabled = true + def redirector() = new OutputStream{ + override def write(i: Int): Unit = synchronized { + if(bufferEnabled) buffer += i.toChar + else originalOutput.print(i.toChar) + } + } + val future = Future{ + Console.withOut(redirector()){ + Console.withErr(redirector())(body) + } + } + + def join(): Unit = { + Thread.sleep(50) + synchronized{ + bufferEnabled = false + buffer.foreach(originalOutput.print) + } + Await.result(future, Duration.Inf) + } + } + + override protected def test(testName: String, testTags: Tag*)(testFun: => Unit) { + val job = new Job(testFun) + super.test(testName, testTags :_*)(job.join()) + } + protected def testSingleThread(testName: String, testTags: Tag*)(testFun: => Unit) { + super.test(testName, testTags :_*)(testFun) + } +} -class TestIndividualFeatures extends FunSuite { +class FunTestPara extends MultithreadedFunSuite{ + def createTest(name : String): Unit ={ + test(name){ + for(i <- 0 to 4) { + println(s"$name $i") + Thread.sleep(500) + } + } + } + (0 to 80).map(_.toString).foreach(createTest) +} + +class FunTestPlay extends FunSuite { + def createTest(name : String): Unit ={ + test(name){ + Thread.sleep(500) + for(i <- 0 to 4) { + println(s"$name $i") + Thread.sleep(500) + } + } + } + (0 to 80).map(_.toString).foreach(createTest) +} + +class TestIndividualFeatures extends MultithreadedFunSuite { val testCount = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_COUNT", "100").toInt val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong val testId : Set[Int] = sys.env.get("VEXRISCV_REGRESSION_TEST_ID") match { @@ -582,24 +645,8 @@ class TestIndividualFeatures extends FunSuite { val zephyrCount = sys.env.getOrElse("VEXRISCV_REGRESSION_ZEPHYR_COUNT", "4") val demwRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble val demRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEM_RATE", "0.5").toDouble + val lock = new{} - def doCmd(cmd: String): String = { - val stdOut = new StringBuilder() - class Logger extends ProcessLogger { - override def err(s: => String): Unit = { - if (!s.startsWith("ar: creating ")) println(s) - } - - override def out(s: => String): Unit = { - println(s) - stdOut ++= s - } - - override def buffer[T](f: => T) = f - } - Process(cmd, new File("src/test/cpp/regression")).!(new Logger) - stdOut.toString() - } val dimensions = List( @@ -617,12 +664,40 @@ class TestIndividualFeatures extends FunSuite { new MmuDimension ) + var clockCounter = 0l + var startAt = System.currentTimeMillis() def doTest(positionsToApply : List[VexRiscvPosition], prefix : String = "", testSeed : Int, universes : mutable.HashSet[VexRiscvUniverse]): Unit ={ val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY) val noWriteback = universes.contains(VexRiscvUniverse.NO_WRITEBACK) - def gen = { + val name = (if(noMemory) "noMemoryStage_" else "") + (if(noWriteback) "noWritebackStage_" else "") + positionsToApply.map(d => d.dimension.name + "_" + d.name).mkString("_") + val workspace = "simWorkspace" + val project = s"$workspace/$prefix" + def doCmd(cmd: String): String = { + val stdOut = new StringBuilder() + class Logger extends ProcessLogger { + override def err(s: => String): Unit = { + if (!s.startsWith("ar: creating ")) println(s) + } + override def out(s: => String): Unit = { + println(s) + stdOut ++= s + } + override def buffer[T](f: => T) = f + } + Process(cmd, new File(project)).!(new Logger) + stdOut.toString() + } + + test(prefix + name) { + println("START TEST " + prefix + name) + + //Cleanup + FileUtils.deleteDirectory(new File(project)) + FileUtils.forceMkdir(new File(project)) + + //Generate RTL FileUtils.deleteQuietly(new File("VexRiscv.v")) - SpinalVerilog{ + SpinalConfig(targetDirectory = project).generateVerilog{ val config = VexRiscvConfig( withMemoryStage = !noMemory, withWriteBackStage = !noWriteback, @@ -634,22 +709,22 @@ class TestIndividualFeatures extends FunSuite { for (positionToApply <- positionsToApply) positionToApply.applyOn(config) new VexRiscv(config) } - } - val name = (if(noMemory) "noMemoryStage_" else "") + (if(noWriteback) "noWritebackStage_" else "") + positionsToApply.map(d => d.dimension.name + "_" + d.name).mkString("_") - test(prefix + "gen_" + name) { - gen - } + //Setup test + val files = List("main.cpp", "encoding.h" ,"makefile", "dhrystoneO3.logRef", "dhrystoneO3C.logRef","dhrystoneO3MC.logRef","dhrystoneO3M.logRef") + files.foreach(f => FileUtils.copyFileToDirectory(new File(s"src/test/cpp/regression/$f"), new File(project))) - - test(prefix + "test_" + name) { - println("START TEST " + prefix + name) + //Test RTL val debug = true - val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=1000000000000l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${coremarkRegression} THREAD_COUNT=1 ") + s" SEED=${testSeed} " + val stdCmd = (s"make run REGRESSION_PATH=../../src/test/cpp/regression VEXRISCV_FILE=VexRiscv.v WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=1000000000000l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${coremarkRegression} THREAD_COUNT=1 ") + s" SEED=${testSeed} " val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ") println(testCmd) val str = doCmd(testCmd) assert(str.contains("REGRESSION SUCCESS") && !str.contains("Broken pipe")) + val pattern = "Had simulate ([0-9]+)".r + val hit = pattern.findFirstMatchIn(str) + + lock.synchronized(clockCounter += hit.get.group(1).toLong) } } @@ -693,7 +768,12 @@ class TestIndividualFeatures extends FunSuite { val testSeed = rand.nextInt() if(testId.contains(i)) - doTest(positions," test_id_" + i + "_", testSeed, universe) + doTest(positions,"test_id_" + i + "_", testSeed, universe) Hack.dCounter += 1 } + testSingleThread("report"){ + val time = (System.currentTimeMillis() - startAt)*1e-3 + val clockPerSecond = (clockCounter/time*1e-3).toLong + println(s"Duration=${(time/60).toInt}mn clocks=${(clockCounter*1e-6).toLong}M clockPerSecond=${clockPerSecond}K") + } } \ No newline at end of file From 54581f6d9e38d1d0d809588dfd752e69d06c8256 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Mon, 2 Mar 2020 14:23:26 +0100 Subject: [PATCH 36/51] Fix #117 DataCache mem blackboxing --- src/main/scala/vexriscv/ip/DataCache.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index eaed1d0..8e62bc7 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -402,7 +402,7 @@ class DataCache(p : DataCacheConfig) extends Component{ //Writes when(tagsWriteCmd.valid && tagsWriteCmd.way(i)){ - tags(tagsWriteCmd.address) := tagsWriteCmd.data + tags.write(tagsWriteCmd.address, tagsWriteCmd.data) } when(dataWriteCmd.valid && dataWriteCmd.way(i)){ data.write( From ef5398ce2107a029f1ea1a51ac37a5119c2d7596 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Mon, 2 Mar 2020 14:23:26 +0100 Subject: [PATCH 37/51] Fix #117 DataCache mem blackboxing --- src/main/scala/vexriscv/ip/DataCache.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index eaed1d0..8e62bc7 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -402,7 +402,7 @@ class DataCache(p : DataCacheConfig) extends Component{ //Writes when(tagsWriteCmd.valid && tagsWriteCmd.way(i)){ - tags(tagsWriteCmd.address) := tagsWriteCmd.data + tags.write(tagsWriteCmd.address, tagsWriteCmd.data) } when(dataWriteCmd.valid && dataWriteCmd.way(i)){ data.write( From fd37962a58c88cb3314e366a5d4b693df94418f6 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Tue, 3 Mar 2020 10:55:59 +0100 Subject: [PATCH 38/51] typo --- doc/smp/smp.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/smp/smp.md b/doc/smp/smp.md index c335f1f..6fa67c6 100644 --- a/doc/smp/smp.md +++ b/doc/smp/smp.md @@ -52,6 +52,8 @@ Composed of 2 stream : ### Probe bus +Composed of 2 stream : + | Name | Direction | Description | |----------|-----------|----------| | probeCmd | M <- S | Used for cache management | @@ -98,7 +100,7 @@ Emitted on the readAck channel (master -> slave), it carry no information, just | Name | From command | Description | |--------------|---------------|----------| -| readSuccess | * | - | +| readSuccess | * | - | ### Write commands From 12463e40a46079167d226b56ed1969b3b43e117a Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 3 Mar 2020 15:59:30 +0100 Subject: [PATCH 39/51] improve debugPlugin step logic --- src/main/scala/vexriscv/plugin/DebugPlugin.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index a1051d7..8c990f9 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -213,11 +213,14 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount : iBusFetcher.haltIt() } - when(stepIt && iBusFetcher.incoming()) { - iBusFetcher.haltIt() + when(stepIt) { + //Assume nothing will stop the CPU in the decode stage when(decode.arbitration.isValid) { haltIt := True } + when(execute.arbitration.isValid) { + decode.arbitration.flushNext := True + } } //Avoid having two C instruction executed in a single step From ff5cfc0ddee98fe89bc1f4f23ac9b4cb748961ce Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 3 Mar 2020 18:27:53 +0100 Subject: [PATCH 40/51] Fix DebugPlugin step --- src/main/scala/vexriscv/plugin/DebugPlugin.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 8c990f9..93e65e3 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -217,8 +217,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount : //Assume nothing will stop the CPU in the decode stage when(decode.arbitration.isValid) { haltIt := True - } - when(execute.arbitration.isValid) { decode.arbitration.flushNext := True } } From 0a212c91fdaa2509c07fe321576bfd1cf80c4de3 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Wed, 4 Mar 2020 18:13:56 +0100 Subject: [PATCH 41/51] update synthesisBench paths --- .../scala/vexriscv/demo/SynthesisBench.scala | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index 91c1e5f..ca925bf 100644 --- a/src/main/scala/vexriscv/demo/SynthesisBench.scala +++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala @@ -114,12 +114,7 @@ object VexRiscvSynthesisBench { // val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full) // val rtls = List(smallAndProductive) - val targets = XilinxStdTargets( - vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin" - ) ++ AlteraStdTargets( - quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin", - quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin" - ) ++ IcestormStdTargets().take(1) + val targets = XilinxStdTargets() ++ AlteraStdTargets() ++ IcestormStdTargets().take(1) // val targets = IcestormStdTargets() Bench(rtls, targets, "/media/miaou/HD/linux/tmp/") @@ -142,12 +137,7 @@ object BrieySynthesisBench { val rtls = List(briey) - val targets = XilinxStdTargets( - vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin" - ) ++ AlteraStdTargets( - quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin", - quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin" - ) + val targets = XilinxStdTargets() ++ AlteraStdTargets() ++ IcestormStdTargets().take(1) Bench(rtls, targets, "/media/miaou/HD/linux/tmp") } @@ -181,12 +171,7 @@ object MuraxSynthesisBench { val rtls = List(murax, muraxFast) - val targets = IcestormStdTargets().take(1) ++ XilinxStdTargets( - vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin" - ) ++ AlteraStdTargets( - quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin", - quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin" - ) + val targets = XilinxStdTargets() ++ AlteraStdTargets() ++ IcestormStdTargets().take(1) Bench(rtls, targets, "/media/miaou/HD/linux/tmp") } From 505d0b700a3897ddbb4a6d3c60d449d796d80730 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Wed, 4 Mar 2020 19:58:50 +0100 Subject: [PATCH 42/51] MulDivPlugin now give names to div stages --- src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index eafa4da..da3738d 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -108,7 +108,7 @@ class MulDivIterativePlugin(genMul : Boolean = true, val div = ifGen(genDiv) (new Area{ assert(isPow2(divUnrollFactor)) - + def area = this //register allocation def numerator = rs1(31 downto 0) def denominator = rs2 @@ -130,13 +130,13 @@ class MulDivIterativePlugin(genMul : Boolean = true, numerator := inNumerator remainder := inRemainder } - case _ => { + case _ => new Area { val remainderShifted = (inRemainder ## inNumerator.msb).asUInt val remainderMinusDenominator = remainderShifted - denominator val outRemainder = !remainderMinusDenominator.msb ? remainderMinusDenominator.resize(32 bits) | remainderShifted.resize(32 bits) val outNumerator = (inNumerator ## !remainderMinusDenominator.msb).asUInt.resize(32 bits) stages(outNumerator, outRemainder, stage - 1) - } + }.setCompositeName(area, "stage_" + (divUnrollFactor-stage)) } stages(numerator, remainder, divUnrollFactor) From 50ec0a1917293a5de2b0a3f2469f80583fb136f8 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Thu, 5 Mar 2020 00:12:46 +0100 Subject: [PATCH 43/51] update readme perf --- README.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index a8f8cc9..dd90af3 100644 --- a/README.md +++ b/README.md @@ -66,53 +66,53 @@ The CPU configurations used below can be found in the `src/scala/vexriscv/demo` ``` VexRiscv small (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) -> - Artix 7 -> 239 Mhz 494 LUT 505 FF - Cyclone V -> 189 Mhz 345 ALMs - Cyclone IV -> 179 Mhz 730 LUT 494 FF + Artix 7 -> 253 Mhz 498 LUT 505 FF + Cyclone V -> 205 Mhz 350 ALMs + Cyclone IV -> 172 Mhz 731 LUT 494 FF iCE40 -> 92 Mhz 1130 LC VexRiscv small (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) -> - Artix 7 -> 238 Mhz 552 LUT 562 FF - Cyclone V -> 192 Mhz 390 ALMs - Cyclone IV -> 172 Mhz 832 LUT 551 FF + Artix 7 -> 225 Mhz 549 LUT 563 FF + Cyclone V -> 194 Mhz 392 ALMs + Cyclone IV -> 172 Mhz 830 LUT 551 FF iCE40 -> 85 Mhz 1292 LC VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) -> - Artix 7 -> 225 Mhz 699 LUT 532 FF - Cyclone V -> 144 Mhz 493 ALMs - Cyclone IV -> 148 Mhz 1,111 LUT 526 FF + Artix 7 -> 213 Mhz 787 LUT 531 FF + Cyclone V -> 150 Mhz 487 ALMs + Cyclone IV -> 151 Mhz 1,115 LUT 526 FF iCE40 -> 63 Mhz 1596 LC VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) -> - Artix 7 -> 225 Mhz 719 LUT 566 FF - Cyclone V -> 145 Mhz 511 ALMs - Cyclone IV -> 150 Mhz 1,138 LUT 532 FF + Artix 7 -> 220 Mhz 719 LUT 570 FF + Cyclone V -> 147 Mhz 516 ALMs + Cyclone IV -> 144 Mhz 1,139 LUT 532 FF iCE40 -> 66 Mhz 1680 LC VexRiscv full no cache (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 219 Mhz 1486 LUT 975 FF - Cyclone V -> 149 Mhz 943 ALMs - Cyclone IV -> 138 Mhz 2,013 LUT 966 FF + Artix 7 -> 210 Mhz 1410 LUT 975 FF + Cyclone V -> 144 Mhz 927 ALMs + Cyclone IV -> 141 Mhz 2,074 LUT 966 FF VexRiscv full (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 204 Mhz 1661 LUT 1172 FF - Cyclone V -> 143 Mhz 1,118 ALMs - Cyclone IV -> 133 Mhz 2,278 LUT 1,061 FF + Artix 7 -> 199 Mhz 1736 LUT 1120 FF + Cyclone V -> 137 Mhz 1,177 ALMs + Cyclone IV -> 142 Mhz 2,409 LUT 1,061 FF VexRiscv full max perf (HZ*IPC) -> (RV32IM, 1.38 DMIPS/Mhz 2.57 Coremark/Mhz, 8KB-I$,8KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) -> - Artix 7 -> 199 Mhz 1739 LUT 1229 FF - Cyclone V -> 132 Mhz 1,129 ALMs - Cyclone IV -> 126 Mhz 2,345 LUT 1,114 FF + Artix 7 -> 197 Mhz 1788 LUT 1210 FF + Cyclone V -> 130 Mhz 1,173 ALMs + Cyclone IV -> 124 Mhz 2,483 LUT 1,114 FF VexRiscv full with MMU (RV32IM, 1.24 DMIPS/Mhz 2.35 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) -> - Artix 7 -> 167 Mhz 1927 LUT 1553 FF - Cyclone V -> 128 Mhz 1,302 ALMs - Cyclone IV -> 125 Mhz 2,685 LUT 1,466 FF + Artix 7 -> 164 Mhz 2000 LUT 1501 FF + Cyclone V -> 125 Mhz 1,375 ALMs + Cyclone IV -> 121 Mhz 2,821 LUT 1,444 FF VexRiscv linux balanced (RV32IMA, 1.21 DMIPS/Mhz 2.27 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, catch exceptions, static branch, MMU, Supervisor, Compatible with mainstream linux) -> - Artix 7 -> 179 Mhz 2685 LUT 2177 FF - Cyclone V -> 136 Mhz 1,666 ALMs - Cyclone IV -> 123 Mhz 3,350 LUT 2,059 FF + Artix 7 -> 176 Mhz 2678 LUT 2087 FF + Cyclone V -> 137 Mhz 1,797 ALMs + Cyclone IV -> 120 Mhz 3,544 LUT 2,059 FF ``` The following configuration results in 1.44 DMIPS/MHz: From 58af94269e0c634a9f4232abc3e73122b38a2901 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Thu, 5 Mar 2020 00:13:04 +0100 Subject: [PATCH 44/51] add CsrPlugin.csrOhDecoder --- .../scala/vexriscv/plugin/CsrPlugin.scala | 117 ++++++++++++------ 1 file changed, 76 insertions(+), 41 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 6e0c41b..0cdc896 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -69,6 +69,7 @@ case class CsrPluginConfig( midelegAccess : CsrAccess = CsrAccess.NONE, pipelineCsrRead : Boolean = false, pipelinedInterrupt : Boolean = true, + csrOhDecoder : Boolean = true, deterministicInteruptionEntry : Boolean = false, //Only used for simulatation purposes wfiOutput : Boolean = false ){ @@ -263,7 +264,7 @@ case class CsrReadToWriteOverride(that : Data, bitOffset : Int) //Used for speci case class CsrOnWrite(doThat :() => Unit) case class CsrOnRead(doThat : () => Unit) case class CsrMapping() extends CsrInterface{ - val mapping = mutable.HashMap[Int,ArrayBuffer[Any]]() + val mapping = mutable.LinkedHashMap[Int,ArrayBuffer[Any]]() def addMappingAt(address : Int,that : Any) = mapping.getOrElseUpdate(address,new ArrayBuffer[Any]) += that override def r(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrRead(that,bitOffset)) override def w(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrWrite(that,bitOffset)) @@ -997,7 +998,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep val imm = IMM(input(INSTRUCTION)) def writeSrc = input(SRC1) // val readDataValid = True - val readData = B(0, 32 bits) + val readData = Bits(32 bits) val writeInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) val writeEnable = writeInstruction && ! blockedBySideEffects && !arbitration.isStuckByOthers// && readDataRegValid @@ -1043,50 +1044,84 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep //Translation of the csrMapping into real logic val csrAddress = input(INSTRUCTION)(csrRange) - Component.current.addPrePopTask(() => { - switch(csrAddress) { - for ((address, jobs) <- csrMapping.mapping) { - is(address) { - val withWrite = jobs.exists(j => j.isInstanceOf[CsrWrite] || j.isInstanceOf[CsrOnWrite]) - val withRead = jobs.exists(j => j.isInstanceOf[CsrRead] || j.isInstanceOf[CsrOnRead]) - if(withRead && withWrite) { - illegalAccess := False - } else { - if (withWrite) illegalAccess.clearWhen(input(CSR_WRITE_OPCODE)) - if (withRead) illegalAccess.clearWhen(input(CSR_READ_OPCODE)) - } + Component.current.afterElaboration{ + def doJobs(jobs : ArrayBuffer[Any]): Unit ={ + val withWrite = jobs.exists(j => j.isInstanceOf[CsrWrite] || j.isInstanceOf[CsrOnWrite]) + val withRead = jobs.exists(j => j.isInstanceOf[CsrRead] || j.isInstanceOf[CsrOnRead]) + if(withRead && withWrite) { + illegalAccess := False + } else { + if (withWrite) illegalAccess.clearWhen(input(CSR_WRITE_OPCODE)) + if (withRead) illegalAccess.clearWhen(input(CSR_READ_OPCODE)) + } - when(writeEnable) { - for (element <- jobs) element match { - case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits)) - case element: CsrOnWrite => - element.doThat() - case _ => - } - } + when(writeEnable) { + for (element <- jobs) element match { + case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits)) + case element: CsrOnWrite => + element.doThat() + case _ => + } + } - for (element <- jobs) element match { - case element: CsrRead if element.that.getBitsWidth != 0 => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits - case _ => - } - - when(readEnable) { - for (element <- jobs) element match { - case element: CsrOnRead => - element.doThat() - case _ => - } - } + when(readEnable) { + for (element <- jobs) element match { + case element: CsrOnRead => + element.doThat() + case _ => } } } - switch(csrAddress) { - for ((address, jobs) <- csrMapping.mapping if jobs.exists(_.isInstanceOf[CsrReadToWriteOverride])) { - is(address) { - for (element <- jobs) element match { - case element: CsrReadToWriteOverride if element.that.getBitsWidth != 0 => readToWriteData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits - case _ => + def doJobsOverride(jobs : ArrayBuffer[Any]): Unit ={ + for (element <- jobs) element match { + case element: CsrReadToWriteOverride if element.that.getBitsWidth != 0 => readToWriteData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits + case _ => + } + } + + csrOhDecoder match { + case false => { + readData := 0 + switch(csrAddress) { + for ((address, jobs) <- csrMapping.mapping) { + is(address) { + doJobs(jobs) + for (element <- jobs) element match { + case element: CsrRead if element.that.getBitsWidth != 0 => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits + case _ => + } + } + } + } + switch(csrAddress) { + for ((address, jobs) <- csrMapping.mapping if jobs.exists(_.isInstanceOf[CsrReadToWriteOverride])) { + is(address) { + doJobsOverride(jobs) + } + } + } + } + case true => { + val oh = csrMapping.mapping.keys.toList.distinct.map(address => address -> RegNextWhen(decode.input(INSTRUCTION)(csrRange) === address, !execute.arbitration.isStuck).setCompositeName(this, "csr_" + address)).toMap + val readDatas = ArrayBuffer[Bits]() + for ((address, jobs) <- csrMapping.mapping) { + when(oh(address)){ + doJobs(jobs) + } + if(jobs.exists(_.isInstanceOf[CsrRead])) { + val masked = B(0, 32 bits) + when(oh(address)) (for (element <- jobs) element match { + case element: CsrRead if element.that.getBitsWidth != 0 => masked(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits + case _ => + }) + readDatas += masked + } + } + readData := readDatas.reduceBalancedTree(_ | _) + for ((address, jobs) <- csrMapping.mapping) { + when(oh(address)){ + doJobsOverride(jobs) } } } @@ -1094,7 +1129,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep illegalAccess setWhen(privilege < csrAddress(9 downto 8).asUInt) illegalAccess clearWhen(!arbitration.isValid || !input(IS_CSR)) - }) + } } } } From b7ae902bbc4a89761209b8c8290db200d104859b Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Thu, 5 Mar 2020 00:14:11 +0100 Subject: [PATCH 45/51] smp spec improvements, no more read abort --- doc/smp/smp.md | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/doc/smp/smp.md b/doc/smp/smp.md index c335f1f..cc06b16 100644 --- a/doc/smp/smp.md +++ b/doc/smp/smp.md @@ -5,9 +5,11 @@ Features : - Two data paths (read + write), but allow dirty/clean sharing by reusing the write data path - Allow multi level coherent interconnect - No ordering, but provide barrier +- Allow cache-full and cache-less agents +## Memory copy status -## Memory copy flags +Memory copy, in other words, cache line, have more states than non coherent systems : | Name | Description | |---------------|-------------| @@ -16,13 +18,14 @@ Features : | Owner/Lodger | lodger => copy of the line, but no other responsibility, owner => the given cache is responsible to write back dirty data and answer probes with the data | | Clean/Dirty | clean => match main memory, dirty => main memory need updates | -All combination of those cache flag are valid. But if a cache line is invalid, the other flags have no meaning. +All combination of those cache flag are valid. But if a cache line is invalid, the other status have no meaning. -Later in the spec, memory copy state can be described as : +Later in the spec, memory copy state can be described for example as : - VSOC for (Valid, Shared, Owner, Clean) - V-OC for (Valid, Shared or Unique, Owner, Clean) - !V-OC for NOT (Valid, Shared or Unique, Owner, Clean) +- ... ## buses @@ -70,11 +73,11 @@ Emitted on the readCmd channel (master -> slave) | readShared | I--- | Get a memory copy as V--- | Want to read a uncached address | | readUnique | I--- | Get a memory copy as VUO- | Want to write a uncached address | | readOnce | I--- | Get a memory copy without coherency tracking | Instruction cache read | -| makeInvalid | VS-- | Make other memory copy as I--- and make yourself VUO- | Want to write into a shared line | +| makeUnique | VS-- | Make other memory copy as I--- and make yourself VUO- | Want to write into a shared line | | readBarrier | N/A | Ensure that the visibility of the memory operations of this channel do not cross the barrier | ISA fence | -makeInvalid should be designed with care. There is a few corner cases : -- While a master has a inflight makeInvalid, a probe can change its state. +makeUnique should be designed with care. There is a few corner cases : +- While a master has a inflight makeUnique, a probe can change its state, in such case, the makeUnique become weak and invalidation is canceled. This is usefull for multi level coherent interconnects. - Multi level coherent interconnect should be careful to properly move the ownership and not lose dirty data I'm not sure yet if we should add some barrier transactions to enforce @@ -83,14 +86,13 @@ I'm not sure yet if we should add some barrier transactions to enforce Emitted on the readRsp channel (master <- slave) -success, abort, error, data shared/unique clean/dirty owner/notOwner +readSuccess, readError, data shared/unique clean/dirty owner/notOwner -| Responses | From command | Description | -|-----------|---------------|----------| -| success | makeInvalid, readBarrier | - | -| abort | makeInvalid | A concurrent makeInvalid toke over | -| error | readShared, readUnique, readOnce | Bad address | -| readData | readShared, readUnique, readOnce | Data + coherency flags (V???) | +| Responses | From command | Description | +|-------------|---------------|----------| +| readSuccess | makeUnique, readBarrier | - | +| readError | readShared, readUnique, readOnce | Bad address | +| readData | readShared, readUnique, readOnce | Data + coherency status (V???) | ### Read ack @@ -108,6 +110,7 @@ Write commands can be emitted on the writeCmd channel (master -> slave) |--------------|---------------|----------|----------| | writeInvalid | V-O- | Write the memory copy and update it status to I--- | Need to free the dirty cache line | | writeShare | V-O- | Write the memory copy but keep it as VSO- | A probe makeShared asked it | +| writeUnique | VUO- | Write the memory copy but keep it as VUO- | A probe probeOnce need to read the data | | evict | V---, !V-OD | Notify the interconnect that the cache line is now I--- | Need to free a clean cache line | | writeBarrier | N/A | Ensure that the visibility of the memory operations of this channel do not cross the barrier | ISA fence | @@ -127,8 +130,11 @@ Probe commands can be emitted on the probeCmd channel (slave -> master) |-------------|-------------|---------------| | makeInvalid | Make the memory copy I--- | Another cache want to make his shared copy unique to write it | | makeShared | Make the memory copy VS-- | Another cache want to read a memory block, so unique copy need to be shared | +| probeOnce | Read the V-O- memory copy | A non coherent agent did a readOnce | -Both makeInvalid and makeShared could result into one of the following probeSuccess, writeInvalid, writeShare. +makeInvalid and makeShared could result into one of the following probeSuccess, writeInvalid, writeShare + +probeOnce can result into one of the following probeSuccess, writeShare, writeUnique To help the slave matching the writeInvalid and writeShare generated from a probe, those request are tagged with a matching ID. From 2c6076ba972ea89082a2f87940034834dfdc16b2 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 7 Mar 2020 13:35:21 +0100 Subject: [PATCH 46/51] improve smp spec --- doc/smp/smp.md | 63 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/doc/smp/smp.md b/doc/smp/smp.md index cc06b16..200ebee 100644 --- a/doc/smp/smp.md +++ b/doc/smp/smp.md @@ -1,12 +1,35 @@ # Coherent interface specification Features : -- 3 buses (write, read, probe) composed of 7 streams +- 3 interface (write, read, probe) composed of 7 streams - Two data paths (read + write), but allow dirty/clean sharing by reusing the write data path - Allow multi level coherent interconnect - No ordering, but provide barrier - Allow cache-full and cache-less agents +## A few hint to help reading the spec + +In order to make the spec more readable, there is some definitions : + +### Stream + +A stream is a primitive interface which carry transactions using a valid/ready handshake. + +### Memory copy + +To talk in a non abstract way, in a system with multiple caches, a given memory address can potentialy be loaded in multiple caches at the same time. So let's define that : + +- The DDR memory is named `main memory` +- Each cache line can be loaded with a part of the main memory, let's name that a `memory copy` + +### Master / Interconnect / Slave + +A master could be for instance a CPU cache, the side of the interconnect toward the main memory or toward a more general interconnect. + +A slave could be main memory, the side of the interconnect toward a CPU cache or toward a less general interconnect. + +The spec will try to stay abstract and define the coherent interface as something which can be used between two agents (cpu, interconnect, main memory) + ## Memory copy status Memory copy, in other words, cache line, have more states than non coherent systems : @@ -27,14 +50,16 @@ Later in the spec, memory copy state can be described for example as : - !V-OC for NOT (Valid, Shared or Unique, Owner, Clean) - ... -## buses +## Coherent interface -One full interface is composed of 3 buses -- write (M -> S) -- read (M -> S) -- probe (M <- S) +One full coherent interface is composed of 3 inner interfaces, them-self composed of 7 stream described bellow as `interfaceName (Side -> StreamName -> Side -> StreamName -> ...)` +- write (M -> writeCmd -> S -> writeRsp -> M) +- read (M -> readCmd- > S -> readRsp -> M -> readAck -> S) +- probe (S -> probeCmd -> M -> probeRsp -> S) -### Read bus +### Read interface + +Used by masters to obtain new memory copies and make copies unique (used to write them). Composed of 3 stream : @@ -42,9 +67,11 @@ Composed of 3 stream : |---------|-----------|----------| | readCmd | M -> S | Emit memory read and cache management commands | | readRsp | M <- S | Return some data and/or a status from readCmd | -| readAck | M -> S | Return ACK from readRsp | +| readAck | M -> S | Return ACK from readRsp to syncronize the interconnect status | -### Write bus +### Write interface + +Used by masters to write data back to the memory and notify the interconnect of memory copies eviction (used to keep potential directories updated). Composed of 2 stream : @@ -53,7 +80,9 @@ Composed of 2 stream : | writeCmd | M -> S | Emit memory writes and cache management commands | | writeRsp | M <- S | Return a status from writeCmd | -### Probe bus +### Probe interface + +Used by the interconnect to order master to change their memory copies status and get memory copies owners data. | Name | Direction | Description | |----------|-----------|----------| @@ -62,7 +91,7 @@ Composed of 2 stream : ## Transactions -This chapter define transactions moving over the 3 previously defined buses. +This chapter define transactions moving over the 3 previously defined interface (read/write/probe). ### Read commands @@ -92,7 +121,7 @@ readSuccess, readError, data shared/unique clean/dirty owner/notOwner |-------------|---------------|----------| | readSuccess | makeUnique, readBarrier | - | | readError | readShared, readUnique, readOnce | Bad address | -| readData | readShared, readUnique, readOnce | Data + coherency status (V???) | +| readData | readShared, readUnique, readOnce | Data + coherency status (V---) | ### Read ack @@ -149,13 +178,15 @@ Emitted on the probeRsp channel (master -> slave), it carry no information, just ## Channel interlocking -There is the streams priority (top => high priority, bottom => low priority ) +This is a delicate subject as if everything was permited, it would be easy to end up with deadlocks. + +There is the streams priority (top => high priority, bottom => low priority) A lower priority stream should not block a higher priority stream in order to avoid deadlocks. - writeCmd, writeRsp, readRsp, readAck, probeRsp. Nothing should realy block them excepted bandwidth - probeCmd. Can be blocked by inflight/generated writes - readCmd. Can be blocked by inflight/generated probes In other words : -Masters can wait the completion of inflight writes before answering probes. -Slaves can emit probes and wait their completion before answering reads. -Slaves can wait on readAck incomming from generated readRsp before at all times +Masters can emit writeCmd and wait their writeRsp completion before answering probes commands. +Slaves can emit probeCmd and wait their proveRsp completion before answering reads. +Slaves can emit readRsp and wait on their readAck completion before doing anything else From 44005ebf31099a4f03670d4f8e8dc2aea3c42204 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sat, 7 Mar 2020 18:22:01 +0100 Subject: [PATCH 47/51] update Synthesis results --- README.md | 76 +++++++++---------- .../scala/vexriscv/demo/SynthesisBench.scala | 8 +- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index dd90af3..d192005 100644 --- a/README.md +++ b/README.md @@ -66,53 +66,53 @@ The CPU configurations used below can be found in the `src/scala/vexriscv/demo` ``` VexRiscv small (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) -> - Artix 7 -> 253 Mhz 498 LUT 505 FF - Cyclone V -> 205 Mhz 350 ALMs - Cyclone IV -> 172 Mhz 731 LUT 494 FF + Artix 7 -> 243 Mhz 504 LUT 505 FF + Cyclone V -> 174 Mhz 352 ALMs + Cyclone IV -> 179 Mhz 731 LUT 494 FF iCE40 -> 92 Mhz 1130 LC VexRiscv small (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) -> - Artix 7 -> 225 Mhz 549 LUT 563 FF - Cyclone V -> 194 Mhz 392 ALMs - Cyclone IV -> 172 Mhz 830 LUT 551 FF + Artix 7 -> 240 Mhz 556 LUT 566 FF + Cyclone V -> 194 Mhz 394 ALMs + Cyclone IV -> 174 Mhz 831 LUT 555 FF iCE40 -> 85 Mhz 1292 LC VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) -> - Artix 7 -> 213 Mhz 787 LUT 531 FF - Cyclone V -> 150 Mhz 487 ALMs - Cyclone IV -> 151 Mhz 1,115 LUT 526 FF + Artix 7 -> 232 Mhz 816 LUT 534 FF + Cyclone V -> 155 Mhz 492 ALMs + Cyclone IV -> 155 Mhz 1,111 LUT 530 FF iCE40 -> 63 Mhz 1596 LC VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) -> - Artix 7 -> 220 Mhz 719 LUT 570 FF - Cyclone V -> 147 Mhz 516 ALMs - Cyclone IV -> 144 Mhz 1,139 LUT 532 FF + Artix 7 -> 220 Mhz 730 LUT 570 FF + Cyclone V -> 142 Mhz 501 ALMs + Cyclone IV -> 150 Mhz 1,139 LUT 536 FF iCE40 -> 66 Mhz 1680 LC VexRiscv full no cache (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 210 Mhz 1410 LUT 975 FF - Cyclone V -> 144 Mhz 927 ALMs - Cyclone IV -> 141 Mhz 2,074 LUT 966 FF + Artix 7 -> 216 Mhz 1418 LUT 949 FF + Cyclone V -> 133 Mhz 933 ALMs + Cyclone IV -> 143 Mhz 2,076 LUT 972 FF VexRiscv full (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 199 Mhz 1736 LUT 1120 FF - Cyclone V -> 137 Mhz 1,177 ALMs - Cyclone IV -> 142 Mhz 2,409 LUT 1,061 FF + Artix 7 -> 199 Mhz 1840 LUT 1158 FF + Cyclone V -> 141 Mhz 1,166 ALMs + Cyclone IV -> 131 Mhz 2,407 LUT 1,067 FF VexRiscv full max perf (HZ*IPC) -> (RV32IM, 1.38 DMIPS/Mhz 2.57 Coremark/Mhz, 8KB-I$,8KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) -> - Artix 7 -> 197 Mhz 1788 LUT 1210 FF - Cyclone V -> 130 Mhz 1,173 ALMs - Cyclone IV -> 124 Mhz 2,483 LUT 1,114 FF + Artix 7 -> 200 Mhz 1935 LUT 1216 FF + Cyclone V -> 130 Mhz 1,166 ALMs + Cyclone IV -> 126 Mhz 2,484 LUT 1,120 FF VexRiscv full with MMU (RV32IM, 1.24 DMIPS/Mhz 2.35 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) -> - Artix 7 -> 164 Mhz 2000 LUT 1501 FF - Cyclone V -> 125 Mhz 1,375 ALMs - Cyclone IV -> 121 Mhz 2,821 LUT 1,444 FF + Artix 7 -> 151 Mhz 2021 LUT 1541 FF + Cyclone V -> 124 Mhz 1,368 ALMs + Cyclone IV -> 128 Mhz 2,826 LUT 1,474 FF VexRiscv linux balanced (RV32IMA, 1.21 DMIPS/Mhz 2.27 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, catch exceptions, static branch, MMU, Supervisor, Compatible with mainstream linux) -> - Artix 7 -> 176 Mhz 2678 LUT 2087 FF - Cyclone V -> 137 Mhz 1,797 ALMs - Cyclone IV -> 120 Mhz 3,544 LUT 2,059 FF + Artix 7 -> 180 Mhz 2883 LUT 2130 FF + Cyclone V -> 131 Mhz 1,764 ALMs + Cyclone IV -> 121 Mhz 3,608 LUT 2,082 FF ``` The following configuration results in 1.44 DMIPS/MHz: @@ -318,9 +318,9 @@ You can find some FPGA projects which instantiate the Briey SoC here (DE1-SoC, D Here are some measurements of Briey SoC timings and area : ``` - Artix 7 -> 186 Mhz 3138 LUT 3328 FF - Cyclone V -> 139 Mhz 2,175 ALMs - Cyclone IV -> 129 Mhz 4,337 LUT 3,170 FF +Artix 7 -> 181 Mhz 3220 LUT 3181 FF +Cyclone V -> 142 Mhz 2,222 ALMs +Cyclone IV -> 130 Mhz 4,538 LUT 3,211 FF ``` ## Murax SoC @@ -373,16 +373,16 @@ Here are some timing and area measurements of the Murax SoC: ``` Murax interlocked stages (0.45 DMIPS/Mhz, 8 bits GPIO) -> - Artix 7 -> 215 Mhz 1044 LUT 1202 FF - Cyclone V -> 173 Mhz 737 ALMs - Cyclone IV -> 144 Mhz 1,484 LUT 1,206 FF - iCE40 -> 64 Mhz 2422 LC (nextpnr) + Artix 7 -> 216 Mhz 1109 LUT 1201 FF + Cyclone V -> 182 Mhz 725 ALMs + Cyclone IV -> 147 Mhz 1,551 LUT 1,223 FF + iCE40 -> 64 Mhz 2422 LC (nextpnr) MuraxFast bypassed stages (0.65 DMIPS/Mhz, 8 bits GPIO) -> - Artix 7 -> 229 Mhz 1269 LUT 1302 FF - Cyclone V -> 159 Mhz 864 ALMs - Cyclone IV -> 137 Mhz 1,688 LUT 1,241 FF - iCE40 -> 66 Mhz 2799 LC (nextpnr) + Artix 7 -> 224 Mhz 1278 LUT 1300 FF + Cyclone V -> 173 Mhz 867 ALMs + Cyclone IV -> 143 Mhz 1,755 LUT 1,258 FF + iCE40 -> 66 Mhz 2799 LC (nextpnr) ``` Some scripts to generate the SoC and call the icestorm toolchain can be found here: `scripts/Murax/` diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index ca925bf..a9961a9 100644 --- a/src/main/scala/vexriscv/demo/SynthesisBench.scala +++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala @@ -117,7 +117,7 @@ object VexRiscvSynthesisBench { val targets = XilinxStdTargets() ++ AlteraStdTargets() ++ IcestormStdTargets().take(1) // val targets = IcestormStdTargets() - Bench(rtls, targets, "/media/miaou/HD/linux/tmp/") + Bench(rtls, targets) } } @@ -137,9 +137,9 @@ object BrieySynthesisBench { val rtls = List(briey) - val targets = XilinxStdTargets() ++ AlteraStdTargets() ++ IcestormStdTargets().take(1) + val targets = XilinxStdTargets() ++ AlteraStdTargets() ++ IcestormStdTargets().take(1) - Bench(rtls, targets, "/media/miaou/HD/linux/tmp") + Bench(rtls, targets) } } @@ -173,7 +173,7 @@ object MuraxSynthesisBench { val targets = XilinxStdTargets() ++ AlteraStdTargets() ++ IcestormStdTargets().take(1) - Bench(rtls, targets, "/media/miaou/HD/linux/tmp") + Bench(rtls, targets) } } From 7a5afb86a57f6848437c6cd8bd23d48be13896eb Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sat, 7 Mar 2020 19:09:33 +0100 Subject: [PATCH 48/51] Fix build.sbt --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ac8feba..cd635f8 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ lazy val root = (project in file(".")). scalaVersion := "2.11.12", version := "2.0.0" )), - scalacOptions += s"-Xplugin:${new File(baseDirectory.value + "/../SpinalHDL/idslplugin/target/scala-2.11/spinalhdl-idsl-plugin_2.11-1.3.9.jar")}", + scalacOptions += s"-Xplugin:${new File(baseDirectory.value + "/../SpinalHDL/idslplugin/target/scala-2.11").listFiles().filter(_.getName.endsWith(".jar")).head}", scalacOptions += s"-Xplugin-require:idsl-plugin", libraryDependencies ++= Seq( // "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.6", From 04bf1a4cedb6f72f049f1aaab3f052c0a2f1804e Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sun, 8 Mar 2020 00:23:19 +0100 Subject: [PATCH 49/51] Fix build.sbt --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index cd635f8..11c11f9 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ lazy val root = (project in file(".")). scalaVersion := "2.11.12", version := "2.0.0" )), - scalacOptions += s"-Xplugin:${new File(baseDirectory.value + "/../SpinalHDL/idslplugin/target/scala-2.11").listFiles().filter(_.getName.endsWith(".jar")).head}", + scalacOptions += s"-Xplugin:${new File(baseDirectory.value + "/../SpinalHDL/idslplugin/target/scala-2.11/spinalhdl-idsl-plugin_2.11-1.4.0.jar")}", scalacOptions += s"-Xplugin-require:idsl-plugin", libraryDependencies ++= Seq( // "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.6", From defe3c55589b7450ede2c4dae3b61bce3c62c848 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sun, 8 Mar 2020 12:35:24 +0100 Subject: [PATCH 50/51] DataCache relax flush timings --- src/main/scala/vexriscv/ip/DataCache.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index 8e62bc7..7cbe4ba 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -490,8 +490,7 @@ class DataCache(p : DataCacheConfig) extends Component{ //Evict the cache after reset logics val flusher = new Area { - val valid = RegInit(True) - mmuRsp.physicalAddress init (0) + val valid = RegInit(False) when(valid) { tagsWriteCmd.valid := valid tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) @@ -506,7 +505,10 @@ class DataCache(p : DataCacheConfig) extends Component{ } io.cpu.flush.ready := False - when(io.cpu.flush.valid && !io.cpu.execute.isValid && !io.cpu.memory.isValid && !io.cpu.writeBack.isValid && !io.cpu.redo){ + val start = RegInit(True) //Used to relax timings + start := !start && io.cpu.flush.valid && !io.cpu.execute.isValid && !io.cpu.memory.isValid && !io.cpu.writeBack.isValid && !io.cpu.redo + + when(start){ io.cpu.flush.ready := True mmuRsp.physicalAddress.getDrivingReg(lineRange) := 0 valid := True From 5f90702b2ffaddff5fa22b8b04a19be7b745faee Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Mon, 9 Mar 2020 13:14:16 +0100 Subject: [PATCH 51/51] SpinalHDL update --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 11c11f9..c1510b2 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ lazy val root = (project in file(".")). scalaVersion := "2.11.12", version := "2.0.0" )), - scalacOptions += s"-Xplugin:${new File(baseDirectory.value + "/../SpinalHDL/idslplugin/target/scala-2.11/spinalhdl-idsl-plugin_2.11-1.4.0.jar")}", + scalacOptions += s"-Xplugin:${new File(baseDirectory.value + "/../SpinalHDL/idslplugin/target/scala-2.11/spinalhdl-idsl-plugin_2.11-1.4.1.jar")}", scalacOptions += s"-Xplugin-require:idsl-plugin", libraryDependencies ++= Seq( // "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.6",