Skip to content
Snippets Groups Projects
Commit 6d25bf40 authored by Alban Gruin's avatar Alban Gruin
Browse files

scoreboard: accept instructions even if they will not be issued next cycle


Signed-off-by: default avatarAlban Gruin <alban.gruin@irit.fr>
parent 04a4e12b
No related branches found
No related tags found
No related merge requests found
......@@ -70,6 +70,7 @@ module scoreboard #(
// this is the FIFO struct of the issue queue
struct packed {
logic pending; // this bit indicates whether the instruction has still not reached EX
logic issued; // this bit indicates whether we issued this instruction e.g.: if it is valid
logic is_rd_fpr_flag; // redundant meta info, added for speed
ariane_pkg::scoreboard_entry_t sbe; // this is the score board entry we will send to ex
......@@ -77,10 +78,14 @@ module scoreboard #(
logic issue_full, issue_en;
logic [BITS_ENTRIES-1:0] issue_cnt_n, issue_cnt_q;
logic [BITS_ENTRIES-1:0] write_pointer_n, write_pointer_q;
logic [BITS_ENTRIES-1:0] issue_pointer_n, issue_pointer_q;
logic [NR_COMMIT_PORTS-1:0][BITS_ENTRIES-1:0] commit_pointer_n, commit_pointer_q;
logic [$clog2(NR_COMMIT_PORTS):0] num_commit;
logic [NR_ENTRIES-1:0] flushed;
logic [$clog2(NR_ENTRIES)-1:0] num_flush;
logic [NR_ENTRIES-1:0] has_mem_access_n, has_mem_access_q;
logic [NR_ENTRIES-1:0] is_cf_n, is_cf_q;
......@@ -102,17 +107,6 @@ module scoreboard #(
assign has_mem_access_o = (|has_mem_access_q);
assign has_control_flow_o = (|is_cf_q);
// an instruction is ready for issue if we have place in the issue FIFO and it the decoder says it is valid
always_comb begin
issue_instr_o = decoded_instr_i;
// make sure we assign the correct trans ID
issue_instr_o.trans_id = issue_pointer_q;
// we are ready if we are not full and don't have any unresolved branches, but it can be
// the case that we have an unresolved branch which is cleared in that cycle (resolved_branch_i == 1)
issue_instr_valid_o = decoded_instr_valid_i & ~unresolved_branch_i & ~issue_full;
decoded_instr_ack_o = issue_ack_i & ~issue_full;
end
// maintain a FIFO with issued instructions
// keep track of all issued instructions
always_comb begin : issue_fifo
......@@ -121,18 +115,44 @@ module scoreboard #(
issue_en = 1'b0;
has_mem_access_n = has_mem_access_q;
is_cf_n = is_cf_q;
decoded_instr_ack_o = 1'b0;
flushed = '0;
decoded_instr_ack_o = decoded_instr_valid_i && ~issue_full;
// if we got a acknowledge from the issue stage, put this scoreboard entry in the queue
if (decoded_instr_valid_i && decoded_instr_ack_o && !flush_unissued_instr_i) begin
if (decoded_instr_valid_i && ~issue_full && !flush_unissued_instr_i) begin
// the decoded instruction we put in there is valid (1st bit)
// increase the issue counter and advance issue pointer
issue_en = 1'b1;
mem_n[issue_pointer_q] = {1'b1, // valid bit
// decoded_instr_ack_o = 1'b1;
mem_n[write_pointer_q] = {1'b1,
1'b1, // valid bit
ariane_pkg::is_rd_fpr(decoded_instr_i.op), // whether rd goes to the fpr
decoded_instr_i // decoded instruction record
};
has_mem_access_n[issue_pointer_q] = decoded_instr_i.fu inside {ariane_pkg::LOAD, ariane_pkg::STORE};
is_cf_n[issue_pointer_q] = decoded_instr_i.fu == ariane_pkg::CTRL_FLOW && decoded_instr_i.op != ariane_pkg::ADD;
has_mem_access_n[write_pointer_q] = decoded_instr_i.fu inside {ariane_pkg::LOAD, ariane_pkg::STORE};
is_cf_n[write_pointer_q] = decoded_instr_i.fu == ariane_pkg::CTRL_FLOW && decoded_instr_i.op != ariane_pkg::ADD;
end
issue_instr_o = mem_n[issue_pointer_q];
issue_instr_o.trans_id = issue_pointer_q;
issue_instr_valid_o = mem_n[issue_pointer_q].pending & !flush_unissued_instr_i;
if (issue_ack_i) begin
mem_n[issue_pointer_q].pending = 1'b0;
end
if (flush_unissued_instr_i) begin
for (int unsigned i = 0; i < NR_ENTRIES; i++) begin
if (mem_q[i].pending) begin
mem_n[i].pending = 1'b0;
mem_n[i].issued = 1'b0;
flushed[i] = 1'b1;
has_mem_access_n[i] = 1'b0;
is_cf_n[i] = 1'b0;
end
end
end
// ------------
......@@ -140,7 +160,7 @@ module scoreboard #(
// ------------
for (int unsigned i = 0; i < NR_ENTRIES; i++) begin
// The FU is NONE -> this instruction is valid immediately
if (mem_q[i].sbe.fu == ariane_pkg::NONE && mem_q[i].issued)
if (mem_q[i].sbe.fu == ariane_pkg::NONE && mem_q[i].issued && ~mem_q[i].pending)
mem_n[i].sbe.valid = 1'b1;
end
......@@ -150,7 +170,7 @@ module scoreboard #(
for (int unsigned i = 0; i < NR_WB_PORTS; i++) begin
// check if this instruction was issued (e.g.: it could happen after a flush that there is still
// something in the pipeline e.g. an incomplete memory operation)
if (wt_valid_i[i] && mem_q[trans_id_i[i]].issued) begin
if (wt_valid_i[i] && mem_q[trans_id_i[i]].issued && ~mem_q[trans_id_i[i]].pending) begin
mem_n[trans_id_i[i]].sbe.valid = 1'b1;
mem_n[trans_id_i[i]].sbe.result = wbdata_i[i];
// save the target address of a branch (needed for debug in commit stage)
......@@ -176,6 +196,7 @@ module scoreboard #(
for (logic [BITS_ENTRIES-1:0] i = 0; i < NR_COMMIT_PORTS; i++) begin
if (commit_ack_i[i]) begin
// this instruction is no longer in issue e.g.: it is considered finished
mem_n[commit_pointer_q[i]].pending = 1'b0;
mem_n[commit_pointer_q[i]].issued = 1'b0;
mem_n[commit_pointer_q[i]].sbe.valid = 1'b0;
has_mem_access_n[commit_pointer_q[i]] = 1'b0;
......@@ -189,6 +210,7 @@ module scoreboard #(
if (flush_i) begin
for (int unsigned i = 0; i < NR_ENTRIES; i++) begin
// set all valid flags for all entries to zero
mem_n[i].pending = 1'b0;
mem_n[i].issued = 1'b0;
mem_n[i].sbe.valid = 1'b0;
mem_n[i].sbe.ex.valid = 1'b0;
......@@ -199,16 +221,24 @@ module scoreboard #(
end
// FIFO counter updates
popcount #(
.INPUT_WIDTH(NR_ENTRIES)
) i_popcount_flush (
.data_i(flushed),
.popcount_o(num_flush)
);
popcount #(
.INPUT_WIDTH(NR_COMMIT_PORTS)
) i_popcount (
) i_popcount_commit (
.data_i(commit_ack_i),
.popcount_o(num_commit)
);
assign issue_cnt_n = (flush_i) ? '0 : issue_cnt_q - num_commit + issue_en;
assign issue_cnt_n = (flush_i) ? '0 : issue_cnt_q - num_commit - num_flush + issue_en;
assign commit_pointer_n[0] = (flush_i) ? '0 : commit_pointer_q[0] + num_commit;
assign issue_pointer_n = (flush_i) ? '0 : issue_pointer_q + issue_en;
assign issue_pointer_n = (flush_i) ? '0 : issue_pointer_q + issue_ack_i;
assign write_pointer_n = (flush_i) ? '0 : write_pointer_q - num_flush + issue_en;
// precompute offsets for commit slots
for (genvar k=1; k < NR_COMMIT_PORTS; k++) begin : gen_cnt_incr
......@@ -236,8 +266,8 @@ module scoreboard #(
// check for all valid entries and set the clobber accordingly
for (int unsigned i = 0; i < NR_ENTRIES; i++) begin
gpr_clobber_vld[mem_q[i].sbe.rd][i] = mem_q[i].issued & ~mem_q[i].is_rd_fpr_flag;
fpr_clobber_vld[mem_q[i].sbe.rd][i] = mem_q[i].issued & mem_q[i].is_rd_fpr_flag;
gpr_clobber_vld[mem_q[i].sbe.rd][i] = ~mem_q[i].pending & mem_q[i].issued & ~mem_q[i].is_rd_fpr_flag;
fpr_clobber_vld[mem_q[i].sbe.rd][i] = ~mem_q[i].pending & mem_q[i].issued & mem_q[i].is_rd_fpr_flag;
clobber_fu[i] = mem_q[i].sbe.fu;
end
......@@ -301,9 +331,9 @@ module scoreboard #(
assign rs_data[k] = wbdata_i[k];
end
for (genvar k = 0; unsigned'(k) < NR_ENTRIES; k++) begin : gen_rs_entries
assign rs1_fwd_req[k+NR_WB_PORTS] = (mem_q[k].sbe.rd == rs1_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_rs1_fpr(issue_instr_o.op));
assign rs2_fwd_req[k+NR_WB_PORTS] = (mem_q[k].sbe.rd == rs2_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_rs2_fpr(issue_instr_o.op));
assign rs3_fwd_req[k+NR_WB_PORTS] = (mem_q[k].sbe.rd == rs3_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_imm_fpr(issue_instr_o.op));
assign rs1_fwd_req[k+NR_WB_PORTS] = (mem_q[k].sbe.rd == rs1_i) & ~mem_q[k].pending & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_rs1_fpr(issue_instr_o.op));
assign rs2_fwd_req[k+NR_WB_PORTS] = (mem_q[k].sbe.rd == rs2_i) & ~mem_q[k].pending & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_rs2_fpr(issue_instr_o.op));
assign rs3_fwd_req[k+NR_WB_PORTS] = (mem_q[k].sbe.rd == rs3_i) & ~mem_q[k].pending & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == ariane_pkg::is_imm_fpr(issue_instr_o.op));
assign rs_data[k+NR_WB_PORTS] = mem_q[k].sbe.result;
end
......@@ -381,11 +411,13 @@ module scoreboard #(
issue_cnt_q <= '0;
commit_pointer_q <= '0;
issue_pointer_q <= '0;
write_pointer_q <= '0;
has_mem_access_q <= '0;
is_cf_q <= '0;
end else begin
issue_cnt_q <= issue_cnt_n;
issue_pointer_q <= issue_pointer_n;
write_pointer_q <= write_pointer_n;
mem_q <= mem_n;
commit_pointer_q <= commit_pointer_n;
has_mem_access_q <= has_mem_access_n;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment