From 8c0b1e50d93ac82e16c7ea8ac70982d50f51c763 Mon Sep 17 00:00:00 2001 From: Pascal Nasahl Date: Fri, 10 Apr 2026 09:54:35 +0200 Subject: [PATCH 1/2] [rtl] Fix Linting Issue in iCache Tweak Infection Linting raised that constant zeros are stored in the `data_tweak_lw_ic1` and `tag_tweak_lw_ic1` FFs. Although this is exactly what we want, we can bypass this linting issue by only storing the relevant bits in the FFs and expand them before appyling the XOR. Signed-off-by: Pascal Nasahl --- rtl/ibex_icache.sv | 57 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/rtl/ibex_icache.sv b/rtl/ibex_icache.sv index abb16f4ed..ebbf2dbe5 100644 --- a/rtl/ibex_icache.sv +++ b/rtl/ibex_icache.sv @@ -324,15 +324,15 @@ module ibex_icache import ibex_pkg::*; #( // Determine the full address used for the outgoing data bank request. Apply '0, wich // effectively disabled the tweak infection, when (a) invalidating the cache and (b) // when there is already an ECC error (we have already raised a minor alert). - logic [ADDR_W-1:0] data_address_ic0; - logic [ADDR_W-1:0] data_tweak_ic0; + logic [ADDR_W-1:0] data_address_ic0; + logic [ADDR_W-IC_LINE_W-1:0] data_tweak_ic0; assign data_address_ic0 = inval_write_req ? '0 : ecc_write_req ? '0 : fill_grant_ic0 ? fill_ram_req_addr : lookup_addr_ic0; // Mask the IC_LINE_W LSBs to remove the offset within a cache line. - assign data_tweak_ic0 = {data_address_ic0[ADDR_W-1:IC_LINE_W], {IC_LINE_W{1'b0}}}; + assign data_tweak_ic0 = data_address_ic0[ADDR_W-1:IC_LINE_W]; // Tie off the unused LSBs. logic unused_data_address_ic0; @@ -343,7 +343,7 @@ module ibex_icache import ibex_pkg::*; #( always_comb begin data_tweak_lw_ic0 = '0; for (int i = 0; i < IC_LINE_BEATS; i++) begin - data_tweak_lw_ic0 |= (LineSizeECC'({data_tweak_ic0}) << + data_tweak_lw_ic0 |= (LineSizeECC'({data_tweak_ic0, {IC_LINE_W{1'b0}}}) << (i * (ADDR_W + IC_DATA_ECC_SIZE))); end end @@ -351,17 +351,37 @@ module ibex_icache import ibex_pkg::*; #( always_comb begin data_tweak_lw_ic0 = '0; for (int i = 0; i < IC_LINE_BEATS; i++) begin - data_tweak_lw_ic0 |= (LineSizeECC'({data_tweak_ic0}) << (i * ADDR_W)); + data_tweak_lw_ic0 |= (LineSizeECC'({data_tweak_ic0, {IC_LINE_W{1'b0}}}) << + (i * ADDR_W)); end end end // Pipeline the tweak to IC1 to align with the data RAM output timing. + logic [ADDR_W-IC_LINE_W-1:0] data_tweak_ic1; always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin - data_tweak_lw_ic1 <= '0; + data_tweak_ic1 <= '0; end else if (data_req_ic0) begin - data_tweak_lw_ic1 <= data_tweak_lw_ic0; + data_tweak_ic1 <= data_tweak_ic0; + end + end + + // Replicate the ADDR_W-bit tweak to match the LineSizeECC width. + if (ICacheECC) begin : gen_ecc_tweak_ic1 + always_comb begin + data_tweak_lw_ic1 = '0; + for (int i = 0; i < IC_LINE_BEATS; i++) begin + data_tweak_lw_ic1 |= (LineSizeECC'({data_tweak_ic1, {IC_LINE_W{1'b0}}}) << + (i * (ADDR_W + IC_DATA_ECC_SIZE))); + end + end + end else begin : gen_no_ecc_tweak_ic1 + always_comb begin + data_tweak_lw_ic1 = '0; + for (int i = 0; i < IC_LINE_BEATS; i++) begin + data_tweak_lw_ic1 |= (LineSizeECC'({data_tweak_ic1, {IC_LINE_W{1'b0}}}) << (i * ADDR_W)); + end end end @@ -384,11 +404,30 @@ module ibex_icache import ibex_pkg::*; #( end // Pipeline the tag tweak to IC1 to align with the tag RAM output timing. + logic [IC_INDEX_W-1:0] tag_index_ic1; always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin - tag_tweak_lw_ic1 <= '0; + tag_index_ic1 <= '0; end else if (tag_req_ic0) begin - tag_tweak_lw_ic1 <= tag_tweak_lw_ic0; + tag_index_ic1 <= tag_index_ic0; + end + end + + // Extend tag_index_ic1 to full TagSizeECC width for use at the read XOR. + if (ICacheECC) begin : gen_ecc_tag_tweak_ic1 + always_comb begin + tag_tweak_lw_ic1 = '0; + for (int i = 0; i < IC_LINE_BEATS; i++) begin + tag_tweak_lw_ic1 |= (TagSizeECC'({tag_index_ic1}) << + (i * (IC_INDEX_W + IC_TAG_ECC_SIZE))); + end + end + end else begin : gen_no_ecc_tag_tweak_ic1 + always_comb begin + tag_tweak_lw_ic1 = '0; + for (int i = 0; i < IC_LINE_BEATS; i++) begin + tag_tweak_lw_ic1 |= (TagSizeECC'({tag_index_ic1}) << (i * IC_INDEX_W)); + end end end end else begin: gen_no_tweak_infection From c06d8d62478d4945aa01e98a53690b7b536c20bf Mon Sep 17 00:00:00 2001 From: Pascal Nasahl Date: Fri, 10 Apr 2026 10:12:09 +0200 Subject: [PATCH 2/2] [rtl] Move ICache Removing Tweak Infection Instead of doing the un-XOR for all ways, just do it for the way we have a hit. This is identical from a functional perspective but is cleaner from an implementation perspective. Signed-off-by: Pascal Nasahl --- rtl/ibex_icache.sv | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/rtl/ibex_icache.sv b/rtl/ibex_icache.sv index ebbf2dbe5..9771a948e 100644 --- a/rtl/ibex_icache.sv +++ b/rtl/ibex_icache.sv @@ -108,7 +108,6 @@ module ibex_icache import ibex_pkg::*; #( // Cache pipeline IC1 signals logic [TagSizeECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] data_rdata_ic1 [IC_NUM_WAYS]; logic [LineSizeECC-1:0] hit_data_ecc_ic1; logic [IC_LINE_SIZE-1:0] hit_data_ic1; logic lookup_valid_ic1; @@ -463,12 +462,6 @@ module ibex_icache import ibex_pkg::*; #( // Tweak infection, XOR the data with the tweak before writing to RAM. assign ic_data_wdata_o = data_wdata_ic0 ^ data_tweak_lw_ic0; - // Data RAMs inputs - // Tweak infection, un-XOR the data using the tweak. - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_data_untweak - assign data_rdata_ic1[way] = ic_data_rdata_i[way] ^ data_tweak_lw_ic1; - end - always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin lookup_valid_ic1 <= 1'b0; @@ -509,12 +502,12 @@ module ibex_icache import ibex_pkg::*; #( assign tag_hit_ic1 = |tag_match_ic1; - // Hit data mux + // Hit data mux. Un-XOR the tweak only for the matching way. always_comb begin hit_data_ecc_ic1 = 'b0; for (int way = 0; way < IC_NUM_WAYS; way++) begin if (tag_match_ic1[way]) begin - hit_data_ecc_ic1 |= data_rdata_ic1[way]; + hit_data_ecc_ic1 |= ic_data_rdata_i[way] ^ data_tweak_lw_ic1; end end end