Skip to content

insn_div.v and insn_rem.v do not actually perform signed division in all cases #30

@kimmeljo

Description

@kimmeljo

Specifically referring to this line (in insn_div.v but same idea applies to insn_rem.v):

wire [`RISCV_FORMAL_XLEN-1:0] result = rvfi_rs2_rdata == `RISCV_FORMAL_XLEN'b0 ? {`RISCV_FORMAL_XLEN{1'b1}} :
                                         rvfi_rs1_rdata == {1'b1, {`RISCV_FORMAL_XLEN-1{1'b0}}} && rvfi_rs2_rdata == {`RISCV_FORMAL_XLEN{1'b1}} ? {1'b1, {`RISCV_FORMAL_XLEN-1{1'b0}}} :
                                         **$signed(rvfi_rs1_rdata) / $signed(rvfi_rs2_rdata)**;

If rvfi_rs1_rdata is a negative number and rvfi_rs2_rdata is a positive number with a larger absolute value, an assertion on rd_wdata fails if the HW correctly returns 0.

Fix (confirmed by shimming locally):

  wire [`RISCV_FORMAL_XLEN-1:0] result = rvfi_rs2_rdata == `RISCV_FORMAL_XLEN'b0 ? {`RISCV_FORMAL_XLEN{1'b1}} :
                                         rvfi_rs1_rdata == {1'b1, {`RISCV_FORMAL_XLEN-1{1'b0}}} && rvfi_rs2_rdata == {`RISCV_FORMAL_XLEN{1'b1}} ? {1'b1, {`RISCV_FORMAL_XLEN-1{1'b0}}} :
                                         **{$signed(rvfi_rs1_rdata) / $signed(rvfi_rs2_rdata)}**;

(surrounding the division expression in {...})

Note that local testing was only performed for RV32*

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions