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

3
.gitmodules vendored
View File

@ -24,3 +24,6 @@
[submodule "addins/branch-predictor-simulator"]
path = addins/branch-predictor-simulator
url = https://github.com/synxlin/branch-predictor-simulator.git
[submodule "addins/FreeRTOS-Kernel"]
path = addins/FreeRTOS-Kernel
url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git

@ -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
subset of the vectors (e.g., only binary16), you should modify the
cvw/testbench/tests-fp.h and comment out the tests you do not want to
test. The best way to do this is to comment out each item out with
the // comment option in SV. For example,
string f128div[] = '{
// "f128_div_rne.tv",
// "f128_div_rz.tv",
// "f128_div_ru.tv",
// "f128_div_rd.tv",
// "f128_div_rnm.tv"
};
testfloat.do in the sim directory. Change the TEST_SIZE="all" to the
specific test you want to run. For example, if you want to run only
binary16, you should set this variable to TEST_SIZE="HP".
4b.) If you want to turn off the generation of wlf files while running
sim-testfloat-batch, you can modify testfloat.do in the sim
directory. Inside this DO file, modify the WAV file to 0 --> i.e.,
set "quietly set WAV 0;"

View File

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

View File

@ -25,14 +25,18 @@ vlib work
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
# $num = the added words after the call
vlog +incdir+../config/$1 +incdir+../config/shared ../src/wally/cvw.sv ../testbench/testbench-fp.sv ../src/fpu/*.sv ../src/fpu/*/*.sv ../src/generic/*.sv ../src/generic/flop/*.sv -suppress 2583,7063,8607,2697
vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench-fp.sv ../src/fpu/*.sv ../src/fpu/*/*.sv ../src/generic/*.sv ../src/generic/flop/*.sv -suppress 2583,7063,8607,2697
vsim -voptargs=+acc work.testbenchfp -G TEST=$2
# Change TEST_SIZE to only test certain FP width
# values are QP, DP, SP, HP
vsim -voptargs=+acc work.testbenchfp -GTEST=$2 -GTEST_SIZE="all"
# Determine if nowave argument is provided
# this removes any output to a wlf or wave window to reduce
# disk space.
if {($argc > 2) && ($3 eq "nowave")} {
# Set WAV variable to avoid having any output to wave (to limit disk space)
quietly set WAV 1;
# Determine if nowave argument is provided this removes any output to
# a wlf or wave window to reduce disk space.
if {$WAV eq 0} {
puts "No wave output is selected"
} else {
puts "wave output is selected"

View File

@ -7,8 +7,15 @@ add wave -noupdate /testbenchfp/Y
add wave -noupdate /testbenchfp/Z
add wave -noupdate /testbenchfp/Res
add wave -noupdate /testbenchfp/Ans
add wave -noupdate /testbenchfp/reset
add wave -noupdate /testbenchfp/DivStart
add wave -noupdate /testbenchfp/FDivBusyE
add wave -noupdate /testbenchfp/CheckNow
add wave -noupdate /testbenchfp/DivDone
add wave -noupdate /testbenchfp/ResMatch
add wave -noupdate /testbenchfp/FlagMatch
add wave -noupdate /testbenchfp/CheckNow
add wave -noupdate /testbenchfp/NaNGood
add wave -group {PostProc} -noupdate /testbenchfp/postprocess/*
add wave -group {PostProc} -noupdate /testbenchfp/postprocess/specialcase/*
add wave -group {PostProc} -noupdate /testbenchfp/postprocess/flags/*

View File

@ -38,7 +38,6 @@ module fdivsqrtfgen2 import cvw::*; #(parameter cvw_t P) (
assign FN = (UM << 1) | (C & ~(C << 2));
assign FZ = '0;
always_comb // Choose which adder input will be used
if (up) F = FP;
else if (uz) F = FZ;

View File

@ -63,7 +63,7 @@ module fdivsqrtiter import cvw::*; #(parameter cvw_t P) (
// Otherwise, the divisor is retained and the residual and result
// are fed back for the next iteration.
// Residual WS/SC registers/initializaiton mux
// Residual WS/SC registers/initialization mux
mux2 #(P.DIVb+4) wsmux(WS[P.DIVCOPIES], X, IFDivStartE, WSN);
mux2 #(P.DIVb+4) wcmux(WC[P.DIVCOPIES], '0, IFDivStartE, WCN);
flopen #(P.DIVb+4) wsreg(clk, FDivBusyE, WSN, WS[0]);

View File

@ -32,6 +32,8 @@ module controller import cvw::*; #(parameter cvw_t P) (
// Decode stage control signals
input logic StallD, FlushD, // Stall, flush Decode stage
input logic [31:0] InstrD, // Instruction in Decode stage
input logic [1:0] STATUS_FS, // is FPU enabled?
input logic [3:0] ENVCFG_CBE, // Cache block operation enables
output logic [2:0] ImmSrcD, // Type of immediate extension
input logic IllegalIEUFPUInstrD, // Illegal IEU and FPU instruction
output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
@ -60,6 +62,9 @@ module controller import cvw::*; #(parameter cvw_t P) (
output logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage
output logic BMUActiveE, // Bit manipulation instruction being executed
output logic MDUActiveE, // Mul/Div instruction being executed
output logic [3:0] CMOpM, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
output logic IFUPrefetchE, // instruction prefetch
output logic LSUPrefetchM, // data prefetch
// Memory stage control signals
input logic StallM, FlushM, // Stall, flush Memory stage
@ -80,16 +85,18 @@ module controller import cvw::*; #(parameter cvw_t P) (
output logic StoreStallD // Store (memory write) causes stall
);
logic [6:0] OpD; // Opcode in Decode stage
logic [2:0] Funct3D; // Funct3 field in Decode stage
logic [6:0] Funct7D; // Funct7 field in Decode stage
logic [4:0] Rs1D; // Rs1 source register in Decode stage
logic [4:0] Rs1D, Rs2D, RdD; // Rs1/2 source register / dest reg in Decode stage
`define CTRLW 23
`define CTRLW 24
// pipelined control signals
logic RegWriteD, RegWriteE; // RegWrite (register will be written)
logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM; // Select which result to write back to register file
logic [2:0] PreImmSrcD; // Immediate source format (before amending for prefetches)
logic [1:0] MemRWD, MemRWE; // Store (write to memory)
logic ALUOpD; // 0 for address generation, 1 for all other operations (must use Funct3)
logic BaseW64D; // W64 for Base instructions specifically
@ -103,6 +110,7 @@ module controller import cvw::*; #(parameter cvw_t P) (
logic CSRReadD; // CSR read instruction
logic [1:0] AtomicD; // Atomic (AMO) instruction
logic FenceXD; // Fence instruction
logic CMOD; // Cache management instruction
logic InvalidateICacheD, FlushDCacheD;// Invalidate I$, flush D$
logic CSRWriteD, CSRWriteE; // CSR write
logic PrivilegedD, PrivilegedE; // Privileged instruction
@ -126,16 +134,27 @@ module controller import cvw::*; #(parameter cvw_t P) (
logic [2:0] ZBBSelectD; // ZBB Mux Select Signal
logic IFunctD, RFunctD, MFunctD; // Detect I, R, and M-type RV32IM/Rv64IM instructions
logic LFunctD, SFunctD, BFunctD; // Detect load, store, branch instructions
logic JFunctD; // detect jalr instruction
logic FLSFunctD; // Detect floating-point loads and stores
logic JRFunctD; // detect jalr instruction
logic FenceFunctD; // Detect fence instruction
logic CMOFunctD; // Detect CMO instruction
logic AFunctD, AMOFunctD; // Detect atomic instructions
logic RWFunctD, MWFunctD; // detect RW/MW instructions
logic PFunctD, CSRFunctD; // detect privileged / CSR instruction
logic FenceM; // Fence.I or sfence.VMA instruction in memory stage
logic [2:0] ALUSelectD; // ALU Output selection mux control
logic IWValidFunct3D; // Detects if Funct3 is valid for IW instructions
logic [3:0] CMOpD, CMOpE; // which CMO instruction 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
logic IFUPrefetchD; // instruction prefetch
logic LSUPrefetchD, LSUPrefetchE; // data prefetch
// Extract fields
assign OpD = InstrD[6:0];
assign Funct3D = InstrD[14:12];
assign Funct7D = InstrD[31:25];
assign Rs1D = InstrD[19:15];
assign Rs2D = InstrD[24:20];
assign RdD = InstrD[11:7];
// Funct 7 checking
// Be rigorous about detecting illegal instructions if CSRs or bit manipulation is supported
@ -156,70 +175,108 @@ module controller import cvw::*; #(parameter cvw_t P) (
assign MFunctD = (Funct7D == 7'b0000001) & (P.M_SUPPORTED | (P.ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv
assign LFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 | Funct3D == 3'b100 | Funct3D == 3'b101 |
((P.XLEN == 64) & (Funct3D == 3'b011 | Funct3D == 3'b110));
assign FLSFunctD = (STATUS_FS != 2'b00) & ((Funct3D == 3'b010 & P.F_SUPPORTED) | (Funct3D == 3'b011 & P.D_SUPPORTED) |
(Funct3D == 3'b100 & P.Q_SUPPORTED) | (Funct3D == 3'b001 & P.ZFH_SUPPORTED));
assign FenceFunctD = (Funct3D == 3'b000) | (P.ZIFENCEI_SUPPORTED & Funct3D == 3'b001);
assign CMOFunctD = (Funct3D == 3'b010 & RdD == 5'b0) &
((P.ZICBOZ_SUPPORTED & InstrD[31:20] == 12'd4 & ENVCFG_CBE[3]) |
(P.ZICBOM_SUPPORTED & ((InstrD[31:20] == 12'd0 & (ENVCFG_CBE[1:0] != 2'b00))) |
(InstrD[31:20] == 12'd1 | InstrD[31:20] == 12'd2) & ENVCFG_CBE[2]));
// *** need to get with enable bits such as MENVCFG_CBZE
assign AFunctD = (Funct3D == 3'b010) | (P.XLEN == 64 & Funct3D == 3'b011);
assign AMOFunctD = (InstrD[31:27] == 5'b00001) |
(InstrD[31:27] == 5'b00000) |
(InstrD[31:27] == 5'b00100) |
(InstrD[31:27] == 5'b01100) |
(InstrD[31:27] == 5'b01000) |
(InstrD[31:27] == 5'b10000) |
(InstrD[31:27] == 5'b10100) |
(InstrD[31:27] == 5'b11000) |
(InstrD[31:27] == 5'b11100);
assign RWFunctD = ((Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b101) & Funct7ZeroD |
(Funct3D == 3'b000 | Funct3D == 3'b101) & Funct7b5D) & (P.XLEN == 64);
assign MWFunctD = MFunctD & (P.XLEN == 64) & ~(Funct3D == 3'b001 | Funct3D == 3'b010 | Funct3D == 3'b011);
assign SFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 |
((P.XLEN == 64) & (Funct3D == 3'b011));
assign BFunctD = (Funct3D[2:1] != 2'b01); // legal branches
assign JFunctD = (Funct3D == 3'b000);
assign BFunctD = Funct3D[2:1] != 2'b01; // legal branches
assign JRFunctD = Funct3D == 3'b000;
assign PFunctD = Funct3D == 3'b000 & Rs1D == 5'b0 & RdD == 5'b0;
assign CSRFunctD = Funct3D[1:0] != 2'b00;
assign IWValidFunct3D = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b101;
end else begin:legalcheck2
assign IFunctD = 1; // Don't bother to separate out shift decoding
assign RFunctD = ~Funct7D[0]; // Not a multiply
assign MFunctD = Funct7D[0] & (P.M_SUPPORTED | (P.ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv
assign LFunctD = 1; // don't bother to check Funct3 for loads
assign FLSFunctD = 1; // don't bother to check Func3 for floating-point loads/stores
assign FenceFunctD = 1; // don't bother to check fields for fences
assign CMOFunctD = 1; // don't bother to check fields for CMO instructions
assign AFunctD = 1; // don't bother to check fields for atomics
assign AMOFunctD = 1; // don't bother to check Funct7 for AMO operations
assign RWFunctD = 1; // don't bother to check fields for RW instructions
assign MWFunctD = 1; // don't bother to check fields for MW instructions
assign SFunctD = 1; // don't bother to check Funct3 for stores
assign BFunctD = 1; // don't bother to check Funct3 for branches
assign JFunctD = 1; // don't bother to check Funct3 for jumps
assign JRFunctD = 1; // don't bother to check Funct3 for jalrs
assign PFunctD = 1; // don't bother to check fields for privileged instructions
assign CSRFunctD = 1; // don't bother to check Funct3 for CSR operations
assign IWValidFunct3D = 1;
end
// Main Instruction Decoder
/* verilator lint_off CASEINCOMPLETE */
always_comb begin
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // default: Illegal instruction
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0_1; // default: Illegal instruction
case(OpD)
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_Illegal
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_CMO_Illegal
7'b0000011: if (LFunctD)
ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // loads
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_1; // flw - only legal if FP supported
7'b0001111: if (P.ZIFENCEI_SUPPORTED)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0_0; // loads
7'b0000111: if (FLSFunctD)
ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0_1; // flw - only legal if FP supported
7'b0001111: if (FenceFunctD) begin
if (P.ZIFENCEI_SUPPORTED)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0_0; // fence
else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0; // fence treated as nop
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0_0; // fence treated as nop
end else if (CMOFunctD) begin
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1_0; // CMO Instruction
end
7'b0010011: if (IFunctD)
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0_0; // I-type ALU
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0_0; // auipc
7'b0011011: if (IFunctD & IWValidFunct3D & P.XLEN == 64)
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0_0; // IW-type ALU for RV64i
7'b0100011: if (SFunctD)
ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // stores
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_1; // fsw - only legal if FP supported
7'b0101111: if (P.A_SUPPORTED) begin
if (InstrD[31:27] == 5'b00010)
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr
ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0_0; // stores
7'b0100111: if (FLSFunctD)
ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0_1; // fsw - only legal if FP supported
7'b0101111: if (P.A_SUPPORTED & AFunctD) begin
if (InstrD[31:27] == 5'b00010 & Rs2D == 5'b0)
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0_0; // lr
else if (InstrD[31:27] == 5'b00011)
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc
else
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0; // amo
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0_0; // sc
else if (AMOFunctD)
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0_0; // amo
end
7'b0110011: if (RFunctD)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0_0; // R-type
else if (MFunctD)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
7'b0111011: if (RFunctD & (P.XLEN == 64))
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
else if (MFunctD & (P.XLEN == 64))
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0_0; // Multiply/divide
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0_0; // lui
7'b0111011: if (RWFunctD)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0_0; // R-type W instructions for RV64i
else if (MWFunctD)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0_0; // W-type Multiply/Divide
7'b1100011: if (BFunctD)
ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
7'b1100111: if (JFunctD)
ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0_0; // branches
7'b1100111: if (JRFunctD)
ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0_0; // jalr
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0_0; // jal
7'b1110011: if (P.ZICSR_SUPPORTED) begin
if (Funct3D == 3'b000)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
else
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
if (PFunctD)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0_0; // privileged; decoded further in privdec modules
else if (CSRFunctD)
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0_0; // csrs
end
endcase
end
@ -230,9 +287,9 @@ module controller import cvw::*; #(parameter cvw_t P) (
// On RV32E, can't write to upper 16 registers. Checking reads to upper 16 is more costly so disregard them.
assign IllegalERegAdrD = P.E_SUPPORTED & P.ZICSR_SUPPORTED & ControlsD[`CTRLW-1] & InstrD[11];
//assign IllegalBaseInstrD = 1'b0;
assign {BaseRegWriteD, ImmSrcD, ALUSrcAD, BaseALUSrcBD, MemRWD,
assign {BaseRegWriteD, PreImmSrcD, ALUSrcAD, BaseALUSrcBD, MemRWD,
ResultSrcD, BranchD, ALUOpD, JumpD, ALUResultSrcD, BaseW64D, CSRReadD,
PrivilegedD, FenceXD, MDUD, AtomicD, unused} = IllegalIEUFPUInstrD ? `CTRLW'b0 : ControlsD;
PrivilegedD, FenceXD, MDUD, AtomicD, CMOD, unused} = IllegalIEUFPUInstrD ? `CTRLW'b0 : ControlsD;
assign CSRZeroSrcD = InstrD[14] ? (InstrD[19:15] == 0) : (Rs1D == 0); // Is a CSR instruction using zero as the source?
assign CSRWriteD = CSRReadD & !(CSRZeroSrcD & InstrD[13]); // Don't write if setting or clearing zeros
@ -300,13 +357,41 @@ module controller import cvw::*; #(parameter cvw_t P) (
assign FlushDCacheD = 0;
end
// Cache Management instructions
always_comb begin
CMOpD = 4'b0000; // default: not a cbo instruction
if ((P.ZICBOM_SUPPORTED | P.ZICBOZ_SUPPORTED) & CMOD) begin
CMOpD[3] = (InstrD[31:20] == 12'd4); // cbo.zero
CMOpD[2] = (InstrD[31:20] == 12'd2); // cbo.clean
CMOpD[1] = (InstrD[31:20] == 12'd1) | ((InstrD[31:20] == 12'd0) & (ENVCFG_CBE[1:0] == 2'b01)); // cbo.flush
CMOpD[0] = (InstrD[31:20] == 12'd0) & (ENVCFG_CBE[1:0] == 2'b11); // cbo.inval
end
end
// Prefetch Hints
always_comb begin
// default: not a prefetch hint
IFUPrefetchD = 1'b0;
LSUPrefetchD = 1'b0;
ImmSrcD = PreImmSrcD;
if (P.ZICBOP_SUPPORTED & (InstrD[14:0] == 15'b110_00000_0010011)) begin // ori with destiation x0 is hint for Prefetch
case (Rs2D) // which type of prefectch? Note: prefetch.r and .w are handled the same in Wally
5'b00000: IFUPrefetchD = 1'b1; // prefetch.i
5'b00001: LSUPrefetchD = 1'b1; // prefetch.r
5'b00011: LSUPrefetchD = 1'b1; // prefetch.w
// default: not a prefetch hint
endcase
if (IFUPrefetchD | LSUPrefetchD) ImmSrcD = 3'b001; // use S-type immediate format for prefetches
end
end
// Decode stage pipeline control register
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD);
// Execute stage pipeline control register and logic
flopenrc #(29) controlregE(clk, reset, FlushE, ~StallE,
{ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, InstrValidD},
{ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE});
flopenrc #(35) controlregE(clk, reset, FlushE, ~StallE,
{ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, CMOpD, IFUPrefetchD, LSUPrefetchD, InstrValidD},
{ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, CMOpE, IFUPrefetchE, LSUPrefetchE, InstrValidE});
// Branch Logic
// The comparator handles both signed and unsigned branches using BranchSignedE
@ -325,9 +410,9 @@ module controller import cvw::*; #(parameter cvw_t P) (
assign IntDivE = MDUE & Funct3E[2]; // Integer division operation
// Memory stage pipeline control register
flopenrc #(20) controlregM(clk, reset, FlushM, ~StallM,
{RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, IntDivE},
{RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM});
flopenrc #(25) controlregM(clk, reset, FlushM, ~StallM,
{RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, IntDivE, CMOpE, LSUPrefetchE},
{RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM, CMOpM, LSUPrefetchM});
// Writeback stage pipeline control register
flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW,

View File

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

View File

@ -27,28 +27,29 @@
// 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 [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
case (ImmSrcD)
// I-type
3'b000: ImmExtD = {{(XLEN-12){InstrD[31]}}, InstrD[31:20]};
3'b000: ImmExtD = {{(P.XLEN-12){InstrD[31]}}, InstrD[31:20]};
// S-type (stores)
3'b001: ImmExtD = {{(XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
3'b001: ImmExtD = {{(P.XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
// B-type (branches)
3'b010: ImmExtD = {{(XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
3'b010: ImmExtD = {{(P.XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
// J-type (jal)
3'b011: ImmExtD = {{(XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
3'b011: ImmExtD = {{(P.XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
// U-type (lui, auipc)
3'b100: ImmExtD = {{(XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
3'b100: ImmExtD = {{(P.XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
// Store Conditional: zero offset
3'b101: if (A_SUPPORTED) ImmExtD = 0;
3'b101: if (P.A_SUPPORTED) ImmExtD = 0;
else ImmExtD = undefined;
default: ImmExtD = undefined; // undefined
endcase
endmodule

View File

@ -30,6 +30,8 @@ module ieu import cvw::*; #(parameter cvw_t P) (
input logic clk, reset,
// Decode stage signals
input logic [31:0] InstrD, // Instruction
input logic [1:0] STATUS_FS, // is FPU enabled?
input logic [3:0] ENVCFG_CBE, // Cache block operation enables
input logic IllegalIEUFPUInstrD, // Illegal instruction
output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
// Execute stage signals
@ -43,6 +45,9 @@ module ieu import cvw::*; #(parameter cvw_t P) (
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU src inputs before the mux choosing between them and PCE to put in srcA/B
output logic [4:0] RdE, // Destination register
output logic MDUActiveE, // Mul/Div instruction being executed
output logic [3:0] CMOpM, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
output logic IFUPrefetchE, // instruction prefetch
output logic LSUPrefetchM, // datata prefetch
// Memory stage signals
input logic SquashSCW, // Squash store conditional, from LSU
output logic [1:0] MemRWM, // Read/write control goes to LSU
@ -97,11 +102,11 @@ module ieu import cvw::*; #(parameter cvw_t P) (
logic BMUActiveE; // Bit manipulation instruction being executed
controller #(P) c(
.clk, .reset, .StallD, .FlushD, .InstrD, .ImmSrcD,
.clk, .reset, .StallD, .FlushD, .InstrD, .STATUS_FS, .ENVCFG_CBE, .ImmSrcD,
.IllegalIEUFPUInstrD, .IllegalBaseInstrD, .StallE, .FlushE, .FlagsE, .FWriteIntE,
.PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .MemReadE, .CSRReadE,
.Funct3E, .IntDivE, .MDUE, .W64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE, .SCE,
.BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .MDUActiveE,
.BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .MDUActiveE, .CMOpM, .IFUPrefetchE, .LSUPrefetchM,
.StallM, .FlushM, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M,
.RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM,
.StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .InvalidateICacheM, .StoreStallD);

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 [1:0] AtomicM, // Atomic memory operation
input logic FlushDCacheM, // Flush D cache to next level of memory
input logic [3:0] CMOpM, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
input logic LSUPrefetchM, // Prefetch
output logic CommittedM, // Delay interrupts while memory operation in flight
output logic SquashSCW, // Store conditional failed disable write to GPR
output logic DCacheMiss, // D cache miss for performance counters
@ -260,6 +262,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '0;
assign FlushDCache = FlushDCacheM & ~(IgnoreRequestTLB | SelHPTW);
// *** need RT to add support for CMOpM and LSUPrefetchM (DH 7/2/23)
// *** prefetch can just act as a read operation
cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.DCACHE_LINELENINBITS), .NUMLINES(P.DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(P.DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(P.LLEN), .MUXINTERVAL(P.LLEN), .READ_ONLY_CACHE(0)) dcache(
.clk, .reset, .Stall(GatedStallW), .SelBusBeat, .FlushStage(FlushW), .CacheRW(CacheRWM), .CacheAtomic(CacheAtomicM),

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 [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
output logic [2:0] FRM_REGW,
output logic [3:0] ENVCFG_CBE,
//
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns
@ -123,7 +124,11 @@ module csr import cvw::*; #(parameter cvw_t P) (
logic [P.XLEN-1:0] TVecAlignedM;
logic InstrValidNotFlushedM;
logic STimerInt;
logic MENVCFG_STCE;
logic [63:0] MENVCFG_REGW;
logic [P.XLEN-1:0] SENVCFG_REGW;
logic ENVCFG_STCE; // supervisor timer counter enable
logic ENVCFG_PBMTE; // page-based memory types enable
logic ENVCFG_FIOM; // fence implies io (presently not used)
// only valid unflushed instructions can access CSRs
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
@ -214,7 +219,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
csri #(P) csri(.clk, .reset,
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt,
.MIDELEG_REGW, .MENVCFG_STCE, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
.MIDELEG_REGW, .ENVCFG_STCE, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
csrsr #(P) csrsr(.clk, .reset, .StallW,
.WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM,
@ -233,10 +238,12 @@ module csr import cvw::*; #(parameter cvw_t P) (
.MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM,
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM,
.MENVCFG_STCE);
.MENVCFG_REGW);
if (P.S_SUPPORTED) begin:csrs
logic STCE;
assign STCE = P.SSTC_SUPPORTED & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_REGW[1] & ENVCFG_STCE));
csrs #(P) csrs(.clk, .reset,
.CSRSWriteM, .STrapM, .CSRAdrM,
.NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW,
@ -244,8 +251,8 @@ module csr import cvw::*; #(parameter cvw_t P) (
.CSRWriteValM, .PrivilegeModeW,
.CSRSReadValM, .STVEC_REGW, .SEPC_REGW,
.SCOUNTEREN_REGW,
.SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .MENVCFG_STCE,
.WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt);
.SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .STCE,
.WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt, .SENVCFG_REGW);
end else begin
assign WriteSSTATUSM = 0;
assign CSRSReadValM = 0;
@ -282,6 +289,17 @@ module csr import cvw::*; #(parameter cvw_t P) (
assign IllegalCSRCAccessM = 1; // counters aren't enabled
end
// Broadcast appropriate environment configuration based on privilege mode
assign ENVCFG_STCE = MENVCFG_REGW[63]; // supervisor timer counter enable
assign ENVCFG_PBMTE = MENVCFG_REGW[62]; // page-based memory types enable
assign ENVCFG_CBE = (PrivilegeModeW == P.M_MODE) ? 4'b1111 :
(PrivilegeModeW == P.S_MODE | !P.S_SUPPORTED) ? MENVCFG_REGW[7:4] :
(MENVCFG_REGW[7:4] & SENVCFG_REGW[7:4]);
// FIOM presently doesn't do anything because Wally fences don't do anything
assign ENVCFG_FIOM = (PrivilegeModeW == P.M_MODE) ? 1'b1 :
(PrivilegeModeW == P.S_MODE | !P.S_SUPPORTED) ? MENVCFG_REGW[0] :
(MENVCFG_REGW[0] & SENVCFG_REGW[0]);
// merge CSR Reads
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM;
flopenrc #(P.XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);

View File

@ -34,7 +34,7 @@ module csri import cvw::*; #(parameter cvw_t P) (
input logic [11:0] CSRAdrM,
input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt,
input logic [11:0] MIDELEG_REGW,
input logic MENVCFG_STCE,
input logic ENVCFG_STCE,
output logic [11:0] MIP_REGW, MIE_REGW,
output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0
);
@ -61,7 +61,7 @@ module csri import cvw::*; #(parameter cvw_t P) (
if (P.S_SUPPORTED) begin:mask
if (P.SSTC_SUPPORTED) begin
assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec)
assign STIP = MENVCFG_STCE ? STimerInt : MIP_REGW_writeable[5];
assign STIP = ENVCFG_STCE ? STimerInt : MIP_REGW_writeable[5];
end else begin
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9)
assign STIP = MIP_REGW_writeable[5];

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 logic WriteMSTATUSM, WriteMSTATUSHM,
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM,
output logic MENVCFG_STCE
output logic [63:0] MENVCFG_REGW
);
logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW;
logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW;
logic [63:0] MENVCFG_REGW;
logic [P.XLEN-1:0] MENVCFGH_REGW;
logic [63:0] MENVCFG_PreWriteValM, MENVCFG_WriteValM;
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
@ -193,15 +192,6 @@ module csrm import cvw::*; #(parameter cvw_t P) (
assign MENVCFGH_REGW = MENVCFG_REGW[63:32];
end
// Extract bit fields
assign MENVCFG_STCE = MENVCFG_REGW[63];
// Uncomment these other fields when they are defined
// assign MENVCFG_PBMTE = MENVCFG_REGW[62];
// assign MENVCFG_CBZE = MENVCFG_REGW[7];
// assign MENVCFG_CBCFE = MENVCFG_REGW[6];
// assign MENVCFG_CBIE = MENVCFG_REGW[5:4];
// assign MENVCFG_FIOM = MENVCFG_REGW[0];
// Read machine mode CSRs
// verilator lint_off WIDTH
logic [5:0] entry;

View File

@ -44,10 +44,12 @@ module csrs import cvw::*; #(parameter cvw_t P) (
output logic [P.XLEN-1:0] SATP_REGW,
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
input logic [63:0] MTIME_CLINT,
input logic MENVCFG_STCE,
input logic STCE,
output logic WriteSSTATUSM,
output logic IllegalCSRSAccessM,
output logic STimerInt
output logic STimerInt,
output logic [P.XLEN-1:0] SENVCFG_REGW
);
// Supervisor CSRs
@ -75,7 +77,6 @@ module csrs import cvw::*; #(parameter cvw_t P) (
logic WriteSENVCFGM;
logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW;
logic [P.XLEN-1:0] SENVCFG_REGW;
logic [P.XLEN-1:0] SENVCFG_WriteValM;
logic [63:0] STIMECMP_REGW;
@ -90,8 +91,8 @@ module csrs import cvw::*; #(parameter cvw_t P) (
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG);
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE));
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)) & (P.XLEN == 32);
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & STCE;
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & STCE & (P.XLEN == 32);
// CSRs
flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
@ -125,19 +126,11 @@ module csrs import cvw::*; #(parameter cvw_t P) (
CSRWriteValM[7] & P.ZICBOZ_SUPPORTED,
CSRWriteValM[6:4] & {3{P.ZICBOM_SUPPORTED}},
3'b0,
CSRWriteValM[0] & P.S_SUPPORTED & P.VIRTMEM_SUPPORTED
CSRWriteValM[0] & P.VIRTMEM_SUPPORTED
};
flopenr #(P.XLEN) SENVCFGreg(clk, reset, WriteSENVCFGM, SENVCFG_WriteValM, SENVCFG_REGW);
// Extract bit fields
// Uncomment these other fields when they are defined
// assign SENVCFG_PBMTE = SENVCFG_REGW[62];
// assign SENVCFG_CBZE = SENVCFG_REGW[7];
// assign SENVCFG_CBCFE = SENVCFG_REGW[6];
// assign SENVCFG_CBIE = SENVCFG_REGW[5:4];
// assign SENVCFG_FIOM = SENVCFG_REGW[0];
// CSR Reads
always_comb begin:csrr
IllegalCSRSAccessM = 0;
@ -157,13 +150,13 @@ module csrs import cvw::*; #(parameter cvw_t P) (
end
SCOUNTEREN:CSRSReadValM = {{(P.XLEN-32){1'b0}}, SCOUNTEREN_REGW};
SENVCFG: CSRSReadValM = SENVCFG_REGW;
STIMECMP: if (P.SSTC_SUPPORTED & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM && MENVCFG_STCE)))
STIMECMP: if (STCE)
CSRSReadValM = STIMECMP_REGW[P.XLEN-1:0];
else begin
CSRSReadValM = 0;
IllegalCSRSAccessM = 1;
end
STIMECMPH: if (P.SSTC_SUPPORTED & (P.XLEN == 32) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM && MENVCFG_STCE)))
STIMECMPH: if (STCE)
CSRSReadValM[31:0] = STIMECMP_REGW[63:32];
else begin // not supported for RV64
CSRSReadValM = 0;

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 [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU
output logic [2:0] FRM_REGW, // FPU rounding mode
output logic [3:0] ENVCFG_CBE, // Cache block operation enables
// PC logic output in privileged unit
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
// control outputs
@ -136,7 +137,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
.STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS,
.MEDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW,
.SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.SetFflagsM, .FRM_REGW,
.SetFflagsM, .FRM_REGW, .ENVCFG_CBE,
.CSRReadValW,.UnalignedPCNextF, .IllegalCSRAccessM, .BigEndianM);
// pipeline early-arriving trap sources

View File

@ -78,6 +78,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD;
logic SquashSCW;
logic MDUActiveE; // Mul/Div instruction being executed
logic [3:0] ENVCFG_CBE; // Cache Block operation enables
logic [3:0] CMOpM; // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
logic IFUPrefetchE, LSUPrefetchM; // instruction / data prefetch hints
// floating point unit signals
logic [2:0] FRM_REGW;
@ -188,10 +191,10 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
// integer execution unit: integer register file, datapath and controller
ieu #(P) ieu(.clk, .reset,
// Decode Stage interface
.InstrD, .IllegalIEUFPUInstrD, .IllegalBaseInstrD,
.InstrD, .STATUS_FS, .ENVCFG_CBE, .IllegalIEUFPUInstrD, .IllegalBaseInstrD,
// Execute Stage interface
.PCE, .PCLinkE, .FWriteIntE, .FCvtIntE, .IEUAdrE, .IntDivE, .W64E,
.Funct3E, .ForwardedSrcAE, .ForwardedSrcBE, .MDUActiveE,
.Funct3E, .ForwardedSrcAE, .ForwardedSrcBE, .MDUActiveE, .CMOpM, .IFUPrefetchE, .LSUPrefetchM,
// Memory stage interface
.SquashSCW, // from LSU
.MemRWM, // read/write control goes to LSU
@ -215,7 +218,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.MemRWM, .Funct3M, .Funct7M(InstrM[31:25]), .AtomicM,
.CommittedM, .DCacheMiss, .DCacheAccess, .SquashSCW,
.FpLoadStoreM, .FWriteDataM, .IEUAdrE, .IEUAdrM, .WriteDataM,
.ReadDataW, .FlushDCacheM,
.ReadDataW, .FlushDCacheM, .CMOpM, .LSUPrefetchM,
// connected to ahb (all stay the same)
.LSUHADDR, .HRDATA, .LSUHWDATA, .LSUHWSTRB, .LSUHSIZE,
.LSUHBURST, .LSUHTRANS, .LSUHWRITE, .LSUHREADY,
@ -291,7 +294,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.PrivilegeModeW, .SATP_REGW,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM);
.FRM_REGW, .ENVCFG_CBE, .BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM);
end else begin
assign CSRReadValW = 0;
assign UnalignedPCNextF = PC2NextF;

View File

@ -30,13 +30,14 @@ module instrNameDecTB(
logic [2:0] funct3;
logic [6:0] funct7;
logic [11:0] imm;
logic [4:0] rs2;
logic [4:0] rs2, rd;
assign op = instr[6:0];
assign funct3 = instr[14:12];
assign funct7 = instr[31:25];
assign imm = instr[31:20];
assign rs2 = instr[24:20];
assign rd = instr[11:7];
// it would be nice to add the operands to the name
// create another variable called decoded
@ -77,7 +78,10 @@ module instrNameDecTB(
else if (funct7[6:1] == 6'b010010) name = "BEXTI";
else if (funct7 == 7'b0010100 & rs2 == 5'b00111) name = "ORC.B";
else name = "ILLEGAL";
10'b0010011_110: name = "ORI";
10'b0010011_110: if (rd == 0 & rs2 == 0) name = "PREFETCH.I";
else if (rd == 0 & rs2 == 1) name = "PREFETCH.R";
else if (rd == 0 & rs2 == 3) name = "PREFETCH.W";
else name = "ORI";
10'b0010011_111: name = "ANDI";
10'b0010111_???: name = "AUIPC";
10'b0100011_000: name = "SB";
@ -215,7 +219,13 @@ module instrNameDecTB(
else if (funct7[6:2] == 5'b11000) name = "AMOMINU.D";
else if (funct7[6:2] == 5'b11100) name = "AMOMAXU.D";
else name = "ILLEGAL";
10'b0001111_???: name = "FENCE";
10'b0001111_000: name = "FENCE";
10'b0001111_001: name = "FENCE.I";
10'b0001111_010: if (instr[31:20] == 12'd0) name = "CBO.INVAL";
else if (instr[31:20] == 12'd1) name = "CBO.CLEAN";
else if (instr[31:20] == 12'd2) name = "CBO.FLUSH";
else if (instr[31:20] == 12'd4) name = "CBO.ZERO";
else name = "ILLEGAL";
10'b1000011_???: name = "FMADD";
10'b1000111_???: name = "FMSUB";
10'b1001011_???: name = "FNMSUB";

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.ZICNTR_SUPPORTED == 0) || (P.ZICSR_SUPPORTED == 1)) else $error("ZICNTR_SUPPORTED requires ZICSR_SUPPORTED");
assert ((P.ZIHPM_SUPPORTED == 0) || (P.ZICNTR_SUPPORTED == 1)) else $error("ZIPHM_SUPPORTED requires ZICNTR_SUPPORTED");
assert ((P.ZICBOM_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOM required DCACHE_SUPPORTED");
assert ((P.ZICBOZ_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOZ required DCACHE_SUPPORTED");
assert ((P.ZICBOP_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOP required DCACHE_SUPPORTED");
end
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -409,7 +409,20 @@ module testbench;
// Support logic
////////////////////////////////////////////////////////////////////////////////
// Track names of instructions
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW);
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
dut.core.ifu.InstrRawF[31:0],
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
dut.core.ifu.InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// watch for problems such as lockup, reading unitialized memory, bad configs
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM,
dut.core.ifu.PCM, dut.core.ifu.InstrM, dut.core.lsu.IEUAdrM, InstrMName);
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
@ -420,15 +433,6 @@ module testbench;
.clk(clk), .ProgramAddrMapFile(ProgramAddrMapFile), .ProgramLabelMapFile(ProgramLabelMapFile));
end
// Track names of instructions
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW);
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
dut.core.ifu.InstrRawF[31:0],
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
dut.core.ifu.InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// Termination condition
// terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed

View File

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

View File

@ -1,7 +1,7 @@
#! /usr/bin/python3
# author: Alessandro Maiuolo
# contact: amaiuolo@g.hmc.edu
# author: Alessandro Maiuolo, Kevin Kim
# contact: amaiuolo@g.hmc.edu, kekim@hmc.edu
# date created: 3-29-2023
# extract all arch test vectors
@ -77,7 +77,7 @@ def create_vectors(my_config):
rounding_mode = "X"
flags = "XX"
# use name to create our new tv
dest_file = open("{}cvw_{}_{}.tv".format(dest_dir, my_config.bits, vector1[:-2]), 'a')
dest_file = open("{}cvw_{}_{}.tv".format(dest_dir, my_config.bits, vector1[:-2]), 'w')
# open vectors
src_file1 = open(source_dir1 + vector1,'r')
src_file2 = open(source_dir2 + vector2,'r')
@ -179,13 +179,56 @@ def create_vectors(my_config):
else:
# print("read false")
reading = False
elif my_config.letter == "M" and my_config.bits == 32:
reading = True
while reading:
# print("trigger 64M")
# get answer from Ref...signature
# answers span two lines and are reversed
answer = src_file2.readline().strip()
print(f"Answer: {answer}")
#print(answer1,answer2)
if not (answer == "6f5ca309"): # if there is still stuff to read
# parse through .S file
detected = False
done = False
op1val = "0"
op2val = "0"
while not (detected or done):
# print("det1")
line = src_file1.readline()
# print(line)
if "op1val" in line:
# print("det2")
# parse line
op1val = line.split("op1val")[1].split("x")[1].split(";")[0]
if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling
op1val = twos_comp(my_config.bits, op1val)
if my_config.op != "fsqrt": # sqrt doesn't have two input vals, unnec here but keeping for later
op2val = line.split("op2val")[1].split("x")[1].strip()
if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there
if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling
op2val = twos_comp(my_config.bits, op2val)
# go to next test in vector
detected = True
elif "RVTEST_CODE_END" in line:
done = True
# ints don't have flags
flags = "XX"
# put it all together
if not done:
translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()), flags.strip(), rounding_mode)
dest_file.write(translation + "\n")
else:
# print("read false")
reading = False
else:
while reading:
# get answer and flags from Ref...signature
answer = src_file2.readline()
# print(answer)
print(answer)
packed = src_file2.readline()[6:]
# print(packed)
print("Packed: ", packed)
if len(packed.strip())>0: # if there is still stuff to read
# print("packed")
# parse through .S file
@ -229,7 +272,7 @@ def create_vectors(my_config):
src_file2.close()
config_list = [
Config(32, "M", "div", "div_", 0),
Config(32, "M", "div", "div-", 0),
Config(32, "F", "fdiv", "fdiv", 1),
Config(32, "F", "fsqrt", "fsqrt", 2),
Config(32, "M", "rem", "rem-", 3),