[rtl] Add ic_scr_key_valid field to CPUCTRL (renamed CPUCTRLSTS)

The ic_scr_key_valid field indicates whether the ICache scrambling key
is valid.

CPUCTRL is also renamed CPUCTRLSTS as it contains both control and
status bits.
This commit is contained in:
Greg Chadwick 2022-09-09 11:06:36 +01:00 committed by Greg Chadwick
parent 06fece4640
commit 70186c57ae
23 changed files with 302 additions and 201 deletions

View file

@ -7,7 +7,7 @@
# end up as float otherwise).
variables:
VERILATOR_VERSION: "4.104"
IBEX_COSIM_VERSION: "9b68f2f9"
IBEX_COSIM_VERSION: "68edd179"
RISCV_TOOLCHAIN_TAR_VERSION: "20220210-1"
RISCV_TOOLCHAIN_TAR_VARIANT: "lowrisc-toolchain-gcc-rv32imcb"
RISCV_COMPLIANCE_GIT_VERSION: "844c6660ef3f0d9b96957991109dfd80cc4938e2"

View file

@ -524,8 +524,8 @@ Reset Value: ``0x0000_0000``
Scratch register to be used by the debug module.
Accessible in Debug Mode only.
CPU Control Register (cpuctrl)
------------------------------
CPU Control and Status Register (cpuctrlsts)
--------------------------------------------
CSR Address: ``0x7C0``
@ -538,6 +538,13 @@ Other bit fields read as zero.
+-------+------+------------------------------------------------------------------+
| Bit# | R/W | Description |
+=======+======+==================================================================+
| 8 | R | **ic_scr_key_valid:** The icache scrambling key is valid. A |
| | | ``fence.i`` instruction is guaranteed to fetch a new key. If |
| | | the instruction cache has not been configured or the core has |
| | | not been configured with security features (ICache parameter |
| | | == 0 or SecureIbex parameter == 0), this field will always read |
| | | as zero. (see :ref:`icache-scramble-key`) |
+-------+------+------------------------------------------------------------------+
| 7 | RW | **double_fault_seen:** A synchronous exception was observed when |
| | | the ``sync_exc_seen`` field was set. This field must be manually |

View file

@ -93,12 +93,32 @@ Indicative RAM sizes for common configurations are given in the table below:
| 4kB, 4 way, 64bit line | 4 x 128 x 22bit | 4 x 128 x 64bit |
+------------------------------+-----------------+------------------+
ICache Scrambling
^^^^^^^^^^^^^^^^^
If ICacheScramble parameter is enabled, all RAM primitives are replaced with scrambling RAM primitive.
For more information about how scrambling works internally (see :file:`vendor/lowrisc_ip/ip/prim/doc/prim_ram_1p_scr.md`).
Interface for receiving scrambling key follows req / ack protocol.
Ibex first requests a new ephemeral key by asserting the request (``scramble_req_o``) and when a fresh valid key is indicated by ``scramble_key_valid_i``, it deasserts the request.
Note that in current implementation, it is assumed req/ack protocol is synchronized before arriving to Ibex top level.
.. _icache-scramble-key:
Scramble Key Renewal
^^^^^^^^^^^^^^^^^^^^
To get a new scrambling key execute a FENCE.I instruction.
With a new scrambling key the existing cache contents are effectively corrupt and will be invalidated by the FENCE.I.
Following a FENCE.I cache lookups will always miss until the invalidation is complete.
This allows CPU fetch and execution to continue using direct memory accesses whilst the scramble key request and cache invalidation proceeds in the background.
Should a second FENCE.I be executed before the first invalidation completes there are two possibilities
1. The request for a new scramble key is still in progress.
As a new request cannot begin whilst one is in progress the FENCE.I is ignored.
2. The request for a new scramble key has completed and the invalidation is in progress.
The invalidation stops and a new scramble key requested and the process starts over.
To guarantee a new scramble key ensure the ``ic_scr_key_valid`` bit in the ``cpuctrlsts`` CSR is set before executing the FENCE.I instruction.
Sub Unit Description
--------------------

View file

@ -5,3 +5,4 @@ sphinx~=3.0
sphinx_rtd_theme
sphinxcontrib-wavedrom
wavedrom>=1.9.0rc1
jinja2 == 3.0.3

View file

@ -114,6 +114,9 @@ class Cosim {
// communication between DUT and Spike (e.g. Performance counters).
virtual void set_csr(const int csr_num, const uint32_t new_val) = 0;
// Set the ICache scramble key valid bit that is visible in CPUCTRLSTS.
virtual void set_ic_scr_key_valid(bool valid) = 0;
// Tell the co-simulation model about observed transactions on the dside
// memory interface of the DUT. Accesses are notified once the response to a
// transaction is seen.

View file

@ -48,6 +48,12 @@ void riscv_cosim_set_csr(Cosim *cosim, const int csr_id,
cosim->set_csr(csr_id, (uint32_t)csr_val[0]);
}
void riscv_cosim_set_ic_scr_key_valid(Cosim *cosim, svBit valid) {
assert(cosim);
cosim->set_ic_scr_key_valid(valid);
}
void riscv_cosim_notify_dside_access(Cosim *cosim, svBit store,
svBitVecVal *addr, svBitVecVal *data,
svBitVecVal *be, svBit error,

View file

@ -21,6 +21,7 @@ void riscv_cosim_set_debug_req(Cosim *cosim, svBit debug_req);
void riscv_cosim_set_mcycle(Cosim *cosim, svBitVecVal *mcycle);
void riscv_cosim_set_csr(Cosim *cosim, const int csr_id,
const svBitVecVal *csr_val);
void riscv_cosim_set_ic_scr_key_valid(Cosim *cosim, svBit valid);
void riscv_cosim_notify_dside_access(Cosim *cosim, svBit store,
svBitVecVal *addr, svBitVecVal *data,
svBitVecVal *be, svBit error,

View file

@ -18,6 +18,7 @@ import "DPI-C" function void riscv_cosim_set_debug_req(chandle cosim_handle, bit
import "DPI-C" function void riscv_cosim_set_mcycle(chandle cosim_handle, bit [63:0] mcycle);
import "DPI-C" function void riscv_cosim_set_csr(chandle cosim_handle, int csr_id,
bit [31:0] csr_val);
import "DPI-C" function void riscv_cosim_set_ic_scr_key_valid(chandle cosim_handle, bit valid);
import "DPI-C" function void riscv_cosim_notify_dside_access(chandle cosim_handle, bit store,
bit [31:0] addr, bit [31:0] data, bit [3:0] be, bit error, bit misaligned_first,
bit misaligned_second);

View file

@ -512,6 +512,10 @@ void SpikeCosim::set_csr(const int csr_num, const uint32_t new_val) {
#endif
}
void SpikeCosim::set_ic_scr_key_valid(bool valid) {
processor->set_ic_scr_key_valid(valid);
}
void SpikeCosim::notify_dside_access(const DSideAccessInfo &access_info) {
// Address must be 32-bit aligned
assert((access_info.addr & 0x3) == 0);

View file

@ -104,6 +104,7 @@ class SpikeCosim : public simif_t, public Cosim {
void set_debug_req(bool debug_req) override;
void set_mcycle(uint64_t mcycle) override;
void set_csr(const int csr_num, const uint32_t new_val) override;
void set_ic_scr_key_valid(bool valid) override;
void notify_dside_access(const DSideAccessInfo &access_info) override;
// The spike co-simulator assumes iside and dside accesses within a step are
// disjoint. If both access the same address within a step memory faults may

View file

@ -132,6 +132,8 @@ class ibex_cosim_scoreboard extends uvm_scoreboard;
riscv_cosim_set_csr(cosim_handle, CSR_MHPMCOUNTER3H + i, rvfi_instr.mhpmcountersh[i]);
end
riscv_cosim_set_ic_scr_key_valid(cosim_handle, rvfi_instr.ic_scr_key_valid);
if (!riscv_cosim_step(cosim_handle, rvfi_instr.rd_addr, rvfi_instr.rd_wdata, rvfi_instr.pc,
rvfi_instr.trap)) begin
// cosim instruction step doesn't match rvfi captured instruction, report a fatal error

View file

@ -30,16 +30,17 @@ class ibex_rvfi_monitor extends uvm_monitor;
while(!vif.monitor_cb.valid) vif.wait_clks(1);
// Read instruction details from RVFI interface
trans_collected = ibex_rvfi_seq_item::type_id::create("trans_collected");
trans_collected.trap = vif.monitor_cb.trap;
trans_collected.pc = vif.monitor_cb.pc_rdata;
trans_collected.rd_addr = vif.monitor_cb.rd_addr;
trans_collected.rd_wdata = vif.monitor_cb.rd_wdata;
trans_collected.order = vif.monitor_cb.order;
trans_collected.mip = vif.monitor_cb.ext_mip;
trans_collected.nmi = vif.monitor_cb.ext_nmi;
trans_collected.debug_req = vif.monitor_cb.ext_debug_req;
trans_collected.mcycle = vif.monitor_cb.ext_mcycle;
trans_collected = ibex_rvfi_seq_item::type_id::create("trans_collected");
trans_collected.trap = vif.monitor_cb.trap;
trans_collected.pc = vif.monitor_cb.pc_rdata;
trans_collected.rd_addr = vif.monitor_cb.rd_addr;
trans_collected.rd_wdata = vif.monitor_cb.rd_wdata;
trans_collected.order = vif.monitor_cb.order;
trans_collected.mip = vif.monitor_cb.ext_mip;
trans_collected.nmi = vif.monitor_cb.ext_nmi;
trans_collected.debug_req = vif.monitor_cb.ext_debug_req;
trans_collected.mcycle = vif.monitor_cb.ext_mcycle;
trans_collected.ic_scr_key_valid = vif.monitor_cb.ext_ic_scr_key_valid;
for (int i=0; i < 10; i++) begin
trans_collected.mhpmcounters[i] = vif.monitor_cb.ext_mhpmcounters[i];

View file

@ -15,6 +15,7 @@ class ibex_rvfi_seq_item extends uvm_sequence_item;
bit [31:0] mhpmcounters [10];
bit [31:0] mhpmcountersh [10];
bit ic_scr_key_valid;
`uvm_object_utils_begin(ibex_rvfi_seq_item)
`uvm_field_int (trap, UVM_DEFAULT)
@ -28,6 +29,7 @@ class ibex_rvfi_seq_item extends uvm_sequence_item;
`uvm_field_int (mcycle, UVM_DEFAULT)
`uvm_field_sarray_int (mhpmcounters, UVM_DEFAULT)
`uvm_field_sarray_int (mhpmcountersh, UVM_DEFAULT)
`uvm_field_int (ic_scr_key_valid, UVM_DEFAULT)
`uvm_object_utils_end
`uvm_object_new

View file

@ -34,6 +34,8 @@ interface core_ibex_rvfi_if(input logic clk);
logic [31:0] ext_mhpmcounters [10];
logic [31:0] ext_mhpmcountersh [10];
logic ext_ic_scr_key_valid;
clocking monitor_cb @(posedge clk);
input reset;
input valid;
@ -63,6 +65,7 @@ interface core_ibex_rvfi_if(input logic clk);
input ext_mcycle;
input ext_mhpmcounters;
input ext_mhpmcountersh;
input ext_ic_scr_key_valid;
endclocking
task automatic wait_clks(input int num);

View file

@ -462,11 +462,11 @@ interface core_ibex_fcov_if import ibex_pkg::*; (
`DV_FCOV_EXPR_SEEN(warl_check_cpuctrl,
fcov_csr_write &&
(cs_registers_i.u_cpuctrl_csr.wr_data_i !=
(cs_registers_i.u_cpuctrlsts_part_csr.wr_data_i !=
cs_registers_i.csr_wdata_int))
`DV_FCOV_EXPR_SEEN(double_fault, cs_registers_i.cpuctrl_d.double_fault_seen)
`DV_FCOV_EXPR_SEEN(icache_enable, cs_registers_i.cpuctrl_d.icache_enable)
`DV_FCOV_EXPR_SEEN(double_fault, cs_registers_i.cpuctrlsts_part_d.double_fault_seen)
`DV_FCOV_EXPR_SEEN(icache_enable, cs_registers_i.cpuctrlsts_part_d.icache_enable)
cp_irq_pending: coverpoint id_stage_i.irq_pending_i | id_stage_i.irq_nm_i;
cp_debug_req: coverpoint id_stage_i.controller_i.fcov_debug_req;

View file

@ -169,44 +169,45 @@ module core_ibex_tb_top;
assign instr_mem_vif.be = 0;
assign instr_mem_vif.wdata = 0;
// RVFI interface connections
assign rvfi_if.reset = ~rst_n;
assign rvfi_if.valid = dut.rvfi_valid;
assign rvfi_if.order = dut.rvfi_order;
assign rvfi_if.insn = dut.rvfi_insn;
assign rvfi_if.trap = dut.rvfi_trap;
assign rvfi_if.intr = dut.rvfi_intr;
assign rvfi_if.mode = dut.rvfi_mode;
assign rvfi_if.ixl = dut.rvfi_ixl;
assign rvfi_if.rs1_addr = dut.rvfi_rs1_addr;
assign rvfi_if.rs2_addr = dut.rvfi_rs2_addr;
assign rvfi_if.rs1_rdata = dut.rvfi_rs1_rdata;
assign rvfi_if.rs2_rdata = dut.rvfi_rs2_rdata;
assign rvfi_if.rd_addr = dut.rvfi_rd_addr;
assign rvfi_if.rd_wdata = dut.rvfi_rd_wdata;
assign rvfi_if.pc_rdata = dut.rvfi_pc_rdata;
assign rvfi_if_pc_wdata = dut.rvfi_pc_wdata;
assign rvfi_if.mem_addr = dut.rvfi_mem_addr;
assign rvfi_if.mem_rmask = dut.rvfi_mem_rmask;
assign rvfi_if.mem_rdata = dut.rvfi_mem_rdata;
assign rvfi_if.mem_wdata = dut.rvfi_mem_wdata;
assign rvfi_if.ext_mip = dut.rvfi_ext_mip;
assign rvfi_if.ext_nmi = dut.rvfi_ext_nmi;
assign rvfi_if.ext_debug_req = dut.rvfi_ext_debug_req;
assign rvfi_if.ext_mcycle = dut.rvfi_ext_mcycle;
assign rvfi_if.ext_mhpmcounters = dut.rvfi_ext_mhpmcounters;
assign rvfi_if.ext_mhpmcountersh = dut.rvfi_ext_mhpmcountersh;
assign rvfi_if.reset = ~rst_n;
assign rvfi_if.valid = dut.rvfi_valid;
assign rvfi_if.order = dut.rvfi_order;
assign rvfi_if.insn = dut.rvfi_insn;
assign rvfi_if.trap = dut.rvfi_trap;
assign rvfi_if.intr = dut.rvfi_intr;
assign rvfi_if.mode = dut.rvfi_mode;
assign rvfi_if.ixl = dut.rvfi_ixl;
assign rvfi_if.rs1_addr = dut.rvfi_rs1_addr;
assign rvfi_if.rs2_addr = dut.rvfi_rs2_addr;
assign rvfi_if.rs1_rdata = dut.rvfi_rs1_rdata;
assign rvfi_if.rs2_rdata = dut.rvfi_rs2_rdata;
assign rvfi_if.rd_addr = dut.rvfi_rd_addr;
assign rvfi_if.rd_wdata = dut.rvfi_rd_wdata;
assign rvfi_if.pc_rdata = dut.rvfi_pc_rdata;
assign rvfi_if_pc_wdata = dut.rvfi_pc_wdata;
assign rvfi_if.mem_addr = dut.rvfi_mem_addr;
assign rvfi_if.mem_rmask = dut.rvfi_mem_rmask;
assign rvfi_if.mem_rdata = dut.rvfi_mem_rdata;
assign rvfi_if.mem_wdata = dut.rvfi_mem_wdata;
assign rvfi_if.ext_mip = dut.rvfi_ext_mip;
assign rvfi_if.ext_nmi = dut.rvfi_ext_nmi;
assign rvfi_if.ext_debug_req = dut.rvfi_ext_debug_req;
assign rvfi_if.ext_mcycle = dut.rvfi_ext_mcycle;
assign rvfi_if.ext_mhpmcounters = dut.rvfi_ext_mhpmcounters;
assign rvfi_if.ext_mhpmcountersh = dut.rvfi_ext_mhpmcountersh;
assign rvfi_if.ext_ic_scr_key_valid = dut.rvfi_ext_ic_scr_key_valid;
// Irq interface connections
assign irq_vif.reset = ~rst_n;
// Dut_if interface connections
assign dut_if.ecall = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ecall_insn;
assign dut_if.wfi = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.wfi_insn;
assign dut_if.ebreak = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ebrk_insn;
assign dut_if.illegal_instr = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.illegal_insn_d;
assign dut_if.dret = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.dret_insn;
assign dut_if.mret = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.mret_insn;
assign dut_if.reset = ~rst_n;
assign dut_if.priv_mode = dut.u_ibex_top.u_ibex_core.priv_mode_id;
assign dut_if.ctrl_fsm_cs = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ctrl_fsm_cs;
assign dut_if.ecall = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ecall_insn;
assign dut_if.wfi = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.wfi_insn;
assign dut_if.ebreak = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ebrk_insn;
assign dut_if.illegal_instr = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.illegal_insn_d;
assign dut_if.dret = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.dret_insn;
assign dut_if.mret = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.mret_insn;
assign dut_if.reset = ~rst_n;
assign dut_if.priv_mode = dut.u_ibex_top.u_ibex_core.priv_mode_id;
assign dut_if.ctrl_fsm_cs = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ctrl_fsm_cs;
// Instruction monitor connections
assign instr_monitor_if.reset = ~rst_n;
assign instr_monitor_if.valid_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_valid_i;

View file

@ -38,6 +38,7 @@ module ibex_simple_system_cosim_checker (
riscv_cosim_set_csr(cosim_handle, int'(CSR_MHPMCOUNTER3H) + i,
u_top.rvfi_ext_mhpmcountersh[i]);
end
riscv_cosim_set_ic_scr_key_valid(cosim_handle, u_top.rvfi_ext_ic_scr_key_valid);
if (riscv_cosim_step(cosim_handle, u_top.rvfi_rd_addr, u_top.rvfi_rd_wdata,
u_top.rvfi_pc_rdata, u_top.rvfi_trap) == 0)

View file

@ -142,6 +142,7 @@ module ibex_core import ibex_pkg::*; #(
output logic [63:0] rvfi_ext_mcycle,
output logic [31:0] rvfi_ext_mhpmcounters [10],
output logic [31:0] rvfi_ext_mhpmcountersh [10],
output logic rvfi_ext_ic_scr_key_valid,
`endif
// CPU Control Signals
@ -1009,6 +1010,7 @@ module ibex_core import ibex_pkg::*; #(
.dummy_instr_seed_o (dummy_instr_seed),
.icache_enable_o (icache_enable),
.csr_shadow_err_o (csr_shadow_err),
.ic_scr_key_valid_i (ic_scr_key_valid_i),
.csr_save_if_i (csr_save_if),
.csr_save_id_i (csr_save_id),
@ -1175,12 +1177,13 @@ module ibex_core import ibex_pkg::*; #(
// 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];
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];
logic [31:0] rvfi_ext_stage_mhpmcounters [RVFI_STAGES][10];
logic [31:0] rvfi_ext_stage_mhpmcountersh [RVFI_STAGES][10];
ibex_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];
logic [31:0] rvfi_ext_stage_mhpmcounters [RVFI_STAGES][10];
logic [31:0] rvfi_ext_stage_mhpmcountersh [RVFI_STAGES][10];
logic rvfi_ext_stage_ic_scr_key_valid [RVFI_STAGES];
logic rvfi_stage_valid_d [RVFI_STAGES];
@ -1223,11 +1226,12 @@ module ibex_core import ibex_pkg::*; #(
rvfi_ext_mip[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = rvfi_ext_stage_mip[RVFI_STAGES].irq_fast;
end
assign rvfi_ext_nmi = rvfi_ext_stage_nmi [RVFI_STAGES];
assign rvfi_ext_debug_req = rvfi_ext_stage_debug_req [RVFI_STAGES];
assign rvfi_ext_mcycle = rvfi_ext_stage_mcycle [RVFI_STAGES-1];
assign rvfi_ext_mhpmcounters = rvfi_ext_stage_mhpmcounters [RVFI_STAGES-1];
assign rvfi_ext_mhpmcountersh = rvfi_ext_stage_mhpmcountersh [RVFI_STAGES-1];
assign rvfi_ext_nmi = rvfi_ext_stage_nmi [RVFI_STAGES];
assign rvfi_ext_debug_req = rvfi_ext_stage_debug_req [RVFI_STAGES];
assign rvfi_ext_mcycle = rvfi_ext_stage_mcycle [RVFI_STAGES-1];
assign rvfi_ext_mhpmcounters = rvfi_ext_stage_mhpmcounters [RVFI_STAGES-1];
assign rvfi_ext_mhpmcountersh = rvfi_ext_stage_mhpmcountersh [RVFI_STAGES-1];
assign rvfi_ext_ic_scr_key_valid = rvfi_ext_stage_ic_scr_key_valid [RVFI_STAGES-1];
// When an instruction takes a trap the `rvfi_trap` signal will be set. Instructions that take
// traps flush the pipeline so ordinarily wouldn't be seen to be retire. The RVFI tracking
@ -1359,35 +1363,36 @@ module ibex_core import ibex_pkg::*; #(
for (genvar i = 0; i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_stage_halt[i] <= '0;
rvfi_stage_trap[i] <= '0;
rvfi_stage_intr[i] <= '0;
rvfi_stage_order[i] <= '0;
rvfi_stage_insn[i] <= '0;
rvfi_stage_mode[i] <= {PRIV_LVL_M};
rvfi_stage_ixl[i] <= CSR_MISA_MXL;
rvfi_stage_rs1_addr[i] <= '0;
rvfi_stage_rs2_addr[i] <= '0;
rvfi_stage_rs3_addr[i] <= '0;
rvfi_stage_pc_rdata[i] <= '0;
rvfi_stage_pc_wdata[i] <= '0;
rvfi_stage_mem_rmask[i] <= '0;
rvfi_stage_mem_wmask[i] <= '0;
rvfi_stage_valid[i] <= '0;
rvfi_stage_rs1_rdata[i] <= '0;
rvfi_stage_rs2_rdata[i] <= '0;
rvfi_stage_rs3_rdata[i] <= '0;
rvfi_stage_rd_wdata[i] <= '0;
rvfi_stage_rd_addr[i] <= '0;
rvfi_stage_mem_rdata[i] <= '0;
rvfi_stage_mem_wdata[i] <= '0;
rvfi_stage_mem_addr[i] <= '0;
rvfi_ext_stage_mip[i+1] <= '0;
rvfi_ext_stage_nmi[i+1] <= '0;
rvfi_ext_stage_debug_req[i+1] <= '0;
rvfi_ext_stage_mcycle[i] <= '0;
rvfi_ext_stage_mhpmcounters[i] <= '{10{'0}};
rvfi_ext_stage_mhpmcountersh[i] <= '{10{'0}};
rvfi_stage_halt[i] <= '0;
rvfi_stage_trap[i] <= '0;
rvfi_stage_intr[i] <= '0;
rvfi_stage_order[i] <= '0;
rvfi_stage_insn[i] <= '0;
rvfi_stage_mode[i] <= {PRIV_LVL_M};
rvfi_stage_ixl[i] <= CSR_MISA_MXL;
rvfi_stage_rs1_addr[i] <= '0;
rvfi_stage_rs2_addr[i] <= '0;
rvfi_stage_rs3_addr[i] <= '0;
rvfi_stage_pc_rdata[i] <= '0;
rvfi_stage_pc_wdata[i] <= '0;
rvfi_stage_mem_rmask[i] <= '0;
rvfi_stage_mem_wmask[i] <= '0;
rvfi_stage_valid[i] <= '0;
rvfi_stage_rs1_rdata[i] <= '0;
rvfi_stage_rs2_rdata[i] <= '0;
rvfi_stage_rs3_rdata[i] <= '0;
rvfi_stage_rd_wdata[i] <= '0;
rvfi_stage_rd_addr[i] <= '0;
rvfi_stage_mem_rdata[i] <= '0;
rvfi_stage_mem_wdata[i] <= '0;
rvfi_stage_mem_addr[i] <= '0;
rvfi_ext_stage_mip[i+1] <= '0;
rvfi_ext_stage_nmi[i+1] <= '0;
rvfi_ext_stage_debug_req[i+1] <= '0;
rvfi_ext_stage_mcycle[i] <= '0;
rvfi_ext_stage_mhpmcounters[i] <= '{10{'0}};
rvfi_ext_stage_mhpmcountersh[i] <= '{10{'0}};
rvfi_ext_stage_ic_scr_key_valid[i] <= '0;
end else begin
rvfi_stage_valid[i] <= rvfi_stage_valid_d[i];
@ -1395,31 +1400,32 @@ module ibex_core import ibex_pkg::*; #(
if (rvfi_id_done) begin
rvfi_stage_halt[i] <= '0;
// TODO: Sort this out for writeback stage
rvfi_stage_trap[i] <= rvfi_trap_id;
rvfi_stage_intr[i] <= rvfi_intr_d;
rvfi_stage_order[i] <= rvfi_stage_order_d;
rvfi_stage_insn[i] <= rvfi_insn_id;
rvfi_stage_mode[i] <= {priv_mode_id};
rvfi_stage_ixl[i] <= CSR_MISA_MXL;
rvfi_stage_rs1_addr[i] <= rvfi_rs1_addr_d;
rvfi_stage_rs2_addr[i] <= rvfi_rs2_addr_d;
rvfi_stage_rs3_addr[i] <= rvfi_rs3_addr_d;
rvfi_stage_pc_rdata[i] <= pc_id;
rvfi_stage_pc_wdata[i] <= pc_set ? branch_target_ex : pc_if;
rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int;
rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
rvfi_stage_rs1_rdata[i] <= rvfi_rs1_data_d;
rvfi_stage_rs2_rdata[i] <= rvfi_rs2_data_d;
rvfi_stage_rs3_rdata[i] <= rvfi_rs3_data_d;
rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d;
rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
rvfi_stage_mem_wdata[i] <= rvfi_mem_wdata_d;
rvfi_stage_mem_addr[i] <= rvfi_mem_addr_d;
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
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] <= cs_registers_i.mcycle_counter_i.counter_val_o;
rvfi_stage_trap[i] <= rvfi_trap_id;
rvfi_stage_intr[i] <= rvfi_intr_d;
rvfi_stage_order[i] <= rvfi_stage_order_d;
rvfi_stage_insn[i] <= rvfi_insn_id;
rvfi_stage_mode[i] <= {priv_mode_id};
rvfi_stage_ixl[i] <= CSR_MISA_MXL;
rvfi_stage_rs1_addr[i] <= rvfi_rs1_addr_d;
rvfi_stage_rs2_addr[i] <= rvfi_rs2_addr_d;
rvfi_stage_rs3_addr[i] <= rvfi_rs3_addr_d;
rvfi_stage_pc_rdata[i] <= pc_id;
rvfi_stage_pc_wdata[i] <= pc_set ? branch_target_ex : pc_if;
rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int;
rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
rvfi_stage_rs1_rdata[i] <= rvfi_rs1_data_d;
rvfi_stage_rs2_rdata[i] <= rvfi_rs2_data_d;
rvfi_stage_rs3_rdata[i] <= rvfi_rs3_data_d;
rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d;
rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
rvfi_stage_mem_wdata[i] <= rvfi_mem_wdata_d;
rvfi_stage_mem_addr[i] <= rvfi_mem_addr_d;
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
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] <= cs_registers_i.mcycle_counter_i.counter_val_o;
rvfi_ext_stage_ic_scr_key_valid[i] <= cs_registers_i.cpuctrlsts_ic_scr_key_valid_q;
// This is done this way because SystemVerilog does not support looping through
// gen_cntrs[k] within a for loop.
for (int k=0; k < 10; k++) begin
@ -1457,12 +1463,13 @@ module ibex_core import ibex_pkg::*; #(
rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
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];
rvfi_ext_stage_mhpmcounters[i] <= rvfi_ext_stage_mhpmcounters[i-1];
rvfi_ext_stage_mhpmcountersh[i] <= rvfi_ext_stage_mhpmcountersh[i-1];
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
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];
rvfi_ext_stage_ic_scr_key_valid[i] <= rvfi_ext_stage_ic_scr_key_valid[i-1];
rvfi_ext_stage_mhpmcounters[i] <= rvfi_ext_stage_mhpmcounters[i-1];
rvfi_ext_stage_mhpmcountersh[i] <= rvfi_ext_stage_mhpmcountersh[i-1];
end
end
end

