Update lowrisc_ibex to lowRISC/ibex@0e7117fb
Update code from upstream repository
https://github.com/lowRISC/ibex.git to revision
0e7117fbec434fcfdf2bcce4ed379d34cdbe68b4
* [lockstep] Introduce optimization barrier around lockstep Ibex
(Michael Schaffner)
* [dv] Remove MISA from csr_description.yaml (Greg Chadwick)
* Update README to match design (Philipp Wagner)
* Fix a couple of synthesis bugs (Tom Roberts)
* [dv] Improvements to functional coverage (Greg Chadwick)
* [rtl] Fix RF read enables for illegal instruction/fetch error (Greg
Chadwick)
* [rtl] illegal_csr_write shouldn't factor in csr_op_en_i (Greg
Chadwick)
* [dv] Add known failure detection to riscv_debug_ebreakmu_test (Greg
Chadwick)
Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
diff --git a/hw/vendor/lowrisc_ibex.lock.hjson b/hw/vendor/lowrisc_ibex.lock.hjson
index d0e438d..8408198 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: 25cd6600c64e6eec4c3f5ee20237b53e4d5a3a52
+ rev: 0e7117fbec434fcfdf2bcce4ed379d34cdbe68b4
}
}
diff --git a/hw/vendor/lowrisc_ibex/README.md b/hw/vendor/lowrisc_ibex/README.md
index 1a4256d..ace6903 100644
--- a/hw/vendor/lowrisc_ibex/README.md
+++ b/hw/vendor/lowrisc_ibex/README.md
@@ -2,16 +2,21 @@
# Ibex RISC-V Core
-Ibex is a small and efficient, 32-bit, in-order RISC-V core with a 2-stage pipeline that implements
-the RV32IMC instruction set architecture.
+Ibex is a production-quality open source 32-bit RISC-V CPU core written in
+SystemVerilog. The CPU core is heavily parametrizable and well suited for
+embedded control applications. Ibex is being extensively verified and has
+seen multiple tape-outs. Ibex supports the Integer (I) or Embedded (E),
+Integer Multiplication and Division (M), Compressed (C), and B (Bit
+Manipulation) extensions.
+The block diagram below shows the *small* parametrization with a 2-stage
+pipeline.
<p align="center"><img src="doc/03_reference/images/blockdiagram.svg" width="650"></p>
-This core was initially developed as part of the [PULP platform](https://www.pulp-platform.org)
-under the name "Zero-riscy" \[[1](https://doi.org/10.1109/PATMOS.2017.8106976)\], and has been
+Ibex was initially developed as part of the [PULP platform](https://www.pulp-platform.org)
+under the name ["Zero-riscy"](https://doi.org/10.1109/PATMOS.2017.8106976), and has been
contributed to [lowRISC](https://www.lowrisc.org) who maintains it and develops it further. It is
-under active development, with further code cleanups, feature additions, and test and verification
-planned for the future.
+under active development.
## Configuration
@@ -96,9 +101,3 @@
Many people have contributed to Ibex through the years. Please have a look at
the [credits file](CREDITS.md) and the commit history for more information.
-
-## References
-1. [Schiavone, Pasquale Davide, et al. "Slow and steady wins the race? A comparison of
- ultra-low-power RISC-V cores for Internet-of-Things applications."
- _27th International Symposium on Power and Timing Modeling, Optimization and Simulation
- (PATMOS 2017)_](https://doi.org/10.1109/PATMOS.2017.8106976)
diff --git a/hw/vendor/lowrisc_ibex/doc/01_overview/index.rst b/hw/vendor/lowrisc_ibex/doc/01_overview/index.rst
index 7eea4c6..67d0247 100644
--- a/hw/vendor/lowrisc_ibex/doc/01_overview/index.rst
+++ b/hw/vendor/lowrisc_ibex/doc/01_overview/index.rst
@@ -1,7 +1,7 @@
Introduction to Ibex
====================
-Ibex is a production-quality open source 32 bit RISC-V CPU core written in SystemVerilog.
+Ibex is a production-quality open source 32-bit RISC-V CPU core written in SystemVerilog.
The CPU core is heavily parametrizable and well suited for embedded control applications.
Ibex is being extensively verified and has seen multiple tape-outs.
diff --git a/hw/vendor/lowrisc_ibex/ibex_top.core b/hw/vendor/lowrisc_ibex/ibex_top.core
index ef27228..823382a 100644
--- a/hw/vendor/lowrisc_ibex/ibex_top.core
+++ b/hw/vendor/lowrisc_ibex/ibex_top.core
@@ -10,6 +10,7 @@
depend:
- lowrisc:ibex:ibex_pkg
- lowrisc:ibex:ibex_core
+ - lowrisc:prim:buf
files:
- rtl/ibex_register_file_ff.sv # generic FF-based
- rtl/ibex_register_file_fpga.sv # FPGA
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
index 26dbf3c..1a6523c 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_controller.sv
@@ -853,6 +853,7 @@
`DV_FCOV_SIGNAL(logic, debug_entry_id,
(ctrl_fsm_cs != DBG_TAKEN_ID) & (ctrl_fsm_ns == DBG_TAKEN_ID))
`DV_FCOV_SIGNAL(logic, pipe_flush, (ctrl_fsm_cs != FLUSH) & (ctrl_fsm_ns == FLUSH))
+ `DV_FCOV_SIGNAL(logic, debug_req, debug_req_i & ~debug_mode_q)
////////////////
// Assertions //
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
index b423268..50a34a2 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
@@ -256,7 +256,7 @@
logic [31:0] csr_wdata_int;
logic [31:0] csr_rdata_int;
logic csr_we_int;
- logic csr_wreq;
+ logic csr_wr;
// Access violation signals
logic illegal_csr;
@@ -279,7 +279,7 @@
// See RISC-V Privileged Specification, version 1.11, Section 2.1
assign illegal_csr_priv = (csr_addr[9:8] > {priv_lvl_q});
- assign illegal_csr_write = (csr_addr[11:10] == 2'b11) && csr_wreq;
+ assign illegal_csr_write = (csr_addr[11:10] == 2'b11) && csr_wr;
assign illegal_csr_insn_o = csr_access_i & (illegal_csr | illegal_csr_write | illegal_csr_priv);
// mip CSR is purely combinational - must be able to re-enable the clock upon WFI
@@ -736,13 +736,10 @@
endcase
end
- assign csr_wreq = csr_op_en_i &
- (csr_op_i inside {CSR_OP_WRITE,
- CSR_OP_SET,
- CSR_OP_CLEAR});
+ assign csr_wr = (csr_op_i inside {CSR_OP_WRITE, CSR_OP_SET, CSR_OP_CLEAR});
// only write CSRs during one clock cycle
- assign csr_we_int = csr_wreq & ~illegal_csr_insn_o;
+ assign csr_we_int = csr_wr & csr_op_en_i & ~illegal_csr_insn_o;
assign csr_rdata_o = csr_rdata_int;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
index 5c158f7..7107ee6 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
@@ -237,6 +237,11 @@
rf_wd_sel_e rf_wdata_sel;
logic rf_we_dec, rf_we_raw;
logic rf_ren_a, rf_ren_b;
+ logic rf_ren_a_dec, rf_ren_b_dec;
+
+ // Read enables should only be asserted for valid and legal instructions
+ assign rf_ren_a = instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o & rf_ren_a_dec;
+ assign rf_ren_b = instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o & rf_ren_b_dec;
assign rf_ren_a_o = rf_ren_a;
assign rf_ren_b_o = rf_ren_b;
@@ -461,8 +466,8 @@
.rf_raddr_a_o ( rf_raddr_a_o ),
.rf_raddr_b_o ( rf_raddr_b_o ),
.rf_waddr_o ( rf_waddr_id_o ),
- .rf_ren_a_o ( rf_ren_a ),
- .rf_ren_b_o ( rf_ren_b ),
+ .rf_ren_a_o ( rf_ren_a_dec ),
+ .rf_ren_b_o ( rf_ren_b_dec ),
// ALU
.alu_operator_o ( alu_operator ),
@@ -849,10 +854,18 @@
`ASSERT(StallIDIfMulticycle, (id_fsm_q == FIRST_CYCLE) & (id_fsm_d == MULTI_CYCLE) |-> stall_id)
- // Stall ID/EX stage for reason that relates to instruction in ID/EX
+
+ // Stall ID/EX stage for reason that relates to instruction in ID/EX, update assertion below if
+ // modifying this.
assign stall_id = stall_ld_hz | stall_mem | stall_multdiv | stall_jump | stall_branch |
stall_alu;
+ // Generally illegal instructions have no reason to stall, however they must still stall waiting
+ // for outstanding memory requests so exceptions related to them take priority over the illegal
+ // instruction exception.
+ `ASSERT(IllegalInsnStallMustBeMemStall, illegal_insn_o & stall_id |-> stall_mem &
+ ~(stall_ld_hz | stall_multdiv | stall_jump | stall_branch | stall_alu))
+
assign instr_done = ~stall_id & ~flush_id & instr_executing;
// Signal instruction in ID is in it's first cycle. It can remain in its
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
index 1d89eb6..07e248d 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
@@ -7,6 +7,8 @@
`define RVFI
`endif
+`include "prim_assert.sv"
+
/**
* Top level module of the ibex RISC-V core
*/
@@ -414,6 +416,225 @@
// Redundant lockstep core implementation
if (Lockstep) begin : gen_lockstep
+ // Note: certain synthesis tools like DC are very smart at optimizing away redundant logic.
+ // Hence, we have to insert an optimization barrier at the IOs of the lockstep Ibex.
+ // This is achieved by manually buffering each bit using prim_buf.
+ // Our Xilinx and DC synthesis flows make sure that these buffers cannot be optimized away
+ // using keep attributes (Vivado) and size_only constraints (DC).
+
+ localparam int NumBufferBits = $bits({
+ hart_id_i,
+ boot_addr_i,
+ instr_req_o,
+ instr_gnt_i,
+ instr_rvalid_i,
+ instr_addr_o,
+ instr_rdata_i,
+ instr_err_i,
+ data_req_o,
+ data_gnt_i,
+ data_rvalid_i,
+ data_we_o,
+ data_be_o,
+ data_addr_o,
+ data_wdata_o,
+ data_rdata_i,
+ data_err_i,
+ dummy_instr_id,
+ rf_raddr_a,
+ rf_raddr_b,
+ rf_waddr_wb,
+ rf_we_wb,
+ rf_wdata_wb_ecc,
+ rf_rdata_a_ecc,
+ rf_rdata_b_ecc,
+ ic_tag_req,
+ ic_tag_write,
+ ic_tag_addr,
+ ic_tag_wdata,
+ ic_data_req,
+ ic_data_write,
+ ic_data_addr,
+ ic_data_wdata,
+ irq_software_i,
+ irq_timer_i,
+ irq_external_i,
+ irq_fast_i,
+ irq_nm_i,
+ irq_pending,
+ debug_req_i,
+ crash_dump_o,
+ core_busy_d
+ });
+
+ logic [NumBufferBits-1:0] buf_in, buf_out;
+
+ logic [31:0] hart_id_local;
+ logic [31:0] boot_addr_local;
+
+ logic instr_req_local;
+ logic instr_gnt_local;
+ logic instr_rvalid_local;
+ logic [31:0] instr_addr_local;
+ logic [31:0] instr_rdata_local;
+ logic instr_err_local;
+
+ logic data_req_local;
+ logic data_gnt_local;
+ logic data_rvalid_local;
+ logic data_we_local;
+ logic [3:0] data_be_local;
+ logic [31:0] data_addr_local;
+ logic [31:0] data_wdata_local;
+ logic [31:0] data_rdata_local;
+ logic data_err_local;
+
+ logic dummy_instr_id_local;
+ logic [4:0] rf_raddr_a_local;
+ logic [4:0] rf_raddr_b_local;
+ logic [4:0] rf_waddr_wb_local;
+ logic rf_we_wb_local;
+ logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_local;
+ logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_local;
+ logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_local;
+
+ logic [IC_NUM_WAYS-1:0] ic_tag_req_local;
+ logic ic_tag_write_local;
+ logic [IC_INDEX_W-1:0] ic_tag_addr_local;
+ logic [TagSizeECC-1:0] ic_tag_wdata_local;
+ logic [IC_NUM_WAYS-1:0] ic_data_req_local;
+ logic ic_data_write_local;
+ logic [IC_INDEX_W-1:0] ic_data_addr_local;
+ logic [LineSizeECC-1:0] ic_data_wdata_local;
+
+ logic irq_software_local;
+ logic irq_timer_local;
+ logic irq_external_local;
+ logic [14:0] irq_fast_local;
+ logic irq_nm_local;
+ logic irq_pending_local;
+
+ logic debug_req_local;
+ crash_dump_t crash_dump_local;
+
+ logic core_busy_local;
+
+ assign buf_in = {
+ hart_id_i,
+ boot_addr_i,
+ instr_req_o,
+ instr_gnt_i,
+ instr_rvalid_i,
+ instr_addr_o,
+ instr_rdata_i,
+ instr_err_i,
+ data_req_o,
+ data_gnt_i,
+ data_rvalid_i,
+ data_we_o,
+ data_be_o,
+ data_addr_o,
+ data_wdata_o,
+ data_rdata_i,
+ data_err_i,
+ dummy_instr_id,
+ rf_raddr_a,
+ rf_raddr_b,
+ rf_waddr_wb,
+ rf_we_wb,
+ rf_wdata_wb_ecc,
+ rf_rdata_a_ecc,
+ rf_rdata_b_ecc,
+ ic_tag_req,
+ ic_tag_write,
+ ic_tag_addr,
+ ic_tag_wdata,
+ ic_data_req,
+ ic_data_write,
+ ic_data_addr,
+ ic_data_wdata,
+ irq_software_i,
+ irq_timer_i,
+ irq_external_i,
+ irq_fast_i,
+ irq_nm_i,
+ irq_pending,
+ debug_req_i,
+ crash_dump_o,
+ core_busy_d
+ };
+
+ assign {
+ hart_id_local,
+ boot_addr_local,
+ instr_req_local,
+ instr_gnt_local,
+ instr_rvalid_local,
+ instr_addr_local,
+ instr_rdata_local,
+ instr_err_local,
+ data_req_local,
+ data_gnt_local,
+ data_rvalid_local,
+ data_we_local,
+ data_be_local,
+ data_addr_local,
+ data_wdata_local,
+ data_rdata_local,
+ data_err_local,
+ dummy_instr_id_local,
+ rf_raddr_a_local,
+ rf_raddr_b_local,
+ rf_waddr_wb_local,
+ rf_we_wb_local,
+ rf_wdata_wb_ecc_local,
+ rf_rdata_a_ecc_local,
+ rf_rdata_b_ecc_local,
+ ic_tag_req_local,
+ ic_tag_write_local,
+ ic_tag_addr_local,
+ ic_tag_wdata_local,
+ ic_data_req_local,
+ ic_data_write_local,
+ ic_data_addr_local,
+ ic_data_wdata_local,
+ irq_software_local,
+ irq_timer_local,
+ irq_external_local,
+ irq_fast_local,
+ irq_nm_local,
+ irq_pending_local,
+ debug_req_local,
+ crash_dump_local,
+ core_busy_local
+ } = buf_out;
+
+ // Manually buffer all input signals.
+ for (genvar k = 0; k < NumBufferBits; k++) begin : gen_buffers
+ prim_buf u_prim_buf (
+ .in_i(buf_in[k]),
+ .out_o(buf_out[k])
+ );
+ end
+
+ logic [TagSizeECC-1:0] ic_tag_rdata_local [IC_NUM_WAYS];
+ logic [LineSizeECC-1:0] ic_data_rdata_local [IC_NUM_WAYS];
+ for (genvar k = 0; k < IC_NUM_WAYS; k++) begin : gen_ways
+ for (genvar j = 0; j < TagSizeECC; j++) begin : gen_tag_bufs
+ prim_buf u_prim_buf (
+ .in_i(ic_tag_rdata[k][j]),
+ .out_o(ic_tag_rdata_local[k][j])
+ );
+ end
+ for (genvar j = 0; j < TagSizeECC; j++) begin : gen_data_bufs
+ prim_buf u_prim_buf (
+ .in_i(ic_data_rdata[k][j]),
+ .out_o(ic_data_rdata_local[k][j])
+ );
+ end
+ end
+
+ logic lockstep_alert_minor_local, lockstep_alert_major_local;
ibex_lockstep #(
.PMPEnable ( PMPEnable ),
.PMPGranularity ( PMPGranularity ),
@@ -443,60 +664,72 @@
.clk_i (clk),
.rst_ni (rst_ni),
- .hart_id_i (hart_id_i),
- .boot_addr_i (boot_addr_i),
+ .hart_id_i (hart_id_local),
+ .boot_addr_i (boot_addr_local),
- .instr_req_i (instr_req_o),
- .instr_gnt_i (instr_gnt_i),
- .instr_rvalid_i (instr_rvalid_i),
- .instr_addr_i (instr_addr_o),
- .instr_rdata_i (instr_rdata_i),
- .instr_err_i (instr_err_i),
+ .instr_req_i (instr_req_local),
+ .instr_gnt_i (instr_gnt_local),
+ .instr_rvalid_i (instr_rvalid_local),
+ .instr_addr_i (instr_addr_local),
+ .instr_rdata_i (instr_rdata_local),
+ .instr_err_i (instr_err_local),
- .data_req_i (data_req_o),
- .data_gnt_i (data_gnt_i),
- .data_rvalid_i (data_rvalid_i),
- .data_we_i (data_we_o),
- .data_be_i (data_be_o),
- .data_addr_i (data_addr_o),
- .data_wdata_i (data_wdata_o),
- .data_rdata_i (data_rdata_i),
- .data_err_i (data_err_i),
+ .data_req_i (data_req_local),
+ .data_gnt_i (data_gnt_local),
+ .data_rvalid_i (data_rvalid_local),
+ .data_we_i (data_we_local),
+ .data_be_i (data_be_local),
+ .data_addr_i (data_addr_local),
+ .data_wdata_i (data_wdata_local),
+ .data_rdata_i (data_rdata_local),
+ .data_err_i (data_err_local),
- .dummy_instr_id_i (dummy_instr_id),
- .rf_raddr_a_i (rf_raddr_a),
- .rf_raddr_b_i (rf_raddr_b),
- .rf_waddr_wb_i (rf_waddr_wb),
- .rf_we_wb_i (rf_we_wb),
- .rf_wdata_wb_ecc_i (rf_wdata_wb_ecc),
- .rf_rdata_a_ecc_i (rf_rdata_a_ecc),
- .rf_rdata_b_ecc_i (rf_rdata_b_ecc),
+ .dummy_instr_id_i (dummy_instr_id_local),
+ .rf_raddr_a_i (rf_raddr_a_local),
+ .rf_raddr_b_i (rf_raddr_b_local),
+ .rf_waddr_wb_i (rf_waddr_wb_local),
+ .rf_we_wb_i (rf_we_wb_local),
+ .rf_wdata_wb_ecc_i (rf_wdata_wb_ecc_local),
+ .rf_rdata_a_ecc_i (rf_rdata_a_ecc_local),
+ .rf_rdata_b_ecc_i (rf_rdata_b_ecc_local),
- .ic_tag_req_i (ic_tag_req),
- .ic_tag_write_i (ic_tag_write),
- .ic_tag_addr_i (ic_tag_addr),
- .ic_tag_wdata_i (ic_tag_wdata),
- .ic_tag_rdata_i (ic_tag_rdata),
- .ic_data_req_i (ic_data_req),
- .ic_data_write_i (ic_data_write),
- .ic_data_addr_i (ic_data_addr),
- .ic_data_wdata_i (ic_data_wdata),
- .ic_data_rdata_i (ic_data_rdata),
+ .ic_tag_req_i (ic_tag_req_local),
+ .ic_tag_write_i (ic_tag_write_local),
+ .ic_tag_addr_i (ic_tag_addr_local),
+ .ic_tag_wdata_i (ic_tag_wdata_local),
+ .ic_tag_rdata_i (ic_tag_rdata_local),
+ .ic_data_req_i (ic_data_req_local),
+ .ic_data_write_i (ic_data_write_local),
+ .ic_data_addr_i (ic_data_addr_local),
+ .ic_data_wdata_i (ic_data_wdata_local),
+ .ic_data_rdata_i (ic_data_rdata_local),
- .irq_software_i (irq_software_i),
- .irq_timer_i (irq_timer_i),
- .irq_external_i (irq_external_i),
- .irq_fast_i (irq_fast_i),
- .irq_nm_i (irq_nm_i),
- .irq_pending_i (irq_pending),
+ .irq_software_i (irq_software_local),
+ .irq_timer_i (irq_timer_local),
+ .irq_external_i (irq_external_local),
+ .irq_fast_i (irq_fast_local),
+ .irq_nm_i (irq_nm_local),
+ .irq_pending_i (irq_pending_local),
- .debug_req_i (debug_req_i),
- .crash_dump_i (crash_dump_o),
+ .debug_req_i (debug_req_local),
+ .crash_dump_i (crash_dump_local),
- .alert_minor_o (lockstep_alert_minor),
- .alert_major_o (lockstep_alert_major),
- .core_busy_i (core_busy_d)
+ .alert_minor_o (lockstep_alert_minor_local),
+ .alert_major_o (lockstep_alert_major_local),
+ .core_busy_i (core_busy_local)
);
+
+ // Manually buffer the output signals.
+ prim_buf u_prim_buf_alert_minor (
+ .in_i(lockstep_alert_minor_local),
+ .out_o(lockstep_alert_minor)
+ );
+
+ prim_buf u_prim_buf_alert_major (
+ .in_i(lockstep_alert_major_local),
+ .out_o(lockstep_alert_major)
+ );
+
end else begin : gen_no_lockstep
assign lockstep_alert_major = 1'b0;
assign lockstep_alert_minor = 1'b0;
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 898d624..07359c4 100644
--- a/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
+++ b/hw/vendor/lowrisc_ibex/syn/tcl/yosys_run_synth.tcl
@@ -33,11 +33,11 @@
yosys "synth $flatten_opt -top $lr_synth_top_module"
yosys "opt -purge"
+yosys "write_verilog $lr_synth_pre_map_out"
+
# 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"
yosys "opt"