-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ifu cache update #769
base: main
Are you sure you want to change the base?
Ifu cache update #769
Changes from 26 commits
28f3f69
88ba556
17994bf
e4dc181
8212f20
4e8aca5
a832289
569bdac
f9c1583
48c8557
dc2464a
85a9ce5
df6f352
ff8641a
2a6c332
a54ec6c
a596d79
6889e37
bbe5ddb
f426719
f090227
7081f51
4335684
1325bc8
c8dfa10
cf674b9
9fbbb75
5624ae6
50bfc64
028dd91
39e0560
cd54d7a
630df38
feea367
d679136
5658c23
6ef3c25
26814d9
deda30b
d596a2f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see what you have been talking about. It's better to separate and put each module into different files. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
|
||
`include "macros.vh" | ||
|
||
module ifu_cache | ||
import ifu_pkg::*; | ||
( | ||
// Chip Signals | ||
input logic Clock, | ||
input logic Rst, | ||
|
||
// CPU Interface | ||
input logic [ADDR_WIDTH-1:0] cpu_reqAddrIn, // requested addr by cpu | ||
output logic [ADDR_WIDTH-1:0] cpu_rspAddrOut, // address of the line in the response to cpu | ||
output logic [LINE_WIDTH-1:0] cpu_rspInsLineOut, // the line in the response to cpu | ||
output logic cpu_rspInsLineValidOut, // valid, meaning the cpu can read the line | ||
|
||
// Memory Interface | ||
input logic [TAG_WIDTH-1:0] mem_rspTagIn, // tag of the line provide by response of the memory | ||
input logic [LINE_WIDTH-1:0] mem_rspInsLineIn, // the line provided in the response of the memory | ||
input logic mem_rspInsLineValidIn, // the line is ready in the response and can be read by the cache | ||
output logic [TAG_WIDTH-1:0] mem_reqTagOut, // tag requested by the cache from the memory | ||
output logic mem_reqTagValidOut, // there is a request for the tag to be brought from the memory | ||
|
||
// Prefetcher Interface | ||
// to be added | ||
// | ||
// debug | ||
output logic dataInsertion, | ||
output logic hitStatusOut, | ||
output logic [NUM_LINES - 2 :0] plruTreeOut | ||
|
||
); | ||
|
||
|
||
/////////////////// | ||
// Logic Defines // | ||
/////////////////// | ||
// tag array | ||
tag_arr_t tagArray [NUM_TAGS]; | ||
logic [ADDR_WIDTH - 1 : OFFSET_WIDTH-1 ] cpu_reqTagIn; | ||
|
||
// data array | ||
data_arr_t dataArray [NUM_LINES]; | ||
// logic dataInsertion; | ||
|
||
// hit status | ||
logic [P_BITS - 1:0] hitPosition; // synthesizable calculated in compilation time | ||
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] updatedTree; // Holds the updated PLRU tree | ||
logic [P_BITS - 1 : 0] plruIndex; // Holds the LRU index | ||
logic updateTreeValid; | ||
|
||
///////////// | ||
// Assigns // | ||
///////////// | ||
assign cpu_reqTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH-1]; | ||
assign hitStatus = |hitArray; | ||
assign mem_reqTagValidOut = !hitStatus; | ||
assign dataInsertion = (mem_reqTagValidOut == VALID) && (mem_rspInsLineValidIn == VALID) && (mem_reqTagOut == mem_rspTagIn); | ||
assign plruTreeOut = plruTree; | ||
assign hitStatusOut = hitStatus; | ||
|
||
|
||
/////////////////////////// | ||
// Always Comb Statement // | ||
/////////////////////////// | ||
|
||
always_comb begin | ||
//////////////// | ||
// 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 // hit handling | ||
cpu_rspInsLineOut = dataArray[hitPosition]; | ||
cpu_rspInsLineValidOut = VALID; // we have the line in cache | ||
lineForPLRU = hitPosition; | ||
end else begin // miss handling | ||
cpu_rspInsLineValidOut = !VALID; // we do not have the line in cache | ||
mem_reqTagOut = cpu_reqTagIn; | ||
lineForPLRU = freeLine; | ||
end | ||
|
||
//////////////////// | ||
// Line Insertion // | ||
//////////////////// | ||
if (dataInsertion) begin | ||
freeLineValid = 0; | ||
freeLine = 0; | ||
//checks if there any empty cache lines before using the PLRU | ||
for (int i = 0 ; i < NUM_TAGS ; i++)begin | ||
if (!tagArray[i].valid)begin | ||
freeLine = i; | ||
freeLineValid = 1; | ||
break; | ||
end | ||
end | ||
//in case all the lines in the cache are full | ||
if (freeLineValid == 0)begin | ||
freeLine = plruIndex; | ||
end | ||
end | ||
end // always_comb end | ||
|
||
|
||
/////////////////////////// | ||
// Always ff Statement // | ||
/////////////////////////// | ||
always_ff @(posedge Clock or posedge Rst) begin | ||
|
||
///////////////// | ||
// Cache Reset // | ||
///////////////// | ||
if (Rst) begin | ||
for (int i = 0 ; i < NUM_TAGS ; i++) begin | ||
tagArray[i] <= 0; | ||
dataArray[i] <= 0; | ||
end | ||
plruTree <= 0; // Reset PLRU tree | ||
end | ||
|
||
if (hitStatus == HIT) begin | ||
plruTree <= updatedTree; //updates the plru tree when there is a hit | ||
end | ||
|
||
if(dataInsertion) begin | ||
dataArray[freeLine] <= mem_rspInsLineIn; | ||
tagArray[freeLine].valid <= VALID; | ||
tagArray[freeLine].tag <= mem_rspTagIn; | ||
plruTree <= updatedTree; | ||
end | ||
end | ||
|
||
|
||
/////////////// | ||
// Utilities // | ||
/////////////// | ||
//Updates the PLRU tree after a hit or replacement. | ||
module updatePLruTree ( | ||
input logic [NUM_LINES - 2 : 0] currentTree, | ||
input logic [P_BITS - 1 : 0] line, | ||
output logic [NUM_LINES - 2 : 0] updatedTree | ||
); | ||
|
||
logic [P_BITS - 1 : 0] index; | ||
|
||
always_comb begin | ||
//index = 0; | ||
updatedTree = currentTree; | ||
for (int level = P_BITS - 1 ; level >= 0; level--) begin | ||
updatedTree[index] = (line >> level) & 1; | ||
index = (index << 1) | ((line >> level) & 1); | ||
end | ||
end | ||
endmodule | ||
|
||
//Computes the least recently used (LRU) index. | ||
module getPLRUIndex ( | ||
input logic [NUM_LINES - 2 : 0] tree, | ||
output logic [P_BITS - 1 : 0] index | ||
); | ||
|
||
always_comb begin | ||
//index = 0; | ||
while(index < NUM_LINES - 1) begin | ||
// Updates the index to search in the next layer in the tree, tree[index] chooses the left or right node | ||
index = (index << 1 ) | tree[index]; | ||
index = index % 15 ; // mod 15 to insure the index is always smaller than 16 | ||
end | ||
//index = index & ((1 << P_BITS) - 1); | ||
end | ||
|
||
endmodule | ||
|
||
|
||
// Module Instantiations | ||
getPLRUIndex plru_index_inst ( | ||
.tree(plruTree), | ||
.index(plruIndex) | ||
); | ||
|
||
updatePLruTree update_plru_inst ( | ||
.currentTree(plruTree), | ||
.line(lineForPLRU), | ||
.updatedTree(updatedTree) | ||
); | ||
|
||
endmodule |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its not necessary to declare parameter al logic. when you declare something as logic, it can be 0,1,x, Z. Its not wrong but for consistent coding style its better not to use logic |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
|
||
|
||
package ifu_pkg; | ||
|
||
|
||
|
||
/////////////////////// | ||
// Parameter Defines // | ||
/////////////////////// | ||
parameter logic HIT = 1'b1; // Indicates a hit | ||
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 ADDR_WIDTH = 32; // Width of address | ||
parameter TAG_WIDTH = 27; // 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 | ||
|
||
///////////////////// | ||
// Package Defines // | ||
///////////////////// | ||
|
||
typedef struct packed { | ||
bit valid; // Valid bit | ||
logic [TAG_WIDTH-1:0] tag; // Tag value | ||
} tag_arr_t; | ||
|
||
typedef struct packed { | ||
logic [LINE_WIDTH-1:0] line; // Tag value | ||
} data_arr_t; | ||
|
||
endpackage |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
|
||
+incdir+../../../source/common/ | ||
|
||
// param packages | ||
../../../source/ifu/ifu_pkg.sv | ||
|
||
|
||
//RTL FIles | ||
../../../source/ifu/ifu.sv | ||
../../../source/ifu/ifu_cache.sv | ||
../../../source/ifu/ifu_prefetcher.sv | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// test file for branch |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
+define+SIM_ONLY | ||
-f ../../../source/ifu/ifu_rtl_list.f | ||
-f ../../../verif/ifu/file_list/ifu_verif_list.f |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
+incdir+../../../source/common/ | ||
+incdir+../../../verif/ifu/tb/ | ||
../../../verif/ifu/tb/ifu_cache_tb.sv | ||
../../../verif/ifu/tb/PLRU_tb.sv |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. out simulator does not support assertion. you don't have to use assertion. If you want we have a special macro inside |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
`timescale 1ns/1ps | ||
|
||
module PLRU_tb; | ||
|
||
import ifu_pkg::*; | ||
|
||
// Inputs | ||
logic Clock; | ||
logic Rst; | ||
logic [ADDR_WIDTH-1:0] cpu_reqAddrIn; | ||
logic [LINE_WIDTH-1:0] mem_rspInsLineIn; | ||
logic mem_rspInsLineValidIn; | ||
logic [TAG_WIDTH-1:0] mem_rspTagIn; | ||
|
||
// Outputs | ||
logic [ADDR_WIDTH-1:0] cpu_rspAddrOut; | ||
logic [LINE_WIDTH-1:0] cpu_rspInsLineOut; | ||
logic cpu_rspInsLineValidOut; | ||
logic [TAG_WIDTH-1:0] mem_reqTagOut; | ||
logic mem_reqTagValidOut; | ||
|
||
// Debug Outputs | ||
logic [LINE_WIDTH-1:0] debug_dataArray [NUM_LINES]; | ||
logic [TAG_WIDTH-1:0] debug_tagArray [NUM_TAGS]; | ||
logic [NUM_TAGS-1:0] debug_validArray; | ||
logic [NUM_LINES-2:0] debug_plruTree; | ||
logic hitStatusOut; | ||
logic dataInsertion; | ||
logic [NUM_LINES - 2 :0] plruTreeOut; | ||
|
||
// Instantiate the DUT (Device Under Test) | ||
ifu_cache | ||
dut ( | ||
.Clock(Clock), | ||
.Rst(Rst), | ||
.cpu_reqAddrIn(cpu_reqAddrIn), | ||
.cpu_rspAddrOut(cpu_rspAddrOut), | ||
.cpu_rspInsLineOut(cpu_rspInsLineOut), | ||
.cpu_rspInsLineValidOut(cpu_rspInsLineValidOut), | ||
.mem_rspTagIn(mem_rspTagIn), | ||
.mem_rspInsLineIn(mem_rspInsLineIn), | ||
.mem_rspInsLineValidIn(mem_rspInsLineValidIn), | ||
.mem_reqTagOut(mem_reqTagOut), | ||
.mem_reqTagValidOut(mem_reqTagValidOut), | ||
.dataInsertion(dataInsertion), | ||
.hitStatusOut(hitStatusOut), | ||
.plruTreeOut(plruTreeOut) | ||
//.debug_plruTree(debug_plruTree) | ||
); | ||
|
||
// Clock generation | ||
always #5 Clock = ~Clock; // 10 ns clock period | ||
|
||
// Testbench Variables | ||
int test_counter = 0; | ||
|
||
// Test Procedure | ||
initial begin | ||
// Initialize signals | ||
Clock = 0; | ||
Rst = 0; | ||
cpu_reqAddrIn = 0; | ||
mem_rspInsLineIn = 0; | ||
mem_rspInsLineValidIn = 0; | ||
mem_rspTagIn = 0; | ||
|
||
// 1. Reset Behavior | ||
$display("Test %0d: Reset Behavior", ++test_counter); | ||
Rst = 1; | ||
#20; // Hold reset for 20 ns | ||
Rst = 0; | ||
#10; | ||
// Verify all entries are invalid and PLRU tree is reset | ||
/*for (int i = 0; i < NUM_TAGS; i++) begin | ||
assert(dut.debug_validArray[i] == 0) else $fatal("Reset failed for validArray[%0d].", i); | ||
end*/ | ||
// assert(dut.debug_plruTree == 0) else $fatal("PLRU tree reset failed."); | ||
|
||
// 2. Basic Cache Miss | ||
$display("Test %0d: Basic Cache Miss", ++test_counter); | ||
cpu_reqAddrIn = 32'h1000; // Set request address | ||
mem_rspInsLineIn = 128'hDEADBEEFDEADBEEFDEADBEEFDEADBEEF; // Line data | ||
mem_rspTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH]; | ||
mem_rspInsLineValidIn = 1; | ||
#10; // Wait for one clock cycle | ||
mem_rspInsLineValidIn = 0; | ||
assert(dut.cpu_rspInsLineValidOut == 0) else $fatal("Cache miss handling failed."); | ||
|
||
// Simulate response from memory | ||
mem_rspInsLineValidIn = 1; | ||
#10; | ||
mem_rspInsLineValidIn = 0; | ||
assert(dut.cpu_rspInsLineOut == 128'hDEADBEEFDEADBEEFDEADBEEFDEADBEEF) else $fatal("Incorrect data inserted in cache."); | ||
|
||
// 3. Basic Cache Hit | ||
$display("Test %0d: Basic Cache Hit", ++test_counter); | ||
cpu_reqAddrIn = 32'h1000; // Access the same address | ||
#10; | ||
assert(dut.cpu_rspInsLineValidOut == 1) else $fatal("Cache hit failed."); | ||
assert(dut.cpu_rspInsLineOut == 128'hDEADBEEFDEADBEEFDEADBEEFDEADBEEF) else $fatal("Incorrect data retrieved on cache hit."); | ||
|
||
// 4. PLRU Replacement | ||
$display("Test %0d: PLRU Replacement", ++test_counter); | ||
for (int i = 0; i < NUM_LINES; i++) begin | ||
cpu_reqAddrIn = i * 4; // Unique addresses | ||
mem_rspInsLineIn = 128'hA5A5A5A5 + i; // Unique data | ||
mem_rspInsLineValidIn = 1; | ||
mem_rspTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH]; | ||
#10; | ||
mem_rspInsLineValidIn = 0; | ||
end | ||
// Insert one more line to trigger replacement | ||
cpu_reqAddrIn = 32'hFFFF; | ||
mem_rspInsLineIn = 128'h123456789ABCDEF; | ||
mem_rspInsLineValidIn = 1; | ||
mem_rspTagIn = cpu_reqAddrIn[ADDR_WIDTH-1:OFFSET_WIDTH]; | ||
#10; | ||
mem_rspInsLineValidIn = 0; | ||
// Check replacement | ||
assert(dut.cpu_rspInsLineValidOut == 0) else $fatal("PLRU replacement failed."); | ||
|
||
$display("All tests passed!"); | ||
$stop; | ||
end | ||
|
||
endmodule |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks good the best way to evaluate it is to see it will work or not and how. good job