View file

@ -81,7 +81,7 @@ module ibex_cs_registers #(
input logic [31:0] pc_id_i,
input logic [31:0] pc_wb_i,
// CPU control bits
// CPU control and status bits
output logic data_ind_timing_o,
output logic dummy_instr_en_o,
output logic [2:0] dummy_instr_mask_o,
@ -89,6 +89,7 @@ module ibex_cs_registers #(
output logic [31:0] dummy_instr_seed_o,
output logic icache_enable_o,
output logic csr_shadow_err_o,
input logic ic_scr_key_valid_i,
// Exception save/restore
input logic csr_save_if_i,
@ -188,7 +189,10 @@ module ibex_cs_registers #(
priv_lvl_e prv;
} dcsr_t;
// CPU control register fields
// Partial CPU control and status register fields
// ICache scramble key valid (ic_scr_key_valid) is registered seperately to this struct. This is
// because it is sampled from the top-level every cycle whilst the other fields only change
// occasionally.
typedef struct packed {
logic double_fault_seen;
logic sync_exc_seen;
@ -196,7 +200,7 @@ module ibex_cs_registers #(
logic dummy_instr_en;
logic data_ind_timing;
logic icache_enable;
} cpu_ctrl_t;
} cpu_ctrl_sts_part_t;
// Interrupt and exception control signals
logic [31:0] exception_pc;
@ -268,9 +272,13 @@ module ibex_cs_registers #(
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;
cpu_ctrl_sts_part_t cpuctrlsts_part_q, cpuctrlsts_part_d;
cpu_ctrl_sts_part_t cpuctrlsts_part_wdata_raw, cpuctrlsts_part_wdata;
logic cpuctrlsts_part_we;
logic cpuctrlsts_part_err;
logic cpuctrlsts_ic_scr_key_valid_q;
logic cpuctrlsts_ic_scr_key_err;
// CSR update logic
logic [31:0] csr_wdata_int;
@ -515,9 +523,11 @@ 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};
// Custom CSR for controlling CPU features and reporting CPU status
CSR_CPUCTRLSTS: begin
csr_rdata_int = {{32 - $bits(cpu_ctrl_sts_part_t) - 1 {1'b0}},
cpuctrlsts_ic_scr_key_valid_q,
cpuctrlsts_part_q};
end
// Custom CSR for LFSR re-seeding (cannot be read)
@ -580,8 +590,8 @@ module ibex_cs_registers #(
mhpmcounter_we = '0;
mhpmcounterh_we = '0;
cpuctrl_we = 1'b0;
cpuctrl_d = cpuctrl_q;
cpuctrlsts_part_we = 1'b0;
cpuctrlsts_part_d = cpuctrlsts_part_q;
double_fault_seen_o = 1'b0;
@ -682,9 +692,9 @@ module ibex_cs_registers #(
mhpmcounterh_we[mhpmcounter_idx] = 1'b1;
end
CSR_CPUCTRL: begin
cpuctrl_d = cpuctrl_wdata;
cpuctrl_we = 1'b1;
CSR_CPUCTRLSTS: begin
cpuctrlsts_part_d = cpuctrlsts_part_wdata;
cpuctrlsts_part_we = 1'b1;
end
default:;
@ -739,12 +749,12 @@ module ibex_cs_registers #(
if (!(mcause_d.irq_ext || mcause_d.irq_int)) begin
// SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC
// SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC
cpuctrl_we = 1'b1;
cpuctrlsts_part_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;
cpuctrlsts_part_d.sync_exc_seen = 1'b1;
if (cpuctrlsts_part_q.sync_exc_seen) begin
double_fault_seen_o = 1'b1;
cpuctrlsts_part_d.double_fault_seen = 1'b1;
end
end
end
@ -765,8 +775,8 @@ module ibex_cs_registers #(
// 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;
cpuctrlsts_part_we = 1'b1;
cpuctrlsts_part_d.sync_exc_seen = 1'b0;
if (nmi_mode_i) begin
// when returning from an NMI restore state from mstack CSR
@ -1558,29 +1568,30 @@ module ibex_cs_registers #(
//////////////////////////
// Cast register write data
assign cpuctrl_wdata_raw = cpu_ctrl_t'(csr_wdata_int[$bits(cpu_ctrl_t)-1:0]);
assign cpuctrlsts_part_wdata_raw =
cpu_ctrl_sts_part_t'(csr_wdata_int[$bits(cpu_ctrl_sts_part_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;
assign cpuctrlsts_part_wdata.data_ind_timing = cpuctrlsts_part_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;
assign unused_dit = cpuctrlsts_part_wdata_raw.data_ind_timing;
// field will always read as zero if not configured
assign cpuctrl_wdata.data_ind_timing = 1'b0;
assign cpuctrlsts_part_wdata.data_ind_timing = 1'b0;
end
assign data_ind_timing_o = cpuctrl_q.data_ind_timing;
assign data_ind_timing_o = cpuctrlsts_part_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;
assign cpuctrlsts_part_wdata.dummy_instr_en = cpuctrlsts_part_wdata_raw.dummy_instr_en;
assign cpuctrlsts_part_wdata.dummy_instr_mask = cpuctrlsts_part_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);
@ -1590,50 +1601,72 @@ module ibex_cs_registers #(
// 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;
assign unused_dummy_en = cpuctrlsts_part_wdata_raw.dummy_instr_en;
assign unused_dummy_mask = cpuctrlsts_part_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;
assign cpuctrlsts_part_wdata.dummy_instr_en = 1'b0;
assign cpuctrlsts_part_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;
assign dummy_instr_en_o = cpuctrlsts_part_q.dummy_instr_en;
assign dummy_instr_mask_o = cpuctrlsts_part_q.dummy_instr_mask;
// Generate icache enable bit
if (ICache) begin : gen_icache_enable
assign cpuctrl_wdata.icache_enable = cpuctrl_wdata_raw.icache_enable;
assign cpuctrlsts_part_wdata.icache_enable = cpuctrlsts_part_wdata_raw.icache_enable;
ibex_csr #(
.Width (1),
.ShadowCopy(ShadowCSR),
.ResetValue(1'b0)
) u_cpuctrlsts_ic_scr_key_valid_q_csr (
.clk_i (clk_i),
.rst_ni (rst_ni),
.wr_data_i (ic_scr_key_valid_i),
.wr_en_i (1'b1),
.rd_data_o (cpuctrlsts_ic_scr_key_valid_q),
.rd_error_o(cpuctrlsts_ic_scr_key_err)
);
end else begin : gen_no_icache
// tieoff for the unused icen bit
logic unused_icen;
assign unused_icen = cpuctrl_wdata_raw.icache_enable;
assign unused_icen = cpuctrlsts_part_wdata_raw.icache_enable;
// icen field will always read as zero if ICache not configured
assign cpuctrl_wdata.icache_enable = 1'b0;
assign cpuctrlsts_part_wdata.icache_enable = 1'b0;
logic unused_ic_scr_key_valid;
assign unused_ic_scr_key_valid = ic_scr_key_valid_i;
// ic_scr_key_valid will always read as zero if ICache not configured
assign cpuctrlsts_ic_scr_key_valid_q = 1'b0;
assign cpuctrlsts_ic_scr_key_err = 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 cpuctrlsts_part_wdata.double_fault_seen = cpuctrlsts_part_wdata_raw.double_fault_seen;
assign cpuctrlsts_part_wdata.sync_exc_seen = cpuctrlsts_part_wdata_raw.sync_exc_seen;
assign icache_enable_o = cpuctrl_q.icache_enable;
assign icache_enable_o = cpuctrlsts_part_q.icache_enable;
ibex_csr #(
.Width ($bits(cpu_ctrl_t)),
.Width ($bits(cpu_ctrl_sts_part_t)),
.ShadowCopy(ShadowCSR),
.ResetValue('0)
) u_cpuctrl_csr (
) u_cpuctrlsts_part_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)
.wr_data_i ({cpuctrlsts_part_d}),
.wr_en_i (cpuctrlsts_part_we),
.rd_data_o (cpuctrlsts_part_q),
.rd_error_o(cpuctrlsts_part_err)
);
assign csr_shadow_err_o = mstatus_err | mtvec_err | pmp_csr_err | cpuctrl_err;
assign csr_shadow_err_o =
mstatus_err | mtvec_err | pmp_csr_err | cpuctrlsts_part_err | cpuctrlsts_ic_scr_key_err;
////////////////
// Assertions //

