make renaming mandatory

This commit is contained in:
Côme Allart 2025-04-17 15:33:09 +02:00
parent 5af65267bc
commit d125a3f7f8
20 changed files with 85 additions and 408 deletions

View file

@ -101,7 +101,6 @@ package build_config_pkg;
cfg.HaltAddress = CVA6Cfg.HaltAddress;
cfg.ExceptionAddress = CVA6Cfg.ExceptionAddress;
cfg.Renaming = CVA6Cfg.Renaming;
cfg.RASDepth = CVA6Cfg.RASDepth;
cfg.BTBEntries = CVA6Cfg.BTBEntries;
cfg.BPType = CVA6Cfg.BPType;

View file

@ -216,8 +216,6 @@ package config_pkg;
int unsigned NrLoadBufEntries;
// Maximum number of outstanding stores
int unsigned MaxOutstandingStores;
// Eliminate WAW hazards
bit Renaming;
// Return address stack depth
int unsigned RASDepth;
// Branch target buffer entries
@ -309,7 +307,6 @@ package config_pkg;
logic [63:0] HaltAddress;
logic [63:0] ExceptionAddress;
bit Renaming;
int unsigned RASDepth;
int unsigned BTBEntries;
bp_type_t BPType;

View file

@ -60,7 +60,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(0),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(1),
RASDepth: unsigned'(2),
BTBEntries: unsigned'(0),
BPType: config_pkg::BHT,

View file

@ -60,7 +60,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(0),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(1),
RASDepth: unsigned'(2),
BTBEntries: unsigned'(0),
BPType: config_pkg::BHT,

View file

@ -115,7 +115,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -113,7 +113,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -113,7 +113,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -112,7 +112,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(1),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -113,7 +113,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -116,7 +116,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -116,7 +116,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -123,7 +123,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -123,7 +123,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -116,7 +116,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -116,7 +116,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -116,7 +116,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -116,7 +116,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -118,7 +118,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: config_pkg::BHT,

View file

@ -67,7 +67,6 @@ package cva6_config_pkg;
SoftwareInterruptEn: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
Renaming: bit'(0),
RASDepth: unsigned'(2),
BTBEntries: unsigned'(0),
BPType: config_pkg::BHT,

View file

