From aa8c4a64dffb4c783a5266c45281391801600246 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Fri, 22 May 2026 23:54:33 -0700 Subject: [PATCH] First shot at happy path --- .../application_wrapper_cache_miss_handler.sv | 192 ++++++++++++++++++ .../cache/application_wrapper_cache_pkg.sv | 8 +- 2 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 src/application_wrapper/cache/application_wrapper_cache_miss_handler.sv diff --git a/src/application_wrapper/cache/application_wrapper_cache_miss_handler.sv b/src/application_wrapper/cache/application_wrapper_cache_miss_handler.sv new file mode 100644 index 0000000..adf168f --- /dev/null +++ b/src/application_wrapper/cache/application_wrapper_cache_miss_handler.sv @@ -0,0 +1,192 @@ +module application_wrapper_cache_miss_handler #( + parameter NUM_WAYS = 4, + parameter NUM_SETS = 64, + + localparam CPU_W = 8, + localparam DATA_W = 64*8, + localparam OFFSET_W = 6, + localparam INDEX_W = $clog2(NUM_SETS), + localparam TAG_W = 32 - INDEX_W - OFFSET_W, + localparam LRU_W = NUM_WAYS-1 + + localparam META_W = TAG_W + 2 +) ( + input logic i_clk, + input logic i_rst, + + // NOTE: tag is physical tag, expected 1 cycle after the index and the offset + input logic [TAG_W-1:0] i_cpu_tag, + input logic [INDEX_W-1:0] i_cpu_index, + input logic [OFFSET_W-1:0] i_cpu_offset, + + input logic i_rdy, + output logic o_rdy, + + input logic i_cpu_we, + + input logic [CPU_W-1:0] i_cpu_data, + output logic [CPU_W-1:0] o_cpu_data, + + output logic [INDEX_W-1:0] o_read_index, + output logic o_read_valid, + + input logic [DATA_W-1:0] i_read_data [NUM_WAYS], + input logic [META_W-1:0] i_read_meta [NUM_WAYS], + + output logic [INDEX_W-1:0] o_write_index, + output logic [NUM_WAYS-1:0] o_write_valid, + + output logic [DATA_W-1:0] o_write_data, + output logic [META_W-1:0] o_write_meta, + + output logic [INDEX_W-1:0] o_lru_read_index, + output logic o_lru_read_valid, + input logic [LRU_W-1:0]] i_lru_read_data, + + output logic [INDEX_W-1:0] o_lru_write_index, + output logic o_lru_write_valid, + output logic [LRU_W-1:0]] o_lru_write_data, +); + + +enum logic [3:0] { + IDLE, + CHECK_VICTIM, + WRITEBACK, + WAIT_WRITEBACK_ACK, + REQUEST_MEMORY, + WAIT_MEMORY, + INSTALL_LINE, + UPDATE_LRU, + REQUEST_OWNERSHIP +} state, state_next; + +logic cpu_we_d1; +logic cpu_i_data_d1; + +logic [INDEX_W-1:0] cpu_index_d1; +logic [OFFSET_W-1:0] cpu_offset_d1; + +logic way_match_found; +logic [NUM_WAYS-1:0] way_select_mask; +mesi_e mesi; +logic [TAG_W-1:0] tag; + +always_ff @(posedge i_clk) begin + if (i_rst) begin + state <= IDLE; + end else begin + state <= state_next; + end + + cpu_we_d1 <= i_cpu_we; + cpu_i_data_d1 <= i_cpu_data + cpu_index_d1 <= i_cpu_index; + cpu_offset_d1 <= i_cpu_offset; +end + +always_comb begin + o_rdy = '0; + o_cpu_data = '0; + + o_read_valid = '0; + o_read_index = '0; + + o_write_valid = '0; + o_write_index = '0; + o_write_data = '0; + o_write_meta = '0; + + o_lru_read_valid = '0; + o_lru_read_index = '0; + o_lru_write_valid = '0; + o_lru_write_index = '0; + o_lru_write_data = '0; + + + state_next = state; + + + case (state) + IDLE: begin + // by default, o_rdy is 1 unless something is wrong + o_rdy = '1; + + // Read from arrays + o_read_index = i_cpu_index; + o_read_valid = i_rdy; + + o_lru_read_index = i_cpu_index; + o_lru_read_valid = i_rdy; + + // data from previous cycle that was read from arrays + way_match_found = '0; + way_select_mask = '0; + for (int i; i < NUM_WAYS; i++) begin + {mesi, tag} = i_read_meta[i]; + if (tag == i_cpu_tag && mesi != MESI_INVALID) begin + way_match_found = '1; + way_select_mask[i] = '1; + break; + end + end + + // We have a match, so either read or write data + if (way_match_found) begin + if (cpu_we_d1) begin + // write data back to the cache array + // check if we are in the M or E states before we write. + // If we are in S then we need to request ownership before + // we can modify it. + if (mesi == MESI_MODIFIED || mesi == MESI_EXCLUSIVE) begin + o_write_data = i_read_data; + o_write_data[cpu_offset_d1 +: 8] = cpu_i_data_d1; + o_write_meta = {MESI_MODIFIED, i_cpu_tag}; + o_write_valid = way_select_mask; + o_write_index = cpu_index_d1; + + end else begin + o_rdy = '0; + state_next = REQUEST_OWNERSHIP; + end + end else begin + // Send the data to the CPU + o_cpu_data = i_read_data[cpu_offset_d1 +: 8]; + end + + // update lru + // start by copying the read data, then change the bits + // based on what we matched. + o_lru_write_index = cpu_index_d1; + o_lru_write_data = i_lru_read_data; + o_lru_write_valid = '1; + + case (way_select_mask) + 4'b0001: begin + o_lru_write_data[0] = '1; + o_lru_write_data[1] = '1; + end + + 4'b0010: begin + o_lru_write_data[0] = '1; + o_lru_write_data[1] = '0; + end + + 4'b0100: begin + o_lru_write_data[0] = '0; + o_lru_write_data[2] = '1; + end + + 4'b1000: begin + o_lru_write_data[0] = '0; + o_lru_write_data[2] = '0; + end + endcase + end + end + + default: begin + end + + endcase +end \ No newline at end of file diff --git a/src/application_wrapper/cache/application_wrapper_cache_pkg.sv b/src/application_wrapper/cache/application_wrapper_cache_pkg.sv index ffb330d..423aaac 100644 --- a/src/application_wrapper/cache/application_wrapper_cache_pkg.sv +++ b/src/application_wrapper/cache/application_wrapper_cache_pkg.sv @@ -19,10 +19,10 @@ package application_wrapper_cache_pkg; } cache_cmd_e; typedef enum logic [1:0] { - MODIFIED, - EXCLUSIVE, - SHARED, - INVALID + MESI_MODIFIED, + MESI_EXCLUSIVE, + MESI_SHARED, + MESI_INVALID } mesi_e; endpackage \ No newline at end of file