diff --git a/.gitignore b/.gitignore
index 3c575c5..eaab2e7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,3 +46,4 @@ obj_dir
simWorkspace/
tmp/
/archive.tar.gz
+*.out32
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 7214425..87447ea 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -45,6 +45,8 @@ before_install:
- sudo make install
- cd ..
+ - git clone https://github.com/SpinalHDL/SpinalHDL.git
+
- cd VexRiscv
#- curl -T README.md -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/README.md
#- curl -X POST -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/publish
diff --git a/README.md b/README.md
index e9dae43..b67b0e3 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ This repository hosts a RISC-V implementation written in SpinalHDL. Here are som
- RV32I[M][C] instruction set
- Pipelined with 5 stages (Fetch, Decode, Execute, Memory, WriteBack)
-- 1.44 DMIPS/Mhz when all features are enabled
+- 1.44 DMIPS/Mhz --no-inline when nearly all features are enabled (1.57 DMIPS/Mhz when the divider lookup table is enabled)
- Optimized for FPGA, fully portable
- AXI4 and Avalon ready
- Optional MUL/DIV extensions
@@ -38,6 +38,7 @@ This repository hosts a RISC-V implementation written in SpinalHDL. Here are som
- Optional interrupts and exception handling with Machine and User modes as defined in the [RISC-V Privileged ISA Specification v1.9](https://riscv.org/specifications/privileged-isa/).
- Two implementations of shift instructions: Single cycle and shiftNumber cycles
- Each stage can have optional bypass or interlock hazard logic
+- Zephyr RISC-V port compatible
- [FreeRTOS port](https://github.com/Dolu1990/FreeRTOS-RISCV)
- The data cache supports atomic LR/SC
- Optional RV32 compressed instruction support in the reworkFetch branch for configurations without instruction cache (will be merge in master, WIP)
@@ -119,6 +120,8 @@ The following configuration results in 1.44 DMIPS/MHz:
- single cycle multiplication with bypassing in the WB stage (late result)
- dynamic branch prediction done in the F stage with a direct mapped target buffer cache (no penalties on correct predictions)
+Note that recently, the capability to remove the Fetch/Memory/WriteBack stage was added to reduce the area of the CPU, which end up with a smaller CPU and a better DMIPS/Mhz for the small configurations.
+
## Dependencies
On Ubuntu 14 :
@@ -422,7 +425,8 @@ val cpu = new VexRiscv(
plugins = List(
new IBusSimplePlugin(
resetVector = 0x00000000l,
- relaxedPcCalculation = true
+ cmdForkOnSecondStage = true,
+ cmdForkPersistence = true
),
new DBusSimplePlugin(
catchAddressMisaligned = false,
@@ -643,19 +647,6 @@ This chapter describes plugins currently implemented.
- [DebugPlugin](#debugplugin)
- [YamlPlugin](#yamlplugin)
-#### PcManagerSimplePlugin
-
-This plugin implements the program counter and a jump service to all plugins.
-
-
-| Parameters | type | description |
-| ------ | ----------- | ------ |
-| resetVector | BigInt | Address of the program counter after the reset |
-| relaxedPcCalculation | Boolean | By default jump have an asynchronous immediate effect on the program counter, which allow to reduce the branch penalties by one cycle but could reduce the FMax as it will combinatorialy drive the instruction bus address signal. To avoid this you can set this parameter to true, which will make the jump affecting the programm counter in a sequancial way, which will cut the combinatorial path but add one additional cycle of penalty when a jump occur. |
-
-
-
-This plugin operates on the prefetch stage.
#### IBusSimplePlugin
@@ -665,8 +656,8 @@ This plugin implement the CPU frontend (instruction fetch) via a very simple and
| ------ | ----------- | ------ |
| catchAccessFault | Boolean | If an the read response specify an read error and this parameter is true, it will generate an CPU exception trap |
| resetVector | BigInt | Address of the program counter after the reset |
-| relaxedPcCalculation | Boolean | By default jump have an asynchronous immediate effect on the program counter, which allow to reduce the branch penalties by one cycle but could reduce the FMax as it will combinatorialy drive the instruction bus address signal. To avoid this you can set this parameter to true, which will make the jump affecting the programm counter in a sequancial way, which will cut the combinatorial path but add one additional cycle of penalty when a jump occur. |
-| relaxedBusCmdValid | Boolean | Same than relaxedPcCalculation, but for the iBus.cmd.valid pin. |
+| cmdForkOnSecondStage | Boolean | By default jump have an asynchronous immediate effect on the program counter, which allow to reduce the branch penalties by one cycle but could reduce the FMax as it will combinatorialy drive the instruction bus address signal. To avoid this you can set this parameter to true, which will make the jump affecting the programm counter in a sequancial way, which will cut the combinatorial path but add one additional cycle of penalty when a jump occur. |
+| cmdForkPersistence | Boolean | If this parameter is false, then request on the iBus can disappear/change before their completion. Which reduce area but isn't safe/supported by many arbitration/slaves. If you set this parameter to true, then the iBus cmd will stay until they are completed.
| compressedGen | Boolean | Enable RVC support |
| busLatencyMin | Int | Specify the minimal latency between the iBus.cmd and iBus.rsp, which will add the corresponding number of stages into the frontend to keep the IPC to 1.|
| injectorStage | Boolean | Add a stage between the frontend and the decode stage of the CPU to improve FMax. (busLatencyMin + injectorStage) should be at least two. |
@@ -700,8 +691,9 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
}
```
-**Important** : There should be at least one cycle latency between que cmd and the rsp. The IBus.cmd can remove request when a CPU jump occure or when the CPU is halted by someting in the pipeline. As many arbitration aren't made for this behaviour, it is important to add a buffer to the iBus.cmd to avoid this. Ex : iBus.cmd.s2mPipe, which add a zero latency buffer and cut the iBus.cmd.ready path.
-You can also do iBus.cmd.s2mPipe.m2sPipe, which will cut all combinatorial path of the bus but then as a latency of 1 cycle. which mean you should probably set the busLatencyMin to 2.
+**Important** : Checkout the cmdForkPersistence parameter, because if it's not set, it can break the iBus compatibility with your memory system (unless you externaly add some buffers)
+
+Setting cmdForkPersistence and cmdForkOnSecondStage improves iBus cmd timings.
Note that bridges are implemented to convert this interface into AXI4 and Avalon
diff --git a/build.sbt b/build.sbt
index 499e838..d84c0a6 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,22 +1,46 @@
-name := "VexRiscv"
-
-organization := "com.github.spinalhdl"
-
-version := "1.0.0"
-
-scalaVersion := "2.11.6"
-
-EclipseKeys.withSource := true
-
-libraryDependencies ++= Seq(
- "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.2.0",
- "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.0",
- "org.scalatest" % "scalatest_2.11" % "2.2.1",
- "org.yaml" % "snakeyaml" % "1.8"
-)
+//name := "VexRiscv"
+//
+//organization := "com.github.spinalhdl"
+//
+//version := "1.0.0"
+//
+//scalaVersion := "2.11.6"
+//
+//EclipseKeys.withSource := true
+//
+//libraryDependencies ++= Seq(
+// "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.2.1",
+// "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.1",
+// "org.scalatest" % "scalatest_2.11" % "2.2.1",
+// "org.yaml" % "snakeyaml" % "1.8"
+//)
+//
+//
+//
+//addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")
+//scalacOptions += "-P:continuations:enable"
+//fork := true
+lazy val root = (project in file(".")).
+ settings(
+ inThisBuild(List(
+ organization := "com.github.spinalhdl",
+ scalaVersion := "2.11.6",
+ version := "1.0.0"
+ )),
+ libraryDependencies ++= Seq(
+ "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.2.2",
+ "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.2",
+ "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"), "SpinalHDL-sim")
+lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "SpinalHDL-core")
+lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "SpinalHDL-lib")*/
addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")
scalacOptions += "-P:continuations:enable"
-fork := true
+fork := true
\ No newline at end of file
diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile
new file mode 100644
index 0000000..ca74503
--- /dev/null
+++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile
@@ -0,0 +1,38 @@
+
+
+VERILOG = ../../../Murax_iCE40_hx8k_breakout_board_xip.v
+
+generate :
+ #(cd ../../..; sbt "run-main vexriscv.demo.Murax_iCE40_hx8k_breakout_board_xip")
+
+../../../Murax_iCE40_hx8k_breakout_board_xip.v :
+ #(cd ../../..; sbt "run-main vexriscv.demo.Murax_iCE40_hx8k_breakout_board_xip")
+
+../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin:
+
+bin/Murax_iCE40_hx8k_breakout_board_xip.blif : ${VERILOG} ../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin
+ mkdir -p bin
+ rm -f Murax_iCE40_hx8k_breakout_board_xip.v*.bin
+ cp ../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin . | true
+ yosys -v3 -p "synth_ice40 -top Murax_iCE40_hx8k_breakout_board_xip -blif bin/Murax_iCE40_hx8k_breakout_board_xip.blif" ${VERILOG}
+
+bin/Murax_iCE40_hx8k_breakout_board_xip.asc : Murax_iCE40_hx8k_breakout_board_xip.pcf bin/Murax_iCE40_hx8k_breakout_board_xip.blif
+ arachne-pnr -p Murax_iCE40_hx8k_breakout_board_xip.pcf -d 8k --max-passes 600 -P ct256 bin/Murax_iCE40_hx8k_breakout_board_xip.blif -o bin/Murax_iCE40_hx8k_breakout_board_xip.asc
+
+bin/Murax_iCE40_hx8k_breakout_board_xip.bin : bin/Murax_iCE40_hx8k_breakout_board_xip.asc
+ icepack bin/Murax_iCE40_hx8k_breakout_board_xip.asc bin/Murax_iCE40_hx8k_breakout_board_xip.bin
+
+compile : bin/Murax_iCE40_hx8k_breakout_board_xip.bin
+
+time: bin/Murax_iCE40_hx8k_breakout_board_xip.bin
+ icetime -tmd hx8k bin/Murax_iCE40_hx8k_breakout_board_xip.asc
+
+prog : bin/Murax_iCE40_hx8k_breakout_board_xip.bin
+ iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin
+
+sudo-prog : bin/Murax_iCE40_hx8k_breakout_board_xip.bin
+ sudo iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin
+
+clean :
+ rm -rf bin
+ rm -f Murax_iCE40_hx8k_breakout_board_xip.v*.bin
diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/Murax_iCE40_hx8k_breakout_board_xip.pcf b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Murax_iCE40_hx8k_breakout_board_xip.pcf
new file mode 100644
index 0000000..4962e25
--- /dev/null
+++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Murax_iCE40_hx8k_breakout_board_xip.pcf
@@ -0,0 +1,23 @@
+## iCE40-hx8k breakout board
+
+set_io io_J3 J3
+set_io io_H16 H16
+set_io io_G15 G15
+set_io io_G16 G16
+set_io io_F15 F15
+set_io io_B12 B12
+set_io io_B10 B10
+set_io io_led[0] B5
+set_io io_led[1] B4
+set_io io_led[2] A2
+set_io io_led[3] A1
+set_io io_led[4] C5
+set_io io_led[5] C4
+set_io io_led[6] B3
+set_io io_led[7] C3
+
+#XIP
+set_io io_P12 P12
+set_io io_P11 P11
+set_io io_R11 R11
+set_io io_R12 R12
\ No newline at end of file
diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md
new file mode 100644
index 0000000..62078a3
--- /dev/null
+++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md
@@ -0,0 +1,84 @@
+This example is for the
+[Lattice iCE40HX-8K Breakout Board](http://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx).
+
+An image of this board is shown below;
+![img/iCE40HX8K-breakout-revA.png]
+
+This board can be purchased for ~$USD 49 directly from Lattice and is supported
+by the IceStorm
+[`iceprog`](https://github.com/cliffordwolf/icestorm/tree/master/iceprog) tool.
+
+
+# Using the example
+
+## Before Starting
+
+Before starting make sure that your board is configured for `CRAM Programming`
+mode. This requires removing jumper `J7` and putting the pair of jumpers on
+`J6` to be parallel to the text on the board.
+
+This is shown in **Figure 5** of the
+[iCE40HX-8K Breakout Board User Guide](http://www.latticesemi.com/view_document?document_id=50373).
+which is also reproduced below;
+![img/cram-programming-config.png]
+
+Once your board is ready, you should follow the setup instructions at the
+[top level](../../../README.md).
+
+You should make sure you have the following tools installed;
+ * Yosys
+ * arachne-pnr
+ * icestorm tools (like icepack and iceprog)
+ * riscv toolchain
+ * sbt
+
+## Building
+
+You should be able to just type `make compile` and get output similar to this;
+```
+...
+ place time 10.14s
+route...
+ pass 1, 15 shared.
+ pass 2, 4 shared.
+ pass 3, 1 shared.
+ pass 4, 0 shared.
+
+After routing:
+span_4 4406 / 29696
+span_12 951 / 5632
+
+ route time 9.12s
+write_txt bin/toplevel.asc...
+icepack bin/toplevel.asc bin/toplevel.bin
+```
+
+The process should take around 30 seconds on a reasonable fast computer.
+
+## Programming
+
+After building you should be able to run `make prog`. You may need to run `make
+sudo-prog` if root is needed to access your USB devices.
+
+You should get output like the following;
+```
+iceprog -S bin/toplevel.bin
+init..
+cdone: high
+reset..
+cdone: low
+programming..
+cdone: high
+Bye.
+```
+
+After programming the LEDs at the top of the board should start flashing in an
+interesting pattern.
+
+## Connect
+
+After programming you should be able to connect to the serial port and have the
+output echoed back to you.
+
+On Linux you can do this using a command like `screen /dev/ttyUSB1`. Then as
+you type you should get back the same characters.
diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/img/cram-programming-config.png b/scripts/Murax/iCE40-hx8k_breakout_board_xip/img/cram-programming-config.png
new file mode 100644
index 0000000..48562bb
Binary files /dev/null and b/scripts/Murax/iCE40-hx8k_breakout_board_xip/img/cram-programming-config.png differ
diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/img/iCE40HX8K-breakout-revA.png b/scripts/Murax/iCE40-hx8k_breakout_board_xip/img/iCE40HX8K-breakout-revA.png
new file mode 100644
index 0000000..2c460bb
Binary files /dev/null and b/scripts/Murax/iCE40-hx8k_breakout_board_xip/img/iCE40HX8K-breakout-revA.png differ
diff --git a/src/main/c/murax/xipBootloader/.gitignore b/src/main/c/murax/xipBootloader/.gitignore
new file mode 100644
index 0000000..2b33f1e
--- /dev/null
+++ b/src/main/c/murax/xipBootloader/.gitignore
@@ -0,0 +1,5 @@
+*.elf
+*.map
+*.d
+*.asm
+*.o
\ No newline at end of file
diff --git a/src/main/c/murax/xipBootloader/crt.S b/src/main/c/murax/xipBootloader/crt.S
new file mode 100644
index 0000000..178f788
--- /dev/null
+++ b/src/main/c/murax/xipBootloader/crt.S
@@ -0,0 +1,54 @@
+#define CTRL_BASE 0xF001F000
+#define XIP_BASE 0xE0040000
+#define CTRL_DATA 0x00
+#define CTRL_STATUS 0x04
+#define CTRL_MODE 0x08
+#define CTRL_RATE 0x20
+#define CTRL_SS_SETUP 0x24
+#define CTRL_SS_HOLD 0x28
+#define CTRL_SS_DISABLE 0x2C
+
+#define CTRL_XIP_CONFIG 0x40
+#define CTRL_XIP_MODE 0x44
+
+.global crtStart
+.global main
+
+#define CTRL x31
+
+crtStart:
+ li x31, CTRL_BASE
+ sw x0, CTRL_MODE(CTRL)
+ li t0, 2
+ sw t0, CTRL_RATE(CTRL)
+ li t0, 4
+ sw t0, CTRL_SS_SETUP(CTRL)
+ sw t0, CTRL_SS_HOLD(CTRL)
+ sw t0, CTRL_SS_DISABLE(CTRL)
+
+
+ li a0, 0x880
+ call spiWrite
+ li a0, 0x181
+ call spiWrite
+ li a0, 0x183
+ call spiWrite
+ li a0, 0x800
+ call spiWrite
+
+
+ li t0, 0x00FF010B
+ sw t0, CTRL_XIP_MODE(CTRL)
+ li t0, 0x1
+ sw t0, CTRL_XIP_CONFIG(CTRL)
+ li t0, XIP_BASE
+ jr t0
+
+
+spiWrite:
+ sw a0,CTRL_DATA(CTRL)
+spiWrite_wait:
+ lw t0,CTRL_STATUS(CTRL)
+ srli t0,t0,0x10
+ beqz t0,spiWrite_wait
+ ret
diff --git a/src/main/c/murax/xipBootloader/crt.bin b/src/main/c/murax/xipBootloader/crt.bin
new file mode 100755
index 0000000..d64a1cb
Binary files /dev/null and b/src/main/c/murax/xipBootloader/crt.bin differ
diff --git a/src/main/c/murax/xipBootloader/demo.S b/src/main/c/murax/xipBootloader/demo.S
new file mode 100644
index 0000000..34d02b1
--- /dev/null
+++ b/src/main/c/murax/xipBootloader/demo.S
@@ -0,0 +1,24 @@
+#define GPIO_BASE 0xF0000000
+#define GPIO_OUTPUT 4
+#define GPIO_OUTPUT_ENABLE 8
+
+
+.global crtStart
+
+crtStart:
+
+
+ li x31, GPIO_BASE
+ li t0, 0x000000FF
+ sw t0, GPIO_OUTPUT_ENABLE(x31)
+
+ li t0,0
+redo:
+ sw t0, GPIO_OUTPUT(x31)
+ li t1,10000
+ addi t0,t0,1
+loop:
+ addi t1,t1,-1
+ bnez t1, loop
+ j redo
+
diff --git a/src/main/c/murax/xipBootloader/demo.bin b/src/main/c/murax/xipBootloader/demo.bin
new file mode 100755
index 0000000..8da3b25
Binary files /dev/null and b/src/main/c/murax/xipBootloader/demo.bin differ
diff --git a/src/main/c/murax/xipBootloader/makefile b/src/main/c/murax/xipBootloader/makefile
new file mode 100644
index 0000000..56b8ab8
--- /dev/null
+++ b/src/main/c/murax/xipBootloader/makefile
@@ -0,0 +1,23 @@
+CFLAGS= -march=rv32i -mabi=ilp32 -g -O3 -MD
+LFLAGS= -nostdlib -mcmodel=medany -nostartfiles -ffreestanding -fPIC -fPIE
+
+
+all: crt.S demo.S
+ riscv64-unknown-elf-gcc -c $(CFLAGS) -o crt.o crt.S
+ riscv64-unknown-elf-gcc $(CFLAGS) -o crt.elf crt.o $(LFLAGS) -Wl,-Bstatic,-T,mapping.ld,-Map,crt.map,--print-memory-usage
+ riscv64-unknown-elf-objdump -S -d crt.elf > crt.asm
+ riscv64-unknown-elf-objcopy -O binary crt.elf crt.bin
+
+ riscv64-unknown-elf-gcc -c $(CFLAGS) -o demo.o demo.S
+ riscv64-unknown-elf-gcc $(CFLAGS) -o demo.elf demo.o $(LFLAGS) -Wl,-Bstatic,-T,mapping.ld,-Map,demo.map,--print-memory-usage
+ riscv64-unknown-elf-objdump -S -d demo.elf > demo.asm
+ riscv64-unknown-elf-objcopy -O binary demo.elf demo.bin
+
+
+
+clean:
+ rm -f *.o
+ rm -f *.bin
+ rm -f *.elf
+ rm -f *.asm
+ rm -f *.map
\ No newline at end of file
diff --git a/src/main/c/murax/xipBootloader/mapping.ld b/src/main/c/murax/xipBootloader/mapping.ld
new file mode 100644
index 0000000..cc1b070
--- /dev/null
+++ b/src/main/c/murax/xipBootloader/mapping.ld
@@ -0,0 +1,96 @@
+/*
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+*/
+OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
+OUTPUT_ARCH(riscv)
+ENTRY(crtStart)
+
+MEMORY {
+ mem : ORIGIN = 0x80000000, LENGTH = 0x00000400
+}
+
+_stack_size = DEFINED(_stack_size) ? _stack_size : 0;
+
+SECTIONS {
+
+ .vector : {
+ *crt.o(.text);
+ } > mem
+
+ .memory : {
+ *(.text);
+ end = .;
+ } > mem
+
+ .rodata :
+ {
+ *(.rdata)
+ *(.rodata .rodata.*)
+ *(.gnu.linkonce.r.*)
+ } > mem
+
+ .ctors :
+ {
+ . = ALIGN(4);
+ _ctors_start = .;
+ KEEP(*(.init_array*))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ . = ALIGN(4);
+ _ctors_end = .;
+ } > mem
+
+ .data :
+ {
+ *(.rdata)
+ *(.rodata .rodata.*)
+ *(.gnu.linkonce.r.*)
+ *(.data .data.*)
+ *(.gnu.linkonce.d.*)
+ . = ALIGN(8);
+ PROVIDE( __global_pointer$ = . + 0x800 );
+ *(.sdata .sdata.*)
+ *(.gnu.linkonce.s.*)
+ . = ALIGN(8);
+ *(.srodata.cst16)
+ *(.srodata.cst8)
+ *(.srodata.cst4)
+ *(.srodata.cst2)
+ *(.srodata .srodata.*)
+ } > mem
+
+ .bss (NOLOAD) : {
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .bss secion */
+ _bss_start = .;
+ *(.sbss*)
+ *(.gnu.linkonce.sb.*)
+ *(.bss .bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(4);
+ _bss_end = .;
+ } > mem
+
+ .noinit (NOLOAD) : {
+ . = ALIGN(4);
+ *(.noinit .noinit.*)
+ . = ALIGN(4);
+ } > mem
+
+ ._stack (NOLOAD):
+ {
+ . = ALIGN(16);
+ PROVIDE (_stack_end = .);
+ . = . + _stack_size;
+ . = ALIGN(16);
+ PROVIDE (_stack_start = .);
+ } > mem
+
+}
+
diff --git a/src/main/scala/vexriscv/Riscv.scala b/src/main/scala/vexriscv/Riscv.scala
index 57251a4..a97f114 100644
--- a/src/main/scala/vexriscv/Riscv.scala
+++ b/src/main/scala/vexriscv/Riscv.scala
@@ -98,7 +98,9 @@ object Riscv{
def ECALL = M"00000000000000000000000001110011"
def EBREAK = M"00000000000100000000000001110011"
+ def FENCEI = M"00000000000000000001000000001111"
def MRET = M"00110000001000000000000001110011"
+ def SRET = M"00010000001000000000000001110011"
def WFI = M"00010000010100000000000001110011"
def FENCE = M"-----------------000-----0001111"
@@ -131,7 +133,20 @@ object Riscv{
def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
def MINSTRETH = 0xB82 // MRW Upper 32 bits of minstret, RV32I only.
+ val SSTATUS = 0x100
+ val SIE = 0x104
+ val STVEC = 0x105
+ val SCOUNTEREN = 0x106
+ val SSCRATCH = 0x140
+ val SEPC = 0x141
+ val SCAUSE = 0x142
+ val SBADADDR = 0x143
+ val SIP = 0x144
+ val SATP = 0x180
+
+
def UCYCLE = 0xC00 // UR Machine ucycle counter.
+ def UCYCLEH = 0xC80
}
}
diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala
index 6ed4dcb..33adf07 100644
--- a/src/main/scala/vexriscv/Services.scala
+++ b/src/main/scala/vexriscv/Services.scala
@@ -47,6 +47,11 @@ trait ExceptionInhibitor{
def inhibateException() : Unit
}
+trait RegFileService{
+ def readStage() : Stage
+}
+
+
case class MemoryTranslatorCmd() extends Bundle{
val isValid = Bool
val virtualAddress = UInt(32 bits)
@@ -88,4 +93,8 @@ class BusReport{
class CacheReport {
@BeanProperty var size = 0
@BeanProperty var bytePerLine = 0
+}
+
+class DebugReport {
+ @BeanProperty var hardwareBreakpointCount = 0
}
\ No newline at end of file
diff --git a/src/main/scala/vexriscv/Stage.scala b/src/main/scala/vexriscv/Stage.scala
index 22a7e9f..d54127c 100644
--- a/src/main/scala/vexriscv/Stage.scala
+++ b/src/main/scala/vexriscv/Stage.scala
@@ -6,7 +6,8 @@ import spinal.lib._
import scala.collection.mutable
-class Stageable[T <: Data](val dataType : T) extends HardType[T](dataType) with Nameable{
+class Stageable[T <: Data](_dataType : => T) extends HardType[T](_dataType) with Nameable{
+ def dataType = apply()
setWeakName(this.getClass.getSimpleName.replace("$",""))
}
diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala
index 094c99b..93d494f 100644
--- a/src/main/scala/vexriscv/TestsWorkspace.scala
+++ b/src/main/scala/vexriscv/TestsWorkspace.scala
@@ -28,51 +28,51 @@ import spinal.lib.eda.altera.{InterruptReceiverTag, ResetEmitterTag}
object TestsWorkspace {
def main(args: Array[String]) {
- SpinalConfig(mergeAsyncProcess = false).generateVerilog {
+ SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "zz_").generateVerilog {
val configFull = VexRiscvConfig(
plugins = List(
- new IBusSimplePlugin(
- resetVector = 0x80000000l,
- relaxedPcCalculation = false,
- relaxedBusCmdValid = false,
- prediction = NONE,
- historyRamSizeLog2 = 10,
- catchAccessFault = true,
- compressedGen = true,
- busLatencyMin = 1,
- injectorStage = true
- ),
-// new IBusCachedPlugin(
+// new IBusSimplePlugin(
// resetVector = 0x80000000l,
-// compressedGen = true,
-// prediction = DYNAMIC_TARGET,
-// injectorStage = true,
-// config = InstructionCacheConfig(
-// cacheSize = 1024*16,
-// bytePerLine = 32,
-// wayCount = 1,
-// addressWidth = 32,
-// cpuDataWidth = 32,
-// memDataWidth = 32,
-// catchIllegalAccess = true,
-// catchAccessFault = true,
-// catchMemoryTranslationMiss = true,
-// asyncTagMemory = false,
-// twoCycleRam = false,
-// twoCycleCache = true
-// ),
-// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
-// portTlbSize = 4
-// )
+// cmdForkOnSecondStage = false,
+// cmdForkPersistence = false,
+// prediction = NONE,
+// historyRamSizeLog2 = 10,
+// catchAccessFault = false,
+// compressedGen = false,
+// busLatencyMin = 1,
+// injectorStage = true
// ),
+ new IBusCachedPlugin(
+ resetVector = 0x80000000l,
+ compressedGen = false,
+ prediction = NONE,
+ injectorStage = true,
+ config = InstructionCacheConfig(
+ cacheSize = 4096,
+ bytePerLine = 32,
+ wayCount = 1,
+ addressWidth = 32,
+ cpuDataWidth = 32,
+ memDataWidth = 32,
+ catchIllegalAccess = true,
+ catchAccessFault = true,
+ catchMemoryTranslationMiss = true,
+ asyncTagMemory = false,
+ twoCycleRam = false,
+ twoCycleCache = true
+ ),
+ memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
+ portTlbSize = 4
+ )
+ ),
// new DBusSimplePlugin(
// catchAddressMisaligned = true,
-// catchAccessFault = true,
+// catchAccessFault = false,
// earlyInjection = false
// ),
new DBusCachedPlugin(
config = new DataCacheConfig(
- cacheSize = 4096*4,
+ cacheSize = 4096,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
@@ -98,7 +98,7 @@ object TestsWorkspace {
ioRange = _(31 downto 28) === 0xF
),
new DecoderSimplePlugin(
- catchIllegalInstruction = true
+ catchIllegalInstruction = false
),
new RegFilePlugin(
regFileReadyKind = plugin.ASYNC,
@@ -108,7 +108,7 @@ object TestsWorkspace {
new SrcPlugin(
separatedAddSub = false
),
- new FullBarrelShifterPlugin(earlyInjection = false),
+ new FullBarrelShifterPlugin(earlyInjection = true),
// new LightShifterPlugin,
new HazardSimplePlugin(
bypassExecute = true,
@@ -129,11 +129,35 @@ object TestsWorkspace {
divUnrollFactor = 1
),
// new DivPlugin,
- new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)),
- new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
+ new CsrPlugin(CsrPluginConfig.all(0x80000020l)),
+// new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/*
+// CsrPluginConfig(
+// catchIllegalAccess = false,
+// mvendorid = null,
+// marchid = null,
+// mimpid = null,
+// mhartid = null,
+// misaExtensionsInit = 0,
+// misaAccess = CsrAccess.READ_ONLY,
+// mtvecAccess = CsrAccess.WRITE_ONLY,
+// mtvecInit = 0x80000020l,
+// mepcAccess = CsrAccess.READ_WRITE,
+// mscratchGen = true,
+// mcauseAccess = CsrAccess.READ_ONLY,
+// mbadaddrAccess = CsrAccess.READ_ONLY,
+// mcycleAccess = CsrAccess.NONE,
+// minstretAccess = CsrAccess.NONE,
+// ecallGen = true,
+// ebreakGen = true,
+// wfiGenAsWait = false,
+// wfiGenAsNop = true,
+// ucycleAccess = CsrAccess.NONE
+// )),
+// new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin(
- earlyBranch = false,
- catchAddressMisaligned = true
+ earlyBranch = true,
+ catchAddressMisaligned = true,
+ fenceiGenAsAJump = true
),
new YamlPlugin("cpu0.yaml")
)
diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala
index afd29bb..01ce0ca 100644
--- a/src/main/scala/vexriscv/VexRiscv.scala
+++ b/src/main/scala/vexriscv/VexRiscv.scala
@@ -6,14 +6,20 @@ import spinal.core._
import scala.collection.mutable.ArrayBuffer
object VexRiscvConfig{
- def apply(plugins : Seq[Plugin[VexRiscv]] = ArrayBuffer()) : VexRiscvConfig = {
+ def apply(withMemoryStage : Boolean, withWriteBackStage : Boolean, plugins : Seq[Plugin[VexRiscv]]): VexRiscvConfig = {
val config = VexRiscvConfig()
config.plugins ++= plugins
+ config.withMemoryStage = withMemoryStage
+ config.withWriteBackStage = withWriteBackStage
config
}
+
+ def apply(plugins : Seq[Plugin[VexRiscv]] = ArrayBuffer()) : VexRiscvConfig = apply(true,true,plugins)
}
case class VexRiscvConfig(){
+ var withMemoryStage = true
+ var withWriteBackStage = true
val plugins = ArrayBuffer[Plugin[VexRiscv]]()
//Default Stageables
@@ -44,6 +50,9 @@ case class VexRiscvConfig(){
object SRC_USE_SUB_LESS extends Stageable(Bool)
object SRC_LESS_UNSIGNED extends Stageable(Bool)
+
+ object HAS_SIDE_EFFECT extends Stageable(Bool)
+
//Formal verification purposes
object FORMAL_HALT extends Stageable(Bool)
object FORMAL_PC_NEXT extends Stageable(UInt(32 bits))
@@ -56,7 +65,7 @@ case class VexRiscvConfig(){
object Src1CtrlEnum extends SpinalEnum(binarySequential){
- val RS, IMU, PC_INCREMENT = newElement() //IMU, IMZ IMJB
+ val RS, IMU, PC_INCREMENT, URS1 = newElement() //IMU, IMZ IMJB
}
object Src2CtrlEnum extends SpinalEnum(binarySequential){
@@ -73,8 +82,15 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
type T = VexRiscv
import config._
- stages ++= List.fill(4)(new Stage())
- val /*prefetch :: fetch :: */decode :: execute :: memory :: writeBack :: Nil = stages.toList
+ //Define stages
+ def newStage(): Stage = { val s = new Stage; stages += s; s }
+ val decode = newStage()
+ val execute = newStage()
+ val memory = ifGen(config.withMemoryStage) (newStage())
+ val writeBack = ifGen(config.withWriteBackStage) (newStage())
+
+ def stagesFromExecute = stages.dropWhile(_ != execute)
+
plugins ++= config.plugins
//regression usage
@@ -83,12 +99,16 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
decode.arbitration.isValid.addAttribute(Verilator.public)
decode.arbitration.flushAll.addAttribute(Verilator.public)
decode.arbitration.haltItself.addAttribute(Verilator.public)
- writeBack.input(config.INSTRUCTION) keep() addAttribute(Verilator.public)
- writeBack.input(config.PC) keep() addAttribute(Verilator.public)
- writeBack.arbitration.isValid keep() addAttribute(Verilator.public)
- writeBack.arbitration.isFiring keep() addAttribute(Verilator.public)
+ if(withWriteBackStage) {
+ writeBack.input(config.INSTRUCTION) keep() addAttribute (Verilator.public)
+ writeBack.input(config.PC) keep() addAttribute (Verilator.public)
+ writeBack.arbitration.isValid keep() addAttribute (Verilator.public)
+ writeBack.arbitration.isFiring keep() addAttribute (Verilator.public)
+ }
decode.arbitration.removeIt.noBackendCombMerge //Verilator perf
- memory.arbitration.removeIt.noBackendCombMerge
+ if(withMemoryStage){
+ memory.arbitration.removeIt.noBackendCombMerge
+ }
execute.arbitration.flushAll.noBackendCombMerge
this(RVC_GEN) = false
diff --git a/src/main/scala/vexriscv/demo/Briey.scala b/src/main/scala/vexriscv/demo/Briey.scala
index 468b039..ca76f8b 100644
--- a/src/main/scala/vexriscv/demo/Briey.scala
+++ b/src/main/scala/vexriscv/demo/Briey.scala
@@ -146,7 +146,7 @@ object BrieyConfig{
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
- wfiGen = false,
+ wfiGenAsWait = false,
ucycleAccess = CsrAccess.NONE
)
),
diff --git a/src/main/scala/vexriscv/demo/FormalSimple.scala b/src/main/scala/vexriscv/demo/FormalSimple.scala
index e540b20..9a4167e 100644
--- a/src/main/scala/vexriscv/demo/FormalSimple.scala
+++ b/src/main/scala/vexriscv/demo/FormalSimple.scala
@@ -15,7 +15,8 @@ object FormalSimple extends App{
new HaltOnExceptionPlugin,
new IBusSimplePlugin(
resetVector = 0x00000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = DYNAMIC_TARGET,
catchAccessFault = false,
compressedGen = true
diff --git a/src/main/scala/vexriscv/demo/GenCustomCsr.scala b/src/main/scala/vexriscv/demo/GenCustomCsr.scala
index 5eae5d0..11db86d 100644
--- a/src/main/scala/vexriscv/demo/GenCustomCsr.scala
+++ b/src/main/scala/vexriscv/demo/GenCustomCsr.scala
@@ -18,7 +18,8 @@ object GenCustomCsr extends App{
new CustomCsrDemoGpioPlugin,
new IBusSimplePlugin(
resetVector = 0x00000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = NONE,
catchAccessFault = false,
compressedGen = false
diff --git a/src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala b/src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala
index 0b4c854..8b137f5 100644
--- a/src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala
+++ b/src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala
@@ -14,7 +14,8 @@ object GenCustomSimdAdd extends App{
new SimdAddPlugin,
new IBusSimplePlugin(
resetVector = 0x00000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = NONE,
catchAccessFault = false,
compressedGen = false
diff --git a/src/main/scala/vexriscv/demo/GenDeterministicVex.scala b/src/main/scala/vexriscv/demo/GenDeterministicVex.scala
index b4b5745..943ba16 100644
--- a/src/main/scala/vexriscv/demo/GenDeterministicVex.scala
+++ b/src/main/scala/vexriscv/demo/GenDeterministicVex.scala
@@ -13,7 +13,8 @@ object GenDeterministicVex extends App{
plugins = List(
new IBusSimplePlugin(
resetVector = 0x80000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = STATIC,
catchAccessFault = true,
compressedGen = false
diff --git a/src/main/scala/vexriscv/demo/GenFull.scala b/src/main/scala/vexriscv/demo/GenFull.scala
index bc0f039..2030b05 100644
--- a/src/main/scala/vexriscv/demo/GenFull.scala
+++ b/src/main/scala/vexriscv/demo/GenFull.scala
@@ -12,10 +12,6 @@ object GenFull extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
- new PcManagerSimplePlugin(
- resetVector = 0x80000000l,
- relaxedPcCalculation = false
- ),
new IBusCachedPlugin(
prediction = DYNAMIC,
config = InstructionCacheConfig(
@@ -54,7 +50,7 @@ object GenFull extends App{
)
),
new MemoryTranslatorPlugin(
- tlbSize = 64,
+ tlbSize = 32,
virtualRange = _(31 downto 28) === 0xC,
ioRange = _(31 downto 28) === 0xF
),
@@ -63,7 +59,7 @@ object GenFull extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
@@ -82,7 +78,7 @@ object GenFull extends App{
),
new MulPlugin,
new DivPlugin,
- new CsrPlugin(CsrPluginConfig.small),
+ new CsrPlugin(CsrPluginConfig.small(0x80000020l)),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin(
earlyBranch = false,
diff --git a/src/main/scala/vexriscv/demo/GenFullNoMmu.scala b/src/main/scala/vexriscv/demo/GenFullNoMmu.scala
index 62c8e58..e1aa722 100644
--- a/src/main/scala/vexriscv/demo/GenFullNoMmu.scala
+++ b/src/main/scala/vexriscv/demo/GenFullNoMmu.scala
@@ -55,7 +55,7 @@ object GenFullNoMmu extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
diff --git a/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala b/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala
index 7a4d2b0..e675aa0 100644
--- a/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala
+++ b/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala
@@ -56,7 +56,7 @@ object GenFullNoMmuMaxPerf extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
diff --git a/src/main/scala/vexriscv/demo/GenFullNoMmuNoCache.scala b/src/main/scala/vexriscv/demo/GenFullNoMmuNoCache.scala
index 24cb45c..77ed87a 100644
--- a/src/main/scala/vexriscv/demo/GenFullNoMmuNoCache.scala
+++ b/src/main/scala/vexriscv/demo/GenFullNoMmuNoCache.scala
@@ -14,7 +14,8 @@ object GenFullNoMmuNoCache extends App{
plugins = List(
new IBusSimplePlugin(
resetVector = 0x80000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = STATIC,
catchAccessFault = false,
compressedGen = false
@@ -28,7 +29,7 @@ object GenFullNoMmuNoCache extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
diff --git a/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala b/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala
index c63efe6..89dffe0 100644
--- a/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala
+++ b/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala
@@ -14,7 +14,8 @@ object GenNoCacheNoMmuMaxPerf extends App{
plugins = List(
new IBusSimplePlugin(
resetVector = 0x80000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = DYNAMIC_TARGET,
historyRamSizeLog2 = 8,
catchAccessFault = true,
@@ -33,7 +34,7 @@ object GenNoCacheNoMmuMaxPerf extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
@@ -51,7 +52,7 @@ object GenNoCacheNoMmuMaxPerf extends App{
pessimisticAddressMatch = false
),
new MulPlugin,
- new DivPlugin,
+ new MulDivIterativePlugin(genMul = false, genDiv = true, mulUnrollFactor = 1, divUnrollFactor = 1,dhrystoneOpt = false),
new CsrPlugin(CsrPluginConfig.small),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin(
diff --git a/src/main/scala/vexriscv/demo/GenSmallAndPerformant.scala b/src/main/scala/vexriscv/demo/GenSmallAndPerformant.scala
index d5a2f77..9bd6f72 100644
--- a/src/main/scala/vexriscv/demo/GenSmallAndPerformant.scala
+++ b/src/main/scala/vexriscv/demo/GenSmallAndPerformant.scala
@@ -13,7 +13,8 @@ object GenSmallAndProductive extends App{
plugins = List(
new IBusSimplePlugin(
resetVector = 0x80000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = NONE,
catchAccessFault = false,
compressedGen = false
@@ -28,7 +29,7 @@ object GenSmallAndProductive extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
diff --git a/src/main/scala/vexriscv/demo/GenSmallAndPerformantICache.scala b/src/main/scala/vexriscv/demo/GenSmallAndPerformantICache.scala
index b6eb53f..29d179d 100644
--- a/src/main/scala/vexriscv/demo/GenSmallAndPerformantICache.scala
+++ b/src/main/scala/vexriscv/demo/GenSmallAndPerformantICache.scala
@@ -42,7 +42,7 @@ object GenSmallAndProductiveICache extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
diff --git a/src/main/scala/vexriscv/demo/GenSmallest.scala b/src/main/scala/vexriscv/demo/GenSmallest.scala
index bd5b78f..9813ccf 100644
--- a/src/main/scala/vexriscv/demo/GenSmallest.scala
+++ b/src/main/scala/vexriscv/demo/GenSmallest.scala
@@ -13,7 +13,8 @@ object GenSmallest extends App{
plugins = List(
new IBusSimplePlugin(
resetVector = 0x80000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = NONE,
catchAccessFault = false,
compressedGen = false
@@ -28,7 +29,7 @@ object GenSmallest extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
diff --git a/src/main/scala/vexriscv/demo/GenSmallestNoCsr.scala b/src/main/scala/vexriscv/demo/GenSmallestNoCsr.scala
index f8f571e..cd1ee31 100644
--- a/src/main/scala/vexriscv/demo/GenSmallestNoCsr.scala
+++ b/src/main/scala/vexriscv/demo/GenSmallestNoCsr.scala
@@ -18,7 +18,8 @@ object GenSmallestNoCsr extends App{
new IBusSimplePlugin(
resetVector = 0x80000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = NONE,
catchAccessFault = false,
compressedGen = false
@@ -33,7 +34,7 @@ object GenSmallestNoCsr extends App{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true,
+ zeroBoot = false,
writeRfInMemoryStage = false
),
new IntAluPlugin,
diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala
index b492397..675ef28 100644
--- a/src/main/scala/vexriscv/demo/Murax.scala
+++ b/src/main/scala/vexriscv/demo/Murax.scala
@@ -5,13 +5,14 @@ import spinal.lib._
import spinal.lib.bus.amba3.apb._
import spinal.lib.bus.misc.SizeMapping
import spinal.lib.com.jtag.Jtag
+import spinal.lib.com.spi.ddr.SpiDdrMaster
import spinal.lib.com.uart._
import spinal.lib.io.{InOutWrapper, TriStateArray}
import spinal.lib.misc.{InterruptCtrl, Prescaler, Timer}
import spinal.lib.soc.pinsec.{PinsecTimerCtrl, PinsecTimerCtrlExternal}
import vexriscv.plugin._
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
-
+import spinal.lib.com.spi.ddr._
import scala.collection.mutable.ArrayBuffer
/**
@@ -38,12 +39,19 @@ case class MuraxConfig(coreFrequency : HertzNumber,
pipelineApbBridge : Boolean,
gpioWidth : Int,
uartCtrlConfig : UartCtrlMemoryMappedConfig,
+ xipConfig : SpiDdrMasterCtrl.MemoryMappingParameters,
+ hardwareBreakpointCount : Int,
cpuPlugins : ArrayBuffer[Plugin[VexRiscv]]){
require(pipelineApbBridge || pipelineMainBus, "At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions")
+ val genXip = xipConfig != null
+
}
+
+
object MuraxConfig{
- def default = MuraxConfig(
+ def default : MuraxConfig = default(false)
+ def default(withXip : Boolean) = MuraxConfig(
coreFrequency = 12 MHz,
onChipRamSize = 8 kB,
onChipRamHexFile = null,
@@ -51,10 +59,18 @@ object MuraxConfig{
pipelineMainBus = false,
pipelineApbBridge = true,
gpioWidth = 32,
+ xipConfig = ifGen(withXip) (SpiDdrMasterCtrl.MemoryMappingParameters(
+ SpiDdrMasterCtrl.Parameters(8, 12, SpiDdrParameter(2, 2, 1)).addFullDuplex(0,1,false),
+ cmdFifoDepth = 32,
+ rspFifoDepth = 32,
+ xip = SpiDdrMasterCtrl.XipBusParameters(addressWidth = 24, dataWidth = 32)
+ )),
+ hardwareBreakpointCount = if(withXip) 3 else 0,
cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
new IBusSimplePlugin(
- resetVector = 0x80000000l,
- relaxedPcCalculation = true,
+ resetVector = if(withXip) 0xF001E000l else 0x80000000l,
+ cmdForkOnSecondStage = true,
+ cmdForkPersistence = withXip, //Required by the Xip controller
prediction = NONE,
catchAccessFault = false,
compressedGen = false
@@ -64,7 +80,7 @@ object MuraxConfig{
catchAccessFault = false,
earlyInjection = false
),
- new CsrPlugin(CsrPluginConfig.smallest(mtvecInit = 0x80000020l)),
+ new CsrPlugin(CsrPluginConfig.smallest(mtvecInit = if(withXip) 0xE0040020l else 0x80000020l)),
new DecoderSimplePlugin(
catchIllegalInstruction = false
),
@@ -146,6 +162,8 @@ case class Murax(config : MuraxConfig) extends Component{
//Peripherals IO
val gpioA = master(TriStateArray(gpioWidth bits))
val uart = master(Uart())
+
+ val xip = ifGen(genXip)(master(SpiDdrMaster(xipConfig.ctrl.spi)))
}
@@ -201,7 +219,7 @@ case class Murax(config : MuraxConfig) extends Component{
//Instanciate the CPU
val cpu = new VexRiscv(
config = VexRiscvConfig(
- plugins = cpuPlugins += new DebugPlugin(debugClockDomain)
+ plugins = cpuPlugins += new DebugPlugin(debugClockDomain, hardwareBreakpointCount)
)
)
@@ -209,7 +227,9 @@ case class Murax(config : MuraxConfig) extends Component{
val timerInterrupt = False
val externalInterrupt = False
for(plugin <- cpu.plugins) plugin match{
- case plugin : IBusSimplePlugin => mainBusArbiter.io.iBus <> plugin.iBus
+ case plugin : IBusSimplePlugin =>
+ mainBusArbiter.io.iBus.cmd <> plugin.iBus.cmd
+ mainBusArbiter.io.iBus.rsp <> plugin.iBus.rsp
case plugin : DBusSimplePlugin => {
if(!pipelineDBus)
mainBusArbiter.io.dBus <> plugin.dBus
@@ -232,11 +252,13 @@ case class Murax(config : MuraxConfig) extends Component{
//****** MainBus slaves ********
+ val mainBusMapping = ArrayBuffer[(SimpleBus,SizeMapping)]()
val ram = new MuraxSimpleBusRam(
onChipRamSize = onChipRamSize,
onChipRamHexFile = onChipRamHexFile,
simpleBusConfig = simpleBusConfig
)
+ mainBusMapping += ram.io.bus -> (0x80000000l, onChipRamSize)
val apbBridge = new MuraxSimpleBusToApbBridge(
apb3Config = Apb3Config(
@@ -246,39 +268,57 @@ case class Murax(config : MuraxConfig) extends Component{
pipelineBridge = pipelineApbBridge,
simpleBusConfig = simpleBusConfig
)
+ mainBusMapping += apbBridge.io.simpleBus -> (0xF0000000l, 1 MB)
//******** APB peripherals *********
+ val apbMapping = ArrayBuffer[(Apb3, SizeMapping)]()
val gpioACtrl = Apb3Gpio(gpioWidth = gpioWidth)
io.gpioA <> gpioACtrl.io.gpio
+ apbMapping += gpioACtrl.io.apb -> (0x00000, 4 kB)
val uartCtrl = Apb3UartCtrl(uartCtrlConfig)
uartCtrl.io.uart <> io.uart
externalInterrupt setWhen(uartCtrl.io.interrupt)
+ apbMapping += uartCtrl.io.apb -> (0x10000, 4 kB)
val timer = new MuraxApb3Timer()
timerInterrupt setWhen(timer.io.interrupt)
+ apbMapping += timer.io.apb -> (0x20000, 4 kB)
+
+ val xip = ifGen(genXip)(new Area{
+ val ctrl = Apb3SpiDdrMasterCtrl(xipConfig)
+ ctrl.io.spi <> io.xip
+ externalInterrupt setWhen(ctrl.io.interrupt)
+ apbMapping += ctrl.io.apb -> (0x1F000, 4 kB)
+
+ val accessBus = new SimpleBus(SimpleBusConfig(24,32))
+ mainBusMapping += accessBus -> (0xE0000000l, 16 MB)
+
+ ctrl.io.xip.cmd.valid <> (accessBus.cmd.valid && !accessBus.cmd.wr)
+ ctrl.io.xip.cmd.ready <> accessBus.cmd.ready
+ ctrl.io.xip.cmd.payload <> accessBus.cmd.address
+
+ ctrl.io.xip.rsp.valid <> accessBus.rsp.valid
+ ctrl.io.xip.rsp.payload <> accessBus.rsp.data
+
+ val bootloader = Apb3Rom("src/main/c/murax/xipBootloader/crt.bin")
+ apbMapping += bootloader.io.apb -> (0x1E000, 4 kB)
+ })
//******** Memory mappings *********
val apbDecoder = Apb3Decoder(
master = apbBridge.io.apb,
- slaves = List[(Apb3, SizeMapping)](
- gpioACtrl.io.apb -> (0x00000, 4 kB),
- uartCtrl.io.apb -> (0x10000, 4 kB),
- timer.io.apb -> (0x20000, 4 kB)
- )
+ slaves = apbMapping
)
val mainBusDecoder = new Area {
val logic = new MuraxSimpleBusDecoder(
master = mainBusArbiter.io.masterBus,
- specification = List[(SimpleBus,SizeMapping)](
- ram.io.bus -> (0x80000000l, onChipRamSize),
- apbBridge.io.simpleBus -> (0xF0000000l, 1 MB)
- ),
+ specification = mainBusMapping,
pipelineMaster = pipelineMainBus
)
}
@@ -293,6 +333,151 @@ object Murax{
}
}
+object Murax_iCE40_hx8k_breakout_board_xip{
+
+ case class SB_GB() extends BlackBox{
+ val USER_SIGNAL_TO_GLOBAL_BUFFER = in Bool()
+ val GLOBAL_BUFFER_OUTPUT = out Bool()
+ }
+
+ case class SB_IO_SCLK() extends BlackBox{
+ addGeneric("PIN_TYPE", B"010000")
+ val PACKAGE_PIN = out Bool()
+ val OUTPUT_CLK = in Bool()
+ val CLOCK_ENABLE = in Bool()
+ val D_OUT_0 = in Bool()
+ val D_OUT_1 = in Bool()
+ setDefinitionName("SB_IO")
+ }
+
+ case class SB_IO_DATA() extends BlackBox{
+ addGeneric("PIN_TYPE", B"110000")
+ val PACKAGE_PIN = inout(Analog(Bool))
+ val CLOCK_ENABLE = in Bool()
+ val INPUT_CLK = in Bool()
+ val OUTPUT_CLK = in Bool()
+ val OUTPUT_ENABLE = in Bool()
+ val D_OUT_0 = in Bool()
+ val D_OUT_1 = in Bool()
+ val D_IN_0 = out Bool()
+ val D_IN_1 = out Bool()
+ setDefinitionName("SB_IO")
+ }
+
+ case class Murax_iCE40_hx8k_breakout_board_xip() extends Component{
+ val io = new Bundle {
+ val J3 = in Bool()
+ val H16 = in Bool()
+ val G15 = in Bool()
+ val G16 = out Bool()
+ val F15 = in Bool()
+ val B12 = out Bool()
+ val B10 = in Bool()
+
+
+ //p12 as mosi mean flash config
+ val P12 = inout(Analog(Bool))
+ val P11 = inout(Analog(Bool))
+ val R11 = out Bool()
+ val R12 = out Bool()
+
+ val led = out Bits(8 bits)
+ }
+ val murax = Murax(MuraxConfig.default(withXip = true))
+ murax.io.asyncReset := False
+
+ val mainClkBuffer = SB_GB()
+ mainClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.J3
+ mainClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.mainClk
+
+ val jtagClkBuffer = SB_GB()
+ jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.H16
+ jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck
+
+ io.led <> murax.io.gpioA.write(7 downto 0)
+
+ murax.io.jtag.tdi <> io.G15
+ murax.io.jtag.tdo <> io.G16
+ murax.io.jtag.tms <> io.F15
+ murax.io.gpioA.read <> 0
+ murax.io.uart.txd <> io.B12
+ murax.io.uart.rxd <> io.B10
+
+
+
+ val xip = new ClockingArea(murax.systemClockDomain) {
+ RegNext(murax.io.xip.ss.asBool) <> io.R12
+
+ val sclkIo = SB_IO_SCLK()
+ sclkIo.PACKAGE_PIN <> io.R11
+ sclkIo.CLOCK_ENABLE := True
+
+ sclkIo.OUTPUT_CLK := ClockDomain.current.readClockWire
+ sclkIo.D_OUT_0 <> murax.io.xip.sclk.write(0)
+ sclkIo.D_OUT_1 <> RegNext(murax.io.xip.sclk.write(1))
+
+ val datas = for ((data, pin) <- (murax.io.xip.data, List(io.P12, io.P11).reverse).zipped) yield new Area {
+ val dataIo = SB_IO_DATA()
+ dataIo.PACKAGE_PIN := pin
+ dataIo.CLOCK_ENABLE := True
+
+ dataIo.OUTPUT_CLK := ClockDomain.current.readClockWire
+ dataIo.OUTPUT_ENABLE <> data.writeEnable
+ dataIo.D_OUT_0 <> data.write(0)
+ dataIo.D_OUT_1 <> RegNext(data.write(1))
+
+ dataIo.INPUT_CLK := ClockDomain.current.readClockWire
+ data.read(0) := dataIo.D_IN_0
+ data.read(1) := RegNext(dataIo.D_IN_1)
+ }
+ }
+
+ }
+
+ def main(args: Array[String]) {
+ SpinalVerilog(Murax_iCE40_hx8k_breakout_board_xip())
+ /*SpinalVerilog{
+ val c = Murax(MuraxConfig.default(withXip = true))
+
+
+
+
+ c.rework {
+ c.resetCtrlClockDomain {
+ c.io.xip.setAsDirectionLess.allowDirectionLessIo.flattenForeach(_.unsetName())
+
+ out(RegNext(c.io.xip.ss)).setName("io_xip_ss")
+
+ val sclk = SB_IO_SCLK()
+ sclk.PACKAGE_PIN := inout(Analog(Bool)).setName("io_xip_sclk")
+ sclk.CLOCK_ENABLE := True
+
+ sclk.OUTPUT_CLK := ClockDomain.current.readClockWire
+ sclk.D_OUT_0 <> c.io.xip.sclk.write(0)
+ sclk.D_OUT_1 <> RegNext(c.io.xip.sclk.write(1))
+
+ for (i <- 0 until c.io.xip.p.dataWidth) {
+ val data = c.io.xip.data(i)
+ val bb = SB_IO_DATA()
+ bb.PACKAGE_PIN := inout(Analog(Bool)).setName(s"io_xip_data_$i" )
+ bb.CLOCK_ENABLE := True
+
+ bb.OUTPUT_CLK := ClockDomain.current.readClockWire
+ bb.OUTPUT_ENABLE <> data.writeEnable
+ bb.D_OUT_0 <> data.write(0)
+ bb.D_OUT_1 <> RegNext(data.write(1))
+
+ bb.INPUT_CLK := ClockDomain.current.readClockWire
+ data.read(0) := bb.D_IN_0
+ data.read(1) := RegNext(bb.D_IN_1)
+ }
+ }
+ }
+ c
+ }*/
+ }
+}
+
object MuraxDhrystoneReady{
def main(args: Array[String]) {
SpinalVerilog(Murax(MuraxConfig.fast.copy(onChipRamSize = 256 kB)))
@@ -312,7 +497,8 @@ object MuraxDhrystoneReadyMulDivStatic{
)
config.cpuPlugins += new IBusSimplePlugin(
resetVector = 0x80000000l,
- relaxedPcCalculation = true,
+ cmdForkOnSecondStage = true,
+ cmdForkPersistence = false,
prediction = STATIC,
catchAccessFault = false,
compressedGen = false
diff --git a/src/main/scala/vexriscv/demo/MuraxUtiles.scala b/src/main/scala/vexriscv/demo/MuraxUtiles.scala
index 8aaf8a0..b940e8c 100644
--- a/src/main/scala/vexriscv/demo/MuraxUtiles.scala
+++ b/src/main/scala/vexriscv/demo/MuraxUtiles.scala
@@ -1,5 +1,7 @@
package vexriscv.demo
+import java.nio.{ByteBuffer, ByteOrder}
+
import spinal.core._
import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3SlaveFactory}
import spinal.lib.bus.misc.SizeMapping
@@ -7,30 +9,6 @@ import spinal.lib.misc.{HexTools, InterruptCtrl, Prescaler, Timer}
import spinal.lib._
import vexriscv.plugin.{DBusSimpleBus, IBusSimpleBus}
-case class SimpleBusConfig(addressWidth : Int, dataWidth : Int)
-
-case class SimpleBusCmd(config : SimpleBusConfig) extends Bundle{
- val wr = Bool
- val address = UInt(config.addressWidth bits)
- val data = Bits(config.dataWidth bits)
- val mask = Bits(4 bit)
-}
-
-case class SimpleBusRsp(config : SimpleBusConfig) extends Bundle{
- val data = Bits(config.dataWidth bits)
-}
-
-
-case class SimpleBus(config : SimpleBusConfig) extends Bundle with IMasterSlave {
- val cmd = Stream(SimpleBusCmd(config))
- val rsp = Flow(SimpleBusRsp(config))
-
- override def asMaster(): Unit = {
- master(cmd)
- slave(rsp)
- }
-}
-
class MuraxMasterArbiter(simpleBusConfig : SimpleBusConfig) extends Component{
val io = new Bundle{
val iBus = slave(IBusSimpleBus(false))
@@ -74,7 +52,7 @@ class MuraxMasterArbiter(simpleBusConfig : SimpleBusConfig) extends Component{
}
-class MuraxSimpleBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, simpleBusConfig : SimpleBusConfig) extends Component{
+case class MuraxSimpleBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, simpleBusConfig : SimpleBusConfig) extends Component{
val io = new Bundle{
val bus = slave(SimpleBus(simpleBusConfig))
}
@@ -96,6 +74,27 @@ class MuraxSimpleBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, simpl
}
+
+case class Apb3Rom(onChipRamBinFile : String) extends Component{
+ import java.nio.file.{Files, Paths}
+ val byteArray = Files.readAllBytes(Paths.get(onChipRamBinFile))
+ val wordCount = (byteArray.length+3)/4
+ val buffer = ByteBuffer.wrap(Files.readAllBytes(Paths.get(onChipRamBinFile))).order(ByteOrder.LITTLE_ENDIAN);
+ val wordArray = (0 until wordCount).map(i => {
+ val v = buffer.getInt
+ if(v < 0) BigInt(v.toLong & 0xFFFFFFFFl) else BigInt(v)
+ })
+
+ val io = new Bundle{
+ val apb = slave(Apb3(log2Up(wordCount*4),32))
+ }
+
+ val rom = Mem(Bits(32 bits), wordCount) initBigInt(wordArray)
+// io.apb.PRDATA := rom.readSync(io.apb.PADDR >> 2)
+ io.apb.PRDATA := rom.readAsync(RegNext(io.apb.PADDR >> 2))
+ io.apb.PREADY := True
+}
+
class MuraxSimpleBusToApbBridge(apb3Config: Apb3Config, pipelineBridge : Boolean, simpleBusConfig : SimpleBusConfig) extends Component{
assert(apb3Config.dataWidth == simpleBusConfig.dataWidth)
@@ -130,7 +129,7 @@ class MuraxSimpleBusToApbBridge(apb3Config: Apb3Config, pipelineBridge : Boolean
}
}
-class MuraxSimpleBusDecoder(master : SimpleBus, val specification : List[(SimpleBus,SizeMapping)], pipelineMaster : Boolean) extends Area{
+class MuraxSimpleBusDecoder(master : SimpleBus, val specification : Seq[(SimpleBus,SizeMapping)], pipelineMaster : Boolean) extends Area{
val masterPipelined = SimpleBus(master.config)
if(!pipelineMaster) {
masterPipelined.cmd << master.cmd
@@ -146,7 +145,7 @@ class MuraxSimpleBusDecoder(master : SimpleBus, val specification : List[(Simple
val hits = for((slaveBus, memorySpace) <- specification) yield {
val hit = memorySpace.hit(masterPipelined.cmd.address)
slaveBus.cmd.valid := masterPipelined.cmd.valid && hit
- slaveBus.cmd.payload := masterPipelined.cmd.payload
+ slaveBus.cmd.payload := masterPipelined.cmd.payload.resized
hit
}
val noHit = !hits.orR
diff --git a/src/main/scala/vexriscv/demo/SimpleBus.scala b/src/main/scala/vexriscv/demo/SimpleBus.scala
new file mode 100644
index 0000000..e8a7404
--- /dev/null
+++ b/src/main/scala/vexriscv/demo/SimpleBus.scala
@@ -0,0 +1,324 @@
+package vexriscv.demo
+
+
+import spinal.core._
+import spinal.lib.bus.misc._
+import spinal.lib._
+
+import scala.collection.mutable
+import scala.collection.mutable.ArrayBuffer
+
+case class SimpleBusConfig(addressWidth : Int, dataWidth : Int)
+
+case class SimpleBusCmd(config : SimpleBusConfig) extends Bundle{
+ val wr = Bool
+ val address = UInt(config.addressWidth bits)
+ val data = Bits(config.dataWidth bits)
+ val mask = Bits(4 bit)
+}
+
+case class SimpleBusRsp(config : SimpleBusConfig) extends Bundle{
+ val data = Bits(config.dataWidth bits)
+}
+
+object SimpleBus{
+ def apply(addressWidth : Int, dataWidth : Int) = new SimpleBus(SimpleBusConfig(addressWidth, dataWidth))
+}
+case class SimpleBus(config : SimpleBusConfig) extends Bundle with IMasterSlave {
+ val cmd = Stream(SimpleBusCmd(config))
+ val rsp = Flow(SimpleBusRsp(config))
+
+ override def asMaster(): Unit = {
+ master(cmd)
+ slave(rsp)
+ }
+
+ def <<(m : SimpleBus) : Unit = {
+ val s = this
+ assert(m.config.addressWidth >= s.config.addressWidth)
+ assert(m.config.dataWidth == s.config.dataWidth)
+ s.cmd.valid := m.cmd.valid
+ s.cmd.wr := m.cmd.wr
+ s.cmd.address := m.cmd.address.resized
+ s.cmd.data := m.cmd.data
+ s.cmd.mask := m.cmd.mask
+ m.cmd.ready := s.cmd.ready
+ m.rsp.valid := s.rsp.valid
+ m.rsp.data := s.rsp.data
+ }
+ def >>(s : SimpleBus) : Unit = s << this
+
+ def cmdM2sPipe(): SimpleBus = {
+ val ret = cloneOf(this)
+ this.cmd.m2sPipe() >> ret.cmd
+ this.rsp << ret.rsp
+ ret
+ }
+
+ def cmdS2mPipe(): SimpleBus = {
+ val ret = cloneOf(this)
+ this.cmd.s2mPipe() >> ret.cmd
+ this.rsp << ret.rsp
+ ret
+ }
+
+ def rspPipe(): SimpleBus = {
+ val ret = cloneOf(this)
+ this.cmd >> ret.cmd
+ this.rsp << ret.rsp.stage()
+ ret
+ }
+}
+
+
+
+
+
+object SimpleBusArbiter{
+ def apply(inputs : Seq[SimpleBus], pendingRspMax : Int, rspRouteQueue : Boolean, transactionLock : Boolean): SimpleBus = {
+ val c = SimpleBusArbiter(inputs.head.config, inputs.size, pendingRspMax, rspRouteQueue, transactionLock)
+ (inputs, c.io.inputs).zipped.foreach(_ <> _)
+ c.io.output
+ }
+}
+
+case class SimpleBusArbiter(simpleBusConfig : SimpleBusConfig, portCount : Int, pendingRspMax : Int, rspRouteQueue : Boolean, transactionLock : Boolean = true) extends Component{
+ val io = new Bundle{
+ val inputs = Vec(slave(SimpleBus(simpleBusConfig)), portCount)
+ val output = master(SimpleBus(simpleBusConfig))
+ }
+ val logic = if(portCount == 1) new Area{
+ io.output << io.inputs(0)
+ } else new Area {
+ val arbiterFactory = StreamArbiterFactory.lowerFirst
+ if(transactionLock) arbiterFactory.transactionLock else arbiterFactory.noLock
+ val arbiter = arbiterFactory.build(SimpleBusCmd(simpleBusConfig), portCount)
+ (arbiter.io.inputs, io.inputs).zipped.foreach(_ <> _.cmd)
+
+ val rspRouteOh = Bits(portCount bits)
+
+ val rsp = if(!rspRouteQueue) new Area{
+ assert(pendingRspMax == 1)
+ val pending = RegInit(False) clearWhen(io.output.rsp.valid)
+ val target = Reg(Bits(portCount bits))
+ rspRouteOh := target
+ when(io.output.cmd.fire && !io.output.cmd.wr){
+ target := arbiter.io.chosenOH
+ pending := True
+ }
+ io.output.cmd << arbiter.io.output.haltWhen(pending && !io.output.rsp.valid)
+ } else new Area{
+ val (outputCmdFork, routeCmdFork) = StreamFork2(arbiter.io.output)
+ io.output.cmd << outputCmdFork
+
+ val rspRoute = routeCmdFork.translateWith(arbiter.io.chosenOH).throwWhen(routeCmdFork.wr).queueLowLatency(size = pendingRspMax, latency = 1)
+ rspRoute.ready := io.output.rsp.valid
+ rspRouteOh := rspRoute.payload
+ }
+
+ for ((input, id) <- io.inputs.zipWithIndex) {
+ input.rsp.valid := io.output.rsp.valid && rspRouteOh(id)
+ input.rsp.payload := io.output.rsp.payload
+ }
+ }
+}
+
+class SimpleBusSlaveFactory(bus: SimpleBus) extends BusSlaveFactoryDelayed{
+ bus.cmd.ready := True
+
+ val readAtCmd = Flow(Bits(bus.config.dataWidth bits))
+ val readAtRsp = readAtCmd.stage()
+
+ val askWrite = (bus.cmd.valid && bus.cmd.wr).allowPruning()
+ val askRead = (bus.cmd.valid && !bus.cmd.wr).allowPruning()
+ val doWrite = (askWrite && bus.cmd.ready).allowPruning()
+ val doRead = (askRead && bus.cmd.ready).allowPruning()
+
+ bus.rsp.valid := readAtRsp.valid
+ bus.rsp.data := readAtRsp.payload
+
+ readAtCmd.valid := doRead
+ readAtCmd.payload := 0
+
+ def readAddress() : UInt = bus.cmd.address
+ def writeAddress() : UInt = bus.cmd.address
+
+ override def readHalt(): Unit = bus.cmd.ready := False
+ override def writeHalt(): Unit = bus.cmd.ready := False
+
+ override def build(): Unit = {
+ super.doNonStopWrite(bus.cmd.data)
+
+ def doMappedElements(jobs : Seq[BusSlaveFactoryElement]) = super.doMappedElements(
+ jobs = jobs,
+ askWrite = askWrite,
+ askRead = askRead,
+ doWrite = doWrite,
+ doRead = doRead,
+ writeData = bus.cmd.data,
+ readData = readAtCmd.payload
+ )
+
+ switch(bus.cmd.address) {
+ for ((address, jobs) <- elementsPerAddress if address.isInstanceOf[SingleMapping]) {
+ is(address.asInstanceOf[SingleMapping].address) {
+ doMappedElements(jobs)
+ }
+ }
+ }
+
+ for ((address, jobs) <- elementsPerAddress if !address.isInstanceOf[SingleMapping]) {
+ when(address.hit(bus.cmd.address)){
+ doMappedElements(jobs)
+ }
+ }
+ }
+
+ override def busDataWidth: Int = bus.config.dataWidth
+ override def wordAddressInc: Int = busDataWidth / 8
+}
+
+case class SimpleBusDecoder(busConfig : SimpleBusConfig, mappings : Seq[AddressMapping], pendingMax : Int = 3) extends Component{
+ val io = new Bundle {
+ val input = slave(SimpleBus(busConfig))
+ val outputs = Vec(master(SimpleBus(busConfig)), mappings.size)
+ }
+ val hasDefault = mappings.contains(DefaultMapping)
+ val logic = if(hasDefault && mappings.size == 1){
+ io.outputs(0) <> io.input
+ } else new Area {
+ val hits = Vec(Bool, mappings.size)
+ for ((slaveBus, memorySpace, hit) <- (io.outputs, mappings, hits).zipped) yield {
+ hit := (memorySpace match {
+ case DefaultMapping => !hits.filterNot(_ == hit).orR
+ case _ => memorySpace.hit(io.input.cmd.address)
+ })
+ slaveBus.cmd.valid := io.input.cmd.valid && hit
+ slaveBus.cmd.payload := io.input.cmd.payload.resized
+ }
+ val noHit = if (!hasDefault) !hits.orR else False
+ io.input.cmd.ready := (hits, io.outputs).zipped.map(_ && _.cmd.ready).orR || noHit
+
+ val rspPendingCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
+ rspPendingCounter := rspPendingCounter + U(io.input.cmd.fire && !io.input.cmd.wr) - U(io.input.rsp.valid)
+ val rspHits = RegNextWhen(hits, io.input.cmd.fire)
+ val rspPending = rspPendingCounter =/= 0
+ val rspNoHit = if (!hasDefault) !rspHits.orR else False
+ io.input.rsp.valid := io.outputs.map(_.rsp.valid).orR || (rspPending && rspNoHit)
+ io.input.rsp.payload := io.outputs.map(_.rsp.payload).read(OHToUInt(rspHits))
+
+ val cmdWait = (io.input.cmd.valid && rspPending && hits =/= rspHits) || rspPendingCounter === pendingMax
+ when(cmdWait) {
+ io.input.cmd.ready := False
+ io.outputs.foreach(_.cmd.valid := False)
+ }
+ }
+}
+
+object SimpleBusConnectors{
+ def direct(m : SimpleBus, s : SimpleBus) : Unit = m >> s
+}
+
+case class SimpleBusInterconnect(){
+ case class MasterModel(var connector : (SimpleBus,SimpleBus) => Unit = SimpleBusConnectors.direct)
+ case class SlaveModel(mapping : AddressMapping, var connector : (SimpleBus,SimpleBus) => Unit = SimpleBusConnectors.direct, var transactionLock : Boolean = true)
+ case class ConnectionModel(m : SimpleBus, s : SimpleBus, var connector : (SimpleBus,SimpleBus) => Unit = SimpleBusConnectors.direct)
+
+ val masters = mutable.LinkedHashMap[SimpleBus, MasterModel]()
+ val slaves = mutable.LinkedHashMap[SimpleBus, SlaveModel]()
+ val connections = ArrayBuffer[ConnectionModel]()
+ var arbitrationPendingRspMaxDefault = 1
+ var arbitrationRspRouteQueueDefault = false
+
+ def perfConfig(): Unit ={
+ arbitrationPendingRspMaxDefault = 7
+ arbitrationRspRouteQueueDefault = true
+ }
+
+ def areaConfig(): Unit ={
+ arbitrationPendingRspMaxDefault = 1
+ arbitrationRspRouteQueueDefault = false
+ }
+
+ def setConnector(bus : SimpleBus)( connector : (SimpleBus,SimpleBus) => Unit): Unit = (masters.get(bus), slaves.get(bus)) match {
+ case (Some(m), _) => m.connector = connector
+ case (None, Some(s)) => s.connector = connector
+ }
+
+ def setConnector(m : SimpleBus, s : SimpleBus)(connector : (SimpleBus,SimpleBus) => Unit): Unit = connections.find(e => e.m == m && e.s == s) match {
+ case Some(c) => c.connector = connector
+ }
+
+ def addSlave(bus: SimpleBus,mapping: AddressMapping) : this.type = {
+ slaves(bus) = SlaveModel(mapping)
+ this
+ }
+
+ def addSlaves(orders : (SimpleBus,AddressMapping)*) : this.type = {
+ orders.foreach(order => addSlave(order._1,order._2))
+ this
+ }
+
+ def noTransactionLockOn(slave : SimpleBus) : Unit = slaves(slave).transactionLock = false
+ def noTransactionLockOn(slaves : Seq[SimpleBus]) : Unit = slaves.foreach(noTransactionLockOn(_))
+
+
+ def addMaster(bus : SimpleBus, accesses : Seq[SimpleBus]) : this.type = {
+ masters(bus) = MasterModel()
+ for(s <- accesses) connections += ConnectionModel(bus, s)
+ this
+ }
+
+ def addMasters(specs : (SimpleBus,Seq[SimpleBus])*) : this.type = {
+ specs.foreach(spec => addMaster(spec._1,spec._2))
+ this
+ }
+
+ def build(): Unit ={
+ def applyName(bus : Bundle,name : String, onThat : Nameable) : Unit = {
+ if(bus.component == Component.current)
+ onThat.setCompositeName(bus,name)
+ else if(bus.isNamed)
+ onThat.setCompositeName(bus.component,bus.getName() + "_" + name)
+ }
+
+ val connectionsInput = mutable.HashMap[ConnectionModel,SimpleBus]()
+ val connectionsOutput = mutable.HashMap[ConnectionModel,SimpleBus]()
+ for((bus, model) <- masters){
+ val busConnections = connections.filter(_.m == bus)
+ val busSlaves = busConnections.map(c => slaves(c.s))
+ val decoder = new SimpleBusDecoder(bus.config, busSlaves.map(_.mapping))
+ applyName(bus,"decoder",decoder)
+ model.connector(bus, decoder.io.input)
+ for((connection, decoderOutput) <- (busConnections, decoder.io.outputs).zipped) {
+ connectionsInput(connection) = decoderOutput
+ }
+ }
+
+ for((bus, model) <- slaves){
+ val busConnections = connections.filter(_.s == bus)
+ val busMasters = busConnections.map(c => masters(c.m))
+ val arbiter = new SimpleBusArbiter(bus.config, busMasters.size, arbitrationPendingRspMaxDefault, arbitrationRspRouteQueueDefault, model.transactionLock)
+ applyName(bus,"arbiter",arbiter)
+ model.connector(arbiter.io.output, bus)
+ for((connection, arbiterInput) <- (busConnections, arbiter.io.inputs).zipped) {
+ connectionsOutput(connection) = arbiterInput
+ }
+ }
+
+ for(connection <- connections){
+ val m = connectionsInput(connection)
+ val s = connectionsOutput(connection)
+ if(m.config == s.config) {
+ connection.connector(m, s)
+ }else{
+ val tmp = cloneOf(s)
+ m >> tmp //Adapte the bus kind.
+ connection.connector(tmp,s)
+ }
+ }
+ }
+
+ //Will make SpinalHDL calling the build function at the end of the current component elaboration
+ Component.current.addPrePopTask(build)
+}
diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala
index f908586..13ebde3 100644
--- a/src/main/scala/vexriscv/demo/SynthesisBench.scala
+++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala
@@ -102,19 +102,30 @@ object VexRiscvSynthesisBench {
val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
-//val rtls = List(smallestNoCsr)
+// val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache)
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
-// val rtls = List(smallAndProductive, full)
+// val rtls = List(fullNoMmu)
val targets = XilinxStdTargets(
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
) ++ AlteraStdTargets(
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
- ) ++ IcestormStdTargets()
+ ) ++ IcestormStdTargets().take(1)
-// val targets = IcestormStdTargets()
- Bench(rtls, targets, "/eda/tmp/")
+
+// val targets = XilinxStdTargets(
+// vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
+// )
+
+// val targets = AlteraStdTargets(
+// quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
+// quartusCycloneVPath = null
+// )
+
+
+ // val targets = IcestormStdTargets()
+ Bench(rtls, targets, "/eda/tmp")
}
}
@@ -173,7 +184,7 @@ object MuraxSynthesisBench {
val rtls = List(murax, muraxFast)
- val targets = IcestormStdTargets() ++ XilinxStdTargets(
+ val targets = IcestormStdTargets().take(1) ++ XilinxStdTargets(
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
) ++ AlteraStdTargets(
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/",
diff --git a/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala b/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala
index 5a720cf..1e926ee 100644
--- a/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala
+++ b/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala
@@ -28,7 +28,8 @@ object VexRiscvAvalonForSim{
plugins = List(
new IBusSimplePlugin(
resetVector = 0x00000000l,
- relaxedPcCalculation = false,
+ cmdForkOnSecondStage = false,
+ cmdForkPersistence = false,
prediction = STATIC,
catchAccessFault = false,
compressedGen = false
@@ -82,7 +83,7 @@ object VexRiscvAvalonForSim{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
@@ -124,7 +125,7 @@ object VexRiscvAvalonForSim{
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
- wfiGen = false,
+ wfiGenAsWait = false,
ucycleAccess = CsrAccess.NONE
)
),
@@ -141,31 +142,31 @@ object VexRiscvAvalonForSim{
var iBus : AvalonMM = null
for (plugin <- cpuConfig.plugins) plugin match {
case plugin: IBusSimplePlugin => {
- plugin.iBus.asDirectionLess() //Unset IO properties of iBus
+ plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
iBus = master(plugin.iBus.toAvalon())
.setName("iBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
}
case plugin: IBusCachedPlugin => {
- plugin.iBus.asDirectionLess() //Unset IO properties of iBus
+ plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
iBus = master(plugin.iBus.toAvalon())
.setName("iBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
}
case plugin: DBusSimplePlugin => {
- plugin.dBus.asDirectionLess()
+ plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toAvalon())
.setName("dBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current))
}
case plugin: DBusCachedPlugin => {
- plugin.dBus.asDirectionLess()
+ plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toAvalon())
.setName("dBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current))
}
case plugin: DebugPlugin => {
- plugin.io.bus.asDirectionLess()
+ plugin.io.bus.setAsDirectionLess()
slave(plugin.io.bus.fromAvalon())
.setName("debugBusAvalon")
.addTag(ClockDomainTag(plugin.debugClockDomain))
diff --git a/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala b/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala
index 15f5db0..e4793d2 100644
--- a/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala
+++ b/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala
@@ -80,7 +80,7 @@ object VexRiscvAvalonWithIntegratedJtag{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
@@ -122,7 +122,7 @@ object VexRiscvAvalonWithIntegratedJtag{
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
- wfiGen = false,
+ wfiGenAsWait = false,
ucycleAccess = CsrAccess.NONE
)
),
@@ -139,31 +139,31 @@ object VexRiscvAvalonWithIntegratedJtag{
var iBus : AvalonMM = null
for (plugin <- cpuConfig.plugins) plugin match {
case plugin: IBusSimplePlugin => {
- plugin.iBus.asDirectionLess() //Unset IO properties of iBus
+ plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
iBus = master(plugin.iBus.toAvalon())
.setName("iBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
}
case plugin: IBusCachedPlugin => {
- plugin.iBus.asDirectionLess() //Unset IO properties of iBus
+ plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
iBus = master(plugin.iBus.toAvalon())
.setName("iBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
}
case plugin: DBusSimplePlugin => {
- plugin.dBus.asDirectionLess()
+ plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toAvalon())
.setName("dBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current))
}
case plugin: DBusCachedPlugin => {
- plugin.dBus.asDirectionLess()
+ plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toAvalon())
.setName("dBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current))
}
case plugin: DebugPlugin => {
- plugin.io.bus.asDirectionLess()
+ plugin.io.bus.setAsDirectionLess()
val jtag = slave(new Jtag())
.setName("jtag")
jtag <> plugin.io.bus.fromJtag()
diff --git a/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala b/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala
index 475efa4..9f339fb 100644
--- a/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala
+++ b/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala
@@ -123,7 +123,7 @@ object VexRiscvAxi4WithIntegratedJtag{
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
- wfiGen = false,
+ wfiGenAsWait = false,
ucycleAccess = CsrAccess.NONE
)
),
@@ -140,31 +140,31 @@ object VexRiscvAxi4WithIntegratedJtag{
var iBus : Axi4ReadOnly = null
for (plugin <- cpuConfig.plugins) plugin match {
case plugin: IBusSimplePlugin => {
- plugin.iBus.asDirectionLess() //Unset IO properties of iBus
+ plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
iBus = master(plugin.iBus.toAxi4ReadOnly().toFullConfig())
.setName("iBusAxi")
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
}
case plugin: IBusCachedPlugin => {
- plugin.iBus.asDirectionLess() //Unset IO properties of iBus
+ plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
iBus = master(plugin.iBus.toAxi4ReadOnly().toFullConfig())
.setName("iBusAxi")
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
}
case plugin: DBusSimplePlugin => {
- plugin.dBus.asDirectionLess()
+ plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toAxi4Shared().toAxi4().toFullConfig())
.setName("dBusAxi")
.addTag(ClockDomainTag(ClockDomain.current))
}
case plugin: DBusCachedPlugin => {
- plugin.dBus.asDirectionLess()
+ plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toAxi4Shared().toAxi4().toFullConfig())
.setName("dBusAxi")
.addTag(ClockDomainTag(ClockDomain.current))
}
case plugin: DebugPlugin => {
- plugin.io.bus.asDirectionLess()
+ plugin.io.bus.setAsDirectionLess()
val jtag = slave(new Jtag())
.setName("jtag")
jtag <> plugin.io.bus.fromJtag()
diff --git a/src/main/scala/vexriscv/demo/VexRiscvCachedWishboneForSim.scala b/src/main/scala/vexriscv/demo/VexRiscvCachedWishboneForSim.scala
index 35cad08..ebf5e82 100644
--- a/src/main/scala/vexriscv/demo/VexRiscvCachedWishboneForSim.scala
+++ b/src/main/scala/vexriscv/demo/VexRiscvCachedWishboneForSim.scala
@@ -79,7 +79,7 @@ object VexRiscvCachedWishboneForSim{
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
- zeroBoot = true
+ zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
@@ -118,19 +118,19 @@ object VexRiscvCachedWishboneForSim{
cpu.rework {
for (plugin <- cpuConfig.plugins) plugin match {
case plugin: IBusSimplePlugin => {
- plugin.iBus.asDirectionLess() //Unset IO properties of iBus
+ plugin.iBus.setAsDirectionLess() //Unset IO properties of iBus
master(plugin.iBus.toWishbone()).setName("iBusWishbone")
}
case plugin: IBusCachedPlugin => {
- plugin.iBus.asDirectionLess()
+ plugin.iBus.setAsDirectionLess()
master(plugin.iBus.toWishbone()).setName("iBusWishbone")
}
case plugin: DBusSimplePlugin => {
- plugin.dBus.asDirectionLess()
+ plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toWishbone()).setName("dBusWishbone")
}
case plugin: DBusCachedPlugin => {
- plugin.dBus.asDirectionLess()
+ plugin.dBus.setAsDirectionLess()
master(plugin.dBus.toWishbone()).setName("dBusWishbone")
}
case _ =>
diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala
index 3ce2a8b..8853820 100644
--- a/src/main/scala/vexriscv/ip/DataCache.scala
+++ b/src/main/scala/vexriscv/ip/DataCache.scala
@@ -6,6 +6,7 @@ import spinal.lib._
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4Shared}
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
+import vexriscv.demo.SimpleBus
case class DataCacheConfig( cacheSize : Int,
bytePerLine : Int,
@@ -342,6 +343,28 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
rsp.error := False //TODO
bus
}
+
+
+
+ def toSimpleBus(): SimpleBus = {
+ val bus = SimpleBus(32,32)
+
+ val counter = Reg(UInt(log2Up(p.burstSize) bits)) init(0)
+ when(bus.cmd.fire){ counter := counter + 1 }
+ when( cmd.fire && cmd.last){ counter := 0 }
+
+ bus.cmd.valid := cmd.valid
+ bus.cmd.address := (cmd.address(31 downto 2) | counter.resized) @@ U"00"
+ bus.cmd.wr := cmd.wr
+ bus.cmd.mask := cmd.mask
+ bus.cmd.data := cmd.data
+ cmd.ready := bus.cmd.ready && (cmd.wr || counter === cmd.length)
+ rsp.valid := bus.rsp.valid
+ rsp.data := bus.rsp.payload.data
+ rsp.error := False
+ bus
+ }
+
}
diff --git a/src/main/scala/vexriscv/ip/InstructionCache.scala b/src/main/scala/vexriscv/ip/InstructionCache.scala
index 508bf9f..8ba3ba4 100644
--- a/src/main/scala/vexriscv/ip/InstructionCache.scala
+++ b/src/main/scala/vexriscv/ip/InstructionCache.scala
@@ -6,6 +6,7 @@ import spinal.lib._
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4ReadOnly}
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
+import vexriscv.demo.{SimpleBus, SimpleBusConfig}
case class InstructionCacheConfig( cacheSize : Int,
@@ -45,6 +46,11 @@ case class InstructionCacheConfig( cacheSize : Int,
constantBurstBehavior = true
)
+ def getSimpleBusConfig() = SimpleBusConfig(
+ addressWidth = 32,
+ dataWidth = 32
+ )
+
def getWishboneConfig() = WishboneConfig(
addressWidth = 30,
dataWidth = 32,
@@ -178,6 +184,24 @@ case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle wit
mm
}
+
+ def toSimpleBus(): SimpleBus = {
+ val simpleBusConfig = p.getSimpleBusConfig()
+ val bus = SimpleBus(simpleBusConfig)
+ val counter = Counter(p.burstSize, bus.cmd.fire)
+ bus.cmd.valid := cmd.valid
+ bus.cmd.address := cmd.address(31 downto widthOf(counter.value) + 2) @@ counter @@ U"00"
+ bus.cmd.wr := False
+ bus.cmd.mask.assignDontCare()
+ bus.cmd.data.assignDontCare()
+ cmd.ready := counter.willOverflow
+ rsp.valid := bus.rsp.valid
+ rsp.data := bus.rsp.payload.data
+ rsp.error := False
+ bus
+ }
+
+
def toWishbone(): Wishbone = {
val wishboneConfig = p.getWishboneConfig()
val bus = Wishbone(wishboneConfig)
diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala
index eff2f09..46e2897 100644
--- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala
@@ -48,16 +48,20 @@ trait PredictionInterface{
def askDecodePrediction() : DecodePredictionBus
}
+
+
class BranchPlugin(earlyBranch : Boolean,
- catchAddressMisaligned : Boolean = false) extends Plugin[VexRiscv] with PredictionInterface{
-
+ catchAddressMisaligned : Boolean = false,
+ fenceiGenAsAJump : Boolean = false,
+ fenceiGenAsANop : Boolean = false) extends Plugin[VexRiscv] with PredictionInterface{
+ def catchAddressMisalignedForReal = catchAddressMisaligned && !pipeline(RVC_GEN)
lazy val branchStage = if(earlyBranch) pipeline.execute else pipeline.memory
object BRANCH_CALC extends Stageable(UInt(32 bits))
object BRANCH_DO extends Stageable(Bool)
object BRANCH_COND_RESULT extends Stageable(Bool)
-// object PREDICTION_HAD_BRANCHED extends Stageable(Bool)
+ object IS_FENCEI extends Stageable(Bool)
var jumpInterface : Flow[UInt] = null
var predictionJumpInterface : Flow[UInt] = null
@@ -82,55 +86,77 @@ class BranchPlugin(earlyBranch : Boolean,
override def setup(pipeline: VexRiscv): Unit = {
import Riscv._
import pipeline.config._
-
- val decoderService = pipeline.service(classOf[DecoderService])
+ import IntAluPlugin._
val bActions = List[(Stageable[_ <: BaseType],Any)](
SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.RS,
SRC_USE_SUB_LESS -> True,
RS1_USE -> True,
- RS2_USE -> True
+ RS2_USE -> True,
+ HAS_SIDE_EFFECT -> True
)
val jActions = List[(Stageable[_ <: BaseType],Any)](
SRC1_CTRL -> Src1CtrlEnum.PC_INCREMENT,
SRC2_CTRL -> Src2CtrlEnum.PC,
SRC_USE_SUB_LESS -> False,
- REGFILE_WRITE_VALID -> True
+ REGFILE_WRITE_VALID -> True,
+ HAS_SIDE_EFFECT -> True
)
- import IntAluPlugin._
+ val decoderService = pipeline.service(classOf[DecoderService])
+
decoderService.addDefault(BRANCH_CTRL, BranchCtrlEnum.INC)
val rvc = pipeline(RVC_GEN)
decoderService.add(List(
- JAL(rvc) -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JAL, ALU_CTRL -> AluCtrlEnum.ADD_SUB)),
- JALR -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JALR, ALU_CTRL -> AluCtrlEnum.ADD_SUB, RS1_USE -> True)),
- BEQ(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)),
- BNE(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)),
- BLT(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)),
- BGE(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)),
- BLTU(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True)),
- BGEU(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True))
+ JAL(true) -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JAL, ALU_CTRL -> AluCtrlEnum.ADD_SUB)),
+ JALR -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JALR, ALU_CTRL -> AluCtrlEnum.ADD_SUB, RS1_USE -> True)),
+ BEQ(true) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)),
+ BNE(true) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)),
+ BLT(true) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)),
+ BGE(true) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)),
+ BLTU(true) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True)),
+ BGEU(true) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True))
))
+ if(fenceiGenAsAJump) {
+ decoderService.addDefault(IS_FENCEI, False)
+ decoderService.add(List(
+ FENCEI -> (List(IS_FENCEI -> True,HAS_SIDE_EFFECT -> True, BRANCH_CTRL -> BranchCtrlEnum.JAL))
+ ))
+ }
+
+ if(fenceiGenAsANop){
+ decoderService.add(List(FENCEI -> List()))
+ }
+
val pcManagerService = pipeline.service(classOf[JumpService])
jumpInterface = pcManagerService.createJumpInterface(branchStage)
- if (catchAddressMisaligned) {
+ if (catchAddressMisalignedForReal) {
val exceptionService = pipeline.service(classOf[ExceptionService])
branchExceptionPort = exceptionService.newExceptionPort(branchStage)
}
}
- override def build(pipeline: VexRiscv): Unit = (fetchPrediction,decodePrediction) match {
- case (null, null) => buildWithoutPrediction(pipeline)
- case (_ , null) => buildFetchPrediction(pipeline)
- case (null, _) => buildDecodePrediction(pipeline)
-// case `DYNAMIC` => buildWithPrediction(pipeline)
-// case `DYNAMIC_TARGET` => buildDynamicTargetPrediction(pipeline)
+ override def build(pipeline: VexRiscv): Unit = {
+ (fetchPrediction,decodePrediction) match {
+ case (null, null) => buildWithoutPrediction(pipeline)
+ case (_ , null) => buildFetchPrediction(pipeline)
+ case (null, _) => buildDecodePrediction(pipeline)
+ }
+ if(fenceiGenAsAJump) {
+ import pipeline._
+ import pipeline.config._
+ when(decode.input(IS_FENCEI)) {
+ decode.output(INSTRUCTION)(12) := False
+ decode.output(INSTRUCTION)(22) := True
+ }
+ execute.arbitration.haltByOther setWhen(execute.arbitration.isValid && execute.input(IS_FENCEI) && stagesFromExecute.tail.map(_.arbitration.isValid).asBits.orR)
+ }
}
def buildWithoutPrediction(pipeline: VexRiscv): Unit = {
@@ -165,23 +191,25 @@ class BranchPlugin(earlyBranch : Boolean,
).asUInt
val branchAdder = branch_src1 + branch_src2
- insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0))
+ insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0"
}
//Apply branchs (JAL,JALR, Bxx)
branchStage plug new Area {
import branchStage._
- jumpInterface.valid := arbitration.isFiring && input(BRANCH_DO)
+ jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO)
jumpInterface.payload := input(BRANCH_CALC)
when(jumpInterface.valid) {
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
}
- if(catchAddressMisaligned) { //TODO conflict with instruction cache two stage
- branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && (if(pipeline(RVC_GEN)) jumpInterface.payload(0 downto 0) =/= 0 else jumpInterface.payload(1 downto 0) =/= 0)
+ if(catchAddressMisalignedForReal) {
+ branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1)
branchExceptionPort.code := 0
branchExceptionPort.badAddr := jumpInterface.payload
+
+ if(branchStage == execute) branchExceptionPort.valid clearWhen(service(classOf[HazardService]).hazardOnExecuteRS)
}
}
}
@@ -196,7 +224,7 @@ class BranchPlugin(earlyBranch : Boolean,
decode plug new Area {
import decode._
- insert(PREDICTION_HAD_BRANCHED) := decodePrediction.cmd.hadBranch
+ insert(PREDICTION_HAD_BRANCHED) := (if(fenceiGenAsAJump) decodePrediction.cmd.hadBranch && !decode.input(IS_FENCEI) else decodePrediction.cmd.hadBranch)
}
//Do real branch calculation
@@ -218,10 +246,16 @@ class BranchPlugin(earlyBranch : Boolean,
)
)
- insert(BRANCH_DO) := input(PREDICTION_HAD_BRANCHED) =/= input(BRANCH_COND_RESULT)
+ val imm = IMM(input(INSTRUCTION))
+ val missAlignedTarget = if(pipeline(RVC_GEN)) False else (input(BRANCH_COND_RESULT) && input(BRANCH_CTRL).mux(
+ BranchCtrlEnum.JALR -> (imm.i_sext(1) ^ input(RS1)(1)),
+ BranchCtrlEnum.JAL -> imm.j_sext(1),
+ default -> imm.b_sext(1)
+ ))
+
+ insert(BRANCH_DO) := input(PREDICTION_HAD_BRANCHED) =/= input(BRANCH_COND_RESULT) || missAlignedTarget
//Calculation of the branch target / correction
- val imm = IMM(input(INSTRUCTION))
val branch_src1,branch_src2 = UInt(32 bits)
switch(input(BRANCH_CTRL)){
is(BranchCtrlEnum.JALR){
@@ -230,11 +264,14 @@ class BranchPlugin(earlyBranch : Boolean,
}
default{
branch_src1 := input(PC)
- branch_src2 := (input(PREDICTION_HAD_BRANCHED) ? (if(pipeline(RVC_GEN)) Mux(input(IS_RVC), B(2), B(4)) else B(4)).resized | imm.b_sext).asUInt
+ branch_src2 := ((input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt
+ when(input(PREDICTION_HAD_BRANCHED) && ! missAlignedTarget){
+ branch_src2 := (if(pipeline(RVC_GEN)) Mux(input(IS_RVC), B(2), B(4)) else B(4)).asUInt.resized
+ }
}
}
val branchAdder = branch_src1 + branch_src2
- insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0))
+ insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0"
}
@@ -242,18 +279,20 @@ class BranchPlugin(earlyBranch : Boolean,
val branchStage = if(earlyBranch) execute else memory
branchStage plug new Area {
import branchStage._
- jumpInterface.valid := input(BRANCH_DO) && arbitration.isFiring
+ jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO)
jumpInterface.payload := input(BRANCH_CALC)
when(jumpInterface.valid) {
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
}
- if(catchAddressMisaligned) {
- val unalignedJump = input(BRANCH_DO) && (if(pipeline(RVC_GEN)) input(BRANCH_CALC)(0 downto 0) =/= 0 else input(BRANCH_CALC)(1 downto 0) =/= 0)
+ if(catchAddressMisalignedForReal) {
+ val unalignedJump = input(BRANCH_DO) && input(BRANCH_CALC)(1)
branchExceptionPort.valid := arbitration.isValid && unalignedJump
branchExceptionPort.code := 0
branchExceptionPort.badAddr := input(BRANCH_CALC) //pipeline.stages(pipeline.indexOf(branchStage)-1).input
+
+ if(branchStage == execute) branchExceptionPort.valid clearWhen(service(classOf[HazardService]).hazardOnExecuteRS)
}
}
@@ -271,6 +310,7 @@ class BranchPlugin(earlyBranch : Boolean,
//Do branch calculations (conditions + target PC)
object NEXT_PC extends Stageable(UInt(32 bits))
+ object TARGET_MISSMATCH extends Stageable(Bool)
execute plug new Area {
import execute._
@@ -298,8 +338,9 @@ class BranchPlugin(earlyBranch : Boolean,
).asUInt
val branchAdder = branch_src1 + branch_src2
- insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0))
+ insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "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)
}
//Apply branchs (JAL,JALR, Bxx)
@@ -307,7 +348,7 @@ class BranchPlugin(earlyBranch : Boolean,
branchStage plug new Area {
import branchStage._
- val predictionMissmatch = fetchPrediction.cmd.hadBranch =/= input(BRANCH_DO) || (input(BRANCH_DO) && fetchPrediction.cmd.targetPc =/= input(BRANCH_CALC))
+ val predictionMissmatch = fetchPrediction.cmd.hadBranch =/= input(BRANCH_DO) || (input(BRANCH_DO) && input(TARGET_MISSMATCH))
fetchPrediction.rsp.wasRight := ! predictionMissmatch
fetchPrediction.rsp.finalPc := input(BRANCH_CALC)
fetchPrediction.rsp.sourceLastWord := {
@@ -317,7 +358,7 @@ class BranchPlugin(earlyBranch : Boolean,
input(PC)
}
- jumpInterface.valid := arbitration.isFiring && predictionMissmatch //Probably just isValid instead of isFiring is better
+ jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && predictionMissmatch //Probably just isValid instead of isFiring is better
jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC))
@@ -325,10 +366,12 @@ class BranchPlugin(earlyBranch : Boolean,
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
}
- if(catchAddressMisaligned) {
- branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && (if(pipeline(RVC_GEN)) input(BRANCH_CALC)(0 downto 0) =/= 0 else input(BRANCH_CALC)(1 downto 0) =/= 0)
+ if(catchAddressMisalignedForReal) {
+ branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && input(BRANCH_CALC)(1)
branchExceptionPort.code := 0
branchExceptionPort.badAddr := input(BRANCH_CALC)
+
+ if(branchStage == execute) branchExceptionPort.valid clearWhen(service(classOf[HazardService]).hazardOnExecuteRS)
}
}
}
diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala
index 065c306..6ad56a6 100644
--- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala
@@ -4,6 +4,7 @@ import spinal.core._
import spinal.lib._
import vexriscv._
import vexriscv.Riscv._
+import vexriscv.plugin.IntAluPlugin.{ALU_BITWISE_CTRL, ALU_CTRL, AluBitwiseCtrlEnum, AluCtrlEnum}
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable
@@ -48,14 +49,29 @@ case class CsrPluginConfig(
mcycleAccess : CsrAccess,
minstretAccess : CsrAccess,
ucycleAccess : CsrAccess,
- wfiGen : Boolean,
+ wfiGenAsWait : Boolean,
ecallGen : Boolean,
+ mtvecModeGen : Boolean = false,
+ noCsrAlu : Boolean = false,
+ wfiGenAsNop : Boolean = false,
+ ebreakGen : Boolean = false,
+ supervisorGen : Boolean = false,
+ sscratchGen : Boolean = false,
+ stvecAccess : CsrAccess = CsrAccess.NONE,
+ sepcAccess : CsrAccess = CsrAccess.NONE,
+ scauseAccess : CsrAccess = CsrAccess.NONE,
+ sbadaddrAccess : CsrAccess = CsrAccess.NONE,
+ scycleAccess : CsrAccess = CsrAccess.NONE,
+ sinstretAccess : CsrAccess = CsrAccess.NONE,
+ satpAccess : CsrAccess = CsrAccess.NONE,
+ medelegAccess : CsrAccess = CsrAccess.NONE,
+ midelegAccess : CsrAccess = CsrAccess.NONE,
+ pipelineCsrRead : Boolean = false,
deterministicInteruptionEntry : Boolean = false //Only used for simulatation purposes
-
){
assert(!ucycleAccess.canWrite)
- def noException = this.copy(ecallGen = false, catchIllegalAccess = false)
+ def noException = this.copy(ecallGen = false, ebreakGen = false, catchIllegalAccess = false)
}
object CsrPluginConfig{
@@ -80,10 +96,42 @@ object CsrPluginConfig{
mcycleAccess = CsrAccess.READ_WRITE,
minstretAccess = CsrAccess.READ_WRITE,
ecallGen = true,
- wfiGen = true,
+ wfiGenAsWait = true,
ucycleAccess = CsrAccess.READ_ONLY
)
+ def all2(mtvecInit : BigInt) : CsrPluginConfig = CsrPluginConfig(
+ catchIllegalAccess = true,
+ mvendorid = 11,
+ marchid = 22,
+ mimpid = 33,
+ mhartid = 0,
+ misaExtensionsInit = 66,
+ misaAccess = CsrAccess.READ_WRITE,
+ mtvecAccess = CsrAccess.READ_WRITE,
+ mtvecInit = mtvecInit,
+ mepcAccess = CsrAccess.READ_WRITE,
+ mscratchGen = true,
+ mcauseAccess = CsrAccess.READ_WRITE,
+ mbadaddrAccess = CsrAccess.READ_WRITE,
+ mcycleAccess = CsrAccess.READ_WRITE,
+ minstretAccess = CsrAccess.READ_WRITE,
+ ecallGen = true,
+ wfiGenAsWait = true,
+ ucycleAccess = CsrAccess.READ_ONLY,
+ supervisorGen = true,
+ sscratchGen = true,
+ stvecAccess = CsrAccess.READ_WRITE,
+ sepcAccess = CsrAccess.READ_WRITE,
+ scauseAccess = CsrAccess.READ_WRITE,
+ sbadaddrAccess = CsrAccess.READ_WRITE,
+ scycleAccess = CsrAccess.READ_WRITE,
+ sinstretAccess = CsrAccess.READ_WRITE,
+ satpAccess = CsrAccess.READ_WRITE,
+ medelegAccess = CsrAccess.READ_WRITE,
+ midelegAccess = CsrAccess.READ_WRITE
+ )
+
def small(mtvecInit : BigInt) = CsrPluginConfig(
catchIllegalAccess = false,
mvendorid = null,
@@ -101,7 +149,7 @@ object CsrPluginConfig{
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
- wfiGen = false,
+ wfiGenAsWait = false,
ucycleAccess = CsrAccess.NONE
)
@@ -122,7 +170,7 @@ object CsrPluginConfig{
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
- wfiGen = false,
+ wfiGenAsWait = false,
ucycleAccess = CsrAccess.NONE
)
@@ -152,7 +200,8 @@ trait CsrInterface{
}
def rw(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) rw(csrAddress,that._1, that._2)
- def r [T <: Data](csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) r(csrAddress,that._1, that._2)
+ def w(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) w(csrAddress,that._1, that._2)
+ def r(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) r(csrAddress,that._1, that._2)
def rw[T <: Data](csrAddress : Int, that : T): Unit = rw(csrAddress,0,that)
def w[T <: Data](csrAddress : Int, that : T): Unit = w(csrAddress,0,that)
def r [T <: Data](csrAddress : Int, that : T): Unit = r(csrAddress,0,that)
@@ -178,10 +227,12 @@ trait IContextSwitching{
def isContextSwitching : Bool
}
-class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface{
+class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface{
import config._
import CsrAccess._
+ assert(!(wfiGenAsNop && wfiGenAsWait))
+
def xlen = 32
//Mannage ExceptionService calls
@@ -194,24 +245,25 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
}
var jumpInterface : Flow[UInt] = null
- var pluginExceptionPort : Flow[ExceptionCause] = null
- var timerInterrupt : Bool = null
- var externalInterrupt : Bool = null
- var privilege : Bits = null
+ var timerInterrupt, externalInterrupt : Bool = null
+ var timerInterruptS, externalInterruptS : Bool = null
+ var privilege : UInt = null
var selfException : Flow[ExceptionCause] = null
var contextSwitching : Bool = null
override def isContextSwitching = contextSwitching
object EnvCtrlEnum extends SpinalEnum(binarySequential){
- val NONE, EBREAK, MRET= newElement()
- val WFI = if(wfiGen) newElement() else null
+ val NONE, XRET = newElement()
+ val WFI = if(wfiGenAsWait) newElement() else null
val ECALL = if(ecallGen) newElement() else null
+ val EBREAK = if(ebreakGen) newElement() else null
}
object ENV_CTRL extends Stageable(EnvCtrlEnum())
object IS_CSR extends Stageable(Bool)
object CSR_WRITE_OPCODE extends Stageable(Bool)
object CSR_READ_OPCODE extends Stageable(Bool)
+ object PIPELINED_CSR_READ extends Stageable(Bits(32 bits))
var allowInterrupts : Bool = null
var allowException : Bool = null
@@ -233,16 +285,18 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
val defaultCsrActions = List[(Stageable[_ <: BaseType],Any)](
IS_CSR -> True,
REGFILE_WRITE_VALID -> True,
- BYPASSABLE_EXECUTE_STAGE -> True,
+ BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> True
- )
+ ) ++ (if(catchIllegalAccess) List(HAS_SIDE_EFFECT -> True) else Nil)
val nonImmediatActions = defaultCsrActions ++ List(
SRC1_CTRL -> Src1CtrlEnum.RS,
RS1_USE -> True
)
- val immediatActions = defaultCsrActions
+ val immediatActions = defaultCsrActions ++ List(
+ SRC1_CTRL -> Src1CtrlEnum.URS1
+ )
val decoderService = pipeline.service(classOf[DecoderService])
@@ -255,30 +309,31 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
CSRRWI -> immediatActions,
CSRRSI -> immediatActions,
CSRRCI -> immediatActions,
- // EBREAK -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.EBREAK)), //TODO
- MRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.MRET))
+ MRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET, HAS_SIDE_EFFECT -> True)),
+ SRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET, HAS_SIDE_EFFECT -> True))
))
- if(wfiGen) decoderService.add(WFI, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.WFI))
- if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL))
+ if(wfiGenAsWait) decoderService.add(WFI, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.WFI))
+ if(wfiGenAsNop) decoderService.add(WFI, Nil)
+ if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL, HAS_SIDE_EFFECT -> True))
+ if(ebreakGen) decoderService.add(EBREAK, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.EBREAK, HAS_SIDE_EFFECT -> True))
val pcManagerService = pipeline.service(classOf[JumpService])
- jumpInterface = pcManagerService.createJumpInterface(pipeline.writeBack)
+ jumpInterface = pcManagerService.createJumpInterface(pipeline.stages.last)
jumpInterface.valid := False
jumpInterface.payload.assignDontCare()
- if(ecallGen) {
- pluginExceptionPort = newExceptionPort(pipeline.execute)
- pluginExceptionPort.valid := False
- pluginExceptionPort.payload.assignDontCare()
- }
timerInterrupt = in Bool() setName("timerInterrupt")
externalInterrupt = in Bool() setName("externalInterrupt")
+ if(supervisorGen){
+ timerInterruptS = in Bool() setName("timerInterruptS")
+ externalInterruptS = in Bool() setName("externalInterruptS")
+ }
contextSwitching = Bool().setName("contextSwitching")
- privilege = RegInit(B"11")
+ privilege = RegInit(U"11").setName("CsrPlugin_privilege")
- if(catchIllegalAccess)
+ if(catchIllegalAccess || ecallGen || ebreakGen)
selfException = newExceptionPort(pipeline.execute)
allowInterrupts = True
@@ -295,31 +350,39 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
import pipeline.config._
val fetcher = service(classOf[IBusFetcher])
- pipeline plug new Area{
- //Define CSR mapping utilities
- implicit class CsrAccessPimper(csrAccess : CsrAccess){
- def apply(csrAddress : Int, thats : (Int, Data)*) : Unit = {
- if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrMapping.w(csrAddress,that._1, that._2)
- if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrMapping.r(csrAddress,that._1, that._2)
- }
- def apply(csrAddress : Int, that : Data) : Unit = {
- if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) csrMapping.w(csrAddress, 0, that)
- if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) csrMapping.r(csrAddress, 0, that)
- }
+ //Define CSR mapping utilities
+ implicit class CsrAccessPimper(csrAccess : CsrAccess){
+ def apply(csrAddress : Int, thats : (Int, Data)*) : Unit = {
+ if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrMapping.w(csrAddress,that._1, that._2)
+ if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrMapping.r(csrAddress,that._1, that._2)
}
+ def apply(csrAddress : Int, that : Data) : Unit = {
+ if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) csrMapping.w(csrAddress, 0, that)
+ if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) csrMapping.r(csrAddress, 0, that)
+ }
+ }
+ val machineCsr = pipeline plug new Area{
//Define CSR registers
+ // Status => MXR, SUM, TVM, TW, TSE ?
val misa = new Area{
val base = Reg(UInt(2 bits)) init(U"01") allowUnsetRegToAvoidLatch
val extensions = Reg(Bits(26 bits)) init(misaExtensionsInit) allowUnsetRegToAvoidLatch
}
- val mtvec = Reg(UInt(xlen bits)).allowUnsetRegToAvoidLatch
- if(mtvecInit != null) mtvec init(mtvecInit)
+
+
+ val mtvec = new Area{
+ val mode = Reg(Bits(2 bits)).allowUnsetRegToAvoidLatch
+ val base = Reg(UInt(xlen-2 bits)).allowUnsetRegToAvoidLatch
+ }
+
+ if(mtvecInit != null) mtvec.mode init(mtvecInit & 0x3)
+ if(mtvecInit != null) mtvec.base init(mtvecInit / 4)
val mepc = Reg(UInt(xlen bits))
val mstatus = new Area{
val MIE, MPIE = RegInit(False)
- val MPP = RegInit(B"11")
+ val MPP = RegInit(U"11")
}
val mip = new Area{
val MEIP = RegNext(externalInterrupt) init(False)
@@ -334,47 +397,155 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
val interrupt = Reg(Bool)
val exceptionCode = Reg(UInt(exceptionCodeWidth bits))
}
- val mbadaddr = Reg(UInt(xlen bits))
+ val mtval = Reg(UInt(xlen bits))
val mcycle = Reg(UInt(64 bits)) randBoot()
val minstret = Reg(UInt(64 bits)) randBoot()
- //Define CSR registers accessibility
+ val medeleg = Reg(Bits(32 bits)) init(0)
+ val mideleg = Reg(Bits(32 bits)) init(0)
+
if(mvendorid != null) READ_ONLY(CSR.MVENDORID, U(mvendorid))
if(marchid != null) READ_ONLY(CSR.MARCHID , U(marchid ))
if(mimpid != null) READ_ONLY(CSR.MIMPID , U(mimpid ))
if(mhartid != null) READ_ONLY(CSR.MHARTID , U(mhartid ))
+ misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions)
//Machine CSR
- misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions)
+ READ_WRITE(CSR.MSTATUS,11 -> mstatus.MPP, 7 -> mstatus.MPIE, 3 -> mstatus.MIE)
READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP)
READ_WRITE(CSR.MIP, 3 -> mip.MSIP)
READ_WRITE(CSR.MIE, 11 -> mie.MEIE, 7 -> mie.MTIE, 3 -> mie.MSIE)
- mtvecAccess(CSR.MTVEC, mtvec)
+ mtvecAccess(CSR.MTVEC, 2 -> mtvec.base, 0 -> mtvec.mode)
mepcAccess(CSR.MEPC, mepc)
- READ_WRITE(CSR.MSTATUS,11 -> mstatus.MPP, 7 -> mstatus.MPIE, 3 -> mstatus.MIE)
if(mscratchGen) READ_WRITE(CSR.MSCRATCH, mscratch)
mcauseAccess(CSR.MCAUSE, xlen-1 -> mcause.interrupt, 0 -> mcause.exceptionCode)
- mbadaddrAccess(CSR.MBADADDR, mbadaddr)
+ mbadaddrAccess(CSR.MBADADDR, mtval)
mcycleAccess(CSR.MCYCLE, mcycle(31 downto 0))
mcycleAccess(CSR.MCYCLEH, mcycle(63 downto 32))
minstretAccess(CSR.MINSTRET, minstret(31 downto 0))
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
+ medelegAccess(CSR.MEDELEG, medeleg)
+ midelegAccess(CSR.MIDELEG, mideleg)
+
//User CSR
ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0))
+ ucycleAccess(CSR.UCYCLEH, mcycle(31 downto 0))
+ }
+
+ val supervisorCsr = ifGen(supervisorGen) {
+ pipeline plug new Area {
+ val sstatus = new Area {
+ val SIE, SPIE = RegInit(False)
+ val SPP = RegInit(U"1")
+ }
+
+ val sip = new Area {
+ val SEIP = RegNext(externalInterruptS) init (False)
+ val STIP = RegNext(timerInterruptS) init (False)
+ val SSIP = RegInit(False)
+ }
+ val sie = new Area {
+ val SEIE, STIE, SSIE = RegInit(False)
+ }
+ val stvec = Reg(UInt(xlen bits)).allowUnsetRegToAvoidLatch
+ val sscratch = if (sscratchGen) Reg(Bits(xlen bits)) else null
+
+ val scause = new Area {
+ val interrupt = Reg(Bool)
+ val exceptionCode = Reg(UInt(exceptionCodeWidth bits))
+ }
+ val stval = Reg(UInt(xlen bits))
+ val sepc = Reg(UInt(xlen bits))
+ val satp = new Area {
+ val PPN = Reg(Bits(22 bits))
+ val ASID = Reg(Bits(9 bits))
+ val MODE = Reg(Bits(1 bits))
+ }
+
+ //Supervisor CSR
+ WRITE_ONLY(CSR.SSTATUS,8 -> sstatus.SPP, 5 -> sstatus.SPIE, 1 -> sstatus.SIE)
+ for(offset <- List(0, 0x200)) {
+ READ_ONLY(CSR.SSTATUS,8 -> sstatus.SPP, 5 -> sstatus.SPIE, 1 -> sstatus.SIE)
+ }
+ READ_ONLY(CSR.SIP, 9 -> sip.SEIP, 5 -> sip.STIP)
+ READ_WRITE(CSR.SIP, 1 -> sip.SSIP)
+ READ_WRITE(CSR.SIE, 9 -> sie.SEIE, 5 -> sie.STIE, 1 -> sie.SSIE)
+
+ stvecAccess(CSR.STVEC, stvec)
+ sepcAccess(CSR.SEPC, sepc)
+ if(sscratchGen) READ_WRITE(CSR.SSCRATCH, sscratch)
+ scauseAccess(CSR.SCAUSE, xlen-1 -> scause.interrupt, 0 -> scause.exceptionCode)
+ sbadaddrAccess(CSR.SBADADDR, stval)
+ satpAccess(CSR.SATP, 31 -> satp.MODE, 22 -> satp.ASID, 0 -> satp.PPN)
+ }
+ }
+ pipeline plug new Area{
+ import machineCsr._
+ import supervisorCsr._
+
+ val lastStage = pipeline.stages.last
+ val beforeLastStage = pipeline.stages(pipeline.stages.size-2)
+ val stagesFromExecute = pipeline.stages.dropWhile(_ != execute)
+
//Manage counters
mcycle := mcycle + 1
- when(writeBack.arbitration.isFiring) {
+ when(lastStage.arbitration.isFiring) {
minstret := minstret + 1
}
- val mepcCaptureStage = if(exceptionPortsInfos.nonEmpty) writeBack else decode
+ case class InterruptSource(cond : Bool, id : Int)
+ case class InterruptModel(privilege : Int, privilegeCond : Bool, sources : ArrayBuffer[InterruptSource])
+ val interruptModel = ArrayBuffer[InterruptModel]()
+ if(supervisorGen) interruptModel += InterruptModel(1, sstatus.SIE && privilege <= "01", ArrayBuffer(
+ InterruptSource(sip.STIP && sie.STIE, 5),
+ InterruptSource(sip.SSIP && sie.SSIE, 1),
+ InterruptSource(sip.SEIP && sie.SEIE, 9)
+ ))
+
+ interruptModel += InterruptModel(3, mstatus.MIE , ArrayBuffer(
+ InterruptSource(mip.MTIP && mie.MTIE, 7),
+ InterruptSource(mip.MSIP && mie.MSIE, 3),
+ InterruptSource(mip.MEIP && mie.MEIE, 11)
+ ))
+
+ case class DelegatorModel(value : Bits, source : Int, target : Int)
+ def solveDelegators(delegators : Seq[DelegatorModel], id : Int, lowerBound : Int): UInt = {
+ val filtredDelegators = delegators.filter(_.target >= lowerBound)
+ val ret = U(lowerBound, 2 bits)
+ for(d <- filtredDelegators){
+ when(!d.value(id)){
+ ret := d.source
+ }
+ }
+ ret
+ }
+
+ def solveDelegators(delegators : Seq[DelegatorModel], id : UInt, lowerBound : UInt): UInt = {
+ if(delegators.isEmpty) return CombInit(lowerBound)
+ val ret = U(delegators.last.target, 2 bits)
+ for(d <- delegators){
+ when(!d.value(id) || d.target < lowerBound){
+ ret := d.source
+ }
+ }
+ ret
+ }
+
+ val interruptDelegators = ArrayBuffer[DelegatorModel]()
+ if(midelegAccess.canWrite) interruptDelegators += DelegatorModel(mideleg,3, 1)
+
+ val exceptionDelegators = ArrayBuffer[DelegatorModel]()
+ if(medelegAccess.canWrite) exceptionDelegators += DelegatorModel(medeleg,3, 1)
+
+
+ val mepcCaptureStage = if(exceptionPortsInfos.nonEmpty) lastStage else decode
//Aggregate all exception port and remove required instructions
@@ -383,6 +554,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
val exceptionValids = Vec(stages.map(s => Bool().setPartialName(s.getName())))
val exceptionValidsRegs = Vec(stages.map(s => Reg(Bool).init(False).setPartialName(s.getName()))).allowUnsetRegToAvoidLatch
val exceptionContext = Reg(ExceptionCause())
+ val exceptionTargetPrivilege = solveDelegators(exceptionDelegators, exceptionContext.code, privilege)
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority)
@@ -405,60 +577,61 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
exceptionValids := exceptionValidsRegs
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
when(port.valid) {
-// if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True
+ if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True
stage.arbitration.removeIt := True
exceptionValids(stageId) := True
- when(!exceptionValidsRegs.takeRight(stages.length-stageId-1).fold(False)(_ || _)) {
- exceptionContext := port.payload
- }
+ exceptionContext := port.payload
}
}
for(stageId <- firstStageIndexWithExceptionPort until stages.length; stage = stages(stageId) ){
- when(stage.arbitration.isFlushed){
- exceptionValids(stageId) := False
- }
val previousStage = if(stageId == firstStageIndexWithExceptionPort) stage else stages(stageId-1)
when(!stage.arbitration.isStuck){
exceptionValidsRegs(stageId) := (if(stageId != firstStageIndexWithExceptionPort) exceptionValids(stageId-1) && !previousStage.arbitration.isStuck else False)
}otherwise{
- exceptionValidsRegs(stageId) := exceptionValids(stageId)
+ if(stage != stages.last)
+ exceptionValidsRegs(stageId) := exceptionValids(stageId)
+ else
+ exceptionValidsRegs(stageId) := False
}
+ if(stage != stages.last) when(stage.arbitration.isFlushed){
+ exceptionValids(stageId) := False
+ }
+ }
- if(stageId != 0){
- when(exceptionValidsRegs(stageId)){
- stages(stageId-1).arbitration.haltByOther := True
- }
- }
+ when(exceptionValidsRegs.orR){
+ fetcher.haltIt()
+// fetcher.flushIt()
}
} else null
- val interruptRequest = ((mip.MSIP && mie.MSIE) || (mip.MEIP && mie.MEIE) || (mip.MTIP && mie.MTIE)) && mstatus.MIE
- val interrupt = interruptRequest && allowInterrupts
- val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last && allowException else False
- val writeBackWasWfi = if(wfiGen) RegNext(writeBack.arbitration.isFiring && writeBack.input(ENV_CTRL) === EnvCtrlEnum.WFI) init(False) else False
+ val interrupt = False
+ val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
+ val interruptTargetPrivilege = UInt(2 bits).assignDontCare()
- val deteriministicLogic = if(deterministicInteruptionEntry) new Area{
- val counter = Reg(UInt(4 bits)) init(0)
- when(!interruptRequest || !mstatus.MIE){
- counter := 0
- } otherwise {
- when(counter < 6){
- when(writeBack.arbitration.isFiring){
- counter := counter + 1
- }
+ for(model <- interruptModel){
+ when(model.privilegeCond){
+ when(model.sources.map(_.cond).orR){
+ interrupt := True
}
- val counterPlusPending = counter + CountOne(stages.tail.map(_.arbitration.isValid))
- when(counterPlusPending < 6){
- inhibateInterrupts()
+ for(source <- model.sources){
+ when(source.cond){
+ interruptCode := source.id
+ interruptTargetPrivilege := solveDelegators(interruptDelegators, source.id, model.privilege)
+ }
}
}
}
+ interrupt.clearWhen(!allowInterrupts)
+
+ val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last && allowException else False
+ val lastStageWasWfi = if(wfiGenAsWait) RegNext(lastStage.arbitration.isFiring && lastStage.input(ENV_CTRL) === EnvCtrlEnum.WFI) init(False) else False
+
//Used to make the pipeline empty softly (for interrupts)
@@ -467,59 +640,94 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
decode.arbitration.haltByOther := True
}
- val done = !List(execute, memory, writeBack).map(_.arbitration.isValid).orR && fetcher.pcValid(mepcCaptureStage)
+ val done = !stagesFromExecute.map(_.arbitration.isValid).orR && fetcher.pcValid(mepcCaptureStage)
if(exceptionPortCtrl != null) done.clearWhen(exceptionPortCtrl.exceptionValidsRegs.tail.orR)
}
//Interrupt/Exception entry logic
- val interruptCode = ((mip.MEIP && mie.MEIE) ? U(11) | ((mip.MSIP && mie.MSIE) ? U(3) | U(7))).addTag(Verilator.public)
val interruptJump = Bool.addTag(Verilator.public)
interruptJump := interrupt && pipelineLiberator.done
+ val hadException = RegNext(exception) init(False)
+ pipelineLiberator.done.clearWhen(hadException)
+
+
+ val targetPrivilege = CombInit(interruptTargetPrivilege)
+ if(exceptionPortCtrl != null) when(hadException) {
+ targetPrivilege := exceptionPortCtrl.exceptionTargetPrivilege
+ }
+
+ val trapCause = CombInit(interruptCode)
+ if(exceptionPortCtrl != null) when( hadException){
+ trapCause := exceptionPortCtrl.exceptionContext.code
+ }
+
when(exception || interruptJump){
- jumpInterface.valid := True
- jumpInterface.payload := mtvec
- memory.arbitration.flushAll := True
- if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValidsRegs.last := False
- mstatus.MIE := False
- mstatus.MPIE := mstatus.MIE
- mstatus.MPP := privilege
- mepc := mepcCaptureStage.input(PC)
- mcause.interrupt := interruptJump
- mcause.exceptionCode := interruptCode
+ switch(privilege){
+ if(supervisorGen) is(1) {
+ sepc := mepcCaptureStage.input(PC)
+ }
+ is(3){
+ mepc := mepcCaptureStage.input(PC)
+ }
+ }
}
- when(RegNext(exception)){
- mbadaddr := (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.badAddr else U(0))
- mcause.exceptionCode := (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.code else U(0))
+ when(hadException || interruptJump){
+ jumpInterface.valid := True
+ jumpInterface.payload := (if(!mtvecModeGen) mtvec.base @@ "00" else (mtvec.mode === 0 || hadException) ? (mtvec.base @@ "00") | ((mtvec.base + trapCause) @@ "00") )
+ beforeLastStage.arbitration.flushAll := True
+
+ switch(targetPrivilege){
+ if(supervisorGen) is(1) {
+ sstatus.SIE := False
+ sstatus.SPIE := sstatus.SIE
+ sstatus.SPP := privilege(0 downto 0)
+ scause.interrupt := !hadException
+ scause.exceptionCode := trapCause
+ if (exceptionPortCtrl != null) {
+ stval := exceptionPortCtrl.exceptionContext.badAddr
+ }
+ }
+
+ is(3){
+ mstatus.MIE := False
+ mstatus.MPIE := mstatus.MIE
+ mstatus.MPP := privilege
+ mcause.interrupt := !hadException
+ mcause.exceptionCode := trapCause
+ if(exceptionPortCtrl != null) {
+ mtval := exceptionPortCtrl.exceptionContext.badAddr
+ }
+ }
+ }
}
+ lastStage plug new Area{
+ import lastStage._
- //Manage MRET instructions
- when(execute.arbitration.isValid && execute.input(ENV_CTRL) === EnvCtrlEnum.MRET) {
- when(memory.arbitration.isValid || writeBack.arbitration.isValid){
- execute.arbitration.haltItself := True
- } otherwise {
+ //Manage MRET / SRET instructions
+ when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
+ jumpInterface.payload := mepc
jumpInterface.valid := True
- jumpInterface.payload := mepc
- decode.arbitration.flushAll := True
- mstatus.MIE := mstatus.MPIE
- privilege := mstatus.MPP
+ beforeLastStage.arbitration.flushAll := True
+ switch(input(INSTRUCTION)(29 downto 28)){
+ is(3){
+ mstatus.MIE := mstatus.MPIE
+ mstatus.MPP := U"00"
+ mstatus.MPIE := True
+ privilege := mstatus.MPP
+ }
+ if(supervisorGen) is(1){
+ sstatus.SIE := sstatus.SPIE
+ sstatus.SPP := U"0"
+ sstatus.SPIE := True
+ privilege := U"0" @@ sstatus.SPP
+ }
+ }
}
}
- //Manage ECALL instructions
- if(ecallGen) when(execute.arbitration.isValid && execute.input(ENV_CTRL) === EnvCtrlEnum.ECALL){
- pluginExceptionPort.valid := True
- pluginExceptionPort.code := 11
- }
-
- //Manage WFI instructions
- if(wfiGen) when(execute.arbitration.isValid && execute.input(ENV_CTRL) === EnvCtrlEnum.WFI){
- when(!interrupt){
- execute.arbitration.haltItself := True
- }
- }
contextSwitching := jumpInterface.valid
@@ -533,41 +741,104 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|| (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0)
)
insert(CSR_READ_OPCODE) := input(INSTRUCTION)(13 downto 7) =/= B"0100000"
- //Assure that the CSR access are in the execute stage when there is nothing left in memory/writeback stages to avoid exception hazard
- arbitration.haltItself setWhen(arbitration.isValid && input(IS_CSR) && (execute.arbitration.isValid || memory.arbitration.isValid))
}
+
+
+ execute plug new Area{
+ import execute._
+ //Manage WFI instructions
+ if(wfiGenAsWait) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.WFI){
+ when(!interrupt){
+ arbitration.haltItself := True
+ }
+ }
+ }
+
+ decode.arbitration.haltByOther setWhen(stagesFromExecute.dropRight(1).map(s => s.arbitration.isValid && s.input(ENV_CTRL) === EnvCtrlEnum.XRET).asBits.orR)
+
execute plug new Area {
import execute._
+ def previousStage = decode
+ val blockedBySideEffects = stagesFromExecute.tail.map(s => s.arbitration.isValid).asBits().orR // && s.input(HAS_SIDE_EFFECT) to improve be less pessimistic
- val illegalAccess = arbitration.isValid && input(IS_CSR)
- if(catchIllegalAccess) {
- val illegalInstruction = arbitration.isValid && privilege === 0 && (input(ENV_CTRL) === EnvCtrlEnum.EBREAK || input(ENV_CTRL) === EnvCtrlEnum.MRET)
-
- selfException.valid := illegalAccess || illegalInstruction
- selfException.code := 2
+ val illegalAccess = True
+ val illegalInstruction = False
+ if(selfException != null) {
+ selfException.valid := False
+ selfException.code.assignDontCare()
selfException.badAddr.assignDontCare()
+ if(catchIllegalAccess) when(illegalAccess || illegalInstruction){
+ selfException.valid := True
+ selfException.code := 2
+ }
}
+ //Manage MRET / SRET instructions
+ when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
+ //TODO check MPP value too
+ when(input(INSTRUCTION)(29 downto 28).asUInt =/= privilege) {
+ illegalInstruction := True
+ }
+ }
+
+
+ //Manage ECALL instructions
+ if(ecallGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.ECALL){
+ selfException.valid := True
+ selfException.code := 11
+ }
+
+
+ if(ebreakGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.EBREAK){
+ selfException.valid := True
+ selfException.code := 3
+ }
+
+
val imm = IMM(input(INSTRUCTION))
- val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
+ def writeSrc = input(SRC1)
+ // val readDataValid = True
val readData = B(0, 32 bits)
- def readDataReg = memory.input(REGFILE_WRITE_DATA) //PIPE OPT
- val readDataRegValid = Reg(Bool) setWhen(arbitration.isValid) clearWhen(!arbitration.isStuck)
- val writeData = input(INSTRUCTION)(13).mux(
- False -> writeSrc,
- True -> Mux(input(INSTRUCTION)(12), readDataReg & ~writeSrc, readDataReg | writeSrc)
- )
-
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
+ val readEnable = readInstruction && ! blockedBySideEffects && !arbitration.isStuckByOthers// && !readDataRegValid
+ //arbitration.isStuckByOthers, in case of the hazardPlugin is in the executeStage
+
+
+// def readDataReg = memory.input(REGFILE_WRITE_DATA) //PIPE OPT
+// val readDataRegValid = Reg(Bool) setWhen(arbitration.isValid) clearWhen(!arbitration.isStuck)
+// val writeDataEnable = input(INSTRUCTION)(13) ? writeSrc | B"xFFFFFFFF"
+// val writeData = if(noCsrAlu) writeSrc else input(INSTRUCTION)(13).mux(
+// False -> writeSrc,
+// True -> Mux(input(INSTRUCTION)(12), ~writeSrc, writeSrc)
+// )
+ val writeData = if(noCsrAlu) writeSrc else input(INSTRUCTION)(13).mux(
+ False -> writeSrc,
+ True -> Mux(input(INSTRUCTION)(12), readData & ~writeSrc, readData | writeSrc)
+ )
+
+
+
+// arbitration.haltItself setWhen(writeInstruction && !readDataRegValid)
- arbitration.haltItself setWhen(writeInstruction && !readDataRegValid)
- val writeEnable = writeInstruction && readDataRegValid
- val readEnable = readInstruction && !readDataRegValid
when(arbitration.isValid && input(IS_CSR)) {
- output(REGFILE_WRITE_DATA) := readData
+ if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData
+ arbitration.haltItself setWhen(blockedBySideEffects)
}
+ if(pipelineCsrRead){
+ insert(PIPELINED_CSR_READ) := readData
+ when(memory.arbitration.isValid && memory.input(IS_CSR)) {
+ memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ)
+ }
+ }
+//
+// Component.current.rework{
+// when(arbitration.isFiring && input(IS_CSR)) {
+// memory.input(REGFILE_WRITE_DATA).getDrivingReg := readData
+// }
+// }
//Translation of the csrMapping into real logic
val csrAddress = input(INSTRUCTION)(csrRange)
@@ -608,7 +879,9 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
}
}
}
- illegalAccess setWhen(privilege.asUInt < csrAddress(9 downto 8).asUInt)
+
+ 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 0547c69..752552a 100644
--- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala
@@ -12,7 +12,7 @@ class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
override def build(pipeline: VexRiscv): Unit = {
super.build(pipeline)
- dBus.asDirectionLess()
+ dBus.setAsDirectionLess()
dAxi = master(dBus.toAxi4Shared().toAxi4()).setName("dAxi")
dBus = null //For safety, as nobody should use it anymore :)
}
@@ -53,7 +53,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
BYPASSABLE_MEMORY_STAGE -> False,
MEMORY_WR -> False,
MEMORY_MANAGMENT -> False
- )
+ ) ++ (if(catchSomething) List(HAS_SIDE_EFFECT -> True) else Nil)
val storeActions = stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.IMS,
diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala
index 102bbe9..3f4479c 100644
--- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala
+++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala
@@ -6,6 +6,7 @@ import spinal.lib._
import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
+import vexriscv.demo.SimpleBus
import vexriscv.ip.DataCacheMemCmd
@@ -131,11 +132,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
mm.read := cmdStage.valid && !cmdStage.wr
mm.write := cmdStage.valid && cmdStage.wr
mm.address := (cmdStage.address >> 2) @@ U"00"
- mm.writeData := cmdStage.size.mux (
- U(0) -> cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0),
- U(1) -> cmdStage.data(15 downto 0) ## cmdStage.data(15 downto 0),
- default -> cmdStage.data(31 downto 0)
- )
+ mm.writeData := cmdStage.data(31 downto 0)
mm.byteEnable := (cmdStage.size.mux (
U(0) -> B"0001",
U(1) -> B"0011",
@@ -179,13 +176,36 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
rsp.error := False //TODO
bus
}
+
+ def toSimpleBus() : SimpleBus = {
+ val bus = SimpleBus(32,32)
+ bus.cmd.valid := cmd.valid
+ bus.cmd.wr := cmd.wr
+ bus.cmd.address := cmd.address.resized
+ bus.cmd.data := cmd.data
+ bus.cmd.mask := cmd.size.mux(
+ 0 -> B"0001",
+ 1 -> B"0011",
+ default -> B"1111"
+ ) |<< cmd.address(1 downto 0)
+ cmd.ready := bus.cmd.ready
+
+ rsp.ready := bus.rsp.valid
+ rsp.data := bus.rsp.data
+
+ bus
+ }
}
-class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFault : Boolean = false, earlyInjection : Boolean = false) extends Plugin[VexRiscv]{
+class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
+ catchAccessFault : Boolean = false,
+ earlyInjection : Boolean = false, /*, idempotentRegions : (UInt) => Bool = (x) => False*/
+ emitCmdInMemoryStage : Boolean = false,
+ onlyLoadWords : Boolean = false) extends Plugin[VexRiscv]{
var dBus : DBusSimpleBus = null
-
+ assert(!(emitCmdInMemoryStage && earlyInjection))
object MEMORY_ENABLE extends Stageable(Bool)
object MEMORY_READ_DATA extends Stageable(Bits(32 bits))
@@ -193,9 +213,12 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
object ALIGNEMENT_FAULT extends Stageable(Bool)
var memoryExceptionPort : Flow[ExceptionCause] = null
+ var rspStage : Stage = null
+
override def setup(pipeline: VexRiscv): Unit = {
import Riscv._
import pipeline.config._
+ import pipeline._
val decoderService = pipeline.service(classOf[DecoderService])
@@ -211,7 +234,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> Bool(earlyInjection)
- )
+ ) ++ (if(catchAccessFault || catchAddressMisaligned) List(HAS_SIDE_EFFECT -> True) else Nil)
val storeActions = stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.IMS,
@@ -220,14 +243,16 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
decoderService.addDefault(MEMORY_ENABLE, False)
decoderService.add(
- List(LB, LH, LW, LBU, LHU, LWU).map(_ -> loadActions) ++
+ (if(onlyLoadWords) List(LW) else List(LB, LH, LW, LBU, LHU, LWU)).map(_ -> loadActions) ++
List(SB, SH, SW).map(_ -> storeActions)
)
+
+ rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory)
if(catchAccessFault || catchAddressMisaligned) {
val exceptionService = pipeline.service(classOf[ExceptionService])
- memoryExceptionPort = exceptionService.newExceptionPort(pipeline.memory)
+ memoryExceptionPort = exceptionService.newExceptionPort(rspStage)
}
}
@@ -237,9 +262,13 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
dBus = master(DBusSimpleBus()).setName("dBus")
+
//Emit dBus.cmd request
- execute plug new Area{
- import execute._
+ val cmdStage = if(emitCmdInMemoryStage) memory else execute
+ cmdStage plug new Area{
+ import cmdStage._
+
+ val cmdSent = if(rspStage == execute) RegInit(False) setWhen(dBus.cmd.fire) clearWhen(!execute.arbitration.isStuck) else False
insert(ALIGNEMENT_FAULT) := {
if (catchAddressMisaligned)
@@ -248,7 +277,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
False
}
- dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.removeIt && !input(ALIGNEMENT_FAULT)
+ dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.isFlushed && !input(ALIGNEMENT_FAULT) && !cmdSent
dBus.cmd.wr := input(INSTRUCTION)(5)
dBus.cmd.address := input(SRC_ADD).asUInt
dBus.cmd.size := input(INSTRUCTION)(13 downto 12).asUInt
@@ -257,7 +286,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0),
default -> input(RS2)(31 downto 0)
)
- when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !input(ALIGNEMENT_FAULT)){
+ when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !input(ALIGNEMENT_FAULT) && !cmdSent){
arbitration.haltItself := True
}
@@ -276,8 +305,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
}
//Collect dBus.rsp read responses
- memory plug new Area {
- import memory._
+ rspStage plug new Area {
+ val s = rspStage; import s._
insert(MEMORY_READ_DATA) := dBus.rsp.data
@@ -298,18 +327,19 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
memoryExceptionPort.valid := True
}
}
- when(!(arbitration.isValid && input(MEMORY_ENABLE))){
+ when(!(arbitration.isValid && input(MEMORY_ENABLE) && (if(cmdStage == rspStage) !arbitration.isStuckByOthers else True))){
memoryExceptionPort.valid := False
}
+
memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt //Drived by IntAluPlugin
}
- assert(!(dBus.rsp.ready && input(MEMORY_ENABLE) && arbitration.isValid && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")
+ if(rspStage != execute) assert(!(dBus.rsp.ready && input(MEMORY_ENABLE) && arbitration.isValid && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")
}
//Reformat read responses, REGFILE_WRITE_DATA overriding
- val injectionStage = if(earlyInjection) memory else writeBack
+ val injectionStage = if(earlyInjection) memory else stages.last
injectionStage plug new Area {
import injectionStage._
@@ -329,10 +359,10 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
)
when(arbitration.isValid && input(MEMORY_ENABLE)) {
- output(REGFILE_WRITE_DATA) := rspFormated
+ output(REGFILE_WRITE_DATA) := (if(!onlyLoadWords) rspFormated else input(MEMORY_READ_DATA))
}
- if(!earlyInjection)
+ if(!earlyInjection && !emitCmdInMemoryStage && config.withWriteBackStage)
assert(!(arbitration.isValid && input(MEMORY_ENABLE) && !input(INSTRUCTION)(5) && arbitration.isStuck),"DBusSimplePlugin doesn't allow writeback stage stall when read happend")
//formal
diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala
index a91348a..7d28b24 100644
--- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala
@@ -96,7 +96,7 @@ case class DebugExtensionIo() extends Bundle with IMasterSlave{
-class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
+class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount : Int = 0) extends Plugin[VexRiscv] {
var io : DebugExtensionIo = null
val injectionAsks = ArrayBuffer[(Stage, Bool)]()
@@ -104,6 +104,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
object IS_EBREAK extends Stageable(Bool)
+ object DO_EBREAK extends Stageable(Bool)
override def setup(pipeline: VexRiscv): Unit = {
import Riscv._
import pipeline.config._
@@ -113,15 +114,18 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(IS_EBREAK, False)
- decoderService.add(EBREAK,List(
- IS_EBREAK -> True,
- SRC_USE_SUB_LESS -> False,
- SRC1_CTRL -> Src1CtrlEnum.RS, // Zero
- SRC2_CTRL -> Src2CtrlEnum.PC,
- ALU_CTRL -> AluCtrlEnum.ADD_SUB //Used to get the PC value in busReadDataReg
- ))
+ decoderService.add(EBREAK,List(IS_EBREAK -> True))
injectionPort = pipeline.service(classOf[IBusFetcher]).getInjectionPort()
+
+ if(pipeline.serviceExist(classOf[ReportService])){
+ val report = pipeline.service(classOf[ReportService])
+ report.add("debug" -> {
+ val e = new DebugReport()
+ e.hardwareBreakpointCount = hardwareBreakpointCount
+ e
+ })
+ }
}
@@ -141,6 +145,11 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
val isPipBusy = isPipActive || RegNext(isPipActive)
val haltedByBreak = RegInit(False)
+ val hardwareBreakpoints = Vec(Reg(new Bundle{
+ val valid = Bool()
+ val pc = UInt(31 bits)
+ }), hardwareBreakpointCount)
+ hardwareBreakpoints.foreach(_.valid init(False))
val busReadDataReg = Reg(Bits(32 bit))
when(writeBack.arbitration.isValid) {
@@ -160,8 +169,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
injectionPort.payload := io.bus.cmd.data
when(io.bus.cmd.valid) {
- switch(io.bus.cmd.address(2 downto 2)) {
- is(0) {
+ switch(io.bus.cmd.address(7 downto 2)) {
+ is(0x0) {
when(io.bus.cmd.wr) {
stepIt := io.bus.cmd.data(4)
resetIt setWhen (io.bus.cmd.data(16)) clearWhen (io.bus.cmd.data(24))
@@ -169,45 +178,31 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
haltedByBreak clearWhen (io.bus.cmd.data(25))
}
}
- is(1) {
+ is(0x1) {
when(io.bus.cmd.wr) {
injectionPort.valid := True
io.bus.cmd.ready := injectionPort.ready
}
}
+ for(i <- 0 until hardwareBreakpointCount){
+ is(0x10 + i){
+ when(io.bus.cmd.wr){
+ hardwareBreakpoints(i).assignFromBits(io.bus.cmd.data)
+ }
+ }
+ }
}
}
-
-
-// Component.current.addPrePopTask(() => {
-// //Check if the decode instruction is driven by a register
-// val instructionDriver = try {decode.input(INSTRUCTION).getDrivingReg} catch { case _ : Throwable => null}
-// if(instructionDriver != null){ //If yes =>
-// //Insert the instruction by writing the "fetch to decode instruction register",
-// // Work even if it need to cross some hierarchy (caches)
-// instructionDriver.component.rework {
-// when(insertDecodeInstruction.pull()) {
-// instructionDriver := io.bus.cmd.data.pull()
-// }
-// }
-// } else{
-// //Insert the instruction via a mux in the decode stage
-// when(RegNext(insertDecodeInstruction)){
-// decode.input(INSTRUCTION) := RegNext(io.bus.cmd.data)
-// }
-// }
-// })
-//
-
- when(execute.input(IS_EBREAK)){
- when(execute.arbitration.isValid ) {
+ decode.insert(DO_EBREAK) := !haltIt && (decode.input(IS_EBREAK) || hardwareBreakpoints.map(hb => hb.valid && hb.pc === (execute.input(PC) >> 1)).foldLeft(False)(_ || _))
+ when(execute.arbitration.isValid && execute.input(DO_EBREAK)){
+ execute.arbitration.haltByOther := True
+ busReadDataReg := execute.input(PC).asBits
+ when(List(memory, writeBack).map(_.arbitration.isValid).orR === False){
iBusFetcher.flushIt()
iBusFetcher.haltIt()
- decode.arbitration.flushAll := True
- }
- when(execute.arbitration.isFiring) {
+ execute.arbitration.flushAll := True
haltIt := True
haltedByBreak := True
}
@@ -215,7 +210,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
when(haltIt) {
iBusFetcher.haltIt()
-// decode.arbitration.haltByOther := True
}
when(stepIt && iBusFetcher.incoming()) {
diff --git a/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala
index ad33efc..3d60498 100644
--- a/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala
+++ b/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala
@@ -151,7 +151,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
import toplevel.config._
toplevel.getAllIo.foreach{io =>
if(io.isInput) io.assignDontCare()
- io.asDirectionLess()
+ io.setAsDirectionLess()
}
toplevel.decode.input(INSTRUCTION).removeAssignments()
toplevel.decode.input(INSTRUCTION) := Delay((in Bits(32 bits)).setName("instruction"),2)
diff --git a/src/main/scala/vexriscv/plugin/ExternalInterruptArrayPlugin.scala b/src/main/scala/vexriscv/plugin/ExternalInterruptArrayPlugin.scala
index ee200ea..fd1a561 100644
--- a/src/main/scala/vexriscv/plugin/ExternalInterruptArrayPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/ExternalInterruptArrayPlugin.scala
@@ -14,7 +14,7 @@ class ExternalInterruptArrayPlugin(arrayWidth : Int = 32, maskCsrId : Int = 0xBC
val csr = pipeline.service(classOf[CsrPlugin])
val mask = Reg(Bits(arrayWidth bits)) init(0)
val pendings = mask & RegNext(externalInterruptArray)
- csr.externalInterrupt.asDirectionLess() := pendings.orR
+ csr.externalInterrupt.setAsDirectionLess() := pendings.orR
csr.rw(maskCsrId, mask)
csr.r(pendingsCsrId, pendings)
}
diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala
index 5584ab2..27a22e0 100644
--- a/src/main/scala/vexriscv/plugin/Fetcher.scala
+++ b/src/main/scala/vexriscv/plugin/Fetcher.scala
@@ -11,14 +11,13 @@ import scala.collection.mutable.ArrayBuffer
//TODO val killLastStage = jump.pcLoad.valid || decode.arbitration.isRemoved
// DBUSSimple check memory halt execute optimization
-abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
- val resetVector : BigInt,
+abstract class IBusFetcherImpl(val resetVector : BigInt,
val keepPcPlus4 : Boolean,
val decodePcGen : Boolean,
val compressedGen : Boolean,
val cmdToRspStageCount : Int,
+ val pcRegReusedForSecondStage : Boolean,
val injectorReadyCutGen : Boolean,
- val relaxedPcCalculation : Boolean,
val prediction : BranchPrediction,
val historyRamSizeLog2 : Int,
val injectorStage : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{
@@ -28,11 +27,11 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
var dynamicTargetFailureCorrection : Flow[UInt] = null
var externalResetVector : UInt = null
assert(cmdToRspStageCount >= 1)
- assert(!(cmdToRspStageCount == 1 && !injectorStage))
+// assert(!(cmdToRspStageCount == 1 && !injectorStage))
assert(!(compressedGen && !decodePcGen))
var fetcherHalt : Bool = null
var fetcherflushIt : Bool = null
- lazy val pcValids = Vec(Bool, 4)
+ var pcValids : Vec[Bool] = null
def pcValid(stage : Stage) = pcValids(pipeline.indexOf(stage))
var incomingInstruction : Bool = null
override def incoming() = incomingInstruction
@@ -51,6 +50,7 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
case class JumpInfo(interface : Flow[UInt], stage: Stage, priority : Int)
val jumpInfos = ArrayBuffer[JumpInfo]()
override def createJumpInterface(stage: Stage, priority : Int = 0): Flow[UInt] = {
+ assert(stage != null)
val interface = Flow(UInt(32 bits))
jumpInfos += JumpInfo(interface,stage, priority)
interface
@@ -62,9 +62,6 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
fetcherHalt = False
fetcherflushIt = False
incomingInstruction = False
- if(catchAccessFault) {
- val exceptionService = pipeline.service(classOf[ExceptionService])
- }
if(resetVector == null) externalResetVector = in(UInt(32 bits).setName("externalResetVector"))
pipeline(RVC_GEN) = compressedGen
@@ -82,6 +79,8 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
}
}
}
+
+ pcValids = Vec(Bool, pipeline.stages.size)
}
@@ -111,46 +110,26 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits)))
}
- val fetchPc = if(relaxedPcCalculation) new PcFetch {
- //PC calculation without Jump
- val pcReg = Reg(UInt(32 bits)) init(if(resetVector != null) resetVector else externalResetVector) addAttribute(Verilator.public)
-
- val pcPlus4 = pcReg + 4
- if (keepPcPlus4) KeepAttribute(pcPlus4)
- when(preOutput.fire) {
- pcReg := pcPlus4
- }
-
- //Realign
- if(compressedGen){
- when(preOutput.fire){
- pcReg(1 downto 0) := 0
- }
- }
-
- preOutput.valid := RegNext(True) init (False) // && !jump.pcLoad.valid
- preOutput.payload := pcReg
-
- //application of the selected jump request
- if(predictionPcLoad != null) {
- when(predictionPcLoad.valid) {
- pcReg := predictionPcLoad.payload
- preOutput.valid := False
- }
- }
- when(jump.pcLoad.valid) {
- pcReg := jump.pcLoad.payload
- }
-
-
- } else new PcFetch{
+ val fetchPc = new PcFetch{
//PC calculation without Jump
val pcReg = Reg(UInt(32 bits)) init(if(resetVector != null) resetVector else externalResetVector) addAttribute(Verilator.public)
val inc = RegInit(False)
+ val propagatePc = False
val pc = pcReg + (inc ## B"00").asUInt
val samplePcNext = False
+ if(compressedGen) {
+ when(inc) {
+ pc(1) := False
+ }
+ }
+
+ when(propagatePc){
+ samplePcNext := True
+ inc := False
+ }
+
if(predictionPcLoad != null) {
when(predictionPcLoad.valid) {
inc := False
@@ -175,17 +154,12 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
pcReg := pc
}
- if(compressedGen) {
- when(preOutput.fire) {
- pcReg(1 downto 0) := 0
- when(pc(1)){
- inc := True
- }
- }
- }
+ pc(0) := False
+ if(!pipeline(RVC_GEN)) pc(1) := False
preOutput.valid := RegNext(True) init (False)
preOutput.payload := pc
+
}
val decodePc = ifGen(decodePcGen)(new Area {
@@ -216,14 +190,6 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
})
-// val iBusCmd = new Area {
-// def input = fetchPc.output
-//
-// // ...
-//
-// val output = Stream(UInt(32 bits))
-// }
-
case class FetchRsp() extends Bundle {
val pc = UInt(32 bits)
val rsp = IBusSimpleRsp()
@@ -232,22 +198,57 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
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) {
- // val doFlush = if(i == cmdToRspStageCount- 1 && ???) killLastStage else flush
- inputPipeline(i) << {i match {
- case 0 => input.m2sPipeWithFlush(flush, relaxedPcCalculation, collapsBubble = false)
- case _ => inputPipeline(i-1).haltWhen(inputPipelineHalt(i-1)).m2sPipeWithFlush(flush,collapsBubble = false)
- }}
+// 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 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
+ })
+
+ stages(0).input << fetchPc.output
+ stages(0).inputSample := True
+ for(s <- stages) {
+ s.halt := False
+ s.output << s.input.haltWhen(s.halt)
}
+ for((s,sNext) <- (stages, stages.tail).zipped) {
+ if(s == stages.head && pcRegReusedForSecondStage) {
+ sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false))
+ sNext.input.payload := fetchPc.pcReg
+ fetchPc.propagatePc setWhen(sNext.input.fire)
+ } else {
+ sNext.input << s.output.m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false)
+ }
+ }
+
+//
+// val pipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount + 1)
+// val halts = Vec(False, cmdToRspStageCount)
+// for(i <- 0 until cmdToRspStageCount + 1) {
+// pipeline(i) << {i match {
+// case 0 => pipeline(0) << fetchPc.output.haltWhen(halts(i))
+// case 1 => pipeline(1).m2sPipeWithFlush(flush, false, collapsBubble = false)
+// case _ => inputPipeline(i-1).haltWhen(inputPipelineHalt(i-1)).m2sPipeWithFlush(flush,collapsBubble = false)
+// }}
+// }
+
// ...
val readyForError = True
val output = Stream(FetchRsp())
- incomingInstruction setWhen(inputPipeline.map(_.valid).orR)
+ incomingInstruction setWhen(stages.tail.map(_.input.valid).reduce(_ || _))
}
val decompressor = ifGen(decodePcGen)(new Area{
@@ -322,15 +323,13 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
}).tail
}
- val nextPcCalc = if (decodePcGen) {
- val valids = pcUpdatedGen(True, False :: List(execute, memory, writeBack).map(_.arbitration.isStuck), true)
- pcValids := Vec(valids.takeRight(4))
+ val stagesFromExecute = stages.dropWhile(_ != execute).toList
+ val nextPcCalc = if (decodePcGen) new Area{
+ val valids = pcUpdatedGen(True, False :: stagesFromExecute.map(_.arbitration.isStuck), true)
+ pcValids := Vec(valids.takeRight(stages.size))
} else new Area{
- val valids = pcUpdatedGen(True, iBusRsp.inputPipeline.map(!_.ready) ++ (if (injectorStage) List(!decodeInput.ready) else Nil) ++ List(execute, memory, writeBack).map(_.arbitration.isStuck), relaxedPcCalculation)
- if(relaxedPcCalculation && fetchPrediction != null) when(fetchPc.predictionPcLoad.valid){
- valids(0).getDrivingReg := False
- }
- pcValids := Vec(valids.takeRight(4))
+ val valids = pcUpdatedGen(True, iBusRsp.stages.tail.map(!_.input.ready) ++ (if (injectorStage) List(!decodeInput.ready) else Nil) ++ stagesFromExecute.map(_.arbitration.isStuck), false)
+ pcValids := Vec(valids.takeRight(stages.size))
}
val decodeRemoved = RegInit(False) setWhen(decode.arbitration.isRemoved) clearWhen(flush) //!decode.arbitration.isStuck || decode.arbitration.isFlushed
@@ -426,7 +425,7 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
}
def stage1ToInjectorPipe[T <: Data](input : T): (T,T) ={
- val iBusRspContext = iBusRsp.inputPipeline.tail.foldLeft(input)((data,stream) => RegNextWhen(data, stream.ready))
+ 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
@@ -450,8 +449,8 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
val historyCache = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
val historyWrite = historyCache.writePort
- val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.inputPipeline(0).ready)
- val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.inputPipeline(0).payload >> 2).resized
+ val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready)
+ val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(0).input.payload >> 2).resized
case class DynamicContext() extends Bundle{
val hazard = Bool
@@ -459,7 +458,7 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
}
val fetchContext = DynamicContext()
fetchContext.hazard := hazard
- fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.inputPipeline(0).ready || flush)
+ fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || flush)
object PREDICTION_CONTEXT extends Stageable(DynamicContext())
decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2
@@ -509,8 +508,8 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
val historyWrite = history.writePort
- val line = history.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.inputPipeline(0).ready || flush)
- val hit = line.source === (iBusRsp.inputPipeline(0).payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.inputPipeline(0).payload(1))) else True)
+ val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || flush)
+ 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){
@@ -518,9 +517,10 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
}
//Avoid write to read hazard
- val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.inputPipeline(0).ready)
- val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.inputPipeline(0).payload >> 2).resized
- fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.inputPipeline(0).fire //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1))
+ 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.fire //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1))
fetchPc.predictionPcLoad.payload := line.target
case class PredictionResult() extends Bundle{
diff --git a/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala b/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala
index e65aaec..5a8f4d3 100644
--- a/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala
@@ -7,11 +7,18 @@ import spinal.lib._
class HazardPessimisticPlugin() extends Plugin[VexRiscv] {
import Riscv._
+
+ override def setup(pipeline: VexRiscv): Unit = {
+ import pipeline.config._
+ val decoderService = pipeline.service(classOf[DecoderService])
+ decoderService.addDefault(HAS_SIDE_EFFECT, False)
+ }
+
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
- val writesInPipeline = List(execute,memory,writeBack).map(s => s.arbitration.isValid && s.input(REGFILE_WRITE_VALID)) :+ RegNext(writeBack.arbitration.isValid && writeBack.input(REGFILE_WRITE_VALID))
- decode.arbitration.haltItself.setWhen(decode.arbitration.isValid && writesInPipeline.orR)
+ val writesInPipeline = stages.dropWhile(_ != execute).map(s => s.arbitration.isValid && s.input(REGFILE_WRITE_VALID)) :+ RegNext(stages.last.arbitration.isValid && stages.last.input(REGFILE_WRITE_VALID))
+ decode.arbitration.haltByOther.setWhen(decode.arbitration.isValid && writesInPipeline.orR)
}
}
diff --git a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala
index cb013b8..c051aa0 100644
--- a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala
+++ b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala
@@ -4,6 +4,9 @@ import vexriscv._
import spinal.core._
import spinal.lib._
+trait HazardService{
+ def hazardOnExecuteRS : Bool
+}
class HazardSimplePlugin(bypassExecute : Boolean = false,
bypassMemory: Boolean = false,
@@ -11,26 +14,40 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
bypassWriteBackBuffer : Boolean = false,
pessimisticUseSrc : Boolean = false,
pessimisticWriteRegFile : Boolean = false,
- pessimisticAddressMatch : Boolean = false) extends Plugin[VexRiscv] {
+ pessimisticAddressMatch : Boolean = false) extends Plugin[VexRiscv] with HazardService{
import Riscv._
+
+
+ def hazardOnExecuteRS = {
+ if(pipeline.service(classOf[RegFileService]).readStage() == pipeline.execute) pipeline.execute.arbitration.isStuckByOthers else False
+ }
+
+ override def setup(pipeline: VexRiscv): Unit = {
+ import pipeline.config._
+ val decoderService = pipeline.service(classOf[DecoderService])
+ decoderService.addDefault(HAS_SIDE_EFFECT, False) //TODO implement it in each plugin
+ }
+
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
val src0Hazard = False
val src1Hazard = False
+ val readStage = service(classOf[RegFileService]).readStage()
+
def trackHazardWithStage(stage : Stage,bypassable : Boolean, runtimeBypassable : Stageable[Bool]): Unit ={
val runtimeBypassableValue = if(runtimeBypassable != null) stage.input(runtimeBypassable) else True
- val addr0Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === decode.input(INSTRUCTION)(rs1Range)
- val addr1Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === decode.input(INSTRUCTION)(rs2Range)
+ val addr0Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs1Range)
+ val addr1Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs2Range)
when(stage.arbitration.isValid && stage.input(REGFILE_WRITE_VALID)) {
if (bypassable) {
when(runtimeBypassableValue) {
when(addr0Match) {
- decode.input(RS1) := stage.output(REGFILE_WRITE_DATA)
+ readStage.input(RS1) := stage.output(REGFILE_WRITE_DATA)
}
when(addr1Match) {
- decode.input(RS2) := stage.output(REGFILE_WRITE_DATA)
+ readStage.input(RS2) := stage.output(REGFILE_WRITE_DATA)
}
}
}
@@ -52,20 +69,20 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
val address = Bits(5 bits)
val data = Bits(32 bits)
}))
- writeBackWrites.valid := writeBack.output(REGFILE_WRITE_VALID) && writeBack.arbitration.isFiring
- writeBackWrites.address := writeBack.output(INSTRUCTION)(rdRange)
- writeBackWrites.data := writeBack.output(REGFILE_WRITE_DATA)
+ writeBackWrites.valid := stages.last.output(REGFILE_WRITE_VALID) && stages.last.arbitration.isFiring
+ writeBackWrites.address := stages.last.output(INSTRUCTION)(rdRange)
+ writeBackWrites.data := stages.last.output(REGFILE_WRITE_DATA)
val writeBackBuffer = writeBackWrites.stage()
- val addr0Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === decode.input(INSTRUCTION)(rs1Range)
- val addr1Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === decode.input(INSTRUCTION)(rs2Range)
+ val addr0Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === readStage.input(INSTRUCTION)(rs1Range)
+ val addr1Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === readStage.input(INSTRUCTION)(rs2Range)
when(writeBackBuffer.valid) {
if (bypassWriteBackBuffer) {
when(addr0Match) {
- decode.input(RS1) := writeBackBuffer.data
+ readStage.input(RS1) := writeBackBuffer.data
}
when(addr1Match) {
- decode.input(RS2) := writeBackBuffer.data
+ readStage.input(RS2) := writeBackBuffer.data
}
} else {
when(addr0Match) {
@@ -77,22 +94,29 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
}
}
- trackHazardWithStage(writeBack,bypassWriteBack,null)
- trackHazardWithStage(memory ,bypassMemory ,BYPASSABLE_MEMORY_STAGE)
- trackHazardWithStage(execute ,bypassExecute ,BYPASSABLE_EXECUTE_STAGE)
+ if(withWriteBackStage) trackHazardWithStage(writeBack,bypassWriteBack,null)
+ if(withMemoryStage) trackHazardWithStage(memory ,bypassMemory ,BYPASSABLE_MEMORY_STAGE)
+ if(readStage != execute) trackHazardWithStage(execute ,bypassExecute , if(stages.last == execute) null else BYPASSABLE_EXECUTE_STAGE)
if(!pessimisticUseSrc) {
- when(!decode.input(RS1_USE)) {
+ when(!readStage.input(RS1_USE)) {
src0Hazard := False
}
- when(!decode.input(RS2_USE)) {
+ when(!readStage.input(RS2_USE)) {
src1Hazard := False
}
}
- when(decode.arbitration.isValid && (src0Hazard || src1Hazard)){
- decode.arbitration.haltItself := True
+ when(readStage.arbitration.isValid && (src0Hazard || src1Hazard)){
+ readStage.arbitration.haltByOther := True
}
}
}
+
+
+class NoHazardPlugin extends Plugin[VexRiscv] with HazardService {
+ override def build(pipeline: VexRiscv): Unit = {}
+
+ def hazardOnExecuteRS = False
+}
\ No newline at end of file
diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala
index 187e95c..66348f4 100644
--- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala
@@ -18,19 +18,19 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
config : InstructionCacheConfig,
memoryTranslatorPortConfig : Any = null,
injectorStage : Boolean = false) extends IBusFetcherImpl(
- catchAccessFault = config.catchAccessFault,
resetVector = resetVector,
keepPcPlus4 = keepPcPlus4,
decodePcGen = compressedGen,
compressedGen = compressedGen,
- cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1),
+ cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1) + (if(relaxedPcCalculation) 1 else 0),
+ pcRegReusedForSecondStage = true,
injectorReadyCutGen = false,
- relaxedPcCalculation = relaxedPcCalculation,
prediction = prediction,
historyRamSizeLog2 = historyRamSizeLog2,
injectorStage = !config.twoCycleCache || injectorStage){
import config._
+
var iBus : InstructionCacheMemBus = null
var mmuBus : MemoryTranslatorBus = null
var privilegeService : PrivilegeService = null
@@ -99,18 +99,20 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus")
iBus <> cache.io.mem
iBus.cmd.address.allowOverride := cache.io.mem.cmd.address // - debugAddressOffset
-
+
+ val stageOffset = if(relaxedPcCalculation) 1 else 0
+ def stages = iBusRsp.stages.drop(stageOffset)
//Connect prefetch cache side
- cache.io.cpu.prefetch.isValid := fetchPc.output.valid
- cache.io.cpu.prefetch.pc := fetchPc.output.payload
- iBusRsp.input << fetchPc.output.haltWhen(cache.io.cpu.prefetch.haltIt)
+ cache.io.cpu.prefetch.isValid := stages(0).input.valid
+ cache.io.cpu.prefetch.pc := stages(0).input.payload
+ stages(0).halt setWhen(cache.io.cpu.prefetch.haltIt)
cache.io.cpu.fetch.isRemoved := flush
val iBusRspOutputHalt = False
if (mmuBus != null) {
cache.io.cpu.fetch.mmuBus <> mmuBus
- (if(twoCycleCache) iBusRsp.inputPipelineHalt(0) else iBusRspOutputHalt) setWhen(mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss)
+ (if(twoCycleCache) stages(1).halt else iBusRspOutputHalt) setWhen(mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss)
} else {
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
@@ -123,15 +125,15 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
}
//Connect fetch cache side
- cache.io.cpu.fetch.isValid := iBusRsp.inputPipeline(0).valid
- cache.io.cpu.fetch.isStuck := !iBusRsp.inputPipeline(0).ready
- cache.io.cpu.fetch.pc := iBusRsp.inputPipeline(0).payload
+ cache.io.cpu.fetch.isValid := stages(1).input.valid
+ cache.io.cpu.fetch.isStuck := !stages(1).input.ready
+ cache.io.cpu.fetch.pc := stages(1).input.payload
if(twoCycleCache){
- cache.io.cpu.decode.isValid := iBusRsp.inputPipeline(1).valid
- cache.io.cpu.decode.isStuck := !iBusRsp.inputPipeline(1).ready
- cache.io.cpu.decode.pc := iBusRsp.inputPipeline(1).payload
+ cache.io.cpu.decode.isValid := stages(2).input.valid
+ cache.io.cpu.decode.isStuck := !stages(2).input.ready
+ cache.io.cpu.decode.pc := stages(2).input.payload
cache.io.cpu.decode.isUser := (if (privilegeService != null) privilegeService.isUser(decode) else False)
if((!twoCycleRam || wayCount == 1) && !compressedGen && !injectorStage){
@@ -145,7 +147,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
// val missHalt = cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss
val cacheRsp = if(twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch
- val cacheRspArbitration = iBusRsp.inputPipeline(if(twoCycleCache) 1 else 0)
+ val cacheRspArbitration = stages(if(twoCycleCache) 2 else 1)
var issueDetected = False
val redoFetch = False //RegNext(False) init(False)
when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected){
@@ -174,58 +176,19 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
}
}
-
- iBusRsp.output.arbitrationFrom(cacheRspArbitration.haltWhen(issueDetected || iBusRspOutputHalt))
+ cacheRspArbitration.halt setWhen(issueDetected || iBusRspOutputHalt)
+ iBusRsp.output.arbitrationFrom(cacheRspArbitration.output)
iBusRsp.output.rsp.inst := cacheRsp.data
- iBusRsp.output.pc := cacheRspArbitration.payload
+ iBusRsp.output.pc := cacheRspArbitration.output.payload
-// if (dataOnDecode) {
-// decode.insert(INSTRUCTION) := cache.io.cpu.decode.data
-// } else {
-// iBusRsp.outputBeforeStage.arbitrationFrom(iBusRsp.inputPipeline(0))
-// iBusRsp.outputBeforeStage.rsp.inst := cache.io.cpu.fetch.data
-// iBusRsp.outputBeforeStage.pc := iBusRsp.inputPipeline(0).payload
-// }
-//
-// cache.io.cpu.decode.pc := injector.inputBeforeHalt.pc
-//
-// val ownDecode = pipeline.plugins.filter(_.isInstanceOf[InstructionInjector]).foldLeft(True)(_ && !_.asInstanceOf[InstructionInjector].isInjecting(decode))
-// cache.io.cpu.decode.isValid := decode.arbitration.isValid && ownDecode
-// cache.io.cpu.decode.isStuck := !injector.inputBeforeHalt.ready
-// cache.io.cpu.decode.isUser := (if (privilegeService != null) privilegeService.isUser(decode) else False)
-// // cache.io.cpu.decode.pc := decode.input(PC)
-//
-// redoBranch.valid := decode.arbitration.isValid && ownDecode && cache.io.cpu.decode.cacheMiss && !cache.io.cpu.decode.mmuMiss && !cache.io.cpu.decode.illegalAccess
-// redoBranch.payload := decode.input(PC)
-// when(redoBranch.valid) {
-// decode.arbitration.redoIt := True
-// decode.arbitration.flushAll := True
-// }
-
- // val redo = RegInit(False) clearWhen(decode.arbitration.isValid) setWhen(redoBranch.valid)
- // when(redoBranch.valid || redo){
- // service(classOf[InterruptionInhibitor]).inhibateInterrupts()
- // }
-
-// if (catchSomething) {
-// val accessFault = if (catchAccessFault) cache.io.cpu.decode.error else False
-// val mmuMiss = if (catchMemoryTranslationMiss) cache.io.cpu.decode.mmuMiss else False
-// val illegalAccess = if (catchIllegalAccess) cache.io.cpu.decode.illegalAccess else False
-
-// decodeExceptionPort.valid := decode.arbitration.isValid && ownDecode && (accessFault || mmuMiss || illegalAccess)
-// decodeExceptionPort.code := mmuMiss ? U(14) | 1
-// decodeExceptionPort.badAddr := decode.input(PC)
-// }
-
- memory plug new Area {
-
- import memory._
+ val flushStage = if(memory != null) memory else execute
+ flushStage plug new Area {
+ import flushStage._
cache.io.flush.cmd.valid := False
when(arbitration.isValid && input(FLUSH_ALL)) {
cache.io.flush.cmd.valid := True
- decode.arbitration.flushAll := True
when(!cache.io.flush.cmd.ready) {
arbitration.haltItself := True
diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala
index 523a2ef..756d372 100644
--- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala
+++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala
@@ -6,6 +6,7 @@ import spinal.lib._
import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
+import vexriscv.demo.SimpleBus
@@ -62,7 +63,7 @@ object IBusSimpleBus{
}
-case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMasterSlave {
+case class IBusSimpleBus(interfaceKeepData : Boolean = false) extends Bundle with IMasterSlave {
var cmd = Stream(IBusSimpleCmd())
var rsp = Flow(IBusSimpleRsp())
@@ -135,6 +136,18 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
bus
}
+ def toSimpleBus(): SimpleBus = {
+ val bus = SimpleBus(32,32)
+ bus.cmd.arbitrationFrom(cmd)
+ bus.cmd.address := cmd.pc.resized
+ bus.cmd.wr := False
+ bus.cmd.mask.assignDontCare()
+ bus.cmd.data.assignDontCare()
+ rsp.valid := bus.rsp.valid
+ rsp.inst := bus.rsp.payload.data
+ rsp.error := False
+ bus
+ }
}
@@ -143,8 +156,9 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
class IBusSimplePlugin(resetVector : BigInt,
+ cmdForkOnSecondStage : Boolean,
+ cmdForkPersistence : Boolean,
catchAccessFault : Boolean = false,
- relaxedPcCalculation : Boolean = false,
prediction : BranchPrediction = NONE,
historyRamSizeLog2 : Int = 10,
keepPcPlus4 : Boolean = false,
@@ -152,24 +166,23 @@ class IBusSimplePlugin(resetVector : BigInt,
busLatencyMin : Int = 1,
pendingMax : Int = 7,
injectorStage : Boolean = true,
- relaxedBusCmdValid : Boolean = false
+ rspHoldValue : Boolean = false,
+ singleInstructionPipeline : Boolean = false
) extends IBusFetcherImpl(
- catchAccessFault = catchAccessFault,
resetVector = resetVector,
keepPcPlus4 = keepPcPlus4,
decodePcGen = compressedGen,
compressedGen = compressedGen,
- cmdToRspStageCount = busLatencyMin,
+ cmdToRspStageCount = busLatencyMin + (if(cmdForkOnSecondStage) 1 else 0),
+ pcRegReusedForSecondStage = !(cmdForkOnSecondStage && cmdForkPersistence),
injectorReadyCutGen = false,
- relaxedPcCalculation = relaxedPcCalculation,
prediction = prediction,
historyRamSizeLog2 = historyRamSizeLog2,
injectorStage = injectorStage){
- assert(!(prediction == DYNAMIC_TARGET && relaxedBusCmdValid), "IBusSimplePlugin doesn't allow dynamic_target prediction and relaxedBusCmdValid together")
- assert(!relaxedBusCmdValid)
var iBus : IBusSimpleBus = null
var decodeExceptionPort : Flow[ExceptionCause] = null
+ if(rspHoldValue) assert(busLatencyMin <= 1)
override def setup(pipeline: VexRiscv): Unit = {
super.setup(pipeline)
@@ -186,60 +199,75 @@ class IBusSimplePlugin(resetVector : BigInt,
import pipeline.config._
pipeline plug new FetchArea(pipeline) {
+ var cmd = Stream(IBusSimpleCmd())
+ iBus.cmd << (if(cmdForkPersistence && !cmdForkOnSecondStage) cmd.s2mPipe() else cmd)
//Avoid sending to many iBus cmd
val pendingCmd = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
- val pendingCmdNext = pendingCmd + iBus.cmd.fire.asUInt - iBus.rsp.fire.asUInt
+ val pendingCmdNext = pendingCmd + cmd.fire.asUInt - iBus.rsp.fire.asUInt
pendingCmd := pendingCmdNext
- val cmd = if(relaxedBusCmdValid) new Area {
- assert(relaxedPcCalculation, "relaxedBusCmdValid can only be used with relaxedPcCalculation")
- def input = fetchPc.output
- def output = iBusRsp.input
-
- val fork = StreamForkVex(input, 2, flush)
- val busFork = fork(0)
- val pipFork = fork(1)
- output << pipFork
-
- val okBus = pendingCmd =/= pendingMax
- iBus.cmd.valid := busFork.valid && okBus
- iBus.cmd.pc := busFork.payload(31 downto 2) @@ "00"
- busFork.ready := iBus.cmd.ready && okBus
- } else new Area {
- def input = fetchPc.output
- def output = iBusRsp.input
-
- output << input.continueWhen(iBus.cmd.fire)
-
- iBus.cmd.valid := input.valid && output.ready && pendingCmd =/= pendingMax
- iBus.cmd.pc := input.payload(31 downto 2) @@ "00"
+ val cmdFork = if(!cmdForkPersistence || !cmdForkOnSecondStage) new Area {
+ //This implementation keep the cmd on the bus until it's executed or the the pipeline is flushed
+ def stage = iBusRsp.stages(if(cmdForkOnSecondStage) 1 else 0)
+ 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
+ }
+ cmd.pc := stage.input.payload(31 downto 2) @@ "00"
+ } else new Area{
+ //This implementation keep the cmd on the bus until it's executed, even if the pipeline is flushed
+ def stage = iBusRsp.stages(1)
+ val pendingFull = pendingCmd === pendingMax
+ val cmdKeep = RegInit(False) setWhen(cmd.valid) 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
+ cmd.pc := stage.input.payload(31 downto 2) @@ "00"
}
-
- val rsp = new Area {
+ 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(flush) {
- discardCounter := (if(relaxedPcCalculation) pendingCmdNext else pendingCmd - iBus.rsp.fire.asUInt)
+ if(cmdForkOnSecondStage && cmdForkPersistence)
+ 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 = StreamFifoLowLatency(IBusSimpleRsp(), cmdToRspStageCount + (if(relaxedBusCmdValid) 1 else 0))
- rspBuffer.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
- rspBuffer.io.flush := flush
+ val rspBuffer = if(!rspHoldValue) new Area{
+ val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0))
+ c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
+ c.io.flush := flush
+ 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 fetchRsp = FetchRsp()
- fetchRsp.pc := inputPipeline.last.payload
- fetchRsp.rsp := rspBuffer.io.pop.payload
- fetchRsp.rsp.error.clearWhen(!rspBuffer.io.pop.valid) //Avoid interference with instruction injection from the debug plugin
+ 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
var issueDetected = False
- val join = StreamJoin(Seq(inputPipeline.last, rspBuffer.io.pop), fetchRsp)
- inputPipeline.last.ready setWhen(!inputPipeline.last.valid)
+ val join = Stream(FetchRsp())
+ join.valid := stages.last.output.valid && rspBufferOutput.valid
+ join.payload := fetchRsp
+ stages.last.output.ready := stages.last.output.valid ? join.fire | join.ready
+ rspBufferOutput.ready := join.fire
output << join.haltWhen(issueDetected)
if(catchAccessFault){
diff --git a/src/main/scala/vexriscv/plugin/IntAluPlugin.scala b/src/main/scala/vexriscv/plugin/IntAluPlugin.scala
index 2610aac..1b7467e 100644
--- a/src/main/scala/vexriscv/plugin/IntAluPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/IntAluPlugin.scala
@@ -84,10 +84,10 @@ class IntAluPlugin extends Plugin[VexRiscv]{
import execute._
val bitwise = input(ALU_BITWISE_CTRL).mux(
- AluBitwiseCtrlEnum.AND -> (input(SRC1) & input(SRC2)),
- AluBitwiseCtrlEnum.OR -> (input(SRC1) | input(SRC2)),
- AluBitwiseCtrlEnum.XOR -> (input(SRC1) ^ input(SRC2)),
- AluBitwiseCtrlEnum.SRC1 -> input(SRC1)
+ AluBitwiseCtrlEnum.AND -> (input(SRC1) & input(SRC2)),
+ AluBitwiseCtrlEnum.OR -> (input(SRC1) | input(SRC2)),
+ AluBitwiseCtrlEnum.XOR -> (input(SRC1) ^ input(SRC2)),
+ AluBitwiseCtrlEnum.SRC1 -> input(SRC1)
)
// mux results
diff --git a/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala b/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala
index 4c72131..db31022 100644
--- a/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala
@@ -129,6 +129,7 @@ class MemoryTranslatorPlugin(tlbSize : Int,
}
//Manage TLBW0 and TLBW1 instructions
+ //TODO not exception safe (sideeffect)
execute plug new Area{
import execute._
val tlbWriteBuffer = Reg(UInt(20 bits))
diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala
index 71a519e..f366854 100644
--- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala
+++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala
@@ -4,12 +4,23 @@ import spinal.core._
import spinal.lib._
import vexriscv.{VexRiscv, _}
-class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mulUnrollFactor : Int = 1, divUnrollFactor : Int = 1) extends Plugin[VexRiscv]{
+object MulDivIterativePlugin{
object IS_MUL extends Stageable(Bool)
object IS_DIV extends Stageable(Bool)
object IS_REM extends Stageable(Bool)
object IS_RS1_SIGNED extends Stageable(Bool)
object IS_RS2_SIGNED extends Stageable(Bool)
+ object FAST_DIV_VALID extends Stageable(Bool)
+ object FAST_DIV_VALUE extends Stageable(UInt(4 bits))
+}
+
+class MulDivIterativePlugin(genMul : Boolean = true,
+ genDiv : Boolean = true,
+ mulUnrollFactor : Int = 1,
+ divUnrollFactor : Int = 1,
+ dhrystoneOpt : Boolean = false,
+ customMul : (UInt, UInt, Stage, VexRiscv) => Area = null) extends Plugin[VexRiscv]{
+ import MulDivIterativePlugin._
override def setup(pipeline: VexRiscv): Unit = {
import Riscv._
@@ -67,7 +78,7 @@ class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mu
val accumulator = Reg(UInt(65 bits))
- val mul = ifGen(genMul) (new Area{
+ val mul = ifGen(genMul) (if(customMul != null) customMul(rs1,rs2,memory,pipeline) else new Area{
assert(isPow2(mulUnrollFactor))
val counter = Counter(32 / mulUnrollFactor + 1)
val done = counter.willOverflowIfInc
@@ -82,6 +93,9 @@ class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mu
}
output(REGFILE_WRITE_DATA) := ((input(INSTRUCTION)(13 downto 12) === B"00") ? accumulator(31 downto 0) | accumulator(63 downto 32)).asBits
}
+ when(!arbitration.isStuck) {
+ counter.clear()
+ }
})
@@ -95,7 +109,7 @@ class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mu
val needRevert = Reg(Bool)
val counter = Counter(32 / divUnrollFactor + 2)
- val done = counter.willOverflowIfInc
+ val done = Reg(Bool) setWhen(counter === counter.end-1) clearWhen(!arbitration.isStuck)
val result = Reg(Bits(32 bits))
when(arbitration.isValid && input(IS_DIV)){
when(!done){
@@ -125,6 +139,11 @@ class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mu
}
output(REGFILE_WRITE_DATA) := result
+// when(input(INSTRUCTION)(13 downto 12) === "00" && counter === 0 && rs2 =/= 0 && rs1 < 16 && rs2 < 16 && !input(RS1).msb && !input(RS2).msb) {
+// output(REGFILE_WRITE_DATA) := B(rs1(3 downto 0) / rs2(3 downto 0)).resized
+// counter.willIncrement := False
+// arbitration.haltItself := False
+// }
}
})
@@ -139,10 +158,20 @@ class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mu
rs1 := twoComplement(rs1Extended, rs1NeedRevert).resized
rs2 := twoComplement(execute.input(RS2), rs2NeedRevert)
- if(genMul) mul.counter.clear()
- if(genDiv) div.needRevert := rs1NeedRevert ^ (rs2NeedRevert && !execute.input(INSTRUCTION)(13))
+ if(genDiv) div.needRevert := (rs1NeedRevert ^ (rs2NeedRevert && !execute.input(INSTRUCTION)(13))) && !(execute.input(RS2) === 0 && execute.input(IS_RS2_SIGNED) && !execute.input(INSTRUCTION)(13))
if(genDiv) div.counter.clear()
}
+
+ 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_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
+ }
+ when(input(FAST_DIV_VALID)) {
+ output(REGFILE_WRITE_DATA) := B(0, 28 bits) ## input(FAST_DIV_VALUE)
+ }
+ }
}
}
}
diff --git a/src/main/scala/vexriscv/plugin/NoPipeliningPlugin.scala b/src/main/scala/vexriscv/plugin/NoPipeliningPlugin.scala
new file mode 100644
index 0000000..b4ad22b
--- /dev/null
+++ b/src/main/scala/vexriscv/plugin/NoPipeliningPlugin.scala
@@ -0,0 +1,23 @@
+package vexriscv.plugin
+
+import spinal.core._
+import spinal.lib._
+import vexriscv._
+
+
+class NoPipeliningPlugin() extends Plugin[VexRiscv] {
+
+ override def setup(pipeline: VexRiscv): Unit = {
+ import pipeline.config._
+ val decoderService = pipeline.service(classOf[DecoderService])
+ decoderService.addDefault(HAS_SIDE_EFFECT, False)
+ }
+
+ override def build(pipeline: VexRiscv): Unit = {
+ import pipeline._
+ import pipeline.config._
+
+ val writesInPipeline = stages.dropWhile(_ != execute).map(s => s.arbitration.isValid && s.input(REGFILE_WRITE_VALID)) :+ RegNext(stages.last.arbitration.isValid && stages.last.input(REGFILE_WRITE_VALID))
+ decode.arbitration.haltByOther.setWhen(stagesFromExecute.map(_.arbitration.isValid).orR)
+ }
+}
diff --git a/src/main/scala/vexriscv/plugin/RegFilePlugin.scala b/src/main/scala/vexriscv/plugin/RegFilePlugin.scala
index c1a4409..8bc561d 100644
--- a/src/main/scala/vexriscv/plugin/RegFilePlugin.scala
+++ b/src/main/scala/vexriscv/plugin/RegFilePlugin.scala
@@ -11,10 +11,18 @@ trait RegFileReadKind
object ASYNC extends RegFileReadKind
object SYNC extends RegFileReadKind
-class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = false, writeRfInMemoryStage : Boolean = false) extends Plugin[VexRiscv]{
+
+class RegFilePlugin(regFileReadyKind : RegFileReadKind,
+ zeroBoot : Boolean = false,
+ x0Init : Boolean = true,
+ writeRfInMemoryStage : Boolean = false,
+ readInExecute : Boolean = false,
+ syncUpdateOnStall : Boolean = true,
+ withShadow : Boolean = false //shadow registers aren't transition hazard free
+ ) extends Plugin[VexRiscv] with RegFileService{
import Riscv._
- assert(!writeRfInMemoryStage)
+ override def readStage(): Stage = if(readInExecute) pipeline.execute else pipeline.decode
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
@@ -28,32 +36,50 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals
import pipeline._
import pipeline.config._
+ val readStage = if(readInExecute) execute else decode
+ val writeStage = if(writeRfInMemoryStage) memory else stages.last
+
val global = pipeline plug new Area{
- val regFile = Mem(Bits(32 bits),32) addAttribute(Verilator.public)
- if(zeroBoot) regFile.init(List.fill(32)(B(0, 32 bits)))
+ val regFileSize = if(withShadow) 64 else 32
+ val regFile = Mem(Bits(32 bits),regFileSize) addAttribute(Verilator.public)
+ if(zeroBoot) regFile.init(List.fill(regFileSize)(B(0, 32 bits)))
+
+ val shadow = ifGen(withShadow)(new Area{
+ val write, read, clear = RegInit(False)
+
+ read clearWhen(clear && !readStage.arbitration.isStuck)
+ write clearWhen(clear && !writeStage.arbitration.isStuck)
+
+ val csrService = pipeline.service(classOf[CsrInterface])
+ csrService.w(0x7C0,2 -> clear, 1 -> read, 0 -> write)
+ })
+ }
+
+ //Disable rd0 write in decoding stage
+ when(decode.input(INSTRUCTION)(rdRange) === 0) {
+ decode.input(REGFILE_WRITE_VALID) := False
}
//Read register file
- decode plug new Area{
- import decode._
-
- //Disable rd0 write in decoding stage
- when(decode.input(INSTRUCTION)(rdRange) === 0) {
- decode.input(REGFILE_WRITE_VALID) := False
- }
+ readStage plug new Area{
+ import readStage._
//read register file
val srcInstruction = regFileReadyKind match{
case `ASYNC` => input(INSTRUCTION)
- case `SYNC` => input(INSTRUCTION_ANTICIPATED)
+ case `SYNC` if !readInExecute => input(INSTRUCTION_ANTICIPATED)
+ case `SYNC` if readInExecute => if(syncUpdateOnStall) Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) else decode.input(INSTRUCTION)
}
- val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt
- val regFileReadAddress2 = srcInstruction(Riscv.rs2Range).asUInt
+ def shadowPrefix(that : Bits) = if(withShadow) global.shadow.read ## that else that
+ val regFileReadAddress1 = U(shadowPrefix(srcInstruction(Riscv.rs1Range)))
+ val regFileReadAddress2 = U(shadowPrefix(srcInstruction(Riscv.rs2Range)))
val (rs1Data,rs2Data) = regFileReadyKind match{
case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2))
- case `SYNC` => (global.regFile.readSync(regFileReadAddress1),global.regFile.readSync(regFileReadAddress2))
+ case `SYNC` =>
+ val enable = if(!syncUpdateOnStall) !readStage.arbitration.isStuck else null
+ (global.regFile.readSync(regFileReadAddress1, enable),global.regFile.readSync(regFileReadAddress2, enable))
}
insert(RS1) := rs1Data
@@ -61,18 +87,29 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals
}
//Write register file
- (if(writeRfInMemoryStage) memory else writeBack) plug new Area {
- import writeBack._
+ writeStage plug new Area {
+ import writeStage._
+ def shadowPrefix(that : Bits) = if(withShadow) global.shadow.write ## that else that
val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public)
regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring
- regFileWrite.address := output(INSTRUCTION)(rdRange).asUInt
+ regFileWrite.address := U(shadowPrefix(output(INSTRUCTION)(rdRange)))
regFileWrite.data := output(REGFILE_WRITE_DATA)
//CPU will initialise constant register zero in the first cycle
- regFileWrite.valid setWhen(RegNext(False) init(True))
- inputInit[Bits](REGFILE_WRITE_DATA, 0)
- inputInit[Bits](INSTRUCTION, 0)
+ if(x0Init) {
+ val boot = RegNext(False) init (True)
+ regFileWrite.valid setWhen (boot)
+ if (writeStage != execute) {
+ inputInit[Bits](REGFILE_WRITE_DATA, 0)
+ inputInit[Bits](INSTRUCTION, 0)
+ } else {
+ when(boot) {
+ regFileWrite.address := 0
+ regFileWrite.data := 0
+ }
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/src/main/scala/vexriscv/plugin/ShiftPlugins.scala b/src/main/scala/vexriscv/plugin/ShiftPlugins.scala
index 4f34847..086528d 100644
--- a/src/main/scala/vexriscv/plugin/ShiftPlugins.scala
+++ b/src/main/scala/vexriscv/plugin/ShiftPlugins.scala
@@ -26,7 +26,7 @@ class FullBarrelShifterPlugin(earlyInjection : Boolean = false) extends Plugin[V
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection),
BYPASSABLE_MEMORY_STAGE -> True,
- RS1_USE -> True
+ RS1_USE -> True
)
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
@@ -35,8 +35,8 @@ class FullBarrelShifterPlugin(earlyInjection : Boolean = false) extends Plugin[V
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection),
BYPASSABLE_MEMORY_STAGE -> True,
- RS1_USE -> True,
- RS2_USE -> True
+ RS1_USE -> True,
+ RS2_USE -> True
)
val decoderService = pipeline.service(classOf[DecoderService])
@@ -152,7 +152,8 @@ class LightShifterPlugin extends Plugin[VexRiscv]{
val isShift = input(SHIFT_CTRL) =/= ShiftCtrlEnum.DISABLE
val amplitudeReg = Reg(UInt(5 bits))
val amplitude = isActive ? amplitudeReg | input(SRC2)(4 downto 0).asUInt
- val shiftInput = isActive ? memory.input(REGFILE_WRITE_DATA) | input(SRC1)
+ val shiftReg = ifGen(!withMemoryStage) (RegNextWhen(execute.output(REGFILE_WRITE_DATA), !arbitration.isStuckByOthers))
+ val shiftInput = isActive ? (if(withMemoryStage) memory.input(REGFILE_WRITE_DATA) else shiftReg) | input(SRC1)
val done = amplitude(4 downto 1) === 0
diff --git a/src/main/scala/vexriscv/plugin/SrcPlugin.scala b/src/main/scala/vexriscv/plugin/SrcPlugin.scala
index da9b151..395c0a7 100644
--- a/src/main/scala/vexriscv/plugin/SrcPlugin.scala
+++ b/src/main/scala/vexriscv/plugin/SrcPlugin.scala
@@ -4,7 +4,7 @@ import vexriscv.{RVC_GEN, Riscv, VexRiscv}
import spinal.core._
-class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean = false) extends Plugin[VexRiscv]{
+class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean = false, decodeAddSub : Boolean = false) extends Plugin[VexRiscv]{
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
@@ -16,7 +16,8 @@ class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean =
insert(SRC1) := input(SRC1_CTRL).mux(
Src1CtrlEnum.RS -> output(RS1),
Src1CtrlEnum.PC_INCREMENT -> (if(pipeline(RVC_GEN)) Mux(input(IS_RVC), B(2), B(4)) else B(4)).resized,
- Src1CtrlEnum.IMU -> imm.u.resized
+ Src1CtrlEnum.IMU -> imm.u.resized,
+ Src1CtrlEnum.URS1 -> input(INSTRUCTION)(Riscv.rs1Range).resized
)
insert(SRC2) := input(SRC2_CTRL).mux(
Src2CtrlEnum.RS -> output(RS2),
@@ -26,9 +27,10 @@ class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean =
)
}
+ val addSubStage = if(decodeAddSub) decode else execute
if(separatedAddSub) {
- execute plug new Area {
- import execute._
+ addSubStage plug new Area {
+ import addSubStage._
// ADD, SUB
val add = (input(SRC1).asUInt + input(SRC2).asUInt).asBits.addAttribute("keep")
@@ -44,8 +46,8 @@ class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean =
insert(SRC_LESS) := less
}
}else{
- execute plug new Area {
- import execute._
+ addSubStage plug new Area {
+ import addSubStage._
// ADD, SUB
val addSub = (input(SRC1).asSInt + Mux(input(SRC_USE_SUB_LESS), ~input(SRC2), input(SRC2)).asSInt + Mux(input(SRC_USE_SUB_LESS), S(1), S(0))).asBits
diff --git a/src/test/cpp/regression/.cproject b/src/test/cpp/regression/.cproject
index ba579f7..736b123 100644
--- a/src/test/cpp/regression/.cproject
+++ b/src/test/cpp/regression/.cproject
@@ -1,11 +1,8 @@
-
-
-
-
-
+
+
@@ -16,6 +13,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -98,40 +124,177 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/test/cpp/regression/.gitignore b/src/test/cpp/regression/.gitignore
index b37f733..576890f 100644
--- a/src/test/cpp/regression/.gitignore
+++ b/src/test/cpp/regression/.gitignore
@@ -1,2 +1,3 @@
*.regTraceRef
/freertos.gtkw
+*.cproject
diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp
index 40478de..ab9fab6 100644
--- a/src/test/cpp/regression/main.cpp
+++ b/src/test/cpp/regression/main.cpp
@@ -301,6 +301,7 @@ public:
status.mpie = status.mie;
mepc = pc;
pcWrite(mtvec.base << 2);
+ if(interrupt) livenessInterrupt = 0;
//status.MPP := privilege
}
@@ -333,7 +334,35 @@ public:
*csrPtr(csr) = value;
}
+
+ int livenessStep = 0;
+ int livenessInterrupt = 0;
+ virtual void liveness(bool mIntTimer, bool mIntExt){
+ livenessStep++;
+ bool interruptRequest = (mie.mtie && mIntTimer);
+ if(interruptRequest){
+ if(status.mie){
+ livenessInterrupt++;
+ }
+ } else {
+ livenessInterrupt = 0;
+ }
+
+ if(livenessStep > 1000){
+ cout << "Liveness step failure" << endl;
+ fail();
+ }
+
+ if(livenessInterrupt > 1000){
+ cout << "Liveness interrupt failure" << endl;
+ fail();
+ }
+
+ }
+
+
virtual void step() {
+ livenessStep = 0;
#define rd32 ((i >> 7) & 0x1F)
#define iBits(lo, len) ((i >> lo) & ((1 << len)-1))
#define iBitsSigned(lo, len) int32_t(i) << (32-lo-len) >> (32-len)
@@ -379,7 +408,11 @@ public:
case 0x37:rfWrite(rd32, i & 0xFFFFF000);pcWrite(pc + 4);break; // LUI
case 0x17:rfWrite(rd32, (i & 0xFFFFF000) + pc);pcWrite(pc + 4);break; //AUIPC
case 0x6F:rfWrite(rd32, pc + 4);pcWrite(pc + (iBits(21, 10) << 1) + (iBits(20, 1) << 11) + (iBits(12, 8) << 12) + (iSign() << 20));break; //JAL
- case 0x67:rfWrite(rd32, pc + 4);pcWrite((i32_rs1 + i32_i_imm) & ~1);break; //JALR
+ case 0x67:{
+ uint32_t target = (i32_rs1 + i32_i_imm) & ~1;
+ rfWrite(rd32, pc + 4);
+ pcWrite(target);
+ } break; //JALR
case 0x63:
switch ((i >> 12) & 0x7) {
case 0x0:if (i32_rs1 == i32_rs2)pcWrite(pc + i32_sb_imm);else pcWrite(pc + 4);break;
@@ -652,6 +685,7 @@ public:
ws->iBusAccessPatch(address,data,&error);
}
virtual bool dRead(int32_t address, int32_t size, uint32_t *data){
+ if(address & (size-1) != 0) cout << "Ref did a unaligned read" << endl;
if((address & 0xF0000000) == 0xF0000000){
MemRead t = periphRead.front();
if(t.address != address || t.size != size){
@@ -664,6 +698,7 @@ public:
}
}
virtual void dWrite(int32_t address, int32_t size, uint32_t data){
+ if(address & (size-1) != 0) cout << "Ref did a unaligned write" << endl;
if((address & 0xF0000000) == 0xF0000000){
MemWrite w;
w.address = address;
@@ -682,7 +717,9 @@ public:
switch(periphWrites.empty() + uint32_t(periphWritesGolden.empty())*2){
case 3: periphWriteTimer = 0; break;
- case 1: case 2: if(periphWriteTimer++ == 20){ cout << "periphWrite timout" << endl; fail();} break;
+ case 1: case 2: if(periphWriteTimer++ == 20){
+ cout << "periphWrite timout" << endl; fail();
+ } break;
case 0:
MemWrite t = periphWrites.front();
MemWrite t2 = periphWritesGolden.front();
@@ -692,6 +729,7 @@ public:
}
periphWrites.pop();
periphWritesGolden.pop();
+ periphWriteTimer = 0;
break;
}
@@ -916,6 +954,10 @@ public:
postReset();
+ //Sync register file initial content
+ for(int i = 1;i < 32;i++){
+ riscvRef.regs[i] = top->VexRiscv->RegFilePlugin_regFile[i];
+ }
resetDone = true;
#ifdef REF
@@ -959,7 +1001,7 @@ public:
mTime += top->VexRiscv->writeBack_arbitration_isFiring*MTIME_INSTR_FACTOR;
#endif
#endif
- #ifdef CSR
+ #ifdef TIMER_INTERRUPT
top->timerInterrupt = mTime >= mTimeCmp ? 1 : 0;
//if(mTime == mTimeCmp) printf("SIM timer tick\n");
#endif
@@ -983,11 +1025,25 @@ public:
#endif
if(top->VexRiscv->writeBack_arbitration_isFiring){
if(riscvRefEnable && top->VexRiscv->writeBack_PC != riscvRef.pc){
- cout << "pc missmatch" << endl;
+ cout << " pc missmatch " << top->VexRiscv->writeBack_PC << " should be " << riscvRef.pc << endl;
fail();
}
- if(riscvRefEnable) riscvRef.step();
+ if(riscvRefEnable) {
+ riscvRef.step();
+ bool mIntTimer = false;
+ bool mIntExt = false;
+
+#ifdef TIMER_INTERRUPT
+ mIntTimer = top->timerInterrupt;
+#endif
+#ifdef EXTERNAL_INTERRUPT
+ mIntExt = top->externalInterrupt;
+#endif
+
+
+ riscvRef.liveness(mIntTimer, mIntExt);
+ }
@@ -2065,6 +2121,60 @@ public:
}
};
+class Compliance : public Workspace{
+public:
+ string name;
+ ofstream out32;
+ int out32Counter = 0;
+ Compliance(string name) : Workspace(name) {
+ //withRiscvRef();
+ loadHex("../../resources/hex/" + name + ".elf.hex");
+ out32.open (name + ".out32");
+ this->name = name;
+ if(name == "I-FENCE.I-01") withInstructionReadCheck = false;
+ }
+
+
+ virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
+ Workspace::dBusAccess(addr,wr,size,mask,data,error);
+ if(wr && addr == 0xF00FFF2C){
+ out32 << hex << setw(8) << std::setfill('0') << *data;
+ if(++out32Counter % 4 == 0) out32 << "\n";
+ *error = 0;
+ }
+ }
+
+ virtual void checks(){
+
+ }
+
+
+
+ virtual void pass(){
+ FILE *refFile = fopen((string("../../resources/ref/") + name + ".reference_output").c_str(), "r");
+ fseek(refFile, 0, SEEK_END);
+ uint32_t refSize = ftell(refFile);
+ fseek(refFile, 0, SEEK_SET);
+ char* ref = new char[refSize];
+ fread(ref, 1, refSize, refFile);
+
+
+ out32.flush();
+ FILE *logFile = fopen((name + ".out32").c_str(), "r");
+ fseek(logFile, 0, SEEK_END);
+ uint32_t logSize = ftell(logFile);
+ fseek(logFile, 0, SEEK_SET);
+ char* log = new char[logSize];
+ fread(log, 1, logSize, logFile);
+
+ if(refSize > logSize || memcmp(log,ref,refSize))
+ fail();
+ else
+ Workspace::pass();
+ }
+};
+
+
#ifdef DEBUG_PLUGIN
#include
@@ -2327,6 +2437,121 @@ string freeRtosTests[] = {
};
+
+string riscvComplianceMain[] = {
+ "I-IO",
+ "I-NOP-01",
+ "I-LUI-01",
+ "I-ADD-01",
+ "I-ADDI-01",
+ "I-AND-01",
+ "I-ANDI-01",
+ "I-SUB-01",
+ "I-OR-01",
+ "I-ORI-01",
+ "I-XOR-01",
+ "I-XORI-01",
+ "I-SRA-01",
+ "I-SRAI-01",
+ "I-SRL-01",
+ "I-SRLI-01",
+ "I-SLL-01",
+ "I-SLLI-01",
+ "I-SLT-01",
+ "I-SLTI-01",
+ "I-SLTIU-01",
+ "I-SLTU-01",
+ "I-AUIPC-01",
+ "I-BEQ-01",
+ "I-BGE-01",
+ "I-BGEU-01",
+ "I-BLT-01",
+ "I-BLTU-01",
+ "I-BNE-01",
+ "I-JAL-01",
+ "I-JALR-01",
+ "I-DELAY_SLOTS-01",
+ "I-ENDIANESS-01",
+ "I-RF_size-01",
+ "I-RF_width-01",
+ "I-RF_x0-01",
+};
+
+
+
+string complianceTestMemory[] = {
+ "I-LB-01",
+ "I-LBU-01",
+ "I-LH-01",
+ "I-LHU-01",
+ "I-LW-01",
+ "I-SB-01",
+ "I-SH-01",
+ "I-SW-01"
+};
+
+
+string complianceTestCsr[] = {
+ "I-CSRRC-01",
+ "I-CSRRCI-01",
+ "I-CSRRS-01",
+ "I-CSRRSI-01",
+ "I-CSRRW-01",
+ "I-CSRRWI-01",
+ #ifndef COMPRESSED
+ "I-MISALIGN_JMP-01", //Only apply for non RVC cores
+ #endif
+ "I-MISALIGN_LDST-01",
+ "I-ECALL-01",
+};
+
+
+string complianceTestMul[] = {
+ "MUL",
+ "MULH",
+ "MULHSU",
+ "MULHU",
+};
+
+string complianceTestDiv[] = {
+ "DIV",
+ "DIVU",
+ "REM",
+ "REMU",
+};
+
+
+string complianceTestC[] = {
+ "C.ADD",
+ "C.ADDI16SP",
+ "C.ADDI4SPN",
+ "C.ADDI",
+ "C.AND",
+ "C.ANDI",
+ "C.BEQZ",
+ "C.BNEZ",
+ "C.JAL",
+ "C.JALR",
+ "C.J",
+ "C.JR",
+ "C.LI",
+ "C.LUI",
+ "C.LW",
+ "C.LWSP",
+ "C.MV",
+ "C.OR",
+ "C.SLLI",
+ "C.SRAI",
+ "C.SRLI",
+ "C.SUB",
+ "C.SW",
+ "C.SWSP",
+ "C.XOR",
+};
+
+
+
+
struct timespec timer_start(){
struct timespec start_time;
clock_gettime(CLOCK_REALTIME, &start_time); //CLOCK_PROCESS_CPUTIME_ID
@@ -2396,10 +2621,13 @@ int main(int argc, char **argv, char **env) {
for(int idx = 0;idx < 1;idx++){
- #ifdef DEBUG_PLUGIN_EXTERNAL
+ #if defined(DEBUG_PLUGIN_EXTERNAL) || defined(RUN_HEX)
{
- Workspace w("debugPluginExternal");
- w.loadHex("../../resources/hex/debugPluginExternal.hex");
+ Workspace w("run");
+ #ifdef RUN_HEX
+ //w.loadHex("/home/spinalvm/hdl/zephyr/zephyrSpinalHdl/samples/synchronization/build/zephyr/zephyr.hex");
+ w.loadHex(RUN_HEX);
+ #endif
w.noInstructionReadCheck();
//w.setIStall(false);
//w.setDStall(false);
@@ -2416,8 +2644,41 @@ int main(int argc, char **argv, char **env) {
#ifdef ISA_TEST
// redo(REDO,TestA().run();)
+ for(const string &name : riscvComplianceMain){
+ redo(REDO, Compliance(name).run();)
+ }
+ for(const string &name : complianceTestMemory){
+ redo(REDO, Compliance(name).run();)
+ }
+ #ifdef COMPRESSED
+ for(const string &name : complianceTestC){
+ redo(REDO, Compliance(name).run();)
+ }
+ #endif
+ #ifdef MUL
+ for(const string &name : complianceTestMul){
+ redo(REDO, Compliance(name).run();)
+ }
+ #endif
+ #ifdef DIV
+ for(const string &name : complianceTestDiv){
+ redo(REDO, Compliance(name).run();)
+ }
+ #endif
+ #ifdef CSR
+ for(const string &name : complianceTestCsr){
+ redo(REDO, Compliance(name).run();)
+ }
+ #endif
+
+ #ifdef FENCEI
+ redo(REDO, Compliance("I-FENCE.I-01").run();)
+ #endif
+ #ifdef EBREAK
+ redo(REDO, Compliance("I-EBREAK-01").run();)
+ #endif
for(const string &name : riscvTestMain){
redo(REDO,RiscvTest(name).run();)
@@ -2444,7 +2705,7 @@ int main(int argc, char **argv, char **env) {
#ifdef CSR
#ifndef COMPRESSED
uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u ,
- 8,6,9,6,10,4,11,4, 12,13,2, 14,2, 15,5,16,17,1 };
+ 8,6,9,6,10,4,11,4, 12,13,0, 14,2, 15,5,16,17,1 };
redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).noInstructionReadCheck()->run(10e4);)
#else
uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u ,
diff --git a/src/test/cpp/regression/makefile b/src/test/cpp/regression/makefile
index 3a5c8f3..a5d5643 100644
--- a/src/test/cpp/regression/makefile
+++ b/src/test/cpp/regression/makefile
@@ -1,4 +1,4 @@
-DEBUG=yes
+DEBUG?=no
IBUS?=CACHED
DBUS?=CACHED
@@ -9,12 +9,15 @@ ISA_TEST?=yes
MUL?=yes
DIV?=yes
CSR?=yes
+EBREAK?=no
+FENCEI?=no
MMU?=yes
SEED?=no
ATOMIC?=no
NO_STALL?=no
DEBUG_PLUGIN?=STD
DEBUG_PLUGIN_EXTERNAL?=no
+RUN_HEX=no
CUSTOM_SIMD_ADD?=no
CUSTOM_CSR?=no
DHRYSTONE=yes
@@ -39,14 +42,35 @@ ADDCFLAGS += -CFLAGS -DTHREAD_COUNT=${THREAD_COUNT}
ifeq ($(DEBUG),yes)
ADDCFLAGS += -CFLAGS -O0 -CFLAGS -g
else
- ADDCFLAGS += -CFLAGS -O3
+ ADDCFLAGS += -CFLAGS -O3
+endif
+
+ifneq ($(shell dplus -VV | grep timerInterrupt ../../../../VexRiscv.v -w),)
+ ADDCFLAGS += -CFLAGS -DTIMER_INTERRUPT
+endif
+
+ifneq ($(shell dplus -VV | grep externalInterrupt ../../../../VexRiscv.v -w),)
+ ADDCFLAGS += -CFLAGS -DEXTERNAL_INTERRUPT
+endif
+
+ifneq ($(RUN_HEX),no)
+ ADDCFLAGS += -CFLAGS -DRUN_HEX='\"$(RUN_HEX)\"'
endif
ifeq ($(COMPRESSED),yes)
ADDCFLAGS += -CFLAGS -DCOMPRESSED
endif
+ifeq ($(FENCEI),yes)
+ ADDCFLAGS += -CFLAGS -DFENCEI
+endif
+
+ifeq ($(EBREAK),yes)
+ ADDCFLAGS += -CFLAGS -DEBREAK
+endif
+
+
ifeq ($(DHRYSTONE),yes)
ADDCFLAGS += -CFLAGS -DDHRYSTONE
endif
diff --git a/src/test/python/gcloud/remoteTest.py b/src/test/python/gcloud/remoteTest.py
index e1b62e1..37bd029 100755
--- a/src/test/python/gcloud/remoteTest.py
+++ b/src/test/python/gcloud/remoteTest.py
@@ -14,6 +14,8 @@ gci.stopScript("src/test/python/gcloud/stopScript.sh")
gci.local("rm -rf archive.tar.gz; git ls-files -z | xargs -0 tar -czf archive.tar.gz")
gci.localToRemote("archive.tar.gz", "")
+gci.local("cd ../SpinalHDL; rm -rf spinal.tar.gz; git ls-files -z | xargs -0 tar -czf spinal.tar.gz")
+gci.localToRemote("../SpinalHDL/spinal.tar.gz", "")
gci.localToRemote("src/test/python/gcloud/run.sh", "")
gci.remote("rm -rf run.txt; setsid nohup sh run.sh &> run.txt")
diff --git a/src/test/python/gcloud/run.sh b/src/test/python/gcloud/run.sh
index 7281216..02c17f9 100644
--- a/src/test/python/gcloud/run.sh
+++ b/src/test/python/gcloud/run.sh
@@ -1,11 +1,17 @@
rm -rf sbtTest.txt
rm -rf VexRiscv
+rm -rf SpinalHDL
+#git clone https://github.com/SpinalHDL/SpinalHDL.git -b dev
+mkdir SpinalHDL
+tar -xzf spinal.tar.gz -C SpinalHDL
mkdir VexRiscv
tar -xzf archive.tar.gz -C VexRiscv
cd VexRiscv
-
-export VEXRISCV_REGRESSION_CONFIG_COUNT=16
-export VEXRISCV_REGRESSION_FREERTOS_COUNT=yes
+sudo git init
+sudo git add *
+sudo git commit -m miaou
+export VEXRISCV_REGRESSION_CONFIG_COUNT=128
+export VEXRISCV_REGRESSION_FREERTOS_COUNT=30
sbt test
cd ..
diff --git a/src/test/resources/asm/C.ADD.elf.objdump b/src/test/resources/asm/C.ADD.elf.objdump
new file mode 100644
index 0000000..32ee1ad
--- /dev/null
+++ b/src/test/resources/asm/C.ADD.elf.objdump
@@ -0,0 +1,334 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.ADD.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4201 li tp,0
+800000f8: 4181 li gp,0
+800000fa: 9192 add gp,gp,tp
+800000fc: c00e sw gp,0(sp)
+800000fe: 4481 li s1,0
+80000100: 4405 li s0,1
+80000102: 9426 add s0,s0,s1
+80000104: c222 sw s0,4(sp)
+80000106: 4601 li a2,0
+80000108: fff00593 li a1,-1
+8000010c: 95b2 add a1,a1,a2
+8000010e: c42e sw a1,8(sp)
+80000110: 4701 li a4,0
+80000112: 000086b7 lui a3,0x8
+80000116: fff68693 addi a3,a3,-1 # 7fff <_start-0x7fff8001>
+8000011a: 96ba add a3,a3,a4
+8000011c: c636 sw a3,12(sp)
+8000011e: 4801 li a6,0
+80000120: 67a1 lui a5,0x8
+80000122: 97c2 add a5,a5,a6
+80000124: c83e sw a5,16(sp)
+80000126: 00001117 auipc sp,0x1
+8000012a: eee10113 addi sp,sp,-274 # 80001014
+8000012e: 4905 li s2,1
+80000130: 4881 li a7,0
+80000132: 98ca add a7,a7,s2
+80000134: c046 sw a7,0(sp)
+80000136: 4a05 li s4,1
+80000138: 4985 li s3,1
+8000013a: 99d2 add s3,s3,s4
+8000013c: c24e sw s3,4(sp)
+8000013e: 4b05 li s6,1
+80000140: fff00a93 li s5,-1
+80000144: 9ada add s5,s5,s6
+80000146: c456 sw s5,8(sp)
+80000148: 4c05 li s8,1
+8000014a: 00008bb7 lui s7,0x8
+8000014e: fffb8b93 addi s7,s7,-1 # 7fff <_start-0x7fff8001>
+80000152: 9be2 add s7,s7,s8
+80000154: c65e sw s7,12(sp)
+80000156: 4d05 li s10,1
+80000158: 6ca1 lui s9,0x8
+8000015a: 9cea add s9,s9,s10
+8000015c: c866 sw s9,16(sp)
+8000015e: 00001117 auipc sp,0x1
+80000162: eca10113 addi sp,sp,-310 # 80001028
+80000166: fff00e13 li t3,-1
+8000016a: 4d81 li s11,0
+8000016c: 9df2 add s11,s11,t3
+8000016e: c06e sw s11,0(sp)
+80000170: fff00f13 li t5,-1
+80000174: 4e85 li t4,1
+80000176: 9efa add t4,t4,t5
+80000178: c276 sw t4,4(sp)
+8000017a: fff00193 li gp,-1
+8000017e: fff00f93 li t6,-1
+80000182: 9f8e add t6,t6,gp
+80000184: c47e sw t6,8(sp)
+80000186: fff00413 li s0,-1
+8000018a: 00008237 lui tp,0x8
+8000018e: fff20213 addi tp,tp,-1 # 7fff <_start-0x7fff8001>
+80000192: 9222 add tp,tp,s0
+80000194: c612 sw tp,12(sp)
+80000196: fff00593 li a1,-1
+8000019a: 64a1 lui s1,0x8
+8000019c: 94ae add s1,s1,a1
+8000019e: c826 sw s1,16(sp)
+800001a0: 00001117 auipc sp,0x1
+800001a4: e9c10113 addi sp,sp,-356 # 8000103c
+800001a8: 000086b7 lui a3,0x8
+800001ac: fff68693 addi a3,a3,-1 # 7fff <_start-0x7fff8001>
+800001b0: 4601 li a2,0
+800001b2: 9636 add a2,a2,a3
+800001b4: c032 sw a2,0(sp)
+800001b6: 000087b7 lui a5,0x8
+800001ba: fff78793 addi a5,a5,-1 # 7fff <_start-0x7fff8001>
+800001be: 4705 li a4,1
+800001c0: 973e add a4,a4,a5
+800001c2: c23a sw a4,4(sp)
+800001c4: 000088b7 lui a7,0x8
+800001c8: fff88893 addi a7,a7,-1 # 7fff <_start-0x7fff8001>
+800001cc: fff00813 li a6,-1
+800001d0: 9846 add a6,a6,a7
+800001d2: c442 sw a6,8(sp)
+800001d4: 000089b7 lui s3,0x8
+800001d8: fff98993 addi s3,s3,-1 # 7fff <_start-0x7fff8001>
+800001dc: 00008937 lui s2,0x8
+800001e0: fff90913 addi s2,s2,-1 # 7fff <_start-0x7fff8001>
+800001e4: 994e add s2,s2,s3
+800001e6: c64a sw s2,12(sp)
+800001e8: 00008ab7 lui s5,0x8
+800001ec: fffa8a93 addi s5,s5,-1 # 7fff <_start-0x7fff8001>
+800001f0: 6a21 lui s4,0x8
+800001f2: 9a56 add s4,s4,s5
+800001f4: c852 sw s4,16(sp)
+800001f6: 00001117 auipc sp,0x1
+800001fa: e5a10113 addi sp,sp,-422 # 80001050
+800001fe: 6ba1 lui s7,0x8
+80000200: 4b01 li s6,0
+80000202: 9b5e add s6,s6,s7
+80000204: c05a sw s6,0(sp)
+80000206: 6ca1 lui s9,0x8
+80000208: 4c05 li s8,1
+8000020a: 9c66 add s8,s8,s9
+8000020c: c262 sw s8,4(sp)
+8000020e: 6da1 lui s11,0x8
+80000210: fff00d13 li s10,-1
+80000214: 9d6e add s10,s10,s11
+80000216: c46a sw s10,8(sp)
+80000218: 6ea1 lui t4,0x8
+8000021a: 00008e37 lui t3,0x8
+8000021e: fffe0e13 addi t3,t3,-1 # 7fff <_start-0x7fff8001>
+80000222: 9e76 add t3,t3,t4
+80000224: c672 sw t3,12(sp)
+80000226: 6fa1 lui t6,0x8
+80000228: 6f21 lui t5,0x8
+8000022a: 9f7e add t5,t5,t6
+8000022c: c87a sw t5,16(sp)
+8000022e: 00001517 auipc a0,0x1
+80000232: dd250513 addi a0,a0,-558 # 80001000
+80000236: 00001597 auipc a1,0x1
+8000023a: e3a58593 addi a1,a1,-454 # 80001070 <_end>
+8000023e: f0100637 lui a2,0xf0100
+80000242: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700feebc>
+
+80000246 :
+80000246: 00b50c63 beq a0,a1,8000025e
+8000024a: 4554 lw a3,12(a0)
+8000024c: c214 sw a3,0(a2)
+8000024e: 4514 lw a3,8(a0)
+80000250: c214 sw a3,0(a2)
+80000252: 4154 lw a3,4(a0)
+80000254: c214 sw a3,0(a2)
+80000256: 4114 lw a3,0(a0)
+80000258: c214 sw a3,0(a2)
+8000025a: 0541 addi a0,a0,16
+8000025c: b7ed j 80000246
+
+8000025e :
+8000025e: f0100537 lui a0,0xf0100
+80000262: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700feeb0>
+80000266: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+
+80001014 :
+80001014: ffff 0xffff
+80001016: ffff 0xffff
+80001018: ffff 0xffff
+8000101a: ffff 0xffff
+8000101c: ffff 0xffff
+8000101e: ffff 0xffff
+80001020: ffff 0xffff
+80001022: ffff 0xffff
+80001024: ffff 0xffff
+80001026: ffff 0xffff
+
+80001028 :
+80001028: ffff 0xffff
+8000102a: ffff 0xffff
+8000102c: ffff 0xffff
+8000102e: ffff 0xffff
+80001030: ffff 0xffff
+80001032: ffff 0xffff
+80001034: ffff 0xffff
+80001036: ffff 0xffff
+80001038: ffff 0xffff
+8000103a: ffff 0xffff
+
+8000103c :
+8000103c: ffff 0xffff
+8000103e: ffff 0xffff
+80001040: ffff 0xffff
+80001042: ffff 0xffff
+80001044: ffff 0xffff
+80001046: ffff 0xffff
+80001048: ffff 0xffff
+8000104a: ffff 0xffff
+8000104c: ffff 0xffff
+8000104e: ffff 0xffff
+
+80001050 :
+80001050: ffff 0xffff
+80001052: ffff 0xffff
+80001054: ffff 0xffff
+80001056: ffff 0xffff
+80001058: ffff 0xffff
+8000105a: ffff 0xffff
+8000105c: ffff 0xffff
+8000105e: ffff 0xffff
+80001060: ffff 0xffff
+80001062: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.ADDI.elf.objdump b/src/test/resources/asm/C.ADDI.elf.objdump
new file mode 100644
index 0000000..e0e0a94
--- /dev/null
+++ b/src/test/resources/asm/C.ADDI.elf.objdump
@@ -0,0 +1,304 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.ADDI.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4181 li gp,0
+800000f8: 0185 addi gp,gp,1
+800000fa: c00e sw gp,0(sp)
+800000fc: 4201 li tp,0
+800000fe: 0209 addi tp,tp,2
+80000100: c212 sw tp,4(sp)
+80000102: 4401 li s0,0
+80000104: 043d addi s0,s0,15
+80000106: c422 sw s0,8(sp)
+80000108: 4481 li s1,0
+8000010a: 04c1 addi s1,s1,16
+8000010c: c626 sw s1,12(sp)
+8000010e: 4581 li a1,0
+80000110: 05fd addi a1,a1,31
+80000112: c82e sw a1,16(sp)
+80000114: 00001117 auipc sp,0x1
+80000118: f0010113 addi sp,sp,-256 # 80001014
+8000011c: 4605 li a2,1
+8000011e: 0605 addi a2,a2,1
+80000120: c032 sw a2,0(sp)
+80000122: 4685 li a3,1
+80000124: 0689 addi a3,a3,2
+80000126: c236 sw a3,4(sp)
+80000128: 4705 li a4,1
+8000012a: 073d addi a4,a4,15
+8000012c: c43a sw a4,8(sp)
+8000012e: 4785 li a5,1
+80000130: 07c1 addi a5,a5,16
+80000132: c63e sw a5,12(sp)
+80000134: 4805 li a6,1
+80000136: 087d addi a6,a6,31
+80000138: c842 sw a6,16(sp)
+8000013a: 00001117 auipc sp,0x1
+8000013e: eee10113 addi sp,sp,-274 # 80001028
+80000142: fff00893 li a7,-1
+80000146: 0885 addi a7,a7,1
+80000148: c046 sw a7,0(sp)
+8000014a: fff00913 li s2,-1
+8000014e: 0909 addi s2,s2,2
+80000150: c24a sw s2,4(sp)
+80000152: fff00993 li s3,-1
+80000156: 09bd addi s3,s3,15
+80000158: c44e sw s3,8(sp)
+8000015a: fff00a13 li s4,-1
+8000015e: 0a41 addi s4,s4,16
+80000160: c652 sw s4,12(sp)
+80000162: fff00a93 li s5,-1
+80000166: 0afd addi s5,s5,31
+80000168: c856 sw s5,16(sp)
+8000016a: 00001117 auipc sp,0x1
+8000016e: ed210113 addi sp,sp,-302 # 8000103c
+80000172: 00080b37 lui s6,0x80
+80000176: fffb0b13 addi s6,s6,-1 # 7ffff <_start-0x7ff80001>
+8000017a: 0b05 addi s6,s6,1
+8000017c: c05a sw s6,0(sp)
+8000017e: 00080bb7 lui s7,0x80
+80000182: fffb8b93 addi s7,s7,-1 # 7ffff <_start-0x7ff80001>
+80000186: 0b89 addi s7,s7,2
+80000188: c25e sw s7,4(sp)
+8000018a: 00080c37 lui s8,0x80
+8000018e: fffc0c13 addi s8,s8,-1 # 7ffff <_start-0x7ff80001>
+80000192: 0c3d addi s8,s8,15
+80000194: c462 sw s8,8(sp)
+80000196: 00080cb7 lui s9,0x80
+8000019a: fffc8c93 addi s9,s9,-1 # 7ffff <_start-0x7ff80001>
+8000019e: 0cc1 addi s9,s9,16
+800001a0: c666 sw s9,12(sp)
+800001a2: 00080d37 lui s10,0x80
+800001a6: fffd0d13 addi s10,s10,-1 # 7ffff <_start-0x7ff80001>
+800001aa: 0d7d addi s10,s10,31
+800001ac: c86a sw s10,16(sp)
+800001ae: 00001117 auipc sp,0x1
+800001b2: ea210113 addi sp,sp,-350 # 80001050
+800001b6: 00080db7 lui s11,0x80
+800001ba: 0d85 addi s11,s11,1
+800001bc: c06e sw s11,0(sp)
+800001be: 00080e37 lui t3,0x80
+800001c2: 0e09 addi t3,t3,2
+800001c4: c272 sw t3,4(sp)
+800001c6: 00080eb7 lui t4,0x80
+800001ca: 0ebd addi t4,t4,15
+800001cc: c476 sw t4,8(sp)
+800001ce: 00080f37 lui t5,0x80
+800001d2: 0f41 addi t5,t5,16
+800001d4: c67a sw t5,12(sp)
+800001d6: 00080fb7 lui t6,0x80
+800001da: 0ffd addi t6,t6,31
+800001dc: c87e sw t6,16(sp)
+800001de: 00001517 auipc a0,0x1
+800001e2: e2250513 addi a0,a0,-478 # 80001000
+800001e6: 00001597 auipc a1,0x1
+800001ea: e8a58593 addi a1,a1,-374 # 80001070 <_end>
+800001ee: f0100637 lui a2,0xf0100
+800001f2: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700feebc>
+
+800001f6 :
+800001f6: 00b50c63 beq a0,a1,8000020e
+800001fa: 4554 lw a3,12(a0)
+800001fc: c214 sw a3,0(a2)
+800001fe: 4514 lw a3,8(a0)
+80000200: c214 sw a3,0(a2)
+80000202: 4154 lw a3,4(a0)
+80000204: c214 sw a3,0(a2)
+80000206: 4114 lw a3,0(a0)
+80000208: c214 sw a3,0(a2)
+8000020a: 0541 addi a0,a0,16
+8000020c: b7ed j 800001f6
+
+8000020e :
+8000020e: f0100537 lui a0,0xf0100
+80000212: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700feeb0>
+80000216: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+
+80001014 :
+80001014: ffff 0xffff
+80001016: ffff 0xffff
+80001018: ffff 0xffff
+8000101a: ffff 0xffff
+8000101c: ffff 0xffff
+8000101e: ffff 0xffff
+80001020: ffff 0xffff
+80001022: ffff 0xffff
+80001024: ffff 0xffff
+80001026: ffff 0xffff
+
+80001028 :
+80001028: ffff 0xffff
+8000102a: ffff 0xffff
+8000102c: ffff 0xffff
+8000102e: ffff 0xffff
+80001030: ffff 0xffff
+80001032: ffff 0xffff
+80001034: ffff 0xffff
+80001036: ffff 0xffff
+80001038: ffff 0xffff
+8000103a: ffff 0xffff
+
+8000103c :
+8000103c: ffff 0xffff
+8000103e: ffff 0xffff
+80001040: ffff 0xffff
+80001042: ffff 0xffff
+80001044: ffff 0xffff
+80001046: ffff 0xffff
+80001048: ffff 0xffff
+8000104a: ffff 0xffff
+8000104c: ffff 0xffff
+8000104e: ffff 0xffff
+
+80001050 :
+80001050: ffff 0xffff
+80001052: ffff 0xffff
+80001054: ffff 0xffff
+80001056: ffff 0xffff
+80001058: ffff 0xffff
+8000105a: ffff 0xffff
+8000105c: ffff 0xffff
+8000105e: ffff 0xffff
+80001060: ffff 0xffff
+80001062: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.ADDI16SP.elf.objdump b/src/test/resources/asm/C.ADDI16SP.elf.objdump
new file mode 100644
index 0000000..bd3351c
--- /dev/null
+++ b/src/test/resources/asm/C.ADDI16SP.elf.objdump
@@ -0,0 +1,194 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.ADDI16SP.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001097 auipc ra,0x1
+800000f2: f1208093 addi ra,ra,-238 # 80001000
+800000f6: 0141 addi sp,sp,16
+800000f8: 0020a023 sw sp,0(ra)
+800000fc: 00001097 auipc ra,0x1
+80000100: f0808093 addi ra,ra,-248 # 80001004
+80000104: 6105 addi sp,sp,32
+80000106: 0020a023 sw sp,0(ra)
+8000010a: 00001097 auipc ra,0x1
+8000010e: efe08093 addi ra,ra,-258 # 80001008
+80000112: 6121 addi sp,sp,64
+80000114: 0020a023 sw sp,0(ra)
+80000118: 00001097 auipc ra,0x1
+8000011c: ef408093 addi ra,ra,-268 # 8000100c
+80000120: 617d addi sp,sp,496
+80000122: 0020a023 sw sp,0(ra)
+80000126: 00001097 auipc ra,0x1
+8000012a: eea08093 addi ra,ra,-278 # 80001010
+8000012e: 7101 addi sp,sp,-512
+80000130: 0020a023 sw sp,0(ra)
+80000134: 00001517 auipc a0,0x1
+80000138: ecc50513 addi a0,a0,-308 # 80001000
+8000013c: 00001597 auipc a1,0x1
+80000140: ee458593 addi a1,a1,-284 # 80001020 <_end>
+80000144: f0100637 lui a2,0xf0100
+80000148: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fef0c>
+
+8000014c :
+8000014c: 00b50c63 beq a0,a1,80000164
+80000150: 4554 lw a3,12(a0)
+80000152: c214 sw a3,0(a2)
+80000154: 4514 lw a3,8(a0)
+80000156: c214 sw a3,0(a2)
+80000158: 4154 lw a3,4(a0)
+8000015a: c214 sw a3,0(a2)
+8000015c: 4114 lw a3,0(a0)
+8000015e: c214 sw a3,0(a2)
+80000160: 0541 addi a0,a0,16
+80000162: b7ed j 8000014c
+
+80000164 :
+80000164: f0100537 lui a0,0xf0100
+80000168: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fef00>
+8000016c: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.ADDI4SPN.elf.objdump b/src/test/resources/asm/C.ADDI4SPN.elf.objdump
new file mode 100644
index 0000000..5a09876
--- /dev/null
+++ b/src/test/resources/asm/C.ADDI4SPN.elf.objdump
@@ -0,0 +1,194 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.ADDI4SPN.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001097 auipc ra,0x1
+800000f2: f1208093 addi ra,ra,-238 # 80001000
+800000f6: 0050 addi a2,sp,4
+800000f8: 00c0a023 sw a2,0(ra)
+800000fc: 00001097 auipc ra,0x1
+80000100: f0808093 addi ra,ra,-248 # 80001004
+80000104: 0034 addi a3,sp,8
+80000106: 00d0a023 sw a3,0(ra)
+8000010a: 00001097 auipc ra,0x1
+8000010e: efe08093 addi ra,ra,-258 # 80001008
+80000112: 0078 addi a4,sp,12
+80000114: 00e0a023 sw a4,0(ra)
+80000118: 00001097 auipc ra,0x1
+8000011c: ef408093 addi ra,ra,-268 # 8000100c
+80000120: 081c addi a5,sp,16
+80000122: 00f0a023 sw a5,0(ra)
+80000126: 00001097 auipc ra,0x1
+8000012a: eea08093 addi ra,ra,-278 # 80001010
+8000012e: 1fe0 addi s0,sp,1020
+80000130: 0080a023 sw s0,0(ra)
+80000134: 00001517 auipc a0,0x1
+80000138: ecc50513 addi a0,a0,-308 # 80001000
+8000013c: 00001597 auipc a1,0x1
+80000140: ee458593 addi a1,a1,-284 # 80001020 <_end>
+80000144: f0100637 lui a2,0xf0100
+80000148: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fef0c>
+
+8000014c :
+8000014c: 00b50c63 beq a0,a1,80000164
+80000150: 4554 lw a3,12(a0)
+80000152: c214 sw a3,0(a2)
+80000154: 4514 lw a3,8(a0)
+80000156: c214 sw a3,0(a2)
+80000158: 4154 lw a3,4(a0)
+8000015a: c214 sw a3,0(a2)
+8000015c: 4114 lw a3,0(a0)
+8000015e: c214 sw a3,0(a2)
+80000160: 0541 addi a0,a0,16
+80000162: b7ed j 8000014c
+
+80000164 :
+80000164: f0100537 lui a0,0xf0100
+80000168: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fef00>
+8000016c: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.AND.elf.objdump b/src/test/resources/asm/C.AND.elf.objdump
new file mode 100644
index 0000000..d78ccb9
--- /dev/null
+++ b/src/test/resources/asm/C.AND.elf.objdump
@@ -0,0 +1,334 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.AND.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4581 li a1,0
+800000f8: 4481 li s1,0
+800000fa: 8ced and s1,s1,a1
+800000fc: c026 sw s1,0(sp)
+800000fe: 4681 li a3,0
+80000100: 4605 li a2,1
+80000102: 8e75 and a2,a2,a3
+80000104: c232 sw a2,4(sp)
+80000106: 4781 li a5,0
+80000108: fff00713 li a4,-1
+8000010c: 8f7d and a4,a4,a5
+8000010e: c43a sw a4,8(sp)
+80000110: 4481 li s1,0
+80000112: 00008437 lui s0,0x8
+80000116: fff40413 addi s0,s0,-1 # 7fff <_start-0x7fff8001>
+8000011a: 8c65 and s0,s0,s1
+8000011c: c622 sw s0,12(sp)
+8000011e: 4601 li a2,0
+80000120: 65a1 lui a1,0x8
+80000122: 8df1 and a1,a1,a2
+80000124: c82e sw a1,16(sp)
+80000126: 00001117 auipc sp,0x1
+8000012a: eee10113 addi sp,sp,-274 # 80001014
+8000012e: 4705 li a4,1
+80000130: 4681 li a3,0
+80000132: 8ef9 and a3,a3,a4
+80000134: c036 sw a3,0(sp)
+80000136: 4405 li s0,1
+80000138: 4785 li a5,1
+8000013a: 8fe1 and a5,a5,s0
+8000013c: c23e sw a5,4(sp)
+8000013e: 4585 li a1,1
+80000140: fff00493 li s1,-1
+80000144: 8ced and s1,s1,a1
+80000146: c426 sw s1,8(sp)
+80000148: 4685 li a3,1
+8000014a: 00008637 lui a2,0x8
+8000014e: fff60613 addi a2,a2,-1 # 7fff <_start-0x7fff8001>
+80000152: 8e75 and a2,a2,a3
+80000154: c632 sw a2,12(sp)
+80000156: 4785 li a5,1
+80000158: 6721 lui a4,0x8
+8000015a: 8f7d and a4,a4,a5
+8000015c: c83a sw a4,16(sp)
+8000015e: 00001117 auipc sp,0x1
+80000162: eca10113 addi sp,sp,-310 # 80001028
+80000166: fff00493 li s1,-1
+8000016a: 4401 li s0,0
+8000016c: 8c65 and s0,s0,s1
+8000016e: c022 sw s0,0(sp)
+80000170: fff00613 li a2,-1
+80000174: 4585 li a1,1
+80000176: 8df1 and a1,a1,a2
+80000178: c22e sw a1,4(sp)
+8000017a: fff00713 li a4,-1
+8000017e: fff00693 li a3,-1
+80000182: 8ef9 and a3,a3,a4
+80000184: c436 sw a3,8(sp)
+80000186: fff00413 li s0,-1
+8000018a: 000087b7 lui a5,0x8
+8000018e: fff78793 addi a5,a5,-1 # 7fff <_start-0x7fff8001>
+80000192: 8fe1 and a5,a5,s0
+80000194: c63e sw a5,12(sp)
+80000196: fff00593 li a1,-1
+8000019a: 64a1 lui s1,0x8
+8000019c: 8ced and s1,s1,a1
+8000019e: c826 sw s1,16(sp)
+800001a0: 00001117 auipc sp,0x1
+800001a4: e9c10113 addi sp,sp,-356 # 8000103c
+800001a8: 000086b7 lui a3,0x8
+800001ac: fff68693 addi a3,a3,-1 # 7fff <_start-0x7fff8001>
+800001b0: 4601 li a2,0
+800001b2: 8e75 and a2,a2,a3
+800001b4: c032 sw a2,0(sp)
+800001b6: 000087b7 lui a5,0x8
+800001ba: fff78793 addi a5,a5,-1 # 7fff <_start-0x7fff8001>
+800001be: 4705 li a4,1
+800001c0: 8f7d and a4,a4,a5
+800001c2: c23a sw a4,4(sp)
+800001c4: 000084b7 lui s1,0x8
+800001c8: fff48493 addi s1,s1,-1 # 7fff <_start-0x7fff8001>
+800001cc: fff00413 li s0,-1
+800001d0: 8c65 and s0,s0,s1
+800001d2: c422 sw s0,8(sp)
+800001d4: 00008637 lui a2,0x8
+800001d8: fff60613 addi a2,a2,-1 # 7fff <_start-0x7fff8001>
+800001dc: 000085b7 lui a1,0x8
+800001e0: fff58593 addi a1,a1,-1 # 7fff <_start-0x7fff8001>
+800001e4: 8df1 and a1,a1,a2
+800001e6: c62e sw a1,12(sp)
+800001e8: 00008737 lui a4,0x8
+800001ec: fff70713 addi a4,a4,-1 # 7fff <_start-0x7fff8001>
+800001f0: 66a1 lui a3,0x8
+800001f2: 8ef9 and a3,a3,a4
+800001f4: c836 sw a3,16(sp)
+800001f6: 00001117 auipc sp,0x1
+800001fa: e5a10113 addi sp,sp,-422 # 80001050
+800001fe: 6421 lui s0,0x8
+80000200: 4781 li a5,0
+80000202: 8fe1 and a5,a5,s0
+80000204: c03e sw a5,0(sp)
+80000206: 65a1 lui a1,0x8
+80000208: 4485 li s1,1
+8000020a: 8ced and s1,s1,a1
+8000020c: c226 sw s1,4(sp)
+8000020e: 66a1 lui a3,0x8
+80000210: fff00613 li a2,-1
+80000214: 8e75 and a2,a2,a3
+80000216: c432 sw a2,8(sp)
+80000218: 67a1 lui a5,0x8
+8000021a: 00008737 lui a4,0x8
+8000021e: fff70713 addi a4,a4,-1 # 7fff <_start-0x7fff8001>
+80000222: 8f7d and a4,a4,a5
+80000224: c63a sw a4,12(sp)
+80000226: 64a1 lui s1,0x8
+80000228: 6421 lui s0,0x8
+8000022a: 8c65 and s0,s0,s1
+8000022c: c822 sw s0,16(sp)
+8000022e: 00001517 auipc a0,0x1
+80000232: dd250513 addi a0,a0,-558 # 80001000
+80000236: 00001597 auipc a1,0x1
+8000023a: e3a58593 addi a1,a1,-454 # 80001070 <_end>
+8000023e: f0100637 lui a2,0xf0100
+80000242: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700feebc>
+
+80000246 :
+80000246: 00b50c63 beq a0,a1,8000025e
+8000024a: 4554 lw a3,12(a0)
+8000024c: c214 sw a3,0(a2)
+8000024e: 4514 lw a3,8(a0)
+80000250: c214 sw a3,0(a2)
+80000252: 4154 lw a3,4(a0)
+80000254: c214 sw a3,0(a2)
+80000256: 4114 lw a3,0(a0)
+80000258: c214 sw a3,0(a2)
+8000025a: 0541 addi a0,a0,16
+8000025c: b7ed j 80000246
+
+8000025e :
+8000025e: f0100537 lui a0,0xf0100
+80000262: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700feeb0>
+80000266: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+
+80001014 :
+80001014: ffff 0xffff
+80001016: ffff 0xffff
+80001018: ffff 0xffff
+8000101a: ffff 0xffff
+8000101c: ffff 0xffff
+8000101e: ffff 0xffff
+80001020: ffff 0xffff
+80001022: ffff 0xffff
+80001024: ffff 0xffff
+80001026: ffff 0xffff
+
+80001028 :
+80001028: ffff 0xffff
+8000102a: ffff 0xffff
+8000102c: ffff 0xffff
+8000102e: ffff 0xffff
+80001030: ffff 0xffff
+80001032: ffff 0xffff
+80001034: ffff 0xffff
+80001036: ffff 0xffff
+80001038: ffff 0xffff
+8000103a: ffff 0xffff
+
+8000103c :
+8000103c: ffff 0xffff
+8000103e: ffff 0xffff
+80001040: ffff 0xffff
+80001042: ffff 0xffff
+80001044: ffff 0xffff
+80001046: ffff 0xffff
+80001048: ffff 0xffff
+8000104a: ffff 0xffff
+8000104c: ffff 0xffff
+8000104e: ffff 0xffff
+
+80001050 :
+80001050: ffff 0xffff
+80001052: ffff 0xffff
+80001054: ffff 0xffff
+80001056: ffff 0xffff
+80001058: ffff 0xffff
+8000105a: ffff 0xffff
+8000105c: ffff 0xffff
+8000105e: ffff 0xffff
+80001060: ffff 0xffff
+80001062: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.ANDI.elf.objdump b/src/test/resources/asm/C.ANDI.elf.objdump
new file mode 100644
index 0000000..525df9d
--- /dev/null
+++ b/src/test/resources/asm/C.ANDI.elf.objdump
@@ -0,0 +1,304 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.ANDI.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4581 li a1,0
+800000f8: 8981 andi a1,a1,0
+800000fa: c02e sw a1,0(sp)
+800000fc: 4601 li a2,0
+800000fe: 8a05 andi a2,a2,1
+80000100: c232 sw a2,4(sp)
+80000102: 4681 li a3,0
+80000104: 8ac1 andi a3,a3,16
+80000106: c436 sw a3,8(sp)
+80000108: 4701 li a4,0
+8000010a: 8b7d andi a4,a4,31
+8000010c: c63a sw a4,12(sp)
+8000010e: 4781 li a5,0
+80000110: 9b85 andi a5,a5,-31
+80000112: c83e sw a5,16(sp)
+80000114: 00001117 auipc sp,0x1
+80000118: f0010113 addi sp,sp,-256 # 80001014
+8000011c: 4405 li s0,1
+8000011e: 8801 andi s0,s0,0
+80000120: c022 sw s0,0(sp)
+80000122: 4485 li s1,1
+80000124: 8885 andi s1,s1,1
+80000126: c226 sw s1,4(sp)
+80000128: 4585 li a1,1
+8000012a: 89c1 andi a1,a1,16
+8000012c: c42e sw a1,8(sp)
+8000012e: 4605 li a2,1
+80000130: 8a7d andi a2,a2,31
+80000132: c632 sw a2,12(sp)
+80000134: 4685 li a3,1
+80000136: 9a85 andi a3,a3,-31
+80000138: c836 sw a3,16(sp)
+8000013a: 00001117 auipc sp,0x1
+8000013e: eee10113 addi sp,sp,-274 # 80001028
+80000142: fff00713 li a4,-1
+80000146: 8b01 andi a4,a4,0
+80000148: c03a sw a4,0(sp)
+8000014a: fff00793 li a5,-1
+8000014e: 8b85 andi a5,a5,1
+80000150: c23e sw a5,4(sp)
+80000152: fff00413 li s0,-1
+80000156: 8841 andi s0,s0,16
+80000158: c422 sw s0,8(sp)
+8000015a: fff00493 li s1,-1
+8000015e: 88fd andi s1,s1,31
+80000160: c626 sw s1,12(sp)
+80000162: fff00593 li a1,-1
+80000166: 9985 andi a1,a1,-31
+80000168: c82e sw a1,16(sp)
+8000016a: 00001117 auipc sp,0x1
+8000016e: ed210113 addi sp,sp,-302 # 8000103c
+80000172: 00080637 lui a2,0x80
+80000176: fff60613 addi a2,a2,-1 # 7ffff <_start-0x7ff80001>
+8000017a: 8a01 andi a2,a2,0
+8000017c: c032 sw a2,0(sp)
+8000017e: 000806b7 lui a3,0x80
+80000182: fff68693 addi a3,a3,-1 # 7ffff <_start-0x7ff80001>
+80000186: 8a85 andi a3,a3,1
+80000188: c236 sw a3,4(sp)
+8000018a: 00080737 lui a4,0x80
+8000018e: fff70713 addi a4,a4,-1 # 7ffff <_start-0x7ff80001>
+80000192: 8b41 andi a4,a4,16
+80000194: c43a sw a4,8(sp)
+80000196: 000807b7 lui a5,0x80
+8000019a: fff78793 addi a5,a5,-1 # 7ffff <_start-0x7ff80001>
+8000019e: 8bfd andi a5,a5,31
+800001a0: c63e sw a5,12(sp)
+800001a2: 00080437 lui s0,0x80
+800001a6: fff40413 addi s0,s0,-1 # 7ffff <_start-0x7ff80001>
+800001aa: 9805 andi s0,s0,-31
+800001ac: c822 sw s0,16(sp)
+800001ae: 00001117 auipc sp,0x1
+800001b2: ea210113 addi sp,sp,-350 # 80001050
+800001b6: 000804b7 lui s1,0x80
+800001ba: 8881 andi s1,s1,0
+800001bc: c026 sw s1,0(sp)
+800001be: 000805b7 lui a1,0x80
+800001c2: 8985 andi a1,a1,1
+800001c4: c22e sw a1,4(sp)
+800001c6: 00080637 lui a2,0x80
+800001ca: 8a41 andi a2,a2,16
+800001cc: c432 sw a2,8(sp)
+800001ce: 000806b7 lui a3,0x80
+800001d2: 8afd andi a3,a3,31
+800001d4: c636 sw a3,12(sp)
+800001d6: 00080737 lui a4,0x80
+800001da: 9b05 andi a4,a4,-31
+800001dc: c83a sw a4,16(sp)
+800001de: 00001517 auipc a0,0x1
+800001e2: e2250513 addi a0,a0,-478 # 80001000
+800001e6: 00001597 auipc a1,0x1
+800001ea: e8a58593 addi a1,a1,-374 # 80001070 <_end>
+800001ee: f0100637 lui a2,0xf0100
+800001f2: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700feebc>
+
+800001f6 :
+800001f6: 00b50c63 beq a0,a1,8000020e
+800001fa: 4554 lw a3,12(a0)
+800001fc: c214 sw a3,0(a2)
+800001fe: 4514 lw a3,8(a0)
+80000200: c214 sw a3,0(a2)
+80000202: 4154 lw a3,4(a0)
+80000204: c214 sw a3,0(a2)
+80000206: 4114 lw a3,0(a0)
+80000208: c214 sw a3,0(a2)
+8000020a: 0541 addi a0,a0,16
+8000020c: b7ed j 800001f6
+
+8000020e :
+8000020e: f0100537 lui a0,0xf0100
+80000212: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700feeb0>
+80000216: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+
+80001014 :
+80001014: ffff 0xffff
+80001016: ffff 0xffff
+80001018: ffff 0xffff
+8000101a: ffff 0xffff
+8000101c: ffff 0xffff
+8000101e: ffff 0xffff
+80001020: ffff 0xffff
+80001022: ffff 0xffff
+80001024: ffff 0xffff
+80001026: ffff 0xffff
+
+80001028 :
+80001028: ffff 0xffff
+8000102a: ffff 0xffff
+8000102c: ffff 0xffff
+8000102e: ffff 0xffff
+80001030: ffff 0xffff
+80001032: ffff 0xffff
+80001034: ffff 0xffff
+80001036: ffff 0xffff
+80001038: ffff 0xffff
+8000103a: ffff 0xffff
+
+8000103c :
+8000103c: ffff 0xffff
+8000103e: ffff 0xffff
+80001040: ffff 0xffff
+80001042: ffff 0xffff
+80001044: ffff 0xffff
+80001046: ffff 0xffff
+80001048: ffff 0xffff
+8000104a: ffff 0xffff
+8000104c: ffff 0xffff
+8000104e: ffff 0xffff
+
+80001050 :
+80001050: ffff 0xffff
+80001052: ffff 0xffff
+80001054: ffff 0xffff
+80001056: ffff 0xffff
+80001058: ffff 0xffff
+8000105a: ffff 0xffff
+8000105c: ffff 0xffff
+8000105e: ffff 0xffff
+80001060: ffff 0xffff
+80001062: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.BEQZ.elf.objdump b/src/test/resources/asm/C.BEQZ.elf.objdump
new file mode 100644
index 0000000..f94b96f
--- /dev/null
+++ b/src/test/resources/asm/C.BEQZ.elf.objdump
@@ -0,0 +1,215 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.BEQZ.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4781 li a5,0
+800000f8: 8f9d sub a5,a5,a5
+800000fa: c789 beqz a5,80000104 <_start+0x104>
+800000fc: 000127b7 lui a5,0x12
+80000100: 3ab78793 addi a5,a5,939 # 123ab <_start-0x7ffedc55>
+80000104: c03e sw a5,0(sp)
+80000106: 00001117 auipc sp,0x1
+8000010a: efe10113 addi sp,sp,-258 # 80001004
+8000010e: 4405 li s0,1
+80000110: 8c01 sub s0,s0,s0
+80000112: c409 beqz s0,8000011c <_start+0x11c>
+80000114: 00012437 lui s0,0x12
+80000118: 3ab40413 addi s0,s0,939 # 123ab <_start-0x7ffedc55>
+8000011c: c022 sw s0,0(sp)
+8000011e: 00001117 auipc sp,0x1
+80000122: eea10113 addi sp,sp,-278 # 80001008
+80000126: 54fd li s1,-1
+80000128: 8c85 sub s1,s1,s1
+8000012a: c489 beqz s1,80000134 <_start+0x134>
+8000012c: 000124b7 lui s1,0x12
+80000130: 3ab48493 addi s1,s1,939 # 123ab <_start-0x7ffedc55>
+80000134: c026 sw s1,0(sp)
+80000136: 00001117 auipc sp,0x1
+8000013a: ed610113 addi sp,sp,-298 # 8000100c
+8000013e: 000085b7 lui a1,0x8
+80000142: fff58593 addi a1,a1,-1 # 7fff <_start-0x7fff8001>
+80000146: 8d8d sub a1,a1,a1
+80000148: c589 beqz a1,80000152 <_start+0x152>
+8000014a: 000125b7 lui a1,0x12
+8000014e: 3ab58593 addi a1,a1,939 # 123ab <_start-0x7ffedc55>
+80000152: c02e sw a1,0(sp)
+80000154: 00001117 auipc sp,0x1
+80000158: ebc10113 addi sp,sp,-324 # 80001010
+8000015c: 6621 lui a2,0x8
+8000015e: 8e11 sub a2,a2,a2
+80000160: c609 beqz a2,8000016a <_start+0x16a>
+80000162: 00012637 lui a2,0x12
+80000166: 3ab60613 addi a2,a2,939 # 123ab <_start-0x7ffedc55>
+8000016a: c032 sw a2,0(sp)
+8000016c: 00001517 auipc a0,0x1
+80000170: e9450513 addi a0,a0,-364 # 80001000
+80000174: 00001597 auipc a1,0x1
+80000178: eac58593 addi a1,a1,-340 # 80001020 <_end>
+8000017c: f0100637 lui a2,0xf0100
+80000180: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fef0c>
+
+80000184 :
+80000184: 00b50c63 beq a0,a1,8000019c
+80000188: 4554 lw a3,12(a0)
+8000018a: c214 sw a3,0(a2)
+8000018c: 4514 lw a3,8(a0)
+8000018e: c214 sw a3,0(a2)
+80000190: 4154 lw a3,4(a0)
+80000192: c214 sw a3,0(a2)
+80000194: 4114 lw a3,0(a0)
+80000196: c214 sw a3,0(a2)
+80000198: 0541 addi a0,a0,16
+8000019a: b7ed j 80000184
+
+8000019c :
+8000019c: f0100537 lui a0,0xf0100
+800001a0: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fef00>
+800001a4: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.BNEZ.elf.objdump b/src/test/resources/asm/C.BNEZ.elf.objdump
new file mode 100644
index 0000000..1519203
--- /dev/null
+++ b/src/test/resources/asm/C.BNEZ.elf.objdump
@@ -0,0 +1,205 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.BNEZ.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4681 li a3,0
+800000f8: e291 bnez a3,800000fc <_start+0xfc>
+800000fa: 4681 li a3,0
+800000fc: c036 sw a3,0(sp)
+800000fe: 00001117 auipc sp,0x1
+80000102: f0610113 addi sp,sp,-250 # 80001004
+80000106: 4705 li a4,1
+80000108: e311 bnez a4,8000010c <_start+0x10c>
+8000010a: 4701 li a4,0
+8000010c: c03a sw a4,0(sp)
+8000010e: 00001117 auipc sp,0x1
+80000112: efa10113 addi sp,sp,-262 # 80001008
+80000116: 57fd li a5,-1
+80000118: e391 bnez a5,8000011c <_start+0x11c>
+8000011a: 4781 li a5,0
+8000011c: c03e sw a5,0(sp)
+8000011e: 00001117 auipc sp,0x1
+80000122: eee10113 addi sp,sp,-274 # 8000100c
+80000126: 00008437 lui s0,0x8
+8000012a: fff40413 addi s0,s0,-1 # 7fff <_start-0x7fff8001>
+8000012e: e011 bnez s0,80000132 <_start+0x132>
+80000130: 4401 li s0,0
+80000132: c022 sw s0,0(sp)
+80000134: 00001117 auipc sp,0x1
+80000138: edc10113 addi sp,sp,-292 # 80001010
+8000013c: 64a1 lui s1,0x8
+8000013e: e091 bnez s1,80000142 <_start+0x142>
+80000140: 4481 li s1,0
+80000142: c026 sw s1,0(sp)
+80000144: 00001517 auipc a0,0x1
+80000148: ebc50513 addi a0,a0,-324 # 80001000
+8000014c: 00001597 auipc a1,0x1
+80000150: ed458593 addi a1,a1,-300 # 80001020 <_end>
+80000154: f0100637 lui a2,0xf0100
+80000158: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fef0c>
+
+8000015c :
+8000015c: 00b50c63 beq a0,a1,80000174
+80000160: 4554 lw a3,12(a0)
+80000162: c214 sw a3,0(a2)
+80000164: 4514 lw a3,8(a0)
+80000166: c214 sw a3,0(a2)
+80000168: 4154 lw a3,4(a0)
+8000016a: c214 sw a3,0(a2)
+8000016c: 4114 lw a3,0(a0)
+8000016e: c214 sw a3,0(a2)
+80000170: 0541 addi a0,a0,16
+80000172: b7ed j 8000015c
+
+80000174 :
+80000174: f0100537 lui a0,0xf0100
+80000178: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fef00>
+8000017c: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.J.elf.objdump b/src/test/resources/asm/C.J.elf.objdump
new file mode 100644
index 0000000..717bca1
--- /dev/null
+++ b/src/test/resources/asm/C.J.elf.objdump
@@ -0,0 +1,211 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.J.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4581 li a1,0
+800000f8: a029 j 80000102 <_start+0x102>
+800000fa: 000125b7 lui a1,0x12
+800000fe: 3ab58593 addi a1,a1,939 # 123ab <_start-0x7ffedc55>
+80000102: c02e sw a1,0(sp)
+80000104: 00001117 auipc sp,0x1
+80000108: f0010113 addi sp,sp,-256 # 80001004
+8000010c: 4605 li a2,1
+8000010e: a029 j 80000118 <_start+0x118>
+80000110: 00012637 lui a2,0x12
+80000114: 3ab60613 addi a2,a2,939 # 123ab <_start-0x7ffedc55>
+80000118: c032 sw a2,0(sp)
+8000011a: 00001117 auipc sp,0x1
+8000011e: eee10113 addi sp,sp,-274 # 80001008
+80000122: 56fd li a3,-1
+80000124: a029 j 8000012e <_start+0x12e>
+80000126: 000126b7 lui a3,0x12
+8000012a: 3ab68693 addi a3,a3,939 # 123ab <_start-0x7ffedc55>
+8000012e: c036 sw a3,0(sp)
+80000130: 00001117 auipc sp,0x1
+80000134: edc10113 addi sp,sp,-292 # 8000100c
+80000138: 00008737 lui a4,0x8
+8000013c: fff70713 addi a4,a4,-1 # 7fff <_start-0x7fff8001>
+80000140: a029 j 8000014a <_start+0x14a>
+80000142: 00012737 lui a4,0x12
+80000146: 3ab70713 addi a4,a4,939 # 123ab <_start-0x7ffedc55>
+8000014a: c03a sw a4,0(sp)
+8000014c: 00001117 auipc sp,0x1
+80000150: ec410113 addi sp,sp,-316 # 80001010
+80000154: 67a1 lui a5,0x8
+80000156: a029 j 80000160 <_start+0x160>
+80000158: 000127b7 lui a5,0x12
+8000015c: 3ab78793 addi a5,a5,939 # 123ab <_start-0x7ffedc55>
+80000160: c03e sw a5,0(sp)
+80000162: 00001517 auipc a0,0x1
+80000166: e9e50513 addi a0,a0,-354 # 80001000
+8000016a: 00001597 auipc a1,0x1
+8000016e: eb658593 addi a1,a1,-330 # 80001020 <_end>
+80000172: f0100637 lui a2,0xf0100
+80000176: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fef0c>
+
+8000017a :
+8000017a: 00b50c63 beq a0,a1,80000192
+8000017e: 4554 lw a3,12(a0)
+80000180: c214 sw a3,0(a2)
+80000182: 4514 lw a3,8(a0)
+80000184: c214 sw a3,0(a2)
+80000186: 4154 lw a3,4(a0)
+80000188: c214 sw a3,0(a2)
+8000018a: 4114 lw a3,0(a0)
+8000018c: c214 sw a3,0(a2)
+8000018e: 0541 addi a0,a0,16
+80000190: b7ed j 8000017a
+
+80000192 :
+80000192: f0100537 lui a0,0xf0100
+80000196: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fef00>
+8000019a: 00052023 sw zero,0(a0)
+8000019e: 0000 unimp
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.JAL.elf.objdump b/src/test/resources/asm/C.JAL.elf.objdump
new file mode 100644
index 0000000..b8a4de7
--- /dev/null
+++ b/src/test/resources/asm/C.JAL.elf.objdump
@@ -0,0 +1,211 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.JAL.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4401 li s0,0
+800000f8: 2029 jal 80000102 <_start+0x102>
+800000fa: 00012437 lui s0,0x12
+800000fe: 3ab40413 addi s0,s0,939 # 123ab <_start-0x7ffedc55>
+80000102: c022 sw s0,0(sp)
+80000104: 00001117 auipc sp,0x1
+80000108: f0010113 addi sp,sp,-256 # 80001004
+8000010c: 4485 li s1,1
+8000010e: 2029 jal 80000118 <_start+0x118>
+80000110: 000124b7 lui s1,0x12
+80000114: 3ab48493 addi s1,s1,939 # 123ab <_start-0x7ffedc55>
+80000118: c026 sw s1,0(sp)
+8000011a: 00001117 auipc sp,0x1
+8000011e: eee10113 addi sp,sp,-274 # 80001008
+80000122: 55fd li a1,-1
+80000124: 2029 jal 8000012e <_start+0x12e>
+80000126: 000125b7 lui a1,0x12
+8000012a: 3ab58593 addi a1,a1,939 # 123ab <_start-0x7ffedc55>
+8000012e: c02e sw a1,0(sp)
+80000130: 00001117 auipc sp,0x1
+80000134: edc10113 addi sp,sp,-292 # 8000100c
+80000138: 00008637 lui a2,0x8
+8000013c: fff60613 addi a2,a2,-1 # 7fff <_start-0x7fff8001>
+80000140: 2029 jal 8000014a <_start+0x14a>
+80000142: 00012637 lui a2,0x12
+80000146: 3ab60613 addi a2,a2,939 # 123ab <_start-0x7ffedc55>
+8000014a: c032 sw a2,0(sp)
+8000014c: 00001117 auipc sp,0x1
+80000150: ec410113 addi sp,sp,-316 # 80001010
+80000154: 66a1 lui a3,0x8
+80000156: 2029 jal 80000160 <_start+0x160>
+80000158: 000126b7 lui a3,0x12
+8000015c: 3ab68693 addi a3,a3,939 # 123ab <_start-0x7ffedc55>
+80000160: c036 sw a3,0(sp)
+80000162: 00001517 auipc a0,0x1
+80000166: e9e50513 addi a0,a0,-354 # 80001000
+8000016a: 00001597 auipc a1,0x1
+8000016e: eb658593 addi a1,a1,-330 # 80001020 <_end>
+80000172: f0100637 lui a2,0xf0100
+80000176: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fef0c>
+
+8000017a :
+8000017a: 00b50c63 beq a0,a1,80000192
+8000017e: 4554 lw a3,12(a0)
+80000180: c214 sw a3,0(a2)
+80000182: 4514 lw a3,8(a0)
+80000184: c214 sw a3,0(a2)
+80000186: 4154 lw a3,4(a0)
+80000188: c214 sw a3,0(a2)
+8000018a: 4114 lw a3,0(a0)
+8000018c: c214 sw a3,0(a2)
+8000018e: 0541 addi a0,a0,16
+80000190: b7ed j 8000017a
+
+80000192 :
+80000192: f0100537 lui a0,0xf0100
+80000196: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fef00>
+8000019a: 00052023 sw zero,0(a0)
+8000019e: 0000 unimp
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.JALR.elf.objdump b/src/test/resources/asm/C.JALR.elf.objdump
new file mode 100644
index 0000000..2959f30
--- /dev/null
+++ b/src/test/resources/asm/C.JALR.elf.objdump
@@ -0,0 +1,220 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.JALR.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4501 li a0,0
+800000f8: 00000617 auipc a2,0x0
+800000fc: 01260613 addi a2,a2,18 # 8000010a <_start+0x10a>
+80000100: 9602 jalr a2
+80000102: 00012537 lui a0,0x12
+80000106: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+8000010a: c032 sw a2,0(sp)
+8000010c: 00001117 auipc sp,0x1
+80000110: ef810113 addi sp,sp,-264 # 80001004
+80000114: 4505 li a0,1
+80000116: 00000697 auipc a3,0x0
+8000011a: 01268693 addi a3,a3,18 # 80000128 <_start+0x128>
+8000011e: 9682 jalr a3
+80000120: 00012537 lui a0,0x12
+80000124: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+80000128: c036 sw a3,0(sp)
+8000012a: 00001117 auipc sp,0x1
+8000012e: ede10113 addi sp,sp,-290 # 80001008
+80000132: 557d li a0,-1
+80000134: 00000717 auipc a4,0x0
+80000138: 01270713 addi a4,a4,18 # 80000146 <_start+0x146>
+8000013c: 9702 jalr a4
+8000013e: 00012537 lui a0,0x12
+80000142: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+80000146: c03a sw a4,0(sp)
+80000148: 00001117 auipc sp,0x1
+8000014c: ec410113 addi sp,sp,-316 # 8000100c
+80000150: 00008537 lui a0,0x8
+80000154: fff50513 addi a0,a0,-1 # 7fff <_start-0x7fff8001>
+80000158: 00000797 auipc a5,0x0
+8000015c: 01278793 addi a5,a5,18 # 8000016a <_start+0x16a>
+80000160: 9782 jalr a5
+80000162: 00012537 lui a0,0x12
+80000166: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+8000016a: c03e sw a5,0(sp)
+8000016c: 00001117 auipc sp,0x1
+80000170: ea410113 addi sp,sp,-348 # 80001010
+80000174: 6521 lui a0,0x8
+80000176: 00000817 auipc a6,0x0
+8000017a: 01280813 addi a6,a6,18 # 80000188 <_start+0x188>
+8000017e: 9802 jalr a6
+80000180: 00012537 lui a0,0x12
+80000184: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+80000188: c042 sw a6,0(sp)
+8000018a: 00001517 auipc a0,0x1
+8000018e: e7650513 addi a0,a0,-394 # 80001000
+80000192: 00001597 auipc a1,0x1
+80000196: e8e58593 addi a1,a1,-370 # 80001020 <_end>
+8000019a: f0100637 lui a2,0xf0100
+8000019e: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fef0c>
+
+800001a2 :
+800001a2: 00b50c63 beq a0,a1,800001ba
+800001a6: 4554 lw a3,12(a0)
+800001a8: c214 sw a3,0(a2)
+800001aa: 4514 lw a3,8(a0)
+800001ac: c214 sw a3,0(a2)
+800001ae: 4154 lw a3,4(a0)
+800001b0: c214 sw a3,0(a2)
+800001b2: 4114 lw a3,0(a0)
+800001b4: c214 sw a3,0(a2)
+800001b6: 0541 addi a0,a0,16
+800001b8: b7ed j 800001a2
+
+800001ba :
+800001ba: f0100537 lui a0,0xf0100
+800001be: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fef00>
+800001c2: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.JR.elf.objdump b/src/test/resources/asm/C.JR.elf.objdump
new file mode 100644
index 0000000..0b05122
--- /dev/null
+++ b/src/test/resources/asm/C.JR.elf.objdump
@@ -0,0 +1,220 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.JR.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4501 li a0,0
+800000f8: 00000197 auipc gp,0x0
+800000fc: 01218193 addi gp,gp,18 # 8000010a <_start+0x10a>
+80000100: 8182 jr gp
+80000102: 00012537 lui a0,0x12
+80000106: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+8000010a: c00e sw gp,0(sp)
+8000010c: 00001117 auipc sp,0x1
+80000110: ef810113 addi sp,sp,-264 # 80001004
+80000114: 4505 li a0,1
+80000116: 00000217 auipc tp,0x0
+8000011a: 01220213 addi tp,tp,18 # 80000128 <_start+0x128>
+8000011e: 8202 jr tp
+80000120: 00012537 lui a0,0x12
+80000124: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+80000128: c012 sw tp,0(sp)
+8000012a: 00001117 auipc sp,0x1
+8000012e: ede10113 addi sp,sp,-290 # 80001008
+80000132: 557d li a0,-1
+80000134: 00000417 auipc s0,0x0
+80000138: 01240413 addi s0,s0,18 # 80000146 <_start+0x146>
+8000013c: 8402 jr s0
+8000013e: 00012537 lui a0,0x12
+80000142: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+80000146: c022 sw s0,0(sp)
+80000148: 00001117 auipc sp,0x1
+8000014c: ec410113 addi sp,sp,-316 # 8000100c
+80000150: 00008537 lui a0,0x8
+80000154: fff50513 addi a0,a0,-1 # 7fff <_start-0x7fff8001>
+80000158: 00000497 auipc s1,0x0
+8000015c: 01248493 addi s1,s1,18 # 8000016a <_start+0x16a>
+80000160: 8482 jr s1
+80000162: 00012537 lui a0,0x12
+80000166: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+8000016a: c026 sw s1,0(sp)
+8000016c: 00001117 auipc sp,0x1
+80000170: ea410113 addi sp,sp,-348 # 80001010
+80000174: 6521 lui a0,0x8
+80000176: 00000597 auipc a1,0x0
+8000017a: 01258593 addi a1,a1,18 # 80000188 <_start+0x188>
+8000017e: 8582 jr a1
+80000180: 00012537 lui a0,0x12
+80000184: 3ab50513 addi a0,a0,939 # 123ab <_start-0x7ffedc55>
+80000188: c02e sw a1,0(sp)
+8000018a: 00001517 auipc a0,0x1
+8000018e: e7650513 addi a0,a0,-394 # 80001000
+80000192: 00001597 auipc a1,0x1
+80000196: e8e58593 addi a1,a1,-370 # 80001020 <_end>
+8000019a: f0100637 lui a2,0xf0100
+8000019e: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fef0c>
+
+800001a2 :
+800001a2: 00b50c63 beq a0,a1,800001ba
+800001a6: 4554 lw a3,12(a0)
+800001a8: c214 sw a3,0(a2)
+800001aa: 4514 lw a3,8(a0)
+800001ac: c214 sw a3,0(a2)
+800001ae: 4154 lw a3,4(a0)
+800001b0: c214 sw a3,0(a2)
+800001b2: 4114 lw a3,0(a0)
+800001b4: c214 sw a3,0(a2)
+800001b6: 0541 addi a0,a0,16
+800001b8: b7ed j 800001a2
+
+800001ba :
+800001ba: f0100537 lui a0,0xf0100
+800001be: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fef00>
+800001c2: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.LI.elf.objdump b/src/test/resources/asm/C.LI.elf.objdump
new file mode 100644
index 0000000..f1b51bd
--- /dev/null
+++ b/src/test/resources/asm/C.LI.elf.objdump
@@ -0,0 +1,304 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.LI.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4181 li gp,0
+800000f8: 4181 li gp,0
+800000fa: c00e sw gp,0(sp)
+800000fc: 4201 li tp,0
+800000fe: 4205 li tp,1
+80000100: c212 sw tp,4(sp)
+80000102: 4401 li s0,0
+80000104: 4441 li s0,16
+80000106: c422 sw s0,8(sp)
+80000108: 4481 li s1,0
+8000010a: 44fd li s1,31
+8000010c: c626 sw s1,12(sp)
+8000010e: 4581 li a1,0
+80000110: 5585 li a1,-31
+80000112: c82e sw a1,16(sp)
+80000114: 00001117 auipc sp,0x1
+80000118: f0010113 addi sp,sp,-256 # 80001014
+8000011c: 4605 li a2,1
+8000011e: 4601 li a2,0
+80000120: c032 sw a2,0(sp)
+80000122: 4685 li a3,1
+80000124: 4685 li a3,1
+80000126: c236 sw a3,4(sp)
+80000128: 4705 li a4,1
+8000012a: 4741 li a4,16
+8000012c: c43a sw a4,8(sp)
+8000012e: 4785 li a5,1
+80000130: 47fd li a5,31
+80000132: c63e sw a5,12(sp)
+80000134: 4805 li a6,1
+80000136: 5805 li a6,-31
+80000138: c842 sw a6,16(sp)
+8000013a: 00001117 auipc sp,0x1
+8000013e: eee10113 addi sp,sp,-274 # 80001028
+80000142: fff00893 li a7,-1
+80000146: 4881 li a7,0
+80000148: c046 sw a7,0(sp)
+8000014a: fff00913 li s2,-1
+8000014e: 4905 li s2,1
+80000150: c24a sw s2,4(sp)
+80000152: fff00993 li s3,-1
+80000156: 49c1 li s3,16
+80000158: c44e sw s3,8(sp)
+8000015a: fff00a13 li s4,-1
+8000015e: 4a7d li s4,31
+80000160: c652 sw s4,12(sp)
+80000162: fff00a93 li s5,-1
+80000166: 5a85 li s5,-31
+80000168: c856 sw s5,16(sp)
+8000016a: 00001117 auipc sp,0x1
+8000016e: ed210113 addi sp,sp,-302 # 8000103c
+80000172: 00080b37 lui s6,0x80
+80000176: fffb0b13 addi s6,s6,-1 # 7ffff <_start-0x7ff80001>
+8000017a: 4b01 li s6,0
+8000017c: c05a sw s6,0(sp)
+8000017e: 00080bb7 lui s7,0x80
+80000182: fffb8b93 addi s7,s7,-1 # 7ffff <_start-0x7ff80001>
+80000186: 4b85 li s7,1
+80000188: c25e sw s7,4(sp)
+8000018a: 00080c37 lui s8,0x80
+8000018e: fffc0c13 addi s8,s8,-1 # 7ffff <_start-0x7ff80001>
+80000192: 4c41 li s8,16
+80000194: c462 sw s8,8(sp)
+80000196: 00080cb7 lui s9,0x80
+8000019a: fffc8c93 addi s9,s9,-1 # 7ffff <_start-0x7ff80001>
+8000019e: 4cfd li s9,31
+800001a0: c666 sw s9,12(sp)
+800001a2: 00080d37 lui s10,0x80
+800001a6: fffd0d13 addi s10,s10,-1 # 7ffff <_start-0x7ff80001>
+800001aa: 5d05 li s10,-31
+800001ac: c86a sw s10,16(sp)
+800001ae: 00001117 auipc sp,0x1
+800001b2: ea210113 addi sp,sp,-350 # 80001050
+800001b6: 00080db7 lui s11,0x80
+800001ba: 4d81 li s11,0
+800001bc: c06e sw s11,0(sp)
+800001be: 00080e37 lui t3,0x80
+800001c2: 4e05 li t3,1
+800001c4: c272 sw t3,4(sp)
+800001c6: 00080eb7 lui t4,0x80
+800001ca: 4ec1 li t4,16
+800001cc: c476 sw t4,8(sp)
+800001ce: 00080f37 lui t5,0x80
+800001d2: 4f7d li t5,31
+800001d4: c67a sw t5,12(sp)
+800001d6: 00080fb7 lui t6,0x80
+800001da: 5f85 li t6,-31
+800001dc: c87e sw t6,16(sp)
+800001de: 00001517 auipc a0,0x1
+800001e2: e2250513 addi a0,a0,-478 # 80001000
+800001e6: 00001597 auipc a1,0x1
+800001ea: e8a58593 addi a1,a1,-374 # 80001070 <_end>
+800001ee: f0100637 lui a2,0xf0100
+800001f2: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700feebc>
+
+800001f6 :
+800001f6: 00b50c63 beq a0,a1,8000020e
+800001fa: 4554 lw a3,12(a0)
+800001fc: c214 sw a3,0(a2)
+800001fe: 4514 lw a3,8(a0)
+80000200: c214 sw a3,0(a2)
+80000202: 4154 lw a3,4(a0)
+80000204: c214 sw a3,0(a2)
+80000206: 4114 lw a3,0(a0)
+80000208: c214 sw a3,0(a2)
+8000020a: 0541 addi a0,a0,16
+8000020c: b7ed j 800001f6
+
+8000020e :
+8000020e: f0100537 lui a0,0xf0100
+80000212: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700feeb0>
+80000216: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+
+80001014 :
+80001014: ffff 0xffff
+80001016: ffff 0xffff
+80001018: ffff 0xffff
+8000101a: ffff 0xffff
+8000101c: ffff 0xffff
+8000101e: ffff 0xffff
+80001020: ffff 0xffff
+80001022: ffff 0xffff
+80001024: ffff 0xffff
+80001026: ffff 0xffff
+
+80001028 :
+80001028: ffff 0xffff
+8000102a: ffff 0xffff
+8000102c: ffff 0xffff
+8000102e: ffff 0xffff
+80001030: ffff 0xffff
+80001032: ffff 0xffff
+80001034: ffff 0xffff
+80001036: ffff 0xffff
+80001038: ffff 0xffff
+8000103a: ffff 0xffff
+
+8000103c :
+8000103c: ffff 0xffff
+8000103e: ffff 0xffff
+80001040: ffff 0xffff
+80001042: ffff 0xffff
+80001044: ffff 0xffff
+80001046: ffff 0xffff
+80001048: ffff 0xffff
+8000104a: ffff 0xffff
+8000104c: ffff 0xffff
+8000104e: ffff 0xffff
+
+80001050 :
+80001050: ffff 0xffff
+80001052: ffff 0xffff
+80001054: ffff 0xffff
+80001056: ffff 0xffff
+80001058: ffff 0xffff
+8000105a: ffff 0xffff
+8000105c: ffff 0xffff
+8000105e: ffff 0xffff
+80001060: ffff 0xffff
+80001062: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.LUI.elf.objdump b/src/test/resources/asm/C.LUI.elf.objdump
new file mode 100644
index 0000000..980309e
--- /dev/null
+++ b/src/test/resources/asm/C.LUI.elf.objdump
@@ -0,0 +1,304 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.LUI.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4181 li gp,0
+800000f8: 6185 lui gp,0x1
+800000fa: c00e sw gp,0(sp)
+800000fc: 4201 li tp,0
+800000fe: 6209 lui tp,0x2
+80000100: c212 sw tp,4(sp)
+80000102: 4401 li s0,0
+80000104: 643d lui s0,0xf
+80000106: c422 sw s0,8(sp)
+80000108: 4481 li s1,0
+8000010a: 64fd lui s1,0x1f
+8000010c: c626 sw s1,12(sp)
+8000010e: 4581 li a1,0
+80000110: 75fd lui a1,0xfffff
+80000112: c82e sw a1,16(sp)
+80000114: 00001117 auipc sp,0x1
+80000118: f0010113 addi sp,sp,-256 # 80001014
+8000011c: 4605 li a2,1
+8000011e: 6605 lui a2,0x1
+80000120: c032 sw a2,0(sp)
+80000122: 4685 li a3,1
+80000124: 6689 lui a3,0x2
+80000126: c236 sw a3,4(sp)
+80000128: 4705 li a4,1
+8000012a: 673d lui a4,0xf
+8000012c: c43a sw a4,8(sp)
+8000012e: 4785 li a5,1
+80000130: 67fd lui a5,0x1f
+80000132: c63e sw a5,12(sp)
+80000134: 4805 li a6,1
+80000136: 787d lui a6,0xfffff
+80000138: c842 sw a6,16(sp)
+8000013a: 00001117 auipc sp,0x1
+8000013e: eee10113 addi sp,sp,-274 # 80001028
+80000142: fff00893 li a7,-1
+80000146: 6885 lui a7,0x1
+80000148: c046 sw a7,0(sp)
+8000014a: fff00913 li s2,-1
+8000014e: 6909 lui s2,0x2
+80000150: c24a sw s2,4(sp)
+80000152: fff00993 li s3,-1
+80000156: 69bd lui s3,0xf
+80000158: c44e sw s3,8(sp)
+8000015a: fff00a13 li s4,-1
+8000015e: 6a7d lui s4,0x1f
+80000160: c652 sw s4,12(sp)
+80000162: fff00a93 li s5,-1
+80000166: 7afd lui s5,0xfffff
+80000168: c856 sw s5,16(sp)
+8000016a: 00001117 auipc sp,0x1
+8000016e: ed210113 addi sp,sp,-302 # 8000103c
+80000172: 00080b37 lui s6,0x80
+80000176: fffb0b13 addi s6,s6,-1 # 7ffff <_start-0x7ff80001>
+8000017a: 6b05 lui s6,0x1
+8000017c: c05a sw s6,0(sp)
+8000017e: 00080bb7 lui s7,0x80
+80000182: fffb8b93 addi s7,s7,-1 # 7ffff <_start-0x7ff80001>
+80000186: 6b89 lui s7,0x2
+80000188: c25e sw s7,4(sp)
+8000018a: 00080c37 lui s8,0x80
+8000018e: fffc0c13 addi s8,s8,-1 # 7ffff <_start-0x7ff80001>
+80000192: 6c3d lui s8,0xf
+80000194: c462 sw s8,8(sp)
+80000196: 00080cb7 lui s9,0x80
+8000019a: fffc8c93 addi s9,s9,-1 # 7ffff <_start-0x7ff80001>
+8000019e: 6cfd lui s9,0x1f
+800001a0: c666 sw s9,12(sp)
+800001a2: 00080d37 lui s10,0x80
+800001a6: fffd0d13 addi s10,s10,-1 # 7ffff <_start-0x7ff80001>
+800001aa: 7d7d lui s10,0xfffff
+800001ac: c86a sw s10,16(sp)
+800001ae: 00001117 auipc sp,0x1
+800001b2: ea210113 addi sp,sp,-350 # 80001050
+800001b6: 00080db7 lui s11,0x80
+800001ba: 6d85 lui s11,0x1
+800001bc: c06e sw s11,0(sp)
+800001be: 00080e37 lui t3,0x80
+800001c2: 6e09 lui t3,0x2
+800001c4: c272 sw t3,4(sp)
+800001c6: 00080eb7 lui t4,0x80
+800001ca: 6ebd lui t4,0xf
+800001cc: c476 sw t4,8(sp)
+800001ce: 00080f37 lui t5,0x80
+800001d2: 6f7d lui t5,0x1f
+800001d4: c67a sw t5,12(sp)
+800001d6: 00080fb7 lui t6,0x80
+800001da: 7ffd lui t6,0xfffff
+800001dc: c87e sw t6,16(sp)
+800001de: 00001517 auipc a0,0x1
+800001e2: e2250513 addi a0,a0,-478 # 80001000
+800001e6: 00001597 auipc a1,0x1
+800001ea: e8a58593 addi a1,a1,-374 # 80001070 <_end>
+800001ee: f0100637 lui a2,0xf0100
+800001f2: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700feebc>
+
+800001f6 :
+800001f6: 00b50c63 beq a0,a1,8000020e
+800001fa: 4554 lw a3,12(a0)
+800001fc: c214 sw a3,0(a2)
+800001fe: 4514 lw a3,8(a0)
+80000200: c214 sw a3,0(a2)
+80000202: 4154 lw a3,4(a0)
+80000204: c214 sw a3,0(a2)
+80000206: 4114 lw a3,0(a0)
+80000208: c214 sw a3,0(a2)
+8000020a: 0541 addi a0,a0,16
+8000020c: b7ed j 800001f6
+
+8000020e :
+8000020e: f0100537 lui a0,0xf0100
+80000212: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700feeb0>
+80000216: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+
+80001014 :
+80001014: ffff 0xffff
+80001016: ffff 0xffff
+80001018: ffff 0xffff
+8000101a: ffff 0xffff
+8000101c: ffff 0xffff
+8000101e: ffff 0xffff
+80001020: ffff 0xffff
+80001022: ffff 0xffff
+80001024: ffff 0xffff
+80001026: ffff 0xffff
+
+80001028 :
+80001028: ffff 0xffff
+8000102a: ffff 0xffff
+8000102c: ffff 0xffff
+8000102e: ffff 0xffff
+80001030: ffff 0xffff
+80001032: ffff 0xffff
+80001034: ffff 0xffff
+80001036: ffff 0xffff
+80001038: ffff 0xffff
+8000103a: ffff 0xffff
+
+8000103c :
+8000103c: ffff 0xffff
+8000103e: ffff 0xffff
+80001040: ffff 0xffff
+80001042: ffff 0xffff
+80001044: ffff 0xffff
+80001046: ffff 0xffff
+80001048: ffff 0xffff
+8000104a: ffff 0xffff
+8000104c: ffff 0xffff
+8000104e: ffff 0xffff
+
+80001050 :
+80001050: ffff 0xffff
+80001052: ffff 0xffff
+80001054: ffff 0xffff
+80001056: ffff 0xffff
+80001058: ffff 0xffff
+8000105a: ffff 0xffff
+8000105c: ffff 0xffff
+8000105e: ffff 0xffff
+80001060: ffff 0xffff
+80001062: ffff 0xffff
+ ...
diff --git a/src/test/resources/asm/C.LW.elf.objdump b/src/test/resources/asm/C.LW.elf.objdump
new file mode 100644
index 0000000..93bca0e
--- /dev/null
+++ b/src/test/resources/asm/C.LW.elf.objdump
@@ -0,0 +1,263 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.LW.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 00001717 auipc a4,0x1
+800000fa: f1e70713 addi a4,a4,-226 # 80001014
+800000fe: 4318 lw a4,0(a4)
+80000100: c03a sw a4,0(sp)
+80000102: 00001117 auipc sp,0x1
+80000106: f0210113 addi sp,sp,-254 # 80001004
+8000010a: 00001797 auipc a5,0x1
+8000010e: f0a78793 addi a5,a5,-246 # 80001014
+80000112: 43dc lw a5,4(a5)
+80000114: c03e sw a5,0(sp)
+80000116: 00001117 auipc sp,0x1
+8000011a: ef210113 addi sp,sp,-270 # 80001008
+8000011e: 00001417 auipc s0,0x1
+80000122: ef640413 addi s0,s0,-266 # 80001014
+80000126: 4400 lw s0,8(s0)
+80000128: c022 sw s0,0(sp)
+8000012a: 00001117 auipc sp,0x1
+8000012e: ee210113 addi sp,sp,-286 # 8000100c
+80000132: 00001497 auipc s1,0x1
+80000136: ee248493 addi s1,s1,-286 # 80001014
+8000013a: 50e4 lw s1,100(s1)
+8000013c: c026 sw s1,0(sp)
+8000013e: 00001117 auipc sp,0x1
+80000142: ed210113 addi sp,sp,-302 # 80001010
+80000146: 00001697 auipc a3,0x1
+8000014a: ece68693 addi a3,a3,-306 # 80001014
+8000014e: 5ef4 lw a3,124(a3)
+80000150: c036 sw a3,0(sp)
+80000152: 00001517 auipc a0,0x1
+80000156: eae50513 addi a0,a0,-338 # 80001000
+8000015a: 00001597 auipc a1,0x1
+8000015e: f4658593 addi a1,a1,-186 # 800010a0 <_end>
+80000162: f0100637 lui a2,0xf0100
+80000166: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fee8c>
+
+8000016a :
+8000016a: 00b50c63 beq a0,a1,80000182
+8000016e: 4554 lw a3,12(a0)
+80000170: c214 sw a3,0(a2)
+80000172: 4514 lw a3,8(a0)
+80000174: c214 sw a3,0(a2)
+80000176: 4154 lw a3,4(a0)
+80000178: c214 sw a3,0(a2)
+8000017a: 4114 lw a3,0(a0)
+8000017c: c214 sw a3,0(a2)
+8000017e: 0541 addi a0,a0,16
+80000180: b7ed j 8000016a
+
+80000182 :
+80000182: f0100537 lui a0,0xf0100
+80000186: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fee80>
+8000018a: 00052023 sw zero,0(a0)
+8000018e: 0000 unimp
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+
+80001014 :
+80001014: 0000 unimp
+80001016: 0000 unimp
+80001018: 0001 nop
+8000101a: 0000 unimp
+8000101c: 0002 c.slli zero,0x0
+8000101e: 0000 unimp
+80001020: 00000003 lb zero,0(zero) # 0 <_start-0x80000000>
+80001024: 0004 0x4
+80001026: 0000 unimp
+80001028: 0005 c.nop 1
+8000102a: 0000 unimp
+8000102c: 0006 c.slli zero,0x1
+8000102e: 0000 unimp
+80001030: 00000007 0x7
+80001034: 0008 0x8
+80001036: 0000 unimp
+80001038: 0009 c.nop 2
+8000103a: 0000 unimp
+8000103c: 000a c.slli zero,0x2
+8000103e: 0000 unimp
+80001040: 0000000b 0xb
+80001044: 000c 0xc
+80001046: 0000 unimp
+80001048: 000d c.nop 3
+8000104a: 0000 unimp
+8000104c: 000e c.slli zero,0x3
+8000104e: 0000 unimp
+80001050: 0000000f fence unknown,unknown
+80001054: 0010 0x10
+80001056: 0000 unimp
+80001058: 0011 c.nop 4
+8000105a: 0000 unimp
+8000105c: 0012 c.slli zero,0x4
+8000105e: 0000 unimp
+80001060: 00000013 nop
+80001064: 0014 0x14
+80001066: 0000 unimp
+80001068: 0015 c.nop 5
+8000106a: 0000 unimp
+8000106c: 0016 c.slli zero,0x5
+8000106e: 0000 unimp
+80001070: 00000017 auipc zero,0x0
+80001074: 0018 0x18
+80001076: 0000 unimp
+80001078: 0019 c.nop 6
+8000107a: 0000 unimp
+8000107c: 001a c.slli zero,0x6
+8000107e: 0000 unimp
+80001080: 0000001b 0x1b
+80001084: 001c 0x1c
+80001086: 0000 unimp
+80001088: 001d c.nop 7
+8000108a: 0000 unimp
+8000108c: 001e c.slli zero,0x7
+8000108e: 0000 unimp
+80001090: 001f 0000 0000 0x1f
+ ...
diff --git a/src/test/resources/asm/C.LWSP.elf.objdump b/src/test/resources/asm/C.LWSP.elf.objdump
new file mode 100644
index 0000000..a8f61ca
--- /dev/null
+++ b/src/test/resources/asm/C.LWSP.elf.objdump
@@ -0,0 +1,262 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.LWSP.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001097 auipc ra,0x1
+800000f2: f1208093 addi ra,ra,-238 # 80001000
+800000f6: 00001117 auipc sp,0x1
+800000fa: f1e10113 addi sp,sp,-226 # 80001014
+800000fe: 4202 lw tp,0(sp)
+80000100: 0040a023 sw tp,0(ra)
+80000104: 00001097 auipc ra,0x1
+80000108: f0008093 addi ra,ra,-256 # 80001004
+8000010c: 00001117 auipc sp,0x1
+80000110: f0810113 addi sp,sp,-248 # 80001014
+80000114: 4412 lw s0,4(sp)
+80000116: 0080a023 sw s0,0(ra)
+8000011a: 00001097 auipc ra,0x1
+8000011e: eee08093 addi ra,ra,-274 # 80001008
+80000122: 00001117 auipc sp,0x1
+80000126: ef210113 addi sp,sp,-270 # 80001014
+8000012a: 4822 lw a6,8(sp)
+8000012c: 0100a023 sw a6,0(ra)
+80000130: 00001097 auipc ra,0x1
+80000134: edc08093 addi ra,ra,-292 # 8000100c
+80000138: 00001117 auipc sp,0x1
+8000013c: edc10113 addi sp,sp,-292 # 80001014
+80000140: 5ff6 lw t6,124(sp)
+80000142: 01f0a023 sw t6,0(ra)
+80000146: 00001097 auipc ra,0x1
+8000014a: eca08093 addi ra,ra,-310 # 80001010
+8000014e: 00001117 auipc sp,0x1
+80000152: ec610113 addi sp,sp,-314 # 80001014
+80000156: 5afe lw s5,252(sp)
+80000158: 0150a023 sw s5,0(ra)
+8000015c: 00001517 auipc a0,0x1
+80000160: ea450513 addi a0,a0,-348 # 80001000
+80000164: 00001597 auipc a1,0x1
+80000168: f3c58593 addi a1,a1,-196 # 800010a0 <_end>
+8000016c: f0100637 lui a2,0xf0100
+80000170: f2c60613 addi a2,a2,-212 # f00fff2c <_end+0x700fee8c>
+
+80000174 :
+80000174: 00b50c63 beq a0,a1,8000018c
+80000178: 4554 lw a3,12(a0)
+8000017a: c214 sw a3,0(a2)
+8000017c: 4514 lw a3,8(a0)
+8000017e: c214 sw a3,0(a2)
+80000180: 4154 lw a3,4(a0)
+80000182: c214 sw a3,0(a2)
+80000184: 4114 lw a3,0(a0)
+80000186: c214 sw a3,0(a2)
+80000188: 0541 addi a0,a0,16
+8000018a: b7ed j 80000174
+
+8000018c :
+8000018c: f0100537 lui a0,0xf0100
+80000190: f2050513 addi a0,a0,-224 # f00fff20 <_end+0x700fee80>
+80000194: 00052023 sw zero,0(a0)
+ ...
+
+Disassembly of section .data:
+
+80001000 :
+80001000: ffff 0xffff
+80001002: ffff 0xffff
+
+80001004 :
+80001004: ffff 0xffff
+80001006: ffff 0xffff
+
+80001008 :
+80001008: ffff 0xffff
+8000100a: ffff 0xffff
+
+8000100c :
+8000100c: ffff 0xffff
+8000100e: ffff 0xffff
+
+80001010 :
+80001010: ffff 0xffff
+80001012: ffff 0xffff
+
+80001014 :
+80001014: 0000 unimp
+80001016: 0000 unimp
+80001018: 0001 nop
+8000101a: 0000 unimp
+8000101c: 0002 c.slli zero,0x0
+8000101e: 0000 unimp
+80001020: 00000003 lb zero,0(zero) # 0 <_start-0x80000000>
+80001024: 0004 0x4
+80001026: 0000 unimp
+80001028: 0005 c.nop 1
+8000102a: 0000 unimp
+8000102c: 0006 c.slli zero,0x1
+8000102e: 0000 unimp
+80001030: 00000007 0x7
+80001034: 0008 0x8
+80001036: 0000 unimp
+80001038: 0009 c.nop 2
+8000103a: 0000 unimp
+8000103c: 000a c.slli zero,0x2
+8000103e: 0000 unimp
+80001040: 0000000b 0xb
+80001044: 000c 0xc
+80001046: 0000 unimp
+80001048: 000d c.nop 3
+8000104a: 0000 unimp
+8000104c: 000e c.slli zero,0x3
+8000104e: 0000 unimp
+80001050: 0000000f fence unknown,unknown
+80001054: 0010 0x10
+80001056: 0000 unimp
+80001058: 0011 c.nop 4
+8000105a: 0000 unimp
+8000105c: 0012 c.slli zero,0x4
+8000105e: 0000 unimp
+80001060: 00000013 nop
+80001064: 0014 0x14
+80001066: 0000 unimp
+80001068: 0015 c.nop 5
+8000106a: 0000 unimp
+8000106c: 0016 c.slli zero,0x5
+8000106e: 0000 unimp
+80001070: 00000017 auipc zero,0x0
+80001074: 0018 0x18
+80001076: 0000 unimp
+80001078: 0019 c.nop 6
+8000107a: 0000 unimp
+8000107c: 001a c.slli zero,0x6
+8000107e: 0000 unimp
+80001080: 0000001b 0x1b
+80001084: 001c 0x1c
+80001086: 0000 unimp
+80001088: 001d c.nop 7
+8000108a: 0000 unimp
+8000108c: 001e c.slli zero,0x7
+8000108e: 0000 unimp
+80001090: 001f 0000 0000 0x1f
+ ...
diff --git a/src/test/resources/asm/C.MV.elf.objdump b/src/test/resources/asm/C.MV.elf.objdump
new file mode 100644
index 0000000..491d682
--- /dev/null
+++ b/src/test/resources/asm/C.MV.elf.objdump
@@ -0,0 +1,334 @@
+
+/home/spinalvm/hdl/riscv-compliance/work//C.MV.elf: file format elf32-littleriscv
+
+
+Disassembly of section .text.init:
+
+80000000 <_start>:
+80000000: 0001 nop
+80000002: 0001 nop
+80000004: 0001 nop
+80000006: 0001 nop
+80000008: 0001 nop
+8000000a: 0001 nop
+8000000c: 0001 nop
+8000000e: 0001 nop
+80000010: 0001 nop
+80000012: 0001 nop
+80000014: 0001 nop
+80000016: 0001 nop
+80000018: 0001 nop
+8000001a: 0001 nop
+8000001c: 0001 nop
+8000001e: 0001 nop
+80000020: 0001 nop
+80000022: 0001 nop
+80000024: 0001 nop
+80000026: 0001 nop
+80000028: 0001 nop
+8000002a: 0001 nop
+8000002c: 0001 nop
+8000002e: 0001 nop
+80000030: 0001 nop
+80000032: 0001 nop
+80000034: 0001 nop
+80000036: 0001 nop
+80000038: 0001 nop
+8000003a: 0001 nop
+8000003c: 0001 nop
+8000003e: 0001 nop
+80000040: 0001 nop
+80000042: 0001 nop
+80000044: 0001 nop
+80000046: 0001 nop
+80000048: 0001 nop
+8000004a: 0001 nop
+8000004c: 0001 nop
+8000004e: 0001 nop
+80000050: 0001 nop
+80000052: 0001 nop
+80000054: 0001 nop
+80000056: 0001 nop
+80000058: 0001 nop
+8000005a: 0001 nop
+8000005c: 0001 nop
+8000005e: 0001 nop
+80000060: 0001 nop
+80000062: 0001 nop
+80000064: 0001 nop
+80000066: 0001 nop
+80000068: 0001 nop
+8000006a: 0001 nop
+8000006c: 0001 nop
+8000006e: 0001 nop
+80000070: 0001 nop
+80000072: 0001 nop
+80000074: 0001 nop
+80000076: 0001 nop
+80000078: 0001 nop
+8000007a: 0001 nop
+8000007c: 0001 nop
+8000007e: 0001 nop
+80000080: 0001 nop
+80000082: 0001 nop
+80000084: 0001 nop
+80000086: 0001 nop
+80000088: 0001 nop
+8000008a: 0001 nop
+8000008c: 0001 nop
+8000008e: 0001 nop
+80000090: 0001 nop
+80000092: 0001 nop
+80000094: 0001 nop
+80000096: 0001 nop
+80000098: 0001 nop
+8000009a: 0001 nop
+8000009c: 0001 nop
+8000009e: 0001 nop
+800000a0: 0001 nop
+800000a2: 0001 nop
+800000a4: 0001 nop
+800000a6: 0001 nop
+800000a8: 0001 nop
+800000aa: 0001 nop
+800000ac: 0001 nop
+800000ae: 0001 nop
+800000b0: 0001 nop
+800000b2: 0001 nop
+800000b4: 0001 nop
+800000b6: 0001 nop
+800000b8: 0001 nop
+800000ba: 0001 nop
+800000bc: 0001 nop
+800000be: 0001 nop
+800000c0: 0001 nop
+800000c2: 0001 nop
+800000c4: 0001 nop
+800000c6: 0001 nop
+800000c8: 0001 nop
+800000ca: 0001 nop
+800000cc: 0001 nop
+800000ce: 0001 nop
+800000d0: 0001 nop
+800000d2: 0001 nop
+800000d4: 0001 nop
+800000d6: 0001 nop
+800000d8: 0001 nop
+800000da: 0001 nop
+800000dc: 0001 nop
+800000de: 0001 nop
+800000e0: 0001 nop
+800000e2: 0001 nop
+800000e4: 0001 nop
+800000e6: 0001 nop
+800000e8: 0001 nop
+800000ea: 0001 nop
+800000ec: 0001 nop
+800000ee: 00001117 auipc sp,0x1
+800000f2: f1210113 addi sp,sp,-238 # 80001000
+800000f6: 4601 li a2,0
+800000f8: 4581 li a1,0
+800000fa: 85b2 mv a1,a2
+800000fc: c02e sw a1,0(sp)
+800000fe: 4701 li a4,0
+80000100: 4685 li a3,1
+80000102: 86ba mv a3,a4
+80000104: c236 sw a3,4(sp)
+80000106: 4401 li s0,0
+80000108: fff00793 li a5,-1
+8000010c: 87a2 mv a5,s0
+8000010e: c43e sw a5,8(sp)
+80000110: 4581 li a1,0
+80000112: 000084b7 lui s1,0x8
+80000116: fff48493 addi s1,s1,-1 # 7fff <_start-0x7fff8001>
+8000011a: 84ae mv s1,a1
+8000011c: c626 sw s1,12(sp)
+8000011e: 4681 li a3,0
+80000120: 6621 lui a2,0x8
+80000122: 8636 mv a2,a3
+80000124: c832 sw a2,16(sp)
+80000126: 00001117 auipc sp,0x1
+8000012a: eee10113 addi sp,sp,-274 # 80001014