@ -136,7 +136,7 @@ module issue_read_operands
logic none, load, store, alu, alu2, ctrl_flow, mult, csr, fpu, fpu_vec, cvxif, accel;
} fus_busy_t;
logic [CVA6Cfg.NrIssuePorts-1:0] stall_raw, stall_waw, stall_rs1, stall_rs2, stall_rs3;
logic [CVA6Cfg.NrIssuePorts-1:0] stall_raw, stall_rs1, stall_rs2, stall_rs3;
logic [CVA6Cfg.NrIssuePorts-1:0] fu_busy; // functional unit is busy
fus_busy_t [CVA6Cfg.NrIssuePorts-1:0] fus_busy; // which functional units are considered busy
logic [CVA6Cfg.NrIssuePorts-1:0] issue_ack;
@ -202,20 +202,6 @@ module issue_read_operands
logic [ CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.XLEN-1:0] rs2_res;
logic [ CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.XLEN-1:0] rs3_res;
// clobber
fu_t [2**ariane_pkg::REG_ADDR_SIZE-1:0] rd_clobber_gpr, rd_clobber_fpr;
logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][CVA6Cfg.NR_SB_ENTRIES:0] gpr_clobber_vld;
logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][CVA6Cfg.NR_SB_ENTRIES:0] fpr_clobber_vld;
ariane_pkg::fu_t [ CVA6Cfg.NR_SB_ENTRIES:0] clobber_fu;
//forward logic
logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.NR_SB_ENTRIES+CVA6Cfg.NrWbPorts-1:0]
rs1_fwd_req, rs2_fwd_req, rs3_fwd_req;
logic [CVA6Cfg.NrIssuePorts-1:0] rs1_is_not_gpr0, rs2_is_not_gpr0, rs3_is_not_gpr0;
logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.NR_SB_ENTRIES+CVA6Cfg.NrWbPorts-1:0][CVA6Cfg.XLEN-1:0] rs_data;
logic [CVA6Cfg.NrIssuePorts-1:0] rs1_available, rs2_available, rs3_available;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] tinst_n, tinst_q; // transformed instruction
// forwarding signals
@ -267,7 +253,7 @@ module issue_read_operands
// TODO check only for 1st instruction ??
// Allow a cvxif transaction if we WaW condition are ok.
assign cvxif_req_allowed = (issue_instr_i[0].fu == CVXIF) && !stall_waw[0];
assign cvxif_req_allowed = (issue_instr_i[0].fu == CVXIF);
assign cvxif_instruction_valid = !issue_instr_i[0].ex.valid && issue_instr_valid_i[0] && cvxif_req_allowed;
assign x_transaction_accepted_o = x_issue_valid_o && x_issue_ready_i && x_issue_resp_i.accept;
assign x_transaction_rejected = x_issue_valid_o && x_issue_ready_i && ~x_issue_resp_i.accept;
@ -435,346 +421,96 @@ module issue_read_operands
assign rs3_fpr[i] = (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(issue_instr_i[i].op));
end
if (CVA6Cfg.Renaming) begin
assign rd_clobber_gpr = '0;
assign rd_clobber_fpr = '0;
assign gpr_clobber_vld = '0;
assign fpr_clobber_vld = '0;
assign clobber_fu = '0;
assign rs1_fwd_req = '0;
assign rs2_fwd_req = '0;
assign rs3_fwd_req = '0;
assign rs1_is_not_gpr0 = '0;
assign rs2_is_not_gpr0 = '0;
assign rs3_is_not_gpr0 = '0;
assign rs_data = '0;
assign rs1_available = '0;
assign rs2_available = '0;
assign rs3_available = '0;
// ----------------------------------
// Renaming
// ----------------------------------
for (genvar i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin
assign rd_list[i] = fwd_i.sbe[i].rd;
assign rd_fpr[i] = CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(fwd_i.sbe[i].op);
end
// ----------------------------------
// Renaming
// ----------------------------------
for (genvar i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin
assign rd_list[i] = fwd_i.sbe[i].rd;
assign rd_fpr[i] = CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(fwd_i.sbe[i].op);
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin : gen_raw_checks
raw_checker #(
.CVA6Cfg(CVA6Cfg)
) i_rs1_last_raw (
.clk_i(clk_i),
.rst_ni(rst_ni),
.rs_i(issue_instr_i[i].rs1),
.rs_fpr_i(rs1_fpr[i]),
.rd_i(rd_list),
.rd_fpr_i(rd_fpr),
.still_issued_i(fwd_i.still_issued),
.issue_pointer_i(fwd_i.issue_pointer),
.idx_o(idx_hzd_rs1[i]),
.valid_o(rs1_raw_check[i])
);
assign rs1_has_raw[i] = rs1_raw_check[i] && !issue_instr_i[i].use_zimm;
raw_checker #(
.CVA6Cfg(CVA6Cfg)
) i_rs2_last_raw (
.clk_i(clk_i),
.rst_ni(rst_ni),
.rs_i(issue_instr_i[i].rs2),
.rs_fpr_i(rs2_fpr[i]),
.rd_i(rd_list),
.rd_fpr_i(rd_fpr),
.still_issued_i(fwd_i.still_issued),
.issue_pointer_i(fwd_i.issue_pointer),
.idx_o(idx_hzd_rs2[i]),
.valid_o(rs2_raw_check[i])
);
assign rs2_has_raw[i] = rs2_raw_check[i];
raw_checker #(
.CVA6Cfg(CVA6Cfg)
) i_rs3_last_raw (
.clk_i(clk_i),
.rst_ni(rst_ni),
.rs_i(issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]),
.rs_fpr_i(rs3_fpr[i]),
.rd_i(rd_list),
.rd_fpr_i(rd_fpr),
.still_issued_i(fwd_i.still_issued),
.issue_pointer_i(fwd_i.issue_pointer),
.idx_o(idx_hzd_rs3[i]),
.valid_o(rs3_raw_check[i])
);
assign rs3_has_raw[i] = rs3_raw_check[i] && rs3_fpr[i];
end
// ----------------------------------
// Read Operands (a.k.a forwarding)
// ----------------------------------
always_comb begin
for (int unsigned i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin
fwd_res[i] = fwd_i.sbe[i].result;
fwd_res_valid[i] = fwd_i.sbe[i].valid;
end
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin : gen_raw_checks
raw_checker #(
.CVA6Cfg(CVA6Cfg)
) i_rs1_last_raw (
.clk_i(clk_i),
.rst_ni(rst_ni),
.rs_i(issue_instr_i[i].rs1),
.rs_fpr_i(rs1_fpr[i]),
.rd_i(rd_list),
.rd_fpr_i(rd_fpr),
.still_issued_i(fwd_i.still_issued),
.issue_pointer_i(fwd_i.issue_pointer),
.idx_o(idx_hzd_rs1[i]),
.valid_o(rs1_raw_check[i])
);
assign rs1_has_raw[i] = rs1_raw_check[i] && !issue_instr_i[i].use_zimm;
raw_checker #(
.CVA6Cfg(CVA6Cfg)
) i_rs2_last_raw (
.clk_i(clk_i),
.rst_ni(rst_ni),
.rs_i(issue_instr_i[i].rs2),
.rs_fpr_i(rs2_fpr[i]),
.rd_i(rd_list),
.rd_fpr_i(rd_fpr),
.still_issued_i(fwd_i.still_issued),
.issue_pointer_i(fwd_i.issue_pointer),
.idx_o(idx_hzd_rs2[i]),
.valid_o(rs2_raw_check[i])
);
assign rs2_has_raw[i] = rs2_raw_check[i];
raw_checker #(
.CVA6Cfg(CVA6Cfg)
) i_rs3_last_raw (
.clk_i(clk_i),
.rst_ni(rst_ni),
.rs_i(issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]),
.rs_fpr_i(rs3_fpr[i]),
.rd_i(rd_list),
.rd_fpr_i(rd_fpr),
.still_issued_i(fwd_i.still_issued),
.issue_pointer_i(fwd_i.issue_pointer),
.idx_o(idx_hzd_rs3[i]),
.valid_o(rs3_raw_check[i])
);
assign rs3_has_raw[i] = rs3_raw_check[i] && rs3_fpr[i];
end
// ----------------------------------
// Read Operands (a.k.a forwarding)
// ----------------------------------
always_comb begin
for (int unsigned i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin
fwd_res[i] = fwd_i.sbe[i].result;
fwd_res_valid[i] = fwd_i.sbe[i].valid;
end
for (int unsigned i = 0; i < CVA6Cfg.NrWbPorts; i++) begin
if (fwd_i.wb[i].valid && !fwd_i.wb[i].ex_valid) begin
fwd_res[fwd_i.wb[i].trans_id] = fwd_i.wb[i].data;
fwd_res_valid[fwd_i.wb[i].trans_id] = 1'b1;
end
for (int unsigned i = 0; i < CVA6Cfg.NrWbPorts; i++) begin
if (fwd_i.wb[i].valid && !fwd_i.wb[i].ex_valid) begin
fwd_res[fwd_i.wb[i].trans_id] = fwd_i.wb[i].data;
fwd_res_valid[fwd_i.wb[i].trans_id] = 1'b1;
end
end
end
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
assign rs1_res[i] = fwd_res[idx_hzd_rs1[i]];
assign rs1_is_not_csr[i] = rs1_fpr[i] || (fwd_i.sbe[idx_hzd_rs1[i]].fu != ariane_pkg::CSR) || (CVA6Cfg.RVS && issue_instr_i[i].op == ariane_pkg::SFENCE_VMA);
assign rs1_valid[i] = fwd_res_valid[idx_hzd_rs1[i]] && rs1_is_not_csr[i];
assign rs1_res[i] = fwd_res[idx_hzd_rs1[i]];
assign rs1_is_not_csr[i] = rs1_fpr[i] || (fwd_i.sbe[idx_hzd_rs1[i]].fu != ariane_pkg::CSR) || (CVA6Cfg.RVS && issue_instr_i[i].op == ariane_pkg::SFENCE_VMA);
assign rs1_valid[i] = fwd_res_valid[idx_hzd_rs1[i]] && rs1_is_not_csr[i];
assign rs2_res[i] = fwd_res[idx_hzd_rs2[i]];
assign rs2_is_not_csr[i] = rs2_fpr[i] || (fwd_i.sbe[idx_hzd_rs2[i]].fu != ariane_pkg::CSR) || (CVA6Cfg.RVS && issue_instr_i[i].op == ariane_pkg::SFENCE_VMA);
assign rs2_valid[i] = fwd_res_valid[idx_hzd_rs2[i]] && rs2_is_not_csr[i];
assign rs2_res[i] = fwd_res[idx_hzd_rs2[i]];
assign rs2_is_not_csr[i] = rs2_fpr[i] || (fwd_i.sbe[idx_hzd_rs2[i]].fu != ariane_pkg::CSR) || (CVA6Cfg.RVS && issue_instr_i[i].op == ariane_pkg::SFENCE_VMA);
assign rs2_valid[i] = fwd_res_valid[idx_hzd_rs2[i]] && rs2_is_not_csr[i];
assign rs3[i] = fwd_res[idx_hzd_rs3[i]];
assign rs3_valid[i] = fwd_res_valid[idx_hzd_rs3[i]];
assign rs3[i] = fwd_res[idx_hzd_rs3[i]];
assign rs3_valid[i] = fwd_res_valid[idx_hzd_rs3[i]];
if (CVA6Cfg.NrRgprPorts == 3) begin
assign rs3_res[i] = rs3[i][CVA6Cfg.XLEN-1:0];
end else begin
assign rs3_res[i] = rs3[i][CVA6Cfg.FLen-1:0];
end
end
end else begin
assign idx_hzd_rs1 = '0;
assign idx_hzd_rs2 = '0;
assign idx_hzd_rs3 = '0;
assign rd_list = '0;
assign rd_fpr = '0;
assign fwd_res = '0;
assign fwd_res_valid = '0;
assign rs1_is_not_csr = '0;
assign rs2_is_not_csr = '0;
// -------------------
// RD clobber process
// -------------------
// rd_clobber output: output currently clobbered destination registers
always_comb begin : clobber_assign
gpr_clobber_vld = '0;
fpr_clobber_vld = '0;
// default (highest entry hast lowest prio in arbiter tree below)
clobber_fu[CVA6Cfg.NR_SB_ENTRIES] = ariane_pkg::NONE;
for (int unsigned i = 0; i < 2 ** ariane_pkg::REG_ADDR_SIZE; i++) begin
gpr_clobber_vld[i][CVA6Cfg.NR_SB_ENTRIES] = 1'b1;
fpr_clobber_vld[i][CVA6Cfg.NR_SB_ENTRIES] = 1'b1;
end
// check for all valid entries and set the clobber accordingly
for (int unsigned i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin
gpr_clobber_vld[fwd_i.sbe[i].rd][i] = fwd_i.still_issued[i] & ~(CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
fwd_i.sbe[i].op));
fpr_clobber_vld[fwd_i.sbe[i].rd][i] = fwd_i.still_issued[i] & (CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
fwd_i.sbe[i].op));
clobber_fu[i] = fwd_i.sbe[i].fu;
end
// GPR[0] is always free
gpr_clobber_vld[0] = '0;
end
for (genvar k = 0; k < 2 ** ariane_pkg::REG_ADDR_SIZE; k++) begin : gen_sel_clobbers
// get fu that is going to clobber this register (there should be only one)
rr_arb_tree #(
.NumIn(CVA6Cfg.NR_SB_ENTRIES + 1),
.DataType(ariane_pkg::fu_t),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
) i_sel_gpr_clobbers (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i(1'b0),
.rr_i ('0),
.req_i (gpr_clobber_vld[k]),
.gnt_o (),
.data_i (clobber_fu),
.gnt_i (1'b1),
.req_o (),
.data_o (rd_clobber_gpr[k]),
.idx_o ()
);
if (CVA6Cfg.FpPresent) begin
rr_arb_tree #(
.NumIn(CVA6Cfg.NR_SB_ENTRIES + 1),
.DataType(ariane_pkg::fu_t),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
) i_sel_fpr_clobbers (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i(1'b0),
.rr_i ('0),
.req_i (fpr_clobber_vld[k]),
.gnt_o (),
.data_i (clobber_fu),
.gnt_i (1'b1),
.req_o (),
.data_o (rd_clobber_fpr[k]),
.idx_o ()
);
end else begin
assign rd_clobber_fpr[k] = NONE;
end
end
// ----------------------------------
// Read Operands (a.k.a forwarding)
// ----------------------------------
// read operand interface: same logic as register file
// WB ports have higher prio than entries
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
for (genvar k = 0; unsigned'(k) < CVA6Cfg.NrWbPorts; k++) begin : gen_rs_wb
assign rs1_fwd_req[i][k] = (fwd_i.sbe[fwd_i.wb[k].trans_id].rd == issue_instr_i[i].rs1) & (fwd_i.still_issued[fwd_i.wb[k].trans_id]) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid) & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
fwd_i.sbe[fwd_i.wb[k].trans_id].op
)) == (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr(
issue_instr_i[i].op
)));
assign rs2_fwd_req[i][k] = (fwd_i.sbe[fwd_i.wb[k].trans_id].rd == issue_instr_i[i].rs2) & (fwd_i.still_issued[fwd_i.wb[k].trans_id]) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid) & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
fwd_i.sbe[fwd_i.wb[k].trans_id].op
)) == (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr(
issue_instr_i[i].op
)));
assign rs3_fwd_req[i][k] = (fwd_i.sbe[fwd_i.wb[k].trans_id].rd == issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]) & (fwd_i.still_issued[fwd_i.wb[k].trans_id]) & fwd_i.wb[k].valid & (~fwd_i.wb[k].ex_valid) & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
fwd_i.sbe[fwd_i.wb[k].trans_id].op
)) == (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(
issue_instr_i[i].op
)));
assign rs_data[i][k] = fwd_i.wb[k].data;
end
for (genvar k = 0; unsigned'(k) < CVA6Cfg.NR_SB_ENTRIES; k++) begin : gen_rs_entries
assign rs1_fwd_req[i][k+CVA6Cfg.NrWbPorts] = (fwd_i.sbe[k].rd == issue_instr_i[i].rs1) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
fwd_i.sbe[k].op
)) == (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr(
issue_instr_i[i].op
)));
assign rs2_fwd_req[i][k+CVA6Cfg.NrWbPorts] = (fwd_i.sbe[k].rd == issue_instr_i[i].rs2) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
fwd_i.sbe[k].op
)) == (CVA6Cfg.FpPresent && ariane_pkg::is_rs2_fpr(
issue_instr_i[i].op
)));
assign rs3_fwd_req[i][k+CVA6Cfg.NrWbPorts] = (fwd_i.sbe[k].rd == issue_instr_i[i].result[ariane_pkg::REG_ADDR_SIZE-1:0]) & fwd_i.still_issued[k] & fwd_i.sbe[k].valid & ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
fwd_i.sbe[k].op
)) == (CVA6Cfg.FpPresent && ariane_pkg::is_imm_fpr(
issue_instr_i[i].op
)));
assign rs_data[i][k+CVA6Cfg.NrWbPorts] = fwd_i.sbe[k].result;
end
// use fixed prio here
// this implicitly gives higher prio to WB ports
rr_arb_tree #(
.NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.DataWidth(CVA6Cfg.XLEN),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
) i_sel_rs1 (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i(1'b0),
.rr_i ('0),
.req_i (rs1_fwd_req[i]),
.gnt_o (),
.data_i (rs_data[i]),
.gnt_i (1'b1),
.req_o (rs1_available[i]),
.data_o (rs1_res[i]),
.idx_o ()
);
rr_arb_tree #(
.NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.DataWidth(CVA6Cfg.XLEN),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
) i_sel_rs2 (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i(1'b0),
.rr_i ('0),
.req_i (rs2_fwd_req[i]),
.gnt_o (),
.data_i (rs_data[i]),
.gnt_i (1'b1),
.req_o (rs2_available[i]),
.data_o (rs2_res[i]),
.idx_o ()
);
rr_arb_tree #(
.NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.DataWidth(CVA6Cfg.XLEN),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
) i_sel_rs3 (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i(1'b0),
.rr_i ('0),
.req_i (rs3_fwd_req[i]),
.gnt_o (),
.data_i (rs_data[i]),
.gnt_i (1'b1),
.req_o (rs3_available[i]),
.data_o (rs3[i]),
.idx_o ()
);
if (CVA6Cfg.NrRgprPorts == 3) begin : gen_gp_three_port
assign rs3_res[i] = rs3[i][riscv::XLEN-1:0];
end else begin : gen_fp_three_port
assign rs3_res[i] = rs3[i][CVA6Cfg.FLen-1:0];
end
assign rs1_has_raw[i] = !issue_instr_i[i].use_zimm && ((CVA6Cfg.FpPresent && is_rs1_fpr(
issue_instr_i[i].op
)) ? rd_clobber_fpr[issue_instr_i[i].rs1] != NONE :
rd_clobber_gpr[issue_instr_i[i].rs1] != NONE);
assign rs1_valid[i] = rs1_available[i] && (CVA6Cfg.FpPresent && is_rs1_fpr(
issue_instr_i[i].op
) ? 1'b1 : ((rd_clobber_gpr[issue_instr_i[i].rs1] != CSR) ||
(CVA6Cfg.RVS && issue_instr_i[i].op == SFENCE_VMA)));
assign rs2_has_raw[i] = ((CVA6Cfg.FpPresent && is_rs2_fpr(
issue_instr_i[i].op
)) ? rd_clobber_fpr[issue_instr_i[i].rs2] != NONE :
rd_clobber_gpr[issue_instr_i[i].rs2] != NONE);
assign rs2_valid[i] = rs2_available[i] && (CVA6Cfg.FpPresent && is_rs2_fpr(
issue_instr_i[i].op
) ? 1'b1 : ((rd_clobber_gpr[issue_instr_i[i].rs2] != CSR) ||
(CVA6Cfg.RVS && issue_instr_i[i].op == SFENCE_VMA)));
assign rs3_has_raw[i] = ((CVA6Cfg.FpPresent && is_imm_fpr(
issue_instr_i[i].op
)) ? rd_clobber_fpr[issue_instr_i[i].result[REG_ADDR_SIZE-1:0]] != NONE : 0);
assign rs3_valid[i] = rs3_available[i];
if (CVA6Cfg.NrRgprPorts == 3) begin
assign rs3_res[i] = rs3[i][CVA6Cfg.XLEN-1:0];
end else begin
assign rs3_res[i] = rs3[i][CVA6Cfg.FLen-1:0];
end
end
@ -1050,44 +786,6 @@ module issue_read_operands
end
end
if (CVA6Cfg.Renaming) begin
assign stall_waw = '0;
end else begin
always_comb begin : gen_check_waw_dependencies
stall_waw = '1;
for (int unsigned i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
if (issue_instr_valid_i[i] && !fu_busy[i]) begin
// -----------------------------------------
// WAW - Write After Write Dependency Check
// -----------------------------------------
// no other instruction has the same destination register -> issue the instruction
if ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
issue_instr_i[i].op
)) ? (rd_clobber_fpr[issue_instr_i[i].rd] == NONE) :
(rd_clobber_gpr[issue_instr_i[i].rd] == NONE)) begin
stall_waw[i] = 1'b0;
end
// or check that the target destination register will be written in this cycle by the
// commit stage
for (int unsigned c = 0; c < CVA6Cfg.NrCommitPorts; c++) begin
if ((CVA6Cfg.FpPresent && ariane_pkg::is_rd_fpr(
issue_instr_i[i].op
)) ? (we_fpr_i[c] && waddr_i[c] == issue_instr_i[i].rd) :
(we_gpr_i[c] && waddr_i[c] == issue_instr_i[i].rd)) begin
stall_waw[i] = 1'b0;
end
end
if (i > 0) begin
if ((issue_instr_i[i].rd == issue_instr_i[i-1].rd) && (issue_instr_i[i].rd != '0)) begin
stall_waw[i] = 1'b1;
end
end
end
end
end
end
// We can issue an instruction if we do not detect that any other instruction is writing the same
// destination register.
// We also need to check if there is an unresolved branch in the scoreboard.
@ -1098,7 +796,7 @@ module issue_read_operands
// check that the instruction we got is valid
// and that the functional unit we need is not busy
if (issue_instr_valid_i[i] && !fu_busy[i]) begin
if (!stall_raw[i] && !stall_waw[i]) begin
if (!stall_raw[i]) begin
issue_ack[i] = 1'b1;
end
if (issue_instr_i[i].ex.valid) begin