mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 21:27:10 -04:00
✂️ Move address checker to store queue
This commit is contained in:
parent
ff91fdbfec
commit
bfae40e2a8
5 changed files with 52 additions and 59 deletions
|
@ -1,3 +1,4 @@
|
|||
|
||||
/* File: ariane_pkg.svh
|
||||
* Author: Florian Zaruba <zarubaf@ethz.ch>
|
||||
* Date: 8.4.2017
|
||||
|
@ -19,6 +20,9 @@ package ariane_pkg;
|
|||
// to uniquely identify the entry in the scoreboard
|
||||
localparam NR_WB_PORTS = 4;
|
||||
localparam ASID_WIDTH = 1;
|
||||
localparam BTB_ENTRIES = 64;
|
||||
localparam BITS_SATURATION_COUNTER = 2;
|
||||
|
||||
localparam logic [63:0] ISA_CODE = (1 << 2) // C - Compressed extension
|
||||
| (1 << 8) // I - RV32I/64I/128I base ISA
|
||||
| (1 << 12) // M - Integer Multiply/Divide extension
|
||||
|
|
30
src/lsu.sv
30
src/lsu.sv
|
@ -441,29 +441,22 @@ module lsu #(
|
|||
// ------------------
|
||||
// LSU Control
|
||||
// ------------------
|
||||
// The LSU consists of two independent block which share a common address translation block.
|
||||
// The one block is the load unit, the other one is the store unit. They will signal their readiness
|
||||
// with separate signals. If they are not ready the LSU control should keep the last applied signals stable.
|
||||
// Furthermore it can be the case that another request for one of the two store units arrives in which case
|
||||
// the LSU controll should sample it and store it for later application to the units. It does so, by storing it in a
|
||||
// two element FIFO.
|
||||
|
||||
// new data arrives here
|
||||
lsu_ctrl_t lsu_req_i;
|
||||
|
||||
assign lsu_req_i = {lsu_valid_i, vaddr_i, operand_b_i, be_i, fu_i, operator_i, trans_id_i};
|
||||
|
||||
lsu_bypass lsu_bypass_i (
|
||||
.lsu_req_i ( lsu_req_i ),
|
||||
.lsu_req_i ( lsu_req_i ),
|
||||
.lus_req_valid_i ( lsu_valid_i ),
|
||||
.pop_ld_i ( pop_ld ),
|
||||
.pop_st_i ( pop_st ),
|
||||
.pop_ld_i ( pop_ld ),
|
||||
.pop_st_i ( pop_st ),
|
||||
|
||||
.ld_ready_i ( ld_ready_o ),
|
||||
.st_ready_i ( st_ready_o),
|
||||
.ld_ready_i ( ld_ready_o ),
|
||||
.st_ready_i ( st_ready_o ),
|
||||
|
||||
.lsu_ctrl_o ( lsu_ctrl ),
|
||||
.ready_o ( lsu_ready_o ),
|
||||
.lsu_ctrl_o ( lsu_ctrl ),
|
||||
.ready_o ( lsu_ready_o ),
|
||||
.*
|
||||
);
|
||||
// ------------
|
||||
|
@ -500,6 +493,15 @@ module lsu #(
|
|||
`endif
|
||||
endmodule
|
||||
|
||||
// ------------------
|
||||
// LSU Control
|
||||
// ------------------
|
||||
// The LSU consists of two independent block which share a common address translation block.
|
||||
// The one block is the load unit, the other one is the store unit. They will signal their readiness
|
||||
// with separate signals. If they are not ready the LSU control should keep the last applied signals stable.
|
||||
// Furthermore it can be the case that another request for one of the two store units arrives in which case
|
||||
// the LSU controll should sample it and store it for later application to the units. It does so, by storing it in a
|
||||
// two element FIFO.
|
||||
module lsu_bypass (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
|
|
@ -49,8 +49,8 @@ module pcgen (
|
|||
assign fetch_address_o = npc_q;
|
||||
|
||||
btb #(
|
||||
.NR_ENTRIES(64),
|
||||
.BITS_SATURATION_COUNTER(2)
|
||||
.NR_ENTRIES ( BTB_ENTRIES ),
|
||||
.BITS_SATURATION_COUNTER ( BITS_SATURATION_COUNTER )
|
||||
)
|
||||
btb_i
|
||||
(
|
||||
|
|
|
@ -25,10 +25,8 @@ module store_queue (
|
|||
// otherwise we will run in a deadlock with the memory arbiter
|
||||
output logic no_st_pending_o, // non-speculative queue is empty (e.g.: everything is committed to the memory hierarchy)
|
||||
|
||||
output logic [63:0] paddr_o, // physical address of the valid store
|
||||
output logic [63:0] data_o, // data at the given address
|
||||
output logic valid_o, // committed data is valid
|
||||
output logic [7:0] be_o, // byte enable set
|
||||
input logic [11:0] page_offset_i,
|
||||
output logic page_offset_matches_o,
|
||||
|
||||
input logic commit_i, // commit the instruction which was placed there most recently
|
||||
output logic ready_o, // the store queue is ready to accept a new request
|
||||
|
@ -74,12 +72,6 @@ module store_queue (
|
|||
logic is_speculative; // set if the entry isn't committed yet
|
||||
} commit_queue_n, commit_queue_q;
|
||||
|
||||
// we can directly output the commit entry since we have just one element in the "queue"
|
||||
assign paddr_o = commit_queue_q.address;
|
||||
assign data_o = commit_queue_q.data;
|
||||
assign be_o = commit_queue_q.be;
|
||||
assign valid_o = commit_queue_q.valid;
|
||||
|
||||
// those signals can directly be output to the memory
|
||||
assign address_index_o = commit_queue_q.address[11:0];
|
||||
// if we got a new request we already saved the tag from the previous cycle
|
||||
|
@ -153,6 +145,34 @@ module store_queue (
|
|||
|
||||
end
|
||||
|
||||
// ------------------
|
||||
// Address Checker
|
||||
// ------------------
|
||||
// The load should return the data stored by the most recent store to the
|
||||
// same physical address. The most direct way to implement this is to
|
||||
// maintain physical addresses in the store buffer.
|
||||
|
||||
// Of course, there are other micro-architectural techniques to accomplish
|
||||
// the same thing: you can interlock and wait for the store buffer to
|
||||
// drain if the load VA matches any store VA modulo the page size (i.e.
|
||||
// bits 11:0). As a special case, it is correct to bypass if the full VA
|
||||
// matches, and no younger stores' VAs match in bits 11:0.
|
||||
//
|
||||
// checks if the requested load is in the store buffer
|
||||
// page offsets are virtually and physically the same
|
||||
always_comb begin : address_checker
|
||||
page_offset_matches_o = 1'b0;
|
||||
// check if the LSBs are identical and the entry is valid
|
||||
if ((page_offset_i[11:3] == commit_queue_q.address[11:3]) && commit_queue_q.valid) begin
|
||||
page_offset_matches_o = 1'b1;
|
||||
end
|
||||
|
||||
if ((page_offset_i[11:3] == paddr_i[11:3]) && valid_i) begin
|
||||
page_offset_matches_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
|
||||
if(~rst_ni) begin
|
||||
|
|
|
@ -59,9 +59,6 @@ module store_unit (
|
|||
|
||||
enum logic [1:0] {IDLE, VALID_STORE, WAIT_TRANSLATION, WAIT_STORE_READY} NS, CS;
|
||||
|
||||
logic [63:0] st_buffer_paddr; // physical address for store
|
||||
logic [63:0] st_data; // aligned data to store buffer
|
||||
logic st_buffer_valid;
|
||||
// store buffer control signals
|
||||
logic st_ready;
|
||||
logic st_valid;
|
||||
|
@ -199,10 +196,6 @@ module store_unit (
|
|||
.data_i ( st_data_q ),
|
||||
.be_i ( st_be_q ),
|
||||
// store buffer out
|
||||
.paddr_o ( st_buffer_paddr ),
|
||||
.data_o ( ),
|
||||
.valid_o ( st_buffer_valid ),
|
||||
.be_o ( ),
|
||||
.ready_o ( st_ready ),
|
||||
.*
|
||||
);
|
||||
|
@ -222,31 +215,5 @@ module store_unit (
|
|||
trans_id_q <= trans_id_n;
|
||||
end
|
||||
end
|
||||
// ------------------
|
||||
// Address Checker
|
||||
// ------------------
|
||||
// The load should return the data stored by the most recent store to the
|
||||
// same physical address. The most direct way to implement this is to
|
||||
// maintain physical addresses in the store buffer.
|
||||
|
||||
// Of course, there are other micro-architectural techniques to accomplish
|
||||
// the same thing: you can interlock and wait for the store buffer to
|
||||
// drain if the load VA matches any store VA modulo the page size (i.e.
|
||||
// bits 11:0). As a special case, it is correct to bypass if the full VA
|
||||
// matches, and no younger stores' VAs match in bits 11:0.
|
||||
//
|
||||
// checks if the requested load is in the store buffer
|
||||
// page offsets are virtually and physically the same
|
||||
always_comb begin : address_checker
|
||||
page_offset_matches_o = 1'b0;
|
||||
// check if the LSBs are identical and the entry is valid
|
||||
if ((lsu_ctrl_i.vaddr[11:3] == st_buffer_paddr[11:3]) && st_buffer_valid) begin
|
||||
page_offset_matches_o = 1'b1;
|
||||
end
|
||||
|
||||
if ((lsu_ctrl_i.vaddr[11:3] == paddr_i[11:3]) && (CS == VALID_STORE)) begin
|
||||
page_offset_matches_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Add table
Add a link
Reference in a new issue