-
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 28 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,170 @@ | ||
`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 | ||
|
||
// Debug | ||
output logic dataInsertion, | ||
output logic hitStatusOut, | ||
output logic [NUM_LINES - 2 :0] plruTreeOut | ||
); | ||
|
||
/////////////////// | ||
// Logic Defines // | ||
/////////////////// | ||
tag_arr_t tagArray [NUM_TAGS]; | ||
logic [ADDR_WIDTH - 1 : OFFSET_WIDTH - 1] cpu_reqTagIn; | ||
data_arr_t dataArray [NUM_LINES]; | ||
|
||
// Hit status | ||
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] updatedTree; | ||
logic [P_BITS - 1 : 0] plruIndex; | ||
|
||
///////////////// | ||
// Assignments/// | ||
//////////////// | ||
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 | ||
cpu_rspInsLineOut = dataArray[hitPosition]; | ||
cpu_rspInsLineValidOut = VALID; | ||
lineForPLRU = hitPosition; | ||
end else begin | ||
cpu_rspInsLineValidOut = !VALID; | ||
mem_reqTagOut = cpu_reqTagIn; | ||
lineForPLRU = freeLine; | ||
end | ||
|
||
// Line Insertion | ||
if (dataInsertion) begin | ||
freeLineValid = 0; | ||
freeLine = 0; | ||
for (int i = 0; i < NUM_TAGS; i++) begin | ||
if (!tagArray[i].valid) begin | ||
freeLine = i; | ||
freeLineValid = 1; | ||
break; | ||
end | ||
end | ||
if (freeLineValid == 0) begin | ||
freeLine = plruIndex; | ||
end | ||
end | ||
end | ||
|
||
/////////////////////////// | ||
// Always_ff Statement //// | ||
/////////////////////////// | ||
|
||
always_ff @(posedge Clock or posedge Rst) begin | ||
if (Rst) begin | ||
for (int i = 0; i < NUM_TAGS; i++) begin | ||
tagArray[i] <= 0; | ||
dataArray[i] <= 0; | ||
end | ||
plruTree <= 0; | ||
end | ||
|
||
if (hitStatus == HIT) begin | ||
plruTree <= updatedTree; | ||
end | ||
|
||
if (dataInsertion) begin | ||
dataArray[freeLine] <= mem_rspInsLineIn; | ||
tagArray[freeLine].valid <= VALID; | ||
tagArray[freeLine].tag <= mem_rspTagIn; | ||
plruTree <= updatedTree; | ||
end | ||
end | ||
|
||
endmodule | ||
|
||
/////////////////// | ||
// Internal Modules | ||
/////////////////// | ||
|
||
module updatePLruTree | ||
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. We don't have 2 modules in the same file. Each file one module, and the name of the module and the file must match |
||
import ifu_pkg::*; | ||
( | ||
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 | ||
if (index < NUM_LINES - 1) begin | ||
updatedTree[index] = (line >> level) & 1; | ||
end | ||
index = (index << 1) | ((line >> level) & 1); | ||
end | ||
end | ||
endmodule | ||
|
||
module getPLRUIndex | ||
import ifu_pkg::*; | ||
( | ||
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 | ||
index = (index << 1) | tree[index]; | ||
end | ||
end | ||
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,124 @@ | ||
`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 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) | ||
); | ||
|
||
// 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; | ||
// Monitor PLRU tree reset | ||
$display("PLRU tree reset to: %0h", dut.plruTreeOut); | ||
|
||
// 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; | ||
// Monitor cache miss handling | ||
$display("cpu_rspInsLineValidOut: %0h", dut.cpu_rspInsLineValidOut); | ||
|
||
// Simulate response from memory | ||
mem_rspInsLineValidIn = 1; | ||
#10; | ||
mem_rspInsLineValidIn = 0; | ||
// Monitor data insertion | ||
$display("Inserted data: %0h", dut.cpu_rspInsLineOut); | ||
|
||
// 3. Basic Cache Hit | ||
$display("Test %0d: Basic Cache Hit", ++test_counter); | ||
cpu_reqAddrIn = 32'h1000; // Access the same address | ||
#10; | ||
// Monitor cache hit | ||
$display("cpu_rspInsLineValidOut: %0h", dut.cpu_rspInsLineValidOut); | ||
$display("Retrieved data: %0h", dut.cpu_rspInsLineOut); | ||
|
||
// 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; | ||
// Monitor each insertion | ||
$display("Inserted data for address %0h: %0h", cpu_reqAddrIn, dut.cpu_rspInsLineOut); | ||
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; | ||
|
||
// Monitor replacement | ||
$display("PLRU replacement check for address %0h: %0h", cpu_reqAddrIn, dut.cpu_rspInsLineOut); | ||
|
||
$display("All tests completed!"); | ||
$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