diff --git a/.gitignore b/.gitignore index dd5a42fe..bda19d1e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ build/ *.vcd fusesoc.conf html -Bender.lock \ No newline at end of file +Bender.lock +.vscode/ \ No newline at end of file diff --git a/hw/ip/prim/fpv/prim_esc_rxtx_fpv.core b/hw/ip/prim/fpv/prim_esc_rxtx_fpv.core index 3aa4c5a7..7c0b97bb 100644 --- a/hw/ip/prim/fpv/prim_esc_rxtx_fpv.core +++ b/hw/ip/prim/fpv/prim_esc_rxtx_fpv.core @@ -18,7 +18,7 @@ targets: default: &default_target # note, this setting is just used # to generate a file list for jg - formal: icarus + default_tool: icarus filesets: - files_formal toplevel: diff --git a/hw/vendor/lowrisc_ibex/dv/riscv_compliance/ibex_riscv_compliance.core b/hw/vendor/lowrisc_ibex/dv/riscv_compliance/ibex_riscv_compliance.core index cf5ef71b..880b9005 100644 --- a/hw/vendor/lowrisc_ibex/dv/riscv_compliance/ibex_riscv_compliance.core +++ b/hw/vendor/lowrisc_ibex/dv/riscv_compliance/ibex_riscv_compliance.core @@ -69,7 +69,7 @@ parameters: WritebackStage: datatype: int paramtype: vlogparam - default: 0 + default: 1 description: "Enables third pipeline stage (EXPERIMENTAL)" BranchPredictor: @@ -145,3 +145,4 @@ targets: - '-Wno-INCABSPATH' - "-Wno-IMPERFECTSCH" - "-Wno-LITENDIAN" + - "-Wno-LATCH" diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core index 6634e1dc..6582d012 100644 --- a/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core +++ b/hw/vendor/lowrisc_ibex/examples/simple_system/ibex_simple_system.core @@ -77,7 +77,7 @@ parameters: WritebackStage: datatype: int paramtype: vlogparam - default: 0 + default: 1 description: "Enables third pipeline stage (EXPERIMENTAL)" SecureIbex: @@ -109,6 +109,12 @@ parameters: default: 4 paramtype: vlogparam description: "Number of PMP regions" + + RVF: + datatype: str + default: ibex_pkg::RV32FSingle + paramtype: vlogdefine + description: "Used to enable the F or D extension with ibex, possible values: ibex_pkg::RV32FDNone, ibex_pkg::RV32FSingle, ibex_pkg::RV32DDouble" targets: default: &default_target @@ -122,6 +128,7 @@ targets: - RV32M - RV32B - RegFile + - RVF - ICache - ICacheECC - BranchTargetALU @@ -176,3 +183,5 @@ targets: - '-Wno-UNOPTFLAT' - '-Wno-INCABSPATH' - "-Wno-IMPERFECTSCH" + - "-Wno-LATCH" + - "-Wno-LITENDIAN" diff --git a/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv b/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv index 1949a781..7589fadc 100644 --- a/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv +++ b/hw/vendor/lowrisc_ibex/examples/simple_system/rtl/ibex_simple_system.sv @@ -18,6 +18,10 @@ `define RegFile ibex_pkg::RegFileFF `endif +`ifndef RVF + `define RVF ibex_pkg::RV32FSingle +`endif + /** * Ibex simple system * @@ -43,8 +47,9 @@ module ibex_simple_system ( parameter ibex_pkg::rv32m_e RV32M = `RV32M; parameter ibex_pkg::rv32b_e RV32B = `RV32B; parameter ibex_pkg::regfile_e RegFile = `RegFile; + parameter ibex_pkg::rvfloat_e RVF = `RVF; parameter bit BranchTargetALU = 1'b0; - parameter bit WritebackStage = 1'b0; + parameter bit WritebackStage = 1'b1; parameter bit ICache = 1'b0; parameter bit ICacheECC = 1'b0; parameter bit BranchPredictor = 1'b0; @@ -170,6 +175,7 @@ module ibex_simple_system ( .RV32E ( RV32E ), .RV32M ( RV32M ), .RV32B ( RV32B ), + .RVF ( RVF ), .RegFile ( RegFile ), .BranchTargetALU ( BranchTargetALU ), .ICache ( ICache ), diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv index 12a487fe..0e740927 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_compressed_decoder.sv @@ -56,6 +56,12 @@ module ibex_compressed_decoder ( 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], {OPCODE_LOAD}}; end + 3'b011: begin + // c.flw -> flw frd`, imm(rs1) + instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], + 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], {OPCODE_LOAD_FP}}; + end + 3'b110: begin // c.sw -> sw rs2', imm(rs1') instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], @@ -63,11 +69,16 @@ module ibex_compressed_decoder ( 2'b00, {OPCODE_STORE}}; end + 3'b111: begin + // c.fsw -> fsw frs2`, imm(rs1`) + instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], + 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], + 2'b00, {OPCODE_STORE_FP}}; + end + 3'b001, - 3'b011, 3'b100, - 3'b101, - 3'b111: begin + 3'b101: begin illegal_instr_o = 1'b1; end @@ -220,6 +231,12 @@ module ibex_compressed_decoder ( if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; end + 3'b011: begin + // c.flwsp -> flw frd, imm(x2) + instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, + 3'b010, instr_i[11:7], OPCODE_LOAD_FP}; + end + 3'b100: begin if (instr_i[12] == 1'b0) begin if (instr_i[6:2] != 5'b0) begin @@ -254,10 +271,14 @@ module ibex_compressed_decoder ( instr_i[11:9], 2'b00, {OPCODE_STORE}}; end - 3'b001, - 3'b011, - 3'b101, 3'b111: begin + // c.fswsp -> fsw frs2, imm(x2) + instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, + instr_i[11:9], 2'b00, {OPCODE_STORE_FP}}; + end + + 3'b001, + 3'b101: begin illegal_instr_o = 1'b1; end diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv index ec15e924..c49180d0 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv @@ -99,6 +99,22 @@ module ibex_core #( output logic [ 3:0] rvfi_mem_wmask, output logic [31:0] rvfi_mem_rdata, output logic [31:0] rvfi_mem_wdata, + output logic [ 4:0] rvfi_frs1_addr, + output logic [ 4:0] rvfi_frs2_addr, + output logic [ 4:0] rvfi_frs3_addr, + output logic [ 4:0] rvfi_frd_addr, + output logic [31:0] rvfi_frs1_rdata, + output logic [31:0] rvfi_frs2_rdata, + output logic [31:0] rvfi_frs3_rdata, + output logic [31:0] rvfi_frd_wdata, + // output logic rvfi_frs1_rvalid, + // output logic rvfi_frs2_rvalid, + // output logic rvfi_frs3_rvalid, + // output logic rvfi_frd_wvalid, + // output logic [31:0] rvfi_csr_fcsr_rmask, + // output logic [31:0] rvfi_csr_fcsr_wmask, + // output logic [31:0] rvfi_csr_fcsr_rdata, + // output logic [31:0] rvfi_csr_fcsr_wdata, `endif // CPU Control Signals @@ -133,7 +149,10 @@ module ibex_core #( logic out_valid_fpu2c; // valid - from core to FPU logic valid_id_fpu; // select which valid signal will go to dec logic fp_rm_dynamic; - logic fp_alu_op_mod; + logic fp_alu_op_mod; + logic fp_rf_ren_a; + logic fp_rf_ren_b; + logic fp_rf_ren_c; logic [4:0] fp_rf_raddr_a; logic [4:0] fp_rf_raddr_b; logic [4:0] fp_rf_raddr_c; @@ -145,9 +164,6 @@ module ibex_core #( logic [2:0][FPU_WIDTH-1:0] fp_operands; // three operands in fpu logic fp_busy; logic fpu_busy_idu; - logic [FPU_WIDTH-1:0] fp_result; - logic [31:0] data_wb; - logic [31:0] rf_int_fp_lsu; logic [4:0] fp_rf_waddr_id; logic [4:0] fp_rf_waddr_wb; logic fp_rf_we; @@ -160,8 +176,10 @@ module ibex_core #( logic fp_swap_oprnds; logic fpu_is_busy; logic fp_load; + logic fflags_en_id; logic [FPU_WIDTH-1:0] fp_rf_wdata_wb; logic [FPU_WIDTH-1:0] fp_rf_wdata_id; + logic [FPU_WIDTH-1:0] fp_result_ex; fpnew_pkg::status_t fp_status; fpnew_pkg::operation_e fp_operation; fpnew_pkg::roundmode_e fp_rounding_mode; @@ -398,6 +416,13 @@ module ibex_core #( logic [31:0] rvfi_mem_wdata_q; logic [31:0] rvfi_mem_addr_d; logic [31:0] rvfi_mem_addr_q; + logic [ 4:0] rvfi_frd_addr_wb; + logic [31:0] rvfi_frd_wdata_wb; + logic rvfi_frd_we_wb; + logic [31:0] rvfi_frd_wdata_d; + logic [31:0] rvfi_frd_wdata_q; + logic [ 4:0] rvfi_frd_addr_d; + logic [ 4:0] rvfi_frd_addr_q; `endif ////////////////////// @@ -647,14 +672,13 @@ module ibex_core #( .trigger_match_i ( trigger_match ), // write data to commit in the register file - .result_ex_i ( data_wb ), // changed by zeeshan from result_ex - // to data_wb for FVCT, FMV.WX ins + .result_ex_i ( result_ex ), .csr_rdata_i ( csr_rdata ), .rf_raddr_a_o ( rf_raddr_a ), .rf_rdata_a_i ( rf_rdata_a ), .rf_raddr_b_o ( rf_raddr_b ), - .rf_rdata_b_i ( rf_int_fp_lsu ), + .rf_rdata_b_i ( rf_rdata_b ), .rf_ren_a_o ( rf_ren_a ), .rf_ren_b_o ( rf_ren_b ), .rf_waddr_id_o ( rf_waddr_id ), @@ -691,6 +715,9 @@ module ibex_core #( .fp_rf_raddr_a_o ( fp_rf_raddr_a ), .fp_rf_raddr_b_o ( fp_rf_raddr_b ), .fp_rf_raddr_c_o ( fp_rf_raddr_c ), + .fp_rf_ren_a_o ( fp_rf_ren_a ), + .fp_rf_ren_b_o ( fp_rf_ren_b ), + .fp_rf_ren_c_o ( fp_rf_ren_c ), .fp_rf_waddr_o ( fp_rf_waddr_id ), .fp_rf_we_o ( fp_rf_wen_id ), .fp_alu_operator_o ( fp_alu_operator ), @@ -709,7 +736,10 @@ module ibex_core #( .fp_rf_wdata_fwd_wb_i ( fp_rf_wdata_wb ), .fp_rf_wdata_id_o ( fp_rf_wdata_id ), .fp_operands_o ( fp_operands ), - .fp_load_o ( fp_load ) + .fp_result_ex_i ( fp_result_ex ), + .fp_load_o ( fp_load ), + .fp_swap_oprnds_o ( fp_swap_oprnds ), + .fflags_en_id_o ( fflags_en_id ) ); // for RVFI only @@ -1003,7 +1033,7 @@ module ibex_core #( .in_valid_i ( in_valid_c2fpu ), .in_ready_o ( out_ready_fpu2c ), .flush_i ( fp_flush ), - .result_o ( fp_result ), + .result_o ( fp_result_ex ), .status_o ( fp_status ), .tag_o ( ), .out_valid_o ( out_valid_fpu2c ), @@ -1030,23 +1060,18 @@ module ibex_core #( .wdata_a_i ( fp_rf_wdata_wb ), .we_a_i ( fp_rf_wen_wb ) ); - assign rf_int_fp_lsu = (is_fp_instr & use_fp_rs2) ? fp_rf_rdata_b : rf_rdata_b; assign fp_frm_fpnew = fp_rm_dynamic ? fp_frm_csr : fp_rounding_mode; - assign in_ready_c2fpu = id_in_ready; //multdiv_ready_id; + assign in_ready_c2fpu = id_in_ready; assign in_valid_c2fpu = (instr_valid_id & is_fp_instr); - // assign ready_id_fpu = id_in_ready; // (is_fp_instr) ? out_ready_fpu2c : id_in_ready; assign valid_id_fpu = (is_fp_instr) ? out_valid_fpu2c : ex_valid; assign fpu_busy_idu = fp_busy & (~out_valid_fpu2c); - assign data_wb = is_fp_instr ? fp_result : result_ex; - assign core_busy_d = ctrl_busy | if_busy | lsu_busy | fp_busy; + assign core_busy_d = ctrl_busy | if_busy | lsu_busy | fpu_busy_idu; end else begin // Before going to sleep, wait for I- and D-side // interfaces to finish ongoing operations. assign core_busy_d = ctrl_busy | if_busy | lsu_busy; - assign data_wb = result_ex; assign valid_id_fpu = ex_valid; - assign rf_int_fp_lsu = rf_rdata_b; end /////////////////// @@ -1109,6 +1134,10 @@ module ibex_core #( assign rvfi_rd_addr_wb = rf_waddr_wb; assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu; assign rvfi_rd_we_wb = rf_we_wb | rf_we_lsu; + + assign rvfi_frd_addr_wb = fp_rf_waddr_wb; + assign rvfi_frd_wdata_wb = fp_rf_wen_wb ? fp_rf_wdata_wb : rf_wdata_lsu; + assign rvfi_frd_we_wb = fp_rf_wen_wb | rf_we_lsu; `endif @@ -1222,7 +1251,7 @@ module ibex_core #( .fp_rm_dynamic_i ( fp_rm_dynamic ), .fp_frm_o ( fp_frm_csr ), .fp_status_i ( fp_status ), - .is_fp_instr_i ( is_fp_instr ) + .fflags_en_id_i ( fflags_en_id ) ); // These assertions are in top-level as instr_valid_id required as the enable term @@ -1310,6 +1339,19 @@ module ibex_core #( logic [31:0] rvfi_stage_mem_rdata [RVFI_STAGES]; logic [31:0] rvfi_stage_mem_wdata [RVFI_STAGES]; + logic rvfi_stage_frs1_rvalid [RVFI_STAGES]; + logic rvfi_stage_frs2_rvalid [RVFI_STAGES]; + logic rvfi_stage_frs3_rvalid [RVFI_STAGES]; + logic rvfi_stage_frd_wvalid [RVFI_STAGES]; + logic [ 4:0] rvfi_stage_frs1_addr [RVFI_STAGES]; + logic [ 4:0] rvfi_stage_frs2_addr [RVFI_STAGES]; + logic [ 4:0] rvfi_stage_frs3_addr [RVFI_STAGES]; + logic [31:0] rvfi_stage_frs1_rdata [RVFI_STAGES]; + logic [31:0] rvfi_stage_frs2_rdata [RVFI_STAGES]; + logic [31:0] rvfi_stage_frs3_rdata [RVFI_STAGES]; + logic [ 4:0] rvfi_stage_frd_addr [RVFI_STAGES]; + logic [31:0] rvfi_stage_frd_wdata [RVFI_STAGES]; + logic rvfi_stage_valid_d [RVFI_STAGES]; assign rvfi_valid = rvfi_stage_valid [RVFI_STAGES-1]; @@ -1336,6 +1378,15 @@ module ibex_core #( assign rvfi_mem_rdata = rvfi_stage_mem_rdata[RVFI_STAGES-1]; assign rvfi_mem_wdata = rvfi_stage_mem_wdata[RVFI_STAGES-1]; + assign rvfi_frs1_addr = rvfi_stage_frs1_addr [RVFI_STAGES-1]; + assign rvfi_frs2_addr = rvfi_stage_frs2_addr [RVFI_STAGES-1]; + assign rvfi_frs3_addr = rvfi_stage_frs3_addr [RVFI_STAGES-1]; + assign rvfi_frs1_rdata = rvfi_stage_frs1_rdata[RVFI_STAGES-1]; + assign rvfi_frs2_rdata = rvfi_stage_frs2_rdata[RVFI_STAGES-1]; + assign rvfi_frs3_rdata = rvfi_stage_frs3_rdata[RVFI_STAGES-1]; + assign rvfi_frd_addr = rvfi_stage_frd_addr [RVFI_STAGES-1]; + assign rvfi_frd_wdata = rvfi_stage_frd_wdata [RVFI_STAGES-1]; + if (WritebackStage) begin : gen_rvfi_wb_stage logic unused_instr_new_id; @@ -1398,6 +1449,15 @@ module ibex_core #( rvfi_stage_mem_rdata[i] <= '0; rvfi_stage_mem_wdata[i] <= '0; rvfi_stage_mem_addr[i] <= '0; + + rvfi_stage_frs1_addr[i] <= '0; + rvfi_stage_frs2_addr[i] <= '0; + rvfi_stage_frs3_addr[i] <= '0; + rvfi_stage_frs1_rdata[i] <= '0; + rvfi_stage_frs2_rdata[i] <= '0; + rvfi_stage_frs3_rdata[i] <= '0; + rvfi_stage_frd_addr[i] <= '0; + rvfi_stage_frd_wdata[i] <= '0; end else begin rvfi_stage_valid[i] <= rvfi_stage_valid_d[i]; @@ -1425,6 +1485,17 @@ module ibex_core #( rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d; rvfi_stage_mem_wdata[i] <= rvfi_mem_wdata_d; rvfi_stage_mem_addr[i] <= rvfi_mem_addr_d; + + rvfi_stage_frs1_addr[i] <= fp_rf_ren_a ? fp_rf_raddr_a : '0; + rvfi_stage_frs2_addr[i] <= fp_rf_ren_b ? fp_rf_raddr_b : '0; + rvfi_stage_frs3_addr[i] <= fp_rf_ren_c ? fp_rf_raddr_c : '0; + rvfi_stage_frs1_rdata[i] <= fp_rf_ren_a ? fp_swap_oprnds ? + fp_operands[1]: fp_operands[0]: '0; + rvfi_stage_frs2_rdata[i] <= fp_rf_ren_b ? fp_swap_oprnds ? + fp_operands[2]: fp_operands[1]: '0; + rvfi_stage_frs3_rdata[i] <= fp_rf_ren_c ? fp_operands[2]: '0; + rvfi_stage_frd_addr[i] <= rvfi_frd_addr_d; + rvfi_stage_frd_wdata[i] <= rvfi_frd_wdata_d; end end else begin if(instr_done_wb) begin @@ -1448,12 +1519,21 @@ module ibex_core #( rvfi_stage_mem_wdata[i] <= rvfi_stage_mem_wdata[i-1]; rvfi_stage_mem_addr[i] <= rvfi_stage_mem_addr[i-1]; + rvfi_stage_frs1_addr[i] <= rvfi_stage_frs1_addr[i-1]; + rvfi_stage_frs2_addr[i] <= rvfi_stage_frs2_addr[i-1]; + rvfi_stage_frs3_addr[i] <= rvfi_stage_frs3_addr[i-1]; + rvfi_stage_frs1_rdata[i] <= rvfi_stage_frs1_rdata[i-1]; + rvfi_stage_frs2_rdata[i] <= rvfi_stage_frs2_rdata[i-1]; + rvfi_stage_frs3_rdata[i] <= rvfi_stage_frs3_rdata[i-1]; + // For 2 RVFI_STAGES/Writeback Stage ignore first stage flops for rd_addr, rd_wdata and // mem_rdata. For RF write addr/data actual write happens in writeback so capture // address/data there. For mem_rdata that is only available from the writeback stage. // Previous stage flops still exist in RTL as they are used by the non writeback config rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d; rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d; + rvfi_stage_frd_addr[i] <= rvfi_frd_addr_d; + rvfi_stage_frd_wdata[i] <= rvfi_frd_wdata_d; rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d; end end @@ -1546,9 +1626,11 @@ module ibex_core #( end always_comb begin - if(rvfi_rd_we_wb) begin + if(rvfi_rd_we_wb | rvfi_frd_we_wb) begin // Capture address/data of write to register file rvfi_rd_addr_d = rvfi_rd_addr_wb; + rvfi_frd_addr_d = rvfi_frd_addr_wb; + rvfi_frd_wdata_d = rvfi_frd_wdata_wb; // f0 is not zero // If writing to x0 zero write data as required by RVFI specification if(rvfi_rd_addr_wb == 5'b0) begin rvfi_rd_wdata_d = '0; @@ -1560,10 +1642,14 @@ module ibex_core #( // stage present) then zero RF write address/data as required by RVFI specification rvfi_rd_addr_d = '0; rvfi_rd_wdata_d = '0; + rvfi_frd_addr_d = '0; + rvfi_frd_wdata_d = '0; end else begin // Otherwise maintain previous value rvfi_rd_addr_d = rvfi_rd_addr_q; rvfi_rd_wdata_d = rvfi_rd_wdata_q; + rvfi_frd_addr_d = rvfi_frd_addr_q; + rvfi_frd_wdata_d = rvfi_frd_wdata_q; end end @@ -1573,9 +1659,13 @@ module ibex_core #( if (!rst_ni) begin rvfi_rd_addr_q <= '0; rvfi_rd_wdata_q <= '0; + rvfi_frd_addr_q <= '0; + rvfi_frd_wdata_q <= '0; end else begin rvfi_rd_addr_q <= rvfi_rd_addr_d; rvfi_rd_wdata_q <= rvfi_rd_wdata_d; + rvfi_frd_addr_q <= rvfi_frd_addr_d; + rvfi_frd_wdata_q <= rvfi_frd_wdata_d; end end diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv index 29a2ac44..657f0084 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core_tracing.sv @@ -104,6 +104,14 @@ module ibex_core_tracing #( logic [ 3:0] rvfi_mem_wmask; logic [31:0] rvfi_mem_rdata; logic [31:0] rvfi_mem_wdata; + logic [ 4:0] rvfi_frs1_addr; + logic [ 4:0] rvfi_frs2_addr; + logic [ 4:0] rvfi_frs3_addr; + logic [ 4:0] rvfi_frd_addr; + logic [31:0] rvfi_frs1_rdata; + logic [31:0] rvfi_frs2_rdata; + logic [31:0] rvfi_frs3_rdata; + logic [31:0] rvfi_frd_wdata; ibex_core #( .PMPEnable ( PMPEnable ), @@ -183,6 +191,14 @@ module ibex_core_tracing #( .rvfi_mem_wmask, .rvfi_mem_rdata, .rvfi_mem_wdata, + .rvfi_frs1_addr, + .rvfi_frs2_addr, + .rvfi_frs3_addr, + .rvfi_frd_addr, + .rvfi_frs1_rdata, + .rvfi_frs2_rdata, + .rvfi_frs3_rdata, + .rvfi_frd_wdata, .fetch_enable_i, .alert_minor_o, @@ -219,7 +235,15 @@ module ibex_core_tracing #( .rvfi_mem_rmask, .rvfi_mem_wmask, .rvfi_mem_rdata, - .rvfi_mem_wdata + .rvfi_mem_wdata, + .rvfi_frs1_addr, + .rvfi_frs2_addr, + .rvfi_frs3_addr, + .rvfi_frd_addr, + .rvfi_frs1_rdata, + .rvfi_frs2_rdata, + .rvfi_frs3_rdata, + .rvfi_frd_wdata ); endmodule diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv index 1f249266..1c90074c 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv @@ -121,7 +121,7 @@ module ibex_cs_registers #( input logic fp_rm_dynamic_i, output fpnew_pkg::roundmode_e fp_frm_o, input fpnew_pkg::status_t fp_status_i, - input logic is_fp_instr_i + input logic fflags_en_id_i ); import ibex_pkg::*; @@ -305,14 +305,15 @@ module ibex_cs_registers #( // Floating point always_comb begin - unique case (frm_q) - 000, - 001, - 010, - 011, - 100: illegal_dyn_mod = 1'b0; - default: illegal_dyn_mod = 1'b1; - endcase + illegal_dyn_mod = 1'b0; + if (frm_d == 3'b111) begin + unique case (frm_q) + 101, + 110, + 111: illegal_dyn_mod = 1'b1; + default: illegal_dyn_mod = 1'b0; + endcase + end fp_frm_o = frm_q; end @@ -510,11 +511,10 @@ module ibex_cs_registers #( exception_pc = pc_id_i; // Floating point - fflags_d = fflags_q; - fflags_en = 1'b0; - - frm_d = frm_q; - frm_en = 1'b0; + fflags_en = 1'b0; + fflags_d = fflags_q; + frm_en = 1'b0; + frm_d = frm_q; priv_lvl_d = priv_lvl_q; mstatus_en = 1'b0; @@ -558,7 +558,7 @@ module ibex_cs_registers #( fflags_en = 1'b1; frm_en = 1'b1; fflags_d = csr_wdata_int[4:0]; - frm_d = csr_wdata_int[7:5]; + frm_d = csr_wdata_int[7:5]; end CSR_FFLAG : begin @@ -821,7 +821,7 @@ module ibex_cs_registers #( .rd_error_o (mstatus_err) ); - assign fflag_wdata = is_fp_instr_i ? fp_status_i : fflags_d; + assign fflag_wdata = fflags_en_id_i ? fp_status_i : fflags_d; // FFLAGS ibex_csr #( .Width (5), @@ -831,7 +831,7 @@ module ibex_cs_registers #( .clk_i (clk_i), .rst_ni (rst_ni), .wr_data_i (fflag_wdata), - .wr_en_i (fflags_en | is_fp_instr_i), + .wr_en_i (fflags_en | fflags_en_id_i), .rd_data_o (fflags_q), .rd_error_o () ); diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv index f27e5a1c..8ae55828 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv @@ -103,6 +103,9 @@ module ibex_decoder #( output logic [4:0] fp_rf_raddr_a_o, output logic [4:0] fp_rf_raddr_b_o, output logic [4:0] fp_rf_raddr_c_o, + output logic fp_rf_ren_a_o, + output logic fp_rf_ren_b_o, + output logic fp_rf_ren_c_o, output logic [4:0] fp_rf_waddr_o, output logic fp_rf_we_o, @@ -119,7 +122,10 @@ module ibex_decoder #( output logic use_fp_rd_o, output logic fp_swap_oprnds_o, output logic fp_load_o, - output logic mv_instr_o + output logic mv_instn_xw_o, + output logic mv_instn_wx_o, + output logic fpu_to_int_rf_o, + output logic fflags_en_id_o ); import ibex_pkg::*; @@ -278,7 +284,13 @@ module ibex_decoder #( fp_src_fmt_o = FP32; fp_dst_fmt_o = FP32; fp_swap_oprnds_o = 1'b0; - mv_instr_o = 1'b0; + mv_instn_xw_o = 1'b0; + mv_instn_wx_o = 1'b0; + fpu_to_int_rf_o = 1'b0; + fp_rf_ren_a_o = 1'b0; + fp_rf_ren_b_o = 1'b0; + fp_rf_ren_c_o = 1'b0; + fflags_en_id_o = 1'b0; opcode = opcode_e'(instr[6:0]); @@ -680,6 +692,9 @@ module ibex_decoder #( data_req_o = 1'b1; data_we_o = 1'b1; data_type_o = 2'b00; + rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; + is_fp_instr_o = 1'b1; use_fp_rs2_o = 1'b1; @@ -700,6 +715,8 @@ module ibex_decoder #( data_req_o = 1'b1; data_type_o = 2'b00; fp_load_o = 1'b1; + rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; use_fp_rd_o = 1'b1; @@ -723,11 +740,15 @@ module ibex_decoder #( fp_rf_we_o = 1'b1; fp_src_fmt_o = FP32; is_fp_instr_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; + fp_rf_ren_c_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; use_fp_rs3_o = 1'b1; use_fp_rd_o = 1'b1; + fflags_en_id_o = 1'b1; unique case (instr[26:25]) 01: begin @@ -745,10 +766,13 @@ module ibex_decoder #( OPCODE_OP_FP: begin fp_src_fmt_o = FP32; is_fp_instr_o = 1'b1; + fflags_en_id_o = 1'b1; unique case (instr[31:25]) 7'b0000001, // FADD.D 7'b0000101: begin // FSUB.D + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; fp_rf_we_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; @@ -759,6 +783,8 @@ module ibex_decoder #( end 7'b0001001, // FMUL.D 7'b0001101:begin // FDIV.D + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; fp_rf_we_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; @@ -768,6 +794,8 @@ module ibex_decoder #( end 7'b0000000, // FADD.S 7'b0000100: begin // FSUB.S + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; fp_rf_we_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; @@ -776,8 +804,10 @@ module ibex_decoder #( illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; end - 7'b0001000, // FMUL.S + 7'b0001000, // FMUL.S 7'b0001100: begin // FDIV.S + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; fp_rf_we_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; @@ -789,6 +819,7 @@ module ibex_decoder #( fp_rf_we_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; if (~|instr[24:20]) begin //FSQRT.D illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; fp_src_fmt_o = FP64; @@ -798,6 +829,8 @@ module ibex_decoder #( fp_rf_we_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fpu_to_int_rf_o = 1'b1; if (~|instr[24:20]) begin illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; @@ -808,6 +841,8 @@ module ibex_decoder #( use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; if (~(instr[14] | (&instr[13:12]))) begin illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; fp_src_fmt_o = FP64; @@ -818,6 +853,8 @@ module ibex_decoder #( use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; if (~(instr[14] | (&instr[13:12]))) begin illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; @@ -828,6 +865,8 @@ module ibex_decoder #( use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; if (~|instr[14:13]) begin illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; fp_src_fmt_o = FP64; @@ -838,6 +877,8 @@ module ibex_decoder #( use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; if (~|instr[14:13]) begin illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; @@ -847,6 +888,7 @@ module ibex_decoder #( fp_rf_we_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; if (~(|instr[24:21] | (~instr[20]))) begin illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; fp_src_fmt_o = FP64; @@ -855,6 +897,8 @@ module ibex_decoder #( 7'b1100000: begin // FCVT.W.S, FCVT.WU.S rf_we = 1'b1; // write back in int_regfile use_fp_rs1_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fpu_to_int_rf_o = 1'b1; if (~|instr[24:21]) begin illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; @@ -864,6 +908,7 @@ module ibex_decoder #( fp_rf_we_o = 1'b1; use_fp_rs1_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; if (~|instr[24:20]) begin illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; fp_src_fmt_o = FP64; @@ -871,12 +916,15 @@ module ibex_decoder #( end 7'b1110000: begin // FMV.X.W , FCLASS.S rf_we = 1'b1; // write back in int_regfile + fp_rf_ren_a_o = 1'b1; + fpu_to_int_rf_o = 1'b1; unique case ({instr[24:20],instr[14:12]}) {5'b00000,3'b000}: begin use_fp_rs1_o = 1'b1; illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; - mv_instr_o = 1'b1; + mv_instn_xw_o = 1'b1; + fflags_en_id_o = 1'b0; end {5'b00000,3'b001}: begin use_fp_rs1_o = 1'b1; @@ -892,6 +940,8 @@ module ibex_decoder #( rf_we = 1'b1; // write back in int_regfile use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; if (~(instr[14]) | (&instr[13:12])) begin illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; fp_src_fmt_o = FP64; @@ -901,6 +951,9 @@ module ibex_decoder #( rf_we = 1'b1; // write back in int_regfile use_fp_rs1_o = 1'b1; use_fp_rs2_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + fp_rf_ren_b_o = 1'b1; + fpu_to_int_rf_o = 1'b1; if (~(instr[14]) | (&instr[13:12])) begin illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; @@ -909,6 +962,7 @@ module ibex_decoder #( 7'b1110001: begin // FCLASS.D rf_we = 1'b1; // write back in int_regfile use_fp_rs1_o = 1'b1; + fp_rf_ren_a_o = 1'b1; unique case ({instr[24:20],instr[14:12]}) {5'b00000,3'b001}: begin illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; @@ -922,6 +976,7 @@ module ibex_decoder #( 7'b1100001: begin // // FCVT.W.D, FCVT.WU.D rf_we = 1'b1; // write back in int_regfile use_fp_rs1_o = 1'b1; + fp_rf_ren_a_o = 1'b1; if (~|instr[24:21]) begin illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; fp_src_fmt_o = FP64; @@ -930,6 +985,7 @@ module ibex_decoder #( 7'b1101000: begin // FCVT.S.W, FCVT.S.WU fp_rf_we_o = 1'b1; use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; if (~|instr[24:21]) begin illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; @@ -938,6 +994,7 @@ module ibex_decoder #( 7'b1111001: begin // FCVT.D.W, FCVT.D.WU rf_we = 1'b1; // write back in int_regfile use_fp_rd_o = 1'b1; + fp_rf_ren_a_o = 1'b1; if (~|instr[24:21]) begin illegal_insn = ((RVF == RV32DDouble) & (fp_invalid_rm)) ? 1'b0 : 1'b1; fp_src_fmt_o = FP64; @@ -946,10 +1003,13 @@ module ibex_decoder #( 7'b1111000: begin // FMV.W.X fp_rf_we_o = 1'b1; use_fp_rd_o = 1'b1; - mv_instr_o = 1'b1; + mv_instn_wx_o = 1'b1; + fp_rf_ren_a_o = 1'b1; + rf_ren_a_o = 1'b1; if (~(|instr[24:20]) | (|instr[14:12])) begin illegal_insn = ((RVF == RV32FDNone) & (~fp_invalid_rm)) ? 1'b1 : 1'b0; fp_src_fmt_o = FP32; + fflags_en_id_o = 1'b0; end end default: illegal_insn = 1'b1; @@ -1643,9 +1703,9 @@ module ibex_decoder #( end 7'b1110000: begin // FMV.X.W , FCLASS.S unique case ({instr[24:20],instr[14:12]}) - // {3'b0000000,3'b000}: begin - // fp_alu_operator_o = ADD; // to be decided YET - // end + {3'b0000000,3'b000}: begin + fp_alu_operator_o = ADD; // we want move, so the result is not relavent + end {3'b000,3'b001}: begin fp_alu_operator_o = CLASSIFY; end @@ -1694,11 +1754,11 @@ module ibex_decoder #( fp_alu_op_mod_o = 1'b1; end end - // 7'b1111000: begin // FMV.W.X - // if ((|instr[24:20]) | (|instr[14:12])) begin - // fp_alu_operator_o = FMADD; // to be decided - // end - // end + 7'b1111000: begin // FMV.W.X + if (~(|instr[24:20]) | (|instr[14:12])) begin + fp_alu_operator_o = ADD; // we want move, so the result is not relavent + end + end default: ; endcase end diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv index 27a0291d..f751bd7f 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv @@ -193,6 +193,9 @@ module ibex_id_stage #( output logic [4:0] fp_rf_raddr_a_o, output logic [4:0] fp_rf_raddr_b_o, output logic [4:0] fp_rf_raddr_c_o, + output logic fp_rf_ren_a_o, + output logic fp_rf_ren_b_o, + output logic fp_rf_ren_c_o, output logic [4:0] fp_rf_waddr_o, output logic fp_rf_we_o, @@ -212,7 +215,10 @@ module ibex_id_stage #( input logic [FPU_WIDTH-1:0] fp_rf_wdata_fwd_wb_i, output logic [FPU_WIDTH-1:0] fp_rf_wdata_id_o, output logic [2:0][FPU_WIDTH-1:0] fp_operands_o, - output logic fp_load_o + input logic [FPU_WIDTH-1:0] fp_result_ex_i, + output logic fp_load_o, + output logic fp_swap_oprnds_o, + output logic fflags_en_id_o ); import ibex_pkg::*; @@ -272,6 +278,7 @@ module ibex_id_stage #( logic [31:0] rf_rdata_a_fwd; logic [31:0] rf_rdata_b_fwd; + logic [31:0] result_wb; // ALU Control alu_op_e alu_operator; @@ -308,44 +315,39 @@ module ibex_id_stage #( logic [31:0] alu_operand_a; logic [31:0] alu_operand_b; - /* FPU Limits STARTS */ - logic mv_instr; - logic fp_swap_oprnds; + /* FPU limit start */ + logic fpu_to_int_rf; + logic mv_instn_xw; + logic mv_instn_wx; logic [FPU_WIDTH-1:0] fp_rf_rdata_a_fwd; logic [FPU_WIDTH-1:0] fp_rf_rdata_b_fwd; logic [FPU_WIDTH-1:0] fp_rf_rdata_c_fwd; logic [FPU_WIDTH-1:0] temp; logic [FPU_WIDTH-1:0] fpu_op_a; - logic [31:0] fpu_op_b; + logic [FPU_WIDTH-1:0] fpu_op_b; logic [FPU_WIDTH-1:0] fpu_op_c; - logic [FPU_WIDTH-1:0] result_wb; - logic [FPU_WIDTH-1:0] fpu_a; - logic [FPU_WIDTH-1:0] fpu_b; - logic [FPU_WIDTH-1:0] fpu_c; + logic [FPU_WIDTH-1:0] fp_result_wb; if (RVF == RV32FSingle || RVF == RV32DDouble) begin - assign fpu_a = use_fp_rs1_o ? fp_rf_rdata_a_fwd : rf_rdata_a_fwd; - assign fpu_b = use_fp_rs2_o ? fp_rf_rdata_b_fwd : rf_rdata_b_fwd; - assign fpu_c = fp_rf_rdata_c_fwd; - - /* Swap operands */ - always_comb begin : swapping - if (fp_swap_oprnds) begin - temp = fpu_c; - fpu_op_c = fpu_a; - fpu_op_a = temp; - end else begin - fpu_op_a = fpu_a; - fpu_op_b = fpu_b; - fpu_op_c = fpu_c; - end - fp_operands_o = {fpu_op_c , fpu_op_b , fpu_op_a}; - end - assign result_wb = mv_instr ? fpu_op_a : result_ex_i; + assign fpu_op_a = use_fp_rs1_o ? fp_rf_rdata_a_fwd : rf_rdata_a_fwd; + assign fpu_op_b = use_fp_rs2_o ? fp_rf_rdata_b_fwd : rf_rdata_b_fwd; + assign fpu_op_c = fp_rf_rdata_c_fwd; + + /* Swap operands for FADD/FSUB */ + assign fp_operands_o = fp_swap_oprnds_o ? {fpu_op_b, fpu_op_a, fpu_op_c} : + {fpu_op_c, fpu_op_b, fpu_op_a}; + + logic [FPU_WIDTH-1:0] fpu_wb_rf_int; + + assign fpu_wb_rf_int = mv_instn_xw ? fpu_op_a : fp_result_ex_i; + + assign result_wb = fpu_to_int_rf ? fpu_wb_rf_int : result_ex_i; + assign fp_result_wb = mv_instn_wx ? rf_rdata_a_fwd : fp_result_ex_i; end else begin - assign fpu_op_b = rf_rdata_b_fwd; + logic unused_fp_result_ex; + assign unused_fp_result_ex = &{ 1'b0, fp_result_ex_i, 1'b0}; end - /* FPU Limits ENDS */ + /* FPU limit end */ ///////////// // LSU Mux // @@ -550,6 +552,9 @@ module ibex_id_stage #( .fp_rf_raddr_a_o ( fp_rf_raddr_a_o ), .fp_rf_raddr_b_o ( fp_rf_raddr_b_o ), .fp_rf_raddr_c_o ( fp_rf_raddr_c_o ), + .fp_rf_ren_a_o ( fp_rf_ren_a_o ), + .fp_rf_ren_b_o ( fp_rf_ren_b_o ), + .fp_rf_ren_c_o ( fp_rf_ren_c_o ), .fp_rf_waddr_o ( fp_rf_waddr_o ), .fp_rf_we_o ( fp_rf_we_o ), .fp_alu_operator_o ( fp_alu_operator_o ), @@ -562,9 +567,12 @@ module ibex_id_stage #( .use_fp_rs2_o ( use_fp_rs2_o ), .use_fp_rs3_o ( use_fp_rs3_o ), .use_fp_rd_o ( use_fp_rd_o ), - .fp_swap_oprnds_o ( fp_swap_oprnds ), + .fp_swap_oprnds_o ( fp_swap_oprnds_o ), .fp_load_o ( fp_load_o ), - .mv_instr_o ( mv_instr ) + .mv_instn_xw_o ( mv_instn_xw ), + .mv_instn_wx_o ( mv_instn_wx ), + .fpu_to_int_rf_o ( fpu_to_int_rf ), + .fflags_en_id_o ( fflags_en_id_o ) ); /////////////////////// @@ -577,18 +585,18 @@ module ibex_id_stage #( // Register file write data mux always_comb begin : rf_wdata_id_mux unique case (rf_wdata_sel) - RF_WD_EX: rf_wdata_id_o = result_ex_i; + RF_WD_EX: rf_wdata_id_o = result_wb; RF_WD_CSR: rf_wdata_id_o = csr_rdata_i; - default: rf_wdata_id_o = result_ex_i; + default: rf_wdata_id_o = result_wb; endcase end - // Register file write data mux + // Floating point register file write data mux always_comb begin : fp_rf_wdata_id_mux unique case (rf_wdata_sel) - RF_WD_EX: fp_rf_wdata_id_o = result_wb; + RF_WD_EX: fp_rf_wdata_id_o = fp_result_wb; RF_WD_CSR: fp_rf_wdata_id_o = csr_rdata_i; - default: fp_rf_wdata_id_o = result_wb; + default: fp_rf_wdata_id_o = fp_result_wb; endcase end @@ -729,7 +737,7 @@ module ibex_id_stage #( assign lsu_we_o = lsu_we; assign lsu_type_o = lsu_type; assign lsu_sign_ext_o = lsu_sign_ext; - assign lsu_wdata_o = fpu_op_b; //rf_rdata_b_fwd; + assign lsu_wdata_o = is_fp_instr_o ? fp_rf_rdata_b_fwd : rf_rdata_b_fwd; // csr_op_en_o is set when CSR access should actually happen. // csv_access_o is set when CSR access instruction is present and is used to compute whether a CSR // access is illegal. A combinational loop would be created if csr_op_en_o was used along (as diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv index 78204982..167fc4a4 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer.sv @@ -65,7 +65,15 @@ module ibex_tracer ( input logic [ 3:0] rvfi_mem_rmask, input logic [ 3:0] rvfi_mem_wmask, input logic [31:0] rvfi_mem_rdata, - input logic [31:0] rvfi_mem_wdata + input logic [31:0] rvfi_mem_wdata, + input logic [ 4:0] rvfi_frs1_addr, + input logic [ 4:0] rvfi_frs2_addr, + input logic [ 4:0] rvfi_frs3_addr, + input logic [ 4:0] rvfi_frd_addr, + input logic [31:0] rvfi_frs1_rdata, + input logic [31:0] rvfi_frs2_rdata, + input logic [31:0] rvfi_frs3_rdata, + input logic [31:0] rvfi_frd_wdata ); // These signals are part of RVFI, but not used in this module currently. @@ -87,6 +95,13 @@ module ibex_tracer ( int unsigned cycle; string decoded_str; logic insn_is_compressed; + logic insn_is_float; + logic float_wx; + logic float_xw; + logic float_lw; + logic float_sw; + logic float_class; + logic float_comp; // Data items accessed during this instruction localparam logic [4:0] RS1 = (1 << 0); @@ -130,18 +145,43 @@ module ibex_tracer ( $fwrite(file_handle, "%15t\t%d\t%h\t%s\t%s\t", $time, cycle, rvfi_pc_rdata, rvfi_insn_str, decoded_str); - if ((data_accessed & RS1) != 0) begin - $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs1_addr), rvfi_rs1_rdata); - end - if ((data_accessed & RS2) != 0) begin - $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs2_addr), rvfi_rs2_rdata); - end - if ((data_accessed & RS3) != 0) begin - $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs3_addr), rvfi_rs3_rdata); - end - if ((data_accessed & RD) != 0) begin - $fwrite(file_handle, " %s=0x%08x", reg_addr_to_str(rvfi_rd_addr), rvfi_rd_wdata); + if (insn_is_float) begin + if ((data_accessed & RS1) != 0) begin + if (float_wx | float_sw) + $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs1_addr), rvfi_rs1_rdata); + else + $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_frs1_addr), rvfi_frs1_rdata); + end + if ((data_accessed & RS2)) begin + if (float_sw) + $fwrite(file_handle, " %s:0x%08x", $sformatf("f%0d", rvfi_frs2_addr), rvfi_frs2_rdata); + else + $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_frs2_addr), rvfi_frs2_rdata); + end + if ((data_accessed & RS3)) begin + $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_frs3_addr), rvfi_frs3_rdata); + end + if ((data_accessed & RD) != 0) begin + if (float_xw | float_class | float_comp) + $fwrite(file_handle, " %s=0x%08x", reg_addr_to_str_rd(rvfi_rd_addr), rvfi_rd_wdata); + else + $fwrite(file_handle, " %s=0x%08x", reg_addr_to_str_rd(rvfi_frd_addr), rvfi_frd_wdata); + end + end else begin + if ((data_accessed & RS1) != 0) begin + $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs1_addr), rvfi_rs1_rdata); + end + if ((data_accessed & RS2) != 0) begin + $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs2_addr), rvfi_rs2_rdata); + end + if ((data_accessed & RS3) != 0) begin + $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs3_addr), rvfi_rs3_rdata); + end + if ((data_accessed & RD) != 0) begin + $fwrite(file_handle, " %s=0x%08x", reg_addr_to_str(rvfi_rd_addr), rvfi_rd_wdata); + end end + if ((data_accessed & MEM) != 0) begin $fwrite(file_handle, " PA:0x%08x", rvfi_mem_addr); @@ -156,13 +196,49 @@ module ibex_tracer ( $fwrite(file_handle, "\n"); endfunction - - // Format register address with "x" prefix, left-aligned to a fixed width of 3 characters. + // Format register address with "x" or "f" prefix, left-aligned to a fixed width of 3 characters. function automatic string reg_addr_to_str(input logic [4:0] addr); if (addr < 10) begin - return $sformatf(" x%0d", addr); + if (insn_is_float) begin + if (float_wx | float_lw | float_sw) + return $sformatf(" x%0d", addr); + else + return $sformatf(" f%0d", addr); + end else begin + return $sformatf(" x%0d", addr); + end + end else begin + if (insn_is_float) begin + if (float_wx | float_lw | float_sw) + return $sformatf("x%0d", addr); + else + return $sformatf("f%0d", addr); + end else begin + return $sformatf("x%0d", addr); + end + end + endfunction + + // Format register address with "x" or "f" prefix, left-aligned to a fixed width of 3 characters. + function automatic string reg_addr_to_str_rd(input logic [4:0] addr); + if (addr < 10) begin + if (insn_is_float) begin + if (float_xw | float_sw | float_class | float_comp) + return $sformatf(" x%0d", addr); + else + return $sformatf(" f%0d", addr); + end else begin + return $sformatf(" x%0d", addr); + end end else begin - return $sformatf("x%0d", addr); + if (insn_is_float) begin + if (float_xw | float_sw | float_class | float_comp) + return $sformatf("x%0d", addr); + else + return $sformatf("f%0d", addr); + end else begin + return $sformatf("x%0d", addr); + end end endfunction @@ -727,6 +803,125 @@ module ibex_tracer ( decoded_str = $sformatf("fence\t%s,%s", predecessor, successor); endfunction + function automatic void decode_fused_ma(input string mnemonic); + insn_is_float = 1'b1; + data_accessed = RS1 | RS2 | RS3 | RD; + decoded_str = $sformatf("%s\tf%0d,f%0d,f%0d,f%0d", mnemonic, rvfi_frd_addr, rvfi_frs1_addr, + rvfi_frs2_addr, rvfi_frs2_addr); + endfunction + + function automatic void decode_fr_insn(input string mnemonic); + insn_is_float = 1'b1; + data_accessed = RS1 | RS2 | RD; + decoded_str = $sformatf("%s\tf%0d,f%0d,f%0d", mnemonic, rvfi_frd_addr, rvfi_frs1_addr, + rvfi_frs2_addr); + endfunction + + function automatic void decode_fsqrt(input string mnemonic); + insn_is_float = 1'b1; + data_accessed = RS1 | RD; + decoded_str = $sformatf("%s\tx%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_frs1_addr); + endfunction + + function automatic void decode_fcvt_f2i(input string mnemonic); + insn_is_float = 1'b1; + float_xw = 1; + data_accessed = RS1 | RD; + decoded_str = $sformatf("%s\tx%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_frs1_addr); + endfunction + + function automatic void decode_fcvt_i2f(input string mnemonic); + insn_is_float = 1'b1; + float_wx = 1; + data_accessed = RS1 | RD; + decoded_str = $sformatf("%s\tf%0d,x%0d", mnemonic, rvfi_frd_addr, rvfi_rs1_addr); + endfunction + + function automatic void decode_fcomp(input string mnemonic); + insn_is_float = 1'b1; + float_comp = 1'b1; + data_accessed = RS2 | RS1 | RD; + decoded_str = $sformatf("%s\tx%0d,f%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_frs1_addr, + rvfi_frs2_addr); + endfunction + + function automatic void decode_fmin_max(input string mnemonic); + insn_is_float = 1'b1; + data_accessed = RS2 | RS1 | RD; + decoded_str = $sformatf("%s\tf%0d,f%0d,f%0d", mnemonic, rvfi_frd_addr, rvfi_frs1_addr, + rvfi_frs2_addr); + endfunction + + function automatic void decode_fsgnj(input string mnemonic); + insn_is_float = 1'b1; + data_accessed = RS2 | RS1 | RD; + decoded_str = $sformatf("%s\tf%0d,f%0d,f%0d", mnemonic, rvfi_frd_addr, rvfi_frs1_addr, + rvfi_frs2_addr); + endfunction + + function automatic void decode_fmv_xw(input string mnemonic); + insn_is_float = 1'b1; + float_xw = 1'b1; + data_accessed = RS1 | RD; + decoded_str = $sformatf("%s\tx%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_frs1_addr); + endfunction + + function automatic void decode_fmv_wx(input string mnemonic); + insn_is_float = 1'b1; + float_wx = 1'b1; + data_accessed = RS1 | RD; + decoded_str = $sformatf("%s\tf%0d,x%0d", mnemonic, rvfi_frd_addr, rvfi_rs1_addr); + endfunction + + function automatic void decode_fclass(input string mnemonic); + insn_is_float = 1'b1; + float_class = 1'b1; + data_accessed = RS1 | RD; + decoded_str = $sformatf("%s\tx%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_frs1_addr); + endfunction + + function automatic void decode_fload_insn(); + string mnemonic; + logic [2:0] size; + float_lw = 1; + size = rvfi_insn[14:12]; + insn_is_float = 1'b1; + + if (size == 3'b010) begin + mnemonic = "flw"; + end else begin + decode_mnemonic("INVALID"); + return; + end + + data_accessed = RD | RS1 | MEM; + decoded_str = $sformatf("%s\tf%0d,%0d(x%0d)", mnemonic, rvfi_frd_addr, + $signed({{20 {rvfi_insn[31]}}, rvfi_insn[31:20]}), rvfi_rs1_addr); + endfunction + + function automatic void decode_fstore_insn(); + string mnemonic; + insn_is_float = 1'b1; + + unique case (rvfi_insn[13:12]) + 2'b10: mnemonic = "fsw"; + default: begin + decode_mnemonic("INVALID"); + return; + end + endcase + + if (!rvfi_insn[14]) begin + // floating point store + float_sw = 1; + data_accessed = RS1 | RS2 | MEM; + decoded_str = $sformatf("%s\tf%0d,%0d(x%0d)", mnemonic, rvfi_frs2_addr, + $signed({ {20 {rvfi_insn[31]}}, rvfi_insn[31:25], rvfi_insn[11:7] }), rvfi_rs1_addr); + end else begin + decode_mnemonic("INVALID"); + end + endfunction + // cycle counter always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin @@ -754,6 +949,13 @@ module ibex_tracer ( decoded_str = ""; data_accessed = 5'h0; insn_is_compressed = 0; + insn_is_float = 0; + float_wx = 0; + float_xw = 0; + float_lw = 0; + float_sw = 0; + float_comp = 0; + float_class = 0; // Check for compressed instructions if (rvfi_insn[1:0] != 2'b11) begin @@ -1042,6 +1244,53 @@ module ibex_tracer ( INSN_CRC32C_H: decode_r1_insn("crc32c.h"); INSN_CRC32C_W: decode_r1_insn("crc32c.w"); + // Single Precision Floating Point + // Floating Load & Store + INSN_FLOAD: decode_fload_insn(); + INSN_FSTORE: decode_fstore_insn(); + + // Fused Multiply & Add Instructions + INSN_FMADD: decode_fused_ma("fmadd.s"); + INSN_FMSUB: decode_fused_ma("fmsub.s"); + INSN_FNMADD: decode_fused_ma("fnmadd.s"); + INSN_FNMSUB: decode_fused_ma("fnmsub.s"); + + // Arithmetic + INSN_FADD: decode_fr_insn("fadd.s"); + INSN_FSUB: decode_fr_insn("fsub.s"); + INSN_FMUL: decode_fr_insn("fmul.s"); + INSN_FDIV: decode_fr_insn("fdiv.s"); + + // Sqaure root + INSN_FSQRT: decode_fsqrt("fsqrt.s"); + + // Conversion + INSN_FCVTWS: decode_fcvt_f2i("fcvt.w.s"); + INSN_FCVTWUS: decode_fcvt_f2i("fcvt.wu.s"); + INSN_FCVTSW: decode_fcvt_i2f("fcvt.s.w"); + INSN_FCVTSWU: decode_fcvt_i2f("fcvt.s.wu"); + + // Comparison + INSN_FEQ: decode_fcomp("feq.s"); + INSN_FLT: decode_fcomp("flt.s"); + INSN_FLE: decode_fcomp("fle.s"); + + // Min & Max + INSN_FMIN: decode_fmin_max("fmin.s"); + INSN_FMAX: decode_fmin_max("fmax.s"); + + // Sign Injection + INSN_FSGNJ: decode_fsgnj("fsgnj.s"); + INSN_FSGNJN: decode_fsgnj("fsgnjn.s"); + INSN_FSGNJX: decode_fsgnj("fsgnjx.s"); + + // Move + INSN_FMVXW: decode_fmv_xw("fmv.x.w"); + INSN_FMVWX: decode_fmv_wx("fmv.w.x"); + + // Determine class of FP result + INSN_FCLASS: decode_fclass("fclass.s"); + default: decode_mnemonic("INVALID"); endcase end diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv index d42d4c94..5816c958 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv @@ -71,6 +71,41 @@ parameter logic [31:0] INSN_PMUH = { 7'b0000001, 10'h?, 3'b001, 5'h?, {OPCODE parameter logic [31:0] INSN_PMULHSU = { 7'b0000001, 10'h?, 3'b010, 5'h?, {OPCODE_OP} }; parameter logic [31:0] INSN_PMULHU = { 7'b0000001, 10'h?, 3'b011, 5'h?, {OPCODE_OP} }; +// RV32F +// Floating Load & Store +parameter logic [31:0] INSN_FLOAD = { 17'h?, 3'b010, 5'h?, {OPCODE_LOAD_FP } }; +parameter logic [31:0] INSN_FSTORE = { 17'h?, 3'b010, 5'h?, {OPCODE_STORE_FP} }; +// Fused Multiply & Add Instructions +parameter logic [31:0] INSN_FMADD = { 5'h?, 2'b00, 18'h?, {OPCODE_MADD_FP} }; +parameter logic [31:0] INSN_FMSUB = { 5'h?, 2'b00, 18'h?, {OPCODE_MSUB_FP} }; +parameter logic [31:0] INSN_FNMADD = { 5'h?, 2'b00, 18'h?, {OPCODE_NMADD_FP} }; +parameter logic [31:0] INSN_FNMSUB = { 5'h?, 2'b00, 18'h?, {OPCODE_NMSUB_FP} }; +// Arithmetic +parameter logic [31:0] INSN_FADD = { 7'b0000000, 18'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FSUB = { 7'b0000100, 18'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FMUL = { 7'b0001000, 18'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FDIV = { 7'b0001100, 18'h?, {OPCODE_OP_FP} }; +// SQRT & Conversion +parameter logic [31:0] INSN_FSQRT = { 7'b0101100, 5'b00000, 13'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FCVTWS = { 7'b1100000, 5'b00000, 13'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FCVTWUS = { 7'b1100000, 5'b00001, 13'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FCVTSW = { 7'b1101000, 5'b00000, 13'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FCVTSWU = { 7'b1101000, 5'b00001, 13'h?, {OPCODE_OP_FP} }; +// Comparison +parameter logic [31:0] INSN_FEQ = { 7'b1010000, 10'h?, 3'b010, 5'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FLT = { 7'b1010000, 10'h?, 3'b001, 5'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FLE = { 7'b1010000, 10'h?, 3'b000, 5'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FMIN = { 7'b0010100, 10'h?, 3'b000, 5'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FMAX = { 7'b0010100, 10'h?, 3'b001, 5'h?, {OPCODE_OP_FP} }; +// Sign Injection +parameter logic [31:0] INSN_FSGNJ = { 7'b0010000, 10'h?, 3'b000, 5'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FSGNJN = { 7'b0010000, 10'h?, 3'b001, 5'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FSGNJX = { 7'b0010000, 10'h?, 3'b010, 5'h?, {OPCODE_OP_FP} }; +// Move & Class +parameter logic [31:0] INSN_FMVXW = { 7'b1110000, 5'b00000, 5'h?, 3'b000, 5'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FMVWX = { 7'b1111000, 5'b00000, 5'h?, 3'b000, 5'h?, {OPCODE_OP_FP} }; +parameter logic [31:0] INSN_FCLASS = { 7'b1110000, 5'b00000, 5'h?, 3'b001, 5'h?, {OPCODE_OP_FP} }; + // RV32B // ZBB parameter logic [31:0] INSN_SLOI = { 5'b00100 , 12'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} }; diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv index 3c7319b5..fac995a7 100644 --- a/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv +++ b/hw/vendor/lowrisc_ibex/rtl/ibex_wb_stage.sv @@ -150,19 +150,21 @@ module ibex_wb_stage #( // floating point if (RVF == RV32FSingle || RVF == RV32DDouble) begin logic [FPU_WIDTH-1:0] fp_rf_wdata_wb_q; + logic [4:0] fp_rf_waddr_wb_q; logic fp_rf_we_wb_q; logic fp_load_q; always_ff @(posedge clk_i) begin if(en_wb_i) begin fp_rf_we_wb_q <= fp_rf_wen_id_i; + fp_rf_waddr_wb_q <= fp_rf_waddr_id_i; fp_rf_wdata_wb_q <= fp_rf_wdata_id_i; fp_load_q <= fp_load_i; end end - assign fp_rf_waddr_wb_o = rf_waddr_wb_q; // no seperate datapath for rd address - assign fp_rf_wdata_wb_mux[0] = rf_wdata_wb_q; // no seperate datapath for data bus + assign fp_rf_waddr_wb_o = fp_rf_waddr_wb_q; + assign fp_rf_wdata_wb_mux[0] = fp_rf_wdata_wb_q; assign fp_rf_wdata_wb_mux_we[0] = fp_rf_we_wb_q & wb_valid_q; // Instruction in writeback will be writing to register file if either rf_we is set or writeback @@ -177,6 +179,7 @@ module ibex_wb_stage #( assign rf_wdata_wb_mux_we[1] = rf_we_lsu_i; assign unused_fpu_wires = &{1'b0, fp_rf_wen_id_i, + fp_rf_waddr_id_i, fp_rf_wdata_id_i, fp_load_i, 1'b0}; diff --git a/hw/vendor/pulp_fpnew/src/fpnew_cast_multi.sv b/hw/vendor/pulp_fpnew/src/fpnew_cast_multi.sv index 9d54c79e..8db2ee95 100644 --- a/hw/vendor/pulp_fpnew/src/fpnew_cast_multi.sv +++ b/hw/vendor/pulp_fpnew/src/fpnew_cast_multi.sv @@ -542,7 +542,8 @@ module fpnew_cast_multi #( .effective_subtraction_i ( 1'b0 ), // no operation happened .abs_rounded_o ( rounded_abs ), .sign_o ( rounded_sign ), - .exact_zero_o ( result_true_zero ) + .exact_zero_o ( result_true_zero ), + .op_i ( op_i ) ); logic [NUM_FORMATS-1:0][WIDTH-1:0] fmt_result; diff --git a/hw/vendor/pulp_fpnew/src/fpnew_divsqrt_multi.sv b/hw/vendor/pulp_fpnew/src/fpnew_divsqrt_multi.sv index 1331f5fe..929c0351 100644 --- a/hw/vendor/pulp_fpnew/src/fpnew_divsqrt_multi.sv +++ b/hw/vendor/pulp_fpnew/src/fpnew_divsqrt_multi.sv @@ -198,11 +198,12 @@ module fpnew_divsqrt_multi #( out_valid = 1'b1; // try to commit result downstream // If downstream accepts our result if (out_ready) begin - state_d = IDLE; // we anticipate going back to idling.. if (in_valid_q && unit_ready) begin // ..unless new work comes in in_ready = 1'b1; // we acknowledge the instruction - state_d = BUSY; // and stay busy with it + // state_d = BUSY; // and stay busy with it + state_d = IDLE; end + // state_d = IDLE; // we anticipate going back to idling.. // Otherwise if downstream is not ready for the result end else begin hold_result = 1'b1; // activate the hold register diff --git a/hw/vendor/pulp_fpnew/src/fpnew_fma.sv b/hw/vendor/pulp_fpnew/src/fpnew_fma.sv index f9fa813b..7947835c 100644 --- a/hw/vendor/pulp_fpnew/src/fpnew_fma.sv +++ b/hw/vendor/pulp_fpnew/src/fpnew_fma.sv @@ -593,7 +593,8 @@ module fpnew_fma #( .effective_subtraction_i ( effective_subtraction_q ), .abs_rounded_o ( rounded_abs ), .sign_o ( rounded_sign ), - .exact_zero_o ( result_zero ) + .exact_zero_o ( result_zero ), + .op_i ( op_i ) ); // Classification after rounding diff --git a/hw/vendor/pulp_fpnew/src/fpnew_fma_multi.sv b/hw/vendor/pulp_fpnew/src/fpnew_fma_multi.sv index 712dfcd9..12cc12ac 100644 --- a/hw/vendor/pulp_fpnew/src/fpnew_fma_multi.sv +++ b/hw/vendor/pulp_fpnew/src/fpnew_fma_multi.sv @@ -716,7 +716,8 @@ module fpnew_fma_multi #( .effective_subtraction_i ( effective_subtraction_q ), .abs_rounded_o ( rounded_abs ), .sign_o ( rounded_sign ), - .exact_zero_o ( result_zero ) + .exact_zero_o ( result_zero ), + .op_i ( op_i ) ); logic [NUM_FORMATS-1:0][WIDTH-1:0] fmt_result; diff --git a/hw/vendor/pulp_fpnew/src/fpnew_rounding.sv b/hw/vendor/pulp_fpnew/src/fpnew_rounding.sv index 60f63bb7..899eb849 100644 --- a/hw/vendor/pulp_fpnew/src/fpnew_rounding.sv +++ b/hw/vendor/pulp_fpnew/src/fpnew_rounding.sv @@ -25,7 +25,9 @@ module fpnew_rounding #( output logic [AbsWidth-1:0] abs_rounded_o, // absolute value without sign output logic sign_o, // Output classification - output logic exact_zero_o // output is an exact zero + output logic exact_zero_o, // output is an exact zero + // Testing input + input fpnew_pkg::operation_e op_i ); logic round_up; // Rounding decision @@ -66,7 +68,7 @@ module fpnew_rounding #( // In case of effective subtraction (thus signs of addition operands must have differed) and a // true zero result, the result sign is '-' in case of RDN and '+' for other modes. assign sign_o = (exact_zero_o && effective_subtraction_i) - ? (rnd_mode_i == fpnew_pkg::RDN) + ? ((rnd_mode_i == fpnew_pkg::RDN) & (op_i != fpnew_pkg::MUL)) : sign_i; endmodule