This commit is contained in:
Ross Thompson 2023-07-06 14:55:43 -05:00
commit 0394f3232f
34 changed files with 1753 additions and 1487 deletions

3
.gitmodules vendored
View File

@ -24,3 +24,6 @@
[submodule "addins/branch-predictor-simulator"] [submodule "addins/branch-predictor-simulator"]
path = addins/branch-predictor-simulator path = addins/branch-predictor-simulator
url = https://github.com/synxlin/branch-predictor-simulator.git 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

@ -0,0 +1 @@
Subproject commit 17a46c252f2f237e03a6768c5d15731215322f31

View File

@ -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 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 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 testfloat.do in the sim directory. Change the TEST_SIZE="all" to the
test. The best way to do this is to comment out each item out with specific test you want to run. For example, if you want to run only
the // comment option in SV. For example, binary16, you should set this variable to TEST_SIZE="HP".
string f128div[] = '{
// "f128_div_rne.tv",
// "f128_div_rz.tv",
// "f128_div_ru.tv",
// "f128_div_rd.tv",
// "f128_div_rnm.tv"
};
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;"

View File

@ -10,6 +10,4 @@
# sqrt - test square root # sqrt - test square root
# all - test everything # all - test everything
# nowave for 2nd argument supresses wlf files vsim -c -do "do testfloat.do rv64fpquad $1"
vsim -c -do "do testfloat.do rv64fpquad $1 $2"

View File

@ -25,14 +25,18 @@ vlib work
# start and run simulation # start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals # remove +acc flag for faster sim during regressions if there is no need to access internal signals
# $num = the added words after the call # $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 # Set WAV variable to avoid having any output to wave (to limit disk space)
# this removes any output to a wlf or wave window to reduce quietly set WAV 1;
# disk space.
if {($argc > 2) && ($3 eq "nowave")} { # 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" puts "No wave output is selected"
} else { } else {
puts "wave output is selected" puts "wave output is selected"

View File

@ -7,8 +7,15 @@ add wave -noupdate /testbenchfp/Y
add wave -noupdate /testbenchfp/Z add wave -noupdate /testbenchfp/Z
add wave -noupdate /testbenchfp/Res add wave -noupdate /testbenchfp/Res
add wave -noupdate /testbenchfp/Ans add wave -noupdate /testbenchfp/Ans
add wave -noupdate /testbenchfp/reset
add wave -noupdate /testbenchfp/DivStart add wave -noupdate /testbenchfp/DivStart
add wave -noupdate /testbenchfp/FDivBusyE 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/*
add wave -group {PostProc} -noupdate /testbenchfp/postprocess/specialcase/* add wave -group {PostProc} -noupdate /testbenchfp/postprocess/specialcase/*
add wave -group {PostProc} -noupdate /testbenchfp/postprocess/flags/* add wave -group {PostProc} -noupdate /testbenchfp/postprocess/flags/*

View File

@ -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 /* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed
case(OpD) case(OpD)
7'b0000111: case(Funct3D) 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'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'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 3'b001: if (P.ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flh
endcase endcase
7'b0100111: case(Funct3D) 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'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'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 3'b001: if (P.ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_00_0xx_0_0_0; // fsh

View File

@ -27,24 +27,24 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module fdivsqrt import cvw::*; #(parameter cvw_t P) ( module fdivsqrt import cvw::*; #(parameter cvw_t P) (
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic [P.FMTBITS-1:0] FmtE, input logic [P.FMTBITS-1:0] FmtE,
input logic XsE, input logic XsE,
input logic [P.NF:0] XmE, YmE, input logic [P.NF:0] XmE, YmE,
input logic [P.NE-1:0] XeE, YeE, input logic [P.NE-1:0] XeE, YeE,
input logic XInfE, YInfE, input logic XInfE, YInfE,
input logic XZeroE, YZeroE, input logic XZeroE, YZeroE,
input logic XNaNE, YNaNE, input logic XNaNE, YNaNE,
input logic FDivStartE, IDivStartE, input logic FDivStartE, IDivStartE,
input logic StallM, input logic StallM,
input logic FlushE, input logic FlushE,
input logic SqrtE, SqrtM, 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 [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 [2:0] Funct3E, Funct3M,
input logic IntDivE, W64E, input logic IntDivE, W64E,
output logic DivStickyM, output logic DivStickyM,
output logic FDivBusyE, IFDivStartE, FDivDoneE, output logic FDivBusyE, IFDivStartE, FDivDoneE,
output logic [P.NE+1:0] QeM, output logic [P.NE+1:0] QeM,
output logic [P.DIVb:0] QmM, output logic [P.DIVb:0] QmM,
output logic [P.XLEN-1:0] FIntDivResultM 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+3:0] D; // Iterator Divisor
logic [P.DIVb:0] FirstU, FirstUM; // Intermediate result values logic [P.DIVb:0] FirstU, FirstUM; // Intermediate result values
logic [P.DIVb+1:0] FirstC; // Step tracker logic [P.DIVb+1:0] FirstC; // Step tracker
logic Firstun; // Quotient selection logic Firstun; // Quotient selection
logic WZeroE; // Early termination flag logic WZeroE; // Early termination flag
logic [P.DURLEN-1:0] CyclesE; // FSM cycles logic [P.DURLEN-1:0] CyclesE; // FSM cycles
logic SpecialCaseM; // Divide by zero, square root of negative, etc. logic SpecialCaseM; // Divide by zero, square root of negative, etc.
logic DivStartE; // Enable signal for flops during stall logic DivStartE; // Enable signal for flops during stall
// Integer div/rem signals // Integer div/rem signals
logic BZeroM; // Denominator is zero logic BZeroM; // Denominator is zero
logic IntDivM; // Integer operation logic IntDivM; // Integer operation
logic [P.DIVBLEN:0] nM, mM; // Shift amounts 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 [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 fdivsqrtpreproc #(P) fdivsqrtpreproc( // Preprocessor
.clk, .IFDivStartE, .Xm(XmE), .Ym(YmE), .Xe(XeE), .Ye(YeE), .clk, .IFDivStartE, .Xm(XmE), .Ym(YmE), .Xe(XeE), .Ye(YeE),

View File

@ -28,8 +28,8 @@
module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) ( module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) (
input logic [P.FMTBITS-1:0] FmtE, input logic [P.FMTBITS-1:0] FmtE,
input logic SqrtE, input logic SqrtE,
input logic IntDivE, input logic IntDivE,
input logic [P.DIVBLEN:0] nE, input logic [P.DIVBLEN:0] nE,
output logic [P.DURLEN-1:0] CyclesE output logic [P.DURLEN-1:0] CyclesE
); );

View File

@ -29,8 +29,8 @@
module fdivsqrtexpcalc import cvw::*; #(parameter cvw_t P) ( module fdivsqrtexpcalc import cvw::*; #(parameter cvw_t P) (
input logic [P.FMTBITS-1:0] Fmt, input logic [P.FMTBITS-1:0] Fmt,
input logic [P.NE-1:0] Xe, Ye, input logic [P.NE-1:0] Xe, Ye,
input logic Sqrt, input logic Sqrt,
input logic XZero, input logic XZero,
input logic [P.DIVBLEN:0] ell, m, input logic [P.DIVBLEN:0] ell, m,
output logic [P.NE+1:0] Qe output logic [P.NE+1:0] Qe
); );

View File

@ -27,18 +27,17 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module fdivsqrtfgen2 import cvw::*; #(parameter cvw_t P) ( 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, input logic [P.DIVb+3:0] C, U, UM,
output logic [P.DIVb+3:0] F 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 // Generate for both positive and negative bits
assign FP = ~(U << 1) & C; assign FP = ~(U << 1) & C;
assign FN = (UM << 1) | (C & ~(C << 2)); assign FN = (UM << 1) | (C & ~(C << 2));
assign FZ = '0; assign FZ = '0;
always_comb // Choose which adder input will be used always_comb // Choose which adder input will be used
if (up) F = FP; if (up) F = FP;
else if (uz) F = FZ; else if (uz) F = FZ;

View File

@ -27,11 +27,11 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module fdivsqrtfgen4 import cvw::*; #(parameter cvw_t P) ( 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, input logic [P.DIVb+3:0] C, U, UM,
output logic [P.DIVb+3:0] F 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 // Generate for both positive and negative bits
assign F2 = (~U << 2) & (C << 2); assign F2 = (~U << 2) & (C << 2);

View File

@ -27,20 +27,20 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module fdivsqrtfsm import cvw::*; #(parameter cvw_t P) ( module fdivsqrtfsm import cvw::*; #(parameter cvw_t P) (
input logic clk, reset, input logic clk, reset,
input logic XInfE, YInfE, input logic XInfE, YInfE,
input logic XZeroE, YZeroE, input logic XZeroE, YZeroE,
input logic XNaNE, YNaNE, input logic XNaNE, YNaNE,
input logic FDivStartE, IDivStartE, input logic FDivStartE, IDivStartE,
input logic XsE, WZeroE, input logic XsE, WZeroE,
input logic SqrtE, input logic SqrtE,
input logic StallM, FlushE, input logic StallM, FlushE,
input logic IntDivE, input logic IntDivE,
input logic ISpecialCaseE, input logic ISpecialCaseE,
input logic [P.DURLEN-1:0] CyclesE, input logic [P.DURLEN-1:0] CyclesE,
output logic IFDivStartE, output logic IFDivStartE,
output logic FDivBusyE, FDivDoneE, output logic FDivBusyE, FDivDoneE,
output logic SpecialCaseM output logic SpecialCaseM
); );
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype;

View File

@ -27,14 +27,14 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module fdivsqrtiter import cvw::*; #(parameter cvw_t P) ( module fdivsqrtiter import cvw::*; #(parameter cvw_t P) (
input logic clk, input logic clk,
input logic IFDivStartE, input logic IFDivStartE,
input logic FDivBusyE, input logic FDivBusyE,
input logic SqrtE, input logic SqrtE,
input logic [P.DIVb+3:0] X, D, input logic [P.DIVb+3:0] X, D,
output logic [P.DIVb:0] FirstU, FirstUM, output logic [P.DIVb:0] FirstU, FirstUM,
output logic [P.DIVb+1:0] FirstC, output logic [P.DIVb+1:0] FirstC,
output logic Firstun, output logic Firstun,
output logic [P.DIVb+3:0] FirstWS, FirstWC 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] UNext[P.DIVCOPIES-1:0]; // U1.b
logic [P.DIVb:0] UMNext[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] 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.DIVCOPIES-1:0] un;
logic [P.DIVb+3:0] WSN, WCN; // Q4.b logic [P.DIVb+3:0] WSN, WCN; // Q4.b
logic [P.DIVb+3:0] DBar, D2, DBar2; // Q4.b logic [P.DIVb+3:0] DBar, D2, DBar2; // Q4.b
logic [P.DIVb+1:0] NextC; logic [P.DIVb+1:0] NextC;
logic [P.DIVb:0] UMux, UMMux; logic [P.DIVb:0] UMux, UMMux;
logic [P.DIVb:0] initU, initUM; 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 // Otherwise, the divisor is retained and the residual and result
// are fed back for the next iteration. // 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) wsmux(WS[P.DIVCOPIES], X, IFDivStartE, WSN);
mux2 #(P.DIVb+4) wcmux(WC[P.DIVCOPIES], '0, IFDivStartE, WCN); mux2 #(P.DIVb+4) wcmux(WC[P.DIVCOPIES], '0, IFDivStartE, WCN);
flopen #(P.DIVb+4) wsreg(clk, FDivBusyE, WSN, WS[0]); flopen #(P.DIVb+4) wsreg(clk, FDivBusyE, WSN, WS[0]);

View File

@ -27,27 +27,27 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) ( module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
input logic clk, reset, input logic clk, reset,
input logic StallM, input logic StallM,
input logic [P.DIVb+3:0] WS, WC, input logic [P.DIVb+3:0] WS, WC,
input logic [P.DIVb+3:0] D, input logic [P.DIVb+3:0] D,
input logic [P.DIVb:0] FirstU, FirstUM, input logic [P.DIVb:0] FirstU, FirstUM,
input logic [P.DIVb+1:0] FirstC, input logic [P.DIVb+1:0] FirstC,
input logic SqrtE, input logic SqrtE,
input logic Firstun, SqrtM, SpecialCaseM, NegQuotM, input logic Firstun, SqrtM, SpecialCaseM, NegQuotM,
input logic [P.XLEN-1:0] AM, 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, input logic [P.DIVBLEN:0] nM, mM,
output logic [P.DIVb:0] QmM, output logic [P.DIVb:0] QmM,
output logic WZeroE, output logic WZeroE,
output logic DivStickyM, output logic DivStickyM,
output logic [P.XLEN-1:0] FIntDivResultM output logic [P.XLEN-1:0] FIntDivResultM
); );
logic [P.DIVb+3:0] W, Sum; logic [P.DIVb+3:0] W, Sum;
logic [P.DIVb:0] PreQmM; logic [P.DIVb:0] PreQmM;
logic NegStickyM; logic NegStickyM;
logic weq0E, WZeroM; logic weq0E, WZeroM;
logic [P.XLEN-1:0] IntDivResultM; logic [P.XLEN-1:0] IntDivResultM;
////////////////////////// //////////////////////////

View File

@ -27,24 +27,24 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) ( module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
input logic clk, input logic clk,
input logic IFDivStartE, input logic IFDivStartE,
input logic [P.NF:0] Xm, Ym, input logic [P.NF:0] Xm, Ym,
input logic [P.NE-1:0] Xe, Ye, input logic [P.NE-1:0] Xe, Ye,
input logic [P.FMTBITS-1:0] FmtE, input logic [P.FMTBITS-1:0] FmtE,
input logic SqrtE, input logic SqrtE,
input logic XZeroE, input logic XZeroE,
input logic [2:0] Funct3E, input logic [2:0] Funct3E,
output logic [P.NE+1:0] QeM, output logic [P.NE+1:0] QeM,
output logic [P.DIVb+3:0] X, D, output logic [P.DIVb+3:0] X, D,
// Int-specific // 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 [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, input logic IntDivE, W64E,
output logic ISpecialCaseE, output logic ISpecialCaseE,
output logic [P.DURLEN-1:0] CyclesE, output logic [P.DURLEN-1:0] CyclesE,
output logic [P.DIVBLEN:0] nM, mM, output logic [P.DIVBLEN:0] nM, mM,
output logic NegQuotM, ALTBM, IntDivM, W64M, output logic NegQuotM, ALTBM, IntDivM, W64M,
output logic AsM, BZeroM, output logic AsM, BZeroM,
output logic [P.XLEN-1:0] AM 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.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.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 [P.DIVBLEN:0] mE, nE, ell; // Leading zeros of inputs
logic NumerZeroE; // Numerator is zero (X or A) logic NumerZeroE; // Numerator is zero (X or A)
logic AZeroE, BZeroE; // A or B is Zero for integer division logic AZeroE, BZeroE; // A or B is Zero for integer division
logic SignedDivE; // signed division logic SignedDivE; // signed division
logic NegQuotE; // Integer quotient is negative logic NegQuotE; // Integer quotient is negative
logic AsE, BsE; // Signs of integer inputs logic AsE, BsE; // Signs of integer inputs
logic [P.XLEN-1:0] AE; // input A after W64 adjustment logic [P.XLEN-1:0] AE; // input A after W64 adjustment
logic ALTBE; 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 // 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); 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}; else assign SqrtX = {2'b11, PreSqrtX, 1'b0};
mux2 #(P.DIVb+4) prexmux(DivX, SqrtX, SqrtE, PreShiftX); mux2 #(P.DIVb+4) prexmux(DivX, SqrtX, SqrtE, PreShiftX);

View File

@ -32,6 +32,8 @@ module controller import cvw::*; #(parameter cvw_t P) (
// Decode stage control signals // Decode stage control signals
input logic StallD, FlushD, // Stall, flush Decode stage input logic StallD, FlushD, // Stall, flush Decode stage
input logic [31:0] InstrD, // Instruction in 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 output logic [2:0] ImmSrcD, // Type of immediate extension
input logic IllegalIEUFPUInstrD, // Illegal IEU and FPU instruction input logic IllegalIEUFPUInstrD, // Illegal IEU and FPU instruction
output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers 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 [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage
output logic BMUActiveE, // Bit manipulation instruction being executed output logic BMUActiveE, // Bit manipulation instruction being executed
output logic MDUActiveE, // Mul/Div 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 // Memory stage control signals
input logic StallM, FlushM, // Stall, flush Memory stage 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 output logic StoreStallD // Store (memory write) causes stall
); );
logic [6:0] OpD; // Opcode in Decode stage logic [6:0] OpD; // Opcode in Decode stage
logic [2:0] Funct3D; // Funct3 field in Decode stage logic [2:0] Funct3D; // Funct3 field in Decode stage
logic [6:0] Funct7D; // Funct7 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 // pipelined control signals
logic RegWriteD, RegWriteE; // RegWrite (register will be written) 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] 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 [1:0] MemRWD, MemRWE; // Store (write to memory)
logic ALUOpD; // 0 for address generation, 1 for all other operations (must use Funct3) logic ALUOpD; // 0 for address generation, 1 for all other operations (must use Funct3)
logic BaseW64D; // W64 for Base instructions specifically 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 CSRReadD; // CSR read instruction
logic [1:0] AtomicD; // Atomic (AMO) instruction logic [1:0] AtomicD; // Atomic (AMO) instruction
logic FenceXD; // Fence instruction logic FenceXD; // Fence instruction
logic CMOD; // Cache management instruction
logic InvalidateICacheD, FlushDCacheD;// Invalidate I$, flush D$ logic InvalidateICacheD, FlushDCacheD;// Invalidate I$, flush D$
logic CSRWriteD, CSRWriteE; // CSR write logic CSRWriteD, CSRWriteE; // CSR write
logic PrivilegedD, PrivilegedE; // Privileged instruction 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 [2:0] ZBBSelectD; // ZBB Mux Select Signal
logic IFunctD, RFunctD, MFunctD; // Detect I, R, and M-type RV32IM/Rv64IM instructions logic IFunctD, RFunctD, MFunctD; // Detect I, R, and M-type RV32IM/Rv64IM instructions
logic LFunctD, SFunctD, BFunctD; // Detect load, store, branch 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 FenceM; // Fence.I or sfence.VMA instruction in memory stage
logic [2:0] ALUSelectD; // ALU Output selection mux control logic [2:0] ALUSelectD; // ALU Output selection mux control
logic IWValidFunct3D; // Detects if Funct3 is valid for IW instructions 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 // Extract fields
assign OpD = InstrD[6:0]; assign OpD = InstrD[6:0];
assign Funct3D = InstrD[14:12]; assign Funct3D = InstrD[14:12];
assign Funct7D = InstrD[31:25]; 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 // Funct 7 checking
// Be rigorous about detecting illegal instructions if CSRs or bit manipulation is supported // 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 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 | 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)); ((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 | assign SFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 |
((P.XLEN == 64) & (Funct3D == 3'b011)); ((P.XLEN == 64) & (Funct3D == 3'b011));
assign BFunctD = (Funct3D[2:1] != 2'b01); // legal branches assign BFunctD = Funct3D[2:1] != 2'b01; // legal branches
assign JFunctD = (Funct3D == 3'b000); 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; assign IWValidFunct3D = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b101;
end else begin:legalcheck2 end else begin:legalcheck2
assign IFunctD = 1; // Don't bother to separate out shift decoding assign IFunctD = 1; // Don't bother to separate out shift decoding
assign RFunctD = ~Funct7D[0]; // Not a multiply assign RFunctD = ~Funct7D[0]; // Not a multiply
assign MFunctD = Funct7D[0] & (P.M_SUPPORTED | (P.ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv 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 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 SFunctD = 1; // don't bother to check Funct3 for stores
assign BFunctD = 1; // don't bother to check Funct3 for branches 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; assign IWValidFunct3D = 1;
end end
// Main Instruction Decoder // Main Instruction Decoder
/* verilator lint_off CASEINCOMPLETE */ /* verilator lint_off CASEINCOMPLETE */
always_comb begin 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) case(OpD)
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_Illegal // RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_CMO_Illegal
7'b0000011: if (LFunctD) 7'b0000011: if (LFunctD)
ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // loads ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0_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'b0000111: if (FLSFunctD)
7'b0001111: if (P.ZIFENCEI_SUPPORTED) 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
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence 7'b0001111: if (FenceFunctD) begin
else if (P.ZIFENCEI_SUPPORTED)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0; // fence treated as nop ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0_0; // fence
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
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
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
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 else
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0; // amo 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_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_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_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_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 end
7'b0110011: if (RFunctD) 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) else if (MFunctD)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // 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; // lui 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 (RFunctD & (P.XLEN == 64)) 7'b0111011: if (RWFunctD)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i 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 (MFunctD & (P.XLEN == 64)) else if (MWFunctD)
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_1_0_0_0_1_00_0_0; // W-type Multiply/Divide
7'b1100011: if (BFunctD) 7'b1100011: if (BFunctD)
ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0_0; // branches
7'b1100111: if (JFunctD) 7'b1100111: if (JRFunctD)
ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr 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; // jal 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 7'b1110011: if (P.ZICSR_SUPPORTED) begin
if (Funct3D == 3'b000) if (PFunctD)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules 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 else if (CSRFunctD)
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0_0; // csrs
end end
endcase endcase
end 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. // 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 IllegalERegAdrD = P.E_SUPPORTED & P.ZICSR_SUPPORTED & ControlsD[`CTRLW-1] & InstrD[11];
//assign IllegalBaseInstrD = 1'b0; //assign IllegalBaseInstrD = 1'b0;
assign {BaseRegWriteD, ImmSrcD, ALUSrcAD, BaseALUSrcBD, MemRWD, assign {BaseRegWriteD, PreImmSrcD, ALUSrcAD, BaseALUSrcBD, MemRWD,
ResultSrcD, BranchD, ALUOpD, JumpD, ALUResultSrcD, BaseW64D, CSRReadD, 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 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 assign CSRWriteD = CSRReadD & !(CSRZeroSrcD & InstrD[13]); // Don't write if setting or clearing zeros
@ -300,13 +357,41 @@ module controller import cvw::*; #(parameter cvw_t P) (
assign FlushDCacheD = 0; assign FlushDCacheD = 0;
end 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 // Decode stage pipeline control register
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD); flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD);
// Execute stage pipeline control register and logic // Execute stage pipeline control register and logic
flopenrc #(29) controlregE(clk, reset, FlushE, ~StallE, 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, InstrValidD}, {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, InstrValidE}); {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 // Branch Logic
// The comparator handles both signed and unsigned branches using BranchSignedE // 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 assign IntDivE = MDUE & Funct3E[2]; // Integer division operation
// Memory stage pipeline control register // Memory stage pipeline control register
flopenrc #(20) controlregM(clk, reset, FlushM, ~StallM, flopenrc #(25) controlregM(clk, reset, FlushM, ~StallM,
{RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, IntDivE}, {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}); {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM, CMOpM, LSUPrefetchM});
// Writeback stage pipeline control register // Writeback stage pipeline control register
flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW, flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW,

View File

@ -98,7 +98,7 @@ module datapath import cvw::*; #(parameter cvw_t P) (
assign Rs2D = InstrD[24:20]; assign Rs2D = InstrD[24:20];
assign RdD = InstrD[11:7]; assign RdD = InstrD[11:7];
regfile #(P.XLEN, P.E_SUPPORTED) regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, R1D, R2D); 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 // Execute stage pipeline register and logic
flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E); flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E);

View File

@ -27,28 +27,29 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module extend #(parameter XLEN, A_SUPPORTED) ( module extend import cvw::*; #(parameter cvw_t P) (
input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits) 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 input logic [2:0] ImmSrcD, // Select what kind of extension to perform
output logic [XLEN-1:0] ImmExtD); // Extended immediate 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 always_comb
case(ImmSrcD) case (ImmSrcD)
// I-type // 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) // 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) // 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) // 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) // 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 // Store Conditional: zero offset
3'b101: if (A_SUPPORTED) ImmExtD = 0; 3'b101: if (P.A_SUPPORTED) ImmExtD = 0;
else ImmExtD = undefined; else ImmExtD = undefined;
default: ImmExtD = undefined; // undefined default: ImmExtD = undefined; // undefined
endcase endcase
endmodule endmodule

View File

@ -30,6 +30,8 @@ module ieu import cvw::*; #(parameter cvw_t P) (
input logic clk, reset, input logic clk, reset,
// Decode stage signals // Decode stage signals
input logic [31:0] InstrD, // Instruction 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 input logic IllegalIEUFPUInstrD, // Illegal instruction
output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
// Execute stage signals // 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 [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 [4:0] RdE, // Destination register
output logic MDUActiveE, // Mul/Div 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, // datata prefetch
// Memory stage signals // Memory stage signals
input logic SquashSCW, // Squash store conditional, from LSU input logic SquashSCW, // Squash store conditional, from LSU
output logic [1:0] MemRWM, // Read/write control goes to 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 logic BMUActiveE; // Bit manipulation instruction being executed
controller #(P) c( 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, .IllegalIEUFPUInstrD, .IllegalBaseInstrD, .StallE, .FlushE, .FlagsE, .FWriteIntE,
.PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .MemReadE, .CSRReadE, .PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .MemReadE, .CSRReadE,
.Funct3E, .IntDivE, .MDUE, .W64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE, .SCE, .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, .StallM, .FlushM, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M,
.RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM, .RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM,
.StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .InvalidateICacheM, .StoreStallD); .StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .InvalidateICacheM, .StoreStallD);

