mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 03:47:15 -04:00
[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:
parent
06fece4640
commit
70186c57ae
23 changed files with 302 additions and 201 deletions
|
@ -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"
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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
|
||||
--------------------
|
||||
|
||||
|
|
|
@ -5,3 +5,4 @@ sphinx~=3.0
|
|||
sphinx_rtd_theme
|
||||
sphinxcontrib-wavedrom
|
||||
wavedrom>=1.9.0rc1
|
||||
jinja2 == 3.0.3
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
3
dv/uvm/core_ibex/env/core_ibex_rvfi_if.sv
vendored
3
dv/uvm/core_ibex/env/core_ibex_rvfi_if.sv
vendored
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
149
rtl/ibex_core.sv
149
rtl/ibex_core.sv
|
@ -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
|
||||
|
|
|
@ -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 //
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue