Update testbench-fp to run TestFloat for all FP operations

This commit is contained in:
James Stine 2023-04-11 22:16:20 -05:00
parent 4797f6ca5e
commit f5201da676
2 changed files with 115 additions and 108 deletions

View File

@ -1,4 +1,4 @@
</////////////////////////////////////////// ///////////////////////////////////////////
// //
// Written: me@KatherineParry.com // Written: me@KatherineParry.com
// Modified: 7/5/2022 // Modified: 7/5/2022
@ -26,32 +26,29 @@
`include "wally-config.vh" `include "wally-config.vh"
`include "tests-fp.vh" `include "tests-fp.vh"
// steps to run FMA Tests
// 1) create test vectors in riscv-wally/Tests/fp with: ./run-all.sh
// 2) go to cvw/testbench/fp/Tests
// 3) run ./sim-fma-batch
module testbenchfp; module testbenchfp;
parameter TEST="none"; parameter TEST="none";
string Tests[]; // list of tests to be run string Tests[]; // list of tests to be run
logic [2:0] OpCtrl[]; // list of op controls logic [2:0] OpCtrl[]; // list of op controls
logic [2:0] Unit[]; // list of units being tested logic [2:0] Unit[]; // list of units being tested
logic WriteInt[]; // Is being written to integer resgiter logic WriteInt[]; // Is being written to integer resgiter
logic [2:0] Frm[4:0] = {3'b100, 3'b010, 3'b011, 3'b001, 3'b000}; // rounding modes: rne-000, rz-001, ru-011, rd-010, rnm-100 logic [2:0] Frm[4:0] = {3'b100, 3'b010, 3'b011, 3'b001, 3'b000}; // rounding modes: rne-000, rz-001, ru-011, rd-010, rnm-100
logic [1:0] Fmt[]; // list of formats for the other units logic [1:0] Fmt[]; // list of formats for the other units
logic clk=0; logic clk=0;
logic [31:0] TestNum=0; // index for the test logic [31:0] TestNum=0; // index for the test
logic [31:0] OpCtrlNum=0; // index for OpCtrl logic [31:0] OpCtrlNum=0; // index for OpCtrl
logic [31:0] errors=0; // how many errors logic [31:0] errors=0; // how many errors
logic [31:0] VectorNum=0; // index for test vector logic [31:0] VectorNum=0; // index for test vector
logic [31:0] FrmNum=0; // index for rounding mode logic [31:0] FrmNum=0; // index for rounding mode
logic [`FLEN*4+7:0] TestVectors[8388609:0]; // list of test vectors logic [`FLEN*4+7:0] TestVectors[8388609:0]; // list of test vectors
logic [1:0] FmtVal; // value of the current Fmt logic [1:0] FmtVal; // value of the current Fmt
logic [2:0] UnitVal, OpCtrlVal, FrmVal; // value of the currnet Unit/OpCtrl/FrmVal logic [2:0] UnitVal, OpCtrlVal, FrmVal; // value of the currnet Unit/OpCtrl/FrmVal
logic WriteIntVal; // value of the current WriteInt logic WriteIntVal; // value of the current WriteInt
logic [`FLEN-1:0] X, Y, Z; // inputs read from TestFloat logic [`FLEN-1:0] X, Y, Z; // inputs read from TestFloat
logic [`FLEN-1:0] XPostBox; // inputs read from TestFloat
logic [`XLEN-1:0] SrcA; // integer input logic [`XLEN-1:0] SrcA; // integer input
logic [`FLEN-1:0] Ans; // correct answer from TestFloat logic [`FLEN-1:0] Ans; // correct answer from TestFloat
logic [`FLEN-1:0] Res; // result from other units logic [`FLEN-1:0] Res; // result from other units
@ -67,15 +64,15 @@ module testbenchfp;
logic [`NF:0] Xm, Ym, Zm; // mantissas of the inputs logic [`NF:0] Xm, Ym, Zm; // mantissas of the inputs
logic XNaN, YNaN, ZNaN; // is the input NaN logic XNaN, YNaN, ZNaN; // is the input NaN
logic XSNaN, YSNaN, ZSNaN; // is the input a signaling NaN logic XSNaN, YSNaN, ZSNaN; // is the input a signaling NaN
logic XSubnorm, ZSubnorm; // is the input denormalized logic XSubnorm, ZSubnorm; // is the input denormalized
logic XInf, YInf, ZInf; // is the input infinity logic XInf, YInf, ZInf; // is the input infinity
logic XZero, YZero, ZZero; // is the input zero logic XZero, YZero, ZZero; // is the input zero
logic XExpMax, YExpMax, ZExpMax; // is the input's exponent all ones logic XExpMax, YExpMax, ZExpMax; // is the input's exponent all ones
logic [`CVTLEN-1:0] CvtLzcInE; // input to the Leading Zero Counter (priority encoder) logic [`CVTLEN-1:0] CvtLzcInE; // input to the Leading Zero Counter (priority encoder)
logic IntZero; logic IntZero;
logic CvtResSgnE; logic CvtResSgnE;
logic [`NE:0] CvtCalcExpE; // the calculated expoent logic [`NE:0] CvtCalcExpE; // the calculated expoent
logic [`LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by logic [`LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by
logic [`DIVb:0] Quot; logic [`DIVb:0] Quot;
logic CvtResSubnormUfE; logic CvtResSubnormUfE;
logic DivStart, FDivBusyE, OldFDivBusyE; logic DivStart, FDivBusyE, OldFDivBusyE;
@ -102,6 +99,15 @@ module testbenchfp;
logic [`NE+1:0] DivCalcExp; logic [`NE+1:0] DivCalcExp;
logic divsqrtop; logic divsqrtop;
// Missing logic vectors fdivsqrt
logic [2:0] Funct3E;
logic [2:0] Funct3M;
logic FlushE;
logic IFDivStartE, FDivDoneE;
logic [`NE+1:0] QeM;
logic [`DIVb:0] QmM;
logic [`XLEN-1:0] FIntDivResultM;
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
@ -147,8 +153,9 @@ module testbenchfp;
Fmt = {Fmt, 2'b11}; Fmt = {Fmt, 2'b11};
end end
end end
end end
if (TEST === "cvtfp" | TEST === "all") begin // if the floating-point conversions are being tested // if the floating-point conversions are being tested
if (TEST === "cvtfp" | TEST === "all") begin
if(`D_SUPPORTED) begin // if double precision is supported if(`D_SUPPORTED) begin // if double precision is supported
// add the 128 <-> 64 bit conversions to the to-be-tested list // add the 128 <-> 64 bit conversions to the to-be-tested list
Tests = {Tests, f128f64cvt}; Tests = {Tests, f128f64cvt};
@ -571,38 +578,23 @@ module testbenchfp;
end end
if (TEST === "div" | TEST === "all") begin // if division is being tested if (TEST === "div" | TEST === "all") begin // if division is being tested
// add the correct tests/op-ctrls/unit/fmt to their lists // add the correct tests/op-ctrls/unit/fmt to their lists
Tests = {f16div, Tests}; Tests = {Tests, f16div};
OpCtrl = {`DIV_OPCTRL, OpCtrl};
WriteInt = {1'b0, WriteInt};
for(int i = 0; i<5; i++) begin
Unit = {`DIVUNIT, Unit};
Fmt = {2'b10, Fmt};
end
/* Tests = {Tests, f16div};
OpCtrl = {OpCtrl, `DIV_OPCTRL}; OpCtrl = {OpCtrl, `DIV_OPCTRL};
WriteInt = {WriteInt, 1'b0}; WriteInt = {WriteInt, 1'b0};
for(int i = 0; i<5; i++) begin for(int i = 0; i<5; i++) begin
Unit = {Unit, `DIVUNIT}; Unit = {Unit, `DIVUNIT};
Fmt = {Fmt, 2'b10}; Fmt = {Fmt, 2'b10};
end */ end
end end
if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested
// add the correct tests/op-ctrls/unit/fmt to their lists // add the correct tests/op-ctrls/unit/fmt to their lists
// reverse order Tests = {Tests, f16sqrt};
Tests = {f16sqrt, Tests};
OpCtrl = {`SQRT_OPCTRL, OpCtrl};
WriteInt = {1'b0, WriteInt};
for(int i = 0; i<5; i++) begin
Unit = {`DIVUNIT, Unit};
Fmt = {2'b10, Fmt};
end
/* Tests = {Tests, f16sqrt};
OpCtrl = {OpCtrl, `SQRT_OPCTRL}; OpCtrl = {OpCtrl, `SQRT_OPCTRL};
WriteInt = {WriteInt, 1'b0}; WriteInt = {WriteInt, 1'b0};
for(int i = 0; i<5; i++) begin for(int i = 0; i<5; i++) begin
Unit = {Unit, `DIVUNIT}; Unit = {Unit, `DIVUNIT};
Fmt = {Fmt, 2'b10}; Fmt = {Fmt, 2'b10};
end */ end
end end
if (TEST === "fma" | TEST === "all") begin // if fma is being tested if (TEST === "fma" | TEST === "all") begin // if fma is being tested
Tests = {Tests, f16fma}; Tests = {Tests, f16fma};
@ -656,18 +648,17 @@ module testbenchfp;
end end
// extract the inputs (X, Y, Z, SrcA) and the output (Ans, AnsFlg) from the current test vector // extract the inputs (X, Y, Z, SrcA) and the output (Ans, AnsFlg) from the current test vector
readvectors readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]), readvectors readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]),
.VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA, .VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA,
.Xs, .Ys, .Zs, .Unit(UnitVal), .Xs, .Ys, .Zs, .Unit(UnitVal),
.Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal), .Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal),
.Xm, .Ym, .Zm, .DivStart, .Xm, .Ym, .Zm, .DivStart,
.XNaN, .YNaN, .ZNaN, .XNaN, .YNaN, .ZNaN,
.XSNaN, .YSNaN, .ZSNaN, .XSNaN, .YSNaN, .ZSNaN,
.XSubnorm, .ZSubnorm, .XSubnorm, .ZSubnorm,
.XZero, .YZero, .ZZero, .XZero, .YZero, .ZZero,
.XInf, .YInf, .ZInf, .XExpMax, .XInf, .YInf, .ZInf, .XExpMax,
.X, .Y, .Z); .X, .Y, .Z, .XPostBox);
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
@ -713,11 +704,16 @@ module testbenchfp;
.XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes)); .XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes));
end end
if (TEST === "div" | TEST === "sqrt" | TEST === "all") begin: fdivsqrt if (TEST === "div" | TEST === "sqrt" | TEST === "all") begin: fdivsqrt
fdivsqrt fdivsqrt(.clk, .reset, .XsE(Xs), .FmtE(ModFmt), .XmE(Xm), .YmE(Ym), .XeE(Xe), .YeE(Ye), .SqrtE(OpCtrlVal[0]), .SqrtM(OpCtrlVal[0]), fdivsqrt fdivsqrt(.clk, .reset, .XsE(Xs), .FmtE(ModFmt), .XmE(Xm), .YmE(Ym),
.XInfE(XInf), .YInfE(YInf), .XZeroE(XZero), .YZeroE(YZero), .XNaNE(XNaN), .YNaNE(YNaN), .XeE(Xe), .YeE(Ye), .SqrtE(OpCtrlVal[0]), .SqrtM(OpCtrlVal[0]),
.FDivStartE(DivStart), .IDivStartE(1'b0), .MDUE(1'b0), .W64E(1'b0), .XInfE(XInf), .YInfE(YInf), .XZeroE(XZero), .YZeroE(YZero),
.StallM(1'b0), .DivSM(DivSticky), .FDivBusyE, .QeM(DivCalcExp), .XNaNE(XNaN), .YNaNE(YNaN),
.QmM(Quot)); .FDivStartE(DivStart), .IDivStartE(1'b0), .W64E(1'b0),
.StallM(1'b0), .DivStickyM(DivSticky), .FDivBusyE, .QeM(DivCalcExp),
.QmM(Quot),
.FlushE(1'b0), .ForwardedSrcAE('0), .ForwardedSrcBE('0), .Funct3M(Funct3M),
.Funct3E(Funct3E), .IntDivE(1'b0), .FIntDivResultM(FIntDivResultM),
.FDivDoneE(FDivDoneE), .IFDivStartE(IFDivStartE));
end end
assign CmpFlg[3:0] = 0; assign CmpFlg[3:0] = 0;
@ -726,6 +722,16 @@ module testbenchfp;
always begin always begin
clk = 1; #5; clk = 0; #5; clk = 1; #5; clk = 0; #5;
end end
// Provide reset for divsqrt to reset state to IDLE
// Previous version did not initiate a divide due to missing state
// information. This starts the FSM by putting the fdivsqrt into
// the IDLE state.
initial
begin
#0 reset = 1'b1;
#25 reset = 1'b0;
end
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
@ -738,7 +744,7 @@ module testbenchfp;
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
//Check if the correct answer and result is a NaN // Check if the correct answer and result is a NaN
always_comb begin always_comb begin
if(UnitVal === `CVTINTUNIT | UnitVal === `CMPUNIT) begin if(UnitVal === `CVTINTUNIT | UnitVal === `CMPUNIT) begin
// an integer output can't be a NaN // an integer output can't be a NaN
@ -809,7 +815,7 @@ end
logic ResMatch, FlagMatch, CheckNow; logic ResMatch, FlagMatch, CheckNow;
always @(posedge clk) always @(posedge clk)
OldFDivBusyE = FDivBusyE; OldFDivBusyE = FDivDoneE;
// check results on falling edge of clk // check results on falling edge of clk
always @(negedge clk) begin always @(negedge clk) begin
@ -912,9 +918,15 @@ always @(negedge clk) begin
$stop; $stop;
end end
if(~(FDivBusyE|DivStart)|(UnitVal != `DIVUNIT)) VectorNum += 1; // increment the vector // Add extra clock cycles in beginning for fdivsqrt to adequate reset state
if(~(FDivBusyE|DivStart)|(UnitVal != `DIVUNIT)) begin
if (TestVectors[VectorNum][0] === 1'bx & Tests[TestNum] !== "") begin // if reached the end of file repeat (12)
@(posedge clk);
if (reset != 1'b1)
VectorNum += 1; // increment the vector
end
if (TestVectors[VectorNum][0] === 1'bx & Tests[TestNum] !== "") begin // if reached the eof
// increment the test // increment the test
TestNum += 1; TestNum += 1;
@ -944,31 +956,29 @@ always @(negedge clk) begin
endmodule endmodule
module readvectors ( module readvectors (
input logic clk, input logic clk,
input logic [`FLEN*4+7:0] TestVector, input logic [`FLEN*4+7:0] TestVector,
input logic [`FMTBITS-1:0] ModFmt, input logic [`FMTBITS-1:0] ModFmt,
input logic [1:0] Fmt, input logic [1:0] Fmt,
input logic [2:0] Unit, input logic [2:0] Unit,
input logic [31:0] VectorNum, input logic [31:0] VectorNum,
input logic [31:0] TestNum, input logic [31:0] TestNum,
input logic [2:0] OpCtrl, input logic [2:0] OpCtrl,
output logic [`FLEN-1:0] Ans, output logic [`FLEN-1:0] Ans,
output logic [`XLEN-1:0] SrcA, output logic [`XLEN-1:0] SrcA,
output logic [4:0] AnsFlg, output logic [4:0] AnsFlg,
output logic Xs, Ys, Zs, // sign bits of XYZ output logic Xs, Ys, Zs, // sign bits of XYZ
output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision) output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision) output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
output logic XSubnorm, ZSubnorm, // is XYZ denormalized output logic XSubnorm, ZSubnorm, // is XYZ denormalized
output logic XZero, YZero, ZZero, // is XYZ zero output logic XZero, YZero, ZZero, // is XYZ zero
output logic XInf, YInf, ZInf, // is XYZ infinity output logic XInf, YInf, ZInf, // is XYZ infinity
output logic XExpMax, output logic XExpMax,
output logic DivStart, output logic DivStart,
output logic [`FLEN-1:0] X, Y, Z output logic [`FLEN-1:0] X, Y, Z, XPostBox
); );
logic XEn, YEn, ZEn; logic XEn, YEn, ZEn;
@ -1331,5 +1341,5 @@ module readvectors (
unpack unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze, unpack unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze,
.Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN, .Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN,
.XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf, .XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf,
.XEn, .YEn, .ZEn, .XExpMax); .XEn, .YEn, .ZEn, .XExpMax, .XPostBox);
endmodule endmodule

View File

@ -25,15 +25,15 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`define PATH "../tests/fp/vectors/" `define PATH "../tests/fp/vectors/"
`define ADD_OPCTRL 3'b110 `define ADD_OPCTRL 3'b110
`define MUL_OPCTRL 3'b100 `define MUL_OPCTRL 3'b100
`define SUB_OPCTRL 3'b111 `define SUB_OPCTRL 3'b111
`define FMA_OPCTRL 3'b000 `define FMA_OPCTRL 3'b000
`define DIV_OPCTRL 3'b000 `define DIV_OPCTRL 3'b000
`define SQRT_OPCTRL 3'b001 `define SQRT_OPCTRL 3'b001
`define LE_OPCTRL 3'b011 `define LE_OPCTRL 3'b011
`define LT_OPCTRL 3'b001 `define LT_OPCTRL 3'b001
`define EQ_OPCTRL 3'b010 `define EQ_OPCTRL 3'b010
`define TO_UI_OPCTRL 3'b000 `define TO_UI_OPCTRL 3'b000
`define TO_I_OPCTRL 3'b001 `define TO_I_OPCTRL 3'b001
`define TO_UL_OPCTRL 3'b010 `define TO_UL_OPCTRL 3'b010
@ -42,16 +42,16 @@
`define FROM_I_OPCTRL 3'b101 `define FROM_I_OPCTRL 3'b101
`define FROM_UL_OPCTRL 3'b110 `define FROM_UL_OPCTRL 3'b110
`define FROM_L_OPCTRL 3'b111 `define FROM_L_OPCTRL 3'b111
`define RNE 3'b000 `define RNE 3'b000
`define RZ 3'b001 `define RZ 3'b001
`define RU 3'b011 `define RU 3'b011
`define RD 3'b010 `define RD 3'b010
`define RNM 3'b100 `define RNM 3'b100
`define FMAUNIT 2 `define FMAUNIT 2
`define DIVUNIT 1 `define DIVUNIT 1
`define CVTINTUNIT 0 `define CVTINTUNIT 0
`define CVTFPUNIT 4 `define CVTFPUNIT 4
`define CMPUNIT 3 `define CMPUNIT 3
string f16rv32cvtint[] = '{ string f16rv32cvtint[] = '{
"ui32_to_f16_rne.tv", "ui32_to_f16_rne.tv",
@ -238,7 +238,6 @@ string f128rv32cvtint[] = '{
"f128_to_i32_rnm.tv" "f128_to_i32_rnm.tv"
}; };
string f32f16cvt[] = '{ string f32f16cvt[] = '{
"f32_to_f16_rne.tv", "f32_to_f16_rne.tv",
"f32_to_f16_rz.tv", "f32_to_f16_rz.tv",
@ -291,7 +290,6 @@ string f64f32cvt[] = '{
"f32_to_f64_rnm.tv" "f32_to_f64_rnm.tv"
}; };
string f128f32cvt[] = '{ string f128f32cvt[] = '{
"f128_to_f32_rne.tv", "f128_to_f32_rne.tv",
"f128_to_f32_rz.tv", "f128_to_f32_rz.tv",
@ -305,7 +303,6 @@ string f128f32cvt[] = '{
"f32_to_f128_rnm.tv" "f32_to_f128_rnm.tv"
}; };
string f128f64cvt[] = '{ string f128f64cvt[] = '{
"f128_to_f64_rne.tv", "f128_to_f64_rne.tv",
"f128_to_f64_rz.tv", "f128_to_f64_rz.tv",