diff --git a/src/snitch_icache_handler.sv b/src/snitch_icache_handler.sv index 3e9ee0b..e09ff48 100644 --- a/src/snitch_icache_handler.sv +++ b/src/snitch_icache_handler.sv @@ -315,7 +315,7 @@ module snitch_icache_handler #( if (hit_valid) begin out_rsp_ready_o = 0; in_rsp_data_o = hit_data; - in_rsp_error_o = 0; + in_rsp_error_o = hit_error; in_rsp_id_o = hit_id; in_rsp_valid_o = 1; hit_ready = in_rsp_ready_i; diff --git a/src/snitch_icache_l0.sv b/src/snitch_icache_l0.sv index d4460f6..447b704 100644 --- a/src/snitch_icache_l0.sv +++ b/src/snitch_icache_l0.sv @@ -12,40 +12,41 @@ module snitch_icache_l0 import snitch_icache_pkg::*; #( - parameter config_t CFG = '0, - parameter int unsigned L0_ID = 0 + parameter config_t CFG = '0, + parameter int unsigned L0_ID = 0 ) ( - input logic clk_i, - input logic rst_ni, - input logic flush_valid_i, - - input logic enable_prefetching_i, - input logic enable_branch_pred_i, - - output icache_l0_events_t icache_events_o, - - input logic [CFG.FETCH_AW-1:0] in_addr_i, - input logic in_valid_i, - output logic [CFG.FETCH_DW-1:0] in_data_o, - output logic in_ready_o, - output logic in_error_o, - - output logic [CFG.FETCH_AW-1:0] out_req_addr_o, - output logic [CFG.ID_WIDTH-1:0] out_req_id_o, - output logic out_req_valid_o, - input logic out_req_ready_i, - - input logic [CFG.LINE_WIDTH-1:0] out_rsp_data_i, - input logic out_rsp_error_i, - input logic [ CFG.ID_WIDTH-1:0] out_rsp_id_i, - input logic out_rsp_valid_i, - output logic out_rsp_ready_o + input logic clk_i, + input logic rst_ni, + input logic flush_valid_i, + + input logic enable_prefetching_i, + input logic enable_branch_pred_i, + + output icache_l0_events_t icache_events_o, + + input logic [CFG.FETCH_AW-1:0] in_addr_i, + input logic in_valid_i, + output logic [CFG.FETCH_DW-1:0] in_data_o, + output logic in_ready_o, + output logic in_error_o, + + output logic [CFG.FETCH_AW-1:0] out_req_addr_o, + output logic [CFG.ID_WIDTH-1:0] out_req_id_o, + output logic out_req_valid_o, + input logic out_req_ready_i, + + input logic [CFG.LINE_WIDTH-1:0] out_rsp_data_i, + input logic out_rsp_error_i, + input logic [ CFG.ID_WIDTH-1:0] out_rsp_id_i, + input logic out_rsp_valid_i, + output logic out_rsp_ready_o ); typedef logic [CFG.FETCH_AW-1:0] addr_t; typedef struct packed { logic [CFG.L0_TAG_WIDTH-1:0] tag; logic vld; + logic err; } tag_t; logic [CFG.L0_TAG_WIDTH-1:0] addr_tag, addr_tag_prefetch, addr_tag_prefetch_req; @@ -138,11 +139,16 @@ module snitch_icache_l0 assign hit_prefetch_any = |hit_prefetch; assign miss = ~hit_any & in_valid_i & ~pending_refill_q & ~prefetching_missed_line; - logic clk_inv; - tc_clk_inverter i_clk_inv ( - .clk_i(clk_i), - .clk_o(clk_inv) - ); + logic [CFG.LINE_WIDTH-1:0] line_in_q; + if (CFG.EARLY_LATCH) begin + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + line_in_q <= '0; + end else begin + line_in_q <= out_rsp_data_i; + end + end + end for (genvar i = 0; i < CFG.L0_LINE_COUNT; i++) begin : gen_array // Tag Array @@ -150,6 +156,7 @@ module snitch_icache_l0 if (!rst_ni) begin tag[i].vld <= 0; tag[i].tag <= 0; + tag[i].err <= 0; end else begin if (evict_strb[i]) begin tag[i].vld <= 1'b0; @@ -158,23 +165,25 @@ module snitch_icache_l0 tag[i].vld <= 1'b0; end else if (validate_strb[i]) begin tag[i].vld <= 1'b1; + tag[i].err <= out_rsp_error_i; end end end if (CFG.EARLY_LATCH) begin : gen_latch + logic clk_vld; tc_clk_gating i_clk_gate ( - .clk_i (clk_inv), - .en_i (validate_strb[i]), - .test_en_i(1'b0), - .clk_o (clk_vld) + .clk_i (clk_i), + .en_i (validate_strb[i]), + .test_en_i(1'b0), + .clk_o (clk_vld) ); // Data Array /* verilator lint_off NOLATCH */ /* verilator lint_off COMBDLY */ always_latch begin if (clk_vld) begin - data[i] <= out_rsp_data_i; + data[i] <= line_in_q; end end /* verilator lint_on COMBDLY */ @@ -192,9 +201,11 @@ module snitch_icache_l0 logic [CFG.LINE_WIDTH-1:0] ins_data; always_comb begin : data_muxer - ins_data = '0; + ins_data = '0; + in_error_o = 1'b0; for (int unsigned i = 0; i < CFG.L0_LINE_COUNT; i++) begin ins_data |= {CFG.LINE_WIDTH{hit[i]}} & data[i]; + in_error_o |= hit[i] & tag[i].err; end in_data_o = CFG.FETCH_DW'( ins_data >> (in_addr_i[CFG.LINE_ALIGN-1:CFG.FETCH_ALIGN] * CFG.FETCH_DW) @@ -205,10 +216,10 @@ module snitch_icache_l0 // multiple entries in the tag array) if (CFG.L0_TAG_WIDTH != CFG.L0_EARLY_TAG_WIDTH) begin : gen_multihit_detection cc_onehot #( - .Width(CFG.L0_LINE_COUNT) + .Width(CFG.L0_LINE_COUNT) ) i_onehot_hit_early ( - .d_i (hit_early), - .is_onehot_o(hit_early_is_onehot) + .d_i (hit_early), + .is_onehot_o(hit_early_is_onehot) ); end else begin : gen_no_multihit_detection assign hit_early_is_onehot = 1'b1; @@ -296,8 +307,6 @@ module snitch_icache_l0 assign out_rsp_ready_o = 1'b1; - assign in_error_o = '0; - assign out_req_addr_o = out_req.addr; assign out_req_id_o = CFG.ID_WIDTH'(1'b1 << {L0_ID, out_req.is_prefetch}); @@ -369,13 +378,13 @@ module snitch_icache_l0 assign ins_idx = 32 * taken_idx; // Find first taken branch lzc #( - .WIDTH(FetchPkts), - .MODE (0) + .WIDTH(FetchPkts), + .MODE (0) ) i_lzc_branch ( - // look at branches and jals - .in_i (mask & (is_branch_taken | is_jal)), - .cnt_o (taken_idx), - .empty_o(no_prefetch) + // look at branches and jals + .in_i (mask & (is_branch_taken | is_jal)), + .cnt_o (taken_idx), + .empty_o(no_prefetch) ); addr_t base_addr, offset, uj_imm, sb_imm;