View file

@ -400,35 +400,36 @@ module ibex_lockstep import ibex_pkg::*; #(
.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 (),
.rvfi_ext_mhpmcounters (),
.rvfi_ext_mhpmcountersh (),
.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 (),
.rvfi_ext_mhpmcounters (),
.rvfi_ext_mhpmcountersh (),
.rvfi_ext_ic_scr_key_valid (),
`endif
.fetch_enable_i (shadow_inputs_q[0].fetch_enable),

View file

@ -584,7 +584,7 @@ package ibex_pkg;
CSR_MHPMCOUNTER29H = 12'hB9D,
CSR_MHPMCOUNTER30H = 12'hB9E,
CSR_MHPMCOUNTER31H = 12'hB9F,
CSR_CPUCTRL = 12'h7C0,
CSR_CPUCTRLSTS = 12'h7C0,
CSR_SECURESEED = 12'h7C1
} csr_num_e;

View file

@ -122,6 +122,7 @@ module ibex_top import ibex_pkg::*; #(
output logic [63:0] rvfi_ext_mcycle,
output logic [31:0] rvfi_ext_mhpmcounters [10],
output logic [31:0] rvfi_ext_mhpmcountersh [10],
output logic rvfi_ext_ic_scr_key_valid,
`endif
// CPU Control Signals
@ -369,6 +370,7 @@ module ibex_top import ibex_pkg::*; #(
.rvfi_ext_mcycle,
.rvfi_ext_mhpmcounters,
.rvfi_ext_mhpmcountersh,
.rvfi_ext_ic_scr_key_valid,
`endif
.fetch_enable_i (fetch_enable_buf),

View file

@ -126,6 +126,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
logic [31:0] rvfi_ext_mhpmcounters [10];
logic [31:0] rvfi_ext_mhpmcountersh [10];
logic rvfi_ext_ic_scr_key_valid;
logic [31:0] unused_perf_regs [10];
logic [31:0] unused_perf_regsh [10];
@ -135,6 +136,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
logic unused_rvfi_ext_nmi;
logic unused_rvfi_ext_debug_req;
logic [63:0] unused_rvfi_ext_mcycle;
logic unused_rvfi_ext_ic_scr_key_valid;
// Tracer doesn't use these signals, though other modules may probe down into tracer to observe
// them.
@ -144,6 +146,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
assign unused_rvfi_ext_mcycle = rvfi_ext_mcycle;
assign unused_perf_regs = rvfi_ext_mhpmcounters;
assign unused_perf_regsh = rvfi_ext_mhpmcountersh;
assign unused_rvfi_ext_ic_scr_key_valid = rvfi_ext_ic_scr_key_valid;
ibex_top #(
.PMPEnable ( PMPEnable ),
@ -243,6 +246,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
.rvfi_ext_mcycle,
.rvfi_ext_mhpmcounters,
.rvfi_ext_mhpmcountersh,
.rvfi_ext_ic_scr_key_valid,
.fetch_enable_i,
.alert_minor_o,