Fixes testbench issues in testing against all vectors. Still a bug in ui32_to_f16_rz.sv - but will fix. Some things can be optimized. Overall, adds a FSM to test things more effectively. Actually is faster than previously as it assumed everything took the same number of cycles. Again, some things can be optimized

This commit is contained in:
James E. Stine 2024-01-29 16:46:34 -06:00
parent df8df0598d
commit 95a97faf3f

View file

@ -83,7 +83,7 @@ module testbenchfp;
logic [P.LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by
logic [P.DIVb:0] Quot;
logic CvtResSubnormUfE;
logic DivStart;
logic DivStart=0;
logic FDivBusyE;
logic OldFDivBusyE;
logic reset = 1'b0;
@ -120,7 +120,11 @@ module testbenchfp;
logic ResMatch; // Check if result match
logic FlagMatch; // Check if IEEE flags match
logic CheckNow; // Final check
logic FMAop; // Is this a FMA operation?
logic FMAop; // Is this a FMA operation?
// FSM for testing each item per clock
typedef enum logic [2:0] {S0, Start, S2, Done} statetype;
statetype state, nextstate;
///////////////////////////////////////////////////////////////////////////////////////////////
@ -676,7 +680,7 @@ module testbenchfp;
.VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA,
.Xs, .Ys, .Zs, .Unit(UnitVal),
.Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal),
.Xm, .Ym, .Zm, .DivStart,
.Xm, .Ym, .Zm,
.XNaN, .YNaN, .ZNaN,
.XSNaN, .YSNaN, .ZSNaN,
.XSubnorm, .ZSubnorm,
@ -748,16 +752,6 @@ module testbenchfp;
clk = 1; #5; clk = 0; #5;
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
///////////////////////////////////////////////////////////////////////////////////////////////
// ||||| ||| |||||||||| ||||| |||
@ -835,45 +829,64 @@ module testbenchfp;
`CMPUNIT: ResFlg = CmpFlg;
`CVTINTUNIT: ResFlg = Flg;
`CVTFPUNIT: ResFlg = Flg;
endcase
end
endcase
// Use four state test sequence to handle div properly.
// Four states should allow other operations to finish
// properly and within time.
case (state)
S0: begin
DivStart = 1'b0;
nextstate = Start;
end
Start: begin
if (UnitVal == `DIVUNIT)
DivStart = 1'b1;
else
DivStart = 1'b0;
nextstate = S2;
end
S2: begin
DivStart = 1'b0;
if ((FDivBusyE)|(~DivDone))
nextstate = S2;
else
nextstate = Done;
end
Done: begin
DivStart = 1'b0;
nextstate = S0;
end
endcase // case (state)
end
// Provide reset for divsqrt to reset state
initial
begin
#0 reset = 1'b1;
#25 reset = 1'b0;
end
// Left-over from before - will remove soon
always @(posedge clk)
OldFDivBusyE = FDivDoneE;
// For FP division this adds extra clock cycles to make sure the
// computation completes.
// state machine to handle timing for testing due
// various cycle counts for different fp/int operations
// Adds vector at start of clock
always @(posedge clk) begin
// Add extra clock cycles in beginning for fdivsqrt to adequate reset state
if (~(FDivBusyE|DivStart)|(UnitVal != `DIVUNIT)) begin
// This allows specific number of clocks to allow each vector
// to complete for division or square root. It is an
// arbitrary value and can be changed, if needed.
case (FmtVal)
// QP
2'b11: begin
repeat (20)
@(posedge clk);
end
// HP
2'b10: begin
repeat (14)
@(posedge clk);
end
// DP
2'b01: begin
repeat (18)
@(posedge clk);
end
// SP
2'b00: begin
repeat (16)
@(posedge clk);
end
endcase // case (FmtVal)
if (reset != 1'b1)
VectorNum += 1; // increment the vector
end
// state machine element for testing
if (reset)
state <= S0;
else
state <= nextstate;
// Increment the vector when Done with each test
if (state == Done)
VectorNum += 1; // increment the vector
end
// check results on falling edge of clk
@ -904,7 +917,7 @@ module testbenchfp;
(YNaN&(Res[P.H_LEN-2:0] === {Y[P.H_LEN-2:P.H_NF],1'b1,Y[P.H_NF-2:0]})) |
(ZNaN&(Res[P.H_LEN-2:0] === {Z[P.H_LEN-2:P.H_NF],1'b1,Z[P.H_NF-2:0]})));
endcase
else if (UnitVal === `CVTFPUNIT) // if converting from floating point to floating point OpCtrl contains the final FP format
else if (UnitVal === `CVTFPUNIT) // if converting from FP to FP OpCtrl contains the final FP format
case (OpCtrlVal[1:0])
2'b11: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res === {1'b0, {P.Q_NE+1{1'b1}}, {P.Q_NF-1{1'b0}}})) |
(AnsFlg[4]&(Res[P.Q_LEN-2:0] === {{P.Q_NE+1{1'b1}}, {P.Q_NF-1{1'b0}}})) |
@ -941,29 +954,22 @@ module testbenchfp;
///////////////////////////////////////////////////////////////////////////////////////////////
// check if result is correct
// wait till the division result is done or one extra cylcle for early termination (to simulate the EM pipline stage)
assign ResMatch = ((Res === Ans) | NaNGood | (NaNGood === 1'bx));
assign FlagMatch = ((ResFlg === AnsFlg) | (AnsFlg === 5'bx));
assign divsqrtop = (OpCtrlVal == `SQRT_OPCTRL) | (OpCtrlVal == `DIV_OPCTRL);
assign FMAop = (OpCtrlVal == `FMAUNIT);
assign DivDone = OldFDivBusyE & ~FDivBusyE;
// Maybe change OpCtrl but for now just look at TEST for fma test
assign CheckNow = ((DivDone | ~divsqrtop) | (TEST == "add" | TEST == "fma" | TEST == "sub")) & (UnitVal !== `CVTINTUNIT) & (UnitVal !== `CMPUNIT);
if (~(ResMatch & FlagMatch) & CheckNow) begin
assign CheckNow = ((DivDone | ~divsqrtop) |
(TEST == "all" | TEST == "add" | TEST == "fma" | TEST == "sub"))
& (UnitVal !== `CVTINTUNIT) & (UnitVal !== `CMPUNIT);
if (~(ResMatch & FlagMatch) & CheckNow & (Ans[0] !== 1'bx)) begin
errors += 1;
$display("\nError in %s", Tests[TestNum]);
$display("TestNum %d OpCtrl %d", TestNum, OpCtrl[TestNum]);
$display("inputs: %h %h %h\nSrcA: %h\n Res: %h %h\n Expected: %h %h", X, Y, Z, SrcA, Res, ResFlg, Ans, AnsFlg);
$stop;
end else if (((UnitVal === `CVTINTUNIT) | (UnitVal === `CMPUNIT)) &
~(ResMatch & FlagMatch) & (Ans[0] !== 1'bx)) begin // Check for conversion and comparisons
errors += 1;
$display("\nError in %s", Tests[TestNum]);
$display("TestNum %d OpCtrl %d", TestNum, OpCtrl[TestNum]);
$display("inputs: %h %h %h\nSrcA: %h\n Res: %h %h\n Ans: %h %h", X, Y, Z, SrcA, Res, ResFlg, Ans, AnsFlg);
$stop;
end
end
if (TestVectors[VectorNum][0] === 1'bx & Tests[TestNum] !== "") begin // if reached the eof
// increment the test
@ -979,11 +985,12 @@ module testbenchfp;
// increment the rounding mode or loop back to rne
if (FrmNum < 4) FrmNum += 1;
else begin
FrmNum = 0;
FrmNum = 0;
// Add some time as a buffer between tests at the end of each test
repeat (10)
@(posedge clk);
end
// (to be removed)
repeat (10)
@(posedge clk);
end
// if no more Tests - finish
if (Tests[TestNum] === "") begin
$display("\nAll Tests completed with %d errors\n", errors);
@ -996,28 +1003,27 @@ endmodule
module readvectors import cvw::*; #(parameter cvw_t P) (
input logic clk,
input logic [P.FLEN*4+7:0] TestVector,
input logic clk,
input logic [P.FLEN*4+7:0] TestVector,
input logic [P.FMTBITS-1:0] ModFmt,
input logic [1:0] Fmt,
input logic [2:0] Unit,
input logic [31:0] VectorNum,
input logic [31:0] TestNum,
input logic [2:0] OpCtrl,
output logic [P.FLEN-1:0] Ans,
output logic [P.XLEN-1:0] SrcA,
output logic [4:0] AnsFlg,
output logic Xs, Ys, Zs, // sign bits of XYZ
output logic [P.NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
output logic [P.NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
output logic XSubnorm, ZSubnorm, // is XYZ denormalized
output logic XZero, YZero, ZZero, // is XYZ zero
output logic XInf, YInf, ZInf, // is XYZ infinity
output logic XExpMax,
output logic DivStart,
output logic [P.FLEN-1:0] X, Y, Z, XPostBox
input logic [1:0] Fmt,
input logic [2:0] Unit,
input logic [31:0] VectorNum,
input logic [31:0] TestNum,
input logic [2:0] OpCtrl,
output logic [P.FLEN-1:0] Ans,
output logic [P.XLEN-1:0] SrcA,
output logic [4:0] AnsFlg,
output logic Xs, Ys, Zs, // sign bits of XYZ
output logic [P.NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
output logic [P.NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
output logic XSubnorm, ZSubnorm, // is XYZ denormalized
output logic XZero, YZero, ZZero, // is XYZ zero
output logic XInf, YInf, ZInf, // is XYZ infinity
output logic XExpMax,
output logic [P.FLEN-1:0] X, Y, Z, XPostBox
);
localparam Q_LEN = 32'd128;
@ -1030,8 +1036,6 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
// apply test vectors on rising edge of clk
// Format of vectors Inputs(1/2/3)_AnsFlg
always @(VectorNum) begin
DivStart = 1'b0;
#1;
AnsFlg = TestVector[4:0];
case (Unit)
`FMAUNIT:
@ -1101,30 +1105,18 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
2'b11: begin // quad
X = TestVector[8+2*(P.Q_LEN)-1:8+(P.Q_LEN)];
Ans = TestVector[8+(P.Q_LEN-1):8];
if (~clk) #5;
DivStart = 1'b1; #10 // one clk cycle
DivStart = 1'b0;
end
2'b01: if (P.D_SUPPORTED) begin // double
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
2'b00: if (P.S_SUPPORTED) begin // single
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+1*(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
2'b10: begin // half
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
endcase
else
@ -1133,33 +1125,21 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
X = TestVector[8+3*(P.Q_LEN)-1:8+2*(P.Q_LEN)];
Y = TestVector[8+2*(P.Q_LEN)-1:8+(P.Q_LEN)];
Ans = TestVector[8+(P.Q_LEN-1):8];
if (~clk) #5;
DivStart = 1'b1; #10 // one clk cycle
DivStart = 1'b0;
end
2'b01: if (P.D_SUPPORTED) begin // double
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]};
Y = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
2'b00: if (P.S_SUPPORTED) begin // single
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]};
Y = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+1*(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
2'b10: begin // half
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]};
Y = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
endcase
`CMPUNIT: