aboutsummaryrefslogtreecommitdiff
path: root/VexRiscv/src/test/cpp/regression
diff options
context:
space:
mode:
Diffstat (limited to 'VexRiscv/src/test/cpp/regression')
-rw-r--r--VexRiscv/src/test/cpp/regression/.gitignore3
-rw-r--r--VexRiscv/src/test/cpp/regression/atomic.gtkw52
-rw-r--r--VexRiscv/src/test/cpp/regression/branch.gtkw31
-rw-r--r--VexRiscv/src/test/cpp/regression/dcache.gtkw85
-rw-r--r--VexRiscv/src/test/cpp/regression/debug.gtkw96
-rw-r--r--VexRiscv/src/test/cpp/regression/default.gtkw100
-rw-r--r--VexRiscv/src/test/cpp/regression/dhrystoneO3.logRef57
-rw-r--r--VexRiscv/src/test/cpp/regression/dhrystoneO3C.logRef57
-rw-r--r--VexRiscv/src/test/cpp/regression/dhrystoneO3M.logRef57
-rw-r--r--VexRiscv/src/test/cpp/regression/dhrystoneO3MC.logRef57
-rw-r--r--VexRiscv/src/test/cpp/regression/encoding.h1471
-rw-r--r--VexRiscv/src/test/cpp/regression/fail.gtkw29
-rw-r--r--VexRiscv/src/test/cpp/regression/icache.gtkw67
-rw-r--r--VexRiscv/src/test/cpp/regression/main.cpp4514
-rw-r--r--VexRiscv/src/test/cpp/regression/makefile345
-rw-r--r--VexRiscv/src/test/cpp/regression/prediction.gtkw43
-rw-r--r--VexRiscv/src/test/cpp/regression/refDiff.gtkw40
-rw-r--r--VexRiscv/src/test/cpp/regression/wrongDiff.gtkw62
-rw-r--r--VexRiscv/src/test/cpp/regression/yolo.gtkw84
19 files changed, 7250 insertions, 0 deletions
diff --git a/VexRiscv/src/test/cpp/regression/.gitignore b/VexRiscv/src/test/cpp/regression/.gitignore
new file mode 100644
index 0000000..576890f
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/.gitignore
@@ -0,0 +1,3 @@
+*.regTraceRef
+/freertos.gtkw
+*.cproject
diff --git a/VexRiscv/src/test/cpp/regression/atomic.gtkw b/VexRiscv/src/test/cpp/regression/atomic.gtkw
new file mode 100644
index 0000000..26e6575
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/atomic.gtkw
@@ -0,0 +1,52 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Thu Jan 4 16:18:18 2018
+[*]
+[dumpfile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/atomic.vcd"
+[dumpfile_mtime] "Thu Jan 4 16:18:11 2018"
+[dumpfile_size] 19545269
+[savefile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/atomic.gtkw"
+[timestart] 1478
+[size] 1784 950
+[pos] -1 -1
+*-7.000000 1726 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[treeopen] TOP.VexRiscv.
+[sst_width] 289
+[signals_width] 559
+[sst_expanded] 1
+[sst_vpaned_height] 191
+@22
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_address[4:0]
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_data[31:0]
+@28
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_valid
+TOP.VexRiscv.dataCache_1.stageB_atomic_entriesHit
+@22
+TOP.VexRiscv.dataCache_1.stageB_atomic_entries_0_address[31:0]
+@28
+TOP.VexRiscv.dataCache_1.stageB_atomic_entries_0_size[1:0]
+TOP.VexRiscv.dataCache_1.stageB_atomic_entries_0_valid
+@22
+TOP.VexRiscv.dataCache_1.stageB_atomic_entries_1_address[31:0]
+@28
+TOP.VexRiscv.dataCache_1.stageB_atomic_entries_1_size[1:0]
+TOP.VexRiscv.dataCache_1.stageB_atomic_entries_1_valid
+@29
+[color] 1
+TOP.VexRiscv.writeBack_arbitration_isFiring
+[color] 1
+TOP.VexRiscv.writeBack_arbitration_isValid
+@23
+[color] 1
+TOP.VexRiscv.writeBack_PC[31:0]
+@28
+TOP.VexRiscv.CsrPlugin_mstatus_MIE
+TOP.VexRiscv.CsrPlugin_mstatus_MPIE
+TOP.VexRiscv.CsrPlugin_mstatus_MPP[1:0]
+@24
+TOP.VexRiscv.RegFilePlugin_regFile(28)[31:0]
+@22
+TOP.VexRiscv.CsrPlugin_mepc[31:0]
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/branch.gtkw b/VexRiscv/src/test/cpp/regression/branch.gtkw
new file mode 100644
index 0000000..9bd2437
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/branch.gtkw
@@ -0,0 +1,31 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Mon Mar 20 10:40:36 2017
+[*]
+[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/dhrystoneO3M.vcd"
+[dumpfile_mtime] "Mon Mar 20 10:40:36 2017"
+[dumpfile_size] 1149914709
+[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/branch.gtkw"
+[timestart] 68
+[size] 1776 953
+[pos] -775 -1
+*-4.000000 87 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[sst_width] 432
+[signals_width] 520
+[sst_expanded] 1
+[sst_vpaned_height] 279
+@28
+TOP.VexRiscv.execute_input_HISTORY_LINE_history[1:0]
+TOP.VexRiscv.fetch_HISTORY_LINE_history[1:0]
+TOP.VexRiscv.memory_input_HISTORY_LINE_history[1:0]
+TOP.VexRiscv.decode_arbitration_isValid
+TOP.VexRiscv.decode_arbitration_isFiring
+@22
+TOP.VexRiscv.decode_input_PC[31:0]
+@28
+TOP.VexRiscv.decode_input_HISTORY_LINE_history[1:0]
+@29
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_valid
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/dcache.gtkw b/VexRiscv/src/test/cpp/regression/dcache.gtkw
new file mode 100644
index 0000000..388eb87
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/dcache.gtkw
@@ -0,0 +1,85 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Sun Apr 23 13:26:26 2017
+[*]
+[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/rv32ui-p-sw.vcd"
+[dumpfile_mtime] "Sun Apr 23 13:04:48 2017"
+[dumpfile_size] 389364
+[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/dcache.gtkw"
+[timestart] 569
+[size] 1776 953
+[pos] -1 -353
+*-3.252876 591 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[treeopen] TOP.VexRiscv.
+[sst_width] 387
+[signals_width] 376
+[sst_expanded] 1
+[sst_vpaned_height] 253
+@800200
+-execute
+@28
+TOP.VexRiscv.dataCache_1.io_cpu_execute_isValid
+@22
+TOP.VexRiscv.dataCache_1.io_cpu_execute_args_address[31:0]
+@28
+TOP.VexRiscv.dataCache_1.io_cpu_execute_args_all
+TOP.VexRiscv.dataCache_1.io_cpu_execute_args_bypass
+@22
+TOP.VexRiscv.dataCache_1.io_cpu_execute_args_data[31:0]
+@28
+TOP.VexRiscv.dataCache_1.io_cpu_execute_args_kind[1:0]
+@22
+TOP.VexRiscv.dataCache_1.io_cpu_execute_args_mask[3:0]
+@28
+TOP.VexRiscv.dataCache_1.io_cpu_execute_args_wr
+TOP.VexRiscv.dataCache_1.io_cpu_execute_isStuck
+@1000200
+-execute
+@28
+TOP.VexRiscv.dataCache_1.io_cpu_memory_isStuck
+@800200
+-writeBack
+@22
+TOP.VexRiscv.dataCache_1.io_cpu_writeBack_data[31:0]
+@28
+TOP.VexRiscv.dataCache_1.io_cpu_writeBack_haltIt
+TOP.VexRiscv.dataCache_1.io_cpu_writeBack_isStuck
+TOP.VexRiscv.dataCache_1.io_cpu_writeBack_isValid
+@1000200
+-writeBack
+@22
+TOP.VexRiscv.dataCache_1.io_mem_cmd_payload_address[31:0]
+TOP.VexRiscv.dataCache_1.io_mem_cmd_payload_data[31:0]
+TOP.VexRiscv.dataCache_1.io_mem_cmd_payload_mask[3:0]
+@28
+TOP.VexRiscv.dataCache_1.io_mem_cmd_payload_wr
+TOP.VexRiscv.dataCache_1.io_mem_cmd_ready
+TOP.VexRiscv.dataCache_1.io_mem_cmd_valid
+@22
+TOP.VexRiscv.dataCache_1.io_mem_rsp_payload_data[31:0]
+@28
+TOP.VexRiscv.dataCache_1.io_mem_rsp_valid
+TOP.VexRiscv.dataCache_1.dataWriteCmd_payload_address[2:0]
+@22
+TOP.VexRiscv.dataCache_1.dataWriteCmd_payload_data[31:0]
+TOP.VexRiscv.dataCache_1.dataWriteCmd_payload_mask[3:0]
+@28
+TOP.VexRiscv.dataCache_1.dataWriteCmd_valid
+TOP.VexRiscv.dataCache_1.clk
+TOP.VexRiscv.dataCache_1.way_dataReadRspTwoEnable
+@22
+TOP.VexRiscv.dataCache_1.way_dataReadRspTwo[31:0]
+@28
+TOP.VexRiscv.dataCache_1.way_tagReadRspTwoEnable
+@22
+TOP.VexRiscv.dataCache_1.way_tagReadRspTwo_address[26:0]
+@28
+TOP.VexRiscv.dataCache_1.way_tagReadRspTwo_dirty
+TOP.VexRiscv.dataCache_1.way_tagReadRspTwo_used
+@29
+TOP.VexRiscv.dataCache_1.way_dataReadRspOneAddress[2:0]
+@22
+TOP.VexRiscv.dataCache_1.way_dataReadRspOne[31:0]
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/debug.gtkw b/VexRiscv/src/test/cpp/regression/debug.gtkw
new file mode 100644
index 0000000..d22d878
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/debug.gtkw
@@ -0,0 +1,96 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Thu Feb 1 00:52:25 2018
+[*]
+[dumpfile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/rv32ui-p-lui.vcd"
+[dumpfile_mtime] "Thu Feb 1 00:52:17 2018"
+[dumpfile_size] 183735
+[savefile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/debug.gtkw"
+[timestart] 0
+[size] 1784 950
+[pos] -1 -1
+*-3.000000 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[treeopen] TOP.VexRiscv.
+[sst_width] 409
+[signals_width] 540
+[sst_expanded] 1
+[sst_vpaned_height] 271
+@22
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_payload[31:0]
+@28
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_valid
+@22
+TOP.VexRiscv.prefetch_PC[31:0]
+@28
+TOP.VexRiscv.debug_bus_cmd_valid
+TOP.VexRiscv.reset
+TOP.VexRiscv.clk
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_samplePcNext
+@22
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_pcBeforeJumps[31:0]
+@28
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_valid
+TOP.VexRiscv.fetch_BranchPlugin_hit
+TOP.VexRiscv.execute_BRANCH_DO
+@22
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_pcReg[31:0]
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_pc[31:0]
+@28
+TOP.VexRiscv.prefetch_arbitration_isValid
+TOP.VexRiscv.fetch_arbitration_isValid
+TOP.VexRiscv.decode_arbitration_isValid
+TOP.VexRiscv.execute_arbitration_isValid
+TOP.VexRiscv.memory_arbitration_isValid
+TOP.VexRiscv.writeBack_arbitration_isValid
+TOP.VexRiscv.CsrPlugin_interrupt
+TOP.VexRiscv.CsrPlugin_exception
+TOP.VexRiscv.decode_arbitration_isStuck
+TOP.VexRiscv.decode_arbitration_isStuckByOthers
+TOP.VexRiscv.execute_arbitration_isStuck
+TOP.VexRiscv.execute_arbitration_isStuckByOthers
+TOP.VexRiscv.fetch_arbitration_isStuck
+TOP.VexRiscv.fetch_arbitration_isStuckByOthers
+TOP.VexRiscv.memory_arbitration_isStuck
+TOP.VexRiscv.memory_arbitration_isStuckByOthers
+TOP.VexRiscv.prefetch_arbitration_isStuck
+TOP.VexRiscv.prefetch_arbitration_isStuckByOthers
+TOP.VexRiscv.writeBack_arbitration_isStuck
+TOP.VexRiscv.writeBack_arbitration_isStuckByOthers
+TOP.VexRiscv.iBus_cmd_valid
+TOP.VexRiscv.iBus_cmd_ready
+@22
+TOP.VexRiscv.iBus_cmd_payload_pc[31:0]
+@28
+TOP.VexRiscv.iBus_rsp_error
+@22
+TOP.VexRiscv.iBus_rsp_inst[31:0]
+@28
+TOP.VexRiscv.iBus_rsp_ready
+TOP.VexRiscv.debug_bus_cmd_valid
+@22
+TOP.VexRiscv.BranchPlugin_counter[8:0]
+@28
+TOP.VexRiscv.decode_IS_EBREAK
+TOP.VexRiscv.execute_IS_EBREAK
+TOP.VexRiscv.CsrPlugin_pipelineLiberator_done
+TOP.VexRiscv.CsrPlugin_pipelineLiberator_enable
+TOP.VexRiscv.DebugPlugin_haltIt
+@22
+TOP.VexRiscv.writeBack_INSTRUCTION[31:0]
+@29
+TOP.VexRiscv.DebugPlugin_stepIt
+@22
+TOP.VexRiscv.debug_bus_cmd_payload_address[7:0]
+TOP.VexRiscv.debug_bus_cmd_payload_data[31:0]
+@28
+TOP.VexRiscv.debug_bus_cmd_payload_wr
+TOP.VexRiscv.debug_bus_cmd_ready
+TOP.VexRiscv.debug_bus_cmd_valid
+@22
+TOP.VexRiscv.debug_bus_rsp_data[31:0]
+@28
+TOP.VexRiscv.debug_resetOut
+TOP.VexRiscv.debugReset
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/default.gtkw b/VexRiscv/src/test/cpp/regression/default.gtkw
new file mode 100644
index 0000000..cea3b75
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/default.gtkw
@@ -0,0 +1,100 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Sat Mar 25 13:21:38 2017
+[*]
+[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/machineCsr.vcd"
+[dumpfile_mtime] "Sat Mar 25 13:21:31 2017"
+[dumpfile_size] 2048473
+[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/default.gtkw"
+[timestart] 0
+[size] 1776 953
+[pos] -1 -1
+*-9.770813 718 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[treeopen] TOP.VexRiscv.
+[sst_width] 294
+[signals_width] 597
+[sst_expanded] 1
+[sst_vpaned_height] 593
+@28
+TOP.VexRiscv.writeBack_arbitration_isValid
+@22
+TOP.VexRiscv.writeBack_PC[31:0]
+TOP.VexRiscv.writeBack_INSTRUCTION[31:0]
+TOP.VexRiscv.RegFilePlugin_regFile(10)[31:0]
+TOP.VexRiscv.RegFilePlugin_regFile(11)[31:0]
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_pcBeforeJumps[31:0]
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_pc[31:0]
+TOP.VexRiscv.MachineCsr_mepc[31:0]
+@28
+TOP.VexRiscv.timerInterrupt
+TOP.VexRiscv.execute_arbitration_isValid
+@22
+TOP.VexRiscv.execute_PC[31:0]
+@28
+TOP.VexRiscv.MachineCsr_mie_MEIE
+TOP.VexRiscv.MachineCsr_mie_MSIE
+TOP.VexRiscv.MachineCsr_mie_MTIE
+TOP.VexRiscv.MachineCsr_mstatus_MIE
+TOP.VexRiscv.MachineCsr_mip_MEIP
+TOP.VexRiscv.MachineCsr_mip_MSIP
+TOP.VexRiscv.MachineCsr_mip_MTIP
+TOP.VexRiscv.MachineCsr_interrupt
+TOP.VexRiscv.MachineCsr_writeBackWfi
+TOP.VexRiscv.writeBack_arbitration_isValid
+TOP.VexRiscv.writeBack_ENV_CTRL[2:0]
+TOP.VexRiscv.execute_EXCEPTION
+TOP.VexRiscv.memory_EXCEPTION
+TOP.VexRiscv.writeBack_EXCEPTION
+TOP.VexRiscv.prefetch_arbitration_isValid
+TOP.VexRiscv.fetch_arbitration_isValid
+TOP.VexRiscv.decode_arbitration_isValid
+TOP.VexRiscv.execute_arbitration_isValid
+TOP.VexRiscv.memory_arbitration_isValid
+TOP.VexRiscv.writeBack_arbitration_isValid
+TOP.VexRiscv.prefetch_arbitration_removeIt
+TOP.VexRiscv.fetch_arbitration_removeIt
+@29
+TOP.VexRiscv.decode_arbitration_removeIt
+@28
+TOP.VexRiscv.execute_arbitration_removeIt
+TOP.VexRiscv.memory_arbitration_removeIt
+TOP.VexRiscv.writeBack_arbitration_removeIt
+TOP.VexRiscv.prefetch_arbitration_isStuck
+TOP.VexRiscv.fetch_arbitration_isStuck
+TOP.VexRiscv.decode_arbitration_isStuck
+TOP.VexRiscv.execute_arbitration_isStuck
+TOP.VexRiscv.memory_arbitration_isStuck
+TOP.VexRiscv.writeBack_arbitration_isStuck
+@22
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_payload[31:0]
+@28
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_valid
+@22
+TOP.VexRiscv.MachineCsr_mepc[31:0]
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_pcReg[31:0]
+TOP.VexRiscv.prefetch_PC_CALC_WITHOUT_JUMP[31:0]
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_pc[31:0]
+TOP.VexRiscv.prefetch_PC[31:0]
+TOP.VexRiscv.fetch_PC[31:0]
+TOP.VexRiscv.decode_PC[31:0]
+TOP.VexRiscv.execute_PC[31:0]
+TOP.VexRiscv.memory_PC[31:0]
+TOP.VexRiscv.writeBack_PC[31:0]
+@28
+TOP.VexRiscv.prefetch_arbitration_isStuckByOthers
+TOP.VexRiscv.fetch_arbitration_isStuckByOthers
+TOP.VexRiscv.decode_arbitration_isStuckByOthers
+TOP.VexRiscv.execute_arbitration_isStuckByOthers
+TOP.VexRiscv.memory_arbitration_isStuckByOthers
+TOP.VexRiscv.writeBack_arbitration_isStuckByOthers
+TOP.VexRiscv.prefetch_arbitration_haltIt
+TOP.VexRiscv.fetch_arbitration_haltIt
+TOP.VexRiscv.decode_arbitration_haltIt
+TOP.VexRiscv.execute_arbitration_haltIt
+TOP.VexRiscv.memory_arbitration_haltIt
+TOP.VexRiscv.writeBack_arbitration_haltIt
+TOP.VexRiscv.MachineCsr_mie_MTIE
+TOP.VexRiscv.MachineCsr_mip_MTIP
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/dhrystoneO3.logRef b/VexRiscv/src/test/cpp/regression/dhrystoneO3.logRef
new file mode 100644
index 0000000..1bdf354
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/dhrystoneO3.logRef
@@ -0,0 +1,57 @@
+
+Dhrystone Benchmark, Version 2.1 (Language: C)
+
+Program compiled without 'register' attribute
+
+Please give the number of runs through the benchmark:
+Execution starts, 200 runs through Dhrystone
+Execution ends
+
+Final values of the variables used in the benchmark:
+
+Int_Glob: 5
+ should be: 5
+Bool_Glob: 1
+ should be: 1
+Ch_1_Glob: A
+ should be: A
+Ch_2_Glob: B
+ should be: B
+Arr_1_Glob[8]: 7
+ should be: 7
+Arr_2_Glob[8][7]: 210
+ should be: Number_Of_Runs + 10
+Ptr_Glob->
+ Ptr_Comp: -2147458812
+ should be: (implementation-dependent)
+ Discr: 0
+ should be: 0
+ Enum_Comp: 2
+ should be: 2
+ Int_Comp: 17
+ should be: 17
+ Str_Comp: DHRYSTONE PROGRAM, SOME STRING
+ should be: DHRYSTONE PROGRAM, SOME STRING
+Next_Ptr_Glob->
+ Ptr_Comp: -2147458812
+ should be: (implementation-dependent), same as above
+ Discr: 0
+ should be: 0
+ Enum_Comp: 1
+ should be: 1
+ Int_Comp: 18
+ should be: 18
+ Str_Comp: DHRYSTONE PROGRAM, SOME STRING
+ should be: DHRYSTONE PROGRAM, SOME STRING
+Int_1_Loc: 5
+ should be: 5
+Int_2_Loc: 13
+ should be: 13
+Int_3_Loc: 7
+ should be: 7
+Enum_Loc: 1
+ should be: 1
+Str_1_Loc: DHRYSTONE PROGRAM, 1'ST STRING
+ should be: DHRYSTONE PROGRAM, 1'ST STRING
+Str_2_Loc: DHRYSTONE PROGRAM, 2'ND STRING
+ should be: DHRYSTONE PROGRAM, 2'ND STRING
diff --git a/VexRiscv/src/test/cpp/regression/dhrystoneO3C.logRef b/VexRiscv/src/test/cpp/regression/dhrystoneO3C.logRef
new file mode 100644
index 0000000..9985a89
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/dhrystoneO3C.logRef
@@ -0,0 +1,57 @@
+
+Dhrystone Benchmark, Version 2.1 (Language: C)
+
+Program compiled without 'register' attribute
+
+Please give the number of runs through the benchmark:
+Execution starts, 200 runs through Dhrystone
+Execution ends
+
+Final values of the variables used in the benchmark:
+
+Int_Glob: 5
+ should be: 5
+Bool_Glob: 1
+ should be: 1
+Ch_1_Glob: A
+ should be: A
+Ch_2_Glob: B
+ should be: B
+Arr_1_Glob[8]: 7
+ should be: 7
+Arr_2_Glob[8][7]: 210
+ should be: Number_Of_Runs + 10
+Ptr_Glob->
+ Ptr_Comp: -2147459900
+ should be: (implementation-dependent)
+ Discr: 0
+ should be: 0
+ Enum_Comp: 2
+ should be: 2
+ Int_Comp: 17
+ should be: 17
+ Str_Comp: DHRYSTONE PROGRAM, SOME STRING
+ should be: DHRYSTONE PROGRAM, SOME STRING
+Next_Ptr_Glob->
+ Ptr_Comp: -2147459900
+ should be: (implementation-dependent), same as above
+ Discr: 0
+ should be: 0
+ Enum_Comp: 1
+ should be: 1
+ Int_Comp: 18
+ should be: 18
+ Str_Comp: DHRYSTONE PROGRAM, SOME STRING
+ should be: DHRYSTONE PROGRAM, SOME STRING
+Int_1_Loc: 5
+ should be: 5
+Int_2_Loc: 13
+ should be: 13
+Int_3_Loc: 7
+ should be: 7
+Enum_Loc: 1
+ should be: 1
+Str_1_Loc: DHRYSTONE PROGRAM, 1'ST STRING
+ should be: DHRYSTONE PROGRAM, 1'ST STRING
+Str_2_Loc: DHRYSTONE PROGRAM, 2'ND STRING
+ should be: DHRYSTONE PROGRAM, 2'ND STRING
diff --git a/VexRiscv/src/test/cpp/regression/dhrystoneO3M.logRef b/VexRiscv/src/test/cpp/regression/dhrystoneO3M.logRef
new file mode 100644
index 0000000..1c6f8d1
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/dhrystoneO3M.logRef
@@ -0,0 +1,57 @@
+
+Dhrystone Benchmark, Version 2.1 (Language: C)
+
+Program compiled without 'register' attribute
+
+Please give the number of runs through the benchmark:
+Execution starts, 200 runs through Dhrystone
+Execution ends
+
+Final values of the variables used in the benchmark:
+
+Int_Glob: 5
+ should be: 5
+Bool_Glob: 1
+ should be: 1
+Ch_1_Glob: A
+ should be: A
+Ch_2_Glob: B
+ should be: B
+Arr_1_Glob[8]: 7
+ should be: 7
+Arr_2_Glob[8][7]: 210
+ should be: Number_Of_Runs + 10
+Ptr_Glob->
+ Ptr_Comp: -2147459860
+ should be: (implementation-dependent)
+ Discr: 0
+ should be: 0
+ Enum_Comp: 2
+ should be: 2
+ Int_Comp: 17
+ should be: 17
+ Str_Comp: DHRYSTONE PROGRAM, SOME STRING
+ should be: DHRYSTONE PROGRAM, SOME STRING
+Next_Ptr_Glob->
+ Ptr_Comp: -2147459860
+ should be: (implementation-dependent), same as above
+ Discr: 0
+ should be: 0
+ Enum_Comp: 1
+ should be: 1
+ Int_Comp: 18
+ should be: 18
+ Str_Comp: DHRYSTONE PROGRAM, SOME STRING
+ should be: DHRYSTONE PROGRAM, SOME STRING
+Int_1_Loc: 5
+ should be: 5
+Int_2_Loc: 13
+ should be: 13
+Int_3_Loc: 7
+ should be: 7
+Enum_Loc: 1
+ should be: 1
+Str_1_Loc: DHRYSTONE PROGRAM, 1'ST STRING
+ should be: DHRYSTONE PROGRAM, 1'ST STRING
+Str_2_Loc: DHRYSTONE PROGRAM, 2'ND STRING
+ should be: DHRYSTONE PROGRAM, 2'ND STRING
diff --git a/VexRiscv/src/test/cpp/regression/dhrystoneO3MC.logRef b/VexRiscv/src/test/cpp/regression/dhrystoneO3MC.logRef
new file mode 100644
index 0000000..a584b67
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/dhrystoneO3MC.logRef
@@ -0,0 +1,57 @@
+
+Dhrystone Benchmark, Version 2.1 (Language: C)
+
+Program compiled without 'register' attribute
+
+Please give the number of runs through the benchmark:
+Execution starts, 200 runs through Dhrystone
+Execution ends
+
+Final values of the variables used in the benchmark:
+
+Int_Glob: 5
+ should be: 5
+Bool_Glob: 1
+ should be: 1
+Ch_1_Glob: A
+ should be: A
+Ch_2_Glob: B
+ should be: B
+Arr_1_Glob[8]: 7
+ should be: 7
+Arr_2_Glob[8][7]: 210
+ should be: Number_Of_Runs + 10
+Ptr_Glob->
+ Ptr_Comp: -2147460916
+ should be: (implementation-dependent)
+ Discr: 0
+ should be: 0
+ Enum_Comp: 2
+ should be: 2
+ Int_Comp: 17
+ should be: 17
+ Str_Comp: DHRYSTONE PROGRAM, SOME STRING
+ should be: DHRYSTONE PROGRAM, SOME STRING
+Next_Ptr_Glob->
+ Ptr_Comp: -2147460916
+ should be: (implementation-dependent), same as above
+ Discr: 0
+ should be: 0
+ Enum_Comp: 1
+ should be: 1
+ Int_Comp: 18
+ should be: 18
+ Str_Comp: DHRYSTONE PROGRAM, SOME STRING
+ should be: DHRYSTONE PROGRAM, SOME STRING
+Int_1_Loc: 5
+ should be: 5
+Int_2_Loc: 13
+ should be: 13
+Int_3_Loc: 7
+ should be: 7
+Enum_Loc: 1
+ should be: 1
+Str_1_Loc: DHRYSTONE PROGRAM, 1'ST STRING
+ should be: DHRYSTONE PROGRAM, 1'ST STRING
+Str_2_Loc: DHRYSTONE PROGRAM, 2'ND STRING
+ should be: DHRYSTONE PROGRAM, 2'ND STRING
diff --git a/VexRiscv/src/test/cpp/regression/encoding.h b/VexRiscv/src/test/cpp/regression/encoding.h
new file mode 100644
index 0000000..c109ce1
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/encoding.h
@@ -0,0 +1,1471 @@
+// See LICENSE for license details.
+
+#ifndef RISCV_CSR_ENCODING_H
+#define RISCV_CSR_ENCODING_H
+
+#define MSTATUS_UIE 0x00000001
+#define MSTATUS_SIE 0x00000002
+#define MSTATUS_HIE 0x00000004
+#define MSTATUS_MIE 0x00000008
+#define MSTATUS_UPIE 0x00000010
+#define MSTATUS_SPIE 0x00000020
+#define MSTATUS_HPIE 0x00000040
+#define MSTATUS_MPIE 0x00000080
+#define MSTATUS_SPP 0x00000100
+#define MSTATUS_HPP 0x00000600
+#define MSTATUS_MPP 0x00001800
+#define MSTATUS_FS 0x00006000
+#define MSTATUS_XS 0x00018000
+#define MSTATUS_MPRV 0x00020000
+#define MSTATUS_SUM 0x00040000
+#define MSTATUS_MXR 0x00080000
+#define MSTATUS_TVM 0x00100000
+#define MSTATUS_TW 0x00200000
+#define MSTATUS_TSR 0x00400000
+#define MSTATUS32_SD 0x80000000
+#define MSTATUS_UXL 0x0000000300000000
+#define MSTATUS_SXL 0x0000000C00000000
+#define MSTATUS64_SD 0x8000000000000000
+
+#define SSTATUS_UIE 0x00000001
+#define SSTATUS_SIE 0x00000002
+#define SSTATUS_UPIE 0x00000010
+#define SSTATUS_SPIE 0x00000020
+#define SSTATUS_SPP 0x00000100
+#define SSTATUS_FS 0x00006000
+#define SSTATUS_XS 0x00018000
+#define SSTATUS_SUM 0x00040000
+#define SSTATUS_MXR 0x00080000
+#define SSTATUS32_SD 0x80000000
+#define SSTATUS_UXL 0x0000000300000000
+#define SSTATUS64_SD 0x8000000000000000
+
+#define DCSR_XDEBUGVER (3U<<30)
+#define DCSR_NDRESET (1<<29)
+#define DCSR_FULLRESET (1<<28)
+#define DCSR_EBREAKM (1<<15)
+#define DCSR_EBREAKH (1<<14)
+#define DCSR_EBREAKS (1<<13)
+#define DCSR_EBREAKU (1<<12)
+#define DCSR_STOPCYCLE (1<<10)
+#define DCSR_STOPTIME (1<<9)
+#define DCSR_CAUSE (7<<6)
+#define DCSR_DEBUGINT (1<<5)
+#define DCSR_HALT (1<<3)
+#define DCSR_STEP (1<<2)
+#define DCSR_PRV (3<<0)
+
+#define DCSR_CAUSE_NONE 0
+#define DCSR_CAUSE_SWBP 1
+#define DCSR_CAUSE_HWBP 2
+#define DCSR_CAUSE_DEBUGINT 3
+#define DCSR_CAUSE_STEP 4
+#define DCSR_CAUSE_HALT 5
+
+#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
+#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
+#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
+
+#define MCONTROL_SELECT (1<<19)
+#define MCONTROL_TIMING (1<<18)
+#define MCONTROL_ACTION (0x3f<<12)
+#define MCONTROL_CHAIN (1<<11)
+#define MCONTROL_MATCH (0xf<<7)
+#define MCONTROL_M (1<<6)
+#define MCONTROL_H (1<<5)
+#define MCONTROL_S (1<<4)
+#define MCONTROL_U (1<<3)
+#define MCONTROL_EXECUTE (1<<2)
+#define MCONTROL_STORE (1<<1)
+#define MCONTROL_LOAD (1<<0)
+
+#define MCONTROL_TYPE_NONE 0
+#define MCONTROL_TYPE_MATCH 2
+
+#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
+#define MCONTROL_ACTION_DEBUG_MODE 1
+#define MCONTROL_ACTION_TRACE_START 2
+#define MCONTROL_ACTION_TRACE_STOP 3
+#define MCONTROL_ACTION_TRACE_EMIT 4
+
+#define MCONTROL_MATCH_EQUAL 0
+#define MCONTROL_MATCH_NAPOT 1
+#define MCONTROL_MATCH_GE 2
+#define MCONTROL_MATCH_LT 3
+#define MCONTROL_MATCH_MASK_LOW 4
+#define MCONTROL_MATCH_MASK_HIGH 5
+
+#define MIP_SSIP (1 << IRQ_S_SOFT)
+#define MIP_HSIP (1 << IRQ_H_SOFT)
+#define MIP_MSIP (1 << IRQ_M_SOFT)
+#define MIP_STIP (1 << IRQ_S_TIMER)
+#define MIP_HTIP (1 << IRQ_H_TIMER)
+#define MIP_MTIP (1 << IRQ_M_TIMER)
+#define MIP_SEIP (1 << IRQ_S_EXT)
+#define MIP_HEIP (1 << IRQ_H_EXT)
+#define MIP_MEIP (1 << IRQ_M_EXT)
+
+#define SIP_SSIP MIP_SSIP
+#define SIP_STIP MIP_STIP
+
+#define PRV_U 0
+#define PRV_S 1
+#define PRV_H 2
+#define PRV_M 3
+
+#define SATP32_MODE 0x80000000
+#define SATP32_ASID 0x7FC00000
+#define SATP32_PPN 0x003FFFFF
+#define SATP64_MODE 0xF000000000000000
+#define SATP64_ASID 0x0FFFF00000000000
+#define SATP64_PPN 0x00000FFFFFFFFFFF
+
+#define SATP_MODE_OFF 0
+#define SATP_MODE_SV32 1
+#define SATP_MODE_SV39 8
+#define SATP_MODE_SV48 9
+#define SATP_MODE_SV57 10
+#define SATP_MODE_SV64 11
+
+#define PMP_R 0x01
+#define PMP_W 0x02
+#define PMP_X 0x04
+#define PMP_A 0x18
+#define PMP_L 0x80
+#define PMP_SHIFT 2
+
+#define PMP_TOR 0x08
+#define PMP_NA4 0x10
+#define PMP_NAPOT 0x18
+
+#define IRQ_S_SOFT 1
+#define IRQ_H_SOFT 2
+#define IRQ_M_SOFT 3
+#define IRQ_S_TIMER 5
+#define IRQ_H_TIMER 6
+#define IRQ_M_TIMER 7
+#define IRQ_S_EXT 9
+#define IRQ_H_EXT 10
+#define IRQ_M_EXT 11
+#define IRQ_COP 12
+#define IRQ_HOST 13
+
+#define DEFAULT_RSTVEC 0x00001000
+#define CLINT_BASE 0x02000000
+#define CLINT_SIZE 0x000c0000
+#define EXT_IO_BASE 0x40000000
+#define DRAM_BASE 0x80000000
+
+// page table entry (PTE) fields
+#define PTE_V 0x001 // Valid
+#define PTE_R 0x002 // Read
+#define PTE_W 0x004 // Write
+#define PTE_X 0x008 // Execute
+#define PTE_U 0x010 // User
+#define PTE_G 0x020 // Global
+#define PTE_A 0x040 // Accessed
+#define PTE_D 0x080 // Dirty
+#define PTE_SOFT 0x300 // Reserved for Software
+
+#define PTE_PPN_SHIFT 10
+
+#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
+
+#ifdef __riscv
+
+#if __riscv_xlen == 64
+# define MSTATUS_SD MSTATUS64_SD
+# define SSTATUS_SD SSTATUS64_SD
+# define RISCV_PGLEVEL_BITS 9
+# define SATP_MODE SATP64_MODE
+#else
+# define MSTATUS_SD MSTATUS32_SD
+# define SSTATUS_SD SSTATUS32_SD
+# define RISCV_PGLEVEL_BITS 10
+# define SATP_MODE SATP32_MODE
+#endif
+#define RISCV_PGSHIFT 12
+#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
+
+#ifndef __ASSEMBLER__
+
+#ifdef __GNUC__
+
+#define read_csr(reg) ({ unsigned long __tmp; \
+ asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
+ __tmp; })
+
+#define write_csr(reg, val) ({ \
+ asm volatile ("csrw " #reg ", %0" :: "rK"(val)); })
+
+#define swap_csr(reg, val) ({ unsigned long __tmp; \
+ asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \
+ __tmp; })
+
+#define set_csr(reg, bit) ({ unsigned long __tmp; \
+ asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
+ __tmp; })
+
+#define clear_csr(reg, bit) ({ unsigned long __tmp; \
+ asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
+ __tmp; })
+
+#define rdtime() read_csr(time)
+#define rdcycle() read_csr(cycle)
+#define rdinstret() read_csr(instret)
+
+#endif
+
+#endif
+
+#endif
+
+#endif
+/* Automatically generated by parse-opcodes. */
+#ifndef RISCV_ENCODING_H
+#define RISCV_ENCODING_H
+#define MATCH_BEQ 0x63
+#define MASK_BEQ 0x707f
+#define MATCH_BNE 0x1063
+#define MASK_BNE 0x707f
+#define MATCH_BLT 0x4063
+#define MASK_BLT 0x707f
+#define MATCH_BGE 0x5063
+#define MASK_BGE 0x707f
+#define MATCH_BLTU 0x6063
+#define MASK_BLTU 0x707f
+#define MATCH_BGEU 0x7063
+#define MASK_BGEU 0x707f
+#define MATCH_JALR 0x67
+#define MASK_JALR 0x707f
+#define MATCH_JAL 0x6f
+#define MASK_JAL 0x7f
+#define MATCH_LUI 0x37
+#define MASK_LUI 0x7f
+#define MATCH_AUIPC 0x17
+#define MASK_AUIPC 0x7f
+#define MATCH_ADDI 0x13
+#define MASK_ADDI 0x707f
+#define MATCH_SLLI 0x1013
+#define MASK_SLLI 0xfc00707f
+#define MATCH_SLTI 0x2013
+#define MASK_SLTI 0x707f
+#define MATCH_SLTIU 0x3013
+#define MASK_SLTIU 0x707f
+#define MATCH_XORI 0x4013
+#define MASK_XORI 0x707f
+#define MATCH_SRLI 0x5013
+#define MASK_SRLI 0xfc00707f
+#define MATCH_SRAI 0x40005013
+#define MASK_SRAI 0xfc00707f
+#define MATCH_ORI 0x6013
+#define MASK_ORI 0x707f
+#define MATCH_ANDI 0x7013
+#define MASK_ANDI 0x707f
+#define MATCH_ADD 0x33
+#define MASK_ADD 0xfe00707f
+#define MATCH_SUB 0x40000033
+#define MASK_SUB 0xfe00707f
+#define MATCH_SLL 0x1033
+#define MASK_SLL 0xfe00707f
+#define MATCH_SLT 0x2033
+#define MASK_SLT 0xfe00707f
+#define MATCH_SLTU 0x3033
+#define MASK_SLTU 0xfe00707f
+#define MATCH_XOR 0x4033
+#define MASK_XOR 0xfe00707f
+#define MATCH_SRL 0x5033
+#define MASK_SRL 0xfe00707f
+#define MATCH_SRA 0x40005033
+#define MASK_SRA 0xfe00707f
+#define MATCH_OR 0x6033
+#define MASK_OR 0xfe00707f
+#define MATCH_AND 0x7033
+#define MASK_AND 0xfe00707f
+#define MATCH_ADDIW 0x1b
+#define MASK_ADDIW 0x707f
+#define MATCH_SLLIW 0x101b
+#define MASK_SLLIW 0xfe00707f
+#define MATCH_SRLIW 0x501b
+#define MASK_SRLIW 0xfe00707f
+#define MATCH_SRAIW 0x4000501b
+#define MASK_SRAIW 0xfe00707f
+#define MATCH_ADDW 0x3b
+#define MASK_ADDW 0xfe00707f
+#define MATCH_SUBW 0x4000003b
+#define MASK_SUBW 0xfe00707f
+#define MATCH_SLLW 0x103b
+#define MASK_SLLW 0xfe00707f
+#define MATCH_SRLW 0x503b
+#define MASK_SRLW 0xfe00707f
+#define MATCH_SRAW 0x4000503b
+#define MASK_SRAW 0xfe00707f
+#define MATCH_LB 0x3
+#define MASK_LB 0x707f
+#define MATCH_LH 0x1003
+#define MASK_LH 0x707f
+#define MATCH_LW 0x2003
+#define MASK_LW 0x707f
+#define MATCH_LD 0x3003
+#define MASK_LD 0x707f
+#define MATCH_LBU 0x4003
+#define MASK_LBU 0x707f
+#define MATCH_LHU 0x5003
+#define MASK_LHU 0x707f
+#define MATCH_LWU 0x6003
+#define MASK_LWU 0x707f
+#define MATCH_SB 0x23
+#define MASK_SB 0x707f
+#define MATCH_SH 0x1023
+#define MASK_SH 0x707f
+#define MATCH_SW 0x2023
+#define MASK_SW 0x707f
+#define MATCH_SD 0x3023
+#define MASK_SD 0x707f
+#define MATCH_FENCE 0xf
+#define MASK_FENCE 0x707f
+#define MATCH_FENCE_I 0x100f
+#define MASK_FENCE_I 0x707f
+#define MATCH_MUL 0x2000033
+#define MASK_MUL 0xfe00707f
+#define MATCH_MULH 0x2001033
+#define MASK_MULH 0xfe00707f
+#define MATCH_MULHSU 0x2002033
+#define MASK_MULHSU 0xfe00707f
+#define MATCH_MULHU 0x2003033
+#define MASK_MULHU 0xfe00707f
+#define MATCH_DIV 0x2004033
+#define MASK_DIV 0xfe00707f
+#define MATCH_DIVU 0x2005033
+#define MASK_DIVU 0xfe00707f
+#define MATCH_REM 0x2006033
+#define MASK_REM 0xfe00707f
+#define MATCH_REMU 0x2007033
+#define MASK_REMU 0xfe00707f
+#define MATCH_MULW 0x200003b
+#define MASK_MULW 0xfe00707f
+#define MATCH_DIVW 0x200403b
+#define MASK_DIVW 0xfe00707f
+#define MATCH_DIVUW 0x200503b
+#define MASK_DIVUW 0xfe00707f
+#define MATCH_REMW 0x200603b
+#define MASK_REMW 0xfe00707f
+#define MATCH_REMUW 0x200703b
+#define MASK_REMUW 0xfe00707f
+#define MATCH_AMOADD_W 0x202f
+#define MASK_AMOADD_W 0xf800707f
+#define MATCH_AMOXOR_W 0x2000202f
+#define MASK_AMOXOR_W 0xf800707f
+#define MATCH_AMOOR_W 0x4000202f
+#define MASK_AMOOR_W 0xf800707f
+#define MATCH_AMOAND_W 0x6000202f
+#define MASK_AMOAND_W 0xf800707f
+#define MATCH_AMOMIN_W 0x8000202f
+#define MASK_AMOMIN_W 0xf800707f
+#define MATCH_AMOMAX_W 0xa000202f
+#define MASK_AMOMAX_W 0xf800707f
+#define MATCH_AMOMINU_W 0xc000202f
+#define MASK_AMOMINU_W 0xf800707f
+#define MATCH_AMOMAXU_W 0xe000202f
+#define MASK_AMOMAXU_W 0xf800707f
+#define MATCH_AMOSWAP_W 0x800202f
+#define MASK_AMOSWAP_W 0xf800707f
+#define MATCH_LR_W 0x1000202f
+#define MASK_LR_W 0xf9f0707f
+#define MATCH_SC_W 0x1800202f
+#define MASK_SC_W 0xf800707f
+#define MATCH_AMOADD_D 0x302f
+#define MASK_AMOADD_D 0xf800707f
+#define MATCH_AMOXOR_D 0x2000302f
+#define MASK_AMOXOR_D 0xf800707f
+#define MATCH_AMOOR_D 0x4000302f
+#define MASK_AMOOR_D 0xf800707f
+#define MATCH_AMOAND_D 0x6000302f
+#define MASK_AMOAND_D 0xf800707f
+#define MATCH_AMOMIN_D 0x8000302f
+#define MASK_AMOMIN_D 0xf800707f
+#define MATCH_AMOMAX_D 0xa000302f
+#define MASK_AMOMAX_D 0xf800707f
+#define MATCH_AMOMINU_D 0xc000302f
+#define MASK_AMOMINU_D 0xf800707f
+#define MATCH_AMOMAXU_D 0xe000302f
+#define MASK_AMOMAXU_D 0xf800707f
+#define MATCH_AMOSWAP_D 0x800302f
+#define MASK_AMOSWAP_D 0xf800707f
+#define MATCH_LR_D 0x1000302f
+#define MASK_LR_D 0xf9f0707f
+#define MATCH_SC_D 0x1800302f
+#define MASK_SC_D 0xf800707f
+#define MATCH_ECALL 0x73
+#define MASK_ECALL 0xffffffff
+#define MATCH_EBREAK 0x100073
+#define MASK_EBREAK 0xffffffff
+#define MATCH_URET 0x200073
+#define MASK_URET 0xffffffff
+#define MATCH_SRET 0x10200073
+#define MASK_SRET 0xffffffff
+#define MATCH_MRET 0x30200073
+#define MASK_MRET 0xffffffff
+#define MATCH_DRET 0x7b200073
+#define MASK_DRET 0xffffffff
+#define MATCH_SFENCE_VMA 0x12000073
+#define MASK_SFENCE_VMA 0xfe007fff
+#define MATCH_WFI 0x10500073
+#define MASK_WFI 0xffffffff
+#define MATCH_CSRRW 0x1073
+#define MASK_CSRRW 0x707f
+#define MATCH_CSRRS 0x2073
+#define MASK_CSRRS 0x707f
+#define MATCH_CSRRC 0x3073
+#define MASK_CSRRC 0x707f
+#define MATCH_CSRRWI 0x5073
+#define MASK_CSRRWI 0x707f
+#define MATCH_CSRRSI 0x6073
+#define MASK_CSRRSI 0x707f
+#define MATCH_CSRRCI 0x7073
+#define MASK_CSRRCI 0x707f
+#define MATCH_FADD_S 0x53
+#define MASK_FADD_S 0xfe00007f
+#define MATCH_FSUB_S 0x8000053
+#define MASK_FSUB_S 0xfe00007f
+#define MATCH_FMUL_S 0x10000053
+#define MASK_FMUL_S 0xfe00007f
+#define MATCH_FDIV_S 0x18000053
+#define MASK_FDIV_S 0xfe00007f
+#define MATCH_FSGNJ_S 0x20000053
+#define MASK_FSGNJ_S 0xfe00707f
+#define MATCH_FSGNJN_S 0x20001053
+#define MASK_FSGNJN_S 0xfe00707f
+#define MATCH_FSGNJX_S 0x20002053
+#define MASK_FSGNJX_S 0xfe00707f
+#define MATCH_FMIN_S 0x28000053
+#define MASK_FMIN_S 0xfe00707f
+#define MATCH_FMAX_S 0x28001053
+#define MASK_FMAX_S 0xfe00707f
+#define MATCH_FSQRT_S 0x58000053
+#define MASK_FSQRT_S 0xfff0007f
+#define MATCH_FADD_D 0x2000053
+#define MASK_FADD_D 0xfe00007f
+#define MATCH_FSUB_D 0xa000053
+#define MASK_FSUB_D 0xfe00007f
+#define MATCH_FMUL_D 0x12000053
+#define MASK_FMUL_D 0xfe00007f
+#define MATCH_FDIV_D 0x1a000053
+#define MASK_FDIV_D 0xfe00007f
+#define MATCH_FSGNJ_D 0x22000053
+#define MASK_FSGNJ_D 0xfe00707f
+#define MATCH_FSGNJN_D 0x22001053
+#define MASK_FSGNJN_D 0xfe00707f
+#define MATCH_FSGNJX_D 0x22002053
+#define MASK_FSGNJX_D 0xfe00707f
+#define MATCH_FMIN_D 0x2a000053
+#define MASK_FMIN_D 0xfe00707f
+#define MATCH_FMAX_D 0x2a001053
+#define MASK_FMAX_D 0xfe00707f
+#define MATCH_FCVT_S_D 0x40100053
+#define MASK_FCVT_S_D 0xfff0007f
+#define MATCH_FCVT_D_S 0x42000053
+#define MASK_FCVT_D_S 0xfff0007f
+#define MATCH_FSQRT_D 0x5a000053
+#define MASK_FSQRT_D 0xfff0007f
+#define MATCH_FADD_Q 0x6000053
+#define MASK_FADD_Q 0xfe00007f
+#define MATCH_FSUB_Q 0xe000053
+#define MASK_FSUB_Q 0xfe00007f
+#define MATCH_FMUL_Q 0x16000053
+#define MASK_FMUL_Q 0xfe00007f
+#define MATCH_FDIV_Q 0x1e000053
+#define MASK_FDIV_Q 0xfe00007f
+#define MATCH_FSGNJ_Q 0x26000053
+#define MASK_FSGNJ_Q 0xfe00707f
+#define MATCH_FSGNJN_Q 0x26001053
+#define MASK_FSGNJN_Q 0xfe00707f
+#define MATCH_FSGNJX_Q 0x26002053
+#define MASK_FSGNJX_Q 0xfe00707f
+#define MATCH_FMIN_Q 0x2e000053
+#define MASK_FMIN_Q 0xfe00707f
+#define MATCH_FMAX_Q 0x2e001053
+#define MASK_FMAX_Q 0xfe00707f
+#define MATCH_FCVT_S_Q 0x40300053
+#define MASK_FCVT_S_Q 0xfff0007f
+#define MATCH_FCVT_Q_S 0x46000053
+#define MASK_FCVT_Q_S 0xfff0007f
+#define MATCH_FCVT_D_Q 0x42300053
+#define MASK_FCVT_D_Q 0xfff0007f
+#define MATCH_FCVT_Q_D 0x46100053
+#define MASK_FCVT_Q_D 0xfff0007f
+#define MATCH_FSQRT_Q 0x5e000053
+#define MASK_FSQRT_Q 0xfff0007f
+#define MATCH_FLE_S 0xa0000053
+#define MASK_FLE_S 0xfe00707f
+#define MATCH_FLT_S 0xa0001053
+#define MASK_FLT_S 0xfe00707f
+#define MATCH_FEQ_S 0xa0002053
+#define MASK_FEQ_S 0xfe00707f
+#define MATCH_FLE_D 0xa2000053
+#define MASK_FLE_D 0xfe00707f
+#define MATCH_FLT_D 0xa2001053
+#define MASK_FLT_D 0xfe00707f
+#define MATCH_FEQ_D 0xa2002053
+#define MASK_FEQ_D 0xfe00707f
+#define MATCH_FLE_Q 0xa6000053
+#define MASK_FLE_Q 0xfe00707f
+#define MATCH_FLT_Q 0xa6001053
+#define MASK_FLT_Q 0xfe00707f
+#define MATCH_FEQ_Q 0xa6002053
+#define MASK_FEQ_Q 0xfe00707f
+#define MATCH_FCVT_W_S 0xc0000053
+#define MASK_FCVT_W_S 0xfff0007f
+#define MATCH_FCVT_WU_S 0xc0100053
+#define MASK_FCVT_WU_S 0xfff0007f
+#define MATCH_FCVT_L_S 0xc0200053
+#define MASK_FCVT_L_S 0xfff0007f
+#define MATCH_FCVT_LU_S 0xc0300053
+#define MASK_FCVT_LU_S 0xfff0007f
+#define MATCH_FMV_X_W 0xe0000053
+#define MASK_FMV_X_W 0xfff0707f
+#define MATCH_FCLASS_S 0xe0001053
+#define MASK_FCLASS_S 0xfff0707f
+#define MATCH_FCVT_W_D 0xc2000053
+#define MASK_FCVT_W_D 0xfff0007f
+#define MATCH_FCVT_WU_D 0xc2100053
+#define MASK_FCVT_WU_D 0xfff0007f
+#define MATCH_FCVT_L_D 0xc2200053
+#define MASK_FCVT_L_D 0xfff0007f
+#define MATCH_FCVT_LU_D 0xc2300053
+#define MASK_FCVT_LU_D 0xfff0007f
+#define MATCH_FMV_X_D 0xe2000053
+#define MASK_FMV_X_D 0xfff0707f
+#define MATCH_FCLASS_D 0xe2001053
+#define MASK_FCLASS_D 0xfff0707f
+#define MATCH_FCVT_W_Q 0xc6000053
+#define MASK_FCVT_W_Q 0xfff0007f
+#define MATCH_FCVT_WU_Q 0xc6100053
+#define MASK_FCVT_WU_Q 0xfff0007f
+#define MATCH_FCVT_L_Q 0xc6200053
+#define MASK_FCVT_L_Q 0xfff0007f
+#define MATCH_FCVT_LU_Q 0xc6300053
+#define MASK_FCVT_LU_Q 0xfff0007f
+#define MATCH_FMV_X_Q 0xe6000053
+#define MASK_FMV_X_Q 0xfff0707f
+#define MATCH_FCLASS_Q 0xe6001053
+#define MASK_FCLASS_Q 0xfff0707f
+#define MATCH_FCVT_S_W 0xd0000053
+#define MASK_FCVT_S_W 0xfff0007f
+#define MATCH_FCVT_S_WU 0xd0100053
+#define MASK_FCVT_S_WU 0xfff0007f
+#define MATCH_FCVT_S_L 0xd0200053
+#define MASK_FCVT_S_L 0xfff0007f
+#define MATCH_FCVT_S_LU 0xd0300053
+#define MASK_FCVT_S_LU 0xfff0007f
+#define MATCH_FMV_W_X 0xf0000053
+#define MASK_FMV_W_X 0xfff0707f
+#define MATCH_FCVT_D_W 0xd2000053
+#define MASK_FCVT_D_W 0xfff0007f
+#define MATCH_FCVT_D_WU 0xd2100053
+#define MASK_FCVT_D_WU 0xfff0007f
+#define MATCH_FCVT_D_L 0xd2200053
+#define MASK_FCVT_D_L 0xfff0007f
+#define MATCH_FCVT_D_LU 0xd2300053
+#define MASK_FCVT_D_LU 0xfff0007f
+#define MATCH_FMV_D_X 0xf2000053
+#define MASK_FMV_D_X 0xfff0707f
+#define MATCH_FCVT_Q_W 0xd6000053
+#define MASK_FCVT_Q_W 0xfff0007f
+#define MATCH_FCVT_Q_WU 0xd6100053
+#define MASK_FCVT_Q_WU 0xfff0007f
+#define MATCH_FCVT_Q_L 0xd6200053
+#define MASK_FCVT_Q_L 0xfff0007f
+#define MATCH_FCVT_Q_LU 0xd6300053
+#define MASK_FCVT_Q_LU 0xfff0007f
+#define MATCH_FMV_Q_X 0xf6000053
+#define MASK_FMV_Q_X 0xfff0707f
+#define MATCH_FLW 0x2007
+#define MASK_FLW 0x707f
+#define MATCH_FLD 0x3007
+#define MASK_FLD 0x707f
+#define MATCH_FLQ 0x4007
+#define MASK_FLQ 0x707f
+#define MATCH_FSW 0x2027
+#define MASK_FSW 0x707f
+#define MATCH_FSD 0x3027
+#define MASK_FSD 0x707f
+#define MATCH_FSQ 0x4027
+#define MASK_FSQ 0x707f
+#define MATCH_FMADD_S 0x43
+#define MASK_FMADD_S 0x600007f
+#define MATCH_FMSUB_S 0x47
+#define MASK_FMSUB_S 0x600007f
+#define MATCH_FNMSUB_S 0x4b
+#define MASK_FNMSUB_S 0x600007f
+#define MATCH_FNMADD_S 0x4f
+#define MASK_FNMADD_S 0x600007f
+#define MATCH_FMADD_D 0x2000043
+#define MASK_FMADD_D 0x600007f
+#define MATCH_FMSUB_D 0x2000047
+#define MASK_FMSUB_D 0x600007f
+#define MATCH_FNMSUB_D 0x200004b
+#define MASK_FNMSUB_D 0x600007f
+#define MATCH_FNMADD_D 0x200004f
+#define MASK_FNMADD_D 0x600007f
+#define MATCH_FMADD_Q 0x6000043
+#define MASK_FMADD_Q 0x600007f
+#define MATCH_FMSUB_Q 0x6000047
+#define MASK_FMSUB_Q 0x600007f
+#define MATCH_FNMSUB_Q 0x600004b
+#define MASK_FNMSUB_Q 0x600007f
+#define MATCH_FNMADD_Q 0x600004f
+#define MASK_FNMADD_Q 0x600007f
+#define MATCH_C_NOP 0x1
+#define MASK_C_NOP 0xffff
+#define MATCH_C_ADDI16SP 0x6101
+#define MASK_C_ADDI16SP 0xef83
+#define MATCH_C_JR 0x8002
+#define MASK_C_JR 0xf07f
+#define MATCH_C_JALR 0x9002
+#define MASK_C_JALR 0xf07f
+#define MATCH_C_EBREAK 0x9002
+#define MASK_C_EBREAK 0xffff
+#define MATCH_C_LD 0x6000
+#define MASK_C_LD 0xe003
+#define MATCH_C_SD 0xe000
+#define MASK_C_SD 0xe003
+#define MATCH_C_ADDIW 0x2001
+#define MASK_C_ADDIW 0xe003
+#define MATCH_C_LDSP 0x6002
+#define MASK_C_LDSP 0xe003
+#define MATCH_C_SDSP 0xe002
+#define MASK_C_SDSP 0xe003
+#define MATCH_C_ADDI4SPN 0x0
+#define MASK_C_ADDI4SPN 0xe003
+#define MATCH_C_FLD 0x2000
+#define MASK_C_FLD 0xe003
+#define MATCH_C_LW 0x4000
+#define MASK_C_LW 0xe003
+#define MATCH_C_FLW 0x6000
+#define MASK_C_FLW 0xe003
+#define MATCH_C_FSD 0xa000
+#define MASK_C_FSD 0xe003
+#define MATCH_C_SW 0xc000
+#define MASK_C_SW 0xe003
+#define MATCH_C_FSW 0xe000
+#define MASK_C_FSW 0xe003
+#define MATCH_C_ADDI 0x1
+#define MASK_C_ADDI 0xe003
+#define MATCH_C_JAL 0x2001
+#define MASK_C_JAL 0xe003
+#define MATCH_C_LI 0x4001
+#define MASK_C_LI 0xe003
+#define MATCH_C_LUI 0x6001
+#define MASK_C_LUI 0xe003
+#define MATCH_C_SRLI 0x8001
+#define MASK_C_SRLI 0xec03
+#define MATCH_C_SRAI 0x8401
+#define MASK_C_SRAI 0xec03
+#define MATCH_C_ANDI 0x8801
+#define MASK_C_ANDI 0xec03
+#define MATCH_C_SUB 0x8c01
+#define MASK_C_SUB 0xfc63
+#define MATCH_C_XOR 0x8c21
+#define MASK_C_XOR 0xfc63
+#define MATCH_C_OR 0x8c41
+#define MASK_C_OR 0xfc63
+#define MATCH_C_AND 0x8c61
+#define MASK_C_AND 0xfc63
+#define MATCH_C_SUBW 0x9c01
+#define MASK_C_SUBW 0xfc63
+#define MATCH_C_ADDW 0x9c21
+#define MASK_C_ADDW 0xfc63
+#define MATCH_C_J 0xa001
+#define MASK_C_J 0xe003
+#define MATCH_C_BEQZ 0xc001
+#define MASK_C_BEQZ 0xe003
+#define MATCH_C_BNEZ 0xe001
+#define MASK_C_BNEZ 0xe003
+#define MATCH_C_SLLI 0x2
+#define MASK_C_SLLI 0xe003
+#define MATCH_C_FLDSP 0x2002
+#define MASK_C_FLDSP 0xe003
+#define MATCH_C_LWSP 0x4002
+#define MASK_C_LWSP 0xe003
+#define MATCH_C_FLWSP 0x6002
+#define MASK_C_FLWSP 0xe003
+#define MATCH_C_MV 0x8002
+#define MASK_C_MV 0xf003
+#define MATCH_C_ADD 0x9002
+#define MASK_C_ADD 0xf003
+#define MATCH_C_FSDSP 0xa002
+#define MASK_C_FSDSP 0xe003
+#define MATCH_C_SWSP 0xc002
+#define MASK_C_SWSP 0xe003
+#define MATCH_C_FSWSP 0xe002
+#define MASK_C_FSWSP 0xe003
+#define MATCH_CUSTOM0 0xb
+#define MASK_CUSTOM0 0x707f
+#define MATCH_CUSTOM0_RS1 0x200b
+#define MASK_CUSTOM0_RS1 0x707f
+#define MATCH_CUSTOM0_RS1_RS2 0x300b
+#define MASK_CUSTOM0_RS1_RS2 0x707f
+#define MATCH_CUSTOM0_RD 0x400b
+#define MASK_CUSTOM0_RD 0x707f
+#define MATCH_CUSTOM0_RD_RS1 0x600b
+#define MASK_CUSTOM0_RD_RS1 0x707f
+#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b
+#define MASK_CUSTOM0_RD_RS1_RS2 0x707f
+#define MATCH_CUSTOM1 0x2b
+#define MASK_CUSTOM1 0x707f
+#define MATCH_CUSTOM1_RS1 0x202b
+#define MASK_CUSTOM1_RS1 0x707f
+#define MATCH_CUSTOM1_RS1_RS2 0x302b
+#define MASK_CUSTOM1_RS1_RS2 0x707f
+#define MATCH_CUSTOM1_RD 0x402b
+#define MASK_CUSTOM1_RD 0x707f
+#define MATCH_CUSTOM1_RD_RS1 0x602b
+#define MASK_CUSTOM1_RD_RS1 0x707f
+#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b
+#define MASK_CUSTOM1_RD_RS1_RS2 0x707f
+#define MATCH_CUSTOM2 0x5b
+#define MASK_CUSTOM2 0x707f
+#define MATCH_CUSTOM2_RS1 0x205b
+#define MASK_CUSTOM2_RS1 0x707f
+#define MATCH_CUSTOM2_RS1_RS2 0x305b
+#define MASK_CUSTOM2_RS1_RS2 0x707f
+#define MATCH_CUSTOM2_RD 0x405b
+#define MASK_CUSTOM2_RD 0x707f
+#define MATCH_CUSTOM2_RD_RS1 0x605b
+#define MASK_CUSTOM2_RD_RS1 0x707f
+#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b
+#define MASK_CUSTOM2_RD_RS1_RS2 0x707f
+#define MATCH_CUSTOM3 0x7b
+#define MASK_CUSTOM3 0x707f
+#define MATCH_CUSTOM3_RS1 0x207b
+#define MASK_CUSTOM3_RS1 0x707f
+#define MATCH_CUSTOM3_RS1_RS2 0x307b
+#define MASK_CUSTOM3_RS1_RS2 0x707f
+#define MATCH_CUSTOM3_RD 0x407b
+#define MASK_CUSTOM3_RD 0x707f
+#define MATCH_CUSTOM3_RD_RS1 0x607b
+#define MASK_CUSTOM3_RD_RS1 0x707f
+#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b
+#define MASK_CUSTOM3_RD_RS1_RS2 0x707f
+#define CSR_FFLAGS 0x1
+#define CSR_FRM 0x2
+#define CSR_FCSR 0x3
+#define CSR_CYCLE 0xc00
+#define CSR_TIME 0xc01
+#define CSR_INSTRET 0xc02
+#define CSR_HPMCOUNTER3 0xc03
+#define CSR_HPMCOUNTER4 0xc04
+#define CSR_HPMCOUNTER5 0xc05
+#define CSR_HPMCOUNTER6 0xc06
+#define CSR_HPMCOUNTER7 0xc07
+#define CSR_HPMCOUNTER8 0xc08
+#define CSR_HPMCOUNTER9 0xc09
+#define CSR_HPMCOUNTER10 0xc0a
+#define CSR_HPMCOUNTER11 0xc0b
+#define CSR_HPMCOUNTER12 0xc0c
+#define CSR_HPMCOUNTER13 0xc0d
+#define CSR_HPMCOUNTER14 0xc0e
+#define CSR_HPMCOUNTER15 0xc0f
+#define CSR_HPMCOUNTER16 0xc10
+#define CSR_HPMCOUNTER17 0xc11
+#define CSR_HPMCOUNTER18 0xc12
+#define CSR_HPMCOUNTER19 0xc13
+#define CSR_HPMCOUNTER20 0xc14
+#define CSR_HPMCOUNTER21 0xc15
+#define CSR_HPMCOUNTER22 0xc16
+#define CSR_HPMCOUNTER23 0xc17
+#define CSR_HPMCOUNTER24 0xc18
+#define CSR_HPMCOUNTER25 0xc19
+#define CSR_HPMCOUNTER26 0xc1a
+#define CSR_HPMCOUNTER27 0xc1b
+#define CSR_HPMCOUNTER28 0xc1c
+#define CSR_HPMCOUNTER29 0xc1d
+#define CSR_HPMCOUNTER30 0xc1e
+#define CSR_HPMCOUNTER31 0xc1f
+#define CSR_SSTATUS 0x100
+#define CSR_SIE 0x104
+#define CSR_STVEC 0x105
+#define CSR_SCOUNTEREN 0x106
+#define CSR_SSCRATCH 0x140
+#define CSR_SEPC 0x141
+#define CSR_SCAUSE 0x142
+#define CSR_STVAL 0x143
+#define CSR_SIP 0x144
+#define CSR_SATP 0x180
+#define CSR_MSTATUS 0x300
+#define CSR_MISA 0x301
+#define CSR_MEDELEG 0x302
+#define CSR_MIDELEG 0x303
+#define CSR_MIE 0x304
+#define CSR_MTVEC 0x305
+#define CSR_MCOUNTEREN 0x306
+#define CSR_MSCRATCH 0x340
+#define CSR_MEPC 0x341
+#define CSR_MCAUSE 0x342
+#define CSR_MTVAL 0x343
+#define CSR_MIP 0x344
+#define CSR_PMPCFG0 0x3a0
+#define CSR_PMPCFG1 0x3a1
+#define CSR_PMPCFG2 0x3a2
+#define CSR_PMPCFG3 0x3a3
+#define CSR_PMPADDR0 0x3b0
+#define CSR_PMPADDR1 0x3b1
+#define CSR_PMPADDR2 0x3b2
+#define CSR_PMPADDR3 0x3b3
+#define CSR_PMPADDR4 0x3b4
+#define CSR_PMPADDR5 0x3b5
+#define CSR_PMPADDR6 0x3b6
+#define CSR_PMPADDR7 0x3b7
+#define CSR_PMPADDR8 0x3b8
+#define CSR_PMPADDR9 0x3b9
+#define CSR_PMPADDR10 0x3ba
+#define CSR_PMPADDR11 0x3bb
+#define CSR_PMPADDR12 0x3bc
+#define CSR_PMPADDR13 0x3bd
+#define CSR_PMPADDR14 0x3be
+#define CSR_PMPADDR15 0x3bf
+#define CSR_TSELECT 0x7a0
+#define CSR_TDATA1 0x7a1
+#define CSR_TDATA2 0x7a2
+#define CSR_TDATA3 0x7a3
+#define CSR_DCSR 0x7b0
+#define CSR_DPC 0x7b1
+#define CSR_DSCRATCH 0x7b2
+#define CSR_MCYCLE 0xb00
+#define CSR_MINSTRET 0xb02
+#define CSR_MHPMCOUNTER3 0xb03
+#define CSR_MHPMCOUNTER4 0xb04
+#define CSR_MHPMCOUNTER5 0xb05
+#define CSR_MHPMCOUNTER6 0xb06
+#define CSR_MHPMCOUNTER7 0xb07
+#define CSR_MHPMCOUNTER8 0xb08
+#define CSR_MHPMCOUNTER9 0xb09
+#define CSR_MHPMCOUNTER10 0xb0a
+#define CSR_MHPMCOUNTER11 0xb0b
+#define CSR_MHPMCOUNTER12 0xb0c
+#define CSR_MHPMCOUNTER13 0xb0d
+#define CSR_MHPMCOUNTER14 0xb0e
+#define CSR_MHPMCOUNTER15 0xb0f
+#define CSR_MHPMCOUNTER16 0xb10
+#define CSR_MHPMCOUNTER17 0xb11
+#define CSR_MHPMCOUNTER18 0xb12
+#define CSR_MHPMCOUNTER19 0xb13
+#define CSR_MHPMCOUNTER20 0xb14
+#define CSR_MHPMCOUNTER21 0xb15
+#define CSR_MHPMCOUNTER22 0xb16
+#define CSR_MHPMCOUNTER23 0xb17
+#define CSR_MHPMCOUNTER24 0xb18
+#define CSR_MHPMCOUNTER25 0xb19
+#define CSR_MHPMCOUNTER26 0xb1a
+#define CSR_MHPMCOUNTER27 0xb1b
+#define CSR_MHPMCOUNTER28 0xb1c
+#define CSR_MHPMCOUNTER29 0xb1d
+#define CSR_MHPMCOUNTER30 0xb1e
+#define CSR_MHPMCOUNTER31 0xb1f
+#define CSR_MHPMEVENT3 0x323
+#define CSR_MHPMEVENT4 0x324
+#define CSR_MHPMEVENT5 0x325
+#define CSR_MHPMEVENT6 0x326
+#define CSR_MHPMEVENT7 0x327
+#define CSR_MHPMEVENT8 0x328
+#define CSR_MHPMEVENT9 0x329
+#define CSR_MHPMEVENT10 0x32a
+#define CSR_MHPMEVENT11 0x32b
+#define CSR_MHPMEVENT12 0x32c
+#define CSR_MHPMEVENT13 0x32d
+#define CSR_MHPMEVENT14 0x32e
+#define CSR_MHPMEVENT15 0x32f
+#define CSR_MHPMEVENT16 0x330
+#define CSR_MHPMEVENT17 0x331
+#define CSR_MHPMEVENT18 0x332
+#define CSR_MHPMEVENT19 0x333
+#define CSR_MHPMEVENT20 0x334
+#define CSR_MHPMEVENT21 0x335
+#define CSR_MHPMEVENT22 0x336
+#define CSR_MHPMEVENT23 0x337
+#define CSR_MHPMEVENT24 0x338
+#define CSR_MHPMEVENT25 0x339
+#define CSR_MHPMEVENT26 0x33a
+#define CSR_MHPMEVENT27 0x33b
+#define CSR_MHPMEVENT28 0x33c
+#define CSR_MHPMEVENT29 0x33d
+#define CSR_MHPMEVENT30 0x33e
+#define CSR_MHPMEVENT31 0x33f
+#define CSR_MVENDORID 0xf11
+#define CSR_MARCHID 0xf12
+#define CSR_MIMPID 0xf13
+#define CSR_MHARTID 0xf14
+#define CSR_CYCLEH 0xc80
+#define CSR_TIMEH 0xc81
+#define CSR_INSTRETH 0xc82
+#define CSR_HPMCOUNTER3H 0xc83
+#define CSR_HPMCOUNTER4H 0xc84
+#define CSR_HPMCOUNTER5H 0xc85
+#define CSR_HPMCOUNTER6H 0xc86
+#define CSR_HPMCOUNTER7H 0xc87
+#define CSR_HPMCOUNTER8H 0xc88
+#define CSR_HPMCOUNTER9H 0xc89
+#define CSR_HPMCOUNTER10H 0xc8a
+#define CSR_HPMCOUNTER11H 0xc8b
+#define CSR_HPMCOUNTER12H 0xc8c
+#define CSR_HPMCOUNTER13H 0xc8d
+#define CSR_HPMCOUNTER14H 0xc8e
+#define CSR_HPMCOUNTER15H 0xc8f
+#define CSR_HPMCOUNTER16H 0xc90
+#define CSR_HPMCOUNTER17H 0xc91
+#define CSR_HPMCOUNTER18H 0xc92
+#define CSR_HPMCOUNTER19H 0xc93
+#define CSR_HPMCOUNTER20H 0xc94
+#define CSR_HPMCOUNTER21H 0xc95
+#define CSR_HPMCOUNTER22H 0xc96
+#define CSR_HPMCOUNTER23H 0xc97
+#define CSR_HPMCOUNTER24H 0xc98
+#define CSR_HPMCOUNTER25H 0xc99
+#define CSR_HPMCOUNTER26H 0xc9a
+#define CSR_HPMCOUNTER27H 0xc9b
+#define CSR_HPMCOUNTER28H 0xc9c
+#define CSR_HPMCOUNTER29H 0xc9d
+#define CSR_HPMCOUNTER30H 0xc9e
+#define CSR_HPMCOUNTER31H 0xc9f
+#define CSR_MCYCLEH 0xb80
+#define CSR_MINSTRETH 0xb82
+#define CSR_MHPMCOUNTER3H 0xb83
+#define CSR_MHPMCOUNTER4H 0xb84
+#define CSR_MHPMCOUNTER5H 0xb85
+#define CSR_MHPMCOUNTER6H 0xb86
+#define CSR_MHPMCOUNTER7H 0xb87
+#define CSR_MHPMCOUNTER8H 0xb88
+#define CSR_MHPMCOUNTER9H 0xb89
+#define CSR_MHPMCOUNTER10H 0xb8a
+#define CSR_MHPMCOUNTER11H 0xb8b
+#define CSR_MHPMCOUNTER12H 0xb8c
+#define CSR_MHPMCOUNTER13H 0xb8d
+#define CSR_MHPMCOUNTER14H 0xb8e
+#define CSR_MHPMCOUNTER15H 0xb8f
+#define CSR_MHPMCOUNTER16H 0xb90
+#define CSR_MHPMCOUNTER17H 0xb91
+#define CSR_MHPMCOUNTER18H 0xb92
+#define CSR_MHPMCOUNTER19H 0xb93
+#define CSR_MHPMCOUNTER20H 0xb94
+#define CSR_MHPMCOUNTER21H 0xb95
+#define CSR_MHPMCOUNTER22H 0xb96
+#define CSR_MHPMCOUNTER23H 0xb97
+#define CSR_MHPMCOUNTER24H 0xb98
+#define CSR_MHPMCOUNTER25H 0xb99
+#define CSR_MHPMCOUNTER26H 0xb9a
+#define CSR_MHPMCOUNTER27H 0xb9b
+#define CSR_MHPMCOUNTER28H 0xb9c
+#define CSR_MHPMCOUNTER29H 0xb9d
+#define CSR_MHPMCOUNTER30H 0xb9e
+#define CSR_MHPMCOUNTER31H 0xb9f
+#define CAUSE_MISALIGNED_FETCH 0x0
+#define CAUSE_FETCH_ACCESS 0x1
+#define CAUSE_ILLEGAL_INSTRUCTION 0x2
+#define CAUSE_BREAKPOINT 0x3
+#define CAUSE_MISALIGNED_LOAD 0x4
+#define CAUSE_LOAD_ACCESS 0x5
+#define CAUSE_MISALIGNED_STORE 0x6
+#define CAUSE_STORE_ACCESS 0x7
+#define CAUSE_USER_ECALL 0x8
+#define CAUSE_SUPERVISOR_ECALL 0x9
+#define CAUSE_HYPERVISOR_ECALL 0xa
+#define CAUSE_MACHINE_ECALL 0xb
+#define CAUSE_FETCH_PAGE_FAULT 0xc
+#define CAUSE_LOAD_PAGE_FAULT 0xd
+#define CAUSE_STORE_PAGE_FAULT 0xf
+#endif
+#ifdef DECLARE_INSN
+DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ)
+DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
+DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
+DECLARE_INSN(bge, MATCH_BGE, MASK_BGE)
+DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
+DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU)
+DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR)
+DECLARE_INSN(jal, MATCH_JAL, MASK_JAL)
+DECLARE_INSN(lui, MATCH_LUI, MASK_LUI)
+DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC)
+DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
+DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI)
+DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI)
+DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU)
+DECLARE_INSN(xori, MATCH_XORI, MASK_XORI)
+DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI)
+DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
+DECLARE_INSN(ori, MATCH_ORI, MASK_ORI)
+DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI)
+DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
+DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
+DECLARE_INSN(sll, MATCH_SLL, MASK_SLL)
+DECLARE_INSN(slt, MATCH_SLT, MASK_SLT)
+DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU)
+DECLARE_INSN(xor, MATCH_XOR, MASK_XOR)
+DECLARE_INSN(srl, MATCH_SRL, MASK_SRL)
+DECLARE_INSN(sra, MATCH_SRA, MASK_SRA)
+DECLARE_INSN(or, MATCH_OR, MASK_OR)
+DECLARE_INSN(and, MATCH_AND, MASK_AND)
+DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
+DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
+DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
+DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW)
+DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW)
+DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW)
+DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW)
+DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW)
+DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW)
+DECLARE_INSN(lb, MATCH_LB, MASK_LB)
+DECLARE_INSN(lh, MATCH_LH, MASK_LH)
+DECLARE_INSN(lw, MATCH_LW, MASK_LW)
+DECLARE_INSN(ld, MATCH_LD, MASK_LD)
+DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU)
+DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU)
+DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU)
+DECLARE_INSN(sb, MATCH_SB, MASK_SB)
+DECLARE_INSN(sh, MATCH_SH, MASK_SH)
+DECLARE_INSN(sw, MATCH_SW, MASK_SW)
+DECLARE_INSN(sd, MATCH_SD, MASK_SD)
+DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE)
+DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I)
+DECLARE_INSN(mul, MATCH_MUL, MASK_MUL)
+DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
+DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU)
+DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU)
+DECLARE_INSN(div, MATCH_DIV, MASK_DIV)
+DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU)
+DECLARE_INSN(rem, MATCH_REM, MASK_REM)
+DECLARE_INSN(remu, MATCH_REMU, MASK_REMU)
+DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW)
+DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW)
+DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW)
+DECLARE_INSN(remw, MATCH_REMW, MASK_REMW)
+DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW)
+DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W)
+DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W)
+DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W)
+DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W)
+DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W)
+DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W)
+DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W)
+DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W)
+DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W)
+DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W)
+DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
+DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D)
+DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D)
+DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D)
+DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D)
+DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D)
+DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D)
+DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D)
+DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D)
+DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D)
+DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D)
+DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D)
+DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
+DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK)
+DECLARE_INSN(uret, MATCH_URET, MASK_URET)
+DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
+DECLARE_INSN(mret, MATCH_MRET, MASK_MRET)
+DECLARE_INSN(dret, MATCH_DRET, MASK_DRET)
+DECLARE_INSN(sfence_vma, MATCH_SFENCE_VMA, MASK_SFENCE_VMA)
+DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
+DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
+DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
+DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
+DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI)
+DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI)
+DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
+DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S)
+DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S)
+DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
+DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S)
+DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S)
+DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S)
+DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S)
+DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S)
+DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S)
+DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S)
+DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D)
+DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D)
+DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D)
+DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D)
+DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D)
+DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D)
+DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D)
+DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D)
+DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D)
+DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D)
+DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S)
+DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D)
+DECLARE_INSN(fadd_q, MATCH_FADD_Q, MASK_FADD_Q)
+DECLARE_INSN(fsub_q, MATCH_FSUB_Q, MASK_FSUB_Q)
+DECLARE_INSN(fmul_q, MATCH_FMUL_Q, MASK_FMUL_Q)
+DECLARE_INSN(fdiv_q, MATCH_FDIV_Q, MASK_FDIV_Q)
+DECLARE_INSN(fsgnj_q, MATCH_FSGNJ_Q, MASK_FSGNJ_Q)
+DECLARE_INSN(fsgnjn_q, MATCH_FSGNJN_Q, MASK_FSGNJN_Q)
+DECLARE_INSN(fsgnjx_q, MATCH_FSGNJX_Q, MASK_FSGNJX_Q)
+DECLARE_INSN(fmin_q, MATCH_FMIN_Q, MASK_FMIN_Q)
+DECLARE_INSN(fmax_q, MATCH_FMAX_Q, MASK_FMAX_Q)
+DECLARE_INSN(fcvt_s_q, MATCH_FCVT_S_Q, MASK_FCVT_S_Q)
+DECLARE_INSN(fcvt_q_s, MATCH_FCVT_Q_S, MASK_FCVT_Q_S)
+DECLARE_INSN(fcvt_d_q, MATCH_FCVT_D_Q, MASK_FCVT_D_Q)
+DECLARE_INSN(fcvt_q_d, MATCH_FCVT_Q_D, MASK_FCVT_Q_D)
+DECLARE_INSN(fsqrt_q, MATCH_FSQRT_Q, MASK_FSQRT_Q)
+DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S)
+DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S)
+DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S)
+DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D)
+DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D)
+DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
+DECLARE_INSN(fle_q, MATCH_FLE_Q, MASK_FLE_Q)
+DECLARE_INSN(flt_q, MATCH_FLT_Q, MASK_FLT_Q)
+DECLARE_INSN(feq_q, MATCH_FEQ_Q, MASK_FEQ_Q)
+DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S)
+DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S)
+DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S)
+DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S)
+DECLARE_INSN(fmv_x_w, MATCH_FMV_X_W, MASK_FMV_X_W)
+DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
+DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D)
+DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
+DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D)
+DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D)
+DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D)
+DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
+DECLARE_INSN(fcvt_w_q, MATCH_FCVT_W_Q, MASK_FCVT_W_Q)
+DECLARE_INSN(fcvt_wu_q, MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q)
+DECLARE_INSN(fcvt_l_q, MATCH_FCVT_L_Q, MASK_FCVT_L_Q)
+DECLARE_INSN(fcvt_lu_q, MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q)
+DECLARE_INSN(fmv_x_q, MATCH_FMV_X_Q, MASK_FMV_X_Q)
+DECLARE_INSN(fclass_q, MATCH_FCLASS_Q, MASK_FCLASS_Q)
+DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W)
+DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU)
+DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L)
+DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU)
+DECLARE_INSN(fmv_w_x, MATCH_FMV_W_X, MASK_FMV_W_X)
+DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W)
+DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
+DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
+DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU)
+DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X)
+DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W)
+DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU)
+DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L)
+DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU)
+DECLARE_INSN(fmv_q_x, MATCH_FMV_Q_X, MASK_FMV_Q_X)
+DECLARE_INSN(flw, MATCH_FLW, MASK_FLW)
+DECLARE_INSN(fld, MATCH_FLD, MASK_FLD)
+DECLARE_INSN(flq, MATCH_FLQ, MASK_FLQ)
+DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW)
+DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD)
+DECLARE_INSN(fsq, MATCH_FSQ, MASK_FSQ)
+DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S)
+DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S)
+DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S)
+DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S)
+DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D)
+DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D)
+DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D)
+DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D)
+DECLARE_INSN(fmadd_q, MATCH_FMADD_Q, MASK_FMADD_Q)
+DECLARE_INSN(fmsub_q, MATCH_FMSUB_Q, MASK_FMSUB_Q)
+DECLARE_INSN(fnmsub_q, MATCH_FNMSUB_Q, MASK_FNMSUB_Q)
+DECLARE_INSN(fnmadd_q, MATCH_FNMADD_Q, MASK_FNMADD_Q)
+DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP)
+DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
+DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
+DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
+DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK)
+DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
+DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
+DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
+DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
+DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
+DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
+DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD)
+DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
+DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW)
+DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD)
+DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
+DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW)
+DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
+DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
+DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
+DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
+DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
+DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
+DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI)
+DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
+DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR)
+DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR)
+DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND)
+DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW)
+DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
+DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
+DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
+DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
+DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
+DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP)
+DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
+DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP)
+DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
+DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
+DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP)
+DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
+DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP)
+DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0)
+DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1)
+DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2)
+DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD)
+DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1)
+DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2)
+DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1)
+DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1)
+DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2)
+DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD)
+DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1)
+DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2)
+DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2)
+DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1)
+DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2)
+DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD)
+DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1)
+DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2)
+DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3)
+DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1)
+DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2)
+DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD)
+DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1)
+DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2)
+#endif
+#ifdef DECLARE_CSR
+DECLARE_CSR(fflags, CSR_FFLAGS)
+DECLARE_CSR(frm, CSR_FRM)
+DECLARE_CSR(fcsr, CSR_FCSR)
+DECLARE_CSR(cycle, CSR_CYCLE)
+DECLARE_CSR(time, CSR_TIME)
+DECLARE_CSR(instret, CSR_INSTRET)
+DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3)
+DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4)
+DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5)
+DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6)
+DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7)
+DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8)
+DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9)
+DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10)
+DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11)
+DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12)
+DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13)
+DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14)
+DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15)
+DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16)
+DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17)
+DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18)
+DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19)
+DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20)
+DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21)
+DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22)
+DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23)
+DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24)
+DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25)
+DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26)
+DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27)
+DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28)
+DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29)
+DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30)
+DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31)
+DECLARE_CSR(sstatus, CSR_SSTATUS)
+DECLARE_CSR(sie, CSR_SIE)
+DECLARE_CSR(stvec, CSR_STVEC)
+DECLARE_CSR(scounteren, CSR_SCOUNTEREN)
+DECLARE_CSR(sscratch, CSR_SSCRATCH)
+DECLARE_CSR(sepc, CSR_SEPC)
+DECLARE_CSR(scause, CSR_SCAUSE)
+DECLARE_CSR(stval, CSR_STVAL)
+DECLARE_CSR(sip, CSR_SIP)
+DECLARE_CSR(satp, CSR_SATP)
+DECLARE_CSR(mstatus, CSR_MSTATUS)
+DECLARE_CSR(misa, CSR_MISA)
+DECLARE_CSR(medeleg, CSR_MEDELEG)
+DECLARE_CSR(mideleg, CSR_MIDELEG)
+DECLARE_CSR(mie, CSR_MIE)
+DECLARE_CSR(mtvec, CSR_MTVEC)
+DECLARE_CSR(mcounteren, CSR_MCOUNTEREN)
+DECLARE_CSR(mscratch, CSR_MSCRATCH)
+DECLARE_CSR(mepc, CSR_MEPC)
+DECLARE_CSR(mcause, CSR_MCAUSE)
+DECLARE_CSR(mtval, CSR_MTVAL)
+DECLARE_CSR(mip, CSR_MIP)
+DECLARE_CSR(pmpcfg0, CSR_PMPCFG0)
+DECLARE_CSR(pmpcfg1, CSR_PMPCFG1)
+DECLARE_CSR(pmpcfg2, CSR_PMPCFG2)
+DECLARE_CSR(pmpcfg3, CSR_PMPCFG3)
+DECLARE_CSR(pmpaddr0, CSR_PMPADDR0)
+DECLARE_CSR(pmpaddr1, CSR_PMPADDR1)
+DECLARE_CSR(pmpaddr2, CSR_PMPADDR2)
+DECLARE_CSR(pmpaddr3, CSR_PMPADDR3)
+DECLARE_CSR(pmpaddr4, CSR_PMPADDR4)
+DECLARE_CSR(pmpaddr5, CSR_PMPADDR5)
+DECLARE_CSR(pmpaddr6, CSR_PMPADDR6)
+DECLARE_CSR(pmpaddr7, CSR_PMPADDR7)
+DECLARE_CSR(pmpaddr8, CSR_PMPADDR8)
+DECLARE_CSR(pmpaddr9, CSR_PMPADDR9)
+DECLARE_CSR(pmpaddr10, CSR_PMPADDR10)
+DECLARE_CSR(pmpaddr11, CSR_PMPADDR11)
+DECLARE_CSR(pmpaddr12, CSR_PMPADDR12)
+DECLARE_CSR(pmpaddr13, CSR_PMPADDR13)
+DECLARE_CSR(pmpaddr14, CSR_PMPADDR14)
+DECLARE_CSR(pmpaddr15, CSR_PMPADDR15)
+DECLARE_CSR(tselect, CSR_TSELECT)
+DECLARE_CSR(tdata1, CSR_TDATA1)
+DECLARE_CSR(tdata2, CSR_TDATA2)
+DECLARE_CSR(tdata3, CSR_TDATA3)
+DECLARE_CSR(dcsr, CSR_DCSR)
+DECLARE_CSR(dpc, CSR_DPC)
+DECLARE_CSR(dscratch, CSR_DSCRATCH)
+DECLARE_CSR(mcycle, CSR_MCYCLE)
+DECLARE_CSR(minstret, CSR_MINSTRET)
+DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3)
+DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4)
+DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5)
+DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6)
+DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7)
+DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8)
+DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9)
+DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10)
+DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11)
+DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12)
+DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13)
+DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14)
+DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15)
+DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16)
+DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17)
+DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18)
+DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19)
+DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20)
+DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21)
+DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22)
+DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23)
+DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24)
+DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25)
+DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26)
+DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27)
+DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
+DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
+DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
+DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
+DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
+DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
+DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
+DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6)
+DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7)
+DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8)
+DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9)
+DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10)
+DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11)
+DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12)
+DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13)
+DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14)
+DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15)
+DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16)
+DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17)
+DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18)
+DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19)
+DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20)
+DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21)
+DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22)
+DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23)
+DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24)
+DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25)
+DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26)
+DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27)
+DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28)
+DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29)
+DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30)
+DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31)
+DECLARE_CSR(mvendorid, CSR_MVENDORID)
+DECLARE_CSR(marchid, CSR_MARCHID)
+DECLARE_CSR(mimpid, CSR_MIMPID)
+DECLARE_CSR(mhartid, CSR_MHARTID)
+DECLARE_CSR(cycleh, CSR_CYCLEH)
+DECLARE_CSR(timeh, CSR_TIMEH)
+DECLARE_CSR(instreth, CSR_INSTRETH)
+DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H)
+DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H)
+DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H)
+DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H)
+DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H)
+DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H)
+DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H)
+DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H)
+DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H)
+DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H)
+DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H)
+DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H)
+DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H)
+DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H)
+DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H)
+DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H)
+DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H)
+DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H)
+DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H)
+DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H)
+DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H)
+DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H)
+DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H)
+DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H)
+DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H)
+DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H)
+DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H)
+DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H)
+DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H)
+DECLARE_CSR(mcycleh, CSR_MCYCLEH)
+DECLARE_CSR(minstreth, CSR_MINSTRETH)
+DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H)
+DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H)
+DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H)
+DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H)
+DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H)
+DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H)
+DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H)
+DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H)
+DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H)
+DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H)
+DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H)
+DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H)
+DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H)
+DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H)
+DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H)
+DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H)
+DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H)
+DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H)
+DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H)
+DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H)
+DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H)
+DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H)
+DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H)
+DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H)
+DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H)
+DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H)
+DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H)
+DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H)
+DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H)
+#endif
+#ifdef DECLARE_CAUSE
+DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH)
+DECLARE_CAUSE("fetch access", CAUSE_FETCH_ACCESS)
+DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION)
+DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT)
+DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD)
+DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS)
+DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE)
+DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS)
+DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL)
+DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL)
+DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL)
+DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL)
+DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT)
+DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT)
+DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT)
+#endif
diff --git a/VexRiscv/src/test/cpp/regression/fail.gtkw b/VexRiscv/src/test/cpp/regression/fail.gtkw
new file mode 100644
index 0000000..d0fff46
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/fail.gtkw
@@ -0,0 +1,29 @@
+[*]
+[*] GTKWave Analyzer v3.3.100 (w)1999-2019 BSI
+[*] Thu Apr 25 14:41:35 2019
+[*]
+[dumpfile] "/home/miaou/pro/VexRiscv/src/test/cpp/regression/C.SLLI.vcd"
+[dumpfile_mtime] "Thu Apr 25 14:39:03 2019"
+[dumpfile_size] 295925
+[savefile] "/home/miaou/pro/VexRiscv/src/test/cpp/regression/fail.gtkw"
+[timestart] 0
+[size] 1920 1030
+[pos] -458 -215
+*-2.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[sst_width] 196
+[signals_width] 366
+[sst_expanded] 1
+[sst_vpaned_height] 299
+@28
+TOP.VexRiscv.lastStageIsValid
+TOP.VexRiscv.lastStageIsFiring
+@22
+TOP.VexRiscv.lastStageInstruction[31:0]
+TOP.VexRiscv.lastStagePc[31:0]
+TOP.VexRiscv.lastStageRegFileWrite_payload_address[4:0]
+TOP.VexRiscv.lastStageRegFileWrite_payload_data[31:0]
+@28
+TOP.VexRiscv.lastStageRegFileWrite_valid
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/icache.gtkw b/VexRiscv/src/test/cpp/regression/icache.gtkw
new file mode 100644
index 0000000..5a7020f
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/icache.gtkw
@@ -0,0 +1,67 @@
+[*]
+[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI
+[*] Wed Apr 11 18:53:23 2018
+[*]
+[dumpfile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/rv32ui-p-lui.vcd"
+[dumpfile_mtime] "Wed Apr 11 18:52:18 2018"
+[dumpfile_size] 325049
+[savefile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/icache.gtkw"
+[timestart] 1006
+[size] 1784 950
+[pos] -383 -155
+*-5.000000 1046 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[treeopen] TOP.VexRiscv.
+[sst_width] 370
+[signals_width] 349
+[sst_expanded] 1
+[sst_vpaned_height] 271
+@28
+TOP.VexRiscv.decode_arbitration_isValid
+TOP.VexRiscv.decode_arbitration_redoIt
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_haltIt
+@22
+TOP.VexRiscv.iBus_cmd_payload_address[31:0]
+@28
+TOP.VexRiscv.iBus_cmd_payload_size[2:0]
+TOP.VexRiscv.iBus_cmd_ready
+@29
+TOP.VexRiscv.iBus_cmd_valid
+@22
+TOP.VexRiscv.iBus_rsp_payload_data[31:0]
+@28
+TOP.VexRiscv.iBus_rsp_payload_error
+TOP.VexRiscv.iBus_rsp_valid
+[color] 2
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_isValid
+[color] 2
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_haltIt
+@22
+[color] 2
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_pc[31:0]
+@28
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_isValid
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_isStuck
+@22
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_data[31:0]
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_pc[31:0]
+@28
+[color] 6
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isValid
+[color] 6
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_cacheMiss
+[color] 6
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_error
+[color] 6
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_illegalAccess
+[color] 6
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isStuck
+[color] 6
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isUser
+[color] 6
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_mmuMiss
+@22
+[color] 6
+TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_pc[31:0]
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/main.cpp b/VexRiscv/src/test/cpp/regression/main.cpp
new file mode 100644
index 0000000..3d61c9a
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/main.cpp
@@ -0,0 +1,4514 @@
+#include "VVexRiscv.h"
+#include "VVexRiscv_VexRiscv.h"
+#ifdef REF
+#include "VVexRiscv_RiscvCore.h"
+#endif
+#include "verilated.h"
+#include "verilated_fst_c.h"
+#include <stdio.h>
+#include <iostream>
+#include <stdlib.h>
+#include <stdint.h>
+#include <cstring>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <mutex>
+#include <iomanip>
+#include <queue>
+#include <time.h>
+#include "encoding.h"
+
+#define VL_RANDOM_I_WIDTH(w) (VL_RANDOM_I() & (1l << w)-1l)
+
+using namespace std;
+
+struct timespec timer_get(){
+ struct timespec start_time;
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
+ return start_time;
+}
+
+class Memory{
+public:
+ uint8_t* mem[1 << 12];
+
+ Memory(){
+ for(uint32_t i = 0;i < (1 << 12);i++) mem[i] = NULL;
+ }
+ ~Memory(){
+ for(uint32_t i = 0;i < (1 << 12);i++) if(mem[i]) delete [] mem[i];
+ }
+
+ uint8_t* get(uint32_t address){
+ if(mem[address >> 20] == NULL) {
+ uint8_t* ptr = new uint8_t[1024*1024];
+ for(uint32_t i = 0;i < 1024*1024;i+=4) {
+ ptr[i + 0] = 0xFF;
+ ptr[i + 1] = 0xFF;
+ ptr[i + 2] = 0xFF;
+ ptr[i + 3] = 0xFF;
+ }
+ mem[address >> 20] = ptr;
+ }
+ return &mem[address >> 20][address & 0xFFFFF];
+ }
+
+ void read(uint32_t address,uint32_t length, uint8_t *data){
+ for(int i = 0;i < length;i++){
+ data[i] = (*this)[address + i];
+ }
+ }
+
+ void write(uint32_t address,uint32_t length, uint8_t *data){
+ for(int i = 0;i < length;i++){
+ (*this)[address + i] = data[i];
+ }
+ }
+
+ uint8_t& operator [](uint32_t address) {
+ return *get(address);
+ }
+
+ /*T operator [](uint32_t address) const {
+ return get(address);
+ }*/
+};
+
+//uint8_t memory[1024 * 1024];
+
+uint32_t hti(char c) {
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return c - '0';
+}
+
+uint32_t hToI(char *c, uint32_t size) {
+ uint32_t value = 0;
+ for (uint32_t i = 0; i < size; i++) {
+ value += hti(c[i]) << ((size - i - 1) * 4);
+ }
+ return value;
+}
+
+void loadHexImpl(string path,Memory* mem) {
+ FILE *fp = fopen(&path[0], "r");
+ if(fp == 0){
+ cout << path << " not found" << endl;
+ }
+ //Preload 0x0 <-> 0x80000000 jumps
+ ((uint32_t*)mem->get(0))[0] = 0x800000b7;
+ ((uint32_t*)mem->get(0))[1] = 0x000080e7;
+ ((uint32_t*)mem->get(0x80000000))[0] = 0x00000097;
+
+ fseek(fp, 0, SEEK_END);
+ uint32_t size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ char* content = new char[size];
+ fread(content, 1, size, fp);
+ fclose(fp);
+
+ int offset = 0;
+ char* line = content;
+ while (1) {
+ if (line[0] == ':') {
+ uint32_t byteCount = hToI(line + 1, 2);
+ uint32_t nextAddr = hToI(line + 3, 4) + offset;
+ uint32_t key = hToI(line + 7, 2);
+// printf("%d %d %d\n", byteCount, nextAddr,key);
+ switch (key) {
+ case 0:
+ for (uint32_t i = 0; i < byteCount; i++) {
+ *(mem->get(nextAddr + i)) = hToI(line + 9 + i * 2, 2);
+ //printf("%x %x %c%c\n",nextAddr + i,hToI(line + 9 + i*2,2),line[9 + i * 2],line[9 + i * 2+1]);
+ }
+ break;
+ case 2:
+// cout << offset << endl;
+ offset = hToI(line + 9, 4) << 4;
+ break;
+ case 4:
+// cout << offset << endl;
+ offset = hToI(line + 9, 4) << 16;
+ break;
+ default:
+// cout << "??? " << key << endl;
+ break;
+ }
+ }
+
+ while (*line != '\n' && size != 0) {
+ line++;
+ size--;
+ }
+ if (size <= 1)
+ break;
+ line++;
+ size--;
+ }
+
+ delete [] content;
+}
+
+void loadBinImpl(string path,Memory* mem, uint32_t offset) {
+ FILE *fp = fopen(&path[0], "r");
+ if(fp == 0){
+ cout << path << " not found" << endl;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ uint32_t size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ char* content = new char[size];
+ fread(content, 1, size, fp);
+ fclose(fp);
+
+ for(int byteId = 0; byteId < size;byteId++){
+ *(mem->get(offset + byteId)) = content[byteId];
+ }
+
+ delete [] content;
+}
+
+
+
+#define TEXTIFY(A) #A
+
+void breakMe(){
+ int a = 0;
+}
+#define assertEq(x,ref) if(x != ref) {\
+ printf("\n*** %s is %d but should be %d ***\n\n",TEXTIFY(x),x,ref);\
+ breakMe();\
+ throw std::exception();\
+}
+
+class success : public std::exception { };
+
+
+
+
+#define MVENDORID 0xF11 // MRO Vendor ID.
+#define MARCHID 0xF12 // MRO Architecture ID.
+#define MIMPID 0xF13 // MRO Implementation ID.
+#define MHARTID 0xF14 // MRO Hardware thread ID.Machine Trap Setup
+#define MSTATUS 0x300 // MRW Machine status register.
+#define MISA 0x301 // MRW ISA and extensions
+#define MEDELEG 0x302 // MRW Machine exception delegation register.
+#define MIDELEG 0x303 // MRW Machine interrupt delegation register.
+#define MIE 0x304 // MRW Machine interrupt-enable register.
+#define MTVEC 0x305 // MRW Machine trap-handler base address. Machine Trap Handling
+#define MSCRATCH 0x340 // MRW Scratch register for machine trap handlers.
+#define MEPC 0x341 // MRW Machine exception program counter.
+#define MCAUSE 0x342 // MRW Machine trap cause.
+#define MBADADDR 0x343 // MRW Machine bad address.
+#define MIP 0x344 // MRW Machine interrupt pending.
+#define MBASE 0x380 // MRW Base register.
+#define MBOUND 0x381 // MRW Bound register.
+#define MIBASE 0x382 // MRW Instruction base register.
+#define MIBOUND 0x383 // MRW Instruction bound register.
+#define MDBASE 0x384 // MRW Data base register.
+#define MDBOUND 0x385 // MRW Data bound register.
+#define MCYCLE 0xB00 // MRW Machine cycle counter.
+#define MINSTRET 0xB02 // MRW Machine instructions-retired counter.
+#define MCYCLEH 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
+#define MINSTRETH 0xB82 // MRW Upper 32 bits of minstret, RV32I only.
+
+
+#define SSTATUS 0x100
+#define SIE 0x104
+#define STVEC 0x105
+#define SCOUNTEREN 0x106
+#define SSCRATCH 0x140
+#define SEPC 0x141
+#define SCAUSE 0x142
+#define STVAL 0x143
+#define SIP 0x144
+#define SATP 0x180
+
+#define UTIME 0xC01 // rdtime
+#define UTIMEH 0xC81
+
+#define SSTATUS_SIE 0x00000002
+#define SSTATUS_SPIE 0x00000020
+#define SSTATUS_SPP 0x00000100
+
+#ifdef SUPERVISOR
+#define MSTATUS_READ_MASK 0xFFFFFFFF
+#else
+#define MSTATUS_READ_MASK 0x7888
+#endif
+
+#ifdef RVF
+#define STATUS_FS_MASK 0x6000
+#else
+#define STATUS_FS_MASK 0x0000
+#endif
+
+#define FFLAGS 0x1
+#define FRM 0x2
+#define FCSR 0x3
+
+#define u32 uint32_t
+#define u64 uint64_t
+
+class FpuRsp{
+public:
+ u32 flags;
+ u64 value;
+};
+
+class FpuCommit{
+public:
+ u64 value;
+};
+
+class FpuCompletion{
+public:
+ u32 flags;
+};
+
+
+bool fpuCommitLut[32] = {true,true,true,true,true,true,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false};
+bool fpuRspLut[32] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,true,false,false,false};
+bool fpuRs1Lut[32] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false};
+class RiscvGolden {
+public:
+ int32_t pc, lastPc;
+ uint32_t lastInstruction;
+ int32_t regs[32];
+ uint64_t stepCounter;
+
+ uint32_t mscratch, sscratch;
+ uint32_t misa;
+ uint32_t privilege;
+
+ uint32_t medeleg;
+ uint32_t mideleg;
+
+ queue<FpuRsp> fpuRsp;
+ queue<FpuCommit> fpuCommit;
+ queue<FpuCompletion> fpuCompletion;
+
+ union status {
+ uint32_t raw;
+ struct {
+ uint32_t _1a : 1;
+ uint32_t sie : 1;
+ uint32_t _1b : 1;
+ uint32_t mie : 1;
+ uint32_t _2a : 1;
+ uint32_t spie : 1;
+ uint32_t _2b : 1;
+ uint32_t mpie : 1;
+ uint32_t spp : 1;
+ uint32_t _3 : 2;
+ uint32_t mpp : 2;
+ uint32_t fs : 2;
+ uint32_t _4 : 2;
+ uint32_t mprv : 1;
+ uint32_t sum : 1;
+ uint32_t mxr : 1;
+ };
+ }__attribute__((packed)) status;
+
+
+
+ uint32_t ipInput;
+ uint32_t ipSoft;
+ union IpOr {
+ uint32_t raw;
+ struct {
+ uint32_t _1a : 1;
+ uint32_t ssip : 1;
+ uint32_t _1b : 1;
+ uint32_t msip : 1;
+ uint32_t _2a : 1;
+ uint32_t stip : 1;
+ uint32_t _2b : 1;
+ uint32_t mtip : 1;
+ uint32_t _3a : 1;
+ uint32_t seip : 1;
+ uint32_t _3b : 1;
+ uint32_t meip : 1;
+ };
+ }__attribute__((packed));
+
+ IpOr getIp(){
+ IpOr ret;
+ ret.raw = ipSoft | ipInput;
+ return ret;
+ }
+
+ union mie {
+ uint32_t raw;
+ struct {
+ uint32_t _1a : 1;
+ uint32_t ssie : 1;
+ uint32_t _1b : 1;
+ uint32_t msie : 1;
+ uint32_t _2a : 1;
+ uint32_t stie : 1;
+ uint32_t _2b : 1;
+ uint32_t mtie : 1;
+ uint32_t _3a : 1;
+ uint32_t seie : 1;
+ uint32_t _3b : 1;
+ uint32_t meie : 1;
+ };
+ }__attribute__((packed)) ie;
+
+ union Xtvec {
+ uint32_t raw;
+ struct __attribute__((packed)) {
+ uint32_t _1 : 2;
+ uint32_t base : 30;
+ };
+ };
+
+ Xtvec mtvec, stvec;
+
+
+
+ union mcause {
+ uint32_t raw;
+ struct __attribute__((packed)) {
+ uint32_t exceptionCode : 31;
+ uint32_t interrupt : 1;
+ };
+ } mcause;
+
+
+ union scause {
+ uint32_t raw;
+ struct __attribute__((packed)){
+ uint32_t exceptionCode : 31;
+ uint32_t interrupt : 1;
+ };
+ } scause;
+
+ union satp {
+ uint32_t raw;
+ struct __attribute__((packed)){
+ uint32_t ppn : 22;
+ uint32_t _x : 9;
+ uint32_t mode : 1;
+ };
+ }satp;
+
+ union Tlb {
+ uint32_t raw;
+ struct __attribute__((packed)){
+ uint32_t v : 1;
+ uint32_t r : 1;
+ uint32_t w : 1;
+ uint32_t x : 1;
+ uint32_t u : 1;
+ uint32_t _dummy : 5;
+ uint32_t ppn : 22;
+ };
+ struct __attribute__((packed)){
+ uint32_t _dummyX : 10;
+ uint32_t ppn0 : 10;
+ uint32_t ppn1 : 12;
+ };
+ };
+
+ union fcsr {
+ uint32_t raw;
+ struct __attribute__((packed)){
+ uint32_t flags : 5;
+ uint32_t frm : 3;
+ };
+ }fcsr;
+
+
+ bool lrscReserved;
+ uint32_t lrscReservedAddress;
+ u32 fpuCompletionTockens;
+ u32 dutRfWriteValue;
+
+ RiscvGolden() {
+ pc = 0x80000000;
+ regs[0] = 0;
+ for (int i = 0; i < 32; i++)
+ regs[i] = 0;
+
+ ie.raw = 0;
+ mtvec.raw = 0x80000020;
+ mcause.raw = 0;
+ mbadaddr = 0;
+ mepc = 0;
+ misa = 0x40041101; //TODO
+ status.raw = 0;
+ status.mpp = 3;
+ status.spp = 1;
+ #ifdef RVF
+ status.fs = 1;
+ misa |= 1 << 5;
+ #endif
+ #ifdef RVD
+ misa |= 1 << 3;
+ #endif
+ fcsr.flags = 0;
+ fcsr.frm = 0;
+ privilege = 3;
+ medeleg = 0;
+ mideleg = 0;
+ satp.mode = 0;
+ ipSoft = 0;
+ ipInput = 0;
+ stepCounter = 0;
+ sbadaddr = 42;
+ lrscReserved = false;
+ fpuCompletionTockens = 0;
+ }
+
+ virtual void rfWrite(int32_t address, int32_t data) {
+ if (address != 0)
+ regs[address] = data;
+ }
+
+ virtual void pcWrite(int32_t target) {
+ if(isPcAligned(target)){
+ lastPc = pc;
+ pc = target;
+ } else {
+ trap(0, 0, target);
+ }
+ }
+ uint32_t mbadaddr, sbadaddr;
+ uint32_t mepc, sepc;
+
+ virtual bool iRead(int32_t address, uint32_t *data) = 0;
+ virtual bool dRead(int32_t address, int32_t size, uint8_t *data) = 0;
+ virtual void dWrite(int32_t address, int32_t size, uint8_t *data) = 0;
+
+ enum AccessKind {READ,WRITE,EXECUTE,READ_WRITE};
+ virtual bool isMmuRegion(uint32_t v) = 0;
+ bool v2p(uint32_t v, uint32_t *p, AccessKind kind){
+ uint32_t effectivePrivilege = status.mprv && kind != EXECUTE ? status.mpp : privilege;
+ if(effectivePrivilege == 3 || satp.mode == 0 || !isMmuRegion(v)){
+ *p = v;
+ } else {
+ Tlb tlb;
+ dRead((satp.ppn << 12) | ((v >> 22) << 2), 4, (uint8_t*)&tlb.raw);
+ if(!tlb.v) return true;
+ bool superPage = true;
+ if(!tlb.x && !tlb.r && !tlb.w){
+ dRead((tlb.ppn << 12) | (((v >> 12) & 0x3FF) << 2), 4, (uint8_t*)&tlb.raw);
+ if(!tlb.v) return true;
+ superPage = false;
+ }
+ if(!tlb.u && effectivePrivilege == 0) return true;
+ if( tlb.u && effectivePrivilege == 1 && !status.sum) return true;
+ if(superPage && tlb.ppn0 != 0) return true;
+ if(kind == READ || kind == READ_WRITE) if(!tlb.r && !(status.mxr && tlb.x)) return true;
+ if(kind == WRITE || kind == READ_WRITE) if(!tlb.w) return true;
+ if(kind == EXECUTE) if(!tlb.x) return true;
+
+ *p = (tlb.ppn1 << 22) | (superPage ? v & 0x3FF000 : tlb.ppn0 << 12) | (v & 0xFFF);
+ }
+ return false;
+ }
+
+ void trap(bool interrupt,int32_t cause) {
+ trap(interrupt, cause, false, 0);
+ }
+ void trap(bool interrupt,int32_t cause, uint32_t value) {
+ trap(interrupt, cause, true, value);
+ }
+ void trap(bool interrupt,int32_t cause, bool valueWrite, uint32_t value) {
+#ifdef FLOW_INFO
+// cout << "TRAP " << (interrupt ? "interrupt" : "exception") << " cause=" << cause << " PC=0x" << hex << pc << " val=0x" << hex << value << dec << endl;
+// if(cause == 9){
+// cout << hex << " a7=0x" << regs[17] << " a0=0x" << regs[10] << " a1=0x" << regs[11] << " a2=0x" << regs[12] << dec << endl;
+// }
+#endif
+ //Check leguality of the interrupt
+ if(interrupt) {
+ bool hit = false;
+ for(int i = 0;i < 5;i++){
+ if(pendingInterrupts[i] == 1 << cause){
+ hit = true;
+ break;
+ }
+ }
+ if(!hit){
+ cout << "DUT had trigger an interrupts which wasn't by the REF" << endl;
+ fail();
+ }
+ }
+
+ uint32_t deleg = interrupt ? mideleg : medeleg;
+ uint32_t targetPrivilege = 3;
+ if(deleg & (1 << cause)) targetPrivilege = 1;
+ targetPrivilege = max(targetPrivilege, privilege);
+ Xtvec xtvec = targetPrivilege == 3 ? mtvec : stvec;
+
+
+
+ switch(targetPrivilege){
+ case 3:
+ if(valueWrite) mbadaddr = value;
+ mcause.interrupt = interrupt;
+ mcause.exceptionCode = cause;
+ status.mpie = status.mie;
+ status.mie = false;
+ status.mpp = privilege;
+ mepc = pc;
+ break;
+ case 1:
+ if(valueWrite) sbadaddr = value;
+ scause.interrupt = interrupt;
+ scause.exceptionCode = cause;
+ status.spie = status.sie;
+ status.sie = false;
+ status.spp = privilege;
+ sepc = pc;
+ break;
+ }
+
+ privilege = targetPrivilege;
+ pcWrite(xtvec.base << 2);
+ if(interrupt) livenessInterrupt = 0;
+
+// if(!interrupt) step(); //As VexRiscv instruction which trap do not reach writeback stage fire
+ }
+
+ uint32_t currentInstruction;
+ void ilegalInstruction(){
+ trap(0, 2, currentInstruction);
+ }
+
+ virtual void fail() {
+ }
+
+
+
+ virtual bool csrRead(int32_t csr, uint32_t *value){
+ if(((csr >> 8) & 0x3) > privilege) return true;
+ switch(csr){
+ case MSTATUS: *value = (status.raw | (((status.raw & 0x6000) == 0x6000) ? 0x80000000 : 0)) & MSTATUS_READ_MASK; break;
+ case MIP: *value = getIp().raw; break;
+ case MIE: *value = ie.raw; break;
+ case MTVEC: *value = mtvec.raw; break;
+ case MCAUSE: *value = mcause.raw; break;
+ case MBADADDR: *value = mbadaddr; break;
+ case MEPC: *value = mepc; break;
+ case MSCRATCH: *value = mscratch; break;
+ case MISA: *value = misa; break;
+ case MEDELEG: *value = medeleg; break;
+ case MIDELEG: *value = mideleg; break;
+ case MHARTID: *value = 0; break;
+
+ case SSTATUS: *value = (status.raw | (((status.raw & 0x6000) == 0x6000) ? 0x80000000 : 0)) & (0x800C0133 | STATUS_FS_MASK); break;
+ case SIP: *value = getIp().raw & 0x333; break;
+ case SIE: *value = ie.raw & 0x333; break;
+ case STVEC: *value = stvec.raw; break;
+ case SCAUSE: *value = scause.raw; break;
+ case STVAL: *value = sbadaddr; break;
+ case SEPC: *value = sepc; break;
+ case SSCRATCH: *value = sscratch; break;
+ case SATP: *value = satp.raw; break;
+
+ #ifdef RVF
+ case FCSR: *value = fcsr.raw; break;
+ case FRM: *value = fcsr.frm; break;
+ case FFLAGS: *value = fcsr.flags; break;
+ #endif
+
+ #ifdef UTIME_INPUT
+ case UTIME: *value = dutRfWriteValue; break;
+ case UTIMEH: *value = dutRfWriteValue; break;
+ #endif
+
+ default: return true; break;
+ }
+ return false;
+ }
+
+ virtual uint32_t csrReadToWriteOverride(int32_t csr, uint32_t value){
+ if(((csr >> 8) & 0x3) > privilege) return true;
+ switch(csr){
+ case MIP: return ipSoft; break;
+ case SIP: return ipSoft & 0x333; break;
+ };
+ return value;
+ }
+
+ #define maskedWrite(dst, src, mask) dst=((dst) & ~(mask))|((src) & (mask));
+
+ virtual bool csrWrite(int32_t csr, uint32_t value){
+ if(((csr >> 8) & 0x3) > privilege) return true;
+ switch(csr){
+ case MSTATUS: status.raw = value & 0x7FFFFFFF; break;
+ case MIP: ipSoft = value; break;
+ case MIE: ie.raw = value; break;
+ case MTVEC: mtvec.raw = value; break;
+ case MCAUSE: mcause.raw = value; break;
+ case MBADADDR: mbadaddr = value; break;
+ case MEPC: mepc = value; break;
+ case MSCRATCH: mscratch = value; break;
+ case MISA: misa = value; break;
+ case MEDELEG: medeleg = value & (~0x8); break;
+ case MIDELEG: mideleg = value; break;
+
+ case SSTATUS: maskedWrite(status.raw, value, 0xC0133 | STATUS_FS_MASK); break;
+ case SIP: maskedWrite(ipSoft, value,0x333); break;
+ case SIE: maskedWrite(ie.raw, value,0x333); break;
+ case STVEC: stvec.raw = value; break;
+ case SCAUSE: scause.raw = value; break;
+ case STVAL: sbadaddr = value; break;
+ case SEPC: sepc = value; break;
+ case SSCRATCH: sscratch = value; break;
+ case SATP: satp.raw = value; break;
+
+ #ifdef RVF
+ case FCSR: fcsr.raw = value & 0x7F; break;
+ case FRM: fcsr.frm = value; break;
+ case FFLAGS: fcsr.flags = value; break;
+ #endif
+
+ default: ilegalInstruction(); return true; break;
+ }
+ return false;
+ }
+
+
+ int livenessStep = 0;
+ int livenessInterrupt = 0;
+ uint32_t pendingInterruptsPtr = 0;
+ uint32_t pendingInterrupts[5] = {0,0,0,0,0};
+ virtual void liveness(bool inWfi){
+ uint32_t pendingInterrupt = getPendingInterrupt();
+ pendingInterrupts[pendingInterruptsPtr++] = getPendingInterrupt();
+ if(pendingInterruptsPtr >= 5) pendingInterruptsPtr = 0;
+ if(pendingInterrupt) livenessInterrupt++; else livenessInterrupt = 0;
+ if(!inWfi) livenessStep++; else livenessStep = 0;
+
+ if(livenessStep > 10000){
+ cout << "Liveness step failure" << endl;
+ fail();
+ }
+
+ if(livenessInterrupt > 1000){
+ cout << "Liveness interrupt failure" << endl;
+ fail();
+ }
+ }
+
+
+ uint32_t getPendingInterrupt(){
+ uint32_t mEnabled = status.mie && privilege == 3 || privilege < 3;
+ uint32_t sEnabled = status.sie && privilege == 1 || privilege < 1;
+
+ uint32_t masked = getIp().raw & ~mideleg & -mEnabled & ie.raw;
+ if (masked == 0)
+ masked = getIp().raw & mideleg & -sEnabled & ie.raw & 0x333;
+
+ if (masked) {
+ if (masked & MIP_MEIP)
+ masked &= MIP_MEIP;
+ else if (masked & MIP_MSIP)
+ masked &= MIP_MSIP;
+ else if (masked & MIP_MTIP)
+ masked &= MIP_MTIP;
+ else if (masked & MIP_SEIP)
+ masked &= MIP_SEIP;
+ else if (masked & MIP_SSIP)
+ masked &= MIP_SSIP;
+ else if (masked & MIP_STIP)
+ masked &= MIP_STIP;
+ else
+ fail();
+ }
+
+ return masked;
+ }
+
+
+ bool isPcAligned(uint32_t pc){
+#ifdef COMPRESSED
+ return (pc & 1) == 0;
+#else
+ return (pc & 3) == 0;
+#endif
+ }
+
+
+
+ virtual void step() {
+ stepCounter++;
+ livenessStep = 0;
+
+ while(fpuCompletionTockens != 0 && !fpuCompletion.empty()){
+ FpuCompletion completion = fpuCompletion.front(); fpuCompletion.pop();
+ fcsr.flags |= completion.flags;
+ fpuCompletionTockens -= 1;
+ }
+
+
+ #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)
+ #define iSign() iBitsSigned(31, 1)
+ #define i32_rs1 regs[(i >> 15) & 0x1F]
+ #define i32_rs2 regs[(i >> 20) & 0x1F]
+ #define i32_i_imm (int32_t(i) >> 20)
+ #define i32_s_imm (iBits(7, 5) + (iBitsSigned(25, 7) << 5))
+ #define i32_shamt ((i >> 20) & 0x1F)
+ #define i32_sb_imm ((iBits(8, 4) << 1) + (iBits(25,6) << 5) + (iBits(7,1) << 11) + (iSign() << 12))
+ #define i32_csr iBits(20, 12)
+ #define i32_func3 iBits(12, 3)
+ #define i32_func7 iBits(25, 7)
+ #define i16_addi4spn_imm ((iBits(6, 1) << 2) + (iBits(5, 1) << 3) + (iBits(11, 2) << 4) + (iBits(7, 4) << 6))
+ #define i16_lw_imm ((iBits(6, 1) << 2) + (iBits(10, 3) << 3) + (iBits(5, 1) << 6))
+ #define i16_addr2 (iBits(2,3) + 8)
+ #define i16_addr1 (iBits(7,3) + 8)
+ #define i16_rf1 regs[i16_addr1]
+ #define i16_rf2 regs[i16_addr2]
+ #define rf_sp regs[2]
+ #define i16_imm (iBits(2, 5) + (iBitsSigned(12, 1) << 5))
+ #define i16_j_imm ((iBits(3, 3) << 1) + (iBits(11, 1) << 4) + (iBits(2, 1) << 5) + (iBits(7, 1) << 6) + (iBits(6, 1) << 7) + (iBits(9, 2) << 8) + (iBits(8, 1) << 10) + (iBitsSigned(12, 1) << 11))
+ #define i16_addi16sp_imm ((iBits(6, 1) << 4) + (iBits(2, 1) << 5) + (iBits(5, 1) << 6) + (iBits(3, 2) << 7) + (iBitsSigned(12, 1) << 9))
+ #define i16_zimm (iBits(2, 5))
+ #define i16_b_imm ((iBits(3, 2) << 1) + (iBits(10, 2) << 3) + (iBits(2, 1) << 5) + (iBits(5, 2) << 6) + (iBitsSigned(12, 1) << 8))
+ #define i16_lwsp_imm ((iBits(4, 3) << 2) + (iBits(12, 1) << 5) + (iBits(2, 2) << 6))
+ #define i16_swsp_imm ((iBits(9, 4) << 2) + (iBits(7, 2) << 6))
+ uint32_t i;
+ uint32_t u32Buf;
+ uint32_t pAddr;
+ if (pc & 2) {
+ if(v2p(pc - 2, &pAddr, EXECUTE)){ trap(0, 12, pc - 2); return; }
+ if(iRead(pAddr, &i)){
+ trap(0, 1, 0);
+ return;
+ }
+ i >>= 16;
+ if ((i & 3) == 3) {
+ uint32_t u32Buf;
+ if(v2p(pc + 2, &pAddr, EXECUTE)){ trap(0, 12, pc + 2); return; }
+ if(iRead(pAddr, &u32Buf)){
+ trap(0, 1, 0);
+ return;
+ }
+ i |= u32Buf << 16;
+ }
+ } else {
+ if(v2p(pc, &pAddr, EXECUTE)){ trap(0, 12, pc); return; }
+ if(iRead(pAddr, &i)){
+ trap(0, 1, 0);
+ return;
+ }
+ }
+ lastInstruction = i;
+ currentInstruction = i;
+ if ((i & 0x3) == 0x3) {
+ //32 bit
+ switch (i & 0x7F) {
+ #ifdef RVF
+ case 0x43:// RVFD
+ case 0x47:
+ case 0x4B:
+ case 0x4F:
+ case 0x53: {
+ u32 format = iBits(25,2);
+ u32 opcode = iBits(27,5);
+ bool withCommit = fpuCommitLut[opcode];
+ bool withRsp = fpuRspLut[opcode];
+ bool withRs1 = fpuRs1Lut[opcode];
+ if((i & 0x7F) != 0x53) { // FMADD
+ withCommit = true;
+ withRsp = false;
+ }
+ #ifdef RVD
+ if(format > 1) ilegalInstruction();
+ #else
+ if(format > 0) ilegalInstruction();
+ #endif
+
+ if(withCommit){
+ FpuCommit commit = fpuCommit.front(); fpuCommit.pop();
+ fpuCompletionTockens += 1;
+// cout << "withRs1 " << withRs1 << " " << opcode << endl;
+ if(withRs1 && memcmp(&i32_rs1, &commit.value, 4)){
+ cout << "FPU commit missmatch DUT=" << hex << commit.value << " REF=" << i32_rs1 << dec << endl;
+ fail();
+ return;
+ }
+ }
+ if(withRsp){
+ auto rsp = fpuRsp.front(); fpuRsp.pop();
+ fcsr.flags |= rsp.flags;
+ rfWrite(rd32, (u32)rsp.value);
+ }
+ status.fs = 3;
+ pcWrite(pc + 4);
+ } break;
+ case 0x07: { //Fpu load
+ uint32_t size = 1 << ((i >> 12) & 0x3);
+ if(size < 4) ilegalInstruction();
+ #ifdef RVD
+ if(size > 8) ilegalInstruction();
+ #else
+ if(format > 4) ilegalInstruction();
+ #endif
+ auto commit = fpuCommit.front(); fpuCommit.pop();
+ fpuCompletionTockens += 1;
+
+
+ uint64_t data = 0;
+ uint32_t address = i32_rs1 + i32_i_imm;
+ if(address & (size-1)){
+ trap(0, 4, address);
+ } else {
+ if(v2p(address, &pAddr, READ)){ trap(0, 13, address); return; }
+ if(dRead(pAddr, size, (uint8_t*)&data)){
+ trap(0, 5, address);
+ } else {
+ if(memcmp(&data, &commit.value, size)){
+ cout << "FPU load missmatch DUT=" << hex << commit.value << " REF=" << data << dec << endl;
+ fail();
+ } else {
+ status.fs = 3;
+ pcWrite(pc + 4);
+ }
+ }
+ }
+ } break;
+ case 0x27: { //Fpu store
+ uint32_t size = 1 << ((i >> 12) & 0x3);
+ if(size < 4) ilegalInstruction();
+ #ifdef RVD
+ if(size > 8) ilegalInstruction();
+ #else
+ if(format > 4) ilegalInstruction();
+ #endif
+
+ auto rsp = fpuRsp.front(); fpuRsp.pop();
+ fcsr.flags |= rsp.flags;
+ uint32_t address = i32_rs1 + i32_s_imm;
+ if(address & (size-1)){
+ trap(0, 6, address);
+ } else {
+ if(v2p(address, &pAddr, WRITE)){ trap(0, 15, address); return; }
+ dWrite(pAddr, size, (uint8_t*) &rsp.value);
+ status.fs = 3;
+ pcWrite(pc + 4);
+ lrscReserved = false;
+ }
+ } break;
+ #endif
+ 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:{
+ uint32_t target = (i32_rs1 + i32_i_imm) & ~1;
+ if(isPcAligned(target)) 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;
+ case 0x1:if (i32_rs1 != i32_rs2)pcWrite(pc + i32_sb_imm);else pcWrite(pc + 4);break;
+ case 0x4:if (i32_rs1 < i32_rs2)pcWrite(pc + i32_sb_imm); else pcWrite(pc + 4);break;
+ case 0x5:if (i32_rs1 >= i32_rs2)pcWrite(pc + i32_sb_imm);else pcWrite(pc + 4);break;
+ case 0x6:if (uint32_t(i32_rs1) < uint32_t(i32_rs2)) pcWrite(pc + i32_sb_imm); else pcWrite(pc + 4);break;
+ case 0x7:if (uint32_t(i32_rs1) >= uint32_t(i32_rs2))pcWrite(pc + i32_sb_imm); else pcWrite(pc + 4);break;
+ }
+ break;
+ case 0x03:{ //LOADS
+ uint32_t data;
+ uint32_t address = i32_rs1 + i32_i_imm;
+ uint32_t size = 1 << ((i >> 12) & 0x3);
+ if(address & (size-1)){
+ trap(0, 4, address);
+ } else {
+ if(v2p(address, &pAddr, READ)){ trap(0, 13, address); return; }
+ if(dRead(pAddr, size, (uint8_t*)&data)){
+ trap(0, 5, address);
+ } else {
+ switch ((i >> 12) & 0x7) {
+ case 0x0:rfWrite(rd32, int8_t(data));pcWrite(pc + 4);break;
+ case 0x1:rfWrite(rd32, int16_t(data));pcWrite(pc + 4);break;
+ case 0x2:rfWrite(rd32, int32_t(data));pcWrite(pc + 4);break;
+ case 0x4:rfWrite(rd32, uint8_t(data));pcWrite(pc + 4);break;
+ case 0x5:rfWrite(rd32, uint16_t(data));pcWrite(pc + 4);break;
+ }
+ }
+ }
+ }break;
+ case 0x23: { //STORE
+ uint32_t address = i32_rs1 + i32_s_imm;
+ uint32_t size = 1 << ((i >> 12) & 0x3);
+ if(address & (size-1)){
+ trap(0, 6, address);
+ } else {
+ if(v2p(address, &pAddr, WRITE)){ trap(0, 15, address); return; }
+ dWrite(pAddr, size, (uint8_t*)&i32_rs2);
+ pcWrite(pc + 4);
+ lrscReserved = false;
+ }
+ }break;
+ case 0x13: //ALUi
+ switch ((i >> 12) & 0x7) {
+ case 0x0:rfWrite(rd32, i32_rs1 + i32_i_imm);pcWrite(pc + 4);break;
+ case 0x1:
+ switch ((i >> 25) & 0x7F) {
+ case 0x00:rfWrite(rd32, i32_rs1 << i32_shamt);pcWrite(pc + 4);break;
+ }
+ break;
+ case 0x2:rfWrite(rd32, i32_rs1 < i32_i_imm);pcWrite(pc + 4);break;
+ case 0x3:rfWrite(rd32, uint32_t(i32_rs1) < uint32_t(i32_i_imm));pcWrite(pc + 4);break;
+ case 0x4:rfWrite(rd32, i32_rs1 ^ i32_i_imm);pcWrite(pc + 4);break;
+ case 0x5:
+ switch ((i >> 25) & 0x7F) {
+ case 0x00:rfWrite(rd32, uint32_t(i32_rs1) >> i32_shamt);pcWrite(pc + 4);break;
+ case 0x20:rfWrite(rd32, i32_rs1 >> i32_shamt);pcWrite(pc + 4);break;
+ }
+ break;
+ case 0x6:rfWrite(rd32, i32_rs1 | i32_i_imm);pcWrite(pc + 4);break;
+ case 0x7: rfWrite(rd32, i32_rs1 & i32_i_imm);pcWrite(pc + 4);break;
+ }
+ break;
+ case 0x33: //ALU
+ if (((i >> 25) & 0x7F) == 0x01) {
+ switch ((i >> 12) & 0x7) {
+ case 0x0:rfWrite(rd32, int32_t(i32_rs1) * int32_t(i32_rs2));pcWrite(pc + 4);break;
+ case 0x1:rfWrite(rd32,(int64_t(i32_rs1) * int64_t(i32_rs2)) >> 32);pcWrite(pc + 4);break;
+ case 0x2:rfWrite(rd32,(int64_t(i32_rs1) * uint64_t(uint32_t(i32_rs2)))>> 32);pcWrite(pc + 4);break;
+ case 0x3:rfWrite(rd32,(uint64_t(uint32_t(i32_rs1)) * uint64_t(uint32_t(i32_rs2))) >> 32);pcWrite(pc + 4);break;
+ case 0x4:rfWrite(rd32,i32_rs2 == 0 ? -1 : int64_t(i32_rs1) / int64_t(i32_rs2));pcWrite(pc + 4);break;
+ case 0x5:rfWrite(rd32,i32_rs2 == 0 ? -1 : uint32_t(i32_rs1) / uint32_t(i32_rs2));pcWrite(pc + 4);break;
+ case 0x6:rfWrite(rd32,i32_rs2 == 0 ? i32_rs1 : int64_t(i32_rs1)% int64_t(i32_rs2));pcWrite(pc + 4);break;
+ case 0x7:rfWrite(rd32,i32_rs2 == 0 ? i32_rs1 : uint32_t(i32_rs1) % uint32_t(i32_rs2));pcWrite(pc + 4);break;
+ }
+ } else {
+ switch ((i >> 12) & 0x7) {
+ case 0x0:
+ switch ((i >> 25) & 0x7F) {
+ case 0x00:rfWrite(rd32, i32_rs1 + i32_rs2);pcWrite(pc + 4);break;
+ case 0x20:rfWrite(rd32, i32_rs1 - i32_rs2);pcWrite(pc + 4);break;
+ }
+ break;
+ case 0x1:rfWrite(rd32, i32_rs1 << (i32_rs2 & 0x1F));pcWrite(pc + 4);break;
+ case 0x2:rfWrite(rd32, i32_rs1 < i32_rs2);pcWrite(pc + 4);break;
+ case 0x3:rfWrite(rd32, uint32_t(i32_rs1) < uint32_t(i32_rs2));pcWrite(pc + 4);break;
+ case 0x4:rfWrite(rd32, i32_rs1 ^ i32_rs2);pcWrite(pc + 4);break;
+ case 0x5:
+ switch ((i >> 25) & 0x7F) {
+ case 0x00:rfWrite(rd32, uint32_t(i32_rs1) >> (i32_rs2 & 0x1F));pcWrite(pc + 4);break;
+ case 0x20:rfWrite(rd32, i32_rs1 >> (i32_rs2 & 0x1F));pcWrite(pc + 4);break;
+ }
+ break;
+ case 0x6:rfWrite(rd32, i32_rs1 | i32_rs2);pcWrite(pc + 4);break;
+ case 0x7:rfWrite(rd32, i32_rs1 & i32_rs2); pcWrite(pc + 4);break;
+ }
+ }
+ break;
+ case 0x73:{
+ if(i32_func3 == 0){
+ switch(i){
+ case 0x30200073:{ //MRET
+ if(privilege < 3){ ilegalInstruction(); return;}
+ privilege = status.mpp;
+ status.mie = status.mpie;
+ status.mpie = 1;
+ status.mpp = 0;
+ pcWrite(mepc);
+ }break;
+ case 0x10200073:{ //SRET
+ if(privilege < 1){ ilegalInstruction(); return;}
+ privilege = status.spp;
+ status.sie = status.spie;
+ status.spie = 1;
+ status.spp = 0;
+ pcWrite(sepc);
+ }break;
+ case 0x00000073:{ //ECALL
+ trap(0, 8+privilege, 0x00000073); //To follow the VexRiscv area saving implementation
+ }break;
+ case 0x10500073:{ //WFI
+ pcWrite(pc + 4);
+ }break;
+ default:
+ if((i & 0xFE007FFF) == 0x12000073){ //SFENCE.VMA
+ pcWrite(pc + 4);
+ }else {
+ ilegalInstruction();
+ }
+ break;
+ }
+ } else {
+ //CSR
+ uint32_t input = (i & 0x4000) ? ((i >> 15) & 0x1F) : i32_rs1;
+ uint32_t clear, set;
+ bool write;
+ switch ((i >> 12) & 0x3) {
+ case 1: clear = ~0; set = input; write = true; break;
+ case 2: clear = 0; set = input; write = ((i >> 15) & 0x1F) != 0; break;
+ case 3: clear = input; set = 0; write = ((i >> 15) & 0x1F) != 0; break;
+ }
+ uint32_t csrAddress = i32_csr;
+ uint32_t old;
+ if(csrRead(i32_csr, &old)) { ilegalInstruction();return; }
+ if(write) if(csrWrite(i32_csr, (csrReadToWriteOverride(i32_csr, old) & ~clear) | set)) { ilegalInstruction();return; }
+ rfWrite(rd32, old);
+ pcWrite(pc + 4);
+ }
+ break;
+ }
+ case 0x2F: // Atomic stuff
+ switch(i32_func3){
+ case 0x2:
+ switch(iBits(27,5)){
+ case 0x2:{ //LR
+ uint32_t data;
+ uint32_t address = i32_rs1;
+ if(address & 3){
+ trap(0, 4, address);
+ } else {
+ if(v2p(address, &pAddr, READ)){ trap(0, 13, address); return; }
+ if(dRead(pAddr, 4, (uint8_t*)&data)){
+ trap(0, 5, address);
+ } else {
+ lrscReserved = true;
+ lrscReservedAddress = pAddr;
+ rfWrite(rd32, data);
+ pcWrite(pc + 4);
+ }
+ }
+ } break;
+ case 0x3:{ //SC
+ uint32_t address = i32_rs1;
+ if(address & 3){
+ trap(0, 6, address);
+ } else {
+ if(v2p(address, &pAddr, WRITE)){ trap(0, 15, address); return; }
+ #ifdef DBUS_EXCLUSIVE
+ bool hit = lrscReserved && lrscReservedAddress == pAddr;
+ #else
+ bool hit = lrscReserved;
+ #endif
+ if(hit){
+ dWrite(pAddr, 4, (uint8_t*)&i32_rs2);
+ }
+ lrscReserved = false;
+ rfWrite(rd32, !hit);
+ pcWrite(pc + 4);
+ }
+ } break;
+ default: {
+ #ifndef AMO
+ ilegalInstruction();
+ #else
+ uint32_t sel = (i >> 27) & 0x1F;
+ uint32_t addr = i32_rs1;
+ int32_t src = i32_rs2;
+ int32_t readValue;
+
+ lrscReserved = false;
+
+
+ uint32_t pAddr;
+ if(v2p(addr, &pAddr, READ_WRITE)){ trap(0, 15, addr); return; }
+ if(dRead(pAddr, 4, (uint8_t*)&readValue)){
+ trap(0, 15, addr); return;
+ return;
+ }
+ int writeValue;
+ switch(sel){
+ case 0x0: writeValue = src + readValue; break;
+ case 0x1: writeValue = src; break;
+ case 0x4: writeValue = src ^ readValue; break;
+ case 0xC: writeValue = src & readValue; break;
+ case 0x8: writeValue = src | readValue; break;
+ case 0x10: writeValue = min(src, readValue); break;
+ case 0x14: writeValue = max(src, readValue); break;
+ case 0x18: writeValue = min((unsigned int)src, (unsigned int)readValue); break;
+ case 0x1C: writeValue = max((unsigned int)src, (unsigned int)readValue); break;
+ default: ilegalInstruction(); return; break;
+ }
+ dWrite(pAddr, 4, (uint8_t*)&writeValue);
+ rfWrite(rd32, readValue);
+ pcWrite(pc + 4);
+ #endif
+ } break;
+ }
+ break;
+ default: ilegalInstruction(); break;
+ }
+ break;
+ case 0x0f:
+ if(i == 0x100F || (i & 0xF00FFFFF) == 0x000F){ // FENCE FENCE.I
+ pcWrite(pc + 4);
+ } else{
+ ilegalInstruction();
+ }
+ break;
+ default: ilegalInstruction(); break;
+ }
+ } else {
+ #ifndef COMPRESSED
+ cout << "ERROR : RiscvGolden got a RVC instruction while the CPU isn't RVC ready" << endl;
+ ilegalInstruction(); return;
+ #endif
+ switch((iBits(0, 2) << 3) + iBits(13, 3)){
+ case 0: rfWrite(i16_addr2, rf_sp + i16_addi4spn_imm); pcWrite(pc + 2); break;
+ case 2: {
+ uint32_t data;
+ uint32_t address = i16_rf1 + i16_lw_imm;
+ if(address & 0x3){
+ trap(0, 4, address);
+ } else {
+ if(v2p(address, &pAddr, READ)){ trap(0, 13, address); return; }
+ if(dRead(pAddr, 4, (uint8_t*)&data)) {
+ trap(0, 5, address);
+ } else {
+ rfWrite(i16_addr2, data); pcWrite(pc + 2);
+ }
+ }
+ } break;
+ case 6: {
+ uint32_t address = i16_rf1 + i16_lw_imm;
+ if(address & 0x3){
+ trap(0, 6, address);
+ } else {
+ if(v2p(address, &pAddr, WRITE)){ trap(0, 15, address); return; }
+ dWrite(pAddr, 4, (uint8_t*)&i16_rf2);
+ pcWrite(pc + 2);
+ lrscReserved = false;
+ }
+ }break;
+ case 8: rfWrite(rd32, regs[rd32] + i16_imm); pcWrite(pc + 2); break;
+ case 9: rfWrite(1, pc + 2);pcWrite(pc + i16_j_imm); break;
+ case 10: rfWrite(rd32, i16_imm);pcWrite(pc + 2); break;
+ case 11:
+ if(rd32 == 2) { rfWrite(2, rf_sp + i16_addi16sp_imm);pcWrite(pc + 2); }
+ else { rfWrite(rd32, i16_imm << 12);pcWrite(pc + 2); } break;
+ case 12:
+ switch(iBits(10,2)){
+ case 0: rfWrite(i16_addr1, uint32_t(i16_rf1) >> i16_zimm); pcWrite(pc + 2);break;
+ case 1: rfWrite(i16_addr1, i16_rf1 >> i16_zimm); pcWrite(pc + 2);break;
+ case 2: rfWrite(i16_addr1, i16_rf1 & i16_imm); pcWrite(pc + 2);break;
+ case 3:
+ switch(iBits(5,2)){
+ case 0: rfWrite(i16_addr1, i16_rf1 - i16_rf2); pcWrite(pc + 2);break;
+ case 1: rfWrite(i16_addr1, i16_rf1 ^ i16_rf2); pcWrite(pc + 2);break;
+ case 2: rfWrite(i16_addr1, i16_rf1 | i16_rf2); pcWrite(pc + 2);break;
+ case 3: rfWrite(i16_addr1, i16_rf1 & i16_rf2); pcWrite(pc + 2);break;
+ }
+ break;
+ }
+ break;
+ case 13: pcWrite(pc + i16_j_imm); break;
+ case 14: pcWrite(i16_rf1 == 0 ? pc + i16_b_imm : pc + 2); break;
+ case 15: pcWrite(i16_rf1 != 0 ? pc + i16_b_imm : pc + 2); break;
+ case 16: rfWrite(rd32, regs[rd32] << i16_zimm); pcWrite(pc + 2); break;
+ case 18:{
+ uint32_t data;
+ uint32_t address = rf_sp + i16_lwsp_imm;
+ if(address & 0x3){
+ trap(0, 4, address);
+ } else {
+ if(v2p(address, &pAddr, READ)){ trap(0, 13, address); return; }
+ if(dRead(pAddr, 4,(uint8_t*) &data)){
+ trap(0, 5, address);
+ } else {
+ rfWrite(rd32, data); pcWrite(pc + 2);
+ }
+ }
+ }break;
+ case 20:
+ if(i & 0x1000){
+ if(iBits(2,10) == 0){
+
+ } else if(iBits(2,5) == 0){
+ rfWrite(1, pc + 2); pcWrite(regs[rd32] & ~1);
+ } else {
+ rfWrite(rd32, regs[rd32] + regs[iBits(2,5)]); pcWrite(pc + 2);
+ }
+ } else {
+ if(iBits(2,5) == 0){
+ pcWrite(regs[rd32] & ~1);
+ } else {
+ rfWrite(rd32, regs[iBits(2,5)]); pcWrite(pc + 2);
+ }
+ }
+ break;
+ case 22: {
+ uint32_t address = rf_sp + i16_swsp_imm;
+ if(address & 3){
+ trap(0,6, address);
+ } else {
+ if(v2p(address, &pAddr, WRITE)){ trap(0, 15, address); return; }
+ dWrite(pAddr, 4, (uint8_t*)&regs[iBits(2,5)]); pcWrite(pc + 2);
+ lrscReserved = false;
+ }
+ }break;
+ }
+ }
+ }
+};
+
+
+class SimElement{
+public:
+ virtual ~SimElement(){}
+ virtual void onReset(){}
+ virtual void postReset(){}
+ virtual void preCycle(){}
+ virtual void postCycle(){}
+};
+
+
+
+class Workspace;
+
+class Workspace{
+public:
+ static mutex staticMutex;
+ static uint32_t testsCounter, successCounter;
+ static uint64_t cycles;
+ uint64_t instanceCycles = 0;
+ vector<SimElement*> simElements;
+ Memory mem;
+ string name;
+ uint64_t currentTime = 22;
+ uint64_t mTimeCmp = 0;
+ uint64_t mTime = 0;
+ VVexRiscv* top;
+ bool resetDone = false;
+ bool riscvRefEnable = false;
+ uint64_t i;
+ double cyclesPerSecond = 10e6;
+ double allowedCycles = 0.0;
+ uint32_t bootPc = -1;
+ uint32_t iStall = STALL,dStall = STALL;
+ #ifdef TRACE
+ VerilatedFstC* tfp;
+ #endif
+ bool allowInvalidate = true;
+
+ uint32_t seed;
+
+ Workspace* setIStall(bool enable) { iStall = enable; return this; }
+ Workspace* setDStall(bool enable) { dStall = enable; return this; }
+
+ ofstream regTraces;
+ ofstream memTraces;
+ ofstream logTraces;
+ ofstream debugLog;
+
+ struct timespec start_time;
+
+ class CpuRef : public RiscvGolden{
+ public:
+ Memory mem;
+
+ class MemWrite {
+ public:
+ int32_t address, size;
+ uint8_t data42[64];
+ };
+
+ class MemRead {
+ public:
+ int32_t address, size;
+ uint8_t data42[64];
+ bool error;
+ };
+
+ uint32_t periphWriteTimer = 0;
+ queue<MemWrite> periphWritesGolden;
+ queue<MemWrite> periphWrites;
+ queue<MemRead> periphRead;
+ Workspace *ws;
+ CpuRef(Workspace *ws){
+ this->ws = ws;
+ }
+
+ virtual void fail() { ws->fail(); }
+
+
+ virtual bool isMmuRegion(uint32_t v) {return ws->isMmuRegion(v);}
+
+ bool rfWriteValid;
+ int32_t rfWriteAddress;
+ int32_t rfWriteData;
+ virtual void rfWrite(int32_t address, int32_t data){
+ rfWriteValid = address != 0;
+ rfWriteAddress = address;
+ rfWriteData = data;
+ RiscvGolden::rfWrite(address,data);
+ }
+
+
+ virtual bool iRead(int32_t address, uint32_t *data){
+ bool error;
+ ws->iBusAccess(address, data, &error);
+// ws->iBusAccessPatch(address,data,&error);
+ return error;
+ }
+
+ virtual bool dRead(int32_t address, int32_t size, uint8_t *data){
+ if(size < 1 || size > 8){
+ cout << "dRead size=" << size << endl;
+ fail();
+ }
+ if((address & (size-1)) != 0)
+ cout << "Ref did a unaligned read" << endl;
+ if(ws->isPerifRegion(address)){
+ MemRead t = periphRead.front();
+ if(t.address != address || t.size != size){
+ cout << "DRead missmatch" << hex << endl;
+ cout << " REF : address=" << address << " size=" << size << endl;
+ cout << " DUT : address=" << t.address << " size=" << t.size << endl;
+ fail();
+ }
+
+ for(int i = 0; i < size; i++){
+ data[i] = t.data42[i];
+ }
+ periphRead.pop();
+ return t.error;
+ }else {
+ mem.read(address, size, data);
+ }
+ return false;
+ }
+ virtual void dWrite(int32_t address, int32_t size, uint8_t *data){
+ if(address & (size-1) != 0)
+ cout << "Ref did a unaligned write" << endl;
+
+ if(!ws->isPerifRegion(address)){
+ mem.write(address, size, data);
+ }
+ if(ws->isDBusCheckedRegion(address)){
+ MemWrite w;
+ w.address = address;
+ w.size = size;
+ for(int i = 0; i < size; i++){
+ w.data42[i] = data[i];
+ }
+ periphWritesGolden.push(w);
+ if(periphWritesGolden.size() > 10){
+ cout << "??? periphWritesGolden" << endl;
+ fail();
+ }
+ }
+ }
+
+
+ void step() {
+ rfWriteValid = false;
+ RiscvGolden::step();
+
+ 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 0:
+ MemWrite t = periphWrites.front();
+ MemWrite t2 = periphWritesGolden.front();
+ bool dataMatch = true;
+ for(int i = 0;i < min(t.size, t2.size);i++) dataMatch &= t.data42[i] == t2.data42[i];
+ if(t.address != t2.address || t.size != t2.size || !dataMatch){
+ cout << hex << "periphWrite missmatch" << endl;
+ cout << " DUT address=" << t.address << " size=" << t.size << " data=" << *((uint32_t*)t.data42) << endl;
+ cout << " REF address=" << t2.address << " size=" << t2.size << " data=" << *((uint32_t*)t2.data42) << endl;
+ fail();
+ }
+ periphWrites.pop();
+ periphWritesGolden.pop();
+ periphWriteTimer = 0;
+ break;
+ }
+
+
+ }
+ };
+
+ CpuRef riscvRef = CpuRef(this);
+ string vcdName;
+ Workspace* setVcdName(string name){
+ vcdName = name;
+ return this;
+ }
+ Workspace(string name){
+ vcdName = name;
+ //seed = VL_RANDOM_I_WIDTH(32)^VL_RANDOM_I_WIDTH(32)^0x1093472;
+ //srand48(seed);
+ // setIStall(false);
+ // setDStall(false);
+ staticMutex.lock();
+ testsCounter++;
+ staticMutex.unlock();
+ this->name = name;
+ top = new VVexRiscv;
+ #ifdef TRACE_ACCESS
+ regTraces.open (name + ".regTrace");
+ memTraces.open (name + ".memTrace");
+ #endif
+ logTraces.open (name + ".logTrace");
+ debugLog.open (name + ".debugTrace");
+ fillSimELements();
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
+ }
+
+ virtual ~Workspace(){
+ delete top;
+ #ifdef TRACE
+ delete tfp;
+ #endif
+
+ for(SimElement* simElement : simElements) {
+ delete simElement;
+ }
+ }
+
+ Workspace* loadHex(string path){
+ loadHexImpl(path,&mem);
+ loadHexImpl(path,&riscvRef.mem);
+ return this;
+ }
+
+ Workspace* loadBin(string path, uint32_t offset){
+ loadBinImpl(path,&mem, offset);
+ loadBinImpl(path,&riscvRef.mem, offset);
+ return this;
+ }
+
+ Workspace* setCyclesPerSecond(double value){
+ cyclesPerSecond = value;
+ return this;
+ }
+
+ Workspace* bootAt(uint32_t pc) {
+ bootPc = pc;
+ riscvRef.pc = pc;
+ return this;
+ }
+
+ Workspace* withRiscvRef(){
+ #ifdef WITH_RISCV_REF
+ riscvRefEnable = true;
+ #endif
+ return this;
+ }
+
+ Workspace* withInvalidation(){
+ allowInvalidate = true;
+ return this;
+ }
+ Workspace* withoutInvalidation(){
+ allowInvalidate = false;
+ return this;
+ }
+ Workspace* writeWord(uint32_t address, uint32_t data){
+ mem.write(address, 4, (uint8_t*)&data);
+ riscvRef.mem.write(address, 4, (uint8_t*)&data);
+ return this;
+ }
+
+ virtual bool isPerifRegion(uint32_t addr) { return false; }
+ virtual bool isMmuRegion(uint32_t addr) { return true;}
+ virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error) {
+ if(addr % 4 != 0) {
+ cout << "Warning, unaligned IBusAccess : " << addr << endl;
+ fail();
+ }
+ *data = ( (mem[addr + 0] << 0)
+ | (mem[addr + 1] << 8)
+ | (mem[addr + 2] << 16)
+ | (mem[addr + 3] << 24));
+ *error = false;
+ }
+
+
+ virtual bool isDBusCheckedRegion(uint32_t address){ return isPerifRegion(address);}
+ virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size, uint8_t *data, bool *error) {
+ assertEq(addr % size, 0);
+ if(!isPerifRegion(addr)) {
+ if(wr){
+ for(uint32_t b = 0;b < size;b++){
+ *mem.get(addr + b) = ((uint8_t*)data)[b];
+ }
+
+ }else{
+ uint32_t innerOffset = addr & (DBUS_LOAD_DATA_WIDTH/8-1);
+ for(uint32_t b = 0;b < size;b++){
+ ((uint8_t*)data)[b] = mem[addr + b];
+ }
+ }
+ }
+
+
+ if(wr){
+ if(isDBusCheckedRegion(addr)){
+ CpuRef::MemWrite w;
+ w.address = addr;
+ w.size = size;
+ for(uint32_t b = 0;b < size;b++){
+ w.data42[b] = data[b];
+ }
+ riscvRef.periphWrites.push(w);
+ }
+ } else {
+ if(isPerifRegion(addr)){
+ CpuRef::MemRead r;
+ r.address = addr;
+ r.size = size;
+ for(uint32_t b = 0;b < size;b++){
+ r.data42[b] = data[b];
+ }
+ r.error = *error;
+ riscvRef.periphRead.push(r);
+ }
+ }
+ }
+
+// void periphAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error){
+// if(wr){
+// CpuRef::MemWrite w;
+// w.address = addr;
+// w.size = 1 << size;
+// w.data = *data;
+// riscvRef.periphWrites.push(w);
+// } else {
+// CpuRef::MemRead r;
+// r.address = addr;
+// r.size = 1 << size;
+// r.data = *data;
+// r.error = *error;
+// riscvRef.periphRead.push(r);
+// }
+// }
+
+ virtual void postReset() {}
+ virtual void checks(){}
+ virtual void pass(){ throw success();}
+ virtual void fail(){ throw std::exception();}
+ virtual void fillSimELements();
+ void dump(uint64_t i){
+ #ifdef TRACE
+ if(i == TRACE_START && i != 0) cout << "**" << endl << "**" << endl << "**" << endl << "**" << endl << "**" << endl << "START TRACE" << endl;
+ if(i >= TRACE_START) tfp->dump(i);
+ #ifdef TRACE_SPORADIC
+ else if(i % 1000000 < 100) tfp->dump(i);
+ #endif
+ #endif
+ }
+
+ uint64_t privilegeCounters[4] = {0,0,0,0};
+ Workspace* run(uint64_t timeout = 5000){
+// cout << "Start " << name << endl;
+ if(timeout == 0) timeout = 0x7FFFFFFFFFFFFFFF;
+
+ currentTime = 4;
+ // init trace dump
+ #ifdef TRACE
+ Verilated::traceEverOn(true);
+ tfp = new VerilatedFstC;
+ top->trace(tfp, 99);
+ tfp->open((vcdName + ".fst").c_str());
+ #endif
+
+ // Reset
+ top->clk = 0;
+ top->reset = 0;
+
+
+ top->eval(); currentTime = 3;
+ for(SimElement* simElement : simElements) simElement->onReset();
+
+ top->reset = 1;
+ top->eval();
+ top->clk = 1;
+ top->eval();
+ top->clk = 0;
+ top->eval();
+ #ifdef CSR
+ top->timerInterrupt = 0;
+ top->externalInterrupt = 1;
+ top->softwareInterrupt = 0;
+ #endif
+ #ifdef SUPERVISOR
+ top->externalInterruptS = 0;
+ #endif
+ #ifdef DEBUG_PLUGIN_EXTERNAL
+ top->timerInterrupt = 0;
+ top->externalInterrupt = 0;
+ #endif
+ dump(0);
+ top->reset = 0;
+ for(SimElement* simElement : simElements) simElement->postReset();
+
+ top->eval(); currentTime = 2;
+
+
+ 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
+ if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc;
+ #else
+ if(bootPc != -1) {
+ #if defined(IBUS_SIMPLE) || defined(IBUS_SIMPLE_WISHBONE) || defined(IBUS_SIMPLE_AHBLITE3)
+ top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc;
+ #ifdef COMPRESSED
+ top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc;
+ #endif
+ #else
+ top->VexRiscv->IBusCachedPlugin_fetchPc_pcReg = bootPc;
+ #ifdef COMPRESSED
+ top->VexRiscv->IBusCachedPlugin_decodePc_pcReg = bootPc;
+ #endif
+ #endif
+ }
+ #endif
+
+
+ bool failed = false;
+ try {
+ // run simulation for 100 clock periods
+ for (i = 16; i < timeout*2; i+=2) {
+ /*while(allowedCycles <= 0.0){
+ struct timespec end_time;
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
+ uint64_t diffInNanos = end_time.tv_sec*1e9 + end_time.tv_nsec - start_time.tv_sec*1e9 - start_time.tv_nsec;
+ start_time = end_time;
+ double dt = diffInNanos*1e-9;
+ allowedCycles += dt*cyclesPerSecond;
+ if(allowedCycles > cyclesPerSecond/100) allowedCycles = cyclesPerSecond/100;
+ }
+ allowedCycles-=1.0;*/
+
+
+ #ifndef REF_TIME
+ #ifndef MTIME_INSTR_FACTOR
+ mTime = i/2;
+ #else
+ mTime += top->VexRiscv->lastStageIsFiring*MTIME_INSTR_FACTOR;
+ #endif
+ #endif
+ #ifdef TIMER_INTERRUPT
+ top->timerInterrupt = mTime >= mTimeCmp ? 1 : 0;
+ //if(mTime == mTimeCmp) printf("SIM timer tick\n");
+ #endif
+
+
+ #ifdef UTIME_INPUT
+ top->utime = mTime;
+ #endif
+
+ currentTime = i;
+
+ #ifdef FLOW_INFO
+ if(i % 5000000 == 0) cout << endl << "**" << endl << "**" << endl << "PROGRESS TRACE_START=" << i << endl;
+ #endif
+
+
+ // dump variables into VCD file and toggle clock
+
+ dump(i);
+ //top->eval();
+ top->clk = 0;
+ top->eval();
+
+ #ifdef CSR
+ if(riscvRefEnable) {
+ riscvRef.ipInput = 0;
+ #ifdef TIMER_INTERRUPT
+ riscvRef.ipInput |= top->timerInterrupt << 7;
+ #endif
+ #ifdef EXTERNAL_INTERRUPT
+ riscvRef.ipInput |= top->externalInterrupt << 11;
+ #endif
+ #ifdef CSR
+ riscvRef.ipInput |= top->softwareInterrupt << 3;
+ #endif
+ #ifdef SUPERVISOR
+ // riscvRef.ipInput |= top->timerInterruptS << 5;
+ riscvRef.ipInput |= top->externalInterruptS << 9;
+ #endif
+
+ riscvRef.liveness(top->VexRiscv->CsrPlugin_inWfi);
+ if(top->VexRiscv->CsrPlugin_interruptJump){
+ if(riscvRefEnable) riscvRef.trap(true, top->VexRiscv->CsrPlugin_interrupt_code);
+ }
+ }
+ #endif
+
+ #ifdef RVF
+ if(riscvRefEnable) {
+ if(top->VexRiscv->writeBack_FpuPlugin_commit_valid && top->VexRiscv->writeBack_FpuPlugin_commit_ready && top->VexRiscv->writeBack_FpuPlugin_commit_payload_write){
+ FpuCommit c;
+ c.value = top->VexRiscv->writeBack_FpuPlugin_commit_payload_value;
+ riscvRef.fpuCommit.push(c);
+ }
+
+ if(top->VexRiscv->FpuPlugin_port_rsp_valid && top->VexRiscv->FpuPlugin_port_rsp_ready && top->VexRiscv->lastStageIsFiring){
+ FpuRsp c;
+ c.value = top->VexRiscv->FpuPlugin_port_rsp_payload_value;
+ c.flags = (top->VexRiscv->FpuPlugin_port_rsp_payload_NX << 0) |
+ (top->VexRiscv->FpuPlugin_port_rsp_payload_NV << 4);
+ riscvRef.fpuRsp.push(c);
+ }
+
+ if(top->VexRiscv->FpuPlugin_port_completion_valid && top->VexRiscv->FpuPlugin_port_completion_payload_written){
+ FpuCompletion c;
+ c.flags = (top->VexRiscv->FpuPlugin_port_completion_payload_flags_NX << 0) |
+ (top->VexRiscv->FpuPlugin_port_completion_payload_flags_UF << 1) |
+ (top->VexRiscv->FpuPlugin_port_completion_payload_flags_OF << 2) |
+ (top->VexRiscv->FpuPlugin_port_completion_payload_flags_DZ << 3) |
+ (top->VexRiscv->FpuPlugin_port_completion_payload_flags_NV << 4);
+ riscvRef.fpuCompletion.push(c);
+ }
+ }
+ #endif
+
+
+
+ if(top->VexRiscv->lastStageIsFiring){
+ if(riscvRefEnable) {
+// privilegeCounters[riscvRef.privilege]++;
+// if((riscvRef.stepCounter & 0xFFFFF) == 0){
+// cout << "privilege report" << endl;
+// cout << "- U " << privilegeCounters[0] << endl;
+// cout << "- S " << privilegeCounters[1] << endl;
+// cout << "- M " << privilegeCounters[3] << endl;
+// }
+ riscvRef.dutRfWriteValue = top->VexRiscv->lastStageRegFileWrite_payload_data;
+ riscvRef.step();
+ bool mIntTimer = false;
+ bool mIntExt = false;
+ }
+
+ if(riscvRefEnable && top->VexRiscv->lastStagePc != riscvRef.lastPc){
+ cout << hex << " pc missmatch " << top->VexRiscv->lastStagePc << " should be " << riscvRef.lastPc << dec << endl;
+ fail();
+ }
+
+
+ bool rfWriteValid = false;
+ int32_t rfWriteAddress;
+ int32_t rfWriteData;
+
+ if(top->VexRiscv->lastStageRegFileWrite_valid == 1 && top->VexRiscv->lastStageRegFileWrite_payload_address != 0){
+ rfWriteValid = true;
+ rfWriteAddress = top->VexRiscv->lastStageRegFileWrite_payload_address;
+ rfWriteData = top->VexRiscv->lastStageRegFileWrite_payload_data;
+ #ifdef TRACE_ACCESS
+ regTraces <<
+ #ifdef TRACE_WITH_TIME
+ currentTime <<
+ #endif
+ " PC " << hex << setw(8) << top->VexRiscv->lastStagePc << " : reg[" << dec << setw(2) << (uint32_t)top->VexRiscv->lastStageRegFileWrite_payload_address << "] = " << hex << setw(8) << top->VexRiscv->lastStageRegFileWrite_payload_data << dec << endl;
+ #endif
+ } else {
+ #ifdef TRACE_ACCESS
+ regTraces <<
+ #ifdef TRACE_WITH_TIME
+ currentTime <<
+ #endif
+ " PC " << hex << setw(8) << top->VexRiscv->lastStagePc << dec << endl;
+ #endif
+ }
+ if(riscvRefEnable) if(rfWriteValid != riscvRef.rfWriteValid ||
+ (rfWriteValid && (rfWriteAddress!= riscvRef.rfWriteAddress || rfWriteData!= riscvRef.rfWriteData))){
+ cout << "regFile write missmatch :" << endl;
+ if(rfWriteValid) cout << " REF: RF[" << riscvRef.rfWriteAddress << "] = 0x" << hex << riscvRef.rfWriteData << dec << endl;
+ if(rfWriteValid) cout << " DUT: RF[" << rfWriteAddress << "] = 0x" << hex << rfWriteData << dec << endl;
+ fail();
+ }
+ }
+
+ #ifdef CSR
+ if(top->VexRiscv->CsrPlugin_hadException){
+ if(riscvRefEnable) {
+ riscvRef.step();
+ }
+ }
+ #endif
+
+ for(SimElement* simElement : simElements) simElement->preCycle();
+
+ dump(i + 1);
+
+ checks();
+ //top->eval();
+ top->clk = 1;
+ top->eval();
+
+ instanceCycles += 1;
+
+ for(SimElement* simElement : simElements) simElement->postCycle();
+ #ifdef RVF
+ top->fpuCmdHalt = VL_RANDOM_I_WIDTH(1);
+ top->fpuCommitHalt = VL_RANDOM_I_WIDTH(1);
+ top->fpuRspHalt = VL_RANDOM_I_WIDTH(1);
+ #endif
+
+
+
+ if (Verilated::gotFinish())
+ exit(0);
+ }
+ cout << "timeout" << endl;
+ fail();
+ } catch (const success e) {
+ staticMutex.lock();
+ cout <<"SUCCESS " << name << endl;
+ successCounter++;
+ cycles += instanceCycles;
+ staticMutex.unlock();
+ } catch (const std::exception& e) {
+ staticMutex.lock();
+
+ cout << "FAIL " << name << " at PC=" << hex << setw(8) << top->VexRiscv->lastStagePc << dec; //<< " seed : " << seed <<
+ if(riscvRefEnable) cout << hex << " REF PC=" << riscvRef.lastPc << " REF I=" << riscvRef.lastInstruction << dec;
+ cout << " time=" << i;
+ cout << endl;
+
+ cycles += instanceCycles;
+ staticMutex.unlock();
+ failed = true;
+ }
+
+
+
+ dump(i+2);
+ dump(i+10);
+ #ifdef TRACE
+ tfp->close();
+ #endif
+ #ifdef STOP_ON_ERROR
+ if(failed){
+ sleep(1);
+ exit(-1);
+ }
+ #endif
+ return this;
+ }
+};
+
+
+class WorkspaceRegression : public Workspace {
+public:
+
+ WorkspaceRegression(string name) : Workspace(name){
+
+ }
+
+ virtual bool isPerifRegion(uint32_t addr) { return (addr & 0xF0000000) == 0xF0000000;}
+
+
+ virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error){
+ Workspace::iBusAccess(addr,data,error);
+ *error = addr == 0xF00FFF60u;
+ }
+
+ virtual void dutPutChar(char c){}
+
+ virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size, uint8_t *dataBytes, bool *error) {
+ uint32_t *data = ((uint32_t*)dataBytes);
+ if(wr){
+ switch(addr){
+ case 0xF0010000u: {
+ cout << (char)*data;
+ logTraces << (char)*data;
+ dutPutChar((char)*data);
+ break;
+ }
+#ifdef EXTERNAL_INTERRUPT
+ case 0xF0011000u: top->externalInterrupt = *data & 1; break;
+#endif
+#ifdef SUPERVISOR
+ case 0xF0012000u: top->externalInterruptS = *data & 1; break;
+#endif
+#ifdef CSR
+ case 0xF0013000u: top->softwareInterrupt = *data & 1; break;
+#endif
+ case 0xF00FFF00u: {
+ cout << (char)*data;
+ logTraces << (char)*data;
+ dutPutChar((char)*data);
+ break;
+ }
+ #ifndef DEBUG_PLUGIN_EXTERNAL
+ case 0xF00FFF20u:
+ if(*data == 0)
+ pass();
+ else
+ fail();
+ break;
+ case 0xF00FFF24u:
+ cout << "TEST ERROR CODE " << *data << endl;
+ fail();
+ break;
+ #endif
+ case 0xF00FFF48u: mTimeCmp = (mTimeCmp & 0xFFFFFFFF00000000) | *data;break;
+ case 0xF00FFF4Cu: mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); break;
+ case 0xF00FFF50u: cout << "mTime " << *data << " : " << mTime << endl;
+ }
+ if((addr & 0xFFFFF000) == 0xF5670000){
+ uint32_t t = 0x900FF000 | (addr & 0xFFF);
+ uint32_t old = (*mem.get(t + 3) << 24) | (*mem.get(t + 2) << 16) | (*mem.get(t + 1) << 8) | (*mem.get(t + 0) << 0);
+ old++;
+ *mem.get(t + 0) = old & 0xFF; old >>= 8;
+ *mem.get(t + 1) = old & 0xFF; old >>= 8;
+ *mem.get(t + 2) = old & 0xFF; old >>= 8;
+ *mem.get(t + 3) = old & 0xFF; old >>= 8;
+ }
+ }else{
+ switch(addr){
+ case 0xF00FFF10u:
+ *data = mTime;
+ #ifdef REF_TIME
+ mTime += 100000;
+ #endif
+ break;
+ case 0xF00FFF40u: *data = mTime; break;
+ case 0xF00FFF44u: *data = mTime >> 32; break;
+ case 0xF00FFF48u: *data = mTimeCmp; break;
+ case 0xF00FFF4Cu: *data = mTimeCmp >> 32; break;
+ case 0xF0010004u: *data = ~0; break;
+ }
+ }
+
+ *error = addr == 0xF00FFF60u;
+ Workspace::dBusAccess(addr,wr,size,dataBytes,error);
+ }
+
+
+
+};
+
+
+
+class ZephyrRegression : public WorkspaceRegression{
+public:
+
+
+ uint32_t regFileWriteRefIndex = 0;
+ const char *target = "PROJECT EXECUTION SUCCESSFUL";
+ const char *hit = target;
+
+ ZephyrRegression(string name) : WorkspaceRegression(name) {
+ cout << endl << endl;
+
+ }
+
+ virtual void dutPutChar(char c){
+ if(*hit == c) hit++; else hit = target;
+ if(*hit == 0) {
+ cout << endl << "T=" << i <<endl;
+ cout << endl;
+ pass();
+ }
+ }
+};
+
+
+
+
+
+
+#ifdef IBUS_SIMPLE
+class IBusSimple : public SimElement{
+public:
+ uint32_t pendings[256];
+ uint32_t rPtr = 0, wPtr = 0;
+
+ Workspace *ws;
+ VVexRiscv* top;
+ IBusSimple(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->iBus_cmd_ready = 1;
+ top->iBus_rsp_valid = 0;
+ }
+
+ virtual void preCycle(){
+ if (top->iBus_cmd_valid && top->iBus_cmd_ready) {
+ //assertEq(top->iBus_cmd_payload_pc & 3,0);
+ pendings[wPtr] = (top->iBus_cmd_payload_pc);
+ wPtr = (wPtr + 1) & 0xFF;
+ //ws->iBusAccess(top->iBus_cmd_payload_pc,&inst_next,&error_next);
+ }
+ }
+ //TODO doesn't catch when instruction removed ?
+ virtual void postCycle(){
+ top->iBus_rsp_valid = 0;
+ if(rPtr != wPtr && (!ws->iStall || VL_RANDOM_I_WIDTH(7) < 100)){
+ uint32_t inst_next;
+ bool error_next;
+ ws->iBusAccess(pendings[rPtr], &inst_next,&error_next);
+ rPtr = (rPtr + 1) & 0xFF;
+ top->iBus_rsp_payload_inst = inst_next;
+ top->iBus_rsp_valid = 1;
+ top->iBus_rsp_payload_error = error_next;
+ } else {
+ top->iBus_rsp_payload_inst = VL_RANDOM_I_WIDTH(32);
+ top->iBus_rsp_payload_error = VL_RANDOM_I_WIDTH(1);
+ }
+ if(ws->iStall) top->iBus_cmd_ready = VL_RANDOM_I_WIDTH(7) < 100;
+ }
+};
+#endif
+
+
+#ifdef IBUS_TC
+
+class IBusTc : public SimElement{
+public:
+
+ uint32_t nextData;
+
+ Workspace *ws;
+ VVexRiscv* top;
+ IBusTc(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ }
+
+ virtual void preCycle(){
+ if (top->iBusTc_enable) {
+ if((top->iBusTc_address & 0x70000000) != 0){
+ printf("IBusTc access out of range\n");
+ ws->fail();
+ }
+ bool error_next;
+ ws->iBusAccess(top->iBusTc_address, &nextData,&error_next);
+ }
+ }
+
+ virtual void postCycle(){
+ top->iBusTc_data = nextData;
+ }
+};
+
+#endif
+
+
+#ifdef IBUS_SIMPLE_AVALON
+
+struct IBusSimpleAvalonRsp{
+ uint32_t data;
+ bool error;
+};
+
+
+class IBusSimpleAvalon : public SimElement{
+public:
+ queue<IBusSimpleAvalonRsp> rsps;
+
+ Workspace *ws;
+ VVexRiscv* top;
+ IBusSimpleAvalon(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->iBusAvalon_waitRequestn = 1;
+ top->iBusAvalon_readDataValid = 0;
+ }
+
+ virtual void preCycle(){
+ if (top->iBusAvalon_read && top->iBusAvalon_waitRequestn) {
+ IBusSimpleAvalonRsp rsp;
+ ws->iBusAccess(top->iBusAvalon_address,&rsp.data,&rsp.error);
+ rsps.push(rsp);
+ }
+ }
+ //TODO doesn't catch when instruction removed ?
+ virtual void postCycle(){
+ if(!rsps.empty() && (!ws->iStall || VL_RANDOM_I_WIDTH(7) < 100)){
+ IBusSimpleAvalonRsp rsp = rsps.front(); rsps.pop();
+ top->iBusAvalon_readDataValid = 1;
+ top->iBusAvalon_readData = rsp.data;
+ top->iBusAvalon_response = rsp.error ? 3 : 0;
+ } else {
+ top->iBusAvalon_readDataValid = 0;
+ top->iBusAvalon_readData = VL_RANDOM_I_WIDTH(32);
+ top->iBusAvalon_response = VL_RANDOM_I_WIDTH(2);
+ }
+ if(ws->iStall)
+ top->iBusAvalon_waitRequestn = VL_RANDOM_I_WIDTH(7) < 100;
+ }
+};
+#endif
+
+
+
+#ifdef IBUS_SIMPLE_AHBLITE3
+class IBusSimpleAhbLite3 : public SimElement{
+public:
+ Workspace *ws;
+ VVexRiscv* top;
+
+ uint32_t iBusAhbLite3_HRDATA;
+ bool iBusAhbLite3_HRESP;
+ bool pending;
+
+ IBusSimpleAhbLite3(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ pending = false;
+ top->iBusAhbLite3_HREADY = 1;
+ top->iBusAhbLite3_HRESP = 0;
+ }
+
+ virtual void preCycle(){
+ if (top->iBusAhbLite3_HTRANS == 2 && top->iBusAhbLite3_HREADY && !top->iBusAhbLite3_HWRITE) {
+ ws->iBusAccess(top->iBusAhbLite3_HADDR,&iBusAhbLite3_HRDATA,&iBusAhbLite3_HRESP);
+ pending = true;
+ }
+ }
+
+ virtual void postCycle(){
+ if(ws->iStall)
+ top->iBusAhbLite3_HREADY = (!ws->iStall || VL_RANDOM_I_WIDTH(7) < 100);
+
+ if(pending && top->iBusAhbLite3_HREADY){
+ top->iBusAhbLite3_HRDATA = iBusAhbLite3_HRDATA;
+ top->iBusAhbLite3_HRESP = iBusAhbLite3_HRESP;
+ pending = false;
+ } else {
+ top->iBusAhbLite3_HRDATA = VL_RANDOM_I_WIDTH(32);
+ top->iBusAhbLite3_HRESP = VL_RANDOM_I_WIDTH(1);
+ }
+ }
+};
+#endif
+
+
+#ifdef IBUS_CACHED
+class IBusCached : public SimElement{
+public:
+ bool error_next = false;
+ uint32_t pendingCount = 0;
+ uint32_t address;
+
+ Workspace *ws;
+ VVexRiscv* top;
+ IBusCached(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+
+ virtual void onReset(){
+ top->iBus_cmd_ready = 1;
+ top->iBus_rsp_valid = 0;
+ }
+
+ virtual void preCycle(){
+ if (top->iBus_cmd_valid && top->iBus_cmd_ready && pendingCount == 0) {
+ assertEq((top->iBus_cmd_payload_address & 3),0);
+ pendingCount = (1 << top->iBus_cmd_payload_size)/4;
+ address = top->iBus_cmd_payload_address;
+ }
+ }
+
+ virtual void postCycle(){
+ bool error;
+ top->iBus_rsp_valid = 0;
+ if(pendingCount != 0 && (!ws->iStall || VL_RANDOM_I_WIDTH(7) < 100)){
+ #ifdef IBUS_TC
+ if((address & 0x70000000) == 0){
+ printf("IBUS_CACHED access out of range\n");
+ ws->fail();
+ }
+ #endif
+ error = false;
+ for(int idx = 0;idx < IBUS_DATA_WIDTH/32;idx++){
+ bool localError = false;
+ ws->iBusAccess(address+idx*4,((uint32_t*)&top->iBus_rsp_payload_data)+idx,&localError);
+ error |= localError;
+ }
+ top->iBus_rsp_payload_error = error;
+ pendingCount-=IBUS_DATA_WIDTH/32;
+ address = address + IBUS_DATA_WIDTH/8;
+ top->iBus_rsp_valid = 1;
+ }
+ if(ws->iStall) top->iBus_cmd_ready = VL_RANDOM_I_WIDTH(7) < 100 && pendingCount == 0;
+ }
+};
+#endif
+
+#ifdef IBUS_CACHED_AVALON
+#include <queue>
+
+struct IBusCachedAvalonTask{
+ uint32_t address;
+ uint32_t pendingCount;
+};
+
+class IBusCachedAvalon : public SimElement{
+public:
+ uint32_t inst_next = VL_RANDOM_I_WIDTH(32);
+ bool error_next = false;
+
+ queue<IBusCachedAvalonTask> tasks;
+ Workspace *ws;
+ VVexRiscv* top;
+
+ IBusCachedAvalon(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->iBusAvalon_waitRequestn = 1;
+ top->iBusAvalon_readDataValid = 0;
+ }
+
+ virtual void preCycle(){
+ if (top->iBusAvalon_read && top->iBusAvalon_waitRequestn) {
+ assertEq(top->iBusAvalon_address & 3,0);
+ IBusCachedAvalonTask task;
+ task.address = top->iBusAvalon_address;
+ task.pendingCount = top->iBusAvalon_burstCount;
+ tasks.push(task);
+ }
+ }
+
+ virtual void postCycle(){
+ bool error;
+ top->iBusAvalon_readDataValid = 0;
+ if(!tasks.empty() && (!ws->iStall || VL_RANDOM_I_WIDTH(7) < 100)){
+ uint32_t &address = tasks.front().address;
+ uint32_t &pendingCount = tasks.front().pendingCount;
+ bool error;
+ ws->iBusAccess(address,&top->iBusAvalon_readData,&error);
+ top->iBusAvalon_response = error ? 3 : 0;
+ pendingCount--;
+ address = (address & ~0x1F) + ((address + 4) & 0x1F);
+ top->iBusAvalon_readDataValid = 1;
+ if(pendingCount == 0)
+ tasks.pop();
+ }
+ if(ws->iStall)
+ top->iBusAvalon_waitRequestn = VL_RANDOM_I_WIDTH(7) < 100;
+ }
+};
+#endif
+
+
+#if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE)
+#include <queue>
+
+class IBusCachedWishbone : public SimElement{
+public:
+
+ Workspace *ws;
+ VVexRiscv* top;
+
+ IBusCachedWishbone(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->iBusWishbone_ACK = !ws->iStall;
+ top->iBusWishbone_ERR = 0;
+ }
+
+ virtual void preCycle(){
+
+ }
+
+ virtual void postCycle(){
+
+ if(ws->iStall)
+ top->iBusWishbone_ACK = VL_RANDOM_I_WIDTH(7) < 100;
+
+ top->iBusWishbone_DAT_MISO = VL_RANDOM_I_WIDTH(32);
+ if (top->iBusWishbone_CYC && top->iBusWishbone_STB && top->iBusWishbone_ACK) {
+ if(top->iBusWishbone_WE){
+
+ } else {
+ bool error;
+ ws->iBusAccess(top->iBusWishbone_ADR << 2,&top->iBusWishbone_DAT_MISO,&error);
+ top->iBusWishbone_ERR = error;
+ }
+ }
+ }
+};
+#endif
+
+
+#ifdef DBUS_SIMPLE
+class DBusSimple : public SimElement{
+public:
+ uint32_t data_next = VL_RANDOM_I_WIDTH(32);
+ bool error_next = false;
+ bool pending = false;
+
+ Workspace *ws;
+ VVexRiscv* top;
+ DBusSimple(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->dBus_cmd_ready = 1;
+ top->dBus_rsp_ready = 1;
+ }
+
+ virtual void preCycle(){
+ if (top->dBus_cmd_valid && top->dBus_cmd_ready) {
+ pending = true;
+ data_next = top->dBus_cmd_payload_data;
+ ws->dBusAccess(top->dBus_cmd_payload_address,top->dBus_cmd_payload_wr,1 << top->dBus_cmd_payload_size,((uint8_t*)&data_next) + (top->dBus_cmd_payload_address & 3),&error_next);
+ }
+ }
+
+ virtual void postCycle(){
+ top->dBus_rsp_ready = 0;
+ if(pending && (!ws->dStall || VL_RANDOM_I_WIDTH(7) < 100)){
+ pending = false;
+ top->dBus_rsp_ready = 1;
+ top->dBus_rsp_data = data_next;
+ top->dBus_rsp_error = error_next;
+ } else{
+ top->dBus_rsp_data = VL_RANDOM_I_WIDTH(32);
+ }
+
+ if(ws->dStall) top->dBus_cmd_ready = VL_RANDOM_I_WIDTH(7) < 100 && !pending;
+ }
+};
+#endif
+
+#ifdef DBUS_SIMPLE_AVALON
+#include <queue>
+struct DBusSimpleAvalonRsp{
+ uint32_t data;
+ bool error;
+};
+
+
+class DBusSimpleAvalon : public SimElement{
+public:
+ queue<DBusSimpleAvalonRsp> rsps;
+
+ Workspace *ws;
+ VVexRiscv* top;
+ DBusSimpleAvalon(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->dBusAvalon_waitRequestn = 1;
+ top->dBusAvalon_readDataValid = 0;
+ }
+
+ virtual void preCycle(){
+ if (top->dBusAvalon_write && top->dBusAvalon_waitRequestn) {
+ bool dummy;
+ ws->dBusAccess(top->dBusAvalon_address,1,2,top->dBusAvalon_byteEnable,&top->dBusAvalon_writeData,&dummy);
+ }
+ if (top->dBusAvalon_read && top->dBusAvalon_waitRequestn) {
+ DBusSimpleAvalonRsp rsp;
+ ws->dBusAccess(top->dBusAvalon_address,0,2,0xF,&rsp.data,&rsp.error);
+ rsps.push(rsp);
+ }
+ }
+ //TODO doesn't catch when instruction removed ?
+ virtual void postCycle(){
+ if(!rsps.empty() && (!ws->iStall || VL_RANDOM_I_WIDTH(7) < 100)){
+ DBusSimpleAvalonRsp rsp = rsps.front(); rsps.pop();
+ top->dBusAvalon_readDataValid = 1;
+ top->dBusAvalon_readData = rsp.data;
+ top->dBusAvalon_response = rsp.error ? 3 : 0;
+ } else {
+ top->dBusAvalon_readDataValid = 0;
+ top->dBusAvalon_readData = VL_RANDOM_I_WIDTH(32);
+ top->dBusAvalon_response = VL_RANDOM_I_WIDTH(2);
+ }
+ if(ws->iStall)
+ top->dBusAvalon_waitRequestn = VL_RANDOM_I_WIDTH(7) < 100;
+ }
+};
+#endif
+
+
+
+#ifdef DBUS_SIMPLE_AHBLITE3
+class DBusSimpleAhbLite3 : public SimElement{
+public:
+ Workspace *ws;
+ VVexRiscv* top;
+
+ uint32_t dBusAhbLite3_HADDR, dBusAhbLite3_HSIZE, dBusAhbLite3_HTRANS, dBusAhbLite3_HWRITE;
+
+ DBusSimpleAhbLite3(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->dBusAhbLite3_HREADY = 1;
+ top->dBusAhbLite3_HRESP = 0;
+ dBusAhbLite3_HTRANS = 0;
+ }
+
+ virtual void preCycle(){
+ if(top->dBusAhbLite3_HREADY && dBusAhbLite3_HTRANS == 2 && dBusAhbLite3_HWRITE){
+ uint32_t data = top->dBusAhbLite3_HWDATA;
+ bool error;
+ ws->dBusAccess(dBusAhbLite3_HADDR, 1, dBusAhbLite3_HSIZE, ((1 << (1 << dBusAhbLite3_HSIZE))-1) << (dBusAhbLite3_HADDR & 0x3),&data,&error);
+ }
+
+ if(top->dBusAhbLite3_HREADY){
+ dBusAhbLite3_HADDR = top->dBusAhbLite3_HADDR ;
+ dBusAhbLite3_HSIZE = top->dBusAhbLite3_HSIZE ;
+ dBusAhbLite3_HTRANS = top->dBusAhbLite3_HTRANS ;
+ dBusAhbLite3_HWRITE = top->dBusAhbLite3_HWRITE ;
+ }
+ }
+
+ virtual void postCycle(){
+ if(ws->iStall)
+ top->dBusAhbLite3_HREADY = (!ws->iStall || VL_RANDOM_I_WIDTH(7) < 100);
+
+ top->dBusAhbLite3_HRDATA = VL_RANDOM_I_WIDTH(32);
+ top->dBusAhbLite3_HRESP = VL_RANDOM_I_WIDTH(1);
+
+ if(top->dBusAhbLite3_HREADY && dBusAhbLite3_HTRANS == 2 && !dBusAhbLite3_HWRITE){
+
+ bool error;
+ ws->dBusAccess(dBusAhbLite3_HADDR, 0, dBusAhbLite3_HSIZE, ((1 << (1 << dBusAhbLite3_HSIZE))-1) << (dBusAhbLite3_HADDR & 0x3),&top->dBusAhbLite3_HRDATA,&error);
+ top->dBusAhbLite3_HRESP = error;
+ }
+ }
+};
+#endif
+
+
+#if defined(DBUS_CACHED_WISHBONE) || defined(DBUS_SIMPLE_WISHBONE)
+#include <queue>
+
+
+class DBusCachedWishbone : public SimElement{
+public:
+
+ Workspace *ws;
+ VVexRiscv* top;
+
+ DBusCachedWishbone(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->dBusWishbone_ACK = !ws->iStall;
+ top->dBusWishbone_ERR = 0;
+ }
+
+ virtual void preCycle(){
+
+ }
+
+ virtual void postCycle(){
+ if(ws->iStall)
+ top->dBusWishbone_ACK = VL_RANDOM_I_WIDTH(7) < 100;
+ top->dBusWishbone_DAT_MISO = VL_RANDOM_I_WIDTH(32);
+ if (top->dBusWishbone_CYC && top->dBusWishbone_STB && top->dBusWishbone_ACK) {
+ if(top->dBusWishbone_WE){
+ bool dummy;
+ ws->dBusAccess(top->dBusWishbone_ADR << 2 ,1,2,top->dBusWishbone_SEL,&top->dBusWishbone_DAT_MOSI,&dummy);
+ } else {
+ bool error;
+ ws->dBusAccess(top->dBusWishbone_ADR << 2,0,2,0xF,&top->dBusWishbone_DAT_MISO,&error);
+ top->dBusWishbone_ERR = error;
+ }
+ }
+ }
+};
+#endif
+
+#ifdef DBUS_CACHED
+
+//#include "VVexRiscv_DataCache.h"
+#include <queue>
+
+struct DBusCachedTask{
+ char data[DBUS_LOAD_DATA_WIDTH/8];
+ bool error;
+ bool last;
+ bool exclusive;
+};
+
+class DBusCached : public SimElement{
+public:
+ queue<DBusCachedTask> rsps;
+ queue<uint32_t> invalidationHint;
+
+ bool reservationValid = false;
+ uint32_t reservationAddress;
+ uint32_t pendingSync = 0;
+
+ Workspace *ws;
+ VVexRiscv* top;
+ DBusCachedTask rsp;
+
+ DBusCached(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->dBus_cmd_ready = 1;
+ top->dBus_rsp_valid = 0;
+ #ifdef DBUS_AGGREGATION
+ top->dBus_rsp_payload_aggregated = 0;
+ #endif
+ #ifdef DBUS_INVALIDATE
+ top->dBus_inv_valid = 0;
+ top->dBus_ack_ready = 0;
+ top->dBus_sync_valid = 0;
+ #ifdef DBUS_AGGREGATION
+ top->dBus_sync_payload_aggregated = 0;
+ #endif
+ #endif
+ }
+
+ virtual void preCycle(){
+ if (top->dBus_cmd_valid && top->dBus_cmd_ready) {
+ if(top->dBus_cmd_payload_wr){
+ int size = 1 << top->dBus_cmd_payload_size;
+ #ifdef DBUS_INVALIDATE
+ pendingSync += 1;
+ #endif
+ #ifndef DBUS_EXCLUSIVE
+ bool error;
+ int shift = top->dBus_cmd_payload_address & (DBUS_STORE_DATA_WIDTH/8-1);
+ ws->dBusAccess(top->dBus_cmd_payload_address,1,size,((uint8_t*)&top->dBus_cmd_payload_data) + shift,&error);
+ #else
+ bool cancel = false, error = false;
+ if(top->dBus_cmd_payload_exclusive){
+ bool hit = reservationValid && reservationAddress == top->dBus_cmd_payload_address;
+ rsp.exclusive = hit;
+ cancel = !hit;
+ }
+ if(!cancel) {
+ for(int idx = 0;idx < 1;idx++){
+ bool localError = false;
+ int shift = top->dBus_cmd_payload_address & (DBUS_STORE_DATA_WIDTH/8-1);
+ ws->dBusAccess(top->dBus_cmd_payload_address,1,size,((uint8_t*)&top->dBus_cmd_payload_data) + shift,&localError);
+ error |= localError;
+ }
+ }
+
+ reservationValid = false;
+ rsp.last = true;
+ rsp.error = error;
+ rsps.push(rsp);
+ #endif
+ } else {
+ bool error = false;
+ uint32_t beatCount = (((1 << top->dBus_cmd_payload_size)*8+DBUS_LOAD_DATA_WIDTH-1) / DBUS_LOAD_DATA_WIDTH)-1;
+ uint32_t startAt = top->dBus_cmd_payload_address;
+ uint32_t endAt = top->dBus_cmd_payload_address + (1 << top->dBus_cmd_payload_size);
+ uint32_t address = top->dBus_cmd_payload_address & ~(DBUS_LOAD_DATA_WIDTH/8-1);
+ uint8_t buffer[64];
+ ws->dBusAccess(top->dBus_cmd_payload_address,0,1 << top->dBus_cmd_payload_size,buffer, &error);
+ for(int beat = 0;beat <= beatCount;beat++){
+ for(int i = 0;i < DBUS_LOAD_DATA_WIDTH/8;i++){
+ rsp.data[i] = (address >= startAt && address < endAt) ? buffer[address-top->dBus_cmd_payload_address] : VL_RANDOM_I_WIDTH(8);
+ address += 1;
+ }
+ rsp.last = beat == beatCount;
+ #ifdef DBUS_EXCLUSIVE
+ if(top->dBus_cmd_payload_exclusive){
+ rsp.exclusive = true;
+ reservationValid = true;
+ reservationAddress = top->dBus_cmd_payload_address;
+ }
+ #endif
+ rsp.error = error;
+ rsps.push(rsp);
+ }
+
+ #ifdef DBUS_INVALIDATE
+ if(ws->allowInvalidate){
+ if(VL_RANDOM_I_WIDTH(7) < 10){
+ invalidationHint.push(top->dBus_cmd_payload_address + VL_RANDOM_I_WIDTH(5));
+ }
+ }
+ #endif
+ }
+ }
+ #ifdef DBUS_INVALIDATE
+ if(top->dBus_sync_valid && top->dBus_sync_ready){
+ pendingSync -= 1;
+ }
+ #endif
+ }
+
+ virtual void postCycle(){
+
+ if(!rsps.empty() && (!ws->dStall || VL_RANDOM_I_WIDTH(7) < 100)){
+ DBusCachedTask rsp = rsps.front();
+ rsps.pop();
+ top->dBus_rsp_valid = 1;
+ top->dBus_rsp_payload_error = rsp.error;
+ for(int idx = 0;idx < DBUS_LOAD_DATA_WIDTH/32;idx++){
+ ((uint32_t*)&top->dBus_rsp_payload_data)[idx] = ((uint32_t*)rsp.data)[idx];
+ }
+ top->dBus_rsp_payload_last = rsp.last;
+ #ifdef DBUS_EXCLUSIVE
+ top->dBus_rsp_payload_exclusive = rsp.exclusive;
+ #endif
+ } else{
+ top->dBus_rsp_valid = 0;
+ for(int idx = 0;idx < DBUS_LOAD_DATA_WIDTH/32;idx++){
+ ((uint32_t*)&top->dBus_rsp_payload_data)[idx] = VL_RANDOM_I_WIDTH(32);
+ }
+ top->dBus_rsp_payload_error = VL_RANDOM_I_WIDTH(1);
+ top->dBus_rsp_payload_last = VL_RANDOM_I_WIDTH(1);
+ #ifdef DBUS_EXCLUSIVE
+ top->dBus_rsp_payload_exclusive = VL_RANDOM_I_WIDTH(1);
+ #endif
+ }
+ top->dBus_cmd_ready = (ws->dStall ? VL_RANDOM_I_WIDTH(7) < 100 : 1);
+
+ #ifdef DBUS_INVALIDATE
+ if(ws->allowInvalidate){
+ if(top->dBus_inv_ready) top->dBus_inv_valid = 0;
+ if(top->dBus_inv_valid == 0 && VL_RANDOM_I_WIDTH(7) < 5){
+ top->dBus_inv_valid = 1;
+ top->dBus_inv_payload_fragment_enable = VL_RANDOM_I_WIDTH(7) < 100;
+ if(!invalidationHint.empty()){
+ top->dBus_inv_payload_fragment_address = invalidationHint.front();
+ invalidationHint.pop();
+ } else {
+ top->dBus_inv_payload_fragment_address = VL_RANDOM_I_WIDTH(32);
+ }
+ }
+ }
+ top->dBus_ack_ready = (ws->dStall ? VL_RANDOM_I_WIDTH(7) < 100 : 1);
+ if(top->dBus_sync_ready) top->dBus_sync_valid = 0;
+ if(top->dBus_sync_valid == 0 && pendingSync != 0 && (ws->dStall ? VL_RANDOM_I_WIDTH(7) < 80 : 1) ){
+ top->dBus_sync_valid = 1;
+ }
+ #endif
+
+ }
+};
+#endif
+
+#ifdef DBUS_CACHED_AVALON
+#include <queue>
+
+struct DBusCachedAvalonTask{
+ uint32_t data;
+ bool error;
+};
+
+class DBusCachedAvalon : public SimElement{
+public:
+ uint32_t beatCounter = 0;
+ queue<DBusCachedAvalonTask> rsps;
+
+ Workspace *ws;
+ VVexRiscv* top;
+ DBusCachedAvalon(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+ }
+
+ virtual void onReset(){
+ top->dBusAvalon_waitRequestn = 1;
+ top->dBusAvalon_readDataValid = 0;
+ }
+
+
+ virtual void preCycle(){
+ if ((top->dBusAvalon_read || top->dBusAvalon_write) && top->dBusAvalon_waitRequestn) {
+ if(top->dBusAvalon_write){
+ uint32_t size = __builtin_popcount(top->dBusAvalon_byteEnable);
+ uint32_t offset = ffs(top->dBusAvalon_byteEnable)-1;
+ bool error_next = false;
+ ws->dBusAccess(top->dBusAvalon_address + beatCounter * 4 + offset,1,size,((uint8_t*)&top->dBusAvalon_writeData)+offset,&error_next);
+ beatCounter++;
+ if(beatCounter == top->dBusAvalon_burstCount){
+ beatCounter = 0;
+ }
+ } else {
+ for(int beat = 0;beat < top->dBusAvalon_burstCount;beat++){
+ DBusCachedAvalonTask rsp;
+ ws->dBusAccess(top->dBusAvalon_address + beat * 4 ,0,4,((uint8_t*)&rsp.data),&rsp.error);
+ rsps.push(rsp);
+ }
+ }
+ }
+ }
+
+ virtual void postCycle(){
+ if(!rsps.empty() && (!ws->dStall || VL_RANDOM_I_WIDTH(7) < 100)){
+ DBusCachedAvalonTask rsp = rsps.front();
+ rsps.pop();
+ top->dBusAvalon_response = rsp.error ? 3 : 0;
+ top->dBusAvalon_readData = rsp.data;
+ top->dBusAvalon_readDataValid = 1;
+ } else{
+ top->dBusAvalon_readDataValid = 0;
+ top->dBusAvalon_readData = VL_RANDOM_I_WIDTH(32);
+ top->dBusAvalon_response = VL_RANDOM_I_WIDTH(2); //TODO
+ }
+
+ top->dBusAvalon_waitRequestn = (ws->dStall ? VL_RANDOM_I_WIDTH(7) < 100 : 1);
+ }
+};
+#endif
+
+
+#ifdef DEBUG_PLUGIN
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <netinet/tcp.h>
+
+/** Returns true on success, or false if there was an error */
+bool SetSocketBlockingEnabled(int fd, bool blocking)
+{
+ if (fd < 0) return false;
+
+#ifdef WIN32
+ unsigned long mode = blocking ? 0 : 1;
+ return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false;
+#else
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0) return false;
+ flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
+ return (fcntl(fd, F_SETFL, flags) == 0) ? true : false;
+#endif
+}
+
+struct DebugPluginTask{
+ bool wr;
+ uint32_t address;
+ uint32_t data;
+};
+
+class DebugPlugin : public SimElement{
+public:
+ Workspace *ws;
+ VVexRiscv* top;
+
+ int serverSocket, clientHandle;
+ struct sockaddr_in serverAddr;
+ struct sockaddr_storage serverStorage;
+ socklen_t addr_size;
+ char buffer[1024];
+ uint32_t timeSpacer = 0;
+ bool taskValid = false;
+ DebugPluginTask task;
+
+
+ DebugPlugin(Workspace* ws){
+ this->ws = ws;
+ this->top = ws->top;
+
+ #ifdef DEBUG_PLUGIN_EXTERNAL
+ ws->mTimeCmp = ~0;
+ #endif
+ top->debugReset = 0;
+
+
+
+ //---- Create the socket. The three arguments are: ----//
+ // 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) //
+ serverSocket = socket(PF_INET, SOCK_STREAM, 0);
+ assert(serverSocket != -1);
+ SetSocketBlockingEnabled(serverSocket,0);
+ int flag = 1;
+ int result = setsockopt(serverSocket, /* socket affected */
+ IPPROTO_TCP, /* set option at TCP level */
+ TCP_NODELAY, /* name of option */
+ (char *) &flag, /* the cast is historical
+ cruft */
+ sizeof(int)); /* length of option value */
+
+ //---- Configure settings of the server address struct ----//
+ // Address family = Internet //
+ serverAddr.sin_family = AF_INET;
+ // Set port number, using htons function to use proper byte order //
+ serverAddr.sin_port = htons(7893);
+ // Set IP address to localhost //
+ serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ // Set all bits of the padding field to 0 //
+ memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
+
+ //---- Bind the address struct to the socket ----//
+ bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
+
+ //---- Listen on the socket, with 5 max connection requests queued ----//
+ listen(serverSocket,1);
+
+ //---- Accept call creates a new socket for the incoming connection ----//
+ addr_size = sizeof serverStorage;
+
+ clientHandle = -1;
+ }
+
+ virtual ~DebugPlugin(){
+ if(clientHandle != -1) {
+ shutdown(clientHandle,SHUT_RDWR);
+ usleep(100);
+ }
+ if(serverSocket != -1) {
+ close(serverSocket);
+ usleep(100);
+ }
+ }
+
+ virtual void onReset(){
+ top->debugReset = 1;
+ }
+
+
+
+ virtual void postReset(){
+ top->debugReset = 0;
+ }
+
+ void connectionReset(){
+ printf("CONNECTION RESET\n");
+ shutdown(clientHandle,SHUT_RDWR);
+ clientHandle = -1;
+ }
+
+
+ virtual void preCycle(){
+
+ }
+
+ virtual void postCycle(){
+ top->reset = top->debug_resetOut;
+ if(timeSpacer == 0){
+ if(clientHandle == -1){
+ clientHandle = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
+ if(clientHandle != -1)
+ printf("CONNECTED\n");
+ timeSpacer = 1000;
+ }
+
+
+ if(clientHandle != -1 && taskValid == false){
+ int requiredSize = 1 + 1 + 4 + 4;
+ int n;
+ timeSpacer = 20;
+ if(ioctl(clientHandle,FIONREAD,&n) != 0){
+ connectionReset();
+ } else if(n >= requiredSize){
+ if(requiredSize != read(clientHandle,buffer,requiredSize)){
+ connectionReset();
+ } else {
+ bool wr = buffer[0];
+ uint32_t size = buffer[1];
+ uint32_t address = *((uint32_t*)(buffer + 2));
+ uint32_t data = *((uint32_t*)(buffer + 6));
+
+ if((address & ~ 0x4) == 0xF00F0000){
+ assert(size == 2);
+ timeSpacer = 100;
+
+ taskValid = true;
+ task.wr = wr;
+ task.address = address;
+ task.data = data;
+ }
+ }
+ } else {
+ int error = 0;
+ socklen_t len = sizeof (error);
+ int retval = getsockopt (clientHandle, SOL_SOCKET, SO_ERROR, &error, &len);
+ if (retval != 0 || error != 0) {
+ connectionReset();
+ }
+ }
+ }
+ } else {
+ timeSpacer--;
+ }
+ }
+
+ void sendRsp(uint32_t data){
+ if(clientHandle != -1){
+ if(send(clientHandle,&data,4,0) == -1) connectionReset();
+ }
+ }
+};
+#endif
+
+#ifdef DEBUG_PLUGIN_STD
+class DebugPluginStd : public DebugPlugin{
+public:
+ DebugPluginStd(Workspace* ws) : DebugPlugin(ws){
+
+ }
+
+ virtual void onReset(){
+ DebugPlugin::onReset();
+ top->debug_bus_cmd_valid = 0;
+ }
+
+ bool rspFire = false;
+
+ virtual void preCycle(){
+ DebugPlugin::preCycle();
+
+ if(rspFire){
+ sendRsp(top->debug_bus_rsp_data);
+ rspFire = false;
+ }
+
+ if(top->debug_bus_cmd_valid && top->debug_bus_cmd_ready){
+ taskValid = false;
+ if(!top->debug_bus_cmd_payload_wr){
+ rspFire = true;
+ }
+ }
+ }
+
+ virtual void postCycle(){
+ DebugPlugin::postCycle();
+
+ if(taskValid){
+ top->debug_bus_cmd_valid = 1;
+ top->debug_bus_cmd_payload_wr = task.wr;
+ top->debug_bus_cmd_payload_address = task.address;
+ top->debug_bus_cmd_payload_data = task.data;
+ }else {
+ top->debug_bus_cmd_valid = 0;
+ top->debug_bus_cmd_payload_wr = VL_RANDOM_I_WIDTH(1);
+ top->debug_bus_cmd_payload_address = VL_RANDOM_I_WIDTH(8);
+ top->debug_bus_cmd_payload_data = VL_RANDOM_I_WIDTH(32);
+ }
+ }
+};
+
+#endif
+
+#ifdef DEBUG_PLUGIN_AVALON
+class DebugPluginAvalon : public DebugPlugin{
+public:
+ DebugPluginAvalon(Workspace* ws) : DebugPlugin(ws){
+
+ }
+
+ virtual void onReset(){
+ DebugPlugin::onReset();
+ top->debugBusAvalon_read = 0;
+ top->debugBusAvalon_write = 0;
+ }
+
+ bool rspFire = false;
+
+ virtual void preCycle(){
+ DebugPlugin::preCycle();
+
+ if(rspFire){
+ sendRsp(top->debugBusAvalon_readData);
+ rspFire = false;
+ }
+
+ if((top->debugBusAvalon_read || top->debugBusAvalon_write) && top->debugBusAvalon_waitRequestn){
+ taskValid = false;
+ if(top->debugBusAvalon_read){
+ rspFire = true;
+ }
+ }
+ }
+
+ virtual void postCycle(){
+ DebugPlugin::postCycle();
+
+ if(taskValid){
+ top->debugBusAvalon_write = task.wr;
+ top->debugBusAvalon_read = !task.wr;
+ top->debugBusAvalon_address = task.address;
+ top->debugBusAvalon_writeData = task.data;
+ }else {
+ top->debugBusAvalon_write = 0;
+ top->debugBusAvalon_read = 0;
+ top->debugBusAvalon_address = VL_RANDOM_I_WIDTH(8);
+ top->debugBusAvalon_writeData = VL_RANDOM_I_WIDTH(32);
+ }
+ }
+};
+
+#endif
+
+void Workspace::fillSimELements(){
+ #ifdef IBUS_SIMPLE
+ simElements.push_back(new IBusSimple(this));
+ #endif
+ #ifdef IBUS_SIMPLE_AVALON
+ simElements.push_back(new IBusSimpleAvalon(this));
+ #endif
+ #ifdef IBUS_SIMPLE_AHBLITE3
+ simElements.push_back(new IBusSimpleAhbLite3(this));
+ #endif
+
+
+ #ifdef IBUS_CACHED
+ simElements.push_back(new IBusCached(this));
+ #endif
+ #ifdef IBUS_CACHED_AVALON
+ simElements.push_back(new IBusCachedAvalon(this));
+ #endif
+ #if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE)
+ simElements.push_back(new IBusCachedWishbone(this));
+ #endif
+
+ #ifdef IBUS_TC
+ simElements.push_back(new IBusTc(this));
+ #endif
+
+ #ifdef DBUS_SIMPLE
+ simElements.push_back(new DBusSimple(this));
+ #endif
+ #ifdef DBUS_SIMPLE_AVALON
+ simElements.push_back(new DBusSimpleAvalon(this));
+ #endif
+ #ifdef DBUS_SIMPLE_AHBLITE3
+ simElements.push_back(new DBusSimpleAhbLite3(this));
+ #endif
+ #ifdef DBUS_CACHED
+ simElements.push_back(new DBusCached(this));
+ #endif
+ #ifdef DBUS_CACHED_AVALON
+ simElements.push_back(new DBusCachedAvalon(this));
+ #endif
+ #if defined(DBUS_CACHED_WISHBONE) || defined(DBUS_SIMPLE_WISHBONE)
+ simElements.push_back(new DBusCachedWishbone(this));
+ #endif
+ #ifdef DEBUG_PLUGIN_STD
+ simElements.push_back(new DebugPluginStd(this));
+ #endif
+ #ifdef DEBUG_PLUGIN_AVALON
+ simElements.push_back(new DebugPluginAvalon(this));
+ #endif
+}
+
+mutex Workspace::staticMutex;
+uint64_t Workspace::cycles = 0;
+uint32_t Workspace::testsCounter = 0, Workspace::successCounter = 0;
+
+#ifndef REF
+#define testA1ReagFileWriteRef {1,10},{2,20},{3,40},{4,60}
+#define testA2ReagFileWriteRef {5,1},{7,3}
+uint32_t regFileWriteRefArray[][2] = {
+ testA1ReagFileWriteRef,
+ testA1ReagFileWriteRef,
+ testA2ReagFileWriteRef,
+ testA2ReagFileWriteRef
+};
+
+class TestA : public WorkspaceRegression{
+public:
+
+
+ uint32_t regFileWriteRefIndex = 0;
+
+ TestA() : WorkspaceRegression("testA") {
+ loadHex(string(REGRESSION_PATH) + "../../resources/hex/testA.hex");
+ }
+
+ virtual void checks(){
+ if(top->VexRiscv->lastStageRegFileWrite_valid == 1 && top->VexRiscv->lastStageRegFileWrite_payload_address != 0){
+ assertEq(top->VexRiscv->lastStageRegFileWrite_payload_address, regFileWriteRefArray[regFileWriteRefIndex][0]);
+ assertEq(top->VexRiscv->lastStageRegFileWrite_payload_data, regFileWriteRefArray[regFileWriteRefIndex][1]);
+ //printf("%d\n",i);
+
+ regFileWriteRefIndex++;
+ if(regFileWriteRefIndex == sizeof(regFileWriteRefArray)/sizeof(regFileWriteRefArray[0])){
+ pass();
+ }
+ }
+ }
+};
+
+class TestX28 : public WorkspaceRegression{
+public:
+ uint32_t refIndex = 0;
+ uint32_t *ref;
+ uint32_t refSize;
+
+ TestX28(string name, uint32_t *ref, uint32_t refSize) : WorkspaceRegression(name) {
+ this->ref = ref;
+ this->refSize = refSize;
+ loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".hex");
+ }
+
+ virtual void checks(){
+ if(top->VexRiscv->lastStageRegFileWrite_valid == 1 && top->VexRiscv->lastStageRegFileWrite_payload_address == 28){
+ assertEq(top->VexRiscv->lastStageRegFileWrite_payload_data, ref[refIndex]);
+ //printf("%d\n",i);
+
+ refIndex++;
+ if(refIndex == refSize){
+ pass();
+ }
+ }
+ }
+};
+
+
+class RiscvTest : public WorkspaceRegression{
+public:
+ RiscvTest(string name) : WorkspaceRegression(name) {
+ loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".hex");
+ bootAt(0x800000bcu);
+ }
+
+ virtual void postReset() {
+// #ifdef CSR
+// top->VexRiscv->prefetch_PcManagerSimplePlugin_pcReg = 0x80000000u;
+// #else
+// #endif
+ }
+
+ virtual void checks(){
+ if(top->VexRiscv->lastStageIsFiring && top->VexRiscv->lastStageInstruction == 0x00000013){
+ uint32_t instruction;
+ bool error;
+ Workspace::mem.read(top->VexRiscv->lastStagePc, 4, (uint8_t*)&instruction);
+ //printf("%x => %x\n", top->VexRiscv->lastStagePc, instruction );
+ if(instruction == 0x00000073){
+ uint32_t code = top->VexRiscv->RegFilePlugin_regFile[28];
+ uint32_t code2 = top->VexRiscv->RegFilePlugin_regFile[3];
+ if((code & 1) == 0 && (code2 & 1) == 0){
+ cout << "Wrong error code"<< endl;
+ fail();
+ }
+ if(code == 1 || code2 == 1){
+ pass();
+ }else{
+ cout << "Error code " << code2/2 << endl;
+ fail();
+ }
+ }
+ }
+ }
+
+ virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error){
+ WorkspaceRegression::iBusAccess(addr,data,error);
+ if(*data == 0x0ff0000f) *data = 0x00000013;
+ if(*data == 0x00000073) *data = 0x00000013;
+ }
+};
+#endif
+class Dhrystone : public WorkspaceRegression{
+public:
+ string hexName;
+ Dhrystone(string name,string hexName,bool iStall, bool dStall) : WorkspaceRegression(name) {
+ setIStall(iStall);
+ setDStall(dStall);
+ withRiscvRef();
+ loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + hexName + ".hex");
+ this->hexName = hexName;
+ }
+
+ virtual void checks(){
+
+ }
+
+ virtual void pass(){
+ FILE *refFile = fopen((hexName + ".logRef").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);
+ fclose(refFile);
+
+
+ logTraces.flush();
+ logTraces.close();
+
+ FILE *logFile = fopen((name + ".logTrace").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);
+ fclose(logFile);
+
+ if(refSize > logSize || memcmp(log,ref,refSize))
+ fail();
+ else
+ Workspace::pass();
+ }
+};
+
+class Compliance : public WorkspaceRegression{
+public:
+ string name;
+ ofstream out32;
+ int out32Counter = 0;
+ Compliance(string name) : WorkspaceRegression(name) {
+ withRiscvRef();
+ loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".elf.hex");
+ out32.open (name + ".out32");
+ this->name = name;
+ }
+
+
+ virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size, uint8_t *dataBytes, bool *error) {
+ if(wr && addr == 0xF00FFF2C){
+ uint32_t *data = (uint32_t*)dataBytes;
+ out32 << hex << setw(8) << std::setfill('0') << *data << dec;
+ if(++out32Counter % 4 == 0) out32 << "\n";
+ }
+ WorkspaceRegression::dBusAccess(addr,wr,size,dataBytes,error);
+ }
+
+ virtual void checks(){
+
+ }
+
+
+
+ virtual void pass(){
+ FILE *refFile = fopen((string(REGRESSION_PATH) + string("../../resources/ref/") + name + ".reference_output").c_str(), "r");
+ fseek(refFile, 0, SEEK_END);
+ uint32_t refSize = ftell(refFile);
+ fseek(refFile, 0, SEEK_SET);
+ char* ref = new char[refSize];
+ fread(ref, 1, refSize, refFile);
+ fclose(refFile);
+
+
+ out32.flush();
+ out32.close();
+
+ 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);
+ fclose(logFile);
+
+ if(refSize > logSize || memcmp(log,ref,refSize))
+ fail();
+ else
+ Workspace::pass();
+ }
+};
+
+
+#ifdef DEBUG_PLUGIN
+
+#include<pthread.h>
+#include<stdlib.h>
+#include<unistd.h>
+#include <netinet/tcp.h>
+
+#define RISCV_SPINAL_FLAGS_RESET 1<<0
+#define RISCV_SPINAL_FLAGS_HALT 1<<1
+#define RISCV_SPINAL_FLAGS_PIP_BUSY 1<<2
+#define RISCV_SPINAL_FLAGS_IS_IN_BREAKPOINT 1<<3
+#define RISCV_SPINAL_FLAGS_STEP 1<<4
+#define RISCV_SPINAL_FLAGS_PC_INC 1<<5
+
+#define RISCV_SPINAL_FLAGS_RESET_SET 1<<16
+#define RISCV_SPINAL_FLAGS_HALT_SET 1<<17
+
+#define RISCV_SPINAL_FLAGS_RESET_CLEAR 1<<24
+#define RISCV_SPINAL_FLAGS_HALT_CLEAR 1<<25
+
+class DebugPluginTest : public WorkspaceRegression{
+public:
+ pthread_t clientThreadId;
+ char buffer[1024];
+ bool clientSuccess = false, clientFail = false;
+
+ static void* clientThreadWrapper(void *debugModule){
+ ((DebugPluginTest*)debugModule)->clientThread();
+ return NULL;
+ }
+
+ int clientSocket;
+ void accessCmd(bool wr, uint32_t size, uint32_t address, uint32_t data){
+ buffer[0] = wr;
+ buffer[1] = size;
+ *((uint32_t*) (buffer + 2)) = address;
+ *((uint32_t*) (buffer + 6)) = data;
+ send(clientSocket,buffer,10,0);
+ }
+
+ void writeCmd(uint32_t size, uint32_t address, uint32_t data){
+ accessCmd(true, 2, address, data);
+ }
+
+
+ uint32_t readCmd(uint32_t size, uint32_t address){
+ accessCmd(false, 2, address, VL_RANDOM_I_WIDTH(32));
+ int error;
+ if((error = recv(clientSocket, buffer, 4, 0)) != 4){
+ printf("Should read 4 bytes, had %d", error);
+ while(1);
+ }
+
+ return *((uint32_t*) buffer);
+ }
+
+
+
+ void clientThread(){
+ struct sockaddr_in serverAddr;
+
+ //---- Create the socket. The three arguments are: ----//
+ // 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) //
+ clientSocket = socket(PF_INET, SOCK_STREAM, 0);
+ int flag = 1;
+ int result = setsockopt(clientSocket, /* socket affected */
+ IPPROTO_TCP, /* set option at TCP level */
+ TCP_NODELAY, /* name of option */
+ (char *) &flag, /* the cast is historical
+ cruft */
+ sizeof(int)); /* length of option value */
+
+ //---- Configure settings of the server address struct ----//
+ // Address family = Internet //
+ serverAddr.sin_family = AF_INET;
+ // Set port number, using htons function to use proper byte order //
+ serverAddr.sin_port = htons(7893);
+ // Set IP address to localhost //
+ serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ // Set all bits of the padding field to 0 //
+ memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
+
+ //---- Connect the socket to the server using the address struct ----//
+ socklen_t addr_size = sizeof serverAddr;
+ int error = connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
+// printf("!! %x\n",readCmd(2,0x8));
+ uint32_t debugAddress = 0xF00F0000;
+ uint32_t readValue;
+
+ while(resetDone != true){usleep(100);}
+
+ while((readCmd(2,debugAddress) & RISCV_SPINAL_FLAGS_HALT) == 0){usleep(100);}
+ if((readValue = readCmd(2,debugAddress + 4)) != 0x8000000C){
+ printf("wrong breakA PC %x\n",readValue);
+ clientFail = true; return;
+ }
+
+ writeCmd(2, debugAddress + 4, 0x13 + (1 << 15)); //Read regfile
+ if((readValue = readCmd(2,debugAddress + 4)) != 10){
+ printf("wrong breakB PC %x\n",readValue);
+ clientFail = true; return;
+ }
+
+ writeCmd(2, debugAddress + 4, 0x13 + (2 << 15)); //Read regfile
+ if((readValue = readCmd(2,debugAddress + 4)) != 20){
+ printf("wrong breakC PC %x\n",readValue);
+ clientFail = true; return;
+ }
+
+ writeCmd(2, debugAddress + 4, 0x13 + (3 << 15)); //Read regfile
+ if((readValue = readCmd(2,debugAddress + 4)) != 30){
+ printf("wrong breakD PC %x\n",readValue);
+ clientFail = true; return;
+ }
+
+ writeCmd(2, debugAddress + 4, 0x13 + (1 << 7) + (40 << 20)); //Write x1 with 40
+ writeCmd(2, debugAddress + 4, 0x80000eb7); //Write x29 with 0x10
+ writeCmd(2, debugAddress + 4, 0x010e8e93); //Write x29 with 0x10
+ writeCmd(2, debugAddress + 4, 0x67 + (29 << 15)); //Branch x29
+ writeCmd(2, debugAddress + 0, RISCV_SPINAL_FLAGS_HALT_CLEAR); //Run CPU
+
+ while((readCmd(2,debugAddress) & RISCV_SPINAL_FLAGS_HALT) == 0){usleep(100);}
+ if((readValue = readCmd(2,debugAddress + 4)) != 0x80000014){
+ printf("wrong breakE PC 3 %x\n",readValue);
+ clientFail = true; return;
+ }
+
+
+ writeCmd(2, debugAddress + 4, 0x13 + (3 << 15)); //Read regfile
+ if((readValue = readCmd(2,debugAddress + 4)) != 60){
+ printf("wrong x1 %x\n",readValue);
+ clientFail = true; return;
+ }
+
+
+ writeCmd(2, debugAddress + 4, 0x80000eb7); //Write x29 with 0x10
+ writeCmd(2, debugAddress + 4, 0x018e8e93); //Write x29 with 0x10
+ writeCmd(2, debugAddress + 4, 0x67 + (29 << 15)); //Branch x29
+ writeCmd(2, debugAddress + 0, RISCV_SPINAL_FLAGS_HALT_CLEAR); //Run CPU
+
+
+
+ while((readCmd(2,debugAddress) & RISCV_SPINAL_FLAGS_HALT) == 0){usleep(100);}
+ if((readValue = readCmd(2,debugAddress + 4)) != 0x80000024){
+ printf("wrong breakF PC 3 %x\n",readValue);
+ clientFail = true; return;
+ }
+
+
+ writeCmd(2, debugAddress + 4, 0x13 + (3 << 15)); //Read x3
+ if((readValue = readCmd(2,debugAddress + 4)) != 171){
+ printf("wrong x3 %x\n",readValue);
+ clientFail = true; return;
+ }
+
+
+ clientSuccess = true;
+ }
+
+
+ DebugPluginTest() : WorkspaceRegression("DebugPluginTest") {
+ loadHex(string(REGRESSION_PATH) + "../../resources/hex/debugPlugin.hex");
+ pthread_create(&clientThreadId, NULL, &clientThreadWrapper, this);
+ }
+
+ virtual ~DebugPluginTest(){
+ if(clientSocket != -1) close(clientSocket);
+ }
+
+ virtual void checks(){
+ if(clientSuccess) pass();
+ if(clientFail) fail();
+ }
+
+ virtual void postReset(){
+ Workspace::postReset();
+ top->VexRiscv->DebugPlugin_debugUsed = 1;
+ }
+};
+
+#endif
+
+
+//#ifdef LITEX
+//class LitexSoC : public Workspace{
+//public:
+//
+// LitexSoC(string name) : Workspace(name) {
+//
+// }
+// virtual bool isDBusCheckedRegion(uint32_t address){ return true;}
+// virtual bool isPerifRegion(uint32_t addr) { return (addr & 0xF0000000) == 0xB0000000 || (addr & 0xE0000000) == 0xE0000000;}
+// virtual bool isMmuRegion(uint32_t addr) { return (addr & 0xFF000000) != 0x81000000;}
+//
+// virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
+// if(isPerifRegion(addr)) switch(addr){
+// //TODO Emulate peripherals here
+// case 0xFFFFFFE0: if(wr) fail(); else *data = mTime; break;
+// case 0xFFFFFFE4: if(wr) fail(); else *data = mTime >> 32; break;
+// case 0xFFFFFFE8: if(wr) mTimeCmp = (mTimeCmp & 0xFFFFFFFF00000000) | *data; else *data = mTimeCmp; break;
+// case 0xFFFFFFEC: if(wr) mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); else *data = mTimeCmp >> 32; break;
+// case 0xFFFFFFF8:
+// if(wr){
+// cout << (char)*data;
+// logTraces << (char)*data;
+// logTraces.flush();
+// } else fail();
+// break;
+// case 0xFFFFFFFC: fail(); break; //Simulation end
+// default: cout << "Unmapped peripheral access : addr=0x" << hex << addr << " wr=" << wr << " mask=0x" << mask << " data=0x" << data << dec << endl; fail(); break;
+// }
+//
+// Workspace::dBusAccess(addr,wr,size,mask,data,error);
+// }
+//};
+//#endif
+
+
+
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+termios stdinRestoreSettings;
+void stdinNonBuffered(){
+ static struct termios old, new1;
+ tcgetattr(STDIN_FILENO, &old); // grab old terminal i/o settings
+ new1 = old; // make new settings same as old settings
+ new1.c_lflag &= ~ICANON; // disable buffered i/o
+ new1.c_lflag &= ~ECHO;
+ tcsetattr(STDIN_FILENO, TCSANOW, &new1); // use these new terminal i/o settings now
+ setvbuf(stdin, NULL, _IONBF, 0);
+ stdinRestoreSettings = old;
+}
+
+
+bool stdinNonEmpty(){
+ struct timeval tv;
+ fd_set fds;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds);
+ select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
+ return (FD_ISSET(0, &fds));
+}
+
+
+void stdoutNonBuffered(){
+ setvbuf(stdout, NULL, _IONBF, 0);
+}
+
+void stdinRestore(){
+ tcsetattr(STDIN_FILENO, TCSANOW, &stdinRestoreSettings);
+}
+
+
+
+void my_handler(int s){
+ printf("Caught signal %d\n",s);
+ stdinRestore();
+ exit(1);
+}
+#include <signal.h>
+
+void captureCtrlC(){
+ struct sigaction sigIntHandler;
+
+ sigIntHandler.sa_handler = my_handler;
+ sigemptyset(&sigIntHandler.sa_mask);
+ sigIntHandler.sa_flags = 0;
+
+ sigaction(SIGINT, &sigIntHandler, NULL);
+}
+
+
+
+
+#if defined(LINUX_SOC) || defined(LINUX_REGRESSION)
+#include <queue>
+class LinuxSoc : public Workspace{
+public:
+ queue <char> customCin;
+ void pushCin(string m){
+ for(char& c : m) {
+ customCin.push(c);
+ }
+ }
+
+ LinuxSoc(string name) : Workspace(name) {
+ #ifdef WITH_USER_IO
+ stdinNonBuffered();
+ captureCtrlC();
+ #endif
+ stdoutNonBuffered();
+ }
+
+ virtual ~LinuxSoc(){
+ #ifdef WITH_USER_IO
+ stdinRestore();
+ #endif
+ }
+ virtual bool isDBusCheckedRegion(uint32_t address){ return true;}
+ virtual bool isPerifRegion(uint32_t addr) { return (addr & 0xF0000000) == 0xF0000000 || (addr & 0xE0000000) == 0xE0000000;}
+ virtual bool isMmuRegion(uint32_t addr) { return true; }
+
+
+
+ virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint8_t *dataBytes, bool *error) {
+ uint32_t *data = (uint32_t*)dataBytes;
+
+ if(isPerifRegion(addr)) {
+ switch(addr){
+ case 0xFFFFFFE0: if(wr) fail(); else *data = mTime; break;
+ case 0xFFFFFFE4: if(wr) fail(); else *data = mTime >> 32; break;
+ case 0xFFFFFFE8: if(wr) mTimeCmp = (mTimeCmp & 0xFFFFFFFF00000000) | *data; else *data = mTimeCmp; break;
+ case 0xFFFFFFEC: if(wr) mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); else *data = mTimeCmp >> 32; break;
+ case 0xFFFFFFF8:
+ if(wr){
+ char c = (char)*data;
+ cout << c;
+ logTraces << c;
+ logTraces.flush();
+ onStdout(c);
+ } else {
+ #ifdef WITH_USER_IO
+ if(stdinNonEmpty()){
+ char c;
+ read(0, &c, 1);
+ *data = c;
+ } else
+ #endif
+ if(!customCin.empty()){
+ *data = customCin.front();
+ customCin.pop();
+ } else {
+ *data = -1;
+ }
+ }
+ break;
+ case 0xFFFFFFFC: fail(); break; //Simulation end
+ default: cout << "Unmapped peripheral access : addr=0x" << hex << addr << " wr=" << wr << " mask=0x" << " data=0x" << data << dec << endl; fail(); break;
+ }
+ }
+ Workspace::dBusAccess(addr,wr,size,dataBytes,error);
+ }
+
+ virtual void onStdout(char c){
+
+ }
+};
+
+class LinuxRegression: public LinuxSoc{
+public:
+ string pendingLine = "";
+ bool pendingLineContain(string m) {
+ return strstr(pendingLine.c_str(), m.c_str()) != NULL;
+ }
+
+ enum State{LOGIN, ECHO_FILE, HEXDUMP, HEXDUMP_CHECK, PASS};
+ State state = LOGIN;
+ LinuxRegression(string name) : LinuxSoc(name) {
+
+ }
+
+ ~LinuxRegression() {
+ }
+
+
+ virtual void onStdout(char c){
+ pendingLine += c;
+ switch(state){
+ case LOGIN: if (pendingLineContain("buildroot login:")) { pushCin("root\n"); state = ECHO_FILE; } break;
+ case ECHO_FILE: if (pendingLineContain("# ")) { pushCin("echo \"miaou\" > test.txt\n"); state = HEXDUMP; pendingLine = "";} break;
+ case HEXDUMP: if (pendingLineContain("# ")) { pushCin("hexdump -C test.txt\n"); state = HEXDUMP_CHECK; pendingLine = "";} break;
+ case HEXDUMP_CHECK: if (pendingLineContain("00000000 6d 69 61 6f 75 0a ")) { pushCin(""); state = PASS; pendingLine = "";} break;
+ case PASS: if (pendingLineContain("# ")) { pass(); } break;
+ }
+ if(c == '\n' || pendingLine.length() > 200) pendingLine = "";
+ }
+};
+
+#endif
+
+#ifdef LINUX_SOC_SMP
+
+class LinuxSocSmp : public Workspace{
+public:
+ queue <char> customCin;
+ void pushCin(string m){
+ for(char& c : m) {
+ customCin.push(c);
+ }
+ }
+
+ LinuxSocSmp(string name) : Workspace(name) {
+ #ifdef WITH_USER_IO
+ stdinNonBuffered();
+ captureCtrlC();
+ #endif
+ stdoutNonBuffered();
+ }
+
+ virtual ~LinuxSocSmp(){
+ #ifdef WITH_USER_IO
+ stdinRestore();
+ #endif
+ }
+ virtual bool isDBusCheckedRegion(uint32_t address){ return true;}
+ virtual bool isPerifRegion(uint32_t addr) { return (addr & 0xF0000000) == 0xF0000000;}
+ virtual bool isMmuRegion(uint32_t addr) { return true; }
+
+
+
+ virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size, uint8_t *dataBytes, bool *error) {
+ uint32_t *data = (uint32_t*)dataBytes;
+ if(isPerifRegion(addr)) switch(addr){
+ case 0xF0010000: if(wr && *data != 0) fail(); else *data = 0; break;
+ case 0xF001BFF8: if(wr) fail(); else *data = mTime; break;
+ case 0xF001BFFC: if(wr) fail(); else *data = mTime >> 32; break;
+ case 0xF0014000: if(wr) mTimeCmp = (mTimeCmp & 0xFFFFFFFF00000000) | *data; else fail(); break;
+ case 0xF0014004: if(wr) mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); else fail(); break;
+ case 0xF0000000:
+ if(wr){
+ char c = (char)*data;
+ cout << c;
+ logTraces << c;
+ logTraces.flush();
+ onStdout(c);
+ }
+ case 0xF0000004:
+ if(!wr){
+ #ifdef WITH_USER_IO
+ if(stdinNonEmpty()){
+ char c;
+ read(0, &c, 1);
+ *data = c;
+ } else
+ #endif
+ if(!customCin.empty()){
+ *data = customCin.front();
+ customCin.pop();
+ } else {
+ *data = -1;
+ }
+ }
+ break;
+ default: cout << "Unmapped peripheral access : addr=0x" << hex << addr << " wr=" << wr << " data=0x" << data << dec << endl; fail(); break;
+ }
+ Workspace::dBusAccess(addr,wr,size,dataBytes,error);
+ }
+
+ virtual void onStdout(char c){
+
+ }
+};
+
+#endif
+
+string riscvTestMain[] = {
+ //"rv32ui-p-simple",
+ "rv32ui-p-lui",
+ "rv32ui-p-auipc",
+ "rv32ui-p-jal",
+ "rv32ui-p-jalr",
+ "rv32ui-p-beq",
+ "rv32ui-p-bge",
+ "rv32ui-p-bgeu",
+ "rv32ui-p-blt",
+ "rv32ui-p-bltu",
+ "rv32ui-p-bne",
+ "rv32ui-p-add",
+ "rv32ui-p-addi",
+ "rv32ui-p-and",
+ "rv32ui-p-andi",
+ "rv32ui-p-or",
+ "rv32ui-p-ori",
+ "rv32ui-p-sll",
+ "rv32ui-p-slli",
+ "rv32ui-p-slt",
+ "rv32ui-p-slti",
+ "rv32ui-p-sra",
+ "rv32ui-p-srai",
+ "rv32ui-p-srl",
+ "rv32ui-p-srli",
+ "rv32ui-p-sub",
+ "rv32ui-p-xor",
+ "rv32ui-p-xori"
+};
+
+string riscvTestMemory[] = {
+ "rv32ui-p-lb",
+ "rv32ui-p-lbu",
+ "rv32ui-p-lh",
+ "rv32ui-p-lhu",
+ "rv32ui-p-lw",
+ "rv32ui-p-sb",
+ "rv32ui-p-sh",
+ "rv32ui-p-sw"
+};
+
+
+string riscvTestFloat[] = {
+ "rv32uf-p-fmadd",
+ "rv32uf-p-fadd",
+ "rv32uf-p-fcmp",
+ "rv32uf-p-fcvt_w",
+ "rv32uf-p-ldst",
+ "rv32uf-p-recoding",
+ "rv32uf-p-fclass",
+ "rv32uf-p-fcvt",
+ "rv32uf-p-fdiv",
+ "rv32uf-p-fmin",
+ "rv32uf-p-move"
+};
+
+
+string riscvTestDouble[] = {
+ "rv32ud-p-fmadd",
+ "rv32ud-p-fadd",
+ "rv32ud-p-fcvt",
+ "rv32ud-p-recoding",
+ "rv32ud-p-fclass",
+ "rv32ud-p-fcvt_w",
+ "rv32ud-p-fmin",
+ "rv32ud-p-fcmp",
+ "rv32ud-p-fdiv",
+ "rv32ud-p-ldst"
+};
+
+
+
+
+string riscvTestMul[] = {
+ "rv32um-p-mul",
+ "rv32um-p-mulh",
+ "rv32um-p-mulhsu",
+ "rv32um-p-mulhu"
+};
+
+string riscvTestDiv[] = {
+ "rv32um-p-div",
+ "rv32um-p-divu",
+ "rv32um-p-rem",
+ "rv32um-p-remu"
+};
+
+string freeRtosTests[] = {
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1",
+// "test1","test1","test1","test1","test1","test1","test1","test1"
+
+ "AltQTest", "AltBlock", "AltPollQ", "blocktim", "countsem", "dead", "EventGroupsDemo", "flop", "integer", "QPeek",
+ "QueueSet", "recmutex", "semtest", "TaskNotify", "crhook", "dynamic",
+ "GenQTest", "PollQ", "QueueOverwrite", "QueueSetPolling", "sp_flop", "test1"
+ //"BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ"
+// "flop"
+// "flop", "sp_flop" // <- Simple test
+ // "AltBlckQ" ???
+
+};
+
+
+string zephyrTests[] = {
+ "tests_kernel_stack_stack_api",
+ "tests_kernel_context",
+// "tests_kernel_critical", //Too long
+ "tests_kernel_fifo_fifo_api",
+ "tests_kernel_mbox_mbox_usage",
+// "tests_kernel_mem_pool_mem_pool_threadsafe", //Too long
+ "tests_kernel_sleep"
+// "tests_kernel_timer_timer_api" //Lock like if the CPU is too slow, it will make it fail
+};
+
+
+
+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
+ return start_time;
+}
+
+long timer_end(struct timespec start_time){
+ struct timespec end_time;
+ clock_gettime(CLOCK_REALTIME, &end_time);
+ uint64_t diffInNanos = end_time.tv_sec*1e9 + end_time.tv_nsec - start_time.tv_sec*1e9 - start_time.tv_nsec;
+ return diffInNanos;
+}
+
+#define redo(count,that) for(uint32_t xxx = 0;xxx < count;xxx++) that
+#include <pthread.h>
+#include <queue>
+#include <functional>
+#include <thread>
+
+
+static void multiThreading(queue<std::function<void()>> *lambdas, std::mutex *mutex){
+ uint32_t counter = 0;
+ while(true){
+ mutex->lock();
+ if(lambdas->empty()){
+ mutex->unlock();
+ break;
+ }
+
+ #ifdef SEED
+ uint32_t seed = SEED + counter;
+ counter++;
+ srand48(seed);
+ printf("MT_SEED=%d \n", seed);
+ #endif
+ std::function<void()> lambda = lambdas->front();
+ lambdas->pop();
+ mutex->unlock();
+
+ lambda();
+ }
+}
+
+
+static void multiThreadedExecute(queue<std::function<void()>> &lambdas){
+ std::mutex mutex;
+ if(THREAD_COUNT == 1){
+ multiThreading(&lambdas, &mutex);
+ } else {
+ std::thread * t[THREAD_COUNT];
+ for(int id = 0;id < THREAD_COUNT;id++){
+ t[id] = new thread(multiThreading,&lambdas,&mutex);
+ }
+ for(int id = 0;id < THREAD_COUNT;id++){
+ t[id]->join();
+ delete t[id];
+ }
+ }
+}
+
+int main(int argc, char **argv, char **env) {
+ #ifdef SEED
+ srand48(SEED);
+ #endif
+ Verilated::randReset(2);
+ Verilated::commandArgs(argc, argv);
+
+ printf("BOOT\n");
+ timespec startedAt = timer_start();
+
+
+#ifdef LINUX_SOC_SMP
+ {
+
+ LinuxSocSmp soc("linuxSmp");
+ #ifndef DEBUG_PLUGIN_EXTERNAL
+ soc.withRiscvRef();
+ soc.loadBin(EMULATOR, 0x80000000);
+ soc.loadBin(VMLINUX, 0x80400000);
+ soc.loadBin(DTB, 0x80FF0000);
+ soc.loadBin(RAMDISK, 0x81000000);
+ #endif
+ //soc.setIStall(true);
+ //soc.setDStall(true);
+ soc.bootAt(0x80000000);
+ soc.run(0);
+// soc.run((496300000l + 2000000) / 2);
+// soc.run(438700000l/2);
+ return -1;
+ }
+#endif
+
+
+
+ #ifdef RVF
+ for(const string &name : riscvTestFloat){
+ redo(REDO,RiscvTest(name).withRiscvRef()->bootAt(0x80000188u)->writeWord(0x80000184u, 0x00305073)->run();)
+ }
+ #endif
+ #ifdef RVD
+ for(const string &name : riscvTestDouble){
+ redo(REDO,RiscvTest(name).withRiscvRef()->bootAt(0x80000188u)->writeWord(0x80000184u, 0x00305073)->run();)
+ }
+ #endif
+ //return 0;
+
+//#ifdef LITEX
+// LitexSoC("linux")
+// .withRiscvRef()
+// ->loadBin(EMULATOR, 0x80000000)
+// ->loadBin(DTB, 0x81000000)
+// ->loadBin(VMLINUX, 0xc0000000)
+// ->loadBin(RAMDISK, 0xc2000000)
+// ->setIStall(false) //TODO It currently improve speed but should be removed later
+// ->setDStall(false)
+// ->bootAt(0x80000000)
+// ->run(0);
+//#endif
+
+// {
+// static struct termios old, new1;
+// tcgetattr(0, &old); /* grab old terminal i/o settings */
+// new1 = old; /* make new settings same as old settings */
+// new1.c_lflag &= ~ICANON; /* disable buffered i/o */
+// new1.c_lflag &= ~ECHO;
+// tcsetattr(0, TCSANOW, &new1); /* use these new terminal i/o settings now */
+// }
+//
+// std::string initialCommand;
+//
+// while(true){
+// if(!inputAvailable()) {
+// std::cout << "Waiting for input (Ctrl-C to cancel)..." << std::endl;
+// sleep(1);
+// } else {
+// char c;
+// read(0, &c, 1); printf("%d\n", c);
+//// std::getline(std::cin, initialCommand);
+// }
+// }
+//
+
+// char c;
+// while (1) { read(0, &c, 1); printf("%d\n", c); }
+// while(true){
+// char c = getchar();
+// if(c > 0)
+// {
+// putchar(c);
+// } else {
+// putchar('*');
+// sleep(500);
+// }
+// }
+
+#ifdef LINUX_SOC
+ {
+
+ LinuxSoc soc("linux");
+ #ifndef DEBUG_PLUGIN_EXTERNAL
+ soc.withRiscvRef();
+ soc.loadBin(EMULATOR, 0x80000000);
+ soc.loadBin(VMLINUX, 0xC0000000);
+ soc.loadBin(DTB, 0xC3000000);
+ soc.loadBin(RAMDISK, 0xC2000000);
+ #endif
+ //soc.setIStall(true);
+ //soc.setDStall(true);
+ soc.bootAt(0x80000000);
+ soc.run(0);
+// soc.run((496300000l + 2000000) / 2);
+// soc.run(438700000l/2);
+ return -1;
+ }
+#endif
+
+
+
+
+
+// #ifdef MMU
+// redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
+// #endif
+// redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
+// return 0;
+
+
+ for(int idx = 0;idx < 1;idx++){
+
+ #if defined(DEBUG_PLUGIN_EXTERNAL) || defined(RUN_HEX)
+ {
+ WorkspaceRegression w("run");
+ #ifdef RUN_HEX
+ //w.loadHex("/home/spinalvm/hdl/zephyr/zephyrSpinalHdl/samples/synchronization/build/zephyr/zephyr.hex");
+ w.loadHex(RUN_HEX);
+ w.withRiscvRef();
+ #endif
+ w.setIStall(false);
+ w.setDStall(false);
+
+ #if defined(TRACE) || defined(TRACE_ACCESS)
+ //w.setCyclesPerSecond(5e3);
+ //printf("Speed reduced 5Khz\n");
+ #endif
+ w.run(0xFFFFFFFFFFFF);
+ exit(0);
+ }
+ #endif
+
+
+ #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
+ #if defined(CSR) && !defined(CSR_SKIP_TEST)
+ 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).withRiscvRef()->run();)
+ }
+ for(const string &name : riscvTestMemory){
+ redo(REDO,RiscvTest(name).withRiscvRef()->run();)
+ }
+
+
+ #ifdef MUL
+ for(const string &name : riscvTestMul){
+ redo(REDO,RiscvTest(name).withRiscvRef()->run();)
+ }
+ #endif
+ #ifdef DIV
+ for(const string &name : riscvTestDiv){
+ redo(REDO,RiscvTest(name).withRiscvRef()->run();)
+ }
+ #endif
+
+ #ifdef COMPRESSED
+ redo(REDO,RiscvTest("rv32uc-p-rvc").withRiscvRef()->bootAt(0x800000FCu)->run());
+ #endif
+
+ #if defined(CSR) && !defined(CSR_SKIP_TEST)
+ #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,0, 14,2, 15,5,16,17,1 };
+ redo(REDO,TestX28("../../cpp/raw/machineCsr/build/machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).withRiscvRef()->setVcdName("machineCsr")->run(10e4);)
+ #else
+ 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, 14,2, 15,5,16,17,1 };
+ redo(REDO,TestX28("../../cpp/raw/machineCsr/build/machineCsrCompressed",machineCsrRef, sizeof(machineCsrRef)/4).withRiscvRef()->setVcdName("machineCsrCompressed")->run(10e4);)
+ #endif
+ #endif
+// #ifdef MMU
+// uint32_t mmuRef[] = {1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5,
+// 13, 0xC4000000,0x33333333, 6,7,
+// 1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5,
+// 13, 0xC4000000,0x33333333, 6,7};
+// redo(REDO,TestX28("mmu",mmuRef, sizeof(mmuRef)/4).noInstructionReadCheck()->run(4e4);)
+// #endif
+
+ #ifdef IBUS_CACHED
+ redo(REDO,WorkspaceRegression("icache").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/icache/build/icache.hex")->bootAt(0x80000000u)->run(50e3););
+ #endif
+ #ifdef DBUS_CACHED
+ redo(REDO,WorkspaceRegression("dcache").loadHex(string(REGRESSION_PATH) + "../raw/dcache/build/dcache.hex")->bootAt(0x80000000u)->run(2500e3););
+ #endif
+
+ #ifdef MMU
+ redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
+ #endif
+ #ifdef SUPERVISOR
+ redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
+ #endif
+
+ #ifdef DEBUG_PLUGIN
+ #ifndef CONCURRENT_OS_EXECUTIONS
+ redo(REDO,DebugPluginTest().run(1e6););
+ #endif
+ #endif
+ #endif
+
+ #ifdef CUSTOM_SIMD_ADD
+ redo(REDO,WorkspaceRegression("custom_simd_add").loadHex(string(REGRESSION_PATH) + "../custom/simd_add/build/custom_simd_add.hex")->bootAt(0x00000000u)->run(50e3););
+ #endif
+
+ #ifdef CUSTOM_CSR
+ redo(REDO,WorkspaceRegression("custom_csr").loadHex(string(REGRESSION_PATH) + "../custom/custom_csr/build/custom_csr.hex")->bootAt(0x00000000u)->run(50e3););
+ #endif
+
+
+ #ifdef LRSC
+ redo(REDO,WorkspaceRegression("lrsc").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/lrsc/build/lrsc.hex")->bootAt(0x00000000u)->run(10e3););
+ #endif
+
+ #ifdef PMP
+ redo(REDO,WorkspaceRegression("pmp").loadHex(string(REGRESSION_PATH) + "../raw/pmp/build/pmp.hex")->bootAt(0x80000000u)->run(10e3););
+ #endif
+
+ #ifdef AMO
+ redo(REDO,WorkspaceRegression("amo").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/amo/build/amo.hex")->bootAt(0x00000000u)->run(10e3););
+ #endif
+
+ #ifdef DHRYSTONE
+ Dhrystone("dhrystoneO3_Stall","dhrystoneO3",true,true).run(1.5e6);
+ #if defined(COMPRESSED)
+ Dhrystone("dhrystoneO3C_Stall","dhrystoneO3C",true,true).run(1.5e6);
+ #endif
+ #if defined(MUL) && defined(DIV)
+ Dhrystone("dhrystoneO3M_Stall","dhrystoneO3M",true,true).run(1.9e6);
+ #if defined(COMPRESSED)
+ Dhrystone("dhrystoneO3MC_Stall","dhrystoneO3MC",true,true).run(1.9e6);
+ #endif
+ #endif
+ #if defined(COMPRESSED)
+ Dhrystone("dhrystoneO3C","dhrystoneO3C",false,false).run(1.9e6);
+ #endif
+ Dhrystone("dhrystoneO3","dhrystoneO3",false,false).run(1.9e6);
+ #if defined(MUL) && defined(DIV)
+ #if defined(COMPRESSED)
+ Dhrystone("dhrystoneO3MC","dhrystoneO3MC",false,false).run(1.9e6);
+ #endif
+ Dhrystone("dhrystoneO3M","dhrystoneO3M",false,false).run(1.9e6);
+ #endif
+ #endif
+
+ #ifdef COREMARK
+ for(int withStall = 1; true ;withStall--){
+ string rv = "rv32i";
+ #if defined(MUL) && defined(DIV)
+ rv += "m";
+ #endif
+ #if defined(COMPRESSED)
+ if(withStall == -2) break;
+ if(withStall != -1) rv += "c";
+ #else
+ if(withStall == -1) break;
+ #endif
+ WorkspaceRegression("coremark_" + rv + (withStall > 0 ? "_stall" : "_nostall")).withRiscvRef()
+ ->loadBin(string(REGRESSION_PATH) + "../../resources/bin/coremark_" + rv + ".bin", 0x80000000)
+ ->bootAt(0x80000000)
+ ->setIStall(withStall > 0)
+ ->setDStall(withStall > 0)
+ ->run(50e6);
+ }
+ #endif
+
+
+
+ #ifdef FREERTOS
+ {
+ #ifdef SEED
+ srand48(SEED);
+ #endif
+ //redo(1,WorkspaceRegression("freeRTOS_demo").loadHex("../../resources/hex/freeRTOS_demo.hex")->bootAt(0x80000000u)->run(100e6);)
+ vector <std::function<void()>> tasks;
+
+ /*for(int redo = 0;redo < 4;redo++)*/{
+ for(const string &name : freeRtosTests){
+ tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O0").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32i_O0.hex")->bootAt(0x80000000u)->run(4e6*15);});
+ tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32i_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
+ #ifdef COMPRESSED
+// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O0").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32ic_O0.hex")->bootAt(0x80000000u)->run(5e6*15);});
+ tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32ic_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
+ #endif
+ #if defined(MUL) && defined(DIV)
+// #ifdef COMPRESSED
+// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32imac_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32imac_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
+// #else
+ tasks.push_back([=]() { WorkspaceRegression(name + "_rv32im_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32im_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
+// #endif
+ #endif
+ }
+ }
+
+ while(tasks.size() > FREERTOS_COUNT){
+ tasks.erase(tasks.begin() + (VL_RANDOM_I_WIDTH(32)%tasks.size()));
+ }
+
+
+ queue <std::function<void()>> tasksSelected(std::deque<std::function<void()>>(tasks.begin(), tasks.end()));
+ multiThreadedExecute(tasksSelected);
+ }
+ #endif
+
+ #ifdef ZEPHYR
+ {
+ #ifdef SEED
+ srand48(SEED);
+ #endif
+ //redo(1,WorkspaceRegression("freeRTOS_demo").loadHex("../../resources/hex/freeRTOS_demo.hex")->bootAt(0x80000000u)->run(100e6);)
+ vector <std::function<void()>> tasks;
+
+ /*for(int redo = 0;redo < 4;redo++)*/{
+ for(const string &name : zephyrTests){
+ #ifdef COMPRESSED
+ tasks.push_back([=]() { ZephyrRegression(name + "_rv32ic").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32ic.hex")->bootAt(0x80000000u)->run(180e6);});
+ #else
+ tasks.push_back([=]() { ZephyrRegression(name + "_rv32i").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32i.hex")->bootAt(0x80000000u)->run(180e6);});
+ #endif
+ #if defined(MUL) && defined(DIV)
+ tasks.push_back([=]() { ZephyrRegression(name + "_rv32im").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32im.hex")->bootAt(0x80000000u)->run(180e6);});
+ #endif
+ }
+ }
+
+ while(tasks.size() > ZEPHYR_COUNT){
+ tasks.erase(tasks.begin() + (VL_RANDOM_I_WIDTH(32)%tasks.size()));
+ }
+
+
+ queue <std::function<void()>> tasksSelected(std::deque<std::function<void()>>(tasks.begin(), tasks.end()));
+ multiThreadedExecute(tasksSelected);
+ }
+ #endif
+
+ #if defined(LINUX_REGRESSION)
+ {
+
+ LinuxRegression soc("linux");
+ #ifndef DEBUG_PLUGIN_EXTERNAL
+ soc.withRiscvRef();
+ soc.loadBin(string(REGRESSION_PATH) + EMULATOR, 0x80000000);
+ soc.loadBin(string(REGRESSION_PATH) + VMLINUX, 0xC0000000);
+ soc.loadBin(string(REGRESSION_PATH) + DTB, 0xC3000000);
+ soc.loadBin(string(REGRESSION_PATH) + RAMDISK, 0xC2000000);
+ #endif
+ //soc.setIStall(true);
+ //soc.setDStall(true);
+ soc.bootAt(0x80000000);
+ soc.run(153995602l*9);
+// soc.run((470000000l + 2000000) / 2);
+// soc.run(438700000l/2);
+ }
+ #endif
+
+ }
+
+ uint64_t duration = timer_end(startedAt);
+ cout << endl << "****************************************************************" << endl;
+ cout << "Had simulate " << Workspace::cycles << " clock cycles in " << duration*1e-9 << " s (" << Workspace::cycles / (duration*1e-6) << " Khz)" << endl;
+ if(Workspace::successCounter == Workspace::testsCounter)
+ cout << "REGRESSION SUCCESS " << Workspace::successCounter << "/" << Workspace::testsCounter << endl;
+ else
+ cout<< "REGRESSION FAILURE " << Workspace::testsCounter - Workspace::successCounter << "/" << Workspace::testsCounter << endl;
+ cout << "****************************************************************" << endl << endl;
+
+
+ exit(0);
+}
diff --git a/VexRiscv/src/test/cpp/regression/makefile b/VexRiscv/src/test/cpp/regression/makefile
new file mode 100644
index 0000000..b8759c9
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/makefile
@@ -0,0 +1,345 @@
+DEBUG?=no
+REGRESSION_PATH?=./
+VEXRISCV_FILE?=../../../../VexRiscv.v
+IBUS?=CACHED
+IBUS_TC?=no
+IBUS_DATA_WIDTH?=32
+DBUS?=CACHED
+DBUS_LOAD_DATA_WIDTH?=32
+DBUS_STORE_DATA_WIDTH?=32
+TRACE?=no
+TRACE_ACCESS?=no
+TRACE_START=0
+TRACE_SPORADIC?=no
+ISA_TEST?=yes
+MUL?=yes
+DIV?=yes
+RVF?=no
+RVD?=no
+CSR?=yes
+CSR_SKIP_TEST?=no
+EBREAK?=no
+FENCEI?=no
+MMU?=yes
+DBUS_EXCLUSIVE?=no
+DBUS_INVALIDATE?=no
+PMP?=no
+SEED?=no
+LRSC?=no
+AMO?=no
+NO_STALL?=no
+DEBUG_PLUGIN?=STD
+DEBUG_PLUGIN_EXTERNAL?=no
+RUN_HEX=no
+WITH_RISCV_REF=yes
+CUSTOM_SIMD_ADD?=no
+CUSTOM_CSR?=no
+DHRYSTONE=yes
+FREERTOS?=no
+ZEPHYR?=no
+REDO?=10
+REF=no
+TRACE_WITH_TIME=no
+REF_TIME=no
+THREAD_COUNT?=$(shell nproc)
+MTIME_INSTR_FACTOR?=no
+COMPRESSED?=no
+SUPERVISOR?=no
+STOP_ON_ERROR?=no
+COREMARK=no
+WITH_USER_IO?=no
+
+
+ADDCFLAGS += -CFLAGS -DREGRESSION_PATH='\"$(REGRESSION_PATH)/\"'
+ADDCFLAGS += -CFLAGS -DIBUS_${IBUS}
+ADDCFLAGS += -CFLAGS -DIBUS_DATA_WIDTH=${IBUS_DATA_WIDTH}
+ADDCFLAGS += -CFLAGS -DDBUS_LOAD_DATA_WIDTH=${DBUS_LOAD_DATA_WIDTH}
+ADDCFLAGS += -CFLAGS -DDBUS_STORE_DATA_WIDTH=${DBUS_STORE_DATA_WIDTH}
+
+ADDCFLAGS += -CFLAGS -DDBUS_${DBUS}
+ADDCFLAGS += -CFLAGS -DREDO=${REDO}
+ADDCFLAGS += -CFLAGS -pthread
+ADDCFLAGS += -CFLAGS -Wno-unused-result
+
+
+
+ADDCFLAGS += -CFLAGS -DTHREAD_COUNT=${THREAD_COUNT}
+
+ifeq ($(DEBUG),yes)
+ ADDCFLAGS += -CFLAGS -O0 -CFLAGS -g
+else
+ ADDCFLAGS += -CFLAGS -O3 -O3
+endif
+
+ifeq ($(CONCURRENT_OS_EXECUTIONS),yes)
+ ADDCFLAGS += -CFLAGS -DCONCURRENT_OS_EXECUTIONS
+endif
+
+ifeq ($(LITEX),yes)
+ ADDCFLAGS += -CFLAGS -DLITEX
+ ADDCFLAGS += -CFLAGS -DVMLINUX='\"$(VMLINUX)\"'
+ ADDCFLAGS += -CFLAGS -DDTB='\"$(DTB)\"'
+ ADDCFLAGS += -CFLAGS -DRAMDISK='\"$(RAMDISK)\"'
+ ADDCFLAGS += -CFLAGS -DEMULATOR='\"$(EMULATOR)\"'
+endif
+
+ifeq ($(LINUX_SOC),yes)
+ ADDCFLAGS += -CFLAGS -DLINUX_SOC
+ ADDCFLAGS += -CFLAGS -DVMLINUX='\"$(VMLINUX)\"'
+ ADDCFLAGS += -CFLAGS -DDTB='\"$(DTB)\"'
+ ADDCFLAGS += -CFLAGS -DRAMDISK='\"$(RAMDISK)\"'
+ ADDCFLAGS += -CFLAGS -DEMULATOR='\"$(EMULATOR)\"'
+endif
+
+ifeq ($(LINUX_SOC_SMP),yes)
+ ADDCFLAGS += -CFLAGS -DLINUX_SOC_SMP
+ ADDCFLAGS += -CFLAGS -DVMLINUX='\"$(VMLINUX)\"'
+ ADDCFLAGS += -CFLAGS -DDTB='\"$(DTB)\"'
+ ADDCFLAGS += -CFLAGS -DRAMDISK='\"$(RAMDISK)\"'
+ ADDCFLAGS += -CFLAGS -DEMULATOR='\"$(EMULATOR)\"'
+endif
+
+
+ARCH_LINUX=rv32i
+ifeq ($(MUL),yes)
+ifeq ($(DIV),yes)
+ARCH_LINUX:=$(ARCH_LINUX)m
+endif
+endif
+ARCH_LINUX:=$(ARCH_LINUX)a
+ifeq ($(COMPRESSED),yes)
+ARCH_LINUX:=$(ARCH_LINUX)c
+endif
+
+ifeq ($(LINUX_REGRESSION),yes)
+ifneq ($(ARCH_LINUX),rv32iac)
+ifneq ($(ARCH_LINUX),rv32ia)
+ ADDCFLAGS += -CFLAGS -DLINUX_REGRESSION
+ ADDCFLAGS += -CFLAGS -DARCH_LINUX='\"$(ARCH_LINUX)\"'
+ ADDCFLAGS += -CFLAGS -DVMLINUX='\"../../resources/VexRiscvRegressionData/sim/linux/$(ARCH_LINUX)/Image\"'
+ ADDCFLAGS += -CFLAGS -DDTB='\"../../resources/VexRiscvRegressionData/sim/linux/$(ARCH_LINUX)/rv32.dtb\"'
+ ADDCFLAGS += -CFLAGS -DRAMDISK='\"../../resources/VexRiscvRegressionData/sim/linux/$(ARCH_LINUX)/rootfs.cpio\"'
+ ADDCFLAGS += -CFLAGS -DEMULATOR='\"../../resources/VexRiscvRegressionData/sim/linux/emulator/emulator.bin\"'
+endif
+endif
+endif
+
+
+ifeq ($(FLOW_INFO),yes)
+ ADDCFLAGS += -CFLAGS -DFLOW_INFO
+endif
+
+
+ifeq ($(COREMARK),yes)
+ ADDCFLAGS += -CFLAGS -DCOREMARK
+endif
+
+ifeq ($(WITH_RISCV_REF),yes)
+ ADDCFLAGS += -CFLAGS -DWITH_RISCV_REF
+endif
+
+
+
+ifneq ($(shell grep timerInterrupt ${VEXRISCV_FILE} -w),)
+ ADDCFLAGS += -CFLAGS -DTIMER_INTERRUPT
+endif
+
+ifneq ($(shell grep externalInterrupt ${VEXRISCV_FILE} -w),)
+ifneq ($(EXTERNAL_INTERRUPT),no)
+ ADDCFLAGS += -CFLAGS -DEXTERNAL_INTERRUPT
+endif
+endif
+
+ifneq ($(shell grep utime ${VEXRISCV_FILE} -w),)
+ ADDCFLAGS += -CFLAGS -DUTIME_INPUT
+endif
+
+ifneq ($(shell grep dBus_rsp_payload_aggregated ${VEXRISCV_FILE} -w),)
+ ADDCFLAGS += -CFLAGS -DDBUS_AGGREGATION
+endif
+
+
+ifneq ($(RUN_HEX),no)
+ ADDCFLAGS += -CFLAGS -DRUN_HEX='\"$(RUN_HEX)\"'
+endif
+
+
+ifeq ($(IBUS_TC),yes)
+ ADDCFLAGS += -CFLAGS -DIBUS_TC=yes
+endif
+ifeq ($(WITH_USER_IO),yes)
+ ADDCFLAGS += -CFLAGS -DWITH_USER_IO=yes
+endif
+
+
+ifeq ($(COMPRESSED),yes)
+ ADDCFLAGS += -CFLAGS -DCOMPRESSED
+endif
+ifeq ($(SUPERVISOR),yes)
+ ADDCFLAGS += -CFLAGS -DSUPERVISOR
+endif
+ifeq ($(FENCEI),yes)
+ ADDCFLAGS += -CFLAGS -DFENCEI
+endif
+
+ifeq ($(EBREAK),yes)
+ ADDCFLAGS += -CFLAGS -DEBREAK
+endif
+
+
+ifeq ($(DHRYSTONE),yes)
+ ADDCFLAGS += -CFLAGS -DDHRYSTONE
+endif
+
+ifeq ($(STOP_ON_ERROR),yes)
+ ADDCFLAGS += -CFLAGS -DSTOP_ON_ERROR
+endif
+
+
+ifeq ($(NO_STALL),yes)
+ ADDCFLAGS += -CFLAGS -DSTALL=0
+else
+ ADDCFLAGS += -CFLAGS -DSTALL=1
+endif
+
+ifneq ($(MTIME_INSTR_FACTOR),no)
+ ADDCFLAGS += -CFLAGS -DMTIME_INSTR_FACTOR=${MTIME_INSTR_FACTOR}
+endif
+
+ifneq ($(SEED),no)
+ ADDCFLAGS += -CFLAGS -DSEED=${SEED}
+endif
+
+ifeq ($(TRACE),yes)
+ VERILATOR_ARGS += --trace-fst
+ ADDCFLAGS += -CFLAGS -DTRACE
+endif
+
+ifeq ($(TRACE_SPORADIC),yes)
+ ADDCFLAGS += -CFLAGS -DTRACE_SPORADIC
+endif
+
+
+
+ifeq ($(CSR),yes)
+ ADDCFLAGS += -CFLAGS -DCSR
+endif
+
+ifeq ($(CSR_SKIP_TEST),yes)
+ ADDCFLAGS += -CFLAGS -DCSR_SKIP_TEST
+endif
+
+
+ifeq ($(LRSC),yes)
+ ADDCFLAGS += -CFLAGS -DLRSC
+endif
+
+ifeq ($(AMO),yes)
+ ADDCFLAGS += -CFLAGS -DAMO
+endif
+
+ifeq ($(CUSTOM_SIMD_ADD),yes)
+ ADDCFLAGS += -CFLAGS -DCUSTOM_SIMD_ADD
+endif
+
+ifeq ($(CUSTOM_CSR),yes)
+ ADDCFLAGS += -CFLAGS -DCUSTOM_CSR
+endif
+
+ifeq ($(TRACE_WITH_TIME),yes)
+ ADDCFLAGS += -CFLAGS -DTRACE_WITH_TIME
+endif
+
+ifeq ($(REF_TIME),yes)
+ ADDCFLAGS += -CFLAGS -DREF_TIME
+endif
+
+ifeq ($(ISA_TEST),yes)
+ ADDCFLAGS += -CFLAGS -DISA_TEST
+endif
+
+ifeq ($(MMU),yes)
+ ADDCFLAGS += -CFLAGS -DMMU
+endif
+
+ifeq ($(DBUS_EXCLUSIVE),yes)
+ ADDCFLAGS += -CFLAGS -DDBUS_EXCLUSIVE
+endif
+ifeq ($(DBUS_INVALIDATE),yes)
+ ADDCFLAGS += -CFLAGS -DDBUS_INVALIDATE
+endif
+
+ifeq ($(PMP),yes)
+ ADDCFLAGS += -CFLAGS -DPMP
+endif
+
+ifeq ($(MUL),yes)
+ ADDCFLAGS += -CFLAGS -DMUL
+endif
+
+ifeq ($(RVF),yes)
+ ADDCFLAGS += -CFLAGS -DRVF
+endif
+
+ifeq ($(RVD),yes)
+ ADDCFLAGS += -CFLAGS -DRVD
+endif
+
+ifeq ($(DIV),yes)
+ ADDCFLAGS += -CFLAGS -DDIV
+endif
+
+ifeq ($(TRACE_ACCESS),yes)
+ ADDCFLAGS += -CFLAGS -DTRACE_ACCESS
+endif
+
+ifneq ($(DEBUG_PLUGIN),no)
+ ADDCFLAGS += -CFLAGS -DDEBUG_PLUGIN
+ ADDCFLAGS += -CFLAGS -DDEBUG_PLUGIN_${DEBUG_PLUGIN}
+endif
+
+ifeq ($(DEBUG_PLUGIN_EXTERNAL),yes)
+ ADDCFLAGS += -CFLAGS -DDEBUG_PLUGIN_EXTERNAL
+endif
+
+ifeq ($(REF),yes)
+ ADDCFLAGS += -CFLAGS -DREF
+endif
+
+ADDCFLAGS += -CFLAGS -DTRACE_START=${TRACE_START}
+ifeq ($(FREERTOS),yes)
+ ADDCFLAGS += -CFLAGS -DFREERTOS
+ ADDCFLAGS += -CFLAGS -DFREERTOS_COUNT=99999
+else
+ifneq ($(FREERTOS),no)
+ ADDCFLAGS += -CFLAGS -DFREERTOS
+ ADDCFLAGS += -CFLAGS -DFREERTOS_COUNT=$(FREERTOS)
+endif
+endif
+
+
+ifeq ($(ZEPHYR),yes)
+ ADDCFLAGS += -CFLAGS -DZEPHYR
+ ADDCFLAGS += -CFLAGS -DZEPHYR_COUNT=99999
+else
+ifneq ($(ZEPHYR),no)
+ ADDCFLAGS += -CFLAGS -DZEPHYR
+ ADDCFLAGS += -CFLAGS -DZEPHYR_COUNT=$(ZEPHYR)
+endif
+endif
+
+all: clean run
+
+run: compile
+ ./obj_dir/VVexRiscv
+
+verilate: ${VEXRISCV_FILE}
+ cp ${VEXRISCV_FILE}*.bin . | true
+ verilator -cc ${VEXRISCV_FILE} -O3 -CFLAGS -std=c++11 -LDFLAGS -pthread ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-UNOPTFLAT -Wno-WIDTH --x-assign unique --exe main.cpp
+
+compile: verilate
+ make -j${THREAD_COUNT} -C obj_dir/ -f VVexRiscv.mk VVexRiscv
+
+clean:
+ rm -rf obj_dir
+
diff --git a/VexRiscv/src/test/cpp/regression/prediction.gtkw b/VexRiscv/src/test/cpp/regression/prediction.gtkw
new file mode 100644
index 0000000..8abfdd9
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/prediction.gtkw
@@ -0,0 +1,43 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Mon Jan 29 13:38:19 2018
+[*]
+[dumpfile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/dhrystoneO3M.vcd"
+[dumpfile_mtime] "Mon Jan 29 13:37:19 2018"
+[dumpfile_size] 1215443558
+[savefile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/prediction.gtkw"
+[timestart] 127017
+[size] 1784 950
+[pos] -383 -155
+*-3.000000 127032 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[sst_width] 400
+[signals_width] 583
+[sst_expanded] 1
+[sst_vpaned_height] 492
+@28
+TOP.VexRiscv.iBus_cmd_valid
+TOP.VexRiscv.decode_arbitration_flushAll
+TOP.VexRiscv.execute_arbitration_flushAll
+TOP.VexRiscv.fetch_arbitration_flushAll
+TOP.VexRiscv.memory_arbitration_flushAll
+TOP.VexRiscv.prefetch_arbitration_flushAll
+TOP.VexRiscv.writeBack_arbitration_flushAll
+TOP.VexRiscv.execute_BranchPlugin_predictionMissmatch
+TOP.VexRiscv.execute_PREDICTION2_confidence[1:0]
+@22
+TOP.VexRiscv.execute_PREDICTION2_source[18:0]
+TOP.VexRiscv.execute_PREDICTION2_target[31:0]
+@28
+TOP.VexRiscv.execute_PREDICTION_HIT2
+TOP.VexRiscv.execute_PREDICTION_WRITE_HAZARD2
+@23
+TOP.VexRiscv.execute_PC[31:0]
+@28
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_valid
+@22
+TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_payload[31:0]
+@29
+TOP.VexRiscv.execute_arbitration_isFiring
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/refDiff.gtkw b/VexRiscv/src/test/cpp/regression/refDiff.gtkw
new file mode 100644
index 0000000..5be0db4
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/refDiff.gtkw
@@ -0,0 +1,40 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Fri Mar 17 18:05:14 2017
+[*]
+[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/DhrystoneRef.vcd"
+[dumpfile_mtime] "Fri Mar 17 18:03:52 2017"
+[dumpfile_size] 1483111421
+[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/refDiff.gtkw"
+[timestart] 36700
+[size] 1774 451
+[pos] -775 -353
+*-2.000000 36713 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[treeopen] TOP.VexRiscv.
+[sst_width] 201
+[signals_width] 583
+[sst_expanded] 1
+[sst_vpaned_height] 68
+@22
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_address[4:0]
+@24
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_data[31:0]
+@28
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_valid
+TOP.VexRiscv.writeBack_arbitration_isValid
+TOP.VexRiscv.clk
+@22
+TOP.VexRiscv.core.writeBack_inInst_payload_instruction[31:0]
+TOP.VexRiscv.core.writeBack_inInst_payload_pcPlus4[31:0]
+TOP.dCmd_payload_address[31:0]
+TOP.dCmd_payload_data[31:0]
+@28
+TOP.dCmd_payload_size[1:0]
+TOP.dCmd_payload_wr
+TOP.dCmd_ready
+TOP.dCmd_valid
+@25
+TOP.dRsp_data[31:0]
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/wrongDiff.gtkw b/VexRiscv/src/test/cpp/regression/wrongDiff.gtkw
new file mode 100644
index 0000000..29d111c
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/wrongDiff.gtkw
@@ -0,0 +1,62 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Sat Mar 18 09:49:22 2017
+[*]
+[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/DhrystoneWrong.vcd"
+[dumpfile_mtime] "Sat Mar 18 08:08:53 2017"
+[dumpfile_size] 1450277049
+[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/wrongDiff.gtkw"
+[timestart] 37402
+[size] 1774 476
+[pos] -1 475
+*-2.000000 37407 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[treeopen] TOP.VexRiscv.
+[sst_width] 201
+[signals_width] 583
+[sst_expanded] 1
+[sst_vpaned_height] 112
+@28
+TOP.VexRiscv.fetch_arbitration_isStuck
+TOP.VexRiscv.decode_arbitration_isStuck
+TOP.VexRiscv.execute_arbitration_isStuck
+TOP.VexRiscv.memory_arbitration_isStuck
+TOP.VexRiscv.writeBack_arbitration_isStuck
+TOP.VexRiscv.prefetch_arbitration_isValid
+TOP.VexRiscv.fetch_arbitration_isValid
+@29
+TOP.VexRiscv.decode_arbitration_isValid
+@28
+TOP.VexRiscv.execute_arbitration_isValid
+TOP.VexRiscv.memory_arbitration_isValid
+TOP.VexRiscv.writeBack_arbitration_isValid
+@22
+TOP.VexRiscv.writeBack_input_PC[31:0]
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_address[4:0]
+@24
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_data[31:0]
+@28
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_valid
+TOP.VexRiscv.writeBack_arbitration_isValid
+TOP.VexRiscv.clk
+TOP.dCmd_valid
+TOP.dCmd_ready
+TOP.dCmd_payload_wr
+TOP.dCmd_payload_size[1:0]
+@22
+TOP.dCmd_payload_address[31:0]
+TOP.dCmd_payload_data[31:0]
+@24
+TOP.dRsp_data[31:0]
+@22
+TOP.VexRiscv.execute_input_PC[31:0]
+TOP.VexRiscv.execute_input_INSTRUCTION[31:0]
+@28
+TOP.VexRiscv.fetch_arbitration_removeIt
+TOP.VexRiscv.decode_arbitration_removeIt
+TOP.VexRiscv.execute_arbitration_removeIt
+TOP.VexRiscv.memory_arbitration_removeIt
+TOP.VexRiscv.writeBack_arbitration_removeIt
+TOP.VexRiscv.execute_arbitration_isValid
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/VexRiscv/src/test/cpp/regression/yolo.gtkw b/VexRiscv/src/test/cpp/regression/yolo.gtkw
new file mode 100644
index 0000000..66b5bbc
--- /dev/null
+++ b/VexRiscv/src/test/cpp/regression/yolo.gtkw
@@ -0,0 +1,84 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Tue Mar 14 21:27:40 2017
+[*]
+[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/rv32ui-p-lw.vcd"
+[dumpfile_mtime] "Tue Mar 14 21:24:45 2017"
+[dumpfile_size] 1017741
+[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/yolo.gtkw"
+[timestart] 41
+[size] 1776 953
+[pos] -1 -1
+*-1.801840 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] TOP.
+[sst_width] 418
+[signals_width] 559
+[sst_expanded] 1
+[sst_vpaned_height] 279
+@28
+TOP.clk
+TOP.dCmd_valid
+TOP.dCmd_ready
+TOP.dCmd_payload_wr
+@22
+TOP.dCmd_payload_address[31:0]
+TOP.dCmd_payload_data[31:0]
+@28
+TOP.dCmd_payload_size[1:0]
+@23
+TOP.dRsp_data[31:0]
+@22
+TOP.iCmd_payload_pc[31:0]
+@28
+TOP.iCmd_ready
+TOP.iCmd_valid
+@22
+TOP.iRsp_inst[31:0]
+@28
+TOP.reset
+TOP.clk
+TOP.iCmd_valid
+@22
+TOP.iCmd_payload_pc[31:0]
+@28
+TOP.iCmd_ready
+@22
+TOP.iRsp_inst[31:0]
+@28
+TOP.reset
+TOP.VexRiscv.writeBack_arbitration_isValid
+@22
+TOP.VexRiscv.writeBack_input_INSTRUCTION[31:0]
+TOP.VexRiscv.writeBack_input_PC[31:0]
+@28
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_valid
+@22
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_address[4:0]
+TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_data[31:0]
+@28
+TOP.VexRiscv.prefetch_arbitration_isValid
+TOP.VexRiscv.fetch_arbitration_isValid
+TOP.VexRiscv.decode_arbitration_isValid
+TOP.VexRiscv.execute_arbitration_isValid
+TOP.VexRiscv.memory_arbitration_isValid
+TOP.VexRiscv.writeBack_arbitration_isValid
+TOP.VexRiscv.prefetch_arbitration_isStuck
+TOP.VexRiscv.fetch_arbitration_isStuck
+TOP.VexRiscv.decode_arbitration_isStuck
+TOP.VexRiscv.execute_arbitration_isStuck
+TOP.VexRiscv.memory_arbitration_isStuck
+TOP.VexRiscv.writeBack_arbitration_isStuck
+@22
+TOP.VexRiscv.prefetch_input_PC[31:0]
+TOP.VexRiscv.fetch_input_PC[31:0]
+TOP.VexRiscv.decode_input_PC[31:0]
+TOP.VexRiscv.execute_input_PC[31:0]
+TOP.VexRiscv.memory_input_PC[31:0]
+TOP.VexRiscv.writeBack_input_PC[31:0]
+TOP.VexRiscv.fetch_input_INSTRUCTION[31:0]
+TOP.VexRiscv.decode_input_INSTRUCTION[31:0]
+TOP.VexRiscv.execute_input_INSTRUCTION[31:0]
+TOP.VexRiscv.memory_input_INSTRUCTION[31:0]
+TOP.VexRiscv.writeBack_input_INSTRUCTION[31:0]
+[pattern_trace] 1
+[pattern_trace] 0