mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge pull request #373 from harshinisrinath1001/main
Improved testing of pmd in priv, fixed bugs, and attempted to reset menvcfg and fixed spacing in fpu/fma and fpu/postprocessing
This commit is contained in:
commit
6ff2b0cc2c
@ -67,7 +67,6 @@ module fma import cvw::*; #(parameter cvw_t P) (
|
|||||||
// - Multiply the mantissas
|
// - Multiply the mantissas
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// calculate the product's exponent
|
// calculate the product's exponent
|
||||||
fmaexpadd #(P) expadd(.Xe, .Ye, .XZero, .YZero, .Pe);
|
fmaexpadd #(P) expadd(.Xe, .Ye, .XZero, .YZero, .Pe);
|
||||||
|
|
||||||
@ -80,6 +79,7 @@ module fma import cvw::*; #(parameter cvw_t P) (
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Alignment shifter
|
// Alignment shifter
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
fmaalign #(P) align(.Ze, .Zm, .XZero, .YZero, .ZZero, .Xe, .Ye, .Am, .ASticky, .KillProd);
|
fmaalign #(P) align(.Ze, .Zm, .XZero, .YZero, .ZZero, .Xe, .Ye, .Am, .ASticky, .KillProd);
|
||||||
|
|
||||||
// ///////////////////////////////////////////////////////////////////////////////
|
// ///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -91,5 +91,3 @@ module fma import cvw::*; #(parameter cvw_t P) (
|
|||||||
fmalza #(3*P.NF+4, P.NF) lza(.A(AmInv), .Pm(PmKilled), .Cin(InvA & (~ASticky | KillProd)), .sub(InvA), .SCnt);
|
fmalza #(3*P.NF+4, P.NF) lza(.A(AmInv), .Pm(PmKilled), .Cin(InvA & (~ASticky | KillProd)), .sub(InvA), .SCnt);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// fmaalign.sv
|
// fmaalign.sv
|
||||||
//
|
//
|
||||||
@ -51,18 +50,16 @@ module fmaalign import cvw::*; #(parameter cvw_t P) (
|
|||||||
// This could have been done using Pe, but ACnt is on the critical path so we replicate logic for speed
|
// 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};
|
assign ACnt = {2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)} + (P.NE+2)'(P.NF+2) - {2'b0, Ze};
|
||||||
|
|
||||||
// Defualt Addition with only inital left shift
|
// Default Addition with only inital left shift
|
||||||
// | 53'b0 | 106'b(product) | 1'b0 |
|
// | 53'b0 | 106'b(product) | 1'b0 |
|
||||||
// | addnend |
|
// | addnend |
|
||||||
|
|
||||||
assign ZmPreshifted = {Zm,(3*P.NF+3)'(0)};
|
assign ZmPreshifted = {Zm,(3*P.NF+3)'(0)};
|
||||||
|
|
||||||
assign KillProd = (ACnt[P.NE+1]&~ZZero)|XZero|YZero;
|
assign KillProd = (ACnt[P.NE+1]&~ZZero)|XZero|YZero;
|
||||||
assign KillZ = $signed(ACnt)>$signed((P.NE+2)'(3)*(P.NE+2)'(P.NF)+(P.NE+2)'(3));
|
assign KillZ = $signed(ACnt)>$signed((P.NE+2)'(3)*(P.NE+2)'(P.NF)+(P.NE+2)'(3));
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
// If the product is too small to effect the sum, kill the product
|
// If the product is too small to effect the sum, kill the product
|
||||||
|
|
||||||
// | 53'b0 | 106'b(product) | 1'b0 |
|
// | 53'b0 | 106'b(product) | 1'b0 |
|
||||||
// | addnend |
|
// | addnend |
|
||||||
if (KillProd) begin
|
if (KillProd) begin
|
||||||
@ -85,11 +82,9 @@ module fmaalign import cvw::*; #(parameter cvw_t P) (
|
|||||||
end else begin
|
end else begin
|
||||||
ZmShifted = ZmPreshifted >> ACnt;
|
ZmShifted = ZmPreshifted >> ACnt;
|
||||||
ASticky = |(ZmShifted[P.NF-1:0]);
|
ASticky = |(ZmShifted[P.NF-1:0]);
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assign Am = ZmShifted[4*P.NF+3:P.NF];
|
assign Am = ZmShifted[4*P.NF+3:P.NF];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -33,4 +33,3 @@ module fmamult import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
assign Pm = Xm * Ym;
|
assign Pm = Xm * Ym;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// seclect the input to the shifter
|
// seclect the input to the shifter
|
||||||
// fp -> int:
|
// fp -> int:
|
||||||
// | P.XLEN zeros | mantissa | 0's if nessisary |
|
// | P.XLEN zeros | mantissa | 0's if necessary |
|
||||||
// .
|
// .
|
||||||
// Other problems:
|
// Other problems:
|
||||||
// - if shifting to the right (neg CalcExp) then don't a 1 in the round bit (to prevent an incorrect plus 1 later durring rounding)
|
// - if shifting to the right (neg CalcExp) then don't a 1 in the round bit (to prevent an incorrect plus 1 later durring rounding)
|
||||||
@ -58,7 +58,7 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
|
|||||||
// | P.NF-1 zeros | mantissa | 0's if nessisary |
|
// | P.NF-1 zeros | mantissa | 0's if nessisary |
|
||||||
// .
|
// .
|
||||||
// - otherwise:
|
// - otherwise:
|
||||||
// | LzcInM | 0's if nessisary |
|
// | LzcInM | 0's if necessary |
|
||||||
// .
|
// .
|
||||||
// change to int shift to the left one
|
// change to int shift to the left one
|
||||||
always_comb
|
always_comb
|
||||||
@ -95,8 +95,6 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// determine if the result underflows ??? -> fp
|
// determine if the result underflows ??? -> fp
|
||||||
// - if the first 1 is shifted out of the result then the result underflows
|
// - if the first 1 is shifted out of the result then the result underflows
|
||||||
// - can't underflow an integer to fp conversions
|
// - can't underflow an integer to fp conversions
|
||||||
|
@ -120,7 +120,6 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign ShiftGtIntSz = (|FullRe[P.Q_NE:7]|(FullRe[6]&~Int64)) | ((|FullRe[4:0]|(FullRe[5]&Int64))&((FullRe[5]&~Int64) | FullRe[6]&Int64));
|
assign ShiftGtIntSz = (|FullRe[P.Q_NE:7]|(FullRe[6]&~Int64)) | ((|FullRe[4:0]|(FullRe[5]&Int64))&((FullRe[5]&~Int64) | FullRe[6]&Int64));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// calulate overflow flag:
|
// calulate overflow flag:
|
||||||
// if the result is greater than or equal to the max exponent(not taking into account sign)
|
// 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 negitive
|
||||||
@ -142,7 +141,6 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||||||
// | | | | | |
|
// | | | | | |
|
||||||
assign Underflow = ((FullRe[P.NE+1] | (FullRe == 0) | ((FullRe == 1) & (Me == 0) & ~(UfPlus1&Guard)))&(Round|Sticky|Guard))&~(InfIn|NaNIn|DivByZero|Invalid);
|
assign Underflow = ((FullRe[P.NE+1] | (FullRe == 0) | ((FullRe == 1) & (Me == 0) & ~(UfPlus1&Guard)))&(Round|Sticky|Guard))&~(InfIn|NaNIn|DivByZero|Invalid);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Inexact
|
// Inexact
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -199,7 +197,6 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||||||
// - don't set flag if an input is NaN or Inf(IEEE says has to be a finite numerator)
|
// - don't set flag if an input is NaN or Inf(IEEE says has to be a finite numerator)
|
||||||
assign DivByZero = YZero&DivOp&~Sqrt&~(XZero|NaNIn|InfIn);
|
assign DivByZero = YZero&DivOp&~Sqrt&~(XZero|NaNIn|InfIn);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// final flags
|
// final flags
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -209,7 +206,3 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign PostProcFlg = {Invalid|(IntInvalid&CvtOp&ToInt), DivByZero, Overflow&~(ToInt&CvtOp), Underflow&~(ToInt&CvtOp), Inexact};
|
assign PostProcFlg = {Invalid|(IntInvalid&CvtOp&ToInt), DivByZero, Overflow&~(ToInt&CvtOp), Underflow&~(ToInt&CvtOp), Inexact};
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,22 +27,22 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// convert shift
|
// convert shift
|
||||||
// fp -> int: | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp
|
// fp -> int: | `XLEN zeros | Mantissa | 0's if necessary | << CalcExp
|
||||||
// process:
|
// process:
|
||||||
// - start - CalcExp = 1 + XExp - Largest Bias
|
// - start - CalcExp = 1 + XExp - Largest Bias
|
||||||
// | `XLEN zeros | Mantissa | 0's if nessisary |
|
// | `XLEN zeros | Mantissa | 0's if necessary |
|
||||||
//
|
//
|
||||||
// - shift left 1 (1)
|
// - shift left 1 (1)
|
||||||
// | `XLEN-1 zeros |bit| frac | 0's if nessisary |
|
// | `XLEN-1 zeros |bit| frac | 0's if necessary |
|
||||||
// . <- binary point
|
// . <- binary point
|
||||||
//
|
//
|
||||||
// - shift left till unbiased exponent is 0 (XExp - Largest Bias)
|
// - shift left till unbiased exponent is 0 (XExp - Largest Bias)
|
||||||
// | 0's | Mantissa | 0's if nessisary |
|
// | 0's | Mantissa | 0's if necessary |
|
||||||
// | keep |
|
// | keep |
|
||||||
//
|
//
|
||||||
// fp -> fp:
|
// fp -> fp:
|
||||||
// - if result is subnormal or underflowed:
|
// - if result is subnormal or underflowed:
|
||||||
// | `NF-1 zeros | Mantissa | 0's if nessisary | << NF+CalcExp-1
|
// | `NF-1 zeros | Mantissa | 0's if necessary | << NF+CalcExp-1
|
||||||
// process:
|
// process:
|
||||||
// - start
|
// - start
|
||||||
// | mantissa | 0's |
|
// | mantissa | 0's |
|
||||||
@ -55,10 +55,10 @@
|
|||||||
// | keep |
|
// | keep |
|
||||||
//
|
//
|
||||||
// - if the input is subnormal:
|
// - if the input is subnormal:
|
||||||
// | lzcIn | 0's if nessisary | << ZeroCnt+1
|
// | lzcIn | 0's if necessary | << ZeroCnt+1
|
||||||
// - plus 1 to shift out the first 1
|
// - plus 1 to shift out the first 1
|
||||||
//
|
//
|
||||||
// int -> fp: | lzcIn | 0's if nessisary | << ZeroCnt+1
|
// int -> fp: | lzcIn | 0's if necessary | << ZeroCnt+1
|
||||||
// - plus 1 to shift out the first 1
|
// - plus 1 to shift out the first 1
|
||||||
|
|
||||||
// fma shift
|
// fma shift
|
||||||
|
@ -108,7 +108,6 @@ module round import cvw::*; #(parameter cvw_t P) (
|
|||||||
// 11 - do nothing if a small number was supposed to subtracted (the sticky bit was set by the small number)
|
// 11 - do nothing if a small number was supposed to subtracted (the sticky bit was set by the small number)
|
||||||
// - Plus 1 otherwise
|
// - Plus 1 otherwise
|
||||||
|
|
||||||
|
|
||||||
// determine what format the final result is in: int or fp
|
// determine what format the final result is in: int or fp
|
||||||
assign IntRes = ToInt;
|
assign IntRes = ToInt;
|
||||||
assign FpRes = ~IntRes;
|
assign FpRes = ~IntRes;
|
||||||
@ -179,15 +178,10 @@ module round import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// only add the Addend sticky if doing an FMA opperation
|
// only add the Addend sticky if doing an FMA opperation
|
||||||
// - the shifter shifts too far left when there's an underflow (shifting out all possible sticky bits)
|
// - the shifter shifts too far left when there's an underflow (shifting out all possible sticky bits)
|
||||||
assign Sticky = FmaASticky&FmaOp | NormSticky | CvtResUf&CvtOp | FmaMe[P.NE+1]&FmaOp | DivSticky&DivOp;
|
assign Sticky = FmaASticky&FmaOp | NormSticky | CvtResUf&CvtOp | FmaMe[P.NE+1]&FmaOp | DivSticky&DivOp;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// determine round and LSB of the rounded value
|
// determine round and LSB of the rounded value
|
||||||
// - underflow round bit is used to determint the underflow flag
|
// - underflow round bit is used to determint the underflow flag
|
||||||
if (P.FPSIZES == 1) begin
|
if (P.FPSIZES == 1) begin
|
||||||
@ -254,7 +248,6 @@ module round import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign LsbRes = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN] : FpLsbRes;
|
assign LsbRes = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN] : FpLsbRes;
|
||||||
assign Round = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN-2] : FpRound;
|
assign Round = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN-2] : FpRound;
|
||||||
|
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
// Determine if you add 1
|
// Determine if you add 1
|
||||||
case (Frm)
|
case (Frm)
|
||||||
@ -282,9 +275,6 @@ module round import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign FpPlus1 = Plus1&~(ToInt&CvtOp);
|
assign FpPlus1 = Plus1&~(ToInt&CvtOp);
|
||||||
assign UfPlus1 = UfCalcPlus1 & (Sticky|Round);
|
assign UfPlus1 = UfCalcPlus1 & (Sticky|Round);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// place Plus1 into the proper position for the format
|
// place Plus1 into the proper position for the format
|
||||||
if (P.FPSIZES == 1) begin
|
if (P.FPSIZES == 1) begin
|
||||||
assign RoundAdd = {{P.FLEN{1'b0}}, FpPlus1};
|
assign RoundAdd = {{P.FLEN{1'b0}}, FpPlus1};
|
||||||
@ -302,13 +292,9 @@ module round import cvw::*; #(parameter cvw_t P) (
|
|||||||
end else if (P.FPSIZES == 4)
|
end else if (P.FPSIZES == 4)
|
||||||
assign RoundAdd = {(P.Q_NE+1+P.H_NF)'(0), FpPlus1&(OutFmt==P.H_FMT), (P.S_NF-P.H_NF-1)'(0), FpPlus1&(OutFmt==P.S_FMT), (P.D_NF-P.S_NF-1)'(0), FpPlus1&(OutFmt==P.D_FMT), (P.Q_NF-P.D_NF-1)'(0), FpPlus1&(OutFmt==P.Q_FMT)};
|
assign RoundAdd = {(P.Q_NE+1+P.H_NF)'(0), FpPlus1&(OutFmt==P.H_FMT), (P.S_NF-P.H_NF-1)'(0), FpPlus1&(OutFmt==P.S_FMT), (P.D_NF-P.S_NF-1)'(0), FpPlus1&(OutFmt==P.D_FMT), (P.Q_NF-P.D_NF-1)'(0), FpPlus1&(OutFmt==P.Q_FMT)};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// trim unneeded bits from fraction
|
// trim unneeded bits from fraction
|
||||||
assign RoundFrac = Mf[P.CORRSHIFTSZ-1:P.CORRSHIFTSZ-P.NF];
|
assign RoundFrac = Mf[P.CORRSHIFTSZ-1:P.CORRSHIFTSZ-P.NF];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// select the exponent
|
// select the exponent
|
||||||
always_comb
|
always_comb
|
||||||
case(PostProcSel)
|
case(PostProcSel)
|
||||||
@ -326,5 +312,4 @@ module round import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign {FullRe, Rf} = {Me, RoundFrac} + RoundAdd;
|
assign {FullRe, Rf} = {Me, RoundFrac} + RoundAdd;
|
||||||
assign Re = FullRe[P.NE-1:0];
|
assign Re = FullRe[P.NE-1:0];
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -290,7 +290,6 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
|||||||
if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b0}}; // unsigned negitive
|
if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b0}}; // unsigned negitive
|
||||||
else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive
|
else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive
|
||||||
|
|
||||||
|
|
||||||
// select the integer output
|
// select the integer output
|
||||||
// - if the input is invalid (out of bounds NaN or Inf) then output overflow res
|
// - if the input is invalid (out of bounds NaN or Inf) then output overflow res
|
||||||
// - if the input underflows
|
// - if the input underflows
|
||||||
|
@ -27,6 +27,18 @@
|
|||||||
#include "WALLY-init-lib.h"
|
#include "WALLY-init-lib.h"
|
||||||
|
|
||||||
main:
|
main:
|
||||||
|
# Tests sret in machine mode
|
||||||
|
la t1, sretdone
|
||||||
|
csrw sepc, t1
|
||||||
|
sret
|
||||||
|
sretdone:
|
||||||
|
addi t2, x0, 42
|
||||||
|
|
||||||
|
# switch to user mode
|
||||||
|
li a0, 0
|
||||||
|
ecall
|
||||||
|
sret #should be treated as illegal instruction
|
||||||
|
mret #mret in user mode and should be illegal
|
||||||
|
|
||||||
# switch to supervisor mode
|
# switch to supervisor mode
|
||||||
li a0, 1
|
li a0, 1
|
||||||
@ -44,16 +56,38 @@ main:
|
|||||||
csrw satp, zero
|
csrw satp, zero
|
||||||
|
|
||||||
# STIMECMP from S mode
|
# STIMECMP from S mode
|
||||||
li t0, 1
|
# 1st is when MENVCFG_STCE is cleared
|
||||||
|
li a0, 3
|
||||||
|
ecall # starts in M-mode
|
||||||
|
csrw menvcfg, x0
|
||||||
|
li a0, 1
|
||||||
ecall # enter S-mode
|
ecall # enter S-mode
|
||||||
csrw stimecmp, zero
|
csrw stimecmp, zero
|
||||||
li t0, 3
|
li a0, 3
|
||||||
ecall # return to M-mode
|
ecall # return to M-mode
|
||||||
csrsi mcounteren, 2 # mcounteren_tm = 1
|
csrsi mcounteren, 2 # mcounteren_tm = 1
|
||||||
li t0, 1
|
li a0, 1
|
||||||
ecall # supervisor mode again
|
ecall # supervisor mode again
|
||||||
csrw stimecmp, zero
|
csrw stimecmp, zero
|
||||||
li t0, 3
|
li a0, 3
|
||||||
|
ecall # machine mode again
|
||||||
|
|
||||||
|
# STIMECMP from S mode
|
||||||
|
# 2nd is when MENVCFG_STCE is set
|
||||||
|
csrci mcounteren, 2 # mcounteren_tm = 0
|
||||||
|
li t0, 1
|
||||||
|
slli t0, t0, 63
|
||||||
|
csrw menvcfg, t0
|
||||||
|
li a0, 1
|
||||||
|
ecall # enter S-mode
|
||||||
|
csrw stimecmp, zero
|
||||||
|
li a0, 3
|
||||||
|
ecall # return to M-mode
|
||||||
|
csrsi mcounteren, 2 # mcounteren_tm = 1
|
||||||
|
li a0, 1
|
||||||
|
ecall # supervisor mode again
|
||||||
|
csrw stimecmp, zero
|
||||||
|
li a0, 3
|
||||||
ecall # machine mode again
|
ecall # machine mode again
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user