diff --git a/src/fpu/fcmp.sv b/src/fpu/fcmp.sv index 9d0d582b5..e330f1fda 100755 --- a/src/fpu/fcmp.sv +++ b/src/fpu/fcmp.sv @@ -36,6 +36,7 @@ module fcmp import cvw::*; #(parameter cvw_t P) ( input logic [P.FMTBITS-1:0] Fmt, // format of fp number input logic [2:0] OpCtrl, // see above table + input logic Zfa, // Zfa variants: fminm, fmaxm, fleq, fltq input logic Xs, Ys, // input signs input logic [P.NE-1:0] Xe, Ye, // input exponents input logic [P.NF:0] Xm, Ym, // input mantissa @@ -70,8 +71,8 @@ module fcmp import cvw::*; #(parameter cvw_t P) ( 3'b110: CmpNV = EitherSNaN; //min 3'b101: CmpNV = EitherSNaN; //max 3'b010: CmpNV = EitherSNaN; //equal - 3'b001: CmpNV = EitherNaN; //less than - 3'b011: CmpNV = EitherNaN; //less than or equal + 3'b001: CmpNV = Zfa ? EitherSNaN : EitherNaN; // fltq / flt perform CompareQuietLess / CompareSignalingLess differing on when to set invalid + 3'b011: CmpNV = Zfa ? EitherSNaN : EitherNaN; // fleq / fle differ on when to set invalid default: CmpNV = 1'bx; endcase end @@ -128,23 +129,35 @@ module fcmp import cvw::*; #(parameter cvw_t P) ( // - if one is a NaN output the non-NaN always_comb if(OpCtrl[0]) // MAX - if(XNaN) - if(YNaN) CmpFpRes = NaNRes; // X = NaN Y = NaN - else CmpFpRes = Y; // X = NaN Y != NaN - else - if(YNaN) CmpFpRes = X; // X != NaN Y = NaN - else // X,Y != NaN - if(LT) CmpFpRes = Y; // X < Y - else CmpFpRes = X; // X > Y + if (Zfa & P.ZFA_SUPPORTED) // fmaxm perform IEEE754 maxNum that produce NaN if either input is NaN + if (XNaN | YNaN) CmpFpRes = NaNRes; // either input is NaN + else + if (LT) CmpFpRes = Y; // X < Y + else CmpFpRes = X; // X > Y + else // fmax performs IEEE754 maxNumber that produces NaN if both inputs are NaN + if(XNaN) + if(YNaN) CmpFpRes = NaNRes; // X = NaN Y = NaN + else CmpFpRes = Y; // X = NaN Y != NaN + else + if(YNaN) CmpFpRes = X; // X != NaN Y = NaN + else // X,Y != NaN + if(LT) CmpFpRes = Y; // X < Y + else CmpFpRes = X; // X > Y else // MIN - if(XNaN) - if(YNaN) CmpFpRes = NaNRes; // X = NaN Y = NaN - else CmpFpRes = Y; // X = NaN Y != NaN - else - if(YNaN) CmpFpRes = X; // X != NaN Y = NaN - else // X,Y != NaN - if(LT) CmpFpRes = X; // X < Y - else CmpFpRes = Y; // X > Y + if (Zfa & P.ZFA_SUPPORTED) // fminm perform IEEE754 minNum that produce NaN if either input is NaN + if (XNaN | YNaN) CmpFpRes = NaNRes; // either input is NaN + else + if (LT) CmpFpRes = X; // X < Y + else CmpFpRes = Y; // X > Y + else // fmin performs IEEE754 minNumber that produces NaN if both inputs are NaN + if(XNaN) + if(YNaN) CmpFpRes = NaNRes; // X = NaN Y = NaN + else CmpFpRes = Y; // X = NaN Y != NaN + else + if(YNaN) CmpFpRes = X; // X != NaN Y = NaN + else // X,Y != NaN + if(LT) CmpFpRes = X; // X < Y + else CmpFpRes = Y; // X > Y // LT/LE/EQ // - -0 = 0 diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index d4cc60e87..9f60a692f 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -54,6 +54,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( output logic [1:0] PostProcSelE, PostProcSelM, // select result in the post processing unit output logic [1:0] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage output logic FPUActiveE, // FP instruction being executed + output logic ZfaE, // Zfa variants of instructions (fli, fminm, fmaxm, fround, froundnx, fleq, fltq, fmvh, fmvp, fcvtmod) // register control signals output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable output logic FWriteIntE, FWriteIntM, // Write to integer register @@ -64,7 +65,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( output logic FDivStartE, IDivStartE // Start division or squareroot ); - `define FCTRLW 12 + `define FCTRLW 13 logic [`FCTRLW-1:0] ControlsD; // control signals logic FRegWriteD; // FP register write enable @@ -79,6 +80,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( logic SupportedFmt; // is the format supported logic SupportedFmt2; // is the source format supported for fp -> fp logic FCvtIntD, FCvtIntM; // convert to integer opperation + logic ZfaD; // Zfa variants of instructions // FPU Instruction Decoder assign Fmt = Funct7D[1:0]; @@ -91,129 +93,164 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( (Fmt2 == 2'b10 & P.ZFH_SUPPORTED) | (Fmt2 == 2'b11 & P.Q_SUPPORTED)); // decode the instruction - // FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt + // FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt_Zfa always_comb if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled - ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0; + ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0; else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt) - ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0; // for anything other than loads and stores, check for supported format + ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0; // for anything other than loads and stores, check for supported format else begin - ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0; // default: non-implemented instruction + ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0; // default: non-implemented instruction /* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed case(OpD) 7'b0000111: case(Funct3D) - 3'b010: ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flw - 3'b011: if (P.D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // fld - 3'b100: if (P.Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flq - 3'b001: if (P.ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flh + 3'b010: ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0_0; // flw + 3'b011: if (P.D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0_0; // fld + 3'b100: if (P.Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0_0; // flq + 3'b001: if (P.ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0_0; // flh endcase 7'b0100111: case(Funct3D) - 3'b010: ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsw - 3'b011: if (P.D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsd - 3'b100: if (P.Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsq - 3'b001: if (P.ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsh + 3'b010: ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0_0; // fsw + 3'b011: if (P.D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0_0; // fsd + 3'b100: if (P.Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0_0; // fsq + 3'b001: if (P.ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0_0; // fsh endcase - 7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0; // fmadd - 7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0; // fmsub - 7'b1001011: ControlsD = `FCTRLW'b1_0_01_10_010_0_0_0; // fnmsub - 7'b1001111: ControlsD = `FCTRLW'b1_0_01_10_011_0_0_0; // fnmadd + 7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0_0; // fmadd + 7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0_0; // fmsub + 7'b1001011: ControlsD = `FCTRLW'b1_0_01_10_010_0_0_0_0; // fnmsub + 7'b1001111: ControlsD = `FCTRLW'b1_0_01_10_011_0_0_0_0; // fnmadd 7'b1010011: casez(Funct7D) - 7'b00000??: ControlsD = `FCTRLW'b1_0_01_10_110_0_0_0; // fadd - 7'b00001??: ControlsD = `FCTRLW'b1_0_01_10_111_0_0_0; // fsub - 7'b00010??: ControlsD = `FCTRLW'b1_0_01_10_100_0_0_0; // fmul - 7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_xx0_1_0_0; // fdiv - 7'b01011??: if (Rs2D == 5'b0000) ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0_0; // fsqrt + 7'b00000??: ControlsD = `FCTRLW'b1_0_01_10_110_0_0_0_0; // fadd + 7'b00001??: ControlsD = `FCTRLW'b1_0_01_10_111_0_0_0_0; // fsub + 7'b00010??: ControlsD = `FCTRLW'b1_0_01_10_100_0_0_0_0; // fmul + 7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_xx0_1_0_0_0; // fdiv + 7'b01011??: if (Rs2D == 5'b0000) ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0_0_0; // fsqrt 7'b00100??: case(Funct3D) - 3'b000: ControlsD = `FCTRLW'b1_0_00_00_000_0_0_0; // fsgnj - 3'b001: ControlsD = `FCTRLW'b1_0_00_00_001_0_0_0; // fsgnjn - 3'b010: ControlsD = `FCTRLW'b1_0_00_00_010_0_0_0; // fsgnjx + 3'b000: ControlsD = `FCTRLW'b1_0_00_00_000_0_0_0_0; // fsgnj + 3'b001: ControlsD = `FCTRLW'b1_0_00_00_001_0_0_0_0; // fsgnjn + 3'b010: ControlsD = `FCTRLW'b1_0_00_00_010_0_0_0_0; // fsgnjx endcase 7'b00101??: case(Funct3D) - 3'b000: ControlsD = `FCTRLW'b1_0_00_00_110_0_0_0; // fmin - 3'b001: ControlsD = `FCTRLW'b1_0_00_00_101_0_0_0; // fmax + 3'b000: ControlsD = `FCTRLW'b1_0_00_00_110_0_0_0_0; // fmin + 3'b001: ControlsD = `FCTRLW'b1_0_00_00_101_0_0_0_0; // fmax + 3'b010: if (P.ZFA_SUPPORTED) ControlsD = `FCTRLW'b1_0_00_00_110_0_0_0_1; // fminm (Zfa) + 3'b011: if (P.ZFA_SUPPORTED) ControlsD = `FCTRLW'b1_0_00_00_101_0_0_0_1; // fmaxm (Zfa) endcase 7'b10100??: case(Funct3D) - 3'b010: ControlsD = `FCTRLW'b0_1_00_00_010_0_0_0; // feq - 3'b001: ControlsD = `FCTRLW'b0_1_00_00_001_0_0_0; // flt - 3'b000: ControlsD = `FCTRLW'b0_1_00_00_011_0_0_0; // fle + 3'b000: ControlsD = `FCTRLW'b0_1_00_00_011_0_0_0_0; // fle + 3'b001: ControlsD = `FCTRLW'b0_1_00_00_001_0_0_0_0; // flt + 3'b010: ControlsD = `FCTRLW'b0_1_00_00_010_0_0_0_0; // feq + 3'b100: if (P.ZFA_SUPPORTED) ControlsD = `FCTRLW'b0_1_00_00_011_0_0_0_1; // fleq (Zfa) + 3'b101: if (P.ZFA_SUPPORTED) ControlsD = `FCTRLW'b0_1_00_00_001_0_0_0_1; // fltq (Zfa) endcase 7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000) - ControlsD = `FCTRLW'b0_1_10_00_000_0_0_0; // fclass + ControlsD = `FCTRLW'b0_1_10_00_000_0_0_0_0; // fclass else if (Funct3D == 3'b000 & Rs2D == 5'b00000) - ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0; // fmv.x.w/d/h/q fp to int register + ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_0; // fmv.x.w/d/h/q fp to int register + else if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct7D[1:0] == 2'b01 & Funct3D == 3'b000 & Rs2D == 5'b00001) + ControlsD = '0; // fmvh.x.d (Zfa) *** needs values for all moves + // coverage off Q not supported in RV64GC + else if (P.ZFA_SUPPORTED & P.XLEN == 64 & P.Q_SUPPORTED & Funct7D[1:0] == 2'b11 & Funct3D == 3'b000 & Rs2D == 5'b00001) + ControlsD = '0; // fmvh.x.q (Zfa) + // coverage on 7'b11110??: if (Funct3D == 3'b000 & Rs2D == 5'b00000) - ControlsD = `FCTRLW'b1_0_00_00_011_0_0_0; // fmv.w/d/h/q.x int to fp reg + ControlsD = `FCTRLW'b1_0_00_00_011_0_0_0_0; // fmv.w/d/h/q.x int to fp reg else if (P.ZFA_SUPPORTED & Funct3D == 3'b000 & Rs2D == 5'b00001) - ControlsD = `FCTRLW'b1_0_00_00_111_0_0_0; // fli + ControlsD = `FCTRLW'b1_0_00_00_111_0_0_0_1; // fli (Zfa) 7'b0100000: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b00) - ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.(d/q/h) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_0; // fcvt.s.(d/q/h) + else if (Rs2D == 5'b00100 & P.ZFA_SUPPORTED) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_1; // fround.s (Zfa) *** needs ctrl for all rounds + else if (Rs2D == 5'b00101 & P.ZFA_SUPPORTED) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_1; // froundnx.s (Zfa) *** needs ctrl for all rounds 7'b0100001: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b01) - ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.(s/h/q) - // coverage off + ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0_0; // fcvt.d.(s/h/q) + else if (Rs2D == 5'b00100 & P.ZFA_SUPPORTED) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_1; // fround.d (Zfa) + else if (Rs2D == 5'b00101 & P.ZFA_SUPPORTED) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_1; // froundnx.d (Zfa) 7'b0100010: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b10) - ControlsD = `FCTRLW'b1_0_01_00_010_0_0_0; // fcvt.h.(s/d/q) + ControlsD = `FCTRLW'b1_0_01_00_010_0_0_0_0; // fcvt.h.(s/d/q) + else if (Rs2D == 5'b00100 & P.ZFA_SUPPORTED) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_1; // fround.h (Zfa) + else if (Rs2D == 5'b00101 & P.ZFA_SUPPORTED) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_1; // froundnx.h (Zfa) + // coverage off // Not covered in testing because rv64gc does not support quad precision 7'b0100011: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b11) - ControlsD = `FCTRLW'b1_0_01_00_011_0_0_0; // fcvt.q.(s/h/d) + ControlsD = `FCTRLW'b1_0_01_00_011_0_0_0_0; // fcvt.q.(s/h/d) + else if (Rs2D == 5'b00100 & P.ZFA_SUPPORTED) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_1; // fround.q (Zfa) + else if (Rs2D == 5'b00101 & P.ZFA_SUPPORTED) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0_1; // froundnx.q (Zfa) // coverage on 7'b1101000: case(Rs2D) - 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s - 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s - 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s - 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s + 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0; // fcvt.s.w w->s + 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0_0; // fcvt.s.wu wu->s + 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0_0; // fcvt.s.l l->s + 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0_0; // fcvt.s.lu lu->s endcase 7'b1100000: case(Rs2D) - 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w - 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu - 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l - 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu + 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1_0; // fcvt.w.s s->w + 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1_0; // fcvt.wu.s s->wu + 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1_0; // fcvt.l.s s->l + 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1_0; // fcvt.lu.s s->lu endcase 7'b1101001: case(Rs2D) - 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d - 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d - 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d - 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d + 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0; // fcvt.d.w w->d + 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0_0; // fcvt.d.wu wu->d + 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0_0; // fcvt.d.l l->d + 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0_0; // fcvt.d.lu lu->d endcase 7'b1100001: case(Rs2D) - 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w - 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu - 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l - 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu + 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1_0; // fcvt.w.d d->w + 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1_0; // fcvt.wu.d d->wu + 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1_0; // fcvt.l.d d->l + 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1_0; // fcvt.lu.d d->lu + 5'b01000: if (P.ZFA_SUPPORTED & P.D_SUPPORTED & Funct3D == 3'b001) + ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1_1; // fcvtmod.w.d (Zfa) endcase - // coverage off 7'b1101010: case(Rs2D) - 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.h.w w->h - 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.h.wu wu->h - 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.h.l l->h - 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.h.lu lu->h + 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0; // fcvt.h.w w->h + 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0_0; // fcvt.h.wu wu->h + 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0_0; // fcvt.h.l l->h + 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0_0; // fcvt.h.lu lu->h endcase 7'b1100010: case(Rs2D) - 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.h h->w - 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.h h->wu - 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.h h->l - 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.h h->lu + 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1_0; // fcvt.w.h h->w + 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1_0; // fcvt.wu.h h->wu + 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1_0; // fcvt.l.h h->l + 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1_0; // fcvt.lu.h h->lu endcase // Not covered in testing because rv64gc does not support quad precision + // coverage off 7'b1101011: case(Rs2D) - 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.q.w w->q - 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.q.wu wu->q - 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.q.l l->q - 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.q.lu lu->q + 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0; // fcvt.q.w w->q + 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0_0; // fcvt.q.wu wu->q + 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0_0; // fcvt.q.l l->q + 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0_0; // fcvt.q.lu lu->q endcase 7'b1100011: case(Rs2D) - 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.q q->w - 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.q q->wu - 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.q q->l - 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.q q->lu + 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1_0; // fcvt.w.q q->w + 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1_0; // fcvt.wu.q q->wu + 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1_0; // fcvt.l.q q->l + 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1_0; // fcvt.lu.q q->lu endcase // coverage on - endcase + 7'b1011001: if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct3D == 3'b000) + ControlsD = '0; // fmvp.d.x (Zfa) + // Not covered in testing because rv64gc does not support quad precision + // coverage off + 7'b1011011: if (P.ZFA_SUPPORTED & P.XLEN == 64 & P.Q_SUPPORTED & Funct3D == 3'b000) + ControlsD = '0; // fmvp.q.x (Zfa) + // coverage on + endcase endcase end /* verilator lint_on CASEINCOMPLETE */ // unswizzle control bits - assign #1 {FRegWriteD, FWriteIntD, FResSelD, PostProcSelD, OpCtrlD, FDivStartD, IllegalFPUInstrD, FCvtIntD} = ControlsD; + assign #1 {FRegWriteD, FWriteIntD, FResSelD, PostProcSelD, OpCtrlD, FDivStartD, IllegalFPUInstrD, FCvtIntD, ZfaD} = ControlsD; // rounding modes: // 000 - round to nearest, ties to even @@ -313,9 +350,9 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( assign Adr3D = InstrD[31:27]; // D/E pipleine register - flopenrc #(14+P.FMTBITS) DECtrlReg3(clk, reset, FlushE, ~StallE, - {FRegWriteD, PostProcSelD, FResSelD, FrmD, FmtD, OpCtrlD, FWriteIntD, FCvtIntD, ~IllegalFPUInstrD}, - {FRegWriteE, PostProcSelE, FResSelE, FrmE, FmtE, OpCtrlE, FWriteIntE, FCvtIntE, FPUActiveE}); + flopenrc #(15+P.FMTBITS) DECtrlReg3(clk, reset, FlushE, ~StallE, + {FRegWriteD, PostProcSelD, FResSelD, FrmD, FmtD, OpCtrlD, FWriteIntD, FCvtIntD, ZfaD, ~IllegalFPUInstrD}, + {FRegWriteE, PostProcSelE, FResSelE, FrmE, FmtE, OpCtrlE, FWriteIntE, FCvtIntE, ZfaE, FPUActiveE}); flopenrc #(15) DEAdrReg(clk, reset, FlushE, ~StallE, {Adr1D, Adr2D, Adr3D}, {Adr1E, Adr2E, Adr3E}); flopenrc #(1) DEFDivStartReg(clk, reset, FlushE, ~StallE|FDivBusyE, FDivStartD, FDivStartE); flopenrc #(3) DEEnReg(clk, reset, FlushE, ~StallE, {XEnD, YEnD, ZEnD}, {XEnE, YEnE, ZEnE}); diff --git a/src/fpu/fpu.sv b/src/fpu/fpu.sv index 8be0e4488..bd387f5d7 100755 --- a/src/fpu/fpu.sv +++ b/src/fpu/fpu.sv @@ -83,6 +83,7 @@ module fpu import cvw::*; #(parameter cvw_t P) ( logic XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation logic FRegWriteE; // Write floating-point register logic FPUActiveE; // FP instruction being executed + logic ZfaE; // Zfa variants of instructions (fli, fminm, fmaxm, fround, froundnx, fleq, fltq, fmvh, fmvp, fcvtmod.w.d) // regfile signals logic [P.FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage @@ -170,7 +171,7 @@ module fpu import cvw::*; #(parameter cvw_t P) ( fctrl #(P) fctrl (.Funct7D(InstrD[31:25]), .OpD(InstrD[6:0]), .Rs2D(InstrD[24:20]), .Funct3D(InstrD[14:12]), .IntDivE, .InstrD, .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, .FRM_REGW, .STATUS_FS, .FDivBusyE, - .reset, .clk, .FRegWriteE, .FRegWriteM, .FRegWriteW, .FrmM, .FmtE, .FmtM, + .reset, .clk, .FRegWriteE, .FRegWriteM, .FRegWriteW, .ZfaE, .FrmM, .FmtE, .FmtM, .FDivStartE, .IDivStartE, .FWriteIntE, .FCvtIntE, .FWriteIntM, .OpCtrlE, .OpCtrlM, .FpLoadStoreM, .IllegalFPUInstrD, .XEnD, .YEnD, .ZEnD, .XEnE, .YEnE, .ZEnE, .FResSelE, .FResSelM, .FResSelW, .FPUActiveE, .PostProcSelE, .PostProcSelM, .FCvtIntW, @@ -247,7 +248,7 @@ module fpu import cvw::*; #(parameter cvw_t P) ( .UmM, .FIntDivResultM); // compare: fmin/fmax, flt/fle/feq - fcmp #(P) fcmp (.Fmt(FmtE), .OpCtrl(OpCtrlE), .Xs(XsE), .Ys(YsE), .Xe(XeE), .Ye(YeE), + fcmp #(P) fcmp (.Fmt(FmtE), .OpCtrl(OpCtrlE), .Zfa(ZfaE), .Xs(XsE), .Ys(YsE), .Xe(XeE), .Ye(YeE), .Xm(XmE), .Ym(YmE), .XZero(XZeroE), .YZero(YZeroE), .XNaN(XNaNE), .YNaN(YNaNE), .XSNaN(XSNaNE), .YSNaN(YSNaNE), .X(XE), .Y(YE), .CmpNV(CmpNVE), .CmpFpRes(CmpFpResE), .CmpIntRes(CmpIntResE)); diff --git a/testbench/tests.vh b/testbench/tests.vh index 86f65eb14..43cbc91a0 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -1999,16 +1999,58 @@ string arch64zbs[] = '{ string arch32zfaf[] = '{ `RISCVARCHTEST, - "rv32i_m/F_Zfa/src/fle_b1-01.S", - "rv32i_m/F_Zfa/src/fle_b19-01.S", - "rv32i_m/F_Zfa/src/fli_b1-01.S", + "rv32i_m/F_Zfa/src/fleq_b1-01.S", + "rv32i_m/F_Zfa/src/fleq_b19-01.S", + "rv32i_m/F_Zfa/src/fli.s-01.S", "rv32i_m/F_Zfa/src/fltq_b1-01.S", "rv32i_m/F_Zfa/src/fltq_b19-01.S", - "rv32i_m/F_Zfa/src/fmin_b1-01.S", - "rv32i_m/F_Zfa/src/fmin_b19-01.S", - "rv32i_m/F_Zfa/src/fmax_b1-01.S", - "rv32i_m/F_Zfa/src/fmax_b19-01.S", - "rv32i_m/F_Zfa/src/fround_b1-01.S" + "rv32i_m/F_Zfa/src/fminm_b1-01.S", + "rv32i_m/F_Zfa/src/fminm_b19-01.S", + "rv32i_m/F_Zfa/src/fmaxm_b1-01.S", + "rv32i_m/F_Zfa/src/fmaxm_b19-01.S" +/* "rv32i_m/F_Zfa/src/fround_b1-01.S" */ + }; + + string arch32zfad[] = '{ + `RISCVARCHTEST, + "rv32i_m/D_Zfa/src/fleq_b1-01.S", + "rv32i_m/D_Zfa/src/fleq_b19-01.S", + "rv32i_m/D_Zfa/src/fli.d-01.S", + "rv32i_m/D_Zfa/src/fltq_b1-01.S", + "rv32i_m/D_Zfa/src/fltq_b19-01.S", + "rv32i_m/D_Zfa/src/fminm_b1-01.S", + "rv32i_m/D_Zfa/src/fminm_b19-01.S", + "rv32i_m/D_Zfa/src/fmaxm_b1-01.S", + "rv32i_m/D_Zfa/src/fmaxm_b19-01.S" +/* "rv32i_m/D_Zfa/src/fround_b1-01.S" */ + }; + + string arch64zfaf[] = '{ + `RISCVARCHTEST, + "rv64i_m/F_Zfa/src/fleq_b1-01.S", + "rv64i_m/F_Zfa/src/fleq_b19-01.S", + "rv64i_m/F_Zfa/src/fli.s-01.S", + "rv64i_m/F_Zfa/src/fltq_b1-01.S", + "rv64i_m/F_Zfa/src/fltq_b19-01.S", + "rv64i_m/F_Zfa/src/fminm_b1-01.S", + "rv64i_m/F_Zfa/src/fminm_b19-01.S", + "rv64i_m/F_Zfa/src/fmaxm_b1-01.S", + "rv64i_m/F_Zfa/src/fmaxm_b19-01.S" +/* "rv64i_m/F_Zfa/src/fround_b1-01.S" */ + }; + + string arch64zfad[] = '{ + `RISCVARCHTEST, + "rv64i_m/D_Zfa/src/fleq_b1-01.S", + "rv64i_m/D_Zfa/src/fleq_b19-01.S", + "rv64i_m/D_Zfa/src/fli.d-01.S", + "rv64i_m/D_Zfa/src/fltq_b1-01.S", + "rv64i_m/D_Zfa/src/fltq_b19-01.S", + "rv64i_m/D_Zfa/src/fminm_b1-01.S", + "rv64i_m/D_Zfa/src/fminm_b19-01.S", + "rv64i_m/D_Zfa/src/fmaxm_b1-01.S", + "rv64i_m/D_Zfa/src/fmaxm_b19-01.S" +/* "rv64i_m/D_Zfa/src/fround_b1-01.S" */ }; string arch32d_fma[] = '{