Skip to content

Commit

Permalink
plru testing for cache
Browse files Browse the repository at this point in the history
  • Loading branch information
Abdullahkeblawi committed Jan 4, 2025
1 parent cd54d7a commit 630df38
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 87 deletions.
130 changes: 64 additions & 66 deletions source/ifu/ifu_cache.sv
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import ifu_pkg::*;
// Debug
output logic dataInsertion,
output logic hitStatusOut,
output logic debug_freeline,
output logic [LINE_WIDTH * NUM_LINES - 1:0] debug_dataArray, // Flattened dataArray
output logic [(TAG_WIDTH + 1) * NUM_TAGS - 1:0] debug_tagArray, // Flattened tagArray with valid bit
output logic [NUM_LINES - 2:0] debug_plruTree, // Current PLRU tree
Expand All @@ -33,35 +32,47 @@ import ifu_pkg::*;
///////////////////
// Logic Defines //
///////////////////
tag_arr_t tagArray [NUM_TAGS];

// cpu
logic [ADDR_WIDTH - 1 : OFFSET_WIDTH] cpu_reqTagIn;

// arrays
tag_arr_t tagArray [NUM_TAGS];
data_arr_t dataArray [NUM_LINES];
logic [P_BITS - 1:0] replacementLine;

// Hit status
// Hit
logic [P_BITS - 1:0] hitPosition;
logic [NUM_TAGS - 1:0] hitArray;
logic hitStatus;

// PLRU
logic [P_BITS - 1:0] lineForPLRU;
logic [P_BITS - 1:0] freeLine;
logic freeLineValid;
logic [NUM_LINES - 2:0] plruTree;
logic [NUM_LINES - 2:0] currentTree;
logic [NUM_LINES - 2:0] tempUpdatedTree;
logic [P_BITS - 1:0] plruIndex;
logic [NUM_LINES - 2:0] updatedPlruTree;
logic [P_BITS - 1:0] updatedPlruIdx; // this is used to calculate the plru after access, or when finding when finding replacementLine (which is the line that we can overwrite)
logic plruAccessLineValid;
logic [P_BITS - 1:0] plruAccessLine;



/////////////
// Assigns //
/////////////

// Requested Tag
assign cpu_reqTagIn = cpu_reqAddrIn[ADDR_WIDTH - 1:OFFSET_WIDTH];

// Hit
assign hitStatus = |hitArray;
assign mem_reqTagValidOut = !hitStatus;

// Insertion
assign dataInsertion = (mem_reqTagValidOut == VALID) && (mem_rspInsLineValidIn == VALID) && (mem_reqTagOut == mem_rspTagIn);
assign debug_freeline = freeLine;

// Debug
assign hitStatusOut = hitStatus;
assign debug_plruTree = plruTree;
assign debug_plruIndex = plruIndex;
assign debug_plruIndex = replacementLine;

// Flattened debug arrays for monitoring
generate
Expand All @@ -78,78 +89,68 @@ endgenerate
// Always Comb Statement //
///////////////////////////
always_comb begin
// Local Variables
automatic int loopCount; // Safeguard for infinite loop
automatic logic [P_BITS - 1:0] index;

// Initialize Local Variables
index = 0;
loopCount = 0;
plruIndex = 0;
freeLine = 0;
freeLineValid = 0;
// Initialize Variables
plruAccessLineValid = 0;
replacementLine = 0;
updatedPlruTree = plruTree;

// Hit Status
for (int i = 0; i < NUM_TAGS; i++) begin
if (cpu_reqTagIn == tagArray[i].tag && tagArray[i].valid == VALID) begin
hitArray[i] = 1;
hitPosition = i;
cpu_rspAddrOut = cpu_reqAddrIn;
end else begin
hitArray[i] = 0;
end
end

// Cache Action
if (hitStatus == HIT) begin
cpu_rspAddrOut = cpu_reqAddrIn;
cpu_rspInsLineOut = dataArray[hitPosition];
cpu_rspInsLineValidOut = VALID;
lineForPLRU = hitPosition;
plruAccessLineValid = VALID;
plruAccessLine = hitPosition;
end else begin
cpu_rspInsLineValidOut = !VALID;
mem_reqTagOut = cpu_reqTagIn;
lineForPLRU = freeLine;
mem_reqTagOut = cpu_reqTagIn;
end

