-
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 34 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
`include "macros.vh" | ||
|
||
module ifu | ||
import ifu_pkg::*; | ||
( | ||
// Chip Signals | ||
input logic Clock, | ||
input logic Rst, | ||
|
||
// CPU Interface | ||
input logic [ADDR_WIDTH-1:0] cpu_reqAddrIn, // Address requested by the CPU | ||
// i think maybe we don't have to put this as an output because the CPU don't care about it. but i put it just in case | ||
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, // Instruction line in the response to CPU | ||
output logic cpu_rspInsLineValidOut, // Indicates if the response is valid | ||
|
||
// Memory Interface | ||
input logic mem_ready_in, // Indicates if memory is ready for requests | ||
input logic [TAG_WIDTH-1:0] mem_rspTagIn, // Tag of the line provided by memory | ||
input logic [LINE_WIDTH-1:0] mem_rspInsLineIn, // Line data provided by memory | ||
input logic mem_rspInsLineValidIn, // Valid signal for memory response | ||
output logic [ADDR_WIDTH-1:0] mem_reqAddrOut, // Address requested by the IFU | ||
output logic mem_reqValidOut // Indicates if a memory request is valid | ||
); | ||
|
||
|
||
|
||
// Cache Module | ||
ifu_cache ifu_cache ( | ||
.Clock(Clock), // Input | ||
.Rst(Rst), // Input | ||
// CPU Interface | ||
.cpu_reqAddrIn(cpu_reqAddrIn), // Input | ||
.cpu_rspAddrOut(cpu_rspAddrOut), // Output | ||
.cpu_rspInsLineOut(cpu_rspInsLineOut), // Output | ||
.cpu_rspInsLineValidOut(cpu_rspInsLineValidOut), // Output | ||
// Memory Interface | ||
.mem_rspTagIn(mem_rspTagIn), // Input | ||
.mem_rspInsLineIn(mem_rspInsLineIn), // Input | ||
.mem_rspInsLineValidIn(mem_rspInsLineValidIn), // Input | ||
.mem_reqTagOut(mem_reqAddrOut), // Output | ||
.mem_reqTagValidOut(mem_reqValidOut), // Output | ||
// Prefetcher Interface | ||
.cache_miss_addr_out(cache_miss_addr), // Output | ||
.cache_miss_valid_out(cache_miss_valid) // Output | ||
); | ||
|
||
|
||
|
||
// Prefetcher Module | ||
ifu_prefetcher ifu_prefetcher ( | ||
.Clock(Clock), // Input | ||
.Rst(Rst), // Input | ||
// CPU Interface | ||
.cpu_reqAddrIn(cpu_reqAddrIn), // Input | ||
// Cache Interface | ||
.cache_miss_addr_in(cache_miss_addr), // Input | ||
.cache_miss_valid_in(cache_miss_valid), // Input | ||
.prefetch_addr_out(prefetch_addr), // Output | ||
.prefetch_addr_valid_out(prefetch_valid), // Output | ||
// Memory Interface | ||
.mem_prefetch_ready_in(mem_ready_in), // Input | ||
.mem_prefetch_addr_out(mem_prefetch_addr), // Output | ||
.mem_prefetch_valid_out(mem_prefetch_valid) // Output | ||
); | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
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. 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,180 @@ | ||
`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 [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 | ||
output logic [P_BITS - 1:0] debug_plruIndex // PLRU index selected for eviction | ||
); | ||
|
||
/////////////////// | ||
// Logic Defines // | ||
/////////////////// | ||
|
||
// 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 | ||
logic [P_BITS - 1:0] hitPosition; | ||
logic [NUM_TAGS - 1:0] hitArray; | ||
logic hitStatus; | ||
|
||
// PLRU | ||
logic [NUM_LINES - 2:0] plruTree; | ||
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); | ||
|
||
// Debug | ||
assign hitStatusOut = hitStatus; | ||
assign debug_plruTree = plruTree; | ||
assign debug_plruIndex = replacementLine; | ||
|
||
// Flattened debug arrays for monitoring | ||
generate | ||
genvar i; | ||
for (i = 0; i < NUM_LINES; i++) begin | ||
assign debug_dataArray[i * LINE_WIDTH +: LINE_WIDTH] = dataArray[i].line; | ||
end | ||
for (i = 0; i < NUM_TAGS; i++) begin | ||
assign debug_tagArray[i * (TAG_WIDTH + 1) +: TAG_WIDTH + 1] = {tagArray[i].valid, tagArray[i].tag}; | ||
end | ||
endgenerate | ||
|
||
/////////////////////////// | ||
// Always Comb Statement // | ||
/////////////////////////// | ||
always_comb begin | ||
|
||
// 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; | ||
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; | ||
plruAccessLineValid = VALID; | ||
plruAccessLine = hitPosition; | ||
end else begin | ||
cpu_rspInsLineValidOut = !VALID; | ||
mem_reqTagOut = cpu_reqTagIn; | ||
end | ||
|
||
// Line Insertion | ||
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 | ||
plruAccessLine = replacementLine; | ||
plruAccessLineValid = VALID; | ||
end | ||
|
||
// 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 | ||
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 <= 15'b0; | ||
end else begin | ||
if (hitStatus == HIT) begin | ||
plruTree <= updatedPlruTree; | ||
end | ||
|
||
if (dataInsertion) begin | ||
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 | ||
|
||
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 = 4; // Width of each offset | ||
parameter ADDR_WIDTH = 32; // Width of address | ||
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 | ||
|
||
///////////////////// | ||
// 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,71 @@ | ||
`include "macros.vh" | ||
|
||
module ifu_prefetcher | ||
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 | ||
|
||
// Cache Interface | ||
input logic [ADDR_WIDTH-1:0] cache_miss_addr_in, // Address causing a miss in the cache | ||
input logic cache_miss_valid_in, // Indicates if the cache miss is valid | ||
output logic [ADDR_WIDTH-1:0] prefetch_addr_out, // Predicted address to prefetch | ||
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 | ||
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 | ||
); | ||
|
||
|
||
|
||
/////////////////// | ||
// Logic Defines // | ||
/////////////////// | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
///////////// | ||
// Assigns // | ||
///////////// | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/////////////////////////// | ||
// Always Comb Statement // | ||
/////////////////////////// | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/////////////////////////// | ||
// Always_ff Statement //// | ||
/////////////////////////// | ||
|
||
|
||
|
||
|
||
endmodule | ||
|
||
|
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 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