Update lowrisc_ibex to lowRISC/ibex@4c813a0
Update code from upstream repository
https://github.com/lowRISC/ibex.git to revision
4c813a0422091d3c0f82df16eb28d2c746c36218
* [ibex/dv] Update OVPsim to use 34-bit address range (Udi)
* [rtl] remove lsu_req_in_id signal (Greg Chadwick)
* [doc] Fix table rendering in README (Greg Chadwick)
* [ibex/ml] Update the ML testlist (Udi)
* [ibex] Update CSR description of cpuctrl/secureseed (Udi)
* [syn] Use latch-based register file in yosys (Tom Roberts)
* [ibex/dv] Update Ibex PMP tests (Udi)
* Update google_riscv-dv to google/riscv-dv@61755c0 (Udi)
* [ibex/rtl] Fix pmpaddr write enable signal (Udi)
* Set `FPGA_XILINX` define whenever Vivado is used (Pirmin Vogel)
* [doc] Update FPGA Synthesis Paragraph in Intro (ganoam)
* Fix typo in examples/sw/benchmarks/README.md (Yuichi Sugiyama)
* Add myself to CREDITS.md (ganoam)
* Remove Verible lint workaround (Philipp Wagner)
* [dv] Add custom CSRs to yaml description file (Pirmin Vogel)
* [dv/ibex] Update CSR listings (Udi)
* Update google_riscv-dv to google/riscv-dv@3cf691d (Udi)
* Properly vendor in mem_model from OpenTitan (Rupert Swarbrick)
* Update lowrisc_ip to lowRISC/opentitan@067272a2 (Rupert Swarbrick)
* Track mem_err_shift better in the ICache scoreboard (Rupert
Swarbrick)
* Minor rejigs to Makefile dvsim wrapper (Rupert Swarbrick)
* Remove duplicated files from dv/uvm/core_ibex/common/utils (Rupert
Swarbrick)
* Define an Ibex-specific top_pkg core (Rupert Swarbrick)
* [dvsim] Print a more helpful path to coverage dashboard (Rupert
Swarbrick)
* [dv] Fix typos (Pirmin Vogel)
* [dv/ibex] Enhance riscv_debug_single_step test (Udi)
* [rtl] Make sure decoder also checks bits 26 and 25 for slli, srli,
srai (Pirmin Vogel)
* [rtl] Add security hardened PC (Tom Roberts)
* [dv/ibex] Switch to request/response terminology (Udi)
* [rtl] Add register-file ECC checking (Tom Roberts)
* [rtl] Add alert outputs (Tom Roberts)
* [params] Add SecureIbex option to simple system (Tom Roberts)
Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
diff --git a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
index 438612e..4e151ef 100644
--- a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
+++ b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
@@ -131,6 +131,13 @@
.esc_tx_i
);
+ // Alert outputs
+ // TODO - Wire these up once driven
+ logic alert_minor, alert_major;
+ logic unused_alert_minor, unused_alert_major;
+ assign unused_alert_minor = alert_minor;
+ assign unused_alert_major = alert_major;
+
ibex_core #(
.PMPEnable ( PMPEnable ),
.PMPGranularity ( PMPGranularity ),
@@ -209,6 +216,8 @@
`endif
.fetch_enable_i,
+ .alert_minor_o (alert_minor),
+ .alert_major_o (alert_major),
.core_sleep_o
);
diff --git a/hw/vendor/lowrisc_ibex.lock.hjson b/hw/vendor/lowrisc_ibex.lock.hjson
index 443ebf6..1adb826 100644
--- a/hw/vendor/lowrisc_ibex.lock.hjson
+++ b/hw/vendor/lowrisc_ibex.lock.hjson
@@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/lowRISC/ibex.git
- rev: 6b9165fa66b49534226acfcb739f2c252be4853c
+ rev: 4c813a0422091d3c0f82df16eb28d2c746c36218
}
}
diff --git a/hw/vendor/lowrisc_ibex/CREDITS.md b/hw/vendor/lowrisc_ibex/CREDITS.md
index 9f140a7..f98e690 100644
--- a/hw/vendor/lowrisc_ibex/CREDITS.md
+++ b/hw/vendor/lowrisc_ibex/CREDITS.md
@@ -29,6 +29,7 @@
- Michael Schaffner
- Nils Graf
- Noah Huesser
+- Noam Gallmann
- Pasquale Davide Schiavone
- Philipp Wagner
- Pirmin Vogel
diff --git a/hw/vendor/lowrisc_ibex/README.md b/hw/vendor/lowrisc_ibex/README.md
index 7cdbbdb..29b7d5b 100644
--- a/hw/vendor/lowrisc_ibex/README.md
+++ b/hw/vendor/lowrisc_ibex/README.md
@@ -20,13 +20,13 @@
The table below indicates performance, area and verification status for a few selected configurations.
These are configurations on which lowRISC is focusing for performance evaluation and design verification (see [supported configs](ibex_configs.yaml)).
-| Config | "small" | "maxperf" | "maxperf-pmp-bmfull" |
-| ------ | ------- | --------- | ---------------- |
-| Features | RV32IMC, 3 cycle mult | RV32IMC, 1 cycle mult, Branch target ALU, Writeback stage | RV32IMCB, 1 cycle mult, Branch target ALU, Writeback stage, 16 PMP regions |
-| Performance (CoreMark/MHz) | 2.47 | 3.13 | 3.05 |
-| Area - Yosys (kGE) | 33.15 | 39.03 | 63.32 |
-| Area - Commercial (estimated kGE) | ~27 | ~31 | ~50 |
-| Verification status | Green | Amber | Amber |
+| Config | "micro" | "small" | "maxperf" | "maxperf-pmp-bmfull" |
+| ------ | ------- | --------| ----------| -------------------- |
+| Features | RV32EC | RV32IMC, 3 cycle mult | RV32IMC, 1 cycle mult, Branch target ALU, Writeback stage | RV32IMCB, 1 cycle mult, Branch target ALU, Writeback stage, 16 PMP regions |
+| Performance (CoreMark/MHz) | 0.904 | 2.47 | 3.13 | 3.05 |
+| Area - Yosys (kGE) | 17.44 | 26.06 | 35.64 | 58.74 |
+| Area - Commercial (estimated kGE) | ~16 | ~24 | ~33 | ~54 |
+| Verification status | Red | Green | Amber | Amber |
Notes:
@@ -34,12 +34,13 @@
Note that different ISAs (use of B and C extensions) give the best results for different configurations.
See the [Benchmarks README](examples/sw/benchmarks/README.md) for more information.
The "maxperf-pmp-bmfull" configuration sets a `SpecBranch` parameter in `ibex_core.sv`; this helps timing but has a small negative performance impact.
-* Yosys synthesis area numbers are based on the Ibex basic synthesis [flow](syn/README.md).
+* Yosys synthesis area numbers are based on the Ibex basic synthesis [flow](syn/README.md) using the latch-based register file.
* Commercial synthesis area numbers are a rough estimate of what might be achievable with a commercial synthesis flow and technology library.
+* For comparison, the original "Zero-riscy" core yields an area of 23.14kGE using our Yosys synthesis flow.
* Verification status is a rough guide to the overall maturity of a particular configuration.
Green indicates that verification is close to complete.
Amber indicates that some verification has been performed, but the configuration is still experimental.
- Red indicates a new configuration with minimal/no verification.
+ Red indicates a configuration with minimal/no verification.
Users must make their own assessment of verification readiness for any tapeout.
## Documentation
diff --git a/hw/vendor/lowrisc_ibex/azure-pipelines.yml b/hw/vendor/lowrisc_ibex/azure-pipelines.yml
index 3968949..31c90aa 100644
--- a/hw/vendor/lowrisc_ibex/azure-pipelines.yml
+++ b/hw/vendor/lowrisc_ibex/azure-pipelines.yml
@@ -9,7 +9,7 @@
VERILATOR_VERSION: 4.032
RISCV_TOOLCHAIN_TAR_VERSION: 20200323-1
RISCV_COMPLIANCE_GIT_VERSION: 844c6660ef3f0d9b96957991109dfd80cc4938e2
- VERIBLE_VERSION: v0.0-459-g4d6929e
+ VERIBLE_VERSION: v0.0-493-g617b404
trigger:
batch: true
diff --git a/hw/vendor/lowrisc_ibex/doc/integration.rst b/hw/vendor/lowrisc_ibex/doc/integration.rst
index f7233d3..2cfc55c 100644
--- a/hw/vendor/lowrisc_ibex/doc/integration.rst
+++ b/hw/vendor/lowrisc_ibex/doc/integration.rst
@@ -68,6 +68,8 @@
// Special control signals
.fetch_enable_i (),
+ .alert_minor_o (),
+ .alert_major_o (),
.core_sleep_o ()
);
@@ -165,3 +167,16 @@
| | | | if an external event (interrupt or |
| | | | debug req) wakes the core up |
+-------------------------+-------------------------+-----+----------------------------------------+
+| ``alert_minor_o`` | 1 | out | Core has detected a fault which it can |
+| | | | safely recover from. Can be used by a |
+| | | | system to log errors over time and |
+| | | | detect tampering / attack. This signal |
+| | | | is a pulse, one cycle per alert. |
++-------------------------+-------------------------+-----+----------------------------------------+
+| ``alert_major_o`` | 1 | out | Core has detected a fault which cannot |
+| | | | be recovered from. Can be used by a |
+| | | | system to reset the core and possibly |
+| | | | take other remedial action. This |
+| | | | signal is a pulse, but might be set |
+| | | | for multiple cycles per alert. |
++-------------------------+-------------------------+-----+----------------------------------------+
diff --git a/hw/vendor/lowrisc_ibex/doc/introduction.rst b/hw/vendor/lowrisc_ibex/doc/introduction.rst
index a914c5a..ddabe51 100644
--- a/hw/vendor/lowrisc_ibex/doc/introduction.rst
+++ b/hw/vendor/lowrisc_ibex/doc/introduction.rst
@@ -73,13 +73,15 @@
ASIC synthesis is supported for Ibex.
The whole design is completely synchronous and uses positive-edge triggered flip-flops, except for the register file, which can be implemented either with latches or with flip-flops.
See :ref:`register-file` for more details.
-The core occupies an area of roughly 18.9 kGE when using the latch-based register file and implementing the RV32IMC ISA, or 11.6 kGE when implementing the RV32EC ISA.
+The core occupies an area of roughly 24 kGE when using the latch-based register file and implementing the RV32IMC ISA, or 16 kGE when implementing the RV32EC ISA.
FPGA Synthesis
--------------
-FPGA synthesis is supported for Ibex when the flip-flop based register file is used.
-Since latches are not well supported on FPGAs, it is crucial to select the flip-flop based register file.
+FPGA Synthesis is supported for Ibex.
+The FPGA-optimized register file implementation should be used.
+The flip-flop based register file is also compatible with FPGA synthesis, however it may result in significantly higher resource utilization.
+Since latches are not well supported on FPGAs, the latch-based register file should not be used.
Contents
--------
diff --git a/hw/vendor/lowrisc_ibex/doc/security.rst b/hw/vendor/lowrisc_ibex/doc/security.rst
index c21dddd..f45d71a 100644
--- a/hw/vendor/lowrisc_ibex/doc/security.rst
+++ b/hw/vendor/lowrisc_ibex/doc/security.rst
@@ -6,6 +6,13 @@
Ibex implements a set of extra features (when the SecureIbex parameter is set) to support security-critical applications.
All features are runtime configurable via bits in the **cpuctrl** custom CSR.
+Outputs
+-------
+
+Ibex has two alert outputs for signalling security issues.
+The major alert (**alert_major_o**) indicates a critical security issue from which the core cannot recover.
+The minor alert (**alert_minor_o**) indicates potential security issues which can be monitored over time by a system.
+
Data Independent Timing
-----------------------
@@ -44,3 +51,18 @@
The interval between instruction insertion is randomized in the core using an LFSR.
Sofware can periodically re-seed this LFSR with true random numbers (if available) via the **secureseed** CSR.
This will make the insertion interval of dummy instructions much harder for an attacker to predict.
+
+Register file ECC
+-----------------
+
+When Ibex is configured with the SecureIbex parameter, ECC checking is added to all reads of the register file.
+This can be useful to detect fault injection attacks since the register file covers a reasonably large area.
+No attempt is made to correct detected errors, but an external alert is raised for the system to take action.
+
+Hardened PC
+-----------
+
+This adds a check that the PC driven from the IF stage has not been modified.
+A check is asserted that the current IF stage PC equals the previous PC plus the correct increment.
+The check is disabled after branches and after reset.
+If a mismatch is detected, a major alert is signaled.
diff --git a/hw/vendor/lowrisc_ibex/doc/verification.rst b/hw/vendor/lowrisc_ibex/doc/verification.rst
index b5fac5c..073b7d0 100644
--- a/hw/vendor/lowrisc_ibex/doc/verification.rst
+++ b/hw/vendor/lowrisc_ibex/doc/verification.rst
@@ -46,8 +46,8 @@
Memory Model
""""""""""""
-The code can be found in the
-`dv/uvm/core_ibex/common/mem_model <https://github.com/lowRISC/ibex/tree/master/dv/uvm/core_ibex/common/mem_model>`_
+The code is vendored from OpenTitan and can be found in the
+`vendor/lowrisc_ip/mem_model <https://github.com/lowRISC/ibex/tree/master/vendor/lowrisc_ip/mem_model>`_
directory.
The testbench instantiates a single instance of this memory model that it loads the compiled
assembly test program into at the beginning of each test.
diff --git a/hw/vendor/lowrisc_ibex/examples/fpga/artya7/rtl/top_artya7.sv b/hw/vendor/lowrisc_ibex/examples/fpga/artya7/rtl/top_artya7.sv
index 6949fd3..37304b4 100644
--- a/hw/vendor/lowrisc_ibex/examples/fpga/artya7/rtl/top_artya7.sv
+++ b/hw/vendor/lowrisc_ibex/examples/fpga/artya7/rtl/top_artya7.sv
@@ -81,6 +81,8 @@
.debug_req_i ('b0),
.fetch_enable_i ('b1),
+ .alert_minor_o (),
+ .alert_major_o (),
.core_sleep_o ()
);
diff --git a/hw/vendor/lowrisc_ibex/examples/fpga/artya7/top_artya7.core b/hw/vendor/lowrisc_ibex/examples/fpga/artya7/top_artya7.core
index cfa1a33..811fb93 100644
--- a/hw/vendor/lowrisc_ibex/examples/fpga/artya7/top_artya7.core
+++ b/hw/vendor/lowrisc_ibex/examples/fpga/artya7/top_artya7.core
@@ -31,12 +31,6 @@
default: "../../../../../examples/sw/led/led.vmem"
paramtype: vlogparam
- FPGA_XILINX:
- datatype: str
- description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters.
- default: 1
- paramtype: vlogdefine
-
# For value definition, please see ip/prim/rtl/prim_pkg.sv
PRIM_DEFAULT_IMPL:
datatype: str
@@ -52,7 +46,6 @@
toplevel: top_artya7
parameters:
- SRAMInitFile
- - FPGA_XILINX
- PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx
tools:
vivado:
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
index 1f56cb8..4e8a93e 100644
--- a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core
@@ -64,6 +64,12 @@
default: 0
description: "Enables third pipeline stage (EXPERIMENTAL)"
+ SecureIbex:
+ datatype: int
+ default: 0
+ paramtype: vlogparam
+ description: "Enables security hardening features (EXPERIMENTAL) [0/1]"
+
PMPEnable:
datatype: int
default: 0
@@ -95,6 +101,7 @@
- MultiplierImplementation
- BranchTargetALU
- WritebackStage
+ - SecureIbex
- PMPEnable
- PMPGranularity
- PMPNumRegions
diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv b/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv
index 06291ab..f4c630e 100644
--- a/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv
+++ b/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv
@@ -23,6 +23,7 @@
input IO_RST_N
);
+ parameter bit SecureIbex = 1'b0;
parameter bit PMPEnable = 1'b0;
parameter int unsigned PMPGranularity = 0;
parameter int unsigned PMPNumRegions = 4;
@@ -146,6 +147,7 @@
);
ibex_core_tracing #(
+ .SecureIbex ( SecureIbex ),
.PMPEnable ( PMPEnable ),
.PMPGranularity ( PMPGranularity ),
.PMPNumRegions ( PMPNumRegions ),
@@ -194,6 +196,8 @@
.debug_req_i ('b0),
.fetch_enable_i ('b1),
+ .alert_minor_o (),
+ .alert_major_o (),
.core_sleep_o ()
);
diff --git a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/README.md b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/README.md
index 1ed303c..d2ad4a7 100644
--- a/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/README.md
+++ b/hw/vendor/lowrisc_ibex/examples/sw/benchmarks/README.md
@@ -68,7 +68,7 @@
passing the desired ISA string into `RV_ISA` when invoking make.
```
-make -C ./examples/sw/bencharmsk/coremark clean
+make -C ./examples/sw/benchmarks/coremark clean
make -C ./examples/sw/benchmarks/coremark RV_ISA=rv32imc
```
diff --git a/hw/vendor/lowrisc_ibex/ibex_core.core b/hw/vendor/lowrisc_ibex/ibex_core.core
index dce96f4..836b274 100644
--- a/hw/vendor/lowrisc_ibex/ibex_core.core
+++ b/hw/vendor/lowrisc_ibex/ibex_core.core
@@ -60,6 +60,12 @@
datatype: bool
paramtype: vlogdefine
+ FPGA_XILINX:
+ datatype: bool
+ description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters.
+ default: false
+ paramtype: vlogdefine
+
RV32E:
datatype: int
default: 0
@@ -138,6 +144,8 @@
- files_rtl
- files_check_tool_requirements
toplevel: ibex_core
+ parameters:
+ - tool_vivado ? (FPGA_XILINX=true)
lint:
<<: *default_target
parameters:
diff --git a/hw/vendor/lowrisc_ibex/lint/verible_waiver.vbw b/hw/vendor/lowrisc_ibex/lint/verible_waiver.vbw
index bc0cfee..8ed90c5 100644
--- a/hw/vendor/lowrisc_ibex/lint/verible_waiver.vbw
+++ b/hw/vendor/lowrisc_ibex/lint/verible_waiver.vbw
@@ -1 +1 @@
-waive --rule=module-filename --regex=".*" --location="ibex_register_file_.+"
+waive --rule=module-filename --location="ibex_register_file_.+"
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
index 2bbc373..832a03b 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
@@ -90,7 +90,6 @@
input logic csr_mstatus_tw_i,
// stall & flush signals
- input logic lsu_req_in_id_i,
input logic stall_id_i,
input logic stall_wb_i,
output logic flush_id_o,
@@ -510,11 +509,11 @@
// If entering debug mode or handling an IRQ the core needs to wait
// until the current instruction has finished executing. Stall IF
// during that time.
- if ((enter_debug_mode || handle_irq) && (stall || lsu_req_in_id_i)) begin
+ if ((enter_debug_mode || handle_irq) && stall) begin
halt_if = 1'b1;
end
- if (!stall && !lsu_req_in_id_i && !special_req_all) begin
+ if (!stall && !special_req_all) begin
if (enter_debug_mode) begin
// enter debug mode
ctrl_fsm_ns = DBG_TAKEN_IF;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
index 6146993..370d1a0 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
@@ -104,6 +104,8 @@
// CPU Control Signals
input logic fetch_enable_i,
+ output logic alert_minor_o,
+ output logic alert_major_o,
output logic core_sleep_o
);
@@ -117,6 +119,8 @@
// by ~3% (based on CoreMark/MHz score).
// Set by default in the max PMP config which has the tightest budget for branch target timing.
localparam bit SpecBranch = PMPEnable & (PMPNumRegions == 16);
+ localparam bit RegFileECC = SecureIbex;
+ localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32;
// IF/ID signals
logic dummy_instr_id;
@@ -144,6 +148,7 @@
logic [31:0] dummy_instr_seed;
logic icache_enable;
logic icache_inval;
+ logic pc_mismatch_alert;
logic instr_first_cycle_id;
logic instr_valid_clear;
@@ -175,6 +180,8 @@
logic [31:0] rf_rdata_a;
logic [4:0] rf_raddr_b;
logic [31:0] rf_rdata_b;
+ logic rf_ren_a;
+ logic rf_ren_b;
logic [4:0] rf_waddr_wb;
logic [31:0] rf_wdata_wb;
// Writeback register write data that can be used on the forwarding path (doesn't factor in memory
@@ -187,6 +194,8 @@
logic [4:0] rf_waddr_id;
logic [31:0] rf_wdata_id;
logic rf_we_id;
+ logic rf_rd_a_wb_match;
+ logic rf_rd_b_wb_match;
// ALU Control
alu_op_e alu_operator_ex;
@@ -334,8 +343,6 @@
logic [31:0] rvfi_mem_wdata_q;
logic [31:0] rvfi_mem_addr_d;
logic [31:0] rvfi_mem_addr_q;
- logic rf_ren_a;
- logic rf_ren_b;
`endif
//////////////////////
@@ -389,7 +396,8 @@
.DmExceptionAddr ( DmExceptionAddr ),
.DummyInstructions ( DummyInstructions ),
.ICache ( ICache ),
- .ICacheECC ( ICacheECC )
+ .ICacheECC ( ICacheECC ),
+ .SecureIbex ( SecureIbex )
) if_stage_i (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
@@ -446,6 +454,7 @@
// pipeline stalls
.id_in_ready_i ( id_in_ready ),
+ .pc_mismatch_alert_o ( pc_mismatch_alert ),
.if_busy_o ( if_busy )
);
@@ -584,13 +593,13 @@
.rf_rdata_a_i ( rf_rdata_a ),
.rf_raddr_b_o ( rf_raddr_b ),
.rf_rdata_b_i ( rf_rdata_b ),
-`ifdef RVFI
.rf_ren_a_o ( rf_ren_a ),
.rf_ren_b_o ( rf_ren_b ),
-`endif
.rf_waddr_id_o ( rf_waddr_id ),
.rf_wdata_id_o ( rf_wdata_id ),
.rf_we_id_o ( rf_we_id ),
+ .rf_rd_a_wb_match_o ( rf_rd_a_wb_match ),
+ .rf_rd_b_wb_match_o ( rf_rd_b_wb_match ),
.rf_waddr_wb_i ( rf_waddr_wb ),
.rf_wdata_fwd_wb_i ( rf_wdata_fwd_wb ),
@@ -747,29 +756,102 @@
.instr_done_wb_o ( instr_done_wb )
);
+ ///////////////////////
+ // Register file ECC //
+ ///////////////////////
+
+ logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc;
+ logic [RegFileDataWidth-1:0] rf_rdata_a_ecc;
+ logic [RegFileDataWidth-1:0] rf_rdata_b_ecc;
+ logic rf_ecc_err_comb;
+
+ if (RegFileECC) begin : gen_regfile_ecc
+
+ logic [1:0] rf_ecc_err_a, rf_ecc_err_b;
+ logic rf_ecc_err_a_id, rf_ecc_err_b_id;
+
+ // ECC checkbit generation for regiter file wdata
+ prim_secded_39_32_enc regfile_ecc_enc (
+ .in (rf_wdata_wb),
+ .out (rf_wdata_wb_ecc)
+ );
+
+ // ECC checking on register file rdata
+ prim_secded_39_32_dec regfile_ecc_dec_a (
+ .in (rf_rdata_a_ecc),
+ .d_o (),
+ .syndrome_o (),
+ .err_o (rf_ecc_err_a)
+ );
+ prim_secded_39_32_dec regfile_ecc_dec_b (
+ .in (rf_rdata_b_ecc),
+ .d_o (),
+ .syndrome_o (),
+ .err_o (rf_ecc_err_b)
+ );
+
+ // Assign read outputs - no error correction, just trigger an alert
+ assign rf_rdata_a = rf_rdata_a_ecc[31:0];
+ assign rf_rdata_b = rf_rdata_b_ecc[31:0];
+
+ // Calculate errors - qualify with WB forwarding to avoid xprop into the alert signal
+ assign rf_ecc_err_a_id = |rf_ecc_err_a & rf_ren_a & ~rf_rd_a_wb_match;
+ assign rf_ecc_err_b_id = |rf_ecc_err_b & rf_ren_b & ~rf_rd_b_wb_match;
+
+ // Combined error
+ assign rf_ecc_err_comb = instr_valid_id & (rf_ecc_err_a_id | rf_ecc_err_b_id);
+
+ end else begin : gen_no_regfile_ecc
+ logic unused_rf_ren_a, unused_rf_ren_b;
+ logic unused_rf_rd_a_wb_match, unused_rf_rd_b_wb_match;
+
+ assign unused_rf_ren_a = rf_ren_a;
+ assign unused_rf_ren_b = rf_ren_b;
+ assign unused_rf_rd_a_wb_match = rf_rd_a_wb_match;
+ assign unused_rf_rd_b_wb_match = rf_rd_b_wb_match;
+ assign rf_wdata_wb_ecc = rf_wdata_wb;
+ assign rf_rdata_a = rf_rdata_a_ecc;
+ assign rf_rdata_b = rf_rdata_b_ecc;
+ assign rf_ecc_err_comb = 1'b0;
+ end
+
ibex_register_file #(
.RV32E (RV32E),
- .DataWidth (32),
+ .DataWidth (RegFileDataWidth),
.DummyInstructions (DummyInstructions)
) register_file_i (
- .clk_i ( clk ),
- .rst_ni ( rst_ni ),
+ .clk_i ( clk_i ),
+ .rst_ni ( rst_ni ),
- .test_en_i ( test_en_i ),
- .dummy_instr_id_i ( dummy_instr_id ),
+ .test_en_i ( test_en_i ),
+ .dummy_instr_id_i ( dummy_instr_id ),
// Read port a
- .raddr_a_i ( rf_raddr_a ),
- .rdata_a_o ( rf_rdata_a ),
+ .raddr_a_i ( rf_raddr_a ),
+ .rdata_a_o ( rf_rdata_a_ecc ),
// Read port b
- .raddr_b_i ( rf_raddr_b ),
- .rdata_b_o ( rf_rdata_b ),
+ .raddr_b_i ( rf_raddr_b ),
+ .rdata_b_o ( rf_rdata_b_ecc ),
// write port
- .waddr_a_i ( rf_waddr_wb ),
- .wdata_a_i ( rf_wdata_wb ),
- .we_a_i ( rf_we_wb )
+ .waddr_a_i ( rf_waddr_wb ),
+ .wdata_a_i ( rf_wdata_wb_ecc ),
+ .we_a_i ( rf_we_wb )
);
+ ///////////////////
+ // Alert outputs //
+ ///////////////////
+
+ // Minor alert - core is in a recoverable state
+ // TODO add I$ ECC errors here
+ assign alert_minor_o = 1'b0;
+
+ // Major alert - core is unrecoverable
+ assign alert_major_o = rf_ecc_err_comb | pc_mismatch_alert;
+
+ `ASSERT_KNOWN(IbexAlertMinorX, alert_minor_o)
+ `ASSERT_KNOWN(IbexAlertMajorX, alert_major_o)
+
// Explict INC_ASSERT block to avoid unused signal lint warnings were asserts are not included
`ifdef INC_ASSERT
// Signals used for assertions only
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv
index e290c35..4fbcde0 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv
@@ -69,6 +69,8 @@
// CPU Control Signals
input logic fetch_enable_i,
+ output logic alert_minor_o,
+ output logic alert_major_o,
output logic core_sleep_o
);
@@ -181,6 +183,8 @@
.rvfi_mem_wdata,
.fetch_enable_i,
+ .alert_minor_o,
+ .alert_major_o,
.core_sleep_o
);
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
index 6e5eaf4..50d1107 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
@@ -825,7 +825,7 @@
// --------------------------
if (i < PMPNumRegions - 1) begin : g_lower
assign pmp_addr_we[i] = csr_we_int & ~pmp_cfg[i].lock &
- (pmp_cfg[i+1].mode != PMP_MODE_TOR) &
+ (~pmp_cfg[i+1].lock | (pmp_cfg[i+1].mode != PMP_MODE_TOR)) &
(csr_addr == (CSR_OFF_PMP_ADDR + i[11:0]));
end else begin : g_upper
assign pmp_addr_we[i] = csr_we_int & ~pmp_cfg[i].lock &
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
index 3b2807e..5788f8d 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv
@@ -348,7 +348,7 @@
3'b001: begin
unique case (instr[31:27])
- 5'b0_0000: illegal_insn = 1'b0; // slli
+ 5'b0_0000: illegal_insn = (instr[26:25] == 2'b00) ? 1'b0 : 1'b1; // slli
5'b0_0100, // sloi
5'b0_1001, // sbclri
5'b0_0101, // sbseti
@@ -385,7 +385,7 @@
end else begin
unique case (instr[31:27])
5'b0_0000, // srli
- 5'b0_1000: illegal_insn = 1'b0; // srai
+ 5'b0_1000: illegal_insn = (instr[26:25] == 2'b00) ? 1'b0 : 1'b1; // srai
5'b0_0100, // sroi
5'b0_1100, // rori
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
index bba4c2a..5e3be70 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
@@ -147,15 +147,15 @@
input logic [31:0] rf_rdata_a_i,
output logic [4:0] rf_raddr_b_o,
input logic [31:0] rf_rdata_b_i,
-`ifdef RVFI
output logic rf_ren_a_o,
output logic rf_ren_b_o,
-`endif
// Register file write (via writeback)
output logic [4:0] rf_waddr_id_o,
output logic [31:0] rf_wdata_id_o,
output logic rf_we_id_o,
+ output logic rf_rd_a_wb_match_o,
+ output logic rf_rd_b_wb_match_o,
// Register write information from writeback (for resolving data hazards)
input logic [4:0] rf_waddr_wb_i,
@@ -206,7 +206,6 @@
logic controller_run;
logic stall_ld_hz;
logic stall_mem;
- logic lsu_req_in_id;
logic stall_multdiv;
logic stall_branch;
logic stall_jump;
@@ -232,10 +231,8 @@
logic rf_we_dec, rf_we_raw;
logic rf_ren_a, rf_ren_b;
-`ifdef RVFI
assign rf_ren_a_o = rf_ren_a;
assign rf_ren_b_o = rf_ren_b;
-`endif
logic [31:0] rf_rdata_a_fwd;
logic [31:0] rf_rdata_b_fwd;
@@ -599,8 +596,6 @@
.debug_ebreaku_i ( debug_ebreaku_i ),
.trigger_match_i ( trigger_match_i ),
- // stall signals
- .lsu_req_in_id_i ( lsu_req_in_id ),
.stall_id_i ( stall_id ),
.stall_wb_i ( stall_wb ),
.flush_id_o ( flush_id ),
@@ -885,13 +880,12 @@
`ASSERT(IbexStallMemNoRequest,
instr_valid_i & lsu_req_dec & ~instr_done |-> ~lsu_req_done_i)
- // Indicate to the controller that an lsu req is in ID stage - we cannot handle interrupts or
- // debug requests until the load/store completes
- assign lsu_req_in_id = instr_valid_i & lsu_req_dec;
-
assign rf_rd_a_wb_match = (rf_waddr_wb_i == rf_raddr_a_o) & |rf_raddr_a_o;
assign rf_rd_b_wb_match = (rf_waddr_wb_i == rf_raddr_b_o) & |rf_raddr_b_o;
+ assign rf_rd_a_wb_match_o = rf_rd_a_wb_match;
+ assign rf_rd_b_wb_match_o = rf_rd_b_wb_match;
+
// If instruction is reading register that load will be writing stall in
// ID until load is complete. No need to stall when reading zero register.
assign rf_rd_a_hz = rf_rd_a_wb_match & rf_ren_a;
@@ -930,7 +924,6 @@
// No load hazards without Writeback Stage
assign stall_ld_hz = 1'b0;
- assign lsu_req_in_id = 1'b0;
// Without writeback stage any valid instruction that hasn't seen an error will execute
assign instr_executing = instr_valid_i & ~instr_fetch_err_i & controller_run;
@@ -943,6 +936,9 @@
assign rf_rdata_a_fwd = rf_rdata_a_i;
assign rf_rdata_b_fwd = rf_rdata_b_i;
+ assign rf_rd_a_wb_match_o = 1'b0;
+ assign rf_rd_b_wb_match_o = 1'b0;
+
// Unused Writeback stage only IO & wiring
// Assign inputs and internal wiring to unused signals to satisfy lint checks
// Tie-off outputs to constant values
@@ -953,7 +949,6 @@
logic unused_outstanding_load_wb;
logic unused_outstanding_store_wb;
logic unused_wb_exception;
- logic unused_rf_ren_a, unused_rf_ren_b;
logic [31:0] unused_rf_wdata_fwd_wb;
assign unused_data_req_done_ex = lsu_req_done_i;
@@ -962,8 +957,6 @@
assign unused_outstanding_load_wb = outstanding_load_wb_i;
assign unused_outstanding_store_wb = outstanding_store_wb_i;
assign unused_wb_exception = wb_exception;
- assign unused_rf_ren_a = rf_ren_a;
- assign unused_rf_ren_b = rf_ren_b;
assign unused_rf_wdata_fwd_wb = rf_wdata_fwd_wb_i;
assign instr_type_wb_o = WB_INSTR_OTHER;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
index dac7836..6b74c2e 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
@@ -17,7 +17,8 @@
parameter int unsigned DmExceptionAddr = 32'h1A110808,
parameter bit DummyInstructions = 1'b0,
parameter bit ICache = 1'b0,
- parameter bit ICacheECC = 1'b0
+ parameter bit ICacheECC = 1'b0,
+ parameter bit SecureIbex = 1'b0
) (
input logic clk_i,
input logic rst_ni,
@@ -83,6 +84,7 @@
input logic id_in_ready_i, // ID stage is ready for new instr
// misc signals
+ output logic pc_mismatch_alert_o,
output logic if_busy_o // IF stage is busy fetching instr
);
@@ -343,6 +345,32 @@
end
end
+ // Check for expected increments of the PC when security hardening enabled
+ if (SecureIbex) begin : g_secure_pc
+ logic [31:0] prev_instr_addr_incr;
+ logic prev_instr_seq_q, prev_instr_seq_d;
+
+ // Do not check for sequential increase after a branch, jump, exception, interrupt or debug
+ // request, all of which will set branch_req. Also do not check after reset.
+ assign prev_instr_seq_d = (prev_instr_seq_q | instr_new_id_d) & ~branch_req;
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ prev_instr_seq_q <= 1'b0;
+ end else begin
+ prev_instr_seq_q <= prev_instr_seq_d;
+ end
+ end
+
+ assign prev_instr_addr_incr = pc_id_o + (instr_is_compressed_id_o ? 32'd2 : 32'd4);
+
+ // Check that the address equals the previous address +2/+4
+ assign pc_mismatch_alert_o = prev_instr_seq_q & (pc_if_o != prev_instr_addr_incr);
+
+ end else begin : g_no_secure_pc
+ assign pc_mismatch_alert_o = 1'b0;
+ end
+
////////////////
// Assertions //
////////////////
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
index 4dd429d..fe42fe9 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
@@ -65,8 +65,8 @@
// With dummy instructions enabled, R0 behaves as a real register but will always return 0 for
// real instructions.
if (DummyInstructions) begin : g_dummy_r0
- logic we_r0_dummy;
- logic [31:0] rf_r0_q;
+ logic we_r0_dummy;
+ logic [DataWidth-1:0] rf_r0_q;
// Write enable for dummy R0 register (waddr_a_i will always be 0 for dummy instructions)
assign we_r0_dummy = we_a_i & dummy_instr_id_i;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
index 7cc4446..0feb7a6 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
@@ -121,9 +121,9 @@
// With dummy instructions enabled, R0 behaves as a real register but will always return 0 for
// real instructions.
if (DummyInstructions) begin : g_dummy_r0
- logic we_r0_dummy;
- logic r0_clock;
- logic [31:0] mem_r0;
+ logic we_r0_dummy;
+ logic r0_clock;
+ logic [DataWidth-1:0] mem_r0;
// Write enable for dummy R0 register (waddr_a_i will always be 0 for dummy instructions)
assign we_r0_dummy = we_a_i & dummy_instr_id_i;
diff --git a/hw/vendor/lowrisc_ibex/syn/README.md b/hw/vendor/lowrisc_ibex/syn/README.md
index d7150d8..ded311e 100644
--- a/hw/vendor/lowrisc_ibex/syn/README.md
+++ b/hw/vendor/lowrisc_ibex/syn/README.md
@@ -98,10 +98,9 @@
* Overall - Every path in the design, WNS (worst negative slack) from this report is the design WNS
that limits the frequency
* reg2reg - Paths from register to register
-* in2x - Paths from an input to any end point, one report is produced per named
- input (e.g. `instr_data_i` has its own report)
-* x2out - Paths from any start point to an output, one report is produced per
- named output (e.g. `data_wdata_o` has its own report)
+* in2reg - Paths from any input to any register
+* reg2out - Paths from any register to any output
+* in2out - Paths from any input to any output
They are available in two formats .rpt and .csv.rpt. The .rpt is the full output
from OpenSTA and gives the full path between the start and end points. The CSV
diff --git a/hw/vendor/lowrisc_ibex/syn/rtl/latch_map.v b/hw/vendor/lowrisc_ibex/syn/rtl/latch_map.v
new file mode 100644
index 0000000..fb1f34d
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/syn/rtl/latch_map.v
@@ -0,0 +1,12 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// Map latch primitives to a specific cell
+module $_DLATCH_P_ (input E, input D, output Q);
+DLH_X1 _TECHMAP_REPLACE_ (
+.G(E),
+.D(D),
+.Q(Q)
+);
+endmodule
diff --git a/hw/vendor/lowrisc_ibex/syn/rtl/prim_clock_gating.v b/hw/vendor/lowrisc_ibex/syn/rtl/prim_clock_gating.v
index ff59172..14d1974 100644
--- a/hw/vendor/lowrisc_ibex/syn/rtl/prim_clock_gating.v
+++ b/hw/vendor/lowrisc_ibex/syn/rtl/prim_clock_gating.v
@@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-// Dummy clock gating module without the clock gate for yosys synthesis
+// Example clock gating module for yosys synthesis
module prim_clock_gating (
input clk_i,
@@ -11,6 +11,13 @@
output clk_o
);
- assign clk_o = clk_i;
+ reg en_latch;
+
+ always @* begin
+ if (!clk_i) begin
+ en_latch = en_i | test_en_i;
+ end
+ end
+ assign clk_o = en_latch & clk_i;
endmodule
diff --git a/hw/vendor/lowrisc_ibex/syn/syn_yosys.sh b/hw/vendor/lowrisc_ibex/syn/syn_yosys.sh
index f730802..071415e 100755
--- a/hw/vendor/lowrisc_ibex/syn/syn_yosys.sh
+++ b/hw/vendor/lowrisc_ibex/syn/syn_yosys.sh
@@ -42,9 +42,9 @@
# remove tracer (not needed for synthesis)
rm -f $LR_SYNTH_OUT_DIR/generated/ibex_tracer.v
-# remove the FPGA & latch-based register file (because we will use the
-# flop-based one instead)
-rm -f $LR_SYNTH_OUT_DIR/generated/ibex_register_file_latch.v
+# remove the FPGA & register-based register file (because we will use the
+# latch-based one instead)
+rm -f $LR_SYNTH_OUT_DIR/generated/ibex_register_file_ff.v
rm -f $LR_SYNTH_OUT_DIR/generated/ibex_register_file_fpga.v
yosys -c ./tcl/yosys_run_synth.tcl | tee ./$LR_SYNTH_OUT_DIR/log/syn.log
diff --git a/hw/vendor/lowrisc_ibex/syn/tcl/lr_synth_flow_var_setup.tcl b/hw/vendor/lowrisc_ibex/syn/tcl/lr_synth_flow_var_setup.tcl
index f1ef0e7..cda1cac 100644
--- a/hw/vendor/lowrisc_ibex/syn/tcl/lr_synth_flow_var_setup.tcl
+++ b/hw/vendor/lowrisc_ibex/syn/tcl/lr_synth_flow_var_setup.tcl
@@ -15,7 +15,7 @@
set_flow_bool_var timing_run 0 "timing run"
set_flow_bool_var ibex_branch_target_alu 0 "Enable branch target ALU in Ibex"
set_flow_bool_var ibex_writeback_stage 0 "Enable writeback stage in Ibex"
-set_flow_bool_var ibex_bitmanip 0 "Enable bitmanip extenion for Ibex"
+set_flow_var ibex_bitmanip 0 "Bitmanip extenion setting for Ibex (0,1,2 - enums not supported)"
set_flow_var ibex_multiplier "fast" "Multiplier implementation for Ibex (slow/fast/single-cycle)"
source $lr_synth_config_file
@@ -25,18 +25,6 @@
#set_flow_var sdc_file "${top_module}.sdc" "SDC file"
set_flow_var sdc_file_in "${lr_synth_top_module}.${lr_synth_cell_library_name}.sdc" "Input SDC file"
set_flow_var abc_sdc_file_in "${lr_synth_top_module}_abc.${lr_synth_cell_library_name}.sdc" "Input SDC file for ABC"
- set flop_in_pin_default "*/D"
- set flop_out_pin_default "*/Q"
-
- # STA needs to know start and end points for identifying reg2reg paths. These
- # can vary depending upon the library used
- if { [string first "nangate" $lr_synth_cell_library_name] == 0 } {
- set flop_in_pin_default "*/D"
- set flop_out_pin_default "*/CK"
- }
-
- set_flow_var flop_in_pin $flop_in_pin_default "In pin to flop for reg2reg path extraction"
- set_flow_var flop_out_pin $flop_out_pin_default "Out pin from flop for reg2reg path extraction"
set sdc_file_out_default [string range $lr_synth_sdc_file_in 0 [expr [string last ".sdc" $lr_synth_sdc_file_in] - 1]]
set sdc_file_out_default "./${lr_synth_out_dir}/generated/$sdc_file_out_default.out.sdc"
@@ -45,7 +33,7 @@
set sta_netlist_out_default [string range $lr_synth_netlist_out 0 [expr [string last ".v" $lr_synth_netlist_out] - 1]]
set sta_netlist_out_default "$sta_netlist_out_default.sta.v"
set_flow_var sta_netlist_out $sta_netlist_out_default "STA netlist out"
- set_flow_var sta_paths_per_group 100 "STA paths reported per group"
+ set_flow_var sta_paths_per_group 1000 "STA paths reported per group"
set_flow_var sta_overall_paths 1000 "STA paths reported in overall report"
puts "clock period: $lr_synth_clk_period ps"
diff --git a/hw/vendor/lowrisc_ibex/syn/tcl/sta_utils.tcl b/hw/vendor/lowrisc_ibex/syn/tcl/sta_utils.tcl
index 38bec70..b7e5bd1 100644
--- a/hw/vendor/lowrisc_ibex/syn/tcl/sta_utils.tcl
+++ b/hw/vendor/lowrisc_ibex/syn/tcl/sta_utils.tcl
@@ -5,37 +5,28 @@
proc setup_path_groups {input_list output_list path_group_list_name} {
upvar $path_group_list_name path_group_list
+ set flops_in [all_registers -edge_triggered -data_pins]
+ set flops_out [all_registers -edge_triggered -clock_pins]
+ group_path -name reg2reg -from $flops_out -to $flops_in
+ lappend path_group_list reg2reg
+
foreach output $output_list {
set output_name [lindex $output 0]
- set output_ports [get_ports $output_name]
- set path_group_name "x2out_${output_name}"
- group_path -name $path_group_name -to $output_ports
- lappend path_group_list $path_group_name
+ lappend outputs_list [get_ports $output_name]
}
+ group_path -name reg2out -from $flops_out -to $outputs_list
+ lappend path_group_list reg2out
foreach input $input_list {
set input_name [lindex $input 0]
- set input_ports [get_ports $input_name]
- set path_group_name "in2x_${input_name}"
- group_path -name $path_group_name -from $input_ports
- lappend path_group_list $path_group_name
+ lappend inputs_list [get_ports $input_name]
}
+ group_path -name in2reg -from $inputs_list -to $flops_in
+ lappend path_group_list in2reg
- global lr_synth_flop_in_pin
- global lr_synth_flop_out_pin
+ group_path -name in2out -from $inputs_list -to $outputs_list
+ lappend path_group_list in2out
- set flops_in [get_pins $lr_synth_flop_in_pin]
- set flops_out [get_pins $lr_synth_flop_out_pin]
-
- group_path -name "reg2reg" -to $flops_in -from $flops_out
- lappend path_group_list "reg2reg"
-}
-
-proc setup_i2o_pathgroup {input_name output_name group_name} {
- set output_ports [get_ports $output_name]
- set input_ports [get_ports $input_name]
-
- group_path -name $group_name -to $output_ports -from $input_ports
}
proc timing_report {path_group rpt_out path_count} {
diff --git a/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl b/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
index 7c63960..7f5bb9b 100644
--- a/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
+++ b/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
@@ -24,15 +24,16 @@
yosys "chparam -set WritebackStage 1 ibex_core"
}
-if { $lr_synth_ibex_bitmanip } {
- yosys "chparam -set RV32B 1 ibex_core"
-}
+yosys "chparam -set RV32B $lr_synth_ibex_bitmanip ibex_core"
yosys "chparam -set MultiplierImplementation \"$lr_synth_ibex_multiplier\" ibex_core"
yosys "synth $flatten_opt -top $lr_synth_top_module"
yosys "opt -purge"
+# Map latch primitives onto latch cells
+yosys "techmap -map rtl/latch_map.v"
+
yosys "write_verilog $lr_synth_pre_map_out"
yosys "dfflibmap -liberty $lr_synth_cell_library_path"
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
index 57ed1a9..446124a 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv.lock.hjson
@@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
- rev: 6cf6b4f389272d8ff5e2b397af43ac6c0dfba2e2
+ rev: 61755c001bec0433fb69458f74d95476d2101cf3
}
}
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.gitignore b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.gitignore
index 4038bdc..232b05e 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.gitignore
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/.gitignore
@@ -12,3 +12,6 @@
*.ucdb
*.vstf
riscv_dv.egg-info
+pygen/pygen_src/test/out/*
+!.gitkeep
+
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/README.md b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/README.md
index 13f8f2a..a4744d6 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/README.md
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/README.md
@@ -83,10 +83,11 @@
## External contributions and collaborations
-This repository is still under active development. We hope the RISC-V processor
-verification platform development to be a collaborative effort of the RISC-V
-community. Free feel to submit issues, feature requests, pull requests through
-Github. You can also send your private collaboration request to [riscv_dv_dev@google.com](riscv_dv_dev@google.com).
+RISC-V DV is now contributed to CHIPS Alliance. We have regular meetings to
+discuss the issues, feature priorities, development progress etc. Please join
+the [mail group](https://lists.chipsalliance.org/g/riscv-dv-wg) for latest
+status.
+
Please refer to CONTRIBUTING.md for license related questions.
## Supporting model
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/cov.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/cov.py
index b49178b..f1ca10b 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/cov.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/cov.py
@@ -53,7 +53,11 @@
build_cmd += (" --custom_target %s" % argv.custom_target)
if argv.stop_on_first_error:
build_cmd += (" --stop_on_first_error")
- run_cmd(build_cmd, debug_cmd = argv.debug)
+ if argv.lsf_cmd != "":
+ build_cmd += (" --lsf_cmd \"%s\"" % argv.lsf_cmd)
+ run_parallel_cmd([build_cmd], argv.timeout, debug_cmd = argv.debug)
+ else:
+ run_cmd(build_cmd, debug_cmd = argv.debug)
def sim_cov(out, cfg, cwd, opts_vec, opts_cov, csv_list):
"""Simulation the coverage collection
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/experimental/README.md b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/experimental/README.md
index 293bd8a..bd37392 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/experimental/README.md
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/experimental/README.md
@@ -13,6 +13,7 @@
```bash
pip3 install python-constraint
pip3 install numpy
+pip3 install bitstring
```
### Generate a simple test
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
index 8392a3c..7c69763 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py
@@ -9,27 +9,27 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-Regression script for RISC-V random instruction generator
"""
-
-
-from collections import defaultdict
-from pygen_src.riscv_instr_gen_config import riscv_instr_gen_config
-from pygen_src.riscv_instr_pkg import riscv_instr_group_t
-from pygen_src.isa import rv32i_instr # NOQA
-import random
-from bitstring import BitArray
import logging
-from copy import copy
+import copy
import sys
+import random
+import os
+import vsc
+from collections import defaultdict
+from bitstring import BitArray
+from pygen_src.riscv_instr_pkg import pkg_ins, riscv_reg_t, riscv_instr_name_t
+from pygen_src.isa import rv32i_instr # NOQA
+from pygen_src.target.rv32i import riscv_core_setting as rcs
+
+logging.basicConfig(filename = os.path.abspath('../test/out/logname.log'), filemode ='w',
+ format = "%(asctime)s %(filename)s %(lineno)s %(levelname)s %(message)s",
+ level = logging.DEBUG)
+@vsc.randobj
class riscv_instr:
-
- logging.basicConfig(level=logging.INFO)
instr_registry = {}
def __init__(self):
@@ -49,13 +49,13 @@
self.imm_type = None
self.imm_len = 0
- self.csr = None
- self.rs2 = None
- self.rs1 = None
- self.rd = None
- self.imm = BitArray(hex="0x00000000")
+ self.csr = vsc.rand_bit_t(12)
+ self.rs2 = vsc.rand_enum_t(riscv_reg_t)
+ self.rs1 = vsc.rand_enum_t(riscv_reg_t)
+ self.rd = vsc.rand_enum_t(riscv_reg_t)
+ self.imm = vsc.rand_bit_t(32)
- self.imm_mask = BitArray(hex="0xffffffff")
+ self.imm_mask = vsc.uint32_t(0xffffffff)
self.is_branch_target = None
self.has_label = 1
self.atomic = 0
@@ -66,20 +66,15 @@
self.is_hint_instr = None
self.is_floating_point = None
self.imm_str = None
- self.comment = None
- self.label = None
+ self.comment = ""
+ self.label = ""
self.is_local_numeric_label = None
self.idx = -1
self.has_rs1 = 1
self.has_rs2 = 1
self.has_rd = 1
self.has_imm = 1
-
- # Fields Added for debugging These fields are actually from a different files.
- self.unsupported_instr = []
- self.XLEN = 32
- self.supported_isa = [riscv_instr_group_t.RV32I]
- self.implemented_csr = []
+ self.shift_t = vsc.uint32_t(0xffffffff)
@classmethod
def register(cls, instr_name):
@@ -94,22 +89,22 @@
self.instr_group.clear()
self.instr_category.clear()
for instr_name, values in self.instr_registry.items():
- if(instr_name in self.unsupported_instr):
+ if(instr_name in rcs.unsupported_instr):
continue
instr_inst = self.create_instr(instr_name)
self.instr_template[instr_name] = instr_inst
if (not instr_inst.is_supported(cfg)):
continue
- if ((self.XLEN != 32) and (instr_name == "C_JAL")):
+ if ((rcs.XLEN != 32) and (instr_name == "C_JAL")):
continue
- if (("SP" in cfg.reserved_regs) and (instr_name == "C_ADDI16SP")):
+ if ((riscv_reg_t.SP in cfg.reserved_regs) and (instr_name == "C_ADDI16SP")):
continue
if (cfg.enable_sfence and instr_name == "SFENCE_VMA"):
continue
if (instr_name in ["FENCE", "FENCE_I", "SFENCE_VMA"]):
continue
- if (instr_inst.group in self.supported_isa and
+ if (instr_inst.group.name in rcs.supported_isa and
not(cfg.disable_compressed_instr and
instr_inst.group in ["RV32C", "RV64C", "RV32DC", "RV32FC", "RV128C"]) and
not(not(cfg.enable_floating_point) and instr_inst.group in
@@ -117,7 +112,6 @@
self.instr_category[instr_inst.category.name].append(instr_name)
self.instr_group[instr_inst.group.name].append(instr_name)
self.instr_names.append(instr_name)
-
self.build_basic_instruction_list(cfg)
self.create_csr_filter(cfg)
@@ -139,8 +133,8 @@
self.instr_category["LOGICAL"] + self.instr_category["COMPARE"])
if(cfg.no_ebreak == 0):
self.basic_instr.append("EBREAK")
- for items in self.supported_isa:
- if("RV32C" in self.supported_isa and not(cfg.disable_compressed_instr)):
+ for items in rcs.supported_isa:
+ if("RV32C" in rcs.supported_isa and not(cfg.disable_compressed_instr)):
self.basic_instr.append("C_EBREAK")
break
if(cfg.no_dret == 0):
@@ -157,7 +151,7 @@
self.exclude_reg.clear()
if(cfg.enable_illegal_csr_instruction):
- self.exclude_reg = self.implemented_csr
+ self.exclude_reg = rcs.implemented_csr
elif(cfg.enable_access_invalid_csr_level):
self.include_reg = cfg.invalid_priv_mode_csrs
else:
@@ -191,36 +185,35 @@
disallowed_instr.extend(exclude_instr)
+ # TODO Randomization logic needs to be frame with PyVSC library
if(len(disallowed_instr) == 0):
- if(len(include_instr) > 0):
- idx = random.randrange(0, len(include_instr) - 1)
- name = include_instr[idx]
- elif(len(allowed_instr > 0)):
- idx = random.randrange(0, len(allowed_instr) - 1)
- name = allowed_instr[idx]
- else:
- idx = random.randrange(0, len(self.instr_names) - 1)
- name = self.instr_names[idx]
- else:
- # TODO
- instr_names_set = set(self.instr_names)
- disallowed_instr_set = set(disallowed_instr)
- allowed_instr_set = set(allowed_instr)
- include_instr_set = set(include_instr)
- excluded_instr_names_list = list(instr_names_set - disallowed_instr_set)
- excluded_allowed_instr_list = list(allowed_instr_set - disallowed_instr_set)
- include_instr_list = list(include_instr_set - disallowed_instr_set)
-
- name = random.choice(excluded_instr_names_list)
- if(len(include_instr) > 0):
- name = random.choice(include_instr_list)
- if(len(allowed_instr) > 0):
- name = random.choice(excluded_allowed_instr_list)
- if(name is None):
- logging.critical("%s Cannot generate random instruction", riscv_instr.__name__)
+ try:
+ if(len(include_instr) > 0):
+ idx = random.randrange(0, len(include_instr) - 1)
+ name = include_instr[idx]
+ elif(len(allowed_instr) > 0):
+ idx = random.randrange(0, len(allowed_instr) - 1)
+ name = allowed_instr[idx]
+ else:
+ idx = random.randrange(0, len(self.instr_names) - 1)
+ name = self.instr_names[idx]
+ except Exception:
+ logging.critical("[%s] Cannot generate random instruction", riscv_instr.__name__)
sys.exit(1)
-
- instr_h = copy(self.instr_template[name])
+ else:
+ try:
+ name = random.choice(self.instr_names)
+ if(len(include_instr) > 0):
+ name = random.choice(include_instr)
+ if(len(allowed_instr) > 0):
+ name = random.choice(allowed_instr)
+ except Exception:
+ logging.critical("[%s] Cannot generate random instruction", riscv_instr.__name__)
+ sys.exit(1)
+ # rs1 rs2 values are overwriting and the last generated values are
+ # getting assigned for a particular instruction hence creating different
+ # object address and id to ratain the randomly generated values.
+ instr_h = copy.deepcopy(self.instr_template[name])
return instr_h
def get_load_store_instr(self, load_store_instr):
@@ -236,7 +229,8 @@
def get_instr(self, name):
if (not self.instr_template.get(name)):
logging.critical("Cannot get instr %s", name)
- instr_h = copy(self.instr_template[name])
+ sys.exit(1)
+ instr_h = copy.copy(self.instr_template[name])
return instr_h
def set_rand_mode(self):
@@ -268,120 +262,197 @@
self.imm_len = 5
else:
self.imm_len = 11
- self.imm_mask = self.imm_mask << self.imm_len
+ self.imm_mask = (self.imm_mask << self.imm_len) & self.shift_t
def extend_imm(self):
sign = 0
- self.imm = self.imm << (32 - self.imm_len)
- # sign = imm[31]
- sign = self.imm.bin[0:1:1]
- self.imm = self.imm >> (32 - self.imm_len)
+ # self.shift_t = 2 ** 32 -1 is used to limit the width after shift operation
+ self.imm = self.imm << (32 - self.imm_len) & self.shift_t
+ sign = (self.imm & 0x80000000) >> 31
+ self.imm = self.imm >> (32 - self.imm_len) & self.shift_t
# Signed extension
- if((sign and not(self.format == "U_FORMAT")) or (self.imm_type in ["UIMM", "NZUIMM"])):
+ if(sign and not((self.format.name == "U_FORMAT") or
+ (self.imm_type.name in ["UIMM", "NZUIMM"]))):
self.imm = self.imm_mask | self.imm
+ def imm_c(self):
+ imm_t = BitArray(uint = self.imm, length = 32)
+ if self.instr_name in [riscv_instr_name_t.SLLIW.name, riscv_instr_name_t.SRLIW.name,
+ riscv_instr_name_t.SRAIW.name]:
+ imm_t[20:27:1] = 0
+ self.imm = imm_t.uint
+ if self.instr_name in [riscv_instr_name_t.SLLI.name, riscv_instr_name_t.SRLI.name,
+ riscv_instr_name_t.SRAI.name]:
+ if rcs.XLEN == 32:
+ imm_t[20:27:1] = 0
+ self.imm = imm_t.uint
+ else:
+ self.imm_t[20:26:1] = 0
+ self.imm = imm_t.uint
+
def post_randomize(self):
+ self.imm_c()
self.extend_imm()
self.update_imm_str()
- def convert2asm(self):
- pass
+ def convert2asm(self, prefix = " "):
+ asm_str = pkg_ins.format_string(string = self.get_instr_name(),
+ length = pkg_ins.MAX_INSTR_STR_LEN)
+ if(self.category.name != "SYSTEM"):
+ if self.format.name == "J_FORMAT":
+ asm_str = '{} {}, {}'.format(asm_str, self.rd.name, self.get_imm())
+ elif self.format.name == "U_FORMAT":
+ asm_str = '{} {}, {}'.format(asm_str, self.rd.name, self.get_imm())
+ elif self.format.name == "I_FORMAT":
+ if(self.instr_name == "NOP"):
+ asm_str = "nop"
+ elif(self.instr_name == "WFI"):
+ asm_str = "wfi"
+ elif(self.instr_name == "FENCE"):
+ asm_str = "fence"
+ elif(self.instr_name == "FENCE_I"):
+ asm_str = "fence.i"
+ elif(self.category.name == "LOAD"):
+ asm_str = '{} {}, {} ({})'.format(
+ asm_str, self.rd.name, self.get_imm(), self.rs1.name)
+ elif(self.category.name == "CSR"):
+ asm_str = '{} {}, 0x{}, {}'.format(
+ asm_str, self.rd.name, self.csr, self.get_imm())
+ else:
+ asm_str = '{} {}, {}, {}'.format(
+ asm_str, self.rd.name, self.rs1.name, self.get_imm())
+ elif self.format.name == "S_FORMAT":
+ if(self.category.name == "STORE"):
+ asm_str = '{} {}, {} ({})'.format(
+ asm_str, self.rs2.name, self.get_imm(), self.rs1.name)
+ else:
+ asm_str = '{} {}, {}, {}'.format(
+ asm_str, self.rs1.name, self.rs2.name, self.get_imm())
+
+ elif self.format.name == "B_FORMAT":
+ if(self.category.name == "STORE"):
+ asm_str = '{} {}, {} ({})'.format(
+ asm_str, self.rs2.name, self.get_imm(), self.rs1.name)
+ else:
+ asm_str = '{} {}, {}, {}'.format(
+ asm_str, self.rs1.name, self.rs2.name, self.get_imm())
+
+ elif self.format.name == "R_FORMAT":
+ if(self.category.name == "CSR"):
+ asm_str = '{} {}, 0x{}, {}'.format(
+ asm_str, self.rd.name, self.csr, self.rs1.name)
+ elif(self.instr_name == "SFENCE_VMA"):
+ asm_str = "sfence.vma x0, x0"
+ else:
+ asm_str = '{} {}, {}, {}'.format(
+ asm_str, self.rd.name, self.rs1.name, self.rs2.name)
+ else:
+ asm_str = 'Fatal_unsupported_format: {} {}'.format(
+ self.format.name, self.instr_name)
+
+ else:
+ if(self.instr_name == "EBREAK"):
+ asm_str = ".4byte 0x00100073 # ebreak"
+
+ if(self.comment != ""):
+ asm_str = asm_str + " #" + self.comment
+ return asm_str.lower()
def get_opcode(self):
- if(self.instr_name.name == "LUI"):
+ if(self.instr_name == "LUI"):
return (BitArray(uint = 55, length = 7).bin)
- elif(self.instr_name.name == "AUIPC"):
+ elif(self.instr_name == "AUIPC"):
return (BitArray(uint = 23, length = 7).bin)
- elif(self.instr_name.name == "JAL"):
+ elif(self.instr_name == "JAL"):
return (BitArray(uint = 23, length = 7).bin)
- elif(self.instr_name.name == "JALR"):
+ elif(self.instr_name == "JALR"):
return (BitArray(uint = 111, length = 7).bin)
- elif(self.instr_name.name in ["BEQ", "BNE", "BLT", "BGE", "BLTU", "BGEU"]):
+ elif(self.instr_name in ["BEQ", "BNE", "BLT", "BGE", "BLTU", "BGEU"]):
return (BitArray(uint = 103, length = 7).bin)
- elif(self.instr_name.name in ["LB", "LH", "LW", "LBU", "LHU", "LWU", "LD"]):
+ elif(self.instr_name in ["LB", "LH", "LW", "LBU", "LHU", "LWU", "LD"]):
return (BitArray(uint = 99, length = 7).bin)
- elif(self.instr_name.name in ["SB", "SH", "SW", "SD"]):
+ elif(self.instr_name in ["SB", "SH", "SW", "SD"]):
return (BitArray(uint = 35, length = 7).bin)
- elif(self.instr_name.name in ["ADDI", "SLTI", "SLTIU", "XORI", "ORI", "ANDI",
- "SLLI", "SRLI", "SRAI", "NOP"]):
+ elif(self.instr_name in ["ADDI", "SLTI", "SLTIU", "XORI", "ORI", "ANDI",
+ "SLLI", "SRLI", "SRAI", "NOP"]):
return (BitArray(uint = 19, length = 7).bin)
- elif(self.instr_name.name in ["ADD", "SUB", "SLL", "SLT", "SLTU", "XOR", "SRL",
- "SRA", "OR", "AND", "MUL", "MULH", "MULHSU", "MULHU",
- "DIV", "DIVU", "REM", "REMU"]):
+ elif(self.instr_name in ["ADD", "SUB", "SLL", "SLT", "SLTU", "XOR", "SRL",
+ "SRA", "OR", "AND", "MUL", "MULH", "MULHSU", "MULHU",
+ "DIV", "DIVU", "REM", "REMU"]):
return (BitArray(uint = 51, length = 7).bin)
- elif(self.instr_name.name in ["ADDIW", "SLLIW", "SRLIW", "SRAIW"]):
+ elif(self.instr_name in ["ADDIW", "SLLIW", "SRLIW", "SRAIW"]):
return (BitArray(uint = 27, length = 7).bin)
- elif(self.instr_name.name in ["MULH", "MULHSU", "MULHU", "DIV", "DIVU", "REM", "REMU"]):
+ elif(self.instr_name in ["MULH", "MULHSU", "MULHU", "DIV", "DIVU", "REM", "REMU"]):
return (BitArray(uint = 51, length = 7).bin)
- elif(self.instr_name.name in ["FENCE", "FENCE_I"]):
+ elif(self.instr_name in ["FENCE", "FENCE_I"]):
return (BitArray(uint = 15, length = 7).bin)
- elif(self.instr_name.name in ["ECALL", "EBREAK", "CSRRW", "CSRRS", "CSRRC", "CSRRWI",
- "CSRRSI", "CSRRCI"]):
+ elif(self.instr_name in ["ECALL", "EBREAK", "CSRRW", "CSRRS", "CSRRC", "CSRRWI",
+ "CSRRSI", "CSRRCI"]):
return (BitArray(uint = 115, length = 7).bin)
- elif(self.instr_name.name in ["ADDW", "SUBW", "SLLW", "SRLW", "SRAW", "MULW", "DIVW",
- "DIVUW", "REMW", "REMUW"]):
+ elif(self.instr_name in ["ADDW", "SUBW", "SLLW", "SRLW", "SRAW", "MULW", "DIVW",
+ "DIVUW", "REMW", "REMUW"]):
return (BitArray(uint = 59, length = 7).bin)
- elif(self.instr_name.name in ["ECALL", "EBREAK", "URET", "SRET", "MRET", "DRET", "WFI",
- "SFENCE_VMA"]):
+ elif(self.instr_name in ["ECALL", "EBREAK", "URET", "SRET", "MRET", "DRET", "WFI",
+ "SFENCE_VMA"]):
return (BitArray(uint = 115, length = 7).bin)
else:
- logging.critical("Unsupported instruction %0s", self.instr_name.name)
+ logging.critical("Unsupported instruction %0s", self.instr_name)
sys.exit(1)
def get_func3(self):
- if(self.instr_name.name in ["JALR", "BEQ", "LB", "SB", "ADDI", "NOP", "ADD", "SUB",
- "FENCE", "ECALL", "EBREAK", "ADDIW", "ADDW", "SUBW", "MUL",
- "MULW", "ECALL", "EBREAK", "URET", "SRET", "MRET", "DRET",
- "WFI", "SFENCE_VMA"]):
+ if(self.instr_name in ["JALR", "BEQ", "LB", "SB", "ADDI", "NOP", "ADD", "SUB",
+ "FENCE", "ECALL", "EBREAK", "ADDIW", "ADDW", "SUBW", "MUL",
+ "MULW", "ECALL", "EBREAK", "URET", "SRET", "MRET", "DRET",
+ "WFI", "SFENCE_VMA"]):
return (BitArray(uint = 0, length = 3).bin)
- elif(self.instr_name.name in ["BNE", "LH", "SH", "SLLI", "SLL", "FENCE_I", "CSRRW", "SLLIW",
- "SLLW", "MULH"]):
+ elif(self.instr_name in ["BNE", "LH", "SH", "SLLI", "SLL", "FENCE_I", "CSRRW", "SLLIW",
+ "SLLW", "MULH"]):
return (BitArray(uint = 1, length = 3).bin)
- elif(self.instr_name.name in ["LW", "SW", "SLTI", "SLT", "CSRRS", "MULHS"]):
+ elif(self.instr_name in ["LW", "SW", "SLTI", "SLT", "CSRRS", "MULHS"]):
return (BitArray(uint = 2, length = 3).bin)
- elif(self.instr_name.name in ["SLTIU", "SLTU", "CSRRC", "LD", "SD", "MULHU"]):
+ elif(self.instr_name in ["SLTIU", "SLTU", "CSRRC", "LD", "SD", "MULHU"]):
return (BitArray(uint = 3, length = 3).bin)
- elif(self.instr_name.name in ["BLT", "LBU", "XORI", "XOR", "DIV", "DIVW"]):
+ elif(self.instr_name in ["BLT", "LBU", "XORI", "XOR", "DIV", "DIVW"]):
return (BitArray(uint = 4, length = 3).bin)
- elif(self.instr_name.name in ["BGE", "LHU", "SRLI", "SRAI", "SRL", "SRA", "CSRRWI", "SRLIW",
- "SRAIW", "SRLW",
- "SRAW", "DIVU", "DIVUW"]):
+ elif(self.instr_name in ["BGE", "LHU", "SRLI", "SRAI", "SRL", "SRA", "CSRRWI", "SRLIW",
+ "SRAIW", "SRLW",
+ "SRAW", "DIVU", "DIVUW"]):
return (BitArray(uint = 5, length = 3).bin)
- elif(self.instr_name.name in ["BLTU", "ORI", "OR", "CSRRSI", "LWU", "REM", "REMW"]):
+ elif(self.instr_name in ["BLTU", "ORI", "OR", "CSRRSI", "LWU", "REM", "REMW"]):
return (BitArray(uint = 6, length = 3).bin)
- elif(self.instr_name.name in ["BGEU", "ANDI", "AND", "CSRRCI", "REMU", "REMUW"]):
+ elif(self.instr_name in ["BGEU", "ANDI", "AND", "CSRRCI", "REMU", "REMUW"]):
return (BitArray(uint = 7, length = 3).bin)
else:
- logging.critical("Unsupported instruction %0s", self.instr_name.name)
+ logging.critical("Unsupported instruction %0s", self.instr_name)
sys.exit(1)
def get_func7(self):
- if(self.instr_name.name in ["SLLI", "SRLI", "ADD", "SLL", "SLT", "SLTU", "XOR",
- "SRL", "OR", "AND", "FENCE", "FENCE_I", "SLLIW",
- "SRLIW", "ADDW", "SLLW", "SRLW", "ECALL", "EBREAK", "URET"]):
+ if(self.instr_name in ["SLLI", "SRLI", "ADD", "SLL", "SLT", "SLTU", "XOR",
+ "SRL", "OR", "AND", "FENCE", "FENCE_I", "SLLIW",
+ "SRLIW", "ADDW", "SLLW", "SRLW", "ECALL", "EBREAK", "URET"]):
return (BitArray(uint = 0, length = 7).bin)
- elif(self.instr_name.name in ["SUB", "SRA", "SRAIW", "SUBW", "SRAW"]):
+ elif(self.instr_name in ["SUB", "SRA", "SRAIW", "SUBW", "SRAW"]):
return (BitArray(uint = 32, length = 7).bin)
- elif(self.instr_name.name in ["MUL", "MULH", "MULHSU", "MULHU", "DIV", "DIVU", "REM",
- "REMU", "MULW", "DIVW", "DIVUW", "REMW", "REMUW"]):
+ elif(self.instr_name in ["MUL", "MULH", "MULHSU", "MULHU", "DIV", "DIVU", "REM",
+ "REMU", "MULW", "DIVW", "DIVUW", "REMW", "REMUW"]):
return (BitArray(uint = 1, length = 7).bin)
- elif(self.instr_name.name in ["SRET", "WFI"]):
+ elif(self.instr_name in ["SRET", "WFI"]):
return (BitArray(uint = 8, length = 7).bin)
- elif(self.instr_name.name == "MRET"):
+ elif(self.instr_name == "MRET"):
return (BitArray(uint = 24, length = 7).bin)
- elif(self.instr_name.name == "DRET"):
+ elif(self.instr_name == "DRET"):
return (BitArray(uint = 61, length = 7).bin)
- elif(self.instr_name.name == "SFENCE_VMA"):
+ elif(self.instr_name == "SFENCE_VMA"):
return (BitArray(uint = 9, length = 7).bin)
else:
- logging.critical("Unsupported instruction %0s", self.instr_name.name)
+ logging.critical("Unsupported instruction %0s", self.instr_name)
sys.exit(1)
def convert2bin(self):
pass # TODO
def get_instr_name(self):
- get_instr_name = self.instr_name.name
+ get_instr_name = self.instr_name
for i in get_instr_name:
if(i == "_"):
get_instr_name = get_instr_name.replace(i, ".")
@@ -401,8 +472,14 @@
pass # TODO
def update_imm_str(self):
- self.imm_str = str(self.imm)
+ self.imm_str = str(self.uintToInt(self.imm))
+
+ def uintToInt(self, x):
+ if x < (2 ** rcs.XLEN) / 2:
+ signed_x = x
+ else:
+ signed_x = x - 2 ** rcs.XLEN
+ return signed_x
riscv_instr_ins = riscv_instr()
-cfg = riscv_instr_gen_config()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr_cov.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr_cov.py
new file mode 100644
index 0000000..2bbe234
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr_cov.py
@@ -0,0 +1,46 @@
+import sys
+import vsc
+import logging
+from enum import Enum, auto
+from pygen_src.riscv_instr_pkg import riscv_reg_t
+
+class operand_sign_e(Enum):
+ POSITIVE = 0
+ NEGATIVE = auto()
+
+class div_result_e(Enum):
+ DIV_NORMAL = 0
+ DIV_BY_ZERO = auto()
+ DIV_OVERFLOW = auto()
+
+class compare_result_e(Enum):
+ EQUAL = 0
+ LARGER = auto()
+ SMALLER = auto()
+
+class logical_similarity_e(Enum):
+ IDENTICAL = 0
+ OPPOSITE = auto()
+ SIMILAR = auto()
+ DIFFERENT = auto()
+
+class special_val_e(Enum):
+ NORMAL_VAL = 0
+ MIN_VAL = auto()
+ MAX_VAL = auto()
+ ZERO_VAL = auto()
+
+
+def get_gpr(reg_name):
+ reg_name = reg_name.upper()
+ if not reg_name in riscv_reg_t:
+ logging.fatal("Cannot convert {} to GPR".format(reg_name))
+ return riscv_reg_t[reg_name]
+
+def get_gpr_state(reg_name):
+ if reg_name in ["zero", "x0"]:
+ return 0
+ elif reg_name in gpr_state:
+ return gpr_state[reg_name]
+ else:
+ logging.warning("Cannot find GPR state: {}".format(reg_name))
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32i_instr.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32i_instr.py
index a7ed7ac..076951c 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32i_instr.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32i_instr.py
@@ -9,9 +9,6 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-Regression script for RISC-V random instruction generator
"""
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py
new file mode 100644
index 0000000..054bdc2
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py
@@ -0,0 +1,568 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+"""
+
+import subprocess
+import logging
+import random
+from bitstring import BitArray
+from pygen_src.riscv_instr_sequence import riscv_instr_sequence
+from pygen_src.riscv_instr_pkg import pkg_ins, privileged_reg_t, privileged_mode_t, mtvec_mode_t
+from pygen_src.riscv_instr_gen_config import cfg
+from pygen_src.target.rv32i import riscv_core_setting as rcs
+'''
+ RISC-V assembly program generator
+
+ This is the main class to generate a complete RISC-V program, including the init routine,
+ instruction section, data section, stack section, page table, interrupt and exception
+ handling etc. Check gen_program() function to see how the program is generated.
+'''
+
+
+class riscv_asm_program_gen:
+
+ def __init__(self):
+ self.instr_stream = []
+ self.directed_instr_stream_ratio = []
+ self.hart = 0
+ self.page_table_list = []
+ self.main_program = []
+ self.sub_program = []
+
+ # Main function to generate the whole program
+
+ # This is the main function to generate all sections of the program.
+ def gen_program(self):
+ # Generate program header
+ self.instr_stream.clear()
+ self.gen_program_header()
+ for hart in range(cfg.num_of_harts):
+ # Commenting out for now
+ # sub_program_name = []
+ self.instr_stream.append(f"h{int(hart)}_start:")
+ if(not(cfg.bare_program_mode)):
+ self.setup_misa()
+ # Create all page tables
+ self.create_page_table(hart)
+ # Setup privileged mode registers and enter target privileged mode
+ self.pre_enter_privileged_mode(hart)
+ # Init section
+ self.gen_init_section(hart)
+ # To DO
+ '''
+ If PMP is supported, we want to generate the associated trap handlers and the test_done
+ section at the start of the program so we can allow access through the pmpcfg0 CSR
+ '''
+ if(rcs.support_pmp and not(cfg.bare_program_mode)):
+ self.gen_trap_handlers(hart)
+ # Ecall handler
+ self.gen_ecall_handler(hart)
+ # Instruction fault handler
+ self.gen_instr_fault_handler(hart)
+ # Load fault handler
+ self.gen_load_fault_handler(hart)
+ # Store fault handler
+ self.gen_store_fault_handler(hart)
+ self.gen_test_done()
+
+ # Generate main program
+ gt_lbl_str = pkg_ins.get_label("main", hart)
+ gt_lbl_str = riscv_instr_sequence()
+ self.main_program.append(gt_lbl_str)
+ self.main_program[hart].instr_cnt = cfg.main_program_instr_cnt
+ self.main_program[hart].is_debug_program = 0
+ self.main_program[hart].label_name = "main"
+ self.main_program[hart].gen_instr(is_main_program = 1, no_branch = cfg.no_branch_jump)
+
+ self.main_program[hart].generate_instr_stream()
+ logging.info("Generating main program instruction stream...done")
+ self.instr_stream.extend(self.main_program[hart].instr_string_list)
+ """
+ If PMP is supported, need to jump from end of main program
+ to test_done section at the end of main_program, as the test_done
+ will have moved to the beginning of the program
+ """
+ self.instr_stream.append("{}j test_done".format(pkg_ins.indent))
+ '''
+ Test done section
+ If PMP isn't supported, generate this in the normal location
+ '''
+ if(hart == 0 and not(rcs.support_pmp)):
+ self.gen_test_done()
+
+ logging.info("Main/sub program generation...done")
+ # program end
+ self.gen_program_end(hart)
+ for hart in range(cfg.num_of_harts):
+ self.gen_data_page_begin(hart)
+ if(cfg.no_data_page):
+ self.gen_data_page()
+
+ if((hart == 0) and ("RV32A" in rcs.supported_isa)):
+ self.gen_data_page(hart, amo = 1)
+
+ self.gen_stack_section(hart)
+ if(not cfg.bare_program_mode):
+ self.gen_kernel_sections(hart)
+
+ def gen_kernel_sections(self, hart):
+ if(rcs.SATP_MODE != "BARE"):
+ self.instr_stream.append(".align 12")
+ else:
+ self.instr_stream.append(".align 2")
+ self.instr_stream.append(pkg_ins.get_label("kernel_instr_start:", hart))
+ self.instr_stream.append(".text")
+
+ self.gen_all_trap_handler(hart)
+ for mode in rcs.supported_privileged_mode:
+ self.gen_interrupt_handler_section(mode, hart)
+
+ self.gen_kernel_stack_section(hart)
+
+ def gen_kernel_program(self, hart, seq):
+ pass
+
+ def gen_sub_program(self, hart, sub_program,
+ sub_program_name, num_sub_program,
+ is_debug = 0, prefix = "sub"):
+ pass
+
+ def gen_callstack(self, main_program, sub_program,
+ sub_program_name, num_sub_program):
+ pass
+
+ def insert_sub_program(self, sub_program, instr_list):
+ pass
+
+ def gen_program_header(self):
+ string = []
+ self.instr_stream.append(".include \"user_define.h\"")
+ self.instr_stream.append(".globl _start")
+ self.instr_stream.append(".section .text")
+ if(cfg.disable_compressed_instr):
+ self.instr_stream.append(".option norvc;")
+ string.append(".include \"user_init.s\"")
+ string.append("csrr x5, mhartid")
+
+ for hart in range(cfg.num_of_harts):
+ string.append("li x6, {}\n{}beq x5, x6, {}f".format(hart, pkg_ins.indent, hart))
+
+ self.gen_section("_start", string)
+
+ for hart in range(cfg.num_of_harts):
+ self.instr_stream.append("{}: j h{}_start".format(hart, hart))
+
+ def gen_program_end(self, hart):
+ if(hart == 0):
+ self.gen_section("write_tohost", ["sw gp, tohost, t5"])
+ self.gen_section("_exit", ["j write_tohost"])
+
+ def gen_data_page_begin(self, hart):
+ self.instr_stream.append(".section .data")
+ if (hart == 0):
+ self.instr_stream.append(".align 6; .global tohost; tohost: .dword 0;")
+ self.instr_stream.append(".align 6; .global fromhost; fromhost: .dword 0;")
+
+ def gen_data_page(self, hart, is_kernel = 0, amo = 0):
+ pass
+
+ def gen_stack_section(self, hart):
+ hart_prefix_string = pkg_ins.hart_prefix(hart)
+ if(cfg.use_push_data_section):
+ self.instr_stream.append(
+ ".pushsection .{}user_stack,\"aw\",@progbits;".format(hart_prefix_string))
+ else:
+ self.instr_stream.append(
+ ".section .{}user_stack,\"aw\",@progbits;".format(hart_prefix_string))
+ if(rcs.SATP_MODE != "BARE"):
+ self.instr_stream.append(".align 12")
+ else:
+ self.instr_stream.append(".align 2")
+
+ self.instr_stream.append(pkg_ins.get_label("user_stack_start:", hart))
+ self.instr_stream.append(".rept {}".format(cfg.kernel_stack_len - 1))
+ self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
+ self.instr_stream.append(".endr")
+ self.instr_stream.append(pkg_ins.get_label("user_stack_end:", hart))
+ self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
+ if (cfg.use_push_data_section):
+ self.instr_stream.push_back(".popsection;")
+
+ def gen_kernel_stack_section(self, hart):
+ hart_prefix_string = pkg_ins.hart_prefix(hart)
+ if(cfg.use_push_data_section):
+ self.instr_stream.append(
+ ".pushsection .{}kernel_stack,\"aw\",@progbits;".format(hart_prefix_string))
+ else:
+ self.instr_stream.append(
+ ".section .{}kernel_stack,\"aw\",@progbits;".format(hart_prefix_string))
+ if(rcs.SATP_MODE != "BARE"):
+ self.instr_stream.append(".align 12")
+ else:
+ self.instr_stream.append(".align 2")
+
+ self.instr_stream.append(pkg_ins.get_label("kernel_stack_start:", hart))
+ self.instr_stream.append(".rept {}".format(cfg.kernel_stack_len - 1))
+ self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
+ self.instr_stream.append(".endr")
+ self.instr_stream.append(pkg_ins.get_label("kernel_stack_end:", hart))
+ self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8))
+ if (cfg.use_push_data_section):
+ self.instr_stream.push_back(".popsection;")
+
+ def gen_init_section(self, hart):
+ string = pkg_ins.format_string("init:", pkg_ins.LABEL_STR_LEN)
+ self.instr_stream.append(string)
+ self.init_gpr()
+ # Init stack pointer to point to the end of the user stack
+ string = "{}la x{}, {}user_stack_end".format(
+ pkg_ins.indent, cfg.sp.value, pkg_ins.hart_prefix(hart))
+ self.instr_stream.append(string)
+ if (cfg.enable_floating_point):
+ self.init_floating_point_gpr()
+ if (cfg.enable_vector_extension):
+ self.init_vector_engine()
+ self.core_is_initialized()
+ self.gen_dummy_csr_write()
+
+ if (rcs.support_pmp):
+ string = pkg_ins.indent + "j main"
+ self.instr_stream.append(string)
+
+ def setup_misa(self):
+ # TO DO
+ misa = 0b01000000
+ self.instr_stream.append("{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0].value, hex(misa)))
+ self.instr_stream.append("{}csrw misa, x{}".format(pkg_ins.indent, cfg.gpr[0].value))
+
+ def core_is_initialized(self):
+ pass
+
+ def gen_dummy_csr_write(self):
+ pass
+
+ def init_gpr(self):
+ reg_val = BitArray(uint = 0, length = pkg_ins.DATA_WIDTH)
+ dist_lst = []
+
+ for dist_val in range(5):
+ if dist_val == 0:
+ reg_val = BitArray(hex='0x0')
+ elif dist_val == 1:
+ reg_val = BitArray(hex='0x80000000')
+ elif dist_val == 2:
+ temp = random.randrange(0x1, 0xf)
+ reg_val = BitArray(hex(temp), length=32)
+ elif dist_val == 3:
+ temp = random.randrange(0x10, 0xefffffff)
+ reg_val = BitArray(hex(temp), length=32)
+ else:
+ temp = random.randrange(0xf0000000, 0xffffffff)
+ reg_val = BitArray(hex(temp), length=32)
+ dist_lst.append(reg_val)
+
+ for i in range(32):
+ init_string = "{}li x{}, {}".format(pkg_ins.indent, i, random.choice(dist_lst))
+ self.instr_stream.append(init_string)
+
+ def init_floating_point_gpr(self):
+ pass
+
+ def init_vector_engine(self):
+ pass
+
+ def gen_test_done(self):
+ string = pkg_ins.format_string("test_done:", pkg_ins.LABEL_STR_LEN)
+ self.instr_stream.append(string)
+ self.instr_stream.append(pkg_ins.indent + "li gp, 1")
+
+ if(cfg.bare_program_mode):
+ self.instr_stream.append(pkg_ins.indent + "j write_tohost")
+ else:
+ self.instr_stream.append(pkg_ins.indent + "ecall")
+
+ def gen_register_dump(self):
+ pass
+
+ def pre_enter_privileged_mode(self, hart):
+ instr = []
+ string = []
+
+ string.append("la x{}, {}kernel_stack_end".format(cfg.tp.value, pkg_ins.hart_prefix(hart)))
+ self.gen_section(pkg_ins.get_label("kernel_sp", hart), string)
+
+ if(not cfg.no_delegation and (cfg.init_privileged_mode != "MACHINE_MODE")):
+ self.gen_delegation(hart)
+ self.trap_vector_init(hart)
+ self.setup_pmp(hart)
+
+ if(cfg.virtual_addr_translation_on):
+ self.page_table_list.process_page_table(instr)
+ self.gen_section(pkg_ins.get_label("process_pt", hart), instr)
+ # Commenting for now
+ # self.setup_epc(hart)
+
+ if(rcs.support_pmp):
+ self.gen_privileged_mode_switch_routine(hart)
+
+ def gen_privileged_mode_switch_routine(self, hart):
+ pass
+
+ def setup_epc(self, hart):
+ instr = []
+ instr.append("la x{}, {}init".format(cfg.gpr[0].value, pkg_ins.hart_prefix(hart)))
+ # if(cfg.virtual_addr_translation_on):
+ # instr.append("slli x{}, x{}")
+ # TODO
+ mode_name = cfg.init_privileged_mode
+ instr.append("csrw mepc, x{}".format(cfg.gpr[0].value))
+ if(not rcs.support_pmp): # TODO
+ instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.name.lower()))
+
+ self.gen_section(pkg_ins.get_label("mepc_setup", hart), instr)
+
+ def setup_pmp(self, hart):
+ pass
+
+ def gen_delegation(self, hart):
+ self.gen_delegation_instr(hart, "MEDELEG", "MIDELEG",
+ cfg.m_mode_exception_delegation,
+ cfg.m_mode_interrupt_delegation)
+ if(rcs.support_umode_trap):
+ self.gen_delegation_instr(hart, "SEDELEG", "SIDELEG",
+ cfg.s_mode_exception_delegation,
+ cfg.s_mode_interrupt_delegation)
+
+ def gen_delegation_instr(self, hart, edeleg, ideleg,
+ edeleg_enable, ideleg_enable):
+ pass
+
+ def trap_vector_init(self, hart):
+ instr = []
+ for items in rcs.supported_privileged_mode:
+ if(items == "MACHINE_MODE"):
+ trap_vec_reg = privileged_reg_t.MTVEC
+ elif(items == "SUPERVISOR_MODE"):
+ trap_vec_reg = privileged_reg_t.STVEC
+ elif(items == "USER_MODE"):
+ trap_vec_reg = privileged_reg_t.UTVEC
+ else:
+ logging.critical(
+ "[riscv_asm_program_gen] Unsupported privileged_mode {}".format(items))
+
+ if(items == "USER_MODE" and not (rcs.support_umode_trap)):
+ continue
+
+ if(items < cfg.init_privileged_mode.name):
+ continue
+
+ tvec_name = trap_vec_reg.name
+ tvec_name = tvec_name.lower()
+ instr.append("la x{}, {}{}_handler".format(
+ cfg.gpr[0].value, pkg_ins.hart_prefix(hart), tvec_name))
+ if(rcs.SATP_MODE != "BARE" and items != "MACHINE_MODE"):
+ instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0].value,
+ cfg.gpr[0].value, rcs.XLEN - 20) +
+ "srli x{}, x{}, {}".format(cfg.gpr[0].value,
+ cfg.gpr[0].value, rcs.XLEN - 20))
+
+ instr.append("ori x{}, x{}, {}".format(
+ cfg.gpr[0].value, cfg.gpr[0].value, cfg.mtvec_mode.value))
+ instr.append("csrw {}, x{} # {}".format(
+ hex(trap_vec_reg.value), cfg.gpr[0].value, trap_vec_reg.name))
+
+ self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr)
+
+ def gen_all_trap_handler(self, hart):
+ if(not rcs.support_pmp):
+ self.gen_trap_handlers(hart)
+ self.gen_ecall_handler(hart)
+ self.gen_instr_fault_handler(hart)
+ self.gen_load_fault_handler(hart)
+ self.gen_store_fault_handler(hart)
+
+ def gen_trap_handlers(self, hart):
+ self.gen_trap_handler_section(hart, "m", privileged_reg_t.MCAUSE,
+ privileged_reg_t.MTVEC, privileged_reg_t.MTVAL,
+ privileged_reg_t.MEPC, privileged_reg_t.MSCRATCH,
+ privileged_reg_t.MSTATUS, privileged_reg_t.MIE,
+ privileged_reg_t.MIP)
+
+ def gen_trap_handler_section(self, hart, mode, cause, tvec,
+ tval, epc, scratch, status, ie, ip):
+ is_interrupt = 1
+ tvec_name = ""
+ instr = []
+ if (cfg.mtvec_mode == mtvec_mode_t.VECTORED):
+ self.gen_interrupt_vector_table(hart, mode, status, cause, ie, ip, scratch, instr)
+ else:
+ # Push user mode GPR to kernel stack before executing exception handling,
+ # this is to avoid exception handling routine modify user program state
+ # unexpectedly
+ # TODO
+ pkg_ins.push_gpr_to_kernel_stack(
+ status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr)
+ # The trap handler will occupy one 4KB page, it will be allocated one entry in
+ # the page table with a specific privileged mode.
+
+ if (rcs.SATP_MODE != "BARE"):
+ self.instr_stream.append(".align 12")
+ else:
+ self.instr_stream.append(".align {}".format(cfg.tvec_alignment))
+
+ tvec_name = tvec.name
+ self.gen_section(pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart), instr)
+
+ # TODO Exception handler
+
+ def gen_interrupt_vector_table(self, hart, mode, status, cause, ie,
+ ip, scratch, instr):
+ pass
+
+ def gen_ecall_handler(self, hart):
+ pass
+
+ def gen_ebreak_handler(self, hart):
+ pass
+
+ def gen_illegal_instr_handler(self, hart):
+ pass
+
+ def gen_instr_fault_handler(self, hart):
+ pass
+
+ def gen_load_fault_handler(self, hart):
+ pass
+
+ def gen_store_fault_handler(self, hart):
+ pass
+
+ def create_page_table(self, hart):
+ pass
+
+ def gen_page_table_section(self, hart):
+ pass
+
+ def gen_plic_section(self, interrupt_handler_instr):
+ pass
+
+ def gen_interrupt_handler_section(self, mode, hart):
+ interrupt_handler_instr = []
+ ls_unit = "w" if (rcs.XLEN == 32) else "d"
+ # TODO
+ # if(mode.value < cfg.init_privileged_mode):
+ # return
+ if(mode is privileged_mode_t.USER_MODE.name and not (rcs.support_umode_trap)):
+ return
+ if(mode == privileged_mode_t.MACHINE_MODE.name):
+ mode_prefix = "m"
+ status = privileged_reg_t.MSTATUS
+ ip = privileged_reg_t.MIP
+ ie = privileged_reg_t.MIE
+ scratch = privileged_reg_t.MSCRATCH
+ elif(mode is privileged_mode_t.SUPERVISOR_MODE.name):
+ mode_prefix = "s"
+ status = privileged_reg_t.SSTATUS
+ ip = privileged_reg_t.SIP
+ ie = privileged_reg_t.SIE
+ scratch = privileged_reg_t.SSCRATCH
+ elif(mode == privileged_mode_t.USER_MODE.name):
+ mode_prefix = "u"
+ status = privileged_reg_t.USTATUS
+ ip = privileged_reg_t.UIP
+ ie = privileged_reg_t.UIE
+ scratch = privileged_reg_t.USCRATCH
+ else:
+ logging.critical("Unsupported mode: %0s" % (mode))
+
+ if(cfg.enable_nested_interrupt):
+ interrupt_handler_instr.append("csrr x%0d, 0x%0x" % (cfg.gpr[0].value, scratch.value))
+ interrupt_handler_instr.append("bgtz x%0d, 1f" % (cfg.gpr[0].value))
+ interrupt_handler_instr.append("csrwi 0x%0x, 0x1" % (scratch.value))
+
+ if(status == privileged_reg_t.MSTATUS):
+ interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 8))
+ elif(status == privileged_reg_t.SSTATUS):
+ interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 2))
+ elif(status == privileged_reg_t.USTATUS):
+ interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 1))
+ else:
+ logging.critical("Unsupported status %0s" % (status.value))
+
+ interrupt_handler_instr.append("1: csrwi 0x%0x,0" % (scratch.value))
+
+ to_extend_interrupt_hanlder_instr = ["csrr x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
+ status.value,
+ status.name),
+ "csrr x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
+ ie.value, ie.name),
+ "csrr x%0d, 0x%0x # %0s;" % (cfg.gpr[0].value,
+ ip.value, ip.name),
+ "csrrc x%0d, 0x%0x, x%0d # %0s;" % (cfg.gpr[0].value,
+ ip.value,
+ cfg.gpr[0].value,
+ ip.name)]
+ interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr)
+ self.gen_plic_section(interrupt_handler_instr)
+ pkg_ins.pop_gpr_from_kernel_stack(status.name, scratch.name, cfg.mstatus_mprv,
+ cfg.sp, cfg.tp, interrupt_handler_instr)
+ interrupt_handler_instr.append("%0sret;" % (mode_prefix))
+
+ if(rcs.SATP_MODE != "BARE"):
+ self.instr_stream.append(".align 12")
+ else:
+ self.instr_stream.append(".align 2")
+
+ self.gen_section(pkg_ins.get_label("%0smode_intr_handler" %
+ (mode_prefix), hart), interrupt_handler_instr)
+
+ def format_section(self, instr):
+ pass
+
+ def gen_section(self, label, instr):
+ if(label != ""):
+ string = pkg_ins.format_string("{}:".format(label), pkg_ins.LABEL_STR_LEN)
+ self.instr_stream.append(string)
+ for items in instr:
+ string = pkg_ins.indent + items
+ self.instr_stream.append(string)
+ self.instr_stream.append("")
+
+ def dump_perf_stats(self):
+ pass
+
+ def gen_test_file(self, test_name):
+ subprocess.run(["mkdir", "-p", "out/asm_tests"])
+ file = open("./out/asm_tests/{}".format(test_name), "w+")
+ for items in self.instr_stream:
+ file.write("{}\n".format(items))
+
+ file.close()
+ logging.info("%0s is generated", test_name)
+
+ def gen_signature_handshake(self, instr, signature_type, core_status = "INITIALIZED",
+ test_result = "TEST_FAIL", csr = "MSCRATCH", addr_label = ""):
+ pass
+
+ def add_directed_instr_stream(self, name, ratio):
+ pass
+
+ def get_directed_instr_stream(self):
+ pass
+
+ def generate_directed_instr_stream(self, hart = 0, label = "", original_instr_cnt = None,
+ min_insert_cnt = 0, kernel_mode = 0, instr_stream = []):
+ pass
+
+ def gen_debug_rom(self, hart):
+ pass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
index d4f2b23..bc1e5f5 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py
@@ -9,9 +9,6 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-Regression script for RISC-V random instruction generator
"""
@@ -24,7 +21,7 @@
def __init__(self):
riscv_instr.__init__(self)
- self.instr_name = instr_n
+ self.instr_name = instr_n.name
self.format = instr_format
self.category = instr_category
self.group = instr_group
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
index 6d59010..0f56094 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py
@@ -9,26 +9,413 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-Regression script for RISC-V random instruction generator
"""
+import argparse
+import logging
+import sys
+import vsc
+from bitstring import BitArray
+from pygen_src.riscv_instr_pkg import mtvec_mode_t, f_rounding_mode_t, \
+ riscv_reg_t, privileged_mode_t, \
+ riscv_instr_group_t
+from pygen_src.target.rv32i import riscv_core_setting as rcs
+
+@vsc.randobj
class riscv_instr_gen_config:
- def __init__(self):
- self.enable_floating_point = 1
- self.disable_compressed_instr = 1
- self.num_of_test = 3
- self.no_fence = 1
+ def __init__(self, argv):
+ # TODO Support for command line argument
+ self.main_program_instr_cnt = 100 # count of main_prog
+ self.sub_program_instr_cnt = [] # count of sub_prog
+ self.debug_program_instr_cnt = 0 # count of debug_rom
+ self.debug_sub_program_instr_cnt = [] # count of debug sub_progrms
+ # Commenting out for now
+ # self.data_page_pattern = list(
+ # map(lambda dta_pg: dta_pg.name, data_pattern_t))
+ # dicts for exception_cause_t & interrupt_cause_t Enum classes
+
+ self.m_mode_exception_delegation = {}
+ self.s_mode_exception_delegation = {}
+ self.m_mode_interrupt_delegation = {}
+ self.s_mode_interrupt_delegation = {}
+
+ # init_privileged_mode default to MACHINE_MODE
+ self.init_privileged_mode = privileged_mode_t.MACHINE_MODE
+
+ self.mstatus = BitArray(bin(0b0), length=rcs.XLEN - 1)
+ self.mie = BitArray(bin(0b0), length=rcs.XLEN - 1)
+ self.sstatus = BitArray(bin(0b0), length=rcs.XLEN - 1)
+ self.sie = BitArray(bin(0b0), length=rcs.XLEN - 1)
+ self.ustatus = BitArray(bin(0b0), length=rcs.XLEN - 1)
+ self.uie = BitArray(bin(0b0), length=rcs.XLEN - 1)
+
+ self.mstatus_mprv = 0
+ self.mstatus_mxr = 0
+ self.mstatus_sum = 0
+ self.mstatus_tvm = 0
+ self.mstatus_fs = BitArray(bin(0b0), length=2)
+ self.mstatus_vs = BitArray(bin(0b0), length=2)
+ self.mtvec_mode = vsc.rand_enum_t(mtvec_mode_t)
+
+ self.tvec_alignment = argv.tvec_alignment
+
+ self.fcsr_rm = list(map(lambda csr_rm: csr_rm.name, f_rounding_mode_t))
self.enable_sfence = 0
- self.reserved_regs = []
- self.enable_illegal_csr_instruction = 0
- self.enable_access_invalid_csr_level = 0
+ self.gpr = []
+
+ # Helper fields for gpr
+ self.gpr0 = vsc.rand_enum_t(riscv_reg_t)
+ self.gpr1 = vsc.rand_enum_t(riscv_reg_t)
+ self.gpr2 = vsc.rand_enum_t(riscv_reg_t)
+ self.gpr3 = vsc.rand_enum_t(riscv_reg_t)
+
+ self.scratch_reg = vsc.rand_enum_t(riscv_reg_t)
+ self.pmp_reg = vsc.rand_enum_t(riscv_reg_t)
+ self.sp = vsc.rand_enum_t(riscv_reg_t)
+ self.tp = vsc.rand_enum_t(riscv_reg_t)
+ self.ra = vsc.rand_enum_t(riscv_reg_t)
+ self.check_misa_init_val = 0
+ self.check_xstatus = 1
+ self.virtual_addr_translation_on = 0
+
+ # Commenting out for now
+ # vector_cfg = riscv_vector_cfg # TODO
+ # pmp_cfg = riscv_pmp_cfg # TODO
+ # self.mem_region = [] # TODO
+ # Self.amo_region = [] # TODO
+
+ self.stack_len = 5000
+
+ # Self.s_mem_region = [] # TODO
+
+ self.kernel_stack_len = 4000
+ self.kernel_program_instr_cnt = 400
+ # list of main implemented CSRs
self.invalid_priv_mode_csrs = []
- self.init_privileged_mode = "MACHINE_MODE"
- self.no_ebreak = 1
- self.no_dret = 1
- self.no_csr_instr = 1
- self.no_wfi = 1
+ self.num_of_sub_program = argv.num_of_sub_program
+ self.instr_cnt = argv.instr_cnt
+ self.num_of_tests = argv.num_of_tests
+ self.no_data_page = argv.no_data_page
+ self.no_branch_jump = argv.no_branch_jump
+ self.no_load_store = argv.no_load_store
+ self.no_csr_instr = argv.no_csr_instr
+ self.no_ebreak = argv.no_ebreak
+ self.no_dret = argv.no_dret
+ self.no_fence = argv.no_fence
+ self.no_wfi = argv.no_wfi
+ self.enable_unaligned_load_store = argv.enable_unaligned_load_store
+ self.illegal_instr_ratio = argv.illegal_instr_ratio
+ self.hint_instr_ratio = argv.hint_instr_ratio
+ self.num_of_harts = argv.num_of_harts
+ self.fix_sp = argv.fix_sp
+ self.use_push_data_section = argv.use_push_data_section
+ self.boot_mode_opts = ""
+ self.enable_page_table_exception = argv.enable_page_table_exception
+ self.no_directed_instr = argv.no_directed_instr
+ self.asm_test_suffix = ""
+ self.enable_interrupt = argv.enable_interrupt
+ self.enable_nested_interrupt = argv.enable_nested_interrupt
+ self.enable_timer_irq = argv.enable_timer_irq
+ self.bare_program_mode = argv.bare_program_mode
+ self.enable_illegal_csr_instruction = argv.enable_illegal_csr_instruction
+ self.enable_access_invalid_csr_level = argv.enable_access_invalid_csr_level
+ self.enable_misaligned_instr = argv.enable_misaligned_instr
+ self.enable_dummy_csr_write = argv.enable_dummy_csr_write
+ self.randomize_csr = argv.randomize_csr
+ self.allow_sfence_exception = argv.allow_sfence_exception
+ self.no_delegation = argv.no_delegation
+ self.force_m_delegation = argv.force_m_delegation
+ self.force_s_delegation = argv.force_s_delegation
+ self.support_supervisor_mode = 0
+ self.disable_compressed_instr = argv.disable_compressed_instr
+ self.require_signature_addr = argv.require_signature_addr
+
+ if(self.require_signature_addr):
+ self.signature_addr = int(argv.signature_addr, 16)
+ else:
+ self.signature_addr = 0xdeadbeef
+
+ self.gen_debug_section = argv.gen_debug_section
+ self.enable_ebreak_in_debug_rom = argv.enable_ebreak_in_debug_rom
+ self.set_dcsr_ebreak = argv.set_dcsr_ebreak
+ self.num_debug_sub_program = argv.num_debug_sub_program
+ self.enable_debug_single_step = argv.enable_debug_single_step
+ self.single_step_iterations = 0
+ self.set_mstatus_tw = argv.set_mstatus_tw
+ self.set_mstatus_mprv = argv.set_mstatus_mprv
+ self.min_stack_len_per_program = 10 * (rcs.XLEN / 8)
+ self.max_stack_len_per_program = 16 * (rcs.XLEN / 8)
+ self.max_branch_step = 20
+ self.max_directed_instr_stream_seq = 20
+ self.reserved_regs = vsc.list_t(vsc.enum_t(riscv_reg_t))
+ self.enable_floating_point = argv.enable_floating_point
+ self.enable_vector_extension = argv.enable_vector_extension
+ self.enable_b_extension = argv.enable_b_extension
+ # Commenting out for now
+ # self.enable_bitmanip_groups = ['ZBB', 'ZBS', 'ZBP', 'ZBE', 'ZBF',
+ # 'ZBC', 'ZBR', 'ZBM', 'ZBT', 'ZB_TMP']
+ self.dist_control_mode = 0
+ self.category_dist = {}
+
+ @vsc.constraint
+ def gpr_c(self):
+ self.gpr0.not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
+ riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
+ self.gpr1.not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
+ riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
+ self.gpr2.not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
+ riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
+ self.gpr3.not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
+ riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
+ vsc.unique(self.gpr0, self.gpr1, self.gpr2, self.gpr3)
+
+ def check_setting(self):
+ support_64b = 0
+ support_128b = 0
+
+ # list of satp_mode_t from riscv_core_setting.py
+ stp_md_lst = rcs.SATP_MODE
+
+ # list of riscv_instr_group_t with names of riscv_instr_name_t in it.
+ supported_isa_lst = list(map(lambda z: z.name, riscv_instr_group_t))
+
+ # check the valid isa support
+ for x in rcs.supported_isa:
+ if x == (supported_isa_lst[1] or supported_isa_lst[3] or supported_isa_lst[5] or
+ supported_isa_lst[8] or supported_isa_lst[11] or supported_isa_lst[13] or
+ supported_isa_lst[19]):
+ support_64b = 1
+ logging.info("support_64b=%d" % support_64b)
+ logging.debug("Supported ISA=%s" % x)
+ elif x == (supported_isa_lst[14] or supported_isa_lst[15]):
+ support_128b = 1
+ logging.info("support_128b=%d" % support_128b)
+ logging.debug("Supported ISA=%s" % x)
+
+ if (support_128b == 1) and (rcs.XLEN != 128):
+ logging.critical("XLEN should be set to 128 based on \
+ riscv_core_setting.supported_isa setting")
+ logging.info("XLEN Value=%d" % rcs.XLEN)
+ sys.exit("XLEN is not equal to 128, set it Accordingly!")
+
+ if (support_128b == 0) and (support_64b == 1) and (rcs.XLEN != 64):
+ logging.critical("XLEN should be set to 64 based on \
+ riscv_core_setting.supported_isa setting")
+ logging.info("XLEN Value=%d" % rcs.XLEN)
+ sys.exit("XLEN is not equal to 64, set it Accordingly!")
+
+ if not(support_128b or support_64b) and (rcs.XLEN != 32):
+ logging.critical("XLEN should be set to 32 based on \
+ riscv_core_setting.supported_isa setting")
+ logging.info("XLEN Value=%d" % rcs.XLEN)
+ sys.exit("XLEN is not equal to 32, set it Accordingly!")
+
+ if not(support_128b or support_64b) and not(('SV32' in stp_md_lst) or
+ ('BARE' in stp_md_lst)):
+ logging.critical("SATP mode is not supported for RV32G ISA")
+ logging.info(stp_md_lst)
+ sys.exit("Supported SATP mode is not provided")
+
+ # TODO
+ def setup_instr_distribution(self):
+ pass
+
+ def init_delegation(self):
+ for i in self.mode_exp_lst:
+ if i == self.mode_exp_lst[0]:
+ continue
+ self.m_mode_exception_delegation[i] = 0
+ self.s_mode_exception_delegation[i] = 0
+
+ for j in self.mode_intrpt_lst:
+ if j == self.mode_intrpt_lst[0]:
+ continue
+ self.m_mode_interrupt_delegation[j] = 0
+ self.s_mode_interrupt_delegation[j] = 0
+
+ def pre_randomize(self):
+ # Clearing the contents of self.gpr after each randomization.
+ # As it is being extended in post_randomize function.
+ self.gpr.clear()
+ for x in rcs.supported_privileged_mode:
+ if(x == "SUPERVISOR_MODE"):
+ self.support_supervisor_mode = 1
+
+ def get_non_reserved_gpr(self):
+ pass
+
+ def post_randomize(self):
+ # Temporary fix for gpr_c constraint.
+ self.gpr.extend((self.gpr0, self.gpr1, self.gpr2, self.gpr3))
+
+ self.reserved_regs.append(self.tp)
+ self.reserved_regs.append(self.sp)
+ self.reserved_regs.append(self.scratch_reg)
+ self.min_stack_len_per_program = 2 * (rcs.XLEN / 8)
+ logging.info("min_stack_len_per_program value = %d"
+ % self.min_stack_len_per_program)
+ self.check_setting() # to check the setting is legal
+
+ # TODO, Need to change the logic once the constraints are up.
+ if "USER_MODE" == self.init_privileged_mode:
+ logging.info("mode=%s" % "USER_MODE")
+ self.no_wfi = 1
+
+ def get_invalid_priv_lvl_csr(self):
+ invalid_lvl = []
+ # Debug CSRs are inaccessible from all but Debug Mode
+ # and we cannot boot into Debug Mode.
+ invalid_lvl.append('D')
+
+ # TODO Need to change the logic once the constraints are up.
+ for mode in self.init_privileged_mode:
+ if mode == "MACHINE_MODE":
+ continue
+ if mode == 'SUPERVISOR_MODE':
+ invalid_lvl.append('M')
+ logging.info("supr_mode---")
+ logging.debug(invalid_lvl)
+ elif mode == 'USER_MODE':
+ invalid_lvl.append('S')
+ invalid_lvl.append('M')
+ logging.info("usr_mode---")
+ logging.debug(invalid_lvl)
+ else:
+ logging.critical("Unsupported initialization privilege mode")
+
+ # implemented_csr from riscv_core_setting.py
+ for x in rcs.implemented_csr:
+ if x[0] in invalid_lvl:
+ self.invalid_priv_mode_csrs.append(x)
+
+ # This function calls all the above defined function which should
+ # be called in init function as per SV logic.This function as to be
+ # called after every instance of the gen_config handle
+ def func_call_init(self):
+ self.init_delegation()
+ # self.setup_instr_distribution() # TODO
+ self.get_invalid_priv_lvl_csr()
+
+
+def parse_args():
+ parse = argparse.ArgumentParser()
+ parse.add_argument('--num_of_tests', help = 'num_of_tests', type = int, default = 1)
+ parse.add_argument('--enable_page_table_exception',
+ help = 'enable_page_table_exception', type = int, default = 0)
+ parse.add_argument('--enable_interrupt', help = 'enable_interrupt',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--enable_nested_interrupt', help = 'enable_nested_interrupt',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--enable_timer_irq', help = 'enable_timer_irq',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--num_of_sub_program', help = 'num_of_sub_program', type = int, default = 5)
+ parse.add_argument('--instr_cnt', help = 'instr_cnt', type = int, default = 200)
+ parse.add_argument('--tvec_alignment', help = 'tvec_alignment', type = int, default = 2)
+ parse.add_argument('--no_ebreak', help = 'no_ebreak', choices = [0, 1], type = int, default = 1)
+ parse.add_argument('--no_dret', help = 'no_dret', choices = [0, 1], type = int, default = 1)
+ parse.add_argument('--no_wfi', help = 'no_wfi', choices = [0, 1], type = int, default = 1)
+
+ # TODO : Enabling no_branch_jump default to 1 for now.
+ parse.add_argument('--no_branch_jump', help = 'no_branch_jump',
+ choices = [0, 1], type = int, default = 1)
+ parse.add_argument('--no_load_store', help = 'no_load_store',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--no_csr_instr', help = 'no_csr_instr',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--fix_sp', help = 'fix_sp', choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--use_push_data_section', help = 'use_push_data_section',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--enable_illegal_csr_instruction',
+ help = 'enable_illegal_csr_instruction', choices = [0, 1],
+ type = int, default = 0)
+ parse.add_argument('--enable_access_invalid_csr_level',
+ help = 'enable_access_invalid_csr_level', choices = [0, 1],
+ type = int, default = 0)
+ parse.add_argument('--enable_misaligned_instr', help = 'enable_misaligned_instr',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--enable_dummy_csr_write', help = 'enable_dummy_csr_write',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--allow_sfence_exception', help = 'allow_sfence_exception',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--no_data_page', help = 'no_data_page',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--no_directed_instr', help = 'no_directed_instr',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--no_fence', help = 'no_fence', choices = [0, 1], type = int, default = 1)
+ parse.add_argument('--no_delegation', help = 'no_delegation',
+ choices = [0, 1], type = int, default = 1)
+ parse.add_argument('--illegal_instr_ratio',
+ help = 'illegal_instr_ratio', type = int, default = 0)
+ parse.add_argument('--hint_instr_ratio', help = 'hint_instr_ratio', type = int, default = 0)
+ parse.add_argument('--num_of_harts', help = 'num_of_harts', type = int, default = rcs.NUM_HARTS)
+ parse.add_argument('--enable_unaligned_load_store',
+ help = 'enable_unaligned_load_store', choices = [0, 1],
+ type = int, default = 0)
+ parse.add_argument('--force_m_delegation', help = 'force_m_delegation',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--force_s_delegation', help = 'force_s_delegation',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--require_signature_addr', help = 'require_signature_addr',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--signature_addr', help = 'signature_addr', default = 0xdeadbeef)
+ parse.add_argument('--disable_compressed_instr',
+ help = 'disable_compressed_instr', choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--randomize_csr', help = 'randomize_csr',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--gen_debug_section', help = 'gen_debug_section',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--bare_program_mode', help = 'bare_program_mode',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--num_debug_sub_program',
+ help = 'num_debug_sub_program', type = int, default = 0)
+ parse.add_argument('--enable_ebreak_in_debug_rom',
+ help = 'enable_ebreak_in_debug_rom', choices = [0, 1],
+ type = int, default = 0)
+ parse.add_argument('--set_dcsr_ebreak', help = 'set_dcsr_ebreak',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--enable_debug_single_step',
+ help = 'enable_debug_single_step', choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--set_mstatus_tw', help = 'set_mstatus_tw',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--set_mstatus_mprv', help = 'set_mstatus_mprv',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--enable_floating_point', help = 'enable_floating_point',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--enable_vector_extension', help = 'enable_vector_extension',
+ choices = [0, 1], type = int, default = 0)
+ parse.add_argument('--enable_b_extension', help = 'enable_b_extension',
+ choices = [0, 1], type = int, default = 0)
+
+ # TODO
+ '''
+ cmdline_enum_processor #(b_ext_group_t)::get_array_values("+enable_bitmanip_groups=",
+ enable_bitmanip_groups);
+ if(inst.get_arg_value("+boot_mode=", boot_mode_opts)) begin
+ `uvm_info(get_full_name(), $sformatf(
+ "Got boot mode option - %0s", boot_mode_opts), UVM_LOW)
+ case(boot_mode_opts)
+ "m" : init_privileged_mode = MACHINE_MODE;
+ "s" : init_privileged_mode = SUPERVISOR_MODE;
+ "u" : init_privileged_mode = USER_MODE;
+ default: `uvm_fatal(get_full_name(),
+ $sformatf("Illegal boot mode option - %0s", boot_mode_opts))
+ endcase
+ init_privileged_mode.rand_mode(0);
+ addr_translaction_rnd_order_c.constraint_mode(0);
+ end
+ `uvm_info(`gfn, $sformatf("riscv_instr_pkg::supported_privileged_mode = %0d",
+ riscv_instr_pkg::supported_privileged_mode.size()), UVM_LOW)
+ void'(inst.get_arg_value("+asm_test_suffix=", asm_test_suffix));
+ // Directed march list from the runtime options, ex. RV32I, RV32M etc.
+ cmdline_enum_processor #(riscv_instr_group_t)::get_array_values("+march=", march_isa);
+ if (march_isa.size != 0) riscv_instr_pkg::supported_isa = march_isa;
+ '''
+
+ args = parse.parse_args()
+ return args
+
+
+args = parse_args()
+cfg = riscv_instr_gen_config(args)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
index 5edc6a4..fd4e134 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py
@@ -9,17 +9,83 @@
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-Regression script for RISC-V random instruction generator
"""
+import logging
from enum import Enum, auto
+from bitstring import BitArray
+from pygen_src.target.rv32i import riscv_core_setting as rcs
+
+
+class mem_region_t:
+ name = 0
+ size_in_bytes = auto()
+ xwr = auto()
+
+
+class satp_mode_t(Enum):
+ BARE = 0b0000
+ SV32 = 0b0001
+ SV39 = 0b1000
+ SV48 = 0b1001
+ SV57 = 0b1010
+ SV64 = 0b1011
+
+
+class f_rounding_mode_t(Enum):
+ RNE = 0b000
+ RTZ = 0b001
+ RDN = 0b010
+ RUP = 0b011
+ RMM = 0b100
+
+
+class mtvec_mode_t(Enum):
+ DIRECT = 0b00
+ VECTORED = 0b01
+
+
+class imm_t(Enum):
+ IMM = 0
+ UIMM = auto()
+ NZUIMM = auto()
+ NZIMM = auto()
+
+
+class privileged_mode_t(Enum):
+ USER_MODE = 0b00
+ SUPERVISOR_MODE = 0b01
+ RESERVED_MODE = 0b10
+ MACHINE_MODE = 0b11
+
+
+class riscv_instr_group_t(Enum):
+ RV32I = 0
+ RV64I = auto()
+ RV32M = auto()
+ RV64M = auto()
+ RV32A = auto()
+ RV64A = auto()
+ RV32F = auto()
+ RV32FC = auto()
+ RV64F = auto()
+ RV32D = auto()
+ RV32DC = auto()
+ RV64D = auto()
+ RV32C = auto()
+ RV64C = auto()
+ RV128I = auto()
+ RV128C = auto()
+ RV32V = auto()
+ RV32B = auto()
+ RV64V = auto()
+ RV64B = auto()
+ RV32X = auto()
+ RV64X = auto()
class riscv_instr_name_t(Enum):
- # RV32I instructions
LUI = 0
AUIPC = auto()
JAL = auto()
@@ -68,7 +134,6 @@
CSRRWI = auto()
CSRRSI = auto()
CSRRCI = auto()
- # RV32B instructions
ANDN = auto()
ORN = auto()
XNOR = auto()
@@ -126,7 +191,6 @@
BFP = auto()
SHFLI = auto()
UNSHFLI = auto()
- # RV64B instructions
ADDIWU = auto()
SLLIU_W = auto()
ADDWU = auto()
@@ -170,7 +234,6 @@
PACKW = auto()
PACKUW = auto()
BFPW = auto()
- # RV32M instructions
MUL = auto()
MULH = auto()
MULHSU = auto()
@@ -179,13 +242,11 @@
DIVU = auto()
REM = auto()
REMU = auto()
- # RV64M instructions
MULW = auto()
DIVW = auto()
DIVUW = auto()
REMW = auto()
REMUW = auto()
- # RV32F instructions
FLW = auto()
FSW = auto()
FMADD_S = auto()
@@ -212,12 +273,10 @@
FCVT_S_W = auto()
FCVT_S_WU = auto()
FMV_W_X = auto()
- # RV64F instruction
FCVT_L_S = auto()
FCVT_LU_S = auto()
FCVT_S_L = auto()
FCVT_S_LU = auto()
- # RV32D instructions
FLD = auto()
FSD = auto()
FMADD_D = auto()
@@ -244,14 +303,12 @@
FCVT_WU_D = auto()
FCVT_D_W = auto()
FCVT_D_WU = auto()
- # RV64D
FCVT_L_D = auto()
FCVT_LU_D = auto()
FMV_X_D = auto()
FCVT_D_L = auto()
FCVT_D_LU = auto()
FMV_D_X = auto()
- # RV64I
LWU = auto()
LD = auto()
SD = auto()
@@ -264,7 +321,6 @@
SLLW = auto()
SRLW = auto()
SRAW = auto()
- # RV32C
C_LW = auto()
C_SW = auto()
C_LWSP = auto()
@@ -292,7 +348,6 @@
C_JAL = auto()
C_JR = auto()
C_JALR = auto()
- # RV64C
C_ADDIW = auto()
C_SUBW = auto()
C_ADDW = auto()
@@ -300,7 +355,6 @@
C_SD = auto()
C_LDSP = auto()
C_SDSP = auto()
- # RV128C
C_SRLI64 = auto()
C_SRAI64 = auto()
C_SLLI64 = auto()
@@ -308,17 +362,14 @@
C_SQ = auto()
C_LQSP = auto()
C_SQSP = auto()
- # RV32FC
C_FLW = auto()
C_FSW = auto()
C_FLWSP = auto()
C_FSWSP = auto()
- # RV32DC
C_FLD = auto()
C_FSD = auto()
C_FLDSP = auto()
C_FSDSP = auto()
- # RV32A
LR_W = auto()
SC_W = auto()
AMOSWAP_W = auto()
@@ -330,7 +381,6 @@
AMOMAX_W = auto()
AMOMINU_W = auto()
AMOMAXU_W = auto()
- # RV64A
LR_D = auto()
SC_D = auto()
AMOSWAP_D = auto()
@@ -342,7 +392,6 @@
AMOMAX_D = auto()
AMOMINU_D = auto()
AMOMAXU_D = auto()
- # Vector instructions
VSETVL = auto()
VSETVLI = auto()
VADD = auto()
@@ -395,12 +444,6 @@
VWMACC = auto()
VWMACCSU = auto()
VWMACCUS = auto()
- '''
- VQMACCU = auto()
- VQMACC = auto()
- VQMACCSU = auto()
- VQMACCUS = auto()
- '''
VMERGE = auto()
VMV = auto()
VSADDU = auto()
@@ -464,7 +507,6 @@
VFNCVT_F_X_W = auto()
VFNCVT_F_F_W = auto()
VFNCVT_ROD_F_F_W = auto()
- # Vector reduction instruction
VREDSUM_VS = auto()
VREDMAXU_VS = auto()
VREDMAX_VS = auto()
@@ -480,7 +522,6 @@
VFREDMAX_VS = auto()
VFWREDOSUM_VS = auto()
VFWREDSUM_VS = auto()
- # Vector mask instruction
VMAND_MM = auto()
VMNAND_MM = auto()
VMANDNOT_MM = auto()
@@ -496,7 +537,6 @@
VMSOF_M = auto()
VIOTA_M = auto()
VID_V = auto()
- # Vector permutation instruction
VMV_X_S = auto()
VMV_S_X = auto()
VFMV_F_S = auto()
@@ -511,19 +551,120 @@
VMV2R_V = auto()
VMV4R_V = auto()
VMV8R_V = auto()
- # Supervisor instruction
DRET = auto()
MRET = auto()
URET = auto()
SRET = auto()
WFI = auto()
SFENCE_VMA = auto()
- # Custom instructions
- # import riscv_custom_instr_enum #TODO: Right now it's not working as expected fix it
- # You can add other instructions here
INVALID_INSTR = auto()
+class riscv_reg_t(Enum):
+ ZERO = 0
+ RA = auto()
+ SP = auto()
+ GP = auto()
+ TP = auto()
+ T0 = auto()
+ T1 = auto()
+ T2 = auto()
+ S0 = auto()
+ S1 = auto()
+ A0 = auto()
+ A1 = auto()
+ A2 = auto()
+ A3 = auto()
+ A4 = auto()
+ A5 = auto()
+ A6 = auto()
+ A7 = auto()
+ S2 = auto()
+ S3 = auto()
+ S4 = auto()
+ S5 = auto()
+ S6 = auto()
+ S7 = auto()
+ S8 = auto()
+ S9 = auto()
+ S10 = auto()
+ S11 = auto()
+ T3 = auto()
+ T4 = auto()
+ T5 = auto()
+ T6 = auto()
+
+
+class riscv_fpr_t(Enum):
+ FT0 = 0
+ FT1 = auto()
+ FT2 = auto()
+ FT3 = auto()
+ FT4 = auto()
+ FT5 = auto()
+ FT6 = auto()
+ FT7 = auto()
+ FS0 = auto()
+ FS1 = auto()
+ FA0 = auto()
+ FA1 = auto()
+ FA2 = auto()
+ FA3 = auto()
+ FA4 = auto()
+ FA5 = auto()
+ FA6 = auto()
+ FA7 = auto()
+ FS2 = auto()
+ FS3 = auto()
+ FS4 = auto()
+ FS5 = auto()
+ FS6 = auto()
+ FS7 = auto()
+ FS8 = auto()
+ FS9 = auto()
+ FS10 = auto()
+ FS11 = auto()
+ FT8 = auto()
+ FT9 = auto()
+ FT10 = auto()
+ FT11 = auto()
+
+
+class riscv_vreg_t(Enum):
+ V0 = 0
+ V1 = auto()
+ V2 = auto()
+ V3 = auto()
+ V4 = auto()
+ V5 = auto()
+ V6 = auto()
+ V7 = auto()
+ V8 = auto()
+ V9 = auto()
+ V10 = auto()
+ V11 = auto()
+ V12 = auto()
+ V13 = auto()
+ V14 = auto()
+ V15 = auto()
+ V16 = auto()
+ V17 = auto()
+ V18 = auto()
+ V19 = auto()
+ V20 = auto()
+ V21 = auto()
+ V22 = auto()
+ V23 = auto()
+ V24 = auto()
+ V25 = auto()
+ V26 = auto()
+ V27 = auto()
+ V28 = auto()
+ V29 = auto()
+ V30 = auto()
+ V31 = auto()
+
+
class riscv_instr_format_t(Enum):
J_FORMAT = 0
U_FORMAT = auto()
@@ -532,7 +673,6 @@
R_FORMAT = auto()
S_FORMAT = auto()
R4_FORMAT = auto()
- # Compressed instruction format
CI_FORMAT = auto()
CB_FORMAT = auto()
CJ_FORMAT = auto()
@@ -542,14 +682,29 @@
CS_FORMAT = auto()
CSS_FORMAT = auto()
CIW_FORMAT = auto()
- # Vector instruction format
VSET_FORMAT = auto()
VA_FORMAT = auto()
- VS2_FORMAT = auto() # op vd,vs2
+ VS2_FORMAT = auto()
VL_FORMAT = auto()
VS_FORMAT = auto()
+class va_variant_t(Enum):
+ VV = 0
+ VI = auto()
+ VX = auto()
+ VF = auto()
+ WV = auto()
+ WI = auto()
+ WX = auto()
+ VVM = auto()
+ VIM = auto()
+ VXM = auto()
+ VFM = auto()
+ VS = auto()
+ VM = auto()
+
+
class riscv_instr_category_t(Enum):
LOAD = 0
STORE = auto()
@@ -566,37 +721,510 @@
CHANGELEVEL = auto()
TRAP = auto()
INTERRUPT = auto()
- # `VECTOR_INCLUDE("riscv_instr_pkg_inc_riscv_instr_category_t.sv") TODO: Fix this
- AMO = auto() # (last one)
+ AMO = auto()
+# typedef bit[11:0] riscv_csr_t;
-class riscv_instr_group_t(Enum):
- RV32I = 0
- RV64I = auto()
- RV32M = auto()
- RV64M = auto()
- RV32A = auto()
- RV64A = auto()
- RV32F = auto()
- RV32FC = auto()
- RV64F = auto()
- RV32D = auto()
- RV32DC = auto()
- RV64D = auto()
- RV32C = auto()
- RV64C = auto()
- RV128I = auto()
- RV128C = auto()
- RV32V = auto()
- RV32B = auto()
- RV64V = auto()
- RV64B = auto()
- RV32X = auto()
- RV64X = auto()
+class privileged_reg_t(Enum):
+ USTATUS = 0x000
+ UIE = 0x004
+ UTVEC = 0x005
+ USCRATCH = 0x040
+ UEPC = 0x041
+ UCAUSE = 0x042
+ UTVAL = 0x043
+ UIP = 0x044
+ FFLAGS = 0x001
+ FRM = 0x002
+ FCSR = 0x003
+ CYCLE = 0xC00
+ TIME = 0xC01
+ INSTRET = 0xC02
+ HPMCOUNTER3 = 0xC03
+ HPMCOUNTER4 = 0xC04
+ HPMCOUNTER5 = 0xC05
+ HPMCOUNTER6 = 0xC06
+ HPMCOUNTER7 = 0xC07
+ HPMCOUNTER8 = 0xC08
+ HPMCOUNTER9 = 0xC09
+ HPMCOUNTER10 = 0xC0A
+ HPMCOUNTER11 = 0xC0B
+ HPMCOUNTER12 = 0xC0C
+ HPMCOUNTER13 = 0xC0D
+ HPMCOUNTER14 = 0xC0E
+ HPMCOUNTER15 = 0xC0F
+ HPMCOUNTER16 = 0xC10
+ HPMCOUNTER17 = 0xC11
+ HPMCOUNTER18 = 0xC12
+ HPMCOUNTER19 = 0xC13
+ HPMCOUNTER20 = 0xC14
+ HPMCOUNTER21 = 0xC15
+ HPMCOUNTER22 = 0xC16
+ HPMCOUNTER23 = 0xC17
+ HPMCOUNTER24 = 0xC18
+ HPMCOUNTER25 = 0xC19
+ HPMCOUNTER26 = 0xC1A
+ HPMCOUNTER27 = 0xC1B
+ HPMCOUNTER28 = 0xC1C
+ HPMCOUNTER29 = 0xC1D
+ HPMCOUNTER30 = 0xC1E
+ HPMCOUNTER31 = 0xC1F
+ CYCLEH = 0xC80
+ TIMEH = 0xC81
+ INSTRETH = 0xC82
+ HPMCOUNTER3H = 0xC83
+ HPMCOUNTER4H = 0xC84
+ HPMCOUNTER5H = 0xC85
+ HPMCOUNTER6H = 0xC86
+ HPMCOUNTER7H = 0xC87
+ HPMCOUNTER8H = 0xC88
+ HPMCOUNTER9H = 0xC89
+ HPMCOUNTER10H = 0xC8A
+ HPMCOUNTER11H = 0xC8B
+ HPMCOUNTER12H = 0xC8C
+ HPMCOUNTER13H = 0xC8D
+ HPMCOUNTER14H = 0xC8E
+ HPMCOUNTER15H = 0xC8F
+ HPMCOUNTER16H = 0xC90
+ HPMCOUNTER17H = 0xC91
+ HPMCOUNTER18H = 0xC92
+ HPMCOUNTER19H = 0xC93
+ HPMCOUNTER20H = 0xC94
+ HPMCOUNTER21H = 0xC95
+ HPMCOUNTER22H = 0xC96
+ HPMCOUNTER23H = 0xC97
+ HPMCOUNTER24H = 0xC98
+ HPMCOUNTER25H = 0xC99
+ HPMCOUNTER26H = 0xC9A
+ HPMCOUNTER27H = 0xC9B
+ HPMCOUNTER28H = 0xC9C
+ HPMCOUNTER29H = 0xC9D
+ HPMCOUNTER30H = 0xC9E
+ HPMCOUNTER31H = 0xC9F
+ SSTATUS = 0x100
+ SEDELEG = 0x102
+ SIDELEG = 0x103
+ SIE = 0x104
+ STVEC = 0x105
+ SCOUNTEREN = 0x106
+ SSCRATCH = 0x140
+ SEPC = 0x141
+ SCAUSE = 0x142
+ STVAL = 0x143
+ SIP = 0x144
+ SATP = 0x180
+ MVENDORID = 0xF11
+ MARCHID = 0xF12
+ MIMPID = 0xF13
+ MHARTID = 0xF14
+ MSTATUS = 0x300
+ MISA = 0x301
+ MEDELEG = 0x302
+ MIDELEG = 0x303
+ MIE = 0x304
+ MTVEC = 0x305
+ MCOUNTEREN = 0x306
+ MSCRATCH = 0x340
+ MEPC = 0x341
+ MCAUSE = 0x342
+ MTVAL = 0x343
+ MIP = 0x344
+ PMPCFG0 = 0x3A0
+ PMPCFG1 = 0x3A1
+ PMPCFG2 = 0x3A2
+ PMPCFG3 = 0x3A3
+ PMPADDR0 = 0x3B0
+ PMPADDR1 = 0x3B1
+ PMPADDR2 = 0x3B2
+ PMPADDR3 = 0x3B3
+ PMPADDR4 = 0x3B4
+ PMPADDR5 = 0x3B5
+ PMPADDR6 = 0x3B6
+ PMPADDR7 = 0x3B7
+ PMPADDR8 = 0x3B8
+ PMPADDR9 = 0x3B9
+ PMPADDR10 = 0x3BA
+ PMPADDR11 = 0x3BB
+ PMPADDR12 = 0x3BC
+ PMPADDR13 = 0x3BD
+ PMPADDR14 = 0x3BE
+ PMPADDR15 = 0x3BF
+ MCYCLE = 0xB00
+ MINSTRET = 0xB02
+ MHPMCOUNTER3 = 0xB03
+ MHPMCOUNTER4 = 0xB04
+ MHPMCOUNTER5 = 0xB05
+ MHPMCOUNTER6 = 0xB06
+ MHPMCOUNTER7 = 0xB07
+ MHPMCOUNTER8 = 0xB08
+ MHPMCOUNTER9 = 0xB09
+ MHPMCOUNTER10 = 0xB0A
+ MHPMCOUNTER11 = 0xB0B
+ MHPMCOUNTER12 = 0xB0C
+ MHPMCOUNTER13 = 0xB0D
+ MHPMCOUNTER14 = 0xB0E
+ MHPMCOUNTER15 = 0xB0F
+ MHPMCOUNTER16 = 0xB10
+ MHPMCOUNTER17 = 0xB11
+ MHPMCOUNTER18 = 0xB12
+ MHPMCOUNTER19 = 0xB13
+ MHPMCOUNTER20 = 0xB14
+ MHPMCOUNTER21 = 0xB15
+ MHPMCOUNTER22 = 0xB16
+ MHPMCOUNTER23 = 0xB17
+ MHPMCOUNTER24 = 0xB18
+ MHPMCOUNTER25 = 0xB19
+ MHPMCOUNTER26 = 0xB1A
+ MHPMCOUNTER27 = 0xB1B
+ MHPMCOUNTER28 = 0xB1C
+ MHPMCOUNTER29 = 0xB1D
+ MHPMCOUNTER30 = 0xB1E
+ MHPMCOUNTER31 = 0xB1F
+ MCYCLEH = 0xB80
+ MINSTRETH = 0xB82
+ MHPMCOUNTER3H = 0xB83
+ MHPMCOUNTER4H = 0xB84
+ MHPMCOUNTER5H = 0xB85
+ MHPMCOUNTER6H = 0xB86
+ MHPMCOUNTER7H = 0xB87
+ MHPMCOUNTER8H = 0xB88
+ MHPMCOUNTER9H = 0xB89
+ MHPMCOUNTER10H = 0xB8A
+ MHPMCOUNTER11H = 0xB8B
+ MHPMCOUNTER12H = 0xB8C
+ MHPMCOUNTER13H = 0xB8D
+ MHPMCOUNTER14H = 0xB8E
+ MHPMCOUNTER15H = 0xB8F
+ MHPMCOUNTER17H = 0xB90
+ MHPMCOUNTER18H = 0xB91
+ MHPMCOUNTER19H = 0xB92
+ MHPMCOUNTER20H = 0xB93
+ MHPMCOUNTER21H = 0xB94
+ MHPMCOUNTER22H = 0xB95
+ MHPMCOUNTER23H = 0xB96
+ MHPMCOUNTER24H = 0xB97
+ MHPMCOUNTER25H = 0xB98
+ MHPMCOUNTER26H = 0xB99
+ MHPMCOUNTER27H = 0xB9A
+ MHPMCOUNTER28H = 0xB9B
+ MHPMCOUNTER29H = 0xB9C
+ MHPMCOUNTER30H = 0xB9D
+ MHPMCOUNTER31H = 0xB9E
+ MCOUNTINHIBIT = 0x320F
+ MHPMEVENT3 = 0x323
+ MHPMEVENT4 = 0x324
+ MHPMEVENT5 = 0x325
+ MHPMEVENT6 = 0x326
+ MHPMEVENT7 = 0x327
+ MHPMEVENT8 = 0x328
+ MHPMEVENT9 = 0x329
+ MHPMEVENT10 = 0x32A
+ MHPMEVENT11 = 0x32B
+ MHPMEVENT12 = 0x32C
+ MHPMEVENT13 = 0x32D
+ MHPMEVENT14 = 0x32E
+ MHPMEVENT15 = 0x32F
+ MHPMEVENT16 = 0x330
+ MHPMEVENT17 = 0x331
+ MHPMEVENT18 = 0x332
+ MHPMEVENT19 = 0x333
+ MHPMEVENT20 = 0x334
+ MHPMEVENT21 = 0x335
+ MHPMEVENT22 = 0x336
+ MHPMEVENT23 = 0x337
+ MHPMEVENT24 = 0x338
+ MHPMEVENT25 = 0x339
+ MHPMEVENT26 = 0x33A
+ MHPMEVENT27 = 0x33B
+ MHPMEVENT28 = 0x33C
+ MHPMEVENT29 = 0x33D
+ MHPMEVENT30 = 0x33E
+ MHPMEVENT31 = 0x33F
+ TSELECT = 0x7A0
+ TDATA1 = 0x7A1
+ TDATA2 = 0x7A2
+ TDATA3 = 0x7A3
+ DCSR = 0x7B0
+ DPC = 0x7B1
+ DSCRATCH0 = 0x7B2
+ DSCRATCH1 = 0x7B3
+ VSTART = 0x008
+ VXSTAT = 0x009
+ VXRM = 0x00A
+ VL = 0xC20
+ VTYPE = 0xC21
+ VLENB = 0xC22
-class imm_t(Enum):
- IMM = 0 # Signed immediate
- UIMM = auto() # Unsigned immediate
- NZUIMM = auto() # Non-zero unsigned immediate
- NZIMM = auto() # Non-zero signed immediate
+class privileged_reg_fld_t(Enum):
+ RSVD = 0
+ MXL = auto()
+ EXTENSION = auto()
+ MODE = auto()
+ ASID = auto()
+ PPN = auto()
+
+
+class privileged_level_t(Enum):
+ M_LEVEL = 0b11
+ S_LEVEL = 0b01
+ U_LEVEL = 0b00
+
+
+class reg_field_access_t(Enum):
+ WPRI = 0
+ WLRL = auto()
+ WARL = auto()
+
+
+class riscv_pseudo_instr_name_t(Enum):
+ LI = 0
+ LA = auto()
+
+
+class data_pattern_t(Enum):
+ RAND_DATA = 0
+ ALL_ZERO = auto()
+ INCR_VAL = auto()
+
+
+class pte_permission_t(Enum):
+ NEXT_LEVEL_PAGE = 0b000
+ READ_ONLY_PAGE = 0b001
+ READ_WRITE_PAGE = 0b011
+ EXECUTE_ONLY_PAGE = 0b100
+ READ_EXECUTE_PAGE = 0b101
+ R_W_EXECUTE_PAGE = 0b111
+
+
+class interrupt_cause_t(Enum):
+ U_SOFTWARE_INTR = 0x0
+ S_SOFTWARE_INTR = 0x1
+ M_SOFTWARE_INTR = 0x3
+ U_TIMER_INTR = 0x4
+ S_TIMER_INTR = 0x5
+ M_TIMER_INTR = 0x7
+ U_EXTERNAL_INTR = 0x8
+ S_EXTERNAL_INTR = 0x9
+ M_EXTERNAL_INTR = 0xB
+
+
+class exception_cause_t(Enum):
+ INSTRUCTION_ADDRESS_MISALIGNED = 0x0
+ INSTRUCTION_ACCESS_FAULT = 0x1
+ ILLEGAL_INSTRUCTION = 0x2
+ BREAKPOINT = 0x3
+ LOAD_ADDRESS_MISALIGNED = 0x4
+ LOAD_ACCESS_FAULT = 0x5
+ STORE_AMO_ADDRESS_MISALIGNED = 0x6
+ STORE_AMO_ACCESS_FAULT = 0x7
+ ECALL_UMODE = 0x8
+ ECALL_SMODE = 0x9
+ ECALL_MMODE = 0xB
+ INSTRUCTION_PAGE_FAULT = 0xC
+ LOAD_PAGE_FAULT = 0xD
+ STORE_AMO_PAGE_FAULT = 0xF
+
+
+class misa_ext_t(Enum):
+ MISA_EXT_A = 0
+ MISA_EXT_B = auto()
+ MISA_EXT_C = auto()
+ MISA_EXT_D = auto()
+ MISA_EXT_E = auto()
+ MISA_EXT_F = auto()
+ MISA_EXT_G = auto()
+ MISA_EXT_H = auto()
+ MISA_EXT_I = auto()
+ MISA_EXT_J = auto()
+ MISA_EXT_K = auto()
+ MISA_EXT_L = auto()
+ MISA_EXT_M = auto()
+ MISA_EXT_N = auto()
+ MISA_EXT_O = auto()
+ MISA_EXT_P = auto()
+ MISA_EXT_Q = auto()
+ MISA_EXT_R = auto()
+ MISA_EXT_S = auto()
+ MISA_EXT_T = auto()
+ MISA_EXT_U = auto()
+ MISA_EXT_V = auto()
+ MISA_EXT_W = auto()
+ MISA_EXT_X = auto()
+ MISA_EXT_Y = auto()
+ MISA_EXT_Z = auto()
+
+
+class hazard_e(Enum):
+ NO_HAZARD = 0
+ RAW_HAZARD = auto()
+ WAR_HAZARD = auto()
+ WAW_HAZARD = auto()
+
+
+class pmp_addr_mode_t(Enum):
+ OFF = 0b00
+ TOR = 0b01
+ NA4 = 0b10
+ NAPOT = 0b11
+
+
+class vtype_t(Enum):
+ ill = 0
+ reserved = auto()
+ vediv = auto()
+ vsew = auto()
+ vlmul = auto()
+
+
+class vxrm_t(Enum):
+ RoundToNearestUp = 0
+ RoundToNearestEven = auto()
+ RoundDown = auto()
+ RoundToOdd = auto()
+
+
+class b_ext_group_t(Enum):
+ ZBB = 0
+ ZBS = auto()
+ ZBP = auto()
+ ZBE = auto()
+ ZBF = auto()
+ ZBC = auto()
+ ZBR = auto()
+ ZBM = auto()
+ ZBT = auto()
+ ZB_TMP = auto()
+
+
+class all_gpr(Enum):
+ ZERO = 0
+ RA = auto()
+ SP = auto()
+ GP = auto()
+ TP = auto()
+ T0 = auto()
+ T1 = auto()
+ T2 = auto()
+ S0 = auto()
+ S1 = auto()
+ A0 = auto()
+ A1 = auto()
+ A2 = auto()
+ A3 = auto()
+ A4 = auto()
+ A5 = auto()
+ A6 = auto()
+ A7 = auto()
+ S2 = auto()
+ S3 = auto()
+ S4 = auto()
+ S5 = auto()
+ S6 = auto()
+ S7 = auto()
+ S8 = auto()
+ S9 = auto()
+ S10 = auto()
+ S11 = auto()
+ T3 = auto()
+ T4 = auto()
+ T5 = auto()
+ T6 = auto()
+
+
+class compressed_gpr(Enum):
+ S0 = 0
+ S1 = auto()
+ A0 = auto()
+ A1 = auto()
+ A2 = auto()
+ A3 = auto()
+ A4 = auto()
+ A5 = auto()
+
+
+class all_categories(Enum):
+ LOAD = 0
+ STORE = auto()
+ SHIFT = auto()
+ ARITHMETIC = auto()
+ LOGICAL = auto()
+ COMPARE = auto()
+ BRANCH = auto()
+ JUMP = auto()
+ SYNCH = auto()
+ SYSTEM = auto()
+ COUNTER = auto()
+ CSR = auto()
+ CHANGELEVEL = auto()
+ TRAP = auto()
+ INTERRUPT = auto()
+ AMO = auto()
+
+def get_val(in_string, hexa=0):
+ if len(in_string) > 2:
+ if "0x" in in_string:
+ out_val = hex(int(in_string, base=16))
+ return out_val
+ if hexa:
+ out_val = hex(int(in_string, base=16))
+ else:
+ out_val = int(in_string)
+ logging.info("riscv_instr_pkg: imm: {} -> {}".format(in_string, out_val))
+ return out_val
+
+class hazard_e(Enum):
+ NO_HAZARD = 0
+ RAW_HAZARD = auto()
+ WAR_HAZARD = auto()
+ WAW_HAZARD = auto()
+
+class riscv_instr_pkg:
+ def __init__(self):
+ self.MPRV_BIT_MASK = BitArray(uint= 0x1 << 0x17, length = rcs.XLEN)
+ self.SUM_BIT_MASK = BitArray(uint = 0x1 << 0x18, length = rcs.XLEN)
+ self.MPP_BIT_MASK = BitArray(uint = 0x3 << 0x11, length = rcs.XLEN)
+ self.MAX_USED_VADDR_BITS = 30
+ self.IMM25_WIDTH = 25
+ self.IMM12_WIDTH = 12
+ self.INSTR_WIDTH = 32
+ self.DATA_WIDTH = 32
+ self.MAX_INSTR_STR_LEN = 11
+ self.LABEL_STR_LEN = 18
+ self.MAX_CALLSTACK_DEPTH = 20
+ self.MAX_SUB_PROGRAM_CNT = 20
+ self.MAX_CALL_PER_FUNC = 5
+ self.indent = self.LABEL_STR_LEN * " "
+
+ def hart_prefix(self, hart = 0):
+ if(rcs.NUM_HARTS <= 1):
+ return ""
+ else:
+ return f"h{hart}_"
+
+ def get_label(self, label, hart=0):
+ return (self.hart_prefix(hart) + label)
+
+ def format_string(self, string, length = 10):
+ formatted_str = length * " "
+ if (int(length) < len(string)):
+ return string
+ formatted_str = string + formatted_str[0: (int(length) - len(string))]
+ return formatted_str
+
+ def format_data(self, data, byte_per_group = 4):
+ string = "0x"
+ for i in range(len(data)):
+ if ((i % byte_per_group == 0) and (i != len(data) - 1) and (i != 0)):
+ string = string + ", 0x"
+ string = string + f"{hex(data[i])}"
+ return string
+
+ def push_gpr_to_kernel_stack(self, status, scratch, mprv, sp, tp, instr):
+ pass
+
+ def pop_gpr_from_kernel_stack(self, status, scratch, mprv, sp, tp, instr):
+ pass
+
+
+pkg_ins = riscv_instr_pkg()
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py
new file mode 100644
index 0000000..d0ca1c4
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py
@@ -0,0 +1,89 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+"""
+import logging
+from pygen_src.riscv_instr_stream import riscv_rand_instr_stream
+from pygen_src.riscv_instr_pkg import pkg_ins
+
+
+class riscv_instr_sequence:
+
+ def __init__(self):
+ self.instr_cnt = 0
+ self.instr_stream = riscv_rand_instr_stream()
+ self.is_main_program = 0
+ self.is_debug_program = 0
+ self.label_name = ""
+ self.instr_string_list = [] # Save the instruction list
+ self.program_stack_len = 0 # Stack space allocated for this program
+ self.directed_instr = [] # List of all directed instruction stream
+ self.illegal_instr_pct = 0 # Percentage of illegal instructions
+ self.hint_instr_pct = 0 # Percentage of hint instructions
+
+ def gen_instr(self, is_main_program, no_branch = 1):
+ self.is_main_program = is_main_program
+ self.instr_stream.initialize_instr_list(self.instr_cnt)
+ logging.info("Start generating %d instruction" % len(self.instr_stream.instr_list))
+ self.instr_stream.gen_instr(no_branch = no_branch, no_load_store = 1,
+ is_debug_program = self.is_debug_program)
+
+ if not is_main_program:
+ self.gen_stack_enter_instr()
+ self.gen_stack_exit_instr()
+
+ # TODO
+ def gen_stack_enter_instr(self):
+ pass
+
+ # TODO
+ def gen_stack_exit_instr(self):
+ pass
+
+ # TODO
+ def post_process_instr(self):
+ pass
+
+ # TODO
+ def insert_jump_instr(self):
+ pass
+
+ def generate_instr_stream(self, no_label = 0):
+ prefix = ''
+ string = ''
+ self.instr_string_list.clear()
+
+ for i in range(len(self.instr_stream.instr_list)):
+ if i == 0:
+ if no_label:
+ prefix = pkg_ins.format_string(string = ' ', length = pkg_ins.LABEL_STR_LEN)
+ else:
+ prefix = pkg_ins.format_string(string = '{}:'.format(
+ self.label_name), length = pkg_ins.LABEL_STR_LEN)
+
+ self.instr_stream.instr_list[i].has_label = 1
+ else:
+ if(self.instr_stream.instr_list[i].has_label):
+ prefix = pkg_ins.format_string(string = '{}'.format(
+ self.instr_stream.instr_list[i].label), length = pkg_ins.LABEL_STR_LEN)
+ else:
+ prefix = pkg_ins.format_string(string = " ", length = pkg_ins.LABEL_STR_LEN)
+ string = prefix + self.instr_stream.instr_list[i].convert2asm()
+ self.instr_string_list.append(string)
+
+ # TODO
+ def generate_return_routine(self):
+ pass
+
+ # TODO
+ def insert_illegal_hint_instr(self):
+ pass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py
new file mode 100644
index 0000000..ad4852a
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py
@@ -0,0 +1,232 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+"""
+import random
+import logging
+import sys
+from pygen_src.riscv_instr_pkg import riscv_instr_name_t,\
+ riscv_instr_category_t, riscv_reg_t
+from pygen_src.isa.riscv_instr import riscv_instr, riscv_instr_ins
+from pygen_src.riscv_instr_gen_config import cfg
+
+
+class riscv_instr_stream:
+ '''
+ Base class for RISC-V instruction stream
+ A instruction stream here is a queue of RISC-V basic instructions.
+ This class also provides some functions to manipulate the instruction stream, like insert a new
+ instruction, mix two instruction streams etc.
+ '''
+
+ def __init__(self):
+ self.instr_list = []
+ self.instr_cnt = 0
+ self.label = " "
+ # User can specify a small group of available registers to generate various hazard condition
+ self.avail_regs = []
+ # Some additional reserved registers that should not be used as rd register
+ # by this instruction stream
+ self.reserved_rd = []
+ self.hart = 0
+
+ def initialize_instr_list(self, instr_cnt):
+ self.instr_list.clear()
+ self.instr_cnt = instr_cnt
+ self.create_instr_instance()
+
+ def create_instr_instance(self):
+ for i in range(self.instr_cnt):
+ instr = riscv_instr()
+ self.instr_list.append(instr)
+
+ def insert_instr(self, instr, idx = -1):
+ """
+ Insert an instruction to the existing instruction stream at the given index
+ When index is -1, the instruction is injected at a random location
+ """
+ current_instr_cnt = len(self.instr_list)
+ if idx == -1:
+ idx = random.randint(0, current_instr_cnt - 1)
+ while self.instr_list[idx].atomic:
+ idx = idx + 1
+ if idx == (current_instr_cnt - 1):
+ self.instr_list.append(instr)
+ return
+ elif idx > current_instr_cnt or idx < 0:
+ logging.error("Cannot insert instr:%0s at idx %0d", instr.convert2asm(), idx)
+ sys.exit(1)
+ self.instr_list.insert(idx, instr)
+
+ def insert_instr_stream(self, new_instr, idx = -1, replace = 0):
+ """
+ Insert an instruction to the existing instruction stream at the given index
+ When index is -1, the instruction is injected at a random location
+ When replace is 1, the original instruction at the inserted position will be replaced
+ """
+ current_instr_cnt = len(self.instr_list)
+
+ if current_instr_cnt == 0:
+ self.instr_list = new_instr
+ return
+
+ if idx == -1:
+ idx = random.randint(0, current_instr_cnt - 1)
+ # cares must be taken to avoid targeting
+ # an atomic instruction (while atomic, find a new idx)
+ for i in range(10):
+ if self.instr_list[idx].atomic:
+ break
+ idx = random.randint(0, current_instr_cnt - 1)
+ if self.instr_list[idx].atomic:
+ for i in range(len(self.instr_list)):
+ if not self.instr_list[i].atomic:
+ idx = i
+ break
+ if self.instr_list[idx].atomic:
+ logging.critical("Cannot inject the instruction")
+ sys.exit(1)
+ elif idx > current_instr_cnt or idx < 0:
+ logging.error("Cannot insert instr stream at idx %0d", idx)
+ sys.exit(1)
+ # When replace is 1, the original instruction at this index will be removed.
+ # The label of the original instruction will be copied to the head
+ # of inserted instruction stream.
+ if replace:
+ new_instr[0].label = self.instr_list[idx].label
+ new_instr[0].has_label = self.instr_list[idx].has_label
+ if idx == 0:
+ self.instr_list = new_instr + self.instr_list[idx + 1:current_instr_cnt - 1]
+ else:
+ self.instr_list = self.instr_list[0:idx - 1] + new_instr + \
+ self.instr_list[idx + 1:current_instr_cnt - 1]
+ else:
+ if idx == 0:
+ self.instr_list = new_instr + self.instr_list[idx:current_instr_cnt - 1]
+ else:
+ self.instr_list = self.instr_list[0:idx - 1] + new_instr + \
+ self.instr_list[idx:current_instr_cnt - 1]
+
+ def mix_instr_stream(self, new_instr, contained = 0):
+ """
+ Mix the input instruction stream with the original instruction, the instruction order is
+ preserved. When 'contained' is set, the original instruction stream will be inside the
+ new instruction stream with the first and last instruction from the input instruction
+ stream.
+ new_instr is a list of riscv_instr
+ """
+ current_instr_cnt = len(self.instr_list)
+ new_instr_cnt = len(new_instr)
+ insert_instr_position = [0] * new_instr_cnt
+ if len(insert_instr_position) > 0:
+ insert_instr_position.sort()
+ for i in range(new_instr_cnt):
+ insert_instr_position[i] = random.randint(0, current_instr_cnt)
+ if len(insert_instr_position) > 0:
+ insert_instr_position.sort()
+ if contained:
+ insert_instr_position[0] = 0
+ if new_instr_cnt > 1:
+ insert_instr_position[new_instr_cnt - 1] = current_instr_cnt - 1
+ for i in range(len(new_instr)):
+ self.insert_instr(new_instr[i], insert_instr_position[i] + i)
+
+ def convert2string(self):
+ s = ""
+ for i in range(len(self.instr_list)):
+ s = s + self.instr_list[i].convert2asm() + "\n"
+ return s
+
+
+class riscv_rand_instr_stream(riscv_instr_stream):
+ """
+ Generate a random instruction stream based on the configuration
+ There are two ways to use this class to generate instruction stream
+ 1. For short instruction stream, you can call randomize() directly.
+ 2. For long instruction stream (>1K), randomize() all instructions together might take a
+ long time for the constraint solver. In this case, you can call gen_instr to generate
+ instructions one by one. The time only grows linearly with the instruction count
+ """
+
+ def __init__(self):
+ # calling super constructor
+ super().__init__()
+ self.kernel_mode = 0
+ self.allowed_instr = []
+ self.category_dist = []
+
+ def create_instr_instance(self):
+ for i in range(self.instr_cnt):
+ self.instr_list.append(None)
+
+ def setup_allowed_instr(self, no_branch = 0, no_load_store = 1):
+ self.allowed_instr = riscv_instr_ins.basic_instr
+ if no_branch == 0:
+ self.allowed_instr.extend(
+ riscv_instr_ins.instr_category[riscv_instr_category_t.BRANCH.name])
+ if no_load_store == 0:
+ self.allowed_instr.extend(
+ riscv_instr_ins.instr_category[riscv_instr_category_t.LOAD.name])
+ self.allowed_instr.extend(
+ riscv_instr_ins.instr_category[riscv_instr_category_t.STORE.name])
+ self.setup_instruction_dist(no_branch, no_load_store)
+
+ # TODO
+ def randomize_avail_regs(self):
+ pass
+
+ def setup_instruction_dist(self, no_branch = 0, no_load_store = 1):
+ if cfg.dist_control_mode:
+ self.category_dist = cfg.category_dist
+ if no_branch:
+ self.category_dist[riscv_instr_category_t.BRANCH.name] = 0
+ if no_load_store:
+ self.category_dist[riscv_instr_category_t.LOAD.name] = 0
+ self.category_dist[riscv_instr_category_t.STORE.name] = 0
+ logging.info("setup_instruction_dist: %0d", len(self.category_dist))
+
+ def gen_instr(self, no_branch = 0, no_load_store = 1, is_debug_program = 0):
+ self.setup_allowed_instr(no_branch, no_load_store)
+ for i in range(len(self.instr_list)):
+ self.instr_list[i] = self.randomize_instr(self.instr_list[i], is_debug_program)
+ while self.instr_list[-1].category == riscv_instr_category_t.BRANCH:
+ self.instr_list.pop()
+ if len(self.instr_list) == 0:
+ break
+
+ def randomize_instr(self, instr, is_in_debug = 0):
+ exclude_instr = []
+ is_SP_in_reserved_rd = riscv_reg_t.SP in self.reserved_rd
+ is_SP_in_reserved_regs = riscv_reg_t.SP in cfg.reserved_regs
+ is_SP_in_avail_regs = riscv_reg_t.SP in self.avail_regs
+ if ((is_SP_in_reserved_rd or is_SP_in_reserved_regs) or
+ (len(self.avail_regs) > 0 and not is_SP_in_avail_regs)):
+ exclude_instr.append(riscv_instr_name_t.C_ADDI4SPN.name)
+ exclude_instr.append(riscv_instr_name_t.C_ADDI16SP.name)
+ exclude_instr.append(riscv_instr_name_t.C_LWSP.name)
+ exclude_instr.append(riscv_instr_name_t.C_LDSP.name)
+ if is_in_debug and (not cfg.enable_ebreak_in_debug_rom):
+ exclude_instr.append(riscv_instr_name_t.EBREAK.name)
+ exclude_instr.append(riscv_instr_name_t.C_EBREAK.name)
+ instr = riscv_instr_ins.get_rand_instr(
+ include_instr = self.allowed_instr, exclude_instr = exclude_instr)
+ instr = self.randomize_gpr(instr)
+ return instr
+
+ def randomize_gpr(self, instr):
+ # TODO
+ """
+ PyVSC library doesn't support inline randomization for list of enum types.
+ The randomization is done directly here.
+ it will be updated once randomization for list of enum types supports in PyVSC.
+ """
+ instr.randomize()
+ return instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py
new file mode 100644
index 0000000..dbf7a2d
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py
@@ -0,0 +1,31 @@
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+"""
+
+XLEN = 32
+
+implemented_csr = ['MVENDORID', 'MARCHID', 'MIMPID', 'MHARTID', 'MSTATUS', 'MISA', 'MIE',
+ 'MTVEC', 'MCOUNTEREN', 'MSCRATCH', 'MEPC', 'MCAUSE', 'MTVAL', 'MIP']
+
+SATP_MODE = 'BARE'
+
+supported_isa = ['RV32I']
+
+supported_privileged_mode = ['MACHINE_MODE']
+
+NUM_HARTS = 1
+
+support_pmp = 0
+
+unsupported_instr = []
+
+support_umode_trap = 0
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
index 67bcb6a..7fa6b1e 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py
@@ -1,29 +1,31 @@
-"""
-Copyright 2020 Google LLC
-Copyright 2020 PerfectVIPs Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-Regression script for RISC-V random instruction generator
-
-"""
-
-import sys
-sys.path.append("../../")
-from pygen_src.isa.rv32i_instr import * # NOQA
-from pygen_src.isa.riscv_instr import cfg, riscv_instr_ins # NOQA
-
-
-class riscv_instr_base_test:
- def __init__(self):
- pass
-
- for _ in range(cfg.num_of_test):
- riscv_instr_ins.create_instr_list(cfg)
+"""
+Copyright 2020 Google LLC
+Copyright 2020 PerfectVIPs Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+"""
+
+import sys
+sys.path.append("../../")
+from pygen_src.riscv_instr_gen_config import cfg # NOQA
+from pygen_src.isa.rv32i_instr import * # NOQA
+from pygen_src.isa.riscv_instr import riscv_instr_ins # NOQA
+from pygen_src.riscv_asm_program_gen import riscv_asm_program_gen # NOQA
+
+
+class riscv_instr_base_test:
+ def __init__(self):
+ pass
+ asm = riscv_asm_program_gen()
+ for _ in range(cfg.num_of_tests):
+ cfg.randomize()
+ riscv_instr_ins.create_instr_list(cfg)
+ test_name = "riscv_asm_test_{}.S".format(_)
+ asm.gen_program()
+ asm.gen_test_file(test_name)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py
new file mode 100644
index 0000000..8cc37c5
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py
@@ -0,0 +1,407 @@
+# Lint as: python3
+"""Tests for riscv_instr_cov."""
+import sys
+import os
+import logging
+import argparse
+import vsc # PyVSC library
+import csv # Python library to read/write from/to CSV files
+from bitstring import BitArray
+from pygen.pygen_src.isa.riscv_instr_cov import *
+from pygen.pygen_src.riscv_instr_pkg import *
+from pygen.pygen_src.target.rv32i import riscv_core_setting as rcs
+
+
+
+logging.basicConfig(filename='logging.log',level=logging.DEBUG)
+
+class riscv_instr():
+ """ Class for a riscv instruction; data parsed from the CSV file will fill
+ different fields of an instruction """
+ # class attr. to keep track of reg_name:reg_value throughout the program
+ gpr_state = {}
+ def __init__(self, instr_name):
+ self.pc = 0 # Program counter (PC) of the instruction
+ self.instr = instr_name
+ self.gpr = None # destination operand of the instruction
+ self.csr = None
+ self.binary = 0 # Instruction binary
+ self.mode = None # Instruction mode
+ self.trace = "None" # String representation of the instruction
+ self.operands = "None" # Instruction operands (srcss/dests)
+ self.pad = None # Not used
+
+ self.rs1_value = None
+ self.rs2_value = None
+ self.rs3_value = None
+ self.rd_value = None
+ self.fs1_value = None
+ self.fs2_value = None
+ self.fs3_value = None
+ self.fd_value = None
+
+ self.mem_addr = None
+ self.unaligned_pc = 0
+ self.unaligned_mem_access = 0
+ self.compressed = 0
+ self.branch_hit = 0
+ self.div_result = None
+ self.rs1_sign = None
+ self.rs2_sign = None
+ self.rs3_sign = None
+ self.fs1_sign = None
+ self.fs2_sign = None
+ self.fs3_sign = None
+ self.imm_sign = None
+ self.rd_sign = None
+ self.gpr_hazard = None
+ self.lsu_hazard = None
+ self.rs1_special_value = None
+ self.rs2_special_value = None
+ self.rs3_special_value = None
+ self.rd_special_value = None
+ self.imm_special_value = None
+ self.compare_result = None
+ self.logical_similarity = None
+
+ # TODO: add & map...
+ #self.imm
+ #self.format
+ #self.category
+
+ def pre_sample(self):
+ unaligned_pc = self.pc[-2:] != "00"
+ self.rs1_sign = self.get_operand_sign(self.rs1_value)
+ self.rs2_sign = self.get_operand_sign(self.rs2_value)
+ self.rs3_sign = self.get_operand_sign(self.rs3_value)
+ self.rd_sign = self.get_operand_sign(self.rd_value)
+ self.fs1_sign = self.get_operand_sign(self.fs1_value)
+ self.fs2_sign = self.get_operand_sign(self.fs2_value)
+ self.fs3_sign = self.get_operand_sign(self.fs3_value)
+ self.fd_sign = self.get_operand_sign(self.fd_value)
+ self.imm_sign = self.get_imm_sign(self.imm)
+ self.rs1_special_value = self.get_operand_special_value(self.rs1_value)
+ self.rd_special_value = self.get_operand_special_value(self.rd_value)
+ self.rs2_special_value = self.get_operand_special_value(self.rs2_value)
+ self.rs3_special_value = self.get_operand_special_value(self.rs3_value)
+ if (self.format != riscv_instr_format_t.R_FORMAT and
+ self.format != riscv_instr_format_t.CR_FORMAT):
+ self.imm_special_value = self.get_imm_special_val(self.imm)
+ if self.category in [riscv_instr_category_t.COMPARE,
+ riscv_instr_category_t.BRANCH]:
+ self.compare_result = self.get_compare_result()
+ if self.category in [riscv_instr_category_t.LOAD,
+ riscv_instr_category_t.STORE]:
+ self.mem_addr = self.rs1_value + self.imm
+ self.unaligned_mem_access = self.is_unaligned_mem_access()
+ if self.unaligned_mem_access:
+ logging.info("Unaligned: {}, mem_addr: {}".format(
+ self.instr, self.mem_addr))
+ if self.category == riscv_instr_category_t.LOGICAL:
+ self.logical_similarity = self.get_logical_similarity()
+ if self.category == riscv_instr_category_t.BRANCH:
+ self.branch_hit = self.is_branch_hit()
+ #TODO: string > enumeration
+ if self.instr in ["DIV", "DIVU", "REM", "REMU", "DIVW", "DIVUW",
+ "REMW", "REMUW"]:
+ self.div_result = self.get_div_result()
+
+ def get_operand_sign(self, operand):
+ #TODO: change operand to vsc.bit_t
+ out = BitArray(int=operand.val, length=rcs.XLEN)
+ if out[0]:
+ return operand_sign_e["NEGATIVE"]
+ else:
+ return operand_sign_e["POSITIVE"]
+
+ def is_unaligned_mem_access(self):
+ #TODO: string > enumeration
+ if (self.instr in ["LWU", "LD", "SD", "C_LD", "C_SD"] and
+ self.mem_addr % 8 != 0):
+ return True
+ elif (self.instr in ["LW", "SW", "C_LW", "C_SW"] and
+ self.mem_addr % 4 != 0):
+ return True
+ elif (self.instr in ["LH", "LHU", "SH"] and
+ self.mem_addr % 2 != 0):
+ return True
+ return False
+
+ def get_imm_sign(self, imm):
+ #TODO: change imm to vsc.int_t(32)
+ out = BitArray(int=imm.val, length=rcs.XLEN)
+ if out[0]:
+ return operand_sign_e["NEGATIVE"]
+ else:
+ return operand_sign_e["POSITIVE"]
+
+ def get_div_result(self):
+ #TODO: change rs2_value to vsc.int_t(32)
+ if self.rs2_value.val == 0:
+ return div_result_e["DIV_BY_ZERO"]
+ elif self.rs2_value.val == 1 and self.rs1_value.val == (1 << (rcs.XLEN-1)):
+ return div_result_e["DIV_OVERFLOW"]
+ else:
+ return div_result_e["DIV_NORMAL"]
+
+ def get_operand_special_value(self, operand):
+ if operand.val == 0:
+ return special_val_e["ZERO_VAL"]
+ elif operand.val == 1 << (rcs.XLEN-1):
+ return special_val_e["MIN_VAL"]
+ elif operand.val == 1 >> 1:
+ return special_val_e["MAX_VAL"]
+ else:
+ return special_val_e["NORMAL_VAL"]
+
+ def get_imm_special_val(self, imm):
+ if imm.val == 0:
+ return special_val_e["ZERO_VAL"]
+ elif self.format == riscv_instr_format_t.U_FORMAT:
+ # unsigned immediate value
+ # TODO: self.imm_len
+ max = vsc.int_t(32, (1 << self.imm_len)-1)
+ if imm.val == 0:
+ return special_val_e["MIN_VAL"]
+ if imm.val == max.val:
+ return special_val_e["MAX_VAL"]
+ else:
+ # signed immediate value
+ max = vsc.int_t(32, (2 ** (self.imm_len - 1)) - 1)
+ min = vsc.int_t(32, -2 ** (self.imm_len - 1))
+ if min.val == imm.val:
+ return special_val_e["MIN_VAL"]
+ if max.val == imm.val:
+ return special_val_e["MAX_VAL"]
+ return special_val_e["NORMAL_VAL"]
+
+ def get_compare_result(self):
+ val1 = vsc.int_t(rcs.XLEN)
+ val2 = vsc.int_t(rcs.XLEN)
+ val1.val = self.rs1_value.val
+ val2.val = self.imm.val if (
+ self.format == riscv_instr_format_t.I_FORMAT) \
+ else self.rs2_value.val
+ if val1.val == val2.val:
+ return compare_result_e["EQUAL"]
+ elif val1.val < val2.val:
+ return compare_result_e["SMALLER"]
+ else:
+ return compare_result_e["LARGER"]
+
+ def is_branch_hit(self):
+ # TODO: string/enumeration
+ if self.instr == "BEQ":
+ return self.rs1_value.val == self.rs2_value.val
+ elif self.instr == "C_BEQZ":
+ return self.rs1_value.val == 0
+ elif self.instr == "BNE":
+ return self.rs1_value.val != self.rs2_value.val
+ elif self.instr == "C_BNEZ":
+ return self.rs1_value.val != 0
+ elif self.instr == "BLT" or self.instr == "BLTU":
+ return self.rs1_value.val < self.rs2_value.val
+ elif self.instr == "BGE" or self.instr == "BGEU":
+ return self.rs1_value.val >= self.rs2_value.val
+ else:
+ logging.error("Unexpected instruction {}".format(self.instr))
+
+ def get_logical_similarity(self):
+ val1 = vsc.int_t(rcs.XLEN, self.rs1_value.val)
+ val2 = vsc.int_t(rcs.XLEN)
+ val2.val = (self.imm.val if self.format == riscv_instr_format_t.I_FORMAT
+ else self.rs2_value.val)
+ temp = bin(val1.val ^ val2.val)
+ bit_difference = len([[ones for ones in temp[2:] if ones=='1']])
+ if val1.val == val2.val:
+ return logical_similarity_e["IDENTICAL"]
+ elif bit_difference == 32:
+ return logical_similarity_e["OPPOSITE"]
+ elif bit_difference < 5:
+ return logical_similarity_e["SIMILAR"]
+ else:
+ return logical_similarity_e["DIFFERENT"]
+
+ def check_hazard_condition(self, pre_instr):
+ # TODO: has_rd(), has_rs1, has_rs2, rd, category, convert2asm (from IG)
+ if pre_instr.has_rd():
+ if ((self.has_rs1 and self.rs1 == pre_instr.rd) or
+ (self.has_rs2 and self.rs1 == pre_instr.rd)):
+ self.gpr_hazard = hazard_e["RAW_HAZARD"]
+ elif self.has_rd and self.rd == pre_instr.rd:
+ self.gpr_hazard = hazard_e["WAW_HAZARD"]
+ elif (self.has_rd and
+ ((pre_instr.has_rs1 and (pre_instr.rs1 == self.rd)) or
+ (pre_instr.has_rs2 and (pre_instr.rs2 == self.rd)))):
+ self.gpr_hazard = hazard_e["WAR_HAZARD"]
+ else:
+ self.gpr_hazard = hazard_e["NO_HAZARD"]
+ if self.category == riscv_instr_category_t.LOAD:
+ # TODO: change mem_addr to vsc type
+ if (pre_instr.category == riscv_instr_category_t.STORE and
+ pre_instr.mem_addr == self.mem_addr):
+ self.lsu_hazard = hazard_e["RAW_HAZARD"]
+ else:
+ self.lsu_hazard = hazard_e["NO_HAZARD"]
+ if self.category == riscv_instr_category_t.STORE:
+ if (pre_instr.category == riscv_instr_category_t.STORE and
+ pre_instr.mem_addr == self.mem_addr):
+ self.lsu_hazard = hazard_e["WAW_HAZARD"]
+ elif (pre_instr.category == riscv_instr_category_t.LOAD and
+ pre_instr.mem_addr == self.mem_addr):
+ self.lsu_hazard = hazard_e["WAR_HAZARD"]
+ else:
+ self.lsu_hazard = hazard_e["NO_HAZARD"]
+ logging.info("Pre: {}, Cur: {}, Hazard: {}/{}".format(
+ pre_instr.convert2asm(), self.convert2asm(),
+ self.gpr_hazard.name, self.lsu_hazard.name))
+
+ def update_src_regs(self, operands):
+ pass
+
+ def update_dst_regs(self, reg_name, val_str):
+ pass
+
+class riscv_instr_cov_test():
+ """ Main class for applying the functional coverage test """
+ def __init__(self, argv):
+ self.trace = {}
+ self.csv_trace = argv
+ self.entry_cnt, self.total_entry_cnt, self.skipped_cnt, \
+ self.unexpected_illegal_instr_cnt = 0, 0, 0, 0
+
+ def run_phase(self):
+ if not self.csv_trace:
+ sys.exit("No CSV file found!")
+ logging.info("{} CSV trace files to be "
+ "processed...\n".format(len(self.csv_trace)))
+ expect_illegal_instr = False
+ # Assuming we get list of csv files pathname from cov.py in argv
+ for csv_file in self.csv_trace:
+ with open("{}".format(csv_file)) as trace_file:
+ self.entry_cnt = 0
+ header = []
+ entry = []
+ csv_reader = csv.reader(trace_file, delimiter=',')
+ line_count = 0
+ # Get the header line
+ for row in csv_reader:
+ if line_count == 0:
+ header = row
+ logging.info("Header: {}".format(header))
+ else:
+ entry = row
+ if len(entry) != len(header):
+ logging.info("Skipping malformed entry[{}]: "
+ "[{}]".format(self.entry_cnt, entry))
+ self.skipped_cnt += 1
+ else:
+ self.trace["csv_entry"] = row
+ for idx in range(len(header)):
+ if "illegal" in entry[idx]:
+ expect_illegal_instr = True
+ self.trace[header[idx]] = entry[idx]
+ if header[idx] != "pad":
+ logging.info("{} = {}".format(header[idx],
+ entry[idx]))
+ self.post_process_trace()
+ if self.trace["instr"] in ["li", "ret", "la"]:
+ pass
+ if "amo" in self.trace["instr"] or \
+ "lr" in self.trace["instr"] or \
+ "sc" in self.trace["instr"]:
+ # TODO: Enable functional coverage for AMO test
+ pass
+ if not self.sample():
+ if not expect_illegal_instr:
+ logging.error("Found unexpected illegal "
+ "instr: {} "
+ "[{}]".format(self.trace[
+ "instr"],entry))
+ self.unexpected_illegal_instr_cnt += 1
+ self.entry_cnt += 1
+ line_count += 1
+ logging.info("[{}]: {} instr processed".format(csv_file,
+ self.entry_cnt))
+ self.total_entry_cnt += self.entry_cnt
+ logging.info("Finished processing {} trace CSV, {} "
+ "instructions".format(len(self.csv_trace),
+ self.total_entry_cnt))
+ if self.skipped_cnt > 0 or self.unexpected_illegal_instr_cnt > 0:
+ logging.error("{} instruction skipped, {} illegal "
+ "instructions".format(self.skipped_cnt),
+ self.unexpected_illegal_instr_cnt)
+
+ def post_process_trace(self):
+ pass
+
+ def sample(self):
+ instr_name, binary = "", ""
+ binary = get_val(self.trace["binary"], hexa=1)
+ if binary[-2:] != "11": #TODO: and RV32C in supported_isa
+ #TODO: sample compressed instruction
+ pass
+ if binary[-2:] == "11":
+ #TODO: sampling
+ pass
+ #TODO: buch of if statements to check if the instruction name is valid
+ # and is a member of registered ones
+ instr_name = self.process_instr_name(self.trace["instr"])
+ instruction = riscv_instr(instr_name)
+ #TODO: check the instruction group...
+ self.assign_trace_info_to_instr(instruction)
+ #TODO: instruction.pre_sample() and sample(instruction)
+ return True
+
+ def assign_trace_info_to_instr(self, instruction):
+ operands, gpr_update, pair = [], [], []
+ instruction.pc = get_val(self.trace["pc"], hexa=1)
+ instruction.binary = get_val(self.trace["binary"], hexa=1)
+ instruction.gpr = self.trace["gpr"]
+ instruction.csr = self.trace["csr"]
+ instruction.mode = self.trace["mode"]
+ instruction.trace = self.trace["instr_str"]
+ instruction.operands = self.trace["operand"]
+ operands = self.trace["operand"].split(",")
+ instruction.update_src_regs(operands)
+ gpr_update = self.trace["gpr"].split(";")
+ if len(gpr_update) == 1 and gpr_update[0] == "":
+ gpr_update = []
+ for dest in gpr_update:
+ pair = dest.split(":")
+ if len(pair) != 2:
+ logging.error("Illegal gpr update format: {}".format(dest))
+ instruction.update_dst_regs(pair[0], pair[1])
+ instruction.pad = self.trace["pad"]
+
+ def process_instr_name(self, instruction):
+ instruction = instruction.upper()
+ instruction.replace(".", "_")
+ instruction = self.update_instr_name(instruction)
+ return instruction
+
+ def update_instr_name(self, instruction):
+ switcher = {
+ # Rename to new name as ovpsim still uses old name
+ "FMV_S_X": "FMV_W_X",
+ "FMV_X_S": "FMV_X_W",
+ # Convert pseudoinstructions
+ "FMV_S": "FSGNJ_S",
+ "FABS_S": "FSGNJX_S",
+ "FNEG_S": "FSGNJN_S",
+ "FMV_D": "FSGNJ_D",
+ "FABS_D": "FSGNJX_D",
+ "FNEG_D": "FSGNJN_D",
+ }
+ # if instruction is not present in the dictionary,second argument well
+ # be assigned as default value of passed argument
+ instruction = switcher.get(instruction, instruction)
+ return instruction
+
+
+def main(argv):
+ cov_test = riscv_instr_cov_test(argv)
+ cov_test.run_phase()
+
+if __name__ == "__main__":
+ main(sys.argv)
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/requirements.txt b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/requirements.txt
index a6b0913..3483387 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/requirements.txt
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/requirements.txt
@@ -7,3 +7,4 @@
sphinx_rtd_theme
rst2pdf
flake8
+pyvsc
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
index 0a18c15..22c7b7f 100755
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
@@ -111,7 +111,7 @@
return super.convert2asm(prefix);
end
- if (comment != "") asm_str_final = {asm_str, " #", comment};
+ if (comment != "") asm_str_final = {asm_str_final, " #", comment};
return asm_str_final.tolower();
endfunction
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
index 88e1325..c444adc 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_instr.sv
@@ -128,7 +128,9 @@
!(!cfg.enable_floating_point &&
(instr_inst.group inside {RV32F, RV64F, RV32D, RV64D})) &&
!(!cfg.enable_vector_extension &&
- (instr_inst.group inside {RVV}))
+ (instr_inst.group inside {RVV})) &&
+ !(cfg.vector_instr_only &&
+ !(instr_inst.group inside {RVV}))
) begin
instr_category[instr_inst.category].push_back(instr_name);
instr_group[instr_inst.group].push_back(instr_name);
@@ -267,13 +269,28 @@
return instr_h;
endfunction : get_rand_instr
- static function riscv_instr get_load_store_instr(riscv_instr_name_t load_store_instr[] = {});
+ static function riscv_instr get_load_store_instr(riscv_instr_name_t load_store_instr[$] = {});
riscv_instr instr_h;
int unsigned idx;
+ int unsigned i;
riscv_instr_name_t name;
if (load_store_instr.size() == 0) begin
load_store_instr = {instr_category[LOAD], instr_category[STORE]};
end
+ // Filter out unsupported load/store instruction
+ if (unsupported_instr.size() > 0) begin
+ while (i < load_store_instr.size()) begin
+ if (load_store_instr[i] inside {unsupported_instr}) begin
+ load_store_instr.delete(i);
+ end else begin
+ i++;
+ end
+ end
+ end
+ if (load_store_instr.size() == 0) begin
+ $error("Cannot find available load/store instruction");
+ $fatal(1);
+ end
idx = $urandom_range(0, load_store_instr.size()-1);
name = load_store_instr[idx];
// Shallow copy for all relevant fields, avoid using create() to improve performance
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_vector_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_vector_instr.sv
index f76f53c..5c23d86 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_vector_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/riscv_vector_instr.sv
@@ -37,6 +37,14 @@
bit is_quad_widening_instr;
bit is_convert_instr;
va_variant_t allowed_va_variants[$];
+ string sub_extension;
+ rand bit [2:0] nfields; // Used by segmented load/store
+
+ constraint avoid_reserved_vregs_c {
+ if (m_cfg.vector_cfg.reserved_vregs.size() > 0) {
+ !(vd inside {m_cfg.vector_cfg.reserved_vregs});
+ }
+ }
constraint va_variant_c {
if (has_va_variant) {
@@ -170,6 +178,28 @@
}
}
+ // Section 7.8. Vector Load/Store Segment Instructions
+ // The LMUL setting must be such that LMUL * NFIELDS <= 8
+ // Vector register numbers accessed by the segment load or store would increment
+ // cannot past 31
+ constraint nfields_c {
+ if (check_sub_extension(sub_extension, "zvlsseg")) {
+ if (m_cfg.vector_cfg.vtype.vlmul < 8) {
+ (nfields + 1) * m_cfg.vector_cfg.vtype.vlmul <= 8;
+ if (category == LOAD) {
+ vd + nfields <= 31;
+ }
+ if (category == STORE) {
+ vs3 + nfields <= 31;
+ }
+ // TODO: Check gcc compile issue with nfields == 0
+ nfields > 0;
+ } else {
+ nfields == 0;
+ }
+ }
+ }
+
constraint vmv_alignment_c {
if (instr_name == VMV2R_V) {
int'(vs2) % 2 == 0;
@@ -223,10 +253,18 @@
}
}
- // TODO: Check why this is needed?
constraint vector_load_store_mask_overlap_c {
+ // TODO: Check why this is needed?
if (category == STORE) {
(vm == 0) -> (vs3 != 0);
+ vs2 != vs3;
+ }
+ // 7.8.3 For vector indexed segment loads, the destination vector register groups
+ // cannot overlap the source vectorregister group (specied by vs2), nor can they
+ // overlap the mask register if masked
+ // AMO instruction uses indexed address mode
+ if (format inside {VLX_FORMAT, VAMO_FORMAT}) {
+ vd != vs2;
}
}
@@ -332,22 +370,65 @@
end
end
VL_FORMAT: begin
- asm_str = $sformatf("%0s %s,(%s)", get_instr_name(), vd.name(), rs1.name());
+ if (sub_extension == "zvlsseg") begin
+ asm_str = $sformatf("%0s %s,(%s)", add_nfields(get_instr_name(), "vlseg"),
+ vd.name(), rs1.name());
+ end else begin
+ asm_str = $sformatf("%0s %s,(%s)", get_instr_name(), vd.name(), rs1.name());
+ end
end
VS_FORMAT: begin
- asm_str = $sformatf("%0s %s,(%s)", get_instr_name(), vs3.name(), rs1.name());
+ if (sub_extension == "zvlsseg") begin
+ asm_str = $sformatf("%0s %s,(%s)", add_nfields(get_instr_name(), "vsseg"),
+ vs3.name(), rs1.name());
+ end else begin
+ asm_str = $sformatf("%0s %s,(%s)", get_instr_name(), vs3.name(), rs1.name());
+ end
end
VLS_FORMAT: begin
- asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(), vd.name(), rs1.name(), rs2.name());
+ if (sub_extension == "zvlsseg") begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s", add_nfields(get_instr_name(), "vlsseg"),
+ vd.name(), rs1.name(), rs2.name());
+ end else begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(),
+ vd.name(), rs1.name(), rs2.name());
+ end
end
VSS_FORMAT: begin
- asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(), vs3.name(), rs1.name(), rs2.name());
+ if (sub_extension == "zvlsseg") begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s", add_nfields(get_instr_name(), "vssseg"),
+ vs3.name(), rs1.name(), rs2.name());
+ end else begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(),
+ vs3.name(), rs1.name(), rs2.name());
+ end
end
- VLV_FORMAT: begin
- asm_str = $sformatf("%0s,%0s,(%0s),%0s", get_instr_name(), vd.name(), rs1.name(), vs2.name());
+ VLX_FORMAT: begin
+ if (sub_extension == "zvlsseg") begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s", add_nfields(get_instr_name(), "vlxseg"),
+ vd.name(), rs1.name(), vs2.name());
+ end else begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(),
+ vd.name(), rs1.name(), vs2.name());
+ end
end
- VSV_FORMAT: begin
- asm_str = $sformatf("%0s,%0s,(%0s),%0s", get_instr_name(), vs3.name(), rs1.name(), vs2.name());
+ VSX_FORMAT: begin
+ if (sub_extension == "zvlsseg") begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s", add_nfields(get_instr_name(), "vsxseg"),
+ vs3.name(), rs1.name(), vs2.name());
+ end else begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(),
+ vs3.name(), rs1.name(), vs2.name());
+ end
+ end
+ VAMO_FORMAT: begin
+ if (wd) begin
+ asm_str = $sformatf("%0s %0s,(%0s),%0s,%0s", get_instr_name(), vd.name(),
+ rs1.name(), vs2.name(), vd.name());
+ end else begin
+ asm_str = $sformatf("%0s x0,(%0s),%0s,%0s", get_instr_name(),
+ rs1.name(), vs2.name(), vs3.name());
+ end
end
default: begin
`uvm_fatal(`gfn, $sformatf("Unsupported format %0s", format.name()))
@@ -379,6 +460,9 @@
has_fs3 = 0;
has_fd = 0;
has_imm = 0;
+ if (sub_extension != "zvlsseg") begin
+ nfields.rand_mode(0);
+ end
if ((name.substr(0, 1) == "VW") || (name.substr(0, 2) == "VFW")) begin
is_widening_instr = 1'b1;
end
@@ -416,4 +500,13 @@
end
endfunction
+ function string add_nfields(string instr_name, string prefix);
+ string suffix = instr_name.substr(prefix.len(), instr_name.len() - 1);
+ return $sformatf("%0s%0d%0s", prefix, nfields + 1, suffix);
+ endfunction
+
+ function bit check_sub_extension(string s, string literal);
+ return s == literal;
+ endfunction
+
endclass : riscv_vector_instr
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32v_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32v_instr.sv
index 2a3eb7e..cd5e6ae 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32v_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/isa/rv32v_instr.sv
@@ -212,7 +212,7 @@
`DEFINE_VA_INSTR(VLW_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VSW_V, VS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VLBU_V, VL_FORMAT, LOAD, RVV)
-`DEFINE_VA_INSTR(VLHU_V, VS_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLHU_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLWU_V, VL_FORMAT, LOAD, RVV)
// Section 7.5 - Vector Strided Instructions
`DEFINE_VA_INSTR(VLSB_V, VLS_FORMAT, LOAD, RVV)
@@ -227,21 +227,21 @@
`DEFINE_VA_INSTR(VSSW_V, VSS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSSE_V, VSS_FORMAT, STORE, RVV)
// Section 7.6 - Vector Indexed Instructions
-`DEFINE_VA_INSTR(VLXB_V, VLV_FORMAT, LOAD, RVV)
-`DEFINE_VA_INSTR(VLXH_V, VLV_FORMAT, LOAD, RVV)
-`DEFINE_VA_INSTR(VLXW_V, VLV_FORMAT, LOAD, RVV)
-`DEFINE_VA_INSTR(VLXBU_V, VLV_FORMAT, LOAD, RVV)
-`DEFINE_VA_INSTR(VLXHU_V, VLV_FORMAT, LOAD, RVV)
-`DEFINE_VA_INSTR(VLXWU_V, VLV_FORMAT, LOAD, RVV)
-`DEFINE_VA_INSTR(VLXE_V, VLV_FORMAT, LOAD, RVV)
-`DEFINE_VA_INSTR(VSXB_V, VSV_FORMAT, STORE, RVV)
-`DEFINE_VA_INSTR(VSXH_V, VSV_FORMAT, STORE, RVV)
-`DEFINE_VA_INSTR(VSXW_V, VSV_FORMAT, STORE, RVV)
-`DEFINE_VA_INSTR(VSXE_V, VSV_FORMAT, STORE, RVV)
-`DEFINE_VA_INSTR(VSUXB_V, VSV_FORMAT, STORE, RVV)
-`DEFINE_VA_INSTR(VSUXH_V, VSV_FORMAT, STORE, RVV)
-`DEFINE_VA_INSTR(VSUXW_V, VSV_FORMAT, STORE, RVV)
-`DEFINE_VA_INSTR(VSUXE_V, VSV_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VLXB_V, VLX_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXH_V, VLX_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXW_V, VLX_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXBU_V, VLX_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXHU_V, VLX_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXWU_V, VLX_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VLXE_V, VLX_FORMAT, LOAD, RVV)
+`DEFINE_VA_INSTR(VSXB_V, VSX_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSXH_V, VSX_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSXW_V, VSX_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSXE_V, VSX_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSUXB_V, VSX_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSUXH_V, VSX_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSUXW_V, VSX_FORMAT, STORE, RVV)
+`DEFINE_VA_INSTR(VSUXE_V, VSX_FORMAT, STORE, RVV)
// Section 7.7 - Vector Unit-Stride Fault-Only-First Loads
`DEFINE_VA_INSTR(VLBFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLHFF_V, VL_FORMAT, LOAD, RVV)
@@ -250,3 +250,75 @@
`DEFINE_VA_INSTR(VLHUFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLWUFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLEFF_V, VL_FORMAT, LOAD, RVV)
+// Section 7.8 - Vector Load/Store Segment Instructions (Zvlsseg)
+// 7.8.1. Vector Unit Strided Segment Loads and Stores
+`DEFINE_VA_INSTR(VLSEGE_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSSEGE_V, VS_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGB_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSSEGB_V, VS_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGH_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSSEGH_V, VS_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGW_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSSEGW_V, VS_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGBU_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGHU_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGWU_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGBFF_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGHFF_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGWFF_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGBUFF_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGHUFF_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGWUFF_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSEGEFF_V, VL_FORMAT, LOAD, RVV, {}, "zvlsseg")
+// 7.8.2. Vector Strided Segment Loads and Stores
+`DEFINE_VA_INSTR(VLSSEGB_V, VLS_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSSEGH_V, VLS_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSSEGW_V, VLS_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSSEGBU_V, VLS_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSSEGHU_V, VLS_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSSEGWU_V, VLS_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLSSEGE_V, VLS_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSSSEGB_V, VSS_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSSSEGH_V, VSS_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSSSEGW_V, VSS_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSSSEGE_V, VSS_FORMAT, STORE, RVV, {}, "zvlsseg")
+// 7.8.3. Vector Indexed Segment Loads and Stores
+`DEFINE_VA_INSTR(VLXSEGB_V, VLX_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLXSEGH_V, VLX_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLXSEGW_V, VLX_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLXSEGBU_V, VLX_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLXSEGHU_V, VLX_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLXSEGWU_V, VLX_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VLXSEGE_V, VLX_FORMAT, LOAD, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSXSEGB_V, VSX_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSXSEGH_V, VSX_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSXSEGW_V, VSX_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSXSEGE_V, VSX_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSUXSEGB_V, VSX_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSUXSEGH_V, VSX_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSUXSEGW_V, VSX_FORMAT, STORE, RVV, {}, "zvlsseg")
+`DEFINE_VA_INSTR(VSUXSEGE_V, VSX_FORMAT, STORE, RVV, {}, "zvlsseg")
+
+// -------------------------------------------------------------------------
+// Section 8. Vector AMO Operations (Zvamo)
+// -------------------------------------------------------------------------
+// 32-bit vector AMOs
+`DEFINE_VA_INSTR(VAMOSWAPW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOADDW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOXORW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOANDW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOORW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOMINW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOMAXW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOMINUW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOMAXUW_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+// SEW-bit vector AMOs
+`DEFINE_VA_INSTR(VAMOSWAPE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOADDE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOXORE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOANDE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOORE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOMINE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOMAXE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOMINUE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
+`DEFINE_VA_INSTR(VAMOMAXUE_V, VAMO_FORMAT, AMO, RVV, {}, "zvamo")
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv
index 4258854..77ff06f 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv
@@ -188,3 +188,32 @@
endfunction
endclass : riscv_amo_instr_stream
+
+
+class riscv_vector_amo_instr_stream extends riscv_vector_load_store_instr_stream;
+
+ constraint amo_address_mode_c {
+ // AMO operation only supports word alignment or element alignemt
+ alignment inside {W_ALIGNMENT, E_ALIGNMENT};
+ // AMO operation uses indexed address mode
+ address_mode == INDEXED;
+ // For the 32-bit vector AMO operations, SEW must be at least 32 bit
+ (cfg.vector_cfg.vtype.vsew < 32) -> (alignment != W_ALIGNMENT);
+ }
+
+ `uvm_object_utils(riscv_vector_amo_instr_stream)
+ `uvm_object_new
+
+ virtual function void add_element_vec_load_stores();
+ allowed_instr = {VAMOSWAPE_V, VAMOADDE_V, VAMOXORE_V,
+ VAMOANDE_V, VAMOORE_V, VAMOMINE_V,
+ VAMOMAXE_V, VAMOMINUE_V, VAMOMAXUE_V, allowed_instr};
+ endfunction
+
+ virtual function void add_w_vec_load_stores();
+ allowed_instr = {VAMOSWAPW_V, VAMOADDW_V, VAMOXORW_V,
+ VAMOANDW_V, VAMOORW_V, VAMOMINW_V,
+ VAMOMAXW_V, VAMOMINUW_V, VAMOMAXUW_V, allowed_instr};
+ endfunction
+
+endclass : riscv_vector_amo_instr_stream
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
index d9a4876..8a61e22 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv
@@ -322,7 +322,7 @@
instr_stream.push_back(".option norvc;");
end
str.push_back(".include \"user_init.s\"");
- str.push_back("csrr x5, mhartid");
+ str.push_back($sformatf("csrr x5, 0x%0x", MHARTID));
for (int hart = 0; hart < cfg.num_of_harts; hart++) begin
str = {str, $sformatf("li x6, %0d", hart),
$sformatf("beq x5, x6, %0df", hart)};
@@ -437,7 +437,7 @@
misa[XLEN-1:XLEN-2] = (XLEN == 32) ? 2'b01 :
(XLEN == 64) ? 2'b10 : 2'b11;
if (cfg.check_misa_init_val) begin
- instr_stream.push_back({indent, "csrr x15, misa"});
+ instr_stream.push_back({indent, $sformatf("csrr x15, 0x%0x", MISA)});
end
foreach (supported_isa[i]) begin
case (supported_isa[i]) inside
@@ -457,8 +457,8 @@
if (SUPERVISOR_MODE inside {supported_privileged_mode}) begin
misa[MISA_EXT_S] = 1'b1;
end
- instr_stream.push_back({indent, $sformatf("li x%0d, 0x%0x",cfg.gpr[0], misa)});
- instr_stream.push_back({indent, $sformatf("csrw misa, x%0d",cfg.gpr[0])});
+ instr_stream.push_back({indent, $sformatf("li x%0d, 0x%0x", cfg.gpr[0], misa)});
+ instr_stream.push_back({indent, $sformatf("csrw 0x%0x, x%0d", MISA, cfg.gpr[0])});
endfunction
// Write to the signature_addr with values to indicate to the core testbench
@@ -543,18 +543,49 @@
LMUL = 1;
SEW = (ELEN <= XLEN) ? ELEN : XLEN;
instr_stream.push_back($sformatf("li x%0d, %0d", cfg.gpr[1], cfg.vector_cfg.vl));
- // vec registers will be loaded from a scalar GPR, one element at a time
instr_stream.push_back($sformatf("%svsetvli x%0d, x%0d, e%0d, m%0d, d%0d",
indent, cfg.gpr[0], cfg.gpr[1], SEW, LMUL, EDIV));
instr_stream.push_back("vec_reg_init:");
- for (int v = 1; v < NUM_VEC_GPR; v++) begin
- for (int e = 0; e < num_elements; e++) begin
- if (e > 0) instr_stream.push_back($sformatf("%0svmv.v.v v0, v%0d", indent, v));
- instr_stream.push_back($sformatf("%0sli x%0d, 0x%0x",
- indent, cfg.gpr[0], $urandom_range(0, 2 ** SEW - 1)));
- instr_stream.push_back($sformatf("%0svslide1up.vx v%0d, v0, t0", indent, v));
+
+ // Vector registers will be initialized using one of the following three methods
+ case (cfg.vreg_init_method)
+ SAME_VALUES_ALL_ELEMS: begin
+ for (int v = 0; v < NUM_VEC_GPR; v++) begin
+ instr_stream.push_back($sformatf("%0svmv.v.x v%0d, x%0d", indent, v, v));
+ end
end
- end
+ RANDOM_VALUES_VMV: begin
+ for (int v = 0; v < NUM_VEC_GPR; v++) begin
+ for (int e = 0; e < num_elements; e++) begin
+ if (e > 0) instr_stream.push_back($sformatf("%0svmv.v.v v0, v%0d", indent, v));
+ instr_stream.push_back($sformatf("%0sli x%0d, 0x%0x",
+ indent, cfg.gpr[0], $urandom_range(0, 2 ** SEW - 1)));
+ if (v > 0) begin
+ instr_stream.push_back($sformatf("%0svslide1up.vx v%0d, v0, x%0d",
+ indent, v, cfg.gpr[0]));
+ end else begin
+ instr_stream.push_back($sformatf("%0svslide1up.vx v%0d, v1, x%0d",
+ indent, v, cfg.gpr[0]));
+ end
+ end
+ end
+ end
+ RANDOM_VALUES_LOAD: begin
+ // Select those memory regions that are big enough for load a vreg
+ mem_region_t valid_mem_region [$];
+ foreach (cfg.mem_region[i])
+ if (cfg.mem_region[i].size_in_bytes * 8 >= VLEN) valid_mem_region.push_back(cfg.mem_region[i]);
+
+ if (valid_mem_region.size() == 0)
+ `uvm_fatal(`gfn, "Couldn't find a memory region big enough to initialize the vector registers")
+
+ for (int v = 0; v < NUM_VEC_GPR; v++) begin
+ int region = $urandom_range(0, valid_mem_region.size()-1);
+ instr_stream.push_back($sformatf("%0sla t0, %0s", indent, valid_mem_region[region].name));
+ instr_stream.push_back($sformatf("%0svle.v v%0d, (t0)", indent, v));
+ end
+ end
+ endcase
endfunction
// Initialize floating point general purpose registers
@@ -576,11 +607,9 @@
virtual function void init_floating_point_gpr_with_spf(int int_floating_gpr);
string str;
bit [31:0] imm = get_rand_spf_value();
- int int_gpr = $urandom_range(0, NUM_GPR - 1);
-
- str = $sformatf("%0sli x%0d, %0d", indent, int_gpr, imm);
+ str = $sformatf("%0sli x%0d, %0d", indent, cfg.gpr[0], imm);
instr_stream.push_back(str);
- str = $sformatf("%0sfmv.w.x f%0d, x%0d", indent, int_floating_gpr, int_gpr);
+ str = $sformatf("%0sfmv.w.x f%0d, x%0d", indent, int_floating_gpr, cfg.gpr[0]);
instr_stream.push_back(str);
endfunction
@@ -588,8 +617,8 @@
virtual function void init_floating_point_gpr_with_dpf(int int_floating_gpr);
string str;
bit [63:0] imm = get_rand_dpf_value();
- int int_gpr1 = $urandom_range(1, NUM_GPR - 1);
- int int_gpr2 = $urandom_range(1, NUM_GPR - 1);
+ int int_gpr1 = cfg.gpr[0];
+ int int_gpr2 = cfg.gpr[1];
str = $sformatf("%0sli x%0d, %0d", indent, int_gpr1, imm[63:32]);
instr_stream.push_back(str);
@@ -711,6 +740,8 @@
trap_vector_init(hart);
// Setup PMP CSRs
setup_pmp(hart);
+ // Generate PMPADDR write test sequence
+ gen_pmp_csr_write(hart);
// Initialize PTE (link page table based on their real physical address)
if(cfg.virtual_addr_translation_on) begin
page_table_list.process_page_table(instr);
@@ -718,6 +749,8 @@
end
// Setup mepc register, jump to init entry
setup_epc(hart);
+ // Initialization of any implementation-specific custom CSRs
+ setup_custom_csrs(hart);
// Move privileged mode support to the "safe" section of the program
// if PMP is supported
if (riscv_instr_pkg::support_pmp) begin
@@ -783,7 +816,7 @@
$sformatf("srli x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN - 12)};
end
mode_name = cfg.init_privileged_mode.name();
- instr.push_back($sformatf("csrw mepc, x%0d", cfg.gpr[0]));
+ instr.push_back($sformatf("csrw 0x%0x, x%0d", MEPC, cfg.gpr[0]));
if (!riscv_instr_pkg::support_pmp) begin
instr.push_back($sformatf("j %0sinit_%0s", hart_prefix(hart), mode_name.tolower()));
end
@@ -800,6 +833,34 @@
end
endfunction
+ // Generates a directed stream of instructions to write random values to all supported
+ // pmpaddr CSRs to test write accessibility.
+ // The original CSR values are restored afterwards.
+ virtual function void gen_pmp_csr_write(int hart);
+ string instr[$];
+ if (riscv_instr_pkg::support_pmp && cfg.pmp_cfg.enable_write_pmp_csr) begin
+ cfg.pmp_cfg.gen_pmp_write_test({cfg.scratch_reg, cfg.pmp_reg}, instr);
+ gen_section(get_label("pmp_csr_write_test", hart), instr);
+ end
+ endfunction
+
+ // Handles creation of a subroutine to initialize any custom CSRs
+ virtual function void setup_custom_csrs(int hart);
+ string instr[$];
+ init_custom_csr(instr);
+ gen_section(get_label("custom_csr_setup", hart), instr);
+ endfunction
+
+ // This function should be overridden in the riscv_asm_program_gen extended class
+ // corresponding to the RTL implementation if it has any custom CSRs defined.
+ //
+ // All that needs to be done in the overridden function is to manually create
+ // the instruction strings to set up any custom CSRs and then to push those strings
+ // into the instr queue.
+ virtual function void init_custom_csr(ref string instr[$]);
+ instr.push_back("nop");
+ endfunction
+
//---------------------------------------------------------------------------------------
// Privileged CSR setup for interrupt and exception handling and delegation
//---------------------------------------------------------------------------------------
@@ -1109,9 +1170,9 @@
gen_signature_handshake(instr, CORE_STATUS, EBREAK_EXCEPTION);
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
instr = {instr,
- $sformatf("csrr x%0d, mepc", cfg.gpr[0]),
+ $sformatf("csrr x%0d, 0x%0x", cfg.gpr[0], MEPC),
$sformatf("addi x%0d, x%0d, 4", cfg.gpr[0], cfg.gpr[0]),
- $sformatf("csrw mepc, x%0d", cfg.gpr[0])
+ $sformatf("csrw 0x%0x, x%0d", MEPC, cfg.gpr[0])
};
pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr);
instr.push_back("mret");
@@ -1130,9 +1191,9 @@
gen_signature_handshake(instr, CORE_STATUS, ILLEGAL_INSTR_EXCEPTION);
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
instr = {instr,
- $sformatf("csrr x%0d, mepc", cfg.gpr[0]),
+ $sformatf("csrr x%0d, 0x%0x", cfg.gpr[0], MEPC),
$sformatf("addi x%0d, x%0d, 4", cfg.gpr[0], cfg.gpr[0]),
- $sformatf("csrw mepc, x%0d", cfg.gpr[0])
+ $sformatf("csrw 0x%0x, x%0d", MEPC, cfg.gpr[0])
};
pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr);
instr.push_back("mret");
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv
index 6e6ba85..f07da54 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv
@@ -223,17 +223,17 @@
virtual function void gen_dcsr_ebreak();
if (MACHINE_MODE inside {riscv_instr_pkg::supported_privileged_mode}) begin
str = {$sformatf("li x%0d, 0x8000", cfg.scratch_reg),
- $sformatf("csrs dcsr, x%0d", cfg.scratch_reg)};
+ $sformatf("csrs 0x%0x, x%0d", DCSR, cfg.scratch_reg)};
debug_main = {debug_main, str};
end
if (SUPERVISOR_MODE inside {riscv_instr_pkg::supported_privileged_mode}) begin
str = {$sformatf("li x%0d, 0x2000", cfg.scratch_reg),
- $sformatf("csrs dcsr, x%0d", cfg.scratch_reg)};
+ $sformatf("csrs 0x%0x, x%0d", DCSR, cfg.scratch_reg)};
debug_main = {debug_main, str};
end
if (USER_MODE inside {riscv_instr_pkg::supported_privileged_mode}) begin
str = {$sformatf("li x%0d, 0x1000", cfg.scratch_reg),
- $sformatf("csrs dcsr, x%0d", cfg.scratch_reg)};
+ $sformatf("csrs 0x%0x, x%0d", DCSR, cfg.scratch_reg)};
debug_main = {debug_main, str};
end
endfunction
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
index ac46845..fc30b41 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_defines.svh
@@ -48,7 +48,7 @@
endfunction \
endclass
- `define VA_INSTR_BODY(instr_n, instr_format, instr_category, instr_group, vav, imm_tp = IMM) \
+ `define VA_INSTR_BODY(instr_n, instr_format, instr_category, instr_group, vav, ext = "") \
static bit valid = riscv_instr::register(instr_n); \
`uvm_object_utils(riscv_``instr_n``_instr) \
function new(string name = ""); \
@@ -57,8 +57,9 @@
this.format = ``instr_format; \
this.group = ``instr_group; \
this.category = ``instr_category; \
- this.imm_type = ``imm_tp; \
+ this.imm_type = IMM; \
this.allowed_va_variants = ``vav; \
+ this.sub_extension = ``ext; \
set_imm_len(); \
set_rand_mode(); \
endfunction \
@@ -90,9 +91,9 @@
`INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
// Vector arithmetic instruction
-`define DEFINE_VA_INSTR(instr_n, instr_format, instr_category, instr_group, vav = {}, imm_tp = IMM)\
+`define DEFINE_VA_INSTR(instr_n, instr_format, instr_category, instr_group, vav = {}, ext = "")\
class riscv_``instr_n``_instr extends riscv_vector_instr; \
- `VA_INSTR_BODY(instr_n, instr_format, instr_category, instr_group, vav, imm_tp)
+ `VA_INSTR_BODY(instr_n, instr_format, instr_category, instr_group, vav, ext)
// Custom extension instruction
`define DEFINE_CUSTOM_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
index e06a622..a8dbbe6 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_illegal_instr.sv
@@ -133,6 +133,7 @@
} else {
// Invalid CSR instructions
!(instr_bin[31:20] inside {csrs});
+ !(instr_bin[31:20] inside {custom_csr});
}
}
}
@@ -165,11 +166,13 @@
c_op != 2'b11;
}
- // Avoid generating illegal func3/func7 errors for opcode used by B-extension
+ // Avoid generating illegal func3/func7 errors for opcode used by B-extension for now
+ //
+ // TODO(udi): add support for generating illegal B-extension instructions
constraint b_extension_c {
if (RV32B inside {supported_isa}) {
if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
- !(opcode inside {7'b0011011, 7'b0010011, 7'b0111011});
+ !(opcode inside {7'b0110011, 7'b0010011, 7'b0111011});
}
}
}
@@ -355,8 +358,8 @@
if (riscv_instr_pkg::RV32A inside {riscv_instr_pkg::supported_isa}) begin
legal_opcode = {legal_opcode, 7'b0101111};
end
- if ((riscv_instr_pkg::RV64I inside {riscv_instr_pkg::supported_isa}) ||
- riscv_instr_pkg::RV64M inside {riscv_instr_pkg::supported_isa}) begin
+ if (riscv_instr_pkg::RV64I inside {riscv_instr_pkg::supported_isa} ||
+ riscv_instr_pkg::RV64M inside {riscv_instr_pkg::supported_isa}) begin
legal_opcode = {legal_opcode, 7'b0111011};
end
if (riscv_instr_pkg::RV64I inside {riscv_instr_pkg::supported_isa}) begin
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
index 3200353..5684d69 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv
@@ -39,6 +39,12 @@
// Pattern of data section: RAND_DATA, ALL_ZERO, INCR_VAL
rand data_pattern_t data_page_pattern;
+ // Initialization of the vregs
+ // SAME_VALUES_ALL_ELEMS - Using vmv.v.x to fill all the elements of the vreg with the same value as the one in the GPR selected
+ // RANDOM_VALUES_VMV - Using vmv.v.x + vslide1up.vx to randomize the contents of each vector element
+ // RANDOM_VALUES_LOAD - Using vle.v, same approach as RANDOM_VALUES_VMV but more efficient for big VLEN
+ vreg_init_method_t vreg_init_method = RANDOM_VALUES_VMV;
+
// Associate array for delegation configuration for each exception and interrupt
// When the bit is 1, the corresponding delegation is enabled.
rand bit m_mode_exception_delegation[exception_cause_t];
@@ -66,7 +72,7 @@
// TVEC alignment
// This value is the log_2 of the byte-alignment of TVEC.BASE field
// As per RISC-V privileged spec, default will be set to 2 (4-byte aligned)
- int tvec_alignment = 2;
+ rand int tvec_alignment = 2;
// Floating point rounding mode
rand f_rounding_mode_t fcsr_rm;
@@ -111,10 +117,7 @@
mem_region_t mem_region[$] = '{
'{name:"region_0", size_in_bytes: 4096, xwr: 3'b111},
- '{name:"region_1", size_in_bytes: 4096 * 4, xwr: 3'b111},
- '{name:"region_2", size_in_bytes: 4096 * 2, xwr: 3'b111},
- '{name:"region_3", size_in_bytes: 512, xwr: 3'b111},
- '{name:"region_4", size_in_bytes: 4096, xwr: 3'b111}
+ '{name:"region_1", size_in_bytes: 4096 * 16, xwr: 3'b111}
};
// Dedicated shared memory region for multi-harts atomic operations
@@ -245,6 +248,8 @@
bit enable_floating_point;
// Vector extension support
bit enable_vector_extension;
+ // Only generate vector instructions
+ bit vector_instr_only;
// Bit manipulation extension support
bit enable_b_extension;
b_ext_group_t enable_bitmanip_groups[] = {ZBB, ZBS, ZBP, ZBE, ZBF, ZBC, ZBR, ZBM, ZBT,
@@ -323,6 +328,13 @@
constraint mtvec_c {
mtvec_mode inside {supported_interrupt_mode};
+ if (mtvec_mode == DIRECT) {
+ soft tvec_alignment == 2;
+ } else {
+ // Setting MODE = Vectored may impose an additional alignmentconstraint on BASE,
+ // requiring up to 4×XLEN-byte alignment
+ soft tvec_alignment == $clog2((XLEN * 4) / 8);
+ }
}
constraint mstatus_c {
@@ -501,6 +513,7 @@
`uvm_field_int(max_directed_instr_stream_seq, UVM_DEFAULT)
`uvm_field_int(enable_floating_point, UVM_DEFAULT)
`uvm_field_int(enable_vector_extension, UVM_DEFAULT)
+ `uvm_field_int(vector_instr_only, UVM_DEFAULT)
`uvm_field_int(enable_b_extension, UVM_DEFAULT)
`uvm_field_array_enum(b_ext_group_t, enable_bitmanip_groups, UVM_DEFAULT)
`uvm_field_int(use_push_data_section, UVM_DEFAULT)
@@ -519,7 +532,6 @@
get_bool_arg_value("+enable_timer_irq=", enable_timer_irq);
get_int_arg_value("+num_of_sub_program=", num_of_sub_program);
get_int_arg_value("+instr_cnt=", instr_cnt);
- get_int_arg_value("+tvec_alignment=", tvec_alignment);
get_bool_arg_value("+no_ebreak=", no_ebreak);
get_bool_arg_value("+no_dret=", no_dret);
get_bool_arg_value("+no_wfi=", no_wfi);
@@ -549,6 +561,9 @@
if (this.require_signature_addr) begin
get_hex_arg_value("+signature_addr=", signature_addr);
end
+ if ($value$plusargs("tvec_alignment=%0d", tvec_alignment)) begin
+ tvec_alignment.rand_mode(0);
+ end
get_bool_arg_value("+gen_debug_section=", gen_debug_section);
get_bool_arg_value("+bare_program_mode=", bare_program_mode);
get_int_arg_value("+num_debug_sub_program=", num_debug_sub_program);
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
index de51c44..5fc181f 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_pkg.sv
@@ -36,6 +36,13 @@
bit [2:0] xwr; // Excutable,Writable,Readale
} mem_region_t;
+ // Initialization of the vregs
+ typedef enum {
+ SAME_VALUES_ALL_ELEMS,
+ RANDOM_VALUES_VMV,
+ RANDOM_VALUES_LOAD
+ } vreg_init_method_t;
+
typedef enum bit [3:0] {
BARE = 4'b0000,
SV32 = 4'b0001,
@@ -634,6 +641,72 @@
VLHUFF_V,
VLWUFF_V,
VLEFF_V,
+ // Segmented load/store instruction
+ VLSEGE_V,
+ VSSEGE_V,
+ VLSEGB_V,
+ VSSEGB_V,
+ VLSEGH_V,
+ VSSEGH_V,
+ VLSEGW_V,
+ VSSEGW_V,
+ VLSEGBFF_V,
+ VLSEGHFF_V,
+ VLSEGWFF_V,
+ VLSEGBUFF_V,
+ VLSEGHUFF_V,
+ VLSEGWUFF_V,
+ VLSEGEFF_V,
+ VLSEGBU_V,
+ VLSEGHU_V,
+ VLSEGWU_V,
+ VLSSEGB_V,
+ VLSSEGH_V,
+ VLSSEGW_V,
+ VLSSEGBU_V,
+ VLSSEGHU_V,
+ VLSSEGWU_V,
+ VLSSEGE_V,
+ VSSSEGB_V,
+ VSSSEGH_V,
+ VSSSEGW_V,
+ VSSSEGE_V,
+ VLXSEGB_V,
+ VLXSEGH_V,
+ VLXSEGW_V,
+ VLXSEGBU_V,
+ VLXSEGHU_V,
+ VLXSEGWU_V,
+ VLXSEGE_V,
+ VSXSEGB_V,
+ VSXSEGH_V,
+ VSXSEGW_V,
+ VSXSEGE_V,
+ VSUXSEGB_V,
+ VSUXSEGH_V,
+ VSUXSEGW_V,
+ VSUXSEGE_V,
+ // Vector AMO instruction
+ // 32-bit vector AMOs
+ VAMOSWAPW_V,
+ VAMOADDW_V,
+ VAMOXORW_V,
+ VAMOANDW_V,
+ VAMOORW_V,
+ VAMOMINW_V,
+ VAMOMAXW_V,
+ VAMOMINUW_V,
+ VAMOMAXUW_V,
+ // SEW-bit vector AMOs
+ VAMOSWAPE_V,
+ VAMOADDE_V,
+ VAMOXORE_V,
+ VAMOANDE_V,
+ VAMOORE_V,
+ VAMOMINE_V,
+ VAMOMAXE_V,
+ VAMOMINUE_V,
+ VAMOMAXUE_V,
// Supervisor instruction
DRET,
MRET,
@@ -693,10 +766,11 @@
VS2_FORMAT, // op vd,vs2
VL_FORMAT,
VS_FORMAT,
- VLV_FORMAT,
- VSV_FORMAT,
+ VLX_FORMAT,
+ VSX_FORMAT,
VLS_FORMAT,
- VSS_FORMAT
+ VSS_FORMAT,
+ VAMO_FORMAT
} riscv_instr_format_t;
@@ -962,6 +1036,10 @@
TDATA1 = 'h7A1, // First Debug/Trace trigger data register
TDATA2 = 'h7A2, // Second Debug/Trace trigger data register
TDATA3 = 'h7A3, // Third Debug/Trace trigger data register
+ TINFO = 'h7A4, // Debug trigger info register
+ TCONTROL = 'h7A5, // Debug trigger control register
+ MCONTEXT = 'h7A8, // Machine mode trigger context register
+ SCONTEXT = 'h7AA, // Supervisor mode trigger context register
DCSR = 'h7B0, // Debug control and status register
DPC = 'h7B1, // Debug PC
DSCRATCH0 = 'h7B2, // Debug scratch register
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_sequence.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_sequence.sv
index b343608..64d0e95 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_sequence.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_sequence.sv
@@ -278,7 +278,7 @@
// If PMP is supported, need to align <main> to a 4-byte boundary.
// TODO(udi) - this might interfere with multi-hart programs,
// may need to specifically match hart0.
- if (riscv_instr_pkg::support_pmp && !uvm_re_match("*main*", label_name)) begin
+ if (riscv_instr_pkg::support_pmp && !uvm_re_match(uvm_glob_to_re("*main*"), label_name)) begin
instr_string_list.push_front(".align 2");
end
insert_illegal_hint_instr();
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_stream.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_stream.sv
index 0f737e2..849c76a 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_stream.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_instr_stream.sv
@@ -243,7 +243,7 @@
randomize_gpr(instr);
endfunction
- function void randomize_gpr(ref riscv_instr instr);
+ function void randomize_gpr(riscv_instr instr);
`DV_CHECK_RANDOMIZE_WITH_FATAL(instr,
if (avail_regs.size() > 0) {
if (has_rs1) {
@@ -276,4 +276,29 @@
)
endfunction
+ function riscv_instr get_init_gpr_instr(riscv_reg_t gpr, bit [XLEN-1:0] val);
+ riscv_pseudo_instr li_instr;
+ li_instr = riscv_pseudo_instr::type_id::create("li_instr");
+ `DV_CHECK_RANDOMIZE_WITH_FATAL(li_instr,
+ pseudo_instr_name == LI;
+ rd == gpr;
+ )
+ li_instr.imm_str = $sformatf("0x%0x", val);
+ return li_instr;
+ endfunction
+
+ function void add_init_vector_gpr_instr(riscv_vreg_t gpr, bit [XLEN-1:0] val);
+ riscv_vector_instr instr;
+ $cast(instr, riscv_instr::get_instr(VMV));
+ instr.m_cfg = cfg;
+ instr.avoid_reserved_vregs_c.constraint_mode(0);
+ `DV_CHECK_RANDOMIZE_WITH_FATAL(instr,
+ va_variant == VX;
+ vd == gpr;
+ rs1 == cfg.gpr[0];
+ )
+ instr_list.push_front(instr);
+ instr_list.push_front(get_init_gpr_instr(cfg.gpr[0], val));
+ endfunction
+
endclass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv
index e95e3cc..e2e3733 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv
@@ -519,21 +519,45 @@
endclass
-class riscv_vector_unit_stride_load_store_instr_stream extends riscv_mem_access_stream;
+class riscv_vector_load_store_instr_stream extends riscv_mem_access_stream;
typedef enum {B_ALIGNMENT, H_ALIGNMENT, W_ALIGNMENT, E_ALIGNMENT} alignment_e;
+ typedef enum {UNIT_STRIDED, STRIDED, INDEXED} address_mode_e;
rand alignment_e alignment;
rand int unsigned data_page_id;
rand int unsigned num_mixed_instr;
- rand riscv_reg_t rs1_reg;
+ rand int unsigned stride_byte_offset;
+ rand int unsigned index_addr;
+ rand address_mode_e address_mode;
+ rand riscv_reg_t rs1_reg; // Base address
+ rand riscv_reg_t rs2_reg; // Stride offset
+ riscv_vreg_t vs2_reg; // Index address
constraint vec_mixed_instr_c {
num_mixed_instr inside {[0:10]};
}
- constraint vec_rs1_c {
+ constraint stride_byte_offset_c {
+ // Keep a reasonable byte offset range to avoid vector memory address overflow
+ stride_byte_offset inside {[1 : 32]};
+ (alignment == H_ALIGNMENT) -> (stride_byte_offset % 2 == 0);
+ (alignment == W_ALIGNMENT) -> (stride_byte_offset % 4 == 0);
+ (alignment == E_ALIGNMENT) -> (stride_byte_offset % cfg.vector_cfg.vtype.vsew == 0);
+ }
+
+ constraint index_addr_c {
+ // Keep a reasonable index address range to avoid vector memory address overflow
+ index_addr inside {[1 : 128]};
+ (alignment == H_ALIGNMENT) -> (index_addr % 2 == 0);
+ (alignment == W_ALIGNMENT) -> (index_addr % 4 == 0);
+ (alignment == E_ALIGNMENT) -> (index_addr % cfg.vector_cfg.vtype.vsew == 0);
+ }
+
+ constraint vec_rs_c {
!(rs1_reg inside {cfg.reserved_regs, reserved_rd, ZERO});
+ !(rs2_reg inside {cfg.reserved_regs, reserved_rd, ZERO});
+ rs1_reg != rs2_reg;
}
constraint vec_data_page_id_c {
@@ -547,9 +571,9 @@
int base;
int max_load_store_addr;
- riscv_instr load_store_instr;
+ riscv_vector_instr load_store_instr;
- `uvm_object_utils(riscv_vector_unit_stride_load_store_instr_stream)
+ `uvm_object_utils(riscv_vector_load_store_instr_stream)
`uvm_object_new
virtual function int get_addr_alignment_mask(int alignment_bytes);
@@ -557,18 +581,23 @@
endfunction
function void post_randomize();
- randomize_base();
- // rs1 cannot be modified by other instructions
- if(!(rs1_reg inside {reserved_rd})) reserved_rd = {reserved_rd, rs1_reg};
+ reserved_rd = {reserved_rd, rs1_reg, rs2_reg};
randomize_avail_regs();
gen_load_store_instr();
+ randomize_addr();
add_mixed_instr(num_mixed_instr);
add_rs1_init_la_instr(rs1_reg, data_page_id, base);
+ if (address_mode == STRIDED) begin
+ instr_list.push_front(get_init_gpr_instr(rs2_reg, stride_byte_offset));
+ end else if (address_mode == INDEXED) begin
+ // TODO: Support different index address for each element
+ add_init_vector_gpr_instr(vs2_reg, index_addr);
+ end
super.post_randomize();
endfunction
- virtual function void randomize_base();
- int ss = stride_span();
+ virtual function void randomize_addr();
+ int ss = address_span();
bit success;
repeat (10) begin
@@ -583,7 +612,7 @@
assert (success) else begin
`uvm_fatal(`gfn, $sformatf({"Expected positive value for max_load_store_addr, got %0d.",
" Perhaps more memory needs to be allocated in the data pages for vector loads and stores.",
- "\ndata_page_id:%0d\ndata_page[data_page_id].size_in_bytes:%0d\nstride_span:%0d",
+ "\ndata_page_id:%0d\ndata_page[data_page_id].size_in_bytes:%0d\naddress_span:%0d",
"\nalignment:%s\nstride_bytes:%0d\nVLEN:%0d\nLMUL:%0d\ncfg.vector_cfg.vtype.vsew:%0d\n\n"},
max_load_store_addr, data_page_id, data_page[data_page_id].size_in_bytes, ss,
alignment.name(), stride_bytes(), VLEN,
@@ -597,9 +626,13 @@
end
endfunction
- virtual function int stride_span();
+ virtual function int address_span();
int num_elements = VLEN * cfg.vector_cfg.vtype.vlmul / cfg.vector_cfg.vtype.vsew;
- stride_span = num_elements * stride_bytes();
+ case (address_mode)
+ UNIT_STRIDED : address_span = num_elements * stride_bytes();
+ STRIDED : address_span = num_elements * stride_byte_offset;
+ INDEXED : address_span = index_addr + num_elements * stride_bytes();
+ endcase
endfunction
virtual function int stride_bytes();
@@ -625,28 +658,136 @@
endfunction
virtual function void add_element_vec_load_stores();
- allowed_instr = {VLE_V, VSE_V, allowed_instr};
+ case (address_mode)
+ UNIT_STRIDED : begin
+ allowed_instr = {VLE_V, VSE_V, allowed_instr};
+ if (cfg.vector_cfg.enable_fault_only_first_load) begin
+ allowed_instr = {VLEFF_V, allowed_instr};
+ end
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLSEGE_V, VSSEGE_V, allowed_instr};
+ if (cfg.vector_cfg.enable_fault_only_first_load) begin
+ allowed_instr = {VLSEGEFF_V, allowed_instr};
+ end
+ end
+ end
+ STRIDED : begin
+ allowed_instr = {VLSE_V, VSSE_V, allowed_instr};
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLSSEGE_V, VSSSEGE_V, allowed_instr};
+ end
+ end
+ INDEXED : begin
+ allowed_instr = {VLXE_V, VSXE_V, allowed_instr};
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLXSEGE_V, VSXSEGE_V, allowed_instr};
+ end
+ end
+ endcase
endfunction
virtual function void add_byte_aligned_vec_load_stores();
- allowed_instr = {VLB_V, VSB_V, VLBU_V, allowed_instr};
+ case (address_mode)
+ UNIT_STRIDED : begin
+ allowed_instr = {VLB_V, VSB_V, VLBU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_fault_only_first_load) begin
+ allowed_instr = {VLBFF_V, VLBUFF_V, allowed_instr};
+ end
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLSEGB_V, VSSEGB_V, VLSEGBU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_fault_only_first_load) begin
+ allowed_instr = {VLSEGBFF_V, VLSEGBUFF_V, allowed_instr};
+ end
+ end
+ end
+ STRIDED : begin
+ allowed_instr = {VLSB_V, VSSB_V, VLSBU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLSSEGB_V, VSSSEGB_V, VLSSEGBU_V, allowed_instr};
+ end
+ end
+ INDEXED : begin
+ allowed_instr = {VLXB_V, VSXB_V, VLXBU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLXSEGB_V, VSXSEGB_V, VLXSEGBU_V, allowed_instr};
+ end
+ end
+ endcase
endfunction
virtual function void add_h_aligned_vec_load_stores();
- allowed_instr = {VLH_V, VSH_V, VLHU_V, allowed_instr};
+ case (address_mode)
+ UNIT_STRIDED : begin
+ allowed_instr = {VLH_V, VSH_V, VLHU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_fault_only_first_load) begin
+ allowed_instr = {VLHFF_V, VLHUFF_V, allowed_instr};
+ end
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLSEGH_V, VSSEGH_V, VLSEGHU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_fault_only_first_load) begin
+ allowed_instr = {VLSEGHFF_V, VLSEGHUFF_V, allowed_instr};
+ end
+ end
+ end
+ STRIDED : begin
+ allowed_instr = {VLSH_V, VSSH_V, VLSHU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLSSEGH_V, VSSSEGH_V, VLSSEGHU_V, allowed_instr};
+ end
+ end
+ INDEXED : begin
+ allowed_instr = {VLXH_V, VSXH_V, VLXHU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLXSEGH_V, VSXSEGH_V, VLXSEGHU_V, allowed_instr};
+ end
+ end
+ endcase
endfunction
virtual function void add_w_aligned_vec_load_stores();
- allowed_instr = {VLW_V, VSW_V, VLWU_V, allowed_instr};
+ case (address_mode)
+ UNIT_STRIDED : begin
+ allowed_instr = {VLW_V, VSW_V, VLWU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_fault_only_first_load) begin
+ allowed_instr = {VLWFF_V, VLWUFF_V, allowed_instr};
+ end
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLSEGW_V, VSSEGW_V, VLSEGWU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_fault_only_first_load) begin
+ allowed_instr = {VLSEGWFF_V, VLSEGWUFF_V, allowed_instr};
+ end
+ end
+ end
+ STRIDED : begin
+ allowed_instr = {VLSW_V, VSSW_V, VLSWU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLSSEGW_V, VSSSEGW_V, VLSSEGWU_V, allowed_instr};
+ end
+ end
+ INDEXED : begin
+ allowed_instr = {VLXW_V, VSXW_V, VLXWU_V, allowed_instr};
+ if (cfg.vector_cfg.enable_zvlsseg) begin
+ allowed_instr = {VLXSEGW_V, VSXSEGW_V, VLXSEGWU_V, allowed_instr};
+ end
+ end
+ endcase
endfunction
virtual function void randomize_vec_load_store_instr();
- load_store_instr = riscv_instr::get_load_store_instr(allowed_instr);
+ $cast(load_store_instr, riscv_instr::get_load_store_instr(allowed_instr));
load_store_instr.m_cfg = cfg;
load_store_instr.has_rs1 = 0;
+ load_store_instr.has_vs2 = 1;
load_store_instr.has_imm = 0;
randomize_gpr(load_store_instr);
load_store_instr.rs1 = rs1_reg;
+ load_store_instr.rs2 = rs2_reg;
+ load_store_instr.vs2 = vs2_reg;
+ if (address_mode == INDEXED) begin
+ cfg.vector_cfg.reserved_vregs = {load_store_instr.vs2};
+ vs2_reg = load_store_instr.vs2;
+ `uvm_info(`gfn, $sformatf("vs2_reg = v%0d", vs2_reg), UVM_LOW)
+ end
load_store_instr.process_load_store = 0;
endfunction
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv
index 1bcadb8..7c2155b 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv
@@ -39,6 +39,10 @@
// allowing all access restrictions to be enforced.
bit enable_pmp_exception_handler = 1'b1;
+ // Setting this bit to 1'b1 enables generation of the directed stream of instructions to test
+ // write accesses to all supported pmpaddr[i] CSRs.
+ bit enable_write_pmp_csr;
+
// pmp CSR configurations
rand pmp_cfg_reg_t pmp_cfg[];
@@ -129,6 +133,7 @@
get_int_arg_value("+pmp_granularity=", pmp_granularity);
get_bool_arg_value("+pmp_randomize=", pmp_randomize);
get_bool_arg_value("+pmp_allow_addr_overlap=", pmp_allow_addr_overlap);
+ get_bool_arg_value("+enable_write_pmp_csr=", enable_write_pmp_csr);
get_hex_arg_value("+pmp_max_offset=", pmp_max_offset);
`uvm_info(`gfn, $sformatf("pmp max offset: 0x%0x", pmp_max_offset), UVM_LOW)
pmp_cfg = new[pmp_num_regions];
@@ -606,4 +611,61 @@
endfunction
+ // This function is used for a directed PMP test to test writes to all the pmpcfg and pmpaddr
+ // CSRs to test that writes succeed or fail appropriately.
+ virtual function void gen_pmp_write_test(riscv_reg_t scratch_reg[2],
+ ref string instr[$]);
+
+ bit [11:0] pmp_addr;
+ bit [11:0] pmpcfg_addr;
+ bit [XLEN-1:0] pmp_val;
+ for (int i = 0; i < pmp_num_regions; i++) begin
+ pmp_addr = base_pmp_addr + i;
+ pmpcfg_addr = base_pmpcfg_addr + (i / cfg_per_csr);
+ // We randomize the upper 31 bits of pmp_val and then add this to the
+ // address of <main>, guaranteeing that the random value written to
+ // pmpaddr[i] doesn't interfere with the safe region.
+ `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(pmp_val, pmp_val[31] == 1'b0;)
+ instr.push_back($sformatf("li x%0d, 0x%0x", scratch_reg[0], pmp_val));
+ instr.push_back($sformatf("la x%0d, main", scratch_reg[1]));
+ instr.push_back($sformatf("add x%0d, x%0d, x%0d",
+ scratch_reg[0], scratch_reg[0], scratch_reg[1]));
+ // Write the randomized address to pmpaddr[i].
+ // Original value of pmpaddr[i] will be written to scratch_reg[0].
+ instr.push_back($sformatf("csrrw x%0d, 0x%0x, x%0d",
+ scratch_reg[0], pmp_addr, scratch_reg[0]));
+ // Restore the original address to pmpaddr[i].
+ // New value of pmpaddr[i] will be written to scratch_reg[0].
+ instr.push_back($sformatf("csrrw x%0d, 0x%0x, x%0d",
+ scratch_reg[0], pmp_addr, scratch_reg[0]));
+ // Randomize value to be written to pmpcfg CSR.
+ //
+ // TODO: support rv64.
+ `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(pmp_val,
+ // Need to constrain pmp_val[7], pmp_val[15], ... to 1'b0
+ // to ensure that the random config regions aren't locked
+ foreach (pmp_val[i]) {
+ if ((i+1) % 8 == 0) {
+ pmp_val[i] == 1'b0;
+ }
+ }
+ )
+ // If we're writing to the pmpcfg CSR that contains region0 config information,
+ // ensure that the "safe" region remains fully accessible.
+ if (pmpcfg_addr == base_pmpcfg_addr) begin
+ pmp_val[7:0] = 'h0f;
+ end
+ instr.push_back($sformatf("li x%0d, 0x%0x", scratch_reg[0], pmp_val));
+ // Write the randomized address to pmpcfg[i].
+ // Original value of pmpcfg[i] will be written to scratch_reg[0].
+ instr.push_back($sformatf("csrrw x%0d, 0x%0x, x%0d",
+ scratch_reg[0], pmpcfg_addr, scratch_reg[0]));
+ // Restore the original address to pmpcfg[i].
+ // New value of pmpcfg[i] will be written to scratch_reg[0].
+ instr.push_back($sformatf("csrrw x%0d, 0x%0x, x%0d",
+ scratch_reg[0], pmpcfg_addr, scratch_reg[0]));
+ end
+
+ endfunction
+
endclass
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privil_reg.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privil_reg.sv
index b9cef94..a4c519a 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privil_reg.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_privil_reg.sv
@@ -282,15 +282,8 @@
// Physical Memory Protection Configuration Register
PMPCFG1: begin
privil_level = M_LEVEL;
- if(XLEN==64) begin
- add_field("PMP8CFG", 8, WARL);
- add_field("PMP9CFG", 8, WARL);
- add_field("PMP10CFG", 8, WARL);
- add_field("PMP11CFG", 8, WARL);
- add_field("PMP12CFG", 8, WARL);
- add_field("PMP13CFG", 8, WARL);
- add_field("PMP14CFG", 8, WARL);
- add_field("PMP15CFG", 8, WARL);
+ if(XLEN!=32) begin
+ `uvm_fatal(`gfn, "CSR PMPCFG1 only exists in RV32.")
end else begin
add_field("PMP4CFG", 8, WARL);
add_field("PMP5CFG", 8, WARL);
@@ -300,14 +293,17 @@
end
// Physical Memory Protection Configuration Register
PMPCFG2: begin
- if(XLEN!=32) begin
- `uvm_fatal(get_full_name(), "CSR PMPCFG2 only exists in RV32.")
- end
privil_level = M_LEVEL;
add_field("PMP8CFG", 8, WARL);
add_field("PMP9CFG", 8, WARL);
add_field("PMP10CFG", 8, WARL);
add_field("PMP11CFG", 8, WARL);
+ if(XLEN==64) begin
+ add_field("PMP12CFG", 8, WARL);
+ add_field("PMP13CFG", 8, WARL);
+ add_field("PMP14CFG", 8, WARL);
+ add_field("PMP15CFG", 8, WARL);
+ end
end
// Physical Memory Protection Configuration Register
PMPCFG3: begin
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_vector_cfg.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_vector_cfg.sv
index 90ce5c3..c6bc29b 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_vector_cfg.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/src/riscv_vector_cfg.sv
@@ -22,6 +22,7 @@
rand bit [XLEN-1:0] vstart;
rand vxrm_t vxrm;
rand bit vxsat;
+ riscv_vreg_t reserved_vregs[$];
// Allow only vector instructions from the random sequences
rand bit only_vec_instr;
@@ -53,6 +54,12 @@
// These hazard conditions are induced by keeping a small (~5) list of registers to select from.
rand bit vec_reg_hazards;
+ // Enable segmented load/store extension ops
+ rand bit enable_zvlsseg = 1'b1;
+
+ // Enable fault only first load ops
+ rand bit enable_fault_only_first_load;
+
constraint legal_c {
solve vtype before vl;
solve vl before vstart;
@@ -89,6 +96,10 @@
if (vec_quad_widening) {vtype.vsew < (ELEN >> 1);}
}
+ constraint vseg_c {
+ enable_zvlsseg -> (vtype.vlmul < 8);
+ }
+
constraint vdeiv_c {
vtype.vediv inside {1, 2, 4, 8};
vtype.vediv <= (vtype.vsew / SELEN);
@@ -103,8 +114,18 @@
`uvm_field_int(vstart, UVM_DEFAULT)
`uvm_field_enum(vxrm_t,vxrm, UVM_DEFAULT)
`uvm_field_int(vxsat, UVM_DEFAULT)
+ `uvm_field_int(enable_zvlsseg, UVM_DEFAULT)
+ `uvm_field_int(enable_fault_only_first_load, UVM_DEFAULT)
`uvm_object_utils_end
- `uvm_object_new
+ function new (string name = "");
+ super.new(name);
+ if ($value$plusargs("enable_zvlsseg=%0d", enable_zvlsseg)) begin
+ enable_zvlsseg.rand_mode(0);
+ end
+ if ($value$plusargs("enable_fault_only_first_load=%0d", enable_fault_only_first_load)) begin
+ enable_fault_only_first_load.rand_mode(0);
+ end
+ endfunction : new
endclass : riscv_vector_cfg
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv
index 707e919..38685e3 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv
@@ -88,10 +88,10 @@
parameter int NUM_HARTS = 1;
// ----------------------------------------------------------------------------
-// Previleged CSR implementation
+// Privileged CSR implementation
// ----------------------------------------------------------------------------
-// Implemented previlieged CSR list
+// Implemented privileged CSR list
`ifdef DSIM
privileged_reg_t implemented_csr[] = {
`else
@@ -114,6 +114,14 @@
MIP // Machine interrupt pending
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv
index 04a2f55..b4ef8f0 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv
@@ -114,6 +114,14 @@
MIP // Machine interrupt pending
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv
index 49c97c8..e8014b3 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv
@@ -77,6 +77,9 @@
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
+// Maxium LMUL supported by the core
+parameter int MAX_LMUL = 8;
+
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
@@ -111,6 +114,14 @@
MIP // Machine interrupt pending
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv
index 1aaf1a1..50b4efa 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv
@@ -114,6 +114,14 @@
MIP // Machine interrupt pending
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imcb/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imcb/riscv_core_setting.sv
index df33010..b404b78 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imcb/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv32imcb/riscv_core_setting.sv
@@ -114,6 +114,14 @@
MIP // Machine interrupt pending
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv
index 4ca59cd..298b6ed 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv
@@ -140,6 +140,14 @@
FCSR // Floating point control and status
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv
index d418120..c49e81f 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv
@@ -139,6 +139,14 @@
FCSR // Floating point control and status
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/testlist.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/testlist.yaml
index 50698ab..4bcd607 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/testlist.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64gcv/testlist.yaml
@@ -48,6 +48,24 @@
gen_test: riscv_instr_base_test
rtl_test: core_base_test
+- test: riscv_vector_arithmetic_stress_test
+ description: >
+ Arithmetic vector instruction stress test, only vector ops are generated
+ gen_opts: >
+ +instr_cnt=10000
+ +num_of_sub_program=0
+ +enable_floating_point=1
+ +enable_vector_extension=1
+ +vector_instr_only=1
+ +no_fence=1
+ +no_data_page=1
+ +no_branch_jump=1
+ +boot_mode=m
+ +no_csr_instr=1
+ iterations: 2
+ gen_test: riscv_instr_base_test
+ rtl_test: core_base_test
+
- test: riscv_vector_load_store_test
description: >
Vector load/store random test
@@ -56,10 +74,26 @@
+num_of_sub_program=0
+enable_floating_point=1
+enable_vector_extension=1
- +directed_instr_0=riscv_vector_unit_stride_load_store_instr_stream,4
+ +directed_instr_0=riscv_vector_load_store_instr_stream,10
+no_branch_jump=1
+boot_mode=m
+no_csr_instr=1
- iterations: 2
+ iterations: 5
+ gen_test: riscv_instr_base_test
+ rtl_test: core_base_test
+
+- test: riscv_vector_amo_test
+ description: >
+ Vector AMO random test
+ gen_opts: >
+ +instr_cnt=10000
+ +num_of_sub_program=0
+ +enable_floating_point=1
+ +enable_vector_extension=1
+ +directed_instr_0=riscv_vector_amo_instr_stream,10
+ +no_branch_jump=1
+ +boot_mode=m
+ +no_csr_instr=1
+ iterations: 5
gen_test: riscv_instr_base_test
rtl_test: core_base_test
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv
index 0071ffa..edfc8b0 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv
@@ -113,6 +113,14 @@
MIP // Machine interrupt pending
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv
index 3bf90a5..76d2e85 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv
@@ -114,6 +114,14 @@
MIP // Machine interrupt pending
};
+// Implementation-specific custom CSRs
+`ifdef DSIM
+bit [11:0] custom_csr[] = {
+`else
+const bit [11:0] custom_csr[] = {
+`endif
+};
+
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
diff --git a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
index 43dc1e5..f509138 100644
--- a/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
+++ b/hw/vendor/lowrisc_ibex/vendor/google_riscv-dv/yaml/simulator.yaml
@@ -108,6 +108,7 @@
cmd:
- "vlib <out>/work"
- "vlog -work <out>/work
+ -err VCP2694 W1
-uvmver 1.2
+define+UVM_REGEX_NO_DPI
+incdir+<setting>
diff --git a/hw/vendor/lowrisc_ibex/vendor/patches/lowrisc_ip/dv_utils/0001-use-ibex-top-pkg.patch b/hw/vendor/lowrisc_ibex/vendor/patches/lowrisc_ip/dv_utils/0001-use-ibex-top-pkg.patch
new file mode 100644
index 0000000..906cec7
--- /dev/null
+++ b/hw/vendor/lowrisc_ibex/vendor/patches/lowrisc_ip/dv_utils/0001-use-ibex-top-pkg.patch
@@ -0,0 +1,13 @@
+diff --git a/dv_utils/dv_utils.core b/dv_utils/dv_utils.core
+index 0dba0235..801e84f6 100644
+--- a/dv_utils.core
++++ b/dv_utils.core
+@@ -10,7 +10,7 @@ filesets:
+ depend:
+ - lowrisc:dv:common_ifs
+ - lowrisc:prim:assert:0.1
+- - lowrisc:constants:top_pkg
++ - lowrisc:ibex:top_pkg
+ files:
+ - dv_utils_pkg.sv
+ - dv_macros.svh: {is_include_file: true}