diff --git a/src/application_wrapper/cache/application_wrapper_cache_l1.sv b/src/application_wrapper/cache/application_wrapper_cache_l1.sv index 5820197..4ff9e03 100644 --- a/src/application_wrapper/cache/application_wrapper_cache_l1.sv +++ b/src/application_wrapper/cache/application_wrapper_cache_l1.sv @@ -88,7 +88,7 @@ logic [31:0] cache_miss_count, cache_miss_count_next; // reset counter logic [INDEX_W-1:0] clear_counter, clear_counter_next; -enum logic [2:0] {RESET, CLEAR, IDLE, READY, EVICT, READ} prev_state, state, state_next; +enum logic [2:0] {RESET, CLEAR, IDLE, READY, EVICT, READ, WAIT_CLEAN_UNIQUE} prev_state, state, state_next; always_ff @(posedge i_clk) begin if (i_rst) begin @@ -263,6 +263,23 @@ always_comb begin // We are accessing something we just wrote to if (latched_we) begin + // if we are writing to a shared cacheline, we must make it unique first! + if (current_data.shared) begin + o_rdy = '0; + + o_cache_cmd = CACHE_CLEAN_UNIQUE; + o_cache_valid = '1; + + latched_we_next = we_d1; + latched_data_next = data_d1; + + read_index_next = index_d1; + read_offset_next = offset_d1; + + + state_next = WAIT_CLEAN_UNIQUE; + end + write_data = current_data; write_data[offset_d1*8 +: 8] = latched_data; @@ -284,9 +301,9 @@ always_comb begin end else begin o_data = current_data[offset_d1*8 +: 8]; end + o_rdy = '1; end - o_rdy = '1; end end @@ -303,14 +320,18 @@ always_comb begin READ: begin o_cache_addr = read_address; - o_cache_cmd = CACHE_READ; + if (latched_we) begin + o_cache_cmd = CACHE_READ_UNIQUE; + end else begin + o_cache_cmd = CACHE_READ_SHARED; + end o_cache_valid = '1; write_index = read_index; write_data = i_cache_data; write_meta_tag.tag = read_address[31:INDEX_W+OFFSET_W]; write_meta_tag.valid = '1; - write_meta_tag.shared = '0; + write_meta_tag.shared = ~latched_we; // if we are about to write, then we requested unique write_meta_tag.clean = ~latched_we; // if we are about to write, then mark dirty data_write_enable = i_cache_rdy; @@ -327,6 +348,28 @@ always_comb begin end end + WAIT_CLEAN_UNIQUE: begin + // Write data after making it unique + if (i_cache_rdy) begin + write_data[offset_d1*8 +: 8] = latched_data; + data_write_enable = i_cache_rdy; + + meta_tag_write_enable = i_cache_rdy; + write_meta_tag.tag = read_address[31:INDEX_W+OFFSET_W]; + write_meta_tag.valid = '1; + write_meta_tag.shared = '0; + write_meta_tag.clean = '0; + + write_index = index_d1; + + if (index == write_index) begin + current_data_next = write_data; + end + + state_next = READY; + end + end + default: begin state_next = READY; end @@ -361,6 +404,20 @@ end already be dirty anyway. */ +/* + + In order for this to be a coherent requester, we need to adjust the protocol slightly + + * CPU Requests data to READ: Send ReadShared request + * CPU Requests data to WRITE: Send ReadUnique request + * CPU Writes to data already in cache: CleanUnique + * Clean cacheline overwritten: Send Evict request + * Dirty cacheline overwritten: Send WriteBackFull request + + The cache <-> CHI interface is handled by a separate module. +*/ + + endmodule \ 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 f595386..6b1f480 100644 --- a/src/application_wrapper/cache/application_wrapper_cache_pkg.sv +++ b/src/application_wrapper/cache/application_wrapper_cache_pkg.sv @@ -10,10 +10,12 @@ package application_wrapper_cache_pkg; logic write_through; } page_table_entry_t; - typedef enum logic [1:0] { + typedef enum logic [2:0] { CACHE_NONE, - CACHE_READ, - CACHE_WRITE + CACHE_READ_SHARED, + CACHE_READ_UNIQUE, + CACHE_WRITE, + CACHE_CLEAN_UNIQUE } cache_cmd_e; endpackage \ No newline at end of file