verilator: Fix simulation issue in fu selection

This commit is contained in:
Florian Zaruba 2019-04-20 23:35:59 +02:00
parent 4e9360079e
commit 6e4a0742ef

View file

@ -80,14 +80,14 @@ module issue_read_operands #(
operand_b_n, operand_b_q,
imm_n, imm_q;
logic alu_valid_n, alu_valid_q;
logic mult_valid_n, mult_valid_q;
logic fpu_valid_n, fpu_valid_q;
logic [1:0] fpu_fmt_n, fpu_fmt_q;
logic [2:0] fpu_rm_n, fpu_rm_q;
logic lsu_valid_n, lsu_valid_q;
logic csr_valid_n, csr_valid_q;
logic branch_valid_n, branch_valid_q;
logic alu_valid_q;
logic mult_valid_q;
logic fpu_valid_q;
logic [1:0] fpu_fmt_q;
logic [2:0] fpu_rm_q;
logic lsu_valid_q;
logic csr_valid_q;
logic branch_valid_q;
logic [TRANS_ID_BITS-1:0] trans_id_n, trans_id_q;
fu_op operator_n, operator_q; // operation to perform
@ -156,7 +156,7 @@ module issue_read_operands #(
// as this is an immediate we do not have to wait on anything here
// 1. check if the source registers are clobbered --> check appropriate clobber list (gpr/fpr)
// 2. poll the scoreboard
if (~issue_instr_i.use_zimm && (is_rs1_fpr(issue_instr_i.op) ? rd_clobber_fpr_i[issue_instr_i.rs1] != NONE
if (!issue_instr_i.use_zimm && (is_rs1_fpr(issue_instr_i.op) ? rd_clobber_fpr_i[issue_instr_i.rs1] != NONE
: rd_clobber_gpr_i[issue_instr_i.rs1] != NONE)) begin
// check if the clobbering instruction is not a CSR instruction, CSR instructions can only
// be fetched through the register file since they can't be forwarded
@ -230,53 +230,65 @@ module issue_read_operands #(
end
// FU select, assert the correct valid out signal (in the next cycle)
always_comb begin : unit_valid
alu_valid_n = 1'b0;
lsu_valid_n = 1'b0;
mult_valid_n = 1'b0;
fpu_valid_n = 1'b0;
fpu_fmt_n = 2'b0;
fpu_rm_n = 3'b0;
csr_valid_n = 1'b0;
branch_valid_n = 1'b0;
// This needs to be like this to make verilator happy. I know its ugly.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
alu_valid_q <= 1'b0;
lsu_valid_q <= 1'b0;
mult_valid_q <= 1'b0;
fpu_valid_q <= 1'b0;
fpu_fmt_q <= 2'b0;
fpu_rm_q <= 3'b0;
csr_valid_q <= 1'b0;
branch_valid_q <= 1'b0;
end else begin
alu_valid_q <= 1'b0;
lsu_valid_q <= 1'b0;
mult_valid_q <= 1'b0;
fpu_valid_q <= 1'b0;
fpu_fmt_q <= 2'b0;
fpu_rm_q <= 3'b0;
csr_valid_q <= 1'b0;
branch_valid_q <= 1'b0;
// Exception pass through:
// If an exception has occurred simply pass it through
// we do not want to issue this instruction
if (~issue_instr_i.ex.valid && issue_instr_valid_i && issue_ack_o) begin
if (!issue_instr_i.ex.valid && issue_instr_valid_i && issue_ack_o) begin
case (issue_instr_i.fu)
ALU:
alu_valid_n = 1'b1;
alu_valid_q <= 1'b1;
CTRL_FLOW:
branch_valid_n = 1'b1;
branch_valid_q <= 1'b1;
MULT:
mult_valid_n = 1'b1;
mult_valid_q <= 1'b1;
FPU : begin
fpu_valid_n = 1'b1;
fpu_fmt_n = orig_instr.rftype.fmt; // fmt bits from instruction
fpu_rm_n = orig_instr.rftype.rm; // rm bits from instruction
fpu_valid_q <= 1'b1;
fpu_fmt_q <= orig_instr.rftype.fmt; // fmt bits from instruction
fpu_rm_q <= orig_instr.rftype.rm; // rm bits from instruction
end
FPU_VEC : begin
fpu_valid_n = 1'b1;
fpu_fmt_n = orig_instr.rvftype.vfmt; // vfmt bits from instruction
fpu_rm_n = {2'b0, orig_instr.rvftype.repl}; // repl bit from instruction
fpu_valid_q <= 1'b1;
fpu_fmt_q <= orig_instr.rvftype.vfmt; // vfmt bits from instruction
fpu_rm_q <= {2'b0, orig_instr.rvftype.repl}; // repl bit from instruction
end
LOAD, STORE:
lsu_valid_n = 1'b1;
lsu_valid_q <= 1'b1;
CSR:
csr_valid_n = 1'b1;
csr_valid_q <= 1'b1;
default:;
endcase
end
// if we got a flush request, de-assert the valid flag, otherwise we will start this
// functional unit with the wrong inputs
if (flush_i) begin
alu_valid_n = 1'b0;
lsu_valid_n = 1'b0;
mult_valid_n = 1'b0;
fpu_valid_n = 1'b0;
csr_valid_n = 1'b0;
branch_valid_n = 1'b0;
alu_valid_q <= 1'b0;
lsu_valid_q <= 1'b0;
mult_valid_q <= 1'b0;
fpu_valid_q <= 1'b0;
csr_valid_q <= 1'b0;
branch_valid_q <= 1'b0;
end
end
end
// We can issue an instruction if we do not detect that any other instruction is writing the same
@ -289,7 +301,7 @@ module issue_read_operands #(
// and that the functional unit we need is not busy
if (issue_instr_valid_i) begin
// check that the corresponding functional unit is not busy
if (~stall && ~fu_busy) begin
if (!stall && !fu_busy) begin
// -----------------------------------------
// WAW - Write After Write Dependency Check
// -----------------------------------------
@ -397,36 +409,20 @@ module issue_read_operands #(
// Registers (ID <-> EX)
// ----------------------
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
if (!rst_ni) begin
operand_a_q <= '{default: 0};
operand_b_q <= '{default: 0};
imm_q <= 64'b0;
alu_valid_q <= 1'b0;
branch_valid_q <= 1'b0;
mult_valid_q <= 1'b0;
fpu_valid_q <= 1'b0;
fpu_fmt_q <= 2'b0;
fpu_rm_q <= 3'b0;
lsu_valid_q <= 1'b0;
csr_valid_q <= 1'b0;
imm_q <= '0;
fu_q <= NONE;
operator_q <= ADD;
trans_id_q <= 5'b0;
pc_o <= 64'b0;
trans_id_q <= '0;
pc_o <= '0;
is_compressed_instr_o <= 1'b0;
branch_predict_o <= '{default: 0};
end else begin
operand_a_q <= operand_a_n;
operand_b_q <= operand_b_n;
imm_q <= imm_n;
alu_valid_q <= alu_valid_n;
branch_valid_q <= branch_valid_n;
mult_valid_q <= mult_valid_n;
fpu_valid_q <= fpu_valid_n;
fpu_fmt_q <= fpu_fmt_n;
fpu_rm_q <= fpu_rm_n;
lsu_valid_q <= lsu_valid_n;
csr_valid_q <= csr_valid_n;
fu_q <= fu_n;
operator_q <= operator_n;
trans_id_q <= trans_id_n;