mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
commit
60cc5c97f4
@ -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
|
||||||
|
@ -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),
|
||||||
|
@ -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
|
||||||
);
|
);
|
||||||
|
@ -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
|
||||||
);
|
);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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]);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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),
|
||||||
|
@ -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);
|
||||||
|
@ -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];
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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";
|
||||||
|
45
testbench/common/ramxdetector.sv
Normal file
45
testbench/common/ramxdetector.sv
Normal 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
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user