// Line Insertion
if (dataInsertion) begin
freeLineValid = 0;
for (int i = 0; i < NUM_TAGS; i++) begin
if (!tagArray[i].valid) begin
freeLine = i;
freeLineValid = 1;
break;
if (dataInsertion) begin
cpu_rspAddrOut = cpu_reqAddrIn;
cpu_rspInsLineOut = mem_rspInsLineValidIn;
cpu_rspInsLineValidOut = VALID;
// PLRU update on Insertion
updatedPlruIdx = 0;
for (int level = 0; level < P_BITS ; level++ ) begin
if (plruTree[updatedPlruIdx] == 0) begin
replacementLine[P_BITS - level - 1] = 0;
updatedPlruIdx = (updatedPlruIdx << 1) + 1;
end else begin
replacementLine[P_BITS - level - 1] = 1;
updatedPlruIdx = (updatedPlruIdx << 1) + 1;
end
end
if (freeLineValid == 0) begin
freeLine = plruIndex;
end
end

// PLRU Tree Update
tempUpdatedTree = currentTree;
for (int level = P_BITS - 1; level >= 0; level--) begin
tempUpdatedTree[index] = !(lineForPLRU[level]);
index = (index << 1) | lineForPLRU[level];
plruAccessLine = hitPosition;
plruAccessLineValid = VALID;
end

// Debug the updated tree
$display("Updated PLRU Tree: %b", tempUpdatedTree);

// PLRU Index Calculation
plruIndex = 0;
while (plruIndex < NUM_LINES - 1 && loopCount < NUM_LINES) begin
if (plruTree[plruIndex] === 1'bx) begin
$display("Error: Invalid value in PLRU Tree at index %0d", plruIndex);
plruIndex = 0;
break;
// PLRU update on access
if (plruAccessLineValid) begin
updatedPlruIdx = 0;
for (int level = 0; level < P_BITS ; level++ ) begin
if (plruAccessLine[P_BITS - level - 1] == 0) begin
updatedPlruTree[updatedPlruIdx] = 1;
updatedPlruIdx = (updatedPlruIdx << 1) + 2;
end else begin
updatedPlruTree[updatedPlruIdx] = 0;
updatedPlruIdx = (updatedPlruIdx << 1) + 1;
end
end
plruIndex = (plruIndex << 1) | plruTree[plruIndex];
loopCount++;
end
if (loopCount == NUM_LINES) begin
$display("Error: Infinite loop detected in PLRU index calculation!");
end
end

end

///////////////////////////
Expand All @@ -161,20 +162,17 @@ always_ff @(posedge Clock or posedge Rst) begin
tagArray[i] <= 0;
dataArray[i] <= 0;
end
plruTree <= 0;
currentTree <= 0;
plruTree <= 15'b0;
end else begin
if (hitStatus == HIT) begin
plruTree <= tempUpdatedTree;
currentTree <= tempUpdatedTree; // Sync currentTree
plruTree <= updatedPlruTree;
end

if (dataInsertion) begin
dataArray[freeLine] <= mem_rspInsLineIn;
tagArray[freeLine].valid <= VALID;
tagArray[freeLine].tag[TAG_WIDTH-1:0] <= mem_rspTagIn[TAG_WIDTH-1:0];
plruTree <= tempUpdatedTree;
currentTree <= tempUpdatedTree; // Sync currentTree
dataArray[replacementLine] <= mem_rspInsLineIn;
tagArray[replacementLine].valid <= VALID;
tagArray[replacementLine].tag[TAG_WIDTH-1:0] <= mem_rspTagIn[TAG_WIDTH-1:0];
plruTree <= updatedPlruTree;
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions source/ifu/ifu_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ parameter logic MISS = 1'b0; // Indicates a miss
parameter logic VALID = 1'b1; // Indicates validity
parameter NUM_TAGS = 16; // Number of tags
parameter NUM_LINES = 16; // Number of lines: should be equal to number of tags
parameter OFFSET_WIDTH = 5; // Width of each offset
parameter OFFSET_WIDTH = 4; // Width of each offset
parameter ADDR_WIDTH = 32; // Width of address
parameter TAG_WIDTH = 27; // Width of each Tag
parameter TAG_WIDTH = 28; // Width of each Tag
parameter LINE_WIDTH = 128; // Width of each cache line
parameter P_BITS = $clog2(NUM_TAGS); // Bits needed for position of line

Expand Down
6 changes: 3 additions & 3 deletions source/ifu/ifu_prefetcher.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include "macros.vh"
`include "macros.vh"

module ifu_prefetcher
import ifu_pkg::*;
Expand All @@ -17,9 +17,9 @@ import ifu_pkg::*;
output logic prefetch_addr_valid_out, // Indicates if the prefetch address is valid

// Memory Interface
input logic mem_prefetch_ready_in // Indicates if memory can accept prefetch requests
input logic mem_prefetch_ready_in, // Indicates if memory can accept prefetch requests
output logic [ADDR_WIDTH-1:0] mem_prefetch_addr_out, // Predicted address sent to memory
output logic mem_prefetch_valid_out, // Indicates if the prefetch request is valid
output logic mem_prefetch_valid_out // Indicates if the prefetch request is valid
);


Expand Down
46 changes: 30 additions & 16 deletions verif/ifu/tb/PLRU_tb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ module PLRU_tb;
// Debug Outputs
logic hitStatusOut;
logic dataInsertion;
logic debug_freeLine;
logic [LINE_WIDTH * NUM_LINES - 1:0] debug_dataArray;
logic [(TAG_WIDTH + 1) * NUM_TAGS - 1:0] debug_tagArray;
logic [NUM_LINES - 2:0] debug_plruTree;
Expand All @@ -44,7 +43,6 @@ module PLRU_tb;
.mem_reqTagValidOut(mem_reqTagValidOut),
.dataInsertion(dataInsertion),
.hitStatusOut(hitStatusOut),
.debug_freeline(debug_freeLine),
.debug_dataArray(debug_dataArray),
.debug_tagArray(debug_tagArray),
.debug_plruTree(debug_plruTree),
Expand Down Expand Up @@ -93,13 +91,14 @@ initial begin
#20; // Hold reset for 20 ns
Rst = 0;
#10;
$display("PLRU tree reset to: %0h", dut.debug_plruTree);
$display("PLRU tree reset to: %0b", dut.debug_plruTree);
display_data_array();
display_tag_array();

// 2. Basic Cache Miss
$display("Test %0d: Basic Cache Miss", ++test_counter);
cpu_reqAddrIn = 32'h1000; // Set request address
$display("Requesting cpu address: %0h", cpu_reqAddrIn);

display_data_array();
display_tag_array();
Expand All @@ -115,56 +114,69 @@ initial begin
// check if data insertion mode is on
#5
$display("Cache miss handled. Data insertion: %0b, hit: %0b, req data: %0h , %0b, rsp data: %0h, %0b", dut.dataInsertion, dut.hitStatusOut, dut.mem_reqTagOut, dut.mem_reqTagValidOut, mem_rspTagIn, mem_rspInsLineValidIn);

$display("PLRU before replacement. Evicted index: %0b", dut.debug_plruIndex);
$display("PLRU tree before replacement: %0b", dut.debug_plruTree);

#10
mem_rspInsLineValidIn = 0;
$display("Inserted data: %0h", dut.cpu_rspInsLineOut);
display_data_array();
display_tag_array();
$display("PLRU replacement executed. Evicted index: %0b", dut.debug_plruIndex);
$display("PLRU tree after replacement: %0b", dut.debug_plruTree);

// 3. Basic Cache Hit
$display("Test %0d: Basic Cache Hit", ++test_counter);
cpu_reqAddrIn = 32'h1000; // Access the same address
$display("Requesting cpu address: %0h", cpu_reqAddrIn);
#10;
$display("Cache hit. Valid line: %0b, Data: %0h", dut.cpu_rspInsLineValidOut, dut.cpu_rspInsLineOut);
$display("PLRU tree after hit: %0h", dut.debug_plruTree);
$display("PLRU tree after hit: %0b", dut.debug_plruTree);

// 4. PLRU Replacement
$display("Test %0d: PLRU Replacement", ++test_counter);
for (i = 0; i < NUM_LINES; i++) begin
cpu_reqAddrIn = i * 32;
for (i = 0; i < NUM_LINES*4; i++) begin
cpu_reqAddrIn = i * 16;
$display("Requesting cpu address: %0h", cpu_reqAddrIn);
#5 // check if memory request is sent
$display("PLRU before replacement. Evicted index: %0b", dut.debug_plruIndex);
$display("PLRU tree before replacement: %0b", dut.debug_plruTree);
$display("Cache miss handled. Data insertion: %0b, hit: %0b, req data: %0h , %0b, rsp data: %0h, %0b", dut.dataInsertion, dut.hitStatusOut, dut.mem_reqTagOut, dut.mem_reqTagValidOut, mem_rspTagIn, mem_rspInsLineValidIn);
#5 // simulate mem response
temp_data = (i + 1) & 8'hFF; // Extract the lower 8 bits
mem_rspTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH];
mem_rspInsLineIn = {16{temp_data}}; // Unique data
mem_rspInsLineValidIn = 1;
mem_rspTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH];
#5;
$display("Cache miss handled. Data insertion: %0b, hit: %0b, req data: %0h , %0b, rsp data: %0h, %0b", dut.dataInsertion, dut.hitStatusOut, dut.mem_reqTagOut, dut.mem_reqTagValidOut, mem_rspTagIn, mem_rspInsLineValidIn);
#10;
#5
mem_rspInsLineValidIn = 0;
$display("Inserted data for address %0h: %0h", cpu_reqAddrIn, mem_rspInsLineIn);
$display("Inserted data for address %0h: %0h", cpu_reqAddrIn, mem_rspTagIn);
display_data_array();
display_tag_array();
$display("PLRU replacement executed. Evicted index: %0b", dut.debug_plruIndex);
$display("PLRU tree after replacement: %0b", dut.debug_plruTree);
end

// Insert one more line to trigger replacement
cpu_reqAddrIn = 32'hFFFF;
$display("Requesting cpu address: %0h", cpu_reqAddrIn);
temp_data = 8'hFF; // Unique data for this case
mem_rspInsLineIn = {16{temp_data}};
mem_rspInsLineValidIn = 1;
mem_rspTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH];
#10;
mem_rspInsLineValidIn = 0;

$display("PLRU replacement executed. Evicted index: %0h", dut.debug_plruIndex);
$display("PLRU tree after replacement: %0h", dut.debug_plruTree);
$display("PLRU replacement executed. Evicted index: %0b", dut.debug_plruIndex);
$display("PLRU tree after replacement: %0b", dut.debug_plruTree);
display_data_array();
display_tag_array();

// 5. Re-accessing Evicted Line
$display("Test %0d: Re-accessing Evicted Line", ++test_counter);
cpu_reqAddrIn = 32'hFFFF; // Accessing evicted line
$display("Requesting cpu address: %0h", cpu_reqAddrIn);
#10;
$display("Cache hit status: %0b, Retrieved data: %0h", dut.cpu_rspInsLineValidOut, dut.cpu_rspInsLineOut);
display_data_array();
Expand All @@ -174,30 +186,32 @@ initial begin
// Insert a second line to trigger replacement again
$display("Test %0d: PLRU Replacement (2nd trigger)", ++test_counter);
cpu_reqAddrIn = 32'hFFFE;
$display("Requesting cpu address: %0h", cpu_reqAddrIn);
temp_data = 8'hFE; // Unique data for this case
mem_rspInsLineIn = {16{temp_data}};
mem_rspInsLineValidIn = 1;
mem_rspTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH];
#10;
mem_rspInsLineValidIn = 0;

$display("PLRU replacement executed. Evicted index: %0h", dut.debug_plruIndex);
$display("PLRU tree after replacement: %0h", dut.debug_plruTree);
$display("PLRU replacement executed. Evicted index: %0b", dut.debug_plruIndex);
$display("PLRU tree after replacement: %0b", dut.debug_plruTree);
display_data_array();
display_tag_array();

// Insert a third line to trigger replacement again
$display("Test %0d: PLRU Replacement (3rd trigger)", ++test_counter);
cpu_reqAddrIn = 32'hFFFD;
$display("Requesting cpu address: %0h", cpu_reqAddrIn);
temp_data = 8'hFD; // Unique data for this case
mem_rspInsLineIn = {16{temp_data}};
mem_rspInsLineValidIn = 1;
mem_rspTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH];
#10;
mem_rspInsLineValidIn = 0;

$display("PLRU replacement executed. Evicted index: %0h", dut.debug_plruIndex);
$display("PLRU tree after replacement: %0h", dut.debug_plruTree);
$display("PLRU replacement executed. Evicted index: %0b", dut.debug_plruIndex);
$display("PLRU tree after replacement: %0b", dut.debug_plruTree);
$display("Final Data Array:");
display_data_array();
$display("Final Tag Array:");
Expand Down

0 comments on commit 630df38

Please sign in to comment.