From cb608c5f2427aa45cb84c77c6d4979f9af4e6fd7 Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Thu, 25 May 2023 15:40:05 +0200 Subject: [PATCH 01/15] update cve2 (wip) --- core-v-mini-mcu.core | 2 +- hw/core-v-mini-mcu/cpu_subsystem.sv | 79 +- .../bhv/cve2_sim_clock_gate.sv | 2 +- .../cv32e20_manifest.flist | 64 + .../openhwgroup_cv32e20/cve2_configs.yaml | 101 ++ hw/vendor/openhwgroup_cv32e20/cve2_core.core | 115 ++ .../openhwgroup_cv32e20/cve2_icache.core | 22 + .../openhwgroup_cv32e20/cve2_multdiv.core | 28 + .../{ibex_pkg.core => cve2_pkg.core} | 6 +- hw/vendor/openhwgroup_cv32e20/cve2_top.core | 115 ++ .../{cve2.core => cve2_top_tracing.core} | 110 +- .../openhwgroup_cv32e20/cve2_tracer.core | 20 + .../lint/verilator_waiver.vlt | 28 +- .../rtl/{ibex_alu.sv => cve2_alu.sv} | 8 +- ...anch_predict.sv => cve2_branch_predict.sv} | 4 +- ..._decoder.sv => cve2_compressed_decoder.sv} | 4 +- ...{ibex_controller.sv => cve2_controller.sv} | 57 +- hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f | 17 + .../rtl/{ibex_core.sv => cve2_core.sv} | 319 +---- .../rtl/{ibex_counter.sv => cve2_counter.sv} | 2 +- ...x_cs_registers.sv => cve2_cs_registers.sv} | 248 +--- .../rtl/{ibex_csr.sv => cve2_csr.sv} | 2 +- .../rtl/{ibex_decoder.sv => cve2_decoder.sv} | 73 +- .../{ibex_ex_block.sv => cve2_ex_block.sv} | 46 +- ...{ibex_fetch_fifo.sv => cve2_fetch_fifo.sv} | 32 +- .../{ibex_id_stage.sv => cve2_id_stage.sv} | 259 ++-- .../{ibex_if_stage.sv => cve2_if_stage.sv} | 387 +----- ..._store_unit.sv => cve2_load_store_unit.sv} | 8 +- ...x_multdiv_fast.sv => cve2_multdiv_fast.sv} | 15 +- ...x_multdiv_slow.sv => cve2_multdiv_slow.sv} | 15 +- .../rtl/{ibex_pkg.sv => cve2_pkg.sv} | 72 +- .../rtl/{ibex_pmp.sv => cve2_pmp.sv} | 14 +- ...default.svh => cve2_pmp_reset_default.svh} | 0 ...etch_buffer.sv => cve2_prefetch_buffer.sv} | 44 +- ...er_file_ff.sv => cve2_register_file_ff.sv} | 34 +- .../rtl/cve2_sleep_unit.sv | 118 -- hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv | 271 ++++ ...bex_top_tracing.sv => cve2_top_tracing.sv} | 49 +- .../rtl/{ibex_tracer.sv => cve2_tracer.sv} | 14 +- ...{ibex_tracer_pkg.sv => cve2_tracer_pkg.sv} | 4 +- .../{ibex_wb_stage.sv => cve2_wb_stage.sv} | 25 +- hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f | 17 - .../rtl/ibex_dummy_instr.sv | 150 --- .../openhwgroup_cv32e20/rtl/ibex_icache.sv | 1165 ----------------- .../openhwgroup_cv32e20/rtl/ibex_lockstep.sv | 491 ------- .../rtl/ibex_register_file_fpga.sv | 83 -- .../rtl/ibex_register_file_latch.sv | 164 --- hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv | 978 -------------- .../openhwgroup_cv32e20/scripts/sec/README.md | 30 + .../scripts/sec/cadence/sec.tcl | 31 + .../openhwgroup_cv32e20/scripts/sec/sec.sh | 108 ++ .../lowrisc_ip/dv/sv/dv_utils/README.md | 0 .../dv/sv/dv_utils/dv_fcov_macros.core | 17 + .../dv/sv/dv_utils/dv_fcov_macros.svh | 112 ++ .../lowrisc_ip/dv/sv/dv_utils/dv_macros.core | 17 + .../lowrisc_ip/dv/sv/dv_utils/dv_macros.svh | 536 ++++++++ .../dv/sv/dv_utils/dv_report_catcher.sv | 46 + .../dv/sv/dv_utils/dv_report_server.sv | 65 + .../dv/sv/dv_utils/dv_test_status.core | 17 + .../dv/sv/dv_utils/dv_test_status_pkg.sv | 31 + .../lowrisc_ip/dv/sv/dv_utils/dv_utils.core | 28 + .../lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv | 223 ++++ .../lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv | 96 ++ hw/vendor/openhwgroup_cve2.lock.hjson | 4 +- hw/vendor/openhwgroup_cve2.vendor.hjson | 26 +- 65 files changed, 2610 insertions(+), 4658 deletions(-) create mode 100644 hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist create mode 100644 hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml create mode 100644 hw/vendor/openhwgroup_cv32e20/cve2_core.core create mode 100644 hw/vendor/openhwgroup_cv32e20/cve2_icache.core create mode 100644 hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core rename hw/vendor/openhwgroup_cv32e20/{ibex_pkg.core => cve2_pkg.core} (73%) create mode 100644 hw/vendor/openhwgroup_cv32e20/cve2_top.core rename hw/vendor/openhwgroup_cv32e20/{cve2.core => cve2_top_tracing.core} (55%) create mode 100644 hw/vendor/openhwgroup_cv32e20/cve2_tracer.core rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_alu.sv => cve2_alu.sv} (99%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_branch_predict.sv => cve2_branch_predict.sv} (98%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_compressed_decoder.sv => cve2_compressed_decoder.sv} (99%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_controller.sv => cve2_controller.sv} (95%) create mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_core.sv => cve2_core.sv} (83%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_counter.sv => cve2_counter.sv} (99%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_cs_registers.sv => cve2_cs_registers.sv} (88%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_csr.sv => cve2_csr.sv} (98%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_decoder.sv => cve2_decoder.sv} (94%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_ex_block.sv => cve2_ex_block.sv} (82%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_fetch_fifo.sv => cve2_fetch_fifo.sv} (92%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_id_stage.sv => cve2_id_stage.sv} (83%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_if_stage.sv => cve2_if_stage.sv} (56%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_load_store_unit.sv => cve2_load_store_unit.sv} (98%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_multdiv_fast.sv => cve2_multdiv_fast.sv} (97%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_multdiv_slow.sv => cve2_multdiv_slow.sv} (96%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_pkg.sv => cve2_pkg.sv} (83%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_pmp.sv => cve2_pmp.sv} (95%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_pmp_reset_default.svh => cve2_pmp_reset_default.svh} (100%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_prefetch_buffer.sv => cve2_prefetch_buffer.sv} (90%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_register_file_ff.sv => cve2_register_file_ff.sv} (66%) delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv create mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_top_tracing.sv => cve2_top_tracing.sv} (78%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_tracer.sv => cve2_tracer.sv} (98%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_tracer_pkg.sv => cve2_tracer_pkg.sv} (99%) rename hw/vendor/openhwgroup_cv32e20/rtl/{ibex_wb_stage.sv => cve2_wb_stage.sv} (91%) delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv create mode 100644 hw/vendor/openhwgroup_cv32e20/scripts/sec/README.md create mode 100644 hw/vendor/openhwgroup_cv32e20/scripts/sec/cadence/sec.tcl create mode 100755 hw/vendor/openhwgroup_cv32e20/scripts/sec/sec.sh create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/README.md create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv create mode 100644 hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv diff --git a/core-v-mini-mcu.core b/core-v-mini-mcu.core index b8e096d0d..021f84c34 100644 --- a/core-v-mini-mcu.core +++ b/core-v-mini-mcu.core @@ -13,7 +13,7 @@ filesets: - x-heep::packages - openhwgroup.org:ip:cv32e40p - openhwgroup.org:ip:cv32e40x - - openhwgroup.org:ip:cve2 + - openhwgroup:cve2:cve2_top - pulp-platform.org:ip:gpio - pulp-platform.org::common_cells - pulp-platform.org::cluster_interconnect diff --git a/hw/core-v-mini-mcu/cpu_subsystem.sv b/hw/core-v-mini-mcu/cpu_subsystem.sv index 75f57a65c..c65eb17c1 100644 --- a/hw/core-v-mini-mcu/cpu_subsystem.sv +++ b/hw/core-v-mini-mcu/cpu_subsystem.sv @@ -59,21 +59,13 @@ module cpu_subsystem if (CPU_TYPE == cv32e20) begin : gen_cv32e20 - logic [4:0] rf_raddr_a, rf_raddr_b, rf_waddr_wb; - logic [31:0] rf_rdata_a, rf_rdata_b, rf_wdata_wb; - logic rf_we_wb; - - import ibex_pkg::*; - - ibex_core #( - .DmHaltAddr(DM_HALTADDRESS), - .DmExceptionAddr(32'h0), - .DbgTriggerEn(1'b1), - .ResetAll(1'b1) - ) cv32e20_i ( + cve2_top cv32e20_i ( .clk_i (clk_i), .rst_ni(rst_ni), + .test_en_i(1'b0), + .ram_cfg_i('0), + .hart_id_i (32'h0), .boot_addr_i(BOOT_ADDR), @@ -94,79 +86,20 @@ module cpu_subsystem .data_rvalid_i(core_data_resp_i.rvalid), .data_err_i (1'b0), - .dummy_instr_id_o (), - .rf_raddr_a_o (rf_raddr_a), - .rf_raddr_b_o (rf_raddr_b), - .rf_waddr_wb_o (rf_waddr_wb), - .rf_we_wb_o (rf_we_wb), - .rf_wdata_wb_ecc_o(rf_wdata_wb), - .rf_rdata_a_ecc_i (rf_rdata_a), - .rf_rdata_b_ecc_i (rf_rdata_b), - - .ic_tag_req_o (), - .ic_tag_write_o (), - .ic_tag_addr_o (), - .ic_tag_wdata_o (), - .ic_tag_rdata_i (), - .ic_data_req_o (), - .ic_data_write_o (), - .ic_data_addr_o (), - .ic_data_wdata_o (), - .ic_data_rdata_i (), - .ic_scr_key_valid_i(), - .irq_software_i(irq_i[3]), .irq_timer_i (irq_i[7]), .irq_external_i(irq_i[11]), .irq_fast_i (irq_i[30:16]), .irq_nm_i (irq_i[31]), - .irq_pending_o (), .debug_req_i(debug_req_i), .crash_dump_o(), - .double_fault_seen_o(), - - .fetch_enable_i(fetch_enable), - .alert_minor_o (), - .alert_major_o (), - .icache_inval_o(), - .core_sleep_o - ); - cv32e40p_register_file #( - .ADDR_WIDTH(6) - ) cv32e20_register_file_i ( - // Clock and Reset - .clk (clk_i), - .rst_n(rst_ni), - - .scan_cg_en_i(1'b0), + //.fetch_enable_i(fetch_enable), - //Read port R1 - .raddr_a_i({1'b0, rf_raddr_a}), - .rdata_a_o(rf_rdata_a), - - //Read port R2 - .raddr_b_i({1'b0, rf_raddr_b}), - .rdata_b_o(rf_rdata_b), - - //Read port R3 - .raddr_c_i('0), - .rdata_c_o(), - - // Write port W1 - .waddr_a_i({1'b0, rf_waddr_wb}), - .wdata_a_i(rf_wdata_wb), - .we_a_i(rf_we_wb), - - // Write port W2 - .waddr_b_i('0), - .wdata_b_i('0), - .we_b_i('0) + .core_sleep_o ); - - assign irq_ack_o = '0; assign irq_id_o = '0; diff --git a/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv b/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv index 8cc81dd3c..7974cf926 100644 --- a/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv +++ b/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv @@ -27,4 +27,4 @@ module cve2_clock_gate ( assign clk_o = clk_i & clk_en; -endmodule // cv32e40p_clock_gate +endmodule // cve2_clock_gate diff --git a/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist b/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist new file mode 100644 index 000000000..96fd38fbe --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2022 OpenHW Group +// +// Licensed under the Solderpad Hardware Licence, 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 +// +// https://solderpad.org/licenses/ +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +/////////////////////////////////////////////////////////////////////////////// +// +// Manifest for the CV32E20 RTL model. +// - Format based on manifest used by other CORE-V cores. +// - Intended to be used by both synthesis and simulation. +// - Relevent synthesis and simulation scripts/Makefiles must set the shell +// ENV variable DESIGN_RTL_DIR as required. +// +// TODO: Replace once-and-for-all with unified manifest (FuseSoc?) +// +/////////////////////////////////////////////////////////////////////////////// + ++incdir+${DESIGN_RTL_DIR}/../shared/rtl/ ++incdir+${DESIGN_RTL_DIR}/../rtl ++incdir+${DESIGN_RTL_DIR}/../shared/rtl/sim ++incdir+${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl ++incdir+${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/dv/sv/dv_utils + +${DESIGN_RTL_DIR}/cve2_pkg.sv +${DESIGN_RTL_DIR}/cve2_tracer_pkg.sv +${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl/prim_secded_pkg.sv +${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv +${DESIGN_RTL_DIR}/cve2_alu.sv +${DESIGN_RTL_DIR}/cve2_branch_predict.sv +${DESIGN_RTL_DIR}/cve2_compressed_decoder.sv +${DESIGN_RTL_DIR}/cve2_controller.sv +${DESIGN_RTL_DIR}/cve2_cs_registers.sv +${DESIGN_RTL_DIR}/cve2_csr.sv +${DESIGN_RTL_DIR}/cve2_counter.sv +${DESIGN_RTL_DIR}/cve2_decoder.sv +${DESIGN_RTL_DIR}/cve2_ex_block.sv +${DESIGN_RTL_DIR}/cve2_fetch_fifo.sv +${DESIGN_RTL_DIR}/cve2_id_stage.sv +${DESIGN_RTL_DIR}/cve2_if_stage.sv +${DESIGN_RTL_DIR}/cve2_load_store_unit.sv +${DESIGN_RTL_DIR}/cve2_multdiv_fast.sv +${DESIGN_RTL_DIR}/cve2_multdiv_slow.sv +${DESIGN_RTL_DIR}/cve2_prefetch_buffer.sv +${DESIGN_RTL_DIR}/cve2_pmp.sv +${DESIGN_RTL_DIR}/cve2_register_file_ff.sv +${DESIGN_RTL_DIR}/cve2_wb_stage.sv +${DESIGN_RTL_DIR}/cve2_core.sv +${DESIGN_RTL_DIR}/cve2_top.sv +${DESIGN_RTL_DIR}/cve2_top_tracing.sv +${DESIGN_RTL_DIR}/cve2_tracer.sv + +${DESIGN_RTL_DIR}/../bhv/cve2_sim_clock_gate.sv diff --git a/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml b/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml new file mode 100644 index 000000000..96de10aa4 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml @@ -0,0 +1,101 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Ibex configurations files, holds the parameter sets that are tested under CI. +# Each configuration must specify the same set of parameters + +# Two-stage pipeline without additional branch target ALU and 3 cycle multiplier +# (4 cycles for mulh), resulting in 2 stall cycles for mul (3 for mulh) +small: + RV32E : 0 + RV32M : "cve2_pkg::RV32MFast" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 0 + BranchPredictor : 0 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + +# Configuration to match that used in the OpenTitan project +opentitan: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BOTEarlGrey" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + BranchPredictor : 0 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# =============================== +# * EXPERIMENTAL CONFIGURATIONS * +# =============================== + +# Three-stage pipeline with additional branch traget ALU and 1 cycle multiplier +# (2 cycles for mulh) so mul does not stall (mulh stall 1 cycles). This is the +# maximum performance configuration. +experimental-maxperf: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + BranchPredictor : 0 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + +# experimental-maxperf config above plus PMP enabled with 16 regions. +experimental-maxperf-pmp: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + BranchPredictor : 0 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf-pmp config above with balanced bitmanip extension +experimental-maxperf-pmp-bmbalanced: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BBalanced" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + BranchPredictor : 0 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf-pmp config above with full bitmanip extension +experimental-maxperf-pmp-bmfull: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BFull" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + BranchPredictor : 0 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf with branch predictor switched on. This exists to allow +# easy use of Ibex with the branch predictor in particular for CI runs. The +# branch predictor will be enabled in all the 'maxperf' configs after further +# development. +experimental-branch-predictor: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + BranchPredictor : 1 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + diff --git a/hw/vendor/openhwgroup_cv32e20/cve2_core.core b/hw/vendor/openhwgroup_cv32e20/cve2_core.core new file mode 100644 index 000000000..f0d775a7b --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/cve2_core.core @@ -0,0 +1,115 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "openhwgroup:cve2:cve2_core:0.1" +description: "Ibex CPU Core Components" + +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - openhwgroup:cve2:cve2_pkg + - lowrisc:dv:dv_fcov_macros + files: + - rtl/cve2_alu.sv + - rtl/cve2_branch_predict.sv + - rtl/cve2_compressed_decoder.sv + - rtl/cve2_controller.sv + - rtl/cve2_cs_registers.sv + - rtl/cve2_csr.sv + - rtl/cve2_counter.sv + - rtl/cve2_decoder.sv + - rtl/cve2_ex_block.sv + - rtl/cve2_fetch_fifo.sv + - rtl/cve2_id_stage.sv + - rtl/cve2_if_stage.sv + - rtl/cve2_load_store_unit.sv + - rtl/cve2_multdiv_fast.sv + - rtl/cve2_multdiv_slow.sv + - rtl/cve2_prefetch_buffer.sv + - rtl/cve2_pmp.sv + - rtl/cve2_wb_stage.sv + - rtl/cve2_core.sv + - rtl/cve2_pmp_reset_default.svh: {is_include_file: true} + file_type: systemVerilogSource + + files_lint_verilator: + files: + - lint/verilator_waiver.vlt: {file_type: vlt} + + files_lint_verible: + files: + - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} + + files_check_tool_requirements: + depend: + - lowrisc:tool:check_tool_requirements + +parameters: + RVFI: + datatype: bool + paramtype: vlogdefine + + SYNTHESIS: + 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 + paramtype: vlogparam + + RV32M: + datatype: str + default: cve2_pkg::RV32MFast + paramtype: vlogdefine + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." + + RV32B: + datatype: str + default: cve2_pkg::RV32BNone + paramtype: vlogdefine + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_lint_verilator) + - tool_veriblelint ? (files_lint_verible) + - files_rtl + toplevel: cve2_core + parameters: + - tool_vivado ? (FPGA_XILINX=true) + lint: + <<: *default_target + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: verilator + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" + # RAM primitives wider than 64bit (required for ECC) fail to build in + # Verilator without increasing the unroll count (see Verilator#1266) + - "--unroll-count 72" + format: + filesets: + - files_rtl + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: veribleformat + toplevel: cve2_core + tools: + veribleformat: + verible_format_args: + - "--inplace" diff --git a/hw/vendor/openhwgroup_cv32e20/cve2_icache.core b/hw/vendor/openhwgroup_cv32e20/cve2_icache.core new file mode 100644 index 000000000..ad2c2617a --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/cve2_icache.core @@ -0,0 +1,22 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_icache:0.1" +description: "Ibex instruction cache" +filesets: + files_rtl: + depend: + - lowrisc:prim:secded + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_icache.sv + file_type: systemVerilogSource + +targets: + default: &default_target + filesets: + - files_rtl + toplevel: cve2_icache + default_tool: vcs diff --git a/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core b/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core new file mode 100644 index 000000000..700e6c9e2 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core @@ -0,0 +1,28 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_multdiv:0.1" +description: "Multiplier and divider" + +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_multdiv_fast.sv + - rtl/cve2_multdiv_slow.sv + file_type: systemVerilogSource + +parameters: + RV32M: + datatype: int + default: 2 + paramtype: vlogparam + description: "Selection of multiplication implementation. Switch to enable single cycle multiplications." + +targets: + default: &default_target + filesets: + - files_rtl diff --git a/hw/vendor/openhwgroup_cv32e20/ibex_pkg.core b/hw/vendor/openhwgroup_cv32e20/cve2_pkg.core similarity index 73% rename from hw/vendor/openhwgroup_cv32e20/ibex_pkg.core rename to hw/vendor/openhwgroup_cv32e20/cve2_pkg.core index 17f47e08c..a89c9e120 100644 --- a/hw/vendor/openhwgroup_cv32e20/ibex_pkg.core +++ b/hw/vendor/openhwgroup_cv32e20/cve2_pkg.core @@ -2,13 +2,13 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:ibex:ibex_pkg:0.1" -description: "Header package for Ibex" +name: "openhwgroup:cve2:cve2_pkg:0.1" +description: "Header package for CVE2" filesets: files_rtl: files: - - rtl/ibex_pkg.sv + - rtl/cve2_pkg.sv file_type: systemVerilogSource targets: diff --git a/hw/vendor/openhwgroup_cv32e20/cve2_top.core b/hw/vendor/openhwgroup_cv32e20/cve2_top.core new file mode 100644 index 000000000..05806e45e --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/cve2_top.core @@ -0,0 +1,115 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "openhwgroup:cve2:cve2_top:0.1" +description: "Ibex, a small RV32 CPU core" + +filesets: + files_rtl: + depend: + - openhwgroup:cve2:cve2_pkg + - openhwgroup:cve2:cve2_core + - lowrisc:prim:buf + - lowrisc:prim:clock_mux2 + - lowrisc:prim:flop + - lowrisc:prim:ram_1p_scr + files: + - rtl/cve2_register_file_ff.sv # generic FF-based + - rtl/cve2_top.sv + file_type: systemVerilogSource + + files_lint_verilator: + files: + - lint/verilator_waiver.vlt: {file_type: vlt} + + files_lint_verible: + files: + - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} + + files_check_tool_requirements: + depend: + - lowrisc:tool:check_tool_requirements + + files_clk_gate: + files: + - bhv/cve2_sim_clock_gate.sv + file_type: systemVerilogSource + +parameters: + RVFI: + datatype: bool + paramtype: vlogdefine + + SYNTHESIS: + 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 + paramtype: vlogparam + + RV32M: + datatype: str + default: cve2_pkg::RV32MFast + paramtype: vlogdefine + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." + + RV32B: + datatype: str + default: cve2_pkg::RV32BNone + paramtype: vlogdefine + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." + + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_lint_verilator) + - tool_veriblelint ? (files_lint_verible) + - files_rtl + - target_sim ? (files_clk_gate) + toplevel: cve2_top + parameters: + - tool_vivado ? (FPGA_XILINX=true) + + lint: + <<: *default_target + parameters: + - SYNTHESIS=true + - RVFI=true + filesets_append: + - files_clk_gate + default_tool: verilator + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" + # RAM primitives wider than 64bit (required for ECC) fail to build in + # Verilator without increasing the unroll count (see Verilator#1266) + - "--unroll-count 72" + + format: + filesets: + - files_rtl + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: veribleformat + toplevel: cve2_top + tools: + veribleformat: + verible_format_args: + - "--inplace" + - "--formal_parameters_indentation=indent" + - "--named_parameter_indentation=indent" + - "--named_port_indentation=indent" + - "--port_declarations_indentation=indent" diff --git a/hw/vendor/openhwgroup_cv32e20/cve2.core b/hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core similarity index 55% rename from hw/vendor/openhwgroup_cv32e20/cve2.core rename to hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core index ec43f9cb5..da631231d 100644 --- a/hw/vendor/openhwgroup_cv32e20/cve2.core +++ b/hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core @@ -2,68 +2,28 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 - -name: "openhwgroup.org:ip:cve2" -description: "OpenHW Group RISC-V Core CVE2" - +name: "lowrisc:cve2:cve2_top_tracing:0.1" +description: "Ibex, a small RV32 CPU core with tracing enabled" filesets: files_rtl: depend: - - lowrisc:prim:assert - - lowrisc:ibex:ibex_pkg - files: - - rtl/ibex_alu.sv - - rtl/ibex_branch_predict.sv - - rtl/ibex_compressed_decoder.sv - - rtl/ibex_controller.sv - - rtl/ibex_cs_registers.sv - - rtl/ibex_csr.sv - - rtl/ibex_counter.sv - - rtl/ibex_decoder.sv - - rtl/ibex_ex_block.sv - - rtl/ibex_fetch_fifo.sv - - rtl/ibex_id_stage.sv - - rtl/ibex_if_stage.sv - - rtl/ibex_load_store_unit.sv - - rtl/ibex_multdiv_fast.sv - - rtl/ibex_multdiv_slow.sv - - rtl/ibex_prefetch_buffer.sv - - rtl/ibex_pmp.sv - - rtl/ibex_wb_stage.sv - - rtl/ibex_dummy_instr.sv - - rtl/ibex_core.sv - - rtl/cve2_sleep_unit.sv - - rtl/ibex_pmp_reset_default.svh: {is_include_file: true} - file_type: systemVerilogSource - - files_lint_verilator: - files: - - lint/verilator_waiver.vlt: {file_type: vlt} - - files_lint_verible: - files: - - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} - - files_clk_gate: + - lowrisc:cve2:cve2_top + - lowrisc:cve2:cve2_tracer files: - - bhv/cve2_sim_clock_gate.sv + - rtl/cve2_top_tracing.sv file_type: systemVerilogSource parameters: + # The tracer uses the RISC-V Formal Interface (RVFI) to collect trace signals. RVFI: datatype: bool paramtype: vlogdefine + default: true SYNTHESIS: 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 @@ -71,21 +31,21 @@ parameters: RV32M: datatype: str - default: ibex_pkg::RV32MFast + default: cve2_pkg::RV32MFast paramtype: vlogdefine - description: "RV32M implementation parameter enum. See the ibex_pkg::rv32m_e enum in ibex_pkg.sv for permitted values." + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." RV32B: datatype: str - default: ibex_pkg::RV32BNone + default: cve2_pkg::RV32BNone paramtype: vlogdefine - description: "Bitmanip implementation parameter enum. See the ibex_pkg::rv32b_e enum in ibex_pkg.sv for permitted values." + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." RegFile: datatype: str - default: ibex_pkg::RegFileFF + default: cve2_pkg::RegFileFF paramtype: vlogdefine - description: "Register file implementation parameter enum. See the ibex_pkg::regfile_e enum in ibex_pkg.sv for permitted values." + description: "Register file implementation parameter enum. See the cve2_pkg::regfile_e enum in cve2_pkg.sv for permitted values." ICache: datatype: int @@ -99,12 +59,6 @@ parameters: paramtype: vlogparam description: "Enable ECC protection in instruction cache" - BranchTargetALU: - datatype: int - default: 0 - paramtype: vlogparam - description: "Enables separate branch target ALU (increasing branch performance EXPERIMENTAL) [0/1]" - WritebackStage: datatype: int default: 0 @@ -117,12 +71,18 @@ parameters: default: 0 description: "Enables static branch prediction (EXPERIMENTAL)" - SecureIbex: + SecureCVE2: datatype: int default: 0 paramtype: vlogparam description: "Enables security hardening features (EXPERIMENTAL) [0/1]" + ICacheScramble: + datatype: int + default: 0 + paramtype: vlogparam + description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]" + PMPEnable: datatype: int default: 0 @@ -144,19 +104,29 @@ parameters: targets: default: &default_target filesets: - - tool_verilator ? (files_lint_verilator) - - tool_veriblelint ? (files_lint_verible) - files_rtl - - target_sim? (files_clk_gate) - - target_sim-opt? (files_clk_gate) - toplevel: ibex_core parameters: - - tool_vivado ? (FPGA_XILINX=true) + - RVFI=true + toplevel: cve2_top_tracing + lint: <<: *default_target parameters: - - SYNTHESIS=true - RVFI=true + - SYNTHESIS=true + - RV32E + - RV32M + - RV32B + - RegFile + - ICache + - ICacheECC + - WritebackStage + - BranchPredictor + - SecureCVE2 + - ICacheScramble + - PMPEnable + - PMPGranularity + - PMPNumRegions default_tool: verilator tools: verilator: @@ -173,8 +143,12 @@ targets: - SYNTHESIS=true - RVFI=true default_tool: veribleformat - toplevel: ibex_core + toplevel: cve2_top_tracing tools: veribleformat: verible_format_args: - "--inplace" + - "--formal_parameters_indentation=indent" + - "--named_parameter_indentation=indent" + - "--named_port_indentation=indent" + - "--port_declarations_indentation=indent" diff --git a/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core b/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core new file mode 100644 index 000000000..0e43a8062 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core @@ -0,0 +1,20 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_tracer:0.1" +description: "Tracer for use with Ibex using the RVFI interface" +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_tracer_pkg.sv + - rtl/cve2_tracer.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt b/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt index b7c952ca7..2b6c72719 100644 --- a/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt +++ b/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt @@ -12,7 +12,7 @@ `verilator_config lint_off -rule PINCONNECTEMPTY -// We have some boolean top-level parameters in e.g. ibex_core_tracing.sv. +// We have some boolean top-level parameters in e.g. cve2_core_tracing.sv. // When building with fusesoc, these get set with defines like // -GRV32M=1 (rather than -GRV32M=1'b1), leading to warnings like: // @@ -23,13 +23,13 @@ lint_off -rule PINCONNECTEMPTY // matches when you set a 1-bit value to a literal 1, so it won't hide // silly mistakes like setting it to 2. // -lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" +lint_off -rule WIDTH -file "*/rtl/cve2_top_tracing.sv" -match "*expects 1 bits*Initial value's CONST '32'h1'*" // Operator expects 1 bit on initial value but initial value's CONST generates // 32 bits, need a specific RV32B waiver as it uses enums so the above catch-all // waiver doesn't work. -lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" -match "*'RV32B'*" +lint_off -rule WIDTH -file "*/rtl/cve2_top_tracing.sv" -match "*'RV32B'*" // Bits of signal are not used: be_i[3:1] // Bits of signal are not used: addr_i[31:10,1:0] @@ -52,21 +52,23 @@ lint_off -rule UNUSED -file "*/rtl/timer.sv" -match "*'timer_addr_i'[31:10]*" // Signal is not used: clk_i // leaving clk and reset connected in-case we want to add assertions -lint_off -rule UNUSED -file "*/rtl/ibex_pmp.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_compressed_decoder.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_decoder.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_branch_predict.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_pmp.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_compressed_decoder.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_decoder.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_branch_predict.sv" -match "*clk_i*" // Signal is not used: rst_ni // leaving clk and reset connected in-case we want to add assertions -lint_off -rule UNUSED -file "*/rtl/ibex_pmp.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_compressed_decoder.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_decoder.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_branch_predict.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_pmp.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_compressed_decoder.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_decoder.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_branch_predict.sv" -match "*rst_ni*" // Temporary waivers until OpenTitan primitives are lint-clean // https://github.com/lowRISC/opentitan/issues/2313 lint_off -file "*/lowrisc_prim_*/rtl/*.sv" -lint_off -rule UNUSED -file "*/rtl/ibex_top_tracing.sv" -match "*RndCnstLfsrSeed*" -lint_off -rule UNUSED -file "*/rtl/ibex_top_tracing.sv" -match "*RndCnstLfsrPerm*" +lint_off -rule UNUSED -file "*/rtl/cve2_top_tracing.sv" -match "*RndCnstLfsrSeed*" +lint_off -rule UNUSED -file "*/rtl/cve2_top_tracing.sv" -match "*RndCnstLfsrPerm*" +lint_off -rule DECLFILENAME -file "*/bhv/cve2_sim_clock_gate.sv" -match "Filename 'cve2_sim_clock_gate' does not match MODULE name: 'cve2_clock_gate'" +lint_off -rule UNOPTFLAT -file "*/rtl/cve2_core.sv" -match "Signal unoptimizable: Feedback to clock or circular logic: 'cve2_top.u_cve2_core.irqs'" diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv similarity index 99% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv index eb6afcaed..2471c621e 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv @@ -6,10 +6,10 @@ /** * Arithmetic logic unit */ -module ibex_alu #( - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone +module cve2_alu #( + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( - input ibex_pkg::alu_op_e operator_i, + input cve2_pkg::alu_op_e operator_i, input logic [31:0] operand_a_i, input logic [31:0] operand_b_i, @@ -31,7 +31,7 @@ module ibex_alu #( output logic comparison_result_o, output logic is_equal_result_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] operand_a_rev; logic [32:0] operand_b_neg; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv similarity index 98% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv index 87f838366..e49c70074 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv @@ -17,7 +17,7 @@ `include "prim_assert.sv" -module ibex_branch_predict ( +module cve2_branch_predict ( input logic clk_i, input logic rst_ni, @@ -30,7 +30,7 @@ module ibex_branch_predict ( output logic predict_branch_taken_o, output logic [31:0] predict_branch_pc_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] imm_j_type; logic [31:0] imm_b_type; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv similarity index 99% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv index e3c6aa52c..1b5b17fff 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv @@ -13,7 +13,7 @@ `include "prim_assert.sv" -module ibex_compressed_decoder ( +module cve2_compressed_decoder ( input logic clk_i, input logic rst_ni, input logic valid_i, @@ -22,7 +22,7 @@ module ibex_compressed_decoder ( output logic is_compressed_o, output logic illegal_instr_o ); - import ibex_pkg::*; + import cve2_pkg::*; // valid_i indicates if instr_i is valid and is used for assertions only. // The following signal is used to avoid possible lint errors. diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv similarity index 95% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 0f2ae7bc7..79008223a 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -8,9 +8,9 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_controller #( +module cve2_controller #( parameter bit WritebackStage = 0, parameter bit BranchPredictor = 0 ) ( @@ -47,12 +47,12 @@ module ibex_controller #( // to prefetcher output logic instr_req_o, // start fetching instructions output logic pc_set_o, // jump to address set by pc_mux - output ibex_pkg::pc_sel_e pc_mux_o, // IF stage fetch address selector + output cve2_pkg::pc_sel_e pc_mux_o, // IF stage fetch address selector // (boot, normal, exception...) output logic nt_branch_mispredict_o, // Not-taken branch in ID/EX was // mispredicted (predicted taken) - output ibex_pkg::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC - output ibex_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs + output cve2_pkg::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC + output cve2_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs // LSU input logic [31:0] lsu_addr_last_i, // for mtval @@ -70,14 +70,14 @@ module ibex_controller #( // interrupt signals input logic csr_mstatus_mie_i, // M-mode interrupt enable bit input logic irq_pending_i, // interrupt request pending - input ibex_pkg::irqs_t irqs_i, // interrupt requests qualified with + input cve2_pkg::irqs_t irqs_i, // interrupt requests qualified with // mie CSR input logic irq_nm_i, // non-maskeable interrupt output logic nmi_mode_o, // core executing NMI handler // debug signals input logic debug_req_i, - output ibex_pkg::dbg_cause_e debug_cause_o, + output cve2_pkg::dbg_cause_e debug_cause_o, output logic debug_csr_save_o, output logic debug_mode_o, input logic debug_single_step_i, @@ -85,9 +85,6 @@ module ibex_controller #( input logic debug_ebreaku_i, input logic trigger_match_i, - // Wakeup Signal - output logic wake_from_sleep_o, - output logic csr_save_if_o, output logic csr_save_id_o, output logic csr_save_wb_o, @@ -95,7 +92,7 @@ module ibex_controller #( output logic csr_restore_dret_id_o, output logic csr_save_cause_o, output logic [31:0] csr_mtval_o, - input ibex_pkg::priv_lvl_e priv_mode_i, + input cve2_pkg::priv_lvl_e priv_mode_i, input logic csr_mstatus_tw_i, // stall & flush signals @@ -110,7 +107,7 @@ module ibex_controller #( output logic perf_tbranch_o // we are executing a taken branch // instruction ); - import ibex_pkg::*; + import cve2_pkg::*; // FSM state encoding typedef enum logic [3:0] { @@ -173,8 +170,8 @@ module ibex_controller #( always_ff @(negedge clk_i) begin // print warning in case of decoding errors if ((ctrl_fsm_cs == DECODE) && instr_valid_i && !instr_fetch_err_i && illegal_insn_d) begin - $display("%t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, ibex_core.hart_id_i, - ibex_id_stage.pc_id_i, ibex_id_stage.instr_rdata_i); + $display("%t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, cve2_core.hart_id_i, + cve2_id_stage.pc_id_i, cve2_id_stage.instr_rdata_i); end end // synopsys translate_on @@ -206,7 +203,7 @@ module ibex_controller #( (mret_insn | (csr_mstatus_tw_i & wfi_insn)); // This is recorded in the illegal_insn_q flop to help timing. Specifically - // it is needed to break the path from ibex_cs_registers/illegal_csr_insn_o + // it is needed to break the path from cve2_cs_registers/illegal_csr_insn_o // to pc_set_o. Clear when controller is in FLUSH so it won't remain set // once illegal instruction is handled. // All terms in this expression are qualified by instr_valid_i @@ -346,7 +343,8 @@ module ibex_controller #( // - while in debug mode [Debug Spec v0.13.2, p.39], // - while in NMI mode (nested NMIs are not supported, NMI has highest priority and // cannot be interrupted by regular interrupts). - assign handle_irq = ~debug_mode_q & ~nmi_mode_q & + // - while single stepping. + assign handle_irq = ~debug_mode_q & ~debug_single_step_i & ~nmi_mode_q & (irq_nm_i | (irq_pending_i & csr_mstatus_mie_i)); // generate ID of fast interrupts, highest priority to lowest ID @@ -441,13 +439,12 @@ module ibex_controller #( // normal execution flow // in debug mode or single step mode we leave immediately (wfi=nop) - if (wake_from_sleep_o) begin - ctrl_fsm_ns = FIRST_FETCH; + if (irq_nm_i || irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i) begin + ctrl_fsm_ns = FIRST_FETCH; end else begin // Make sure clock remains disabled. ctrl_busy_o = 1'b0; end - end FIRST_FETCH: begin @@ -742,9 +739,6 @@ module ibex_controller #( csr_restore_dret_id_o = 1'b1; end else if (wfi_insn) begin ctrl_fsm_ns = WAIT_SLEEP; - end else if (csr_pipe_flush && handle_irq) begin - // start handling IRQs when doing CSR-related pipeline flushes - ctrl_fsm_ns = IRQ_TAKEN; end end // exc_req_q @@ -821,20 +815,17 @@ module ibex_controller #( end end - assign wake_from_sleep_o = irq_nm_i || irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i; - - ////////// // FCOV // ////////// - //`DV_FCOV_SIGNAL(logic, interrupt_taken, (ctrl_fsm_cs != IRQ_TAKEN) & (ctrl_fsm_ns == IRQ_TAKEN)) - //`DV_FCOV_SIGNAL(logic, debug_entry_if, - // (ctrl_fsm_cs != DBG_TAKEN_IF) & (ctrl_fsm_ns == DBG_TAKEN_IF)) - //`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) + `DV_FCOV_SIGNAL(logic, interrupt_taken, (ctrl_fsm_cs != IRQ_TAKEN) & (ctrl_fsm_ns == IRQ_TAKEN)) + `DV_FCOV_SIGNAL(logic, debug_entry_if, + (ctrl_fsm_cs != DBG_TAKEN_IF) & (ctrl_fsm_ns == DBG_TAKEN_IF)) + `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 // @@ -923,7 +914,7 @@ module ibex_controller #( `ifdef RVFI // Workaround for internal verilator error when using hierarchical refers to calcuate this - // directly in ibex_core + // directly in cve2_core logic rvfi_flush_next; assign rvfi_flush_next = ctrl_fsm_ns == FLUSH; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f new file mode 100644 index 000000000..3250f7072 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f @@ -0,0 +1,17 @@ +cve2_pkg.sv +cve2_alu.sv +cve2_compressed_decoder.sv +cve2_controller.sv +cve2_counter.sv +cve2_cs_registers.sv +cve2_decoder.sv +cve2_ex_block.sv +cve2_id_stage.sv +cve2_if_stage.sv +cve2_load_store_unit.sv +cve2_multdiv_slow.sv +cve2_multdiv_fast.sv +cve2_prefetch_buffer.sv +cve2_fetch_fifo.sv +cve2_register_file_ff.sv +cve2_core.sv diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv similarity index 83% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv index f57c87d9a..f6329b5f7 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv @@ -12,7 +12,7 @@ /** * Top level module of the ibex RISC-V core */ -module ibex_core import ibex_pkg::*; #( +module cve2_core import cve2_pkg::*; #( parameter bit PMPEnable = 1'b0, parameter int unsigned PMPGranularity = 0, parameter int unsigned PMPNumRegions = 4, @@ -21,23 +21,10 @@ module ibex_core import ibex_pkg::*; #( parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, parameter rv32b_e RV32B = RV32BNone, - parameter bit BranchTargetALU = 1'b0, parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, parameter bit BranchPredictor = 1'b0, parameter bit DbgTriggerEn = 1'b0, parameter int unsigned DbgHwBreakNum = 1, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter bit SecureIbex = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit RegFileECC = 1'b0, - parameter int unsigned RegFileDataWidth = 32, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -45,6 +32,8 @@ module ibex_core import ibex_pkg::*; #( input logic clk_i, input logic rst_ni, + input logic test_en_i, + input logic [31:0] hart_id_i, input logic [31:0] boot_addr_i, @@ -67,29 +56,6 @@ module ibex_core import ibex_pkg::*; #( input logic [31:0] data_rdata_i, input logic data_err_i, - // Register file interface - output logic dummy_instr_id_o, - output logic [4:0] rf_raddr_a_o, - output logic [4:0] rf_raddr_b_o, - output logic [4:0] rf_waddr_wb_o, - output logic rf_we_wb_o, - output logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_o, - input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i, - - // RAMs interface - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - // Interrupt inputs input logic irq_software_i, input logic irq_timer_i, @@ -103,7 +69,6 @@ module ibex_core import ibex_pkg::*; #( output crash_dump_t crash_dump_o, // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - output logic double_fault_seen_o, // RISC-V Formal Interface // Does not comply with the coding standards of _i/_o suffixes, but follows @@ -139,22 +104,13 @@ module ibex_core import ibex_pkg::*; #( `endif // CPU Control Signals - // SEC_CM: FETCH.CTRL.LC_GATED - input logic fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_o, - output logic icache_inval_o, - output logic core_sleep_o + output logic core_busy_o ); localparam int unsigned PMP_NUM_CHAN = 3; // SEC_CM: CORE.DATA_REG_SW.SCA - localparam bit DataIndTiming = SecureIbex; - localparam bit PCIncrCheck = SecureIbex; - localparam bit ShadowCSR = 1'b0; // IF/ID signals - logic dummy_instr_id; logic instr_valid_id; logic instr_new_id; logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage @@ -174,17 +130,6 @@ module ibex_core import ibex_pkg::*; #( logic [33:0] imd_val_q_ex[2]; // Intermediate register for multicycle Ops logic [1:0] imd_val_we_ex; - logic data_ind_timing; - logic dummy_instr_en; - logic [2:0] dummy_instr_mask; - logic dummy_instr_seed_en; - logic [31:0] dummy_instr_seed; - logic icache_enable; - logic icache_inval; - logic icache_ecc_error; - logic pc_mismatch_alert; - logic csr_shadow_err; - logic instr_first_cycle_id; logic instr_valid_clear; logic pc_set; @@ -225,22 +170,16 @@ module ibex_core import ibex_pkg::*; #( logic [31:0] rf_wdata_lsu; logic rf_we_wb; logic rf_we_lsu; - logic rf_ecc_err_comb; 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; logic [31:0] alu_operand_a_ex; logic [31:0] alu_operand_b_ex; - logic [31:0] bt_a_operand; - logic [31:0] bt_b_operand; - logic [31:0] alu_adder_result_ex; // Used to forward computed address to LSU logic [31:0] result_ex; @@ -339,7 +278,7 @@ module ibex_core import ibex_pkg::*; #( logic perf_instr_ret_compressed_wb_spec; logic perf_iside_wait; logic perf_dside_wait; - logic perf_mul_wait; + logic perf_wfi_wait; logic perf_div_wait; logic perf_jump; logic perf_branch; @@ -350,63 +289,24 @@ module ibex_core import ibex_pkg::*; #( // for RVFI logic illegal_insn_id, unused_illegal_insn_id; // ID stage sees an illegal instruction - ////////////////////////////////////////////////////////////////////////////////////////////// - // ____ _ _ __ __ _ // - // / ___| | ___ ___| | __ | \/ | __ _ _ __ __ _ __ _ ___ _ __ ___ ___ _ __ | |_ // - // | | | |/ _ \ / __| |/ / | |\/| |/ _` | '_ \ / _` |/ _` |/ _ \ '_ ` _ \ / _ \ '_ \| __| // - // | |___| | (_) | (__| < | | | | (_| | | | | (_| | (_| | __/ | | | | | __/ | | | |_ // - // \____|_|\___/ \___|_|\_\ |_| |_|\__,_|_| |_|\__,_|\__, |\___|_| |_| |_|\___|_| |_|\__| // - // |___/ // - ////////////////////////////////////////////////////////////////////////////////////////////// - - logic clk; - logic fetch_enable; - logic wake_from_sleep; - - cve2_sleep_unit sleep_unit_i ( - // Clock, reset interface - .clk_ungated_i(clk_i), // Ungated clock - .rst_n (rst_ni), - .clk_gated_o (clk), // Gated clock - .scan_cg_en_i (1'b0), - - // Core sleep - .core_sleep_o(core_sleep_o), - - // Fetch enable - .fetch_enable_i(fetch_enable_i), - .fetch_enable_o(fetch_enable), - - // Core status - .if_busy_i (if_busy), - .ctrl_busy_i(ctrl_busy), - .lsu_busy_i (lsu_busy), - - // WFI wake - .wake_from_sleep_i(wake_from_sleep) - ); + ////////////////////// + // Clock management // + ////////////////////// + // Before going to sleep, wait for I- and D-side + // interfaces to finish ongoing operations. + assign core_busy_o = ctrl_busy | if_busy | lsu_busy; ////////////// // IF stage // ////////////// - ibex_if_stage #( + cve2_if_stage #( .DmHaltAddr (DmHaltAddr), .DmExceptionAddr (DmExceptionAddr), - .DummyInstructions(DummyInstructions), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .PCIncrCheck (PCIncrCheck), - .ResetAll ( ResetAll ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), .BranchPredictor (BranchPredictor) ) if_stage_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), .boot_addr_i(boot_addr_i), @@ -420,18 +320,6 @@ module ibex_core import ibex_pkg::*; #( .instr_rdata_i (instr_rdata_i), .instr_err_i (instr_err_i), - .ic_tag_req_o (ic_tag_req_o), - .ic_tag_write_o (ic_tag_write_o), - .ic_tag_addr_o (ic_tag_addr_o), - .ic_tag_wdata_o (ic_tag_wdata_o), - .ic_tag_rdata_i (ic_tag_rdata_i), - .ic_data_req_o (ic_data_req_o), - .ic_data_write_o (ic_data_write_o), - .ic_data_addr_o (ic_data_addr_o), - .ic_data_wdata_o (ic_data_wdata_o), - .ic_data_rdata_i (ic_data_rdata_i), - .ic_scr_key_valid_i(ic_scr_key_valid_i), - // outputs to ID stage .instr_valid_id_o (instr_valid_id), .instr_new_id_o (instr_new_id), @@ -443,7 +331,6 @@ module ibex_core import ibex_pkg::*; #( .instr_fetch_err_o (instr_fetch_err), .instr_fetch_err_plus2_o (instr_fetch_err_plus2), .illegal_c_insn_id_o (illegal_c_insn_id), - .dummy_instr_id_o (dummy_instr_id), .pc_if_o (pc_if), .pc_id_o (pc_id), .pmp_err_if_i (pmp_req_err[PMP_I]), @@ -456,13 +343,6 @@ module ibex_core import ibex_pkg::*; #( .nt_branch_mispredict_i(nt_branch_mispredict), .exc_pc_mux_i (exc_pc_mux_id), .exc_cause (exc_cause), - .dummy_instr_en_i (dummy_instr_en), - .dummy_instr_mask_i (dummy_instr_mask), - .dummy_instr_seed_en_i (dummy_instr_seed_en), - .dummy_instr_seed_i (dummy_instr_seed), - .icache_enable_i (icache_enable), - .icache_inval_i (icache_inval), - .icache_ecc_error_o (icache_ecc_error), // branch targets .branch_target_ex_i(branch_target_ex), @@ -477,7 +357,6 @@ module ibex_core import ibex_pkg::*; #( // pipeline stalls .id_in_ready_i(id_in_ready), - .pc_mismatch_alert_o(pc_mismatch_alert), .if_busy_o (if_busy) ); @@ -485,24 +364,21 @@ module ibex_core import ibex_pkg::*; #( // available assign perf_iside_wait = id_in_ready & ~instr_valid_id; - // fetch_enable_i can be used to stop the core fetching new instructions - assign instr_req_gated = instr_req_int & fetch_enable; + // For non secure Ibex only the bottom bit of fetch enable is considered + assign instr_req_gated = instr_req_int; ////////////// // ID stage // ////////////// - ibex_id_stage #( + cve2_id_stage #( .RV32E (RV32E), .RV32M (RV32M), .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU), - .DataIndTiming (DataIndTiming), .WritebackStage (WritebackStage), .BranchPredictor(BranchPredictor) ) id_stage_i ( - - .clk_i(clk), + .clk_i (clk_i), .rst_ni(rst_ni), // Processor Enable @@ -531,7 +407,6 @@ module ibex_core import ibex_pkg::*; #( .nt_branch_addr_o (nt_branch_addr), .exc_pc_mux_o (exc_pc_mux_id), .exc_cause_o (exc_cause), - .icache_inval_o (icache_inval), .instr_fetch_err_i (instr_fetch_err), .instr_fetch_err_plus2_i(instr_fetch_err_plus2), @@ -551,9 +426,6 @@ module ibex_core import ibex_pkg::*; #( .imd_val_d_ex_i (imd_val_d_ex), .imd_val_we_ex_i(imd_val_we_ex), - .bt_a_operand_o(bt_a_operand), - .bt_b_operand_o(bt_b_operand), - .mult_en_ex_o (mult_en_ex), .div_en_ex_o (div_en_ex), .mult_sel_ex_o (mult_sel_ex), @@ -578,7 +450,6 @@ module ibex_core import ibex_pkg::*; #( .priv_mode_i (priv_mode_id), .csr_mstatus_tw_i (csr_mstatus_tw), .illegal_csr_insn_i (illegal_csr_insn_id), - .data_ind_timing_i (data_ind_timing), // LSU .lsu_req_o (lsu_req), // to load store unit @@ -611,9 +482,6 @@ module ibex_core import ibex_pkg::*; #( .debug_ebreaku_i (debug_ebreaku), .trigger_match_i (trigger_match), - // Wakeup Signal - .wake_from_sleep_o(wake_from_sleep), - // write data to commit in the register file .result_ex_i(result_ex), .csr_rdata_i(csr_rdata), @@ -627,8 +495,8 @@ module ibex_core import ibex_pkg::*; #( .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_rd_a_wb_match_o(), + .rf_rd_b_wb_match_o(), .rf_waddr_wb_i (rf_waddr_wb), .rf_wdata_fwd_wb_i(rf_wdata_fwd_wb), @@ -646,21 +514,19 @@ module ibex_core import ibex_pkg::*; #( .perf_branch_o (perf_branch), .perf_tbranch_o (perf_tbranch), .perf_dside_wait_o(perf_dside_wait), - .perf_mul_wait_o (perf_mul_wait), + .perf_wfi_wait_o (perf_wfi_wait), .perf_div_wait_o (perf_div_wait), .instr_id_done_o (instr_id_done) ); - assign icache_inval_o = icache_inval; // for RVFI only assign unused_illegal_insn_id = illegal_insn_id; - ibex_ex_block #( + cve2_ex_block #( .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU) + .RV32B (RV32B) ) ex_block_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), // ALU signal from ID stage @@ -669,10 +535,6 @@ module ibex_core import ibex_pkg::*; #( .alu_operand_b_i (alu_operand_b_ex), .alu_instr_first_cycle_i(instr_first_cycle_id), - // Branch target ALU signal from ID stage - .bt_a_operand_i(bt_a_operand), - .bt_b_operand_i(bt_b_operand), - // Multipler/Divider signal from ID stage .multdiv_operator_i (multdiv_operator_ex), .mult_en_i (mult_en_ex), @@ -683,7 +545,6 @@ module ibex_core import ibex_pkg::*; #( .multdiv_operand_a_i (multdiv_operand_a_ex), .multdiv_operand_b_i (multdiv_operand_b_ex), .multdiv_ready_id_i (multdiv_ready_id), - .data_ind_timing_i (data_ind_timing), // Intermediate value register .imd_val_we_o(imd_val_we_ex), @@ -707,8 +568,8 @@ module ibex_core import ibex_pkg::*; #( assign data_req_o = data_req_out & ~pmp_req_err[PMP_D]; assign lsu_resp_err = lsu_load_err | lsu_store_err; - ibex_load_store_unit load_store_unit_i ( - .clk_i (clk), + cve2_load_store_unit load_store_unit_i ( + .clk_i (clk_i), .rst_ni(rst_ni), // data interface @@ -753,11 +614,10 @@ module ibex_core import ibex_pkg::*; #( .perf_store_o(perf_store) ); - ibex_wb_stage #( - .ResetAll ( ResetAll ), + cve2_wb_stage #( .WritebackStage(WritebackStage) ) wb_stage_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni (rst_ni), .en_wb_i (en_wb), .instr_type_wb_i (instr_type_wb), @@ -794,67 +654,6 @@ module ibex_core import ibex_pkg::*; #( .instr_done_wb_o(instr_done_wb) ); - ///////////////////////////// - // Register file interface // - ///////////////////////////// - - assign dummy_instr_id_o = dummy_instr_id; - assign rf_raddr_a_o = rf_raddr_a; - assign rf_waddr_wb_o = rf_waddr_wb; - assign rf_we_wb_o = rf_we_wb; - assign rf_raddr_b_o = rf_raddr_b; - - if (RegFileECC) begin : gen_regfile_ecc - - // SEC_CM: DATA_REG_SW.INTEGRITY - 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_inv_39_32_enc regfile_ecc_enc ( - .data_i(rf_wdata_wb), - .data_o(rf_wdata_wb_ecc_o) - ); - - // ECC checking on register file rdata - prim_secded_inv_39_32_dec regfile_ecc_dec_a ( - .data_i (rf_rdata_a_ecc_i), - .data_o (), - .syndrome_o(), - .err_o (rf_ecc_err_a) - ); - prim_secded_inv_39_32_dec regfile_ecc_dec_b ( - .data_i (rf_rdata_b_ecc_i), - .data_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_i[31:0]; - assign rf_rdata_b = rf_rdata_b_ecc_i[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_o = rf_wdata_wb; - assign rf_rdata_a = rf_rdata_a_ecc_i; - assign rf_rdata_b = rf_rdata_b_ecc_i; - assign rf_ecc_err_comb = 1'b0; - end - /////////////////////// // Crash dump output // /////////////////////// @@ -864,15 +663,6 @@ module ibex_core import ibex_pkg::*; #( assign crash_dump_o.last_data_addr = lsu_addr_last; assign crash_dump_o.exception_addr = csr_mepc; - /////////////////// - // Alert outputs // - /////////////////// - - // Minor alert - core is in a recoverable state - assign alert_minor_o = icache_ecc_error; - - // Major alert - core is unrecoverable - assign alert_major_o = rf_ecc_err_comb | pc_mismatch_alert | csr_shadow_err; // Explict INC_ASSERT block to avoid unused signal lint warnings were asserts are not included `ifdef INC_ASSERT @@ -916,8 +706,24 @@ module ibex_core import ibex_pkg::*; #( //////////////////////// // RF (Register File) // //////////////////////// -`ifdef RVFI -`endif + cve2_register_file_ff #( + .RV32E (RV32E), + .DataWidth (32), + .WordZeroVal (32'0) + ) register_file_i ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .test_en_i(test_en_i), + + .raddr_a_i(rf_raddr_a), + .rdata_a_o(rf_rdata_a), + .raddr_b_i(rf_raddr_b), + .rdata_b_o(rf_rdata_b), + .waddr_a_i(rf_waddr_wb), + .wdata_a_i(rf_wdata_wb), + .we_a_i (rf_we_wb) + ); ///////////////////////////////////////// @@ -927,13 +733,9 @@ module ibex_core import ibex_pkg::*; #( assign csr_wdata = alu_operand_a_ex; assign csr_addr = csr_num_e'(csr_access ? alu_operand_b_ex[11:0] : 12'b0); - ibex_cs_registers #( + cve2_cs_registers #( .DbgTriggerEn (DbgTriggerEn), .DbgHwBreakNum (DbgHwBreakNum), - .DataIndTiming (DataIndTiming), - .DummyInstructions(DummyInstructions), - .ShadowCSR (ShadowCSR), - .ICache (ICache), .MHPMCounterNum (MHPMCounterNum), .MHPMCounterWidth (MHPMCounterWidth), .PMPEnable (PMPEnable), @@ -943,7 +745,7 @@ module ibex_core import ibex_pkg::*; #( .RV32M (RV32M), .RV32B (RV32B) ) cs_registers_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), // Hart ID from outside @@ -995,14 +797,6 @@ module ibex_core import ibex_pkg::*; #( .pc_id_i(pc_id), .pc_wb_i(pc_wb), - .data_ind_timing_o (data_ind_timing), - .dummy_instr_en_o (dummy_instr_en), - .dummy_instr_mask_o (dummy_instr_mask), - .dummy_instr_seed_en_o(dummy_instr_seed_en), - .dummy_instr_seed_o (dummy_instr_seed), - .icache_enable_o (icache_enable), - .csr_shadow_err_o (csr_shadow_err), - .csr_save_if_i (csr_save_if), .csr_save_id_i (csr_save_id), .csr_save_wb_i (csr_save_wb), @@ -1013,8 +807,6 @@ module ibex_core import ibex_pkg::*; #( .csr_mtval_i (csr_mtval), .illegal_csr_insn_o(illegal_csr_insn_id), - .double_fault_seen_o, - // performance counter related signals .instr_ret_i (perf_instr_ret_wb), .instr_ret_compressed_i (perf_instr_ret_compressed_wb), @@ -1027,7 +819,7 @@ module ibex_core import ibex_pkg::*; #( .mem_load_i (perf_load), .mem_store_i (perf_store), .dside_wait_i (perf_dside_wait), - .mul_wait_i (perf_mul_wait), + .wfi_wait_i (perf_wfi_wait), .div_wait_i (perf_div_wait) ); @@ -1055,7 +847,7 @@ module ibex_core import ibex_pkg::*; #( assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ; assign pmp_priv_lvl[PMP_D] = priv_mode_lsu; - ibex_pmp #( + cve2_pmp #( .PMPGranularity(PMPGranularity), .PMPNumChan (PMP_NUM_CHAN), .PMPNumRegions (PMPNumRegions) @@ -1161,14 +953,14 @@ module ibex_core import ibex_pkg::*; #( logic new_debug_req; logic new_nmi; logic new_irq; - ibex_pkg::irqs_t captured_mip; + cve2_pkg::irqs_t captured_mip; logic captured_nmi; logic captured_debug_req; logic captured_valid; // RVFI extension for co-simulation support // debug_req and MIP captured at IF -> ID transition so one extra stage - ibex_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1]; + cve2_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1]; logic rvfi_ext_stage_nmi [RVFI_STAGES+1]; logic rvfi_ext_stage_debug_req [RVFI_STAGES+1]; logic [63:0] rvfi_ext_stage_mcycle [RVFI_STAGES]; @@ -1238,7 +1030,7 @@ module ibex_core import ibex_pkg::*; #( // awaiting instruction retirement and RF Write data/Mem read data whilst instruction is in WB // So first stage becomes valid when instruction leaves ID/EX stage and remains valid until // instruction leaves WB - assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id) | + assign rvfi_stage_valid_d[0] = rvfi_id_done | (rvfi_stage_valid[0] & ~rvfi_wb_done); // Second stage is output stage so simple valid cycle after instruction leaves WB (and so has // retired) @@ -1266,7 +1058,7 @@ module ibex_core import ibex_pkg::*; #( end else begin : gen_rvfi_no_wb_stage // Without writeback stage first RVFI stage is output stage so simply valid the cycle after // instruction leaves ID/EX (and so has retired) - assign rvfi_stage_valid_d[0] = rvfi_id_done & ~dummy_instr_id; + assign rvfi_stage_valid_d[0] = rvfi_id_done; // Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly // setup register write signals assign rvfi_instr_new_wb = instr_new_id; @@ -1275,7 +1067,7 @@ module ibex_core import ibex_pkg::*; #( assign rvfi_wb_done = instr_done_wb; end - assign rvfi_stage_order_d = dummy_instr_id ? rvfi_stage_order[0] : rvfi_stage_order[0] + 64'd1; + assign rvfi_stage_order_d = rvfi_stage_order[0] + 64'd1; // For interrupts and debug Ibex will take the relevant trap as soon as whatever instruction in ID // finishes or immediately if the ID stage is empty. The rvfi_ext interface provides the DV @@ -1602,7 +1394,4 @@ module ibex_core import ibex_pkg::*; #( assign unused_instr_done_wb = instr_done_wb; `endif - // Certain parameter combinations are not supported - `ASSERT_INIT(IllegalParamSecure, !(SecureIbex && (RV32M == RV32MNone))) - endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv similarity index 99% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv index a6187b784..417614b16 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv @@ -1,4 +1,4 @@ -module ibex_counter #( +module cve2_counter #( parameter int CounterWidth = 32, // When set `counter_val_upd_o` provides an incremented version of the counter value, otherwise // the output is hard-wired to 0. This is required to allow Xilinx DSP inference to work diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv similarity index 88% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv index aa3282051..0b3c206f7 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv @@ -12,21 +12,17 @@ `include "prim_assert.sv" -module ibex_cs_registers #( +module cve2_cs_registers #( parameter bit DbgTriggerEn = 0, parameter int unsigned DbgHwBreakNum = 1, - parameter bit DataIndTiming = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit ShadowCSR = 1'b0, - parameter bit ICache = 1'b0, parameter int unsigned MHPMCounterNum = 10, parameter int unsigned MHPMCounterWidth = 40, parameter bit PMPEnable = 0, parameter int unsigned PMPGranularity = 0, parameter int unsigned PMPNumRegions = 4, parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( // Clock and Reset input logic clk_i, @@ -36,8 +32,8 @@ module ibex_cs_registers #( input logic [31:0] hart_id_i, // Privilege mode - output ibex_pkg::priv_lvl_e priv_mode_id_o, - output ibex_pkg::priv_lvl_e priv_mode_lsu_o, + output cve2_pkg::priv_lvl_e priv_mode_id_o, + output cve2_pkg::priv_lvl_e priv_mode_lsu_o, output logic csr_mstatus_tw_o, // mtvec @@ -47,9 +43,9 @@ module ibex_cs_registers #( // Interface to registers (SRAM like) input logic csr_access_i, - input ibex_pkg::csr_num_e csr_addr_i, + input cve2_pkg::csr_num_e csr_addr_i, input logic [31:0] csr_wdata_i, - input ibex_pkg::csr_op_e csr_op_i, + input cve2_pkg::csr_op_e csr_op_i, input csr_op_en_i, output logic [31:0] csr_rdata_o, @@ -60,18 +56,18 @@ module ibex_cs_registers #( input logic [14:0] irq_fast_i, input logic nmi_mode_i, output logic irq_pending_o, // interrupt request pending - output ibex_pkg::irqs_t irqs_o, // interrupt requests qualified with mie + output cve2_pkg::irqs_t irqs_o, // interrupt requests qualified with mie output logic csr_mstatus_mie_o, output logic [31:0] csr_mepc_o, // PMP - output ibex_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions], + output cve2_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions], output logic [33:0] csr_pmp_addr_o [PMPNumRegions], - output ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o, + output cve2_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o, // debug input logic debug_mode_i, - input ibex_pkg::dbg_cause_e debug_cause_i, + input cve2_pkg::dbg_cause_e debug_cause_i, input logic debug_csr_save_i, output logic [31:0] csr_depc_o, output logic debug_single_step_o, @@ -83,15 +79,6 @@ module ibex_cs_registers #( input logic [31:0] pc_id_i, input logic [31:0] pc_wb_i, - // CPU control bits - output logic data_ind_timing_o, - output logic dummy_instr_en_o, - output logic [2:0] dummy_instr_mask_o, - output logic dummy_instr_seed_en_o, - output logic [31:0] dummy_instr_seed_o, - output logic icache_enable_o, - output logic csr_shadow_err_o, - // Exception save/restore input logic csr_save_if_i, input logic csr_save_id_i, @@ -99,12 +86,11 @@ module ibex_cs_registers #( input logic csr_restore_mret_i, input logic csr_restore_dret_i, input logic csr_save_cause_i, - input ibex_pkg::exc_cause_e csr_mcause_i, + input cve2_pkg::exc_cause_e csr_mcause_i, input logic [31:0] csr_mtval_i, output logic illegal_csr_insn_o, // access to non-existent CSR, // with wrong priviledge level, or // missing write permissions - output logic double_fault_seen_o, // Performance Counters input logic instr_ret_i, // instr retired in ID/EX stage input logic instr_ret_compressed_i, // compressed instr retired @@ -117,11 +103,11 @@ module ibex_cs_registers #( input logic mem_load_i, // load from memory in this cycle input logic mem_store_i, // store to memory in this cycle input logic dside_wait_i, // core waiting for the dside - input logic mul_wait_i, // core waiting for multiply + input logic wfi_wait_i, // core waiting for interrupt input logic div_wait_i // core waiting for divide ); - import ibex_pkg::*; + import cve2_pkg::*; localparam int unsigned RV32BEnabled = (RV32B == RV32BNone) ? 0 : 1; localparam int unsigned RV32MEnabled = (RV32M == RV32MNone) ? 0 : 1; @@ -174,23 +160,12 @@ module ibex_cs_registers #( priv_lvl_e prv; } dcsr_t; - // CPU control register fields - typedef struct packed { - logic double_fault_seen; - logic sync_exc_seen; - logic [2:0] dummy_instr_mask; - logic dummy_instr_en; - logic data_ind_timing; - logic icache_enable; - } cpu_ctrl_t; - // Interrupt and exception control signals logic [31:0] exception_pc; // CSRs priv_lvl_e priv_lvl_q, priv_lvl_d; status_t mstatus_q, mstatus_d; - logic mstatus_err; logic mstatus_en; irqs_t mie_q, mie_d; logic mie_en; @@ -203,7 +178,6 @@ module ibex_cs_registers #( logic [31:0] mtval_q, mtval_d; logic mtval_en; logic [31:0] mtvec_q, mtvec_d; - logic mtvec_err; logic mtvec_en; irqs_t mip; dcsr_t dcsr_q, dcsr_d; @@ -224,7 +198,6 @@ module ibex_cs_registers #( // PMP Signals logic [31:0] pmp_addr_rdata [PMP_MAX_REGIONS]; logic [PMP_CFG_W-1:0] pmp_cfg_rdata [PMP_MAX_REGIONS]; - logic pmp_csr_err; pmp_mseccfg_t pmp_mseccfg; // Hardware performance monitor signals @@ -253,11 +226,6 @@ module ibex_cs_registers #( logic [31:0] tmatch_control_rdata; logic [31:0] tmatch_value_rdata; - // CPU control bits - cpu_ctrl_t cpuctrl_q, cpuctrl_d, cpuctrl_wdata_raw, cpuctrl_wdata; - logic cpuctrl_we; - logic cpuctrl_err; - // CSR update logic logic [31:0] csr_wdata_int; logic [31:0] csr_rdata_int; @@ -308,6 +276,8 @@ module ibex_cs_registers #( CSR_MIMPID: csr_rdata_int = CSR_MIMPID_VALUE; // mhartid: unique hardware thread id CSR_MHARTID: csr_rdata_int = hart_id_i; + // mconfigptr: pointer to configuration data structre + CSR_MCONFIGPTR: csr_rdata_int = CSR_MCONFIGPTR_VALUE; // mstatus: always M-mode, contains IE bit CSR_MSTATUS: begin @@ -319,6 +289,13 @@ module ibex_cs_registers #( csr_rdata_int[CSR_MSTATUS_TW_BIT] = mstatus_q.tw; end + // mstatush: All zeros for Ibex (fixed little endian and all other bits reserved) + CSR_MSTATUSH: csr_rdata_int = '0; + + // menvcfg: machine environment configuration, all zeros for Ibex (none of the relevant + // features are implemented) + CSR_MENVCFG, CSR_MENVCFGH: csr_rdata_int = '0; + // misa CSR_MISA: csr_rdata_int = MISA_VALUE; @@ -486,11 +463,6 @@ module ibex_cs_registers #( illegal_csr = ~DbgTriggerEn; end - // Custom CSR for controlling CPU features - CSR_CPUCTRL: begin - csr_rdata_int = {{32 - $bits(cpu_ctrl_t) {1'b0}}, cpuctrl_q}; - end - // Custom CSR for LFSR re-seeding (cannot be read) CSR_SECURESEED: begin csr_rdata_int = '0; @@ -539,11 +511,6 @@ module ibex_cs_registers #( mhpmcounter_we = '0; mhpmcounterh_we = '0; - cpuctrl_we = 1'b0; - cpuctrl_d = cpuctrl_q; - - double_fault_seen_o = 1'b0; - if (csr_we_int) begin unique case (csr_addr_i) // mstatus: IE bit @@ -641,11 +608,6 @@ module ibex_cs_registers #( mhpmcounterh_we[mhpmcounter_idx] = 1'b1; end - CSR_CPUCTRL: begin - cpuctrl_d = cpuctrl_wdata; - cpuctrl_we = 1'b1; - end - default:; endcase end @@ -695,17 +657,6 @@ module ibex_cs_registers #( // save previous status for recoverable NMI mstack_en = 1'b1; - if (!mcause_d[5]) begin - // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC - // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - cpuctrl_we = 1'b1; - - cpuctrl_d.sync_exc_seen = 1'b1; - if (cpuctrl_q.sync_exc_seen) begin - double_fault_seen_o = 1'b1; - cpuctrl_d.double_fault_seen = 1'b1; - end - end end end // csr_save_cause_i @@ -718,10 +669,12 @@ module ibex_cs_registers #( mstatus_en = 1'b1; mstatus_d.mie = mstatus_q.mpie; // re-enable interrupts + if (mstatus_q.mpp != PRIV_LVL_M) begin + mstatus_d.mprv = 1'b0; + end + // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - cpuctrl_we = 1'b1; - cpuctrl_d.sync_exc_seen = 1'b0; if (nmi_mode_i) begin // when returning from an NMI restore state from mstack CSR @@ -801,9 +754,8 @@ module ibex_cs_registers #( mpp: PRIV_LVL_U, mprv: 1'b0, tw: 1'b0}; - ibex_csr #( + cve2_csr #( .Width ($bits(status_t)), - .ShadowCopy(ShadowCSR), .ResetValue({MSTATUS_RST_VAL}) ) u_mstatus_csr ( .clk_i (clk_i), @@ -811,11 +763,11 @@ module ibex_cs_registers #( .wr_data_i ({mstatus_d}), .wr_en_i (mstatus_en), .rd_data_o (mstatus_q), - .rd_error_o(mstatus_err) + .rd_error_o() ); // MEPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -833,7 +785,7 @@ module ibex_cs_registers #( assign mie_d.irq_timer = csr_wdata_int[CSR_MTIX_BIT]; assign mie_d.irq_external = csr_wdata_int[CSR_MEIX_BIT]; assign mie_d.irq_fast = csr_wdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW]; - ibex_csr #( + cve2_csr #( .Width ($bits(irqs_t)), .ShadowCopy(1'b0), .ResetValue('0) @@ -847,7 +799,7 @@ module ibex_cs_registers #( ); // MSCRATCH - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -861,7 +813,7 @@ module ibex_cs_registers #( ); // MCAUSE - ibex_csr #( + cve2_csr #( .Width (6), .ShadowCopy(1'b0), .ResetValue('0) @@ -875,7 +827,7 @@ module ibex_cs_registers #( ); // MTVAL - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -889,9 +841,8 @@ module ibex_cs_registers #( ); // MTVEC - ibex_csr #( + cve2_csr #( .Width (32), - .ShadowCopy(ShadowCSR), .ResetValue(32'd1) ) u_mtvec_csr ( .clk_i (clk_i), @@ -899,7 +850,7 @@ module ibex_cs_registers #( .wr_data_i (mtvec_d), .wr_en_i (mtvec_en), .rd_data_o (mtvec_q), - .rd_error_o(mtvec_err) + .rd_error_o() ); // DCSR @@ -909,7 +860,7 @@ module ibex_cs_registers #( prv: PRIV_LVL_M, default: '0 }; - ibex_csr #( + cve2_csr #( .Width ($bits(dcsr_t)), .ShadowCopy(1'b0), .ResetValue({DCSR_RESET_VAL}) @@ -923,7 +874,7 @@ module ibex_cs_registers #( ); // DEPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -937,7 +888,7 @@ module ibex_cs_registers #( ); // DSCRATCH0 - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -951,7 +902,7 @@ module ibex_cs_registers #( ); // DSCRATCH1 - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -966,7 +917,7 @@ module ibex_cs_registers #( // MSTACK localparam status_stk_t MSTACK_RESET_VAL = '{mpie: 1'b1, mpp: PRIV_LVL_U}; - ibex_csr #( + cve2_csr #( .Width ($bits(status_stk_t)), .ShadowCopy(1'b0), .ResetValue({MSTACK_RESET_VAL}) @@ -980,7 +931,7 @@ module ibex_cs_registers #( ); // MSTACK_EPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -994,7 +945,7 @@ module ibex_cs_registers #( ); // MSTACK_CAUSE - ibex_csr #( + cve2_csr #( .Width (6), .ShadowCopy(1'b0), .ResetValue('0) @@ -1013,10 +964,10 @@ module ibex_cs_registers #( if (PMPEnable) begin : g_pmp_registers // PMP reset values - `ifdef IBEX_CUSTOM_PMP_RESET_VALUES - `include "ibex_pmp_reset.svh" + `ifdef CVE2_CUSTOM_PMP_RESET_VALUES + `include "cve2_pmp_reset.svh" `else - `include "ibex_pmp_reset_default.svh" + `include "cve2_pmp_reset_default.svh" `endif pmp_mseccfg_t pmp_mseccfg_q, pmp_mseccfg_d; @@ -1102,9 +1053,8 @@ module ibex_cs_registers #( &csr_wdata_int[(i%4)*PMP_CFG_W+:2]; assign pmp_cfg_wdata[i].read = csr_wdata_int[(i%4)*PMP_CFG_W]; - ibex_csr #( + cve2_csr #( .Width ($bits(pmp_cfg_t)), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_cfg_rst[i]) ) u_pmp_cfg_csr ( .clk_i (clk_i), @@ -1131,9 +1081,8 @@ module ibex_cs_registers #( (csr_addr == (CSR_OFF_PMP_ADDR + i[11:0])); end - ibex_csr #( + cve2_csr #( .Width (PMPAddrWidth), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_addr_rst[i][33-:PMPAddrWidth]) ) u_pmp_addr_csr ( .clk_i (clk_i), @@ -1164,9 +1113,8 @@ module ibex_cs_registers #( // MSECCFG.RLB cannot be set again assign pmp_mseccfg_d.rlb = any_pmp_entry_locked ? 1'b0 : csr_wdata_int[CSR_MSECCFG_RLB_BIT]; - ibex_csr #( + cve2_csr #( .Width ($bits(pmp_mseccfg_t)), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_mseccfg_rst) ) u_pmp_mseccfg ( .clk_i (clk_i), @@ -1177,7 +1125,6 @@ module ibex_cs_registers #( .rd_error_o(pmp_mseccfg_err) ); - assign pmp_csr_err = (|pmp_cfg_err) | (|pmp_addr_err) | pmp_mseccfg_err; assign pmp_mseccfg = pmp_mseccfg_q; end else begin : g_no_pmp_tieoffs @@ -1190,7 +1137,6 @@ module ibex_cs_registers #( assign csr_pmp_cfg_o[i] = pmp_cfg_t'(1'b0); assign csr_pmp_addr_o[i] = '0; end - assign pmp_csr_err = 1'b0; assign pmp_mseccfg = '0; end @@ -1219,7 +1165,7 @@ module ibex_cs_registers #( end // When adding or altering performance counter meanings and default - // mappings please update dv/verilator/pcount/cpp/ibex_pcounts.cc + // mappings please update dv/verilator/pcount/cpp/cve2_pcounts.cc // appropriately. // // active counters @@ -1234,7 +1180,7 @@ module ibex_cs_registers #( mhpmcounter_incr[8] = branch_i; // num of branches (conditional) mhpmcounter_incr[9] = branch_taken_i; // num of taken branches (conditional) mhpmcounter_incr[10] = instr_ret_compressed_i; // num of compressed instr - mhpmcounter_incr[11] = mul_wait_i; // cycles waiting for multiply + mhpmcounter_incr[11] = wfi_wait_i; // cycles waiting for multiply mhpmcounter_incr[12] = div_wait_i; // cycles waiting for divide end @@ -1255,7 +1201,7 @@ module ibex_cs_registers #( end // mcycle - ibex_counter #( + cve2_counter #( .CounterWidth(64) ) mcycle_counter_i ( .clk_i(clk_i), @@ -1270,7 +1216,7 @@ module ibex_cs_registers #( // minstret - ibex_counter #( + cve2_counter #( .CounterWidth(64), .ProvideValUpd(1) ) minstret_counter_i ( @@ -1306,7 +1252,7 @@ module ibex_cs_registers #( if (i < MHPMCounterNum) begin : gen_imp logic [63:0] mhpmcounter_raw, mhpmcounter_next; - ibex_counter #( + cve2_counter #( .CounterWidth(MHPMCounterWidth), .ProvideValUpd(Cnt == 10) ) mcounters_variable_i ( @@ -1407,7 +1353,7 @@ module ibex_cs_registers #( assign tmatch_value_d = csr_wdata_int[31:0]; // Registers - ibex_csr #( + cve2_csr #( .Width (DbgHwNumLen), .ShadowCopy(1'b0), .ResetValue('0) @@ -1421,7 +1367,7 @@ module ibex_cs_registers #( ); for (genvar i = 0; i < DbgHwBreakNum; i++) begin : g_dbg_tmatch_reg - ibex_csr #( + cve2_csr #( .Width (1), .ShadowCopy(1'b0), .ResetValue('0) @@ -1434,7 +1380,7 @@ module ibex_cs_registers #( .rd_error_o() ); - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -1501,88 +1447,12 @@ module ibex_cs_registers #( // CPU control register // ////////////////////////// - // Cast register write data - assign cpuctrl_wdata_raw = cpu_ctrl_t'(csr_wdata_int[$bits(cpu_ctrl_t)-1:0]); - - // Generate fixed time execution bit - if (DataIndTiming) begin : gen_dit - // SEC_CM: CORE.DATA_REG_SW.SCA - assign cpuctrl_wdata.data_ind_timing = cpuctrl_wdata_raw.data_ind_timing; - - end else begin : gen_no_dit - // tieoff for the unused bit - logic unused_dit; - assign unused_dit = cpuctrl_wdata_raw.data_ind_timing; - - // field will always read as zero if not configured - assign cpuctrl_wdata.data_ind_timing = 1'b0; - end - - assign data_ind_timing_o = cpuctrl_q.data_ind_timing; - - // Generate dummy instruction signals - if (DummyInstructions) begin : gen_dummy - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - assign cpuctrl_wdata.dummy_instr_en = cpuctrl_wdata_raw.dummy_instr_en; - assign cpuctrl_wdata.dummy_instr_mask = cpuctrl_wdata_raw.dummy_instr_mask; - - // Signal a write to the seed register - assign dummy_instr_seed_en_o = csr_we_int && (csr_addr == CSR_SECURESEED); - assign dummy_instr_seed_o = csr_wdata_int; - - end else begin : gen_no_dummy - // tieoff for the unused bit - logic unused_dummy_en; - logic [2:0] unused_dummy_mask; - assign unused_dummy_en = cpuctrl_wdata_raw.dummy_instr_en; - assign unused_dummy_mask = cpuctrl_wdata_raw.dummy_instr_mask; - - // field will always read as zero if not configured - assign cpuctrl_wdata.dummy_instr_en = 1'b0; - assign cpuctrl_wdata.dummy_instr_mask = 3'b000; - assign dummy_instr_seed_en_o = 1'b0; - assign dummy_instr_seed_o = '0; - end - - assign dummy_instr_en_o = cpuctrl_q.dummy_instr_en; - assign dummy_instr_mask_o = cpuctrl_q.dummy_instr_mask; - - // Generate icache enable bit - if (ICache) begin : gen_icache_enable - assign cpuctrl_wdata.icache_enable = cpuctrl_wdata_raw.icache_enable; - end else begin : gen_no_icache - // tieoff for the unused icen bit - logic unused_icen; - assign unused_icen = cpuctrl_wdata_raw.icache_enable; - - // icen field will always read as zero if ICache not configured - assign cpuctrl_wdata.icache_enable = 1'b0; - end - - assign cpuctrl_wdata.double_fault_seen = cpuctrl_wdata_raw.double_fault_seen; - assign cpuctrl_wdata.sync_exc_seen = cpuctrl_wdata_raw.sync_exc_seen; - - assign icache_enable_o = cpuctrl_q.icache_enable; - - ibex_csr #( - .Width ($bits(cpu_ctrl_t)), - .ShadowCopy(ShadowCSR), - .ResetValue('0) - ) u_cpuctrl_csr ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .wr_data_i ({cpuctrl_d}), - .wr_en_i (cpuctrl_we), - .rd_data_o (cpuctrl_q), - .rd_error_o(cpuctrl_err) - ); - - assign csr_shadow_err_o = mstatus_err | mtvec_err | pmp_csr_err | cpuctrl_err; + // Removed //////////////// // Assertions // //////////////// - `ASSERT(IbexCsrOpEnRequiresAccess, csr_op_en_i |-> csr_access_i) + `ASSERT(CVE2CsrOpEnRequiresAccess, csr_op_en_i |-> csr_access_i) endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv similarity index 98% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv index 309a325f8..b464bcced 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv @@ -8,7 +8,7 @@ `include "prim_assert.sv" -module ibex_csr #( +module cve2_csr #( parameter int unsigned Width = 32, parameter bit ShadowCopy = 1'b0, parameter bit [Width-1:0] ResetValue = '0 diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv similarity index 94% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv index 4b0195930..5b9cbca14 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv @@ -13,11 +13,10 @@ `include "prim_assert.sv" -module ibex_decoder #( +module cve2_decoder #( parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit BranchTargetALU = 0 + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( input logic clk_i, input logic rst_ni, @@ -31,8 +30,6 @@ module ibex_decoder #( output logic ecall_insn_o, // syscall instr encountered output logic wfi_insn_o, // wait for interrupt instr encountered output logic jump_set_o, // jump taken set signal - input logic branch_taken_i, // registered branch decision - output logic icache_inval_o, // from IF-ID pipeline register input logic instr_first_cycle_i, // instruction read is in its first cycle @@ -43,10 +40,8 @@ module ibex_decoder #( input logic illegal_c_insn_i, // compressed instruction decode failed // immediates - output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a - output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b - output ibex_pkg::op_a_sel_e bt_a_mux_sel_o, // branch target selection operand a - output ibex_pkg::imm_b_sel_e bt_b_mux_sel_o, // branch target selection operand b + output cve2_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a + output cve2_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b output logic [31:0] imm_i_type_o, output logic [31:0] imm_s_type_o, output logic [31:0] imm_b_type_o, @@ -55,7 +50,7 @@ module ibex_decoder #( output logic [31:0] zimm_rs1_type_o, // register file - output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection + output cve2_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection output logic rf_we_o, // write enable for regfile output logic [4:0] rf_raddr_a_o, output logic [4:0] rf_raddr_b_o, @@ -64,10 +59,10 @@ module ibex_decoder #( output logic rf_ren_b_o, // Instruction reads from RF addr B // ALU - output ibex_pkg::alu_op_e alu_operator_o, // ALU operation selection - output ibex_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC, + output cve2_pkg::alu_op_e alu_operator_o, // ALU operation selection + output cve2_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC, // immediate or zero - output ibex_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or + output cve2_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or // immediate output logic alu_multicycle_o, // ternary bitmanip instruction @@ -77,12 +72,12 @@ module ibex_decoder #( output logic mult_sel_o, // as above but static, for data muxes output logic div_sel_o, // as above but static, for data muxes - output ibex_pkg::md_op_e multdiv_operator_o, + output cve2_pkg::md_op_e multdiv_operator_o, output logic [1:0] multdiv_signed_mode_o, // CSRs output logic csr_access_o, // access to CSR - output ibex_pkg::csr_op_e csr_op_o, // operation to perform on CSR + output cve2_pkg::csr_op_e csr_op_o, // operation to perform on CSR // LSU output logic data_req_o, // start transaction to data memory @@ -97,7 +92,7 @@ module ibex_decoder #( output logic branch_in_dec_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic illegal_insn; logic illegal_reg_rv32e; @@ -206,7 +201,6 @@ module ibex_decoder #( jump_in_dec_o = 1'b0; jump_set_o = 1'b0; branch_in_dec_o = 1'b0; - icache_inval_o = 1'b0; multdiv_operator_o = MD_OP_MULL; multdiv_signed_mode_o = 2'b00; @@ -244,8 +238,8 @@ module ibex_decoder #( jump_in_dec_o = 1'b1; if (instr_first_cycle_i) begin - // Calculate jump target (and store PC + 4 if BranchTargetALU is configured) - rf_we = BranchTargetALU; + // Calculate jump target (and store PC) + rf_we = 1'b0; jump_set_o = 1'b1; end else begin // Calculate and store PC+4 @@ -257,8 +251,8 @@ module ibex_decoder #( jump_in_dec_o = 1'b1; if (instr_first_cycle_i) begin - // Calculate jump target (and store PC + 4 if BranchTargetALU is configured) - rf_we = BranchTargetALU; + // Calculate jump target (and store PC) + rf_we = 1'b0; jump_set_o = 1'b1; end else begin // Calculate and store PC+4 @@ -572,14 +566,12 @@ module ibex_decoder #( // FENCE.I is implemented as a jump to the next PC, this gives the required flushing // behaviour (iside prefetch buffer flushed and response to any outstanding iside // requests will be ignored). - // If present, the ICache will also be flushed. jump_in_dec_o = 1'b1; rf_we = 1'b0; if (instr_first_cycle_i) begin jump_set_o = 1'b1; - icache_inval_o = 1'b1; end end default: begin @@ -676,10 +668,6 @@ module ibex_decoder #( imm_a_mux_sel_o = IMM_A_ZERO; imm_b_mux_sel_o = IMM_B_I; - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_I; - - opcode_alu = opcode_e'(instr_alu[6:0]); use_rs3_d = 1'b0; @@ -694,13 +682,8 @@ module ibex_decoder #( /////////// OPCODE_JAL: begin // Jump and Link - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_J; - end - // Jumps take two cycles without the BTALU - if (instr_first_cycle_i && !BranchTargetALU) begin + if (instr_first_cycle_i) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; @@ -716,13 +699,8 @@ module ibex_decoder #( end OPCODE_JALR: begin // Jump and Link Register - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_REG_A; - bt_b_mux_sel_o = IMM_B_I; - end - // Jumps take two cycles without the BTALU - if (instr_first_cycle_i && !BranchTargetALU) begin + if (instr_first_cycle_i) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_IMM; @@ -749,24 +727,18 @@ module ibex_decoder #( default: ; endcase - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - // Not-taken branch will jump to next instruction (used in secure mode) - bt_b_mux_sel_o = branch_taken_i ? IMM_B_B : IMM_B_INCR_PC; - end - // Without branch target ALU, a branch is a two-stage operation using the Main ALU in both // stages if (instr_first_cycle_i) begin // First evaluate the branch condition alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_REG_B; - end else if (!BranchTargetALU) begin + end else begin // Then calculate jump target alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; // Not-taken branch will jump to next instruction (used in secure mode) - imm_b_mux_sel_o = branch_taken_i ? IMM_B_B : IMM_B_INCR_PC; + imm_b_mux_sel_o = IMM_B_B; alu_operator_o = ALU_ADD; end end @@ -1147,15 +1119,10 @@ module ibex_decoder #( end 3'b001: begin // FENCE.I will flush the IF stage, prefetch buffer and ICache if present. - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_INCR_PC; - end else begin alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; imm_b_mux_sel_o = IMM_B_INCR_PC; alu_operator_o = ALU_ADD; - end end default: ; endcase diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv similarity index 82% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv index ee900164b..683191a75 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv @@ -8,27 +8,21 @@ * * Execution block: Hosts ALU and MUL/DIV unit */ -module ibex_ex_block #( - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit BranchTargetALU = 0 +module cve2_ex_block #( + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( input logic clk_i, input logic rst_ni, // ALU - input ibex_pkg::alu_op_e alu_operator_i, + input cve2_pkg::alu_op_e alu_operator_i, input logic [31:0] alu_operand_a_i, input logic [31:0] alu_operand_b_i, input logic alu_instr_first_cycle_i, - // Branch Target ALU - // All of these signals are unusued when BranchTargetALU == 0 - input logic [31:0] bt_a_operand_i, - input logic [31:0] bt_b_operand_i, - // Multiplier/Divider - input ibex_pkg::md_op_e multdiv_operator_i, + input cve2_pkg::md_op_e multdiv_operator_i, input logic mult_en_i, // dynamic enable signal, for FSM control input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes @@ -37,7 +31,6 @@ module ibex_ex_block #( input logic [31:0] multdiv_operand_a_i, input logic [31:0] multdiv_operand_b_i, input logic multdiv_ready_id_i, - input logic data_ind_timing_i, // intermediate val reg output logic [1:0] imd_val_we_o, @@ -53,7 +46,7 @@ module ibex_ex_block #( output logic ex_valid_o // EX has valid output ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] alu_result, multdiv_result; @@ -91,29 +84,16 @@ module ibex_ex_block #( // branch handling assign branch_decision_o = alu_cmp_result; - if (BranchTargetALU) begin : g_branch_target_alu - logic [32:0] bt_alu_result; - logic unused_bt_carry; - - assign bt_alu_result = bt_a_operand_i + bt_b_operand_i; - - assign unused_bt_carry = bt_alu_result[32]; - assign branch_target_o = bt_alu_result[31:0]; - end else begin : g_no_branch_target_alu - // Unused bt_operand signals cause lint errors, this avoids them - logic [31:0] unused_bt_a_operand, unused_bt_b_operand; + // Unused bt_operand signals cause lint errors, this avoids them + //logic [31:0] unused_bt_a_operand, unused_bt_b_operand; - assign unused_bt_a_operand = bt_a_operand_i; - assign unused_bt_b_operand = bt_b_operand_i; - - assign branch_target_o = alu_adder_result_ex_o; - end + assign branch_target_o = alu_adder_result_ex_o; ///////// // ALU // ///////// - ibex_alu #( + cve2_alu #( .RV32B(RV32B) ) alu_i ( .operator_i (alu_operator_i), @@ -138,7 +118,7 @@ module ibex_ex_block #( //////////////// if (RV32M == RV32MSlow) begin : gen_multdiv_slow - ibex_multdiv_slow multdiv_i ( + cve2_multdiv_slow multdiv_i ( .clk_i (clk_i), .rst_ni (rst_ni), .mult_en_i (mult_en_i), @@ -152,7 +132,6 @@ module ibex_ex_block #( .alu_adder_ext_i (alu_adder_result_ext), .alu_adder_i (alu_adder_result_ex_o), .equal_to_zero_i (alu_is_equal_result), - .data_ind_timing_i (data_ind_timing_i), .valid_o (multdiv_valid), .alu_operand_a_o (multdiv_alu_operand_a), .alu_operand_b_o (multdiv_alu_operand_b), @@ -163,7 +142,7 @@ module ibex_ex_block #( .multdiv_result_o (multdiv_result) ); end else if (RV32M == RV32MFast || RV32M == RV32MSingleCycle) begin : gen_multdiv_fast - ibex_multdiv_fast #( + cve2_multdiv_fast #( .RV32M(RV32M) ) multdiv_i ( .clk_i (clk_i), @@ -181,7 +160,6 @@ module ibex_ex_block #( .alu_adder_ext_i (alu_adder_result_ext), .alu_adder_i (alu_adder_result_ex_o), .equal_to_zero_i (alu_is_equal_result), - .data_ind_timing_i (data_ind_timing_i), .imd_val_q_i (imd_val_q_i), .imd_val_d_o (multdiv_imd_val_d), .imd_val_we_o (multdiv_imd_val_we), diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv similarity index 92% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv index 61179ed08..20b2b62b3 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv @@ -12,9 +12,8 @@ `include "prim_assert.sv" -module ibex_fetch_fifo #( - parameter int unsigned NUM_REQS = 2, - parameter bit ResetAll = 1'b0 +module cve2_fetch_fifo #( + parameter int unsigned NUM_REQS = 2 ) ( input logic clk_i, input logic rst_ni, @@ -149,19 +148,11 @@ module ibex_fetch_fifo #( assign instr_addr_d = clear_i ? in_addr_i[31:1] : instr_addr_next; - if (ResetAll) begin : g_instr_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_addr_q <= '0; - end else if (instr_addr_en) begin - instr_addr_q <= instr_addr_d; - end - end - end else begin : g_instr_addr_nr - always_ff @(posedge clk_i) begin - if (instr_addr_en) begin - instr_addr_q <= instr_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_addr_q <= '0; + end else if (instr_addr_en) begin + instr_addr_q <= instr_addr_d; end end @@ -234,7 +225,7 @@ module ibex_fetch_fifo #( end for (genvar i = 0; i < DEPTH; i++) begin : g_fifo_regs - if (ResetAll) begin : g_rdata_ra + begin : g_rdata always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rdata_q[i] <= '0; @@ -244,13 +235,6 @@ module ibex_fetch_fifo #( err_q[i] <= err_d[i]; end end - end else begin : g_rdata_nr - always_ff @(posedge clk_i) begin - if (entry_en[i]) begin - rdata_q[i] <= rdata_d[i]; - err_q[i] <= err_d[i]; - end - end end end diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv similarity index 83% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv index 1644d0722..caf1a58fd 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv @@ -15,14 +15,12 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_id_stage #( +module cve2_id_stage #( parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit DataIndTiming = 1'b0, - parameter bit BranchTargetALU = 0, + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone, parameter bit WritebackStage = 0, parameter bit BranchPredictor = 0 ) ( @@ -43,18 +41,17 @@ module ibex_id_stage #( output logic instr_first_cycle_id_o, output logic instr_valid_clear_o, // kill instr in IF-ID reg output logic id_in_ready_o, // ID stage is ready for next instr - output logic icache_inval_o, // Jumps and branches input logic branch_decision_i, // IF and ID stage signals output logic pc_set_o, - output ibex_pkg::pc_sel_e pc_mux_o, + output cve2_pkg::pc_sel_e pc_mux_o, output logic nt_branch_mispredict_o, output logic [31:0] nt_branch_addr_o, - output ibex_pkg::exc_pc_sel_e exc_pc_mux_o, - output ibex_pkg::exc_cause_e exc_cause_o, + output cve2_pkg::exc_pc_sel_e exc_pc_mux_o, + output cve2_pkg::exc_cause_e exc_cause_o, input logic illegal_c_insn_i, input logic instr_fetch_err_i, @@ -66,7 +63,7 @@ module ibex_id_stage #( input logic ex_valid_i, // EX stage has valid output input logic lsu_resp_valid_i, // LSU has valid output, or is done // ALU - output ibex_pkg::alu_op_e alu_operator_ex_o, + output cve2_pkg::alu_op_e alu_operator_ex_o, output logic [31:0] alu_operand_a_ex_o, output logic [31:0] alu_operand_b_ex_o, @@ -75,16 +72,12 @@ module ibex_id_stage #( input logic [33:0] imd_val_d_ex_i[2], output logic [33:0] imd_val_q_ex_o[2], - // Branch target ALU - output logic [31:0] bt_a_operand_o, - output logic [31:0] bt_b_operand_o, - // MUL, DIV output logic mult_en_ex_o, output logic div_en_ex_o, output logic mult_sel_ex_o, output logic div_sel_ex_o, - output ibex_pkg::md_op_e multdiv_operator_ex_o, + output cve2_pkg::md_op_e multdiv_operator_ex_o, output logic [1:0] multdiv_signed_mode_ex_o, output logic [31:0] multdiv_operand_a_ex_o, output logic [31:0] multdiv_operand_b_ex_o, @@ -92,7 +85,7 @@ module ibex_id_stage #( // CSR output logic csr_access_o, - output ibex_pkg::csr_op_e csr_op_o, + output cve2_pkg::csr_op_e csr_op_o, output logic csr_op_en_o, output logic csr_save_if_o, output logic csr_save_id_o, @@ -101,10 +94,9 @@ module ibex_id_stage #( output logic csr_restore_dret_id_o, output logic csr_save_cause_o, output logic [31:0] csr_mtval_o, - input ibex_pkg::priv_lvl_e priv_mode_i, + input cve2_pkg::priv_lvl_e priv_mode_i, input logic csr_mstatus_tw_i, input logic illegal_csr_insn_i, - input logic data_ind_timing_i, // Interface to load store unit output logic lsu_req_o, @@ -124,7 +116,7 @@ module ibex_id_stage #( // Interrupt signals input logic csr_mstatus_mie_i, input logic irq_pending_i, - input ibex_pkg::irqs_t irqs_i, + input cve2_pkg::irqs_t irqs_i, input logic irq_nm_i, output logic nmi_mode_o, @@ -133,7 +125,7 @@ module ibex_id_stage #( // Debug Signal output logic debug_mode_o, - output ibex_pkg::dbg_cause_e debug_cause_o, + output cve2_pkg::dbg_cause_e debug_cause_o, output logic debug_csr_save_o, input logic debug_req_i, input logic debug_single_step_i, @@ -141,9 +133,6 @@ module ibex_id_stage #( input logic debug_ebreaku_i, input logic trigger_match_i, - // Wakeup Signal - output logic wake_from_sleep_o, - // Write back signal input logic [31:0] result_ex_i, input logic [31:0] csr_rdata_i, @@ -169,7 +158,7 @@ module ibex_id_stage #( input logic rf_write_wb_i, output logic en_wb_o, - output ibex_pkg::wb_instr_type_e instr_type_wb_o, + output cve2_pkg::wb_instr_type_e instr_type_wb_o, output logic instr_perf_count_id_o, input logic ready_wb_i, input logic outstanding_load_wb_i, @@ -181,12 +170,12 @@ module ibex_id_stage #( output logic perf_tbranch_o, // executing a taken branch instr output logic perf_dside_wait_o, // instruction in ID/EX is awaiting memory // access to finish before proceeding - output logic perf_mul_wait_o, + output logic perf_wfi_wait_o, output logic perf_div_wait_o, output logic instr_id_done_o ); - import ibex_pkg::*; + import cve2_pkg::*; // Decoder/Controller, ID stage internal signals logic illegal_insn_dec; @@ -203,7 +192,6 @@ module ibex_id_stage #( logic branch_set, branch_set_raw, branch_set_raw_d; logic branch_jump_set_done_q, branch_jump_set_done_d; logic branch_not_set; - logic branch_taken; logic jump_in_dec; logic jump_set_dec; logic jump_set, jump_set_raw; @@ -260,9 +248,6 @@ module ibex_id_stage #( logic [33:0] imd_val_q[2]; - op_a_sel_e bt_a_mux_sel; - imm_b_sel_e bt_b_mux_sel; - imm_a_sel_e imm_a_mux_sel; imm_b_sel_e imm_b_mux_sel, imm_b_mux_sel_dec; @@ -313,75 +298,30 @@ module ibex_id_stage #( endcase end - if (BranchTargetALU) begin : g_btalu_muxes - // Branch target ALU operand A mux - always_comb begin : bt_operand_a_mux - unique case (bt_a_mux_sel) - OP_A_REG_A: bt_a_operand_o = rf_rdata_a_fwd; - OP_A_CURRPC: bt_a_operand_o = pc_id_i; - default: bt_a_operand_o = pc_id_i; - endcase - end - - // Branch target ALU operand B mux - always_comb begin : bt_immediate_b_mux - unique case (bt_b_mux_sel) - IMM_B_I: bt_b_operand_o = imm_i_type; - IMM_B_B: bt_b_operand_o = imm_b_type; - IMM_B_J: bt_b_operand_o = imm_j_type; - IMM_B_INCR_PC: bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4; - default: bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4; - endcase - end - - // Reduced main ALU immediate MUX for Operand B - always_comb begin : immediate_b_mux - unique case (imm_b_mux_sel) - IMM_B_I: imm_b = imm_i_type; - IMM_B_S: imm_b = imm_s_type; - IMM_B_U: imm_b = imm_u_type; - IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; - IMM_B_INCR_ADDR: imm_b = 32'h4; - default: imm_b = 32'h4; - endcase - end - `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { - IMM_B_I, - IMM_B_S, - IMM_B_U, - IMM_B_INCR_PC, - IMM_B_INCR_ADDR}) - end else begin : g_nobtalu - op_a_sel_e unused_a_mux_sel; - imm_b_sel_e unused_b_mux_sel; - - assign unused_a_mux_sel = bt_a_mux_sel; - assign unused_b_mux_sel = bt_b_mux_sel; - assign bt_a_operand_o = '0; - assign bt_b_operand_o = '0; - - // Full main ALU immediate MUX for Operand B - always_comb begin : immediate_b_mux - unique case (imm_b_mux_sel) - IMM_B_I: imm_b = imm_i_type; - IMM_B_S: imm_b = imm_s_type; - IMM_B_B: imm_b = imm_b_type; - IMM_B_U: imm_b = imm_u_type; - IMM_B_J: imm_b = imm_j_type; - IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; - IMM_B_INCR_ADDR: imm_b = 32'h4; - default: imm_b = 32'h4; - endcase - end - `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { - IMM_B_I, - IMM_B_S, - IMM_B_B, - IMM_B_U, - IMM_B_J, - IMM_B_INCR_PC, - IMM_B_INCR_ADDR}) + op_a_sel_e unused_a_mux_sel; + imm_b_sel_e unused_b_mux_sel; + + // Full main ALU immediate MUX for Operand B + always_comb begin : immediate_b_mux + unique case (imm_b_mux_sel) + IMM_B_I: imm_b = imm_i_type; + IMM_B_S: imm_b = imm_s_type; + IMM_B_B: imm_b = imm_b_type; + IMM_B_U: imm_b = imm_u_type; + IMM_B_J: imm_b = imm_j_type; + IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; + IMM_B_INCR_ADDR: imm_b = 32'h4; + default: imm_b = 32'h4; + endcase end + `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { + IMM_B_I, + IMM_B_S, + IMM_B_B, + IMM_B_U, + IMM_B_J, + IMM_B_INCR_PC, + IMM_B_INCR_ADDR}) // ALU MUX for Operand B assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : rf_rdata_b_fwd; @@ -422,11 +362,10 @@ module ibex_id_stage #( // Decoder // ///////////// - ibex_decoder #( + cve2_decoder #( .RV32E (RV32E), .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU) + .RV32B (RV32B) ) decoder_i ( .clk_i (clk_i), .rst_ni(rst_ni), @@ -439,8 +378,6 @@ module ibex_id_stage #( .ecall_insn_o (ecall_insn_dec), .wfi_insn_o (wfi_insn_dec), .jump_set_o (jump_set_dec), - .branch_taken_i(branch_taken), - .icache_inval_o(icache_inval_o), // from IF-ID pipeline register .instr_first_cycle_i(instr_first_cycle), @@ -451,8 +388,6 @@ module ibex_id_stage #( // immediates .imm_a_mux_sel_o(imm_a_mux_sel), .imm_b_mux_sel_o(imm_b_mux_sel_dec), - .bt_a_mux_sel_o (bt_a_mux_sel), - .bt_b_mux_sel_o (bt_b_mux_sel), .imm_i_type_o (imm_i_type), .imm_s_type_o (imm_s_type), @@ -501,7 +436,7 @@ module ibex_id_stage #( ); ///////////////////////////////// - // CSR-related pipline flushes // + // CSR-related pipeline flushes // ///////////////////////////////// always_comb begin : csr_pipeline_flushes csr_pipe_flush = 1'b0; @@ -510,10 +445,15 @@ module ibex_id_stage #( // - When enabling interrupts, pending IRQs become visible to the controller only during // the next cycle. If during that cycle the core disables interrupts again, it does not // see any pending IRQs and consequently does not start to handle interrupts. + // - When modifying any PMP CSR, PMP check of the next instruction might get invalidated. + // Hence, a pipeline flush is needed to instantiate another PMP check with the updated CSRs. // - When modifying debug CSRs - TODO: Check if this is really needed if (csr_op_en_o == 1'b1 && (csr_op_o == CSR_OP_WRITE || csr_op_o == CSR_OP_SET)) begin - if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS || - csr_num_e'(instr_rdata_i[31:20]) == CSR_MIE) begin + if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS || + csr_num_e'(instr_rdata_i[31:20]) == CSR_MIE || + csr_num_e'(instr_rdata_i[31:20]) == CSR_MSECCFG || + // To catch all PMPCFG/PMPADDR registers, get the shared top most 7 bits. + instr_rdata_i[31:25] == 7'h1D) begin csr_pipe_flush = 1'b1; end end else if (csr_op_en_o == 1'b1 && csr_op_o != CSR_OP_READ) begin @@ -532,7 +472,7 @@ module ibex_id_stage #( assign illegal_insn_o = instr_valid_i & (illegal_insn_dec | illegal_csr_insn_i); - ibex_controller #( + cve2_controller #( .WritebackStage (WritebackStage), .BranchPredictor(BranchPredictor) ) controller_i ( @@ -613,9 +553,6 @@ module ibex_id_stage #( .debug_ebreaku_i (debug_ebreaku_i), .trigger_match_i (trigger_match_i), - // Wakeup Signal - .wake_from_sleep_o(wake_from_sleep_o), - .stall_id_i(stall_id), .stall_wb_i(stall_wb), .flush_id_o(flush_id), @@ -659,31 +596,24 @@ module ibex_id_stage #( // Branch set control // //////////////////////// - if (BranchTargetALU && !DataIndTiming) begin : g_branch_set_direct - // Branch set fed straight to controller with branch target ALU - // (condition pass/fail used same cycle as generated instruction request) - assign branch_set_raw = branch_set_raw_d; - end else begin : g_branch_set_flop - // SEC_CM: CORE.DATA_REG_SW.SCA - // Branch set flopped without branch target ALU, or in fixed time execution mode - // (condition pass/fail used next cycle where branch target is calculated) - logic branch_set_raw_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - branch_set_raw_q <= 1'b0; - end else begin - branch_set_raw_q <= branch_set_raw_d; - end + // SEC_CM: CORE.DATA_REG_SW.SCA + // Branch set flopped without branch target ALU, or in fixed time execution mode + // (condition pass/fail used next cycle where branch target is calculated) + logic branch_set_raw_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + branch_set_raw_q <= 1'b0; + end else begin + branch_set_raw_q <= branch_set_raw_d; end + end - // Branches always take two cycles in fixed time execution mode, with or without the branch - // target ALU (to avoid a path from the branch decision into the branch target ALU operand - // muxing). - assign branch_set_raw = (BranchTargetALU && !data_ind_timing_i) ? branch_set_raw_d : - branch_set_raw_q; + // Branches always take two cycles in fixed time execution mode, with or without the branch + // target ALU (to avoid a path from the branch decision into the branch target ALU operand + // muxing). + assign branch_set_raw = branch_set_raw_q; - end // Track whether the current instruction in ID/EX has done a branch or jump set. assign branch_jump_set_done_d = (branch_set_raw | jump_set_raw | branch_jump_set_done_q) & @@ -707,30 +637,6 @@ module ibex_id_stage #( assign jump_set = jump_set_raw & ~branch_jump_set_done_q; assign branch_set = branch_set_raw & ~branch_jump_set_done_q; - // Branch condition is calculated in the first cycle and flopped for use in the second cycle - // (only used in fixed time execution mode to determine branch destination). - if (DataIndTiming) begin : g_sec_branch_taken - // SEC_CM: CORE.DATA_REG_SW.SCA - logic branch_taken_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - branch_taken_q <= 1'b0; - end else begin - branch_taken_q <= branch_decision_i; - end - end - - assign branch_taken = ~data_ind_timing_i | branch_taken_q; - - end else begin : g_nosec_branch_taken - - // Signal unused without fixed time execution mode - only taken branches will trigger - // branch_set_raw - assign branch_taken = 1'b1; - - end - // Holding branch_set/jump_set high for more than one cycle should not cause a functional issue. // However it could generate needless prefetch buffer flushes and instruction fetches. The ID/EX // designs ensures that this never happens for non-predicted branches. @@ -808,22 +714,21 @@ module ibex_id_stage #( // All branches take two cycles in fixed time execution mode, regardless of branch // condition. // SEC_CM: CORE.DATA_REG_SW.SCA - id_fsm_d = (data_ind_timing_i || (!BranchTargetALU && branch_decision_i)) ? + id_fsm_d = (branch_decision_i) ? MULTI_CYCLE : FIRST_CYCLE; - stall_branch = (~BranchTargetALU & branch_decision_i) | data_ind_timing_i; - branch_set_raw_d = (branch_decision_i | data_ind_timing_i); + stall_branch = branch_decision_i; + branch_set_raw_d = branch_decision_i; if (BranchPredictor) begin - branch_not_set = ~branch_decision_i; + branch_not_set = 1'b1; end perf_branch_o = 1'b1; end jump_in_dec: begin // uncond branch operation - // BTALU means jumps only need one cycle - id_fsm_d = BranchTargetALU ? FIRST_CYCLE : MULTI_CYCLE; - stall_jump = ~BranchTargetALU; + id_fsm_d = MULTI_CYCLE; + stall_jump = 1'b1; jump_set_raw = jump_set_dec; end alu_multicycle_dec: begin @@ -1061,19 +966,17 @@ module ibex_id_stage #( // stage) assign en_wb_o = instr_done; - assign perf_mul_wait_o = stall_multdiv & mult_en_dec; + assign perf_wfi_wait_o = wfi_insn_dec; assign perf_div_wait_o = stall_multdiv & div_en_dec; ////////// // FCOV // ////////// - //`DV_FCOV_SIGNAL_GEN_IF(logic, rf_rd_wb_hz, - // (gen_stall_mem.rf_rd_a_hz | gen_stall_mem.rf_rd_b_hz) & instr_valid_i, WritebackStage) - //`DV_FCOV_SIGNAL(logic, branch_taken, - // instr_executing & (id_fsm_q == FIRST_CYCLE) & branch_decision_i) - //`DV_FCOV_SIGNAL(logic, branch_not_taken, - // instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i) + `DV_FCOV_SIGNAL_GEN_IF(logic, rf_rd_wb_hz, + (gen_stall_mem.rf_rd_a_hz | gen_stall_mem.rf_rd_b_hz) & instr_valid_i, WritebackStage) + `DV_FCOV_SIGNAL(logic, branch_not_taken, + instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i) //////////////// // Assertions // @@ -1086,16 +989,6 @@ module ibex_id_stage #( OP_A_FWD, OP_A_CURRPC, OP_A_IMM}) - `ASSERT_KNOWN_IF(IbexBTAluAOpMuxSelKnown, bt_a_mux_sel, instr_valid_i) - `ASSERT(IbexBTAluAOpMuxSelValid, instr_valid_i |-> bt_a_mux_sel inside { - OP_A_REG_A, - OP_A_CURRPC}) - `ASSERT_KNOWN_IF(IbexBTAluBOpMuxSelKnown, bt_b_mux_sel, instr_valid_i) - `ASSERT(IbexBTAluBOpMuxSelValid, instr_valid_i |-> bt_b_mux_sel inside { - IMM_B_I, - IMM_B_B, - IMM_B_J, - IMM_B_INCR_PC}) `ASSERT(IbexRegfileWdataSelValid, instr_valid_i |-> rf_wdata_sel inside { RF_WD_EX, RF_WD_CSR}) diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv similarity index 56% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv index c430b669e..a74f97b49 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv @@ -12,19 +12,9 @@ `include "prim_assert.sv" -module ibex_if_stage import ibex_pkg::*; #( +module cve2_if_stage import cve2_pkg::*; #( parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808, - parameter bit DummyInstructions = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - parameter bit PCIncrCheck = 1'b0, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, parameter bit BranchPredictor = 1'b0 ) ( input logic clk_i, @@ -41,19 +31,6 @@ module ibex_if_stage import ibex_pkg::*; #( input logic [31:0] instr_rdata_i, input logic instr_err_i, - // ICache RAM IO - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - // output of ID stage output logic instr_valid_id_o, // instr in IF-ID is valid output logic instr_new_id_o, // instr in IF-ID is new @@ -71,7 +48,6 @@ module ibex_if_stage import ibex_pkg::*; #( output logic instr_fetch_err_plus2_o, // bus error misaligned output logic illegal_c_insn_id_o, // compressed decoder thinks this // is an invalid instr - output logic dummy_instr_id_o, // Instruction is a dummy output logic [31:0] pc_if_o, output logic [31:0] pc_id_o, input logic pmp_err_if_i, @@ -87,14 +63,6 @@ module ibex_if_stage import ibex_pkg::*; #( input exc_pc_sel_e exc_pc_mux_i, // selects ISR address input exc_cause_e exc_cause, // selects ISR address for // vectorized interrupt lines - input logic dummy_instr_en_i, - input logic [2:0] dummy_instr_mask_i, - input logic dummy_instr_seed_en_i, - input logic [31:0] dummy_instr_seed_i, - input logic icache_enable_i, - input logic icache_inval_i, - output logic icache_ecc_error_o, - // jump and branch target input logic [31:0] branch_target_ex_i, // branch/jump target address @@ -110,7 +78,6 @@ module ibex_if_stage import ibex_pkg::*; #( 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 ); @@ -149,17 +116,10 @@ module ibex_if_stage import ibex_pkg::*; #( logic if_id_pipe_reg_we; // IF-ID pipeline reg write enable - // Dummy instruction signals - logic stall_dummy_instr; - logic [31:0] instr_out; - logic instr_is_compressed_out; - logic illegal_c_instr_out; - logic instr_err_out; - logic predict_branch_taken; logic [31:0] predict_branch_pc; - ibex_pkg::pc_sel_e pc_mux_internal; + cve2_pkg::pc_sel_e pc_mux_internal; logic [7:0] unused_boot_addr; logic [7:0] unused_csr_mtvec; @@ -205,122 +165,35 @@ module ibex_if_stage import ibex_pkg::*; #( // tell CS register file to initialize mtvec on boot assign csr_mtvec_init_o = (pc_mux_i == PC_BOOT) & pc_set_i; - if (ICache) begin : gen_icache - // Full I-Cache option - ibex_icache #( - .ICacheECC (ICacheECC), - .ResetAll (ResetAll), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC) - ) icache_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .req_i ( req_i ), - - .branch_i ( branch_req ), - .branch_mispredict_i ( nt_branch_mispredict_i ), - .mispredict_addr_i ( nt_branch_addr_i ), - .addr_i ( {fetch_addr_n[31:1], 1'b0} ), - - .ready_i ( fetch_ready ), - .valid_o ( fetch_valid ), - .rdata_o ( fetch_rdata ), - .addr_o ( fetch_addr ), - .err_o ( fetch_err ), - .err_plus2_o ( fetch_err_plus2 ), - - .instr_req_o ( instr_req_o ), - .instr_addr_o ( instr_addr_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_rvalid_i ( instr_rvalid_i ), - .instr_rdata_i ( instr_rdata_i ), - .instr_err_i ( instr_err_i ), - - .ic_tag_req_o ( ic_tag_req_o ), - .ic_tag_write_o ( ic_tag_write_o ), - .ic_tag_addr_o ( ic_tag_addr_o ), - .ic_tag_wdata_o ( ic_tag_wdata_o ), - .ic_tag_rdata_i ( ic_tag_rdata_i ), - .ic_data_req_o ( ic_data_req_o ), - .ic_data_write_o ( ic_data_write_o ), - .ic_data_addr_o ( ic_data_addr_o ), - .ic_data_wdata_o ( ic_data_wdata_o ), - .ic_data_rdata_i ( ic_data_rdata_i ), - .ic_scr_key_valid_i ( ic_scr_key_valid_i ), - - .icache_enable_i ( icache_enable_i ), - .icache_inval_i ( icache_inval_i ), - .busy_o ( prefetch_busy ), - .ecc_error_o ( icache_ecc_error_o ) - ); - end else begin : gen_prefetch_buffer - // prefetch buffer, caches a fixed number of instructions - ibex_prefetch_buffer #( - .ResetAll (ResetAll) - ) prefetch_buffer_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .req_i ( req_i ), - - .branch_i ( branch_req ), - .branch_mispredict_i ( nt_branch_mispredict_i ), - .mispredict_addr_i ( nt_branch_addr_i ), - .addr_i ( {fetch_addr_n[31:1], 1'b0} ), - - .ready_i ( fetch_ready ), - .valid_o ( fetch_valid ), - .rdata_o ( fetch_rdata ), - .addr_o ( fetch_addr ), - .err_o ( fetch_err ), - .err_plus2_o ( fetch_err_plus2 ), - - .instr_req_o ( instr_req_o ), - .instr_addr_o ( instr_addr_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_rvalid_i ( instr_rvalid_i ), - .instr_rdata_i ( instr_rdata_i ), - .instr_err_i ( instr_err_i ), - - .busy_o ( prefetch_busy ) - ); - // ICache tieoffs - logic unused_icen, unused_icinv, unused_scr_key_valid; - logic [TagSizeECC-1:0] unused_tag_ram_input [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] unused_data_ram_input [IC_NUM_WAYS]; - assign unused_icen = icache_enable_i; - assign unused_icinv = icache_inval_i; - assign unused_tag_ram_input = ic_tag_rdata_i; - assign unused_data_ram_input = ic_data_rdata_i; - assign unused_scr_key_valid = ic_scr_key_valid_i; - assign ic_tag_req_o = 'b0; - assign ic_tag_write_o = 'b0; - assign ic_tag_addr_o = 'b0; - assign ic_tag_wdata_o = 'b0; - assign ic_data_req_o = 'b0; - assign ic_data_write_o = 'b0; - assign ic_data_addr_o = 'b0; - assign ic_data_wdata_o = 'b0; - assign icache_ecc_error_o = 'b0; - -`ifndef SYNTHESIS - // If we don't instantiate an icache and this is a simulation then we have a problem because the - // simulator might discard the icache module entirely, including some DPI exports that it - // implies. This then causes problems for linking against C++ testbench code that expected them. - // As a slightly ugly hack, let's define the DPI functions here (the real versions are defined - // in prim_util_get_scramble_params.svh) - export "DPI-C" function simutil_get_scramble_key; - export "DPI-C" function simutil_get_scramble_nonce; - function automatic int simutil_get_scramble_key(output bit [127:0] val); - return 0; - endfunction - function automatic int simutil_get_scramble_nonce(output bit [319:0] nonce); - return 0; - endfunction -`endif - end + // prefetch buffer, caches a fixed number of instructions + cve2_prefetch_buffer #( + ) prefetch_buffer_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .req_i ( req_i ), + + .branch_i ( branch_req ), + .branch_mispredict_i ( nt_branch_mispredict_i ), + .mispredict_addr_i ( nt_branch_addr_i ), + .addr_i ( {fetch_addr_n[31:1], 1'b0} ), + + .ready_i ( fetch_ready ), + .valid_o ( fetch_valid ), + .rdata_o ( fetch_rdata ), + .addr_o ( fetch_addr ), + .err_o ( fetch_err ), + .err_plus2_o ( fetch_err_plus2 ), + + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), + .instr_err_i ( instr_err_i ), + + .busy_o ( prefetch_busy ) + ); assign unused_fetch_addr_n0 = fetch_addr_n[0]; @@ -347,7 +220,7 @@ module ibex_if_stage import ibex_pkg::*; #( // // since it does not matter where we decompress instructions, we do it here // to ease timing closure - ibex_compressed_decoder compressed_decoder_i ( + cve2_compressed_decoder compressed_decoder_i ( .clk_i (clk_i), .rst_ni (rst_ni), .valid_i (fetch_valid & ~fetch_err), @@ -357,66 +230,6 @@ module ibex_if_stage import ibex_pkg::*; #( .illegal_instr_o(illegal_c_insn) ); - // Dummy instruction insertion - if (DummyInstructions) begin : gen_dummy_instr - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - logic insert_dummy_instr; - logic [31:0] dummy_instr_data; - - ibex_dummy_instr #( - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm) - ) dummy_instr_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .dummy_instr_en_i (dummy_instr_en_i), - .dummy_instr_mask_i (dummy_instr_mask_i), - .dummy_instr_seed_en_i(dummy_instr_seed_en_i), - .dummy_instr_seed_i (dummy_instr_seed_i), - .fetch_valid_i (fetch_valid), - .id_in_ready_i (id_in_ready_i), - .insert_dummy_instr_o (insert_dummy_instr), - .dummy_instr_data_o (dummy_instr_data) - ); - - // Mux between actual instructions and dummy instructions - assign instr_out = insert_dummy_instr ? dummy_instr_data : instr_decompressed; - assign instr_is_compressed_out = insert_dummy_instr ? 1'b0 : instr_is_compressed; - assign illegal_c_instr_out = insert_dummy_instr ? 1'b0 : illegal_c_insn; - assign instr_err_out = insert_dummy_instr ? 1'b0 : if_instr_err; - - // Stall the IF stage if we insert a dummy instruction. The dummy will execute between whatever - // is currently in the ID stage and whatever is valid from the prefetch buffer this cycle. The - // PC of the dummy instruction will match whatever is next from the prefetch buffer. - assign stall_dummy_instr = insert_dummy_instr; - - // Register the dummy instruction indication into the ID stage - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_instr_id_o <= 1'b0; - end else if (if_id_pipe_reg_we) begin - dummy_instr_id_o <= insert_dummy_instr; - end - end - - end else begin : gen_no_dummy_instr - logic unused_dummy_en; - logic [2:0] unused_dummy_mask; - logic unused_dummy_seed_en; - logic [31:0] unused_dummy_seed; - - assign unused_dummy_en = dummy_instr_en_i; - assign unused_dummy_mask = dummy_instr_mask_i; - assign unused_dummy_seed_en = dummy_instr_seed_en_i; - assign unused_dummy_seed = dummy_instr_seed_i; - assign instr_out = instr_decompressed; - assign instr_is_compressed_out = instr_is_compressed; - assign illegal_c_instr_out = illegal_c_insn; - assign instr_err_out = if_instr_err; - assign stall_dummy_instr = 1'b0; - assign dummy_instr_id_o = 1'b0; - end - // The ID stage becomes valid as soon as any instruction is registered in the ID stage flops. // Note that the current instruction is squashed by the incoming pc_set_i signal. // Valid is held until it is explicitly cleared (due to an instruction completing or an exception) @@ -441,77 +254,27 @@ module ibex_if_stage import ibex_pkg::*; #( // IF-ID pipeline registers, frozen when the ID stage is stalled assign if_id_pipe_reg_we = instr_new_id_d; - if (ResetAll) begin : g_instr_rdata_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_rdata_id_o <= '0; - instr_rdata_alu_id_o <= '0; - instr_fetch_err_o <= '0; - instr_fetch_err_plus2_o <= '0; - instr_rdata_c_id_o <= '0; - instr_is_compressed_id_o <= '0; - illegal_c_insn_id_o <= '0; - pc_id_o <= '0; - end else if (if_id_pipe_reg_we) begin - instr_rdata_id_o <= instr_out; - // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. - instr_rdata_alu_id_o <= instr_out; - instr_fetch_err_o <= instr_err_out; - instr_fetch_err_plus2_o <= if_instr_err_plus2; - instr_rdata_c_id_o <= if_instr_rdata[15:0]; - instr_is_compressed_id_o <= instr_is_compressed_out; - illegal_c_insn_id_o <= illegal_c_instr_out; - pc_id_o <= pc_if_o; - end - end - end else begin : g_instr_rdata_nr - always_ff @(posedge clk_i) begin - if (if_id_pipe_reg_we) begin - instr_rdata_id_o <= instr_out; - // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. - instr_rdata_alu_id_o <= instr_out; - instr_fetch_err_o <= instr_err_out; - instr_fetch_err_plus2_o <= if_instr_err_plus2; - instr_rdata_c_id_o <= if_instr_rdata[15:0]; - instr_is_compressed_id_o <= instr_is_compressed_out; - illegal_c_insn_id_o <= illegal_c_instr_out; - pc_id_o <= pc_if_o; - end - end - end - - // Check for expected increments of the PC when security hardening enabled - if (PCIncrCheck) begin : g_secure_pc - // SEC_CM: PC.CTRL_FLOW.CONSISTENCY - logic [31:0] prev_instr_addr_incr, prev_instr_addr_incr_buf; - 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 or for dummys. - assign prev_instr_seq_d = (prev_instr_seq_q | instr_new_id_d) & - ~branch_req & ~if_instr_err & ~stall_dummy_instr; - - 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 + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_rdata_id_o <= '0; + instr_rdata_alu_id_o <= '0; + instr_fetch_err_o <= '0; + instr_fetch_err_plus2_o <= '0; + instr_rdata_c_id_o <= '0; + instr_is_compressed_id_o <= '0; + illegal_c_insn_id_o <= '0; + pc_id_o <= '0; + end else if (if_id_pipe_reg_we) begin + instr_rdata_id_o <= instr_decompressed; + // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. + instr_rdata_alu_id_o <= instr_decompressed; + instr_fetch_err_o <= if_instr_err; + instr_fetch_err_plus2_o <= if_instr_err_plus2; + instr_rdata_c_id_o <= if_instr_rdata[15:0]; + instr_is_compressed_id_o <= instr_is_compressed; + illegal_c_insn_id_o <= illegal_c_insn; + pc_id_o <= pc_if_o; end - - assign prev_instr_addr_incr = pc_id_o + (instr_is_compressed_id_o ? 32'd2 : 32'd4); - - // Buffer anticipated next PC address to ensure optimiser cannot remove the check. - prim_buf #(.Width(32)) u_prev_instr_addr_incr_buf ( - .in_i (prev_instr_addr_incr), - .out_o(prev_instr_addr_incr_buf) - ); - - // 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_buf); - - end else begin : g_no_secure_pc - assign pc_mismatch_alert_o = 1'b0; end if (BranchPredictor) begin : g_branch_predictor @@ -525,7 +288,7 @@ module ibex_if_stage import ibex_pkg::*; #( logic predict_branch_taken_raw; // ID stages needs to know if branch was predicted taken so it can signal mispredicts - if (ResetAll) begin : g_bp_taken_ra + begin : g_bp_taken always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin instr_bp_taken_q <= '0; @@ -533,12 +296,6 @@ module ibex_if_stage import ibex_pkg::*; #( instr_bp_taken_q <= instr_bp_taken_d; end end - end else begin : g_bp_taken_nr - always_ff @(posedge clk_i) begin - if (if_id_pipe_reg_we) begin - instr_bp_taken_q <= instr_bp_taken_d; - end - end end // When branch prediction is enabled a skid buffer between the IF and ID/EX stage is introduced. @@ -551,7 +308,7 @@ module ibex_if_stage import ibex_pkg::*; #( assign instr_skid_en = predict_branch_taken & ~pc_set_i & ~id_in_ready_i & ~instr_skid_valid_q; - assign instr_skid_valid_d = (instr_skid_valid_q & ~id_in_ready_i & ~stall_dummy_instr) | + assign instr_skid_valid_d = (instr_skid_valid_q & ~id_in_ready_i) | instr_skid_en; always_ff @(posedge clk_i or negedge rst_ni) begin @@ -562,29 +319,19 @@ module ibex_if_stage import ibex_pkg::*; #( end end - if (ResetAll) begin : g_instr_skid_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_skid_bp_taken_q <= '0; - instr_skid_data_q <= '0; - instr_skid_addr_q <= '0; - end else if (instr_skid_en) begin - instr_skid_bp_taken_q <= predict_branch_taken; - instr_skid_data_q <= fetch_rdata; - instr_skid_addr_q <= fetch_addr; - end - end - end else begin : g_instr_skid_nr - always_ff @(posedge clk_i) begin - if (instr_skid_en) begin - instr_skid_bp_taken_q <= predict_branch_taken; - instr_skid_data_q <= fetch_rdata; - instr_skid_addr_q <= fetch_addr; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_skid_bp_taken_q <= '0; + instr_skid_data_q <= '0; + instr_skid_addr_q <= '0; + end else if (instr_skid_en) begin + instr_skid_bp_taken_q <= predict_branch_taken; + instr_skid_data_q <= fetch_rdata; + instr_skid_addr_q <= fetch_addr; end end - ibex_branch_predict branch_predict_i ( + cve2_branch_predict branch_predict_i ( .clk_i (clk_i), .rst_ni (rst_ni), .fetch_rdata_i(fetch_rdata), @@ -610,7 +357,7 @@ module ibex_if_stage import ibex_pkg::*; #( assign if_instr_bus_err = ~instr_skid_valid_q & fetch_err; assign instr_bp_taken_d = instr_skid_valid_q ? instr_skid_bp_taken_q : predict_branch_taken; - assign fetch_ready = id_in_ready_i & ~stall_dummy_instr & ~instr_skid_valid_q; + assign fetch_ready = id_in_ready_i & ~instr_skid_valid_q; assign instr_bp_taken_o = instr_bp_taken_q; @@ -625,7 +372,7 @@ module ibex_if_stage import ibex_pkg::*; #( assign if_instr_rdata = fetch_rdata; assign if_instr_addr = fetch_addr; assign if_instr_bus_err = fetch_err; - assign fetch_ready = id_in_ready_i & ~stall_dummy_instr; + assign fetch_ready = id_in_ready_i; end //////////////// @@ -669,7 +416,7 @@ module ibex_if_stage import ibex_pkg::*; #( logic mispredicted, mispredicted_d, mispredicted_q; - assign next_pc = fetch_addr + (instr_is_compressed_out ? 32'd2 : 32'd4); + assign next_pc = fetch_addr + (instr_is_compressed ? 32'd2 : 32'd4); logic predicted_branch; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv similarity index 98% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv index 6ec55b077..548e75c8f 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv @@ -12,9 +12,9 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_load_store_unit +module cve2_load_store_unit ( input logic clk_i, input logic rst_ni, @@ -503,8 +503,8 @@ module ibex_load_store_unit // FCOV // ////////// - //`DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q) - //`DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q) + `DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q) + `DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q) //////////////// // Assertions // diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv similarity index 97% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv index 3f0d27ac3..0f9b9549b 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv @@ -14,8 +14,8 @@ `include "prim_assert.sv" -module ibex_multdiv_fast #( - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast +module cve2_multdiv_fast #( + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast ) ( input logic clk_i, input logic rst_ni, @@ -23,14 +23,13 @@ module ibex_multdiv_fast #( input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes input logic div_sel_i, // static decoder output, for data muxes - input ibex_pkg::md_op_e operator_i, + input cve2_pkg::md_op_e operator_i, input logic [1:0] signed_mode_i, input logic [31:0] op_a_i, input logic [31:0] op_b_i, input logic [33:0] alu_adder_ext_i, input logic [31:0] alu_adder_i, input logic equal_to_zero_i, - input logic data_ind_timing_i, output logic [32:0] alu_operand_a_o, output logic [32:0] alu_operand_b_o, @@ -45,7 +44,7 @@ module ibex_multdiv_fast #( output logic valid_o ); - import ibex_pkg::*; + import cve2_pkg::*; // Both multiplier variants logic signed [34:0] mac_res_signed; @@ -424,7 +423,7 @@ module ibex_multdiv_fast #( // normal and will naturally return -1 op_remainder_d = '1; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; // Record that this is a div by zero to stop the sign change at the end of the // division (in data_ind_timing mode). div_by_zero_d = equal_to_zero_i; @@ -435,7 +434,7 @@ module ibex_multdiv_fast #( // normal and will naturally return operand a op_remainder_d = {2'b0, op_a_i}; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; end // 0 - B = 0 iff B == 0 alu_operand_a_o = {32'h0 , 1'b1}; @@ -530,4 +529,4 @@ module ibex_multdiv_fast #( `endif `endif -endmodule // ibex_mult +endmodule // cve2_mult diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv similarity index 96% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv index 214d3f599..70732cc6d 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv @@ -11,7 +11,7 @@ `include "prim_assert.sv" -module ibex_multdiv_slow +module cve2_multdiv_slow ( input logic clk_i, input logic rst_ni, @@ -19,14 +19,13 @@ module ibex_multdiv_slow input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes input logic div_sel_i, // static decoder output, for data muxes - input ibex_pkg::md_op_e operator_i, + input cve2_pkg::md_op_e operator_i, input logic [1:0] signed_mode_i, input logic [31:0] op_a_i, input logic [31:0] op_b_i, input logic [33:0] alu_adder_ext_i, input logic [31:0] alu_adder_i, input logic equal_to_zero_i, - input logic data_ind_timing_i, output logic [32:0] alu_operand_a_o, output logic [32:0] alu_operand_b_o, @@ -42,7 +41,7 @@ module ibex_multdiv_slow output logic valid_o ); - import ibex_pkg::*; + import cve2_pkg::*; typedef enum logic [2:0] { MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH @@ -191,7 +190,7 @@ module ibex_multdiv_slow op_b_shift_d = op_b_ext >> 1; // Proceed with multiplication by 0/1 in data-independent time mode // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && ((op_b_ext >> 1) == 0)) ? MD_LAST : MD_COMP; + md_state_d = ((op_b_ext >> 1) == 0) ? MD_LAST : MD_COMP; end MD_OP_MULH: begin op_a_shift_d = op_a_ext; @@ -207,7 +206,7 @@ module ibex_multdiv_slow // normal and will naturally return -1 accum_window_d = {33{1'b1}}; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; // Record that this is a div by zero to stop the sign change at the end of the // division (in data_ind_timing mode). div_by_zero_d = equal_to_zero_i; @@ -219,7 +218,7 @@ module ibex_multdiv_slow // normal and will naturally return operand a accum_window_d = op_a_ext; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; end default:; endcase @@ -252,7 +251,7 @@ module ibex_multdiv_slow // Multiplication is complete once op_b is zero, unless in data_ind_timing mode where // the maximum possible shift-add operations will be completed regardless of op_b // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = ((!data_ind_timing_i && (op_b_shift_d == 0)) || + md_state_d = ((op_b_shift_d == 0) || (multdiv_count_q == 5'd1)) ? MD_LAST : MD_COMP; end MD_OP_MULH: begin diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv similarity index 83% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv index fec80fdf7..f3d71ce31 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv @@ -6,7 +6,7 @@ /** * Package with constants used by Ibex */ -package ibex_pkg; +package cve2_pkg; //////////////// // IO Structs // @@ -31,12 +31,6 @@ package ibex_pkg; // Parameter Enums // ///////////////////// - typedef enum integer { - RegFileFF = 0, - RegFileFPGA = 1, - RegFileLatch = 2 - } regfile_e; - typedef enum integer { RV32MNone = 0, RV32MSlow = 1, @@ -329,27 +323,6 @@ package ibex_pkg; DBG_CAUSE_STEP = 3'h4 } dbg_cause_e; - // ICache constants - parameter int unsigned ADDR_W = 32; - parameter int unsigned BUS_SIZE = 32; - parameter int unsigned BUS_BYTES = BUS_SIZE/8; - parameter int unsigned BUS_W = $clog2(BUS_BYTES); - parameter int unsigned IC_SIZE_BYTES = 4096; - parameter int unsigned IC_NUM_WAYS = 2; - parameter int unsigned IC_LINE_SIZE = 64; - parameter int unsigned IC_LINE_BYTES = IC_LINE_SIZE/8; - parameter int unsigned IC_LINE_W = $clog2(IC_LINE_BYTES); - parameter int unsigned IC_NUM_LINES = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES; - parameter int unsigned IC_LINE_BEATS = IC_LINE_BYTES / BUS_BYTES; - parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS); - parameter int unsigned IC_INDEX_W = $clog2(IC_NUM_LINES); - parameter int unsigned IC_INDEX_HI = IC_INDEX_W + IC_LINE_W - 1; - parameter int unsigned IC_TAG_SIZE = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit - parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords - // ICache Scrambling Parameters - parameter int unsigned SCRAMBLE_KEY_W = 128; - parameter int unsigned SCRAMBLE_NONCE_W = 64; - // PMP constants parameter int unsigned PMP_MAX_REGIONS = 16; parameter int unsigned PMP_CFG_W = 8; @@ -391,10 +364,11 @@ package ibex_pkg; // CSRs typedef enum logic[11:0] { // Machine information - CSR_MVENDORID = 12'hF11, - CSR_MARCHID = 12'hF12, - CSR_MIMPID = 12'hF13, - CSR_MHARTID = 12'hF14, + CSR_MVENDORID = 12'hF11, + CSR_MARCHID = 12'hF12, + CSR_MIMPID = 12'hF13, + CSR_MHARTID = 12'hF14, + CSR_MCONFIGPTR = 12'hF15, // Machine trap setup CSR_MSTATUS = 12'h300, @@ -402,6 +376,10 @@ package ibex_pkg; CSR_MIE = 12'h304, CSR_MTVEC = 12'h305, CSR_MCOUNTEREN= 12'h306, + CSR_MSTATUSH = 12'h310, + + CSR_MENVCFG = 12'h30A, + CSR_MENVCFGH = 12'h31A, // Machine trap handling CSR_MSCRATCH = 12'h340, @@ -593,28 +571,10 @@ package ibex_pkg; // commit). localparam logic [31:0] CSR_MIMPID_VALUE = 32'b0; - // These LFSR parameters have been generated with - // $ opentitan/util/design/gen-lfsr-seed.py --width 32 --seed 2480124384 --prefix "" - parameter int LfsrWidth = 32; - typedef logic [LfsrWidth-1:0] lfsr_seed_t; - typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t; - parameter lfsr_seed_t RndCnstLfsrSeedDefault = 32'hac533bf4; - parameter lfsr_perm_t RndCnstLfsrPermDefault = { - 160'h1e35ecba467fd1b12e958152c04fa43878a8daed - }; - parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKeyDefault = - 128'h14e8cecae3040d5e12286bb3cc113298; - parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonceDefault = - 64'hf79780bc735f3843; - - // Fetch enable. Mult-bit signal used for security hardening. For non-secure implementation all - // bits other than the bottom bit are ignored. - typedef logic [3:0] fetch_enable_t; - - // Note that if adjusting these parameters it is assumed the bottom bit is set for On and unset - // for Off. This allows the use of FetchEnableOn/FetchEnableOff to work for both secure and - // non-secure Ibex. If this assumption is broken the RTL that uses the fetch_enable signal within - // `ibex_core` may need adjusting. - parameter fetch_enable_t FetchEnableOn = 4'b1001; - parameter fetch_enable_t FetchEnableOff = 4'b0110; + // Machine Configuration Pointer + // 0 indicates the configuration data structure does not eixst. Ibex implementors may wish to + // alter this to point to their system specific configuration data structure. + localparam logic [31:0] CSR_MCONFIGPTR_VALUE = 32'b0; + endpackage + diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv similarity index 95% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv index 16e806a27..b531eefdf 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -module ibex_pmp #( +module cve2_pmp #( // Granularity of NAPOT access, // 0 = No restriction, 1 = 8 byte, 2 = 16 byte, 3 = 32 byte, etc. parameter int unsigned PMPGranularity = 0, @@ -16,19 +16,19 @@ module ibex_pmp #( input logic rst_ni, // Interface to CSRs - input ibex_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions], + input cve2_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions], input logic [33:0] csr_pmp_addr_i [PMPNumRegions], - input ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i, + input cve2_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i, - input ibex_pkg::priv_lvl_e priv_mode_i [PMPNumChan], + input cve2_pkg::priv_lvl_e priv_mode_i [PMPNumChan], // Access checking channels input logic [33:0] pmp_req_addr_i [PMPNumChan], - input ibex_pkg::pmp_req_e pmp_req_type_i [PMPNumChan], + input cve2_pkg::pmp_req_e pmp_req_type_i [PMPNumChan], output logic pmp_req_err_o [PMPNumChan] ); - import ibex_pkg::*; + import cve2_pkg::*; // Access Checking Signals logic [33:0] region_start_addr [PMPNumRegions]; @@ -177,7 +177,7 @@ module ibex_pmp #( assign pmp_req_err_o[c] = access_fault[c]; end - // RLB, rule locking bypass, is only relevant to ibex_cs_registers which controls writes to the + // RLB, rule locking bypass, is only relevant to cve2_cs_registers which controls writes to the // PMP CSRs. Tie to unused signal here to prevent lint warnings. logic unused_csr_pmp_mseccfg_rlb; assign unused_csr_pmp_mseccfg_rlb = csr_pmp_mseccfg_i.rlb; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp_reset_default.svh b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp_reset_default.svh similarity index 100% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp_reset_default.svh rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp_reset_default.svh diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv similarity index 90% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv index 5b834ce2d..95dee2e4f 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv @@ -9,8 +9,7 @@ * Prefetch Buffer that caches instructions. This cuts overly long critical * paths to the instruction cache. */ -module ibex_prefetch_buffer #( - parameter bit ResetAll = 1'b0 +module cve2_prefetch_buffer #( ) ( input logic clk_i, input logic rst_ni, @@ -94,9 +93,8 @@ module ibex_prefetch_buffer #( // Overlay the fifo fill state with the outstanding requests to see if there is space. assign fifo_ready = ~&(fifo_busy | rdata_outstanding_rev); - ibex_fetch_fifo #( - .NUM_REQS (NUM_REQS), - .ResetAll (ResetAll) + cve2_fetch_fifo #( + .NUM_REQS (NUM_REQS) ) fifo_i ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -156,19 +154,11 @@ module ibex_prefetch_buffer #( assign stored_addr_d = instr_addr; // CPU resets with a branch, so no need to reset these addresses - if (ResetAll) begin : g_stored_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - stored_addr_q <= '0; - end else if (stored_addr_en) begin - stored_addr_q <= stored_addr_d; - end - end - end else begin : g_stored_addr_nr - always_ff @(posedge clk_i) begin - if (stored_addr_en) begin - stored_addr_q <= stored_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + stored_addr_q <= '0; + end else if (stored_addr_en) begin + stored_addr_q <= stored_addr_d; end end // 2. fetch_addr_q @@ -182,19 +172,11 @@ module ibex_prefetch_buffer #( // Current address + 4 {{29{1'b0}},(valid_new_req & ~valid_req_q),2'b00}; - if (ResetAll) begin : g_fetch_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fetch_addr_q <= '0; - end else if (fetch_addr_en) begin - fetch_addr_q <= fetch_addr_d; - end - end - end else begin : g_fetch_addr_nr - always_ff @(posedge clk_i) begin - if (fetch_addr_en) begin - fetch_addr_q <= fetch_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + fetch_addr_q <= '0; + end else if (fetch_addr_en) begin + fetch_addr_q <= fetch_addr_d; end end diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv similarity index 66% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv index 90b0c7197..148ba225e 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv @@ -10,10 +10,9 @@ * This register file is based on flip flops. Use this register file when * targeting FPGA synthesis or Verilator simulation. */ -module ibex_register_file_ff #( +module cve2_register_file_ff #( parameter bit RV32E = 0, parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset @@ -21,7 +20,6 @@ module ibex_register_file_ff #( input logic rst_ni, input logic test_en_i, - input logic dummy_instr_id_i, //Read port R1 input logic [4:0] raddr_a_i, @@ -63,34 +61,8 @@ module ibex_register_file_ff #( end end - // With dummy instructions enabled, R0 behaves as a real register but will always return 0 for - // real instructions. - if (DummyInstructions) begin : g_dummy_r0 - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - 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; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rf_r0_q <= WordZeroVal; - end else if (we_r0_dummy) begin - rf_r0_q <= wdata_a_i; - end - end - - // Output the dummy data for dummy instructions, otherwise R0 reads as zero - assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : WordZeroVal; - - end else begin : g_normal_r0 - logic unused_dummy_instr_id; - assign unused_dummy_instr_id = dummy_instr_id_i; - - // R0 is nil - assign rf_reg[0] = WordZeroVal; - end + // R0 is nil + assign rf_reg[0] = WordZeroVal; assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1]; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv deleted file mode 100644 index 803880317..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2020 Silicon Labs, Inc. -// -// This file, and derivatives thereof are licensed under the -// Solderpad License, Version 2.0 (the "License"). -// -// Use of this file means you agree to the terms and conditions -// of the license and are in full compliance with the License. -// -// You may obtain a copy of the License at: -// -// https://solderpad.org/licenses/SHL-2.0/ -// -// Unless required by applicable law or agreed to in writing, software -// and hardware implementations thereof distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED. -// -// See the License for the specific language governing permissions and -// limitations under the License. - -//////////////////////////////////////////////////////////////////////////////// -// Engineer: Arjan Bink - arjan.bink@silabs.com // -// // -// Design Name: Sleep Unit // -// Project Name: CVE2 // -// Language: SystemVerilog // -// // -// Description: Sleep unit containing the instantiated clock gate which // -// provides the gated clock (clk_gated_o) for the rest // -// of the design. Forked version of cv32e40p // -// // -// The clock is gated for the following scenarios: // -// // -// - While waiting for fetch to become enabled // -// - While blocked on a WFI (PULP_CLUSTER = 0) // -// - While clock_en_i = 0 during a p.elw (PULP_CLUSTER = 1) // -// // -// Sleep is signaled via core_sleep_o when: // -// - During a WFI (except in debug) // -// // -// // -//////////////////////////////////////////////////////////////////////////////// - -module cve2_sleep_unit ( - // Clock, reset interface - input logic clk_ungated_i, // Free running clock - input logic rst_n, - output logic clk_gated_o, // Gated clock - input logic scan_cg_en_i, // Enable all clock gates for testing - - // Core sleep - output logic core_sleep_o, - - // Fetch enable - input logic fetch_enable_i, - output logic fetch_enable_o, - - // Core status - input logic if_busy_i, - input logic ctrl_busy_i, - input logic lsu_busy_i, - - // WFI wake - input logic wake_from_sleep_i -); - - logic fetch_enable_q; // Sticky version of fetch_enable_i - logic fetch_enable_d; - logic core_busy_q; // Is core still busy (and requires a clock) with what needs to finish before entering sleep? - logic core_busy_d; - logic clock_en; // Final clock enable - - ////////////////////////////////////////////////////////////////////////////// - // Sleep FSM - ////////////////////////////////////////////////////////////////////////////// - - // Make sticky version of fetch_enable_i - assign fetch_enable_d = fetch_enable_i ? 1'b1 : fetch_enable_q; - - - // Busy when any of the sub units is busy (typically wait for the instruction buffer to fill up) - assign core_busy_d = if_busy_i || ctrl_busy_i || lsu_busy_i; - - // Enable the clock only after the initial fetch enable while busy or waking up to become busy - assign clock_en = fetch_enable_q && (wake_from_sleep_i || core_busy_q); - - // Sleep only in response to WFI which leads to clock disable; debug_wfi_no_sleep_o in - // cv32e40p_controller determines the scenarios for which WFI can(not) cause sleep. - assign core_sleep_o = fetch_enable_q && !clock_en; - - - always_ff @(posedge clk_ungated_i, negedge rst_n) begin - if (rst_n == 1'b0) begin - core_busy_q <= 1'b0; - fetch_enable_q <= 1'b0; - end else begin - core_busy_q <= core_busy_d; - fetch_enable_q <= fetch_enable_d; - end - end - - // Fetch enable for Controller - assign fetch_enable_o = fetch_enable_q; - - // Main clock gate of CV32E40P - cve2_clock_gate core_clock_gate_i ( - .clk_i (clk_ungated_i), - .en_i (clock_en), - .scan_cg_en_i(scan_cg_en_i), - .clk_o (clk_gated_o) - ); - - //---------------------------------------------------------------------------- - // Assertions - TODO - //---------------------------------------------------------------------------- - - -endmodule // cve2_sleep_unit diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv new file mode 100644 index 000000000..3954d8a94 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -0,0 +1,271 @@ +// Copyright lowRISC contributors. +// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`ifdef RISCV_FORMAL + `define RVFI +`endif + +`include "prim_assert.sv" + +/** + * Top level module of the ibex RISC-V core + */ +module cve2_top import cve2_pkg::*; #( + parameter int unsigned MHPMCounterNum = 0, + parameter int unsigned MHPMCounterWidth = 40, + parameter bit RV32E = 1'b0, + parameter rv32m_e RV32M = RV32MFast, + parameter bit WritebackStage = 1'b0, + parameter bit BranchPredictor = 1'b0, + parameter int unsigned DmHaltAddr = 32'h1A110800, + parameter int unsigned DmExceptionAddr = 32'h1A110808 +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic test_en_i, // enable all clock gates for testing + input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, + + input logic [31:0] hart_id_i, + input logic [31:0] boot_addr_i, + + // Instruction memory interface + output logic instr_req_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + output logic [31:0] instr_addr_o, + input logic [31:0] instr_rdata_i, + input logic instr_err_i, + + // Data memory interface + output logic data_req_o, + input logic data_gnt_i, + input logic data_rvalid_i, + output logic data_we_o, + output logic [3:0] data_be_o, + output logic [31:0] data_addr_o, + output logic [31:0] data_wdata_o, + input logic [31:0] data_rdata_i, + input logic data_err_i, + + // Interrupt inputs + input logic irq_software_i, + input logic irq_timer_i, + input logic irq_external_i, + input logic [14:0] irq_fast_i, + input logic irq_nm_i, // non-maskeable interrupt + + // Debug Interface + input logic debug_req_i, + output crash_dump_t crash_dump_o, + + // RISC-V Formal Interface + // Does not comply with the coding standards of _i/_o suffixes, but follows + // the convention of RISC-V Formal Interface Specification. +`ifdef RVFI + output logic rvfi_valid, + output logic [63:0] rvfi_order, + output logic [31:0] rvfi_insn, + output logic rvfi_trap, + output logic rvfi_halt, + output logic rvfi_intr, + output logic [ 1:0] rvfi_mode, + output logic [ 1:0] rvfi_ixl, + output logic [ 4:0] rvfi_rs1_addr, + output logic [ 4:0] rvfi_rs2_addr, + output logic [ 4:0] rvfi_rs3_addr, + output logic [31:0] rvfi_rs1_rdata, + output logic [31:0] rvfi_rs2_rdata, + output logic [31:0] rvfi_rs3_rdata, + output logic [ 4:0] rvfi_rd_addr, + output logic [31:0] rvfi_rd_wdata, + output logic [31:0] rvfi_pc_rdata, + output logic [31:0] rvfi_pc_wdata, + output logic [31:0] rvfi_mem_addr, + output logic [ 3:0] rvfi_mem_rmask, + output logic [ 3:0] rvfi_mem_wmask, + output logic [31:0] rvfi_mem_rdata, + output logic [31:0] rvfi_mem_wdata, + output logic [31:0] rvfi_ext_mip, + output logic rvfi_ext_nmi, + output logic rvfi_ext_debug_req, + output logic [63:0] rvfi_ext_mcycle, +`endif + + // CPU Control Signals + output logic core_sleep_o +); + + // Scrambling Parameter + localparam int unsigned NumAddrScrRounds = 0; + + // Physical Memory Protection + localparam bit PMPEnable = 1'b0; + localparam int unsigned PMPGranularity = 0; + localparam int unsigned PMPNumRegions = 4; + + // Trigger support + localparam bit DbgTriggerEn = 1'b1; + localparam int unsigned DbgHwBreakNum = 1; + + // Bit manipulation extension + localparam rv32b_e RV32B = RV32BNone; + + // Clock signals + logic clk; + logic core_busy_d, core_busy_q; + logic clock_en; + logic irq_pending; + + ///////////////////// + // Main clock gate // + ///////////////////// + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + core_busy_q <= 1'b0; + end else begin + core_busy_q <= core_busy_d; + end + end + + assign clock_en = core_busy_q | debug_req_i | irq_pending | irq_nm_i; + assign core_sleep_o = ~clock_en; + + cve2_clock_gate core_clock_gate_i ( + .clk_i (clk_i), + .en_i (clock_en), + .scan_cg_en_i(test_en_i), + .clk_o (clk) + ); + + //////////////////////// + // Core instantiation // + //////////////////////// + + cve2_core #( + .PMPEnable (PMPEnable), + .PMPGranularity (PMPGranularity), + .PMPNumRegions (PMPNumRegions), + .MHPMCounterNum (MHPMCounterNum), + .MHPMCounterWidth (MHPMCounterWidth), + .RV32E (RV32E), + .RV32M (RV32M), + .RV32B (RV32B), + .BranchPredictor (BranchPredictor), + .DbgTriggerEn (DbgTriggerEn), + .DbgHwBreakNum (DbgHwBreakNum), + .WritebackStage (WritebackStage), + .DmHaltAddr (DmHaltAddr), + .DmExceptionAddr (DmExceptionAddr) + ) u_cve2_core ( + .clk_i(clk), + .rst_ni, + .test_en_i, + + .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, + + .irq_software_i, + .irq_timer_i, + .irq_external_i, + .irq_fast_i, + .irq_nm_i, + .irq_pending_o(irq_pending), + + .debug_req_i, + .crash_dump_o, + +`ifdef RVFI + .rvfi_valid, + .rvfi_order, + .rvfi_insn, + .rvfi_trap, + .rvfi_halt, + .rvfi_intr, + .rvfi_mode, + .rvfi_ixl, + .rvfi_rs1_addr, + .rvfi_rs2_addr, + .rvfi_rs3_addr, + .rvfi_rs1_rdata, + .rvfi_rs2_rdata, + .rvfi_rs3_rdata, + .rvfi_rd_addr, + .rvfi_rd_wdata, + .rvfi_pc_rdata, + .rvfi_pc_wdata, + .rvfi_mem_addr, + .rvfi_mem_rmask, + .rvfi_mem_wmask, + .rvfi_mem_rdata, + .rvfi_mem_wdata, + .rvfi_ext_mip, + .rvfi_ext_nmi, + .rvfi_ext_debug_req, + .rvfi_ext_mcycle, +`endif + + .core_busy_o (core_busy_d) + ); + + //////////////////////// + // Rams Instantiation // + //////////////////////// + + prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg; + logic unused_ram_inputs; + + assign unused_ram_cfg = ram_cfg_i; + assign unused_ram_inputs = (|NumAddrScrRounds); + + + // X checks for top-level outputs + `ASSERT_KNOWN(IbexInstrReqX, instr_req_o) + `ASSERT_KNOWN_IF(IbexInstrReqPayloadX, instr_addr_o, instr_req_o) + + `ASSERT_KNOWN(IbexDataReqX, data_req_o) + `ASSERT_KNOWN_IF(IbexDataReqPayloadX, + {data_we_o, data_be_o, data_addr_o, data_wdata_o}, data_req_o) + + `ASSERT_KNOWN(IbexCoreSleepX, core_sleep_o) + + // X check for top-level inputs + `ASSERT_KNOWN(IbexTestEnX, test_en_i) + `ASSERT_KNOWN(IbexRamCfgX, ram_cfg_i) + `ASSERT_KNOWN(IbexHartIdX, hart_id_i) + `ASSERT_KNOWN(IbexBootAddrX, boot_addr_i) + + `ASSERT_KNOWN(IbexInstrGntX, instr_gnt_i) + `ASSERT_KNOWN(IbexInstrRValidX, instr_rvalid_i) + `ASSERT_KNOWN_IF(IbexInstrRPayloadX, + {instr_rdata_i, instr_err_i}, instr_rvalid_i) + + `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) + `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) + `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_err_i}, data_rvalid_i) + + `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) + + `ASSERT_KNOWN(IbexDebugReqX, debug_req_i) +endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv similarity index 78% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv index f43846539..9a8bec32d 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv @@ -6,27 +6,16 @@ * Top level module of the ibex RISC-V core with tracing enabled */ -module ibex_top_tracing import ibex_pkg::*; #( - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, +module cve2_top_tracing import cve2_pkg::*; #( parameter int unsigned MHPMCounterNum = 0, parameter int unsigned MHPMCounterWidth = 40, parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, parameter rv32b_e RV32B = RV32BNone, - parameter regfile_e RegFile = RegFileFF, - parameter bit BranchTargetALU = 1'b0, parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, parameter bit BranchPredictor = 1'b0, parameter bit DbgTriggerEn = 1'b0, parameter int unsigned DbgHwBreakNum = 1, - parameter bit SecureIbex = 1'b0, - parameter bit ICacheScramble = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -71,19 +60,11 @@ module ibex_top_tracing import ibex_pkg::*; #( input logic [14:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt - // Scrambling Interface - input logic scramble_key_valid_i, - input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i, - input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i, - output logic scramble_req_o, - // Debug Interface input logic debug_req_i, output crash_dump_t crash_dump_o, - output logic double_fault_seen_o, // CPU Control Signals - input fetch_enable_t fetch_enable_i, output logic alert_minor_o, output logic alert_major_internal_o, output logic alert_major_bus_o, @@ -91,7 +72,7 @@ module ibex_top_tracing import ibex_pkg::*; #( ); - // ibex_tracer relies on the signals from the RISC-V Formal Interface + // cve2_tracer relies on the signals from the RISC-V Formal Interface `ifndef RVFI $fatal("Fatal error: RVFI needs to be defined globally."); `endif @@ -136,30 +117,19 @@ module ibex_top_tracing import ibex_pkg::*; #( assign unused_rvfi_ext_debug_req = rvfi_ext_debug_req; assign unused_rvfi_ext_mcycle = rvfi_ext_mcycle; - ibex_top #( - .PMPEnable ( PMPEnable ), - .PMPGranularity ( PMPGranularity ), - .PMPNumRegions ( PMPNumRegions ), + cve2_top #( .MHPMCounterNum ( MHPMCounterNum ), .MHPMCounterWidth ( MHPMCounterWidth ), .RV32E ( RV32E ), .RV32M ( RV32M ), .RV32B ( RV32B ), - .RegFile ( RegFile ), - .BranchTargetALU ( BranchTargetALU ), - .ICache ( ICache ), - .ICacheECC ( ICacheECC ), .BranchPredictor ( BranchPredictor ), .DbgTriggerEn ( DbgTriggerEn ), .DbgHwBreakNum ( DbgHwBreakNum ), .WritebackStage ( WritebackStage ), - .SecureIbex ( SecureIbex ), - .ICacheScramble ( ICacheScramble ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), .DmHaltAddr ( DmHaltAddr ), .DmExceptionAddr ( DmExceptionAddr ) - ) u_ibex_top ( + ) u_cve2_top ( .clk_i, .rst_ni, @@ -196,14 +166,8 @@ module ibex_top_tracing import ibex_pkg::*; #( .irq_fast_i, .irq_nm_i, - .scramble_key_valid_i, - .scramble_key_i, - .scramble_nonce_i, - .scramble_req_o, - .debug_req_i, .crash_dump_o, - .double_fault_seen_o, .rvfi_valid, .rvfi_order, @@ -233,15 +197,14 @@ module ibex_top_tracing import ibex_pkg::*; #( .rvfi_ext_debug_req, .rvfi_ext_mcycle, - .fetch_enable_i, .alert_minor_o, .alert_major_internal_o, .alert_major_bus_o, .core_sleep_o ); - ibex_tracer - u_ibex_tracer ( + cve2_tracer + u_cve2_tracer ( .clk_i, .rst_ni, diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv similarity index 98% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv index bd36a2147..707419e44 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv @@ -12,12 +12,12 @@ * All traced instructions are written to a log file. By default, the log file is named * trace_core_.log, with being the 8 digit hart ID of the core being traced. * - * The file name base, defaulting to "trace_core" can be set using the "ibex_tracer_file_base" - * plusarg passed to the simulation, e.g. "+ibex_tracer_file_base=ibex_my_trace". The exact syntax + * The file name base, defaulting to "trace_core" can be set using the "cve2_tracer_file_base" + * plusarg passed to the simulation, e.g. "+cve2_tracer_file_base=cve2_my_trace". The exact syntax * of passing plusargs to a simulation depends on the simulator. * * The creation of the instruction trace is enabled by default but can be disabled for a simulation. - * This behaviour is controlled by the plusarg "ibex_tracer_enable". Use "ibex_tracer_enable=0" to + * This behaviour is controlled by the plusarg "cve2_tracer_enable". Use "cve2_tracer_enable=0" to * disable the tracer. * * The trace contains six columns, separated by tabs: @@ -34,7 +34,7 @@ * to the one produced by objdump. This simplifies the correlation between the static program * information from the objdump-generated disassembly, and the runtime information from this tracer. */ -module ibex_tracer ( +module cve2_tracer ( input logic clk_i, input logic rst_ni, @@ -79,7 +79,7 @@ module ibex_tracer ( logic [ 1:0] unused_rvfi_mode = rvfi_mode; logic [ 1:0] unused_rvfi_ixl = rvfi_ixl; - import ibex_tracer_pkg::*; + import cve2_tracer_pkg::*; int file_handle; string file_name; @@ -98,7 +98,7 @@ module ibex_tracer ( logic trace_log_enable; initial begin - if ($value$plusargs("ibex_tracer_enable=%b", trace_log_enable)) begin + if ($value$plusargs("cve2_tracer_enable=%b", trace_log_enable)) begin if (trace_log_enable == 1'b0) begin $display("%m: Instruction trace disabled."); end @@ -112,7 +112,7 @@ module ibex_tracer ( if (file_handle == 32'h0) begin string file_name_base = "trace_core"; - void'($value$plusargs("ibex_tracer_file_base=%s", file_name_base)); + void'($value$plusargs("cve2_tracer_file_base=%s", file_name_base)); $sformat(file_name, "%s_%h.log", file_name_base, hart_id_i); $display("%m: Writing execution trace to %s", file_name); diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv similarity index 99% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv index 6dbbfc905..700dd37b3 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv @@ -3,8 +3,8 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -package ibex_tracer_pkg; - import ibex_pkg::*; +package cve2_tracer_pkg; + import cve2_pkg::*; parameter logic [1:0] OPCODE_C0 = 2'b00; parameter logic [1:0] OPCODE_C1 = 2'b01; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb_stage.sv similarity index 91% rename from hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv rename to hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb_stage.sv index 14364c573..7e9af8dab 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb_stage.sv @@ -12,17 +12,16 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_wb_stage #( - parameter bit ResetAll = 1'b0, +module cve2_wb_stage #( parameter bit WritebackStage = 1'b0 ) ( input logic clk_i, input logic rst_ni, input logic en_wb_i, - input ibex_pkg::wb_instr_type_e instr_type_wb_i, + input cve2_pkg::wb_instr_type_e instr_type_wb_i, input logic [31:0] pc_id_i, input logic instr_is_compressed_id_i, input logic instr_perf_count_id_i, @@ -56,7 +55,7 @@ module ibex_wb_stage #( output logic instr_done_wb_o ); - import ibex_pkg::*; + import cve2_pkg::*; // 0 == RF write from ID // 1 == RF write from LSU @@ -95,7 +94,7 @@ module ibex_wb_stage #( end end - if (ResetAll) begin : g_wb_regs_ra + begin : g_wb_regs always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rf_we_wb_q <= '0; @@ -115,18 +114,6 @@ module ibex_wb_stage #( wb_count_q <= instr_perf_count_id_i; end end - end else begin : g_wb_regs_nr - always_ff @(posedge clk_i) begin - if (en_wb_i) begin - rf_we_wb_q <= rf_we_id_i; - rf_waddr_wb_q <= rf_waddr_id_i; - rf_wdata_wb_q <= rf_wdata_id_i; - wb_instr_type_q <= instr_type_wb_i; - wb_pc_q <= pc_id_i; - wb_compressed_q <= instr_is_compressed_id_i; - wb_count_q <= instr_perf_count_id_i; - end - end end assign rf_waddr_wb_o = rf_waddr_wb_q; @@ -208,7 +195,7 @@ module ibex_wb_stage #( ({32{rf_wdata_wb_mux_we[1]}} & rf_wdata_wb_mux[1]); assign rf_we_wb_o = |rf_wdata_wb_mux_we; - //`DV_FCOV_SIGNAL_GEN_IF(logic, wb_valid, g_writeback_stage.wb_valid_q, WritebackStage) + `DV_FCOV_SIGNAL_GEN_IF(logic, wb_valid, g_writeback_stage.wb_valid_q, WritebackStage) `ASSERT(RFWriteFromOneSourceOnly, $onehot0(rf_wdata_wb_mux_we)) endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f b/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f deleted file mode 100644 index 83e8396b8..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f +++ /dev/null @@ -1,17 +0,0 @@ -ibex_pkg.sv -ibex_alu.sv -ibex_compressed_decoder.sv -ibex_controller.sv -ibex_counter.sv -ibex_cs_registers.sv -ibex_decoder.sv -ibex_ex_block.sv -ibex_id_stage.sv -ibex_if_stage.sv -ibex_load_store_unit.sv -ibex_multdiv_slow.sv -ibex_multdiv_fast.sv -ibex_prefetch_buffer.sv -ibex_fetch_fifo.sv -ibex_register_file_ff.sv -ibex_core.sv diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv b/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv deleted file mode 100644 index ba33adc41..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Dummy instruction module - * - * Provides pseudo-randomly inserted fake instructions for secure code obfuscation - */ - -// SEC_CM: CTRL_FLOW.UNPREDICTABLE -module ibex_dummy_instr import ibex_pkg::*; #( - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault -) ( - // Clock and reset - input logic clk_i, - input logic rst_ni, - - // Interface to CSRs - input logic dummy_instr_en_i, - input logic [2:0] dummy_instr_mask_i, - input logic dummy_instr_seed_en_i, - input logic [31:0] dummy_instr_seed_i, - - // Interface to IF stage - input logic fetch_valid_i, - input logic id_in_ready_i, - output logic insert_dummy_instr_o, - output logic [31:0] dummy_instr_data_o -); - - localparam int unsigned TIMEOUT_CNT_W = 5; - localparam int unsigned OP_W = 5; - - typedef enum logic [1:0] { - DUMMY_ADD = 2'b00, - DUMMY_MUL = 2'b01, - DUMMY_DIV = 2'b10, - DUMMY_AND = 2'b11 - } dummy_instr_e; - - typedef struct packed { - dummy_instr_e instr_type; - logic [OP_W-1:0] op_b; - logic [OP_W-1:0] op_a; - logic [TIMEOUT_CNT_W-1:0] cnt; - } lfsr_data_t; - localparam int unsigned LFSR_OUT_W = $bits(lfsr_data_t); - - lfsr_data_t lfsr_data; - logic [TIMEOUT_CNT_W-1:0] dummy_cnt_incr, dummy_cnt_threshold; - logic [TIMEOUT_CNT_W-1:0] dummy_cnt_d, dummy_cnt_q; - logic dummy_cnt_en; - logic lfsr_en; - logic [LFSR_OUT_W-1:0] lfsr_state; - logic insert_dummy_instr; - logic [6:0] dummy_set; - logic [2:0] dummy_opcode; - logic [31:0] dummy_instr; - logic [31:0] dummy_instr_seed_q, dummy_instr_seed_d; - - // Shift the LFSR every time we insert an instruction - assign lfsr_en = insert_dummy_instr & id_in_ready_i; - - assign dummy_instr_seed_d = dummy_instr_seed_q ^ dummy_instr_seed_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_instr_seed_q <= '0; - end else if (dummy_instr_seed_en_i) begin - dummy_instr_seed_q <= dummy_instr_seed_d; - end - end - - prim_lfsr #( - .LfsrDw ( LfsrWidth ), - .StateOutDw ( LFSR_OUT_W ), - .DefaultSeed ( RndCnstLfsrSeed ), - .StatePermEn ( 1'b1 ), - .StatePerm ( RndCnstLfsrPerm ) - ) lfsr_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .seed_en_i ( dummy_instr_seed_en_i ), - .seed_i ( dummy_instr_seed_d ), - .lfsr_en_i ( lfsr_en ), - .entropy_i ( '0 ), - .state_o ( lfsr_state ) - ); - - // Extract fields from LFSR - assign lfsr_data = lfsr_data_t'(lfsr_state); - - // Set count threshold for inserting a new instruction. This is the pseudo-random value from the - // LFSR with a mask applied (based on CSR config data) to shorten the period if required. - assign dummy_cnt_threshold = lfsr_data.cnt & {dummy_instr_mask_i,{TIMEOUT_CNT_W-3{1'b1}}}; - assign dummy_cnt_incr = dummy_cnt_q + {{TIMEOUT_CNT_W-1{1'b0}},1'b1}; - // Clear the counter everytime a new instruction is inserted - assign dummy_cnt_d = insert_dummy_instr ? '0 : dummy_cnt_incr; - // Increment the counter for each executed instruction while dummy instuctions are - // enabled. - assign dummy_cnt_en = dummy_instr_en_i & id_in_ready_i & - (fetch_valid_i | insert_dummy_instr); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_cnt_q <= '0; - end else if (dummy_cnt_en) begin - dummy_cnt_q <= dummy_cnt_d; - end - end - - // Insert a dummy instruction each time the counter hits the threshold - assign insert_dummy_instr = dummy_instr_en_i & (dummy_cnt_q == dummy_cnt_threshold); - - // Encode instruction - always_comb begin - unique case (lfsr_data.instr_type) - DUMMY_ADD: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b000; - end - DUMMY_MUL: begin - dummy_set = 7'b0000001; - dummy_opcode = 3'b000; - end - DUMMY_DIV: begin - dummy_set = 7'b0000001; - dummy_opcode = 3'b100; - end - DUMMY_AND: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b111; - end - default: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b000; - end - endcase - end - - // SET RS2 RS1 OP RD - assign dummy_instr = {dummy_set, lfsr_data.op_b, lfsr_data.op_a, dummy_opcode, 5'h00, 7'h33}; - - // Assign outputs - assign insert_dummy_instr_o = insert_dummy_instr; - assign dummy_instr_data_o = dummy_instr; - -endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv b/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv deleted file mode 100644 index c15a29b57..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv +++ /dev/null @@ -1,1165 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Instruction cache - * - * Provides an instruction cache along with cache management, instruction buffering and prefetching - */ - -`include "prim_assert.sv" - -module ibex_icache import ibex_pkg::*; #( - parameter bit ICacheECC = 1'b0, - parameter bit ResetAll = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - // Only cache branch targets - parameter bit BranchCache = 1'b0 -) ( - // Clock and reset - input logic clk_i, - input logic rst_ni, - - // Signal that the core would like instructions - input logic req_i, - - // Set the cache's address counter - input logic branch_i, - input logic branch_mispredict_i, - input logic [31:0] mispredict_addr_i, - input logic [31:0] addr_i, - - // IF stage interface: Pass fetched instructions to the core - input logic ready_i, - output logic valid_o, - output logic [31:0] rdata_o, - output logic [31:0] addr_o, - output logic err_o, - output logic err_plus2_o, - - // Instruction memory / interconnect interface: Fetch instruction data from memory - output logic instr_req_o, - input logic instr_gnt_i, - output logic [31:0] instr_addr_o, - input logic [BUS_SIZE-1:0] instr_rdata_i, - input logic instr_err_i, - input logic instr_rvalid_i, - - // RAM IO - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - - // Cache status - input logic icache_enable_i, - input logic icache_inval_i, - output logic busy_o, - output logic ecc_error_o -); - - // Number of fill buffers (must be >= 2) - localparam int unsigned NUM_FB = 4; - // Request throttling threshold - localparam int unsigned FB_THRESHOLD = NUM_FB - 2; - - // Prefetch signals - logic [ADDR_W-1:0] lookup_addr_aligned; - logic [ADDR_W-1:0] prefetch_addr_d, prefetch_addr_q; - logic prefetch_addr_en; - logic branch_or_mispredict; - // Cache pipelipe IC0 signals - logic lookup_throttle; - logic lookup_req_ic0; - logic [ADDR_W-1:0] lookup_addr_ic0; - logic [IC_INDEX_W-1:0] lookup_index_ic0; - logic fill_req_ic0; - logic [IC_INDEX_W-1:0] fill_index_ic0; - logic [IC_TAG_SIZE-1:0] fill_tag_ic0; - logic [IC_LINE_SIZE-1:0] fill_wdata_ic0; - logic lookup_grant_ic0; - logic lookup_actual_ic0; - logic fill_grant_ic0; - logic tag_req_ic0; - logic [IC_INDEX_W-1:0] tag_index_ic0; - logic [IC_NUM_WAYS-1:0] tag_banks_ic0; - logic tag_write_ic0; - logic [TagSizeECC-1:0] tag_wdata_ic0; - logic data_req_ic0; - logic [IC_INDEX_W-1:0] data_index_ic0; - logic [IC_NUM_WAYS-1:0] data_banks_ic0; - logic data_write_ic0; - logic [LineSizeECC-1:0] data_wdata_ic0; - // Cache pipelipe IC1 signals - logic [TagSizeECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] data_rdata_ic1 [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] hit_data_ecc_ic1; - logic [IC_LINE_SIZE-1:0] hit_data_ic1; - logic lookup_valid_ic1; - logic [ADDR_W-1:IC_INDEX_HI+1] lookup_addr_ic1; - logic [IC_NUM_WAYS-1:0] tag_match_ic1; - logic tag_hit_ic1; - logic [IC_NUM_WAYS-1:0] tag_invalid_ic1; - logic [IC_NUM_WAYS-1:0] lowest_invalid_way_ic1; - logic [IC_NUM_WAYS-1:0] round_robin_way_ic1, round_robin_way_q; - logic [IC_NUM_WAYS-1:0] sel_way_ic1; - logic ecc_err_ic1; - logic ecc_write_req; - logic [IC_NUM_WAYS-1:0] ecc_write_ways; - logic [IC_INDEX_W-1:0] ecc_write_index; - // Fill buffer signals - logic [$clog2(NUM_FB)-1:0] fb_fill_level; - logic fill_cache_new; - logic fill_new_alloc; - logic fill_spec_req, fill_spec_done, fill_spec_hold; - logic [NUM_FB-1:0][NUM_FB-1:0] fill_older_d, fill_older_q; - logic [NUM_FB-1:0] fill_alloc_sel, fill_alloc; - logic [NUM_FB-1:0] fill_busy_d, fill_busy_q; - logic [NUM_FB-1:0] fill_done; - logic [NUM_FB-1:0] fill_in_ic1; - logic [NUM_FB-1:0] fill_stale_d, fill_stale_q; - logic [NUM_FB-1:0] fill_cache_d, fill_cache_q; - logic [NUM_FB-1:0] fill_hit_ic1, fill_hit_d, fill_hit_q; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_ext_cnt_d, fill_ext_cnt_q; - logic [NUM_FB-1:0] fill_ext_hold_d, fill_ext_hold_q; - logic [NUM_FB-1:0] fill_ext_done_d, fill_ext_done_q; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_rvd_cnt_d, fill_rvd_cnt_q; - logic [NUM_FB-1:0] fill_rvd_done; - logic [NUM_FB-1:0] fill_ram_done_d, fill_ram_done_q; - logic [NUM_FB-1:0] fill_out_grant; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_out_cnt_d, fill_out_cnt_q; - logic [NUM_FB-1:0] fill_out_done; - logic [NUM_FB-1:0] fill_ext_req, fill_rvd_exp, fill_ram_req, fill_out_req; - logic [NUM_FB-1:0] fill_data_sel, fill_data_reg; - logic [NUM_FB-1:0] fill_data_hit, fill_data_rvd; - logic [NUM_FB-1:0][IC_LINE_BEATS_W-1:0] fill_ext_off, fill_rvd_off; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_ext_beat, fill_rvd_beat; - logic [NUM_FB-1:0] fill_ext_arb, fill_ram_arb, fill_out_arb; - logic [NUM_FB-1:0] fill_rvd_arb; - logic [NUM_FB-1:0] fill_entry_en; - logic [NUM_FB-1:0] fill_addr_en; - logic [NUM_FB-1:0] fill_way_en; - logic [NUM_FB-1:0][IC_LINE_BEATS-1:0] fill_data_en; - logic [NUM_FB-1:0][IC_LINE_BEATS-1:0] fill_err_d, fill_err_q; - logic [ADDR_W-1:0] fill_addr_q [NUM_FB]; - logic [IC_NUM_WAYS-1:0] fill_way_q [NUM_FB]; - logic [IC_LINE_SIZE-1:0] fill_data_d [NUM_FB]; - logic [IC_LINE_SIZE-1:0] fill_data_q [NUM_FB]; - logic [ADDR_W-1:BUS_W] fill_ext_req_addr; - logic [ADDR_W-1:0] fill_ram_req_addr; - logic [IC_NUM_WAYS-1:0] fill_ram_req_way; - logic [IC_LINE_SIZE-1:0] fill_ram_req_data; - logic [IC_LINE_SIZE-1:0] fill_out_data; - logic [IC_LINE_BEATS-1:0] fill_out_err; - // External req signals - logic instr_req; - logic [ADDR_W-1:BUS_W] instr_addr; - // Data output signals - logic skid_complete_instr; - logic skid_ready; - logic output_compressed; - logic skid_valid_d, skid_valid_q, skid_en; - logic [15:0] skid_data_d, skid_data_q; - logic skid_err_q; - logic output_valid; - logic addr_incr_two; - logic output_addr_en; - logic [ADDR_W-1:1] output_addr_incr; - logic [ADDR_W-1:1] output_addr_d, output_addr_q; - logic [15:0] output_data_lo, output_data_hi; - logic data_valid, output_ready; - logic [IC_LINE_SIZE-1:0] line_data; - logic [IC_LINE_BEATS-1:0] line_err; - logic [31:0] line_data_muxed; - logic line_err_muxed; - logic [31:0] output_data; - logic output_err; - // Invalidations - logic start_inval, inval_done; - logic inval_lock, inval_req_d, inval_req_q; - logic reset_inval_q; - logic inval_prog_d, inval_prog_q; - logic [IC_INDEX_W-1:0] inval_index_d, inval_index_q; - - ////////////////////////// - // Instruction prefetch // - ////////////////////////// - - assign branch_or_mispredict = branch_i | branch_mispredict_i; - - assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:IC_LINE_W], {IC_LINE_W{1'b0}}}; - - // The prefetch address increments by one cache line for each granted request. - // This address is also updated if there is a branch that is not granted, since the target - // address (addr_i) is only valid for one cycle while branch_i is high. - - // The captured branch target address is not forced to be aligned since the offset in the cache - // line must also be recorded for later use by the fill buffers. - assign prefetch_addr_d = - lookup_grant_ic0 ? (lookup_addr_aligned + - {{ADDR_W-IC_LINE_W-1{1'b0}}, 1'b1, {IC_LINE_W{1'b0}}}) : - branch_i ? addr_i : - mispredict_addr_i; - - assign prefetch_addr_en = branch_or_mispredict | lookup_grant_ic0; - - if (ResetAll) begin : g_prefetch_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - prefetch_addr_q <= '0; - end else if (prefetch_addr_en) begin - prefetch_addr_q <= prefetch_addr_d; - end - end - end else begin : g_prefetch_addr_nr - always_ff @(posedge clk_i) begin - if (prefetch_addr_en) begin - prefetch_addr_q <= prefetch_addr_d; - end - end - end - - //////////////////////// - // Pipeline stage IC0 // - //////////////////////// - - // Cache lookup - assign lookup_throttle = (fb_fill_level > FB_THRESHOLD[$clog2(NUM_FB)-1:0]); - - assign lookup_req_ic0 = req_i & ~&fill_busy_q & (branch_or_mispredict | ~lookup_throttle) & - ~ecc_write_req; - assign lookup_addr_ic0 = branch_i ? addr_i : - branch_mispredict_i ? mispredict_addr_i : - prefetch_addr_q; - assign lookup_index_ic0 = lookup_addr_ic0[IC_INDEX_HI:IC_LINE_W]; - - // Cache write - assign fill_req_ic0 = (|fill_ram_req); - assign fill_index_ic0 = fill_ram_req_addr[IC_INDEX_HI:IC_LINE_W]; - assign fill_tag_ic0 = {(~inval_prog_q & ~ecc_write_req), - fill_ram_req_addr[ADDR_W-1:IC_INDEX_HI+1]}; - assign fill_wdata_ic0 = fill_ram_req_data; - - // Arbitrated signals - lookups have highest priority - assign lookup_grant_ic0 = lookup_req_ic0; - assign fill_grant_ic0 = fill_req_ic0 & ~lookup_req_ic0 & ~inval_prog_q & - ~ecc_write_req; - // Qualified lookup grant to mask ram signals in IC1 if access was not made - assign lookup_actual_ic0 = lookup_grant_ic0 & icache_enable_i & ~inval_prog_q & - ~icache_inval_i & ~inval_lock & ~start_inval; - - // Tagram - assign tag_req_ic0 = lookup_req_ic0 | fill_req_ic0 | inval_prog_q | ecc_write_req; - assign tag_index_ic0 = inval_prog_q ? inval_index_q : - ecc_write_req ? ecc_write_index : - fill_grant_ic0 ? fill_index_ic0 : - lookup_index_ic0; - assign tag_banks_ic0 = ecc_write_req ? ecc_write_ways : - fill_grant_ic0 ? fill_ram_req_way : - {IC_NUM_WAYS{1'b1}}; - assign tag_write_ic0 = fill_grant_ic0 | inval_prog_q | ecc_write_req; - - // Dataram - assign data_req_ic0 = lookup_req_ic0 | fill_req_ic0; - assign data_index_ic0 = tag_index_ic0; - assign data_banks_ic0 = tag_banks_ic0; - assign data_write_ic0 = tag_write_ic0; - - // Append ECC checkbits to write data if required - if (ICacheECC) begin : gen_ecc_wdata - // SEC_CM: ICACHE.MEM.INTEGRITY - // Tagram ECC - // Reuse the same ecc encoding module for larger cache sizes by padding with zeros - logic [21:0] tag_ecc_input_padded; - logic [27:0] tag_ecc_output_padded; - logic [22-IC_TAG_SIZE:0] unused_tag_ecc_output; - - assign tag_ecc_input_padded = {{22-IC_TAG_SIZE{1'b0}},fill_tag_ic0}; - assign unused_tag_ecc_output = tag_ecc_output_padded[21:IC_TAG_SIZE-1]; - - prim_secded_inv_28_22_enc tag_ecc_enc ( - .data_i (tag_ecc_input_padded), - .data_o (tag_ecc_output_padded) - ); - - assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22],tag_ecc_output_padded[IC_TAG_SIZE-1:0]}; - - // Dataram ECC - for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks - prim_secded_inv_39_32_enc data_ecc_enc ( - .data_i (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]), - .data_o (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC]) - ); - end - - end else begin : gen_noecc_wdata - assign tag_wdata_ic0 = fill_tag_ic0; - assign data_wdata_ic0 = fill_wdata_ic0; - end - - //////////////// - // IC0 -> IC1 // - //////////////// - - // Tag RAMs outputs - assign ic_tag_req_o = {IC_NUM_WAYS{tag_req_ic0}} & tag_banks_ic0; - assign ic_tag_write_o = tag_write_ic0; - assign ic_tag_addr_o = tag_index_ic0; - assign ic_tag_wdata_o = tag_wdata_ic0; - - // Tag RAMs inputs - assign tag_rdata_ic1 = ic_tag_rdata_i; - - // Data RAMs outputs - assign ic_data_req_o = {IC_NUM_WAYS{data_req_ic0}} & data_banks_ic0; - assign ic_data_write_o = data_write_ic0; - assign ic_data_addr_o = data_index_ic0; - assign ic_data_wdata_o = data_wdata_ic0; - - // Data RAMs inputs - assign data_rdata_ic1 = ic_data_rdata_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_valid_ic1 <= 1'b0; - end else begin - lookup_valid_ic1 <= lookup_actual_ic0; - end - end - - if (ResetAll) begin : g_lookup_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_addr_ic1 <= '0; - fill_in_ic1 <= '0; - end else if (lookup_grant_ic0) begin - lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:IC_INDEX_HI+1]; - fill_in_ic1 <= fill_alloc_sel; - end - end - end else begin : g_lookup_addr_nr - always_ff @(posedge clk_i) begin - if (lookup_grant_ic0) begin - lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:IC_INDEX_HI+1]; - fill_in_ic1 <= fill_alloc_sel; - end - end - end - - //////////////////////// - // Pipeline stage IC1 // - //////////////////////// - - // Tag matching - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_match - assign tag_match_ic1[way] = (tag_rdata_ic1[way][IC_TAG_SIZE-1:0] == - {1'b1,lookup_addr_ic1[ADDR_W-1:IC_INDEX_HI+1]}); - assign tag_invalid_ic1[way] = ~tag_rdata_ic1[way][IC_TAG_SIZE-1]; - end - - assign tag_hit_ic1 = |tag_match_ic1; - - // Hit data mux - always_comb begin - hit_data_ecc_ic1 = 'b0; - for (int way = 0; way < IC_NUM_WAYS; way++) begin - if (tag_match_ic1[way]) begin - hit_data_ecc_ic1 |= data_rdata_ic1[way]; - end - end - end - - // Way selection for allocations to the cache (onehot signals) - // 1 first invalid way - // 2 global round-robin (pseudorandom) way - assign lowest_invalid_way_ic1[0] = tag_invalid_ic1[0]; - assign round_robin_way_ic1[0] = round_robin_way_q[IC_NUM_WAYS-1]; - for (genvar way = 1; way < IC_NUM_WAYS; way++) begin : gen_lowest_way - assign lowest_invalid_way_ic1[way] = tag_invalid_ic1[way] & ~|tag_invalid_ic1[way-1:0]; - assign round_robin_way_ic1[way] = round_robin_way_q[way-1]; - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - round_robin_way_q <= {{IC_NUM_WAYS-1{1'b0}}, 1'b1}; - end else if (lookup_valid_ic1) begin - round_robin_way_q <= round_robin_way_ic1; - end - end - - assign sel_way_ic1 = |tag_invalid_ic1 ? lowest_invalid_way_ic1 : - round_robin_way_q; - - // ECC checking logic - if (ICacheECC) begin : gen_data_ecc_checking - // SEC_CM: ICACHE.MEM.INTEGRITY - logic [IC_NUM_WAYS-1:0] tag_err_ic1; - logic [IC_LINE_BEATS*2-1:0] data_err_ic1; - logic ecc_correction_write_d, ecc_correction_write_q; - logic [IC_NUM_WAYS-1:0] ecc_correction_ways_d, ecc_correction_ways_q; - logic [IC_INDEX_W-1:0] lookup_index_ic1, ecc_correction_index_q; - - // Tag ECC checking - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_ecc - logic [1:0] tag_err_bank_ic1; - logic [27:0] tag_rdata_padded_ic1; - - // Expand the tag rdata with extra padding if the tag size is less than the maximum - assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TagSizeECC-1-:6], - {22-IC_TAG_SIZE{1'b0}}, - tag_rdata_ic1[way][IC_TAG_SIZE-1:0]}; - - prim_secded_inv_28_22_dec data_ecc_dec ( - .data_i (tag_rdata_padded_ic1), - .data_o (), - .syndrome_o (), - .err_o (tag_err_bank_ic1) - ); - assign tag_err_ic1[way] = |tag_err_bank_ic1; - end - - // Data ECC checking - // Note - could generate for all ways and mux after - for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks - prim_secded_inv_39_32_dec data_ecc_dec ( - .data_i (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]), - .data_o (), - .syndrome_o (), - .err_o (data_err_ic1[bank*2+:2]) - ); - - assign hit_data_ic1[bank*BUS_SIZE+:BUS_SIZE] = - hit_data_ecc_ic1[bank*BusSizeECC+:BUS_SIZE]; - - end - - // Tag ECC across all ways is always expected to be correct so the check does not need to be - // qualified by hit or tag valid. Initial (invalid with correct ECC) tags are written on reset - // and all further tag writes produce correct ECC. For data ECC no initialisation is done on - // reset so unused data (in particular those ways that don't have a valid tag) may have - // incorrect ECC. We only check data ECC where tags indicate it is valid and we have hit on it. - assign ecc_err_ic1 = lookup_valid_ic1 & (((|data_err_ic1) & tag_hit_ic1) | (|tag_err_ic1)); - - // Error correction - // All ways will be invalidated on a tag error to prevent X-propagation from data_err_ic1 on - // spurious hits. Also prevents the same line being allocated twice when there was a true - // hit and a spurious hit. - assign ecc_correction_ways_d = {IC_NUM_WAYS{|tag_err_ic1}} | - (tag_match_ic1 & {IC_NUM_WAYS{|data_err_ic1}}); - assign ecc_correction_write_d = ecc_err_ic1; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - ecc_correction_write_q <= 1'b0; - end else begin - ecc_correction_write_q <= ecc_correction_write_d; - end - end - - // The index is required in IC1 only when ECC is configured so is registered here - if (ResetAll) begin : g_lookup_ind_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_index_ic1 <= '0; - end else if (lookup_grant_ic0) begin - lookup_index_ic1 <= lookup_addr_ic0[IC_INDEX_HI-:IC_INDEX_W]; - end - end - end else begin : g_lookup_ind_nr - always_ff @(posedge clk_i) begin - if (lookup_grant_ic0) begin - lookup_index_ic1 <= lookup_addr_ic0[IC_INDEX_HI-:IC_INDEX_W]; - end - end - end - - // Store the ways with errors to be invalidated - if (ResetAll) begin : g_ecc_correction_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - ecc_correction_ways_q <= '0; - ecc_correction_index_q <= '0; - end else if (ecc_err_ic1) begin - ecc_correction_ways_q <= ecc_correction_ways_d; - ecc_correction_index_q <= lookup_index_ic1; - end - end - end else begin : g_ecc_correction_nr - always_ff @(posedge clk_i) begin - if (ecc_err_ic1) begin - ecc_correction_ways_q <= ecc_correction_ways_d; - ecc_correction_index_q <= lookup_index_ic1; - end - end - end - - assign ecc_write_req = ecc_correction_write_q; - assign ecc_write_ways = ecc_correction_ways_q; - assign ecc_write_index = ecc_correction_index_q; - - assign ecc_error_o = ecc_err_ic1; - end else begin : gen_no_data_ecc - assign ecc_err_ic1 = 1'b0; - assign ecc_write_req = 1'b0; - assign ecc_write_ways = '0; - assign ecc_write_index = '0; - assign hit_data_ic1 = hit_data_ecc_ic1; - - assign ecc_error_o = 1'b0; - end - - /////////////////////////////// - // Cache allocation decision // - /////////////////////////////// - - if (BranchCache) begin : gen_caching_logic - - // Cache branch target + a number of subsequent lines - localparam int unsigned CACHE_AHEAD = 2; - localparam int unsigned CACHE_CNT_W = (CACHE_AHEAD == 1) ? 1 : $clog2(CACHE_AHEAD) + 1; - logic cache_cnt_dec; - logic [CACHE_CNT_W-1:0] cache_cnt_d, cache_cnt_q; - - assign cache_cnt_dec = lookup_grant_ic0 & (|cache_cnt_q); - assign cache_cnt_d = branch_i ? CACHE_AHEAD[CACHE_CNT_W-1:0] : - (cache_cnt_q - {{CACHE_CNT_W-1{1'b0}},cache_cnt_dec}); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - cache_cnt_q <= '0; - end else begin - cache_cnt_q <= cache_cnt_d; - end - end - - assign fill_cache_new = (branch_i | (|cache_cnt_q)) & icache_enable_i & - ~icache_inval_i & ~inval_lock & ~inval_prog_q; - - end else begin : gen_cache_all - - // Cache all missing fetches - assign fill_cache_new = icache_enable_i & ~start_inval & ~inval_prog_q; - end - - ////////////////////////// - // Fill buffer tracking // - ////////////////////////// - - always_comb begin - fb_fill_level = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_busy_q[i] & ~fill_stale_q[i]) begin - fb_fill_level += {{$clog2(NUM_FB) - 1{1'b0}}, 1'b1}; - end - end - end - - // Allocate a new buffer for every granted lookup - assign fill_new_alloc = lookup_grant_ic0; - // Track whether a speculative external request was made from IC0, and whether it was granted - // Speculative requests are only made for branches, or if the cache is disabled - assign fill_spec_req = (~icache_enable_i | branch_or_mispredict) & ~|fill_ext_req; - assign fill_spec_done = fill_spec_req & instr_gnt_i; - assign fill_spec_hold = fill_spec_req & ~instr_gnt_i; - - for (genvar fb = 0; fb < NUM_FB; fb++) begin : gen_fbs - - ///////////////////////////// - // Fill buffer allocations // - ///////////////////////////// - - // Allocate the lowest available buffer - if (fb == 0) begin : gen_fb_zero - assign fill_alloc_sel[fb] = ~fill_busy_q[fb]; - end else begin : gen_fb_rest - assign fill_alloc_sel[fb] = ~fill_busy_q[fb] & (&fill_busy_q[fb-1:0]); - end - - assign fill_alloc[fb] = fill_alloc_sel[fb] & fill_new_alloc; - assign fill_busy_d[fb] = fill_alloc[fb] | (fill_busy_q[fb] & ~fill_done[fb]); - - // Track which other fill buffers are older than this one (for age-based arbitration) - // TODO sparsify - assign fill_older_d[fb] = (fill_alloc[fb] ? fill_busy_q : fill_older_q[fb]) & ~fill_done; - - // A fill buffer can release once all its actions are completed - // all data written to the cache (unless hit or error) - assign fill_done[fb] = (fill_ram_done_q[fb] | fill_hit_q[fb] | ~fill_cache_q[fb] | - (|fill_err_q[fb])) & - // all data output unless stale due to intervening branch - (fill_out_done[fb] | fill_stale_q[fb] | branch_or_mispredict) & - // all external requests completed - fill_rvd_done[fb]; - - ///////////////////////////////// - // Fill buffer status tracking // - ///////////////////////////////// - - // Track staleness (requests become stale when a branch intervenes) - assign fill_stale_d[fb] = fill_busy_q[fb] & (branch_or_mispredict | fill_stale_q[fb]); - // Track whether or not this request should allocate to the cache - // Any invalidation or disabling of the cache while the buffer is busy will stop allocation - assign fill_cache_d[fb] = (fill_alloc[fb] & fill_cache_new) | - (fill_cache_q[fb] & fill_busy_q[fb] & - icache_enable_i & ~icache_inval_i & ~inval_lock); - // Record whether the request hit in the cache - assign fill_hit_ic1[fb] = lookup_valid_ic1 & fill_in_ic1[fb] & tag_hit_ic1 & ~ecc_err_ic1; - assign fill_hit_d[fb] = fill_hit_ic1[fb] | (fill_hit_q[fb] & fill_busy_q[fb]); - - /////////////////////////////////////////// - // Fill buffer external request tracking // - /////////////////////////////////////////// - - // Make an external request - assign fill_ext_req[fb] = fill_busy_q[fb] & ~fill_ext_done_d[fb]; - - // Count the number of completed external requests (each line requires IC_LINE_BEATS requests) - assign fill_ext_cnt_d[fb] = fill_alloc[fb] ? - {{IC_LINE_BEATS_W{1'b0}},fill_spec_done} : - (fill_ext_cnt_q[fb] + {{IC_LINE_BEATS_W{1'b0}}, - fill_ext_arb[fb] & instr_gnt_i}); - // External request must be held until granted - assign fill_ext_hold_d[fb] = (fill_alloc[fb] & fill_spec_hold) | - (fill_ext_arb[fb] & ~instr_gnt_i); - // External requests are completed when the counter is filled or when the request is cancelled - assign fill_ext_done_d[fb] = (fill_ext_cnt_q[fb][IC_LINE_BEATS_W] | - // external requests are considered complete if the request hit - fill_hit_ic1[fb] | fill_hit_q[fb] | - // cancel if the line won't be cached and, it is stale - (~fill_cache_q[fb] & (branch_or_mispredict | fill_stale_q[fb] | - // or we're already at the end of the line - fill_ext_beat[fb][IC_LINE_BEATS_W]))) & - // can't cancel while we are waiting for a grant on the bus - ~fill_ext_hold_q[fb] & fill_busy_q[fb]; - // Track whether this fill buffer expects to receive beats of data - assign fill_rvd_exp[fb] = fill_busy_q[fb] & ~fill_rvd_done[fb]; - // Count the number of rvalid beats received - assign fill_rvd_cnt_d[fb] = fill_alloc[fb] ? '0 : - (fill_rvd_cnt_q[fb] + - {{IC_LINE_BEATS_W{1'b0}},fill_rvd_arb[fb]}); - // External data is complete when all issued external requests have received their data - assign fill_rvd_done[fb] = (fill_ext_done_q[fb] & ~fill_ext_hold_q[fb]) & - (fill_rvd_cnt_q[fb] == fill_ext_cnt_q[fb]); - - ////////////////////////////////////// - // Fill buffer data output tracking // - ////////////////////////////////////// - - // Send data to the IF stage for requests that are not stale, have not completed their - // data output, and have data available to send. - // Data is available if: - // - The request hit in the cache - // - Buffered data is available (fill_rvd_cnt_q is ahead of fill_out_cnt_q) - // - Data is available from the bus this cycle (fill_rvd_arb) - assign fill_out_req[fb] = fill_busy_q[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] & - (fill_hit_ic1[fb] | fill_hit_q[fb] | - (fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_rvd_arb[fb]); - - // Calculate when a beat of data is output. Any ECC error squashes the output that cycle. - assign fill_out_grant[fb] = fill_out_arb[fb] & output_ready; - - // Count the beats of data output to the IF stage - assign fill_out_cnt_d[fb] = fill_alloc[fb] ? {1'b0,lookup_addr_ic0[IC_LINE_W-1:BUS_W]} : - (fill_out_cnt_q[fb] + - {{IC_LINE_BEATS_W{1'b0}},fill_out_grant[fb]}); - // Data output complete when the counter fills - assign fill_out_done[fb] = fill_out_cnt_q[fb][IC_LINE_BEATS_W]; - - ////////////////////////////////////// - // Fill buffer ram request tracking // - ////////////////////////////////////// - - // make a fill request once all data beats received - assign fill_ram_req[fb] = fill_busy_q[fb] & fill_rvd_cnt_q[fb][IC_LINE_BEATS_W] & - // unless the request hit, was non-allocating or got an error - ~fill_hit_q[fb] & fill_cache_q[fb] & ~|fill_err_q[fb] & - // or the request was already completed - ~fill_ram_done_q[fb]; - - // Record when a cache allocation request has been completed - assign fill_ram_done_d[fb] = fill_ram_arb[fb] | (fill_ram_done_q[fb] & fill_busy_q[fb]); - - ////////////////////////////// - // Fill buffer line offsets // - ////////////////////////////// - - // When we branch into the middle of a line, the output count will not start from zero. This - // beat count is used to know which incoming rdata beats are relevant. - assign fill_ext_beat[fb] = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} + - fill_ext_cnt_q[fb][IC_LINE_BEATS_W:0]; - assign fill_ext_off[fb] = fill_ext_beat[fb][IC_LINE_BEATS_W-1:0]; - assign fill_rvd_beat[fb] = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} + - fill_rvd_cnt_q[fb][IC_LINE_BEATS_W:0]; - assign fill_rvd_off[fb] = fill_rvd_beat[fb][IC_LINE_BEATS_W-1:0]; - - ///////////////////////////// - // Fill buffer arbitration // - ///////////////////////////// - - // Age based arbitration - all these signals are one-hot - assign fill_ext_arb[fb] = fill_ext_req[fb] & ~|(fill_ext_req & fill_older_q[fb]); - assign fill_ram_arb[fb] = fill_ram_req[fb] & fill_grant_ic0 & - ~|(fill_ram_req & fill_older_q[fb]); - // Calculate which fill buffer is the oldest one which still needs to output data to IF - assign fill_data_sel[fb] = ~|(fill_busy_q & ~fill_out_done & ~fill_stale_q & - fill_older_q[fb]); - // Arbitrate the request which has data available to send, and is the oldest outstanding - assign fill_out_arb[fb] = fill_out_req[fb] & fill_data_sel[fb]; - // Assign incoming rvalid data to the oldest fill buffer expecting it - assign fill_rvd_arb[fb] = instr_rvalid_i & fill_rvd_exp[fb] & - ~|(fill_rvd_exp & fill_older_q[fb]); - - ///////////////////////////// - // Fill buffer data muxing // - ///////////////////////////// - - // Output data muxing controls - // 1. Select data from the fill buffer data register - assign fill_data_reg[fb] = fill_busy_q[fb] & ~fill_stale_q[fb] & - ~fill_out_done[fb] & fill_data_sel[fb] & - // The incoming data is already ahead of the output count - ((fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_hit_q[fb] | - (|fill_err_q[fb])); - // 2. Select IC1 hit data - assign fill_data_hit[fb] = fill_busy_q[fb] & fill_hit_ic1[fb] & fill_data_sel[fb]; - // 3. Select incoming instr_rdata_i - assign fill_data_rvd[fb] = fill_busy_q[fb] & fill_rvd_arb[fb] & ~fill_hit_q[fb] & - ~fill_hit_ic1[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] & - // The incoming data lines up with the output count - (fill_rvd_beat[fb] == fill_out_cnt_q[fb]) & fill_data_sel[fb]; - - - /////////////////////////// - // Fill buffer registers // - /////////////////////////// - - // Fill buffer general enable - assign fill_entry_en[fb] = fill_alloc[fb] | fill_busy_q[fb]; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_busy_q[fb] <= 1'b0; - fill_older_q[fb] <= '0; - fill_stale_q[fb] <= 1'b0; - fill_cache_q[fb] <= 1'b0; - fill_hit_q[fb] <= 1'b0; - fill_ext_cnt_q[fb] <= '0; - fill_ext_hold_q[fb] <= 1'b0; - fill_ext_done_q[fb] <= 1'b0; - fill_rvd_cnt_q[fb] <= '0; - fill_ram_done_q[fb] <= 1'b0; - fill_out_cnt_q[fb] <= '0; - end else if (fill_entry_en[fb]) begin - fill_busy_q[fb] <= fill_busy_d[fb]; - fill_older_q[fb] <= fill_older_d[fb]; - fill_stale_q[fb] <= fill_stale_d[fb]; - fill_cache_q[fb] <= fill_cache_d[fb]; - fill_hit_q[fb] <= fill_hit_d[fb]; - fill_ext_cnt_q[fb] <= fill_ext_cnt_d[fb]; - fill_ext_hold_q[fb] <= fill_ext_hold_d[fb]; - fill_ext_done_q[fb] <= fill_ext_done_d[fb]; - fill_rvd_cnt_q[fb] <= fill_rvd_cnt_d[fb]; - fill_ram_done_q[fb] <= fill_ram_done_d[fb]; - fill_out_cnt_q[fb] <= fill_out_cnt_d[fb]; - end - end - - //////////////////////////////////////// - // Fill buffer address / data storage // - //////////////////////////////////////// - - assign fill_addr_en[fb] = fill_alloc[fb]; - assign fill_way_en[fb] = (lookup_valid_ic1 & fill_in_ic1[fb]); - - if (ResetAll) begin : g_fill_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_addr_q[fb] <= '0; - end else if (fill_addr_en[fb]) begin - fill_addr_q[fb] <= lookup_addr_ic0; - end - end - end else begin : g_fill_addr_nr - always_ff @(posedge clk_i) begin - if (fill_addr_en[fb]) begin - fill_addr_q[fb] <= lookup_addr_ic0; - end - end - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_way_q[fb] <= '0; - end else if (fill_way_en[fb]) begin - fill_way_q[fb] <= sel_way_ic1; - end - end - - // Data either comes from the cache or the bus. If there was an ECC error, we must take - // the incoming bus data since the cache hit data is corrupted. - assign fill_data_d[fb] = fill_hit_ic1[fb] ? hit_data_ic1 : - {IC_LINE_BEATS{instr_rdata_i}}; - - for (genvar b = 0; b < IC_LINE_BEATS; b++) begin : gen_data_buf - // Error tracking (per beat) - assign fill_err_d[fb][b] = (fill_rvd_arb[fb] & instr_err_i & - (fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])) | - // Hold the error once recorded - (fill_busy_q[fb] & fill_err_q[fb][b]); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_err_q[fb][b] <= '0; - end else if (fill_entry_en[fb]) begin - fill_err_q[fb][b] <= fill_err_d[fb][b]; - end - end - - // Enable the relevant part of the data register (or all for cache hits) - // Ignore incoming rvalid data when we already have cache hit data - assign fill_data_en[fb][b] = fill_hit_ic1[fb] | - (fill_rvd_arb[fb] & ~fill_hit_q[fb] & - (fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])); - - if (ResetAll) begin : g_fill_data_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= '0; - end else if (fill_data_en[fb][b]) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE]; - end - end - end else begin : g_fill_data_nr - always_ff @(posedge clk_i) begin - if (fill_data_en[fb][b]) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE]; - end - end - end - - end - end - - //////////////////////////////// - // Fill buffer one-hot muxing // - //////////////////////////////// - - // External req info - always_comb begin - fill_ext_req_addr = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_ext_arb[i]) begin - fill_ext_req_addr |= {fill_addr_q[i][ADDR_W-1:IC_LINE_W], fill_ext_off[i]}; - end - end - end - - // Cache req info - always_comb begin - fill_ram_req_addr = '0; - fill_ram_req_way = '0; - fill_ram_req_data = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_ram_arb[i]) begin - fill_ram_req_addr |= fill_addr_q[i]; - fill_ram_req_way |= fill_way_q[i]; - fill_ram_req_data |= fill_data_q[i]; - end - end - end - - // IF stage output data - always_comb begin - fill_out_data = '0; - fill_out_err = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_data_reg[i]) begin - fill_out_data |= fill_data_q[i]; - // Ignore any speculative errors accumulated on cache hits - fill_out_err |= (fill_err_q[i] & ~{IC_LINE_BEATS{fill_hit_q[i]}}); - end - end - end - - /////////////////////// - // External requests // - /////////////////////// - - assign instr_req = ((~icache_enable_i | branch_or_mispredict) & lookup_grant_ic0) | - (|fill_ext_req); - - assign instr_addr = |fill_ext_req ? fill_ext_req_addr : - lookup_addr_ic0[ADDR_W-1:BUS_W]; - - assign instr_req_o = instr_req; - assign instr_addr_o = {instr_addr[ADDR_W-1:BUS_W],{BUS_W{1'b0}}}; - - //////////////////////// - // Output data muxing // - //////////////////////// - - // Mux between line-width data sources - assign line_data = |fill_data_hit ? hit_data_ic1 : fill_out_data; - assign line_err = |fill_data_hit ? {IC_LINE_BEATS{1'b0}} : fill_out_err; - - // Mux the relevant beat of line data, based on the output address - always_comb begin - line_data_muxed = '0; - line_err_muxed = 1'b0; - for (int unsigned i = 0; i < IC_LINE_BEATS; i++) begin - // When data has been skidded, the output address is behind by one - if ((output_addr_q[IC_LINE_W-1:BUS_W] + {{IC_LINE_BEATS_W-1{1'b0}},skid_valid_q}) == - i[IC_LINE_BEATS_W-1:0]) begin - line_data_muxed |= line_data[i*32+:32]; - line_err_muxed |= line_err[i]; - end - end - end - - // Mux between incoming rdata and the muxed line data - assign output_data = |fill_data_rvd ? instr_rdata_i : line_data_muxed; - assign output_err = |fill_data_rvd ? instr_err_i : line_err_muxed; - - // Output data is valid (from any of the three possible sources). Note that fill_out_arb - // must be used here rather than fill_out_req because data can become valid out of order - // (e.g. cache hit data can become available ahead of an older outstanding miss). - assign data_valid = |fill_out_arb; - - // Skid buffer data - assign skid_data_d = output_data[31:16]; - - assign skid_en = data_valid & (ready_i | skid_ready); - - if (ResetAll) begin : g_skid_data_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - skid_data_q <= '0; - skid_err_q <= '0; - end else if (skid_en) begin - skid_data_q <= skid_data_d; - skid_err_q <= output_err; - end - end - end else begin : g_skid_data_nr - always_ff @(posedge clk_i) begin - if (skid_en) begin - skid_data_q <= skid_data_d; - skid_err_q <= output_err; - end - end - end - - // The data in the skid buffer is ready if it's a complete compressed instruction or if there's - // an error (no need to wait for the second half) - assign skid_complete_instr = skid_valid_q & ((skid_data_q[1:0] != 2'b11) | skid_err_q); - - // Data can be loaded into the skid buffer for an unaligned uncompressed instruction - assign skid_ready = output_addr_q[1] & ~skid_valid_q & (~output_compressed | output_err); - - assign output_ready = (ready_i | skid_ready) & ~skid_complete_instr; - - assign output_compressed = (rdata_o[1:0] != 2'b11); - - assign skid_valid_d = - // Branches invalidate the skid buffer - branch_or_mispredict ? 1'b0 : - // Once valid, the skid buffer stays valid until a compressed instruction realigns the stream - (skid_valid_q ? ~(ready_i & ((skid_data_q[1:0] != 2'b11) | skid_err_q)) : - // The skid buffer becomes valid when: - // - we branch to an unaligned uncompressed instruction - (data_valid & - (((output_addr_q[1] & (~output_compressed | output_err)) | - // - a compressed instruction misaligns the stream - (~output_addr_q[1] & output_compressed & ~output_err & ready_i))))); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - skid_valid_q <= 1'b0; - end else begin - skid_valid_q <= skid_valid_d; - end - end - - // Signal that valid data is available to the IF stage - // Note that if the first half of an unaligned instruction reports an error, we do not need - // to wait for the second half - // Compressed instruction completely satisfied by skid buffer - assign output_valid = skid_complete_instr | - // Output data available and, output stream aligned, or skid data available, - (data_valid & (~output_addr_q[1] | skid_valid_q | - // or this is an error or an unaligned compressed instruction - output_err | (output_data[17:16] != 2'b11))); - - // Update the address on branches and every time an instruction is driven - assign output_addr_en = branch_or_mispredict | (ready_i & valid_o); - - // Increment the address by two every time a compressed instruction is popped - assign addr_incr_two = output_compressed & ~err_o; - - // Next IF stage PC - assign output_addr_incr = (output_addr_q[31:1] + - // Increment address by 4 or 2 - {29'd0, ~addr_incr_two, addr_incr_two}); - - // Redirect the address on branches or mispredicts - assign output_addr_d = branch_i ? addr_i[31:1] : - branch_mispredict_i ? mispredict_addr_i[31:1] : - output_addr_incr; - - if (ResetAll) begin : g_output_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - output_addr_q <= '0; - end else if (output_addr_en) begin - output_addr_q <= output_addr_d; - end - end - end else begin : g_output_addr_nr - always_ff @(posedge clk_i) begin - if (output_addr_en) begin - output_addr_q <= output_addr_d; - end - end - end - - // Mux the data from BUS_SIZE to halfword - // This muxing realigns data when instruction words are split across BUS_W e.g. - // word 1 |----|*h1*| - // word 0 |*h0*|----| --> |*h1*|*h0*| - // 31 15 0 31 15 0 - always_comb begin - output_data_lo = '0; - for (int unsigned i = 0; i < IC_OUTPUT_BEATS; i++) begin - if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin - output_data_lo |= output_data[i*16+:16]; - end - end - end - - always_comb begin - output_data_hi = '0; - for (int unsigned i = 0; i < IC_OUTPUT_BEATS - 1; i++) begin - if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin - output_data_hi |= output_data[(i+1)*16+:16]; - end - end - if (&output_addr_q[BUS_W-1:1]) begin - output_data_hi |= output_data[15:0]; - end - end - - assign valid_o = output_valid & ~branch_mispredict_i; - assign rdata_o = {output_data_hi, (skid_valid_q ? skid_data_q : output_data_lo)}; - assign addr_o = {output_addr_q, 1'b0}; - assign err_o = (skid_valid_q & skid_err_q) | (~skid_complete_instr & output_err); - // Error caused by the second half of a misaligned uncompressed instruction - // (only relevant when err_o is set) - assign err_plus2_o = skid_valid_q & ~skid_err_q; - - /////////////////// - // Invalidations // - /////////////////// - - - // We need to save the invalidation request inside a register. That way we can wait - // until we have a valid scrambling key to do it. Since the key itself is needed for - // starting to fill in the RAMs and read from them, ICache also needs to stop operating. - assign inval_req_d = (inval_req_q | icache_inval_i) & ~(inval_done & inval_prog_q); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_req_q <= 1'b0; - end else begin - inval_req_q <= inval_req_d; - end - end - - // This will act like a lock mechanism. - // Main idea is to lock the invalidation request until we got a valid scrambling key. - assign inval_lock = inval_req_d & ~ic_scr_key_valid_i; - - // Invalidate on reset, or when instructed. If an invalidation request is received while a - // previous invalidation is ongoing, it does not need to be restarted. Do not start - // this process until inval lock is removed meaning the scrambling key is valid. - assign start_inval = ~inval_lock & (~reset_inval_q | inval_req_q) & ~inval_prog_q ; - assign inval_prog_d = ~inval_lock & (start_inval | (inval_prog_q & ~inval_done)); - assign inval_done = &inval_index_q; - assign inval_index_d = start_inval ? '0 : (inval_index_q + {{IC_INDEX_W-1{1'b0}},1'b1}); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_prog_q <= 1'b0; - reset_inval_q <= 1'b0; - end else begin - inval_prog_q <= inval_prog_d; - reset_inval_q <= 1'b1; - end - end - - if (ResetAll) begin : g_inval_index_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_index_q <= '0; - end else if (inval_prog_d) begin - inval_index_q <= inval_index_d; - end - end - end else begin : g_inval_index_nr - always_ff @(posedge clk_i) begin - if (inval_prog_d) begin - inval_index_q <= inval_index_d; - end - end - end - - ///////////////// - // Busy status // - ///////////////// - - // Only busy (for WFI purposes) while an invalidation is in-progress, or external requests are - // outstanding. - assign busy_o = inval_req_q | (|(fill_busy_q & ~fill_rvd_done)); - - //////////////// - // Assertions // - //////////////// - - `ASSERT_INIT(size_param_legal, (IC_LINE_SIZE > 32)) - - // ECC primitives will need to be changed for different sizes - `ASSERT_INIT(ecc_tag_param_legal, (IC_TAG_SIZE <= 27)) - `ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_SIZE == 32)) - - // Lookups in the tag ram should always give a known result - `ASSERT_KNOWN(TagHitKnown, lookup_valid_ic1 & tag_hit_ic1) - `ASSERT_KNOWN(TagInvalidKnown, lookup_valid_ic1 & tag_invalid_ic1) - - // This is only used for the Yosys-based formal flow. Once we have working bind support, we can - // get rid of it. -`ifdef FORMAL - `ifdef YOSYS - // Unfortunately, Yosys doesn't support passing unpacked arrays as ports. Explicitly pack up the - // signals we need. - logic [NUM_FB-1:0][ADDR_W-1:0] packed_fill_addr_q; - always_comb begin - for (int i = 0; i < NUM_FB; i++) begin - packed_fill_addr_q[i][ADDR_W-1:0] = fill_addr_q[i]; - end - end - - `include "formal_tb_frag.svh" - `endif -`endif - - -endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv b/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv deleted file mode 100644 index 4f986d0cd..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv +++ /dev/null @@ -1,491 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -// Ibex lockstep module -// This module instantiates a second copy of the core logic, and compares it's outputs against -// those from the main core. The second core runs synchronously with the main core, delayed by -// LockstepOffset cycles. - -// SEC_CM: LOGIC.SHADOW -module ibex_lockstep import ibex_pkg::*; #( - parameter int unsigned LockstepOffset = 2, - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, - parameter int unsigned MHPMCounterNum = 0, - parameter int unsigned MHPMCounterWidth = 40, - parameter bit RV32E = 1'b0, - parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter bit SecureIbex = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit RegFileECC = 1'b0, - parameter int unsigned RegFileDataWidth = 32, - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808 -) ( - input logic clk_i, - input logic rst_ni, - - input logic [31:0] hart_id_i, - input logic [31:0] boot_addr_i, - - input logic instr_req_i, - input logic instr_gnt_i, - input logic instr_rvalid_i, - input logic [31:0] instr_addr_i, - input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, - input logic instr_err_i, - - input logic data_req_i, - input logic data_gnt_i, - input logic data_rvalid_i, - input logic data_we_i, - input logic [3:0] data_be_i, - input logic [31:0] data_addr_i, - input logic [31:0] data_wdata_i, - output logic [6:0] data_wdata_intg_o, - input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, - input logic data_err_i, - - input logic dummy_instr_id_i, - input logic [4:0] rf_raddr_a_i, - input logic [4:0] rf_raddr_b_i, - input logic [4:0] rf_waddr_wb_i, - input logic rf_we_wb_i, - input logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i, - - input logic [IC_NUM_WAYS-1:0] ic_tag_req_i, - input logic ic_tag_write_i, - input logic [IC_INDEX_W-1:0] ic_tag_addr_i, - input logic [TagSizeECC-1:0] ic_tag_wdata_i, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - input logic [IC_NUM_WAYS-1:0] ic_data_req_i, - input logic ic_data_write_i, - input logic [IC_INDEX_W-1:0] ic_data_addr_i, - input logic [LineSizeECC-1:0] ic_data_wdata_i, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - - input logic irq_software_i, - input logic irq_timer_i, - input logic irq_external_i, - input logic [14:0] irq_fast_i, - input logic irq_nm_i, - input logic irq_pending_i, - - input logic debug_req_i, - input crash_dump_t crash_dump_i, - input logic double_fault_seen_i, - - input fetch_enable_t fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, - input logic icache_inval_i, - input logic core_busy_i, - input logic test_en_i, - input logic scan_rst_ni -); - - localparam int unsigned LockstepOffsetW = $clog2(LockstepOffset); - // Core outputs are delayed for an extra cycle due to shadow output registers - localparam int unsigned OutputsOffset = LockstepOffset + 1; - - ////////////////////// - // Reset generation // - ////////////////////// - - // Upon reset, the comparison is stopped and the shadow core is reset, both immediately. A - // counter is started. After LockstepOffset clock cycles: - // - The counter is stopped. - // - The reset of the shadow core is synchronously released. - // The comparison is started in the following clock cycle. - - logic [LockstepOffsetW-1:0] rst_shadow_cnt_d, rst_shadow_cnt_q, rst_shadow_cnt_incr; - // Internally generated resets cause IMPERFECTSCH warnings - /* verilator lint_off IMPERFECTSCH */ - logic rst_shadow_set_d, rst_shadow_set_q; - logic rst_shadow_n, enable_cmp_q; - /* verilator lint_on IMPERFECTSCH */ - - assign rst_shadow_cnt_incr = rst_shadow_cnt_q + LockstepOffsetW'(1); - - assign rst_shadow_set_d = (rst_shadow_cnt_q == LockstepOffsetW'(LockstepOffset - 1)); - assign rst_shadow_cnt_d = rst_shadow_set_d ? rst_shadow_cnt_q : rst_shadow_cnt_incr; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rst_shadow_cnt_q <= '0; - enable_cmp_q <= '0; - end else begin - rst_shadow_cnt_q <= rst_shadow_cnt_d; - enable_cmp_q <= rst_shadow_set_q; - end - end - - // The primitives below are used to place size-only constraints in order to prevent - // synthesis optimizations and preserve anchor points for constraining backend tools. - prim_flop #( - .Width(1), - .ResetValue(1'b0) - ) u_prim_rst_shadow_set_flop ( - .clk_i (clk_i), - .rst_ni(rst_ni), - .d_i (rst_shadow_set_d), - .q_o (rst_shadow_set_q) - ); - - prim_clock_mux2 #( - .NoFpgaBufG(1'b1) - ) u_prim_rst_shadow_n_mux2 ( - .clk0_i(rst_shadow_set_q), - .clk1_i(scan_rst_ni), - .sel_i (test_en_i), - .clk_o (rst_shadow_n) - ); - - ////////////////// - // Input delays // - ////////////////// - - typedef struct packed { - logic instr_gnt; - logic instr_rvalid; - logic [31:0] instr_rdata; - logic instr_err; - logic data_gnt; - logic data_rvalid; - logic [31:0] data_rdata; - logic data_err; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc; - logic irq_software; - logic irq_timer; - logic irq_external; - logic [14:0] irq_fast; - logic irq_nm; - logic debug_req; - fetch_enable_t fetch_enable; - logic ic_scr_key_valid; - } delayed_inputs_t; - - delayed_inputs_t [LockstepOffset-1:0] shadow_inputs_q; - delayed_inputs_t shadow_inputs_in; - logic [6:0] instr_rdata_intg_q, data_rdata_intg_q; - // Packed arrays must be dealt with separately - logic [TagSizeECC-1:0] shadow_tag_rdata_q [IC_NUM_WAYS][LockstepOffset]; - logic [LineSizeECC-1:0] shadow_data_rdata_q [IC_NUM_WAYS][LockstepOffset]; - - // Assign the inputs to the delay structure - assign shadow_inputs_in.instr_gnt = instr_gnt_i; - assign shadow_inputs_in.instr_rvalid = instr_rvalid_i; - assign shadow_inputs_in.instr_rdata = instr_rdata_i; - assign shadow_inputs_in.instr_err = instr_err_i; - assign shadow_inputs_in.data_gnt = data_gnt_i; - assign shadow_inputs_in.data_rvalid = data_rvalid_i; - assign shadow_inputs_in.data_rdata = data_rdata_i; - assign shadow_inputs_in.data_err = data_err_i; - assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i; - assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i; - assign shadow_inputs_in.irq_software = irq_software_i; - assign shadow_inputs_in.irq_timer = irq_timer_i; - assign shadow_inputs_in.irq_external = irq_external_i; - assign shadow_inputs_in.irq_fast = irq_fast_i; - assign shadow_inputs_in.irq_nm = irq_nm_i; - assign shadow_inputs_in.debug_req = debug_req_i; - assign shadow_inputs_in.fetch_enable = fetch_enable_i; - assign shadow_inputs_in.ic_scr_key_valid = ic_scr_key_valid_i; - - // Delay the inputs - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_rdata_intg_q <= '0; - data_rdata_intg_q <= '0; - for (int unsigned i = 0; i < LockstepOffset; i++) begin - shadow_inputs_q[i] <= delayed_inputs_t'('0); - shadow_tag_rdata_q[i] <= '{default: 0}; - shadow_data_rdata_q[i] <= '{default: 0}; - end - end else begin - instr_rdata_intg_q <= instr_rdata_intg_i; - data_rdata_intg_q <= data_rdata_intg_i; - for (int unsigned i = 0; i < LockstepOffset - 1; i++) begin - shadow_inputs_q[i] <= shadow_inputs_q[i+1]; - shadow_tag_rdata_q[i] <= shadow_tag_rdata_q[i+1]; - shadow_data_rdata_q[i] <= shadow_data_rdata_q[i+1]; - end - shadow_inputs_q[LockstepOffset-1] <= shadow_inputs_in; - shadow_tag_rdata_q[LockstepOffset-1] <= ic_tag_rdata_i; - shadow_data_rdata_q[LockstepOffset-1] <= ic_data_rdata_i; - end - end - - //////////////////////////// - // Bus integrity checking // - //////////////////////////// - - // SEC_CM: BUS.INTEGRITY - logic bus_intg_err; - logic [1:0] instr_intg_err, data_intg_err; - logic [31:0] unused_wdata; - - // Checks on incoming data - prim_secded_inv_39_32_dec u_instr_intg_dec ( - .data_i ({instr_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].instr_rdata}), - .data_o (), - .syndrome_o (), - .err_o (instr_intg_err) - ); - - prim_secded_inv_39_32_dec u_data_intg_dec ( - .data_i ({data_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].data_rdata}), - .data_o (), - .syndrome_o (), - .err_o (data_intg_err) - ); - - assign bus_intg_err = (shadow_inputs_q[LockstepOffset-1].instr_rvalid & |instr_intg_err) | - (shadow_inputs_q[LockstepOffset-1].data_rvalid & |data_intg_err); - - // Generate integrity bits - prim_secded_inv_39_32_enc u_data_gen ( - .data_i (data_wdata_i), - .data_o ({data_wdata_intg_o, unused_wdata}) - ); - - /////////////////// - // Output delays // - /////////////////// - - typedef struct packed { - logic instr_req; - logic [31:0] instr_addr; - logic data_req; - logic data_we; - logic [3:0] data_be; - logic [31:0] data_addr; - logic [31:0] data_wdata; - logic dummy_instr_id; - logic [4:0] rf_raddr_a; - logic [4:0] rf_raddr_b; - logic [4:0] rf_waddr_wb; - logic rf_we_wb; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [IC_NUM_WAYS-1:0] ic_tag_req; - logic ic_tag_write; - logic [IC_INDEX_W-1:0] ic_tag_addr; - logic [TagSizeECC-1:0] ic_tag_wdata; - logic [IC_NUM_WAYS-1:0] ic_data_req; - logic ic_data_write; - logic [IC_INDEX_W-1:0] ic_data_addr; - logic [LineSizeECC-1:0] ic_data_wdata; - logic irq_pending; - crash_dump_t crash_dump; - logic double_fault_seen; - logic icache_inval; - logic core_busy; - } delayed_outputs_t; - - delayed_outputs_t [OutputsOffset-1:0] core_outputs_q; - delayed_outputs_t core_outputs_in; - delayed_outputs_t shadow_outputs_d, shadow_outputs_q; - - // Assign core outputs to the structure - assign core_outputs_in.instr_req = instr_req_i; - assign core_outputs_in.instr_addr = instr_addr_i; - assign core_outputs_in.data_req = data_req_i; - assign core_outputs_in.data_we = data_we_i; - assign core_outputs_in.data_be = data_be_i; - assign core_outputs_in.data_addr = data_addr_i; - assign core_outputs_in.data_wdata = data_wdata_i; - assign core_outputs_in.dummy_instr_id = dummy_instr_id_i; - assign core_outputs_in.rf_raddr_a = rf_raddr_a_i; - assign core_outputs_in.rf_raddr_b = rf_raddr_b_i; - assign core_outputs_in.rf_waddr_wb = rf_waddr_wb_i; - assign core_outputs_in.rf_we_wb = rf_we_wb_i; - assign core_outputs_in.rf_wdata_wb_ecc = rf_wdata_wb_ecc_i; - assign core_outputs_in.ic_tag_req = ic_tag_req_i; - assign core_outputs_in.ic_tag_write = ic_tag_write_i; - assign core_outputs_in.ic_tag_addr = ic_tag_addr_i; - assign core_outputs_in.ic_tag_wdata = ic_tag_wdata_i; - assign core_outputs_in.ic_data_req = ic_data_req_i; - assign core_outputs_in.ic_data_write = ic_data_write_i; - assign core_outputs_in.ic_data_addr = ic_data_addr_i; - assign core_outputs_in.ic_data_wdata = ic_data_wdata_i; - assign core_outputs_in.irq_pending = irq_pending_i; - assign core_outputs_in.crash_dump = crash_dump_i; - assign core_outputs_in.double_fault_seen = double_fault_seen_i; - assign core_outputs_in.icache_inval = icache_inval_i; - assign core_outputs_in.core_busy = core_busy_i; - - // Delay the outputs - always_ff @(posedge clk_i) begin - for (int unsigned i = 0; i < OutputsOffset - 1; i++) begin - core_outputs_q[i] <= core_outputs_q[i+1]; - end - core_outputs_q[OutputsOffset-1] <= core_outputs_in; - end - - /////////////////////////////// - // Shadow core instantiation // - /////////////////////////////// - - logic shadow_alert_minor, shadow_alert_major; - - ibex_core #( - .PMPEnable ( PMPEnable ), - .PMPGranularity ( PMPGranularity ), - .PMPNumRegions ( PMPNumRegions ), - .MHPMCounterNum ( MHPMCounterNum ), - .MHPMCounterWidth ( MHPMCounterWidth ), - .RV32E ( RV32E ), - .RV32M ( RV32M ), - .RV32B ( RV32B ), - .BranchTargetALU ( BranchTargetALU ), - .ICache ( ICache ), - .ICacheECC ( ICacheECC ), - .BusSizeECC ( BusSizeECC ), - .TagSizeECC ( TagSizeECC ), - .LineSizeECC ( LineSizeECC ), - .BranchPredictor ( BranchPredictor ), - .DbgTriggerEn ( DbgTriggerEn ), - .DbgHwBreakNum ( DbgHwBreakNum ), - .WritebackStage ( WritebackStage ), - .ResetAll ( ResetAll ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), - .SecureIbex ( SecureIbex ), - .DummyInstructions ( DummyInstructions ), - .RegFileECC ( RegFileECC ), - .RegFileDataWidth ( RegFileDataWidth ), - .DmHaltAddr ( DmHaltAddr ), - .DmExceptionAddr ( DmExceptionAddr ) - ) u_shadow_core ( - .clk_i (clk_i), - .rst_ni (rst_shadow_n), - - .hart_id_i (hart_id_i), - .boot_addr_i (boot_addr_i), - - .instr_req_o (shadow_outputs_d.instr_req), - .instr_gnt_i (shadow_inputs_q[0].instr_gnt), - .instr_rvalid_i (shadow_inputs_q[0].instr_rvalid), - .instr_addr_o (shadow_outputs_d.instr_addr), - .instr_rdata_i (shadow_inputs_q[0].instr_rdata), - .instr_err_i (shadow_inputs_q[0].instr_err), - - .data_req_o (shadow_outputs_d.data_req), - .data_gnt_i (shadow_inputs_q[0].data_gnt), - .data_rvalid_i (shadow_inputs_q[0].data_rvalid), - .data_we_o (shadow_outputs_d.data_we), - .data_be_o (shadow_outputs_d.data_be), - .data_addr_o (shadow_outputs_d.data_addr), - .data_wdata_o (shadow_outputs_d.data_wdata), - .data_rdata_i (shadow_inputs_q[0].data_rdata), - .data_err_i (shadow_inputs_q[0].data_err), - - .dummy_instr_id_o (shadow_outputs_d.dummy_instr_id), - .rf_raddr_a_o (shadow_outputs_d.rf_raddr_a), - .rf_raddr_b_o (shadow_outputs_d.rf_raddr_b), - .rf_waddr_wb_o (shadow_outputs_d.rf_waddr_wb), - .rf_we_wb_o (shadow_outputs_d.rf_we_wb), - .rf_wdata_wb_ecc_o (shadow_outputs_d.rf_wdata_wb_ecc), - .rf_rdata_a_ecc_i (shadow_inputs_q[0].rf_rdata_a_ecc), - .rf_rdata_b_ecc_i (shadow_inputs_q[0].rf_rdata_b_ecc), - - .ic_tag_req_o (shadow_outputs_d.ic_tag_req), - .ic_tag_write_o (shadow_outputs_d.ic_tag_write), - .ic_tag_addr_o (shadow_outputs_d.ic_tag_addr), - .ic_tag_wdata_o (shadow_outputs_d.ic_tag_wdata), - .ic_tag_rdata_i (shadow_tag_rdata_q[0]), - .ic_data_req_o (shadow_outputs_d.ic_data_req), - .ic_data_write_o (shadow_outputs_d.ic_data_write), - .ic_data_addr_o (shadow_outputs_d.ic_data_addr), - .ic_data_wdata_o (shadow_outputs_d.ic_data_wdata), - .ic_data_rdata_i (shadow_data_rdata_q[0]), - .ic_scr_key_valid_i (shadow_inputs_q[0].ic_scr_key_valid), - - .irq_software_i (shadow_inputs_q[0].irq_software), - .irq_timer_i (shadow_inputs_q[0].irq_timer), - .irq_external_i (shadow_inputs_q[0].irq_external), - .irq_fast_i (shadow_inputs_q[0].irq_fast), - .irq_nm_i (shadow_inputs_q[0].irq_nm), - .irq_pending_o (shadow_outputs_d.irq_pending), - - .debug_req_i (shadow_inputs_q[0].debug_req), - .crash_dump_o (shadow_outputs_d.crash_dump), - .double_fault_seen_o (shadow_outputs_d.double_fault_seen), - -`ifdef RVFI - .rvfi_valid (), - .rvfi_order (), - .rvfi_insn (), - .rvfi_trap (), - .rvfi_halt (), - .rvfi_intr (), - .rvfi_mode (), - .rvfi_ixl (), - .rvfi_rs1_addr (), - .rvfi_rs2_addr (), - .rvfi_rs3_addr (), - .rvfi_rs1_rdata (), - .rvfi_rs2_rdata (), - .rvfi_rs3_rdata (), - .rvfi_rd_addr (), - .rvfi_rd_wdata (), - .rvfi_pc_rdata (), - .rvfi_pc_wdata (), - .rvfi_mem_addr (), - .rvfi_mem_rmask (), - .rvfi_mem_wmask (), - .rvfi_mem_rdata (), - .rvfi_mem_wdata (), - .rvfi_ext_mip (), - .rvfi_ext_nmi (), - .rvfi_ext_debug_req (), - .rvfi_ext_mcycle (), -`endif - - .fetch_enable_i (shadow_inputs_q[0].fetch_enable), - .alert_minor_o (shadow_alert_minor), - .alert_major_o (shadow_alert_major), - .icache_inval_o (shadow_outputs_d.icache_inval), - .core_busy_o (shadow_outputs_d.core_busy) - ); - - // Register the shadow core outputs - always_ff @(posedge clk_i) begin - shadow_outputs_q <= shadow_outputs_d; - end - - ///////////////////////// - // Compare the outputs // - ///////////////////////// - - logic outputs_mismatch; - - assign outputs_mismatch = enable_cmp_q & (shadow_outputs_q != core_outputs_q[0]); - assign alert_major_internal_o = outputs_mismatch | shadow_alert_major; - assign alert_major_bus_o = bus_intg_err; - assign alert_minor_o = shadow_alert_minor; - -endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv b/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv deleted file mode 100644 index 678549aba..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * RISC-V register file - * - * Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0. - * - * This register file is designed to make FPGA synthesis tools infer RAM primitives. For Xilinx - * FPGA architectures, it will produce RAM32M primitives. Other vendors have not yet been tested. - */ -module ibex_register_file_fpga #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, - parameter logic [DataWidth-1:0] WordZeroVal = '0 -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, - input logic dummy_instr_id_i, - - //Read port R1 - input logic [ 4:0] raddr_a_i, - output logic [DataWidth-1:0] rdata_a_o, - //Read port R2 - input logic [ 4:0] raddr_b_i, - output logic [DataWidth-1:0] rdata_b_o, - // Write port W1 - input logic [ 4:0] waddr_a_i, - input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i -); - - localparam int ADDR_WIDTH = RV32E ? 4 : 5; - localparam int NUM_WORDS = 2 ** ADDR_WIDTH; - - logic [DataWidth-1:0] mem[NUM_WORDS]; - logic we; // write enable if writing to any register other than R0 - - // async_read a - assign rdata_a_o = (raddr_a_i == '0) ? '0 : mem[raddr_a_i]; - - // async_read b - assign rdata_b_o = (raddr_b_i == '0) ? '0 : mem[raddr_b_i]; - - // we select - assign we = (waddr_a_i == '0) ? 1'b0 : we_a_i; - - // Note that the SystemVerilog LRM requires variables on the LHS of assignments within - // "always_ff" to not be written to by any other process. However, to enable the initialization - // of the inferred RAM32M primitives with non-zero values, below "initial" procedure is needed. - // Therefore, we use "always" instead of the generally preferred "always_ff" for the synchronous - // write procedure. - always @(posedge clk_i) begin : sync_write - if (we == 1'b1) begin - mem[waddr_a_i] <= wdata_a_i; - end - end : sync_write - - // Make sure we initialize the BRAM with the correct register reset value. - initial begin - for (int k = 0; k < NUM_WORDS; k++) begin - mem[k] = WordZeroVal; - end - end - - // Reset not used in this register file version - logic unused_rst_ni; - assign unused_rst_ni = rst_ni; - - // Dummy instruction changes not relevant for FPGA implementation - logic unused_dummy_instr; - assign unused_dummy_instr = dummy_instr_id_i; - // Test enable signal not used in FPGA implementation - logic unused_test_en; - assign unused_test_en = test_en_i; - -endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv b/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv deleted file mode 100644 index f1e4df75e..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * RISC-V register file - * - * Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0. - * This register file is based on latches and is thus smaller than the flip-flop - * based RF. It requires a target technology-specific clock gating cell. Use this - * register file when targeting ASIC synthesis or event-based simulators. - */ -module ibex_register_file_latch #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, - parameter logic [DataWidth-1:0] WordZeroVal = '0 -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, - input logic dummy_instr_id_i, - - //Read port R1 - input logic [4:0] raddr_a_i, - output logic [DataWidth-1:0] rdata_a_o, - - //Read port R2 - input logic [4:0] raddr_b_i, - output logic [DataWidth-1:0] rdata_b_o, - - // Write port W1 - input logic [4:0] waddr_a_i, - input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i - -); - - localparam int unsigned ADDR_WIDTH = RV32E ? 4 : 5; - localparam int unsigned NUM_WORDS = 2**ADDR_WIDTH; - - logic [DataWidth-1:0] mem[NUM_WORDS]; - - logic [NUM_WORDS-1:1] waddr_onehot_a; - - logic [NUM_WORDS-1:1] mem_clocks; - logic [DataWidth-1:0] wdata_a_q; - - // internal addresses - logic [ADDR_WIDTH-1:0] raddr_a_int, raddr_b_int, waddr_a_int; - - assign raddr_a_int = raddr_a_i[ADDR_WIDTH-1:0]; - assign raddr_b_int = raddr_b_i[ADDR_WIDTH-1:0]; - assign waddr_a_int = waddr_a_i[ADDR_WIDTH-1:0]; - - logic clk_int; - - ////////// - // READ // - ////////// - assign rdata_a_o = mem[raddr_a_int]; - assign rdata_b_o = mem[raddr_b_int]; - - /////////// - // WRITE // - /////////// - // Global clock gating - prim_clock_gating cg_we_global ( - .clk_i ( clk_i ), - .en_i ( we_a_i ), - .test_en_i ( test_en_i ), - .clk_o ( clk_int ) - ); - - // Sample input data - // Use clk_int here, since otherwise we don't want to write anything anyway. - always_ff @(posedge clk_int or negedge rst_ni) begin : sample_wdata - if (!rst_ni) begin - wdata_a_q <= WordZeroVal; - end else begin - if (we_a_i) begin - wdata_a_q <= wdata_a_i; - end - end - end - - // Write address decoding - always_comb begin : wad - for (int i = 1; i < NUM_WORDS; i++) begin : wad_word_iter - if (we_a_i && (waddr_a_int == 5'(i))) begin - waddr_onehot_a[i] = 1'b1; - end else begin - waddr_onehot_a[i] = 1'b0; - end - end - end - - // Individual clock gating (if integrated clock-gating cells are available) - for (genvar x = 1; x < NUM_WORDS; x++) begin : gen_cg_word_iter - prim_clock_gating cg_i ( - .clk_i ( clk_int ), - .en_i ( waddr_onehot_a[x] ), - .test_en_i ( test_en_i ), - .clk_o ( mem_clocks[x] ) - ); - end - - // Actual write operation: - // Generate the sequential process for the NUM_WORDS words of the memory. - // The process is synchronized with the clocks mem_clocks[i], i = 1, ..., NUM_WORDS-1. - for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_latches - always_latch begin - if (mem_clocks[i]) begin - mem[i] = wdata_a_q; - end - end - end - - // With dummy instructions enabled, R0 behaves as a real register but will always return 0 for - // real instructions. - if (DummyInstructions) begin : g_dummy_r0 - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - 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; - - // R0 clock gate - prim_clock_gating cg_i ( - .clk_i ( clk_int ), - .en_i ( we_r0_dummy ), - .test_en_i ( test_en_i ), - .clk_o ( r0_clock ) - ); - - always_latch begin : latch_wdata - if (r0_clock) begin - mem_r0 = wdata_a_q; - end - end - - // Output the dummy data for dummy instructions, otherwise R0 reads as zero - assign mem[0] = dummy_instr_id_i ? mem_r0 : WordZeroVal; - - end else begin : g_normal_r0 - logic unused_dummy_instr_id; - assign unused_dummy_instr_id = dummy_instr_id_i; - - assign mem[0] = WordZeroVal; - end - -`ifdef VERILATOR - initial begin - $display("Latch-based register file not supported for Verilator simulation"); - $fatal; - end -`endif - -endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv b/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv deleted file mode 100644 index b566bb17e..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv +++ /dev/null @@ -1,978 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -`ifdef RISCV_FORMAL - `define RVFI -`endif - -`include "prim_assert.sv" - -/** - * Top level module of the ibex RISC-V core - */ -module ibex_top import ibex_pkg::*; #( - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, - parameter int unsigned MHPMCounterNum = 0, - parameter int unsigned MHPMCounterWidth = 40, - parameter bit RV32E = 1'b0, - parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter regfile_e RegFile = RegFileFF, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit SecureIbex = 1'b0, - parameter bit ICacheScramble = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808, - // Default seed and nonce for scrambling - parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKey = RndCnstIbexKeyDefault, - parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonce = RndCnstIbexNonceDefault -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, // enable all clock gates for testing - input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, - - input logic [31:0] hart_id_i, - input logic [31:0] boot_addr_i, - - // Instruction memory interface - output logic instr_req_o, - input logic instr_gnt_i, - input logic instr_rvalid_i, - output logic [31:0] instr_addr_o, - input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, - input logic instr_err_i, - - // Data memory interface - output logic data_req_o, - input logic data_gnt_i, - input logic data_rvalid_i, - output logic data_we_o, - output logic [3:0] data_be_o, - output logic [31:0] data_addr_o, - output logic [31:0] data_wdata_o, - output logic [6:0] data_wdata_intg_o, - input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, - input logic data_err_i, - - // Interrupt inputs - input logic irq_software_i, - input logic irq_timer_i, - input logic irq_external_i, - input logic [14:0] irq_fast_i, - input logic irq_nm_i, // non-maskeable interrupt - - // Scrambling Interface - input logic scramble_key_valid_i, - input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i, - input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i, - output logic scramble_req_o, - - // Debug Interface - input logic debug_req_i, - output crash_dump_t crash_dump_o, - output logic double_fault_seen_o, - - // RISC-V Formal Interface - // Does not comply with the coding standards of _i/_o suffixes, but follows - // the convention of RISC-V Formal Interface Specification. -`ifdef RVFI - output logic rvfi_valid, - output logic [63:0] rvfi_order, - output logic [31:0] rvfi_insn, - output logic rvfi_trap, - output logic rvfi_halt, - output logic rvfi_intr, - output logic [ 1:0] rvfi_mode, - output logic [ 1:0] rvfi_ixl, - output logic [ 4:0] rvfi_rs1_addr, - output logic [ 4:0] rvfi_rs2_addr, - output logic [ 4:0] rvfi_rs3_addr, - output logic [31:0] rvfi_rs1_rdata, - output logic [31:0] rvfi_rs2_rdata, - output logic [31:0] rvfi_rs3_rdata, - output logic [ 4:0] rvfi_rd_addr, - output logic [31:0] rvfi_rd_wdata, - output logic [31:0] rvfi_pc_rdata, - output logic [31:0] rvfi_pc_wdata, - output logic [31:0] rvfi_mem_addr, - output logic [ 3:0] rvfi_mem_rmask, - output logic [ 3:0] rvfi_mem_wmask, - output logic [31:0] rvfi_mem_rdata, - output logic [31:0] rvfi_mem_wdata, - output logic [31:0] rvfi_ext_mip, - output logic rvfi_ext_nmi, - output logic rvfi_ext_debug_req, - output logic [63:0] rvfi_ext_mcycle, -`endif - - // CPU Control Signals - input fetch_enable_t fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, - output logic core_sleep_o, - - // DFT bypass controls - input logic scan_rst_ni -); - - localparam bit Lockstep = SecureIbex; - localparam bit ResetAll = Lockstep; - localparam bit DummyInstructions = SecureIbex; - localparam bit RegFileECC = SecureIbex; - localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32; - // Icache parameters - localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE; - localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS; - localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE; - // Scrambling Parameter - localparam int unsigned NumAddrScrRounds = ICacheScramble ? 2 : 0; - localparam int unsigned NumDiffRounds = NumAddrScrRounds; - - // Clock signals - logic clk; - logic core_busy_d, core_busy_q; - logic clock_en; - logic irq_pending; - // Core <-> Register file signals - logic dummy_instr_id; - logic [4:0] rf_raddr_a; - logic [4:0] rf_raddr_b; - logic [4:0] rf_waddr_wb; - logic rf_we_wb; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc, rf_rdata_a_ecc_buf; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc, rf_rdata_b_ecc_buf; - // Core <-> RAMs signals - logic [IC_NUM_WAYS-1:0] ic_tag_req; - logic ic_tag_write; - logic [IC_INDEX_W-1:0] ic_tag_addr; - logic [TagSizeECC-1:0] ic_tag_wdata; - logic [TagSizeECC-1:0] ic_tag_rdata [IC_NUM_WAYS]; - logic [IC_NUM_WAYS-1:0] ic_data_req; - logic ic_data_write; - logic [IC_INDEX_W-1:0] ic_data_addr; - logic [LineSizeECC-1:0] ic_data_wdata; - logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS]; - // Alert signals - logic core_alert_major, core_alert_minor; - logic lockstep_alert_major_internal, lockstep_alert_major_bus; - logic lockstep_alert_minor; - // Scramble signals - logic icache_inval; - logic [SCRAMBLE_KEY_W-1:0] scramble_key_q; - logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_q; - logic scramble_key_valid_d, scramble_key_valid_q; - logic scramble_req_d, scramble_req_q; - - fetch_enable_t fetch_enable_buf; - - ///////////////////// - // Main clock gate // - ///////////////////// - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - core_busy_q <= 1'b0; - end else begin - core_busy_q <= core_busy_d; - end - end - - assign clock_en = core_busy_q | debug_req_i | irq_pending | irq_nm_i; - assign core_sleep_o = ~clock_en; - - prim_clock_gating core_clock_gate_i ( - .clk_i (clk_i), - .en_i (clock_en), - .test_en_i(test_en_i), - .clk_o (clk) - ); - - //////////////////////// - // Core instantiation // - //////////////////////// - - // Buffer security critical signals to prevent synthesis optimisation removing them - prim_buf #(.Width($bits(fetch_enable_t))) u_fetch_enable_buf ( - .in_i (fetch_enable_i), - .out_o(fetch_enable_buf) - ); - - prim_buf #(.Width(RegFileDataWidth)) u_rf_rdata_a_ecc_buf ( - .in_i (rf_rdata_a_ecc), - .out_o(rf_rdata_a_ecc_buf) - ); - - prim_buf #(.Width(RegFileDataWidth)) u_rf_rdata_b_ecc_buf ( - .in_i (rf_rdata_b_ecc), - .out_o(rf_rdata_b_ecc_buf) - ); - - ibex_core #( - .PMPEnable (PMPEnable), - .PMPGranularity (PMPGranularity), - .PMPNumRegions (PMPNumRegions), - .MHPMCounterNum (MHPMCounterNum), - .MHPMCounterWidth (MHPMCounterWidth), - .RV32E (RV32E), - .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU (BranchTargetALU), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .BranchPredictor (BranchPredictor), - .DbgTriggerEn (DbgTriggerEn), - .DbgHwBreakNum (DbgHwBreakNum), - .WritebackStage (WritebackStage), - .ResetAll (ResetAll), - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm), - .SecureIbex (SecureIbex), - .DummyInstructions(DummyInstructions), - .RegFileECC (RegFileECC), - .RegFileDataWidth (RegFileDataWidth), - .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr) - ) u_ibex_core ( - .clk_i(clk), - .rst_ni, - - .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_o (dummy_instr_id), - .rf_raddr_a_o (rf_raddr_a), - .rf_raddr_b_o (rf_raddr_b), - .rf_waddr_wb_o (rf_waddr_wb), - .rf_we_wb_o (rf_we_wb), - .rf_wdata_wb_ecc_o(rf_wdata_wb_ecc), - .rf_rdata_a_ecc_i (rf_rdata_a_ecc_buf), - .rf_rdata_b_ecc_i (rf_rdata_b_ecc_buf), - - .ic_tag_req_o (ic_tag_req), - .ic_tag_write_o (ic_tag_write), - .ic_tag_addr_o (ic_tag_addr), - .ic_tag_wdata_o (ic_tag_wdata), - .ic_tag_rdata_i (ic_tag_rdata), - .ic_data_req_o (ic_data_req), - .ic_data_write_o (ic_data_write), - .ic_data_addr_o (ic_data_addr), - .ic_data_wdata_o (ic_data_wdata), - .ic_data_rdata_i (ic_data_rdata), - .ic_scr_key_valid_i(scramble_key_valid_q), - - .irq_software_i, - .irq_timer_i, - .irq_external_i, - .irq_fast_i, - .irq_nm_i, - .irq_pending_o(irq_pending), - - .debug_req_i, - .crash_dump_o, - .double_fault_seen_o, - -`ifdef RVFI - .rvfi_valid, - .rvfi_order, - .rvfi_insn, - .rvfi_trap, - .rvfi_halt, - .rvfi_intr, - .rvfi_mode, - .rvfi_ixl, - .rvfi_rs1_addr, - .rvfi_rs2_addr, - .rvfi_rs3_addr, - .rvfi_rs1_rdata, - .rvfi_rs2_rdata, - .rvfi_rs3_rdata, - .rvfi_rd_addr, - .rvfi_rd_wdata, - .rvfi_pc_rdata, - .rvfi_pc_wdata, - .rvfi_mem_addr, - .rvfi_mem_rmask, - .rvfi_mem_wmask, - .rvfi_mem_rdata, - .rvfi_mem_wdata, - .rvfi_ext_mip, - .rvfi_ext_nmi, - .rvfi_ext_debug_req, - .rvfi_ext_mcycle, -`endif - - .fetch_enable_i(fetch_enable_buf), - .alert_minor_o (core_alert_minor), - .alert_major_o (core_alert_major), - .icache_inval_o(icache_inval), - .core_busy_o (core_busy_d) - ); - - ///////////////////////////////// - // Register file Instantiation // - ///////////////////////////////// - - if (RegFile == RegFileFF) begin : gen_regfile_ff - ibex_register_file_ff #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga - ibex_register_file_fpga #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end else if (RegFile == RegFileLatch) begin : gen_regfile_latch - ibex_register_file_latch #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end - - /////////////////////////////// - // Scrambling Infrastructure // - /////////////////////////////// - - if (ICacheScramble) begin : gen_scramble - - // SEC_CM: ICACHE.MEM.SCRAMBLE - // Scramble key valid starts with OTP returning new valid key and stays high - // until we request a new valid key. - assign scramble_key_valid_d = scramble_req_q ? scramble_key_valid_i : - icache_inval ? 1'b0 : - scramble_key_valid_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - scramble_key_q <= RndCnstIbexKey; - scramble_nonce_q <= RndCnstIbexNonce; - end else if (scramble_key_valid_i) begin - scramble_key_q <= scramble_key_i; - scramble_nonce_q <= scramble_nonce_i; - end - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - scramble_key_valid_q <= 1'b1; - scramble_req_q <= '0; - end else begin - scramble_key_valid_q <= scramble_key_valid_d; - scramble_req_q <= scramble_req_d; - end - end - - // Scramble key request starts with invalidate signal from ICache and stays high - // until we got a valid key. - assign scramble_req_d = scramble_req_q ? ~scramble_key_valid_i : icache_inval; - assign scramble_req_o = scramble_req_q; - - end else begin : gen_noscramble - - logic unused_scramble_inputs = scramble_key_valid_i & (|scramble_key_i) & (|RndCnstIbexKey) & - (|scramble_nonce_i) & (|RndCnstIbexNonce) & scramble_req_q & - icache_inval & scramble_key_valid_d & scramble_req_d; - - assign scramble_req_d = 1'b0; - assign scramble_req_q = 1'b0; - assign scramble_req_o = 1'b0; - assign scramble_key_q = '0; - assign scramble_nonce_q = '0; - assign scramble_key_valid_q = 1'b1; - assign scramble_key_valid_d = 1'b1; - end - - //////////////////////// - // Rams Instantiation // - //////////////////////// - - if (ICache) begin : gen_rams - - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams_inner - - // SEC_CM: ICACHE.MEM.SCRAMBLE - // Tag RAM instantiation - prim_ram_1p_scr #( - .Width (TagSizeECC), - .Depth (IC_NUM_LINES), - .DataBitsPerMask (TagSizeECC), - .EnableParity (0), - .DiffWidth (TagSizeECC), - .NumAddrScrRounds (NumAddrScrRounds), - .NumDiffRounds (NumDiffRounds) - ) tag_bank ( - .clk_i, - .rst_ni, - - .key_valid_i (scramble_key_valid_q), - .key_i (scramble_key_q), - .nonce_i (scramble_nonce_q), - - .req_i (ic_tag_req[way]), - - .gnt_o (), - .write_i (ic_tag_write), - .addr_i (ic_tag_addr), - .wdata_i (ic_tag_wdata), - .wmask_i ({TagSizeECC{1'b1}}), - .intg_error_i(1'b0), - - .rdata_o (ic_tag_rdata[way]), - .rvalid_o (), - .raddr_o (), - .rerror_o (), - .cfg_i (ram_cfg_i) - ); - - // Data RAM instantiation - prim_ram_1p_scr #( - .Width (LineSizeECC), - .Depth (IC_NUM_LINES), - .DataBitsPerMask (LineSizeECC), - .ReplicateKeyStream (1), - .EnableParity (0), - .DiffWidth (LineSizeECC), - .NumAddrScrRounds (NumAddrScrRounds), - .NumDiffRounds (NumDiffRounds) - ) data_bank ( - .clk_i, - .rst_ni, - - .key_valid_i (scramble_key_valid_q), - .key_i (scramble_key_q), - .nonce_i (scramble_nonce_q), - - .req_i (ic_data_req[way]), - - .gnt_o (), - .write_i (ic_data_write), - .addr_i (ic_data_addr), - .wdata_i (ic_data_wdata), - .wmask_i ({LineSizeECC{1'b1}}), - .intg_error_i(1'b0), - - .rdata_o (ic_data_rdata[way]), - .rvalid_o (), - .raddr_o (), - .rerror_o (), - .cfg_i (ram_cfg_i) - ); - end - - end else begin : gen_norams - - prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg; - logic unused_ram_inputs; - - assign unused_ram_cfg = ram_cfg_i; - assign unused_ram_inputs = (|ic_tag_req) & ic_tag_write & (|ic_tag_addr) & (|ic_tag_wdata) & - (|ic_data_req) & ic_data_write & (|ic_data_addr) & (|ic_data_wdata) & - (|scramble_key_q) & (|scramble_nonce_q) & scramble_key_valid_q & - scramble_key_valid_d & (|scramble_nonce_q) & - (|NumAddrScrRounds); - - assign ic_tag_rdata = '{default:'b0}; - assign ic_data_rdata = '{default:'b0}; - - end - - // Redundant lockstep core implementation - if (Lockstep) begin : gen_lockstep - // SEC_CM: LOGIC.SHADOW - // 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_rdata_intg_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_rdata_intg_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, - scramble_key_valid_i, - irq_software_i, - irq_timer_i, - irq_external_i, - irq_fast_i, - irq_nm_i, - irq_pending, - debug_req_i, - crash_dump_o, - double_fault_seen_o, - fetch_enable_i, - icache_inval, - 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 [6:0] instr_rdata_intg_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 [6:0] data_wdata_intg_local; - logic [31:0] data_rdata_local; - logic [6:0] data_rdata_intg_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 scramble_key_valid_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 double_fault_seen_local; - fetch_enable_t fetch_enable_local; - - logic icache_inval_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_rdata_intg_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_rdata_intg_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, - scramble_key_valid_q, - irq_software_i, - irq_timer_i, - irq_external_i, - irq_fast_i, - irq_nm_i, - irq_pending, - debug_req_i, - crash_dump_o, - double_fault_seen_o, - fetch_enable_i, - icache_inval, - 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_rdata_intg_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_rdata_intg_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, - scramble_key_valid_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, - double_fault_seen_local, - fetch_enable_local, - icache_inval_local, - core_busy_local - } = buf_out; - - // Manually buffer all input signals. - prim_buf #(.Width(NumBufferBits)) u_signals_prim_buf ( - .in_i(buf_in), - .out_o(buf_out) - ); - - 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 - prim_buf #(.Width(TagSizeECC)) u_tag_prim_buf ( - .in_i(ic_tag_rdata[k]), - .out_o(ic_tag_rdata_local[k]) - ); - prim_buf #(.Width(LineSizeECC)) u_data_prim_buf ( - .in_i(ic_data_rdata[k]), - .out_o(ic_data_rdata_local[k]) - ); - end - - logic lockstep_alert_minor_local, lockstep_alert_major_internal_local; - logic lockstep_alert_major_bus_local; - - ibex_lockstep #( - .PMPEnable (PMPEnable), - .PMPGranularity (PMPGranularity), - .PMPNumRegions (PMPNumRegions), - .MHPMCounterNum (MHPMCounterNum), - .MHPMCounterWidth (MHPMCounterWidth), - .RV32E (RV32E), - .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU (BranchTargetALU), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .BranchPredictor (BranchPredictor), - .DbgTriggerEn (DbgTriggerEn), - .DbgHwBreakNum (DbgHwBreakNum), - .WritebackStage (WritebackStage), - .ResetAll (ResetAll), - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm), - .SecureIbex (SecureIbex), - .DummyInstructions(DummyInstructions), - .RegFileECC (RegFileECC), - .RegFileDataWidth (RegFileDataWidth), - .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr) - ) u_ibex_lockstep ( - .clk_i (clk), - .rst_ni (rst_ni), - - .hart_id_i (hart_id_local), - .boot_addr_i (boot_addr_local), - - .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_rdata_intg_i (instr_rdata_intg_local), - .instr_err_i (instr_err_local), - - .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_wdata_intg_o (data_wdata_intg_local), - .data_rdata_i (data_rdata_local), - .data_rdata_intg_i (data_rdata_intg_local), - .data_err_i (data_err_local), - - .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_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), - .ic_scr_key_valid_i (scramble_key_valid_local), - - .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_local), - .crash_dump_i (crash_dump_local), - .double_fault_seen_i (double_fault_seen_local), - - .fetch_enable_i (fetch_enable_local), - .alert_minor_o (lockstep_alert_minor_local), - .alert_major_internal_o (lockstep_alert_major_internal_local), - .alert_major_bus_o (lockstep_alert_major_bus_local), - .icache_inval_i (icache_inval_local), - .core_busy_i (core_busy_local), - .test_en_i (test_en_i), - .scan_rst_ni (scan_rst_ni) - ); - - // Manually buffer the output signals. - prim_buf #(.Width (7)) u_prim_buf_wdata_intg ( - .in_i(data_wdata_intg_local), - .out_o(data_wdata_intg_o) - ); - - 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_internal ( - .in_i (lockstep_alert_major_internal_local), - .out_o(lockstep_alert_major_internal) - ); - - prim_buf u_prim_buf_alert_major_bus ( - .in_i (lockstep_alert_major_bus_local), - .out_o(lockstep_alert_major_bus) - ); - - end else begin : gen_no_lockstep - assign lockstep_alert_major_internal = 1'b0; - assign lockstep_alert_major_bus = 1'b0; - assign lockstep_alert_minor = 1'b0; - assign data_wdata_intg_o = 'b0; - logic unused_scan, unused_intg; - assign unused_scan = scan_rst_ni; - assign unused_intg = |{instr_rdata_intg_i, data_rdata_intg_i}; - end - - assign alert_major_internal_o = core_alert_major | lockstep_alert_major_internal; - assign alert_major_bus_o = lockstep_alert_major_bus; - assign alert_minor_o = core_alert_minor | lockstep_alert_minor; - - // X checks for top-level outputs - `ASSERT_KNOWN(IbexInstrReqX, instr_req_o) - `ASSERT_KNOWN_IF(IbexInstrReqPayloadX, instr_addr_o, instr_req_o) - - `ASSERT_KNOWN(IbexDataReqX, data_req_o) - `ASSERT_KNOWN_IF(IbexDataReqPayloadX, - {data_we_o, data_be_o, data_addr_o, data_wdata_o, data_wdata_intg_o}, data_req_o) - - `ASSERT_KNOWN(IbexScrambleReqX, scramble_req_o) - `ASSERT_KNOWN(IbexDoubleFaultSeenX, double_fault_seen_o) - `ASSERT_KNOWN(IbexAlertMinorX, alert_minor_o) - `ASSERT_KNOWN(IbexAlertMajorInternalX, alert_major_internal_o) - `ASSERT_KNOWN(IbexAlertMajorBusX, alert_major_bus_o) - `ASSERT_KNOWN(IbexCoreSleepX, core_sleep_o) - - // X check for top-level inputs - `ASSERT_KNOWN(IbexTestEnX, test_en_i) - `ASSERT_KNOWN(IbexRamCfgX, ram_cfg_i) - `ASSERT_KNOWN(IbexHartIdX, hart_id_i) - `ASSERT_KNOWN(IbexBootAddrX, boot_addr_i) - - `ASSERT_KNOWN(IbexInstrGntX, instr_gnt_i) - `ASSERT_KNOWN(IbexInstrRValidX, instr_rvalid_i) - `ASSERT_KNOWN_IF(IbexInstrRPayloadX, - {instr_rdata_i, instr_rdata_intg_i, instr_err_i}, instr_rvalid_i) - - `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) - `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) - `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_rdata_intg_i, data_err_i}, data_rvalid_i) - - `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) - - `ASSERT_KNOWN(IbexScrambleKeyValidX, scramble_key_valid_i) - `ASSERT_KNOWN_IF(IbexScramblePayloadX, {scramble_key_i, scramble_nonce_i}, scramble_key_valid_i) - - `ASSERT_KNOWN(IbexDebugReqX, debug_req_i) - `ASSERT_KNOWN(IbexFetchEnableX, fetch_enable_i) -endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/scripts/sec/README.md b/hw/vendor/openhwgroup_cv32e20/scripts/sec/README.md new file mode 100644 index 000000000..418199153 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/scripts/sec/README.md @@ -0,0 +1,30 @@ +# Sequential Equivalence Checking (SEC) + +This folder contains a SEC script that runs on +Cadence Jaspergold + +### Running the script + +From a bash shell, please execute: + +``` +./sec.sh -t cadence +``` + +Use `sh ./sec.sh -t {cadence}` if you run it from a tcsh shell. + +The script clones the `cve2` `main` branch of the core as a golden reference, and uses the current repository's `rtl` as revised version. + +If you want to use another golden reference rtl, Set the `GOLDEN_RTL` enviromental variable to the new rtl before calling the `sec.sh` script. + +``` +export GOLDEN_RTL=YOUR_GOLDEN_CORE_RTL_PATH +``` +or + +``` +setenv GOLDEN_RTL YOUR_GOLDEN_CORE_RTL_PATH +``` +If the script succeeds, it returns 0, otherwise 1. + +The `sec.tcl` scripts in the tool specific folders are executed on the tools to perform `RTL to RTL` SEC. diff --git a/hw/vendor/openhwgroup_cv32e20/scripts/sec/cadence/sec.tcl b/hw/vendor/openhwgroup_cv32e20/scripts/sec/cadence/sec.tcl new file mode 100644 index 000000000..f6d62b8cc --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/scripts/sec/cadence/sec.tcl @@ -0,0 +1,31 @@ +# Copyright 2023 OpenHW Group +# +# Licensed under the Solderpad Hardware Licence, 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 +# +# https://solderpad.org/licenses/ +# +# 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. + +check_sec -setup -spec_top cve2_core -imp_top cve2_core \ + -spec_analyze "-sv -f ./golden.src" \ + -imp_analyze "-sv -f ./revised.src"\ + -auto_map_reset_x_values + + +clock clk_i +reset ~rst_ni + +check_sec -map -auto + +check_sec -waive -waive_signals gen_regfile_ff.test_en_i +check_sec -waive -waive_signals cve2_core_imp.gen_regfile_ff.test_en_i + +check_sec -prove + +check_sec -signoff -get_valid_status -summary -file $report_dir/summary.cadence.log diff --git a/hw/vendor/openhwgroup_cv32e20/scripts/sec/sec.sh b/hw/vendor/openhwgroup_cv32e20/scripts/sec/sec.sh new file mode 100755 index 000000000..438189c85 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/scripts/sec/sec.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +# Copyright 2023 OpenHW Group +# +# Licensed under the Solderpad Hardware Licence, 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 +# +# https://solderpad.org/licenses/ +# +# 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. + +usage() { # Function: Print a help message. + echo "Usage: $0 [ -t {cadence,synopsys,mentor} ]" 1>&2 +} +exit_abnormal() { # Function: Exit with error. + usage + exit 1 +} + +while getopts "t:" flag +do + case "${flag}" in + t) + target_tool=${OPTARG} + ;; + :) + exit_abnormal + ;; + *) + exit_abnormal + ;; + ?) + exit_abnormal + ;; + esac +done + +if [ ! -d ./reports/ ]; then + mkdir -p ./reports/ +fi + +if [[ "${target_tool}" != "cadence" && "${target_tool}" != "synopsys" && "${target_tool}" != "mentor" ]]; then + exit_abnormal +fi + +if [[ -z "${GOLDEN_RTL}" ]]; then + echo "The env variable GOLDEN_RTL is empty." + if [ ! -d "./ref_design" ]; then + echo "Cloning Golden Design...." + git clone https://github.com/openhwgroup/cve2.git ref_design + fi + export GOLDEN_RTL=$(pwd)/ref_design/rtl +else + echo "SEC: Using ${GOLDEN_RTL} as reference design" +fi + +REVISED_DIR=$( readlink -f $(pwd)/../../) + +GOLDEN_DIR=$(readlink -f ./ref_design/) + + +var_golden_rtl=$(awk '{ if ($0 ~ "{DESIGN_RTL_DIR}" && $0 !~ "#" && $0 !~ "tracer" && $0 !~ "wrapper") print $0 }' ${GOLDEN_DIR}/cv32e20_manifest.flist | sed 's|${DESIGN_RTL_DIR}|./ref_design/rtl/|') + +var_revised_rtl=$(awk '{ if ($0 ~ "{DESIGN_RTL_DIR}" && $0 !~ "#" && $0 !~ "tracer" && $0 !~ "wrapper") print $0 }' ${REVISED_DIR}/cv32e20_manifest.flist | sed 's|${DESIGN_RTL_DIR}|../../rtl/|') + +echo $var_golden_rtl > golden.src +echo $var_revised_rtl > revised.src + +report_dir=$(readlink -f $(dirname "${BASH_SOURCE[0]}"))/reports/$(date +%Y-%m-%d/%H-%M)/ + +if [[ -d ${report_dir} ]]; then + rm -rf ${report_dir} +fi +mkdir -p ${report_dir} + +if [[ "${target_tool}" == "cadence" ]]; then + tcl_script=$(readlink -f $(dirname "${BASH_SOURCE[0]}"))/cadence/sec.tcl + jg -sec -proj ${report_dir} -batch -tcl ${tcl_script} -define report_dir ${report_dir} &> ${report_dir}/output.candence.log + + if [ ! -f ${report_dir}/summary.cadence.log ]; then + echo "Something went wrong during the process" + exit 1 + fi + grep -Eq "Overall SEC status[ ]+- Complete" ${report_dir}/summary.cadence.log + RESULT=$? + +elif [[ "${target_tool}" == "synopsys" ]]; then + echo "Synopsys tool is not implemented yet" + exit 1 + +elif [[ "${target_tool}" == "mentor" ]]; then + echo "Mentor tool is not implemented yet" + exit 1 +fi + +if [[ $RESULT == 0 ]]; then + echo "SEC: The DESIGN IS SEQUENTIAL EQUIVALENT" + exit 0 +else + echo "SEC: The DESIGN IS NOT SEQUENTIAL EQUIVALENT" + exit 1 +fi + diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/README.md b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core new file mode 100644 index 000000000..02c033560 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_fcov_macros" +description: "DV FCOV macros" + +filesets: + files_fcov: + files: + - dv_fcov_macros.svh: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_fcov diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh new file mode 100644 index 000000000..8ca12cdc8 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh @@ -0,0 +1,112 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Include FCOV RTL by default. Disable it for synthesis and where explicitly requested (by defining +// DV_FCOV_DISABLE). +`ifdef SYNTHESIS + `define DV_FCOV_DISABLE +`elsif YOSYS + `define DV_FCOV_DISABLE +`endif + +// Disable instantiations of FCOV coverpoints or covergroups. +`ifdef VERILATOR + `define DV_FCOV_DISABLE_CP +`elsif DV_FCOV_DISABLE + `define DV_FCOV_DISABLE_CP +`endif + +// Instantiates a covergroup in an interface or module. +// +// This macro assumes that a covergroup of the same name as the NAME_ arg is defined in the +// interface or module. It just adds some extra signals and logic to control the creation of the +// covergroup instance with ~bit en_~. This defaults to 0. It is ORed with the external +// COND_ signal. The testbench can modify it at t = 0 based on the test being run. +// NOTE: This is not meant to be invoked inside a class. +// +// NAME_ : Name of the covergroup. +// COND_ : External condition / expr that controls the creation of the covergroup. +// ARGS_ : Arguments to covergroup instance, if any. Args MUST BE wrapped in (..). +`ifndef DV_FCOV_INSTANTIATE_CG +`ifdef DV_FCOV_DISABLE_CP + `define DV_FCOV_INSTANTIATE_CG(NAME_, COND_ = 1'b1, ARGS_ = ()) +`else + `define DV_FCOV_INSTANTIATE_CG(NAME_, COND_ = 1'b1, ARGS_ = ()) \ + bit en_``NAME_ = 1'b0; \ + NAME_ NAME_``_inst; \ + initial begin \ + /* The #1 delay below allows any part of the tb to control the conditions first at t = 0. */ \ + #1; \ + if ((en_``NAME_) || (COND_)) begin \ + $display("%0t: (%0s:%0d) [%m] %0s", $time, `__FILE__, `__LINE__, \ + {"Creating covergroup ", `"NAME_`"}); \ + NAME_``_inst = new``ARGS_; \ + end \ + end +`endif +`endif + +// Creates a coverpoint for an expression where only the expression true case is of interest for +// coverage (e.g. where the expression indicates an event has occured). +`ifndef DV_FCOV_EXPR_SEEN +`ifdef DV_FCOV_DISABLE_CP + `define DV_FCOV_EXPR_SEEN(NAME_, EXPR_) +`else + `define DV_FCOV_EXPR_SEEN(NAME_, EXPR_) cp_``NAME_: coverpoint EXPR_ { bins seen = {1}; } +`endif +`endif + +// Creates a SVA cover that can be used in a covergroup. +// +// This macro creates an unnamed SVA cover from the property (or an expression) `PROP_` and an event +// with the name `EV_NAME_`. When the SVA cover is hit, the event is triggered. A coverpoint can +// cover the `triggered` property of the event. +`ifndef DV_FCOV_SVA +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SVA(EV_NAME_, PROP_, CLK_ = clk_i, RST_ = rst_ni) +`else + `define DV_FCOV_SVA(EV_NAME_, PROP_, CLK_ = clk_i, RST_ = rst_ni) \ + event EV_NAME_; \ + cover property (@(posedge CLK_) disable iff (RST_ == 0) (PROP_)) begin \ + -> EV_NAME_; \ + end +`endif +`endif + +// Coverage support is not always available but it's useful to include extra fcov signals for +// linting purposes. They need to be marked as unused to avoid warnings. +`ifndef DV_FCOV_MARK_UNUSED + `define DV_FCOV_MARK_UNUSED(TYPE_, NAME_) \ + TYPE_ unused_fcov_``NAME_; \ + assign unused_fcov_``NAME_ = fcov_``NAME_; +`endif + +// Define a signal and expression in the design for capture in functional coverage +`ifndef DV_FCOV_SIGNAL +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SIGNAL(TYPE_, NAME_, EXPR_) +`else + `define DV_FCOV_SIGNAL(TYPE_, NAME_, EXPR_) \ + TYPE_ fcov_``NAME_; \ + assign fcov_``NAME_ = EXPR_; \ + `DV_FCOV_MARK_UNUSED(TYPE_, NAME_) +`endif +`endif + +// Define a signal and expression in the design for capture in functional coverage depending on +// design configuration. The input GEN_COND_ must be a constant or parameter. +`ifndef DV_FCOV_SIGNAL_GEN_IF +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SIGNAL_GEN_IF(TYPE_, NAME_, EXPR_, GEN_COND_, DEFAULT_ = '0) +`else + `define DV_FCOV_SIGNAL_GEN_IF(TYPE_, NAME_, EXPR_, GEN_COND_, DEFAULT_ = '0) \ + TYPE_ fcov_``NAME_; \ + if (GEN_COND_) begin : g_fcov_``NAME_ \ + assign fcov_``NAME_ = EXPR_; \ + end else begin : g_no_fcov_``NAME_ \ + assign fcov_``NAME_ = DEFAULT_; \ + end \ + `DV_FCOV_MARK_UNUSED(TYPE_, NAME_) +`endif +`endif diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core new file mode 100644 index 000000000..5f2fb800b --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_macros" +description: "A collection of macros used in DV." + +filesets: + files_dv: + files: + - dv_macros.svh: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: &default_target + filesets: + - files_dv diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh new file mode 100644 index 000000000..2e5e1375f --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh @@ -0,0 +1,536 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`ifdef UVM + `include "uvm_macros.svh" +`endif + +// UVM speficic macros +`ifndef gfn +`ifdef UVM + // verilog_lint: waive macro-name-style + `define gfn get_full_name() +`else + // verilog_lint: waive macro-name-style + `define gfn $sformatf("%m") +`endif +`endif + +`ifndef gtn + // verilog_lint: waive macro-name-style + `define gtn get_type_name() +`endif + +`ifndef gn + // verilog_lint: waive macro-name-style + `define gn get_name() +`endif + +`ifndef gmv + // verilog_lint: waive macro-name-style + `define gmv(csr) csr.get_mirrored_value() +`endif + +// cast base class obj holding extended class handle to extended class handle; +// throw error if cast fails +`ifndef downcast + // verilog_lint: waive macro-name-style + `define downcast(EXT_, BASE_, MSG_="", SEV_=fatal, ID_=`gfn) \ + begin \ + if (!$cast(EXT_, BASE_)) begin \ + `dv_``SEV_($sformatf({"Cast failed: base class variable %0s ", \ + "does not hold extended class %0s handle %s"}, \ + `"BASE_`", `"EXT_`", MSG_), ID_) \ + end \ + end +`endif + +// Note, UVM provides a macro `uvm_new_func -- which only applies to uvm_components +`ifndef uvm_object_new + `define uvm_object_new \ + function new (string name=""); \ + super.new(name); \ + endfunction : new +`endif + +`ifndef uvm_create_obj + `define uvm_create_obj(_type_name_, _inst_name_) \ + _inst_name_ = _type_name_::type_id::create(`"_inst_name_`"); +`endif + +`ifndef uvm_component_new + `define uvm_component_new \ + function new (string name="", uvm_component parent=null); \ + super.new(name, parent); \ + endfunction : new +`endif + +`ifndef uvm_create_comp + `define uvm_create_comp(_type_name_, _inst_name_) \ + _inst_name_ = _type_name_::type_id::create(`"_inst_name_`", this); +`endif + +// Convert arbitrary text / expression to string. +`ifndef DV_STRINGIFY + `define DV_STRINGIFY(I_) `"I_`" +`endif + +`ifndef DUT_HIER_STR + `define DUT_HIER_STR `DV_STRINGIFY(`DUT_HIER) +`endif + +// Common check macros used by DV_CHECK error and fatal macros. +// Note: Should not be called by user code +`ifndef DV_CHECK + `define DV_CHECK(T_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!(T_)) begin \ + `dv_``SEV_($sformatf("Check failed (%s) %s ", `"T_`", MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_EQ + `define DV_CHECK_EQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) == (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s == %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_NE + `define DV_CHECK_NE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) != (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s != %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_CASE_EQ + `define DV_CHECK_CASE_EQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) === (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s === %s (0x%0h [%0b] vs 0x%0h [%0b]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_CASE_NE + `define DV_CHECK_CASE_NE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) !== (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s !== %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_LT + `define DV_CHECK_LT(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) < (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s < %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_GT + `define DV_CHECK_GT(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) > (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s > %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_LE + `define DV_CHECK_LE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) <= (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s <= %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_GE + `define DV_CHECK_GE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) >= (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s >= %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_STREQ + `define DV_CHECK_STREQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + if (!((ACT_) == (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed \"%s\" == \"%s\" %s", ACT_, EXP_, MSG_), ID_) \ + end +`endif + +`ifndef DV_CHECK_STRNE + `define DV_CHECK_STRNE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + if (!((ACT_) != (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed \"%s\" != \"%s\" %s", ACT_, EXP_, MSG_), ID_) \ + end +`endif + +// Fatal version of the checks +`ifndef DV_CHECK_FATAL + `define DV_CHECK_FATAL(T_, MSG_="", ID_=`gfn) \ + `DV_CHECK(T_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_EQ_FATAL + `define DV_CHECK_EQ_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_EQ(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_NE_FATAL + `define DV_CHECK_NE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_NE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_LT_FATAL + `define DV_CHECK_LT_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_LT(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_GT_FATAL + `define DV_CHECK_GT_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_GT(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_LE_FATAL + `define DV_CHECK_LE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_LE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_GE_FATAL + `define DV_CHECK_GE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_GE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_STREQ_FATAL + `define DV_CHECK_STREQ_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_STREQ(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_STRNE_FATAL + `define DV_CHECK_STRNE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_STRNE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +// Shorthand for common foo.randomize() + fatal check +`ifndef DV_CHECK_RANDOMIZE_FATAL + `define DV_CHECK_RANDOMIZE_FATAL(VAR_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(VAR_.randomize(), MSG_, ID_) +`endif + +// Shorthand for common foo.randomize() with { } + fatal check +`ifndef DV_CHECK_RANDOMIZE_WITH_FATAL + `define DV_CHECK_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(VAR_.randomize() with {WITH_C_}, MSG_, ID_) +`endif + +// Shorthand for common std::randomize(foo) + fatal check +`ifndef DV_CHECK_STD_RANDOMIZE_FATAL + `define DV_CHECK_STD_RANDOMIZE_FATAL(VAR_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(std::randomize(VAR_), MSG_, ID_) +`endif + +// Shorthand for common std::randomize(foo) with { } + fatal check +`ifndef DV_CHECK_STD_RANDOMIZE_WITH_FATAL + `define DV_CHECK_STD_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_, MSG_="Randomization failed!",ID_=`gfn) \ + `DV_CHECK_FATAL(std::randomize(VAR_) with {WITH_C_}, MSG_, ID_) +`endif + +// Shorthand for common cls_inst.randomize(member) + fatal check +// Randomizes a specific member of a class instance. +`ifndef DV_CHECK_MEMBER_RANDOMIZE_FATAL + `define DV_CHECK_MEMBER_RANDOMIZE_FATAL(VAR_, CLS_INST_=this, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(CLS_INST_.randomize(VAR_), MSG_, ID_) +`endif + +// Shorthand for common cls_inst.randomize(member) with { } + fatal check +// Randomizes a specific member of a class instance with inline constraints. +`ifndef DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL + `define DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(VAR_, C_, CLS_INST_=this, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(CLS_INST_.randomize(VAR_) with {C_}, MSG_, ID_) +`endif + +// print static/dynamic 1d array or queue +`ifndef DV_PRINT_ARR_CONTENTS +`define DV_PRINT_ARR_CONTENTS(ARR_, V_=uvm_pkg::UVM_MEDIUM, ID_=`gfn) \ + begin \ + foreach (ARR_[i]) begin \ + `dv_info($sformatf("%s[%0d] = %0d (0x%0h)", `"ARR_`", i, ARR_[i], ARR_[i]), V_, ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_TLM_FIFO_CONTENTS +`define DV_EOT_PRINT_TLM_FIFO_CONTENTS(TYP_, FIFO_, SEV_=error, ID_=`gfn) \ + begin \ + while (!FIFO_.is_empty()) begin \ + TYP_ item; \ + void'(FIFO_.try_get(item)); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"FIFO_`", item.sprint()), ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_TLM_FIFO_ARR_CONTENTS +`define DV_EOT_PRINT_TLM_FIFO_ARR_CONTENTS(TYP_, FIFO_, SEV_=error, ID_=`gfn) \ + begin \ + foreach (FIFO_[i]) begin \ + while (!FIFO_[i].is_empty()) begin \ + TYP_ item; \ + void'(FIFO_[i].try_get(item)); \ + `dv_``SEV_($sformatf("%s[%0d] item uncompared:\n%s", `"FIFO_`", i, item.sprint()), ID_) \ + end \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_Q_CONTENTS +`define DV_EOT_PRINT_Q_CONTENTS(TYP_, Q_, SEV_=error, ID_=`gfn) \ + begin \ + while (Q_.size() != 0) begin \ + TYP_ item = Q_.pop_front(); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"Q_`", item.sprint()), ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_Q_ARR_CONTENTS +`define DV_EOT_PRINT_Q_ARR_CONTENTS(TYP_, Q_, SEV_=error, ID_=`gfn) \ + begin \ + foreach (Q_[i]) begin \ + while (Q_[i].size() != 0) begin \ + TYP_ item = Q_[i].pop_front(); \ + `dv_``SEV_($sformatf("%s[%0d] item uncompared:\n%s", `"Q_`", i, item.sprint()), ID_) \ + end \ + end \ + end +`endif + +// check for non-empty mailbox and print items that were uncompared at end of test +`ifndef DV_EOT_PRINT_MAILBOX_CONTENTS +`define DV_EOT_PRINT_MAILBOX_CONTENTS(TYP_, MAILBOX_, SEV_=error, ID_=`gfn) \ + begin \ + while (MAILBOX_.num() != 0) begin \ + TYP_ item; \ + void'(MAILBOX_.try_get(item)); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"MAILBOX_`", item.sprint()), ID_) \ + end \ + end +`endif + +// get parity - implemented as a macro so that it can be invoked in constraints as well +`ifndef GET_PARITY + `define GET_PARITY(val, odd=0) (^val ^ odd) +`endif + +// Wait a task or statement with exit condition +// Kill the thread when either the wait statement is completed or exit condition occurs +// input WAIT_ need to be a statement. Here are some examples +// `DV_SPINWAIT(wait(...);, "Wait for ...") +// `DV_SPINWAIT( +// while (1) begin +// ... +// end) +`ifndef DV_SPINWAIT_EXIT +`define DV_SPINWAIT_EXIT(WAIT_, EXIT_, MSG_ = "exit condition occurred!", ID_ =`gfn) \ + begin \ + fork begin \ + fork \ + begin \ + WAIT_ \ + end \ + begin \ + EXIT_ \ + if (MSG_ != "") begin \ + `dv_info(MSG_, uvm_pkg::UVM_HIGH, ID_) \ + end \ + end \ + join_any \ + disable fork; \ + end join \ + end +`endif + +// wait a task or statement with timer watchdog +`ifndef DV_SPINWAIT +`define DV_SPINWAIT(WAIT_, MSG_ = "timeout occurred!", TIMEOUT_NS_ = default_spinwait_timeout_ns, ID_ =`gfn) \ + `DV_SPINWAIT_EXIT(WAIT_, wait_timeout(TIMEOUT_NS_, ID_, MSG_);, "", ID_) +`endif + +// Control assertions in the DUT. +// +// This macro is invoked in top level testbench that instantiates the DUT. It spawns off an initial +// block that forever waits for a resource of type bit named by the string arg ~LABEL_~ that +// can be set by any entity in the testbench. Based on the value set, it enables or disables the +// assertions at the hierarchy of the provided path. The entity setting the resource value invokes +// uvm_config_db#(bit)::set(...) and this macro calls the corresponding get. +// +// LABEL_ : Name of the assertion control resource bit (string). +// HIER_ : Path to the module within which the assertion is controlled. +// LEVELS_: Number of levels within the module to control the assertions. +// SCOPE_ : Hierarchical string path to the testbench where this macro is invoked, example: %m. +// ID_ : Identifier string used for UVM logs. +`ifndef DV_ASSERT_CTRL +`define DV_ASSERT_CTRL(LABEL_, HIER_, LEVELS_ = 0, SCOPE_ = "", ID_ = $sformatf("%m")) \ + initial begin \ + bit assert_en; \ + forever begin \ + uvm_config_db#(bit)::wait_modified(null, SCOPE_, LABEL_); \ + if (!uvm_config_db#(bit)::get(null, SCOPE_, LABEL_, assert_en)) begin \ + `uvm_fatal(ID_, $sformatf("Failed to get \"%0s\" from uvm_config_db", LABEL_)) \ + end \ + if (assert_en) begin \ + `uvm_info(ID_, $sformatf("Enabling assertions: %0s", `DV_STRINGIFY(HIER_)), UVM_LOW) \ + $asserton(LEVELS_, HIER_); \ + end else begin \ + `uvm_info(ID_, $sformatf("Disabling assertions: %0s", `DV_STRINGIFY(HIER_)), UVM_LOW) \ + $assertoff(LEVELS_, HIER_); \ + end \ + end \ + end +`endif + +// Retrieves a plusarg value representing an enum literal. +// +// The plusarg is parsed as a string, which needs to be converted into the enum literal whose name +// matches the string. This functionality is provided by the UVM helper function below. +// +// ENUM_: The enum type. +// VAR_: The enum variable to which the plusarg value will be set (must be declared already). +// PLUSARG_: the name of the plusarg (as raw text). This is typically the same as the enum variable. +// CHECK_EXISTS_: Throws a fatal error if the plusarg is not set. +`ifndef DV_GET_ENUM_PLUSARG +`define DV_GET_ENUM_PLUSARG(ENUM_, VAR_, PLUSARG_ = VAR_, CHECK_EXISTS_ = 0, ID_ = `gfn) \ + begin \ + string str; \ + if ($value$plusargs("``PLUSARG_``=%0s", str)) begin \ + if (!uvm_enum_wrapper#(ENUM_)::from_name(str, VAR_)) begin \ + `uvm_fatal(ID_, $sformatf("Cannot find %s from enum ``ENUM_``", VAR_.name())) \ + end \ + end else if (CHECK_EXISTS_) begin \ + `uvm_fatal(ID_, "Please pass the plusarg +``PLUSARG_``=<``ENUM_``-literal>") \ + end \ + end +`endif + +// Enable / disable assertions at a module hierarchy identified by LABEL_. +// +// This goes in conjunction with `DV_ASSERT_CTRL() macro above, but is invoked in the entity that is +// sending the req to turn on / off the assertions. Note that that piece of code invoking this macro +// does not have the information on the actual hierarchical path to the module or the levels - this +// is 'wrapped' into the LABEL_ instead. DV user needs to uniquify the label sufficienly enough to +// reflect it. +// +// LABEL_ : Name of the assertion control resource bit (string). +// VALUE_ : Value of the control bit - 1 - enable assertions, 0 - disable assertions. +// SCOPE_ : Hierarchical string path to the testbench where this macro is invoked, example: %m. +`ifndef DV_ASSERT_CTRL_REQ +`define DV_ASSERT_CTRL_REQ(LABEL_, VALUE_, SCOPE_="") \ + begin \ + uvm_config_db#(bit)::set(null, SCOPE_, LABEL_, VALUE_); \ + end +`endif + +// Macros for logging (info, warning, error and fatal severities). +// +// These are meant to be invoked in modules and interfaces that are shared between DV and Verilator +// testbenches. We waive the lint requirement for these to be in uppercase, since they are +// UVM-adjacent. +`ifdef UVM +`ifndef dv_info + // verilog_lint: waive macro-name-style + `define dv_info(MSG_, VERBOSITY_ = uvm_pkg::UVM_LOW, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(VERBOSITY_, uvm_pkg::UVM_INFO, ID_)) begin \ + uvm_pkg::uvm_report_info(ID_, MSG_, VERBOSITY_, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_warning + // verilog_lint: waive macro-name-style + `define dv_warning(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_WARNING, ID_)) begin \ + uvm_pkg::uvm_report_warning(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_error + // verilog_lint: waive macro-name-style + `define dv_error(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_ERROR, ID_)) begin \ + uvm_pkg::uvm_report_error(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_fatal + // verilog_lint: waive macro-name-style + `define dv_fatal(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_FATAL, ID_)) begin \ + uvm_pkg::uvm_report_fatal(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`else // UVM + +`ifndef dv_info + // verilog_lint: waive macro-name-style + `define dv_info(MSG_, VERBOSITY = DUMMY_, ID_ = $sformatf("%m")) \ + $display("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_warning + // verilog_lint: waive macro-name-style + `define dv_warning(MSG_, ID_ = $sformatf("%m")) \ + $warning("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_error + // verilog_lint: waive macro-name-style + `define dv_error(MSG_, ID_ = $sformatf("%m")) \ + $error("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_fatal + // verilog_lint: waive macro-name-style + `define dv_fatal(MSG_, ID_ = $sformatf("%m")) \ + $fatal("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`endif // UVM + +// Macros for constrain clk with common frequencies +// constrain clock to run at 24Mhz - 100Mhz and use higher weights on 24, 25, 48, 50, 100 +`ifndef DV_COMMON_CLK_CONSTRAINT +`define DV_COMMON_CLK_CONSTRAINT(FREQ_) \ + FREQ_ dist { \ + [24:25] :/ 2, \ + [26:47] :/ 1, \ + [48:50] :/ 2, \ + [51:95] :/ 1, \ + 96 :/ 1, \ + [97:99] :/ 1, \ + 100 :/ 1 \ + }; +`endif diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv new file mode 100644 index 000000000..91e3337e6 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv @@ -0,0 +1,46 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// Report catcher/demoter +class dv_report_catcher extends uvm_report_catcher; + + // Stores a new severity indexed by the ID and + // the regular expression to match the message + protected uvm_severity m_changed_sev[string][string]; + + `uvm_object_utils(dv_report_catcher) + `uvm_object_new + + // Called for all report messages - defined in uvm_report_catcher + virtual function action_e catch(); + string id = get_id(); + if (m_changed_sev.exists(id)) begin + string report_msg = get_message(); + foreach (m_changed_sev[id][msg]) begin + if (uvm_re_match(msg, report_msg)) begin + set_severity(m_changed_sev[id][msg]); + end + end + end + return THROW; + endfunction + + // Change severity of a message with ID == id and message text + // matching msg which is treated as a regular expression + virtual function void add_change_sev(string id, string msg, uvm_severity sev); + m_changed_sev[id][msg] = sev; + endfunction + + // Remove a change entry + // If msg == "" then remove all changes for a given id + virtual function void remove_change_sev(string id, string msg = ""); + if (m_changed_sev.exists(id)) + if (msg == "") begin + // Delete all with id if message is blank + m_changed_sev.delete(id); + end else if (m_changed_sev[id].exists(msg)) begin + m_changed_sev[id].delete(msg); + end + endfunction + +endclass diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv new file mode 100644 index 000000000..a5d7440eb --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv @@ -0,0 +1,65 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Standardize look & feel of report phase and uvm logging messages. +class dv_report_server extends uvm_default_report_server; + + bit show_file_line = 1'b1; + // if enabled, show the relative path of the file. By default only show file name + bit show_file_path = 1'b0; + bit use_default_uvm_report_message_format = 1'b0; + + function new (string name = ""); + super.new(name); + // provide ability to override these knobs over cli + void'($value$plusargs("show_file_line=%0b", show_file_line)); + void'($value$plusargs("show_file_path=%0b", show_file_path)); + void'($value$plusargs("use_default_uvm_report_message_format=%0b", + use_default_uvm_report_message_format)); + endfunction + + function void report_summarize(UVM_FILE file = 0); + int num_uvm_warning; + int num_uvm_error; + int num_uvm_fatal; + + num_uvm_warning = get_severity_count(UVM_WARNING); + num_uvm_error = get_severity_count(UVM_ERROR); + num_uvm_fatal = get_severity_count(UVM_FATAL); + + // Print default summary report + super.report_summarize(file); + + // Print final test pass-fail - external tool can use this signature for test status + // Treat UVM_WARNINGs as a sign of test failure since it could silently result in false pass + dv_test_status_pkg::dv_test_status((num_uvm_warning + num_uvm_error + num_uvm_fatal) == 0); + endfunction + + // Override default messaging format to standard "pretty" format for all testbenches + virtual function string compose_report_message(uvm_report_message report_message, + string report_object_name = ""); + + if (use_default_uvm_report_message_format) begin + return (super.compose_report_message(report_message, report_object_name)); + end else begin + uvm_severity severity = report_message.get_severity(); + string filename = report_message.get_filename(); + int line = report_message.get_line(); + string obj_name = report_message.get_report_object().get_full_name(); + string id = report_message.get_id(); + string message = report_message.get_message(); + string file_line; + + if (show_file_line && filename != "") begin + if (!show_file_path) filename = str_utils_pkg::str_path_basename(filename); + file_line = $sformatf("(%0s:%0d) ", filename, line); + end + obj_name = {obj_name, ((obj_name != "") ? " " : "")}; + compose_report_message = $sformatf({"%0s @ %t: ", file_line, obj_name, "[%0s] %0s"}, + severity.name(), $realtime, id, message); + return compose_report_message; + end + endfunction + +endclass diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core new file mode 100644 index 000000000..bbec1b052 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_test_status" +description: "DV test status reporting utilities" + +filesets: + files_dv: + files: + - dv_test_status_pkg.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv new file mode 100644 index 000000000..3a81ddfcc --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv @@ -0,0 +1,31 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package dv_test_status_pkg; + + // Prints the test status signature & banner. + // + // This function takes a boolean arg indicating whether the test passed or failed and prints the + // signature along with a banner. The signature can be used by external scripts to determine if + // the test passed or failed. + function automatic void dv_test_status(bit passed); + if (passed) begin + $display("\nTEST PASSED CHECKS"); + $display(" _____ _ _ _ "); + $display("|_ _|__ ___| |_ _ __ __ _ ___ ___ ___ __| | |"); + $display(" | |/ _ \\/ __| __| | '_ \\ / _` / __/ __|/ _ \\/ _` | |"); + $display(" | | __/\\__ \\ |_ | |_) | (_| \\__ \\__ \\ __/ (_| |_|"); + $display(" |_|\\___||___/\\__| | .__/ \\__,_|___/___/\\___|\\__,_(_)"); + $display(" |_| \n"); + end else begin + $display("\nTEST FAILED CHECKS"); + $display(" _____ _ __ _ _ _ _ "); + $display("|_ _|__ ___| |_ / _| __ _(_) | ___ __| | |"); + $display(" | |/ _ \\/ __| __| | |_ / _` | | |/ _ \\/ _` | |"); + $display(" | | __/\\__ \\ |_ | _| (_| | | | __/ (_| |_|"); + $display(" |_|\\___||___/\\__| |_| \\__,_|_|_|\\___|\\__,_(_)\n"); + end + endfunction + +endpackage diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core new file mode 100644 index 000000000..1e4052366 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core @@ -0,0 +1,28 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_utils" +description: "DV utilities" + +filesets: + files_dv: + depend: + - lowrisc:dv:dv_macros + - lowrisc:dv:dv_fcov_macros + - lowrisc:dv:common_ifs + - lowrisc:prim:assert:0.1 + - lowrisc:cve2:bus_params_pkg + - lowrisc:dv:str_utils + - lowrisc:dv:dv_test_status + files: + - dv_utils_pkg.sv + - dv_report_catcher.sv: {is_include_file: true} + - dv_report_server.sv: {is_include_file: true} + - dv_vif_wrap.sv: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv new file mode 100644 index 000000000..62f3b7659 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv @@ -0,0 +1,223 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package dv_utils_pkg; + // dep packages + import uvm_pkg::*; + import bus_params_pkg::*; + + // macro includes + `include "dv_macros.svh" +`ifdef UVM + `include "uvm_macros.svh" +`endif + + // common parameters used across all benches + parameter int NUM_MAX_INTERRUPTS = 32; + typedef logic [NUM_MAX_INTERRUPTS-1:0] interrupt_t; + + parameter int NUM_MAX_ALERTS = 32; + typedef logic [NUM_MAX_ALERTS-1:0] alert_t; + + // types & variables + typedef bit [31:0] uint; + typedef bit [7:0] uint8; + typedef bit [15:0] uint16; + typedef bit [31:0] uint32; + typedef bit [63:0] uint64; + + // TODO: The above typedefs violate the name rule, which is fixed below. Cleanup the codebase to + // use the typedefs below and remove the ones above. + typedef bit [7:0] uint8_t; + typedef bit [15:0] uint16_t; + typedef bit [31:0] uint32_t; + typedef bit [63:0] uint64_t; + + // typedef parameterized pins_if for ease of implementation for interrupts and alerts + typedef virtual pins_if #(NUM_MAX_INTERRUPTS) intr_vif; + typedef virtual pins_if #(1) devmode_vif; + + // interface direction / mode - Host or Device + typedef enum bit { + Host, + Device + } if_mode_e; + + // compare operator types + typedef enum { + CompareOpEq, + CompareOpCaseEq, + CompareOpNe, + CompareOpCaseNe, + CompareOpGt, + CompareOpGe, + CompareOpLt, + CompareOpLe + } compare_op_e; + + // mem address struct + typedef struct { + uvm_reg_addr_t start_addr; + uvm_reg_addr_t end_addr; + } addr_range_t; + + // Enum representing a bus operation type - read or write. + typedef enum bit { + BusOpWrite = 1'b0, + BusOpRead = 1'b1 + } bus_op_e; + + // Enum representing a type of host requests - read only, write only or random read & write + typedef enum int { + HostReqNone = 0, + HostReqReadOnly = 1, + HostReqWriteOnly = 2, + HostReqReadWrite = 3 + } host_req_type_e; + + // Enum representing clock frequency difference on 2 clocks + typedef enum bit [1:0] { + ClkFreqDiffNone, + ClkFreqDiffSmall, + ClkFreqDiffBig, + ClkFreqDiffAny + } clk_freq_diff_e; + + string msg_id = "dv_utils_pkg"; + + // return the smaller value of 2 inputs + function automatic int min2(int a, int b); + return (a < b) ? a : b; + endfunction + + // return the bigger value of 2 inputs + function automatic int max2(int a, int b); + return (a > b) ? a : b; + endfunction + + // return the biggest value within the given queue of integers. + function automatic int max(const ref int int_q[$]); + `DV_CHECK_GT_FATAL(int_q.size(), 0, "max function cannot accept an empty queue of integers!", + msg_id) + // Assign the first value from the queue in case of negative integers. + max = int_q[0]; + foreach (int_q[i]) max = max2(max, int_q[i]); + return max; + endfunction + + // get absolute value of the input. Usage: absolute(val) or absolute(a - b) + function automatic uint absolute(int val); + return val >= 0 ? val : -val; + endfunction + + // endian swaps a 32-bit data word + function automatic logic [31:0] endian_swap(logic [31:0] data); + return {<<8{data}}; + endfunction + + // endian swaps bytes at a word granularity, while preserving overall word ordering. + // + // e.g. if `arr[] = '{'h0, 'h1, 'h2, 'h3, 'h4, 'h5, 'h6, 'h7}`, this function will produce: + // `'{'h3, 'h2, 'h1, 'h0, 'h7, 'h6, 'h5, 'h4}` + function automatic void endian_swap_byte_arr(ref bit [7:0] arr[]); + arr = {<< byte {arr}}; + arr = {<< 32 {arr}}; + endfunction + +`ifdef UVM + // Simple function to set max errors before quitting sim + function automatic void set_max_quit_count(int n); + uvm_report_server report_server = uvm_report_server::get_server(); + report_server.set_max_quit_count(n); + endfunction + + // return if uvm_fatal occurred + function automatic bit has_uvm_fatal_occurred(); + uvm_report_server report_server = uvm_report_server::get_server(); + return report_server.get_severity_count(UVM_FATAL) > 0; + endfunction + + // task that waits for the specfied timeout + task automatic wait_timeout(input uint timeout_ns, + input string error_msg_id = msg_id, + input string error_msg = "timeout occurred!", + input bit report_fatal = 1); + #(timeout_ns * 1ns); + if (report_fatal) `uvm_fatal(error_msg_id, error_msg) + else `uvm_error(error_msg_id, error_msg) + endtask : wait_timeout + + // get masked data based on provided byte mask; if csr reg handle is provided (optional) then + // masked bytes from csr's mirrored value are returned, else masked bytes are 0's + function automatic bit [bus_params_pkg::BUS_DW-1:0] + get_masked_data(bit [bus_params_pkg::BUS_DW-1:0] data, + bit [bus_params_pkg::BUS_DBW-1:0] mask, + uvm_reg csr = null); + bit [bus_params_pkg::BUS_DW-1:0] csr_data; + csr_data = (csr != null) ? csr.get_mirrored_value() : '0; + get_masked_data = data; + foreach (mask[i]) begin + if (~mask[i]) get_masked_data[i * 8 +: 8] = csr_data[i * 8 +: 8]; + end + endfunction + + // create a sequence by name and return the handle of uvm_sequence + function automatic uvm_sequence create_seq_by_name(string seq_name); + uvm_object obj; + uvm_factory factory; + uvm_sequence seq; + + factory = uvm_factory::get(); + obj = factory.create_object_by_name(seq_name, "", seq_name); + if (obj == null) begin + // print factory overrides to help debug + factory.print(1); + `uvm_fatal(msg_id, $sformatf("could not create %0s seq", seq_name)) + end + if (!$cast(seq, obj)) begin + `uvm_fatal(msg_id, $sformatf("cast failed - %0s is not a uvm_sequence", seq_name)) + end + return seq; + endfunction +`endif + + // Returns the hierarchical path to the interface / module N levels up. + // + // Meant to be invoked inside a module or interface. + // hier: String input of the interface / module, typically $sformatf("%m"). + // n_levels_up: Integer number of levels up the hierarchy to omit. + // Example: if (hier = tb.dut.foo.bar, n_levels_up = 2), then return tb.dut + function automatic string get_parent_hier(string hier, int n_levels_up = 1); + int idx; + int level; + if (n_levels_up <= 0) return hier; + for (idx = hier.len() - 1; idx >= 0; idx--) begin + if (hier[idx] == ".") level++; + if (level == n_levels_up) break; + end + return (hier.substr(0, idx - 1)); + endfunction + + // Periodically check for the existence of a magic file (dv.stop). Exit if it exists. This + // provides a mechanism to gracefully kill a simulation without direct access to the process. + task automatic poll_for_stop(uint interval_ns = 10_000, string filename = "dv.stop"); + fork + while (1) begin + #(interval_ns * 1ns); + if (!$system($sformatf("test -f %0s", filename))) begin + $system($sformatf("rm %0s", filename)); + `dv_fatal($sformatf("Found %0s file. Exiting!", filename), "poll_for_stop") + end + end + join_none + endtask : poll_for_stop + + // sources +`ifdef UVM + `include "dv_report_catcher.sv" + `include "dv_report_server.sv" + `include "dv_vif_wrap.sv" +`endif + +endpackage diff --git a/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv new file mode 100644 index 000000000..61d99479e --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv @@ -0,0 +1,96 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Abstract class meant to hold arbitrary virtual interface handles. +// +// Written primarily for an interface which implements functional coverage, this could be used +// for other purposes as well. This abstract class provides utilities & macros to retrieve +// virtual interface handles that are bound to a DUT's sub-modules. These sub-module interfaces must +// self-register using the `DV_VIF_WRAP_SET_VIF()` macro (see details below). The extended class +// then implements the `get_vifs()` method using the `DV_VIF_WRAP_GET_VIF*` macros below to retrieve +// the sub-module interface handles it maintains. +virtual class dv_vif_wrap; + string hier; // Represents the hierarchy of the parent module or interface. + string name; // Name of the class instance. + + function new(string hier, string name = ""); + this.hier = hier; + this.name = name; + endfunction + + // Abstract method implemented by the extended class. It is recommended to invoke the helper + // macros below rather than manually define it. + pure virtual task get_vifs(); + +endclass + +// Helper macros. +// +// These are defined in the file itself since they are tightly coupled to the class definition +// above. These are scoped globally so that extended classes can invoke them. + +// Enable an interface to register itself (set its handle into the config db). +// +// Meant to be invoked from an interface. The macros invocation causes the interface to register +// itself into the uvm_resource_db pool. The derived class of dv_vif_wrap retrieves the handle to +// that interface handle from the uvm_resource db pool. +// +// SV LRM does not yet allow referencing the instance of an interface within itself as one +// would in case of a class using the ~this~ keyword. However, most major simulators actually +// support this in their own custom way. On VCS, a reference to self within the interface can be set +// using `interface::self()` construct. On Xcelium, this is achieved by simply referencing the +// interface name. +// +// _IF: The SV interface +// _VIF: The corresponding virtual interface handle name +// _LEVEL: # of hierarchical levels the module to which the SV interface is bound, starting at the +// top level DUT instance. +`define DV_VIF_WRAP_SET_VIF(_IF, _VIF, _LEVEL = 0) \ + import uvm_pkg::*; \ + function automatic void self_register(); \ + string path; \ + virtual _IF vif; \ + /* Initial block adds another level in the path hierarchy which needs to be split out. */ \ + /* Add one more to go one level up the interface instance. */ \ + /* Example: tb.dut.core.u_foo_if.self_register -> tb.dut.core. */ \ + path = dv_utils_pkg::get_parent_hier(.hier($sformatf("%m")), .n_levels_up(2 + _LEVEL)); \ +`ifdef VCS \ + vif = interface::self(); \ +`elsif XCELIUM \ + vif = _IF; \ +`else \ + vif = _IF; \ +`endif \ + uvm_pkg::uvm_resource_db#(virtual _IF)::set(path, `"_VIF`", vif); \ + endfunction \ + initial self_register(); + +// Enables the retrieval of individual vifs. +// +// The three macros below go together to define the _get_vifs() task in the extended class. +`define DV_VIF_WRAP_GET_VIFS_BEGIN \ + task get_vifs(); \ + fork \ + +// To avoid race condition between the instant when an interface handle is set into the config db +// and the instant when it is retrieved (in the same time step, at t = 0), the macro below invokes +// uvm_config_db#(..)::wait_modified() to ensure that the retrieval is done only after the set. +`define DV_VIF_WRAP_GET_VIF(_IF, _VIF) \ + begin \ + bit vif_found; \ + /* At most 2 retries. */ \ + repeat (2) begin \ + /* Force the evaluation at the end of the time step. */ \ + #0; \ + if (uvm_pkg::uvm_resource_db#(virtual _IF)::read_by_name(hier, `"_VIF`", _VIF)) begin \ + vif_found = 1'b1; \ + break; \ + end \ + end \ + `DV_CHECK_FATAL(vif_found, {`"_VIF`", " not found in the resource db"}, hier) \ + end + +`define DV_VIF_WRAP_GET_VIFS_END \ + join \ + endtask diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index d1cc1ce7f..3d215d72a 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/davideschiavone/cve2.git - rev: 5039e60cdea6a76282576ca7e93a35ee9a3ff2e9 + url: https://github.com/openhwgroup/cve2.git + rev: 1253782b42c5dc269bbd9dfb487d17d73aaa7119 } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index 8c8600694..9b9b464ec 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -6,8 +6,8 @@ target_dir: "openhwgroup_cv32e20", upstream: { - url: "https://github.com/davideschiavone/cve2.git", - rev: "5039e60cdea6a76282576ca7e93a35ee9a3ff2e9", + url: "https://github.com/openhwgroup/cve2.git", + rev: "1253782b42c5dc269bbd9dfb487d17d73aaa7119", }, exclude_from_upstream: [ @@ -16,12 +16,30 @@ "examples", "formal", ".dir-locals.el", - "cv32e40p_manifest.flist", "doc", "shared", "syn", "util", - "vendor", + "vendor/eembc_coremark", + "vendor/eembc_coremark.lock.hjson", + "vendor/google_riscv-dv", + "vendor/google_riscv-dv.lock.hjson", + "vendor/google_riscv-dv.vendor.hjson", + "vendor/lowrisc_ip.lock.hjson", + "vendor/lowrisc_ip.vendor.hjson", + "vendor/patches", + "vendor/lowrisc_ip/ip" + "vendor/lowrisc_ip/lint" + "vendor/lowrisc_ip/util" + "vendor/lowrisc_ip/dv/tools", + "vendor/lowrisc_ip/dv/verilator", + "vendor/lowrisc_ip/dv/sv/common_ifs", + "vendor/lowrisc_ip/dv/sv/csr_utils", + "vendor/lowrisc_ip/dv/sv/dv_base_reg", + "vendor/lowrisc_ip/dv/sv/dv_lib", + "vendor/lowrisc_ip/dv/sv/mem_bkdr_util", + "vendor/lowrisc_ip/dv/sv/mem_model", + "vendor/lowrisc_ip/dv/sv/str_utils", ".github", "azure-pipelines.yml", "check_tool_requirements.core", From 79d04e7421d477140185a766685398413c2c0f2d Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Thu, 25 May 2023 16:07:17 +0200 Subject: [PATCH 02/15] update cve2 with fetch enable --- hw/core-v-mini-mcu/cpu_subsystem.sv | 4 ++-- hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv | 7 +++++-- hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv | 2 ++ hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv | 2 ++ hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv | 8 +++++++- hw/vendor/openhwgroup_cve2.lock.hjson | 4 ++-- hw/vendor/openhwgroup_cve2.vendor.hjson | 4 ++-- hw/vendor/waiver/lint/cve2.vlt | 2 ++ 8 files changed, 24 insertions(+), 9 deletions(-) diff --git a/hw/core-v-mini-mcu/cpu_subsystem.sv b/hw/core-v-mini-mcu/cpu_subsystem.sv index c65eb17c1..f770e3d5a 100644 --- a/hw/core-v-mini-mcu/cpu_subsystem.sv +++ b/hw/core-v-mini-mcu/cpu_subsystem.sv @@ -92,10 +92,10 @@ module cpu_subsystem .irq_fast_i (irq_i[30:16]), .irq_nm_i (irq_i[31]), - .debug_req_i(debug_req_i), + .debug_req_i (debug_req_i), .crash_dump_o(), - //.fetch_enable_i(fetch_enable), + .fetch_enable_i(fetch_enable), .core_sleep_o ); diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 79008223a..776cf2c02 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -17,6 +17,7 @@ module cve2_controller #( input logic clk_i, input logic rst_ni, + input logic fetch_enable_i, // core can fetch instructions leave RESET state output logic ctrl_busy_o, // core is busy processing instrs // decoder related signals @@ -410,9 +411,11 @@ module cve2_controller #( instr_req_o = 1'b0; pc_mux_o = PC_BOOT; pc_set_o = 1'b1; - ctrl_fsm_ns = BOOT_SET; + if (fetch_enable_i == 1'b1) + begin + ctrl_fsm_ns = BOOT_SET; + end end - BOOT_SET: begin // copy boot address to instr fetch address instr_req_o = 1'b1; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv index f6329b5f7..77186a823 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv @@ -104,6 +104,7 @@ module cve2_core import cve2_pkg::*; #( `endif // CPU Control Signals + input logic fetch_enable_i, output logic core_busy_o ); @@ -382,6 +383,7 @@ module cve2_core import cve2_pkg::*; #( .rst_ni(rst_ni), // Processor Enable + .fetch_enable_i(fetch_enable_i), .ctrl_busy_o (ctrl_busy), .illegal_insn_o(illegal_insn_id), diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv index caf1a58fd..cbb19e030 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv @@ -27,6 +27,7 @@ module cve2_id_stage #( input logic clk_i, input logic rst_ni, + input logic fetch_enable_i, output logic ctrl_busy_o, output logic illegal_insn_o, @@ -479,6 +480,7 @@ module cve2_id_stage #( .clk_i (clk_i), .rst_ni(rst_ni), + .fetch_enable_i(fetch_enable_i), .ctrl_busy_o(ctrl_busy_o), // decoder related signals diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv index 3954d8a94..eca87741e 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -96,6 +96,7 @@ module cve2_top import cve2_pkg::*; #( `endif // CPU Control Signals + input logic fetch_enable_i, output logic core_sleep_o ); @@ -118,6 +119,7 @@ module cve2_top import cve2_pkg::*; #( logic clk; logic core_busy_d, core_busy_q; logic clock_en; + logic fetch_enable_d, fetch_enable_q; logic irq_pending; ///////////////////// @@ -127,13 +129,16 @@ module cve2_top import cve2_pkg::*; #( always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin core_busy_q <= 1'b0; + fetch_enable_q <= 1'b0; end else begin core_busy_q <= core_busy_d; + fetch_enable_q <= fetch_enable_d; end end assign clock_en = core_busy_q | debug_req_i | irq_pending | irq_nm_i; assign core_sleep_o = ~clock_en; + assign fetch_enable_d = fetch_enable_i ? 1'b1 : fetch_enable_q; cve2_clock_gate core_clock_gate_i ( .clk_i (clk_i), @@ -226,7 +231,8 @@ module cve2_top import cve2_pkg::*; #( .rvfi_ext_mcycle, `endif - .core_busy_o (core_busy_d) + .fetch_enable_i (fetch_enable_q), + .core_busy_o (core_busy_d) ); //////////////////////// diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index 3d215d72a..2d4a6d327 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/openhwgroup/cve2.git - rev: 1253782b42c5dc269bbd9dfb487d17d73aaa7119 + url: https://github.com/davideschiavone/cve2.git + rev: e168b236496e3f2bb884d3aa2c1f345f6ef344f0 } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index 9b9b464ec..495a2f7c4 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -6,8 +6,8 @@ target_dir: "openhwgroup_cv32e20", upstream: { - url: "https://github.com/openhwgroup/cve2.git", - rev: "1253782b42c5dc269bbd9dfb487d17d73aaa7119", + url: "https://github.com/davideschiavone/cve2.git", + rev: "e168b236496e3f2bb884d3aa2c1f345f6ef344f0", }, exclude_from_upstream: [ diff --git a/hw/vendor/waiver/lint/cve2.vlt b/hw/vendor/waiver/lint/cve2.vlt index ac5b00763..c9b682a39 100644 --- a/hw/vendor/waiver/lint/cve2.vlt +++ b/hw/vendor/waiver/lint/cve2.vlt @@ -6,3 +6,5 @@ lint_off -rule DECLFILENAME -file "*bhv/cve2_sim_clock_gate.sv" -match "*Filename 'cve2_sim_clock_gate' does not match MODULE name: 'cve2_clock_gate'*" lint_off -rule UNOPTFLAT -file "*rtl/*.sv" -match "*" +lint_off -rule UNUSED -file "*rtl/cve2_core.sv" -match "Signal is not used: 'rf_ren_a'*" +lint_off -rule UNUSED -file "*rtl/cve2_core.sv" -match "Signal is not used: 'rf_ren_b'*" From 3ad4dbe90106e79494d54bb3afe3ee69e3fd60d5 Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Wed, 31 May 2023 17:21:58 +0200 Subject: [PATCH 03/15] update cve2 (removed wb stage) --- .../cv32e20_manifest.flist | 2 +- hw/vendor/openhwgroup_cv32e20/cve2_core.core | 2 +- .../rtl/cve2_controller.sv | 71 +------ .../openhwgroup_cv32e20/rtl/cve2_core.sv | 132 ++---------- .../rtl/cve2_cs_registers.sv | 19 +- .../openhwgroup_cv32e20/rtl/cve2_ex_block.sv | 4 +- .../openhwgroup_cv32e20/rtl/cve2_id_stage.sv | 193 +---------------- .../rtl/cve2_load_store_unit.sv | 6 - .../rtl/cve2_multdiv_fast.sv | 12 +- hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv | 2 - .../rtl/cve2_top_tracing.sv | 2 - hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv | 69 ++++++ .../openhwgroup_cv32e20/rtl/cve2_wb_stage.sv | 201 ------------------ .../scripts/sec/cadence/sec.tcl | 3 +- hw/vendor/openhwgroup_cve2.lock.hjson | 2 +- hw/vendor/openhwgroup_cve2.vendor.hjson | 2 +- hw/vendor/waiver/lint/cve2.vlt | 1 + 17 files changed, 116 insertions(+), 607 deletions(-) create mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv delete mode 100644 hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb_stage.sv diff --git a/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist b/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist index 96fd38fbe..9284d9154 100644 --- a/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist +++ b/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist @@ -55,7 +55,7 @@ ${DESIGN_RTL_DIR}/cve2_multdiv_slow.sv ${DESIGN_RTL_DIR}/cve2_prefetch_buffer.sv ${DESIGN_RTL_DIR}/cve2_pmp.sv ${DESIGN_RTL_DIR}/cve2_register_file_ff.sv -${DESIGN_RTL_DIR}/cve2_wb_stage.sv +${DESIGN_RTL_DIR}/cve2_wb.sv ${DESIGN_RTL_DIR}/cve2_core.sv ${DESIGN_RTL_DIR}/cve2_top.sv ${DESIGN_RTL_DIR}/cve2_top_tracing.sv diff --git a/hw/vendor/openhwgroup_cv32e20/cve2_core.core b/hw/vendor/openhwgroup_cv32e20/cve2_core.core index f0d775a7b..6d621a437 100644 --- a/hw/vendor/openhwgroup_cv32e20/cve2_core.core +++ b/hw/vendor/openhwgroup_cv32e20/cve2_core.core @@ -29,7 +29,7 @@ filesets: - rtl/cve2_multdiv_slow.sv - rtl/cve2_prefetch_buffer.sv - rtl/cve2_pmp.sv - - rtl/cve2_wb_stage.sv + - rtl/cve2_wb.sv - rtl/cve2_core.sv - rtl/cve2_pmp_reset_default.svh: {is_include_file: true} file_type: systemVerilogSource diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 776cf2c02..b050c2af9 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -11,7 +11,6 @@ `include "dv_fcov_macros.svh" module cve2_controller #( - parameter bit WritebackStage = 0, parameter bit BranchPredictor = 0 ) ( input logic clk_i, @@ -59,7 +58,6 @@ module cve2_controller #( input logic [31:0] lsu_addr_last_i, // for mtval input logic load_err_i, input logic store_err_i, - output logic wb_exception_o, // Instruction in WB taking an exception output logic id_exception_o, // Instruction in ID taking an exception // jump/branch signals @@ -88,7 +86,6 @@ module cve2_controller #( output logic csr_save_if_o, output logic csr_save_id_o, - output logic csr_save_wb_o, output logic csr_restore_mret_id_o, output logic csr_restore_dret_id_o, output logic csr_save_cause_o, @@ -98,9 +95,7 @@ module cve2_controller #( // stall & flush signals input logic stall_id_i, - input logic stall_wb_i, output logic flush_id_o, - input logic ready_wb_i, // performance monitors output logic perf_jump_o, // we are executing a jump @@ -151,7 +146,6 @@ module cve2_controller #( logic enter_debug_mode; logic ebreak_into_debug; logic handle_irq; - logic id_wb_pending; logic [3:0] mfip_id; logic unused_irq_timer; @@ -237,40 +231,7 @@ module cve2_controller #( // generic special request signal, applies to all instructions assign special_req = special_req_pc_change | special_req_flush_only; - // Is there an instruction in ID or WB that has yet to complete? - assign id_wb_pending = instr_valid_i | ~ready_wb_i; - // Exception/fault prioritisation is taken from Table 3.7 of Priviledged Spec v1.11 - if (WritebackStage) begin : g_wb_exceptions - always_comb begin - instr_fetch_err_prio = 0; - illegal_insn_prio = 0; - ecall_insn_prio = 0; - ebrk_insn_prio = 0; - store_err_prio = 0; - load_err_prio = 0; - - // Note that with the writeback stage store/load errors occur on the instruction in writeback, - // all other exception/faults occur on the instruction in ID/EX. The faults from writeback - // must take priority as that instruction is architecurally ordered before the one in ID/EX. - if (store_err_q) begin - store_err_prio = 1'b1; - end else if (load_err_q) begin - load_err_prio = 1'b1; - end else if (instr_fetch_err) begin - instr_fetch_err_prio = 1'b1; - end else if (illegal_insn_q) begin - illegal_insn_prio = 1'b1; - end else if (ecall_insn) begin - ecall_insn_prio = 1'b1; - end else if (ebrk_insn) begin - ebrk_insn_prio = 1'b1; - end - end - - // Instruction in writeback is generating an exception so instruction in ID must not execute - assign wb_exception_o = load_err_q | store_err_q | load_err_i | store_err_i; - end else begin : g_no_wb_exceptions always_comb begin instr_fetch_err_prio = 0; illegal_insn_prio = 0; @@ -293,8 +254,6 @@ module cve2_controller #( load_err_prio = 1'b1; end end - assign wb_exception_o = 1'b0; - end `ASSERT_IF(IbexExceptionPrioOnehot, $onehot({instr_fetch_err_prio, @@ -371,7 +330,6 @@ module cve2_controller #( csr_save_if_o = 1'b0; csr_save_id_o = 1'b0; - csr_save_wb_o = 1'b0; csr_restore_mret_id_o = 1'b0; csr_restore_dret_id_o = 1'b0; csr_save_cause_o = 1'b0; @@ -497,15 +455,9 @@ module cve2_controller #( // FLUSH state. retain_id = 1'b1; - // Wait for the writeback stage to either be ready for a new instruction or raise its own - // exception before going to FLUSH. If the instruction in writeback raises an exception it - // must take priority over any exception from an instruction in ID/EX. Only once the - // writeback stage is ready can we be certain that won't happen. Without a writeback - // stage ready_wb_i == 1 so the FSM will always go directly to FLUSH. + // The FSM will always go directly to FLUSH. - if (ready_wb_i | wb_exception_o) begin - ctrl_fsm_ns = FLUSH; - end + ctrl_fsm_ns = FLUSH; end if (branch_set_i || jump_set_i) begin @@ -525,12 +477,12 @@ module cve2_controller #( end // If entering debug mode or handling an IRQ the core needs to wait until any instruction in - // ID or WB has finished executing. Stall IF during that time. - if ((enter_debug_mode || handle_irq) && (stall || id_wb_pending)) begin + // ID has finished executing. Stall IF during that time. + if ((enter_debug_mode || handle_irq) && (stall || instr_valid_i)) begin halt_if = 1'b1; end - if (!stall && !special_req && !id_wb_pending) begin + if (!stall && !special_req && !instr_valid_i) begin if (enter_debug_mode) begin // enter debug mode ctrl_fsm_ns = DBG_TAKEN_IF; @@ -657,13 +609,7 @@ module cve2_controller #( pc_mux_o = PC_EXC; exc_pc_mux_o = debug_mode_q ? EXC_PC_DBG_EXC : EXC_PC_EXC; - if (WritebackStage) begin : g_writeback_mepc_save - // With the writeback stage present whether an instruction accessing memory will cause - // an exception is only known when it is in writeback. So when taking such an exception - // epc must come from writeback. - csr_save_id_o = ~(store_err_q | load_err_q); - csr_save_wb_o = store_err_q | load_err_q; - end else begin : g_no_writeback_mepc_save + begin : g_no_writeback_mepc_save csr_save_id_o = 1'b0; end @@ -779,9 +725,8 @@ module cve2_controller #( /////////////////// // If high current instruction cannot complete this cycle. Either because it needs more cycles to - // finish (stall_id_i) or because the writeback stage cannot accept it yet (stall_wb_i). If there - // is no writeback stage stall_wb_i is a constant 0. - assign stall = stall_id_i | stall_wb_i; + // finish (stall_id_i) + assign stall = stall_id_i; // signal to IF stage that ID stage is ready for next instr assign id_in_ready_o = ~stall & ~halt_if & ~retain_id; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv index 77186a823..c4795d60f 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv @@ -21,7 +21,6 @@ module cve2_core import cve2_pkg::*; #( parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, parameter rv32b_e RV32B = RV32BNone, - parameter bit WritebackStage = 1'b0, parameter bit BranchPredictor = 1'b0, parameter bit DbgTriggerEn = 1'b0, parameter int unsigned DbgHwBreakNum = 1, @@ -126,7 +125,6 @@ module cve2_core import cve2_pkg::*; #( logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage logic [31:0] pc_if; // Program counter in IF stage logic [31:0] pc_id; // Program counter in ID stage - logic [31:0] pc_wb; // Program counter in WB stage logic [33:0] imd_val_d_ex[2]; // Intermediate register for multicycle Ops logic [33:0] imd_val_q_ex[2]; // Intermediate register for multicycle Ops logic [1:0] imd_val_we_ex; @@ -167,7 +165,6 @@ module cve2_core import cve2_pkg::*; #( logic [31:0] rf_wdata_wb; // Writeback register write data that can be used on the forwarding path (doesn't factor in memory // read data as this is too late for the forwarding path) - logic [31:0] rf_wdata_fwd_wb; logic [31:0] rf_wdata_lsu; logic rf_we_wb; logic rf_we_lsu; @@ -193,7 +190,6 @@ module cve2_core import cve2_pkg::*; #( logic [1:0] multdiv_signed_mode_ex; logic [31:0] multdiv_operand_a_ex; logic [31:0] multdiv_operand_b_ex; - logic multdiv_ready_id; // CSR control logic csr_access; @@ -212,7 +208,6 @@ module cve2_core import cve2_pkg::*; #( logic lsu_sign_ext; logic lsu_req; logic [31:0] lsu_wdata; - logic lsu_req_done; // stall control logic id_in_ready; @@ -225,13 +220,8 @@ module cve2_core import cve2_pkg::*; #( logic instr_req_int; // Id stage asserts a req to instruction core interface logic instr_req_gated; - // Writeback stage - logic en_wb; - wb_instr_type_e instr_type_wb; - logic ready_wb; - logic rf_write_wb; - logic outstanding_load_wb; - logic outstanding_store_wb; + // Writeback + logic en_wb; // Interrupts logic nmi_mode; @@ -248,7 +238,6 @@ module cve2_core import cve2_pkg::*; #( logic csr_save_if; logic csr_save_id; - logic csr_save_wb; logic csr_restore_mret_id; logic csr_restore_dret_id; logic csr_save_cause; @@ -271,12 +260,9 @@ module cve2_core import cve2_pkg::*; #( // signals relating to instruction movements between pipeline stages // used by performance counters and RVFI logic instr_id_done; - logic instr_done_wb; logic perf_instr_ret_wb; logic perf_instr_ret_compressed_wb; - logic perf_instr_ret_wb_spec; - logic perf_instr_ret_compressed_wb_spec; logic perf_iside_wait; logic perf_dside_wait; logic perf_wfi_wait; @@ -376,7 +362,6 @@ module cve2_core import cve2_pkg::*; #( .RV32E (RV32E), .RV32M (RV32M), .RV32B (RV32B), - .WritebackStage (WritebackStage), .BranchPredictor(BranchPredictor) ) id_stage_i ( .clk_i (clk_i), @@ -436,7 +421,6 @@ module cve2_core import cve2_pkg::*; #( .multdiv_signed_mode_ex_o(multdiv_signed_mode_ex), .multdiv_operand_a_ex_o (multdiv_operand_a_ex), .multdiv_operand_b_ex_o (multdiv_operand_b_ex), - .multdiv_ready_id_o (multdiv_ready_id), // CSR ID/EX .csr_access_o (csr_access), @@ -444,7 +428,6 @@ module cve2_core import cve2_pkg::*; #( .csr_op_en_o (csr_op_en), .csr_save_if_o (csr_save_if), // control signal to save PC .csr_save_id_o (csr_save_id), // control signal to save PC - .csr_save_wb_o (csr_save_wb), // control signal to save PC .csr_restore_mret_id_o(csr_restore_mret_id), // restore mstatus upon MRET .csr_restore_dret_id_o(csr_restore_dret_id), // restore mstatus upon MRET .csr_save_cause_o (csr_save_cause), @@ -459,7 +442,6 @@ module cve2_core import cve2_pkg::*; #( .lsu_type_o (lsu_type), // to load store unit .lsu_sign_ext_o(lsu_sign_ext), // to load store unit .lsu_wdata_o (lsu_wdata), // to load store unit - .lsu_req_done_i(lsu_req_done), // from load store unit .lsu_addr_incr_req_i(lsu_addr_incr_req), .lsu_addr_last_i (lsu_addr_last), @@ -497,19 +479,9 @@ module cve2_core import cve2_pkg::*; #( .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_b_wb_match_o(), - .rf_waddr_wb_i (rf_waddr_wb), - .rf_wdata_fwd_wb_i(rf_wdata_fwd_wb), - .rf_write_wb_i (rf_write_wb), - - .en_wb_o (en_wb), - .instr_type_wb_o (instr_type_wb), + .en_wb_o (en_wb), .instr_perf_count_id_o (instr_perf_count_id), - .ready_wb_i (ready_wb), - .outstanding_load_wb_i (outstanding_load_wb), - .outstanding_store_wb_i(outstanding_store_wb), // Performance Counters .perf_jump_o (perf_jump), @@ -546,7 +518,6 @@ module cve2_core import cve2_pkg::*; #( .multdiv_signed_mode_i(multdiv_signed_mode_ex), .multdiv_operand_a_i (multdiv_operand_a_ex), .multdiv_operand_b_i (multdiv_operand_b_ex), - .multdiv_ready_id_i (multdiv_ready_id), // Intermediate value register .imd_val_we_o(imd_val_we_ex), @@ -596,7 +567,6 @@ module cve2_core import cve2_pkg::*; #( .lsu_rdata_o (rf_wdata_lsu), .lsu_rdata_valid_o(rf_we_lsu), .lsu_req_i (lsu_req), - .lsu_req_done_o (lsu_req_done), .adder_result_ex_i(alu_adder_result_ex), @@ -616,26 +586,17 @@ module cve2_core import cve2_pkg::*; #( .perf_store_o(perf_store) ); - cve2_wb_stage #( - .WritebackStage(WritebackStage) - ) wb_stage_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .en_wb_i (en_wb), - .instr_type_wb_i (instr_type_wb), - .pc_id_i (pc_id), + cve2_wb #( + ) wb_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .en_wb_i (en_wb), + .instr_is_compressed_id_i(instr_is_compressed_id), .instr_perf_count_id_i (instr_perf_count_id), - .ready_wb_o (ready_wb), - .rf_write_wb_o (rf_write_wb), - .outstanding_load_wb_o (outstanding_load_wb), - .outstanding_store_wb_o (outstanding_store_wb), - .pc_wb_o (pc_wb), .perf_instr_ret_wb_o (perf_instr_ret_wb), .perf_instr_ret_compressed_wb_o (perf_instr_ret_compressed_wb), - .perf_instr_ret_wb_spec_o (perf_instr_ret_wb_spec), - .perf_instr_ret_compressed_wb_spec_o(perf_instr_ret_compressed_wb_spec), .rf_waddr_id_i(rf_waddr_id), .rf_wdata_id_i(rf_wdata_id), @@ -644,16 +605,12 @@ module cve2_core import cve2_pkg::*; #( .rf_wdata_lsu_i(rf_wdata_lsu), .rf_we_lsu_i (rf_we_lsu), - .rf_wdata_fwd_wb_o(rf_wdata_fwd_wb), - .rf_waddr_wb_o(rf_waddr_wb), .rf_wdata_wb_o(rf_wdata_wb), .rf_we_wb_o (rf_we_wb), .lsu_resp_valid_i(lsu_resp_valid), - .lsu_resp_err_i (lsu_resp_err), - - .instr_done_wb_o(instr_done_wb) + .lsu_resp_err_i (lsu_resp_err) ); /////////////////////// @@ -680,19 +637,7 @@ module cve2_core import cve2_pkg::*; #( assign outstanding_store_id = id_stage_i.instr_executing & id_stage_i.lsu_req_dec & id_stage_i.lsu_we; - if (WritebackStage) begin : gen_wb_stage - // When the writeback stage is present a load/store could be in ID or WB. A Load/store in ID can - // see a response before it moves to WB when it is unaligned otherwise we should only see - // a response when load/store is in WB. - assign outstanding_load_resp = outstanding_load_wb | - (outstanding_load_id & load_store_unit_i.split_misaligned_access); - - assign outstanding_store_resp = outstanding_store_wb | - (outstanding_store_id & load_store_unit_i.split_misaligned_access); - - // When writing back the result of a load, the load must have made it to writeback - `ASSERT(NoMemRFWriteWithoutPendingLoad, rf_we_lsu |-> outstanding_load_wb, clk_i, !rst_ni) - end else begin : gen_no_wb_stage + begin : gen_no_wb_stage // Without writeback stage only look into whether load or store is in ID to determine if // a response is expected. assign outstanding_load_resp = outstanding_load_id; @@ -711,7 +656,7 @@ module cve2_core import cve2_pkg::*; #( cve2_register_file_ff #( .RV32E (RV32E), .DataWidth (32), - .WordZeroVal (32'0) + .WordZeroVal (32'h0) ) register_file_i ( .clk_i (clk_i), .rst_ni(rst_ni), @@ -797,11 +742,9 @@ module cve2_core import cve2_pkg::*; #( .pc_if_i(pc_if), .pc_id_i(pc_id), - .pc_wb_i(pc_wb), .csr_save_if_i (csr_save_if), .csr_save_id_i (csr_save_id), - .csr_save_wb_i (csr_save_wb), .csr_restore_mret_i(csr_restore_mret_id), .csr_restore_dret_i(csr_restore_dret_id), .csr_save_cause_i (csr_save_cause), @@ -812,8 +755,6 @@ module cve2_core import cve2_pkg::*; #( // performance counter related signals .instr_ret_i (perf_instr_ret_wb), .instr_ret_compressed_i (perf_instr_ret_compressed_wb), - .instr_ret_spec_i (perf_instr_ret_wb_spec), - .instr_ret_compressed_spec_i(perf_instr_ret_compressed_wb_spec), .iside_wait_i (perf_iside_wait), .jump_i (perf_jump), .branch_i (perf_branch), @@ -890,7 +831,7 @@ module cve2_core import cve2_pkg::*; #( // second stage. RVFI outputs are all straight from flops. So 2 stage pipeline requires a single // set of flops (instr_info => RVFI_out), 3 stage pipeline requires two sets (instr_info => wb // => RVFI_out) - localparam int RVFI_STAGES = WritebackStage ? 2 : 1; + localparam int RVFI_STAGES = 1; logic rvfi_stage_valid [RVFI_STAGES]; logic [63:0] rvfi_stage_order [RVFI_STAGES]; @@ -947,10 +888,8 @@ module cve2_core import cve2_pkg::*; #( logic [31:0] rvfi_mem_addr_d; logic [31:0] rvfi_mem_addr_q; logic rvfi_trap_id; - logic rvfi_trap_wb; logic [63:0] rvfi_stage_order_d; logic rvfi_id_done; - logic rvfi_wb_done; logic new_debug_req; logic new_nmi; @@ -1023,41 +962,7 @@ module cve2_core import cve2_pkg::*; #( assign rvfi_id_done = instr_id_done | (id_stage_i.controller_i.rvfi_flush_next & id_stage_i.controller_i.id_exception_o); - if (WritebackStage) begin : gen_rvfi_wb_stage - logic unused_instr_new_id; - - assign unused_instr_new_id = instr_new_id; - - // With writeback stage first RVFI stage buffers instruction information captured in ID/EX - // awaiting instruction retirement and RF Write data/Mem read data whilst instruction is in WB - // So first stage becomes valid when instruction leaves ID/EX stage and remains valid until - // instruction leaves WB - assign rvfi_stage_valid_d[0] = rvfi_id_done | - (rvfi_stage_valid[0] & ~rvfi_wb_done); - // Second stage is output stage so simple valid cycle after instruction leaves WB (and so has - // retired) - assign rvfi_stage_valid_d[1] = rvfi_wb_done; - - // Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB) - logic rvfi_instr_new_wb_q; - - // Signal new instruction in WB either when one has just entered or when a trap is progressing - // through the tracking pipeline - assign rvfi_instr_new_wb = rvfi_instr_new_wb_q | (rvfi_stage_valid[0] & rvfi_stage_trap[0]); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rvfi_instr_new_wb_q <= 0; - end else begin - rvfi_instr_new_wb_q <= rvfi_id_done; - end - end - - assign rvfi_trap_id = id_stage_i.controller_i.id_exception_o; - assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu; - // WB is instantly done in the tracking pipeline when a trap is progress through the pipeline - assign rvfi_wb_done = instr_done_wb | (rvfi_stage_valid[0] & rvfi_stage_trap[0]); - end else begin : gen_rvfi_no_wb_stage + begin : gen_rvfi_no_wb_stage // Without writeback stage first RVFI stage is output stage so simply valid the cycle after // instruction leaves ID/EX (and so has retired) assign rvfi_stage_valid_d[0] = rvfi_id_done; @@ -1065,8 +970,6 @@ module cve2_core import cve2_pkg::*; #( // setup register write signals assign rvfi_instr_new_wb = instr_new_id; assign rvfi_trap_id = id_stage_i.controller_i.exc_req_d | id_stage_i.controller_i.exc_req_lsu; - assign rvfi_trap_wb = 1'b0; - assign rvfi_wb_done = instr_done_wb; end assign rvfi_stage_order_d = rvfi_stage_order[0] + 64'd1; @@ -1204,9 +1107,8 @@ module cve2_core import cve2_pkg::*; #( rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o; end end else begin - if (rvfi_wb_done) begin rvfi_stage_halt[i] <= rvfi_stage_halt[i-1]; - rvfi_stage_trap[i] <= rvfi_stage_trap[i-1] | rvfi_trap_wb; + rvfi_stage_trap[i] <= rvfi_stage_trap[i-1]; rvfi_stage_intr[i] <= rvfi_stage_intr[i-1]; rvfi_stage_order[i] <= rvfi_stage_order[i-1]; rvfi_stage_insn[i] <= rvfi_stage_insn[i-1]; @@ -1237,7 +1139,6 @@ module cve2_core import cve2_pkg::*; #( rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i]; rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i]; rvfi_ext_stage_mcycle[i] <= rvfi_ext_stage_mcycle[i-1]; - end end end end @@ -1390,10 +1291,9 @@ module cve2_core import cve2_pkg::*; #( end `else - logic unused_instr_new_id, unused_instr_id_done, unused_instr_done_wb; + logic unused_instr_new_id, unused_instr_id_done; assign unused_instr_id_done = instr_id_done; assign unused_instr_new_id = instr_new_id; - assign unused_instr_done_wb = instr_done_wb; `endif endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv index 0b3c206f7..1097adeb0 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv @@ -77,12 +77,10 @@ module cve2_cs_registers #( input logic [31:0] pc_if_i, input logic [31:0] pc_id_i, - input logic [31:0] pc_wb_i, // Exception save/restore input logic csr_save_if_i, input logic csr_save_id_i, - input logic csr_save_wb_i, input logic csr_restore_mret_i, input logic csr_restore_dret_i, input logic csr_save_cause_i, @@ -94,8 +92,6 @@ module cve2_cs_registers #( // Performance Counters input logic instr_ret_i, // instr retired in ID/EX stage input logic instr_ret_compressed_i, // compressed instr retired - input logic instr_ret_spec_i, // speculative instr_ret_i - input logic instr_ret_compressed_spec_i, // speculative instr_ret_compressed_i input logic iside_wait_i, // core waiting for the iside input logic jump_i, // jump instr seen (j, jr, jal, jalr) input logic branch_i, // branch instr seen (bf, bnf) @@ -219,7 +215,7 @@ module cve2_cs_registers #( logic unused_mhpmcounterh_we_1; logic unused_mhpmcounter_incr_1; - logic [63:0] minstret_next, minstret_raw; + logic [63:0] minstret_raw; // Debug / trigger registers logic [31:0] tselect_rdata; @@ -623,9 +619,6 @@ module cve2_cs_registers #( csr_save_id_i: begin exception_pc = pc_id_i; end - csr_save_wb_i: begin - exception_pc = pc_wb_i; - end default:; endcase @@ -1227,7 +1220,7 @@ module cve2_cs_registers #( .counter_we_i(mhpmcounter_we[2]), .counter_val_i(csr_wdata_int), .counter_val_o(minstret_raw), - .counter_val_upd_o(minstret_next) + .counter_val_upd_o() ); // Where the writeback stage is present instruction in ID observing value of minstret must take @@ -1237,7 +1230,7 @@ module cve2_cs_registers #( // so the incorrect value doesn't matter. A similar behaviour is required for the compressed // instruction retired counter below. When the writeback stage isn't present the speculative // signals are always 0. - assign mhpmcounter[2] = instr_ret_spec_i & ~mcountinhibit[2] ? minstret_next : minstret_raw; + assign mhpmcounter[2] = minstret_raw; // reserved: assign mhpmcounter[1] = '0; @@ -1270,7 +1263,6 @@ module cve2_cs_registers #( // Special behaviour for reading compressed instruction retired counter, see comment on // `mhpmcounter[2]` above for further information. assign mhpmcounter[Cnt] = - instr_ret_compressed_spec_i & ~mcountinhibit[Cnt] ? mhpmcounter_next: mhpmcounter_raw; end else begin : gen_other_cnts logic [63:0] unused_mhpmcounter_next; @@ -1280,11 +1272,6 @@ module cve2_cs_registers #( end end else begin : gen_unimp assign mhpmcounter[Cnt] = '0; - - if (Cnt == 10) begin : gen_no_compressed_instr_cnt - logic unused_instr_ret_compressed_spec_i; - assign unused_instr_ret_compressed_spec_i = instr_ret_compressed_spec_i; - end end end diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv index 683191a75..98713a3d8 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv @@ -30,7 +30,6 @@ module cve2_ex_block #( input logic [1:0] multdiv_signed_mode_i, input logic [31:0] multdiv_operand_a_i, input logic [31:0] multdiv_operand_b_i, - input logic multdiv_ready_id_i, // intermediate val reg output logic [1:0] imd_val_we_o, @@ -138,7 +137,7 @@ module cve2_ex_block #( .imd_val_q_i (imd_val_q_i), .imd_val_d_o (multdiv_imd_val_d), .imd_val_we_o (multdiv_imd_val_we), - .multdiv_ready_id_i(multdiv_ready_id_i), + .multdiv_ready_id_i(1'b1), .multdiv_result_o (multdiv_result) ); end else if (RV32M == RV32MFast || RV32M == RV32MSingleCycle) begin : gen_multdiv_fast @@ -163,7 +162,6 @@ module cve2_ex_block #( .imd_val_q_i (imd_val_q_i), .imd_val_d_o (multdiv_imd_val_d), .imd_val_we_o (multdiv_imd_val_we), - .multdiv_ready_id_i(multdiv_ready_id_i), .valid_o (multdiv_valid), .multdiv_result_o (multdiv_result) ); diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv index cbb19e030..bac0a6982 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv @@ -21,7 +21,6 @@ module cve2_id_stage #( parameter bit RV32E = 0, parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone, - parameter bit WritebackStage = 0, parameter bit BranchPredictor = 0 ) ( input logic clk_i, @@ -82,7 +81,6 @@ module cve2_id_stage #( output logic [1:0] multdiv_signed_mode_ex_o, output logic [31:0] multdiv_operand_a_ex_o, output logic [31:0] multdiv_operand_b_ex_o, - output logic multdiv_ready_id_o, // CSR output logic csr_access_o, @@ -90,7 +88,6 @@ module cve2_id_stage #( output logic csr_op_en_o, output logic csr_save_if_o, output logic csr_save_id_o, - output logic csr_save_wb_o, output logic csr_restore_mret_id_o, output logic csr_restore_dret_id_o, output logic csr_save_cause_o, @@ -106,11 +103,6 @@ module cve2_id_stage #( output logic lsu_sign_ext_o, output logic [31:0] lsu_wdata_o, - input logic lsu_req_done_i, // Data req to LSU is complete and - // instruction can move to writeback - // (only relevant where writeback stage is - // present) - input logic lsu_addr_incr_req_i, input logic [31:0] lsu_addr_last_i, @@ -150,20 +142,9 @@ module cve2_id_stage #( 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, - input logic [31:0] rf_wdata_fwd_wb_i, - input logic rf_write_wb_i, output logic en_wb_o, - output cve2_pkg::wb_instr_type_e instr_type_wb_o, output logic instr_perf_count_id_o, - input logic ready_wb_i, - input logic outstanding_load_wb_i, - input logic outstanding_store_wb_i, // Performance Counters output logic perf_jump_o, // executing a jump instr @@ -186,9 +167,6 @@ module cve2_id_stage #( logic ecall_insn_dec; logic wfi_insn_dec; - logic wb_exception; - logic id_exception; - logic branch_in_dec; logic branch_set, branch_set_raw, branch_set_raw_d; logic branch_jump_set_done_q, branch_jump_set_done_d; @@ -202,13 +180,11 @@ module cve2_id_stage #( logic instr_executing; logic instr_done; logic controller_run; - logic stall_ld_hz; logic stall_mem; logic stall_multdiv; logic stall_branch; logic stall_jump; logic stall_id; - logic stall_wb; logic flush_id; logic multicycle_done; @@ -474,7 +450,6 @@ module cve2_id_stage #( assign illegal_insn_o = instr_valid_i & (illegal_insn_dec | illegal_csr_insn_i); cve2_controller #( - .WritebackStage (WritebackStage), .BranchPredictor(BranchPredictor) ) controller_i ( .clk_i (clk_i), @@ -519,9 +494,7 @@ module cve2_id_stage #( .lsu_addr_last_i(lsu_addr_last_i), .load_err_i (lsu_load_err_i), .store_err_i (lsu_store_err_i), - .wb_exception_o (wb_exception), - .id_exception_o (id_exception), - + .id_exception_o (), // jump/branch control .branch_set_i (branch_set), .branch_not_set_i (branch_not_set), @@ -537,7 +510,6 @@ module cve2_id_stage #( // CSR Controller Signals .csr_save_if_o (csr_save_if_o), .csr_save_id_o (csr_save_id_o), - .csr_save_wb_o (csr_save_wb_o), .csr_restore_mret_id_o(csr_restore_mret_id_o), .csr_restore_dret_id_o(csr_restore_dret_id_o), .csr_save_cause_o (csr_save_cause_o), @@ -556,9 +528,7 @@ module cve2_id_stage #( .trigger_match_i (trigger_match_i), .stall_id_i(stall_id), - .stall_wb_i(stall_wb), .flush_id_o(flush_id), - .ready_wb_i(ready_wb_i), // Performance Counters .perf_jump_o (perf_jump_o), @@ -692,13 +662,9 @@ module cve2_id_stage #( FIRST_CYCLE: begin unique case (1'b1) lsu_req_dec: begin - if (!WritebackStage) begin + begin // LSU operation id_fsm_d = MULTI_CYCLE; - end else begin - if(~lsu_req_done_i) begin - id_fsm_d = MULTI_CYCLE; - end end end multdiv_en_dec: begin @@ -749,7 +715,7 @@ module cve2_id_stage #( rf_we_raw = rf_we_dec & ex_valid_i; end - if (multicycle_done & ready_wb_i) begin + if (multicycle_done) begin id_fsm_d = FIRST_CYCLE; end else begin stall_multdiv = multdiv_en_dec; @@ -765,22 +731,19 @@ module cve2_id_stage #( end end - // Note for the two-stage configuration ready_wb_i is always set - assign multdiv_ready_id_o = ready_wb_i; - `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, update assertion below if // modifying this. - assign stall_id = stall_ld_hz | stall_mem | stall_multdiv | stall_jump | stall_branch | + assign stall_id = 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)) + ~(stall_multdiv | stall_jump | stall_branch | stall_alu)) assign instr_done = ~stall_id & ~flush_id & instr_executing; @@ -791,119 +754,6 @@ module cve2_id_stage #( // Used by ALU to access RS3 if ternary instruction. assign instr_first_cycle_id_o = instr_first_cycle; - if (WritebackStage) begin : gen_stall_mem - // Register read address matches write address in WB - logic rf_rd_a_wb_match; - logic rf_rd_b_wb_match; - // Hazard between registers being read and written - logic rf_rd_a_hz; - logic rf_rd_b_hz; - - logic outstanding_memory_access; - - logic instr_kill; - - assign multicycle_done = lsu_req_dec ? ~stall_mem : ex_valid_i; - - // Is a memory access ongoing that isn't finishing this cycle - assign outstanding_memory_access = (outstanding_load_wb_i | outstanding_store_wb_i) & - ~lsu_resp_valid_i; - - // Can start a new memory access if any previous one has finished or is finishing - assign data_req_allowed = ~outstanding_memory_access; - - // Instruction won't execute because: - // - There is a pending exception in writeback - // The instruction in ID/EX will be flushed and the core will jump to an exception handler - // - The controller isn't running instructions - // This either happens in preparation for a flush and jump to an exception handler e.g. in - // response to an IRQ or debug request or whilst the core is sleeping or resetting/fetching - // first instruction in which case any valid instruction in ID/EX should be ignored. - // - There was an error on instruction fetch - assign instr_kill = instr_fetch_err_i | - wb_exception | - id_exception | - ~controller_run; - - // With writeback stage instructions must be prevented from executing if there is: - // - A load hazard - // - A pending memory access - // If it receives an error response this results in a precise exception from WB so ID/EX - // instruction must not execute until error response is known). - // - A load/store error - // This will cause a precise exception for the instruction in WB so ID/EX instruction must not - // execute - // - // instr_executing_spec is a speculative signal. It indicates an instruction can execute - // assuming there are no exceptions from writeback and any outstanding memory access won't - // receive an error. It is required so branch and jump requests don't factor in an incoming dmem - // error (that in turn would factor directly into imem requests leading to a feedthrough path). - // - // instr_executing is the full signal, it will only allow execution once any potential - // exceptions from writeback have been resolved. - assign instr_executing_spec = instr_valid_i & - ~instr_fetch_err_i & - controller_run & - ~stall_ld_hz; - - assign instr_executing = instr_valid_i & - ~instr_kill & - ~stall_ld_hz & - ~outstanding_memory_access; - - `ASSERT(IbexExecutingSpecIfExecuting, instr_executing |-> instr_executing_spec) - - `ASSERT(IbexStallIfValidInstrNotExecuting, - instr_valid_i & ~instr_kill & ~instr_executing |-> stall_id) - - `ASSERT(IbexCannotRetireWithPendingExceptions, - instr_done |-> ~(wb_exception | outstanding_memory_access)) - - // Stall for reasons related to memory: - // * There is an outstanding memory access that won't resolve this cycle (need to wait to allow - // precise exceptions) - // * There is a load/store request not being granted or which is unaligned and waiting to issue - // a second request (needs to stay in ID for the address calculation) - assign stall_mem = instr_valid_i & - (outstanding_memory_access | (lsu_req_dec & ~lsu_req_done_i)); - - // If we stall a load in ID for any reason, it must not make an LSU request - // (otherwide we might issue two requests for the same instruction) - `ASSERT(IbexStallMemNoRequest, - instr_valid_i & lsu_req_dec & ~instr_done |-> ~lsu_req_done_i) - - 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; - assign rf_rd_b_hz = rf_rd_b_wb_match & rf_ren_b; - - // If instruction is read register that writeback is writing forward writeback data to read - // data. Note this doesn't factor in load data as it arrives too late, such hazards are - // resolved via a stall (see above). - assign rf_rdata_a_fwd = rf_rd_a_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_a_i; - assign rf_rdata_b_fwd = rf_rd_b_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_b_i; - - assign stall_ld_hz = outstanding_load_wb_i & (rf_rd_a_hz | rf_rd_b_hz); - - assign instr_type_wb_o = ~lsu_req_dec ? WB_INSTR_OTHER : - lsu_we ? WB_INSTR_STORE : - WB_INSTR_LOAD; - - assign instr_id_done_o = en_wb_o & ready_wb_i; - - // Stall ID/EX as instruction in ID/EX cannot proceed to writeback yet - assign stall_wb = en_wb_o & ~ready_wb_i; - - assign perf_dside_wait_o = instr_valid_i & ~instr_kill & - (outstanding_memory_access | stall_ld_hz); - end else begin : gen_no_stall_mem - assign multicycle_done = lsu_req_dec ? lsu_resp_valid_i : ex_valid_i; assign data_req_allowed = instr_first_cycle; @@ -912,9 +762,6 @@ module cve2_id_stage #( // Then stall until it is complete assign stall_mem = instr_valid_i & (lsu_req_dec & (~lsu_resp_valid_i | instr_first_cycle)); - // No load hazards without Writeback Stage - assign stall_ld_hz = 1'b0; - // Without writeback stage any valid instruction that hasn't seen an error will execute assign instr_executing_spec = instr_valid_i & ~instr_fetch_err_i & controller_run; assign instr_executing = instr_executing_spec; @@ -927,45 +774,21 @@ module cve2_id_stage #( 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 logic unused_data_req_done_ex; - logic [4:0] unused_rf_waddr_wb; - logic unused_rf_write_wb; - logic unused_outstanding_load_wb; - logic unused_outstanding_store_wb; - logic unused_wb_exception; - logic [31:0] unused_rf_wdata_fwd_wb; - logic unused_id_exception; - - assign unused_data_req_done_ex = lsu_req_done_i; - assign unused_rf_waddr_wb = rf_waddr_wb_i; - assign unused_rf_write_wb = rf_write_wb_i; - 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_wdata_fwd_wb = rf_wdata_fwd_wb_i; - assign unused_id_exception = id_exception; - - assign instr_type_wb_o = WB_INSTR_OTHER; - assign stall_wb = 1'b0; assign perf_dside_wait_o = instr_executing & lsu_req_dec & ~lsu_resp_valid_i; assign instr_id_done_o = instr_done; - end // Signal which instructions to count as retired in minstret, all traps along with ebrk and // ecall instructions are not counted. assign instr_perf_count_id_o = ~ebrk_insn & ~ecall_insn_dec & ~illegal_insn_dec & ~illegal_csr_insn_i & ~instr_fetch_err_i; - // An instruction is ready to move to the writeback stage (or retire if there is no writeback - // stage) + // An instruction is ready to move to the writeback assign en_wb_o = instr_done; assign perf_wfi_wait_o = wfi_insn_dec; @@ -975,8 +798,8 @@ module cve2_id_stage #( // FCOV // ////////// - `DV_FCOV_SIGNAL_GEN_IF(logic, rf_rd_wb_hz, - (gen_stall_mem.rf_rd_a_hz | gen_stall_mem.rf_rd_b_hz) & instr_valid_i, WritebackStage) + `DV_FCOV_SIGNAL(logic, branch_taken, + instr_executing & (id_fsm_q == FIRST_CYCLE) & branch_decision_i) `DV_FCOV_SIGNAL(logic, branch_not_taken, instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i) diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv index 548e75c8f..3575fadf9 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv @@ -50,10 +50,6 @@ module cve2_load_store_unit // -> mtval // -> AGU for misaligned accesses - output logic lsu_req_done_o, // Signals that data request is complete - // (only need to await final data - // response) -> to ID/EX - output logic lsu_resp_valid_o, // LSU has response from transaction -> to ID/EX // exception signals @@ -453,8 +449,6 @@ module cve2_load_store_unit endcase end - assign lsu_req_done_o = (lsu_req_i | (ls_fsm_cs != IDLE)) & (ls_fsm_ns == IDLE); - // registers for FSM always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv index 0f9b9549b..d1d400a31 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv @@ -38,8 +38,6 @@ module cve2_multdiv_fast #( output logic [33:0] imd_val_d_o[2], output logic [1:0] imd_val_we_o, - input logic multdiv_ready_id_i, - output logic [31:0] multdiv_result_o, output logic valid_o ); @@ -209,7 +207,7 @@ module cve2_multdiv_fast #( mult_valid = 1'b0; mult_state_d = MULH; end else begin - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end end @@ -228,7 +226,7 @@ module cve2_multdiv_fast #( mult_state_d = MULL; mult_valid = 1'b1; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end default: begin @@ -327,7 +325,7 @@ module cve2_multdiv_fast #( // Note no state transition will occur if mult_hold is set mult_state_d = ALBL; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end else begin accum = imd_val_q_i[0]; mac_res_d = mac_res; @@ -350,7 +348,7 @@ module cve2_multdiv_fast #( // Note no state transition will occur if mult_hold is set mult_state_d = ALBL; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end default: begin mult_state_d = ALBL; @@ -507,7 +505,7 @@ module cve2_multdiv_fast #( // Hold result until ID stage is ready to accept it // Note no state transition will occur if div_hold is set md_state_d = MD_IDLE; - div_hold = ~multdiv_ready_id_i; + div_hold = 1'b0; div_valid = 1'b1; end diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv index eca87741e..caa56b10e 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -17,7 +17,6 @@ module cve2_top import cve2_pkg::*; #( parameter int unsigned MHPMCounterWidth = 40, parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, - parameter bit WritebackStage = 1'b0, parameter bit BranchPredictor = 1'b0, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 @@ -163,7 +162,6 @@ module cve2_top import cve2_pkg::*; #( .BranchPredictor (BranchPredictor), .DbgTriggerEn (DbgTriggerEn), .DbgHwBreakNum (DbgHwBreakNum), - .WritebackStage (WritebackStage), .DmHaltAddr (DmHaltAddr), .DmExceptionAddr (DmExceptionAddr) ) u_cve2_core ( diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv index 9a8bec32d..04d891885 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv @@ -12,7 +12,6 @@ module cve2_top_tracing import cve2_pkg::*; #( parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, parameter rv32b_e RV32B = RV32BNone, - parameter bit WritebackStage = 1'b0, parameter bit BranchPredictor = 1'b0, parameter bit DbgTriggerEn = 1'b0, parameter int unsigned DbgHwBreakNum = 1, @@ -126,7 +125,6 @@ module cve2_top_tracing import cve2_pkg::*; #( .BranchPredictor ( BranchPredictor ), .DbgTriggerEn ( DbgTriggerEn ), .DbgHwBreakNum ( DbgHwBreakNum ), - .WritebackStage ( WritebackStage ), .DmHaltAddr ( DmHaltAddr ), .DmExceptionAddr ( DmExceptionAddr ) ) u_cve2_top ( diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv new file mode 100644 index 000000000..dee73f74e --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv @@ -0,0 +1,69 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Writeback passthrough + * + * The writeback stage is not present therefore this module acts as + * a simple passthrough to write data direct to the register file. + */ + +`include "prim_assert.sv" +`include "dv_fcov_macros.svh" + +module cve2_wb #( +) ( + input logic clk_i, + input logic rst_ni, + input logic en_wb_i, + + input logic instr_is_compressed_id_i, + input logic instr_perf_count_id_i, + + output logic perf_instr_ret_wb_o, + output logic perf_instr_ret_compressed_wb_o, + + input logic [4:0] rf_waddr_id_i, + input logic [31:0] rf_wdata_id_i, + input logic rf_we_id_i, + + input logic [31:0] rf_wdata_lsu_i, + input logic rf_we_lsu_i, + + output logic [4:0] rf_waddr_wb_o, + output logic [31:0] rf_wdata_wb_o, + output logic rf_we_wb_o, + + input logic lsu_resp_valid_i, + input logic lsu_resp_err_i +); + + import cve2_pkg::*; + + // 0 == RF write from ID + // 1 == RF write from LSU + logic [31:0] rf_wdata_wb_mux [2]; + logic [1:0] rf_wdata_wb_mux_we; + + // without writeback stage just pass through register write signals + assign rf_waddr_wb_o = rf_waddr_id_i; + assign rf_wdata_wb_mux[0] = rf_wdata_id_i; + assign rf_wdata_wb_mux_we[0] = rf_we_id_i; + + // Increment instruction retire counters for valid instructions which are not lsu errors. + assign perf_instr_ret_wb_o = instr_perf_count_id_i & en_wb_i & + ~(lsu_resp_valid_i & lsu_resp_err_i); + assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i; + + assign rf_wdata_wb_mux[1] = rf_wdata_lsu_i; + assign rf_wdata_wb_mux_we[1] = rf_we_lsu_i; + + // RF write data can come from ID results (all RF writes that aren't because of loads will come + // from here) or the LSU (RF writes for load data) + assign rf_wdata_wb_o = ({32{rf_wdata_wb_mux_we[0]}} & rf_wdata_wb_mux[0]) | + ({32{rf_wdata_wb_mux_we[1]}} & rf_wdata_wb_mux[1]); + assign rf_we_wb_o = |rf_wdata_wb_mux_we; + + `ASSERT(RFWriteFromOneSourceOnly, $onehot0(rf_wdata_wb_mux_we)) +endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb_stage.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb_stage.sv deleted file mode 100644 index 7e9af8dab..000000000 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb_stage.sv +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Writeback Stage - * - * Writeback is an optional third pipeline stage. It writes data back to the register file that was - * produced in the ID/EX stage or awaits a response to a load/store (LSU writes direct to register - * file for load data). If the writeback stage is not present (WritebackStage == 0) this acts as - * a simple passthrough to write data direct to the register file. - */ - -`include "prim_assert.sv" -`include "dv_fcov_macros.svh" - -module cve2_wb_stage #( - parameter bit WritebackStage = 1'b0 -) ( - input logic clk_i, - input logic rst_ni, - - input logic en_wb_i, - input cve2_pkg::wb_instr_type_e instr_type_wb_i, - input logic [31:0] pc_id_i, - input logic instr_is_compressed_id_i, - input logic instr_perf_count_id_i, - - output logic ready_wb_o, - output logic rf_write_wb_o, - output logic outstanding_load_wb_o, - output logic outstanding_store_wb_o, - output logic [31:0] pc_wb_o, - output logic perf_instr_ret_wb_o, - output logic perf_instr_ret_compressed_wb_o, - output logic perf_instr_ret_wb_spec_o, - output logic perf_instr_ret_compressed_wb_spec_o, - - input logic [4:0] rf_waddr_id_i, - input logic [31:0] rf_wdata_id_i, - input logic rf_we_id_i, - - input logic [31:0] rf_wdata_lsu_i, - input logic rf_we_lsu_i, - - output logic [31:0] rf_wdata_fwd_wb_o, - - output logic [4:0] rf_waddr_wb_o, - output logic [31:0] rf_wdata_wb_o, - output logic rf_we_wb_o, - - input logic lsu_resp_valid_i, - input logic lsu_resp_err_i, - - output logic instr_done_wb_o -); - - import cve2_pkg::*; - - // 0 == RF write from ID - // 1 == RF write from LSU - logic [31:0] rf_wdata_wb_mux [2]; - logic [1:0] rf_wdata_wb_mux_we; - - if (WritebackStage) begin : g_writeback_stage - logic [31:0] rf_wdata_wb_q; - logic rf_we_wb_q; - logic [4:0] rf_waddr_wb_q; - - logic wb_done; - - logic wb_valid_q; - logic [31:0] wb_pc_q; - logic wb_compressed_q; - logic wb_count_q; - wb_instr_type_e wb_instr_type_q; - - logic wb_valid_d; - - // Stage becomes valid if an instruction enters for ID/EX and valid is cleared when instruction - // is done - assign wb_valid_d = (en_wb_i & ready_wb_o) | (wb_valid_q & ~wb_done); - - // Writeback for non load/store instructions always completes in a cycle (so instantly done) - // Writeback for load/store must wait for response to be received by the LSU - // Signal only relevant if wb_valid_q set - assign wb_done = (wb_instr_type_q == WB_INSTR_OTHER) | lsu_resp_valid_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - wb_valid_q <= 1'b0; - end else begin - wb_valid_q <= wb_valid_d; - end - end - - begin : g_wb_regs - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rf_we_wb_q <= '0; - rf_waddr_wb_q <= '0; - rf_wdata_wb_q <= '0; - wb_instr_type_q <= wb_instr_type_e'(0); - wb_pc_q <= '0; - wb_compressed_q <= '0; - wb_count_q <= '0; - end else if (en_wb_i) begin - rf_we_wb_q <= rf_we_id_i; - rf_waddr_wb_q <= rf_waddr_id_i; - rf_wdata_wb_q <= rf_wdata_id_i; - wb_instr_type_q <= instr_type_wb_i; - wb_pc_q <= pc_id_i; - wb_compressed_q <= instr_is_compressed_id_i; - wb_count_q <= instr_perf_count_id_i; - end - end - end - - assign rf_waddr_wb_o = rf_waddr_wb_q; - assign rf_wdata_wb_mux[0] = rf_wdata_wb_q; - assign rf_wdata_wb_mux_we[0] = rf_we_wb_q & wb_valid_q; - - assign ready_wb_o = ~wb_valid_q | wb_done; - - // Instruction in writeback will be writing to register file if either rf_we is set or writeback - // is awaiting load data. This is used for determining RF read hazards in ID/EX - assign rf_write_wb_o = wb_valid_q & (rf_we_wb_q | (wb_instr_type_q == WB_INSTR_LOAD)); - - assign outstanding_load_wb_o = wb_valid_q & (wb_instr_type_q == WB_INSTR_LOAD); - assign outstanding_store_wb_o = wb_valid_q & (wb_instr_type_q == WB_INSTR_STORE); - - assign pc_wb_o = wb_pc_q; - - assign instr_done_wb_o = wb_valid_q & wb_done; - - // Increment instruction retire counters for valid instructions which are not lsu errors. - // Speculative versions of the signals do not factor in exceptions and whether the instruction - // is done yet. These are used to get correct values for instructions reading the relevant - // performance counters in the ID stage. - assign perf_instr_ret_wb_spec_o = wb_count_q; - assign perf_instr_ret_compressed_wb_spec_o = perf_instr_ret_wb_spec_o & wb_compressed_q; - assign perf_instr_ret_wb_o = instr_done_wb_o & wb_count_q & - ~(lsu_resp_valid_i & lsu_resp_err_i); - assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & wb_compressed_q; - - // Forward data that will be written to the RF back to ID to resolve data hazards. The flopped - // rf_wdata_wb_q is used rather than rf_wdata_wb_o as the latter includes read data from memory - // that returns too late to be used on the forwarding path. - assign rf_wdata_fwd_wb_o = rf_wdata_wb_q; - end else begin : g_bypass_wb - // without writeback stage just pass through register write signals - assign rf_waddr_wb_o = rf_waddr_id_i; - assign rf_wdata_wb_mux[0] = rf_wdata_id_i; - assign rf_wdata_wb_mux_we[0] = rf_we_id_i; - - // Increment instruction retire counters for valid instructions which are not lsu errors. - // The speculative signals are always 0 when no writeback stage is present as the raw counter - // values will be correct. - assign perf_instr_ret_wb_spec_o = 1'b0; - assign perf_instr_ret_compressed_wb_spec_o = 1'b0; - assign perf_instr_ret_wb_o = instr_perf_count_id_i & en_wb_i & - ~(lsu_resp_valid_i & lsu_resp_err_i); - assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i; - - // ready needs to be constant 1 without writeback stage (otherwise ID/EX stage will stall) - assign ready_wb_o = 1'b1; - - // Unused Writeback stage only IO & wiring - // Assign inputs and internal wiring to unused signals to satisfy lint checks - // Tie-off outputs to constant values - logic unused_clk; - logic unused_rst; - wb_instr_type_e unused_instr_type_wb; - logic [31:0] unused_pc_id; - - assign unused_clk = clk_i; - assign unused_rst = rst_ni; - assign unused_instr_type_wb = instr_type_wb_i; - assign unused_pc_id = pc_id_i; - - assign outstanding_load_wb_o = 1'b0; - assign outstanding_store_wb_o = 1'b0; - assign pc_wb_o = '0; - assign rf_write_wb_o = 1'b0; - assign rf_wdata_fwd_wb_o = 32'b0; - assign instr_done_wb_o = 1'b0; - end - - assign rf_wdata_wb_mux[1] = rf_wdata_lsu_i; - assign rf_wdata_wb_mux_we[1] = rf_we_lsu_i; - - // RF write data can come from ID results (all RF writes that aren't because of loads will come - // from here) or the LSU (RF writes for load data) - assign rf_wdata_wb_o = ({32{rf_wdata_wb_mux_we[0]}} & rf_wdata_wb_mux[0]) | - ({32{rf_wdata_wb_mux_we[1]}} & rf_wdata_wb_mux[1]); - assign rf_we_wb_o = |rf_wdata_wb_mux_we; - - `DV_FCOV_SIGNAL_GEN_IF(logic, wb_valid, g_writeback_stage.wb_valid_q, WritebackStage) - - `ASSERT(RFWriteFromOneSourceOnly, $onehot0(rf_wdata_wb_mux_we)) -endmodule diff --git a/hw/vendor/openhwgroup_cv32e20/scripts/sec/cadence/sec.tcl b/hw/vendor/openhwgroup_cv32e20/scripts/sec/cadence/sec.tcl index f6d62b8cc..79b8842c2 100644 --- a/hw/vendor/openhwgroup_cv32e20/scripts/sec/cadence/sec.tcl +++ b/hw/vendor/openhwgroup_cv32e20/scripts/sec/cadence/sec.tcl @@ -23,8 +23,7 @@ reset ~rst_ni check_sec -map -auto -check_sec -waive -waive_signals gen_regfile_ff.test_en_i -check_sec -waive -waive_signals cve2_core_imp.gen_regfile_ff.test_en_i +check_sec -waive -waive_signals test_en_i check_sec -prove diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index 2d4a6d327..c6e437676 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/davideschiavone/cve2.git - rev: e168b236496e3f2bb884d3aa2c1f345f6ef344f0 + rev: 721bf75c9bde3cf62edc6ea0432bb422112b3d1e } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index 495a2f7c4..926b0a592 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/davideschiavone/cve2.git", - rev: "e168b236496e3f2bb884d3aa2c1f345f6ef344f0", + rev: "721bf75c9bde3cf62edc6ea0432bb422112b3d1e", }, exclude_from_upstream: [ diff --git a/hw/vendor/waiver/lint/cve2.vlt b/hw/vendor/waiver/lint/cve2.vlt index c9b682a39..7b3fc6bb6 100644 --- a/hw/vendor/waiver/lint/cve2.vlt +++ b/hw/vendor/waiver/lint/cve2.vlt @@ -8,3 +8,4 @@ lint_off -rule DECLFILENAME -file "*bhv/cve2_sim_clock_gate.sv" -match "*Filenam lint_off -rule UNOPTFLAT -file "*rtl/*.sv" -match "*" lint_off -rule UNUSED -file "*rtl/cve2_core.sv" -match "Signal is not used: 'rf_ren_a'*" lint_off -rule UNUSED -file "*rtl/cve2_core.sv" -match "Signal is not used: 'rf_ren_b'*" +lint_off -rule UNUSED -file "*rtl/cve2_wb.sv" -match "Signal is not used:*" From 09e88ee23b122d7f92279c380cf1535f1968d1de Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Thu, 1 Jun 2023 17:41:02 +0200 Subject: [PATCH 04/15] update cve2 remote --- hw/vendor/openhwgroup_cve2.lock.hjson | 4 ++-- hw/vendor/openhwgroup_cve2.vendor.hjson | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index c6e437676..88abd025c 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/davideschiavone/cve2.git - rev: 721bf75c9bde3cf62edc6ea0432bb422112b3d1e + url: https://github.com/openhwgroup/cve2.git + rev: 06c4a0c0e64f713a60011dc69704d67e62c8d078 } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index 926b0a592..6179f0e03 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -6,8 +6,8 @@ target_dir: "openhwgroup_cv32e20", upstream: { - url: "https://github.com/davideschiavone/cve2.git", - rev: "721bf75c9bde3cf62edc6ea0432bb422112b3d1e", + url: "https://github.com/openhwgroup/cve2.git", + rev: "06c4a0c0e64f713a60011dc69704d67e62c8d078", }, exclude_from_upstream: [ From d13a2b43b0cdf7224ea047c58423a9c1ed9aaa0e Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Fri, 11 Aug 2023 11:52:21 +0200 Subject: [PATCH 05/15] update cve2 --- .../rtl/cve2_controller.sv | 2 +- .../rtl/cve2_top_tracing.sv | 26 ++++--------------- hw/vendor/openhwgroup_cve2.lock.hjson | 4 +-- hw/vendor/openhwgroup_cve2.vendor.hjson | 4 +-- 4 files changed, 10 insertions(+), 26 deletions(-) diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 69dd95ab1..5d26fdd95 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -159,7 +159,7 @@ module cve2_controller #( always_ff @(negedge clk_i) begin // print warning in case of decoding errors if ((ctrl_fsm_cs == DECODE) && instr_valid_i && !instr_fetch_err_i && illegal_insn_d) begin - $display("%t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, cve2_core.hart_id_i, + $display("%m @ %t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, cve2_core.hart_id_i, cve2_id_stage.pc_id_i, cve2_id_stage.instr_rdata_i); end end diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv index 3ca0ec673..515c0564a 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 /** - * Top level module of the ibex RISC-V core with tracing enabled + * Top level module of the cve2 RISC-V core with tracing enabled */ module cve2_top_tracing import cve2_pkg::*; #( @@ -11,9 +11,7 @@ module cve2_top_tracing import cve2_pkg::*; #( parameter int unsigned MHPMCounterWidth = 40, parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, + parameter bit BranchPredictor = 1'b0, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -22,7 +20,6 @@ module cve2_top_tracing import cve2_pkg::*; #( input logic rst_ni, input logic test_en_i, // enable all clock gates for testing - input logic scan_rst_ni, input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, @@ -35,7 +32,6 @@ module cve2_top_tracing import cve2_pkg::*; #( input logic instr_rvalid_i, output logic [31:0] instr_addr_o, input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, input logic instr_err_i, // Data memory interface @@ -46,9 +42,7 @@ module cve2_top_tracing import cve2_pkg::*; #( output logic [3:0] data_be_o, output logic [31:0] data_addr_o, output logic [31:0] data_wdata_o, - output logic [6:0] data_wdata_intg_o, input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, input logic data_err_i, // Interrupt inputs @@ -63,9 +57,7 @@ module cve2_top_tracing import cve2_pkg::*; #( output crash_dump_t crash_dump_o, // CPU Control Signals - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, + input logic fetch_enable_i, output logic core_sleep_o ); @@ -120,9 +112,7 @@ module cve2_top_tracing import cve2_pkg::*; #( .MHPMCounterWidth ( MHPMCounterWidth ), .RV32E ( RV32E ), .RV32M ( RV32M ), - .RV32B ( RV32B ), - .DbgTriggerEn ( DbgTriggerEn ), - .DbgHwBreakNum ( DbgHwBreakNum ), + .BranchPredictor ( BranchPredictor ), .DmHaltAddr ( DmHaltAddr ), .DmExceptionAddr ( DmExceptionAddr ) ) u_cve2_top ( @@ -130,7 +120,6 @@ module cve2_top_tracing import cve2_pkg::*; #( .rst_ni, .test_en_i, - .scan_rst_ni, .ram_cfg_i, .hart_id_i, @@ -141,7 +130,6 @@ module cve2_top_tracing import cve2_pkg::*; #( .instr_rvalid_i, .instr_addr_o, .instr_rdata_i, - .instr_rdata_intg_i, .instr_err_i, .data_req_o, @@ -151,9 +139,7 @@ module cve2_top_tracing import cve2_pkg::*; #( .data_be_o, .data_addr_o, .data_wdata_o, - .data_wdata_intg_o, .data_rdata_i, - .data_rdata_intg_i, .data_err_i, .irq_software_i, @@ -193,9 +179,7 @@ module cve2_top_tracing import cve2_pkg::*; #( .rvfi_ext_debug_req, .rvfi_ext_mcycle, - .alert_minor_o, - .alert_major_internal_o, - .alert_major_bus_o, + .fetch_enable_i, .core_sleep_o ); diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index cc4f8ed5c..a0f03d6a7 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/davideschiavone/cve2.git - rev: 2ff63f71a78999460b1b36b7723f87b82c1eb572 + url: https://github.com/openhwgroup/cve2.git + rev: 00f7eb1dd9462e33e8b7b5a27e7b2d2f7e0ef1c8 } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index a3e002847..ba705ce74 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -6,8 +6,8 @@ target_dir: "openhwgroup_cv32e20", upstream: { - url: "https://github.com/davideschiavone/cve2.git", - rev: "2ff63f71a78999460b1b36b7723f87b82c1eb572", + url: "https://github.com/openhwgroup/cve2.git", + rev: "00f7eb1dd9462e33e8b7b5a27e7b2d2f7e0ef1c8", }, exclude_from_upstream: [ From 667721b010c1d23898a9f29ca6a403e3bdcb7142 Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Wed, 16 Aug 2023 15:44:11 +0200 Subject: [PATCH 06/15] update cve2 --- hw/core-v-mini-mcu/cpu_subsystem.sv | 4 +-- .../rtl/cve2_controller.sv | 11 +++--- .../openhwgroup_cv32e20/rtl/cve2_core.sv | 2 +- .../rtl/cve2_cs_registers.sv | 12 +++---- .../openhwgroup_cv32e20/rtl/cve2_if_stage.sv | 10 +++--- hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv | 35 +++++++++---------- hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv | 2 +- hw/vendor/openhwgroup_cve2.lock.hjson | 4 +-- hw/vendor/openhwgroup_cve2.vendor.hjson | 4 +-- 9 files changed, 42 insertions(+), 42 deletions(-) diff --git a/hw/core-v-mini-mcu/cpu_subsystem.sv b/hw/core-v-mini-mcu/cpu_subsystem.sv index 1942325d5..22398443c 100644 --- a/hw/core-v-mini-mcu/cpu_subsystem.sv +++ b/hw/core-v-mini-mcu/cpu_subsystem.sv @@ -89,8 +89,8 @@ module cpu_subsystem .irq_software_i(irq_i[3]), .irq_timer_i (irq_i[7]), .irq_external_i(irq_i[11]), - .irq_fast_i (irq_i[30:16]), - .irq_nm_i (irq_i[31]), + .irq_fast_i (irq_i[31:16]), + .irq_nm_i (1'b0), .debug_req_i (debug_req_i), .crash_dump_o(), diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 5d26fdd95..16ef29dba 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -303,7 +303,7 @@ module cve2_controller #( always_comb begin : gen_mfip_id mfip_id = 4'd0; - for (int i = 14; i >= 0; i--) begin + for (int i = 15; i >= 0; i--) begin if (irqs_i.irq_fast[i]) begin mfip_id = i[3:0]; end @@ -499,12 +499,13 @@ module cve2_controller #( if (irq_nm_i && !nmi_mode_q) begin exc_cause_o = EXC_CAUSE_IRQ_NM; nmi_mode_d = 1'b1; // enter NMI mode - end else if (irqs_i.irq_fast != 15'b0) begin + end else if (irqs_i.irq_fast != 16'b0) begin // generate exception cause ID from fast interrupt ID: // - first bit distinguishes interrupts from exceptions, - // - second bit adds 16 to fast interrupt ID - // for example EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16} - exc_cause_o = exc_cause_e'({2'b11, mfip_id}); + // - third bit adds 16 to fast interrupt ID so that the interrup 0 becomes 16 and the interrupt 15 becomes 31 (hence 5bits) + // - second bit is always 0 as the FAST interrupts are represented in the first 5bits, the 6th is always 0 cause is used by the NMI (in that case is 1 as represented by the number 32) + // for example EXC_CAUSE_IRQ_FAST_0 = {1'b1, 6'd16} + exc_cause_o = exc_cause_e'({3'b101, mfip_id}); end else if (irqs_i.irq_external) begin exc_cause_o = EXC_CAUSE_IRQ_EXTERNAL_M; end else if (irqs_i.irq_software) begin diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv index ea2693c85..600f87890 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv @@ -58,7 +58,7 @@ module cve2_core import cve2_pkg::*; #( input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt output logic irq_pending_o, diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv index 34f30a6de..78bfc6f0d 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv @@ -53,7 +53,7 @@ module cve2_cs_registers #( input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic nmi_mode_i, output logic irq_pending_o, // interrupt request pending output cve2_pkg::irqs_t irqs_o, // interrupt requests qualified with mie @@ -169,7 +169,7 @@ module cve2_cs_registers #( logic mscratch_en; logic [31:0] mepc_q, mepc_d; logic mepc_en; - logic [5:0] mcause_q, mcause_d; + logic [6:0] mcause_q, mcause_d; logic mcause_en; logic [31:0] mtval_q, mtval_d; logic mtval_en; @@ -189,7 +189,7 @@ module cve2_cs_registers #( status_stk_t mstack_q, mstack_d; logic mstack_en; logic [31:0] mstack_epc_q, mstack_epc_d; - logic [5:0] mstack_cause_q, mstack_cause_d; + logic [6:0] mstack_cause_q, mstack_cause_d; // PMP Signals logic [31:0] pmp_addr_rdata [PMP_MAX_REGIONS]; @@ -482,7 +482,7 @@ module cve2_cs_registers #( mepc_en = 1'b0; mepc_d = {csr_wdata_int[31:1], 1'b0}; mcause_en = 1'b0; - mcause_d = {csr_wdata_int[31], csr_wdata_int[4:0]}; + mcause_d = {csr_wdata_int[31], csr_wdata_int[5:0]}; mtval_en = 1'b0; mtval_d = csr_wdata_int; mtvec_en = csr_mtvec_init_i; @@ -807,7 +807,7 @@ module cve2_cs_registers #( // MCAUSE cve2_csr #( - .Width (6), + .Width (7), .ShadowCopy(1'b0), .ResetValue('0) ) u_mcause_csr ( @@ -939,7 +939,7 @@ module cve2_cs_registers #( // MSTACK_CAUSE cve2_csr #( - .Width (6), + .Width (7), .ShadowCopy(1'b0), .ResetValue('0) ) u_mstack_cause_csr ( diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv index 5272759e4..cbb050547 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv @@ -101,7 +101,7 @@ module cve2_if_stage import cve2_pkg::*; #( logic [31:0] exc_pc; - logic [5:0] irq_id; + logic [6:0] irq_id; logic unused_irq_bit; logic if_id_pipe_reg_we; // IF-ID pipeline reg write enable @@ -116,16 +116,16 @@ module cve2_if_stage import cve2_pkg::*; #( // extract interrupt ID from exception cause assign irq_id = {exc_cause}; - assign unused_irq_bit = irq_id[5]; // MSB distinguishes interrupts from exceptions + assign unused_irq_bit = irq_id[6]; // MSB distinguishes interrupts from exceptions // exception PC selection mux always_comb begin : exc_pc_mux unique case (exc_pc_mux_i) - EXC_PC_EXC: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; - EXC_PC_IRQ: exc_pc = { csr_mtvec_i[31:8], 1'b0, irq_id[4:0], 2'b00 }; + EXC_PC_EXC: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; + EXC_PC_IRQ: exc_pc = { csr_mtvec_i[31:8], irq_id[5:0], 2'b00 }; EXC_PC_DBD: exc_pc = DmHaltAddr; EXC_PC_DBG_EXC: exc_pc = DmExceptionAddr; - default: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; + default: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; endcase end diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv index f3d71ce31..e488580b6 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv @@ -292,26 +292,25 @@ package cve2_pkg; logic irq_software; logic irq_timer; logic irq_external; - logic [14:0] irq_fast; // 15 fast interrupts, - // one interrupt is reserved for NMI (not visible through mip/mie) + logic [15:0] irq_fast; // 16 fast interrupts } irqs_t; // Exception cause - typedef enum logic [5:0] { - EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 5'd03}, - EXC_CAUSE_IRQ_TIMER_M = {1'b1, 5'd07}, - EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 5'd11}, - // EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16}, - // EXC_CAUSE_IRQ_FAST_14 = {1'b1, 5'd30}, - EXC_CAUSE_IRQ_NM = {1'b1, 5'd31}, // == EXC_CAUSE_IRQ_FAST_15 - EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 5'd00}, - EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 5'd01}, - EXC_CAUSE_ILLEGAL_INSN = {1'b0, 5'd02}, - EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03}, - EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05}, - EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07}, - EXC_CAUSE_ECALL_UMODE = {1'b0, 5'd08}, - EXC_CAUSE_ECALL_MMODE = {1'b0, 5'd11} + typedef enum logic [6:0] { + EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 6'd03}, + EXC_CAUSE_IRQ_TIMER_M = {1'b1, 6'd07}, + EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 6'd11}, + // EXC_CAUSE_IRQ_FAST_0 = {1'b1, 6'd16}, + // EXC_CAUSE_IRQ_FAST_15 = {1'b1, 6'd31}, + EXC_CAUSE_IRQ_NM = {1'b1, 6'd32}, + EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 6'd00}, + EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 6'd01}, + EXC_CAUSE_ILLEGAL_INSN = {1'b0, 6'd02}, + EXC_CAUSE_BREAKPOINT = {1'b0, 6'd03}, + EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 6'd05}, + EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 6'd07}, + EXC_CAUSE_ECALL_UMODE = {1'b0, 6'd08}, + EXC_CAUSE_ECALL_MMODE = {1'b0, 6'd11} } exc_cause_e; // Debug cause @@ -547,7 +546,7 @@ package cve2_pkg; parameter int unsigned CSR_MTIX_BIT = 7; parameter int unsigned CSR_MEIX_BIT = 11; parameter int unsigned CSR_MFIX_BIT_LOW = 16; - parameter int unsigned CSR_MFIX_BIT_HIGH = 30; + parameter int unsigned CSR_MFIX_BIT_HIGH = 31; // CSR Machine Security Configuration bits parameter int unsigned CSR_MSECCFG_MML_BIT = 0; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv index be2ebc47a..34af60b7b 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -53,7 +53,7 @@ module cve2_top import cve2_pkg::*; #( input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt // Debug Interface diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index a0f03d6a7..8af70a287 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/openhwgroup/cve2.git - rev: 00f7eb1dd9462e33e8b7b5a27e7b2d2f7e0ef1c8 + url: https://github.com/davideschiavone/cve2.git + rev: 538f406f6d6007e075188d69ed889c4fc3887b61 } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index ba705ce74..75218a65e 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -6,8 +6,8 @@ target_dir: "openhwgroup_cv32e20", upstream: { - url: "https://github.com/openhwgroup/cve2.git", - rev: "00f7eb1dd9462e33e8b7b5a27e7b2d2f7e0ef1c8", + url: "https://github.com/davideschiavone/cve2.git", + rev: "538f406f6d6007e075188d69ed889c4fc3887b61", }, exclude_from_upstream: [ From fe28bbeb279935ee1c4249c89de176a9bfce371b Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Mon, 28 Aug 2023 11:32:41 +0200 Subject: [PATCH 07/15] fix nmi cve2 --- hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv | 2 +- hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv | 2 +- hw/vendor/openhwgroup_cve2.lock.hjson | 2 +- hw/vendor/openhwgroup_cve2.vendor.hjson | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv index 78bfc6f0d..cfd67f4d0 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv @@ -318,7 +318,7 @@ module cve2_cs_registers #( CSR_MEPC: csr_rdata_int = mepc_q; // mcause: exception cause - CSR_MCAUSE: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]}; + CSR_MCAUSE: csr_rdata_int = {mcause_q[6], 25'b0, mcause_q[5:0]}; // mtval: trap value CSR_MTVAL: csr_rdata_int = mtval_q; diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv index 515c0564a..989e83d7d 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv @@ -49,7 +49,7 @@ module cve2_top_tracing import cve2_pkg::*; #( input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt // Debug Interface diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index 8af70a287..58551ae7a 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/davideschiavone/cve2.git - rev: 538f406f6d6007e075188d69ed889c4fc3887b61 + rev: f135a3a2e6c6aa40737a9c766429b1d4b5de6874 } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index 75218a65e..12e483c24 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/davideschiavone/cve2.git", - rev: "538f406f6d6007e075188d69ed889c4fc3887b61", + rev: "f135a3a2e6c6aa40737a9c766429b1d4b5de6874", }, exclude_from_upstream: [ From b9f6e7c6d0e77eb747cead9ce3df42684694dde7 Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Wed, 30 Aug 2023 14:28:55 +0200 Subject: [PATCH 08/15] update cve2 --- .../openhwgroup_cv32e20/.readthedocs.yaml | 23 +++++++++++++++++++ hw/vendor/openhwgroup_cve2.lock.hjson | 4 ++-- hw/vendor/openhwgroup_cve2.vendor.hjson | 4 ++-- 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml diff --git a/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml b/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml new file mode 100644 index 000000000..00178f192 --- /dev/null +++ b/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml @@ -0,0 +1,23 @@ +# Copyright 2023 OpenHW Group +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: "ubuntu-20.04" + tools: + python: "3.9" + +# Build from the docs directory with Sphinx +sphinx: + configuration: doc/conf.py + +# Explicitly set the Python requirements +python: + install: + - requirements: doc/requirements.txt \ No newline at end of file diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index 58551ae7a..e7081c3a6 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/davideschiavone/cve2.git - rev: f135a3a2e6c6aa40737a9c766429b1d4b5de6874 + url: https://github.com/openhwgroup/cve2.git + rev: 9a79be864fe658998f49182737054b1ff55cd28c } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index 12e483c24..5ac5a84ff 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -6,8 +6,8 @@ target_dir: "openhwgroup_cv32e20", upstream: { - url: "https://github.com/davideschiavone/cve2.git", - rev: "f135a3a2e6c6aa40737a9c766429b1d4b5de6874", + url: "https://github.com/openhwgroup/cve2.git", + rev: "9a79be864fe658998f49182737054b1ff55cd28c", }, exclude_from_upstream: [ From 684eed4bbd44849728ecf5910ea0d50a0423cf41 Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Wed, 4 Oct 2023 13:14:57 +0200 Subject: [PATCH 09/15] update core --- .../rtl/cve2_controller.sv | 22 +++++++++++++------ .../openhwgroup_cv32e20/rtl/cve2_core.sv | 6 +++-- .../rtl/cve2_cs_registers.sv | 10 +++++++++ hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv | 21 +++++++++--------- hw/vendor/openhwgroup_cve2.lock.hjson | 2 +- hw/vendor/openhwgroup_cve2.vendor.hjson | 2 +- 6 files changed, 41 insertions(+), 22 deletions(-) diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 16ef29dba..43d8b9fc5 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -140,7 +140,7 @@ module cve2_controller #( logic enter_debug_mode; logic ebreak_into_debug; logic handle_irq; - + logic irq_enabled; logic [3:0] mfip_id; logic unused_irq_timer; @@ -291,12 +291,15 @@ module cve2_controller #( priv_mode_i == PRIV_LVL_U ? debug_ebreaku_i : 1'b0; + // MIE bit only applies when in M mode + assign irq_enabled = csr_mstatus_mie_i | (priv_mode_i == PRIV_LVL_U); + // Interrupts including NMI are ignored, // - while in debug mode [Debug Spec v0.13.2, p.39], // - while in NMI mode (nested NMIs are not supported, NMI has highest priority and // cannot be interrupted by regular interrupts). // - while single stepping. - assign handle_irq = ~debug_mode_q & ~debug_single_step_i & ~nmi_mode_q & + assign handle_irq = ~debug_mode_q & ~nmi_mode_q & (irq_nm_i | (irq_pending_i & csr_mstatus_mie_i)); // generate ID of fast interrupts, highest priority to lowest ID @@ -532,11 +535,11 @@ module cve2_controller #( csr_save_cause_o = 1'b1; if (trigger_match_i) begin - debug_cause_o = DBG_CAUSE_TRIGGER; - end else if (debug_single_step_i) begin - debug_cause_o = DBG_CAUSE_STEP; + debug_cause_o = DBG_CAUSE_TRIGGER; // (priority 4) + end else if (debug_req_i) begin + debug_cause_o = DBG_CAUSE_HALTREQ; // (priority 1) end else begin - debug_cause_o = DBG_CAUSE_HALTREQ; + debug_cause_o = DBG_CAUSE_STEP; // (priority 0, lowest) end // enter debug mode @@ -680,9 +683,14 @@ module cve2_controller #( // Leave all other signals as is to ensure CSRs and PC get set as if // core was entering exception handler, entry to debug mode will then // see the appropriate state and setup dpc correctly. + // If an EBREAK instruction is causing us to enter debug mode on the // same cycle as a debug_req or single step, honor the EBREAK and - // proceed to DBG_TAKEN_ID. + // proceed to DBG_TAKEN_ID, as it has the highest priority. + // [Debug Spec v1.0.0-STABLE, p.53] + // cause==EBREAK -> prio 3 (highest) + // cause==debug_req -> prio 2 + // cause==step -> prio 1 (lowest) if (enter_debug_mode_prio_q && !(ebrk_insn_prio && ebreak_into_debug)) begin ctrl_fsm_ns = DBG_TAKEN_IF; end diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv index 600f87890..4f79b67f9 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv @@ -947,8 +947,10 @@ module cve2_core import cve2_pkg::*; #( // Factor in exceptions taken in ID so RVFI tracking picks up flushed instructions that took // a trap - assign rvfi_id_done = instr_id_done | (id_stage_i.controller_i.rvfi_flush_next & - id_stage_i.controller_i.exc_req_d); + // MRET causes MSTATUS to get written one clock later. Fix rvfi_valid when executing MRET + assign rvfi_id_done = (instr_id_done & !id_stage_i.controller_i.mret_insn)| + id_stage_i.csr_restore_mret_id_o | + (id_stage_i.controller_i.rvfi_flush_next & id_stage_i.controller_i.exc_req_d); // Without writeback stage first RVFI stage is output stage so simply valid the cycle after // instruction leaves ID/EX (and so has retired) diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv index cfd67f4d0..dfce09858 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv @@ -468,6 +468,16 @@ module cve2_cs_registers #( illegal_csr = 1'b1; end endcase + + if (!PMPEnable) begin + if (csr_addr inside {CSR_PMPCFG0, CSR_PMPCFG1, CSR_PMPCFG2, CSR_PMPCFG3, + CSR_PMPADDR0, CSR_PMPADDR1, CSR_PMPADDR2, CSR_PMPADDR3, + CSR_PMPADDR4, CSR_PMPADDR5, CSR_PMPADDR6, CSR_PMPADDR7, + CSR_PMPADDR8, CSR_PMPADDR9, CSR_PMPADDR10, CSR_PMPADDR11, + CSR_PMPADDR12, CSR_PMPADDR13, CSR_PMPADDR14, CSR_PMPADDR15}) begin + illegal_csr = 1'b1; + end + end end // write logic diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv index e488580b6..6cd8f4b1e 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv @@ -553,25 +553,24 @@ package cve2_pkg; parameter int unsigned CSR_MSECCFG_MMWP_BIT = 1; parameter int unsigned CSR_MSECCFG_RLB_BIT = 2; - // Vendor ID - // No JEDEC ID has been allocated to lowRISC so the value is 0 to indicate the field is not - // implemented - localparam logic [31:0] CSR_MVENDORID_VALUE = 32'b0; + // Machine Vendor ID - OpenHW JEDEC ID is '2 decimal (bank 13)' + parameter MVENDORID_OFFSET = 7'h2; // Final byte without parity bit + parameter MVENDORID_BANK = 25'hC; // Number of continuation codes - // Architecture ID - // Top bit is unset to indicate an open source project. The lower bits are an ID allocated by the - // RISC-V Foundation. Note this is allocated specifically to Ibex, should significant changes be - // made a different architecture ID should be supplied. - localparam logic [31:0] CSR_MARCHID_VALUE = {1'b0, 31'd22}; + // Machine Architecture ID (https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md) + parameter MARCHID = 32'd35; + + localparam logic [31:0] CSR_MVENDORID_VALUE = {MVENDORID_BANK, MVENDORID_OFFSET}; + localparam logic [31:0] CSR_MARCHID_VALUE = MARCHID; // Implementation ID - // 0 indicates this field is not implemeted. Ibex implementors may wish to indicate an RTL/netlist + // 0 indicates this field is not implemeted. cve2 implementors may wish to indicate an RTL/netlist // version here using their own unique encoding (e.g. 32 bits of the git hash of the implemented // commit). localparam logic [31:0] CSR_MIMPID_VALUE = 32'b0; // Machine Configuration Pointer - // 0 indicates the configuration data structure does not eixst. Ibex implementors may wish to + // 0 indicates the configuration data structure does not eixst. cve2 implementors may wish to // alter this to point to their system specific configuration data structure. localparam logic [31:0] CSR_MCONFIGPTR_VALUE = 32'b0; diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index e7081c3a6..665d32f7d 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/openhwgroup/cve2.git - rev: 9a79be864fe658998f49182737054b1ff55cd28c + rev: 9e0615bc3b9503152e1a223794eb996f5b469cea } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index 5ac5a84ff..007585d56 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/openhwgroup/cve2.git", - rev: "9a79be864fe658998f49182737054b1ff55cd28c", + rev: "9e0615bc3b9503152e1a223794eb996f5b469cea", }, exclude_from_upstream: [ From 35e61aa11213d3dd9a901812bfb2be029dce2088 Mon Sep 17 00:00:00 2001 From: Schiavone Pasquale Davide Date: Mon, 11 Dec 2023 14:06:09 +0100 Subject: [PATCH 10/15] add suppress error in vsim --- core-v-mini-mcu.core | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/core-v-mini-mcu.core b/core-v-mini-mcu.core index 409b1325a..0285203da 100644 --- a/core-v-mini-mcu.core +++ b/core-v-mini-mcu.core @@ -102,6 +102,7 @@ filesets: ip-fpga: files: + - hw/fpga/scripts/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } - hw/fpga/scripts/generate_sram.tcl: { file_type: tclSource } - hw/fpga/prim_xilinx_clk.sv: { file_type: systemVerilogSource } - hw/fpga/cv32e40p_xilinx_clock_gate.sv: { file_type: systemVerilogSource } @@ -114,16 +115,6 @@ filesets: - hw/fpga/pad_cell_bypass_input_xilinx.sv: { file_type: systemVerilogSource } - hw/fpga/pad_cell_bypass_output_xilinx.sv: { file_type: systemVerilogSource } - ip-fpga-pynq-z2: - files: - - hw/fpga/scripts/pynq-z2/set_board.tcl: { file_type: tclSource } - - hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } - - ip-fpga-nexys: - files: - - hw/fpga/scripts/nexys/set_board.tcl: { file_type: tclSource } - - hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } - fpga-arm-emulation: depend: - pulp-platform.org::axi_spi_slave @@ -271,7 +262,7 @@ parameters: datatype: bool paramtype: vlogdefine default: false - FPGA_NEXYS: + FPGA_NETLIST: datatype: bool paramtype: vlogdefine default: false @@ -351,6 +342,7 @@ targets: - -override_timescale 1ns/1ps - -suppress vlog-2583 - -suppress vlog-2577 + - -suppress vlog-2720 - -pedanticerrors - -define MODELSIM vsim_options: @@ -394,9 +386,7 @@ targets: default_tool: vivado description: Digilent Nexys-A7-100T Board filesets_append: - - x_heep_system - rtl-fpga - - ip-fpga-nexys - ip-fpga - xdc-fpga-nexys parameters: @@ -405,7 +395,6 @@ targets: - X_EXT - SYNTHESIS=true - REMOVE_OBI_FIFO - - FPGA_NEXYS=true tools: vivado: part: xc7a100tcsg324-1 @@ -418,7 +407,6 @@ targets: filesets_append: - x_heep_system - rtl-fpga - - ip-fpga-pynq-z2 - ip-fpga - xdc-fpga-pynq-z2 parameters: From 93076bc64a036408683ac804ec1cca4b8684d1a9 Mon Sep 17 00:00:00 2001 From: Schiavone Pasquale Davide Date: Tue, 12 Dec 2023 11:39:54 +0100 Subject: [PATCH 11/15] removed wrong assert --- hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv index 34af60b7b..00c38a4a5 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -265,7 +265,6 @@ module cve2_top import cve2_pkg::*; #( `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) - `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_err_i}, data_rvalid_i) `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) From f416d0bce6463e45c2e2217232f94e9fa5059297 Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Tue, 12 Dec 2023 11:47:39 +0100 Subject: [PATCH 12/15] update patch vendor --- hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv | 1 + .../patches/openhwgroup_cv32e20/cv32e20_assert.patch | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv index 00c38a4a5..34af60b7b 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -265,6 +265,7 @@ module cve2_top import cve2_pkg::*; #( `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) + `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_err_i}, data_rvalid_i) `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) diff --git a/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch b/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch new file mode 100644 index 000000000..4ac84c153 --- /dev/null +++ b/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch @@ -0,0 +1,12 @@ +diff --git a/rtl/cve2_top.sv b/rtl/cve2_top.sv +index 34af60b7..00c38a4a 100644 +--- a/rtl/cve2_top.sv ++++ b/rtl/cve2_top.sv +@@ -265,7 +265,6 @@ module cve2_top import cve2_pkg::*; #( + + `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) + `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) +- `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_err_i}, data_rvalid_i) + + `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) + From a392e220469d896a842cb275a0ae89cf5d4be0b3 Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Tue, 12 Dec 2023 11:49:48 +0100 Subject: [PATCH 13/15] update patch vendor --- hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv | 1 - hw/vendor/openhwgroup_cve2.vendor.hjson | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv index 34af60b7b..00c38a4a5 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -265,7 +265,6 @@ module cve2_top import cve2_pkg::*; #( `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) - `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_err_i}, data_rvalid_i) `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index 007585d56..ac910b73a 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -10,6 +10,8 @@ rev: "9e0615bc3b9503152e1a223794eb996f5b469cea", }, + patch_dir: "patches/openhwgroup_cv32e20", + exclude_from_upstream: [ "ci", "dv", From 4b8a3c665e740186d11b04345ee4162ef0350e2d Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Tue, 12 Dec 2023 13:26:04 +0100 Subject: [PATCH 14/15] fix .core --- core-v-mini-mcu.core | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/core-v-mini-mcu.core b/core-v-mini-mcu.core index 0285203da..9c1ffadff 100644 --- a/core-v-mini-mcu.core +++ b/core-v-mini-mcu.core @@ -102,7 +102,6 @@ filesets: ip-fpga: files: - - hw/fpga/scripts/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } - hw/fpga/scripts/generate_sram.tcl: { file_type: tclSource } - hw/fpga/prim_xilinx_clk.sv: { file_type: systemVerilogSource } - hw/fpga/cv32e40p_xilinx_clock_gate.sv: { file_type: systemVerilogSource } @@ -115,6 +114,16 @@ filesets: - hw/fpga/pad_cell_bypass_input_xilinx.sv: { file_type: systemVerilogSource } - hw/fpga/pad_cell_bypass_output_xilinx.sv: { file_type: systemVerilogSource } + ip-fpga-pynq-z2: + files: + - hw/fpga/scripts/pynq-z2/set_board.tcl: { file_type: tclSource } + - hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } + + ip-fpga-nexys: + files: + - hw/fpga/scripts/nexys/set_board.tcl: { file_type: tclSource } + - hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } + fpga-arm-emulation: depend: - pulp-platform.org::axi_spi_slave @@ -262,7 +271,7 @@ parameters: datatype: bool paramtype: vlogdefine default: false - FPGA_NETLIST: + FPGA_NEXYS: datatype: bool paramtype: vlogdefine default: false @@ -386,7 +395,9 @@ targets: default_tool: vivado description: Digilent Nexys-A7-100T Board filesets_append: + - x_heep_system - rtl-fpga + - ip-fpga-nexys - ip-fpga - xdc-fpga-nexys parameters: @@ -395,6 +406,7 @@ targets: - X_EXT - SYNTHESIS=true - REMOVE_OBI_FIFO + - FPGA_NEXYS=true tools: vivado: part: xc7a100tcsg324-1 @@ -407,6 +419,7 @@ targets: filesets_append: - x_heep_system - rtl-fpga + - ip-fpga-pynq-z2 - ip-fpga - xdc-fpga-pynq-z2 parameters: From bf5891afd4c227295dc73e3de5c00081339ffeb2 Mon Sep 17 00:00:00 2001 From: davide schiavone Date: Tue, 12 Dec 2023 13:54:01 +0100 Subject: [PATCH 15/15] update core and cpu ss --- hw/core-v-mini-mcu/cpu_subsystem.sv | 5 ++++- hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv | 4 ---- hw/vendor/openhwgroup_cve2.lock.hjson | 2 +- hw/vendor/openhwgroup_cve2.vendor.hjson | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/hw/core-v-mini-mcu/cpu_subsystem.sv b/hw/core-v-mini-mcu/cpu_subsystem.sv index 7c8dc8e82..256723f60 100644 --- a/hw/core-v-mini-mcu/cpu_subsystem.sv +++ b/hw/core-v-mini-mcu/cpu_subsystem.sv @@ -59,7 +59,10 @@ module cpu_subsystem if (CPU_TYPE == cv32e20) begin : gen_cv32e20 - cve2_top cv32e20_i ( + cve2_top #( + .DmHaltAddr(DM_HALTADDRESS), + .DmExceptionAddr('0) + ) cv32e20_i ( .clk_i (clk_i), .rst_ni(rst_ni), diff --git a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 43d8b9fc5..fba4352f3 100644 --- a/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv +++ b/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -140,7 +140,6 @@ module cve2_controller #( logic enter_debug_mode; logic ebreak_into_debug; logic handle_irq; - logic irq_enabled; logic [3:0] mfip_id; logic unused_irq_timer; @@ -291,9 +290,6 @@ module cve2_controller #( priv_mode_i == PRIV_LVL_U ? debug_ebreaku_i : 1'b0; - // MIE bit only applies when in M mode - assign irq_enabled = csr_mstatus_mie_i | (priv_mode_i == PRIV_LVL_U); - // Interrupts including NMI are ignored, // - while in debug mode [Debug Spec v0.13.2, p.39], // - while in NMI mode (nested NMIs are not supported, NMI has highest priority and diff --git a/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/openhwgroup_cve2.lock.hjson index 665d32f7d..a9251111f 100644 --- a/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/openhwgroup_cve2.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/openhwgroup/cve2.git - rev: 9e0615bc3b9503152e1a223794eb996f5b469cea + rev: f5b21e71c9b511477b04ef81d1292858c51ac20c } } diff --git a/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/openhwgroup_cve2.vendor.hjson index ac910b73a..d398c1eb3 100644 --- a/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/openhwgroup/cve2.git", - rev: "9e0615bc3b9503152e1a223794eb996f5b469cea", + rev: "f5b21e71c9b511477b04ef81d1292858c51ac20c", }, patch_dir: "patches/openhwgroup_cv32e20",