From 2b9f6f3d0b9d2776a498ad580cd33db7a053b0b8 Mon Sep 17 00:00:00 2001 From: Savan Roshan Date: Fri, 1 Nov 2019 00:39:02 -0400 Subject: [PATCH] Fixed eviction_wb --- rtl/cache/VX_Cache_Bank.v | 470 ++++++++++---------- rtl/cache/VX_cache_data_per_index.v | 8 +- rtl/cache/VX_d_cache.v | 653 ++++++++++++++-------------- 3 files changed, 567 insertions(+), 564 deletions(-) diff --git a/rtl/cache/VX_Cache_Bank.v b/rtl/cache/VX_Cache_Bank.v index 5753c7d0..1ffafc0a 100644 --- a/rtl/cache/VX_Cache_Bank.v +++ b/rtl/cache/VX_Cache_Bank.v @@ -1,235 +1,235 @@ -// To Do: Change way_id_out to an internal register which holds when in between access and finished. -// Also add a bit about wheter the "Way ID" is valid / being held or if it is just default -// Also make sure all possible output states are transmitted back to the bank correctly - -`include "../VX_define.v" -// `include "VX_cache_data.v" - - -module VX_Cache_Bank - #( - parameter CACHE_SIZE = 4096, // Bytes - parameter CACHE_WAYS = 1, - parameter CACHE_BLOCK = 128, // Bytes - parameter CACHE_BANKS = 8 - ) - ( - clk, - rst, - state, - read_or_write, // Read = 0 | Write = 1 - i_p_mem_read, - i_p_mem_write, - valid_in, - //write_from_mem, - actual_index, - o_tag, - block_offset, - writedata, - fetched_writedata, - - byte_select, - - readdata, - hit, - //miss, - - eviction_wb, // Need to evict - eviction_addr, // What's the eviction tag - - data_evicted, - evicted_way, - way_use - ); - - localparam NUMBER_BANKS = CACHE_BANKS; - localparam CACHE_BLOCK_PER_BANK = (CACHE_BLOCK / CACHE_BANKS); - localparam NUM_WORDS_PER_BLOCK = CACHE_BLOCK / (CACHE_BANKS*4); - localparam NUMBER_INDEXES = `NUM_IND; - - localparam CACHE_IDLE = 0; // Idle - localparam SEND_MEM_REQ = 1; // Write back this block into memory - localparam RECIV_MEM_RSP = 2; - - // Inputs - input wire rst; - input wire clk; - input wire [3:0] state; -//input wire write_from_mem; - - // Reading Data - input wire[`CACHE_IND_SIZE_RNG] actual_index; - - - input wire[`CACHE_TAG_SIZE_RNG] o_tag; // When write_from_mem = 1, o_tag is the new tag - input wire[`CACHE_OFFSET_SIZE_RNG] block_offset; - - - input wire[31:0] writedata; - input wire valid_in; - input wire read_or_write; // Specifies if it is a read or write operation - - input wire[NUM_WORDS_PER_BLOCK-1:0][31:0] fetched_writedata; - input wire[2:0] i_p_mem_read; - input wire[2:0] i_p_mem_write; - input wire[1:0] byte_select; - - - input wire[$clog2(CACHE_WAYS)-1:0] evicted_way; - output wire[$clog2(CACHE_WAYS)-1:0] way_use; - - // Outputs - // Normal shit - output wire[31:0] readdata; - output wire hit; - //output wire miss; - - // Eviction Data (Notice) - output wire eviction_wb; // Need to evict - output wire[31:0] eviction_addr; // What's the eviction tag - - // Eviction Data (Extraction) - output wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_evicted; - - - - wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_use; - wire[`CACHE_TAG_SIZE_RNG] tag_use; - wire[`CACHE_TAG_SIZE_RNG] eviction_tag; - wire valid_use; - wire dirty_use; - wire access; - wire write_from_mem; - wire miss; // -10/21 - - - - wire[$clog2(CACHE_WAYS)-1:0] update_way; - wire[$clog2(CACHE_WAYS)-1:0] way_to_update; - - assign miss = (tag_use != o_tag) && valid_use && valid_in; - - - assign data_evicted = data_use; - - assign eviction_wb = miss && (dirty_use != 1'b0) && valid_use; - assign eviction_tag = tag_use; - assign access = (state == CACHE_IDLE) && valid_in; - assign write_from_mem = (state == RECIV_MEM_RSP) && valid_in; // TODO - assign hit = (access && (tag_use == o_tag) && valid_use); - //assign eviction_addr = {eviction_tag, actual_index, block_offset, 5'b0}; // Fix with actual data - assign eviction_addr = {eviction_tag, actual_index, 7'b0}; // Fix with actual data - assign update_way = hit ? way_use : 0; - - - - wire lb = (i_p_mem_read == `LB_MEM_READ); - wire lh = (i_p_mem_read == `LH_MEM_READ); - wire lhu = (i_p_mem_read == `LHU_MEM_READ); - wire lbu = (i_p_mem_read == `LBU_MEM_READ); - - wire sw = (i_p_mem_write == `SW_MEM_WRITE); - wire sb = (i_p_mem_write == `SB_MEM_WRITE); - wire sh = (i_p_mem_write == `SH_MEM_WRITE); - - wire b0 = (byte_select == 0); - wire b1 = (byte_select == 1); - wire b2 = (byte_select == 2); - wire b3 = (byte_select == 3); - - wire[31:0] data_unQual = b0 ? (data_use[block_offset] ) : - b1 ? (data_use[block_offset] >> 8) : - b2 ? (data_use[block_offset] >> 16) : - (data_use[block_offset] >> 24); - - - wire[31:0] lb_data = (data_unQual[7] ) ? (data_unQual | 32'hFFFFFF00) : (data_unQual & 32'hFF); - wire[31:0] lh_data = (data_unQual[15]) ? (data_unQual | 32'hFFFF0000) : (data_unQual & 32'hFFFF); - wire[31:0] lbu_data = (data_unQual & 32'hFF); - wire[31:0] lhu_data = (data_unQual & 32'hFFFF); - wire[31:0] lw_data = (data_unQual); - - wire[31:0] data_Qual = lb ? lb_data : - lh ? lh_data : - lhu ? lhu_data : - lbu ? lbu_data : - lw_data; - - - assign readdata = (access) ? data_Qual : 32'b0; // Fix with actual data - - - wire[3:0] sb_mask = (b0 ? 4'b0001 : (b1 ? 4'b0010 : (b2 ? 4'b0100 : 4'b1000))); - wire[3:0] sh_mask = (b0 ? 4'b0011 : 4'b1100); - - - wire[NUM_WORDS_PER_BLOCK-1:0][3:0] we; - wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_write; - genvar g; - for (g = 0; g < NUM_WORDS_PER_BLOCK; g = g + 1) begin - wire normal_write = (read_or_write && ((access && (block_offset == g))) && !miss); - - assign we[g] = (write_from_mem) ? 4'b1111 : - (normal_write && sw) ? 4'b1111 : - (normal_write && sb) ? sb_mask : - (normal_write && sh) ? sh_mask : - 4'b0000; - - - // assign we[g] = (normal_write || (write_from_mem)) ? 1'b1 : 1'b0; - assign data_write[g] = write_from_mem ? fetched_writedata[g] : writedata; - assign way_to_update = write_from_mem ? evicted_way : update_way; - end - - - VX_cache_data_per_index #( - .CACHE_SIZE(CACHE_SIZE), - .CACHE_WAYS(CACHE_WAYS), - .CACHE_BLOCK(CACHE_BLOCK), - .CACHE_BANKS(CACHE_BANKS), - .NUM_WORDS_PER_BLOCK(NUM_WORDS_PER_BLOCK)) data_structures( - .clk (clk), - .rst (rst), - .valid_in (valid_in), - // Inputs - .addr (actual_index), - .we (we), - .evict (write_from_mem), - .data_write (data_write), - .tag_write (o_tag), - .way_to_update(way_to_update), - // Outputs - .tag_use (tag_use), - .data_use (data_use), - .valid_use (valid_use), - .dirty_use (dirty_use), - .way (way_use) - ); - - // VX_cache_data #( - // .CACHE_SIZE(CACHE_SIZE), - // .CACHE_WAYS(CACHE_WAYS), - // .CACHE_BLOCK(CACHE_BLOCK), - // .CACHE_BANKS(CACHE_BANKS), - // .NUM_WORDS_PER_BLOCK(NUM_WORDS_PER_BLOCK)) data_structures( - // .clk (clk), - // .rst (rst), - // // Inputs - // .addr (actual_index), - // .we (we), - // .evict (write_from_mem), - // .data_write(data_write), - // .tag_write (o_tag), - // // Outputs - // .tag_use (tag_use), - // .data_use (data_use), - // .valid_use (valid_use), - // .dirty_use (dirty_use) - // ); - - -endmodule - - - - +// To Do: Change way_id_out to an internal register which holds when in between access and finished. +// Also add a bit about wheter the "Way ID" is valid / being held or if it is just default +// Also make sure all possible output states are transmitted back to the bank correctly + +`include "../VX_define.v" +// `include "VX_cache_data.v" + + +module VX_Cache_Bank + #( + parameter CACHE_SIZE = 4096, // Bytes + parameter CACHE_WAYS = 1, + parameter CACHE_BLOCK = 128, // Bytes + parameter CACHE_BANKS = 8 + ) + ( + clk, + rst, + state, + read_or_write, // Read = 0 | Write = 1 + i_p_mem_read, + i_p_mem_write, + valid_in, + //write_from_mem, + actual_index, + o_tag, + block_offset, + writedata, + fetched_writedata, + + byte_select, + + readdata, + hit, + //miss, + + eviction_wb, // Need to evict + eviction_addr, // What's the eviction tag + + data_evicted, + evicted_way, + way_use + ); + + localparam NUMBER_BANKS = CACHE_BANKS; + localparam CACHE_BLOCK_PER_BANK = (CACHE_BLOCK / CACHE_BANKS); + localparam NUM_WORDS_PER_BLOCK = CACHE_BLOCK / (CACHE_BANKS*4); + localparam NUMBER_INDEXES = `NUM_IND; + + localparam CACHE_IDLE = 0; // Idle + localparam SEND_MEM_REQ = 1; // Write back this block into memory + localparam RECIV_MEM_RSP = 2; + + // Inputs + input wire rst; + input wire clk; + input wire [3:0] state; +//input wire write_from_mem; + + // Reading Data + input wire[`CACHE_IND_SIZE_RNG] actual_index; + + + input wire[`CACHE_TAG_SIZE_RNG] o_tag; // When write_from_mem = 1, o_tag is the new tag + input wire[`CACHE_OFFSET_SIZE_RNG] block_offset; + + + input wire[31:0] writedata; + input wire valid_in; + input wire read_or_write; // Specifies if it is a read or write operation + + input wire[NUM_WORDS_PER_BLOCK-1:0][31:0] fetched_writedata; + input wire[2:0] i_p_mem_read; + input wire[2:0] i_p_mem_write; + input wire[1:0] byte_select; + + + input wire[$clog2(CACHE_WAYS)-1:0] evicted_way; + output wire[$clog2(CACHE_WAYS)-1:0] way_use; + + // Outputs + // Normal shit + output wire[31:0] readdata; + output wire hit; + //output wire miss; + + // Eviction Data (Notice) + output wire eviction_wb; // Need to evict + output wire[31:0] eviction_addr; // What's the eviction tag + + // Eviction Data (Extraction) + output wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_evicted; + + + + wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_use; + wire[`CACHE_TAG_SIZE_RNG] tag_use; + wire[`CACHE_TAG_SIZE_RNG] eviction_tag; + wire valid_use; + wire dirty_use; + wire access; + wire write_from_mem; + wire miss; // -10/21 + + + + wire[$clog2(CACHE_WAYS)-1:0] update_way; + wire[$clog2(CACHE_WAYS)-1:0] way_to_update; + + assign miss = (tag_use != o_tag) && valid_use && valid_in; + + + assign data_evicted = data_use; + + assign eviction_wb = miss && (dirty_use != 1'b0) && valid_use; + assign eviction_tag = tag_use; + assign access = (state == CACHE_IDLE) && valid_in; + assign write_from_mem = (state == RECIV_MEM_RSP) && valid_in; // TODO + assign hit = (access && (tag_use == o_tag) && valid_use); + //assign eviction_addr = {eviction_tag, actual_index, block_offset, 5'b0}; // Fix with actual data + assign eviction_addr = {eviction_tag, actual_index, 7'b0}; // Fix with actual data + assign update_way = hit ? way_use : 0; + + + + wire lb = (i_p_mem_read == `LB_MEM_READ); + wire lh = (i_p_mem_read == `LH_MEM_READ); + wire lhu = (i_p_mem_read == `LHU_MEM_READ); + wire lbu = (i_p_mem_read == `LBU_MEM_READ); + + wire sw = (i_p_mem_write == `SW_MEM_WRITE); + wire sb = (i_p_mem_write == `SB_MEM_WRITE); + wire sh = (i_p_mem_write == `SH_MEM_WRITE); + + wire b0 = (byte_select == 0); + wire b1 = (byte_select == 1); + wire b2 = (byte_select == 2); + wire b3 = (byte_select == 3); + + wire[31:0] data_unQual = b0 ? (data_use[block_offset] ) : + b1 ? (data_use[block_offset] >> 8) : + b2 ? (data_use[block_offset] >> 16) : + (data_use[block_offset] >> 24); + + + wire[31:0] lb_data = (data_unQual[7] ) ? (data_unQual | 32'hFFFFFF00) : (data_unQual & 32'hFF); + wire[31:0] lh_data = (data_unQual[15]) ? (data_unQual | 32'hFFFF0000) : (data_unQual & 32'hFFFF); + wire[31:0] lbu_data = (data_unQual & 32'hFF); + wire[31:0] lhu_data = (data_unQual & 32'hFFFF); + wire[31:0] lw_data = (data_unQual); + + wire[31:0] data_Qual = lb ? lb_data : + lh ? lh_data : + lhu ? lhu_data : + lbu ? lbu_data : + lw_data; + + + assign readdata = (access) ? data_Qual : 32'b0; // Fix with actual data + + + wire[3:0] sb_mask = (b0 ? 4'b0001 : (b1 ? 4'b0010 : (b2 ? 4'b0100 : 4'b1000))); + wire[3:0] sh_mask = (b0 ? 4'b0011 : 4'b1100); + + + wire[NUM_WORDS_PER_BLOCK-1:0][3:0] we; + wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_write; + genvar g; + for (g = 0; g < NUM_WORDS_PER_BLOCK; g = g + 1) begin + wire normal_write = (read_or_write && ((access && (block_offset == g))) && !miss); + + assign we[g] = (write_from_mem) ? 4'b1111 : + (normal_write && sw) ? 4'b1111 : + (normal_write && sb) ? sb_mask : + (normal_write && sh) ? sh_mask : + 4'b0000; + + + // assign we[g] = (normal_write || (write_from_mem)) ? 1'b1 : 1'b0; + assign data_write[g] = write_from_mem ? fetched_writedata[g] : writedata; + assign way_to_update = write_from_mem ? evicted_way : update_way; + end + + + VX_cache_data_per_index #( + .CACHE_SIZE(CACHE_SIZE), + .CACHE_WAYS(CACHE_WAYS), + .CACHE_BLOCK(CACHE_BLOCK), + .CACHE_BANKS(CACHE_BANKS), + .NUM_WORDS_PER_BLOCK(NUM_WORDS_PER_BLOCK)) data_structures( + .clk (clk), + .rst (rst), + .valid_in (valid_in), + // Inputs + .addr (actual_index), + .we (we), + .evict (write_from_mem), + .data_write (data_write), + .tag_write (o_tag), + .way_to_update(way_to_update), + // Outputs + .tag_use (tag_use), + .data_use (data_use), + .valid_use (valid_use), + .dirty_use (dirty_use), + .way (way_use) + ); + + // VX_cache_data #( + // .CACHE_SIZE(CACHE_SIZE), + // .CACHE_WAYS(CACHE_WAYS), + // .CACHE_BLOCK(CACHE_BLOCK), + // .CACHE_BANKS(CACHE_BANKS), + // .NUM_WORDS_PER_BLOCK(NUM_WORDS_PER_BLOCK)) data_structures( + // .clk (clk), + // .rst (rst), + // // Inputs + // .addr (actual_index), + // .we (we), + // .evict (write_from_mem), + // .data_write(data_write), + // .tag_write (o_tag), + // // Outputs + // .tag_use (tag_use), + // .data_use (data_use), + // .valid_use (valid_use), + // .dirty_use (dirty_use) + // ); + + +endmodule + + + + diff --git a/rtl/cache/VX_cache_data_per_index.v b/rtl/cache/VX_cache_data_per_index.v index 2a4b2e77..d6bf11ab 100644 --- a/rtl/cache/VX_cache_data_per_index.v +++ b/rtl/cache/VX_cache_data_per_index.v @@ -66,10 +66,10 @@ module VX_cache_data_per_index - wire hit = |hit_per_way && valid_in; - wire miss = ~hit && valid_in; - wire update = |we && valid_in && !miss; - wire valid = &valid_use_per_way && valid_in; + wire hit = |hit_per_way; + wire miss = ~hit; + wire update = |we && !miss; + wire valid = &valid_use_per_way; assign way = hit ? way_index : (valid ? eviction_way_index[addr] : (invalid_found ? invalid_index : 0)); assign tag_use = hit ? tag_use_per_way[way_index] : (valid ? tag_use_per_way[eviction_way_index[addr]] : (invalid_found ? tag_use_per_way[invalid_index] : 0)); diff --git a/rtl/cache/VX_d_cache.v b/rtl/cache/VX_d_cache.v index 1bf09ede..e0e8d7db 100644 --- a/rtl/cache/VX_d_cache.v +++ b/rtl/cache/VX_d_cache.v @@ -1,325 +1,328 @@ -// Cache Memory (8way 4word) // -// i_ means input port // -// o_ means output port // -// _p_ means data exchange with processor // -// _m_ means data exchange with memory // - - -// TO DO: -// - Send in a response from memory of what the data is from the test bench - -`include "../VX_define.v" -//`include "VX_priority_encoder.v" -// `include "VX_Cache_Bank.v" -//`include "cache_set.v" - -module VX_d_cache - #( - parameter CACHE_SIZE = 4096, // Bytes - parameter CACHE_WAYS = 1, - parameter CACHE_BLOCK = 128, // Bytes - parameter CACHE_BANKS = 8, - parameter NUM_REQ = 8 - ) - ( - clk, - rst, - i_p_addr, - //i_p_byte_en, - i_p_writedata, - i_p_read_or_write, // 0 = Read | 1 = Write - i_p_mem_read, - i_p_mem_write, - i_p_valid, - //i_p_write, - o_p_readdata, - o_p_delay, // 0 = all threads done | 1 = Still threads that need to - - o_m_evict_addr, - o_m_read_addr, - - o_m_writedata, - - o_m_read_or_write, // 0 = Read | 1 = Write - o_m_valid, - i_m_readdata, - - i_m_ready - ); - - parameter NUMBER_BANKS = CACHE_BANKS; - localparam NUM_WORDS_PER_BLOCK = CACHE_BLOCK / (CACHE_BANKS*4); - - localparam CACHE_BLOCK_PER_BANK = (CACHE_BLOCK / NUMBER_BANKS); - - localparam CACHE_IDLE = 0; // Idle - localparam SEND_MEM_REQ = 1; // Write back this block into memory - localparam RECIV_MEM_RSP = 2; - - - //parameter cache_entry = 9; - input wire clk, rst; - input wire [NUM_REQ-1:0] i_p_valid; - input wire [NUM_REQ-1:0][31:0] i_p_addr; // FIXME - input wire [NUM_REQ-1:0][31:0] i_p_writedata; - input wire i_p_read_or_write; //, i_p_write; - output reg [NUM_REQ-1:0][31:0] o_p_readdata; - output wire o_p_delay; - output reg [31:0] o_m_evict_addr; // Address is xxxxxxxxxxoooobbbyy - output reg [31:0] o_m_read_addr; - output reg o_m_valid; - output reg[NUMBER_BANKS - 1:0][NUM_WORDS_PER_BLOCK-1:0][31:0] o_m_writedata; - output reg o_m_read_or_write; //, o_m_write; - input wire[NUMBER_BANKS - 1:0][NUM_WORDS_PER_BLOCK-1:0][31:0] i_m_readdata; - input wire i_m_ready; - - input wire[2:0] i_p_mem_read; - input wire[2:0] i_p_mem_write; - - - // Buffer for final data - reg [NUM_REQ-1:0][31:0] final_data_read; - reg [NUM_REQ-1:0][31:0] new_final_data_read; - wire[NUM_REQ-1:0][31:0] new_final_data_read_Qual; - - assign o_p_readdata = new_final_data_read_Qual; - - - - wire[NUMBER_BANKS - 1 : 0][NUM_REQ-1:0] thread_track_banks; // Valid thread mask per bank - wire[NUMBER_BANKS - 1 : 0][$clog2(NUM_REQ)-1:0] index_per_bank; // Index of thread each bank will try to service - wire[NUMBER_BANKS - 1 : 0][NUM_REQ-1:0] use_mask_per_bank; // A mask of index_per_bank - wire[NUMBER_BANKS - 1 : 0] valid_per_bank; // Valid request going to each bank - wire[NUMBER_BANKS - 1 : 0][NUM_REQ-1:0] threads_serviced_per_bank; // Bank successfully serviced per bank - - wire[NUMBER_BANKS-1:0][31:0] readdata_per_bank; // Data read from each bank - wire[NUMBER_BANKS-1:0] hit_per_bank; // Whether each bank got a hit or a miss - wire[NUMBER_BANKS-1:0] eviction_wb; - - - wire[NUMBER_BANKS -1 : 0][$clog2(CACHE_WAYS)-1:0] evicted_way_new; - reg [NUMBER_BANKS -1 : 0][$clog2(CACHE_WAYS)-1:0] evicted_way_old; - wire[NUMBER_BANKS -1 : 0][$clog2(CACHE_WAYS)-1:0] way_used; - - // Internal State - reg [3:0] state; - wire[3:0] new_state; - - wire[NUM_REQ-1:0] use_valid; // Valid used throught the code - reg[NUM_REQ-1:0] stored_valid; // Saving the threads still left (bank conflict or bank miss) - wire[NUM_REQ-1:0] new_stored_valid; // New stored valid - - - - reg[NUMBER_BANKS - 1 : 0][31:0] eviction_addr_per_bank; - - reg[31:0] miss_addr; - reg[31:0] evict_addr; - - wire curr_processor_request_valid = (|i_p_valid); - - - assign use_valid = (stored_valid == 0) ? i_p_valid : stored_valid; - - - - - - - VX_cache_bank_valid #(.NUMBER_BANKS(NUMBER_BANKS)) multip_banks( - .i_p_valid (use_valid), - .i_p_addr (i_p_addr), - .thread_track_banks(thread_track_banks) - ); - - - reg[NUM_REQ-1:0] threads_serviced_Qual; - - reg[NUM_REQ-1:0] debug_hit_per_bank_mask[NUMBER_BANKS-1:0]; - - genvar bid; - for (bid = 0; bid < NUMBER_BANKS; bid=bid+1) - begin - wire[NUM_REQ-1:0] use_threads_track_banks = thread_track_banks[bid]; - wire[$clog2(NUM_REQ)-1:0] use_thread_index = index_per_bank[bid]; - wire use_write_final_data = hit_per_bank[bid]; - wire[31:0] use_data_final_data = readdata_per_bank[bid]; - VX_priority_encoder_w_mask #(.N(NUM_REQ)) choose_thread( - .valids(use_threads_track_banks), - .mask (use_mask_per_bank[bid]), - .index (index_per_bank[bid]), - .found (valid_per_bank[bid]) - ); - - assign debug_hit_per_bank_mask[bid] = {NUM_REQ{hit_per_bank[bid]}}; - assign threads_serviced_per_bank[bid] = use_mask_per_bank[bid] & debug_hit_per_bank_mask[bid]; - end - - integer test_bid; - always @(*) begin - new_final_data_read = 0; - for (test_bid=0; test_bid < NUMBER_BANKS; test_bid=test_bid+1) - begin - if (hit_per_bank[test_bid]) begin - new_final_data_read[index_per_bank[test_bid]] = readdata_per_bank[test_bid]; - end - end - end - - - wire[NUMBER_BANKS - 1 : 0] detect_bank_miss; - assign threads_serviced_Qual = threads_serviced_per_bank[0] | threads_serviced_per_bank[1] | - threads_serviced_per_bank[2] | threads_serviced_per_bank[3] | - threads_serviced_per_bank[4] | threads_serviced_per_bank[5] | - threads_serviced_per_bank[6] | threads_serviced_per_bank[7]; - // genvar bbid; - // always @(*) begin - // for (bbid = 0; bbid < NUMBER_BANKS; bbid=bbid+1) - // begin - // assign threads_serviced_Qual = threads_serviced_Qual | threads_serviced_per_bank[bbid]; - // end - // end - - - - genvar tid; - for (tid = 0; tid < NUM_REQ; tid =tid+1) - begin - assign new_final_data_read_Qual[tid] = threads_serviced_Qual[tid] ? new_final_data_read[tid] : final_data_read[tid]; - end - - - assign detect_bank_miss = (valid_per_bank & ~hit_per_bank); - - wire delay; - assign delay = (new_stored_valid != 0) || (state != CACHE_IDLE); // add other states - - assign o_p_delay = delay; - - wire[NUMBER_BANKS - 1 : 0][$clog2(NUM_REQ)-1:0] send_index_to_bank = index_per_bank; - - - wire[$clog2(NUMBER_BANKS)-1:0] miss_bank_index; - wire miss_found; - VX_generic_priority_encoder #(.N(NUMBER_BANKS)) get_miss_index - ( - .valids(detect_bank_miss), - .index (miss_bank_index), - .found (miss_found) - ); - - - - assign new_state = ((state == CACHE_IDLE) && (|detect_bank_miss)) ? SEND_MEM_REQ : - (state == SEND_MEM_REQ) ? RECIV_MEM_RSP : - ((state == RECIV_MEM_RSP) && !i_m_ready) ? RECIV_MEM_RSP : - CACHE_IDLE; - - // Handle if there is more than one miss - assign new_stored_valid = use_valid & (~threads_serviced_Qual); - -/////////////////////////////////////////////////////////////////////// - genvar cur_t; - integer init_b; - always @(posedge clk, posedge rst) begin - if (rst) begin - final_data_read <= 0; - // new_final_data_read = 0; - state <= 0; - stored_valid <= 0; - // eviction_addr_per_bank <= 0; - miss_addr <= 0; - evict_addr <= 0; - // threads_serviced_Qual = 0; - // for (init_b = 0; init_b < NUMBER_BANKS; init_b=init_b+1) - // begin - // debug_hit_per_bank_mask[init_b] <= 0; - // end - evicted_way_old <= 0; - - end else begin - state <= new_state; - - stored_valid <= new_stored_valid; - - if (miss_found) begin - miss_addr <= i_p_addr[send_index_to_bank[miss_bank_index]]; - evict_addr <= eviction_addr_per_bank[miss_bank_index]; - end - - final_data_read <= new_final_data_read_Qual; - evicted_way_old <= evicted_way_new; - end - end - - - genvar bank_id; - generate - for (bank_id = 0; bank_id < NUMBER_BANKS; bank_id = bank_id + 1) - begin - wire[31:0] bank_addr = (state == SEND_MEM_REQ) ? evict_addr : - (state == RECIV_MEM_RSP) ? miss_addr : - i_p_addr[send_index_to_bank[bank_id]]; - - assign evicted_way_new[bank_id] = (state == SEND_MEM_REQ) ? way_used[bank_id] : - (state == RECIV_MEM_RSP) ? evicted_way_old[bank_id] : - 0; - - wire[1:0] byte_select = bank_addr[1:0]; - wire[`CACHE_OFFSET_SIZE_RNG] cache_offset = bank_addr[`CACHE_ADDR_OFFSET_RNG]; - wire[`CACHE_IND_SIZE_RNG] cache_index = bank_addr[`CACHE_ADDR_IND_RNG]; - wire[`CACHE_TAG_SIZE_RNG] cache_tag = bank_addr[`CACHE_ADDR_TAG_RNG]; - - - wire normal_valid_in = valid_per_bank[bank_id]; - wire use_valid_in = ((state == RECIV_MEM_RSP) && i_m_ready) ? 1'b1 : - ((state == RECIV_MEM_RSP) && !i_m_ready) ? 1'b0 : - ((state == SEND_MEM_REQ)) ? 1'b0 : - normal_valid_in; - - VX_Cache_Bank #( - .CACHE_SIZE(CACHE_SIZE), - .CACHE_WAYS(CACHE_WAYS), - .CACHE_BLOCK(CACHE_BLOCK), - .CACHE_BANKS(CACHE_BANKS)) bank_structure - ( - .clk (clk), - .rst (rst), - .state (state), - .valid_in (use_valid_in), - .actual_index (cache_index), - .o_tag (cache_tag), - .block_offset (cache_offset), - .writedata (i_p_writedata[send_index_to_bank[bank_id]]), - .read_or_write (i_p_read_or_write), - .i_p_mem_read (i_p_mem_read), - .i_p_mem_write (i_p_mem_write), - .byte_select (byte_select), - .hit (hit_per_bank[bank_id]), - .readdata (readdata_per_bank[bank_id]), // Data read - .eviction_addr (eviction_addr_per_bank[bank_id]), - .data_evicted (o_m_writedata[bank_id]), - .eviction_wb (eviction_wb[bank_id]), // Something needs to be written back - .fetched_writedata(i_m_readdata[bank_id]), // Data From memory - .evicted_way (evicted_way_new[bank_id]), - .way_use (way_used[bank_id]) - ); - - end - endgenerate - - // Mem Rsp - - // Req to mem: - assign o_m_evict_addr = evict_addr & 32'hffffffc0; - assign o_m_read_addr = miss_addr & 32'hffffffc0; - assign o_m_valid = (state == SEND_MEM_REQ); - assign o_m_read_or_write = (state == SEND_MEM_REQ) && (|eviction_wb); - //end - -endmodule - - - - - +// Cache Memory (8way 4word) // +// i_ means input port // +// o_ means output port // +// _p_ means data exchange with processor // +// _m_ means data exchange with memory // + + +// TO DO: +// - Send in a response from memory of what the data is from the test bench + +`include "../VX_define.v" +//`include "VX_priority_encoder.v" +// `include "VX_Cache_Bank.v" +//`include "cache_set.v" + +module VX_d_cache + #( + parameter CACHE_SIZE = 4096, // Bytes + parameter CACHE_WAYS = 1, + parameter CACHE_BLOCK = 128, // Bytes + parameter CACHE_BANKS = 8, + parameter NUM_REQ = 8 + ) + ( + clk, + rst, + i_p_addr, + //i_p_byte_en, + i_p_writedata, + i_p_read_or_write, // 0 = Read | 1 = Write + i_p_mem_read, + i_p_mem_write, + i_p_valid, + //i_p_write, + o_p_readdata, + o_p_delay, // 0 = all threads done | 1 = Still threads that need to + + o_m_evict_addr, + o_m_read_addr, + + o_m_writedata, + + o_m_read_or_write, // 0 = Read | 1 = Write + o_m_valid, + i_m_readdata, + + i_m_ready + ); + + parameter NUMBER_BANKS = CACHE_BANKS; + localparam NUM_WORDS_PER_BLOCK = CACHE_BLOCK / (CACHE_BANKS*4); + + localparam CACHE_BLOCK_PER_BANK = (CACHE_BLOCK / NUMBER_BANKS); + + localparam CACHE_IDLE = 0; // Idle + localparam SEND_MEM_REQ = 1; // Write back this block into memory + localparam RECIV_MEM_RSP = 2; + + + //parameter cache_entry = 9; + input wire clk, rst; + input wire [NUM_REQ-1:0] i_p_valid; + input wire [NUM_REQ-1:0][31:0] i_p_addr; // FIXME + input wire [NUM_REQ-1:0][31:0] i_p_writedata; + input wire i_p_read_or_write; //, i_p_write; + output reg [NUM_REQ-1:0][31:0] o_p_readdata; + output wire o_p_delay; + output reg [31:0] o_m_evict_addr; // Address is xxxxxxxxxxoooobbbyy + output reg [31:0] o_m_read_addr; + output reg o_m_valid; + output reg[NUMBER_BANKS - 1:0][NUM_WORDS_PER_BLOCK-1:0][31:0] o_m_writedata; + output reg o_m_read_or_write; //, o_m_write; + input wire[NUMBER_BANKS - 1:0][NUM_WORDS_PER_BLOCK-1:0][31:0] i_m_readdata; + input wire i_m_ready; + + input wire[2:0] i_p_mem_read; + input wire[2:0] i_p_mem_write; + + + // Buffer for final data + reg [NUM_REQ-1:0][31:0] final_data_read; + reg [NUM_REQ-1:0][31:0] new_final_data_read; + wire[NUM_REQ-1:0][31:0] new_final_data_read_Qual; + + assign o_p_readdata = new_final_data_read_Qual; + + + + wire[NUMBER_BANKS - 1 : 0][NUM_REQ-1:0] thread_track_banks; // Valid thread mask per bank + wire[NUMBER_BANKS - 1 : 0][$clog2(NUM_REQ)-1:0] index_per_bank; // Index of thread each bank will try to service + wire[NUMBER_BANKS - 1 : 0][NUM_REQ-1:0] use_mask_per_bank; // A mask of index_per_bank + wire[NUMBER_BANKS - 1 : 0] valid_per_bank; // Valid request going to each bank + wire[NUMBER_BANKS - 1 : 0][NUM_REQ-1:0] threads_serviced_per_bank; // Bank successfully serviced per bank + + wire[NUMBER_BANKS-1:0][31:0] readdata_per_bank; // Data read from each bank + wire[NUMBER_BANKS-1:0] hit_per_bank; // Whether each bank got a hit or a miss + wire[NUMBER_BANKS-1:0] eviction_wb; + reg[NUMBER_BANKS-1:0] eviction_wb_old; + + + wire[NUMBER_BANKS -1 : 0][$clog2(CACHE_WAYS)-1:0] evicted_way_new; + reg [NUMBER_BANKS -1 : 0][$clog2(CACHE_WAYS)-1:0] evicted_way_old; + wire[NUMBER_BANKS -1 : 0][$clog2(CACHE_WAYS)-1:0] way_used; + + // Internal State + reg [3:0] state; + wire[3:0] new_state; + + wire[NUM_REQ-1:0] use_valid; // Valid used throught the code + reg[NUM_REQ-1:0] stored_valid; // Saving the threads still left (bank conflict or bank miss) + wire[NUM_REQ-1:0] new_stored_valid; // New stored valid + + + + reg[NUMBER_BANKS - 1 : 0][31:0] eviction_addr_per_bank; + + reg[31:0] miss_addr; + reg[31:0] evict_addr; + + wire curr_processor_request_valid = (|i_p_valid); + + + assign use_valid = (stored_valid == 0) ? i_p_valid : stored_valid; + + + + + + + VX_cache_bank_valid #(.NUMBER_BANKS(NUMBER_BANKS)) multip_banks( + .i_p_valid (use_valid), + .i_p_addr (i_p_addr), + .thread_track_banks(thread_track_banks) + ); + + + reg[NUM_REQ-1:0] threads_serviced_Qual; + + reg[NUM_REQ-1:0] debug_hit_per_bank_mask[NUMBER_BANKS-1:0]; + + genvar bid; + for (bid = 0; bid < NUMBER_BANKS; bid=bid+1) + begin + wire[NUM_REQ-1:0] use_threads_track_banks = thread_track_banks[bid]; + wire[$clog2(NUM_REQ)-1:0] use_thread_index = index_per_bank[bid]; + wire use_write_final_data = hit_per_bank[bid]; + wire[31:0] use_data_final_data = readdata_per_bank[bid]; + VX_priority_encoder_w_mask #(.N(NUM_REQ)) choose_thread( + .valids(use_threads_track_banks), + .mask (use_mask_per_bank[bid]), + .index (index_per_bank[bid]), + .found (valid_per_bank[bid]) + ); + + assign debug_hit_per_bank_mask[bid] = {NUM_REQ{hit_per_bank[bid]}}; + assign threads_serviced_per_bank[bid] = use_mask_per_bank[bid] & debug_hit_per_bank_mask[bid]; + end + + integer test_bid; + always @(*) begin + new_final_data_read = 0; + for (test_bid=0; test_bid < NUMBER_BANKS; test_bid=test_bid+1) + begin + if (hit_per_bank[test_bid]) begin + new_final_data_read[index_per_bank[test_bid]] = readdata_per_bank[test_bid]; + end + end + end + + + wire[NUMBER_BANKS - 1 : 0] detect_bank_miss; + assign threads_serviced_Qual = threads_serviced_per_bank[0] | threads_serviced_per_bank[1] | + threads_serviced_per_bank[2] | threads_serviced_per_bank[3] | + threads_serviced_per_bank[4] | threads_serviced_per_bank[5] | + threads_serviced_per_bank[6] | threads_serviced_per_bank[7]; + // genvar bbid; + // always @(*) begin + // for (bbid = 0; bbid < NUMBER_BANKS; bbid=bbid+1) + // begin + // assign threads_serviced_Qual = threads_serviced_Qual | threads_serviced_per_bank[bbid]; + // end + // end + + + + genvar tid; + for (tid = 0; tid < NUM_REQ; tid =tid+1) + begin + assign new_final_data_read_Qual[tid] = threads_serviced_Qual[tid] ? new_final_data_read[tid] : final_data_read[tid]; + end + + + assign detect_bank_miss = (valid_per_bank & ~hit_per_bank); + + wire delay; + assign delay = (new_stored_valid != 0) || (state != CACHE_IDLE); // add other states + + assign o_p_delay = delay; + + wire[NUMBER_BANKS - 1 : 0][$clog2(NUM_REQ)-1:0] send_index_to_bank = index_per_bank; + + + wire[$clog2(NUMBER_BANKS)-1:0] miss_bank_index; + wire miss_found; + VX_generic_priority_encoder #(.N(NUMBER_BANKS)) get_miss_index + ( + .valids(detect_bank_miss), + .index (miss_bank_index), + .found (miss_found) + ); + + + + assign new_state = ((state == CACHE_IDLE) && (|detect_bank_miss)) ? SEND_MEM_REQ : + (state == SEND_MEM_REQ) ? RECIV_MEM_RSP : + ((state == RECIV_MEM_RSP) && !i_m_ready) ? RECIV_MEM_RSP : + CACHE_IDLE; + + // Handle if there is more than one miss + assign new_stored_valid = use_valid & (~threads_serviced_Qual); + +/////////////////////////////////////////////////////////////////////// + genvar cur_t; + integer init_b; + always @(posedge clk, posedge rst) begin + if (rst) begin + final_data_read <= 0; + // new_final_data_read = 0; + state <= 0; + stored_valid <= 0; + // eviction_addr_per_bank <= 0; + miss_addr <= 0; + evict_addr <= 0; + // threads_serviced_Qual = 0; + // for (init_b = 0; init_b < NUMBER_BANKS; init_b=init_b+1) + // begin + // debug_hit_per_bank_mask[init_b] <= 0; + // end + evicted_way_old <= 0; + eviction_wb_old <= 0; + + end else begin + state <= new_state; + + stored_valid <= new_stored_valid; + + if (miss_found) begin + miss_addr <= i_p_addr[send_index_to_bank[miss_bank_index]]; + evict_addr <= eviction_addr_per_bank[miss_bank_index]; + end + + final_data_read <= new_final_data_read_Qual; + evicted_way_old <= evicted_way_new; + eviction_wb_old <= eviction_wb; + end + end + + + genvar bank_id; + generate + for (bank_id = 0; bank_id < NUMBER_BANKS; bank_id = bank_id + 1) + begin + wire[31:0] bank_addr = (state == SEND_MEM_REQ) ? evict_addr : + (state == RECIV_MEM_RSP) ? miss_addr : + i_p_addr[send_index_to_bank[bank_id]]; + + assign evicted_way_new[bank_id] = (state == SEND_MEM_REQ) ? way_used[bank_id] : + (state == RECIV_MEM_RSP) ? evicted_way_old[bank_id] : + 0; + + wire[1:0] byte_select = bank_addr[1:0]; + wire[`CACHE_OFFSET_SIZE_RNG] cache_offset = bank_addr[`CACHE_ADDR_OFFSET_RNG]; + wire[`CACHE_IND_SIZE_RNG] cache_index = bank_addr[`CACHE_ADDR_IND_RNG]; + wire[`CACHE_TAG_SIZE_RNG] cache_tag = bank_addr[`CACHE_ADDR_TAG_RNG]; + + + wire normal_valid_in = valid_per_bank[bank_id]; + wire use_valid_in = ((state == RECIV_MEM_RSP) && i_m_ready) ? 1'b1 : + ((state == RECIV_MEM_RSP) && !i_m_ready) ? 1'b0 : + ((state == SEND_MEM_REQ)) ? 1'b0 : + normal_valid_in; + + VX_Cache_Bank #( + .CACHE_SIZE(CACHE_SIZE), + .CACHE_WAYS(CACHE_WAYS), + .CACHE_BLOCK(CACHE_BLOCK), + .CACHE_BANKS(CACHE_BANKS)) bank_structure + ( + .clk (clk), + .rst (rst), + .state (state), + .valid_in (use_valid_in), + .actual_index (cache_index), + .o_tag (cache_tag), + .block_offset (cache_offset), + .writedata (i_p_writedata[send_index_to_bank[bank_id]]), + .read_or_write (i_p_read_or_write), + .i_p_mem_read (i_p_mem_read), + .i_p_mem_write (i_p_mem_write), + .byte_select (byte_select), + .hit (hit_per_bank[bank_id]), + .readdata (readdata_per_bank[bank_id]), // Data read + .eviction_addr (eviction_addr_per_bank[bank_id]), + .data_evicted (o_m_writedata[bank_id]), + .eviction_wb (eviction_wb[bank_id]), // Something needs to be written back + .fetched_writedata(i_m_readdata[bank_id]), // Data From memory + .evicted_way (evicted_way_new[bank_id]), + .way_use (way_used[bank_id]) + ); + + end + endgenerate + + // Mem Rsp + + // Req to mem: + assign o_m_evict_addr = evict_addr & 32'hffffffc0; + assign o_m_read_addr = miss_addr & 32'hffffffc0; + assign o_m_valid = (state == SEND_MEM_REQ); + assign o_m_read_or_write = (state == SEND_MEM_REQ) && (|eviction_wb_old); + //end + +endmodule + + + + +