Merge branch 'main' of https://github.com/openhwgroup/cvw into dev

This commit is contained in:
David Harris 2024-01-29 14:51:27 -08:00
commit 35cd4e1d6c

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: