Skip to content

Commit

Permalink
Exception priority fix (FV), addr_bound_vio for clc/csc fix (FV), mis…
Browse files Browse the repository at this point in the history
…c cleanup
  • Loading branch information
kliuMsft committed Jan 22, 2024
1 parent 8c30aca commit 5c37f9a
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 95 deletions.
80 changes: 25 additions & 55 deletions rtl/cheri_ex.sv
Expand Up @@ -9,8 +9,7 @@ module cheri_ex import cheri_pkg::*; #(
parameter int unsigned TSMapSize,
parameter bit CheriPPLBC = 1'b1,
parameter bit CheriSBND2 = 1'b0,
parameter bit CheriStkZ = 1'b1,
parameter bit StkZ1Cycle = 1'b1
parameter bit CheriStkZ = 1'b1
)(
// Clock and Reset
input logic clk_i,
Expand Down Expand Up @@ -69,9 +68,9 @@ module cheri_ex import cheri_pkg::*; #(

output logic cheri_ex_valid_o,
output logic cheri_ex_err_o,
output logic [10:0] cheri_ex_err_info_o,
output logic [11:0] cheri_ex_err_info_o,
output logic cheri_wb_err_o,
output logic [10:0] cheri_wb_err_info_o,
output logic [11:0] cheri_wb_err_info_o,

// lsu interface
output logic lsu_req_o,
Expand Down Expand Up @@ -209,9 +208,9 @@ module cheri_ex import cheri_pkg::*; #(
logic lc_cglg, lc_csdlm, lc_ctag;
logic [31:0] pc_id_nxt;

full_cap_t setaddr1_outcap, setaddr2_outcap, setbounds_outcap;
logic [10:0] cheri_wb_err_info_q, cheri_wb_err_info_d;
logic [10:0] cheri_ex_err_info_q, cheri_ex_err_info_d;
full_cap_t setaddr1_outcap, setbounds_outcap;
logic [11:0] cheri_wb_err_info_q, cheri_wb_err_info_d;
logic [11:0] cheri_ex_err_info_q, cheri_ex_err_info_d;
logic set_bounds_done;

logic [4:0] cheri_err_cause, rv32_err_cause;
Expand Down Expand Up @@ -826,9 +825,6 @@ module cheri_ex import cheri_pkg::*; #(
logic top_vio, base_vio, top_equal;
logic cs2_bad_type;

// CSEAL/CUNSEAL, CIS_SUBSET, CLC/CSC checks are done here
// CJAL/CJALR use separate set_addr checking for timing

// generate the address used to check top bound violation
if (cheri_operator_i[CSEAL] | cheri_operator_i[CUNSEAL])
base_chkaddr = rf_rdata_b; // cs2.address
Expand Down Expand Up @@ -871,7 +867,9 @@ module cheri_ex import cheri_pkg::*; #(

if (debug_mode_i)
addr_bound_vio = 1'b0;
else if (is_cap | cheri_operator_i[CIS_SUBSET])
else if (is_cap)
addr_bound_vio = top_vio | base_vio | top_equal;
else if (cheri_operator_i[CIS_SUBSET])
addr_bound_vio = top_vio | base_vio;
else if (cheri_operator_i[CJAL] | cheri_operator_i[CJALR])
addr_bound_vio = top_vio | base_vio | top_equal;
Expand Down Expand Up @@ -937,6 +935,7 @@ module cheri_ex import cheri_pkg::*; #(
//
// fault case mtval generation
// report to csr as mtval
logic ls_addr_misaligned_only;

assign cheri_ex_err_info_o = cheri_ex_err_info_q;
assign cheri_wb_err_info_o = cheri_wb_err_info_q;
Expand All @@ -945,27 +944,29 @@ module cheri_ex import cheri_pkg::*; #(

always_comb begin : err_cause_comb
cheri_err_cause = vio_cause_enc(addr_bound_vio, perm_vio_vec);
rv32_err_cause = vio_cause_enc(addr_bound_vio_rv32, perm_vio_vec_rv32);
rv32_err_cause = vio_cause_enc(addr_bound_vio_rv32, perm_vio_vec_rv32);

ls_addr_misaligned_only = perm_vio_vec[PVIO_ALIGN] && (cheri_err_cause == 0);

if (cheri_exec_id_i & ~CheriPPLBC & cheri_tsafe_en_i & is_load_cap & cheri_lsu_err)
// 2-stage ppl load/store, error treated as EX error, cheri CLC check error
cheri_ex_err_info_d = {1'b0, rf_raddr_a_i, cheri_err_cause};
cheri_ex_err_info_d = {2'b00, rf_raddr_a_i, cheri_err_cause};
else if (cheri_exec_id_i & ~CheriPPLBC & cheri_tsafe_en_i & is_load_cap & clbc_err)
// 2-stage ppl load/store, error treated as EX error, memory error
cheri_ex_err_info_d = {1'b0, rf_raddr_a_i, 5'h1f};
cheri_ex_err_info_d = {2'b00, rf_raddr_a_i, 5'h1f};
else
cheri_ex_err_info_d = cheri_ex_err_info_q;

// cheri_wb_err_raw is already qualified by instr
if (cheri_operator_i[CCSR_RW] & cheri_wb_err_raw & cheri_exec_id_i)
// cspecialrw traps
cheri_wb_err_info_d = {1'b1, cheri_cs2_dec_i, cheri_err_cause};
cheri_wb_err_info_d = {1'b0, 1'b1, cheri_cs2_dec_i, cheri_err_cause};
else if (cheri_wb_err_raw & cheri_exec_id_i)
cheri_wb_err_info_d = {1'b0, rf_raddr_a_i, cheri_err_cause};
cheri_wb_err_info_d = {1'b0, 1'b0, rf_raddr_a_i, cheri_err_cause};
else if ((is_load_cap | is_store_cap) & cheri_lsu_err & cheri_exec_id_i)
cheri_wb_err_info_d = {1'b0, rf_raddr_a_i, cheri_err_cause};
cheri_wb_err_info_d = {ls_addr_misaligned_only, 1'b0, rf_raddr_a_i, cheri_err_cause};
else if (rv32_lsu_req_i & rv32_lsu_err)
cheri_wb_err_info_d = {1'b0, rf_raddr_a_i, rv32_err_cause};
cheri_wb_err_info_d = {1'b0, 1'b0, rf_raddr_a_i, rv32_err_cause};
else
cheri_wb_err_info_d = cheri_wb_err_info_q;
end
Expand All @@ -977,7 +978,7 @@ module cheri_ex import cheri_pkg::*; #(
cheri_ex_err_info_q <= 'h0;
end else begin
// Simple flop here works since if cheri_wb_err, lsu request won't be generated
// so wb stage only takes 1 cycle. QQQ
// so wb stage only takes 1 cycle.
cheri_wb_err_q <= cheri_wb_err_d;
cheri_wb_err_info_q <= cheri_wb_err_info_d;
cheri_ex_err_info_q <= cheri_ex_err_info_d;
Expand Down Expand Up @@ -1092,13 +1093,7 @@ module cheri_ex import cheri_pkg::*; #(
logic cpu_stkz_stall0, cpu_stkz_stall1;
logic cpu_stkz_err;

if (CheriStkZ & ~StkZ1Cycle) begin
// load/store takes 2 cycles when stkz_active
// always stall both lsu_req and cpu_lsu_dec duing first_cycle
assign lsu_req_o = ~cpu_stkz_stall0 & (instr_is_cheri_i ? cheri_lsu_req : rv32_lsu_req_i);
assign cpu_lsu_dec_o = ~cpu_stkz_stall1 & ((instr_is_cheri_i && is_cap) | instr_is_rv32lsu_i);

end else if (CheriStkZ & StkZ1Cycle) begin
if (CheriStkZ) begin
// load/store takes 1 cycle when stkz_active
assign lsu_req_o = ~cpu_stkz_stall0 & (instr_is_cheri_i ? cheri_lsu_req : rv32_lsu_req_i);
assign cpu_lsu_dec_o = ~cpu_stkz_stall1 & ((instr_is_cheri_i && is_cap) | instr_is_rv32lsu_i);
Expand Down Expand Up @@ -1164,35 +1159,7 @@ end
// Stack fast clearing support
//

if (CheriStkZ & ~StkZ1Cycle) begin
logic lsu_addr_in_range, stkz_stall_q;

// can't directly use csr_mshwm_i (high watermark) as the stack base here
// since mshwm itself will be updated by lsu write request
assign lsu_addr_in_range = (cpu_lsu_addr[31:4] >= stkz_base_i[31:4]) &&
(cpu_lsu_addr[31:2] < stkz_ptr_i[31:2]);

assign cpu_stkz_stall0 = (stkz_active_i & instr_first_cycle_i) | stkz_stall_q;
assign cpu_stkz_stall1 = cpu_stkz_stall0;

// load/store takes 2 cycles when stkz_active.
// -- we are doing this such that cpu_lsu_dec doesn't have to wait for address range
// check results combinatorially
// -- Note stkz_active_i is asserted synchronously by writing to the new stkz_ptr CSR.
// As such it is not possible for active to go from '0' to '1' in the middle of an
// load/store instruction when we want to keep lsu_req high while waiting for lsu_req_done
// QQQ may need an assertion for this.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
stkz_stall_q <= 1'b0;
cpu_stkz_err <= 1'b0;
end else begin
stkz_stall_q <= stkz_active_i & lsu_addr_in_range;
cpu_stkz_err <= lsu_req_done_i & stkz_abort_i & lsu_addr_in_range; // QQQ see the 1cyle case
end
end

end else if (CheriStkZ & StkZ1Cycle) begin
if (CheriStkZ) begin
logic lsu_addr_in_range, stkz_stall_q;

assign lsu_addr_in_range = (cpu_lsu_addr[31:4] >= stkz_base_i[31:4]) &&
Expand All @@ -1204,6 +1171,9 @@ end
// - however in the first cycle we speculatively still assert cpu_lsu_dec_o to let LSU choose
// the address from cpu core (and hold back stkz/tbre_req). In the next cycle we can deassert
// cpu_lsu_dec_o to let stkz/tbre_req go through
// -- Note stkz_active_i is asserted synchronously by writing to the new stkz_ptr CSR.
// As such it is not possible for active to go from '0' to '1' in the middle of an
// load/store instruction when we want to keep lsu_req high while waiting for lsu_req_done
assign cpu_stkz_stall0 = (instr_first_cycle_i & stkz_active_i & lsu_addr_in_range) | stkz_stall_q;
assign cpu_stkz_stall1 = ~instr_first_cycle_i & stkz_stall_q;

Expand Down
8 changes: 4 additions & 4 deletions rtl/cheri_pkg.sv
Expand Up @@ -859,14 +859,12 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas
function automatic logic [4:0] vio_cause_enc (logic bound_vio, logic[W_PVIO-1:0] perm_vio_vec);
logic [4:0] vio_cause;

if (bound_vio)
vio_cause = 5'h1;
else if (perm_vio_vec[PVIO_TAG])
if (perm_vio_vec[PVIO_TAG])
vio_cause = 5'h2;
else if (perm_vio_vec[PVIO_SEAL])
vio_cause = 5'h3;
else if (perm_vio_vec[PVIO_EX])
vio_cause = 5'h3;
vio_cause = 5'h11;
else if (perm_vio_vec[PVIO_LD])
vio_cause = 5'h12;
else if (perm_vio_vec[PVIO_SD])
Expand All @@ -877,6 +875,8 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas
vio_cause = 5'h16;
else if (perm_vio_vec[PVIO_ASR])
vio_cause = 5'h18;
else if (bound_vio)
vio_cause = 5'h1;
else
vio_cause = 5'h0;

Expand Down
4 changes: 2 additions & 2 deletions rtl/cheri_regfile.sv
Expand Up @@ -37,7 +37,7 @@ module cheri_regfile import cheri_pkg::*; #(
input logic [4:0] trvk_addr_i,
input logic trvk_en_i,
input logic trvk_clrtag_i,
input logic [6:0] trvk_par_i, // make sure this is included in lockstep compare QQQ
input logic [6:0] trvk_par_i, // make sure this is included in lockstep compare
input logic [4:0] trsv_addr_i,
input logic trsv_en_i,
input logic [6:0] trsv_par_i,
Expand Down Expand Up @@ -180,7 +180,7 @@ module cheri_regfile import cheri_pkg::*; #(
logic [4:0] trvk_addr_q;
logic trvk_en_q;
logic trvk_clrtag_q;
logic [6:0] trvk_par_q; // make sure this is included in lockstep compare QQQ
logic [6:0] trvk_par_q;
logic [4:0] trsv_addr_q;
logic trsv_en_q;
logic [6:0] trsv_par_q;
Expand Down
26 changes: 18 additions & 8 deletions rtl/ibex_controller.sv
Expand Up @@ -119,8 +119,8 @@ module ibex_controller #(
input logic cheri_ex_valid_i, // from cheri EX
input logic cheri_ex_err_i,
input logic cheri_wb_err_i,
input logic [10:0] cheri_ex_err_info_i,
input logic [10:0] cheri_wb_err_info_i,
input logic [11:0] cheri_ex_err_info_i,
input logic [11:0] cheri_wb_err_info_i,
input logic cheri_branch_req_i,
input logic [31:0] cheri_branch_target_i
);
Expand Down Expand Up @@ -760,17 +760,27 @@ module ibex_controller #(
end
store_err_prio: begin
if (cheri_pmode_i & lsu_err_is_cheri_q) begin
exc_cause_o = EXC_CAUSE_CHERI_FAULT;
csr_mtval_o = cheri_wb_err_info_i;
if (cheri_wb_err_info_i[11]) begin
exc_cause_o = EXC_CAUSE_STORE_ADDR_MISALIGN;
csr_mtval_o = lsu_addr_last_i;
end else begin
exc_cause_o = EXC_CAUSE_CHERI_FAULT;
csr_mtval_o = cheri_wb_err_info_i[10:0];
end
end else begin
exc_cause_o = EXC_CAUSE_STORE_ACCESS_FAULT;
csr_mtval_o = lsu_addr_last_i;
end
end
load_err_prio: begin
if (cheri_pmode_i & lsu_err_is_cheri_q) begin
exc_cause_o = EXC_CAUSE_CHERI_FAULT;
csr_mtval_o = cheri_wb_err_info_i;
if (cheri_wb_err_info_i[11]) begin
exc_cause_o = EXC_CAUSE_LOAD_ADDR_MISALIGN;
csr_mtval_o = lsu_addr_last_i;
end else begin
exc_cause_o = EXC_CAUSE_CHERI_FAULT;
csr_mtval_o = cheri_wb_err_info_i[10:0];
end
end else begin
exc_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT;
csr_mtval_o = lsu_addr_last_i;
Expand All @@ -779,13 +789,13 @@ module ibex_controller #(
cheri_ex_err_prio: begin
if (cheri_pmode_i) begin
exc_cause_o = EXC_CAUSE_CHERI_FAULT;
csr_mtval_o = cheri_ex_err_info_i;
csr_mtval_o = cheri_ex_err_info_i[10:0];
end
end
cheri_wb_err_prio: begin
if (cheri_pmode_i) begin
exc_cause_o = EXC_CAUSE_CHERI_FAULT;
csr_mtval_o = cheri_wb_err_info_i;
csr_mtval_o = cheri_wb_err_info_i[10:0];
end
end

Expand Down
10 changes: 3 additions & 7 deletions rtl/ibex_core.sv
Expand Up @@ -424,9 +424,9 @@ module ibex_core import ibex_pkg::*; import cheri_pkg::*; #(
reg_cap_t cheri_result_cap;
logic cheri_ex_valid;
logic cheri_ex_err;
logic [10:0] cheri_ex_err_info;
logic [11:0] cheri_ex_err_info;
logic cheri_wb_err;
logic [10:0] cheri_wb_err_info;
logic [11:0] cheri_wb_err_info;
logic [OPDW-1:0] cheri_operator;

logic rv32_lsu_req;
Expand Down Expand Up @@ -867,8 +867,7 @@ module ibex_core import ibex_pkg::*; import cheri_pkg::*; #(
.TSMapSize (TSMapSize),
.CheriPPLBC (CheriPPLBC),
.CheriSBND2 (CheriSBND2),
.CheriStkZ (CheriTBRE),
.StkZ1Cycle (1'b1)
.CheriStkZ (CheriTBRE)
) u_cheri_ex (
.clk_i (clk_i),
.rst_ni (rst_ni),
Expand Down Expand Up @@ -1275,9 +1274,6 @@ module ibex_core import ibex_pkg::*; import cheri_pkg::*; #(

assign rf_wcap_vec = reg2vec(rf_wcap_wb);

// need to protect the TRSV/TRVK interfaces ?? QQQ


// ECC checkbit generation
// -- for simplicity just linearly add the parity bits together.
// this is not as good as the full secded implementation (some double errors won't be detected)
Expand Down
2 changes: 1 addition & 1 deletion rtl/ibex_cs_registers.sv
Expand Up @@ -861,7 +861,7 @@ module ibex_cs_registers import cheri_pkg::*; #(

// only write CSRs during one clock cycle

// enforcing the CHERI CSR access policy. QQQ
// enforcing the CHERI CSR access policy.
// -- is reading zero back ok? or do we need to generate illegal access exception??
// -- also note IBEX didn't implement user-mode TIME/counters.
// for now we are allowing reading the M-mode counters (assuming only use single priv level)
Expand Down
4 changes: 2 additions & 2 deletions rtl/ibex_id_stage.sv
Expand Up @@ -209,9 +209,9 @@ module ibex_id_stage import cheri_pkg::*; #(

input logic cheri_ex_valid_i,
input logic cheri_ex_err_i,
input logic [10:0] cheri_ex_err_info_i,
input logic [11:0] cheri_ex_err_info_i,
input logic cheri_wb_err_i,
input logic [10:0] cheri_wb_err_info_i,
input logic [11:0] cheri_wb_err_info_i,
input logic cheri_branch_req_i, // from cheri EX
input logic [31:0] cheri_branch_target_i
);
Expand Down
2 changes: 1 addition & 1 deletion rtl/ibex_load_store_unit.sv
Expand Up @@ -581,7 +581,7 @@ module ibex_load_store_unit import ibex_pkg::*; import cheri_pkg::*; #(

CTX_WAIT_RESP: begin // only needed if mem allows 2 active req
if (cheri_pmode_i) begin
addr_incr_req_o = 1'b0;
addr_incr_req_o = 1'b1; // stay 1 to reduce unnecessary addr toggling
data_req_o = 1'b0;
if (data_rvalid_i) ls_fsm_ns = IDLE;
end else begin
Expand Down
32 changes: 17 additions & 15 deletions rtl/ibex_pkg.sv
Expand Up @@ -311,21 +311,23 @@ package ibex_pkg;

// 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},
EXC_CAUSE_CHERI_FAULT = {1'b0, 5'd28}
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_ADDR_MISALIGN = {1'b0, 5'd04},
EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05},
EXC_CAUSE_STORE_ADDR_MISALIGN = {1'b0, 5'd06},
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},
EXC_CAUSE_CHERI_FAULT = {1'b0, 5'd28}
} exc_cause_e;

// Debug cause
Expand Down

0 comments on commit 5c37f9a

Please sign in to comment.