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"