diff --git a/.gitmodules b/.gitmodules index 78243a1de..6c46deabf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -24,3 +24,6 @@ [submodule "addins/branch-predictor-simulator"] path = addins/branch-predictor-simulator url = https://github.com/synxlin/branch-predictor-simulator.git +[submodule "addins/FreeRTOS-Kernel"] + path = addins/FreeRTOS-Kernel + url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git diff --git a/addins/FreeRTOS-Kernel b/addins/FreeRTOS-Kernel new file mode 160000 index 000000000..17a46c252 --- /dev/null +++ b/addins/FreeRTOS-Kernel @@ -0,0 +1 @@ +Subproject commit 17a46c252f2f237e03a6768c5d15731215322f31 diff --git a/sim/FPbuild.txt b/sim/FPbuild.txt index edb4a645c..99f414804 100644 --- a/sim/FPbuild.txt +++ b/sim/FPbuild.txt @@ -34,18 +34,14 @@ other FP tests given by the great SoftFloat/TestFloat output. 4a.) Each test will test all its vectors - if you want to test a subset of the vectors (e.g., only binary16), you should modify the -cvw/testbench/tests-fp.h and comment out the tests you do not want to -test. The best way to do this is to comment out each item out with -the // comment option in SV. For example, - -string f128div[] = '{ -// "f128_div_rne.tv", -// "f128_div_rz.tv", -// "f128_div_ru.tv", -// "f128_div_rd.tv", -// "f128_div_rnm.tv" -}; +testfloat.do in the sim directory. Change the TEST_SIZE="all" to the +specific test you want to run. For example, if you want to run only +binary16, you should set this variable to TEST_SIZE="HP". +4b.) If you want to turn off the generation of wlf files while running +sim-testfloat-batch, you can modify testfloat.do in the sim +directory. Inside this DO file, modify the WAV file to 0 --> i.e., +set "quietly set WAV 0;" diff --git a/sim/sim-testfloat-batch b/sim/sim-testfloat-batch index 4cb03792e..073553e52 100755 --- a/sim/sim-testfloat-batch +++ b/sim/sim-testfloat-batch @@ -10,6 +10,4 @@ # sqrt - test square root # all - test everything -# nowave for 2nd argument supresses wlf files - -vsim -c -do "do testfloat.do rv64fpquad $1 $2" \ No newline at end of file +vsim -c -do "do testfloat.do rv64fpquad $1" \ No newline at end of file diff --git a/sim/testfloat.do b/sim/testfloat.do index c8e8ae7b4..85bd6dfc5 100644 --- a/sim/testfloat.do +++ b/sim/testfloat.do @@ -25,14 +25,18 @@ vlib work # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals # $num = the added words after the call -vlog +incdir+../config/$1 +incdir+../config/shared ../src/wally/cvw.sv ../testbench/testbench-fp.sv ../src/fpu/*.sv ../src/fpu/*/*.sv ../src/generic/*.sv ../src/generic/flop/*.sv -suppress 2583,7063,8607,2697 +vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench-fp.sv ../src/fpu/*.sv ../src/fpu/*/*.sv ../src/generic/*.sv ../src/generic/flop/*.sv -suppress 2583,7063,8607,2697 -vsim -voptargs=+acc work.testbenchfp -G TEST=$2 +# Change TEST_SIZE to only test certain FP width +# values are QP, DP, SP, HP +vsim -voptargs=+acc work.testbenchfp -GTEST=$2 -GTEST_SIZE="all" -# Determine if nowave argument is provided -# this removes any output to a wlf or wave window to reduce -# disk space. -if {($argc > 2) && ($3 eq "nowave")} { +# Set WAV variable to avoid having any output to wave (to limit disk space) +quietly set WAV 1; + +# Determine if nowave argument is provided this removes any output to +# a wlf or wave window to reduce disk space. +if {$WAV eq 0} { puts "No wave output is selected" } else { puts "wave output is selected" diff --git a/sim/wave-fpu.do b/sim/wave-fpu.do index 05ccb2154..08b6b3378 100644 --- a/sim/wave-fpu.do +++ b/sim/wave-fpu.do @@ -7,8 +7,15 @@ add wave -noupdate /testbenchfp/Y add wave -noupdate /testbenchfp/Z add wave -noupdate /testbenchfp/Res add wave -noupdate /testbenchfp/Ans +add wave -noupdate /testbenchfp/reset add wave -noupdate /testbenchfp/DivStart add wave -noupdate /testbenchfp/FDivBusyE +add wave -noupdate /testbenchfp/CheckNow +add wave -noupdate /testbenchfp/DivDone +add wave -noupdate /testbenchfp/ResMatch +add wave -noupdate /testbenchfp/FlagMatch +add wave -noupdate /testbenchfp/CheckNow +add wave -noupdate /testbenchfp/NaNGood add wave -group {PostProc} -noupdate /testbenchfp/postprocess/* add wave -group {PostProc} -noupdate /testbenchfp/postprocess/specialcase/* add wave -group {PostProc} -noupdate /testbenchfp/postprocess/flags/* diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 76855bf81..bdc61f784 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -101,13 +101,13 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( /* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed case(OpD) 7'b0000111: case(Funct3D) - 3'b010: ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flw + 3'b010: ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flw 3'b011: if (P.D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // fld 3'b100: if (P.Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flq 3'b001: if (P.ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flh endcase 7'b0100111: case(Funct3D) - 3'b010: ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsw + 3'b010: ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsw 3'b011: if (P.D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsd 3'b100: if (P.Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsq 3'b001: if (P.ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsh diff --git a/src/fpu/fdivsqrt/fdivsqrt.sv b/src/fpu/fdivsqrt/fdivsqrt.sv index 1a1b893e0..9112da9d1 100644 --- a/src/fpu/fdivsqrt/fdivsqrt.sv +++ b/src/fpu/fdivsqrt/fdivsqrt.sv @@ -27,24 +27,24 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module fdivsqrt import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic reset, + input logic clk, + input logic reset, input logic [P.FMTBITS-1:0] FmtE, - input logic XsE, + input logic XsE, input logic [P.NF:0] XmE, YmE, input logic [P.NE-1:0] XeE, YeE, - input logic XInfE, YInfE, - input logic XZeroE, YZeroE, - input logic XNaNE, YNaNE, - input logic FDivStartE, IDivStartE, - input logic StallM, - input logic FlushE, - input logic SqrtE, SqrtM, + input logic XInfE, YInfE, + input logic XZeroE, YZeroE, + input logic XNaNE, YNaNE, + input logic FDivStartE, IDivStartE, + input logic StallM, + input logic FlushE, + input logic SqrtE, SqrtM, input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // these are the src outputs before the mux choosing between them and PCE to put in srcA/B - input logic [2:0] Funct3E, Funct3M, - input logic IntDivE, W64E, - output logic DivStickyM, - output logic FDivBusyE, IFDivStartE, FDivDoneE, + input logic [2:0] Funct3E, Funct3M, + input logic IntDivE, W64E, + output logic DivStickyM, + output logic FDivBusyE, IFDivStartE, FDivDoneE, output logic [P.NE+1:0] QeM, output logic [P.DIVb:0] QmM, output logic [P.XLEN-1:0] FIntDivResultM @@ -58,19 +58,19 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) ( logic [P.DIVb+3:0] D; // Iterator Divisor logic [P.DIVb:0] FirstU, FirstUM; // Intermediate result values logic [P.DIVb+1:0] FirstC; // Step tracker - logic Firstun; // Quotient selection - logic WZeroE; // Early termination flag + logic Firstun; // Quotient selection + logic WZeroE; // Early termination flag logic [P.DURLEN-1:0] CyclesE; // FSM cycles - logic SpecialCaseM; // Divide by zero, square root of negative, etc. - logic DivStartE; // Enable signal for flops during stall + logic SpecialCaseM; // Divide by zero, square root of negative, etc. + logic DivStartE; // Enable signal for flops during stall // Integer div/rem signals - logic BZeroM; // Denominator is zero - logic IntDivM; // Integer operation + logic BZeroM; // Denominator is zero + logic IntDivM; // Integer operation logic [P.DIVBLEN:0] nM, mM; // Shift amounts - logic NegQuotM, ALTBM, AsM, W64M; // Special handling for postprocessor + logic NegQuotM, ALTBM, AsM, W64M; // Special handling for postprocessor logic [P.XLEN-1:0] AM; // Original Numerator for postprocessor - logic ISpecialCaseE; // Integer div/remainder special cases + logic ISpecialCaseE; // Integer div/remainder special cases fdivsqrtpreproc #(P) fdivsqrtpreproc( // Preprocessor .clk, .IFDivStartE, .Xm(XmE), .Ym(YmE), .Xe(XeE), .Ye(YeE), diff --git a/src/fpu/fdivsqrt/fdivsqrtcycles.sv b/src/fpu/fdivsqrt/fdivsqrtcycles.sv index c7aea4588..09b17871a 100644 --- a/src/fpu/fdivsqrt/fdivsqrtcycles.sv +++ b/src/fpu/fdivsqrt/fdivsqrtcycles.sv @@ -28,8 +28,8 @@ module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) ( input logic [P.FMTBITS-1:0] FmtE, - input logic SqrtE, - input logic IntDivE, + input logic SqrtE, + input logic IntDivE, input logic [P.DIVBLEN:0] nE, output logic [P.DURLEN-1:0] CyclesE ); diff --git a/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv b/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv index adc1d6bf5..5531276df 100644 --- a/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv @@ -29,8 +29,8 @@ module fdivsqrtexpcalc import cvw::*; #(parameter cvw_t P) ( input logic [P.FMTBITS-1:0] Fmt, input logic [P.NE-1:0] Xe, Ye, - input logic Sqrt, - input logic XZero, + input logic Sqrt, + input logic XZero, input logic [P.DIVBLEN:0] ell, m, output logic [P.NE+1:0] Qe ); diff --git a/src/fpu/fdivsqrt/fdivsqrtfgen2.sv b/src/fpu/fdivsqrt/fdivsqrtfgen2.sv index 73afeb527..990e3f19f 100644 --- a/src/fpu/fdivsqrt/fdivsqrtfgen2.sv +++ b/src/fpu/fdivsqrt/fdivsqrtfgen2.sv @@ -27,18 +27,17 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module fdivsqrtfgen2 import cvw::*; #(parameter cvw_t P) ( - input logic up, uz, + input logic up, uz, input logic [P.DIVb+3:0] C, U, UM, output logic [P.DIVb+3:0] F ); - logic [P.DIVb+3:0] FP, FN, FZ; + logic [P.DIVb+3:0] FP, FN, FZ; // Generate for both positive and negative bits assign FP = ~(U << 1) & C; assign FN = (UM << 1) | (C & ~(C << 2)); assign FZ = '0; - always_comb // Choose which adder input will be used if (up) F = FP; else if (uz) F = FZ; diff --git a/src/fpu/fdivsqrt/fdivsqrtfgen4.sv b/src/fpu/fdivsqrt/fdivsqrtfgen4.sv index e0f19957e..fc648f5bd 100644 --- a/src/fpu/fdivsqrt/fdivsqrtfgen4.sv +++ b/src/fpu/fdivsqrt/fdivsqrtfgen4.sv @@ -27,11 +27,11 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module fdivsqrtfgen4 import cvw::*; #(parameter cvw_t P) ( - input logic [3:0] udigit, + input logic [3:0] udigit, input logic [P.DIVb+3:0] C, U, UM, output logic [P.DIVb+3:0] F ); - logic [P.DIVb+3:0] F2, F1, F0, FN1, FN2; + logic [P.DIVb+3:0] F2, F1, F0, FN1, FN2; // Generate for both positive and negative bits assign F2 = (~U << 2) & (C << 2); diff --git a/src/fpu/fdivsqrt/fdivsqrtfsm.sv b/src/fpu/fdivsqrt/fdivsqrtfsm.sv index a10c9f6c9..a727e5536 100644 --- a/src/fpu/fdivsqrt/fdivsqrtfsm.sv +++ b/src/fpu/fdivsqrt/fdivsqrtfsm.sv @@ -27,20 +27,20 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module fdivsqrtfsm import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic XInfE, YInfE, - input logic XZeroE, YZeroE, - input logic XNaNE, YNaNE, - input logic FDivStartE, IDivStartE, - input logic XsE, WZeroE, - input logic SqrtE, - input logic StallM, FlushE, - input logic IntDivE, - input logic ISpecialCaseE, + input logic clk, reset, + input logic XInfE, YInfE, + input logic XZeroE, YZeroE, + input logic XNaNE, YNaNE, + input logic FDivStartE, IDivStartE, + input logic XsE, WZeroE, + input logic SqrtE, + input logic StallM, FlushE, + input logic IntDivE, + input logic ISpecialCaseE, input logic [P.DURLEN-1:0] CyclesE, - output logic IFDivStartE, - output logic FDivBusyE, FDivDoneE, - output logic SpecialCaseM + output logic IFDivStartE, + output logic FDivBusyE, FDivDoneE, + output logic SpecialCaseM ); typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; diff --git a/src/fpu/fdivsqrt/fdivsqrtiter.sv b/src/fpu/fdivsqrt/fdivsqrtiter.sv index 0d9600ad5..1d40e8d9a 100644 --- a/src/fpu/fdivsqrt/fdivsqrtiter.sv +++ b/src/fpu/fdivsqrt/fdivsqrtiter.sv @@ -27,14 +27,14 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module fdivsqrtiter import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic IFDivStartE, - input logic FDivBusyE, - input logic SqrtE, + input logic clk, + input logic IFDivStartE, + input logic FDivBusyE, + input logic SqrtE, input logic [P.DIVb+3:0] X, D, output logic [P.DIVb:0] FirstU, FirstUM, output logic [P.DIVb+1:0] FirstC, - output logic Firstun, + output logic Firstun, output logic [P.DIVb+3:0] FirstWS, FirstWC ); @@ -48,11 +48,11 @@ module fdivsqrtiter import cvw::*; #(parameter cvw_t P) ( logic [P.DIVb:0] UNext[P.DIVCOPIES-1:0]; // U1.b logic [P.DIVb:0] UMNext[P.DIVCOPIES-1:0]; // U1.b logic [P.DIVb+1:0] C[P.DIVCOPIES:0]; // Q2.b - logic [P.DIVb+1:0] initC; // Q2.b + logic [P.DIVb+1:0] initC; // Q2.b logic [P.DIVCOPIES-1:0] un; - logic [P.DIVb+3:0] WSN, WCN; // Q4.b - logic [P.DIVb+3:0] DBar, D2, DBar2; // Q4.b + logic [P.DIVb+3:0] WSN, WCN; // Q4.b + logic [P.DIVb+3:0] DBar, D2, DBar2; // Q4.b logic [P.DIVb+1:0] NextC; logic [P.DIVb:0] UMux, UMMux; logic [P.DIVb:0] initU, initUM; @@ -63,7 +63,7 @@ module fdivsqrtiter import cvw::*; #(parameter cvw_t P) ( // Otherwise, the divisor is retained and the residual and result // are fed back for the next iteration. - // Residual WS/SC registers/initializaiton mux + // Residual WS/SC registers/initialization mux mux2 #(P.DIVb+4) wsmux(WS[P.DIVCOPIES], X, IFDivStartE, WSN); mux2 #(P.DIVb+4) wcmux(WC[P.DIVCOPIES], '0, IFDivStartE, WCN); flopen #(P.DIVb+4) wsreg(clk, FDivBusyE, WSN, WS[0]); diff --git a/src/fpu/fdivsqrt/fdivsqrtpostproc.sv b/src/fpu/fdivsqrt/fdivsqrtpostproc.sv index ad4742421..19856e932 100644 --- a/src/fpu/fdivsqrt/fdivsqrtpostproc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtpostproc.sv @@ -27,27 +27,27 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic StallM, + input logic clk, reset, + input logic StallM, input logic [P.DIVb+3:0] WS, WC, input logic [P.DIVb+3:0] D, input logic [P.DIVb:0] FirstU, FirstUM, input logic [P.DIVb+1:0] FirstC, - input logic SqrtE, - input logic Firstun, SqrtM, SpecialCaseM, NegQuotM, + input logic SqrtE, + input logic Firstun, SqrtM, SpecialCaseM, NegQuotM, input logic [P.XLEN-1:0] AM, - input logic RemOpM, ALTBM, BZeroM, AsM, W64M, + input logic RemOpM, ALTBM, BZeroM, AsM, W64M, input logic [P.DIVBLEN:0] nM, mM, output logic [P.DIVb:0] QmM, - output logic WZeroE, - output logic DivStickyM, + output logic WZeroE, + output logic DivStickyM, output logic [P.XLEN-1:0] FIntDivResultM ); logic [P.DIVb+3:0] W, Sum; logic [P.DIVb:0] PreQmM; - logic NegStickyM; - logic weq0E, WZeroM; + logic NegStickyM; + logic weq0E, WZeroM; logic [P.XLEN-1:0] IntDivResultM; ////////////////////////// diff --git a/src/fpu/fdivsqrt/fdivsqrtpreproc.sv b/src/fpu/fdivsqrt/fdivsqrtpreproc.sv index 2d50b9299..ef14bda78 100644 --- a/src/fpu/fdivsqrt/fdivsqrtpreproc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtpreproc.sv @@ -27,24 +27,24 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic IFDivStartE, + input logic clk, + input logic IFDivStartE, input logic [P.NF:0] Xm, Ym, input logic [P.NE-1:0] Xe, Ye, input logic [P.FMTBITS-1:0] FmtE, - input logic SqrtE, - input logic XZeroE, - input logic [2:0] Funct3E, + input logic SqrtE, + input logic XZeroE, + input logic [2:0] Funct3E, output logic [P.NE+1:0] QeM, output logic [P.DIVb+3:0] X, D, // Int-specific input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B - input logic IntDivE, W64E, - output logic ISpecialCaseE, + input logic IntDivE, W64E, + output logic ISpecialCaseE, output logic [P.DURLEN-1:0] CyclesE, output logic [P.DIVBLEN:0] nM, mM, - output logic NegQuotM, ALTBM, IntDivM, W64M, - output logic AsM, BZeroM, + output logic NegQuotM, ALTBM, IntDivM, W64M, + output logic AsM, BZeroM, output logic [P.XLEN-1:0] AM ); @@ -54,11 +54,11 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) ( logic [P.NE+1:0] QeE; // Quotient Exponent (FP only) logic [P.DIVb-1:0] IFX, IFD; // Correctly-sized inputs for iterator, selected from int or fp input logic [P.DIVBLEN:0] mE, nE, ell; // Leading zeros of inputs - logic NumerZeroE; // Numerator is zero (X or A) - logic AZeroE, BZeroE; // A or B is Zero for integer division - logic SignedDivE; // signed division - logic NegQuotE; // Integer quotient is negative - logic AsE, BsE; // Signs of integer inputs + logic NumerZeroE; // Numerator is zero (X or A) + logic AZeroE, BZeroE; // A or B is Zero for integer division + logic SignedDivE; // signed division + logic NegQuotE; // Integer quotient is negative + logic AsE, BsE; // Signs of integer inputs logic [P.XLEN-1:0] AE; // input A after W64 adjustment logic ALTBE; @@ -166,7 +166,7 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) ( // Sqrt is initialized on step one as R(X-1), so depends on Radix mux2 #(P.DIVb+1) sqrtxmux({~XZeroE, Xfract}, {1'b0, ~XZeroE, Xfract[P.DIVb-1:1]}, (Xe[0] ^ ell[0]), PreSqrtX); - if (P.RADIX == 2) assign SqrtX = {3'b111, PreSqrtX}; + if (P.RADIX == 2) assign SqrtX = {3'b111, PreSqrtX}; else assign SqrtX = {2'b11, PreSqrtX, 1'b0}; mux2 #(P.DIVb+4) prexmux(DivX, SqrtX, SqrtE, PreShiftX); diff --git a/src/ieu/controller.sv b/src/ieu/controller.sv index 838560ed1..c543348e5 100644 --- a/src/ieu/controller.sv +++ b/src/ieu/controller.sv @@ -32,6 +32,8 @@ module controller import cvw::*; #(parameter cvw_t P) ( // Decode stage control signals input logic StallD, FlushD, // Stall, flush Decode stage input logic [31:0] InstrD, // Instruction in Decode stage + input logic [1:0] STATUS_FS, // is FPU enabled? + input logic [3:0] ENVCFG_CBE, // Cache block operation enables output logic [2:0] ImmSrcD, // Type of immediate extension input logic IllegalIEUFPUInstrD, // Illegal IEU and FPU instruction output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers @@ -60,6 +62,9 @@ module controller import cvw::*; #(parameter cvw_t P) ( output logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage output logic BMUActiveE, // Bit manipulation instruction being executed output logic MDUActiveE, // Mul/Div instruction being executed + output logic [3:0] CMOpM, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero + output logic IFUPrefetchE, // instruction prefetch + output logic LSUPrefetchM, // data prefetch // Memory stage control signals input logic StallM, FlushM, // Stall, flush Memory stage @@ -80,16 +85,18 @@ module controller import cvw::*; #(parameter cvw_t P) ( output logic StoreStallD // Store (memory write) causes stall ); + logic [6:0] OpD; // Opcode in Decode stage logic [2:0] Funct3D; // Funct3 field in Decode stage logic [6:0] Funct7D; // Funct7 field in Decode stage - logic [4:0] Rs1D; // Rs1 source register in Decode stage + logic [4:0] Rs1D, Rs2D, RdD; // Rs1/2 source register / dest reg in Decode stage - `define CTRLW 23 + `define CTRLW 24 // pipelined control signals logic RegWriteD, RegWriteE; // RegWrite (register will be written) logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM; // Select which result to write back to register file + logic [2:0] PreImmSrcD; // Immediate source format (before amending for prefetches) logic [1:0] MemRWD, MemRWE; // Store (write to memory) logic ALUOpD; // 0 for address generation, 1 for all other operations (must use Funct3) logic BaseW64D; // W64 for Base instructions specifically @@ -103,6 +110,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( logic CSRReadD; // CSR read instruction logic [1:0] AtomicD; // Atomic (AMO) instruction logic FenceXD; // Fence instruction + logic CMOD; // Cache management instruction logic InvalidateICacheD, FlushDCacheD;// Invalidate I$, flush D$ logic CSRWriteD, CSRWriteE; // CSR write logic PrivilegedD, PrivilegedE; // Privileged instruction @@ -126,16 +134,27 @@ module controller import cvw::*; #(parameter cvw_t P) ( logic [2:0] ZBBSelectD; // ZBB Mux Select Signal logic IFunctD, RFunctD, MFunctD; // Detect I, R, and M-type RV32IM/Rv64IM instructions logic LFunctD, SFunctD, BFunctD; // Detect load, store, branch instructions - logic JFunctD; // detect jalr instruction + logic FLSFunctD; // Detect floating-point loads and stores + logic JRFunctD; // detect jalr instruction + logic FenceFunctD; // Detect fence instruction + logic CMOFunctD; // Detect CMO instruction + logic AFunctD, AMOFunctD; // Detect atomic instructions + logic RWFunctD, MWFunctD; // detect RW/MW instructions + logic PFunctD, CSRFunctD; // detect privileged / CSR instruction logic FenceM; // Fence.I or sfence.VMA instruction in memory stage logic [2:0] ALUSelectD; // ALU Output selection mux control logic IWValidFunct3D; // Detects if Funct3 is valid for IW instructions + logic [3:0] CMOpD, CMOpE; // which CMO instruction 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero + logic IFUPrefetchD; // instruction prefetch + logic LSUPrefetchD, LSUPrefetchE; // data prefetch // Extract fields - assign OpD = InstrD[6:0]; + assign OpD = InstrD[6:0]; assign Funct3D = InstrD[14:12]; assign Funct7D = InstrD[31:25]; - assign Rs1D = InstrD[19:15]; + assign Rs1D = InstrD[19:15]; + assign Rs2D = InstrD[24:20]; + assign RdD = InstrD[11:7]; // Funct 7 checking // Be rigorous about detecting illegal instructions if CSRs or bit manipulation is supported @@ -156,70 +175,108 @@ module controller import cvw::*; #(parameter cvw_t P) ( assign MFunctD = (Funct7D == 7'b0000001) & (P.M_SUPPORTED | (P.ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv assign LFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 | Funct3D == 3'b100 | Funct3D == 3'b101 | ((P.XLEN == 64) & (Funct3D == 3'b011 | Funct3D == 3'b110)); + assign FLSFunctD = (STATUS_FS != 2'b00) & ((Funct3D == 3'b010 & P.F_SUPPORTED) | (Funct3D == 3'b011 & P.D_SUPPORTED) | + (Funct3D == 3'b100 & P.Q_SUPPORTED) | (Funct3D == 3'b001 & P.ZFH_SUPPORTED)); + assign FenceFunctD = (Funct3D == 3'b000) | (P.ZIFENCEI_SUPPORTED & Funct3D == 3'b001); + assign CMOFunctD = (Funct3D == 3'b010 & RdD == 5'b0) & + ((P.ZICBOZ_SUPPORTED & InstrD[31:20] == 12'd4 & ENVCFG_CBE[3]) | + (P.ZICBOM_SUPPORTED & ((InstrD[31:20] == 12'd0 & (ENVCFG_CBE[1:0] != 2'b00))) | + (InstrD[31:20] == 12'd1 | InstrD[31:20] == 12'd2) & ENVCFG_CBE[2])); + // *** need to get with enable bits such as MENVCFG_CBZE + assign AFunctD = (Funct3D == 3'b010) | (P.XLEN == 64 & Funct3D == 3'b011); + assign AMOFunctD = (InstrD[31:27] == 5'b00001) | + (InstrD[31:27] == 5'b00000) | + (InstrD[31:27] == 5'b00100) | + (InstrD[31:27] == 5'b01100) | + (InstrD[31:27] == 5'b01000) | + (InstrD[31:27] == 5'b10000) | + (InstrD[31:27] == 5'b10100) | + (InstrD[31:27] == 5'b11000) | + (InstrD[31:27] == 5'b11100); + assign RWFunctD = ((Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b101) & Funct7ZeroD | + (Funct3D == 3'b000 | Funct3D == 3'b101) & Funct7b5D) & (P.XLEN == 64); + assign MWFunctD = MFunctD & (P.XLEN == 64) & ~(Funct3D == 3'b001 | Funct3D == 3'b010 | Funct3D == 3'b011); assign SFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 | ((P.XLEN == 64) & (Funct3D == 3'b011)); - assign BFunctD = (Funct3D[2:1] != 2'b01); // legal branches - assign JFunctD = (Funct3D == 3'b000); + assign BFunctD = Funct3D[2:1] != 2'b01; // legal branches + assign JRFunctD = Funct3D == 3'b000; + assign PFunctD = Funct3D == 3'b000 & Rs1D == 5'b0 & RdD == 5'b0; + assign CSRFunctD = Funct3D[1:0] != 2'b00; assign IWValidFunct3D = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b101; end else begin:legalcheck2 assign IFunctD = 1; // Don't bother to separate out shift decoding assign RFunctD = ~Funct7D[0]; // Not a multiply assign MFunctD = Funct7D[0] & (P.M_SUPPORTED | (P.ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv assign LFunctD = 1; // don't bother to check Funct3 for loads + assign FLSFunctD = 1; // don't bother to check Func3 for floating-point loads/stores + assign FenceFunctD = 1; // don't bother to check fields for fences + assign CMOFunctD = 1; // don't bother to check fields for CMO instructions + assign AFunctD = 1; // don't bother to check fields for atomics + assign AMOFunctD = 1; // don't bother to check Funct7 for AMO operations + assign RWFunctD = 1; // don't bother to check fields for RW instructions + assign MWFunctD = 1; // don't bother to check fields for MW instructions assign SFunctD = 1; // don't bother to check Funct3 for stores assign BFunctD = 1; // don't bother to check Funct3 for branches - assign JFunctD = 1; // don't bother to check Funct3 for jumps + assign JRFunctD = 1; // don't bother to check Funct3 for jalrs + assign PFunctD = 1; // don't bother to check fields for privileged instructions + assign CSRFunctD = 1; // don't bother to check Funct3 for CSR operations assign IWValidFunct3D = 1; end // Main Instruction Decoder /* verilator lint_off CASEINCOMPLETE */ always_comb begin - ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // default: Illegal instruction + ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0_1; // default: Illegal instruction case(OpD) - // RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_Illegal - 7'b0000011: if (LFunctD) - ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // loads - 7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_1; // flw - only legal if FP supported - 7'b0001111: if (P.ZIFENCEI_SUPPORTED) - ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence - else - ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0; // fence treated as nop + // RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_CMO_Illegal + 7'b0000011: if (LFunctD) + ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0_0; // loads + 7'b0000111: if (FLSFunctD) + ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0_1; // flw - only legal if FP supported + 7'b0001111: if (FenceFunctD) begin + if (P.ZIFENCEI_SUPPORTED) + ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0_0; // fence + else + ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0_0; // fence treated as nop + end else if (CMOFunctD) begin + ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1_0; // CMO Instruction + end 7'b0010011: if (IFunctD) - ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU - 7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc + ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0_0; // I-type ALU + 7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0_0; // auipc 7'b0011011: if (IFunctD & IWValidFunct3D & P.XLEN == 64) - ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i + ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0_0; // IW-type ALU for RV64i 7'b0100011: if (SFunctD) - ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // stores - 7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_1; // fsw - only legal if FP supported - 7'b0101111: if (P.A_SUPPORTED) begin - if (InstrD[31:27] == 5'b00010) - ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr + ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0_0; // stores + 7'b0100111: if (FLSFunctD) + ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0_1; // fsw - only legal if FP supported + 7'b0101111: if (P.A_SUPPORTED & AFunctD) begin + if (InstrD[31:27] == 5'b00010 & Rs2D == 5'b0) + ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0_0; // lr else if (InstrD[31:27] == 5'b00011) - ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc - else - ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0; // amo + ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0_0; // sc + else if (AMOFunctD) + ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0_0; // amo end 7'b0110011: if (RFunctD) - ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type + ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0_0; // R-type else if (MFunctD) - ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide - 7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui - 7'b0111011: if (RFunctD & (P.XLEN == 64)) - ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i - else if (MFunctD & (P.XLEN == 64)) - ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide + ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0_0; // Multiply/divide + 7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0_0; // lui + 7'b0111011: if (RWFunctD) + ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0_0; // R-type W instructions for RV64i + else if (MWFunctD) + ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0_0; // W-type Multiply/Divide 7'b1100011: if (BFunctD) - ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches - 7'b1100111: if (JFunctD) - ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr - 7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal + ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0_0; // branches + 7'b1100111: if (JRFunctD) + ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0_0; // jalr + 7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0_0; // jal 7'b1110011: if (P.ZICSR_SUPPORTED) begin - if (Funct3D == 3'b000) - ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules - else - ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs + if (PFunctD) + ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0_0; // privileged; decoded further in privdec modules + else if (CSRFunctD) + ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0_0; // csrs end endcase end @@ -230,9 +287,9 @@ module controller import cvw::*; #(parameter cvw_t P) ( // On RV32E, can't write to upper 16 registers. Checking reads to upper 16 is more costly so disregard them. assign IllegalERegAdrD = P.E_SUPPORTED & P.ZICSR_SUPPORTED & ControlsD[`CTRLW-1] & InstrD[11]; //assign IllegalBaseInstrD = 1'b0; - assign {BaseRegWriteD, ImmSrcD, ALUSrcAD, BaseALUSrcBD, MemRWD, + assign {BaseRegWriteD, PreImmSrcD, ALUSrcAD, BaseALUSrcBD, MemRWD, ResultSrcD, BranchD, ALUOpD, JumpD, ALUResultSrcD, BaseW64D, CSRReadD, - PrivilegedD, FenceXD, MDUD, AtomicD, unused} = IllegalIEUFPUInstrD ? `CTRLW'b0 : ControlsD; + PrivilegedD, FenceXD, MDUD, AtomicD, CMOD, unused} = IllegalIEUFPUInstrD ? `CTRLW'b0 : ControlsD; assign CSRZeroSrcD = InstrD[14] ? (InstrD[19:15] == 0) : (Rs1D == 0); // Is a CSR instruction using zero as the source? assign CSRWriteD = CSRReadD & !(CSRZeroSrcD & InstrD[13]); // Don't write if setting or clearing zeros @@ -299,14 +356,42 @@ module controller import cvw::*; #(parameter cvw_t P) ( assign InvalidateICacheD = 0; assign FlushDCacheD = 0; end - + + // Cache Management instructions + always_comb begin + CMOpD = 4'b0000; // default: not a cbo instruction + if ((P.ZICBOM_SUPPORTED | P.ZICBOZ_SUPPORTED) & CMOD) begin + CMOpD[3] = (InstrD[31:20] == 12'd4); // cbo.zero + CMOpD[2] = (InstrD[31:20] == 12'd2); // cbo.clean + CMOpD[1] = (InstrD[31:20] == 12'd1) | ((InstrD[31:20] == 12'd0) & (ENVCFG_CBE[1:0] == 2'b01)); // cbo.flush + CMOpD[0] = (InstrD[31:20] == 12'd0) & (ENVCFG_CBE[1:0] == 2'b11); // cbo.inval + end + end + + // Prefetch Hints + always_comb begin + // default: not a prefetch hint + IFUPrefetchD = 1'b0; + LSUPrefetchD = 1'b0; + ImmSrcD = PreImmSrcD; + if (P.ZICBOP_SUPPORTED & (InstrD[14:0] == 15'b110_00000_0010011)) begin // ori with destiation x0 is hint for Prefetch + case (Rs2D) // which type of prefectch? Note: prefetch.r and .w are handled the same in Wally + 5'b00000: IFUPrefetchD = 1'b1; // prefetch.i + 5'b00001: LSUPrefetchD = 1'b1; // prefetch.r + 5'b00011: LSUPrefetchD = 1'b1; // prefetch.w + // default: not a prefetch hint + endcase + if (IFUPrefetchD | LSUPrefetchD) ImmSrcD = 3'b001; // use S-type immediate format for prefetches + end + end + // Decode stage pipeline control register flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD); // Execute stage pipeline control register and logic - flopenrc #(29) controlregE(clk, reset, FlushE, ~StallE, - {ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, InstrValidD}, - {ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE}); + flopenrc #(35) controlregE(clk, reset, FlushE, ~StallE, + {ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, CMOpD, IFUPrefetchD, LSUPrefetchD, InstrValidD}, + {ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, CMOpE, IFUPrefetchE, LSUPrefetchE, InstrValidE}); // Branch Logic // The comparator handles both signed and unsigned branches using BranchSignedE @@ -325,9 +410,9 @@ module controller import cvw::*; #(parameter cvw_t P) ( assign IntDivE = MDUE & Funct3E[2]; // Integer division operation // Memory stage pipeline control register - flopenrc #(20) controlregM(clk, reset, FlushM, ~StallM, - {RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, IntDivE}, - {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM}); + flopenrc #(25) controlregM(clk, reset, FlushM, ~StallM, + {RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, IntDivE, CMOpE, LSUPrefetchE}, + {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM, CMOpM, LSUPrefetchM}); // Writeback stage pipeline control register flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW, diff --git a/src/ieu/datapath.sv b/src/ieu/datapath.sv index 799a25988..bb7638514 100644 --- a/src/ieu/datapath.sv +++ b/src/ieu/datapath.sv @@ -98,7 +98,7 @@ module datapath import cvw::*; #(parameter cvw_t P) ( assign Rs2D = InstrD[24:20]; assign RdD = InstrD[11:7]; regfile #(P.XLEN, P.E_SUPPORTED) regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, R1D, R2D); - extend #(P.XLEN, P.A_SUPPORTED) ext(.InstrD(InstrD[31:7]), .ImmSrcD, .ImmExtD); + extend #(P) ext(.InstrD(InstrD[31:7]), .ImmSrcD, .ImmExtD); // Execute stage pipeline register and logic flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E); diff --git a/src/ieu/extend.sv b/src/ieu/extend.sv index e0551e9dc..bcda43e0a 100644 --- a/src/ieu/extend.sv +++ b/src/ieu/extend.sv @@ -27,28 +27,29 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// -module extend #(parameter XLEN, A_SUPPORTED) ( - input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits) - input logic [2:0] ImmSrcD, // Select what kind of extension to perform - output logic [XLEN-1:0] ImmExtD); // Extended immediate +module extend import cvw::*; #(parameter cvw_t P) ( + input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits) + input logic [2:0] ImmSrcD, // Select what kind of extension to perform + output logic [P.XLEN-1:0] ImmExtD); // Extended immediate - localparam [XLEN-1:0] undefined = {(XLEN){1'bx}}; // could change to 0 after debug + localparam [P.XLEN-1:0] undefined = {(P.XLEN){1'bx}}; // could change to 0 after debug always_comb - case(ImmSrcD) + case (ImmSrcD) // I-type - 3'b000: ImmExtD = {{(XLEN-12){InstrD[31]}}, InstrD[31:20]}; + 3'b000: ImmExtD = {{(P.XLEN-12){InstrD[31]}}, InstrD[31:20]}; // S-type (stores) - 3'b001: ImmExtD = {{(XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]}; + 3'b001: ImmExtD = {{(P.XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]}; // B-type (branches) - 3'b010: ImmExtD = {{(XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0}; + 3'b010: ImmExtD = {{(P.XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0}; // J-type (jal) - 3'b011: ImmExtD = {{(XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0}; + 3'b011: ImmExtD = {{(P.XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0}; // U-type (lui, auipc) - 3'b100: ImmExtD = {{(XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0}; + 3'b100: ImmExtD = {{(P.XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0}; // Store Conditional: zero offset - 3'b101: if (A_SUPPORTED) ImmExtD = 0; + 3'b101: if (P.A_SUPPORTED) ImmExtD = 0; else ImmExtD = undefined; default: ImmExtD = undefined; // undefined endcase + endmodule diff --git a/src/ieu/ieu.sv b/src/ieu/ieu.sv index c4e60aca9..2656b003d 100644 --- a/src/ieu/ieu.sv +++ b/src/ieu/ieu.sv @@ -30,6 +30,8 @@ module ieu import cvw::*; #(parameter cvw_t P) ( input logic clk, reset, // Decode stage signals input logic [31:0] InstrD, // Instruction + input logic [1:0] STATUS_FS, // is FPU enabled? + input logic [3:0] ENVCFG_CBE, // Cache block operation enables input logic IllegalIEUFPUInstrD, // Illegal instruction output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers // Execute stage signals @@ -43,6 +45,9 @@ module ieu import cvw::*; #(parameter cvw_t P) ( output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU src inputs before the mux choosing between them and PCE to put in srcA/B output logic [4:0] RdE, // Destination register output logic MDUActiveE, // Mul/Div instruction being executed + output logic [3:0] CMOpM, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero + output logic IFUPrefetchE, // instruction prefetch + output logic LSUPrefetchM, // datata prefetch // Memory stage signals input logic SquashSCW, // Squash store conditional, from LSU output logic [1:0] MemRWM, // Read/write control goes to LSU @@ -97,11 +102,11 @@ module ieu import cvw::*; #(parameter cvw_t P) ( logic BMUActiveE; // Bit manipulation instruction being executed controller #(P) c( - .clk, .reset, .StallD, .FlushD, .InstrD, .ImmSrcD, + .clk, .reset, .StallD, .FlushD, .InstrD, .STATUS_FS, .ENVCFG_CBE, .ImmSrcD, .IllegalIEUFPUInstrD, .IllegalBaseInstrD, .StallE, .FlushE, .FlagsE, .FWriteIntE, .PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .MemReadE, .CSRReadE, .Funct3E, .IntDivE, .MDUE, .W64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE, .SCE, - .BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .MDUActiveE, + .BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .MDUActiveE, .CMOpM, .IFUPrefetchE, .LSUPrefetchM, .StallM, .FlushM, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M, .RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM, .StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .InvalidateICacheM, .StoreStallD); diff --git a/src/lsu/lsu.sv b/src/lsu/lsu.sv index 9c0d00543..9fda87cd0 100644 --- a/src/lsu/lsu.sv +++ b/src/lsu/lsu.sv @@ -39,6 +39,8 @@ module lsu import cvw::*; #(parameter cvw_t P) ( input logic [6:0] Funct7M, // Atomic memory operation function input logic [1:0] AtomicM, // Atomic memory operation input logic FlushDCacheM, // Flush D cache to next level of memory + input logic [3:0] CMOpM, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero + input logic LSUPrefetchM, // Prefetch output logic CommittedM, // Delay interrupts while memory operation in flight output logic SquashSCW, // Store conditional failed disable write to GPR output logic DCacheMiss, // D cache miss for performance counters @@ -224,7 +226,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( logic [1:0] DTIMMemRWM; // The DTIM uses untranslated addresses, so it is not compatible with virtual memory. - mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr); + mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr); assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0; // **** fix ReadDataWordM to be LLEN. ByteMask is wrong length. // **** create config to support DTIM with floating point. @@ -258,8 +260,10 @@ module lsu import cvw::*; #(parameter cvw_t P) ( assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM; assign CacheRWM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0; assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '0; - assign FlushDCache = FlushDCacheM & ~(IgnoreRequestTLB | SelHPTW); + assign FlushDCache = FlushDCacheM & ~(IgnoreRequestTLB | SelHPTW); + // *** need RT to add support for CMOpM and LSUPrefetchM (DH 7/2/23) + // *** prefetch can just act as a read operation cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.DCACHE_LINELENINBITS), .NUMLINES(P.DCACHE_WAYSIZEINBYTES*8/LINELEN), .NUMWAYS(P.DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(P.LLEN), .MUXINTERVAL(P.LLEN), .READ_ONLY_CACHE(0)) dcache( .clk, .reset, .Stall(GatedStallW), .SelBusBeat, .FlushStage(FlushW), .CacheRW(CacheRWM), .CacheAtomic(CacheAtomicM), diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index fba8a89c5..ccca40a00 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -84,6 +84,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0], output logic [2:0] FRM_REGW, + output logic [3:0] ENVCFG_CBE, // output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns @@ -123,7 +124,11 @@ module csr import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] TVecAlignedM; logic InstrValidNotFlushedM; logic STimerInt; - logic MENVCFG_STCE; + logic [63:0] MENVCFG_REGW; + logic [P.XLEN-1:0] SENVCFG_REGW; + logic ENVCFG_STCE; // supervisor timer counter enable + logic ENVCFG_PBMTE; // page-based memory types enable + logic ENVCFG_FIOM; // fence implies io (presently not used) // only valid unflushed instructions can access CSRs assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW; @@ -214,7 +219,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( csri #(P) csri(.clk, .reset, .CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM, .MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt, - .MIDELEG_REGW, .MENVCFG_STCE, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable); + .MIDELEG_REGW, .ENVCFG_STCE, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable); csrsr #(P) csrsr(.clk, .reset, .StallW, .WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM, @@ -233,10 +238,12 @@ module csr import cvw::*; #(parameter cvw_t P) ( .MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM, .IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM, - .MENVCFG_STCE); + .MENVCFG_REGW); if (P.S_SUPPORTED) begin:csrs + logic STCE; + assign STCE = P.SSTC_SUPPORTED & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_REGW[1] & ENVCFG_STCE)); csrs #(P) csrs(.clk, .reset, .CSRSWriteM, .STrapM, .CSRAdrM, .NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW, @@ -244,8 +251,8 @@ module csr import cvw::*; #(parameter cvw_t P) ( .CSRWriteValM, .PrivilegeModeW, .CSRSReadValM, .STVEC_REGW, .SEPC_REGW, .SCOUNTEREN_REGW, - .SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .MENVCFG_STCE, - .WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt); + .SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .STCE, + .WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt, .SENVCFG_REGW); end else begin assign WriteSSTATUSM = 0; assign CSRSReadValM = 0; @@ -282,6 +289,17 @@ module csr import cvw::*; #(parameter cvw_t P) ( assign IllegalCSRCAccessM = 1; // counters aren't enabled end + // Broadcast appropriate environment configuration based on privilege mode + assign ENVCFG_STCE = MENVCFG_REGW[63]; // supervisor timer counter enable + assign ENVCFG_PBMTE = MENVCFG_REGW[62]; // page-based memory types enable + assign ENVCFG_CBE = (PrivilegeModeW == P.M_MODE) ? 4'b1111 : + (PrivilegeModeW == P.S_MODE | !P.S_SUPPORTED) ? MENVCFG_REGW[7:4] : + (MENVCFG_REGW[7:4] & SENVCFG_REGW[7:4]); + // FIOM presently doesn't do anything because Wally fences don't do anything + assign ENVCFG_FIOM = (PrivilegeModeW == P.M_MODE) ? 1'b1 : + (PrivilegeModeW == P.S_MODE | !P.S_SUPPORTED) ? MENVCFG_REGW[0] : + (MENVCFG_REGW[0] & SENVCFG_REGW[0]); + // merge CSR Reads assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM; flopenrc #(P.XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW); diff --git a/src/privileged/csri.sv b/src/privileged/csri.sv index ca89617d9..2e5488af7 100644 --- a/src/privileged/csri.sv +++ b/src/privileged/csri.sv @@ -34,7 +34,7 @@ module csri import cvw::*; #(parameter cvw_t P) ( input logic [11:0] CSRAdrM, input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt, input logic [11:0] MIDELEG_REGW, - input logic MENVCFG_STCE, + input logic ENVCFG_STCE, output logic [11:0] MIP_REGW, MIE_REGW, output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0 ); @@ -61,7 +61,7 @@ module csri import cvw::*; #(parameter cvw_t P) ( if (P.S_SUPPORTED) begin:mask if (P.SSTC_SUPPORTED) begin assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec) - assign STIP = MENVCFG_STCE ? STimerInt : MIP_REGW_writeable[5]; + assign STIP = ENVCFG_STCE ? STimerInt : MIP_REGW_writeable[5]; end else begin assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9) assign STIP = MIP_REGW_writeable[5]; diff --git a/src/privileged/csrm.sv b/src/privileged/csrm.sv index 61226f790..fd2496c44 100644 --- a/src/privileged/csrm.sv +++ b/src/privileged/csrm.sv @@ -48,12 +48,11 @@ module csrm import cvw::*; #(parameter cvw_t P) ( output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], output logic WriteMSTATUSM, WriteMSTATUSHM, output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM, - output logic MENVCFG_STCE + output logic [63:0] MENVCFG_REGW ); logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW; - logic [63:0] MENVCFG_REGW; logic [P.XLEN-1:0] MENVCFGH_REGW; logic [63:0] MENVCFG_PreWriteValM, MENVCFG_WriteValM; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; @@ -193,15 +192,6 @@ module csrm import cvw::*; #(parameter cvw_t P) ( assign MENVCFGH_REGW = MENVCFG_REGW[63:32]; end - // Extract bit fields - assign MENVCFG_STCE = MENVCFG_REGW[63]; - // Uncomment these other fields when they are defined - // assign MENVCFG_PBMTE = MENVCFG_REGW[62]; - // assign MENVCFG_CBZE = MENVCFG_REGW[7]; - // assign MENVCFG_CBCFE = MENVCFG_REGW[6]; - // assign MENVCFG_CBIE = MENVCFG_REGW[5:4]; - // assign MENVCFG_FIOM = MENVCFG_REGW[0]; - // Read machine mode CSRs // verilator lint_off WIDTH logic [5:0] entry; diff --git a/src/privileged/csrs.sv b/src/privileged/csrs.sv index 97c8b3f22..84a4d0a4b 100644 --- a/src/privileged/csrs.sv +++ b/src/privileged/csrs.sv @@ -44,10 +44,12 @@ module csrs import cvw::*; #(parameter cvw_t P) ( output logic [P.XLEN-1:0] SATP_REGW, input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, input logic [63:0] MTIME_CLINT, - input logic MENVCFG_STCE, + input logic STCE, output logic WriteSSTATUSM, output logic IllegalCSRSAccessM, - output logic STimerInt + output logic STimerInt, + output logic [P.XLEN-1:0] SENVCFG_REGW + ); // Supervisor CSRs @@ -75,7 +77,6 @@ module csrs import cvw::*; #(parameter cvw_t P) ( logic WriteSENVCFGM; logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW; - logic [P.XLEN-1:0] SENVCFG_REGW; logic [P.XLEN-1:0] SENVCFG_WriteValM; logic [63:0] STIMECMP_REGW; @@ -90,8 +91,8 @@ module csrs import cvw::*; #(parameter cvw_t P) ( assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM); assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN); assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG); - assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)); - assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)) & (P.XLEN == 32); + assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & STCE; + assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & STCE & (P.XLEN == 32); // CSRs flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); @@ -125,18 +126,10 @@ module csrs import cvw::*; #(parameter cvw_t P) ( CSRWriteValM[7] & P.ZICBOZ_SUPPORTED, CSRWriteValM[6:4] & {3{P.ZICBOM_SUPPORTED}}, 3'b0, - CSRWriteValM[0] & P.S_SUPPORTED & P.VIRTMEM_SUPPORTED + CSRWriteValM[0] & P.VIRTMEM_SUPPORTED }; flopenr #(P.XLEN) SENVCFGreg(clk, reset, WriteSENVCFGM, SENVCFG_WriteValM, SENVCFG_REGW); - - // Extract bit fields - // Uncomment these other fields when they are defined - // assign SENVCFG_PBMTE = SENVCFG_REGW[62]; - // assign SENVCFG_CBZE = SENVCFG_REGW[7]; - // assign SENVCFG_CBCFE = SENVCFG_REGW[6]; - // assign SENVCFG_CBIE = SENVCFG_REGW[5:4]; - // assign SENVCFG_FIOM = SENVCFG_REGW[0]; // CSR Reads always_comb begin:csrr @@ -157,13 +150,13 @@ module csrs import cvw::*; #(parameter cvw_t P) ( end SCOUNTEREN:CSRSReadValM = {{(P.XLEN-32){1'b0}}, SCOUNTEREN_REGW}; SENVCFG: CSRSReadValM = SENVCFG_REGW; - STIMECMP: if (P.SSTC_SUPPORTED & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM && MENVCFG_STCE))) + STIMECMP: if (STCE) CSRSReadValM = STIMECMP_REGW[P.XLEN-1:0]; else begin CSRSReadValM = 0; IllegalCSRSAccessM = 1; end - STIMECMPH: if (P.SSTC_SUPPORTED & (P.XLEN == 32) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM && MENVCFG_STCE))) + STIMECMPH: if (STCE) CSRSReadValM[31:0] = STIMECMP_REGW[63:32]; else begin // not supported for RV64 CSRSReadValM = 0; diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index 95ba2b0bd..1023618b5 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -82,6 +82,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration entries to MMU output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU output logic [2:0] FRM_REGW, // FPU rounding mode + output logic [3:0] ENVCFG_CBE, // Cache block operation enables // PC logic output in privileged unit output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic // control outputs @@ -136,7 +137,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS, .MEDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .SetFflagsM, .FRM_REGW, + .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .CSRReadValW,.UnalignedPCNextF, .IllegalCSRAccessM, .BigEndianM); // pipeline early-arriving trap sources diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index 39f780a60..793ea5777 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -78,6 +78,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD; logic SquashSCW; logic MDUActiveE; // Mul/Div instruction being executed + logic [3:0] ENVCFG_CBE; // Cache Block operation enables + logic [3:0] CMOpM; // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero + logic IFUPrefetchE, LSUPrefetchM; // instruction / data prefetch hints // floating point unit signals logic [2:0] FRM_REGW; @@ -188,10 +191,10 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( // integer execution unit: integer register file, datapath and controller ieu #(P) ieu(.clk, .reset, // Decode Stage interface - .InstrD, .IllegalIEUFPUInstrD, .IllegalBaseInstrD, + .InstrD, .STATUS_FS, .ENVCFG_CBE, .IllegalIEUFPUInstrD, .IllegalBaseInstrD, // Execute Stage interface .PCE, .PCLinkE, .FWriteIntE, .FCvtIntE, .IEUAdrE, .IntDivE, .W64E, - .Funct3E, .ForwardedSrcAE, .ForwardedSrcBE, .MDUActiveE, + .Funct3E, .ForwardedSrcAE, .ForwardedSrcBE, .MDUActiveE, .CMOpM, .IFUPrefetchE, .LSUPrefetchM, // Memory stage interface .SquashSCW, // from LSU .MemRWM, // read/write control goes to LSU @@ -215,7 +218,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .MemRWM, .Funct3M, .Funct7M(InstrM[31:25]), .AtomicM, .CommittedM, .DCacheMiss, .DCacheAccess, .SquashSCW, .FpLoadStoreM, .FWriteDataM, .IEUAdrE, .IEUAdrM, .WriteDataM, - .ReadDataW, .FlushDCacheM, + .ReadDataW, .FlushDCacheM, .CMOpM, .LSUPrefetchM, // connected to ahb (all stay the same) .LSUHADDR, .HRDATA, .LSUHWDATA, .LSUHWSTRB, .LSUHSIZE, .LSUHBURST, .LSUHTRANS, .LSUHWRITE, .LSUHREADY, @@ -289,9 +292,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .MTIME_CLINT, .IEUAdrM, .SetFflagsM, .InstrAccessFaultF, .HPTWInstrAccessFaultF, .LoadAccessFaultM, .StoreAmoAccessFaultM, .SelHPTW, .PrivilegeModeW, .SATP_REGW, - .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, + .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM); + .FRM_REGW, .ENVCFG_CBE, .BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM); end else begin assign CSRReadValW = 0; assign UnalignedPCNextF = PC2NextF; diff --git a/testbench/common/instrNameDecTB.sv b/testbench/common/instrNameDecTB.sv index 1529de5e6..8f6fbe869 100644 --- a/testbench/common/instrNameDecTB.sv +++ b/testbench/common/instrNameDecTB.sv @@ -30,13 +30,14 @@ module instrNameDecTB( logic [2:0] funct3; logic [6:0] funct7; logic [11:0] imm; - logic [4:0] rs2; + logic [4:0] rs2, rd; assign op = instr[6:0]; assign funct3 = instr[14:12]; assign funct7 = instr[31:25]; assign imm = instr[31:20]; assign rs2 = instr[24:20]; + assign rd = instr[11:7]; // it would be nice to add the operands to the name // create another variable called decoded @@ -77,7 +78,10 @@ module instrNameDecTB( else if (funct7[6:1] == 6'b010010) name = "BEXTI"; else if (funct7 == 7'b0010100 & rs2 == 5'b00111) name = "ORC.B"; else name = "ILLEGAL"; - 10'b0010011_110: name = "ORI"; + 10'b0010011_110: if (rd == 0 & rs2 == 0) name = "PREFETCH.I"; + else if (rd == 0 & rs2 == 1) name = "PREFETCH.R"; + else if (rd == 0 & rs2 == 3) name = "PREFETCH.W"; + else name = "ORI"; 10'b0010011_111: name = "ANDI"; 10'b0010111_???: name = "AUIPC"; 10'b0100011_000: name = "SB"; @@ -215,7 +219,13 @@ module instrNameDecTB( else if (funct7[6:2] == 5'b11000) name = "AMOMINU.D"; else if (funct7[6:2] == 5'b11100) name = "AMOMAXU.D"; else name = "ILLEGAL"; - 10'b0001111_???: name = "FENCE"; + 10'b0001111_000: name = "FENCE"; + 10'b0001111_001: name = "FENCE.I"; + 10'b0001111_010: if (instr[31:20] == 12'd0) name = "CBO.INVAL"; + else if (instr[31:20] == 12'd1) name = "CBO.CLEAN"; + else if (instr[31:20] == 12'd2) name = "CBO.FLUSH"; + else if (instr[31:20] == 12'd4) name = "CBO.ZERO"; + else name = "ILLEGAL"; 10'b1000011_???: name = "FMADD"; 10'b1000111_???: name = "FMSUB"; 10'b1001011_???: name = "FNMSUB"; diff --git a/testbench/common/ramxdetector.sv b/testbench/common/ramxdetector.sv new file mode 100644 index 000000000..987bbefea --- /dev/null +++ b/testbench/common/ramxdetector.sv @@ -0,0 +1,45 @@ +/////////////////////////////////////////// +// ramxdetector.sv +// +// Written: David_Harris@hmc.edu +// Modified: 2 July 2023 +// +// Purpose: Detects if the processor is attempting to read unitialized RAM +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module ramxdetector #(parameter XLEN, LLEN) ( + input logic clk, + input logic MemReadM, + input logic LSULoadAccessFaultM, + input logic [LLEN-1:0] ReadDataM, + input logic [XLEN-1:0] PCM, + input logic [31:0] InstrM, + input logic [XLEN-1:0] IEUAdrM, + input string InstrMName +); + + always_ff @(posedge clk) + if (MemReadM & ~LSULoadAccessFaultM & (ReadDataM === 'bx)) begin + $display("WARNING: Attempting to read from unitialized RAM. Processor may go haywire if it uses x value. But this is normal in WALLY-mmu tests."); + $display(" PCM = %x InstrM = %x (%s), IEUAdrM = %x", PCM, InstrM, InstrMName, IEUAdrM); + //$stop; + end + +endmodule diff --git a/testbench/common/riscvassertions.sv b/testbench/common/riscvassertions.sv index 50577c37d..d1007ec41 100644 --- a/testbench/common/riscvassertions.sv +++ b/testbench/common/riscvassertions.sv @@ -58,6 +58,9 @@ module riscvassertions import cvw::*; #(parameter cvw_t P); assert ((P.ZMMUL_SUPPORTED == 0) || (P.M_SUPPORTED ==0)) else $error("At most one of ZMMUL_SUPPORTED and M_SUPPORTED can be enabled"); assert ((P.ZICNTR_SUPPORTED == 0) || (P.ZICSR_SUPPORTED == 1)) else $error("ZICNTR_SUPPORTED requires ZICSR_SUPPORTED"); assert ((P.ZIHPM_SUPPORTED == 0) || (P.ZICNTR_SUPPORTED == 1)) else $error("ZIPHM_SUPPORTED requires ZICNTR_SUPPORTED"); + assert ((P.ZICBOM_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOM required DCACHE_SUPPORTED"); + assert ((P.ZICBOZ_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOZ required DCACHE_SUPPORTED"); + assert ((P.ZICBOP_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOP required DCACHE_SUPPORTED"); end endmodule diff --git a/testbench/testbench-fp.sv b/testbench/testbench-fp.sv index 63660b025..08d674f1d 100644 --- a/testbench/testbench-fp.sv +++ b/testbench/testbench-fp.sv @@ -1,10 +1,8 @@ /////////////////////////////////////////// // -// Written: me@KatherineParry.com -// Modified: 7/5/2022 -// Modified: 4/2/2023 +// Written: me@KatherineParry.com, james.stine@okstate.edu // -// Purpose: Testbench for Testfloat +// Purpose: Testbench for UCB Testfloat on Wally // // A component of the Wally configurable RISC-V project. // @@ -23,1330 +21,1385 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// -`include "wally-config.vh" + `include "config.vh" `include "tests-fp.vh" import cvw::*; module testbenchfp; - parameter TEST="none"; + // Two parameters TEST, TEST_SIZE used with testfloat.do in sim dir + // to run specific precisions (e.g., quad or all) + parameter TEST="none"; + parameter TEST_SIZE="none"; - string Tests[]; // list of tests to be run - logic [2:0] OpCtrl[]; // list of op controls - logic [2:0] Unit[]; // list of units being tested - 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 [1:0] Fmt[]; // list of formats for the other units + `include "parameter-defs.vh" - logic clk=0; - logic [31:0] TestNum=0; // index for the test - logic [31:0] OpCtrlNum=0; // index for OpCtrl - logic [31:0] errors=0; // how many errors - logic [31:0] VectorNum=0; // index for test vector - logic [31:0] FrmNum=0; // index for rounding mode - logic [`FLEN*4+7:0] TestVectors[8388609:0]; // list of test vectors + // FIXME: needs cleaning of unused variables (jes) + string Tests[]; // list of tests to be run + logic [2:0] OpCtrl[]; // list of op controls + logic [2:0] Unit[]; // list of units being tested + 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 [1:0] Fmt[]; // list of formats for the other units - logic [1:0] FmtVal; // value of the current Fmt - logic [2:0] UnitVal, OpCtrlVal, FrmVal; // value of the currnet Unit/OpCtrl/FrmVal - logic WriteIntVal; // value of the current WriteInt - 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 [`FLEN-1:0] Ans; // correct answer from TestFloat - logic [`FLEN-1:0] Res; // result from other units - logic [4:0] AnsFlg; // correct flags read from testfloat - logic [4:0] ResFlg, Flg; // Result flags - logic [`FMTBITS-1:0] ModFmt; // format - 10 = half, 00 = single, 01 = double, 11 = quad - logic [`FLEN-1:0] FpRes, FpCmpRes; // Results from each unit - logic [`XLEN-1:0] IntRes, CmpRes; // Results from each unit - logic [4:0] FmaFlg, CvtFlg, DivFlg, CmpFlg; // Outputed flags - logic AnsNaN, ResNaN, NaNGood; - logic Xs, Ys, Zs; // sign of the inputs - logic [`NE-1:0] Xe, Ye, Ze; // exponent of the inputs - logic [`NF:0] Xm, Ym, Zm; // mantissas of the inputs - logic XNaN, YNaN, ZNaN; // is the input NaN - logic XSNaN, YSNaN, ZSNaN; // is the input a signaling NaN - logic XSubnorm, ZSubnorm; // is the input denormalized - logic XInf, YInf, ZInf; // is the input infinity - logic XZero, YZero, ZZero; // is the input zero - 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 IntZero; - logic CvtResSgnE; - logic [`NE:0] CvtCalcExpE; // the calculated expoent - logic [`LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by - logic [`DIVb:0] Quot; - logic CvtResSubnormUfE; - logic DivStart, FDivBusyE, OldFDivBusyE; - logic reset = 1'b0; - logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt; - logic [`DURLEN-1:0] Dur; + logic clk=0; + logic [31:0] TestNum=0; // index for the test + logic [31:0] OpCtrlNum=0; // index for OpCtrl + logic [31:0] errors=0; // how many errors + logic [31:0] VectorNum=0; // index for test vector + logic [31:0] FrmNum=0; // index for rounding mode + logic [P.FLEN*4+7:0] TestVectors[8388609:0]; // list of test vectors - // in-between FMA signals - logic Mult; - logic Ss; - logic [`NE+1:0] Pe; - logic [`NE+1:0] Se; - logic ASticky; - logic KillProd; - logic [$clog2(3*`NF+5)-1:0] SCnt; - logic [3*`NF+3:0] Sm; - logic InvA; - logic NegSum; - logic As; - logic Ps; - logic DivSticky; - logic DivDone; - logic DivNegSticky; - logic [`NE+1:0] DivCalcExp; - logic divsqrtop; + logic [1:0] FmtVal; // value of the current Fmt + logic [2:0] UnitVal, OpCtrlVal, FrmVal; // value of the currnet Unit/OpCtrl/FrmVal + logic WriteIntVal; // value of the current WriteInt + logic [P.FLEN-1:0] X, Y, Z; // inputs read from TestFloat + logic [P.FLEN-1:0] XPostBox; // inputs read from TestFloat + logic [P.XLEN-1:0] SrcA; // integer input + logic [P.FLEN-1:0] Ans; // correct answer from TestFloat + logic [P.FLEN-1:0] Res; // result from other units + logic [4:0] AnsFlg; // correct flags read from testfloat + logic [4:0] ResFlg, Flg; // Result flags + logic [P.FMTBITS-1:0] ModFmt; // format - 10 = half, 00 = single, 01 = double, 11 = quad + logic [P.FLEN-1:0] FpRes, FpCmpRes; // Results from each unit + logic [P.XLEN-1:0] IntRes, CmpRes; // Results from each unit + logic [4:0] FmaFlg, CvtFlg, DivFlg; // Outputed flags + logic [4:0] CmpFlg; // Outputed flags + logic AnsNaN, ResNaN, NaNGood; + logic Xs, Ys, Zs; // sign of the inputs + logic [P.NE-1:0] Xe, Ye, Ze; // exponent of the inputs + logic [P.NF:0] Xm, Ym, Zm; // mantissas of the inputs + logic XNaN, YNaN, ZNaN; // is the input NaN + logic XSNaN, YSNaN, ZSNaN; // is the input a signaling NaN + logic XSubnorm, ZSubnorm; // is the input denormalized + logic XInf, YInf, ZInf; // is the input infinity + logic XZero, YZero, ZZero; // is the input zero + logic XExpMax, YExpMax, ZExpMax; // is the input's exponent all ones + logic [P.CVTLEN-1:0] CvtLzcInE; // input to the Leading Zero Counter (priority encoder) + logic IntZero; + logic CvtResSgnE; + logic [P.NE:0] CvtCalcExpE; // the calculated exponent + logic [P.LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by + logic [P.DIVb:0] Quot; + logic CvtResSubnormUfE; + logic DivStart; + logic FDivBusyE; + logic OldFDivBusyE; + logic reset = 1'b0; + logic [$clog2(P.NF+2)-1:0] XZeroCnt, YZeroCnt; + logic [P.DURLEN-1:0] Dur; + + // in-between FMA signals + logic Mult; + logic Ss; + logic [P.NE+1:0] Pe; + logic [P.NE+1:0] Se; + logic ASticky; + logic KillProd; + logic [$clog2(3*P.NF+5)-1:0] SCnt; + logic [3*P.NF+3:0] Sm; + logic InvA; + logic NegSum; + logic As; + logic Ps; + logic DivSticky; + logic DivDone; + logic DivNegSticky; + logic [P.NE+1:0] DivCalcExp; + 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; + logic [2:0] Funct3E; + logic [2:0] Funct3M; + logic FlushE; + logic IFDivStartE; + logic FDivDoneE; + logic [P.NE+1:0] QeM; + logic [P.DIVb:0] QmM; + logic [P.XLEN-1:0] FIntDivResultM; + logic ResMatch; // Check if result match + logic FlagMatch; // Check if IEEE flags match + logic CheckNow; // Final check + logic FMAop; // Is this a FMA operation? + + /////////////////////////////////////////////////////////////////////////////////////////////// - `include "parameter-defs.vh" - - /////////////////////////////////////////////////////////////////////////////////////////////// + // ||||||||| |||||||| ||||||| ||||||||| ||||||| |||||||| ||| + // ||| ||| ||| ||| ||| ||| ||| + // ||| |||||||| ||||||| ||| ||||||| |||||||| ||| + // ||| ||| ||| ||| ||| ||| ||| + // ||| |||||||| ||||||| ||| ||||||| |||||||| ||||||||| - // ||||||||| |||||||| ||||||| ||||||||| ||||||| |||||||| ||| - // ||| ||| ||| ||| ||| ||| ||| - // ||| |||||||| ||||||| ||| ||||||| |||||||| ||| - // ||| ||| ||| ||| ||| ||| ||| - // ||| |||||||| ||||||| ||| ||||||| |||||||| ||||||||| + /////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////// - - // select tests relevent to the specified configuration - // cvtint - test integer conversion unit (fcvtint) - // cvtfp - test floating-point conversion unit (fcvtfp) - // cmp - test comparison unit's LT, LE, EQ opperations (fcmp) - // add - test addition - // sub - test subtraction - // div - test division - // sqrt - test square root - // all - test all of the above - initial begin - $display("TEST is %s", TEST); - if (`Q_SUPPORTED) begin // if Quad percision is supported - if (TEST === "cvtint"| TEST === "all") begin // if testing integer conversion - // add the 128-bit cvtint tests to the to-be-tested list - Tests = {Tests, f128rv32cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b11}; - end - if (`XLEN == 64) begin // if 64-bit integers are supported add their conversions - Tests = {Tests, f128rv64cvtint}; + // select tests relevent to the specified configuration + // cvtint - test integer conversion unit (fcvtint) + // cvtfp - test floating-point conversion unit (fcvtfp) + // cmp - test comparison unit's LT, LE, EQ opperations (fcmp) + // add - test addition + // sub - test subtraction + // div - test division + // sqrt - test square root + // all - test all of the above + + initial begin + // Information displayed for user on what is simulating + $display("\nThe start of simulation..."); + $display("This simulation for TEST is %s", TEST); + $display("This simulation for TEST is of the operand size of %s", TEST_SIZE); + if (P.Q_SUPPORTED & (TEST_SIZE == "QP" | TEST_SIZE == "all")) begin // if Quad percision is supported + if (TEST === "cvtint" | TEST === "all") begin // if testing integer conversion + // add the 128-bit cvtint tests to the to-be-tested list + Tests = {Tests, f128rv32cvtint}; // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; // add what unit is used and the fmt to their lists (one for each test) for(int i = 0; i<20; i++) begin Unit = {Unit, `CVTINTUNIT}; Fmt = {Fmt, 2'b11}; end - end - end - // if the floating-point conversions are being tested - if (TEST === "cvtfp" | TEST === "all") begin - if(`D_SUPPORTED) begin // if double precision is supported - // add the 128 <-> 64 bit conversions to the to-be-tested list - Tests = {Tests, f128f64cvt}; - // add the op-ctrls (i.e. the format of the result) - OpCtrl = {OpCtrl, 3'b01, 3'b11}; - WriteInt = {WriteInt, 1'b0, 1'b0}; - // add the unit being tested and fmt (input format) - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b11}; - end - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - if(`F_SUPPORTED) begin // if single precision is supported - // add the 128 <-> 32 bit conversions to the to-be-tested list - Tests = {Tests, f128f32cvt}; - // add the op-ctrls (i.e. the format of the result) - OpCtrl = {OpCtrl, 3'b00, 3'b11}; - WriteInt = {WriteInt, 1'b0, 1'b0}; - // add the unit being tested and fmt (input format) - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b11}; - end - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - if(`ZFH_SUPPORTED) begin // if half precision is supported - // add the 128 <-> 16 bit conversions to the to-be-tested list - Tests = {Tests, f128f16cvt}; - // add the op-ctrls (i.e. the format of the result) - OpCtrl = {OpCtrl, 3'b10, 3'b11}; - WriteInt = {WriteInt, 1'b0, 1'b0}; - // add the unit being tested and fmt (input format) - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b11}; - end - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b10}; - end - end + if (P.XLEN == 64) begin // if 64-bit integers are supported add their conversions + Tests = {Tests, f128rv64cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b11}; + end + end + end + // if the floating-point conversions are being tested + if (TEST === "cvtfp" | TEST === "all") begin + if (P.D_SUPPORTED) begin // if double precision is supported + // add the 128 <-> 64 bit conversions to the to-be-tested list + Tests = {Tests, f128f64cvt}; + // add the op-ctrls (i.e. the format of the result) + OpCtrl = {OpCtrl, 3'b01, 3'b11}; + WriteInt = {WriteInt, 1'b0, 1'b0}; + // add the unit being tested and fmt (input format) + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b11}; + end + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + if (P.F_SUPPORTED) begin // if single precision is supported + // add the 128 <-> 32 bit conversions to the to-be-tested list + Tests = {Tests, f128f32cvt}; + // add the op-ctrls (i.e. the format of the result) + OpCtrl = {OpCtrl, 3'b00, 3'b11}; + WriteInt = {WriteInt, 1'b0, 1'b0}; + // add the unit being tested and fmt (input format) + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b11}; + end + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + if (P.ZFH_SUPPORTED) begin // if half precision is supported + // add the 128 <-> 16 bit conversions to the to-be-tested list + Tests = {Tests, f128f16cvt}; + // add the op-ctrls (i.e. the format of the result) + OpCtrl = {OpCtrl, 3'b10, 3'b11}; + WriteInt = {WriteInt, 1'b0, 1'b0}; + // add the unit being tested and fmt (input format) + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b11}; + end + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + end + if (TEST === "cmp" | TEST === "all") begin// if comparisons are being tested + // add the compare tests/op-ctrls/unit/fmt + Tests = {Tests, f128cmp}; + OpCtrl = {OpCtrl, `EQ_OPCTRL, `LE_OPCTRL, `LT_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b0}; + for(int i = 0; i<15; i++) begin + Unit = {Unit, `CMPUNIT}; + Fmt = {Fmt, 2'b11}; + end + end + if (TEST === "add" | TEST === "all") begin // if addition is being tested + // add the addition tests/op-ctrls/unit/fmt + Tests = {Tests, f128add}; + OpCtrl = {OpCtrl, `ADD_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b11}; + end + end + if (TEST === "sub" | TEST === "all") begin // if subtraction is being tested + // add the subtraction tests/op-ctrls/unit/fmt + Tests = {Tests, f128sub}; + OpCtrl = {OpCtrl, `SUB_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b11}; + end + end + if (TEST === "mul" | TEST === "all") begin // if multiplication is being tested + // add the multiply tests/op-ctrls/unit/fmt + Tests = {Tests, f128mul}; + OpCtrl = {OpCtrl, `MUL_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b11}; + end + end + if (TEST === "div" | TEST === "all") begin // if division is being tested + // add the divide tests/op-ctrls/unit/fmt + Tests = {Tests, f128div}; + OpCtrl = {OpCtrl, `DIV_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `DIVUNIT}; + Fmt = {Fmt, 2'b11}; + end + end + if (TEST === "sqrt" | TEST === "all") begin // if square-root is being tested + // add the square-root tests/op-ctrls/unit/fmt + Tests = {Tests, f128sqrt}; + OpCtrl = {OpCtrl, `SQRT_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `DIVUNIT}; + Fmt = {Fmt, 2'b11}; + end + end + if (TEST === "fma" | TEST === "all") begin // if fused-mutliply-add is being tested + Tests = {Tests, f128fma}; + OpCtrl = {OpCtrl, `FMA_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b11}; + end + end end - if (TEST === "cmp" | TEST === "all") begin// if comparisons are being tested - // add the compare tests/op-ctrls/unit/fmt - Tests = {Tests, f128cmp}; - OpCtrl = {OpCtrl, `EQ_OPCTRL, `LE_OPCTRL, `LT_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b0}; - for(int i = 0; i<15; i++) begin - Unit = {Unit, `CMPUNIT}; - Fmt = {Fmt, 2'b11}; - end - end - if (TEST === "add" | TEST === "all") begin // if addition is being tested - // add the addition tests/op-ctrls/unit/fmt - Tests = {Tests, f128add}; - OpCtrl = {OpCtrl, `ADD_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b11}; - end - end - if (TEST === "sub" | TEST === "all") begin // if subtraction is being tested - // add the subtraction tests/op-ctrls/unit/fmt - Tests = {Tests, f128sub}; - OpCtrl = {OpCtrl, `SUB_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b11}; - end - end - if (TEST === "mul" | TEST === "all") begin // if multiplication is being tested - // add the multiply tests/op-ctrls/unit/fmt - Tests = {Tests, f128mul}; - OpCtrl = {OpCtrl, `MUL_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b11}; - end - end - if (TEST === "div" | TEST === "all") begin // if division is being tested - // add the divide tests/op-ctrls/unit/fmt - Tests = {Tests, f128div}; - OpCtrl = {OpCtrl, `DIV_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `DIVUNIT}; - Fmt = {Fmt, 2'b11}; - end - end - if (TEST === "sqrt" | TEST === "all") begin // if square-root is being tested - // add the square-root tests/op-ctrls/unit/fmt - Tests = {Tests, f128sqrt}; - OpCtrl = {OpCtrl, `SQRT_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `DIVUNIT}; - Fmt = {Fmt, 2'b11}; - end - end - if (TEST === "fma" | TEST === "all") begin // if fused-mutliply-add is being tested - Tests = {Tests, f128fma}; - OpCtrl = {OpCtrl, `FMA_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b11}; - end - end - end - if (`D_SUPPORTED) begin // if double precision is supported - if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested - Tests = {Tests, f64rv32cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b01}; - end - if (`XLEN == 64) begin // if 64-bit integers are being supported - Tests = {Tests, f64rv64cvtint}; + if (P.D_SUPPORTED & (TEST_SIZE == "DP" | TEST_SIZE == "all")) begin // if double precision is supported + if (TEST === "cvtint" | TEST === "all") begin // if integer conversion is being tested + Tests = {Tests, f64rv32cvtint}; // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; // add what unit is used and the fmt to their lists (one for each test) for(int i = 0; i<20; i++) begin Unit = {Unit, `CVTINTUNIT}; Fmt = {Fmt, 2'b01}; end - end + if (P.XLEN == 64) begin // if 64-bit integers are being supported + Tests = {Tests, f64rv64cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + end + if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversions are being tested + if (P.F_SUPPORTED) begin // if single precision is supported + // add the 64 <-> 32 bit conversions to the to-be-tested list + Tests = {Tests, f64f32cvt}; + // add the op-ctrls (i.e. the format of the result) + OpCtrl = {OpCtrl, 3'b00, 3'b01}; + WriteInt = {WriteInt, 1'b0, 1'b0}; + // add the unit being tested and fmt (input format) + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b01}; + end + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + if (P.ZFH_SUPPORTED) begin // if half precision is supported + // add the 64 <-> 16 bit conversions to the to-be-tested list + Tests = {Tests, f64f16cvt}; + // add the op-ctrls (i.e. the format of the result) + OpCtrl = {OpCtrl, 3'b10, 3'b01}; + WriteInt = {WriteInt, 1'b0, 1'b0}; + // add the unit being tested and fmt (input format) + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b01}; + end + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + end + if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f64cmp}; + OpCtrl = {OpCtrl, `EQ_OPCTRL, `LE_OPCTRL, `LT_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b0}; + for(int i = 0; i<15; i++) begin + Unit = {Unit, `CMPUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + if (TEST === "add" | TEST === "all") begin // if addition is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f64add}; + OpCtrl = {OpCtrl, `ADD_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + if (TEST === "sub" | TEST === "all") begin // if subtration is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f64sub}; + OpCtrl = {OpCtrl, `SUB_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + if (TEST === "mul" | TEST === "all") begin // if multiplication is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f64mul}; + OpCtrl = {OpCtrl, `MUL_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + if (TEST === "div" | TEST === "all") begin // if division is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f64div}; + OpCtrl = {OpCtrl, `DIV_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `DIVUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + if (TEST === "sqrt" | TEST === "all") begin // if square-root is being tessted + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f64sqrt}; + OpCtrl = {OpCtrl, `SQRT_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `DIVUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + if (TEST === "fma" | TEST === "all") begin // if the fused multiply add is being tested + Tests = {Tests, f64fma}; + OpCtrl = {OpCtrl, `FMA_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b01}; + end + end end - if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversions are being tested - if(`F_SUPPORTED) begin // if single precision is supported - // add the 64 <-> 32 bit conversions to the to-be-tested list - Tests = {Tests, f64f32cvt}; - // add the op-ctrls (i.e. the format of the result) - OpCtrl = {OpCtrl, 3'b00, 3'b01}; - WriteInt = {WriteInt, 1'b0, 1'b0}; - // add the unit being tested and fmt (input format) - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b01}; - end - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - if(`ZFH_SUPPORTED) begin // if half precision is supported - // add the 64 <-> 16 bit conversions to the to-be-tested list - Tests = {Tests, f64f16cvt}; - // add the op-ctrls (i.e. the format of the result) - OpCtrl = {OpCtrl, 3'b10, 3'b01}; - WriteInt = {WriteInt, 1'b0, 1'b0}; - // add the unit being tested and fmt (input format) - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b01}; - end - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - end - if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f64cmp}; - OpCtrl = {OpCtrl, `EQ_OPCTRL, `LE_OPCTRL, `LT_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b0}; - for(int i = 0; i<15; i++) begin - Unit = {Unit, `CMPUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - if (TEST === "add" | TEST === "all") begin // if addition is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f64add}; - OpCtrl = {OpCtrl, `ADD_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - if (TEST === "sub" | TEST === "all") begin // if subtration is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f64sub}; - OpCtrl = {OpCtrl, `SUB_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - if (TEST === "mul" | TEST === "all") begin // if multiplication is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f64mul}; - OpCtrl = {OpCtrl, `MUL_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - if (TEST === "div" | TEST === "all") begin // if division is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f64div}; - OpCtrl = {OpCtrl, `DIV_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `DIVUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - if (TEST === "sqrt" | TEST === "all") begin // if square-root is being tessted - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f64sqrt}; - OpCtrl = {OpCtrl, `SQRT_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `DIVUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - if (TEST === "fma" | TEST === "all") begin // if the fused multiply add is being tested - Tests = {Tests, f64fma}; - OpCtrl = {OpCtrl, `FMA_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - end - if (`F_SUPPORTED) begin // if single precision being supported - if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested - Tests = {Tests, f32rv32cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b00}; - end - if (`XLEN == 64) begin // if 64-bit integers are supported - Tests = {Tests, f32rv64cvtint}; + if (P.F_SUPPORTED & (TEST_SIZE == "SP" | TEST_SIZE == "all")) begin // if single precision being supported + if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested + Tests = {Tests, f32rv32cvtint}; // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; // add what unit is used and the fmt to their lists (one for each test) for(int i = 0; i<20; i++) begin Unit = {Unit, `CVTINTUNIT}; Fmt = {Fmt, 2'b00}; end - end + if (P.XLEN == 64) begin // if 64-bit integers are supported + Tests = {Tests, f32rv64cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + end + if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversion is being tested + if (P.ZFH_SUPPORTED) begin + // add the 32 <-> 16 bit conversions to the to-be-tested list + Tests = {Tests, f32f16cvt}; + // add the op-ctrls (i.e. the format of the result) + OpCtrl = {OpCtrl, 3'b10, 3'b00}; + WriteInt = {WriteInt, 1'b0, 1'b0}; + // add the unit being tested and fmt (input format) + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b00}; + end + for(int i = 0; i<5; i++) begin + Unit = {Unit, `CVTFPUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + end + if (TEST === "cmp" | TEST === "all") begin // if comparision is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f32cmp}; + OpCtrl = {OpCtrl, `EQ_OPCTRL, `LE_OPCTRL, `LT_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b0}; + for(int i = 0; i<15; i++) begin + Unit = {Unit, `CMPUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + if (TEST === "add" | TEST === "all") begin // if addition is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f32add}; + OpCtrl = {OpCtrl, `ADD_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + if (TEST === "sub" | TEST === "all") begin // if subtration is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f32sub}; + OpCtrl = {OpCtrl, `SUB_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + if (TEST === "mul" | TEST === "all") begin // if multiply is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f32mul}; + OpCtrl = {OpCtrl, `MUL_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + if (TEST === "div" | TEST === "all") begin // if division is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f32div}; + OpCtrl = {OpCtrl, `DIV_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `DIVUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f32sqrt}; + OpCtrl = {OpCtrl, `SQRT_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `DIVUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + if (TEST === "fma" | TEST === "all") begin // if fma is being tested + Tests = {Tests, f32fma}; + OpCtrl = {OpCtrl, `FMA_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b00}; + end + end end - if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversion is being tested - if(`ZFH_SUPPORTED) begin - // add the 32 <-> 16 bit conversions to the to-be-tested list - Tests = {Tests, f32f16cvt}; - // add the op-ctrls (i.e. the format of the result) - OpCtrl = {OpCtrl, 3'b10, 3'b00}; - WriteInt = {WriteInt, 1'b0, 1'b0}; - // add the unit being tested and fmt (input format) - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b00}; - end - for(int i = 0; i<5; i++) begin - Unit = {Unit, `CVTFPUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - end - if (TEST === "cmp" | TEST === "all") begin // if comparision is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f32cmp}; - OpCtrl = {OpCtrl, `EQ_OPCTRL, `LE_OPCTRL, `LT_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b0}; - for(int i = 0; i<15; i++) begin - Unit = {Unit, `CMPUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - if (TEST === "add" | TEST === "all") begin // if addition is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f32add}; - OpCtrl = {OpCtrl, `ADD_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - if (TEST === "sub" | TEST === "all") begin // if subtration is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f32sub}; - OpCtrl = {OpCtrl, `SUB_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - if (TEST === "mul" | TEST === "all") begin // if multiply is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f32mul}; - OpCtrl = {OpCtrl, `MUL_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - if (TEST === "div" | TEST === "all") begin // if division is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f32div}; - OpCtrl = {OpCtrl, `DIV_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `DIVUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f32sqrt}; - OpCtrl = {OpCtrl, `SQRT_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `DIVUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - if (TEST === "fma" | TEST === "all") begin // if fma is being tested - Tests = {Tests, f32fma}; - OpCtrl = {OpCtrl, `FMA_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - end - if (`ZFH_SUPPORTED) begin // if half precision supported - if (TEST === "cvtint"| TEST === "all") begin // if in conversions are being tested - Tests = {Tests, f16rv32cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b10}; - end - if (`XLEN == 64) begin // if 64-bit integers are supported - Tests = {Tests, f16rv64cvtint}; + if (P.ZFH_SUPPORTED & (TEST_SIZE == "HP" | TEST_SIZE == "all")) begin // if half precision supported + if (TEST === "cvtint" | TEST === "all") begin // if in conversions are being tested + Tests = {Tests, f16rv32cvtint}; // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; // add what unit is used and the fmt to their lists (one for each test) for(int i = 0; i<20; i++) begin Unit = {Unit, `CVTINTUNIT}; Fmt = {Fmt, 2'b10}; end - end + if (P.XLEN == 64) begin // if 64-bit integers are supported + Tests = {Tests, f16rv64cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + end + if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f16cmp}; + OpCtrl = {OpCtrl, `EQ_OPCTRL, `LE_OPCTRL, `LT_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b0}; + for(int i = 0; i<15; i++) begin + Unit = {Unit, `CMPUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + if (TEST === "add" | TEST === "all") begin // if addition is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f16add}; + OpCtrl = {OpCtrl, `ADD_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + if (TEST === "sub" | TEST === "all") begin // if subtraction is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f16sub}; + OpCtrl = {OpCtrl, `SUB_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + if (TEST === "mul" | TEST === "all") begin // if multiplication is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f16mul}; + OpCtrl = {OpCtrl, `MUL_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + if (TEST === "div" | TEST === "all") begin // if division is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f16div}; + OpCtrl = {OpCtrl, `DIV_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `DIVUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested + // add the correct tests/op-ctrls/unit/fmt to their lists + Tests = {Tests, f16sqrt}; + OpCtrl = {OpCtrl, `SQRT_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `DIVUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + if (TEST === "fma" | TEST === "all") begin // if fma is being tested + Tests = {Tests, f16fma}; + OpCtrl = {OpCtrl, `FMA_OPCTRL}; + WriteInt = {WriteInt, 1'b0}; + for(int i = 0; i<5; i++) begin + Unit = {Unit, `FMAUNIT}; + Fmt = {Fmt, 2'b10}; + end + end end - if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f16cmp}; - OpCtrl = {OpCtrl, `EQ_OPCTRL, `LE_OPCTRL, `LT_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b0}; - for(int i = 0; i<15; i++) begin - Unit = {Unit, `CMPUNIT}; - Fmt = {Fmt, 2'b10}; - end + // check if nothing is being tested + if (Tests.size() == 0) begin + $display("TEST %s not supported in this configuration", TEST); + $stop; end - if (TEST === "add" | TEST === "all") begin // if addition is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f16add}; - OpCtrl = {OpCtrl, `ADD_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - if (TEST === "sub" | TEST === "all") begin // if subtraction is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f16sub}; - OpCtrl = {OpCtrl, `SUB_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - if (TEST === "mul" | TEST === "all") begin // if multiplication is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f16mul}; - OpCtrl = {OpCtrl, `MUL_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - if (TEST === "div" | TEST === "all") begin // if division is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f16div}; - OpCtrl = {OpCtrl, `DIV_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `DIVUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested - // add the correct tests/op-ctrls/unit/fmt to their lists - Tests = {Tests, f16sqrt}; - OpCtrl = {OpCtrl, `SQRT_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `DIVUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - if (TEST === "fma" | TEST === "all") begin // if fma is being tested - Tests = {Tests, f16fma}; - OpCtrl = {OpCtrl, `FMA_OPCTRL}; - WriteInt = {WriteInt, 1'b0}; - for(int i = 0; i<5; i++) begin - Unit = {Unit, `FMAUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - end + end - // check if nothing is being tested - if (Tests.size() == 0) begin - $display("TEST %s not supported in this configuration", TEST); - $stop; - end - end + /////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////// + // ||||||||| |||||||| ||||||||| ||||||| ||||||||| |||||||| ||||||| ||||||||| + // ||| ||| ||| ||| ||| || || ||| ||| ||| ||| + // |||||||| |||||||| ||||||||| || || ||| |||||||| ||||||| ||| + // ||| || ||| ||| ||| || || ||| ||| ||| ||| + // ||| ||| |||||||| ||| ||| ||||||| ||| |||||||| ||||||| ||| - // ||||||||| |||||||| ||||||||| ||||||| ||||||||| |||||||| ||||||| ||||||||| - // ||| ||| ||| ||| ||| || || ||| ||| ||| ||| - // |||||||| |||||||| ||||||||| || || ||| |||||||| ||||||| ||| - // ||| || ||| ||| ||| || || ||| ||| ||| ||| - // ||| ||| |||||||| ||| ||| ||||||| ||| |||||||| ||||||| ||| + /////////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////// + // Read the first test + initial begin + //string testname = {`PATH, Tests[TestNum]}; + string p = `PATH; + string testname; + string tt0; + tt0 = $psprintf("%s", Tests[TestNum]); + testname = {p, tt0}; + $display("Here you are %s", testname); + $display("\n\nRunning %s vectors ", Tests[TestNum]); + $readmemh(testname, TestVectors); + // set the test index to 0 + TestNum = 0; + end - // Read the first test - initial begin - $display("\n\nRunning %s vectors", Tests[TestNum]); - $readmemh({`PATH, Tests[TestNum]}, TestVectors); - // set the test index to 0 - TestNum = 0; - end + // set a the signals for all tests + always_comb UnitVal = Unit[TestNum]; + always_comb FmtVal = Fmt[TestNum]; + always_comb OpCtrlVal = OpCtrl[OpCtrlNum]; + always_comb WriteIntVal = WriteInt[OpCtrlNum]; + always_comb FrmVal = Frm[FrmNum]; - // set a the signals for all tests - always_comb UnitVal = Unit[TestNum]; - always_comb FmtVal = Fmt[TestNum]; - always_comb OpCtrlVal = OpCtrl[OpCtrlNum]; - always_comb WriteIntVal = WriteInt[OpCtrlNum]; - always_comb FrmVal = Frm[FrmNum]; + // modify the format signal if only 2 percisions supported + // - 1 for the larger precision + // - 0 for the smaller precision + always_comb begin + if (P.FMTBITS == 1) ModFmt = FmtVal == P.FMT; + else ModFmt = FmtVal; + end - // modify the format signal if only 2 percisions supported - // - 1 for the larger precision - // - 0 for the smaller precision - always_comb begin - if(`FMTBITS == 1) ModFmt = FmtVal == `FMT; - else ModFmt = FmtVal; - end + // extract the inputs (X, Y, Z, SrcA) and the output (Ans, AnsFlg) from the current test vector + readvectors #(P) readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]), + .VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA, + .Xs, .Ys, .Zs, .Unit(UnitVal), + .Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal), + .Xm, .Ym, .Zm, .DivStart, + .XNaN, .YNaN, .ZNaN, + .XSNaN, .YSNaN, .ZSNaN, + .XSubnorm, .ZSubnorm, + .XZero, .YZero, .ZZero, + .XInf, .YInf, .ZInf, .XExpMax, + .X, .Y, .Z, .XPostBox); - // 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]), - .VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA, - .Xs, .Ys, .Zs, .Unit(UnitVal), - .Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal), - .Xm, .Ym, .Zm, .DivStart, - .XNaN, .YNaN, .ZNaN, - .XSNaN, .YSNaN, .ZSNaN, - .XSubnorm, .ZSubnorm, - .XZero, .YZero, .ZZero, - .XInf, .YInf, .ZInf, .XExpMax, - .X, .Y, .Z, .XPostBox); + /////////////////////////////////////////////////////////////////////////////////////////////// + // ||||||| ||| ||| ||||||||| + // ||| ||| ||| ||| ||| + // ||| ||| ||| ||| ||| + // ||| ||| ||| ||| ||| + // ||||||| ||||||||| ||| - /////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////// - // ||||||| ||| ||| ||||||||| - // ||| ||| ||| ||| ||| - // ||| ||| ||| ||| ||| - // ||| ||| ||| ||| ||| - // ||||||| ||||||||| ||| - - /////////////////////////////////////////////////////////////////////////////////////////////// - - // instantiate devices under test - if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "sub" | TEST === "all") begin : fma - fma #(P) fma(.Xs(Xs), .Ys(Ys), .Zs(Zs), - .Xe(Xe), .Ye(Ye), .Ze(Ze), - .Xm(Xm), .Ym(Ym), .Zm(Zm), - .XZero, .YZero, .ZZero, .Ss, .Se, - .OpCtrl(OpCtrlVal), .Sm, .InvA, .SCnt, .As, .Ps, - .ASticky); - end - - postprocess #(P) postprocess(.Xs(Xs), .Ys(Ys), .PostProcSel(UnitVal[1:0]), - .OpCtrl(OpCtrlVal), .DivQm(Quot), .DivQe(DivCalcExp), - .Xm(Xm), .Ym(Ym), .Zm(Zm), .CvtCe(CvtCalcExpE), .DivSticky(DivSticky), .FmaSs(Ss), - .XNaN(XNaN), .YNaN(YNaN), .ZNaN(ZNaN), .CvtResSubnormUf(CvtResSubnormUfE), - .XZero(XZero), .YZero(YZero), .CvtShiftAmt(CvtShiftAmtE), - .XInf(XInf), .YInf(YInf), .ZInf(ZInf), .CvtCs(CvtResSgnE), .ToInt(WriteIntVal), - .XSNaN(XSNaN), .YSNaN(YSNaN), .ZSNaN(ZSNaN), .CvtLzcIn(CvtLzcInE), .IntZero, - .FmaASticky(ASticky), .FmaSe(Se), - .FmaSm(Sm), .FmaSCnt(SCnt), .FmaAs(As), .FmaPs(Ps), .Fmt(ModFmt), .Frm(FrmVal), - .PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes)); - - if (TEST === "cvtfp" | TEST === "cvtint" | TEST === "all") begin : fcvt - fcvt fcvt (.Xs(Xs), .Xe(Xe), .Xm(Xm), .Int(SrcA), .ToInt(WriteIntVal), - .XZero(XZero), .OpCtrl(OpCtrlVal), .IntZero, - .Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), .ResSubnormUf(CvtResSubnormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE)); - end - - if (TEST === "cmp" | TEST === "all") begin: fcmp - fcmp fcmp (.Fmt(ModFmt), .OpCtrl(OpCtrlVal), .Xs, .Ys, .Xe, .Ye, - .Xm, .Ym, .XZero, .YZero, .CmpIntRes(CmpRes), - .XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes)); - end - if (TEST === "div" | TEST === "sqrt" | TEST === "all") begin: fdivsqrt - fdivsqrt #(P) fdivsqrt(.clk, .reset, .XsE(Xs), .FmtE(ModFmt), .XmE(Xm), .YmE(Ym), - .XeE(Xe), .YeE(Ye), .SqrtE(OpCtrlVal[0]), .SqrtM(OpCtrlVal[0]), - .XInfE(XInf), .YInfE(YInf), .XZeroE(XZero), .YZeroE(YZero), - .XNaNE(XNaN), .YNaNE(YNaN), - .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 - - assign CmpFlg[3:0] = 0; - - // produce clock - always begin - 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 - -/////////////////////////////////////////////////////////////////////////////////////////////// - -// ||||| ||| |||||||||| ||||| ||| -// ||||||| ||| ||| ||| ||||||| ||| -// |||| ||| ||| |||||||||| |||| ||| ||| -// |||| ||| ||| ||| ||| |||| ||| ||| -// |||| ||| ||| ||| ||| |||| ||| ||| -// |||| |||||| ||| ||| |||| |||||| - -/////////////////////////////////////////////////////////////////////////////////////////////// - - // Check if the correct answer and result is a NaN - always_comb begin - if(UnitVal === `CVTINTUNIT | UnitVal === `CMPUNIT) begin - // an integer output can't be a NaN - AnsNaN = 1'b0; - ResNaN = 1'b0; - end - else if (UnitVal === `CVTFPUNIT) begin - case (OpCtrlVal[1:0]) - 4'b11: begin // quad - AnsNaN = &Ans[`Q_LEN-2:`NF]&(|Ans[`Q_NF-1:0]); - ResNaN = &Res[`Q_LEN-2:`NF]&(|Res[`Q_NF-1:0]); - end - 4'b01: begin // double - AnsNaN = &Ans[`D_LEN-2:`D_NF]&(|Ans[`D_NF-1:0]); - ResNaN = &Res[`D_LEN-2:`D_NF]&(|Res[`D_NF-1:0]); - end - 4'b00: begin // single - AnsNaN = &Ans[`S_LEN-2:`S_NF]&(|Ans[`S_NF-1:0]); - ResNaN = &Res[`S_LEN-2:`S_NF]&(|Res[`S_NF-1:0]); - end - 4'b10: begin // half - AnsNaN = &Ans[`H_LEN-2:`H_NF]&(|Ans[`H_NF-1:0]); - ResNaN = &Res[`H_LEN-2:`H_NF]&(|Res[`H_NF-1:0]); - end - endcase - end - else begin - case (FmtVal) - 4'b11: begin // quad - AnsNaN = &Ans[`Q_LEN-2:`Q_NF]&(|Ans[`Q_NF-1:0]); - ResNaN = &Res[`Q_LEN-2:`Q_NF]&(|Res[`Q_NF-1:0]); - end - 4'b01: begin // double - AnsNaN = &Ans[`D_LEN-2:`D_NF]&(|Ans[`D_NF-1:0]); - ResNaN = &Res[`D_LEN-2:`D_NF]&(|Res[`D_NF-1:0]); - end - 4'b00: begin // single - AnsNaN = &Ans[`S_LEN-2:`S_NF]&(|Ans[`S_NF-1:0]); - ResNaN = &Res[`S_LEN-2:`S_NF]&(|Res[`S_NF-1:0]); - end - 4'b10: begin // half - AnsNaN = &Ans[`H_LEN-2:`H_NF]&(|Ans[`H_NF-1:0]); - ResNaN = &Res[`H_LEN-2:`H_NF]&(|Res[`H_NF-1:0]); - end - endcase - end - end -always_comb begin - // select the result to check - case (UnitVal) - `FMAUNIT: Res = FpRes; - `DIVUNIT: Res = FpRes; - `CMPUNIT: Res = CmpRes; - `CVTINTUNIT: if(WriteIntVal) Res = IntRes; else Res = FpRes; - `CVTFPUNIT: Res = FpRes; - endcase - - // select the flag to check - case (UnitVal) - `FMAUNIT: ResFlg = Flg; - `DIVUNIT: ResFlg = Flg; - `CMPUNIT: ResFlg = CmpFlg; - `CVTINTUNIT: ResFlg = Flg; - `CVTFPUNIT: ResFlg = Flg; - endcase -end - - logic ResMatch, FlagMatch, CheckNow; - -always @(posedge clk) - OldFDivBusyE = FDivDoneE; - -// check results on falling edge of clk -always @(negedge clk) begin - - - // check if the NaN value is good. IEEE754-2019 sections 6.3 and 6.2.3 specify: - // - 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) - 4'b11: NaNGood = (((`IEEE754==0)&AnsNaN&(Res === {1'b0, {`Q_NE+1{1'b1}}, {`Q_NF-1{1'b0}}})) | - (AnsFlg[4]&(Res[`Q_LEN-2:0] === {{`Q_NE+1{1'b1}}, {`Q_NF-1{1'b0}}})) | - (XNaN&(Res[`Q_LEN-2:0] === {X[`Q_LEN-2:`Q_NF],1'b1,X[`Q_NF-2:0]})) | - (YNaN&(Res[`Q_LEN-2:0] === {Y[`Q_LEN-2:`Q_NF],1'b1,Y[`Q_NF-2:0]})) | - (ZNaN&(Res[`Q_LEN-2:0] === {Z[`Q_LEN-2:`Q_NF],1'b1,Z[`Q_NF-2:0]}))); - 4'b01: NaNGood = (((`IEEE754==0)&AnsNaN&(Res[`D_LEN-1:0] === {1'b0, {`D_NE+1{1'b1}}, {`D_NF-1{1'b0}}})) | - (AnsFlg[4]&(Res[`D_LEN-2:0] === {{`D_NE+1{1'b1}}, {`D_NF-1{1'b0}}})) | - (XNaN&(Res[`D_LEN-2:0] === {X[`D_LEN-2:`D_NF],1'b1,X[`D_NF-2:0]})) | - (YNaN&(Res[`D_LEN-2:0] === {Y[`D_LEN-2:`D_NF],1'b1,Y[`D_NF-2:0]})) | - (ZNaN&(Res[`D_LEN-2:0] === {Z[`D_LEN-2:`D_NF],1'b1,Z[`D_NF-2:0]}))); - 4'b00: NaNGood = (((`IEEE754==0)&AnsNaN&(Res[`S_LEN-1:0] === {1'b0, {`S_NE+1{1'b1}}, {`S_NF-1{1'b0}}})) | - (AnsFlg[4]&(Res[`S_LEN-2:0] === {{`S_NE+1{1'b1}}, {`S_NF-1{1'b0}}})) | - (XNaN&(Res[`S_LEN-2:0] === {X[`S_LEN-2:`S_NF],1'b1,X[`S_NF-2:0]})) | - (YNaN&(Res[`S_LEN-2:0] === {Y[`S_LEN-2:`S_NF],1'b1,Y[`S_NF-2:0]})) | - (ZNaN&(Res[`S_LEN-2:0] === {Z[`S_LEN-2:`S_NF],1'b1,Z[`S_NF-2:0]}))); - 4'b10: NaNGood = (((`IEEE754==0)&AnsNaN&(Res[`H_LEN-1:0] === {1'b0, {`H_NE+1{1'b1}}, {`H_NF-1{1'b0}}})) | - (AnsFlg[4]&(Res[`H_LEN-2:0] === {{`H_NE+1{1'b1}}, {`H_NF-1{1'b0}}})) | - (XNaN&(Res[`H_LEN-2:0] === {X[`H_LEN-2:`H_NF],1'b1,X[`H_NF-2:0]})) | - (YNaN&(Res[`H_LEN-2:0] === {Y[`H_LEN-2:`H_NF],1'b1,Y[`H_NF-2:0]})) | - (ZNaN&(Res[`H_LEN-2:0] === {Z[`H_LEN-2:`H_NF],1'b1,Z[`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 = (((`IEEE754==0)&AnsNaN&(Res === {1'b0, {`Q_NE+1{1'b1}}, {`Q_NF-1{1'b0}}})) | - (AnsFlg[4]&(Res[`Q_LEN-2:0] === {{`Q_NE+1{1'b1}}, {`Q_NF-1{1'b0}}})) | - (AnsNaN&(Res[`Q_LEN-2:0] === Ans[`Q_LEN-2:0])) | - (XNaN&(Res[`Q_LEN-2:0] === {X[`Q_LEN-2:`Q_NF],1'b1,X[`Q_NF-2:0]})) | - (YNaN&(Res[`Q_LEN-2:0] === {Y[`Q_LEN-2:`Q_NF],1'b1,Y[`Q_NF-2:0]}))); - 2'b01: NaNGood = (((`IEEE754==0)&AnsNaN&(Res[`D_LEN-1:0] === {1'b0, {`D_NE+1{1'b1}}, {`D_NF-1{1'b0}}})) | - (AnsFlg[4]&(Res[`D_LEN-2:0] === {{`D_NE+1{1'b1}}, {`D_NF-1{1'b0}}})) | - (AnsNaN&(Res[`D_LEN-2:0] === Ans[`D_LEN-2:0])) | - (XNaN&(Res[`D_LEN-2:0] === {X[`D_LEN-2:`D_NF],1'b1,X[`D_NF-2:0]})) | - (YNaN&(Res[`D_LEN-2:0] === {Y[`D_LEN-2:`D_NF],1'b1,Y[`D_NF-2:0]}))); - 2'b00: NaNGood = (((`IEEE754==0)&AnsNaN&(Res[`S_LEN-1:0] === {1'b0, {`S_NE+1{1'b1}}, {`S_NF-1{1'b0}}})) | - (AnsFlg[4]&(Res[`S_LEN-2:0] === {{`S_NE+1{1'b1}}, {`S_NF-1{1'b0}}})) | - (AnsNaN&(Res[`S_LEN-2:0] === Ans[`S_LEN-2:0])) | - (XNaN&(Res[`S_LEN-2:0] === {X[`S_LEN-2:`S_NF],1'b1,X[`S_NF-2:0]})) | - (YNaN&(Res[`S_LEN-2:0] === {Y[`S_LEN-2:`S_NF],1'b1,Y[`S_NF-2:0]}))); - 2'b10: NaNGood = (((`IEEE754==0)&AnsNaN&(Res[`H_LEN-1:0] === {1'b0, {`H_NE+1{1'b1}}, {`H_NF-1{1'b0}}})) | - (AnsFlg[4]&(Res[`H_LEN-2:0] === {{`H_NE+1{1'b1}}, {`H_NF-1{1'b0}}})) | - (AnsNaN&(Res[`H_LEN-2:0] === Ans[`H_LEN-2:0])) | - (XNaN&(Res[`H_LEN-2:0] === {X[`H_LEN-2:`H_NF],1'b1,X[`H_NF-2:0]})) | - (YNaN&(Res[`H_LEN-2:0] === {Y[`H_LEN-2:`H_NF],1'b1,Y[`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) - // if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&~((FDivBusyE===1'b1)|DivStart)&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin - assign ResMatch = (Res === Ans | NaNGood | NaNGood === 1'bx); - assign FlagMatch = (ResFlg === AnsFlg | AnsFlg === 5'bx); - assign divsqrtop = OpCtrlVal == `SQRT_OPCTRL | OpCtrlVal == `DIV_OPCTRL; - assign DivDone = OldFDivBusyE & ~FDivBusyE; - - //assign divsqrtop = OpCtrl[TestNum] == `SQRT_OPCTRL | OpCtrl[TestNum] == `DIV_OPCTRL; - assign CheckNow = (DivDone | ~divsqrtop) & (UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT); - if(~(ResMatch & FlagMatch) & CheckNow) begin -// if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&(DivDone | (TEST != "sqrt" & TEST != "div"))&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin - errors += 1; - $display("TestNum %d OpCtrl %d", TestNum, OpCtrl[TestNum]); - $display("Error in %s", Tests[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) & ~(((WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&Xs&(Res[`XLEN-1:0] === (`XLEN)'(0))) | - (WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~Xs|XNaN)&OpCtrlVal[1]&(Res[`XLEN-1:0] === {1'b0, {`XLEN-1{1'b1}}})) | - (WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~Xs|XNaN)&~OpCtrlVal[1]&(Res[`XLEN-1:0] === {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}})) | - (~(WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&Xs&~XNaN)&(Res === Ans | NaNGood | NaNGood === 1'bx))) & (ResFlg === AnsFlg | AnsFlg === 5'bx))) begin - errors += 1; - $display("There is an error in %s", Tests[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 - - // Add extra clock cycles in beginning for fdivsqrt to adequate reset state - if(~(FDivBusyE|DivStart)|(UnitVal != `DIVUNIT)) begin - repeat (12) - @(posedge clk); - if (reset != 1'b1) - VectorNum += 1; // increment the vector - end + // instantiate devices under test + if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "sub" | TEST === "all") begin : fma + fma #(P) fma(.Xs(Xs), .Ys(Ys), .Zs(Zs), + .Xe(Xe), .Ye(Ye), .Ze(Ze), + .Xm(Xm), .Ym(Ym), .Zm(Zm), + .XZero, .YZero, .ZZero, .Ss, .Se, + .OpCtrl(OpCtrlVal), .Sm, .InvA, .SCnt, .As, .Ps, + .ASticky); + end - if (TestVectors[VectorNum][0] === 1'bx & Tests[TestNum] !== "") begin // if reached the eof + postprocess #(P) postprocess(.Xs(Xs), .Ys(Ys), .PostProcSel(UnitVal[1:0]), + .OpCtrl(OpCtrlVal), .DivQm(Quot), .DivQe(DivCalcExp), + .Xm(Xm), .Ym(Ym), .Zm(Zm), .CvtCe(CvtCalcExpE), .DivSticky(DivSticky), .FmaSs(Ss), + .XNaN(XNaN), .YNaN(YNaN), .ZNaN(ZNaN), .CvtResSubnormUf(CvtResSubnormUfE), + .XZero(XZero), .YZero(YZero), .CvtShiftAmt(CvtShiftAmtE), + .XInf(XInf), .YInf(YInf), .ZInf(ZInf), .CvtCs(CvtResSgnE), .ToInt(WriteIntVal), + .XSNaN(XSNaN), .YSNaN(YSNaN), .ZSNaN(ZSNaN), .CvtLzcIn(CvtLzcInE), .IntZero, + .FmaASticky(ASticky), .FmaSe(Se), + .FmaSm(Sm), .FmaSCnt(SCnt), .FmaAs(As), .FmaPs(Ps), .Fmt(ModFmt), .Frm(FrmVal), + .PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes)); + + if (TEST === "cvtfp" | TEST === "cvtint" | TEST === "all") begin : fcvt + fcvt #(P) fcvt (.Xs(Xs), .Xe(Xe), .Xm(Xm), .Int(SrcA), .ToInt(WriteIntVal), + .XZero(XZero), .OpCtrl(OpCtrlVal), .IntZero, + .Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), + .ResSubnormUf(CvtResSubnormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE)); + end - // increment the test - TestNum += 1; + if (TEST === "cmp" | TEST === "all") begin: fcmp + fcmp #(P) fcmp (.Fmt(ModFmt), .OpCtrl(OpCtrlVal), .Xs, .Ys, .Xe, .Ye, + .Xm, .Ym, .XZero, .YZero, .CmpIntRes(CmpRes), + .XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes)); + end + + if (TEST === "div" | TEST === "sqrt" | TEST === "all") begin: fdivsqrt + fdivsqrt #(P) fdivsqrt(.clk, .reset, .XsE(Xs), .FmtE(ModFmt), .XmE(Xm), .YmE(Ym), + .XeE(Xe), .YeE(Ye), .SqrtE(OpCtrlVal[0]), .SqrtM(OpCtrlVal[0]), + .XInfE(XInf), .YInfE(YInf), .XZeroE(XZero), .YZeroE(YZero), + .XNaNE(XNaN), .YNaNE(YNaN), + .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 - // clear the vectors - for(int i=0; i<6133248; i++) TestVectors[i] = {`FLEN*4+8{1'bx}}; - // read next files - $readmemh({`PATH, Tests[TestNum]}, TestVectors); + assign CmpFlg[3:0] = 0; - // set the vector index back to 0 - VectorNum = 0; - // incemet the operation if all the rounding modes have been tested - if(FrmNum === 4) OpCtrlNum += 1; - // increment the rounding mode or loop back to rne - if(FrmNum < 4) FrmNum += 1; - else FrmNum = 0; + // produce clock + always begin + clk = 1; #5; clk = 0; #5; + end - // if no more Tests - finish - if(Tests[TestNum] === "") begin - $display("\nAll Tests completed with %d errors\n", errors); - $stop; - 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 + + /////////////////////////////////////////////////////////////////////////////////////////////// - $display("Running %s vectors", Tests[TestNum]); - end - end + // ||||| ||| |||||||||| ||||| ||| + // ||||||| ||| ||| ||| ||||||| ||| + // |||| ||| ||| |||||||||| |||| ||| ||| + // |||| ||| ||| ||| ||| |||| ||| ||| + // |||| ||| ||| ||| ||| |||| ||| ||| + // |||| |||||| ||| ||| |||| |||||| + + /////////////////////////////////////////////////////////////////////////////////////////////// + + // Check if the correct answer and result is a NaN + always_comb begin + if (UnitVal === `CVTINTUNIT | UnitVal === `CMPUNIT) begin + // an integer output can't be a NaN + AnsNaN = 1'b0; + ResNaN = 1'b0; + end + else if (UnitVal === `CVTFPUNIT) begin + case (OpCtrlVal[1:0]) + 4'b11: begin // quad + AnsNaN = &Ans[P.Q_LEN-2:P.NF]&(|Ans[P.Q_NF-1:0]); + ResNaN = &Res[P.Q_LEN-2:P.NF]&(|Res[P.Q_NF-1:0]); + end + 4'b01: begin // double + AnsNaN = &Ans[P.D_LEN-2:P.D_NF]&(|Ans[P.D_NF-1:0]); + ResNaN = &Res[P.D_LEN-2:P.D_NF]&(|Res[P.D_NF-1:0]); + end + 4'b00: begin // single + AnsNaN = &Ans[P.S_LEN-2:P.S_NF]&(|Ans[P.S_NF-1:0]); + ResNaN = &Res[P.S_LEN-2:P.S_NF]&(|Res[P.S_NF-1:0]); + end + 4'b10: begin // half + AnsNaN = &Ans[P.H_LEN-2:P.H_NF]&(|Ans[P.H_NF-1:0]); + ResNaN = &Res[P.H_LEN-2:P.H_NF]&(|Res[P.H_NF-1:0]); + end + endcase + end + else begin + case (FmtVal) + 4'b11: begin // quad + AnsNaN = &Ans[P.Q_LEN-2:P.Q_NF]&(|Ans[P.Q_NF-1:0]); + ResNaN = &Res[P.Q_LEN-2:P.Q_NF]&(|Res[P.Q_NF-1:0]); + end + 4'b01: begin // double + AnsNaN = &Ans[P.D_LEN-2:P.D_NF]&(|Ans[P.D_NF-1:0]); + ResNaN = &Res[P.D_LEN-2:P.D_NF]&(|Res[P.D_NF-1:0]); + end + 4'b00: begin // single + AnsNaN = &Ans[P.S_LEN-2:P.S_NF]&(|Ans[P.S_NF-1:0]); + ResNaN = &Res[P.S_LEN-2:P.S_NF]&(|Res[P.S_NF-1:0]); + end + 4'b10: begin // half + AnsNaN = &Ans[P.H_LEN-2:P.H_NF]&(|Ans[P.H_NF-1:0]); + ResNaN = &Res[P.H_LEN-2:P.H_NF]&(|Res[P.H_NF-1:0]); + end + endcase + end + end + + always_comb begin + // select the result to check + case (UnitVal) + `FMAUNIT: Res = FpRes; + `DIVUNIT: Res = FpRes; + `CMPUNIT: Res = CmpRes; + `CVTINTUNIT: if (WriteIntVal) Res = IntRes; else Res = FpRes; + `CVTFPUNIT: Res = FpRes; + endcase + + // select the flag to check + case (UnitVal) + `FMAUNIT: ResFlg = Flg; + `DIVUNIT: ResFlg = Flg; + `CMPUNIT: ResFlg = CmpFlg; + `CVTINTUNIT: ResFlg = Flg; + `CVTFPUNIT: ResFlg = Flg; + endcase + end + + always @(posedge clk) + OldFDivBusyE = FDivDoneE; + + // For FP division this adds extra clock cycles to make sure the + // computation completes. + 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 + 4'b11: begin + repeat (20) + @(posedge clk); + end + // HP + 4'b10: begin + repeat (14) + @(posedge clk); + end + // DP + 4'b01: begin + repeat (18) + @(posedge clk); + end + // SP + 4'b00: begin + repeat (16) + @(posedge clk); + end + endcase // case (FmtVal) + if (reset != 1'b1) + VectorNum += 1; // increment the vector + end + end + + // check results on falling edge of clk + always @(negedge clk) begin + // check if the NaN value is good. IEEE754-2019 sections 6.3 and 6.2.3 specify: + // - 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) + 4'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]}))); + 4'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]}))); + 4'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]}))); + 4'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; + + // 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) & + ~(((WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&Xs&(Res[P.XLEN-1:0] === (P.XLEN)'(0))) | + (WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~Xs|XNaN)&OpCtrlVal[1]&(Res[P.XLEN-1:0] === {1'b0, {P.XLEN-1{1'b1}}})) | + (WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~Xs|XNaN)&~OpCtrlVal[1]&(Res[P.XLEN-1:0] === {{P.XLEN-32{1'b0}}, 1'b0, {31{1'b1}}})) | + (~(WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&Xs&~XNaN)&(Res === Ans | NaNGood | NaNGood === 1'bx))) & (ResFlg === AnsFlg | AnsFlg === 5'bx))) begin + errors += 1; + $display("There is an error in %s", Tests[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 + + if (TestVectors[VectorNum][0] === 1'bx & Tests[TestNum] !== "") begin // if reached the eof + // increment the test + TestNum += 1; + // clear the vectors + for(int i=0; i<6133248; i++) TestVectors[i] = {P.FLEN*4+8{1'bx}}; + // read next files + $readmemh({`PATH, Tests[TestNum]}, TestVectors); + // set the vector index back to 0 + VectorNum = 0; + // incemet the operation if all the rounding modes have been tested + if (FrmNum === 4) OpCtrlNum += 1; + // increment the rounding mode or loop back to rne + if (FrmNum < 4) FrmNum += 1; + else FrmNum = 0; + // if no more Tests - finish + if (Tests[TestNum] === "") begin + $display("\nAll Tests completed with %d errors\n", errors); + $stop; + end + $display("Running %s vectors", Tests[TestNum]); + end + end endmodule module readvectors ( - input logic clk, - input logic [`FLEN*4+7:0] TestVector, - input logic [`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 [`FLEN-1:0] Ans, - output logic [`XLEN-1:0] SrcA, - output logic [4:0] AnsFlg, - 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 [`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 [`FLEN-1:0] X, Y, Z, XPostBox -); + 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 + ); + + localparam Q_LEN = 32'd128; + `include "parameter-defs.vh" - logic XEn, YEn, ZEn; + logic XEn; + logic YEn; + logic ZEn; + logic FPUActive; - `include "parameter-defs.vh" + // 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: + case (Fmt) + 2'b11: begin // quad + if (OpCtrl === `FMA_OPCTRL) begin + X = TestVector[8+4*(P.Q_LEN)-1:8+3*(P.Q_LEN)]; + Y = TestVector[8+3*(P.Q_LEN)-1:8+2*(P.Q_LEN)]; + Z = TestVector[8+2*(P.Q_LEN)-1:8+P.Q_LEN]; + end + else begin + X = TestVector[8+3*(P.Q_LEN)-1:8+2*(P.Q_LEN)]; + if (OpCtrl === `MUL_OPCTRL) Y = TestVector[8+2*(P.Q_LEN)-1:8+(P.Q_LEN)]; else Y = {2'b0, {P.Q_NE-1{1'b1}}, (P.Q_NF)'(0)}; + if (OpCtrl === `MUL_OPCTRL) Z = 0; else Z = TestVector[8+2*(P.Q_LEN)-1:8+(P.Q_LEN)]; + end + Ans = TestVector[8+(P.Q_LEN-1):8]; + end + 2'b01: if (P.D_SUPPORTED) begin // double + if (OpCtrl === `FMA_OPCTRL) begin + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+4*(P.D_LEN)-1:8+3*(P.D_LEN)]}; + Y = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]}; + Z = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+P.D_LEN]}; + end + else begin + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]}; + if (OpCtrl === `MUL_OPCTRL) Y = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]}; + else Y = {{P.FLEN-P.D_LEN{1'b1}}, 2'b0, {P.D_NE-1{1'b1}}, (P.D_NF)'(0)}; + if (OpCtrl === `MUL_OPCTRL) Z = {{P.FLEN-P.D_LEN{1'b1}}, {P.D_LEN{1'b0}}}; + else Z = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]}; + end + Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; + end + 2'b00: if (P.S_SUPPORTED) begin // single + if (OpCtrl === `FMA_OPCTRL) begin + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+4*(P.S_LEN)-1:8+3*(P.S_LEN)]}; + Y = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]}; + Z = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+P.S_LEN]}; + end + else begin + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]}; + if (OpCtrl === `MUL_OPCTRL) Y = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+(P.S_LEN)]}; + else Y = {{P.FLEN-P.S_LEN{1'b1}}, 2'b0, {P.S_NE-1{1'b1}}, (P.S_NF)'(0)}; + if (OpCtrl === `MUL_OPCTRL) Z = {{P.FLEN-P.S_LEN{1'b1}}, {P.S_LEN{1'b0}}}; + else Z = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+(P.S_LEN)]}; + end + Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; + end + 2'b10: begin // half + if (OpCtrl === `FMA_OPCTRL) begin + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+4*(P.H_LEN)-1:8+3*(P.H_LEN)]}; + Y = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]}; + Z = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+P.H_LEN]}; + end + else begin + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]}; + if (OpCtrl === `MUL_OPCTRL) Y = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]}; + else Y = {{P.FLEN-P.H_LEN{1'b1}}, 2'b0, {P.H_NE-1{1'b1}}, (P.H_NF)'(0)}; + if (OpCtrl === `MUL_OPCTRL) Z = {{P.FLEN-P.H_LEN{1'b1}}, {P.H_LEN{1'b0}}}; + else Z = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]}; + end + Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; + end + endcase + `DIVUNIT: + if (OpCtrl[0]) + case (Fmt) + 2'b11: begin // quad + #20; + 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 + #20; + 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 + #20; + 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 + #20; + 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 + case (Fmt) + 2'b11: begin // quad + #20; + 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 + #20; + 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 + #20; + 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 + #20; + 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: + case (Fmt) + 2'b11: begin // quad + X = TestVector[12+2*(P.Q_LEN)-1:12+(P.Q_LEN)]; + Y = TestVector[12+(P.Q_LEN)-1:12]; + Ans = TestVector[8]; + end + 2'b01: if (P.D_SUPPORTED) begin // double + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[12+2*(P.D_LEN)-1:12+(P.D_LEN)]}; + Y = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[12+(P.D_LEN)-1:12]}; + Ans = TestVector[8]; + end + 2'b00: if (P.S_SUPPORTED) begin // single + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[12+2*(P.S_LEN)-1:12+(P.S_LEN)]}; + Y = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[12+(P.S_LEN)-1:12]}; + Ans = TestVector[8]; + end + 2'b10: begin // half + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[12+2*(P.H_LEN)-1:12+(P.H_LEN)]}; + Y = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[12+(P.H_LEN)-1:12]}; + Ans = TestVector[8]; + end + endcase + `CVTFPUNIT: + case (Fmt) + 2'b11: begin // quad + case (OpCtrl[1:0]) + 2'b11: begin // quad + X = {TestVector[8+P.Q_LEN+P.Q_LEN-1:8+(P.Q_LEN)]}; + Ans = TestVector[8+(P.Q_LEN-1):8]; + end + 2'b01: if (P.D_SUPPORTED) begin // double + X = {TestVector[8+P.Q_LEN+P.D_LEN-1:8+(P.D_LEN)]}; + Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; + end + 2'b00: begin // single + X = {TestVector[8+P.Q_LEN+P.S_LEN-1:8+(P.S_LEN)]}; + Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; + end + 2'b10: begin // half + X = {TestVector[8+P.Q_LEN+P.H_LEN-1:8+(P.H_LEN)]}; + Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; + end + endcase + end + 2'b01: if (P.D_SUPPORTED) begin // double + case (OpCtrl[1:0]) + 2'b11: begin // quad + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.Q_LEN-1:8+(P.Q_LEN)]}; + Ans = TestVector[8+(P.Q_LEN-1):8]; + end + 2'b01: begin // double + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.D_LEN-1:8+(P.D_LEN)]}; + Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; + end + 2'b00: begin // single + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.S_LEN-1:8+(P.S_LEN)]}; + Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; + end + 2'b10: begin // half + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.H_LEN-1:8+(P.H_LEN)]}; + Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; + end + endcase + end + 2'b00: if (P.S_SUPPORTED) begin // single + case (OpCtrl[1:0]) + 2'b11: begin // quad + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.Q_LEN-1:8+(P.Q_LEN)]}; + Ans = TestVector[8+(P.Q_LEN-1):8]; + end + 2'b01: if (P.D_SUPPORTED) begin // double + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.D_LEN-1:8+(P.D_LEN)]}; + Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; + end + 2'b00: begin // single + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.S_LEN-1:8+(P.S_LEN)]}; + Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; + end + 2'b10: begin // half + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.H_LEN-1:8+(P.H_LEN)]}; + Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; + end + endcase + end + 2'b10: begin // half + case (OpCtrl[1:0]) + 2'b11: begin // quad + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.Q_LEN-1:8+(P.Q_LEN)]}; + Ans = TestVector[8+(P.Q_LEN-1):8]; + end + 2'b01: if (P.D_SUPPORTED) begin // double + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.D_LEN-1:8+(P.D_LEN)]}; + Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; + end + 2'b00: if (P.S_SUPPORTED) begin // single + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.S_LEN-1:8+(P.S_LEN)]}; + Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; + end + 2'b10: begin // half + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.H_LEN-1:8+(P.H_LEN)]}; + Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; + end + endcase + end + endcase + `CVTINTUNIT: + case (Fmt) + 2'b11: begin // quad + // {is the integer a long, is the opperation to an integer} + casex ({OpCtrl[2:1]}) + 2'b11: begin // long -> quad + X = {P.FLEN{1'bx}}; + SrcA = TestVector[8+P.Q_LEN+P.XLEN-1:8+(P.Q_LEN)]; + Ans = TestVector[8+(P.Q_LEN-1):8]; + end + 2'b10: begin // int -> quad + // correctly sign extend the integer depending on if it's a signed/unsigned test + X = {P.FLEN{1'bx}}; + SrcA = {{P.XLEN-32{TestVector[8+P.Q_LEN+32-1]}}, TestVector[8+P.Q_LEN+32-1:8+(P.Q_LEN)]}; + Ans = TestVector[8+(P.Q_LEN-1):8]; + end + 2'b01: begin // quad -> long + X = {TestVector[8+P.XLEN+P.Q_LEN-1:8+(P.XLEN)]}; + SrcA = {P.XLEN{1'bx}}; + Ans = {TestVector[8+(P.XLEN-1):8]}; + end + 2'b00: begin // quad -> int + X = {TestVector[8+32+P.Q_LEN-1:8+(32)]}; + SrcA = {P.XLEN{1'bx}}; + Ans = {{P.XLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; + end + endcase + end + 2'b01: if (P.D_SUPPORTED) begin // double + // {Int->Fp?, is the integer a long} + casex ({OpCtrl[2:1]}) + 2'b11: begin // long -> double + X = {P.FLEN{1'bx}}; + SrcA = TestVector[8+P.D_LEN+P.XLEN-1:8+(P.D_LEN)]; + Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; + end + 2'b10: begin // int -> double + // correctly sign extend the integer depending on if it's a signed/unsigned test + X = {P.FLEN{1'bx}}; + SrcA = {{P.XLEN-32{TestVector[8+P.D_LEN+32-1]}}, TestVector[8+P.D_LEN+32-1:8+(P.D_LEN)]}; + Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; + end + 2'b01: begin // double -> long + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.XLEN+P.D_LEN-1:8+(P.XLEN)]}; + SrcA = {P.XLEN{1'bx}}; + Ans = {TestVector[8+(P.XLEN-1):8]}; + end + 2'b00: begin // double -> int + X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+32+P.D_LEN-1:8+(32)]}; + SrcA = {P.XLEN{1'bx}}; + Ans = {{P.XLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; + end + endcase + end + 2'b00: if (P.S_SUPPORTED) begin // single + // {is the integer a long, is the opperation to an integer} + casex ({OpCtrl[2:1]}) + 2'b11: begin // long -> single + X = {P.FLEN{1'bx}}; + SrcA = TestVector[8+P.S_LEN+P.XLEN-1:8+(P.S_LEN)]; + Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; + end + 2'b10: begin // int -> single + // correctly sign extend the integer depending on if it's a signed/unsigned test + X = {P.FLEN{1'bx}}; + SrcA = {{P.XLEN-32{TestVector[8+P.S_LEN+32-1]}}, TestVector[8+P.S_LEN+32-1:8+(P.S_LEN)]}; + Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; + end + 2'b01: begin // single -> long + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.XLEN+P.S_LEN-1:8+(P.XLEN)]}; + SrcA = {P.XLEN{1'bx}}; + Ans = {TestVector[8+(P.XLEN-1):8]}; + end + 2'b00: begin // single -> int + X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+32+P.S_LEN-1:8+(32)]}; + SrcA = {P.XLEN{1'bx}}; + Ans = {{P.XLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; + end + endcase + end + 2'b10: begin // half + // {is the integer a long, is the opperation to an integer} + casex ({OpCtrl[2:1]}) + 2'b11: begin // long -> half + X = {P.FLEN{1'bx}}; + SrcA = TestVector[8+P.H_LEN+P.XLEN-1:8+(P.H_LEN)]; + Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; + end + 2'b10: begin // int -> half + // correctly sign extend the integer depending on if it's a signed/unsigned test + X = {P.FLEN{1'bx}}; + SrcA = {{P.XLEN-32{TestVector[8+P.H_LEN+32-1]}}, TestVector[8+P.H_LEN+32-1:8+(P.H_LEN)]}; + Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; + end + 2'b01: begin // half -> long + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.XLEN+P.H_LEN-1:8+(P.XLEN)]}; + SrcA = {P.XLEN{1'bx}}; + Ans = {TestVector[8+(P.XLEN-1):8]}; + end + 2'b00: begin // half -> int + X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+32+P.H_LEN-1:8+(32)]}; + SrcA = {P.XLEN{1'bx}}; + Ans = {{P.XLEN-32{TestVector[8+32-1]}}, TestVector[8+(32-1):8]}; + end + endcase + end + endcase + endcase + end - // apply test vectors on rising edge of clk - // Format of vectors Inputs(1/2/3)_AnsFlg - always @(VectorNum) begin - #1; - AnsFlg = TestVector[4:0]; - DivStart = 1'b0; - case (Unit) - `FMAUNIT: - case (Fmt) - 2'b11: begin // quad - if(OpCtrl === `FMA_OPCTRL) begin - X = TestVector[8+4*(`Q_LEN)-1:8+3*(`Q_LEN)]; - Y = TestVector[8+3*(`Q_LEN)-1:8+2*(`Q_LEN)]; - Z = TestVector[8+2*(`Q_LEN)-1:8+`Q_LEN]; - end - else begin - X = TestVector[8+3*(`Q_LEN)-1:8+2*(`Q_LEN)]; - if(OpCtrl === `MUL_OPCTRL) Y = TestVector[8+2*(`Q_LEN)-1:8+(`Q_LEN)]; else Y = {2'b0, {`Q_NE-1{1'b1}}, (`Q_NF)'(0)}; - if(OpCtrl === `MUL_OPCTRL) Z = 0; else Z = TestVector[8+2*(`Q_LEN)-1:8+(`Q_LEN)]; - end - Ans = TestVector[8+(`Q_LEN-1):8]; - end - 2'b01: if (`D_SUPPORTED)begin // double - if(OpCtrl === `FMA_OPCTRL) begin - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+4*(`D_LEN)-1:8+3*(`D_LEN)]}; - Y = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+3*(`D_LEN)-1:8+2*(`D_LEN)]}; - Z = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+2*(`D_LEN)-1:8+`D_LEN]}; - end - else begin - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+3*(`D_LEN)-1:8+2*(`D_LEN)]}; - if(OpCtrl === `MUL_OPCTRL) Y = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+2*(`D_LEN)-1:8+(`D_LEN)]}; - else Y = {{`FLEN-`D_LEN{1'b1}}, 2'b0, {`D_NE-1{1'b1}}, (`D_NF)'(0)}; - if(OpCtrl === `MUL_OPCTRL) Z = {{`FLEN-`D_LEN{1'b1}}, {`D_LEN{1'b0}}}; - else Z = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+2*(`D_LEN)-1:8+(`D_LEN)]}; - end - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - end - 2'b00: if (`S_SUPPORTED)begin // single - if(OpCtrl === `FMA_OPCTRL) begin - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+4*(`S_LEN)-1:8+3*(`S_LEN)]}; - Y = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+3*(`S_LEN)-1:8+2*(`S_LEN)]}; - Z = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+2*(`S_LEN)-1:8+`S_LEN]}; - end - else begin - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+3*(`S_LEN)-1:8+2*(`S_LEN)]}; - if(OpCtrl === `MUL_OPCTRL) Y = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+2*(`S_LEN)-1:8+(`S_LEN)]}; - else Y = {{`FLEN-`S_LEN{1'b1}}, 2'b0, {`S_NE-1{1'b1}}, (`S_NF)'(0)}; - if(OpCtrl === `MUL_OPCTRL) Z = {{`FLEN-`S_LEN{1'b1}}, {`S_LEN{1'b0}}}; - else Z = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+2*(`S_LEN)-1:8+(`S_LEN)]}; - end - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - end - 2'b10: begin // half - if(OpCtrl === `FMA_OPCTRL) begin - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+4*(`H_LEN)-1:8+3*(`H_LEN)]}; - Y = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+3*(`H_LEN)-1:8+2*(`H_LEN)]}; - Z = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+2*(`H_LEN)-1:8+`H_LEN]}; - end - else begin - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+3*(`H_LEN)-1:8+2*(`H_LEN)]}; - if(OpCtrl === `MUL_OPCTRL) Y = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+2*(`H_LEN)-1:8+(`H_LEN)]}; - else Y = {{`FLEN-`H_LEN{1'b1}}, 2'b0, {`H_NE-1{1'b1}}, (`H_NF)'(0)}; - if(OpCtrl === `MUL_OPCTRL) Z = {{`FLEN-`H_LEN{1'b1}}, {`H_LEN{1'b0}}}; - else Z = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+2*(`H_LEN)-1:8+(`H_LEN)]}; - end - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - end - endcase - `DIVUNIT: - if(OpCtrl[0]) - case (Fmt) - 2'b11: begin // quad - X = TestVector[8+2*(`Q_LEN)-1:8+(`Q_LEN)]; - Ans = TestVector[8+(`Q_LEN-1):8]; - if (~clk) #5; - DivStart = 1'b1; #10 // one clk cycle - DivStart = 1'b0; - end - 2'b01: if (`D_SUPPORTED)begin // double - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+2*(`D_LEN)-1:8+(`D_LEN)]}; - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - if (~clk) #5; - DivStart = 1'b1; #10 - DivStart = 1'b0; - end - 2'b00: if (`S_SUPPORTED)begin // single - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+2*(`S_LEN)-1:8+1*(`S_LEN)]}; - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - if (~clk) #5; - DivStart = 1'b1; #10 - DivStart = 1'b0; - end - 2'b10: begin // half - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+2*(`H_LEN)-1:8+(`H_LEN)]}; - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - if (~clk) #5; - DivStart = 1'b1; #10 - DivStart = 1'b0; - end - endcase - else - case (Fmt) - 2'b11: begin // quad - X = TestVector[8+3*(`Q_LEN)-1:8+2*(`Q_LEN)]; - Y = TestVector[8+2*(`Q_LEN)-1:8+(`Q_LEN)]; - Ans = TestVector[8+(`Q_LEN-1):8]; - if (~clk) #5; - DivStart = 1'b1; #10 // one clk cycle - DivStart = 1'b0; - end - 2'b01: if (`D_SUPPORTED)begin // double - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+3*(`D_LEN)-1:8+2*(`D_LEN)]}; - Y = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+2*(`D_LEN)-1:8+(`D_LEN)]}; - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - if (~clk) #5; - DivStart = 1'b1; #10 - DivStart = 1'b0; - end - 2'b00: if (`S_SUPPORTED)begin // single - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+3*(`S_LEN)-1:8+2*(`S_LEN)]}; - Y = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+2*(`S_LEN)-1:8+1*(`S_LEN)]}; - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - if (~clk) #5; - DivStart = 1'b1; #10 - DivStart = 1'b0; - end - 2'b10: begin // half - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+3*(`H_LEN)-1:8+2*(`H_LEN)]}; - Y = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+2*(`H_LEN)-1:8+(`H_LEN)]}; - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - if (~clk) #5; - DivStart = 1'b1; #10 - DivStart = 1'b0; - end - endcase - `CMPUNIT: - case (Fmt) - 2'b11: begin // quad - X = TestVector[12+2*(`Q_LEN)-1:12+(`Q_LEN)]; - Y = TestVector[12+(`Q_LEN)-1:12]; - Ans = TestVector[8]; - end - 2'b01: if (`D_SUPPORTED)begin // double - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[12+2*(`D_LEN)-1:12+(`D_LEN)]}; - Y = {{`FLEN-`D_LEN{1'b1}}, TestVector[12+(`D_LEN)-1:12]}; - Ans = TestVector[8]; - end - 2'b00: if (`S_SUPPORTED)begin // single - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[12+2*(`S_LEN)-1:12+(`S_LEN)]}; - Y = {{`FLEN-`S_LEN{1'b1}}, TestVector[12+(`S_LEN)-1:12]}; - Ans = TestVector[8]; - end - 2'b10: begin // half - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[12+2*(`H_LEN)-1:12+(`H_LEN)]}; - Y = {{`FLEN-`H_LEN{1'b1}}, TestVector[12+(`H_LEN)-1:12]}; - Ans = TestVector[8]; - end - endcase - `CVTFPUNIT: - case (Fmt) - 2'b11: begin // quad - case (OpCtrl[1:0]) - 2'b11: begin // quad - X = {TestVector[8+`Q_LEN+`Q_LEN-1:8+(`Q_LEN)]}; - Ans = TestVector[8+(`Q_LEN-1):8]; - end - 2'b01: if (`D_SUPPORTED)begin // double - X = {TestVector[8+`Q_LEN+`D_LEN-1:8+(`D_LEN)]}; - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - end - 2'b00: begin // single - X = {TestVector[8+`Q_LEN+`S_LEN-1:8+(`S_LEN)]}; - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - end - 2'b10: begin // half - X = {TestVector[8+`Q_LEN+`H_LEN-1:8+(`H_LEN)]}; - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - end - endcase - end - 2'b01: if (`D_SUPPORTED)begin // double - case (OpCtrl[1:0]) - 2'b11: begin // quad - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+`D_LEN+`Q_LEN-1:8+(`Q_LEN)]}; - Ans = TestVector[8+(`Q_LEN-1):8]; - end - 2'b01: begin // double - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+`D_LEN+`D_LEN-1:8+(`D_LEN)]}; - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - end - 2'b00: begin // single - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+`D_LEN+`S_LEN-1:8+(`S_LEN)]}; - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - end - 2'b10: begin // half - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+`D_LEN+`H_LEN-1:8+(`H_LEN)]}; - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - end - endcase - end - 2'b00: if (`S_SUPPORTED)begin // single - case (OpCtrl[1:0]) - 2'b11: begin // quad - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+`S_LEN+`Q_LEN-1:8+(`Q_LEN)]}; - Ans = TestVector[8+(`Q_LEN-1):8]; - end - 2'b01: if (`D_SUPPORTED)begin // double - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+`S_LEN+`D_LEN-1:8+(`D_LEN)]}; - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - end - 2'b00: begin // single - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+`S_LEN+`S_LEN-1:8+(`S_LEN)]}; - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - end - 2'b10: begin // half - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+`S_LEN+`H_LEN-1:8+(`H_LEN)]}; - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - end - endcase - end - 2'b10: begin // half - case (OpCtrl[1:0]) - 2'b11: begin // quad - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+`H_LEN+`Q_LEN-1:8+(`Q_LEN)]}; - Ans = TestVector[8+(`Q_LEN-1):8]; - end - 2'b01: if (`D_SUPPORTED)begin // double - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+`H_LEN+`D_LEN-1:8+(`D_LEN)]}; - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - end - 2'b00: if (`S_SUPPORTED)begin // single - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+`H_LEN+`S_LEN-1:8+(`S_LEN)]}; - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - end - 2'b10: begin // half - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+`H_LEN+`H_LEN-1:8+(`H_LEN)]}; - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - end - endcase - end - endcase - - `CVTINTUNIT: - case (Fmt) - 2'b11: begin // quad - // {is the integer a long, is the opperation to an integer} - casex ({OpCtrl[2:1]}) - 2'b11: begin // long -> quad - X = {`FLEN{1'bx}}; - SrcA = TestVector[8+`Q_LEN+`XLEN-1:8+(`Q_LEN)]; - Ans = TestVector[8+(`Q_LEN-1):8]; - end - 2'b10: begin // int -> quad - // correctly sign extend the integer depending on if it's a signed/unsigned test - X = {`FLEN{1'bx}}; - SrcA = {{`XLEN-32{TestVector[8+`Q_LEN+32-1]}}, TestVector[8+`Q_LEN+32-1:8+(`Q_LEN)]}; - Ans = TestVector[8+(`Q_LEN-1):8]; - end - 2'b01: begin // quad -> long - X = {TestVector[8+`XLEN+`Q_LEN-1:8+(`XLEN)]}; - SrcA = {`XLEN{1'bx}}; - Ans = {TestVector[8+(`XLEN-1):8]}; - end - 2'b00: begin // quad -> int - X = {TestVector[8+32+`Q_LEN-1:8+(32)]}; - SrcA = {`XLEN{1'bx}}; - Ans = {{`XLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; - end - endcase - end - 2'b01: if (`D_SUPPORTED)begin // double - // {Int->Fp?, is the integer a long} - casex ({OpCtrl[2:1]}) - 2'b11: begin // long -> double - X = {`FLEN{1'bx}}; - SrcA = TestVector[8+`D_LEN+`XLEN-1:8+(`D_LEN)]; - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - end - 2'b10: begin // int -> double - // correctly sign extend the integer depending on if it's a signed/unsigned test - X = {`FLEN{1'bx}}; - SrcA = {{`XLEN-32{TestVector[8+`D_LEN+32-1]}}, TestVector[8+`D_LEN+32-1:8+(`D_LEN)]}; - Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; - end - 2'b01: begin // double -> long - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+`XLEN+`D_LEN-1:8+(`XLEN)]}; - SrcA = {`XLEN{1'bx}}; - Ans = {TestVector[8+(`XLEN-1):8]}; - end - 2'b00: begin // double -> int - X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+32+`D_LEN-1:8+(32)]}; - SrcA = {`XLEN{1'bx}}; - Ans = {{`XLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; - end - endcase - end - 2'b00: if (`S_SUPPORTED)begin // single - // {is the integer a long, is the opperation to an integer} - casex ({OpCtrl[2:1]}) - 2'b11: begin // long -> single - X = {`FLEN{1'bx}}; - SrcA = TestVector[8+`S_LEN+`XLEN-1:8+(`S_LEN)]; - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - end - 2'b10: begin // int -> single - // correctly sign extend the integer depending on if it's a signed/unsigned test - X = {`FLEN{1'bx}}; - SrcA = {{`XLEN-32{TestVector[8+`S_LEN+32-1]}}, TestVector[8+`S_LEN+32-1:8+(`S_LEN)]}; - Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; - end - 2'b01: begin // single -> long - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+`XLEN+`S_LEN-1:8+(`XLEN)]}; - SrcA = {`XLEN{1'bx}}; - Ans = {TestVector[8+(`XLEN-1):8]}; - end - 2'b00: begin // single -> int - X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+32+`S_LEN-1:8+(32)]}; - SrcA = {`XLEN{1'bx}}; - Ans = {{`XLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; - end - endcase - end - 2'b10: begin // half - // {is the integer a long, is the opperation to an integer} - casex ({OpCtrl[2:1]}) - 2'b11: begin // long -> half - X = {`FLEN{1'bx}}; - SrcA = TestVector[8+`H_LEN+`XLEN-1:8+(`H_LEN)]; - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - end - 2'b10: begin // int -> half - // correctly sign extend the integer depending on if it's a signed/unsigned test - X = {`FLEN{1'bx}}; - SrcA = {{`XLEN-32{TestVector[8+`H_LEN+32-1]}}, TestVector[8+`H_LEN+32-1:8+(`H_LEN)]}; - Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; - end - 2'b01: begin // half -> long - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+`XLEN+`H_LEN-1:8+(`XLEN)]}; - SrcA = {`XLEN{1'bx}}; - Ans = {TestVector[8+(`XLEN-1):8]}; - end - 2'b00: begin // half -> int - X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+32+`H_LEN-1:8+(32)]}; - SrcA = {`XLEN{1'bx}}; - Ans = {{`XLEN-32{TestVector[8+32-1]}}, TestVector[8+(32-1):8]}; - end - endcase - end - endcase - endcase - end - - assign XEn = ~((Unit == `CVTINTUNIT)&OpCtrl[2]); - assign YEn = ~((Unit == `CVTINTUNIT)|(Unit == `CVTFPUNIT)|((Unit == `DIVUNIT)&OpCtrl[0])); - assign ZEn = (Unit == `FMAUNIT); - - unpack #(P) unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze, - .Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN, - .XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf, - .XEn, .YEn, .ZEn, .XExpMax, .XPostBox); + assign XEn = ~((Unit == `CVTINTUNIT)&OpCtrl[2]); + assign YEn = ~((Unit == `CVTINTUNIT)|(Unit == `CVTFPUNIT)|((Unit == `DIVUNIT)&OpCtrl[0])); + assign ZEn = (Unit == `FMAUNIT); + // Will fix with better activation - for now, this works (jes) + assign FPUActive = 1'b1; + + unpack #(P) unpack(.X, .Y, .Z, .Fmt(ModFmt), .FPUActive, .Xs, .Ys, .Zs, .Xe, .Ye, .Ze, + .Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN, + .XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf, + .XEn, .YEn, .ZEn, .XExpMax, .XPostBox); endmodule diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 9ed35496d..0bcc34079 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -409,7 +409,20 @@ module testbench; // Support logic //////////////////////////////////////////////////////////////////////////////// + // Track names of instructions + string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; + logic [31:0] InstrW; + flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); + instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, + dut.core.ifu.InstrRawF[31:0], + dut.core.ifu.InstrD, dut.core.ifu.InstrE, + dut.core.ifu.InstrM, InstrW, + InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); + + // watch for problems such as lockup, reading unitialized memory, bad configs watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck + ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM, + dut.core.ifu.PCM, dut.core.ifu.InstrM, dut.core.lsu.IEUAdrM, InstrMName); riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER) loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename); @@ -420,15 +433,6 @@ module testbench; .clk(clk), .ProgramAddrMapFile(ProgramAddrMapFile), .ProgramLabelMapFile(ProgramLabelMapFile)); end - // Track names of instructions - string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; - logic [31:0] InstrW; - flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); - instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, - dut.core.ifu.InstrRawF[31:0], - dut.core.ifu.InstrD, dut.core.ifu.InstrE, - dut.core.ifu.InstrM, InstrW, - InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // Termination condition // terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed diff --git a/testbench/tests.vh b/testbench/tests.vh index f38f28056..116d39424 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -2031,8 +2031,8 @@ string arch64zbs[] = '{ "rv32i_m/privilege/src/WALLY-mie-01.S", "rv32i_m/privilege/src/WALLY-minfo-01.S", "rv32i_m/privilege/src/WALLY-misa-01.S", -// "rv32i_m/privilege/src/WALLY-mmu-sv32-01.S", - "rv32i_m/privilege/src/WALLY-mmu-sv32-svadu-01.S", + // "rv32i_m/privilege/src/WALLY-mmu-sv32-01.S", // run this if SVADU_SUPPORTED = 0 + "rv32i_m/privilege/src/WALLY-mmu-sv32-svadu-01.S", // run this if SVADU_SUPPORTED = 1 "rv32i_m/privilege/src/WALLY-mtvec-01.S", "rv32i_m/privilege/src/WALLY-pma-01.S", "rv32i_m/privilege/src/WALLY-pmp-01.S", diff --git a/tests/fp/combined_IF_vectors/extract_arch_vectors.py b/tests/fp/combined_IF_vectors/extract_arch_vectors.py index 8d3945f14..12669bc58 100755 --- a/tests/fp/combined_IF_vectors/extract_arch_vectors.py +++ b/tests/fp/combined_IF_vectors/extract_arch_vectors.py @@ -1,7 +1,7 @@ #! /usr/bin/python3 -# author: Alessandro Maiuolo -# contact: amaiuolo@g.hmc.edu +# author: Alessandro Maiuolo, Kevin Kim +# contact: amaiuolo@g.hmc.edu, kekim@hmc.edu # date created: 3-29-2023 # extract all arch test vectors @@ -77,7 +77,7 @@ def create_vectors(my_config): rounding_mode = "X" flags = "XX" # use name to create our new tv - dest_file = open("{}cvw_{}_{}.tv".format(dest_dir, my_config.bits, vector1[:-2]), 'a') + dest_file = open("{}cvw_{}_{}.tv".format(dest_dir, my_config.bits, vector1[:-2]), 'w') # open vectors src_file1 = open(source_dir1 + vector1,'r') src_file2 = open(source_dir2 + vector2,'r') @@ -144,7 +144,7 @@ def create_vectors(my_config): answer2 = src_file2.readline().strip() answer1 = src_file2.readline().strip() answer = answer1 + answer2 - # print(answer1,answer2) + #print(answer1,answer2) if not (answer2 == "e7d4b281" and answer1 == "6f5ca309"): # if there is still stuff to read # parse through .S file detected = False @@ -179,13 +179,56 @@ def create_vectors(my_config): else: # print("read false") reading = False + elif my_config.letter == "M" and my_config.bits == 32: + reading = True + while reading: + # print("trigger 64M") + # get answer from Ref...signature + # answers span two lines and are reversed + answer = src_file2.readline().strip() + print(f"Answer: {answer}") + #print(answer1,answer2) + if not (answer == "6f5ca309"): # if there is still stuff to read + # parse through .S file + detected = False + done = False + op1val = "0" + op2val = "0" + while not (detected or done): + # print("det1") + line = src_file1.readline() + # print(line) + if "op1val" in line: + # print("det2") + # parse line + op1val = line.split("op1val")[1].split("x")[1].split(";")[0] + if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling + op1val = twos_comp(my_config.bits, op1val) + if my_config.op != "fsqrt": # sqrt doesn't have two input vals, unnec here but keeping for later + op2val = line.split("op2val")[1].split("x")[1].strip() + if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there + if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling + op2val = twos_comp(my_config.bits, op2val) + # go to next test in vector + detected = True + elif "RVTEST_CODE_END" in line: + done = True + # ints don't have flags + flags = "XX" + # put it all together + if not done: + translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()), flags.strip(), rounding_mode) + dest_file.write(translation + "\n") + else: + # print("read false") + reading = False else: while reading: # get answer and flags from Ref...signature answer = src_file2.readline() - # print(answer) + print(answer) packed = src_file2.readline()[6:] - # print(packed) + print("Packed: ", packed) if len(packed.strip())>0: # if there is still stuff to read # print("packed") # parse through .S file @@ -229,7 +272,7 @@ def create_vectors(my_config): src_file2.close() config_list = [ -Config(32, "M", "div", "div_", 0), +Config(32, "M", "div", "div-", 0), Config(32, "F", "fdiv", "fdiv", 1), Config(32, "F", "fsqrt", "fsqrt", 2), Config(32, "M", "rem", "rem-", 3),