diff --git a/README.md b/README.md index 830bd59..22bfba8 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 -> 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 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 -> 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 -> 226 Mhz 689 LUT 531 FF - Cyclone V -> 145 Mhz 499 ALMs - Cyclone IV -> 150 Mhz 1,111 LUT 525 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 -> 230 Mhz 734 LUT 564 FF - Cyclone V -> 145 Mhz 511 ALMs - Cyclone IV -> 144 Mhz 1,145 LUT 531 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 -> 219 Mhz 1537 LUT 977 FF - Cyclone V -> 139 Mhz 958 ALMs - Cyclone IV -> 135 Mhz 2,011 LUT 968 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 -> 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 -> 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 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 -> 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 -> 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 -> 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 -> 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 -> 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: @@ -186,24 +185,47 @@ NOTES: [![Build Status](https://travis-ci.org/SpinalHDL/VexRiscv.svg?branch=master)](https://travis-ci.org/SpinalHDL/VexRiscv) -To run tests (Verilator simulator is required), go in the `src/test/cpp/regression` folder and run: +To run tests (need java, scala, verilator), just do : ```sh -# To test the GenFull CPU -# (Don't worry about the CSR test not passing, basically the GenFull isn't the truly full version of the CPU, some CSR features are disabled 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 tests 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 To use this, you just need to use the same command as with running tests, but adding `DEBUG_PLUGIN_EXTERNAL=yes` in the make arguments. @@ -296,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 @@ -351,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/build.sbt b/build.sbt index a938f34..e97471a 100644 --- a/build.sbt +++ b/build.sbt @@ -1,3 +1,4 @@ +val spinalVersion = "1.4.0" lazy val root = (project in file(".")). settings( @@ -7,16 +8,13 @@ lazy val root = (project in file(".")). version := "2.0.0" )), libraryDependencies ++= Seq( - "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.8", - "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.8", - "org.scalatest" % "scalatest_2.11" % "2.2.1", - "org.yaml" % "snakeyaml" % "1.8" + "com.github.spinalhdl" % "spinalhdl-core_2.11" % spinalVersion, + "com.github.spinalhdl" % "spinalhdl-lib_2.11" % spinalVersion, + compilerPlugin("com.github.spinalhdl" % "spinalhdl-idsl-plugin_2.11" % spinalVersion), + "org.scalatest" % "scalatest_2.11" % "2.2.1", + "org.yaml" % "snakeyaml" % "1.8" ), name := "VexRiscv" - )//.dependsOn(spinalHdlSim,spinalHdlCore,spinalHdlLib) -//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 diff --git a/doc/smp/smp.md b/doc/smp/smp.md new file mode 100644 index 0000000..5e22e4d --- /dev/null +++ b/doc/smp/smp.md @@ -0,0 +1,194 @@ +# Coherent interface specification + +Features : +- 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 : + +| 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 | 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 status have no meaning. + +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) +- ... + +## Coherent interface + +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 interface + +Used by masters to obtain new memory copies and make copies unique (used to write them). + +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 to syncronize the interconnect status | + +### 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 : + +| Name | Direction | Description | +|---------|-----------|----------| +| writeCmd | M -> S | Emit memory writes and cache management commands | +| writeRsp | M <- S | Return a status from writeCmd | + +### Probe interface + +Used by the interconnect to order master to change their memory copies status and get memory copies owners data. + +Composed of 2 stream : + +| 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 interface (read/write/probe). + +### 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 | +| 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 | + +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 + +### Read responses + +Emitted on the readRsp channel (master <- slave) + +readSuccess, readError, data shared/unique clean/dirty owner/notOwner + +| Responses | From command | Description | +|-------------|---------------|----------| +| readSuccess | makeUnique, readBarrier | - | +| readError | readShared, readUnique, readOnce | Bad address | +| readData | readShared, readUnique, readOnce | Data + coherency status (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 | +| 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 | + +### 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 | +| probeOnce | Read the V-O- memory copy | A non coherent agent did a readOnce | + +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. + +### 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 + +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 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 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/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/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/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/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index 08a7d72..a9961a9 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 @@ -96,7 +97,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)) } @@ -113,15 +114,10 @@ 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") + Bench(rtls, targets) } } @@ -132,7 +128,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 }) @@ -141,14 +137,9 @@ 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") + Bench(rtls, targets) } } @@ -161,7 +152,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 +163,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 }) @@ -180,14 +171,9 @@ 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") + Bench(rtls, targets) } } diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index 838489d..7cbe4ba 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 @@ -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( @@ -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 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/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..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)) @@ -447,9 +448,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 +642,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 + } } } } @@ -685,7 +687,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 @@ -762,7 +764,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 + } @@ -775,8 +777,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)) { @@ -808,17 +810,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) @@ -844,7 +858,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 +931,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" } @@ -984,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 @@ -1030,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) } } } @@ -1081,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)) - }) + } } } } 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/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 1b0084b..93e65e3 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 @@ -214,10 +213,11 @@ 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 + decode.arbitration.flushNext := True } } 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..1de5021 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -16,12 +16,14 @@ 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, val injectorStage : Boolean, - val relaxPredictorAddress : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{ + val relaxPredictorAddress : Boolean, + 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 @@ -31,7 +33,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 @@ -42,12 +43,10 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, injectionPort = Stream(Bits(32 bits)) injectionPort } - + 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 - 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] = { @@ -61,7 +60,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")) @@ -75,21 +73,33 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } 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 + s == IBUS_RSP || s == DECOMPRESSOR + } + + class FetchArea(pipeline : VexRiscv) extends Area { import pipeline._ import pipeline.config._ + val externalFlush = stages.map(_.arbitration.flushNext).orR - //JumpService hardware implementation + def getFlushAt(s : Any, lastCond : Boolean = true): Bool = { + if(isDrivingDecode(s) && lastCond) pipeline.decode.arbitration.isRemoved else externalFlush + } + + //Arbitrate jump requests into pcLoad val jump = new Area { val sortedByStage = jumpInfos.sortWith((a, b) => { (pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage)) || @@ -103,7 +113,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 @@ -112,12 +122,16 @@ 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)) + val flushed = False if(compressedGen) when(inc) { pc(1) := False @@ -125,22 +139,27 @@ 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){ + 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 || fetcherflushIt || pcRegPropagate)){ + when(booted && (output.ready || correction || pcRegPropagate)){ pcReg := pc } pc(0) := False - if(!pipeline(RVC_GEN)) pc(1) := False + if(!compressedGen) pc(1) := False output.valid := !fetcherHalt && booted output.payload := pc @@ -148,6 +167,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)) @@ -170,6 +190,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 } }) @@ -177,116 +198,109 @@ 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 redoFetch = 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() }) stages(0).input << fetchPc.output - stages(0).inputSample := True for(s <- stages) { s.halt := False s.output << s.input.haltWhen(s.halt) } + if(fetchPc.redo != null) { + fetchPc.redo.valid := redoFetch + fetchPc.redo.payload := stages.last.input.payload + } + + 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 sFlushed = if(s != stages.head) flush else False + val sNextFlushed = flush 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(sNextFlushed, false, collapsBubble = false, flushInput = sFlushed)) 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(sNextFlushed, false, collapsBubble = false, flushInput = sFlushed) } } -// -// 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(_ || _)) } val decompressor = ifGen(decodePcGen)(new Area{ - def input = iBusRsp.output + 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)) + val isInputLowRvc = input.rsp.inst(1 downto 0) =/= 3 + val isInputHighRvc = input.rsp.inst(17 downto 16) =/= 3 + 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 decompressed = RvcDecompressor(raw(15 downto 0)) - output.valid := (isRvc ? (bufferValid || input.valid) | (input.valid && (bufferValid || !input.pc(1)))) + output.valid := input.valid && !(throw2Bytes && !bufferValid && !isInputHighRvc) 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))*/) { - input.pc.getDrivingReg(1) := True - } - }) + input.ready := output.ready && (!iBusRsp.stages.last.input.valid || flushNext || (!(bufferValid && isInputHighRvc) && !(aligned && isInputLowRvc && isInputHighRvc))) - 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.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) + bufferValid setWhen(bufferFill) + } + + when(flush || consumeCurrent){ + throw2BytesReg := False + bufferValid := False + } + + if(fetchPc.redo != null) { + fetchPc.redo.payload(1) setWhen(throw2BytesReg) } - bufferValid.clearWhen(fetcherflushIt) - iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending - incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3) }) 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 decodeInput = inputBeforeStage.m2sPipeWithFlush(fetcherflushIt, collapsBubble = false) + val flushStage = getFlushAt(INJECTOR_M2S) + 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) @@ -298,16 +312,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 @@ -316,20 +330,17 @@ 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)) } - 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) { @@ -415,18 +426,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 { @@ -449,10 +457,10 @@ 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)._2 + decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._3 val decodeContextPrediction = decode.input(PREDICTION_CONTEXT).line.history.msb val branchStage = decodePrediction.stage @@ -488,13 +496,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") @@ -502,26 +508,40 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, case class BranchPredictorLine() extends Bundle{ val source = Bits(30 - historyRamSizeLog2 bits) val branchWish = UInt(2 bits) + val last2Bytes = ifGen(compressedGen)(Bool) val target = UInt(32 bits) - val unaligned = ifGen(compressedGen)(Bool) } 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 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) - } + 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 - //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)) + 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)) + + fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).input.valid fetchPc.predictionPcLoad.payload := line.target case class PredictionResult() extends Bundle{ @@ -535,22 +555,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.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 - } - } + val (iBusRspContext, iBusRspContextOutput, injectorContext) = stage1ToInjectorPipe(fetchContext) object PREDICTION_CONTEXT extends Stageable(PredictionResult()) pipeline.decode.insert(PREDICTION_CONTEXT) := injectorContext @@ -565,7 +570,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 @@ -582,27 +587,31 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring) + val compressor = compressedGen generate new Area{ + val predictionBranch = iBusRspContext.hit && !iBusRspContext.hazard && iBusRspContext.line.branchWish(1) + val unalignedWordIssue = iBusRsp.output.valid && predictionBranch && iBusRspContext.line.last2Bytes && Mux(decompressor.unaligned, !decompressor.isInputHighRvc, decompressor.isInputLowRvc && !decompressor.isInputHighRvc) - - 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){ + 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 - decode.arbitration.isValid := False - decode.arbitration.flushNext := True - dynamicTargetFailureCorrection.valid := True + iBusRsp.redoFetch := True } - }) + + //Do not trigger prediction hit when it is one for the upper RVC word and we aren't there yet + 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(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 a7b2194..642fcbb 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -35,18 +35,21 @@ 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, compressedGen = compressedGen, cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1) + (if(relaxedPcCalculation) 1 else 0), - pcRegReusedForSecondStage = true, + allowPcRegReusedForSecondStage = true, injectorReadyCutGen = false, prediction = prediction, historyRamSizeLog2 = historyRamSizeLog2, injectorStage = (!config.twoCycleCache && !withoutInjectorStage) || injectorStage, - relaxPredictorAddress = relaxPredictorAddress){ + relaxPredictorAddress = relaxPredictorAddress, + fetchRedoGen = true, + predictionBuffer = predictionBuffer){ import config._ assert(isPow2(cacheSize)) @@ -58,7 +61,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 @@ -86,9 +88,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) @@ -157,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 } @@ -211,7 +210,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) { @@ -237,19 +236,9 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, decodeExceptionPort.code := 1 } - when(!iBusRsp.readyForError){ - redoFetch := False - cache.io.cpu.fill.valid := False + when(redoFetch) { + iBusRsp.redoFetch := True } -// 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) 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..b8bc978 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -233,27 +233,31 @@ 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, decodePcGen = compressedGen, compressedGen = compressedGen, cmdToRspStageCount = busLatencyMin + (if(cmdForkOnSecondStage) 1 else 0), - pcRegReusedForSecondStage = !(cmdForkOnSecondStage && cmdForkPersistence), + allowPcRegReusedForSecondStage = !(cmdForkOnSecondStage && cmdForkPersistence), injectorReadyCutGen = false, prediction = prediction, historyRamSizeLog2 = historyRamSizeLog2, injectorStage = injectorStage, - relaxPredictorAddress = relaxPredictorAddress){ + relaxPredictorAddress = relaxPredictorAddress, + fetchRedoGen = memoryTranslatorPortConfig != null, + predictionBuffer = predictionBuffer){ 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) +// if(rspHoldValue) assert(busLatencyMin <= 1) + assert(!rspHoldValue, "rspHoldValue not supported yet") + assert(!singleInstructionPipeline) override def setup(pipeline: VexRiscv): Unit = { super.setup(pipeline) @@ -268,7 +272,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 } } @@ -282,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) @@ -292,104 +298,98 @@ 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) @@ "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){ - 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) } 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 { 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(fetcherflushIt) { - 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 := fetcherflushIt - 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 - val redoRequired = 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 - output << join.haltWhen(exceptionDetected || redoRequired) + rspBuffer.output.ready := join.fire + output << join.haltWhen(exceptionDetected) 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) + when(stages.last.input.valid && mmu.joinCtx.refilling) { + iBusRsp.redoFetch := True + } } 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..60c1682 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" ) @@ -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 } diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index 6820f8e..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) @@ -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 diff --git a/src/main/scala/vexriscv/plugin/MulPlugin.scala b/src/main/scala/vexriscv/plugin/MulPlugin.scala index 96db3e9..31714e8 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)) + KeepAttribute(input(RS2)) + } } //First aggregation of partial multiplication 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; \ 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/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") { diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 005f335..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.FunSuite +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 @@ -313,7 +316,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 +325,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 +348,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 +500,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{ @@ -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,32 +557,100 @@ class DecoderDimension extends VexRiscvDimension("Decoder") { } } - - - - -class TestIndividualFeatures extends FunSuite { - 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() +object PlayFuture extends App{ + implicit val ec = ExecutionContext.global + val x = for(i <- 0 until 160) yield Future { + print(s"$i ") + Thread.sleep(1000) } + 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 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 { + 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 + val lock = new{} + + val dimensions = List( - new IBusDimension, + new IBusDimension(rvcRate), new DBusDimension, new MulDivDimension, new ShiftDimension, @@ -586,18 +658,46 @@ 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 ) + 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, @@ -609,61 +709,52 @@ 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 + name + "_gen") { - 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 + name + "_test") { - 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=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 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) } } - 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 +767,13 @@ 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 } + 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