View File

@ -39,6 +39,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
input logic [6:0] Funct7M, // Atomic memory operation function input logic [6:0] Funct7M, // Atomic memory operation function
input logic [1:0] AtomicM, // Atomic memory operation input logic [1:0] AtomicM, // Atomic memory operation
input logic FlushDCacheM, // Flush D cache to next level of memory 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 CommittedM, // Delay interrupts while memory operation in flight
output logic SquashSCW, // Store conditional failed disable write to GPR output logic SquashSCW, // Store conditional failed disable write to GPR
output logic DCacheMiss, // D cache miss for performance counters 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; logic [1:0] DTIMMemRWM;
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory. // 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; assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0;
// **** fix ReadDataWordM to be LLEN. ByteMask is wrong length. // **** fix ReadDataWordM to be LLEN. ByteMask is wrong length.
// **** create config to support DTIM with floating point. // **** 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 CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
assign CacheRWM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0; assign CacheRWM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '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), 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( .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), .clk, .reset, .Stall(GatedStallW), .SelBusBeat, .FlushStage(FlushW), .CacheRW(CacheRWM), .CacheAtomic(CacheAtomicM),

View File

@ -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 [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 var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
output logic [2:0] FRM_REGW, 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] CSRReadValW, // value read from CSR
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns 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 [P.XLEN-1:0] TVecAlignedM;
logic InstrValidNotFlushedM; logic InstrValidNotFlushedM;
logic STimerInt; 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 // only valid unflushed instructions can access CSRs
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW; assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
@ -214,7 +219,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
csri #(P) csri(.clk, .reset, csri #(P) csri(.clk, .reset,
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM, .CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt, .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, csrsr #(P) csrsr(.clk, .reset, .StallW,
.WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM, .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, .MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM, .MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM,
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM, .IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM,
.MENVCFG_STCE); .MENVCFG_REGW);
if (P.S_SUPPORTED) begin:csrs 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, csrs #(P) csrs(.clk, .reset,
.CSRSWriteM, .STrapM, .CSRAdrM, .CSRSWriteM, .STrapM, .CSRAdrM,
.NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW, .NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW,
@ -244,8 +251,8 @@ module csr import cvw::*; #(parameter cvw_t P) (
.CSRWriteValM, .PrivilegeModeW, .CSRWriteValM, .PrivilegeModeW,
.CSRSReadValM, .STVEC_REGW, .SEPC_REGW, .CSRSReadValM, .STVEC_REGW, .SEPC_REGW,
.SCOUNTEREN_REGW, .SCOUNTEREN_REGW,
.SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .MENVCFG_STCE, .SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .STCE,
.WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt); .WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt, .SENVCFG_REGW);
end else begin end else begin
assign WriteSSTATUSM = 0; assign WriteSSTATUSM = 0;
assign CSRSReadValM = 0; assign CSRSReadValM = 0;
@ -282,6 +289,17 @@ module csr import cvw::*; #(parameter cvw_t P) (
assign IllegalCSRCAccessM = 1; // counters aren't enabled assign IllegalCSRCAccessM = 1; // counters aren't enabled
end 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 // merge CSR Reads
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM; assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM;
flopenrc #(P.XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW); flopenrc #(P.XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);

View File

@ -34,7 +34,7 @@ module csri import cvw::*; #(parameter cvw_t P) (
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt, input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt,
input logic [11:0] MIDELEG_REGW, 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, MIE_REGW,
output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0 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.S_SUPPORTED) begin:mask
if (P.SSTC_SUPPORTED) begin 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 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 end else begin
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9) assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9)
assign STIP = MIP_REGW_writeable[5]; assign STIP = MIP_REGW_writeable[5];

View File

@ -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 var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
output logic WriteMSTATUSM, WriteMSTATUSHM, output logic WriteMSTATUSM, WriteMSTATUSHM,
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM, 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] MISA_REGW, MHARTID_REGW;
logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_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 [P.XLEN-1:0] MENVCFGH_REGW;
logic [63:0] MENVCFG_PreWriteValM, MENVCFG_WriteValM; logic [63:0] MENVCFG_PreWriteValM, MENVCFG_WriteValM;
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
@ -193,15 +192,6 @@ module csrm import cvw::*; #(parameter cvw_t P) (
assign MENVCFGH_REGW = MENVCFG_REGW[63:32]; assign MENVCFGH_REGW = MENVCFG_REGW[63:32];
end 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 // Read machine mode CSRs
// verilator lint_off WIDTH // verilator lint_off WIDTH
logic [5:0] entry; logic [5:0] entry;

View File

@ -44,10 +44,12 @@ module csrs import cvw::*; #(parameter cvw_t P) (
output logic [P.XLEN-1:0] SATP_REGW, output logic [P.XLEN-1:0] SATP_REGW,
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
input logic [63:0] MTIME_CLINT, input logic [63:0] MTIME_CLINT,
input logic MENVCFG_STCE, input logic STCE,
output logic WriteSSTATUSM, output logic WriteSSTATUSM,
output logic IllegalCSRSAccessM, output logic IllegalCSRSAccessM,
output logic STimerInt output logic STimerInt,
output logic [P.XLEN-1:0] SENVCFG_REGW
); );
// Supervisor CSRs // Supervisor CSRs
@ -75,7 +77,6 @@ module csrs import cvw::*; #(parameter cvw_t P) (
logic WriteSENVCFGM; logic WriteSENVCFGM;
logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW; 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 [P.XLEN-1:0] SENVCFG_WriteValM;
logic [63:0] STIMECMP_REGW; 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 WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN); assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG); assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG);
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)); assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & STCE;
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)) & (P.XLEN == 32); assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & STCE & (P.XLEN == 32);
// CSRs // CSRs
flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
@ -125,19 +126,11 @@ module csrs import cvw::*; #(parameter cvw_t P) (
CSRWriteValM[7] & P.ZICBOZ_SUPPORTED, CSRWriteValM[7] & P.ZICBOZ_SUPPORTED,
CSRWriteValM[6:4] & {3{P.ZICBOM_SUPPORTED}}, CSRWriteValM[6:4] & {3{P.ZICBOM_SUPPORTED}},
3'b0, 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); 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 // CSR Reads
always_comb begin:csrr always_comb begin:csrr
IllegalCSRSAccessM = 0; IllegalCSRSAccessM = 0;
@ -157,13 +150,13 @@ module csrs import cvw::*; #(parameter cvw_t P) (
end end
SCOUNTEREN:CSRSReadValM = {{(P.XLEN-32){1'b0}}, SCOUNTEREN_REGW}; SCOUNTEREN:CSRSReadValM = {{(P.XLEN-32){1'b0}}, SCOUNTEREN_REGW};
SENVCFG: CSRSReadValM = SENVCFG_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]; CSRSReadValM = STIMECMP_REGW[P.XLEN-1:0];
else begin else begin
CSRSReadValM = 0; CSRSReadValM = 0;
IllegalCSRSAccessM = 1; IllegalCSRSAccessM = 1;
end 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]; CSRSReadValM[31:0] = STIMECMP_REGW[63:32];
else begin // not supported for RV64 else begin // not supported for RV64
CSRSReadValM = 0; CSRSReadValM = 0;

View File

@ -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 [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 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 [2:0] FRM_REGW, // FPU rounding mode
output logic [3:0] ENVCFG_CBE, // Cache block operation enables
// PC logic output in privileged unit // PC logic output in privileged unit
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
// control outputs // 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, .STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS,
.MEDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW,
.SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.SetFflagsM, .FRM_REGW, .SetFflagsM, .FRM_REGW, .ENVCFG_CBE,
.CSRReadValW,.UnalignedPCNextF, .IllegalCSRAccessM, .BigEndianM); .CSRReadValW,.UnalignedPCNextF, .IllegalCSRAccessM, .BigEndianM);
// pipeline early-arriving trap sources // pipeline early-arriving trap sources

View File

@ -78,6 +78,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD; logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD;
logic SquashSCW; logic SquashSCW;
logic MDUActiveE; // Mul/Div instruction being executed 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 // floating point unit signals
logic [2:0] FRM_REGW; 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 // integer execution unit: integer register file, datapath and controller
ieu #(P) ieu(.clk, .reset, ieu #(P) ieu(.clk, .reset,
// Decode Stage interface // Decode Stage interface
.InstrD, .IllegalIEUFPUInstrD, .IllegalBaseInstrD, .InstrD, .STATUS_FS, .ENVCFG_CBE, .IllegalIEUFPUInstrD, .IllegalBaseInstrD,
// Execute Stage interface // Execute Stage interface
.PCE, .PCLinkE, .FWriteIntE, .FCvtIntE, .IEUAdrE, .IntDivE, .W64E, .PCE, .PCLinkE, .FWriteIntE, .FCvtIntE, .IEUAdrE, .IntDivE, .W64E,
.Funct3E, .ForwardedSrcAE, .ForwardedSrcBE, .MDUActiveE, .Funct3E, .ForwardedSrcAE, .ForwardedSrcBE, .MDUActiveE, .CMOpM, .IFUPrefetchE, .LSUPrefetchM,
// Memory stage interface // Memory stage interface
.SquashSCW, // from LSU .SquashSCW, // from LSU
.MemRWM, // read/write control goes to 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, .MemRWM, .Funct3M, .Funct7M(InstrM[31:25]), .AtomicM,
.CommittedM, .DCacheMiss, .DCacheAccess, .SquashSCW, .CommittedM, .DCacheMiss, .DCacheAccess, .SquashSCW,
.FpLoadStoreM, .FWriteDataM, .IEUAdrE, .IEUAdrM, .WriteDataM, .FpLoadStoreM, .FWriteDataM, .IEUAdrE, .IEUAdrM, .WriteDataM,
.ReadDataW, .FlushDCacheM, .ReadDataW, .FlushDCacheM, .CMOpM, .LSUPrefetchM,
// connected to ahb (all stay the same) // connected to ahb (all stay the same)
.LSUHADDR, .HRDATA, .LSUHWDATA, .LSUHWSTRB, .LSUHSIZE, .LSUHADDR, .HRDATA, .LSUHWDATA, .LSUHWSTRB, .LSUHSIZE,
.LSUHBURST, .LSUHTRANS, .LSUHWRITE, .LSUHREADY, .LSUHBURST, .LSUHTRANS, .LSUHWRITE, .LSUHREADY,
@ -291,7 +294,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.PrivilegeModeW, .SATP_REGW, .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, .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 end else begin
assign CSRReadValW = 0; assign CSRReadValW = 0;
assign UnalignedPCNextF = PC2NextF; assign UnalignedPCNextF = PC2NextF;

View File

@ -30,13 +30,14 @@ module instrNameDecTB(
logic [2:0] funct3; logic [2:0] funct3;
logic [6:0] funct7; logic [6:0] funct7;
logic [11:0] imm; logic [11:0] imm;
logic [4:0] rs2; logic [4:0] rs2, rd;
assign op = instr[6:0]; assign op = instr[6:0];
assign funct3 = instr[14:12]; assign funct3 = instr[14:12];
assign funct7 = instr[31:25]; assign funct7 = instr[31:25];
assign imm = instr[31:20]; assign imm = instr[31:20];
assign rs2 = instr[24:20]; assign rs2 = instr[24:20];
assign rd = instr[11:7];
// it would be nice to add the operands to the name // it would be nice to add the operands to the name
// create another variable called decoded // create another variable called decoded
@ -77,7 +78,10 @@ module instrNameDecTB(
else if (funct7[6:1] == 6'b010010) name = "BEXTI"; else if (funct7[6:1] == 6'b010010) name = "BEXTI";
else if (funct7 == 7'b0010100 & rs2 == 5'b00111) name = "ORC.B"; else if (funct7 == 7'b0010100 & rs2 == 5'b00111) name = "ORC.B";
else name = "ILLEGAL"; 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'b0010011_111: name = "ANDI";
10'b0010111_???: name = "AUIPC"; 10'b0010111_???: name = "AUIPC";
10'b0100011_000: name = "SB"; 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'b11000) name = "AMOMINU.D";
else if (funct7[6:2] == 5'b11100) name = "AMOMAXU.D"; else if (funct7[6:2] == 5'b11100) name = "AMOMAXU.D";
else name = "ILLEGAL"; 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'b1000011_???: name = "FMADD";
10'b1000111_???: name = "FMSUB"; 10'b1000111_???: name = "FMSUB";
10'b1001011_???: name = "FNMSUB"; 10'b1001011_???: name = "FNMSUB";

View File

@ -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

View File

@ -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.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.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.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 end
endmodule endmodule

File diff suppressed because it is too large Load Diff

View File

@ -409,7 +409,20 @@ module testbench;
// Support logic // 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 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 riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER) loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename); loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
@ -420,15 +433,6 @@ module testbench;
.clk(clk), .ProgramAddrMapFile(ProgramAddrMapFile), .ProgramLabelMapFile(ProgramLabelMapFile)); .clk(clk), .ProgramAddrMapFile(ProgramAddrMapFile), .ProgramLabelMapFile(ProgramLabelMapFile));
end 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 // Termination condition
// terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed // terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed

View File

@ -2031,8 +2031,8 @@ string arch64zbs[] = '{
"rv32i_m/privilege/src/WALLY-mie-01.S", "rv32i_m/privilege/src/WALLY-mie-01.S",
"rv32i_m/privilege/src/WALLY-minfo-01.S", "rv32i_m/privilege/src/WALLY-minfo-01.S",
"rv32i_m/privilege/src/WALLY-misa-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-01.S", // run this if SVADU_SUPPORTED = 0
"rv32i_m/privilege/src/WALLY-mmu-sv32-svadu-01.S", "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-mtvec-01.S",
"rv32i_m/privilege/src/WALLY-pma-01.S", "rv32i_m/privilege/src/WALLY-pma-01.S",
"rv32i_m/privilege/src/WALLY-pmp-01.S", "rv32i_m/privilege/src/WALLY-pmp-01.S",

View File

@ -1,7 +1,7 @@
#! /usr/bin/python3 #! /usr/bin/python3
# author: Alessandro Maiuolo # author: Alessandro Maiuolo, Kevin Kim
# contact: amaiuolo@g.hmc.edu # contact: amaiuolo@g.hmc.edu, kekim@hmc.edu
# date created: 3-29-2023 # date created: 3-29-2023
# extract all arch test vectors # extract all arch test vectors
@ -77,7 +77,7 @@ def create_vectors(my_config):
rounding_mode = "X" rounding_mode = "X"
flags = "XX" flags = "XX"
# use name to create our new tv # 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 # open vectors
src_file1 = open(source_dir1 + vector1,'r') src_file1 = open(source_dir1 + vector1,'r')
src_file2 = open(source_dir2 + vector2,'r') src_file2 = open(source_dir2 + vector2,'r')
@ -144,7 +144,7 @@ def create_vectors(my_config):
answer2 = src_file2.readline().strip() answer2 = src_file2.readline().strip()
answer1 = src_file2.readline().strip() answer1 = src_file2.readline().strip()
answer = answer1 + answer2 answer = answer1 + answer2
# print(answer1,answer2) #print(answer1,answer2)
if not (answer2 == "e7d4b281" and answer1 == "6f5ca309"): # if there is still stuff to read if not (answer2 == "e7d4b281" and answer1 == "6f5ca309"): # if there is still stuff to read
# parse through .S file # parse through .S file
detected = False detected = False
@ -179,13 +179,56 @@ def create_vectors(my_config):
else: else:
# print("read false") # print("read false")
reading = 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: else:
while reading: while reading:
# get answer and flags from Ref...signature # get answer and flags from Ref...signature
answer = src_file2.readline() answer = src_file2.readline()
# print(answer) print(answer)
packed = src_file2.readline()[6:] packed = src_file2.readline()[6:]
# print(packed) print("Packed: ", packed)
if len(packed.strip())>0: # if there is still stuff to read if len(packed.strip())>0: # if there is still stuff to read
# print("packed") # print("packed")
# parse through .S file # parse through .S file
@ -229,7 +272,7 @@ def create_vectors(my_config):
src_file2.close() src_file2.close()
config_list = [ config_list = [
Config(32, "M", "div", "div_", 0), Config(32, "M", "div", "div-", 0),
Config(32, "F", "fdiv", "fdiv", 1), Config(32, "F", "fdiv", "fdiv", 1),
Config(32, "F", "fsqrt", "fsqrt", 2), Config(32, "F", "fsqrt", "fsqrt", 2),
Config(32, "M", "rem", "rem-", 3), Config(32, "M", "rem", "rem-", 3),