mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-03 10:15:19 +00:00
Merge pull request #573 from davidharrishmc/dev
fcvt fix, coverage improvement
This commit is contained in:
commit
b11e8ea420
@ -46,4 +46,7 @@ extend PATH /usr/local/bin/verilator # Change this for your path to Verilator
|
||||
#set path = ($RISCV/imperas-riscv-tests/riscv-ovpsim-plus/bin/Linux64 $path)
|
||||
#setenv LD_LIBRARY_PATH $RISCV/imperas_riscv_tests/riscv-ovpsim-plus/bin/Linux64:$LD_LIBRARY_PATH # remove if no imperas
|
||||
|
||||
# Verilator needs a larger stack to simulate CORE-V Wally
|
||||
limit stacksize unlimited
|
||||
|
||||
echo "setup done"
|
||||
|
@ -37,7 +37,7 @@ module fclassify import cvw::*; #(parameter cvw_t P) (
|
||||
);
|
||||
|
||||
logic PInf, PZero, PNorm, PSubnorm; // is the input a positive infinity/zero/normal/subnormal
|
||||
logic NInf, NZero, NNorm, NSubnorm; // is the input a negitive infinity/zero/normal/subnormal
|
||||
logic NInf, NZero, NNorm, NSubnorm; // is the input a negative infinity/zero/normal/subnormal
|
||||
logic XNorm; // is the input normal
|
||||
|
||||
// determine the sub categories
|
||||
|
@ -215,7 +215,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
||||
// rounding modes:
|
||||
// 000 - round to nearest, ties to even
|
||||
// 001 - round twords 0 - round to min magnitude
|
||||
// 010 - round down - round twords negitive infinity
|
||||
// 010 - round down - round twords negative infinity
|
||||
// 011 - round up - round twords positive infinity
|
||||
// 100 - round to nearest, ties to max magnitude - round to nearest, ties away from zero
|
||||
// 111 - dynamic - choose FRM_REGW as rounding mode
|
||||
|
@ -80,7 +80,7 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// negation
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 1) negate the input if the input is a negitive singed integer
|
||||
// 1) negate the input if the input is a negative singed integer
|
||||
// 2) trim the input to the proper size (kill the 32 most significant zeroes if needed)
|
||||
|
||||
assign PosInt = Cs ? -Int : Int;
|
||||
@ -182,7 +182,7 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
||||
assign Ce = {1'b0, OldExp} - (P.NE+1)'(P.BIAS) - {{P.NE-P.LOGCVTLEN+1{1'b0}}, (LeadingZeros)} + {2'b0, NewBias};
|
||||
|
||||
// find if the result is dnormal or underflows
|
||||
// - if Calculated expoenent is 0 or negitive (and the input/result is not exactaly 0)
|
||||
// - if Calculated expoenent is 0 or negative (and the input/result is not exactaly 0)
|
||||
// - can't underflow an integer to Fp conversion
|
||||
assign ResSubnormUf = (~|Ce | Ce[P.NE])&~XZero&~IntToFp;
|
||||
|
||||
@ -190,7 +190,7 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
||||
// shifter
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// kill the shift if it's negitive
|
||||
// kill the shift if it's negative
|
||||
// select the amount to shift by
|
||||
// fp -> int:
|
||||
// - shift left by CalcExp - essentially shifting until the unbiased exponent = 0
|
||||
|
@ -42,8 +42,8 @@ module fmaadd import cvw::*; #(parameter cvw_t P) (
|
||||
output logic [3*P.NF+3:0] Sm // the positive sum
|
||||
);
|
||||
|
||||
logic [3*P.NF+3:0] PreSum, NegPreSum; // possibly negitive sum
|
||||
logic NegSum; // was the sum negitive
|
||||
logic [3*P.NF+3:0] PreSum, NegPreSum; // possibly negative sum
|
||||
logic NegSum; // was the sum negative
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Addition
|
||||
@ -54,8 +54,8 @@ module fmaadd import cvw::*; #(parameter cvw_t P) (
|
||||
// Kill the product if the product is too small to effect the addition (determined in fma1.sv)
|
||||
assign PmKilled = {2*P.NF+2{~KillProd}}&Pm;
|
||||
// Do the addition
|
||||
// - calculate a positive and negitive sum in parallel
|
||||
// if there was a small negitive number killed in the alignment stage one needs to be subtracted from the sum
|
||||
// - calculate a positive and negative sum in parallel
|
||||
// if there was a small negative number killed in the alignment stage one needs to be subtracted from the sum
|
||||
// prod - addend where some of the addend is put into the sticky bit then don't add +1 from negation
|
||||
// ie ~(InvA&ASticky&~KillProd)&InvA = (~ASticky|KillProd)&InvA
|
||||
// addend - prod where product is killed (and not exactly zero) then don't add +1 from negation
|
||||
@ -66,10 +66,10 @@ module fmaadd import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// Choose the positive sum and accompanying LZA result.
|
||||
assign Sm = NegSum ? NegPreSum : PreSum;
|
||||
// is the result negitive
|
||||
// if p - z is the Sum negitive
|
||||
// is the result negative
|
||||
// if p - z is the Sum negative
|
||||
// if -p + z is the Sum positive
|
||||
// if -p - z then the Sum is negitive
|
||||
// if -p - z then the Sum is negative
|
||||
assign Ss = NegSum^Ps;
|
||||
assign Se = KillProd ? {2'b0, Ze} : Pe;
|
||||
endmodule
|
||||
|
@ -45,7 +45,7 @@ module fmaalign import cvw::*; #(parameter cvw_t P) (
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// determine the shift count for alignment
|
||||
// - negitive means Z is larger, so shift Z left
|
||||
// - negative means Z is larger, so shift Z left
|
||||
// - positive means the product is larger, so shift Z right
|
||||
// This could have been done using Pe, but ACnt is on the critical path so we replicate logic for speed
|
||||
assign ACnt = {2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)} + (P.NE+2)'(P.NF+2) - {2'b0, Ze};
|
||||
|
@ -36,7 +36,7 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
);
|
||||
|
||||
logic [P.LOGNORMSHIFTSZ-1:0] NormShift; // normalized result shift amount
|
||||
logic [P.LOGNORMSHIFTSZ-1:0] DivSubnormShiftAmt; // subnormal result shift amount (killed if negitive)
|
||||
logic [P.LOGNORMSHIFTSZ-1:0] DivSubnormShiftAmt; // subnormal result shift amount (killed if negative)
|
||||
logic [P.NE+1:0] DivSubnormShift; // subnormal result shift amount
|
||||
|
||||
// is the result subnormal
|
||||
@ -62,7 +62,7 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
// shift one more if the it's a minimally redundent radix 4 - one entire cycle needed for integer bit
|
||||
assign NormShift = (P.LOGNORMSHIFTSZ)'(P.NF);
|
||||
|
||||
// if the shift amount is negitive then don't shift (keep sticky bit)
|
||||
// if the shift amount is negative then don't shift (keep sticky bit)
|
||||
// need to multiply the early termination shift by LOGR*DIVCOPIES = left shift of log2(LOGR*DIVCOPIES)
|
||||
assign DivSubnormShiftAmt = DivSubnormShiftPos ? DivSubnormShift[P.LOGNORMSHIFTSZ-1:0] : '0;
|
||||
assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift;
|
||||
|
@ -47,7 +47,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
||||
input logic Int64, // convert to 64 bit integer
|
||||
input logic Signed, // convert to a signed integer
|
||||
input logic [P.NE:0] CvtCe, // the calculated expoent - Cvt
|
||||
input logic [1:0] CvtNegResMsbs, // the negitive integer result's most significant bits
|
||||
input logic [1:0] CvtNegResMsbs, // the negative integer result's most significant bits
|
||||
// divsqrt
|
||||
input logic DivOp, // conversion opperation?
|
||||
input logic Sqrt, // Sqrt?
|
||||
@ -122,7 +122,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// calulate overflow flag:
|
||||
// if the result is greater than or equal to the max exponent(not taking into account sign)
|
||||
// | and the exponent isn't negitive
|
||||
// | and the exponent isn't negative
|
||||
// | | if the input isnt infinity or NaN
|
||||
// | | |
|
||||
assign Overflow = ResExpGteMax & ~FullRe[P.NE+1]&~(InfIn|NaNIn|DivByZero);
|
||||
@ -132,7 +132,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// calculate underflow flag: detecting tininess after rounding
|
||||
// the exponent is negitive
|
||||
// the exponent is negative
|
||||
// | the result is subnormal
|
||||
// | | the result is normal and rounded from a Subnorm
|
||||
// | | | and if given an unbounded exponent the result does not round
|
||||
@ -170,7 +170,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
||||
// invalid flag for integer result
|
||||
// if the input is NaN or infinity
|
||||
// | if the integer res overflows (out of range)
|
||||
// | | if the input was negitive but ouputing to a unsigned number
|
||||
// | | if the input was negative but ouputing to a unsigned number
|
||||
// | | | the res doesn't round to zero
|
||||
// | | | | or the res rounds up out of bounds
|
||||
// | | | | and the res didn't underflow
|
||||
|
@ -47,7 +47,7 @@ module resultsign(
|
||||
|
||||
// determine the sign for a result of 0
|
||||
// The IEEE754-2019 standard specifies:
|
||||
// - the sign of an exact zero sum (with operands of diffrent signs) should be positive unless rounding toward negitive infinity
|
||||
// - the sign of an exact zero sum (with operands of diffrent signs) should be positive unless rounding toward negative infinity
|
||||
// - when the exact result of an FMA opperation is non-zero, but is zero due to rounding, use the sign of the exact result
|
||||
// - if x = +0 or -0 then x+x=x and x-(-x)=x
|
||||
// - the sign of a product is the exclisive or or the opperand's signs
|
||||
@ -63,10 +63,10 @@ module resultsign(
|
||||
assign Zeros = (FmaPs^FmaAs)&~(Round|Guard|Sticky)&~Mult ? Frm[1:0] == 2'b10 : FmaPs;
|
||||
|
||||
// determine the sign of an infinity result
|
||||
// is the result negitive
|
||||
// if p - z is the Sum negitive
|
||||
// is the result negative
|
||||
// if p - z is the Sum negative
|
||||
// if -p + z is the Sum positive
|
||||
// if -p - z then the Sum is negitive
|
||||
// if -p - z then the Sum is negative
|
||||
assign Infs = ZInf ? FmaAs : FmaPs;
|
||||
|
||||
// select the result sign
|
||||
|
@ -277,7 +277,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// IEEE 754
|
||||
// select the overflow integer res
|
||||
// - negitive infinity and out of range negitive input
|
||||
// - negative infinity and out of range negative input
|
||||
// | int | long |
|
||||
// signed | -2^31 | -2^63 |
|
||||
// unsigned | 2^32-1 | 2^64-1 |
|
||||
@ -291,7 +291,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// RISC-V
|
||||
// select the overflow integer res
|
||||
// - negitive infinity and out of range negitive input
|
||||
// - negative infinity and out of range negative input
|
||||
// | int | long |
|
||||
// signed | -2^31 | -2^63 |
|
||||
// unsigned | 0 | 0 |
|
||||
@ -303,38 +303,37 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
||||
//
|
||||
// other: 32 bit unsinged res should be sign extended as if it were a signed number
|
||||
|
||||
if(P.IEEE754) begin
|
||||
if(P.IEEE754) begin
|
||||
always_comb
|
||||
if(Signed)
|
||||
if(Xs&~NaNIn) // signed negitive
|
||||
if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}};
|
||||
else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}};
|
||||
else // signed positive
|
||||
if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}};
|
||||
else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}};
|
||||
else
|
||||
if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b1}}; // unsigned negitive
|
||||
else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive
|
||||
end // if (P.IEEE754)
|
||||
else begin
|
||||
if(Signed)
|
||||
if(Xs&~NaNIn) // signed negative
|
||||
if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}};
|
||||
else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}};
|
||||
else // signed positive
|
||||
if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}};
|
||||
else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}};
|
||||
else
|
||||
if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b1}}; // unsigned negative
|
||||
else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive
|
||||
end else begin
|
||||
always_comb
|
||||
if(Signed)
|
||||
if(Xs&~NaNIn) // signed negitive
|
||||
if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}};
|
||||
else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}};
|
||||
else // signed positive
|
||||
if(Int64) OfIntRes = {1'b0, {P.XLEN-1{1'b1}}};
|
||||
else OfIntRes = {{P.XLEN-32{1'b0}}, 1'b0, {31{1'b1}}};
|
||||
else
|
||||
if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b0}}; // unsigned negitive
|
||||
else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive
|
||||
end // else: !if(P.IEEE754)
|
||||
if(Signed)
|
||||
if(Xs&~NaNIn) // signed negative
|
||||
if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}};
|
||||
else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}};
|
||||
else // signed positive
|
||||
if(Int64) OfIntRes = {1'b0, {P.XLEN-1{1'b1}}};
|
||||
else OfIntRes = {{P.XLEN-32{1'b0}}, 1'b0, {31{1'b1}}};
|
||||
else
|
||||
if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b0}}; // unsigned negative
|
||||
else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive
|
||||
end
|
||||
|
||||
|
||||
// select the integer output
|
||||
// - if the input is invalid (out of bounds NaN or Inf) then output overflow res
|
||||
// - if the input underflows
|
||||
// - if rounding and signed opperation and negitive input, output -1
|
||||
// - if rounding and signed opperation and negative input, output -1
|
||||
// - otherwise output a rounded 0
|
||||
// - otherwise output the normal res (trmined and sign extended if nessisary)
|
||||
always_comb
|
||||
|
@ -160,9 +160,9 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
||||
CSRSReadValM = 0;
|
||||
IllegalCSRSAccessM = 1;
|
||||
end
|
||||
STIMECMPH: if (STCE)
|
||||
STIMECMPH: if (STCE & P.XLEN == 32) // not supported for RV64
|
||||
CSRSReadValM = {{(P.XLEN-32){1'b0}}, STIMECMP_REGW[63:32]};
|
||||
else begin // not supported for RV64
|
||||
else begin
|
||||
CSRSReadValM = 0;
|
||||
IllegalCSRSAccessM = 1;
|
||||
end
|
||||
|
@ -882,98 +882,88 @@ module testbenchfp;
|
||||
// - the sign of the NaN does not matter for the opperations being tested
|
||||
// - when 2 or more NaNs are inputed the NaN that is propigated doesn't matter
|
||||
if (UnitVal !== `CVTFPUNIT & UnitVal !== `CVTINTUNIT)
|
||||
case (FmtVal)
|
||||
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}}})) |
|
||||
(XNaN&(Res[P.Q_LEN-2:0] === {X[P.Q_LEN-2:P.Q_NF],1'b1,X[P.Q_NF-2:0]})) |
|
||||
(YNaN&(Res[P.Q_LEN-2:0] === {Y[P.Q_LEN-2:P.Q_NF],1'b1,Y[P.Q_NF-2:0]})) |
|
||||
(ZNaN&(Res[P.Q_LEN-2:0] === {Z[P.Q_LEN-2:P.Q_NF],1'b1,Z[P.Q_NF-2:0]})));
|
||||
2'b01: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.D_LEN-1:0] === {1'b0, {P.D_NE+1{1'b1}}, {P.D_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.D_LEN-2:0] === {{P.D_NE+1{1'b1}}, {P.D_NF-1{1'b0}}})) |
|
||||
(XNaN&(Res[P.D_LEN-2:0] === {X[P.D_LEN-2:P.D_NF],1'b1,X[P.D_NF-2:0]})) |
|
||||
(YNaN&(Res[P.D_LEN-2:0] === {Y[P.D_LEN-2:P.D_NF],1'b1,Y[P.D_NF-2:0]})) |
|
||||
(ZNaN&(Res[P.D_LEN-2:0] === {Z[P.D_LEN-2:P.D_NF],1'b1,Z[P.D_NF-2:0]})));
|
||||
2'b00: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.S_LEN-1:0] === {1'b0, {P.S_NE+1{1'b1}}, {P.S_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.S_LEN-2:0] === {{P.S_NE+1{1'b1}}, {P.S_NF-1{1'b0}}})) |
|
||||
(XNaN&(Res[P.S_LEN-2:0] === {X[P.S_LEN-2:P.S_NF],1'b1,X[P.S_NF-2:0]})) |
|
||||
(YNaN&(Res[P.S_LEN-2:0] === {Y[P.S_LEN-2:P.S_NF],1'b1,Y[P.S_NF-2:0]})) |
|
||||
(ZNaN&(Res[P.S_LEN-2:0] === {Z[P.S_LEN-2:P.S_NF],1'b1,Z[P.S_NF-2:0]})));
|
||||
2'b10: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.H_LEN-1:0] === {1'b0, {P.H_NE+1{1'b1}}, {P.H_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.H_LEN-2:0] === {{P.H_NE+1{1'b1}}, {P.H_NF-1{1'b0}}})) |
|
||||
(XNaN&(Res[P.H_LEN-2:0] === {X[P.H_LEN-2:P.H_NF],1'b1,X[P.H_NF-2:0]})) |
|
||||
(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
|
||||
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}}})) |
|
||||
(AnsNaN&(Res[P.Q_LEN-2:0] === Ans[P.Q_LEN-2:0])) |
|
||||
(XNaN&(Res[P.Q_LEN-2:0] === {X[P.Q_LEN-2:P.Q_NF],1'b1,X[P.Q_NF-2:0]})) |
|
||||
(YNaN&(Res[P.Q_LEN-2:0] === {Y[P.Q_LEN-2:P.Q_NF],1'b1,Y[P.Q_NF-2:0]})));
|
||||
2'b01: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.D_LEN-1:0] === {1'b0, {P.D_NE+1{1'b1}}, {P.D_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.D_LEN-2:0] === {{P.D_NE+1{1'b1}}, {P.D_NF-1{1'b0}}})) |
|
||||
(AnsNaN&(Res[P.D_LEN-2:0] === Ans[P.D_LEN-2:0])) |
|
||||
(XNaN&(Res[P.D_LEN-2:0] === {X[P.D_LEN-2:P.D_NF],1'b1,X[P.D_NF-2:0]})) |
|
||||
(YNaN&(Res[P.D_LEN-2:0] === {Y[P.D_LEN-2:P.D_NF],1'b1,Y[P.D_NF-2:0]})));
|
||||
2'b00: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.S_LEN-1:0] === {1'b0, {P.S_NE+1{1'b1}}, {P.S_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.S_LEN-2:0] === {{P.S_NE+1{1'b1}}, {P.S_NF-1{1'b0}}})) |
|
||||
(AnsNaN&(Res[P.S_LEN-2:0] === Ans[P.S_LEN-2:0])) |
|
||||
(XNaN&(Res[P.S_LEN-2:0] === {X[P.S_LEN-2:P.S_NF],1'b1,X[P.S_NF-2:0]})) |
|
||||
(YNaN&(Res[P.S_LEN-2:0] === {Y[P.S_LEN-2:P.S_NF],1'b1,Y[P.S_NF-2:0]})));
|
||||
2'b10: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.H_LEN-1:0] === {1'b0, {P.H_NE+1{1'b1}}, {P.H_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.H_LEN-2:0] === {{P.H_NE+1{1'b1}}, {P.H_NF-1{1'b0}}})) |
|
||||
(AnsNaN&(Res[P.H_LEN-2:0] === Ans[P.H_LEN-2:0])) |
|
||||
(XNaN&(Res[P.H_LEN-2:0] === {X[P.H_LEN-2:P.H_NF],1'b1,X[P.H_NF-2:0]})) |
|
||||
(YNaN&(Res[P.H_LEN-2:0] === {Y[P.H_LEN-2:P.H_NF],1'b1,Y[P.H_NF-2:0]})));
|
||||
endcase
|
||||
else NaNGood = 1'b0; // integers can't be NaNs
|
||||
case (FmtVal)
|
||||
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}}})) |
|
||||
(XNaN&(Res[P.Q_LEN-2:0] === {X[P.Q_LEN-2:P.Q_NF],1'b1,X[P.Q_NF-2:0]})) |
|
||||
(YNaN&(Res[P.Q_LEN-2:0] === {Y[P.Q_LEN-2:P.Q_NF],1'b1,Y[P.Q_NF-2:0]})) |
|
||||
(ZNaN&(Res[P.Q_LEN-2:0] === {Z[P.Q_LEN-2:P.Q_NF],1'b1,Z[P.Q_NF-2:0]})));
|
||||
2'b01: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.D_LEN-1:0] === {1'b0, {P.D_NE+1{1'b1}}, {P.D_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.D_LEN-2:0] === {{P.D_NE+1{1'b1}}, {P.D_NF-1{1'b0}}})) |
|
||||
(XNaN&(Res[P.D_LEN-2:0] === {X[P.D_LEN-2:P.D_NF],1'b1,X[P.D_NF-2:0]})) |
|
||||
(YNaN&(Res[P.D_LEN-2:0] === {Y[P.D_LEN-2:P.D_NF],1'b1,Y[P.D_NF-2:0]})) |
|
||||
(ZNaN&(Res[P.D_LEN-2:0] === {Z[P.D_LEN-2:P.D_NF],1'b1,Z[P.D_NF-2:0]})));
|
||||
2'b00: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.S_LEN-1:0] === {1'b0, {P.S_NE+1{1'b1}}, {P.S_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.S_LEN-2:0] === {{P.S_NE+1{1'b1}}, {P.S_NF-1{1'b0}}})) |
|
||||
(XNaN&(Res[P.S_LEN-2:0] === {X[P.S_LEN-2:P.S_NF],1'b1,X[P.S_NF-2:0]})) |
|
||||
(YNaN&(Res[P.S_LEN-2:0] === {Y[P.S_LEN-2:P.S_NF],1'b1,Y[P.S_NF-2:0]})) |
|
||||
(ZNaN&(Res[P.S_LEN-2:0] === {Z[P.S_LEN-2:P.S_NF],1'b1,Z[P.S_NF-2:0]})));
|
||||
2'b10: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.H_LEN-1:0] === {1'b0, {P.H_NE+1{1'b1}}, {P.H_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.H_LEN-2:0] === {{P.H_NE+1{1'b1}}, {P.H_NF-1{1'b0}}})) |
|
||||
(XNaN&(Res[P.H_LEN-2:0] === {X[P.H_LEN-2:P.H_NF],1'b1,X[P.H_NF-2:0]})) |
|
||||
(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
|
||||
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}}})) |
|
||||
(AnsNaN&(Res[P.Q_LEN-2:0] === Ans[P.Q_LEN-2:0])) |
|
||||
(XNaN&(Res[P.Q_LEN-2:0] === {X[P.Q_LEN-2:P.Q_NF],1'b1,X[P.Q_NF-2:0]})) |
|
||||
(YNaN&(Res[P.Q_LEN-2:0] === {Y[P.Q_LEN-2:P.Q_NF],1'b1,Y[P.Q_NF-2:0]})));
|
||||
2'b01: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.D_LEN-1:0] === {1'b0, {P.D_NE+1{1'b1}}, {P.D_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.D_LEN-2:0] === {{P.D_NE+1{1'b1}}, {P.D_NF-1{1'b0}}})) |
|
||||
(AnsNaN&(Res[P.D_LEN-2:0] === Ans[P.D_LEN-2:0])) |
|
||||
(XNaN&(Res[P.D_LEN-2:0] === {X[P.D_LEN-2:P.D_NF],1'b1,X[P.D_NF-2:0]})) |
|
||||
(YNaN&(Res[P.D_LEN-2:0] === {Y[P.D_LEN-2:P.D_NF],1'b1,Y[P.D_NF-2:0]})));
|
||||
2'b00: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.S_LEN-1:0] === {1'b0, {P.S_NE+1{1'b1}}, {P.S_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.S_LEN-2:0] === {{P.S_NE+1{1'b1}}, {P.S_NF-1{1'b0}}})) |
|
||||
(AnsNaN&(Res[P.S_LEN-2:0] === Ans[P.S_LEN-2:0])) |
|
||||
(XNaN&(Res[P.S_LEN-2:0] === {X[P.S_LEN-2:P.S_NF],1'b1,X[P.S_NF-2:0]})) |
|
||||
(YNaN&(Res[P.S_LEN-2:0] === {Y[P.S_LEN-2:P.S_NF],1'b1,Y[P.S_NF-2:0]})));
|
||||
2'b10: NaNGood = (((P.IEEE754==0)&AnsNaN&(Res[P.H_LEN-1:0] === {1'b0, {P.H_NE+1{1'b1}}, {P.H_NF-1{1'b0}}})) |
|
||||
(AnsFlg[4]&(Res[P.H_LEN-2:0] === {{P.H_NE+1{1'b1}}, {P.H_NF-1{1'b0}}})) |
|
||||
(AnsNaN&(Res[P.H_LEN-2:0] === Ans[P.H_LEN-2:0])) |
|
||||
(XNaN&(Res[P.H_LEN-2:0] === {X[P.H_LEN-2:P.H_NF],1'b1,X[P.H_NF-2:0]})) |
|
||||
(YNaN&(Res[P.H_LEN-2:0] === {Y[P.H_LEN-2:P.H_NF],1'b1,Y[P.H_NF-2:0]})));
|
||||
endcase
|
||||
else NaNGood = 1'b0; // integers can't be NaNs
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ||||||| ||| ||| ||||||| ||||||| ||| |||
|
||||
// ||| ||| ||| ||| ||| ||| |||
|
||||
// ||| |||||||||| ||||||| ||| ||||||
|
||||
// ||| ||| ||| ||| ||| ||| |||
|
||||
// ||||||| ||| ||| ||||||| ||||||| ||| |||
|
||||
// ||||||| ||| ||| ||||||| ||||||| ||| |||
|
||||
// ||| ||| ||| ||| ||| ||| |||
|
||||
// ||| |||||||||| ||||||| ||| ||||||
|
||||
// ||| ||| ||| ||| ||| ||| |||
|
||||
// ||||||| ||| ||| ||||||| ||||||| ||| |||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 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;
|
||||
// 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
|
||||
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
|
||||
|
||||
// TestFloat sets the result to all 1's when there is an invalid result, however in
|
||||
// http://www.jhauser.us/arithmetic/TestFloat-3/doc/TestFloat-general.html it says
|
||||
// for an unsigned integer result 0 is also okay
|
||||
|
||||
// TestFloat outputs 800... for both the largest integer values for both positive and negitive numbers but
|
||||
// the riscv spec specifies 2^31-1 for positive values out of range and NaNs ie 7fff...
|
||||
else if ( ((UnitVal === `CVTINTUNIT) | (UnitVal === `CMPUNIT)) & ~FlagMatch ) begin
|
||||
// ResMatch & FlagMatch checks the result again. It is checked within the
|
||||
// test again to avoid issues related when the values change tests (e.g., f16_eq_rne -> f16_eq_rz)
|
||||
if (~(ResMatch & FlagMatch)) 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 Ans: %h %h", X, Y, Z, SrcA, Res, ResFlg, Ans, AnsFlg);
|
||||
$stop;
|
||||
end
|
||||
// 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
|
||||
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
|
||||
|
@ -40,6 +40,10 @@ main:
|
||||
sw t5, 0(t0)
|
||||
fence.i
|
||||
|
||||
# Test not being able to write illegal SATP mode
|
||||
li t5, 0xA000000000080010
|
||||
csrw satp, t5
|
||||
|
||||
# Page table root address at 0x80010000; SV48
|
||||
li t5, 0x9000000000080010
|
||||
csrw satp, t5
|
||||
|
Loading…
Reference in New Issue
Block a user