Add commit full signal to store buffer

This commit is contained in:
Florian Zaruba 2017-08-02 11:38:37 +02:00
parent d330ed32a6
commit a2726cfcae
6 changed files with 43 additions and 20 deletions

View file

@ -186,6 +186,7 @@ module ariane
logic csr_commit_commit_ex;
// LSU Commit
logic lsu_commit_commit_ex;
logic lsu_commit_ready_ex_commit;
logic no_st_pending_ex_commit;
// --------------
// ID <-> COMMIT
@ -430,6 +431,7 @@ module ariane
.lsu_trans_id_o ( lsu_trans_id_ex_id ),
.lsu_valid_o ( lsu_valid_ex_id ),
.lsu_commit_i ( lsu_commit_commit_ex ), // from commit
.lsu_commit_ready_o ( lsu_commit_ready_ex_commit ), // to commit
.lsu_exception_o ( lsu_exception_ex_id ),
.no_st_pending_o ( no_st_pending_ex_commit ),
@ -479,6 +481,7 @@ module ariane
.wdata_a_o ( wdata_a_commit_id ),
.we_a_o ( we_a_commit_id ),
.commit_lsu_o ( lsu_commit_commit_ex ),
.commit_lsu_ready_i ( lsu_commit_ready_ex_commit ),
.commit_csr_o ( csr_commit_commit_ex ),
.pc_o ( pc_commit ),
.csr_op_o ( csr_op_commit_csr ),

View file

@ -41,6 +41,7 @@ module commit_stage (
input exception csr_exception_i,
// commit signals to ex
output logic commit_lsu_o, // commit the pending store
input logic commit_lsu_ready_i,
input logic no_st_pending_i, // there is no store pending
output logic commit_csr_o, // commit the pending CSR instruction
output logic fence_i_o, // flush icache and pipeline
@ -69,6 +70,8 @@ module commit_stage (
// we will not commit the instruction if we took an exception
// but we do not commit the instruction if we requested a halt
if (commit_instr_i.valid && !halt_i) begin
commit_ack_o = 1'b1;
// register will be the all zero register.
// and also acknowledge the instruction, this is mainly done for the instruction tracer
// as it will listen on the instruction ack signal. For the overall result it does not make any
@ -82,11 +85,13 @@ module commit_stage (
// do not commit the instruction if we got an exception since the store buffer will be cleared
// by the subsequent flush triggered by an exception
if (commit_instr_i.fu == STORE) begin
commit_lsu_o = 1'b1;
if (commit_lsu_ready_i)
commit_lsu_o = 1'b1;
else // if the LSU buffer is not ready - do not commit, wait
commit_ack_o = 1'b0;
end
end
commit_ack_o = 1'b1;
// ---------
// CSR Logic
// ---------

View file

@ -60,6 +60,7 @@ module ex_stage #(
output logic [63:0] lsu_result_o,
output logic [TRANS_ID_BITS-1:0] lsu_trans_id_o,
input logic lsu_commit_i,
output logic lsu_commit_ready_o, // commit queue is ready to accept another commit request
output exception lsu_exception_o,
output logic no_st_pending_o,
// CSR
@ -144,7 +145,8 @@ module ex_stage #(
// Load-Store Unit
// ----------------
lsu lsu_i (
.commit_i ( lsu_commit_i ),
.commit_i ( lsu_commit_i ),
.commit_ready_o ( lsu_commit_ready_o ),
.*
);

View file

@ -38,6 +38,7 @@ module lsu #(
output logic [63:0] lsu_result_o,
output logic lsu_valid_o, // transaction id for which the output is the requested one
input logic commit_i, // commit the pending store
output logic commit_ready_o, // commit queue is ready to accept another commit request
input logic enable_translation_i, // enable virtual memory translation
input logic en_ld_st_translation_i, // enable virtual memory translation for load/stores

View file

@ -29,6 +29,7 @@ module store_buffer (
output logic page_offset_matches_o,
input logic commit_i, // commit the instruction which was placed there most recently
output logic commit_ready_o, // commit queue is ready to accept another commit request
output logic ready_o, // the store queue is ready to accept a new request
// it is only ready if it can unconditionally commit the instruction, e.g.:
// the commit buffer needs to be empty
@ -49,8 +50,10 @@ module store_buffer (
input logic data_gnt_i,
input logic data_rvalid_i
);
// depth of store-buffer
localparam int unsigned DEPTH = 4;
// depth of store-buffers
localparam int unsigned DEPTH_SPEC = 4;
// allocate more space for the commit buffer to be on the save side
localparam int unsigned DEPTH_COMMIT = 4;
// we need to keep the tag portion of the address for a cycle later
logic [43:0] address_tag_n, address_tag_q;
@ -65,27 +68,27 @@ module store_buffer (
logic [63:0] data;
logic [7:0] be;
logic valid; // this entry is valid, we need this for checking if the address offset matches
} speculative_queue_n [DEPTH-1:0], speculative_queue_q [DEPTH-1:0],
commit_queue_n [DEPTH-1:0], commit_queue_q [DEPTH-1:0];
} speculative_queue_n [DEPTH_SPEC-1:0], speculative_queue_q [DEPTH_SPEC-1:0],
commit_queue_n [DEPTH_COMMIT-1:0], commit_queue_q [DEPTH_COMMIT-1:0];
// keep a status count for both buffers
logic [$clog2(DEPTH):0] speculative_status_cnt_n, speculative_status_cnt_q;
logic [$clog2(DEPTH):0] commit_status_cnt_n, commit_status_cnt_q;
logic [$clog2(DEPTH_SPEC):0] speculative_status_cnt_n, speculative_status_cnt_q;
logic [$clog2(DEPTH_COMMIT):0] commit_status_cnt_n, commit_status_cnt_q;
// Speculative queue
logic [$clog2(DEPTH)-1:0] speculative_read_pointer_n, speculative_read_pointer_q;
logic [$clog2(DEPTH)-1:0] speculative_write_pointer_n, speculative_write_pointer_q;
logic [$clog2(DEPTH_SPEC)-1:0] speculative_read_pointer_n, speculative_read_pointer_q;
logic [$clog2(DEPTH_SPEC)-1:0] speculative_write_pointer_n, speculative_write_pointer_q;
// Commit Queue
logic [$clog2(DEPTH)-1:0] commit_read_pointer_n, commit_read_pointer_q;
logic [$clog2(DEPTH)-1:0] commit_write_pointer_n, commit_write_pointer_q;
logic [$clog2(DEPTH_COMMIT)-1:0] commit_read_pointer_n, commit_read_pointer_q;
logic [$clog2(DEPTH_COMMIT)-1:0] commit_write_pointer_n, commit_write_pointer_q;
// ----------------------------------------
// Speculative Queue - Core Interface
// ----------------------------------------
always_comb begin : core_if
automatic logic [DEPTH:0] speculative_status_cnt = speculative_status_cnt_q;
automatic logic [DEPTH_SPEC:0] speculative_status_cnt = speculative_status_cnt_q;
// we are ready if the speculative and the commit queue have a space left
ready_o = (speculative_status_cnt_q < DEPTH) && (commit_status_cnt_q < DEPTH);
ready_o = speculative_status_cnt_q < (DEPTH_SPEC - 1);
// default assignments
speculative_status_cnt_n = speculative_status_cnt_q;
speculative_read_pointer_n = speculative_read_pointer_q;
@ -93,7 +96,7 @@ module store_buffer (
speculative_queue_n = speculative_queue_q;
// LSU interface
// we are ready to accept a new entry and the input data is valid
if (ready_o && valid_i) begin
if (valid_i) begin
speculative_queue_n[speculative_write_pointer_q].address = paddr_i;
speculative_queue_n[speculative_write_pointer_q].data = data_i;
speculative_queue_n[speculative_write_pointer_q].be = be_i;
@ -116,9 +119,9 @@ module store_buffer (
speculative_status_cnt_n = speculative_status_cnt;
// when we flush evict the speculative stores
if (flush_i) begin
if (ready_o && flush_i) begin
// reset all valid flags
for (int unsigned i = 0; i < DEPTH; i++)
for (int unsigned i = 0; i < DEPTH_SPEC; i++)
speculative_queue_n[i].valid = 1'b0;
speculative_write_pointer_n = speculative_read_pointer_q;
@ -141,7 +144,8 @@ module store_buffer (
assign data_we_o = 1'b1; // we will always write in the store queue
always_comb begin : store_if
automatic logic [DEPTH:0] commit_status_cnt = commit_status_cnt_q;
automatic logic [DEPTH_COMMIT:0] commit_status_cnt = commit_status_cnt_q;
commit_ready_o = (commit_status_cnt_q < DEPTH_COMMIT);
// no store is pending if we don't have any element in the commit queue e.g.: it is empty
no_st_pending_o = (commit_status_cnt_q == 0);
// default assignments
@ -201,12 +205,14 @@ module store_buffer (
always_comb begin : address_checker
page_offset_matches_o = 1'b0;
// check if the LSBs are identical and the entry is valid
for (int unsigned i = 0; i < DEPTH; i++) begin
for (int unsigned i = 0; i < DEPTH_COMMIT; i++) begin
// Check if the page offset matches and whether the entry is valid, for the commit queue
if ((page_offset_i[11:3] == commit_queue_q[i].address[11:3]) && commit_queue_q[i].valid) begin
page_offset_matches_o = 1'b1;
break;
end
end
for (int unsigned i = 0; i < DEPTH_SPEC; i++) begin
// do the same for the speculative queue
if ((page_offset_i[11:3] == speculative_queue_q[i].address[11:3]) && speculative_queue_q[i].valid) begin
page_offset_matches_o = 1'b1;
@ -255,6 +261,10 @@ module store_buffer (
assert property (
@(posedge clk_i) rst_ni && flush_i |-> !commit_i)
else $error ("You are trying to commit and flush in the same cycle");
assert property (
@(posedge clk_i) rst_ni && !ready_o |-> !valid_i)
else $error ("You are trying to push new data although the buffer is not ready");
`endif
`endif
endmodule

View file

@ -28,6 +28,8 @@ module store_unit (
input lsu_ctrl_t lsu_ctrl_i,
output logic pop_st_o,
input logic commit_i,
output logic commit_ready_o,
// store unit output port
output logic valid_o,
output logic [TRANS_ID_BITS-1:0] trans_id_o,