From 0028411f84810037bca15bad1784462110bab6d8 Mon Sep 17 00:00:00 2001 From: Naga Sitaram M Date: Wed, 11 Oct 2023 14:05:12 +0530 Subject: [PATCH] Cache --- RISC_V/Cache/TLB_tb.v | 34 ++ RISC_V/Cache/cache_coherence.v | 164 ++++++++ RISC_V/Cache/cache_coherence_tb.v | 102 +++++ RISC_V/Cache/cache_controller.v | 52 +++ RISC_V/Cache/cache_controller_tb.v | 47 +++ RISC_V/Cache/data_cache.v | 583 +++++++++++++++++++++++++++++ RISC_V/Cache/data_cache_tb.v | 236 ++++++++++++ RISC_V/Cache/inst_cache.v | 576 ++++++++++++++++++++++++++++ RISC_V/Cache/inst_cache_tb.v | 111 ++++++ RISC_V/Cache/main_memory.v | 83 ++++ RISC_V/Cache/page_table.v | 50 +++ RISC_V/Cache/page_table_tb.v | 102 +++++ RISC_V/Cache/tlb.v | 325 ++++++++++++++++ 13 files changed, 2465 insertions(+) create mode 100644 RISC_V/Cache/TLB_tb.v create mode 100644 RISC_V/Cache/cache_coherence.v create mode 100644 RISC_V/Cache/cache_coherence_tb.v create mode 100644 RISC_V/Cache/cache_controller.v create mode 100644 RISC_V/Cache/cache_controller_tb.v create mode 100644 RISC_V/Cache/data_cache.v create mode 100644 RISC_V/Cache/data_cache_tb.v create mode 100644 RISC_V/Cache/inst_cache.v create mode 100644 RISC_V/Cache/inst_cache_tb.v create mode 100644 RISC_V/Cache/main_memory.v create mode 100644 RISC_V/Cache/page_table.v create mode 100644 RISC_V/Cache/page_table_tb.v create mode 100644 RISC_V/Cache/tlb.v diff --git a/RISC_V/Cache/TLB_tb.v b/RISC_V/Cache/TLB_tb.v new file mode 100644 index 0000000..096d5a7 --- /dev/null +++ b/RISC_V/Cache/TLB_tb.v @@ -0,0 +1,34 @@ +module TLB_tb(); +reg clock; +reg tlb_en; +reg clear_refer; +//reg [21:0] VPN; +reg [33:0] VA; +//wire [19:0] PPN_o; +wire [31:0] PA; +wire tlb_hit; + +tlb uut(.clock(clock),.tlb_en(tlb_en),.clear_refer(clear_refer),.VA(VA),.PA(PA),.tlb_hit(tlb_hit)); + + +initial begin +clock=1'b0; +tlb_en=1'b1; +clear_refer=1'b1; +//#3 +//clear_refer=1'b0; +VA=34'b1000000000000000000110011010100101; +#50 +VA=34'b0101111000001010010101000111110001; +#50 +VA=34'b1100000000000111100000000000011110; +#50 +VA=34'b0101001010001110100101001110100101; +#50 clear_refer =1'b0; +VA=34'b1010000001111000000000010111111001; + +end + + + always #10 clock = ~clock; +endmodule diff --git a/RISC_V/Cache/cache_coherence.v b/RISC_V/Cache/cache_coherence.v new file mode 100644 index 0000000..c668a02 --- /dev/null +++ b/RISC_V/Cache/cache_coherence.v @@ -0,0 +1,164 @@ +module cache_coherence ( input RMS, // read miss, shared +input RME, // read miss, exclusive +input WM, // write miss +input WH, // write hit +input SHR, // snoop hit on read +input SHW, // snoop hit on write +input READ_DONE, +input clk, +input reset, +input send_abort, +input write_back_done, +input AllInvDone, +input [2:0] state, +output reg [2:0] new_state, +output reg Cache_Sector_Fill, Invalidate, AdrRetry +); +parameter +INVALID = 3'b000, +SHARED_1 = 3'b001, +EXCLUSIVE = 3'b010, +MODIFIED = 3'b011, +Cache_Fill = 3'b100, +start_write_back = 3'b101, +WaitUntilAllInv = 3'b110; +// Declare current_state and next_state variable. +reg [2:0] present_state; +reg [2:0] next_state; +always @(present_state or RMS or RME or WM or WH or SHW or READ_DONE + or SHR or write_back_done or AllInvDone or send_abort or state or reset) + begin +Cache_Sector_Fill = 0; // Default values +Invalidate = 0; +AdrRetry = 0; +next_state = present_state; +if (reset) + next_state = state; +else begin +case(present_state) + +INVALID: +// ReadMiss (shared/exclusive), Write Miss +if (RMS || RME || WM) +begin +Cache_Sector_Fill = 1; +next_state = Cache_Fill ; +end +else +begin +next_state = INVALID; +end + +Cache_Fill: +if (send_abort) +begin +next_state = INVALID; +end +else if (READ_DONE) +begin +if (RMS) +begin +next_state = SHARED_1; +end +else if (RME) +begin +next_state = EXCLUSIVE; +end +else if (WM) +begin +Invalidate = 1; +next_state = WaitUntilAllInv; +end +else +begin +next_state = Cache_Fill ; +end +end +else +begin +next_state = Cache_Fill ; +end + +SHARED_1: +if (SHW) // Snoop Hit on a Write. +begin +next_state = INVALID; +end +else if (WH) // Write Hit +begin +Invalidate = 1; +next_state = WaitUntilAllInv; +end +else +begin // Snoop Hit on a Read or Read Hit or any other +next_state = SHARED_1; +end + +WaitUntilAllInv: +if (AllInvDone) +begin +next_state = MODIFIED; +end +else +begin +next_state = WaitUntilAllInv; +end + +EXCLUSIVE: +if (SHR) // Snoop Hit on a Read: +begin +AdrRetry = 0; +next_state = SHARED_1; +end +else if (SHW) // Snoop Hit on a Write +begin +next_state = INVALID; +end +else if (WH) // Write Hit +begin +next_state = MODIFIED; +end +else +begin // Read Hit +next_state = EXCLUSIVE; +end + +MODIFIED: +if (SHW) // Snoop Hit on a Write +begin +next_state = INVALID; +end +else if (SHR) // Snoop Hit on a Read +begin +AdrRetry = 1; +next_state = start_write_back; +end +else // Read Hit or Write Hit or anything else. +begin +next_state = MODIFIED; +end +start_write_back: +if (write_back_done) +begin +next_state = SHARED_1; +end +else +begin +next_state = start_write_back; +end +endcase +end +end + +/* Sequential */ + +always @(posedge clk) +begin +present_state = next_state; +new_state = next_state; +end +endmodule + + + + diff --git a/RISC_V/Cache/cache_coherence_tb.v b/RISC_V/Cache/cache_coherence_tb.v new file mode 100644 index 0000000..902e30a --- /dev/null +++ b/RISC_V/Cache/cache_coherence_tb.v @@ -0,0 +1,102 @@ +module cache_coherence_tb; +reg RMS, RME, WM, WH, RH, SHR, SHW, clk, READ_DONE , reset,send_abort, write_back_done, AllInvDone, PA, PB, countE; +reg [2:0] state, SectorInCacheA, SectorInCacheB; +reg [3:0] count; + +wire [2:0] new_state; +wire Cache_Sector_Fill, Invalidate, AdrRetry; +cache_coherence uut (.new_state(new_state), .Cache_Sector_Fill(Cache_Sector_Fill), .Invalidate(Invalidate), .AdrRetry(AdrRetry), .RMS(RMS), .RME(RME), .WM(WM), .WH(WH), .SHR(SHR), .SHW(SHW), .state(state), .READ_DONE(READ_DONE), .clk(clk), .reset(reset), .send_abort(send_abort), .write_back_done(write_back_done), .AllInvDone(AllInvDone)); +initial +begin +/* The states of sector in both caches are initialized to Invalid (0). */ +SectorInCacheA = 0; SectorInCacheB = 0; +/* Signals set/rest by cache controller */ +// Write Hit +WH = 0; +// ReadMiss (Shared) +RMS = 0; +// WriteMiss +WM = 0; +// Snoop hit on read operation +SHR = 0; +// Snoop hit on write operation +SHW = 0; + +READ_DONE = 0; + +AllInvDone = 0; + +write_back_done = 0; + +send_abort = 0; +state = SectorInCacheA ; PA = 1; PB = 0; RME = 1; +reset = 1; #6 reset = 0; + +#40 PA = 0; PB = 1; RME = 0; RMS = 1; state = SectorInCacheB; +reset = 1;#10 reset = 0; +#50 PB = 0; PA = 1; SHR = 1; state = SectorInCacheA; +reset = 1; #10 reset = 0; +#20 SHR = 0; WH = 1; state = SectorInCacheA; +reset = 1; #10 reset = 0; +#50 PA = 0; PB = 1; RMS = 1; WH = 0; state = SectorInCacheB; +reset = 1; #10 reset = 0; +#30 SHR = 1; RMS = 0; PA = 1; PB = 0; state = SectorInCacheA; +reset = 1; #10 reset = 0; +#20 PB = 1; PA = 0; SHR = 0; state = SectorInCacheB; +reset = 1; #10 reset = 0; +// PA states writing back. +#20 PB = 0; PA = 1; state = SectorInCacheA; +reset = 1; #10 reset = 0; +#30 write_back_done = 1; +#10 write_back_done = 0; +// PB retry. +#10 PA = 0; PB = 1; RMS = 1; state = SectorInCacheB; +reset = 1; #10 reset = 0; +// #100 $stop; +// #100 $finish; +end +always @(new_state) +begin +if (PA == 1) SectorInCacheA = new_state ; +else if (PB == 1) SectorInCacheB = new_state ; +end +always @(posedge clk) +begin +if (Invalidate) +begin +#10 SectorInCacheB = 0; +#10 AllInvDone = 1; +#15 AllInvDone = 0; +end +else if (Cache_Sector_Fill) +begin +count = 0; +countE = 1; + // Intialize the Read_Done variable to 0; +READ_DONE = 0; +end +else if (AdrRetry) +begin +countE = 0; +send_abort = 1; +#40 send_abort = 0; +end +end +always @(posedge clk) +begin +if (READ_DONE == 1) READ_DONE = 0; +if (countE == 1) +begin +if ( count == 2 ) +begin +READ_DONE = 1; +countE = 0; +end +else count = count + 1; +end +end +initial clk = 0; +always #5 clk = ~clk ; + +endmodule + diff --git a/RISC_V/Cache/cache_controller.v b/RISC_V/Cache/cache_controller.v new file mode 100644 index 0000000..ace540e --- /dev/null +++ b/RISC_V/Cache/cache_controller.v @@ -0,0 +1,52 @@ +module cache_controller( + input clk, + input [6:0] tag, //tag field + input [5:0] index,//cache line + input wr_en, //write/read signal (1,0) + input flush, //reset cache - set all valid bits to zero + input ready, //data block ready sig from memory + output stall, //stall the processor (1,0) + output wr_en_mem,//write/read signal to memory (1,0) + output update_cache,//update data array + output reg cache_hit //indicate cache hit/loss (1,0) + ); + +integer i; //used to flush and initialize tag and validity fields + +reg [6:0] tag_field [63:0]; +reg validity_field [63:0]; + + +initial begin + for (i=0;i<64;i=i+1) begin + validity_field[i]=1'b0; + tag_field[i]=1'b0; + end +end + +assign update_cache=ready; +assign stall=~(cache_hit|wr_en); +assign wr_en_mem=wr_en; + +always @(posedge clk) begin + + if (validity_field[index]) cache_hit=(tag_field[index]==tag); + else cache_hit=0; + + if (~wr_en) begin + if (ready) begin + validity_field[index]=1; + tag_field[index]=tag; + end + end + + if (flush) begin + for (i=0;i<64;i=i+1) begin + validity_field[i]=1'b0; + end + end + +end + +endmodule + diff --git a/RISC_V/Cache/cache_controller_tb.v b/RISC_V/Cache/cache_controller_tb.v new file mode 100644 index 0000000..06d68be --- /dev/null +++ b/RISC_V/Cache/cache_controller_tb.v @@ -0,0 +1,47 @@ +module cache_controller_tb; +reg clk; +reg [6:0] tag; //tag field +reg [5:0] index; //cache line +reg wr_en; //write/read signal (1,0) +reg flush; //reset cache - set all valid bits to zero +reg ready; //data block ready sig from memory +wire stall; //stall the processor (1,0) +wire wr_en_mem; //write/read signal to memory (1,0) +wire update_cache; //update data array +wire cache_hit; + +cache_controller uut(.clk(clk),.tag(tag),.index(index),.wr_en(wr_en),.flush(flush),.ready(ready),.stall(stall),.wr_en_mem(wr_en_mem),.update_cache(update_cache),.cache_hit(cache_hit)); +initial begin +clk=1'b0; +wr_en=1'b1; +ready=1'b1; +tag=7'h00; +index=6'h01; +#10 +tag=7'h24; +index=6'h02; +#10 +tag=7'h26; +index=6'h45; +#10 +tag=7'h56; +index=6'h08; +#10 +wr_en=1'b0; +tag=7'h00; +index=6'h01; +#10 +tag=7'h24; +index=6'h02; +#10 +tag=7'h26; +index=6'h45; +#10 +tag=7'h56; +index=6'h08; +#10 flush=1'b1; +end +always #5 clk=~clk; +endmodule + + diff --git a/RISC_V/Cache/data_cache.v b/RISC_V/Cache/data_cache.v new file mode 100644 index 0000000..6cd511c --- /dev/null +++ b/RISC_V/Cache/data_cache.v @@ -0,0 +1,583 @@ +`define TAG 31:13 // position of tag in address +`define INDEX 12:3 // position of index in address +`define OFFSET 2:0 // position of offset in address + +module data_cache +#( + // Cache parameters + parameter SIZE = 32*1024*8, + parameter NWAYS = 8, + parameter NSETS =1024 , + parameter BLOCK_SIZE = 64, + parameter WIDTH = 32, + // Memory related paramter, make sure it matches memory module + parameter MWIDTH = 64, // same as block size + // More cache related parameters + parameter INDEX_WIDTH = 10, + parameter TAG_WIDTH = 19, + parameter OFFSET_WIDTH = 3, + parameter WORD1 = 3, + parameter WORD2 = 7 +) +( + input wire clock, + input wire [WIDTH-1:0] address, // address form CPU + input wire [WIDTH-1:0] din, // data from CPU (if st inst) + input wire rden, // 1 if ld instruction + input wire wren, // 1 if st instruction + output wire hit_miss, // 1 if hit, 0 while handling miss + output wire [WIDTH-1:0] q, // data from cache to CPU + output wire [MWIDTH-1:0] mdout, // data from cache to memory + output wire [WIDTH-1:0] mrdaddress, // memory read address + output wire mrden, // read enable, 1 if reading from memory + output wire [WIDTH-1:0] mwraddress, // memory write address + output wire mwren, // write enable, 1 if writing to memory + input wire [MWIDTH-1:0] mq // data coming from memory +); + +/******************************************************************* +* Global Parameters and Initializations +*******************************************************************/ + +// WAY 1 cache data +reg valid1 [0:NSETS-1]; +reg dirty1 [0:NSETS-1]; +reg [1:0] lru1 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag1 [0:NSETS-1]; +reg [MWIDTH-1:0] mem1 [0:NSETS-1]; + +// WAY 2 cache data +reg valid2 [0:NSETS-1]; +reg dirty2 [0:NSETS-1]; +reg [1:0] lru2 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag2 [0:NSETS-1]; +reg [MWIDTH-1:0] mem2 [0:NSETS-1]; + +// WAY 3 cache data +reg valid3 [0:NSETS-1]; +reg dirty3 [0:NSETS-1]; +reg [1:0] lru3 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag3 [0:NSETS-1]; +reg [MWIDTH-1:0] mem3 [0:NSETS-1]; + +// WAY 4 cache data +reg valid4 [0:NSETS-1]; +reg dirty4 [0:NSETS-1]; +reg [1:0] lru4 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag4 [0:NSETS-1]; +reg [MWIDTH-1:0] mem4 [0:NSETS-1]; +// WAY 5 cache data +reg valid5 [0:NSETS-1]; +reg dirty5 [0:NSETS-1]; +reg [1:0] lru5 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag5 [0:NSETS-1]; +reg [MWIDTH-1:0] mem5 [0:NSETS-1]; + +// WAY 6 cache data +reg valid6 [0:NSETS-1]; +reg dirty6 [0:NSETS-1]; +reg [1:0] lru6 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag6 [0:NSETS-1]; +reg [MWIDTH-1:0] mem6 [0:NSETS-1]; +// WAY 7 cache data +reg valid7 [0:NSETS-1]; +reg dirty7 [0:NSETS-1]; +reg [1:0] lru7 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag7 [0:NSETS-1]; +reg [MWIDTH-1:0] mem7 [0:NSETS-1]; /*synthesis ramstyle = "M20K" */ + +// WAY 8 cache data +reg valid8 [0:NSETS-1]; +reg dirty8 [0:NSETS-1]; +reg [1:0] lru8 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag8 [0:NSETS-1]; +reg [MWIDTH-1:0] mem8 [0:NSETS-1]; + +// initialize the cache to zero +integer k; +initial +begin + for(k = 0; k < NSETS; k = k +1) + begin + valid1[k] = 0; + valid2[k] = 0; + valid3[k] = 0; + valid4[k] = 0; + valid5[k] = 0; + valid6[k] = 0; + valid7[k] = 0; + valid8[k] = 0; + dirty1[k] = 0; + dirty2[k] = 0; + dirty3[k] = 0; + dirty4[k] = 0; + dirty5[k] = 0; + dirty6[k] = 0; + dirty7[k] = 0; + dirty8[k] = 0; + lru1[k] = 2'b00; + lru2[k] = 2'b00; + lru3[k] = 2'b00; + lru4[k] = 2'b00; + lru5[k] = 2'b00; + lru6[k] = 2'b00; + lru7[k] = 2'b00; + lru8[k] = 2'b00; + end +end + +// internal registers +reg _hit_miss = 1'b0; +reg [WIDTH-1:0] _q = {WIDTH{1'b0}}; +reg [MWIDTH-1:0] _mdout = {MWIDTH{1'b0}}; +reg [WIDTH-1:0] _mwraddress = {WIDTH{1'b0}}; +reg _mwren = 1'b0; + +// output assignments of internal registers +assign hit_miss = _hit_miss; +assign mrden = !((valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) + || (valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) + || (valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) + || (valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) + || (valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) + || (valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) + || (valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) + || (valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG]))); +assign mwren = _mwren; +assign mdout = _mdout; +assign mrdaddress = {address[`TAG],address[`INDEX]}; +assign mwraddress = _mwraddress; +assign q = _q; + +// state parameters +localparam idle = 1'b0; // receive requests from CPU +localparam miss = 1'b1; // write back dirty block and put in new data + +// state register +reg currentState = idle; + +/******************************************************************* +* State Machine +*******************************************************************/ + +always @(posedge clock) +begin + case (currentState) + idle: begin + // reset write enable, if it was turned on + _mwren <= 0; + // set _hit_miss register + _hit_miss <= ((valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) + || (valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) + || (valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) + || (valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) + || (valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) + || (valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) + || (valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) + || (valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG]))); + + // do nothing on a null request + if(~rden && ~wren) currentState <= idle; + + // check way 1 + else if(valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem1[address[`INDEX]][WIDTH-1:0] : mem1[address[`INDEX]][2*WIDTH-1:WIDTH]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + dirty1[address[`INDEX]] <= 1; + if(address[`OFFSET] <= WORD1) mem1[address[`INDEX]][WIDTH-1:0] <= din; + else mem1[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; + end + // update LRU data + if(lru2[address[`INDEX]] <= lru1[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru1[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru1[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru1[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru1[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru1[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru1[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru1[address[`INDEX]] <= 0; + end + + // check way 2 + else if(valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem2[address[`INDEX]][WIDTH-1:0] : mem2[address[`INDEX]][2*WIDTH-1:WIDTH]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + dirty2[address[`INDEX]] <= 1; + if(address[`OFFSET] <= WORD1) mem2[address[`INDEX]][WIDTH-1:0] <= din; + else mem2[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru2[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru2[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru2[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru2[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru2[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru2[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru2[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru2[address[`INDEX]] <= 0; + end + + // check way 3 + else if(valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem3[address[`INDEX]][WIDTH-1:0] : mem3[address[`INDEX]][2*WIDTH-1:WIDTH]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + dirty3[address[`INDEX]] <= 1; + if(address[`OFFSET] <= WORD1) mem3[address[`INDEX]][WIDTH-1:0] <= din; + else mem3[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru3[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru3[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru3[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru3[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru3[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru3[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru3[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru3[address[`INDEX]] <= 0; + end + + // check way 4 + else if(valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem4[address[`INDEX]][WIDTH-1:0] : mem4[address[`INDEX]][2*WIDTH-1:WIDTH]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + dirty4[address[`INDEX]] <= 1; + if(address[`OFFSET] <= WORD1) mem4[address[`INDEX]][WIDTH-1:0] <= din; + else mem4[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru4[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru4[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru4[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru4[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru4[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru4[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru4[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru4[address[`INDEX]] <= 0; + end + + // check way 5 + else if(valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem5[address[`INDEX]][WIDTH-1:0] : mem5[address[`INDEX]][2*WIDTH-1:WIDTH]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + dirty5[address[`INDEX]] <= 1; + if(address[`OFFSET] <= WORD1) mem5[address[`INDEX]][WIDTH-1:0] <= din; + else mem5[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru5[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru5[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru5[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru5[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru5[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru5[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru5[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru5[address[`INDEX]] <= 0; + end + + // check way 6 + else if(valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem6[address[`INDEX]][WIDTH-1:0] : mem6[address[`INDEX]][2*WIDTH-1:WIDTH]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + dirty6[address[`INDEX]] <= 1; + if(address[`OFFSET] <= WORD1) mem6[address[`INDEX]][WIDTH-1:0] <= din; + else mem6[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru6[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru6[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru6[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru6[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru6[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru6[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru6[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru6[address[`INDEX]] <= 0; + end + + // check way 7 + else if(valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem7[address[`INDEX]][WIDTH-1:0] : mem7[address[`INDEX]][2*WIDTH-1:WIDTH]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + dirty7[address[`INDEX]] <= 1; + if(address[`OFFSET] <= WORD1) mem7[address[`INDEX]][WIDTH-1:0] <= din; + else mem7[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru7[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru7[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru7[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru7[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru7[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru7[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru7[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru7[address[`INDEX]] <= 0; + end + + // check way 8 + else if(valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem8[address[`INDEX]][WIDTH-1:0] : mem8[address[`INDEX]][2*WIDTH-1:WIDTH]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + dirty8[address[`INDEX]] <= 1; + if(address[`OFFSET] <= WORD1) mem8[address[`INDEX]][WIDTH-1:0] <= din; + else mem8[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru8[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru8[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru8[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru8[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru8[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru8[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru8[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + lru8[address[`INDEX]] <= 0; + end + + // miss + else currentState <= miss; + end + + miss: begin + // one of the ways is invalid -- no need to evict + if(~valid1[address[`INDEX]]) + begin + mem1[address[`INDEX]] <= mq; + tag1[address[`INDEX]] <= address[`TAG]; + dirty1[address[`INDEX]] <= 0; + valid1[address[`INDEX]] <= 1; + end + + else if(~valid2[address[`INDEX]]) + begin + mem2[address[`INDEX]] <= mq; + tag2[address[`INDEX]] <= address[`TAG]; + dirty2[address[`INDEX]] <= 0; + valid2[address[`INDEX]] <= 1; + end + + else if(~valid3[address[`INDEX]]) + begin + mem3[address[`INDEX]] <= mq; + tag3[address[`INDEX]] <= address[`TAG]; + dirty3[address[`INDEX]] <= 0; + valid3[address[`INDEX]] <= 1; + end + + else if(~valid4[address[`INDEX]]) + begin + mem4[address[`INDEX]] <= mq; + tag4[address[`INDEX]] <= address[`TAG]; + dirty4[address[`INDEX]] <= 0; + valid4[address[`INDEX]] <= 1; + end + + else if(~valid5[address[`INDEX]]) + begin + mem5[address[`INDEX]] <= mq; + tag5[address[`INDEX]] <= address[`TAG]; + dirty5[address[`INDEX]] <= 0; + valid5[address[`INDEX]] <= 1; + end + + else if(~valid6[address[`INDEX]]) + begin + mem6[address[`INDEX]] <= mq; + tag6[address[`INDEX]] <= address[`TAG]; + dirty6[address[`INDEX]] <= 0; + valid6[address[`INDEX]] <= 1; + end + + else if(~valid7[address[`INDEX]]) + begin + mem7[address[`INDEX]] <= mq; + tag7[address[`INDEX]] <= address[`TAG]; + dirty7[address[`INDEX]] <= 0; + valid7[address[`INDEX]] <= 1; + end + + else if(~valid8[address[`INDEX]]) + begin + mem8[address[`INDEX]] <= mq; + tag8[address[`INDEX]] <= address[`TAG]; + dirty8[address[`INDEX]] <= 0; + valid8[address[`INDEX]] <= 1; + end + + // way 1 is LRU + else if(lru1[address[`INDEX]] == 3) + begin + // dirty block writeback + if(dirty1[address[`INDEX]] == 1) + begin + _mwraddress <= {tag1[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem1[address[`INDEX]]; + end + mem1[address[`INDEX]] <= mq; + tag1[address[`INDEX]] <= address[`TAG]; + dirty1[address[`INDEX]] <= 0; + valid1[address[`INDEX]] <= 1; + end + + // way 2 is LRU + else if(lru2[address[`INDEX]] == 3) + begin + // dirty block writeback + if(dirty2[address[`INDEX]] == 1) + begin + _mwraddress <= {tag2[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem2[address[`INDEX]]; + end + mem2[address[`INDEX]] <= mq; + tag2[address[`INDEX]] <= address[`TAG]; + dirty2[address[`INDEX]] <= 0; + valid2[address[`INDEX]] <= 1; + end + + // way 3 is LRU + else if(lru3[address[`INDEX]] == 3) + begin + // dirty block writeback + if(dirty3[address[`INDEX]] == 1) + begin + _mwraddress <= {tag3[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem3[address[`INDEX]]; + end + mem3[address[`INDEX]] <= mq; + tag3[address[`INDEX]] <= address[`TAG]; + dirty3[address[`INDEX]] <= 0; + valid3[address[`INDEX]] <= 1; + end + + // way 4 is LRU + else if(lru4[address[`INDEX]] == 3) + begin + // dirty block writeback + if(dirty4[address[`INDEX]] == 1) + begin + _mwraddress <= {tag4[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem4[address[`INDEX]]; + end + mem4[address[`INDEX]] <= mq; + tag4[address[`INDEX]] <= address[`TAG]; + dirty4[address[`INDEX]] <= 0; + valid4[address[`INDEX]] <= 1; + end + + // way 5 is LRU + else if(lru5[address[`INDEX]] == 3) + begin + // dirty block writeback + if(dirty5[address[`INDEX]] == 1) + begin + _mwraddress <= {tag5[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem5[address[`INDEX]]; + end + mem5[address[`INDEX]] <= mq; + tag5[address[`INDEX]] <= address[`TAG]; + dirty5[address[`INDEX]] <= 0; + valid5[address[`INDEX]] <= 1; + end + + // way 6 is LRU + else if(lru6[address[`INDEX]] == 3) + begin + // dirty block writeback + if(dirty6[address[`INDEX]] == 1) + begin + _mwraddress <= {tag6[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem6[address[`INDEX]]; + end + mem6[address[`INDEX]] <= mq; + tag6[address[`INDEX]] <= address[`TAG]; + dirty6[address[`INDEX]] <= 0; + valid6[address[`INDEX]] <= 1; + end + + // way 7 is LRU + else if(lru7[address[`INDEX]] == 3) + begin + // dirty block writeback + if(dirty7[address[`INDEX]] == 1) + begin + _mwraddress <= {tag7[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem4[address[`INDEX]]; + end + mem7[address[`INDEX]] <= mq; + tag7[address[`INDEX]] <= address[`TAG]; + dirty7[address[`INDEX]] <= 0; + valid7[address[`INDEX]] <= 1; + end + + // way 8 is LRU + else if(lru8[address[`INDEX]] == 3) + begin + // dirty block writeback + if(dirty8[address[`INDEX]] == 1) + begin + _mwraddress <= {tag8[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem8[address[`INDEX]]; + end + mem8[address[`INDEX]] <= mq; + tag8[address[`INDEX]] <= address[`TAG]; + dirty8[address[`INDEX]] <= 0; + valid8[address[`INDEX]] <= 1; + end + + currentState <= idle; + end + + default: currentState <= idle; + + endcase + +end + +endmodule + + diff --git a/RISC_V/Cache/data_cache_tb.v b/RISC_V/Cache/data_cache_tb.v new file mode 100644 index 0000000..c5ad9de --- /dev/null +++ b/RISC_V/Cache/data_cache_tb.v @@ -0,0 +1,236 @@ +module data_cache_tb; + reg clk; + + wire [31:0] data_in; + wire [63:0] data_out; + wire [31:0] rd_addr; + wire rd_en; + wire [31:0] wr_addr; + wire wr_en; + + reg [31:0] d_cache_addr = 0; + reg [63:0] d_cache_din = 0; + reg d_cache_rden = 0; + reg d_cache_wren = 0; + wire d_cache_hit_miss; + wire [31:0] d_cache_q; + + data_cache DUT_CACHE ( + .clock(clk), + .address(d_cache_addr), + .din(d_cache_din), + .rden(d_cache_rden), + .wren(d_cache_wren), + .hit_miss(d_cache_hit_miss), + .q(d_cache_q), + .mdout(data_in), + .mrdaddress(rd_addr), + .mrden(rd_en), + .mwraddress(wr_addr), + .mwren(wr_en), + .mq(data_out) + ); + + defparam DUT_CACHE.SIZE = 32*1024*8; + defparam DUT_CACHE.NWAYS = 8; + defparam DUT_CACHE.NSETS = 1024; + defparam DUT_CACHE.BLOCK_SIZE = 64; + defparam DUT_CACHE.WIDTH = 32; + defparam DUT_CACHE.MWIDTH = 64; + + main_memory DUT_MEM ( + .clock(clk), + .data(data_in), + .rdaddress(rd_addr), + .rden(rd_en), + .wraddress(wr_addr), + .wren(wr_en), + .q(data_out) + ); + + defparam DUT_MEM.WIDTH = 32; + defparam DUT_MEM.DEPTH = 128; + defparam DUT_MEM.FILE = "main_mem_text.txt"; + + + always + begin + + // basic writeback ///////////////////////////////////////////////////////////////////////////////////////////////////////// + + # 100; // This should be a miss + + d_cache_addr <= 32'h00000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a hit + + d_cache_addr <= 32'h00000008; + d_cache_din <= 32'hBADDBEEF; + d_cache_rden <= 0; + d_cache_wren <= 1; + + # 100; // This should be a miss + + d_cache_addr <= 32'h10000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss + + d_cache_addr <= 32'h20000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss + + d_cache_addr <= 32'h30000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss and eviction + + d_cache_addr <= 32'h40000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss (evicted) + + d_cache_addr <= 32'h00000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a hit + + d_cache_addr <= 32'h30000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + // repeated writes (w/ offset) ///////////////////////////////////////////////////////////////////////////////////////////////////////// + + # 100; // This should be a miss + + d_cache_addr <= 32'h00000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a hit + + d_cache_addr <= 32'h00000008; + d_cache_din <= 32'hBADDBEEF; + d_cache_rden <= 0; + d_cache_wren <= 1; + + # 100; // This should be a hit + + d_cache_addr <= 32'h0000000B; + d_cache_din <= 32'h00000000; + d_cache_rden <= 0; + d_cache_wren <= 1; + + # 100; // This should be a hit + + d_cache_addr <= 32'h0000000C; + d_cache_din <= 32'hAAAAAAAA; + d_cache_rden <= 0; + d_cache_wren <= 1; + + # 100; // This should be a miss + + d_cache_addr <= 32'h10000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss + + d_cache_addr <= 32'h20000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss + + d_cache_addr <= 32'h30000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss and eviction + + d_cache_addr <= 32'h40000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss (evicted) + + d_cache_addr <= 32'h00000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a miss + + d_cache_addr <= 32'h10000008; + d_cache_din <= 32'hBADDBEEF; + d_cache_rden <= 0; + d_cache_wren <= 1; + + // repeated reads (w/ offset) ///////////////////////////////////////////////////////////////////////////////////////////////////////// + + # 100; // This should be a miss + + d_cache_addr <= 32'h00000008; + d_cache_din <= 0; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a hit + + d_cache_addr <= 32'h0000000B; + d_cache_din <= 32'hBADDBEEF; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a hit + + d_cache_addr <= 32'h0000000C; + d_cache_din <= 32'h00000000; + d_cache_rden <= 1; + d_cache_wren <= 0; + + # 100; // This should be a hit + + d_cache_addr <= 32'h0000000F; + d_cache_din <= 32'hAAAAAAAA; + d_cache_rden <= 1; + d_cache_wren <= 0; + + #50; + $finish; + end + + initial + begin +$monitor("time=%4d | addr=%10d | hm=%b | q=%08x | way1=%08h | way2=%08h | way3=%08h | way4=%08h | way5=%08h | way6=%08h | way7=%08h | way8=%08h | mem[1]=%08h | lru1=%d | lru2=%d | lru3=%d | lru4=%d | lru5=%d | lru6=%d | lru7=%d | lru8=%d " ,$time,d_cache_addr,d_cache_hit_miss,DUT_CACHE.q,DUT_CACHE.mem1[1],DUT_CACHE.mem2[1],DUT_CACHE.mem3[1],DUT_CACHE.mem4[1],DUT_CACHE.mem5[1],DUT_CACHE.mem6[1],DUT_CACHE.mem7[1],DUT_CACHE.mem8[1],DUT_MEM.mem[1],DUT_CACHE.lru1[1],DUT_CACHE.lru2[1],DUT_CACHE.lru3[1],DUT_CACHE.lru4[1],DUT_CACHE.lru5[1],DUT_CACHE.lru6[1],DUT_CACHE.lru7[1],DUT_CACHE.lru8[1]); + end + + always + begin + clk = 1'b1; + #5; + clk = 1'b0; + #5; + end + +endmodule diff --git a/RISC_V/Cache/inst_cache.v b/RISC_V/Cache/inst_cache.v new file mode 100644 index 0000000..efe5d77 --- /dev/null +++ b/RISC_V/Cache/inst_cache.v @@ -0,0 +1,576 @@ +`define TAG 31:13 // position of tag in address +`define INDEX 12:2 // position of index in address +`define OFFSET 1:0 // position of offset in address + +module inst_cache +#( + // Cache parameters + parameter SIZE = 16*1024*8, + parameter NWAYS = 8, + parameter NSETS = 2048, + parameter BLOCK_SIZE = 32, + parameter WIDTH = 32, + // Memory related paramter, make sure it matches memory module + parameter MWIDTH = 32, // same as block size + // More cache related parameters + parameter INDEX_WIDTH = 11, + parameter TAG_WIDTH = 19, + parameter OFFSET_WIDTH = 2 +) +( + input wire clock, + input wire [WIDTH-1:0] address, // address form CPU + input wire [WIDTH-1:0] din, // data from CPU (if st inst) + input wire rden, // 1 if ld instruction + input wire wren, // 1 if st instruction + output wire hit_miss, // 1 if hit, 0 while handling miss + output wire [WIDTH-1:0] q, // data from cache to CPU + output wire [MWIDTH-1:0] mdout, // data from cache to memory + output wire [WIDTH-1:0] mrdaddress, // memory read address + output wire mrden, // read enable, 1 if reading from memory + output wire [WIDTH-1:0] mwraddress, // memory write address + output wire mwren, // write enable, 1 if writing to memory + input wire [MWIDTH-1:0] mq // data coming from memory +); + +/*********************** +* Global Parameters and Initializations +***********************/ + +// WAY 1 cache data +reg valid1 [0:NSETS-1]; +reg dirty1 [0:NSETS-1]; +reg lru1 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag1 [0:NSETS-1]; +reg [MWIDTH-1:0] mem1 [0:NSETS-1] ; +// WAY 2 cache data +reg valid2 [0:NSETS-1]; +reg dirty2 [0:NSETS-1]; +reg lru2 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag2 [0:NSETS-1]; +reg [MWIDTH-1:0] mem2 [0:NSETS-1] ; + +// WAY 3 cache data +reg valid3 [0:NSETS-1]; +reg dirty3 [0:NSETS-1]; +reg lru3 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag3 [0:NSETS-1]; +reg [MWIDTH-1:0] mem3 [0:NSETS-1] ; + +// WAY 4 cache data +reg valid4 [0:NSETS-1]; +reg dirty4 [0:NSETS-1]; +reg lru4 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag4 [0:NSETS-1]; +reg [MWIDTH-1:0] mem4 [0:NSETS-1]; + +// WAY 5 cache data +reg valid5 [0:NSETS-1]; +reg dirty5 [0:NSETS-1]; +reg lru5 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag5 [0:NSETS-1]; +reg [MWIDTH-1:0] mem5 [0:NSETS-1] ; + +// WAY 6 cache data +reg valid6 [0:NSETS-1]; +reg dirty6 [0:NSETS-1]; +reg lru6 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag6 [0:NSETS-1]; +reg [MWIDTH-1:0] mem6 [0:NSETS-1]; + +// WAY 7 cache data +reg valid7 [0:NSETS-1]; +reg dirty7 [0:NSETS-1]; +reg lru7 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag7 [0:NSETS-1]; +reg [MWIDTH-1:0] mem7 [0:NSETS-1] ; + +// WAY 8 cache data +reg valid8 [0:NSETS-1]; +reg dirty8 [0:NSETS-1]; +reg lru8 [0:NSETS-1]; +reg [TAG_WIDTH-1:0] tag8 [0:NSETS-1]; +reg [MWIDTH-1:0] mem8 [0:NSETS-1] ; + +// initialize everything to 0 +integer k; +initial +begin + for(k = 0; k < NSETS; k = k +1) + begin + valid1[k] = 0; + valid2[k] = 0; + valid3[k] = 0; + valid4[k] = 0; + valid5[k] = 0; + valid6[k] = 0; + valid7[k] = 0; + valid8[k] = 0; + dirty1[k] = 0; + dirty2[k] = 0; + dirty3[k] = 0; + dirty4[k] = 0; + dirty5[k] = 0; + dirty6[k] = 0; + dirty7[k] = 0; + dirty8[k] = 0; + lru1[k] = 0; + lru2[k] = 0; + lru3[k] = 0; + lru4[k] = 0; + lru5[k] = 0; + lru6[k] = 0; + lru7[k] = 0; + lru8[k] = 0; + end +end + +// internal registers +reg _hit_miss = 1'b0; +reg [WIDTH-1:0] _q = {WIDTH{1'b0}}; +reg [MWIDTH-1:0] _mdout = {MWIDTH{1'b0}}; +reg [WIDTH-1:0] _mwraddress = {WIDTH{1'b0}}; +reg _mwren = 1'b0; + +// output assignments of internal registers +assign hit_miss = _hit_miss; +assign mrden = !((valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) + || (valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) + || (valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) + || (valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) + || (valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) + || (valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) + || (valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) + || (valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG]))); +assign mwren = _mwren; +assign mdout = _mdout; +assign mrdaddress = {address[`TAG],address[`INDEX]}; +assign mwraddress = _mwraddress; +assign q = _q; + +// state parameters +localparam idle = 1'b0; // receive requests from CPU +localparam miss = 1'b1; // miss state: write back dirty block and request memory data + +// state register +reg currentState = idle; + +/*********************** +* State Machine +***********************/ + +always @(posedge clock) +begin + case (currentState) + idle: begin + // reset write enable, if it was turned on + _mwren <= 0; + // set _hit_miss register + _hit_miss <= ((valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) + || (valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) + || (valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) + || (valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) + || (valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) + || (valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) + || (valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) + || (valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG]))); + + // do nothing on null request + if(~rden && ~wren) currentState <= idle; + + // check way 1 + else if(valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= mem1[address[`INDEX]]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + mem1[address[`INDEX]] <= din; + dirty1[address[`INDEX]] <= 1; + end + // update LRU data + lru1[address[`INDEX]] <= 0; + if(lru2[address[`INDEX]] <= lru1[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru1[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru1[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru1[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru1[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru1[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru1[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + end + + // check way 2 + else if(valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= mem2[address[`INDEX]]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + mem2[address[`INDEX]] <= din; + dirty2[address[`INDEX]] <= 1; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru2[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru2[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru2[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru2[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru2[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru2[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru2[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru2[address[`INDEX]] <= 0; + end + + // check way 3 + else if(valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= mem3[address[`INDEX]]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + mem3[address[`INDEX]] <= din; + dirty3[address[`INDEX]] <= 1; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru3[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru3[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru3[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru3[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru3[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru3[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru3[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru3[address[`INDEX]] <= 0; + end + + // check way 4 + else if(valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= mem4[address[`INDEX]]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + mem4[address[`INDEX]] <= din; + dirty4[address[`INDEX]] <= 1; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru4[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru4[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru4[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru4[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru4[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru4[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru4[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru4[address[`INDEX]] <= 0; + end + + // check way 5 + else if(valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= mem5[address[`INDEX]]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + mem5[address[`INDEX]] <= din; + dirty5[address[`INDEX]] <= 1; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru5[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru5[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru5[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru5[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru5[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru5[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru5[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru5[address[`INDEX]] <= 0; + end + + // check way 6 + else if(valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= mem6[address[`INDEX]]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + mem6[address[`INDEX]] <= din; + dirty6[address[`INDEX]] <= 1; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru6[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru6[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru6[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru6[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru6[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru6[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru6[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru6[address[`INDEX]] <= 0; + end + + // check way 7 + else if(valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= mem7[address[`INDEX]]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + mem7[address[`INDEX]] <= din; + dirty7[address[`INDEX]] <= 1; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru7[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru7[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru7[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru7[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru7[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru7[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru8[address[`INDEX]] <= lru7[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; + lru7[address[`INDEX]] <= 0; + end + + // check way 8 + else if(valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG])) + begin + // read hit + if(rden) _q <= mem8[address[`INDEX]]; + // write hit + else if(wren) + begin + _q = {WIDTH{1'b0}}; + mem8[address[`INDEX]] <= din; + dirty8[address[`INDEX]] <= 1; + end + // update LRU data + if(lru1[address[`INDEX]] <= lru8[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; + if(lru2[address[`INDEX]] <= lru8[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; + if(lru3[address[`INDEX]] <= lru8[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; + if(lru4[address[`INDEX]] <= lru8[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; + if(lru5[address[`INDEX]] <= lru8[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; + if(lru6[address[`INDEX]] <= lru8[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; + if(lru7[address[`INDEX]] <= lru8[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; + lru8[address[`INDEX]] <= 0; + end + + // miss + else currentState <= miss; + end + + miss: begin + // one of the ways is invalid -- no need to evict + if(~valid1[address[`INDEX]]) + begin + mem1[address[`INDEX]] <= mq; + tag1[address[`INDEX]] <= address[`TAG]; + dirty1[address[`INDEX]] <= 0; + valid1[address[`INDEX]] <= 1; + end + + else if(~valid2[address[`INDEX]]) + begin + mem2[address[`INDEX]] <= mq; + tag2[address[`INDEX]] <= address[`TAG]; + dirty2[address[`INDEX]] <= 0; + valid2[address[`INDEX]] <= 1; + end + else if(~valid3[address[`INDEX]]) + begin + mem3[address[`INDEX]] <= mq; + tag3[address[`INDEX]] <= address[`TAG]; + dirty3[address[`INDEX]] <= 0; + valid3[address[`INDEX]] <= 1; + end + + else if(~valid4[address[`INDEX]]) + begin + mem4[address[`INDEX]] <= mq; + tag4[address[`INDEX]] <= address[`TAG]; + dirty4[address[`INDEX]] <= 0; + valid4[address[`INDEX]] <= 1; + end + + + else if(~valid5[address[`INDEX]]) + begin + mem5[address[`INDEX]] <= mq; + tag5[address[`INDEX]] <= address[`TAG]; + dirty5[address[`INDEX]] <= 0; + valid5[address[`INDEX]] <= 1; + end + + + else if(~valid6[address[`INDEX]]) + begin + mem6[address[`INDEX]] <= mq; + tag6[address[`INDEX]] <= address[`TAG]; + dirty6[address[`INDEX]] <= 0; + valid6[address[`INDEX]] <= 1; + end + + + else if(~valid7[address[`INDEX]]) + begin + mem7[address[`INDEX]] <= mq; + tag7[address[`INDEX]] <= address[`TAG]; + dirty7[address[`INDEX]] <= 0; + valid7[address[`INDEX]] <= 1; + end + + + else if(~valid8[address[`INDEX]]) + begin + mem8[address[`INDEX]] <= mq; + tag8[address[`INDEX]] <= address[`TAG]; + dirty8[address[`INDEX]] <= 0; + valid8[address[`INDEX]] <= 1; + end + + + // way 1 is LRU + else if(lru1[address[`INDEX]] == 1) + begin + // dirty block writeback + if(dirty1[address[`INDEX]] == 1) + begin + _mwraddress <= {tag1[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem1[address[`INDEX]]; + end + mem1[address[`INDEX]] <= mq; + tag1[address[`INDEX]] <= address[`TAG]; + dirty1[address[`INDEX]] <= 0; + valid1[address[`INDEX]] <= 1; + end + + // way 2 is LRU + else if(lru2[address[`INDEX]] == 1) + begin + // dirty block writeback + if(dirty2[address[`INDEX]] == 1) + begin + _mwraddress <= {tag2[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem2[address[`INDEX]]; + end + mem2[address[`INDEX]] <= mq; + tag2[address[`INDEX]] <= address[`TAG]; + dirty2[address[`INDEX]] <= 0; + valid2[address[`INDEX]] <= 1; + end + + // way 3 is LRU + else if(lru3[address[`INDEX]] == 1) + begin + // dirty block writeback + if(dirty3[address[`INDEX]] == 1) + begin + _mwraddress <= {tag3[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem3[address[`INDEX]]; + end + mem3[address[`INDEX]] <= mq; + tag3[address[`INDEX]] <= address[`TAG]; + dirty3[address[`INDEX]] <= 0; + valid3[address[`INDEX]] <= 1; + end + + // way 4 is LRU + else if(lru4[address[`INDEX]] == 1) + begin + // dirty block writeback + if(dirty4[address[`INDEX]] == 1) + begin + _mwraddress <= {tag4[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem4[address[`INDEX]]; + end + mem4[address[`INDEX]] <= mq; + tag4[address[`INDEX]] <= address[`TAG]; + dirty4[address[`INDEX]] <= 0; + valid4[address[`INDEX]] <= 1; + end + + // way 5 is LRU + else if(lru5[address[`INDEX]] == 1) + begin + // dirty block writeback + if(dirty5[address[`INDEX]] == 1) + begin + _mwraddress <= {tag5[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem5[address[`INDEX]]; + end + mem5[address[`INDEX]] <= mq; + tag5[address[`INDEX]] <= address[`TAG]; + dirty5[address[`INDEX]] <= 0; + valid5[address[`INDEX]] <= 1; + end + + // way 6 is LRU + else if(lru6[address[`INDEX]] == 1) + begin + // dirty block writeback + if(dirty6[address[`INDEX]] == 1) + begin + _mwraddress <= {tag6[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem6[address[`INDEX]]; + end + mem6[address[`INDEX]] <= mq; + tag6[address[`INDEX]] <= address[`TAG]; + dirty6[address[`INDEX]] <= 0; + valid6[address[`INDEX]] <= 1; + end + + // way 7 is LRU + else if(lru7[address[`INDEX]] == 1) + begin + // dirty block writeback + if(dirty7[address[`INDEX]] == 1) + begin + _mwraddress <= {tag7[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem7[address[`INDEX]]; + end + mem7[address[`INDEX]] <= mq; + tag7[address[`INDEX]] <= address[`TAG]; + dirty7[address[`INDEX]] <= 0; + valid7[address[`INDEX]] <= 1; + end + + // way 8 is LRU + else if(lru8[address[`INDEX]] == 1) + begin + // dirty block writeback + if(dirty8[address[`INDEX]] == 1) + begin + _mwraddress <= {tag8[address[`INDEX]],address[`INDEX]}; + _mwren <= 1; + _mdout <= mem8[address[`INDEX]]; + end + mem8[address[`INDEX]] <= mq; + tag8[address[`INDEX]] <= address[`TAG]; + dirty8[address[`INDEX]] <= 0; + valid8[address[`INDEX]] <= 1; + end + + currentState <= idle; + end + + default: currentState <= idle; + + endcase + +end + +endmodule \ No newline at end of file diff --git a/RISC_V/Cache/inst_cache_tb.v b/RISC_V/Cache/inst_cache_tb.v new file mode 100644 index 0000000..0dcbc4e --- /dev/null +++ b/RISC_V/Cache/inst_cache_tb.v @@ -0,0 +1,111 @@ +`timescale 1ns / 1ps + +module inst_cache_tb; + reg clk; + + wire [31:0] data_in; + wire [31:0] data_out; + wire [31:0] rd_addr; + wire rd_en; + wire [31:0] wr_addr; + wire wr_en; + reg [31:0] i_cache_addr = 0; + reg [31:0] i_cache_din = 0; + reg i_cache_rden = 0; + reg i_cache_wren = 0; + wire i_cache_hit_miss; + wire [31:0] i_cache_q; + + inst_cache DUT_CACHE ( + .clock(clk), + .address(i_cache_addr), + .din(i_cache_din), + .rden(i_cache_rden), + .wren(i_cache_wren), + .hit_miss(i_cache_hit_miss), + .q(i_cache_q), + .mdout(data_in), + .mrdaddress(rd_addr), + .mrden(rd_en), + .mwraddress(wr_addr), + .mwren(wr_en), + .mq(data_out) + ); + + defparam DUT_CACHE.SIZE = 16*1024*8; + defparam DUT_CACHE.NWAYS = 8; + defparam DUT_CACHE.NSETS = 2048; + defparam DUT_CACHE.BLOCK_SIZE = 64; + defparam DUT_CACHE.WIDTH = 32; + defparam DUT_CACHE.MWIDTH = 64; + + main_memory DUT_MEM ( + .clock(clk), + .data(data_in), + .rdaddress(rd_addr), + .rden(rd_en), + .wraddress(wr_addr), + .wren(wr_en), + .q(data_out) + ); + + defparam DUT_MEM.WIDTH = 32; + defparam DUT_MEM.DEPTH = 128; + defparam DUT_MEM.FILE = "main_mem_text.txt"; + + + always + begin + # 100; // This should be a miss + + i_cache_addr <= 32'h00000004; + i_cache_din <= 0; + i_cache_rden <= 1; + i_cache_wren <= 0; + + # 100; // This should be a miss + + i_cache_addr <= 32'h10000004; + i_cache_din <= 0; + i_cache_rden <= 1; + i_cache_wren <= 0; + + # 100; // This should be a hit + + i_cache_addr <= 32'h00000005; + i_cache_din <= 32'hBADDBEEF; + i_cache_rden <= 1; + i_cache_wren <= 0; + + # 100; // This should be a hit + + i_cache_addr <= 32'h10000006; + i_cache_din <= 32'h00000000; + i_cache_rden <= 1; + i_cache_wren <= 0; + + # 100; // This should be a hit + + i_cache_addr <= 32'h00000007; + i_cache_din <= 32'hAAAAAAAA; + i_cache_rden <= 1; + i_cache_wren <= 0; + + #50; + $finish; + end + + initial + begin + $monitor("time=%4d | addr=%10d | hm=%b | q=%08x | way1=%08h | way2=%08h | way3=%08h | way4=%08h | way5=%08h | way6=%08h | way7=%08h | way8=%08h | mem1=%08h | lru1=%d | lru2=%d | lru3=%d | lru4=%d | lru5=%d | lru6=%d | lru7=%d | lru8=%d" ,$time,i_cache_addr,i_cache_hit_miss,DUT_CACHE.q,DUT_CACHE.mem1[1],DUT_CACHE.mem2[1],DUT_CACHE.mem3[1],DUT_CACHE.mem4[1],DUT_CACHE.mem5[1],DUT_CACHE.mem6[1],DUT_CACHE.mem7[1],DUT_CACHE.mem8[1],DUT_MEM.mem[1],DUT_CACHE.lru1[1],DUT_CACHE.lru2[1],DUT_CACHE.lru3[1],DUT_CACHE.lru4[1],DUT_CACHE.lru5[1],DUT_CACHE.lru6[1],DUT_CACHE.lru7[1],DUT_CACHE.lru8[1]); + end + + always + begin + clk = 1'b1; + #5; + clk = 1'b0; + #5; + end + +endmodule diff --git a/RISC_V/Cache/main_memory.v b/RISC_V/Cache/main_memory.v new file mode 100644 index 0000000..d49d2a9 --- /dev/null +++ b/RISC_V/Cache/main_memory.v @@ -0,0 +1,83 @@ + +`define CLOG2(x) ( \ + (x <= 2) ? 1 : \ + (x <= 4) ? 2 : \ + (x <= 8) ? 3 : \ + (x <= 16) ? 4 : \ + (x <= 32) ? 5 : \ + (x <= 64) ? 6 : \ + (x <= 128) ? 7 : \ + (x <= 256) ? 8 : \ + (x <= 512) ? 9 : \ + (x <= 1024) ? 10 : \ + (x <= 2048) ? 11 : \ + (x <= 4096) ? 12 : \ + (x <= 8192) ? 13 : \ + (x <= 16384) ? 14 : \ + (x <= 32768) ? 15 : \ + (x <= 65536) ? 16 : \ + (x <= 131072) ? 17 : \ + (x <= 262144) ? 18 : \ + (x <= 524288) ? 19 : \ + (x <= 1048576) ? 20 : \ + (x <= 2097152) ? 21 : \ + (x <= 4194304) ? 22 : \ + (x <= 8388608) ? 23 : \ + (x <= 16777216) ? 24 : \ + (x <= 33554432) ? 25 : \ + (x <= 67108864) ? 26 : \ + (x <= 134217728) ? 27 : \ + (x <= 268435456) ? 28 : \ + (x <= 536870912) ? 29 : \ + (x <= 1073741824) ? 30 : \ + -1) + +module main_memory + #( + parameter WIDTH = 8, + parameter DEPTH = 64, + parameter FILE = "", + parameter INIT = 0 + ) + ( + input wire clock, + input wire [WIDTH-1:0] data, + input wire [`CLOG2(DEPTH)-1:0] rdaddress, + input wire rden, + input wire [`CLOG2(DEPTH)-1:0] wraddress, + input wire wren, + output reg [WIDTH-1:0] q + ); + + reg [WIDTH-1:0] mem [0:DEPTH-1] ; + + integer file; + integer scan; + integer i; + + initial + begin + // read file contents if FILE is given + if (FILE != "") + // If you get error here, check path to FILE + $readmemh(FILE, mem); + + // set all data to 0 if INIT is true + if (INIT) + for (i = 0; i < DEPTH; i = i + 1) + mem[i] = {WIDTH{1'b0}}; + end + + always @ (posedge clock) + begin + if (wren) + mem[wraddress] <= data; + end + + always @ (posedge clock) + begin + if (rden) + q <= mem[rdaddress]; + end + + endmodule diff --git a/RISC_V/Cache/page_table.v b/RISC_V/Cache/page_table.v new file mode 100644 index 0000000..8a49a98 --- /dev/null +++ b/RISC_V/Cache/page_table.v @@ -0,0 +1,50 @@ +module page_table( +input clock, +input [21:0] VPN, +output reg [19:0] PPN_o, +output reg valid_o + ); + +parameter PTE_ENTRIES = 4194304; + +reg [31:0] PPN [PTE_ENTRIES-1:0]; +reg valid [PTE_ENTRIES-1:0]; + +integer i; +integer ppn_curr; + +initial begin + ppn_curr = 4194304; + for(i = 0; i < 4194304 ; i = i + 1) + begin + if(i<4194286) + begin + valid[i]=1'b1; + PPN[i] = { i % 1048576 +1'b1 }; + end + else + begin + valid[i]=1'b0; + PPN[i] = { i % 1048576 +1'b1}; + end + + end + end + + always @(posedge clock) begin + if(valid[VPN])begin + PPN_o=PPN[VPN]; + valid_o=valid[VPN]; + end else begin + PPN[VPN]=ppn_curr; + valid[VPN]=1'b1; + PPN_o=PPN[VPN]; + + + + ppn_curr=ppn_curr+1;//PPN_curr++ + end + end + + +endmodule diff --git a/RISC_V/Cache/page_table_tb.v b/RISC_V/Cache/page_table_tb.v new file mode 100644 index 0000000..b9ddde8 --- /dev/null +++ b/RISC_V/Cache/page_table_tb.v @@ -0,0 +1,102 @@ +module page_table_tb(); + reg clk; + reg tlb_en; + reg read_write; + wire tlb_hit; + wire hit_miss; + reg clear_refer; + reg [33:0] _address2; + reg [31:0] din; + wire [31:0] PA; + + integer time_curr=0; + + TLB tlb(clk, + tlb_en, + read_write, + clear_refer, + _address2,//virtual address + PA,//PYHSICAL ADDRESS + + tlb_hit + ); + + data_cache cache(clk, + _address, // address form CPU + _address2, + din, // data from CPU (if st inst) + rden, // 1 if ld instruction + wren, // 1 if st instruction + hit_miss, // 1 if hit, 0 while handling miss + q, // data from cache to CPU + mdout, // data from cache to memory + mrdaddress, // memory read address + mrden, // read enable, 1 if reading from memory + mwraddress, // memory write address + mwren, // write enable, 1 if writing to memory + mq // data coming from memory + ); + +always #5 clk = ~clk; +always #5 time_curr =time_curr+5; + initial + begin + clk=1'b1; + tlb_en=1'b1; + clear_refer=1'b0; + assign clear_refer= (time_curr /(16*10))%2; + #10 read_write = 0; _address2 = 34'h0; //should miss + + #10 read_write = 1; _address2 = 34'h0; din = 32'h11111111; //should hit + + #10 read_write = 0; _address2 = 34'h0; //should hit and read out 0xff + + + #10 read_write = 0; _address2 = 34'h200; //should miss + + #10 read_write = 0; _address2 = 34'h0; //should hit + + #10 read_write = 0; _address2 = 34'h300; //should miss + + #10 read_write = 0; _address2 = 34'h200; //should miss + + #10 read_write = 0; _address2 = 34'h240; //should miss + + #10 read_write = 0; _address2 = 34'h50; + + #10 read_write = 0; _address2 = 34'h360; //should miss + + #10 read_write = 0; _address2 = 34'h270; + + #10 read_write = 0; _address2 = 34'h80; + + #10 read_write = 1; _address2 = 34'h90; din = 32'h11111111; + + #10 read_write = 0; _address2 = 34'hA0; //should hit + + #10 read_write = 0; _address2 = 34'h2B0; //should miss + + #10 read_write = 0; _address2 = 34'hC0; + + #10 read_write = 0; _address2 = 34'h3D0; //should miss + + #10 read_write = 0; _address2 = 34'h2E0; + + #10 read_write = 0; _address2 = 34'hF0; + + #10 read_write = 1; _address2 = 34'h100; din = 32'h11111111; + + #10 read_write = 0; _address2 = 34'h110; //should hit + + #10 read_write = 0; _address2 = 34'h200; + + #10 read_write = 0; _address2 = 34'h0; + + #10 read_write = 0; _address2 = 34'h300; + + #10 read_write = 0; _address2 = 34'h200; + + +end + +endmodule \ No newline at end of file diff --git a/RISC_V/Cache/tlb.v b/RISC_V/Cache/tlb.v new file mode 100644 index 0000000..c211d2d --- /dev/null +++ b/RISC_V/Cache/tlb.v @@ -0,0 +1,325 @@ +`include "page_table.v" + module tlb( + input clock, + input tlb_en, + input clear_refer, + input [33:0] VA,//virtual address + output reg [31:0] PA,//PYHSICAL ADDRESS + //input [16:0] PT_DATA + output reg tlb_hit +); + + + reg [19:0] PPN [52:0]; + reg [21:0] VPN [52:0]; + reg refer [52:0]; + reg valid [52:0]; + integer i=0; + reg [2:0] visit_entry; + + wire [11:0]_VA = VA[11:0]; + wire [19:0] page_table_PPN_out; + wire page_table_valid_out; + page_table pt(clock,VA[33:12],page_table_PPN_out,page_table_valid_out); + + initial + begin + VPN[0]=22'b0101001010001110100101; + PPN[0]=20'b01001010001110100110; + VPN[1]=22'b1010001110101110101011; + PPN[1]=20'b10001110101110101100; + VPN[2]=22'b0000101111111111111111; + PPN[2]=20'b00110000000000000000; + VPN[3]=22'b0101111000001010010101; + PPN[3]=20'b01111000001010010110; + VPN[4]=22'b1101011010001010001011; + PPN[4]=20'b01011010001010001100; + VPN[5]=22'b0001101001111100010101; + PPN[5]=20'b01101001111100010110; + VPN[6]=22'b0010100101111110000011; + PPN[6]=20'b10100101111110000100; + VPN[7]=22'b1101011010000101111111; + PPN[7]=20'b01011010000110000000; + end + always @(posedge clock) begin + if(tlb_en) begin + /*if(clear_refer) begin + for(i=0; i<8; i=i+1) + begin + refer[i] <= 1'b0; + end + end + for(i = 0 ;i < 7; i = i + 1) begin + if (VA[33:12]==VPN[i]) begin + tlb_hit <= 1; + visit_entry <= i; + end + else tlb_hit <= 0; + end + end*/ + case(i) + 0: begin + if(clear_refer) + begin + refer[i] <= 1'b0; + i <= i+1; + end + else + begin + refer[i] <= 1'b1; + i <= i+1; + end + if(VA[33:12] == VPN[i]) + begin + tlb_hit <= 1; + visit_entry <= i; + end + else tlb_hit <= 0; + end + 1: begin + if(clear_refer) + begin + refer[i] <= 1'b0; + i <= i+1; + end + else + begin + refer[i] <= 1'b1; + i <= i+1; + end + if(VA[33:12] == VPN[i]) + begin + tlb_hit = 1; + visit_entry = i; + end + else tlb_hit = 0; + end + 2: begin + if(clear_refer) + begin + refer[i] <= 1'b0; + i <= i+1; + end + else + begin + refer[i] <= 1'b1; + i <= i+1; + end + if(VA[33:12] == VPN[i]) + begin + tlb_hit <= 1; + visit_entry <= i; + end + else tlb_hit <= 0; + end + 3: begin + if(clear_refer) + begin + refer[i] <= 1'b0; + i <= i+1; + end + else + begin + refer[i] <= 1'b1; + i <= i+1; + end + if(VA[33:12] == VPN[i]) + begin + tlb_hit <= 1; + visit_entry <= i; + end + else tlb_hit <= 0; + end + 4: begin + if(clear_refer) + begin + refer[i] <= 1'b0; + i <= i+1; + end + else + begin + refer[i] <= 1'b1; + i <= i+1; + end + if(VA[33:12] == VPN[i]) + begin + tlb_hit <= 1; + visit_entry <= i; + end + else tlb_hit <= 0; + end + 5: begin + if(clear_refer) + begin + refer[i] <= 1'b0; + i <= i+1; + end + else + begin + refer[i] <= 1'b1; + i <= i+1; + end + if(VA[33:12] == VPN[i]) + begin + tlb_hit <= 1; + visit_entry <= i; + end + else tlb_hit <= 0; + end + 6: begin + if(clear_refer) + begin + refer[i] <= 1'b0; + i <= i+1; + end + else + begin + refer[i] <= 1'b1; + i <= i+1; + end + if(VA[33:12] == VPN[i]) + begin + tlb_hit <= 1; + visit_entry <= i; + end + else tlb_hit <= 0; + end + 7: begin + if(clear_refer) refer[i] <= 1'b0; + else refer[i] <= 1'b1; + if(VA[33:12] == VPN[i]) + begin + tlb_hit <= 1; + visit_entry <= i; + end + else tlb_hit <= 0; + end + default: tlb_hit = 1'bx; + endcase + + case(i) + 0: begin + if(tlb_hit) + begin + #10 PA = {PPN[visit_entry],_VA[11:0]}; + refer[visit_entry] <= 1; + end + else + begin + if(refer[i]==0) begin + visit_entry = i; end + valid[visit_entry]=page_table_valid_out; + #10 PA = {page_table_PPN_out,_VA[11:0]}; + refer[visit_entry] = 1; + end + end + 1: begin + if(tlb_hit) + begin + #10 PA = {PPN[visit_entry],_VA[11:0]}; + refer[visit_entry] = 1; + end + else + begin + if(refer[i]==0) begin + visit_entry = i; end + valid[visit_entry]=page_table_valid_out; + #10 PA = {page_table_PPN_out,_VA[11:0]}; + refer[visit_entry] = 1; + end + end + 2: begin + if(tlb_hit) + begin + #10 PA = {PPN[visit_entry],_VA[11:0]}; + refer[visit_entry] = 1; + end + else + begin + if(refer[i]==0) begin + visit_entry = i; end + valid[visit_entry]=page_table_valid_out; + #10 PA = {page_table_PPN_out,_VA[11:0]}; + refer[visit_entry] = 1; + end + end + 3: begin + if(tlb_hit) + begin + #10 PA <= {PPN[visit_entry],_VA[11:0]}; + refer[visit_entry] <= 1; + end + else + begin + if(refer[i]==0) begin + visit_entry <= i; end + valid[visit_entry]<=page_table_valid_out; + #10 PA <= {page_table_PPN_out,_VA[11:0]}; + refer[visit_entry] <= 1; + end + end + 4: begin + if(tlb_hit) + begin + #10 PA <= {PPN[visit_entry],VA[11:0]}; + refer[visit_entry] <= 1; + end + else + begin + if(refer[i]==0) begin + visit_entry <= i; end + valid[visit_entry]<=page_table_valid_out; + #10 PA <= {page_table_PPN_out,VA[11:0]}; + refer[visit_entry] <= 1; + end + end + 5: begin + if(tlb_hit) + begin + #10 PA <= {PPN[visit_entry],VA[11:0]}; + refer[visit_entry] <= 1; + end + else + begin + if(refer[i]==0) begin + visit_entry <= i; end + valid[visit_entry]<=page_table_valid_out; + #10 PA <= {page_table_PPN_out,VA[11:0]}; + refer[visit_entry] <= 1; + end + end + 6: begin + if(tlb_hit) + begin + #10 PA <= {PPN[visit_entry],VA[11:0]}; + refer[visit_entry] <= 1; + end + else + begin + if(refer[i]==0) begin + visit_entry <= i; end + valid[visit_entry]<=page_table_valid_out; + #10 PA <= {page_table_PPN_out,VA[11:0]}; + refer[visit_entry] <= 1; + end + end + 7: begin + if(tlb_hit) + begin + #10 PA = {PPN[visit_entry],VA[11:0]}; + refer[visit_entry] = 1; + end + else + begin + if(refer[i]==0) begin + visit_entry = i; end + #10 PA = {page_table_PPN_out,VA[11:0]}; + valid[visit_entry]=page_table_valid_out; + refer[visit_entry] = 1; + end + end + default: #10 PA <= 32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; + endcase + end + end +endmodule