Merge branch 'main' into Zicclsm

This commit is contained in:
Rose Thompson 2023-11-10 16:15:32 -06:00
commit b74bfbeefd
66 changed files with 2825 additions and 209 deletions

@ -1 +1 @@
Subproject commit 873d16e748ad60023dcdda3926144957c096e31d
Subproject commit 197179fdc9dfeeca821e848f373c897a3fdae86c

View file

@ -119,6 +119,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
localparam SDC_SUPPORTED = 1'b0;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b1;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Bus Interface width
localparam AHBW = 32'd64;
@ -127,6 +130,7 @@ localparam AHBW = 32'd64;
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 0;
localparam SPI_LOOPBACK_TEST = 0;
// Hardware configuration
localparam UART_PRESCALE = 32'd0;
@ -136,6 +140,7 @@ localparam PLIC_NUM_SRC = 32'd53;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd20;
localparam BPRED_SUPPORTED = 1;

View file

@ -136,10 +136,15 @@ localparam SDC_SUPPORTED = 1'b1;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b1;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Test modes
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 0;
localparam SPI_LOOPBACK_TEST = 0;
// Hardware configuration
localparam UART_PRESCALE = 32'd0;
@ -150,6 +155,7 @@ localparam PLIC_NUM_SRC = 32'd53;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd20;
localparam BPRED_SUPPORTED = 1;

View file

@ -120,6 +120,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
localparam SDC_SUPPORTED = 1'b0;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b0;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Bus Interface width
localparam AHBW = 32'd32;
@ -128,6 +131,7 @@ localparam AHBW = 32'd32;
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 1;
localparam SPI_LOOPBACK_TEST = 0;
// Hardware configuration
localparam UART_PRESCALE = 32'd1;
@ -138,6 +142,7 @@ localparam PLIC_NUM_SRC = 32'd10;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd9;
localparam BPRED_SUPPORTED = 0;

View file

@ -121,6 +121,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
localparam SDC_SUPPORTED = 1'b0;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b1;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Bus Interface width
localparam AHBW = 32'd32;
@ -129,6 +132,7 @@ localparam AHBW = 32'd32;
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 1;
localparam SPI_LOOPBACK_TEST = 1;
// Hardware configuration
localparam UART_PRESCALE = 32'd1;
@ -139,6 +143,7 @@ localparam PLIC_NUM_SRC = 32'd10;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd9;
localparam BPRED_SUPPORTED = 1;

View file

@ -120,6 +120,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
localparam SDC_SUPPORTED = 1'b0;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b0;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Bus Interface width
localparam AHBW = 32'd32;
@ -128,6 +131,7 @@ localparam AHBW = 32'd32;
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 1;
localparam SPI_LOOPBACK_TEST = 1;
// Hardware configuration
localparam UART_PRESCALE = 32'd1;
@ -138,6 +142,8 @@ localparam PLIC_NUM_SRC = 32'd10;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd9;
localparam BPRED_SUPPORTED = 0;

View file

@ -119,6 +119,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
localparam SDC_SUPPORTED = 1'b0;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b1;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Bus Interface width
localparam AHBW = 32'd32;
@ -127,6 +130,7 @@ localparam AHBW = 32'd32;
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 1;
localparam SPI_LOOPBACK_TEST = 1;
// Hardware configuration
localparam UART_PRESCALE = 32'd1;
@ -137,6 +141,7 @@ localparam PLIC_NUM_SRC = 32'd10;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd9;
localparam BPRED_SUPPORTED = 0;

View file

@ -125,11 +125,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
localparam SDC_SUPPORTED = 1'b0;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b1;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Test modes
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 1;
localparam SPI_LOOPBACK_TEST = 1;
// Hardware configuration
localparam UART_PRESCALE = 32'd1;
@ -140,6 +144,7 @@ localparam PLIC_NUM_SRC = 32'd10;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd9;
localparam BPRED_SUPPORTED = 1;

View file

@ -125,11 +125,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
localparam SDC_SUPPORTED = 1'b0;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b1;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Test modes
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 1;
localparam SPI_LOOPBACK_TEST = 1;
// Hardware configuration
localparam UART_PRESCALE = 32'd1;
@ -140,6 +144,7 @@ localparam PLIC_NUM_SRC = 32'd10;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd9;
localparam BPRED_SUPPORTED = 1;

View file

@ -125,11 +125,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
localparam SDC_SUPPORTED = 1'b0;
localparam logic [63:0] SDC_BASE = 64'h00013000;
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam SPI_SUPPORTED = 1'b0;
localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
// Test modes
// Tie GPIO outputs back to inputs
localparam GPIO_LOOPBACK_TEST = 1;
localparam SPI_LOOPBACK_TEST = 1;
// Hardware configuration
localparam UART_PRESCALE = 32'd1;
@ -140,6 +144,7 @@ localparam PLIC_NUM_SRC = 32'd10;
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
localparam PLIC_GPIO_ID = 32'd3;
localparam PLIC_UART_ID = 32'd10;
localparam PLIC_SPI_ID = 32'd6;
localparam PLIC_SDC_ID = 32'd9;
localparam BPRED_SUPPORTED = 0;

View file

@ -74,12 +74,17 @@ localparam cvw_t P = '{
SDC_SUPPORTED : SDC_SUPPORTED,
SDC_BASE : SDC_BASE,
SDC_RANGE : SDC_RANGE,
SPI_SUPPORTED : SPI_SUPPORTED,
SPI_BASE : SPI_BASE,
SPI_RANGE : SPI_RANGE,
GPIO_LOOPBACK_TEST : GPIO_LOOPBACK_TEST,
SPI_LOOPBACK_TEST : SPI_LOOPBACK_TEST,
UART_PRESCALE : UART_PRESCALE ,
PLIC_NUM_SRC : PLIC_NUM_SRC,
PLIC_NUM_SRC_LT_32 : PLIC_NUM_SRC_LT_32,
PLIC_GPIO_ID : PLIC_GPIO_ID,
PLIC_UART_ID : PLIC_UART_ID,
PLIC_SPI_ID : PLIC_SPI_ID,
PLIC_SDC_ID : PLIC_SDC_ID,
BPRED_SUPPORTED : BPRED_SUPPORTED,
/* verilator lint_off ENUMVALUE */

View file

@ -6,7 +6,7 @@
echo "Executing Wally setup.csh"
# Path to Wally repository
set WALLY = $PWD
setenv WALLY $PWD
echo '$WALLY set to ' ${WALLY}
# Extend alias which makes extending PATH much easier.

View file

@ -11,16 +11,21 @@
--override refRoot/cpu/tvec_align=64
# bit manipulation
--override cpu/add_implicit_Extensions=B
--override cpu/add_Extensions=B
#--override cpu/add_implicit_Extensions=B
--override cpu/bitmanip_version=1.0.0
# More extensions
--override cpu/Zcb=T
# Cache block operations
--override cpu/Zicbom=T
--override cpu/Zicbop=T
--override cpu/Zicboz=T
--override cpu/Svpbmt=T
# 64 KiB continuous huge pages supported
--override cpu/Svnapot_page_mask=1<<16
--override cpu/Svpbmt=T
--override cpu/Svnapot_page_mask=65536
# clarify
@ -39,10 +44,14 @@
--override cpu/ignore_non_leaf_DAU=1
--override cpu/wfi_is_nop=T
--override cpu/misa_Extensions_mask=0x0
--override cpu/updatePTEA=T
--override cpu/updatePTED=T
--override cpu/Sstc=T
# Enable SVADU hardware update of A/D bits when menvcfg.HADE=1
--override cpu/Svadu=T
--override cpu/updatePTEA=F
--override cpu/updatePTED=F
# THIS NEEDS FIXING to 16
--override cpu/PMP_registers=16
--override cpu/PMP_undefined=T
@ -68,7 +77,8 @@
--callcommand refRoot/cpu/setPMA -lo 0x0002000000 -hi 0x000200FFFF -attributes " rw--A- 1248 " # CLINT
--callcommand refRoot/cpu/setPMA -lo 0x000C000000 -hi 0x000FFFFFFF -attributes " rw--A- --4- " # PLIC
--callcommand refRoot/cpu/setPMA -lo 0x0010000000 -hi 0x0010000007 -attributes " rw--A- 1--- " # UART0 error - 0x10000000 - 0x100000FF
--callcommand refRoot/cpu/setPMA -lo 0x0010060000 -hi 0x00100600FF -attributes " rw--A- --4- " # GPIO error - 0x10006000 - 0x100060FF
--callcommand refRoot/cpu/setPMA -lo 0x0010060000 -hi 0x00100600FF -attributes " rw--A- --4- " # GPIO error - 0x10069000 - 0x100600FF
--callcommand refRoot/cpu/setPMA -lo 0x0010040000 -hi 0x0010040FFF -attributes " rw--A- --4- " # SPI error - 0x10040000 - 0x10040FFF
--callcommand refRoot/cpu/setPMA -lo 0x0080000000 -hi 0x008FFFFFFF -attributes " rwx--- 1248 " # UNCORE_RAM
# Enable the Imperas instruction coverage

View file

@ -1,2 +1,2 @@
vsim -do "do wally.do rv64gc wally64priv"
vsim -do "do wally.do rv64gc wally64periph"

View file

@ -1 +1 @@
vsim -c -do "do wally-batch.do rv64gc wally64priv"
vsim -c -do "do wally-batch.do rv64gc wally64periph"

View file

@ -8,15 +8,9 @@ basepath=$(dirname $0)/..
#for config in rv32e rv64gc rv32gc rv32imc rv32i rv64i rv64fpquad; do
for config in rv64gc; do
echo "$config simulating..."
if !($verilator --timescale "1ns/1ns" --timing --cc "$@" --top-module testbench "-I$basepath/config/shared" "-I$basepath/config/$config" $basepath/src/wally/cvw.sv $basepath/testbench/common/*.sv $basepath/testbench/testbench.sv $basepath/src/*/*.sv $basepath/src/*/*/*.sv --relative-includes ); then
if !($verilator --timescale "1ns/1ns" --timing --exe --cc "$@" --top-module testbench "-I$basepath/config/shared" "-I$basepath/config/$config" $basepath/src/cvw.sv $basepath/testbench/testbench.sv $basepath/testbench/common/*.sv $basepath/src/*/*.sv $basepath/src/*/*/*.sv --relative-includes ); then
echo "Exiting after $config lint due to errors or warnings"
exit 1
fi
done
echo "All lints run with no errors or warnings"
# --lint-only just runs lint rather than trying to compile and simulate
# -I points to the include directory where files such as `include config.vh are found
# For more exhaustive (and sometimes spurious) warnings, add --Wall to the Verilator command
# Unfortunately, this produces a bunch of UNUSED and UNDRIVEN signal warnings in blocks that are configured to not exist.
echo "Verilation complete"

View file

@ -126,7 +126,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
// Tag Array
/////////////////////////////////////////////////////////////////////////////////////////////
ram1p1rwe #(.P(P), .DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn),
ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn),
.addr(CacheSet), .dout(ReadTag),
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
@ -148,12 +148,12 @@ module cacheway import cvw::*; #(parameter cvw_t P,
for(words = 0; words < NUMSRAM; words++) begin: word
if (!READ_ONLY_CACHE) begin:wordram
ram1p1rwbe #(.P(P), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
end else begin:wordram // no byte-enable needed for i$.
ram1p1rwe #(.P(P), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.we(SelectedWriteWordEn));

View file

@ -129,11 +129,15 @@ typedef struct packed {
logic SDC_SUPPORTED;
logic [63:0] SDC_BASE;
logic [63:0] SDC_RANGE;
logic SPI_SUPPORTED;
logic [63:0] SPI_BASE;
logic [63:0] SPI_RANGE;
// Test modes
// Tie GPIO outputs back to inputs
logic GPIO_LOOPBACK_TEST;
logic SPI_LOOPBACK_TEST;
// Hardware configuration
int UART_PRESCALE ;
@ -143,6 +147,7 @@ typedef struct packed {
logic PLIC_NUM_SRC_LT_32;
int PLIC_GPIO_ID;
int PLIC_UART_ID;
int PLIC_SPI_ID;
int PLIC_SDC_ID;
logic BPRED_SUPPORTED;

View file

@ -68,7 +68,7 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
logic BZeroM; // Denominator is zero
logic IntDivM; // Integer operation
logic [P.DIVBLEN:0] nM, mM; // Shift amounts
logic NegQuotM, ALTBM, AsM, W64M; // Special handling for postprocessor
logic ALTBM, AsM, BsM, W64M; // Special handling for postprocessor
logic [P.XLEN-1:0] AM; // Original Numerator for postprocessor
logic ISpecialCaseE; // Integer div/remainder special cases
@ -78,7 +78,7 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
// Int-specific
.ForwardedSrcAE, .ForwardedSrcBE, .IntDivE, .W64E, .ISpecialCaseE,
.BZeroM, .nM, .mM, .AM,
.IntDivM, .W64M, .NegQuotM, .ALTBM, .AsM);
.IntDivM, .W64M, .ALTBM, .AsM, .BsM);
fdivsqrtfsm #(P) fdivsqrtfsm( // FSM
.clk, .reset, .XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE,
@ -96,6 +96,6 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
.SqrtE, .Firstun, .SqrtM, .SpecialCaseM,
.QmM, .WZeroE, .DivStickyM,
// Int-specific
.nM, .mM, .ALTBM, .AsM, .BZeroM, .NegQuotM, .W64M, .RemOpM(Funct3M[1]), .AM,
.nM, .mM, .ALTBM, .AsM, .BsM, .BZeroM, .W64M, .RemOpM(Funct3M[1]), .AM,
.FIntDivResultM);
endmodule

View file

@ -65,7 +65,8 @@ module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) (
endcase
always_comb begin
if (SqrtE) fbits = Nf + 2 + 2; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2
if (SqrtE) fbits = Nf + 2 + 1; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 *** unclear why it works with just +1; is it related to DIVCOPIES logic below?
// if (SqrtE) fbits = Nf + 2 + 2; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2
else fbits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs
if (P.IDIV_ON_FPU) CyclesE = IntDivE ? ((nE + 1)/P.DIVCOPIES) : (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);
else CyclesE = (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);

View file

@ -34,9 +34,9 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
input logic [P.DIVb:0] FirstU, FirstUM,
input logic [P.DIVb+1:0] FirstC,
input logic SqrtE,
input logic Firstun, SqrtM, SpecialCaseM, NegQuotM,
input logic Firstun, SqrtM, SpecialCaseM,
input logic [P.XLEN-1:0] AM,
input logic RemOpM, ALTBM, BZeroM, AsM, W64M,
input logic RemOpM, ALTBM, BZeroM, AsM, BsM, W64M,
input logic [P.DIVBLEN:0] nM, mM,
output logic [P.DIVb:0] QmM,
output logic WZeroE,
@ -49,6 +49,7 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
logic NegStickyM;
logic weq0E, WZeroM;
logic [P.XLEN-1:0] IntDivResultM;
logic NegQuotM; // Integer quotient is negative
//////////////////////////
// Execute Stage: Detect early termination for an exact result
@ -103,6 +104,7 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
assign UnsignedQuotM = {3'b000, PreQmM};
// Integer remainder: sticky and sign correction muxes
assign NegQuotM = AsM ^ BsM; // Integer Quotient is negative
mux2 #(P.DIVb+4) normremdmux(W, W+D, NegStickyM, NormRemDM);
mux2 #(P.DIVb+4) normremsmux(NormRemDM, -NormRemDM, AsM, NormRemM);
mux2 #(P.DIVb+4) quotresmux(UnsignedQuotM, -UnsignedQuotM, NegQuotM, NormQuotM);

View file

@ -43,8 +43,8 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
output logic ISpecialCaseE,
output logic [P.DURLEN-1:0] CyclesE,
output logic [P.DIVBLEN:0] nM, mM,
output logic NegQuotM, ALTBM, IntDivM, W64M,
output logic AsM, BZeroM,
output logic ALTBM, IntDivM, W64M,
output logic AsM, BsM, BZeroM,
output logic [P.XLEN-1:0] AM
);
@ -57,7 +57,6 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
logic NumerZeroE; // Numerator is zero (X or A)
logic AZeroE, BZeroE; // A or B is Zero for integer division
logic SignedDivE; // signed division
logic NegQuotE; // Integer quotient is negative
logic AsE, BsE; // Signs of integer inputs
logic [P.XLEN-1:0] AE; // input A after W64 adjustment
logic ALTBE;
@ -84,7 +83,6 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
assign BZeroE = ~(|BE);
assign AsE = AE[P.XLEN-1] & SignedDivE;
assign BsE = BE[P.XLEN-1] & SignedDivE;
assign NegQuotE = AsE ^ BsE; // Integer Quotient is negative
// Force integer inputs to be postiive
mux2 #(P.XLEN) posamux(AE, -AE, AsE, PosA);
@ -192,9 +190,9 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
// pipeline registers
flopen #(1) mdureg(clk, IFDivStartE, IntDivE, IntDivM);
flopen #(1) altbreg(clk, IFDivStartE, ALTBE, ALTBM);
flopen #(1) negquotreg(clk, IFDivStartE, NegQuotE, NegQuotM);
flopen #(1) bzeroreg(clk, IFDivStartE, BZeroE, BZeroM);
flopen #(1) asignreg(clk, IFDivStartE, AsE, AsM);
flopen #(1) bsignreg(clk, IFDivStartE, BsE, BsM);
flopen #(P.DIVBLEN+1) nreg(clk, IFDivStartE, nE, nM);
flopen #(P.DIVBLEN+1) mreg(clk, IFDivStartE, mE, mM);
flopen #(P.XLEN) srcareg(clk, IFDivStartE, AE, AM);

View file

@ -32,8 +32,7 @@
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=44,
parameter PRELOAD_ENABLED=0) (
module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRELOAD_ENABLED=0) (
input logic clk,
input logic ce,
input logic [$clog2(DEPTH)-1:0] addr,
@ -48,7 +47,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
// ***************************************************************************
// TRUE SRAM macro
// ***************************************************************************
if ((P.USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
if ((USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
genvar index;
// 64 x 128-bit SRAM
logic [WIDTH-1:0] BitWriteMask;
@ -58,7 +57,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
.A(addr), .D(din),
.BWEB(~BitWriteMask), .Q(dout));
end else if ((P.USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
end else if ((USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
genvar index;
// 64 x 44-bit SRAM
logic [WIDTH-1:0] BitWriteMask;
@ -68,7 +67,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
.A(addr), .D(din),
.BWEB(~BitWriteMask), .Q(dout));
end else if ((P.USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
end else if ((USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
genvar index;
// 64 x 22-bit SRAM
logic [WIDTH-1:0] BitWriteMask;

View file

@ -30,8 +30,7 @@
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
module ram1p1rwe import cvw::* ; #(parameter cvw_t P,
parameter DEPTH=64, WIDTH=44) (
module ram1p1rwe import cvw::* ; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44) (
input logic clk,
input logic ce,
input logic [$clog2(DEPTH)-1:0] addr,
@ -45,19 +44,19 @@ module ram1p1rwe import cvw::* ; #(parameter cvw_t P,
// ***************************************************************************
// TRUE SRAM macro
// ***************************************************************************
if ((P.USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
if ((USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
// 64 x 128-bit SRAM
ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din),
.BWEB('0), .Q(dout));
end else if ((P.USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
end else if ((USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
// 64 x 44-bit SRAM
ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din),
.BWEB('0), .Q(dout));
end else if ((P.USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
end else if ((USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
// 64 x 22-bit SRAM
ram1p1rwbe_64x22 sram1 (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din),

View file

@ -31,8 +31,7 @@
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
parameter DEPTH=1024, WIDTH=68) (
module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68) (
input logic clk,
input logic ce1, ce2,
input logic [$clog2(DEPTH)-1:0] ra1,
@ -51,7 +50,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
// TRUE Smem macro
// ***************************************************************************
if ((P.USE_SRAM == 1) & (WIDTH == 68) & (DEPTH == 1024)) begin
if ((USE_SRAM == 1) & (WIDTH == 68) & (DEPTH == 1024)) begin
ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk),
.CEBA(~ce1), .CEBB(~ce2),
@ -63,7 +62,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
.QA(rd1),
.QB());
end else if ((P.USE_SRAM == 1) & (WIDTH == 36) & (DEPTH == 1024)) begin
end else if ((USE_SRAM == 1) & (WIDTH == 36) & (DEPTH == 1024)) begin
ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk),
.CEBA(~ce1), .CEBB(~ce2),
@ -75,7 +74,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
.QA(rd1),
.QB());
end else if ((P.USE_SRAM == 1) & (WIDTH == 2) & (DEPTH == 1024)) begin
end else if ((USE_SRAM == 1) & (WIDTH == 2) & (DEPTH == 1024)) begin
logic [SRAMWIDTH-1:0] SRAMReadData;
logic [SRAMWIDTH-1:0] SRAMWriteData;

View file

@ -25,9 +25,7 @@
// This model actually works correctly with vivado.
module rom1p1r #(parameter ADDR_WIDTH = 8,
parameter DATA_WIDTH = 32,
parameter PRELOAD_ENABLED = 0)
module rom1p1r #(parameter ADDR_WIDTH = 8, DATA_WIDTH = 32, PRELOAD_ENABLED = 0)
(input logic clk,
input logic ce,
input logic [ADDR_WIDTH-1:0] addr,

View file

@ -92,7 +92,7 @@ module btb import cvw::*; #(parameter cvw_t P,
// An optimization may be using a PC relative address.
ram2p1r1wbe #(P, 2**Depth, P.XLEN+4) memory(
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**Depth), .WIDTH(P.XLEN+4)) memory(
.clk, .ce1(~StallF | reset), .ra1(PCNextFIndex), .rd1(TableBTBPredF),
.ce2(~StallW & ~FlushW), .wa2(PCMIndex), .wd2({InstrClassM, IEUAdrM}), .we2(BTBWrongM), .bwe2('1));

View file

@ -84,7 +84,7 @@ module gshare import cvw::*; #(parameter cvw_t P,
assign BPDirPredF = MatchX ? FwdNewDirPredF : TableBPDirPredF;
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF),
.rd1(TableBPDirPredF),

View file

@ -58,7 +58,7 @@ module gsharebasic import cvw::*; #(parameter cvw_t P,
assign IndexM = GHRM;
end
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF),
.rd1(BPDirPredF),

View file

@ -59,7 +59,7 @@ module localaheadbp import cvw::*; #(parameter cvw_t P,
//assign IndexNextF = LHR;
assign IndexM = LHRW;
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallD), .ce2(~StallW & ~FlushW),
.ra1(LHRF),
.rd1(BPDirPredD),
@ -92,7 +92,7 @@ module localaheadbp import cvw::*; #(parameter cvw_t P,
assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]};
assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]};
ram2p1r1wbe #(P, 2**m, k) BHT(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) BHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexLHRNextF),
.rd1(LHRF),

View file

@ -56,7 +56,7 @@ module localbpbasic import cvw::*; #(parameter cvw_t P,
assign IndexNextF = LHR;
assign IndexM = LHRM;
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF),
.rd1(BPDirPredF),

View file

@ -58,7 +58,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
logic SpeculativeFlushedF;
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallD), .ce2(~StallW & ~FlushW),
.ra1(LHRF),
.rd1(BPDirPredD),
@ -89,7 +89,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]};
assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]};
ram2p1r1wbe #(P, 2**m, k) BHT(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) BHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexLHRNextF),
.rd1(LHRCommittedF),
@ -101,7 +101,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
assign IndexLHRD = {PCE[m+1] ^ PCE[1], PCE[m:2]};
assign LHRNextE = BranchD ? {BPDirPredD[1], LHRE[k-1:1]} : LHRE;
// *** replace with a small CAM
ram2p1r1wbe #(P, 2**m, k) SHB(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) SHB(.clk(clk),
.ce1(~StallF), .ce2(~StallE & ~FlushE),
.ra1(IndexLHRNextF),
.rd1(LHRSpeculativeF),

View file

@ -53,7 +53,7 @@ module twoBitPredictor import cvw::*; #(parameter cvw_t P, parameter XLEN,
assign IndexM = {PCM[k+1] ^ PCM[1], PCM[k:2]};
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF),
.rd1(BPDirPredF),

View file

@ -114,10 +114,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
logic [31:0] IROMInstrF; // Instruction from the IROM
logic [31:0] ICacheInstrF; // Instruction from the I$
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
logic CompressedF; // The fetched instruction is compressed
logic CompressedD; // The decoded instruction is compressed
logic CompressedE; // The execution instruction is compressed
logic CompressedM; // The execution instruction is compressed
logic CompressedF, CompressedE; // The fetched instruction is compressed
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
@ -389,31 +386,40 @@ module ifu import cvw::*; #(parameter cvw_t P) (
assign BranchMisalignedFaultE = (IEUAdrE[1] & ~P.COMPRESSED_SUPPORTED) & PCSrcE;
flopenr #(1) InstrMisalignedReg(clk, reset, ~StallM, BranchMisalignedFaultE, InstrMisalignedFaultM);
// Instruction and PC pipeline registers
// Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0.
// Instruction and PC pipeline registers flush to NOP, not zero
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
// InstrM is only needed with CSRs or atomic operations
if (P.ZICSR_SUPPORTED | P.A_SUPPORTED)
if (P.ZICSR_SUPPORTED | P.A_SUPPORTED) begin
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
else assign InstrM = 0;
end else assign InstrM = 0;
// PCM is only needed with CSRs or branch prediction
if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED)
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
else assign PCM = 0;
flopenrc #(1) CompressedDReg(clk, reset, FlushD, ~StallD, CompressedF, CompressedD);
flopenrc #(1) CompressedEReg(clk, reset, FlushE, ~StallE, CompressedD, CompressedE);
assign PCLinkE = PCE + (CompressedE ? 'd2 : 'd4); // 'd4 means 4 but stops Design Compiler complaining about signed to unsigned conversion
// If compressed instructions are supported, increment PCLink by 2 or 4 for a jal. Otherwise, just by 4
if (P.COMPRESSED_SUPPORTED) begin
logic CompressedD; // instruction is compressed
flopenrc #(1) CompressedDReg(clk, reset, FlushD, ~StallD, CompressedF, CompressedD);
flopenrc #(1) CompressedEReg(clk, reset, FlushE, ~StallE, CompressedD, CompressedE);
assign PCLinkE = PCE + (CompressedE ? 'd2 : 'd4); // 'd4 means 4 but stops Design Compiler complaining about signed to unsigned conversion
end else begin
assign CompressedE = 0;
assign PCLinkE = PCE + 'd4;
end
// pipeline original compressed instruction in case it is needed for MTVAL on an illegal instruction exception
if (P.ZICSR_SUPPORTED) begin
if (P.ZICSR_SUPPORTED & P.COMPRESSED_SUPPORTED | 1) begin
logic CompressedM; // instruction is compressed
flopenrc #(16) InstrRawEReg(clk, reset, FlushE, ~StallE, InstrRawD[15:0], InstrRawE);
flopenrc #(16) InstrRawMReg(clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM);
flopenrc #(1) CompressedMReg(clk, reset, FlushM, ~StallM, CompressedE, CompressedM);
mux2 #(32) InstrOrigMux(InstrM, {16'b0, InstrRawM}, CompressedM, InstrOrigM);
end else assign InstrOrigM = 0;
end else
assign InstrOrigM = InstrM;
endmodule

View file

@ -49,6 +49,6 @@ module dtim import cvw::*; #(parameter cvw_t P) (
assign we = MemRWM[0] & ~FlushW; // have to ignore write if Trap.
ram1p1rwbe #(.P(P), .DEPTH(DEPTH), .WIDTH(P.LLEN))
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(DEPTH), .WIDTH(P.LLEN))
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
endmodule

View file

@ -32,23 +32,24 @@ module adrdecs import cvw::*; #(parameter cvw_t P) (
input logic [P.PA_BITS-1:0] PhysicalAddress,
input logic AccessRW, AccessRX, AccessRWX,
input logic [1:0] Size,
output logic [10:0] SelRegions
output logic [11:0] SelRegions
);
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
// Determine which region of physical memory (if any) is being accessed
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[10]);
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[9]);
adrdec #(P.PA_BITS) ddr4dec(PhysicalAddress, P.EXT_MEM_BASE[P.PA_BITS-1:0], P.EXT_MEM_RANGE[P.PA_BITS-1:0], P.EXT_MEM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[8]);
adrdec #(P.PA_BITS) bootromdec(PhysicalAddress, P.BOOTROM_BASE[P.PA_BITS-1:0], P.BOOTROM_RANGE[P.PA_BITS-1:0], P.BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[7]);
adrdec #(P.PA_BITS) uncoreramdec(PhysicalAddress, P.UNCORE_RAM_BASE[P.PA_BITS-1:0], P.UNCORE_RAM_RANGE[P.PA_BITS-1:0], P.UNCORE_RAM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[6]);
adrdec #(P.PA_BITS) clintdec(PhysicalAddress, P.CLINT_BASE[P.PA_BITS-1:0], P.CLINT_RANGE[P.PA_BITS-1:0], P.CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[5]);
adrdec #(P.PA_BITS) gpiodec(PhysicalAddress, P.GPIO_BASE[P.PA_BITS-1:0], P.GPIO_RANGE[P.PA_BITS-1:0], P.GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[4]);
adrdec #(P.PA_BITS) uartdec(PhysicalAddress, P.UART_BASE[P.PA_BITS-1:0], P.UART_RANGE[P.PA_BITS-1:0], P.UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[3]);
adrdec #(P.PA_BITS) plicdec(PhysicalAddress, P.PLIC_BASE[P.PA_BITS-1:0], P.PLIC_RANGE[P.PA_BITS-1:0], P.PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[2]);
adrdec #(P.PA_BITS) sdcdec(PhysicalAddress, P.SDC_BASE[P.PA_BITS-1:0], P.SDC_RANGE[P.PA_BITS-1:0], P.SDC_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[1]);
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[11]);
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[10]);
adrdec #(P.PA_BITS) ddr4dec(PhysicalAddress, P.EXT_MEM_BASE[P.PA_BITS-1:0], P.EXT_MEM_RANGE[P.PA_BITS-1:0], P.EXT_MEM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[9]);
adrdec #(P.PA_BITS) bootromdec(PhysicalAddress, P.BOOTROM_BASE[P.PA_BITS-1:0], P.BOOTROM_RANGE[P.PA_BITS-1:0], P.BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[8]);
adrdec #(P.PA_BITS) uncoreramdec(PhysicalAddress, P.UNCORE_RAM_BASE[P.PA_BITS-1:0], P.UNCORE_RAM_RANGE[P.PA_BITS-1:0], P.UNCORE_RAM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[7]);
adrdec #(P.PA_BITS) clintdec(PhysicalAddress, P.CLINT_BASE[P.PA_BITS-1:0], P.CLINT_RANGE[P.PA_BITS-1:0], P.CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[6]);
adrdec #(P.PA_BITS) gpiodec(PhysicalAddress, P.GPIO_BASE[P.PA_BITS-1:0], P.GPIO_RANGE[P.PA_BITS-1:0], P.GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[5]);
adrdec #(P.PA_BITS) uartdec(PhysicalAddress, P.UART_BASE[P.PA_BITS-1:0], P.UART_RANGE[P.PA_BITS-1:0], P.UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[4]);
adrdec #(P.PA_BITS) plicdec(PhysicalAddress, P.PLIC_BASE[P.PA_BITS-1:0], P.PLIC_RANGE[P.PA_BITS-1:0], P.PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[3]);
adrdec #(P.PA_BITS) sdcdec(PhysicalAddress, P.SDC_BASE[P.PA_BITS-1:0], P.SDC_RANGE[P.PA_BITS-1:0], P.SDC_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE & 4'b1100, SelRegions[2]);
adrdec #(P.PA_BITS) spidec(PhysicalAddress, P.SPI_BASE[P.PA_BITS-1:0], P.SPI_RANGE[P.PA_BITS-1:0], P.SPI_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[1]);
assign SelRegions[0] = ~|(SelRegions[10:1]); // none of the regions are selected
assign SelRegions[0] = ~|(SelRegions[11:1]); // none of the regions are selected
endmodule
// verilator lint_on UNOPTFLAT

View file

@ -44,7 +44,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
logic PMAAccessFault;
logic AccessRW, AccessRWX, AccessRX;
logic [10:0] SelRegions;
logic [11:0] SelRegions;
logic AtomicAllowed;
logic CacheableRegion, IdempotentRegion;
@ -57,18 +57,18 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
// Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable
assign CacheableRegion = SelRegions[8] | SelRegions[7] | SelRegions[6]; // exclusion-tag: unused-cachable
assign CacheableRegion = SelRegions[9] | SelRegions[8] | SelRegions[7]; // exclusion-tag: unused-cachable
assign Cacheable = (PBMemoryType == 2'b00) ? CacheableRegion : 0;
// Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly
// I/O is nonidempotent. PBMT can override PMA; NC is idempotent and IO is non-idempotent
assign IdempotentRegion = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7] | SelRegions[6]; // exclusion-tag: unused-idempotent
assign IdempotentRegion = SelRegions[11] | SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7]; // exclusion-tag: unused-idempotent
assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01);
// Atomic operations are only allowed on RAM
assign AtomicAllowed = SelRegions[10] | SelRegions[8] | SelRegions[6]; // exclusion-tag: unused-atomic
assign AtomicAllowed = SelRegions[11] | SelRegions[9] | SelRegions[7]; // exclusion-tag: unused-idempotent
// Check if tightly integrated memories are selected
assign SelTIM = SelRegions[10] | SelRegions[9]; // exclusion-tag: unused-tim
assign SelTIM = SelRegions[11] | SelRegions[10]; // exclusion-tag: unused-idempotent
// Detect access faults
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;

View file

@ -49,7 +49,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
input logic PENABLE,
output logic [P.XLEN-1:0] PRDATA,
output logic PREADY,
input logic UARTIntr,GPIOIntr,SDCIntr,
input logic UARTIntr,GPIOIntr, SPIIntr, SDCIntr,
output logic MExtInt, SExtInt
);
@ -156,6 +156,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
requests = {P.PLIC_NUM_SRC{1'b0}};
if(P.PLIC_GPIO_ID != 0) requests[P.PLIC_GPIO_ID] = GPIOIntr;
if(P.PLIC_UART_ID != 0) requests[P.PLIC_UART_ID] = UARTIntr;
if(P.PLIC_SPI_ID != 0) requests[P.PLIC_SPI_ID] = SPIIntr;
if(P.PLIC_SDC_ID !=0) requests[P.PLIC_SDC_ID] = SDCIntr;
end

View file

@ -71,7 +71,7 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
mux2 #(P.PA_BITS) adrmux(HADDR, HADDRD, memwriteD | ~HREADY, RamAddr);
// single-ported RAM
ram1p1rwbe #(.P(P), .DEPTH(RANGE/8), .WIDTH(P.XLEN), .PRELOAD_ENABLED(P.FPGA)) memory(.clk(HCLK), .ce(1'b1),
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(RANGE/8), .WIDTH(P.XLEN), .PRELOAD_ENABLED(P.FPGA)) memory(.clk(HCLK), .ce(1'b1),
.addr(RamAddr[ADDR_WIDTH+OFFSET-1:OFFSET]), .we(memwriteD), .din(HWDATA), .bwe(HWSTRB), .dout(HREADRam));
// use this to add arbitrary latency to ram. Helps test AHB controller correctness

500
src/uncore/spi_apb.sv Normal file
View file

@ -0,0 +1,500 @@
///////////////////////////////////////////
// spi_apb.sv
//
// Written: Naiche Whyte-Aguayo nwhyteaguayo@g.hmc.edu 11/16/2022
//
// Purpose: SPI peripheral
// See FU540-C000-v1.0 for specifications
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021-23 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.
////////////////////////////////////////////////////////////////////////////////////////////////
// Current limitations: Flash read sequencer mode not implemented, dual and quad modes untestable with current test plan.
// Attempt to move from >= comparisons by initializing in FSM differently
// Parameterize SynchFIFO
// look at ReadIncrement/WriteIncrement delay necessity
/*
SPI module is written to the specifications described in FU540-C000-v1.0. At the top level, it is consists of synchronous 8 byte transmit and recieve FIFOs connected to shift registers.
The FIFOs are connected to WALLY by an apb control register interface, which includes various control registers for modifying the SPI transmission along with registers for writing
to the transmit FIFO and reading from the receive FIFO. The transmissions themselves are then controlled by a finite state machine. The SPI module uses 4 tristate pins for SPI input/output,
along with a 4 bit Chip Select signal, a clock signal, and an interrupt signal to WALLY.
*/
module spi_apb import cvw::*; #(parameter cvw_t P) (
input logic PCLK, PRESETn,
input logic PSEL,
input logic [7:0] PADDR,
input logic [P.XLEN-1:0] PWDATA,
input logic [P.XLEN/8-1:0] PSTRB,
input logic PWRITE,
input logic PENABLE,
output logic PREADY,
output logic [P.XLEN-1:0] PRDATA,
output logic SPIOut,
input logic SPIIn,
output logic [3:0] SPICS,
output logic SPIIntr
);
//SPI control registers. Refer to SiFive FU540-C000 manual
logic [11:0] SckDiv;
logic [1:0] SckMode;
logic [1:0] ChipSelectID;
logic [3:0] ChipSelectDef;
logic [1:0] ChipSelectMode;
logic [15:0] Delay0, Delay1;
logic [4:0] Format;
logic [7:0] ReceiveData;
logic [2:0] TransmitWatermark, ReceiveWatermark;
logic [8:0] TransmitData;
logic [1:0] InterruptEnable, InterruptPending;
//Bus interface signals
logic [7:0] Entry;
logic Memwrite;
logic [31:0] Din, Dout;
logic TransmitInactive; //High when there is no transmission, used as hardware interlock signal
//FIFO FSM signals
//Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark;
logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
logic TransmitFIFOReadIncrement;
logic TransmitFIFOWriteIncrement;
logic ReceiveFIFOReadIncrement;
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData;
logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel;
logic [7:0] ReceiveShiftRegEndian; //reverses ReceiveShiftReg if Format[2] set (little endian transmission)
//Transmission signals
logic sck;
logic [11:0] DivCounter; //counter for sck
logic SCLKenable; //flip flop enable high every sclk edge
//Delay signals
logic [8:0] ImplicitDelay1; //Adds implicit delay to cs-sck delay counter based on phase
logic [8:0] ImplicitDelay2; //Adds implicit delay to sck-cs delay counter based on phase
logic [8:0] CS_SCKCount; //Counter for cs-sck delay
logic [8:0] SCK_CSCount; //Counter for sck-cs delay
logic [8:0] InterCSCount; //Counter for inter cs delay
logic [8:0] InterXFRCount; //Counter for inter xfr delay
logic CS_SCKCompare; //Boolean comparison signal, high when CS_SCKCount >= cs-sck delay
logic SCK_CSCompare; //Boolean comparison signal, high when SCK_CSCount >= sck-cs delay
logic InterCSCompare; //Boolean comparison signal, high when InterCSCount >= inter cs delay
logic InterXFRCompare; //Boolean comparison signal, high when InterXFRCount >= inter xfr delay
logic ZeroDelayHoldMode; //High when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
//Frame counting signals
logic [3:0] FrameCount; //Counter for number of frames in transmission
logic FrameCompare; //Boolean comparison signal, high when FrameCount = Format[7:4]
logic [3:0] ReceivePenultimateFrame; //Frame number - 1
logic [3:0] ReceivePenultimateFrameCount; //Counter
logic ReceivePenultimateFrameBoolean; //High when penultimate frame in transmission has been reached
//State fsm signals
logic Active; //High when state is either Active1 or Active0 (during transmission)
logic Active0; //High when state is Active0
//Shift reg signals
logic ShiftEdge; //Determines which edge of sck to shift from TransmitShiftReg
logic [7:0] TransmitShiftReg; //Transmit shift register
logic [7:0] ReceiveShiftReg; //Receive shift register
logic SampleEdge; //Determines which edge of sck to sample from ReceiveShiftReg
logic [7:0] TransmitDataEndian; //Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB
logic TransmitShiftRegLoad; //Determines when to load TransmitShiftReg
logic ReceiveShiftFull; //High when receive shift register is full
logic TransmitShiftEmpty; //High when transmit shift register is empty
logic ShiftIn; //Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST)
logic [3:0] LeftShiftAmount; //Determines left shift amount to left-align data when little endian
logic [7:0] ASR; //AlignedReceiveShiftReg
//CS signals
logic [3:0] ChipSelectAuto; //Assigns ChipSelect value to selected CS signal based on CS ID
logic [3:0] ChipSelectInternal; //Defines what each ChipSelect signal should be based on transmission status and ChipSelectDef
logic DelayMode; //Determines where to place implicit half cycle delay based on sck phase for CS assertion
//Miscellaneous signals delayed/early by 1 PCLK cycle
logic ReceiveShiftFullDelay; //Delays ReceiveShiftFull signal by 1 PCLK cycle
logic TransmitFIFOWriteIncrementDelay; //TransmitFIFOWriteIncrement delayed by 1 PCLK cycle
logic ReceiveShiftFullDelayPCLK; //ReceiveShiftFull delayed by 1 PCLK cycle
logic TransmitFIFOReadEmptyDelay;
logic SCLKenableEarly; //SCLKenable 1 PCLK cycle early, needed for on time register changes when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
//APB access
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
assign Memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
assign PREADY = TransmitInactive; // tie PREADY to transmission for hardware interlock
//Account for subword read/write circuitry
// -- Note SPI registers are 32 bits no matter what; access them with LW SW.
assign Din = PWDATA[31:0];
if (P.XLEN == 64) assign PRDATA = {Dout, Dout};
else assign PRDATA = Dout;
//Register access
always_ff@(posedge PCLK, negedge PRESETn)
if (~PRESETn) begin
SckDiv <= #1 12'd3;
SckMode <= #1 2'b0;
ChipSelectID <= #1 2'b0;
ChipSelectDef <= #1 4'b1111;
ChipSelectMode <= #1 0;
Delay0 <= #1 {8'b1,8'b1};
Delay1 <= #1 {8'b0,8'b1};
Format <= #1 {5'b10000};
TransmitData <= #1 9'b0;
TransmitWatermark <= #1 3'b0;
ReceiveWatermark <= #1 3'b0;
InterruptEnable <= #1 2'b0;
InterruptPending <= #1 2'b0;
end else begin //writes
//According to FU540 spec: Once interrupt is pending, it will remain set until number
//of entries in tx/rx fifo is strictly more/less than tx/rxmark
/* verilator lint_off CASEINCOMPLETE */
if (Memwrite & TransmitInactive)
case(Entry) //flop to sample inputs
8'h00: SckDiv <= Din[11:0];
8'h04: SckMode <= Din[1:0];
8'h10: ChipSelectID <= Din[1:0];
8'h14: ChipSelectDef <= Din[3:0];
8'h18: ChipSelectMode <= Din[1:0];
8'h28: Delay0 <= {Din[23:16], Din[7:0]};
8'h2C: Delay1 <= {Din[23:16], Din[7:0]};
8'h40: Format <= {Din[19:16], Din[2]};
8'h48: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0];
8'h50: TransmitWatermark <= Din[2:0];
8'h54: ReceiveWatermark <= Din[2:0];
8'h70: InterruptEnable <= Din[1:0];
endcase
/* verilator lint_off CASEINCOMPLETE */
//interrupt clearance
InterruptPending[0] <= TransmitReadMark;
InterruptPending[1] <= RecieveWriteMark;
case(Entry) // flop to sample inputs
8'h00: Dout <= #1 {20'b0, SckDiv};
8'h04: Dout <= #1 {30'b0, SckMode};
8'h10: Dout <= #1 {30'b0, ChipSelectID};
8'h14: Dout <= #1 {28'b0, ChipSelectDef};
8'h18: Dout <= #1 {30'b0, ChipSelectMode};
8'h28: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]};
8'h2C: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]};
8'h40: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0};
8'h48: Dout <= #1 {23'b0, TransmitFIFOWriteFull, 8'b0};
8'h4C: Dout <= #1 {23'b0, ReceiveFIFOReadEmpty, ReceiveData[7:0]};
8'h50: Dout <= #1 {29'b0, TransmitWatermark};
8'h54: Dout <= #1 {29'b0, ReceiveWatermark};
8'h70: Dout <= #1 {30'b0, InterruptEnable};
8'h74: Dout <= #1 {30'b0, InterruptPending};
default: Dout <= #1 32'b0;
endcase
end
//SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
//Generates a high signal at the rising and falling edge of SCLK by counting from 0 to SckDiv
assign SCLKenable = (DivCounter == SckDiv);
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) DivCounter <= #1 0;
else if (SCLKenable) DivCounter <= 0;
else DivCounter <= DivCounter + 12'b1;
//Boolean logic that tracks frame progression
assign FrameCompare = (FrameCount < Format[4:1]);
assign ReceivePenultimateFrameBoolean = ((FrameCount + 4'b0001) == Format[4:1]);
//Computing delays
// When sckmode.pha = 0, an extra half-period delay is implicit in the cs-sck delay, and vice-versa for sck-cs
assign ImplicitDelay1 = SckMode[0] ? 9'b0 : 9'b1;
assign ImplicitDelay2 = SckMode[0] ? 9'b1 : 9'b0;
assign CS_SCKCompare = CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1);
assign SCK_CSCompare = SCK_CSCount >= (({Delay0[15:8], 1'b0}) + ImplicitDelay2);
assign InterCSCompare = (InterCSCount >= ({Delay1[7:0],1'b0}));
assign InterXFRCompare = (InterXFRCount >= ({Delay1[15:8], 1'b0}));
//Calculate when tx/rx shift registers are full/empty
TransmitShiftFSM TransmitShiftFSM_1 (PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0, TransmitShiftEmpty);
ReceiveShiftFSM ReceiveShiftFSM_1 (PCLK, PRESETn, SCLKenable, ReceivePenultimateFrameBoolean, SampleEdge, SckMode[0], ReceiveShiftFull);
//Calculate tx/rx fifo write and recieve increment signals
assign TransmitFIFOWriteIncrement = (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) TransmitFIFOWriteIncrementDelay <= 0;
else TransmitFIFOWriteIncrementDelay <= TransmitFIFOWriteIncrement;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
//Tx/Rx FIFOs
SynchFIFO #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
SynchFIFO #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1;
else if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveShiftFullDelay <= 0;
else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveShiftFullDelayPCLK <= 0;
else if (SCLKenableEarly) ReceiveShiftFullDelayPCLK <= ReceiveShiftFull;
assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty));
//Main FSM which controls SPI transmission
typedef enum logic [2:0] {CS_INACTIVE, DELAY_0, ACTIVE_0, ACTIVE_1, DELAY_1,INTER_CS, INTER_XFR} statetype;
statetype state;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) begin state <= CS_INACTIVE;
FrameCount <= 4'b0;
/* verilator lint_off CASEINCOMPLETE */
end else if (SCLKenable) begin
case (state)
CS_INACTIVE: begin
CS_SCKCount <= 9'b1;
SCK_CSCount <= 9'b10;
FrameCount <= 4'b0;
InterCSCount <= 9'b10;
InterXFRCount <= 9'b1;
if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty) & ((|(Delay0[7:0])) | ~SckMode[0])) state <= DELAY_0;
else if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty)) state <= ACTIVE_0;
end
DELAY_0: begin
CS_SCKCount <= CS_SCKCount + 9'b1;
if (CS_SCKCompare) state <= ACTIVE_0;
end
ACTIVE_0: begin
FrameCount <= FrameCount + 4'b1;
state <= ACTIVE_1;
end
ACTIVE_1: begin
InterXFRCount <= 9'b1;
if (FrameCompare) state <= ACTIVE_0;
else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
state <= ACTIVE_0;
CS_SCKCount <= 9'b1;
SCK_CSCount <= 9'b10;
FrameCount <= 4'b0;
InterCSCount <= 9'b10;
end
else if (ChipSelectMode[1:0] == 2'b10) state <= INTER_XFR;
else if (~|(Delay0[15:8]) & (~SckMode[0])) state <= INTER_CS;
else state <= DELAY_1;
end
DELAY_1: begin
SCK_CSCount <= SCK_CSCount + 9'b1;
if (SCK_CSCompare) state <= INTER_CS;
end
INTER_CS: begin
InterCSCount <= InterCSCount + 9'b1;
if (InterCSCompare ) state <= CS_INACTIVE;
end
INTER_XFR: begin
CS_SCKCount <= 9'b1;
SCK_CSCount <= 9'b10;
FrameCount <= 4'b0;
InterCSCount <= 9'b10;
InterXFRCount <= InterXFRCount + 9'b1;
if (InterXFRCompare & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE;
end
endcase
end
/* verilator lint_off CASEINCOMPLETE */
assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull);
assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef;
assign sck = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1];
assign Active = (state == ACTIVE_0 | state == ACTIVE_1);
assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0);
assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4])));
assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
assign Active0 = (state == ACTIVE_0);
//Signal tracks which edge of sck to shift data
always_comb
case(SckMode[1:0])
2'b00: ShiftEdge = ~sck & SCLKenable;
2'b01: ShiftEdge = (sck & |(FrameCount) & SCLKenable);
2'b10: ShiftEdge = sck & SCLKenable;
2'b11: ShiftEdge = (~sck & |(FrameCount) & SCLKenable);
default: ShiftEdge = sck & SCLKenable;
endcase
//Transmit shift register
assign TransmitDataEndian = Format[0] ? {TransmitFIFOReadData[0], TransmitFIFOReadData[1], TransmitFIFOReadData[2], TransmitFIFOReadData[3], TransmitFIFOReadData[4], TransmitFIFOReadData[5], TransmitFIFOReadData[6], TransmitFIFOReadData[7]} : TransmitFIFOReadData[7:0];
always_ff @(posedge PCLK, negedge PRESETn)
if(~PRESETn) TransmitShiftReg <= 8'b0;
else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian;
else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
assign SPIOut = TransmitShiftReg[7];
//If in loopback mode, receive shift register is connected directly to module's output pins. Else, connected to SPIIn
//There are no setup/hold time issues because transmit shift register and receive shift register always shift/sample on opposite edges
assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn;
//Receive shift register
always_ff @(posedge PCLK, negedge PRESETn)
if(~PRESETn) ReceiveShiftReg <= 8'b0;
else if (SampleEdge & SCLKenable) begin
if (~Active) ReceiveShiftReg <= 8'b0;
else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
end
//Aligns received data and reverses if little-endian
assign LeftShiftAmount = 4'h8 - Format[4:1];
assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0];
assign ReceiveShiftRegEndian = Format[0] ? {ASR[0], ASR[1], ASR[2], ASR[3], ASR[4], ASR[5], ASR[6], ASR[7]} : ASR[7:0];
//Interrupt logic: raise interrupt if any enabled interrupts are pending
assign SPIIntr = |(InterruptPending & InterruptEnable);
//Chip select logic
always_comb
case(ChipSelectID[1:0])
2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
2'b01: ChipSelectAuto = {ChipSelectDef[3],ChipSelectDef[2], ChipSelectInternal[1], ChipSelectDef[0]};
2'b10: ChipSelectAuto = {ChipSelectDef[3],ChipSelectInternal[2], ChipSelectDef[1], ChipSelectDef[0]};
2'b11: ChipSelectAuto = {ChipSelectInternal[3],ChipSelectDef[2], ChipSelectDef[1], ChipSelectDef[0]};
endcase
assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto;
endmodule
module SynchFIFO #(parameter M =3 , N= 8)(
input logic PCLK, wen, ren, PRESETn,
input logic winc,rinc,
input logic [N-1:0] wdata,
input logic [M-1:0] wwatermarklevel, rwatermarklevel,
output logic [N-1:0] rdata,
output logic wfull, rempty,
output logic wwatermark, rwatermark);
/* Pointer FIFO using design elements from "Simulation and Synthesis Techniques
for Asynchronous FIFO Design" by Clifford E. Cummings. Namely, M bit read and write pointers
are an extra bit larger than address size to determine full/empty conditions.
Watermark comparisons use 2's complement subtraction between the M-1 bit pointers,
which are also used to address memory
*/
logic [N-1:0] mem[2**M];
logic [M:0] rptr, wptr;
logic [M:0] rptrnext, wptrnext;
logic rempty_val;
logic wfull_val;
logic [M-1:0] raddr;
logic [M-1:0] waddr;
assign rdata = mem[raddr];
always_ff @(posedge PCLK)
if (winc & ~wfull) mem[waddr] <= wdata;
// write and read are enabled
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) begin
rptr <= 0;
wptr <= 0;
wfull <= 1'b0;
rempty <= 1'b1;
end
else begin
if (wen) begin
wfull <= wfull_val;
wptr <= wptrnext;
end
if (ren) begin
rptr <= rptrnext;
rempty <= rempty_val;
end
end
assign raddr = rptr[M-1:0];
assign rptrnext = rptr + {3'b0, (rinc & ~rempty)};
assign rempty_val = (wptr == rptrnext);
assign rwatermark = ((waddr - raddr) < rwatermarklevel) & ~wfull;
assign waddr = wptr[M-1:0];
assign wwatermark = ((waddr - raddr) > wwatermarklevel) | wfull;
assign wptrnext = wptr + {3'b0, (winc & ~wfull)};
assign wfull_val = ({~wptrnext[M], wptrnext[M-1:0]} == rptr);
endmodule
module TransmitShiftFSM(
input logic PCLK, PRESETn,
input logic TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0,
output logic TransmitShiftEmpty);
typedef enum logic [1:0] {TransmitShiftEmptyState, TransmitShiftHoldState, TransmitShiftNotEmptyState} statetype;
statetype TransmitState, TransmitNextState;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) TransmitState <= TransmitShiftEmptyState;
else TransmitState <= TransmitNextState;
always_comb
case(TransmitState)
TransmitShiftEmptyState: begin
if (TransmitFIFOReadEmpty | (~TransmitFIFOReadEmpty & (ReceivePenultimateFrameBoolean & Active0))) TransmitNextState = TransmitShiftEmptyState;
else if (~TransmitFIFOReadEmpty) TransmitNextState = TransmitShiftNotEmptyState;
end
TransmitShiftNotEmptyState: begin
if (ReceivePenultimateFrameBoolean & Active0) TransmitNextState = TransmitShiftEmptyState;
else TransmitNextState = TransmitShiftNotEmptyState;
end
endcase
assign TransmitShiftEmpty = (TransmitNextState == TransmitShiftEmptyState);
endmodule
module ReceiveShiftFSM(
input logic PCLK, PRESETn, SCLKenable,
input logic ReceivePenultimateFrameBoolean, SampleEdge, SckMode,
output logic ReceiveShiftFull
);
typedef enum logic [1:0] {ReceiveShiftFullState, ReceiveShiftNotFullState, ReceiveShiftDelayState} statetype;
statetype ReceiveState, ReceiveNextState;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveState <= ReceiveShiftNotFullState;
else if (SCLKenable) begin
case (ReceiveState)
ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState;
ReceiveShiftNotFullState: if (ReceivePenultimateFrameBoolean & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState;
else ReceiveState <= ReceiveShiftNotFullState;
ReceiveShiftDelayState: ReceiveState <= ReceiveShiftFullState;
endcase
end
assign ReceiveShiftFull = SckMode ? (ReceiveState == ReceiveShiftFullState) : (ReceiveState == ReceiveShiftDelayState);
endmodule

View file

@ -54,28 +54,31 @@ module uncore import cvw::*; #(parameter cvw_t P)(
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
input logic UARTSin, // UART serial input
output logic UARTSout, // UART serial output
input logic SDCIntr
input logic SDCIntr,
input logic SPIIn,
output logic SPIOut,
output logic [3:0] SPICS
);
logic [P.XLEN-1:0] HREADRam, HREADSDC;
logic [10:0] HSELRegions;
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD;
logic [11:0] HSELRegions;
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC, HSELSPI;
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD, HSELSPID;
logic HRESPRam, HRESPSDC;
logic HREADYRam, HRESPSDCD;
logic [P.XLEN-1:0] HREADBootRom;
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
logic HSELNoneD;
logic UARTIntr,GPIOIntr;
logic UARTIntr,GPIOIntr, SPIIntr;
logic SDCIntM;
logic PCLK, PRESETn, PWRITE, PENABLE;
logic [3:0] PSEL, PREADY;
logic [4:0] PSEL, PREADY;
logic [31:0] PADDR;
logic [P.XLEN-1:0] PWDATA;
logic [P.XLEN/8-1:0] PSTRB;
logic [3:0][P.XLEN-1:0] PRDATA;
logic [4:0][P.XLEN-1:0] PRDATA;
logic [P.XLEN-1:0] HREADBRIDGE;
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
@ -88,14 +91,14 @@ module uncore import cvw::*; #(parameter cvw_t P)(
adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions);
// unswizzle HSEL signals
assign {HSELDTIM, HSELIROM, HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELEXTSDC} = HSELRegions[10:1];
assign {HSELDTIM, HSELIROM, HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELSDC, HSELSPI} = HSELRegions[11:1];
// AHB -> APB bridge
ahbapbbridge #(P, 4) ahbapbbridge (
.HCLK, .HRESETn, .HSEL({HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
ahbapbbridge #(P, 5) ahbapbbridge (
.HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
.HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE),
.PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA);
assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART; // if any of the bridge signals are selected
assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI; // if any of the bridge signals are selected
// on-chip RAM
if (P.UNCORE_RAM_SUPPORTED) begin : ram
@ -121,7 +124,7 @@ module uncore import cvw::*; #(parameter cvw_t P)(
if (P.PLIC_SUPPORTED == 1) begin : plic
plic_apb #(P) plic(.PCLK, .PRESETn, .PSEL(PSEL[2]), .PADDR(PADDR[27:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
.PRDATA(PRDATA[2]), .PREADY(PREADY[2]), .UARTIntr, .GPIOIntr, .SDCIntr, .MExtInt, .SExtInt);
.PRDATA(PRDATA[2]), .PREADY(PREADY[2]), .UARTIntr, .GPIOIntr, .SDCIntr, .SPIIntr, .MExtInt, .SExtInt);
end else begin : plic
assign MExtInt = 0;
assign SExtInt = 0;
@ -145,6 +148,14 @@ module uncore import cvw::*; #(parameter cvw_t P)(
end else begin : uart
assign UARTSout = 0; assign UARTIntr = 0;
end
if (P.SPI_SUPPORTED == 1) begin : spi
spi_apb #(P) spi (
.PCLK, .PRESETn, .PSEL(PSEL[4]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
.PREADY(PREADY[4]), .PRDATA(PRDATA[4]),
.SPIOut, .SPIIn, .SPICS, .SPIIntr);
end else begin : spi
assign SPIOut = 0; assign SPICS = 0; assign SPIIntr = 0;
end
// AHB Read Multiplexer
assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) |
@ -168,6 +179,8 @@ module uncore import cvw::*; #(parameter cvw_t P)(
// takes more than 1 cycle to repsond it needs to hold on to the old select until the
// device is ready. Hense this register must be selectively enabled by HREADY.
// However on reset None must be seleted.
flopenl #(11) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 11'b1, {HSELDTIMD, HSELIROMD, HSELEXTD, HSELBootRomD, HSELRamD, HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELEXTSDCD, HSELNoneD});
flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1,
{HSELDTIMD, HSELIROMD, HSELEXTD, HSELBootRomD, HSELRamD,
HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELEXTSDCD, HSELSPID, HSELNoneD});
flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED);
endmodule

View file

@ -54,11 +54,14 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
output logic [31:0] GPIOEN, // output enables for GPIO
input logic UARTSin, // UART serial data input
output logic UARTSout, // UART serial data output
input logic SDCIntr
input logic SDCIntr,
input logic SPIIn, // SPI pins in
output logic SPIOut, // SPI pins out
output logic [3:0] SPICS // SPI chip select pins
);
// Uncore signals
logic [P.AHBW-1:0] HRDATA; // from AHB mux in uncore
logic [P.AHBW-1:0] HRDATA; // from AHB mux in uncore
logic HRESP; // response from AHB
logic MTimerInt, MSwInt;// timer and software interrupts from CLINT
logic [63:0] MTIME_CLINT; // from CLINT to CSRs
@ -80,7 +83,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC,
.MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin,
.UARTSout, .MTIME_CLINT, .SDCIntr);
.UARTSout, .MTIME_CLINT, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
end
endmodule

View file

@ -31,3 +31,12 @@ SAIFPOWER
0: switching factor power analysis
1: RTL simulation driven power analysis.
-----
Extra Tool (PPA)
To run ppa analysis that hones into target frequency, you can type:
python3 ppa/ppaSynth.py from the synthDC directory. This runs a sweep
across all modules listed at the bottom of the ppaSynth.py file.

View file

@ -1,5 +1,9 @@
#!/usr/bin/python3
#
# Python regression test for DC
# Madeleine Masser-Frye mmasserfrye@hmc.edu 5/22
# James Stine james.stine@okstate.edu 15 October 2023
#
import scipy.optimize as opt
import subprocess
@ -565,6 +569,7 @@ def makeLineLegend():
fullLeg += [lines.Line2D([0], [0], color='black', label='smallest', linestyle='--')]
fullLeg += [lines.Line2D([0], [0], color='blue', label='tsmc28', marker='^')]
fullLeg += [lines.Line2D([0], [0], color='green', label='sky90', marker='o')]
fullLeg += [lines.Line2D([0], [0], color='green', label='sky130', marker='+')]
fullLeg += [lines.Line2D([0], [0], color='red', label='combined', marker='_')]
fig.legend(handles=fullLeg, ncol=5, handlelength=1.4, loc='center')
saveStr = './plots/legend.png'
@ -689,7 +694,7 @@ def makePlotDirectory():
os.makedirs(new_directory)
os.chdir(new_directory)
if 'freq' in folder:
for tech in ['sky90', 'tsmc28']:
for tech in ['sky90', 'sky130', 'tsmc28']:
for mod in modules:
tech_directory = os.path.join(new_directory, tech)
mod_directory = os.path.join(tech_directory, mod)
@ -702,15 +707,14 @@ def makePlotDirectory():
if __name__ == '__main__':
##############################
# set up stuff, global variables
widths = [8, 16, 32, 64, 128]
modules = ['priorityencoder', 'add', 'csa', 'shiftleft', 'comparator', 'flop', 'mux2', 'mux4', 'mux8', 'mult'] #, 'mux2d', 'mux4d', 'mux8d']
widths = [8, 16, 32, 64, 128]
modules = ['priorityencoder', 'add', 'csa', 'shiftleft', 'comparator', 'flop', 'mux2', 'mux4', 'mux8', 'mult']
normAddWidth = 32 # divisor to use with N since normalizing to add_32
fitDict = {'add': ['cg', 'l', 'l'], 'mult': ['cg', 's', 's'], 'comparator': ['cg', 'l', 'l'], 'csa': ['c', 'l', 'l'], 'shiftleft': ['cg', 'l', 'ln'], 'flop': ['c', 'l', 'l'], 'priorityencoder': ['cg', 'l', 'l']}
fitDict.update(dict.fromkeys(['mux2', 'mux4', 'mux8'], ['cg', 'l', 'l']))
fitDict = {'add': ['cg', 'l', 'l'], 'mult': ['cg', 's', 's'], 'comparator': ['cg', 'l', 'l'], 'csa': ['c', 'l', 'l'], 'shiftleft': ['cg', 'l', 'ln'], 'flop': ['c', 'l', 'l'], 'priorityencoder': ['cg', 'l', 'l']} fitDict.update(dict.fromkeys(['mux2', 'mux4', 'mux8'], ['cg', 'l', 'l']))
TechSpec = namedtuple("TechSpec", "tech color shape delay area lpower denergy")
techSpecs = [['sky90', 'green', 'o', 43.2e-3, 1440.600027, 714.057, 0.658022690438], ['tsmc28', 'blue', '^', 12.2e-3, 209.286002, 1060.0, .08153281695882594]]
techSpecs = [['sky90', 'green', 'o', 43.2e-3, 1440.600027, 714.057, 0.658022690438], ['sky130', 'red', 'o', 43.2e-3, 1440.600027, 714.057, 0.658022690438], ['tsmc28', 'blue', '^', 12.2e-3, 209.286002, 1060.0, .08153281695882594]]
techSpecs = [TechSpec(*t) for t in techSpecs]
combined = TechSpec('combined fit', 'red', '_', 0, 0, 0, 0)
##############################
@ -731,7 +735,8 @@ if __name__ == '__main__':
for mod in modules:
for w in widths:
freqPlot('sky90', mod, w)
freqPlot('tsmc28', mod, w)
plotPPA(mod, norm=False)
plotPPA(mod, aleOpt=True)
#freqPlot('sky130', mod, w)
#freqPlot('tsmc28', mod, w)
#plotPPA(mod, norm=False)
#plotPPA(mod, aleOpt=True)
plt.close('all')

View file

@ -1,5 +1,9 @@
#!/usr/bin/python3
# Madeleine Masser-Frye mmasserfrye@hmc.edu 6/22
#
# Python regression test for DC
# Madeleine Masser-Frye mmasserfrye@hmc.edu 5/22
# James Stine james.stine@okstate.edu 15 October 2023
#
import subprocess
import re
@ -7,7 +11,9 @@ from multiprocessing import Pool
from ppaAnalyze import synthsfromcsv
def runCommand(module, width, tech, freq):
command = "make synth DESIGN=ppa_{}_{} TECH={} DRIVE=INV FREQ={} MAXOPT=1 MAXCORES=1".format(module, width, tech, freq)
command = "make synth DESIGN={} WIDTH={} TECH={} DRIVE=INV FREQ={} MAXOPT=1 MAXCORES=1".format(module, width, tech, freq)
print('here we go')
subprocess.Popen(command, shell=True)
def deleteRedundant(synthsToRun):
@ -20,7 +26,7 @@ def deleteRedundant(synthsToRun):
def freqSweep(module, width, tech):
synthsToRun = []
arr = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
allSynths = synthsfromcsv('bestSynths.csv')
allSynths = synthsfromcsv('ppa/bestSynths.csv')
for synth in allSynths:
if (synth.module == module) & (synth.tech == tech) & (synth.width == width):
f = 1000/synth.delay
@ -54,20 +60,20 @@ def allCombos(widths, modules, techs, freqs):
if __name__ == '__main__':
##### Run specific syntheses
widths = [8, 16, 32, 64, 128]
modules = ['mult', 'add', 'shiftleft', 'flop', 'comparator', 'priorityencoder', 'add', 'csa', 'mux2', 'mux4', 'mux8']
techs = ['sky90', 'tsmc28']
freqs = [5000]
synthsToRun = allCombos(widths, modules, techs, freqs)
widths = [8, 16, 32, 64, 128]
modules = ['mult', 'add', 'shiftleft', 'flop', 'comparator', 'priorityencoder', 'add', 'csa', 'mux2', 'mux4', 'mux8']
techs = ['sky90', 'tsmc28']
freqs = [5000]
synthsToRun = allCombos(widths, modules, techs, freqs)
##### Run a sweep based on best delay found in existing syntheses
module = 'add'
width = 32
tech = 'sky90'
synthsToRun = freqSweep(module, width, tech)
module = 'add'
width = 32
tech = 'sky90'
synthsToRun = freqSweep(module, width, tech)
##### Only do syntheses for which a run doesn't already exist
synthsToRun = filterRedundant(synthsToRun)
synthsToRun = filterRedundant(synthsToRun)
pool = Pool(processes=25)
pool.starmap(print, synthsToRun)
pool = Pool(processes=25)
pool.starmap(runCommand, synthsToRun)

View file

@ -32,17 +32,15 @@ eval file copy -force [glob ${hdl_src}/cvw.sv] {$outputDir/hdl/}
eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/}
eval file copy -force [glob ${hdl_src}/*/*/*.sv] {$outputDir/hdl/}
# Check if a wrapper is needed (when cvw_t parameters are used)
# Check if a wrapper is needed and create it (to pass parameters when cvw_t parameters are used)
set wrapper 0
if {[eval exec grep "cvw_t" {$outputDir/hdl/$::env(DESIGN).sv}] ne ""} {
if {[catch {eval exec grep "cvw_t" $outputDir/hdl/$::env(DESIGN).sv}] == 0} {
echo "Creating wrapper"
set wrapper 1
# make the wrapper
exec python3 $::env(WALLY)/synthDC/scripts/wrapperGen.py $::env(DESIGN) $outputDir/hdl
}
# Only for FMA class project; comment out when done
# eval file copy -force [glob ${hdl_src}/fma/fma16.v] {hdl/}
# Enables name mapping
if { $saifpower == 1 } {
saif_map -start
@ -310,6 +308,8 @@ set filename [format "%s%s" $outputDir "/reports/mindelay.rep"]
redirect $filename { report_timing -capacitance -transition_time -nets -delay_type min -nworst 1 }
set filename [format "%s%s" $outputDir "/reports/per_module_timing.rep"]
redirect -append $filename { echo "\n\n\n//// Critical paths through Stall ////\n\n\n" }
redirect -append $filename { report_timing -capacitance -transition_time -nets -through {Stall*} -nworst 1 }
redirect -append $filename { echo "\n\n\n//// Critical paths through ifu ////\n\n\n" }
redirect -append $filename { report_timing -capacitance -transition_time -nets -through {ifu/*} -nworst 1 }
redirect -append $filename { echo "\n\n\n//// Critical paths through ieu ////\n\n\n" }

View file

@ -21,7 +21,7 @@ args=parser.parse_args()
fin_path = glob.glob(f"{os.getenv('WALLY')}/src/**/{args.DESIGN}.sv",recursive=True)[0]
fin = open(fin_path, "r")
fin = open(fin_path, "r", encoding='utf-8')
lines = fin.readlines()

View file

@ -1,5 +1,5 @@
///////////////////////////////////////////
// shadowmem.sv
// DCacheFlushFSM.sv
//
// Written: David Harris David_Harris@hmc.edu and Ross Thompson ross1728@gmail.com
// Modified: 14 June 2023

View file

@ -217,7 +217,7 @@ module loggers import cvw::*; #(parameter cvw_t P,
logic PCSrcM;
string LogFile;
logic resetD, resetEdge;
flopenrc #(1) PCSrcMReg(clk, reset, dut.core.FlushM, ~dut.core.StallM, dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PCSrcE, PCSrcM);
flopenrc #(1) PCSrcMReg(clk, reset, dut.core.FlushM, ~dut.core.StallM, dut.core.ifu.PCSrcE, PCSrcM);
flop #(1) ResetDReg(clk, reset, resetD);
assign resetEdge = ~reset & resetD;
initial begin

View file

@ -30,11 +30,13 @@ module watchdog #(parameter XLEN, WatchDogTimerThreshold)
);
// check for hang up.
logic [XLEN-1:0] PCW;
flopenr #(XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
logic [XLEN-1:0] OldPCW;
logic [XLEN-1:0] PCM, PCW, OldPCW;
integer WatchDogTimerCount;
logic WatchDogTimeOut;
flopenr #(XLEN) PCMReg(clk, reset, ~dut.core.ifu.StallM, dut.core.ifu.PCE, PCM); // duplicate PCM register because it is not in ifu for all configurations
flopenr #(XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, PCM, PCW);
always_ff @(posedge clk) begin
OldPCW <= PCW;
if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1;

View file

@ -644,11 +644,11 @@ module testbenchfp;
// Read the first test
initial begin
//string testname = {`PATH, Tests[TestNum]};
string p = `PATH;
static string pp = `PATH;
string testname;
string tt0;
tt0 = $psprintf("%s", Tests[TestNum]);
testname = {p, tt0};
testname = {pp, tt0};
$display("Here you are %s", testname);
$display("\n\nRunning %s vectors ", Tests[TestNum]);
$readmemh(testname, TestVectors);

View file

@ -72,6 +72,7 @@ module testbench;
logic HMASTLOCK;
logic HCLK, HRESETn;
logic [P.XLEN-1:0] PCW;
logic [31:0] NextInstrE, InstrM;
string ProgramAddrMapFile, ProgramLabelMapFile;
integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
@ -81,7 +82,8 @@ module testbench;
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
logic UARTSin, UARTSout;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
logic SDCIntr;
logic HREADY;
@ -214,7 +216,7 @@ module testbench;
`endif
flopenr #(P.XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW);
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW);
// check assertions for a legal configuration
riscvassertions #(P) riscvassertions();
@ -255,13 +257,13 @@ module testbench;
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr);
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
// Track names of instructions
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,
InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// initialize tests
@ -298,6 +300,10 @@ module testbench;
.ProgramLabelMapFile(ProgramLabelMapFile));
end
// Duplicate copy of pipeline registers that are optimized out of some configurations
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
// Termination condition
// terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed
// or sw gp,-56(t0) for new Imperas tests
@ -311,7 +317,7 @@ module testbench;
(dut.core.ieu.dp.regf.we3 &
dut.core.ieu.dp.regf.a3 == 3 &
dut.core.ieu.dp.regf.wd3 == 1)) |
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk),

View file

@ -229,10 +229,16 @@ module testbench;
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Cache Issue ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [31:0] NextInstrE, InstrM;
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
logic probe;
if (NO_SPOOFING)
assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c
& testbench.dut.core.InstrM != 32'h14021273
& InstrM != 32'h14021273
& testbench.dut.core.InstrValidM;
@ -276,6 +282,8 @@ module testbench;
logic SDCCmdOE;
logic [3:0] SDCDatIn;
logic SDCIntr;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
// Hardwire UART, GPIO pins
@ -434,13 +442,10 @@ module testbench;
// Wally
wallypipelinedsoc #(P) dut(.clk, .reset, .reset_ext,
.HRDATAEXT, .HREADYEXT, .HREADY, .HSELEXT, .HRESPEXT, .HCLK,
.HRESETn, .HADDR, .HWDATA, .HWRITE, .HWSTRB, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK,
.TIMECLK('0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout,
.SDCIntr);
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
// W-stage hardware not needed by Wally itself
parameter nop = 'h13;
@ -452,7 +457,7 @@ module testbench;
`define FLUSHW dut.core.FlushW
`define STALLW dut.core.StallW
flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : dut.core.ifu.InstrM, InstrW);
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW);
flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW);
flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW);
flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW);
@ -969,7 +974,7 @@ module testbench;
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,
InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// ------------------

View file

@ -212,10 +212,16 @@ module testbench;
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Cache Issue ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [31:0] NextInstrE, InstrM;
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(dut.core.clk, dut.core.reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
logic probe;
if (NO_SPOOFING)
assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c
& testbench.dut.core.InstrM != 32'h14021273
& InstrM != 32'h14021273
& testbench.dut.core.InstrValidM;
@ -252,6 +258,8 @@ module testbench;
logic [31:0] GPIOIN;
logic [31:0] GPIOOUT, GPIOEN;
logic UARTSin, UARTSout;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
// FPGA-specific Stuff
logic SDCIntr;
@ -262,13 +270,10 @@ module testbench;
assign SDCIntr = 0;
// Wally
wallypipelinedsoc #(P) dut(.clk, .reset, .reset_ext,
.HRDATAEXT, .HREADYEXT, .HREADY, .HSELEXT, .HSELEXTSDC, .HRESPEXT, .HCLK,
.HRESETn, .HADDR, .HWDATA, .HWRITE, .HWSTRB, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK,
.TIMECLK('0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout,
.SDCIntr);
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
// W-stage hardware not needed by Wally itself
parameter nop = 'h13;
@ -280,7 +285,7 @@ module testbench;
`define FLUSHW dut.core.FlushW
`define STALLW dut.core.StallW
flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : dut.core.ifu.InstrM, InstrW);
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW);
flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW);
flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW);
flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW);
@ -794,7 +799,7 @@ module testbench;
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,
InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// ------------------

View file

@ -70,6 +70,8 @@ module testbench;
logic [3:0] SDCDatIn;
tri1 [3:0] SDCDat;
tri1 SDCCmd;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
logic HREADY;
logic HSELEXT;
@ -426,10 +428,10 @@ module testbench;
assign SDCDat = '0;
end
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCCmdIn, .SDCCmdOut, .SDCCmdOE, .SDCDatIn, .SDCCLK);
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
// generate clock to sequence tests
always begin
@ -440,20 +442,25 @@ module testbench;
// Support logic
////////////////////////////////////////////////////////////////////////////////
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [31:0] NextInstrE, InstrM;
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
// 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);
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, 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,
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);
dut.core.ifu.PCM, 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);
@ -478,7 +485,7 @@ module testbench;
(dut.core.ieu.dp.regf.we3 &
dut.core.ieu.dp.regf.a3 == 3 &
dut.core.ieu.dp.regf.wd3 == 1)) |
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));

View file

@ -64,7 +64,8 @@ module testbench;
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
logic UARTSin, UARTSout;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
logic SDCIntr;
logic HREADY;
@ -367,6 +368,7 @@ module testbench;
// instantiate device to be tested
assign GPIOIN = 0;
assign UARTSin = 1;
assign SPIIn = 0;
if(P.EXT_MEM_SUPPORTED) begin
ram_ahb #(.BASE(P.EXT_MEM_BASE), .RANGE(P.EXT_MEM_RANGE))
@ -397,7 +399,7 @@ module testbench;
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr);
.UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
// generate clock to sequence tests
always begin
@ -408,20 +410,25 @@ module testbench;
// Support logic
////////////////////////////////////////////////////////////////////////////////
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [31:0] NextInstrE, InstrM;
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
// 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);
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, 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,
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);
dut.core.ifu.PCM, 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);
@ -446,7 +453,7 @@ module testbench;
(dut.core.ieu.dp.regf.we3 &
dut.core.ieu.dp.regf.a3 == 3 &
dut.core.ieu.dp.regf.wd3 == 1)) |
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));

View file

@ -2010,7 +2010,8 @@ string arch64zbs[] = '{
"rv64i_m/privilege/src/WALLY-gpio-01.S",
"rv64i_m/privilege/src/WALLY-plic-01.S",
"rv64i_m/privilege/src/WALLY-plic-s-01.S",
"rv64i_m/privilege/src/WALLY-uart-01.S"
"rv64i_m/privilege/src/WALLY-uart-01.S",
"rv64i_m/privilege/src/WALLY-spi-01.S"
};
string wally32e[] = '{
@ -2096,7 +2097,8 @@ string arch64zbs[] = '{
"rv32i_m/privilege/src/WALLY-clint-01.S",
"rv32i_m/privilege/src/WALLY-uart-01.S",
"rv32i_m/privilege/src/WALLY-plic-01.S",
"rv32i_m/privilege/src/WALLY-plic-s-01.S"
"rv32i_m/privilege/src/WALLY-plic-s-01.S",
"rv32i_m/privilege/src/WALLY-spi-01.S"
};

View file

@ -1,11 +1,10 @@
///////////////////////////////////////////
// testbench.sv
// wallywrapper.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Wally Testbench and helper modules
// Applies test programs from the riscv-arch-test and Imperas suites
// Purpose: Wrapper module to define parameters for Wally Verilator linting
//
// A component of the Wally configurable RISC-V project.
//
@ -51,6 +50,8 @@ module wallywrapper;
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
logic UARTSin, UARTSout;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
logic SDCIntr;
logic HREADY;
@ -70,6 +71,6 @@ module wallywrapper;
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr);
.UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr);
endmodule

View file

@ -56,6 +56,7 @@ target_tests_nosim = \
WALLY-clint-01 \
WALLY-plic-01 \
WALLY-uart-01 \
WALLY-spi-01 \
WALLY-cbom-01 \
WALLY-cboz-01 \

View file

@ -0,0 +1,288 @@
00000003 # reset tests sck_div
00000000 # sck_mode
00000000 # cs_id
0000000F # cs_def
00000000 # cs_mode
00010001 # delay 0
00000001 # delay 1
00080000 # fmt
00000000 # tx_data
00000000 # tx_mark
00000000 # rx_mark
00000000 # ie reset
00000000 # ip reset
00000000 # fifo watermark and edge case tests
00000001
00000003
00000003
00000074
00000063
00000052
00000041
000000A1
00000003
000000B2
00000001
000000C3
000000D4
00000003
000000A4
00000001
000000B4
000000A5
000000B5
000000C5
000000D5
000000A7
000000B7
000000C7
00000002
000000D7
00000000
00000011 #basic read write
000000FF
000000A0
0000000B
00000079
00000000
000000C0
00000011
00000020 #delay registers
00000032
00000048
000000AF
00000050
0000006B
00000011
00000015
00000011 #delay1
00000022
00000033
00000044
0000007B
00000021
00000032
00000043
00000054
00000066
00000077
00000088
00000099
00000066
00000077
00000088
00000099
00000065
00000076
00000087
00000098
00000048
000000DD
000000CC
000000BB
000000AA
000000DE
000000CD
000000BC
000000AB
000000CE hold mode deassert
000000F0 #fmt register
00000000
00000080
00000000
00000080
000000A8
000000F8
00000048
00000070
00000000
00000008
00000003
00000017
0000000F
0000001F
00000062 # hardware interlock
00000026
000000D2
0000002D
00000048
00000037
00000026
00000015
00000084
00000073
00000062
00000051
00000046
00000035
00000024
00000013
00000064
00000053
00000042
00000031
00000001 #watermark interrupts
00000000 #read mip
00000000 #read tx ip
00000022 #clear 1 frame from rx fifo
00000000 # read recieve ip
00000002 #read recieve ip
00000000 #read mip
00000033 #clear frame
00000000 # read receive ip
00000044 #clear frame
00000055 #clear frame
00000001 #read tx ip
00000800 #read mip
00000022 #clear frame
00000000 #read rx ip
00000000 #read mip 94
00000002 #read rx ip
00000800 #read mip
00000033 #clear frame
00000000 #read rx wm
00000000 #read mip 99

View file

@ -865,6 +865,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
.equ PLIC_INTPRI_GPIO, 0x0C00000C # GPIO is interrupt 3
.equ PLIC_INTPRI_UART, 0x0C000028 # UART is interrupt 10
.equ PLIC_INTPRI_SPI, 0x0C000018 # SPI in interrupt 6
.equ PLIC_INTPENDING0, 0x0C001000 # intPending0 register
.equ PLIC_INTEN00, 0x0C002000 # interrupt enables for context 0 (machine mode) sources 31:1
.equ PLIC_INTEN10, 0x0C002080 # interrupt enables for context 1 (supervisor mode) sources 31:1
@ -877,6 +878,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
.4byte PLIC_THRESH1, 7, write32_test # Set PLIC supervisor mode interrupt threshold to 7 to accept no interrupts
.4byte PLIC_INTPRI_GPIO, 7, write32_test # Set GPIO to high priority
.4byte PLIC_INTPRI_UART, 7, write32_test # Set UART to high priority
.4byte PLIC_INTPRI_SPI, 7, write32_test # Set UART to high priority
.4byte PLIC_INTEN00, 0xFFFFFFFF, write32_test # Enable all interrupt sources for machine mode
.4byte PLIC_INTEN10, 0x00000000, write32_test # Disable all interrupt sources for supervisor mode
.endm
@ -1028,6 +1030,12 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
sw t3, 0(t2)
sw t4, -4(sp)
addi sp, sp, -4
li t2, 0x0C000018 // SPI priority
li t3, 7
lw t4, 0(t2)
sw t3, 0(t2)
sw t4, -4(sp)
addi sp, sp, -4
li t2, 0x0C002000
li t3, 0x0C200004
li t4, 0xFFF
@ -1038,11 +1046,14 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
sw t6, 0(t2) // restore saved enable status
li t2, 0x0C00000C // GPIO priority
li t3, 0x0C000028 // UART priority
lw t4, 4(sp) // load stored GPIO and UART priority
lw t5, 0(sp)
addi sp, sp, 8 // restore stack pointer
sw t4, 0(t2)
sw t5, 0(t3)
li t6, 0x0C000018 // SPI priority
lw a4, 8(sp) // load stored GPIO prioroty
lw t4, 4(sp) // load stored UART priority
lw t5, 0(sp) // load stored SPI priority
addi sp, sp, 12 // restore stack pointer
sw a4, 0(t2)
sw t4, 0(t3)
sw t5, 0(t6)
j test_loop
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
@ -1128,6 +1139,34 @@ uart_clearmodemintr:
lb t2, 0(t2)
j test_loop
spi_data_wait:
li t2, 0x10040054
sw t4, 0(t2) // set rx watermark level
li t2, 0x10040074
lw t3, 0(t2) //read ip (interrupt pending register)
slli t3, t3, 28
srli t3, t3, 28
li t2, 0x00000002
bge t3, t2, spi_data_ready //branch to done if transmission complete
j spi_data_wait //else check again
spi_data_ready:
li t2, 0x10040070
li t3, 0x00000000
sw t3, 0(t2) //disable rx watermark interrupt
j test_loop
spi_burst_send: //function for loading multiple frames at once to test delays without returning to test loop
mv t2, t4
sw t2, 0(t3)
srli t2, t2, 8
sw t2, 0(t3)
srli t2, t2, 8
sw t2, 0(t3)
srli t2, t2, 8
sw t2, 0(t3)
j test_loop
goto_s_mode:
// return to address in t3,
li a0, 3 // Trap handler behavior (go to supervisor mode)

View file

@ -0,0 +1,660 @@
///////////////////////////////////////////
//
// WALLY-spi
//
// Author: David_Harris@hmc.edu and Naiche Whyte-Aguayo
//
// Created 2023-02-01
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
#include "WALLY-TEST-LIB-32.h"
RVTEST_ISA("RV32I_Zicsr_Zifencei")
RVTEST_CASE(0,"//check ISA:=regex(.*32.*);check ISA:=regex(.*I.*); def Drvtest_mtrap_routine=True;def TEST_CASE_1=True;def NO_SAIL=True;",spi)
INIT_TESTS
TRAP_HANDLER m
j run_test_loop // begin test loop/table tests instead of executing inline code.
INIT_TEST_TABLE
END_TESTS
TEST_STACK_AND_DATA
.align 2
test_cases:
# ---------------------------------------------------------------------------------------------
# Test Contents
#
# Here is where the actual tests are held, or rather, what the actual tests do.
# each entry consists of 3 values that will be read in as follows:
#
# '.4byte [x28 Value], [x29 Value], [x30 value]'
# or
# '.4byte [address], [value], [test type]'
#
# The encoding for x30 test type values can be found in the test handler in the framework file
# ---------------------------------------------------------------------------------------------
.equ SPI, 0x10040000
.equ sck_div, (SPI+0x00)
.equ sck_mode, (SPI+0x04)
.equ cs_id, (SPI+0x10)
.equ cs_def, (SPI+0x14)
.equ cs_mode, (SPI+0x18)
.equ delay0, (SPI+0x28)
.equ delay1, (SPI+0x2C)
.equ fmt, (SPI+0x40)
.equ tx_data, (SPI+0x48)
.equ rx_data, (SPI+0x4C)
.equ tx_mark, (SPI+0x50)
.equ rx_mark, (SPI+0x54)
.equ ie, (SPI+0x70)
.equ ip, (SPI+0x74)
# =========== Verify all registers reset to correct values ===========
.4byte sck_div, 0x00000003, read32_test # sck_div reset to 0x3
.4byte sck_mode, 0x00000000, read32_test # sck_mode reset to 0x0
.4byte cs_id, 0x00000000, read32_test # cs_id reset to 0x0
.4byte cs_def, 0x0000000F, read32_test # cs_def reset to 0x1
.4byte cs_mode, 0x00000000, read32_test # cs_mode reset to 0x0
.4byte delay0, 0x00010001, read32_test # delay0 reset to [31:24] 0x0, [23:16] 0x1, [15:8] 0x0, [7:0] 0x1
.4byte delay1, 0x00000001, read32_test # delay1 reset to 0x1
.4byte fmt, 0x00080000, read32_test # fmt reset to [31:20] 0x0, [19:16] 0x8, [15:0] 0x0 for non-flash enabled SPI controllers
.4byte tx_data, 0x00000000, read32_test # tx_data [30:0] reset to 0x0, [31] read only
.4byte tx_mark, 0x00000000, read32_test # tx_mark reset to 0x0 for non-flash enabled controllers
.4byte rx_mark, 0x00000000, read32_test # rx_mark reset to 0x0
.4byte ie, 0x00000000, read32_test # ie reset to 0x0
.4byte ip, 0x00000000, read32_test # ip reset to 0x0
#test watermark interrupts at beginning where fifo read/write pointers are known b/c reset
# txwmp raised when # of entries in txfifo < txmark, rxwm raised when # of entries in rxfifo > rxmark
.4byte ip, 0x00000000, read32_test # txfifo entries not < 0, rxfifo entries not > 0;
.4byte tx_mark, 0x00000004, write32_test # set tx_mark to 4
.4byte rx_mark, 0x00000003, write32_test # set rx_mark to 3
.4byte ip, 0x00000001, read32_test # tx entries < 4, rx entries ! > 3
.4byte tx_data, 0x41526374, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait
.4byte ip, 0x00000003, read32_test # tx entries < 4, rx entries > 3, visual inspection should see tx TransmitFIFOReadIncrement
# txfifo wptr now at 0011, rxfifo wptr at 0000
.4byte rx_mark, 0x00000007, write32_test # set rx_mark to 7
.4byte tx_data, 0xD4C3B2A1, spi_burst_send
.4byte 0x0, 0x00000007, spi_data_wait # rxfifo full, txfifo wptr at 1000, rxfifo wptr at 0000
.4byte ip, 0x00000003, read32_test
.4byte rx_data, 0x00000074, read32_test
.4byte rx_data, 0x00000063, read32_test # clear 2 entries, txfifo wptr at 1000, rxfifo wptr at 0010
.4byte tx_data, 0x000000A4, write32_test
.4byte tx_data, 0x000000B4, write32_test # tx 1010, rx 0010
.4byte 0x0, 0x00000007, spi_data_wait # 8 tx 1010, rx 0010
.4byte rx_mark, 0x00000004, write32_test
.4byte rx_data, 0x00000052, read32_test # 7 rx 0011
.4byte rx_data, 0x00000041, read32_test # 6 rx 0100
.4byte rx_data, 0x000000A1, read32_test # 5 rx 0101
.4byte ip, 0x00000003, read32_test # 5 things in rx fifo
.4byte rx_data, 0x000000B2, read32_test # 4 tx 1010, rx 0110
.4byte ip, 0x00000001, read32_test # 4 entries in rxfifo, not strictly greater than 4
.4byte rx_mark, 0x00000007, write32_test
.4byte tx_data, 0xD5C5B5A5, spi_burst_send # 8 tx1110, rx 0110
.4byte 0x0, 0x00000007, spi_data_wait
.4byte rx_mark, 0x00000005, write32_test
.4byte rx_data, 0x000000C3, read32_test # tx 1110, rx 0111
.4byte rx_data, 0x000000D4, read32_test # tx 1110, rx 1000
.4byte ip, 0x00000003, read32_test # 6 entries
.4byte rx_data, 0x000000A4, read32_test # tx 1110, rx 1001
.4byte ip, 0x00000001, read32_test # 5 entries
.4byte rx_data, 0x000000B4, read32_test # tx 1110, rx 1010
.4byte rx_data, 0x000000A5, read32_test # tx 1110, rx 1011
.4byte rx_mark, 0x00000006, write32_test
.4byte tx_data, 0xD7C7B7A7, spi_burst_send
.4byte 0x0, 0x00000006, spi_data_wait # tx 0010, rx 1011
.4byte tx_mark, 0x00000000, write32_test
.4byte rx_mark, 0x00000000, write32_test
.4byte rx_data, 0x000000B5, read32_test # tx 0010, rx 1100
.4byte rx_data, 0x000000C5, read32_test # tx 0010, rx 1101
.4byte rx_data, 0x000000D5, read32_test # tx 0010, rx 1110
.4byte rx_data, 0x000000A7, read32_test # tx 0010, rx 1111
.4byte rx_data, 0x000000B7, read32_test # tx 0010, rx 0000
.4byte rx_data, 0x000000C7, read32_test # tx 0010, rx 0001
.4byte ip, 0x00000002, read32_test
.4byte rx_data, 0x000000D7, read32_test # tx 0010, rx 1010
.4byte ip, 0x00000000, read32_test
.4byte tx_mark, 0x00000000, write32_test
.4byte rx_mark, 0x00000000, write32_test # reset watermark registers
# =========== Basic read-write ===========
.4byte tx_data, 0x000000011, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000011, read32_test # read rx_data
# =========== Different cs_mode, sck_mode, cs_def, sck_div ===========
# Test sck_div
.4byte sck_div, 0x00000101, write32_test # set sck_div to 0x101
.4byte tx_data, 0x000000FF, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x000000FF, read32_test # read rx_data
# Test phase
.4byte sck_div, 0x00000003, write32_test # reset sck_div to 0x03 so only sck_mode is different
.4byte sck_mode, 0x00000001, write32_test # change phase to falling edge
.4byte tx_data, 0x000000A0, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x000000A0, read32_test # read rx_data
# Test polarity
.4byte sck_mode, 0x00000000, write32_test # reset sck phase to rising edge
.4byte sck_mode, 0x00000002, write32_test # set sck polarity active low
.4byte tx_data, 0x0000000B, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x0000000B, read32_test # read rx_data
# Test chip select polarity
.4byte sck_mode, 0x00000000, write32_test # reset sck polarity to active high
.4byte cs_def, 0x0000000E, write32_test # set cs[0] to inactive low
.4byte tx_data, 0x00000079, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000079, read32_test # read rx_data
# Test chip id
.4byte cs_def, 0x0000000F, write32_test # reset all cs to active low
.4byte cs_id, 0x00000001, write32_test # select cs[1]
.4byte tx_data, 0x00000000, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000000, read32_test # read rx_data
# Test cs hold mode
.4byte cs_id, 0x00000000, write32_test # select cs[0]
.4byte cs_mode, 0x00000002, write32_test # set cs_mode to HOLD
.4byte tx_data, 0x000000C0, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x000000C0, read32_test # read rx_data
# Test cs OFF mode
.4byte cs_mode, 0x00000003, write32_test # set cs_mode to OFF
.4byte tx_data, 0x00000011, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000011, read32_test # read rx_data
# =========== Test delay0 register ===========
# Test cs-sck delay of 0 with sck phase = 0 (implicit half cycle delay)
.4byte cs_mode, 0x00000000, write32_test # reset cs_mode to auto, all cs and sck mode settings should be defualt
.4byte delay0, 0x00010000, write32_test # set cs-sck delay to 0
.4byte tx_data, 0x00000020, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000020, read32_test # read rx_data
# Test cs-sck delay of 0 with sck phase 1 (no delay)
.4byte sck_mode, 0x00000001, write32_test # set sck_mode[0] to 1 (sck phase = 1)
.4byte tx_data, 0x00000032, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000032, read32_test # read rx_data
# Test arbitrary cs-sck delay (sck phase 1)
.4byte delay0, 0x00010005, write32_test # set cs-sck delay to 5 cycles
.4byte tx_data, 0x00000048, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000048, read32_test # read rx_data
# Test arbitrary cs-sck delay (sck phase 0)
.4byte sck_mode, 0x00000000, write32_test # set sck phase to 0
.4byte delay0, 0x00010005, write32_test # set cs-sck delay to AF cycles
.4byte tx_data, 0x000000AF, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x000000AF, read32_test # read rx_data
# Test sck-cs delay of 0 with sck phase = 0 (no delay)
.4byte delay0, 0x00000001, write32_test # set cs-sck delay to 0
.4byte tx_data, 0x00000050, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000050, read32_test # read rx_data
# Test sck-cs delay of 0 with sck phase 1 (implicit half cycle delay)
.4byte sck_mode, 0x00000001, write32_test # set sck_mode[0] to 1 (sck phase = 1)
.4byte tx_data, 0x0000006B, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x0000006B, read32_test # read rx_data
# Test arbitrary sck-cs delay (sck phase 1)
.4byte delay0, 0x00050001, write32_test # set cs-sck delay to A5 cycles
.4byte tx_data, 0x00000011, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000011, read32_test # read rx_data
# Test arbitrary sck-cs delay (sck phase 0)
.4byte sck_mode, 0x00000000, write32_test # set sck phase to 0
.4byte delay0, 0x00050001, write32_test # set cs-sck delay to 5 cycles
.4byte tx_data, 0x00000015, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000015, read32_test # read rx_data
# =========== Test delay1 register ===========
# Test inter cs delay
.4byte delay0, 0x00010001, write32_test # reset delay0 register
.4byte delay1, 0x00000005, write32_test # set inter_cs delay to 5
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x44332211, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000011, read32_test
.4byte rx_data, 0x00000022, read32_test
.4byte rx_data, 0x00000033, read32_test
.4byte rx_data, 0x00000044, read32_test
#test long inter_cs delay
.4byte delay1, 0x000000A5, write32_test
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x0000007B, write32_test
.4byte 0x0, 0x00000000, spi_data_wait
.4byte rx_data, 0x0000007B, read32_test
# Test inter_cs delay set to 0
.4byte delay1, 0x00000000, write32_test # set inter_cs delay to 5
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x54433221, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000021, read32_test
.4byte rx_data, 0x00000032, read32_test
.4byte rx_data, 0x00000043, read32_test
.4byte rx_data, 0x00000054, read32_test
# Test inter_xfr delay of 0 (maybe change behavior to half-period instead of period)
.4byte delay1, 0x00000001, write32_test # reset inter_cs delay to 1
.4byte cs_mode, 0x00000002, write32_test # set cs_mode to HOLD
.4byte tx_data, 0x99887766, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000066, read32_test
.4byte rx_data, 0x00000077, read32_test
.4byte rx_data, 0x00000088, read32_test
.4byte rx_data, 0x00000099, read32_test
# Test inter_xfr delay 0 with phase = 1
.4byte sck_mode, 0x00000001, write32_test
.4byte tx_data, 0x99887766, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait
.4byte rx_data, 0x00000066, read32_test
.4byte rx_data, 0x00000077, read32_test
.4byte rx_data, 0x00000088, read32_test
.4byte rx_data, 0x00000099, read32_test
# Test arbitrary inter_xfr delay
.4byte delay1, 0x00050001, write32_test # set inter_xfr delay to 5
.4byte sck_mode, 0x00000001, write32_test
.4byte tx_data, 0x98877665, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000065, read32_test
.4byte rx_data, 0x00000076, read32_test
.4byte rx_data, 0x00000087, read32_test
.4byte rx_data, 0x00000098, read32_test
# test long inter_xfr delay
.4byte delay1, 0x00A50001, write32_test
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x00000048, write32_test
.4byte 0x0, 0x00000000, spi_data_wait
.4byte rx_data, 0x00000048, read32_test
# Test cs-sck delay with cs_mode = HOLD
.4byte delay1, 0x00000001, write32_test # set inter_xfr delay to 0
.4byte delay0, 0x00010005, write32_test # set cs-sck delay to 5 (should have no effect because cs is never inactive)
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0xAABBCCDD, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x000000DD, read32_test # read rx_data
.4byte rx_data, 0x000000CC, read32_test
.4byte rx_data, 0x000000BB, read32_test
.4byte rx_data, 0x000000AA, read32_test
# Test sck-cs delay cs_mode = HOLD
.4byte delay0, 0x00000501, write32_test # set sck-cs delay to 5 (should have no effect because cs is never inactive)
.4byte tx_data, 0xABBCCDDE, spi_burst_send # place 8'h11 into tx_data
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x000000DE, read32_test # read rx_data
.4byte rx_data, 0x000000CD, read32_test
.4byte rx_data, 0x000000BC, read32_test
.4byte rx_data, 0x000000AB, read32_test
# Test hold mode deassert conditions
.4byte delay1, 0x00000001, write32_test # reset delay1 register
.4byte delay0, 0x00010001, write32_test # reset delay0 register
.4byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
.4byte tx_data, 0x000000CE, write32_test # place data into tx_data
.4byte cs_id, 0x00000001, write32_test #change selected cs pin. should deassert cs[0] in hold mode
.4byte cs_def, 0x0000000D, write32_test # change selected cs pins def value. should deassert cs[1]
.4byte cs_mode, 0x00000000, write32_test # change cs_mode to auto, should deassert cs[1], have now gone through all deassertion conditions
.4byte cs_def, 0x0000000F, write32_test # reset cs_def
.4byte cs_id, 0x00000000, write32_test # reset cs_id
.4byte rx_data, 0x000000CE, read32_test # clear rx_fifo
# =========== Test frame format (fmt) register ===========
# Test frame length of 4
.4byte delay1, 0x00000001, write32_test # reset delay1 register
.4byte delay0, 0x00010001, write32_test # reset delay0 register
.4byte sck_mode, 0x00000000, write32_test #reset sckmode register
.4byte cs_mode, 0x00000000, write32_test # set cs_mode to AUTO
.4byte fmt, 0x00040000, write32_test # set frame length to 4
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x000000F0, read32_test # read rx_data
# Test frame length of 0
#.4byte fmt, 0x00000000, write32_test # set frame length to 4
#.4byte tx_data, 0x00000077, write32_test # place 8'h11 into tx_data
#.4byte 0x0, 0x0101, spi_data_wait # wait for transmission to end
#.4byte rx_data, 0x00000077, read32_test # read rx_data
# test frame length 1 burst
.4byte fmt, 0x00010000, write32_test
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x80008000, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait
.4byte rx_data, 0x00000000, read32_test
.4byte rx_data, 0x00000080, read32_test
.4byte rx_data, 0x00000000, read32_test
.4byte rx_data, 0x00000080, read32_test
# Test big endian with frame length = 5
.4byte fmt, 0x00050000, write32_test # set frame length to 5, big endian
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x000000A8, read32_test # read rx_data
# Test big endian burst with frame length = 5
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x03774FFF, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait
.4byte rx_data, 0x000000F8, read32_test
.4byte rx_data, 0x00000048, read32_test
.4byte rx_data, 0x00000070, read32_test
.4byte rx_data, 0x00000000, read32_test
# Test little endian with frame length = 5
.4byte fmt, 0x00050004, write32_test # set frame length to 5, little-endian
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.4byte rx_data, 0x00000008, read32_test # read rx_data -> 08
#test little endian burst with frame length = 5
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0xFF4F7703, spi_burst_send
.4byte 0x0, 0x00000003, spi_data_wait
.4byte rx_data, 0x00000003, read32_test #03
.4byte rx_data, 0x00000017, read32_test #17
.4byte rx_data, 0x0000000F, read32_test #0F
.4byte rx_data, 0x0000001F, read32_test #1F
# Test dual SPI protocol, frame length = 8, big endian
#.4byte fmt, 0x00080001, write32_test # set frame length to 8, big-endian, dual SPI
#.4byte tx_data, 0x000000C8, write32_test # place 8'h11 into tx_data
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.4byte rx_data, 0x00000000, read32_test # read rx_data
# Test dual SPI protocol, frame length = 4
#.4byte fmt, 0x00040001, write32_test # set frame length to 8, big-endian, dual SPI
#.4byte tx_data, 0x000000A2, write32_test # place 8'h11 into tx_data
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.4byte rx_data, 0x000000A0, read32_test # read rx_data
# Test dual SPI protocol, frame length = 5
#.4byte fmt, 0x00050001, write32_test # set frame length to 8, big-endian, dual SPI
#.4byte tx_data, 0x00000075, write32_test # place 8'h11 into tx_data
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.4byte rx_data, 0x00000074, read32_test # read rx_data
# Test dual SPI protocol burst, frame length = 5
#.4byte tx_data, 0x30733FFF, spi_burst_send
#.4byte 0x0, 0x00000003, spi_data_wait
#.4byte rx_data, 0x000000FC, read32_test
#.4byte rx_data, 0x0000003C, read32_test
#.4byte rx_data, 0x00000070, read32_test
#.4byte rx_data, 0x00000030, read32_test
# Test quad SPI protocol, frame length = 5
#.4byte fmt, 0x00050002, write32_test # set frame length to 8, big-endian, dual SPI
#.4byte tx_data, 0x0000003F, write32_test # place 8'h11 into tx_data
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.4byte rx_data, 0x0000003F, read32_test # read rx_data
# Test quad SPI protocol, frame length = 4
#.4byte fmt, 0x00040002, write32_test # set frame length to 8, big-endian, dual SPI
#.4byte tx_data, 0x0000000F, write32_test # place 8'h11 into tx_data
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.4byte rx_data, 0x00000000, read32_test # read rx_data
# Test quad SPI protocol, frame length = 8
#.4byte fmt, 0x00080002, write32_test # set frame length to 8, big-endian, dual SPI
#.4byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.4byte rx_data, 0x000000F0, read32_test # read rx_data
#=========== Test Hardware Interlock ================
# interlock in base case
.4byte fmt, 0x00080000, write32_test # reset fmt register
.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x00000062, write32_test # initiate transmission
.4byte sck_mode, 0x00000002, write32_test # flip polarity during transmission
.4byte tx_data, 0x00000026, write32_test # transmit second frame w/ control register updated
.4byte 0x0, 0x00000001, spi_data_wait
.4byte rx_data, 0x00000062, read32_test
.4byte rx_data, 0x00000026, read32_test # clear rx fifo
.4byte sck_mode, 0x00000000, write32_test # reset polarity
# interlock in case where cs_mode is auto, but there is minimal intercs delay
.4byte delay0, 0x00000001, write32_test # set sck-cs delay to 0, with sck.pha 0 there is 0 delay
.4byte tx_data, 0x000000D2, write32_test # initiate transmission
.4byte sck_mode, 0x00000002, write32_test # flip sck polarity
.4byte tx_data, 0x0000002D, write32_test # transmit second frame
.4byte 0x0, 0x00000001, spi_data_wait
.4byte rx_data, 0x000000D2, read32_test
.4byte rx_data, 0x0000002D, read32_test # clear rx fifo
.4byte sck_mode, 0x00000000, write32_test # reset polarity
# interlock in case where cs_mode = hold, 0 intercs delay
.4byte delay0, 0x00010001, write32_test # reset delay0
.4byte sck_mode, 0x00000000, write32_test # reset polarity
.4byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
.4byte tx_data, 0x15263748, spi_burst_send # place 4 frames into tx fifo
.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte sck_mode, 0x00000000, write32_test # flip polarity again
.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.4byte rx_data, 0x00000048, read32_test
.4byte rx_data, 0x00000037, read32_test
.4byte rx_data, 0x00000026, read32_test
.4byte rx_data, 0x00000015, read32_test #clear rx fifo
# interlock in case where cs_mode = hold, intercs delay
.4byte sck_mode, 0x00000000, write32_test # reset polarity
.4byte delay1, 0x00010001, write32_test # set intercs delay to 1
.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x51627384, spi_burst_send # place 4 frames into tx fifo
.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte sck_mode, 0x00000000, write32_test # flip polarity again
.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.4byte rx_data, 0x00000084, read32_test
.4byte rx_data, 0x00000073, read32_test
.4byte rx_data, 0x00000062, read32_test
.4byte rx_data, 0x00000051, read32_test #clear rx fifo
# repeat previous set of tests with cs_mode = off
.4byte cs_mode, 0x00000003, write32_test # set cs_mode to hold
.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x13243546, spi_burst_send # place 4 frames into tx fifo
.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte sck_mode, 0x00000000, write32_test # flip polarity again
.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.4byte rx_data, 0x00000046, read32_test
.4byte rx_data, 0x00000035, read32_test
.4byte rx_data, 0x00000024, read32_test
.4byte rx_data, 0x00000013, read32_test #clear rx fifo
# interlock in case where cs_mode = hold, intercs delay
.4byte sck_mode, 0x00000000, write32_test # reset polarity
.4byte delay1, 0x00000000, write32_test # set intercs delay to 0
.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.4byte tx_data, 0x31425364, spi_burst_send # place 4 frames into tx fifo
.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.4byte sck_mode, 0x00000000, write32_test # flip polarity again
.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.4byte rx_data, 0x00000064, read32_test
.4byte rx_data, 0x00000053, read32_test
.4byte rx_data, 0x00000042, read32_test
.4byte rx_data, 0x00000031, read32_test #clear rx fifo
# =========== Test watermark interrupts ===========
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
SETUP_PLIC
.4byte delay1, 0x0000001, write32_test # reset delay1 register
.4byte cs_mode, 0x00000000, write32_test # reset cs_mode
.4byte tx_mark, 0x00000001, write32_test # set transmit watermark to 1 (any entry turns mark off)
#.4byte ie, 0x00000000, write32_test # enable transmit interrupt
.4byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
.4byte 0x0, 0x00000000, readmip_test
.4byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
.4byte ip, 0x00000000, read32_test # tx watermark interupt should be off 125
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
.4byte tx_mark, 0x00000000, write32_test # set tx_mark to 0
.4byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
.4byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
#.4byte ie, 0x0000002, write32_test # enable receive interrupts
.4byte ip, 0x00000000, read32_test # rx interrupts should be low (rx FIFO has 3 entries)
.4byte rx_mark, 0x00000002, write32_test # set recieve watermark to 2
.4byte ip, 0x00000002, read32_test # recieve interrupt should be high
.4byte 0x0, 0x00000000, readmip_test
.4byte rx_data, 0x00000033, read32_test # clear one more entry from recieve FIFO (2 entries)
.4byte ip, 0x00000000, read32_test # receive interrupt should be low
.4byte rx_data, 0x00000044, read32_test
.4byte rx_data, 0x00000055, read32_test # clear rx fifo
.4byte tx_mark, 0x00000001, write32_test # set transmit watermark to 0
.4byte ie, 0x00000001, write32_test # enable transmit interrupt
.4byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
.4byte 0x0, 0x00000800, readmip_test
.4byte ie, 0x00000000, write32_test # disable tx intr
.4byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
.4byte tx_mark, 0x00000000, write32_test
.4byte 0x0, 0x00000000, claim_m_plic_interrupts
.4byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
.4byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
.4byte ie, 0x0000002, write32_test # enable receive interrupts
.4byte ip, 0x00000000, read32_test # rx interrupts should be low (rx FIFO has 3 entries)
.4byte 0x0, 0x00000000, readmip_test
.4byte rx_mark, 0x00000002, write32_test # set recieve watermark to 2
.4byte ip, 0x00000002, read32_test # recieve interrupt should be high
.4byte 0x0, 0x00000800, readmip_test
.4byte rx_data, 0x00000033, read32_test # clear one more entry from recieve FIFO (2 entries)
.4byte 0x0, 0x00000000, claim_m_plic_interrupts
.4byte ip, 0x00000000, read32_test # receive interrupt should be low
.4byte 0x0, 0x00000000, readmip_test
.4byte 0x0, 0x0, terminate_test

View file

@ -54,6 +54,9 @@ target_tests_nosim = \
WALLY-trap-s-01 \
WALLY-trap-u-01 \
WALLY-status-fp-enabled-01 \
WALLY-spi-01 \
WALLY-gpio-01 \
WALLY-uart-01 \
WALLY-wfi-01 \
WALLY-cbom-01 \
WALLY-cboz-01 \

View file

@ -0,0 +1,288 @@
00000003 # reset tests sck_div
00000000
00000000 # sck_mode
00000000
00000000 # cs_id
00000000
0000000F # cs_def
00000000
00000000 # cs_mode
00000000
00010001 # delay 0
00000000
00000001 # delay 1
00000000
00080000 # fmt
00000000
00000000 # tx_data
00000000
00000000 # tx_mark
00000000
00000000 # rx_mark
00000000
00000000 # ie reset
00000000
00000000 # ip reset
00000000
00000000 # fifo watermark and edge case tests
00000000
00000001
00000000
00000003
00000000
00000003
00000000
00000074
00000000
00000063
00000000
00000052
00000000
00000041
00000000
000000A1
00000000
00000003
00000000
000000B2
00000000
00000001
00000000
000000C3
00000000
000000D4
00000000
00000003
00000000
000000A4
00000000
00000001
00000000
000000B4
00000000
000000A5
00000000
000000B5
00000000
000000C5
00000000
000000D5
00000000
000000A7
00000000
000000B7
00000000
000000C7
00000000
00000002
00000000
000000D7
00000000
00000000
00000000
00000011 #basic read write
00000000
000000FF
00000000
000000A0
00000000
0000000B
00000000
00000079
00000000
00000000
00000000
000000C0
00000000
00000011
00000000
00000020 #delay registers
00000000
00000032
00000000
00000048
00000000
000000AF
00000000
00000050
00000000
0000006B
00000000
00000011
00000000
00000015
00000000
00000011 #delay1
00000000
00000022
00000000
00000033
00000000
00000044
00000000
0000007B
00000000
00000021
00000000
00000032
00000000
00000043
00000000
00000054
00000000
00000066
00000000
00000077
00000000
00000088
00000000
00000099
00000000
00000066
00000000
00000077
00000000
00000088
00000000
00000099
00000000
00000065
00000000
00000076
00000000
00000087
00000000
00000098
00000000
00000048
00000000
000000DD
00000000
000000CC
00000000
000000BB
00000000
000000AA
00000000
000000DE
00000000
000000CD
00000000
000000BC
00000000
000000AB
00000000
000000CE hold mode deassert
00000000
000000F0 #fmt register
00000000
00000000
00000000
00000080
00000000
00000000
00000000
00000080
00000000
000000A8
00000000
000000F8
00000000
00000048
00000000
00000070
00000000
00000000
00000000
00000008
00000000
00000003
00000000
00000017
00000000
0000000F
00000000
0000001F
00000000
00000062 # hardware interlock
00000000
00000026
00000000
000000D2
00000000
0000002D
00000000
00000048
00000000
00000037
00000000
00000026
00000000
00000015
00000000
00000084
00000000
00000073
00000000
00000062
00000000
00000051
00000000
00000046
00000000
00000035
00000000
00000024
00000000
00000013
00000000
00000064
00000000
00000053
00000000
00000042
00000000
00000031
00000000
00000001 #watermark interrupts
00000000
00000000 #read mip
00000000
00000000 #read tx ip
00000000
00000022 #clear 1 frame from rx fifo
00000000
00000000 # read recieve ip
00000000
00000002 #read recieve ip
00000000
00000000 #read mip
00000000
00000033 #clear frame
00000000
00000000 # read receive ip
00000000
00000044 #clear frame
00000000
00000055 #clear frame
00000000
00000001 #read tx ip
00000000
00000800 #read mip
00000000
00000022 #clear frame
00000000
00000000 #read rx ip
00000000
00000000 #read mip 94
00000000
00000002 #read rx ip
00000000
00000800 #read mip
00000000
00000033 #clear frame
00000000
00000000 #read rx wm
00000000
00000000 #read mip 99
00000000

View file

@ -886,6 +886,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
.equ PLIC_INTPRI_GPIO, 0x0C00000C # GPIO is interrupt 3
.equ PLIC_INTPRI_UART, 0x0C000028 # UART is interrupt 10
.equ PLIC_INTPRI_SPI, 0x0C000018 # SPI in interrupt 6
.equ PLIC_INTPENDING0, 0x0C001000 # intPending0 register
.equ PLIC_INTEN00, 0x0C002000 # interrupt enables for context 0 (machine mode) sources 31:1
.equ PLIC_INTEN10, 0x0C002080 # interrupt enables for context 1 (supervisor mode) sources 31:1
@ -898,6 +899,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
.8byte PLIC_THRESH1, 7, write32_test # Set PLIC supervisor mode interrupt threshold to 7 to accept no interrupts
.8byte PLIC_INTPRI_GPIO, 7, write32_test # Set GPIO to high priority
.8byte PLIC_INTPRI_UART, 7, write32_test # Set UART to high priority
.8byte PLIC_INTPRI_SPI, 7, write32_test # Set SPI to high priority
.8byte PLIC_INTEN00, 0xFFFFFFFF, write32_test # Enable all interrupt sources for machine mode
.8byte PLIC_INTEN10, 0x00000000, write32_test # Disable all interrupt sources for supervisor mode
.endm
@ -1067,6 +1069,12 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
sw t3, 0(t2)
sw t4, -4(sp)
addi sp, sp, -4
li t2, 0x0C000018 // SPI priority
li t3, 7
lw t4, 0(t2)
sw t3, 0(t2)
sw t4, -4(sp)
addi sp, sp, -4
li t2, 0x0C002000
li t3, 0x0C200004
li t4, 0xFFF
@ -1077,11 +1085,14 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
sw t6, 0(t2) // restore saved enable status
li t2, 0x0C00000C // GPIO priority
li t3, 0x0C000028 // UART priority
lw t4, 4(sp) // load stored GPIO and UART priority
lw t5, 0(sp)
addi sp, sp, 8 // restore stack pointer
sw t4, 0(t2)
sw t5, 0(t3)
li t6, 0x0C000018 // SPI priority
lw a4, 8(sp) // load stored GPIO prioroty
lw t4, 4(sp) // load stored UART priority
lw t5, 0(sp) // load stored SPI priority
addi sp, sp, 12 // restore stack pointer
sw a4, 0(t2)
sw t4, 0(t3)
sw t5, 0(t6)
j test_loop
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
@ -1167,6 +1178,34 @@ uart_clearmodemintr:
lb t2, 0(t2)
j test_loop
spi_data_wait:
li t2, 0x10040054
sw t4, 0(t2) // set rx watermark level
li t2, 0x10040074
lw t3, 0(t2) //read ip (interrupt pending register)
slli t3, t3, 56
srli t3, t3, 56
li t2, 0x00000002
bge t3, t2, spi_data_ready //branch to done if transmission complete
j spi_data_wait //else check again
spi_data_ready:
li t2, 0x10040070
li t3, 0x00000000
sw t3, 0(t2) //disable rx watermark interrupt
j test_loop
spi_burst_send: //function for loading multiple frames at once to test delays without returning to test loop
mv t2, t4
sw t2, 0(t3)
srli t2, t2, 8
sw t2, 0(t3)
srli t2, t2, 8
sw t2, 0(t3)
srli t2, t2, 8
sw t2, 0(t3)
j test_loop
goto_s_mode:
// return to address in t3,
li a0, 3 // Trap handler behavior (go to supervisor mode)

View file

@ -0,0 +1,662 @@
///////////////////////////////////////////
//
// WALLY-spi
//
// Author: David_Harris@hmc.edu and Naiche Whyte-Aguayo
//
// Created 2023-02-01
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
#include "WALLY-TEST-LIB-64.h"
RVTEST_ISA("RV64I_Zicsr_Zifencei")
RVTEST_CASE(0,"//check ISA:=regex(.*64.*);check ISA:=regex(.*I.*); def Drvtest_mtrap_routine=True;def TEST_CASE_1=True;def NO_SAIL=True;",spi)
INIT_TESTS
TRAP_HANDLER m
j run_test_loop // begin test loop/table tests instead of executing inline code.
INIT_TEST_TABLE
END_TESTS
TEST_STACK_AND_DATA
.align 3
test_cases:
# ---------------------------------------------------------------------------------------------
# Test Contents
#
# Here is where the actual tests are held, or rather, what the actual tests do.
# each entry consists of 3 values that will be read in as follows:
#
# '.8byte [x28 Value], [x29 Value], [x30 value]'
# or
# '.8byte [address], [value], [test type]'
#
# The encoding for x30 test type values can be found in the test handler in the framework file
# ---------------------------------------------------------------------------------------------
.equ SPI, 0x10040000
.equ sck_div, (SPI+0x00)
.equ sck_mode, (SPI+0x04)
.equ cs_id, (SPI+0x10)
.equ cs_def, (SPI+0x14)
.equ cs_mode, (SPI+0x18)
.equ delay0, (SPI+0x28)
.equ delay1, (SPI+0x2C)
.equ fmt, (SPI+0x40)
.equ tx_data, (SPI+0x48)
.equ rx_data, (SPI+0x4C)
.equ tx_mark, (SPI+0x50)
.equ rx_mark, (SPI+0x54)
.equ ie, (SPI+0x70)
.equ ip, (SPI+0x74)
# =========== Verify all registers reset to correct values ===========
.8byte sck_div, 0x00000003, read32_test # sck_div reset to 0x3
.8byte sck_mode, 0x00000000, read32_test # sck_mode reset to 0x0
.8byte cs_id, 0x00000000, read32_test # cs_id reset to 0x0
.8byte cs_def, 0x0000000F, read32_test # cs_def reset to 0x1
.8byte cs_mode, 0x00000000, read32_test # cs_mode reset to 0x0
.8byte delay0, 0x00010001, read32_test # delay0 reset to [31:24] 0x0, [23:16] 0x1, [15:8] 0x0, [7:0] 0x1
.8byte delay1, 0x00000001, read32_test # delay1 reset to 0x1
.8byte fmt, 0x00080000, read32_test # fmt reset to [31:20] 0x0, [19:16] 0x8, [15:0] 0x0 for non-flash enabled SPI controllers
.8byte tx_data, 0x00000000, read32_test # tx_data [30:0] reset to 0x0, [31] read only
.8byte tx_mark, 0x00000000, read32_test # tx_mark reset to 0x0 for non-flash enabled controllers
.8byte rx_mark, 0x00000000, read32_test # rx_mark reset to 0x0
.8byte ie, 0x00000000, read32_test # ie reset to 0x0
.8byte ip, 0x00000000, read32_test # ip reset to 0x0
# =========== watermark interrupts ===============
#test watermark interrupts at beginning where fifo read/write pointers are known b/c reset
# txwmp raised when # of entries in txfifo < txmark, rxwm raised when # of entries in rxfifo > rxmark
.8byte ip, 0x00000000, read32_test # txfifo entries not < 0, rxfifo entries not > 0;
.8byte tx_mark, 0x00000004, write32_test # set tx_mark to 4
.8byte rx_mark, 0x00000003, write32_test # set rx_mark to 3
.8byte ip, 0x00000001, read32_test # tx entries < 4, rx entries ! > 3
.8byte tx_data, 0x41526374, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait
.8byte ip, 0x00000003, read32_test # tx entries < 4, rx entries > 3, visual inspection should see tx TransmitFIFOReadIncrement
# txfifo wptr now at 0011, rxfifo wptr at 0000
.8byte rx_mark, 0x00000007, write32_test # set rx_mark to 7
.8byte tx_data, 0xD4C3B2A1, spi_burst_send
.8byte 0x0, 0x00000007, spi_data_wait # rxfifo full, txfifo wptr at 1000, rxfifo wptr at 0000
.8byte ip, 0x00000003, read32_test
.8byte rx_data, 0x00000074, read32_test
.8byte rx_data, 0x00000063, read32_test # clear 2 entries, txfifo wptr at 1000, rxfifo wptr at 0010
.8byte tx_data, 0x000000A4, write32_test
.8byte tx_data, 0x000000B4, write32_test # tx 1010, rx 0010
.8byte 0x0, 0x00000007, spi_data_wait # 8 tx 1010, rx 0010
.8byte rx_mark, 0x00000004, write32_test
.8byte rx_data, 0x00000052, read32_test # 7 rx 0011
.8byte rx_data, 0x00000041, read32_test # 6 rx 0100
.8byte rx_data, 0x000000A1, read32_test # 5 rx 0101
.8byte ip, 0x00000003, read32_test # 5 things in rx fifo
.8byte rx_data, 0x000000B2, read32_test # 4 tx 1010, rx 0110
.8byte ip, 0x00000001, read32_test # 4 entries in rxfifo, not strictly greater than 4
.8byte rx_mark, 0x00000007, write32_test
.8byte tx_data, 0xD5C5B5A5, spi_burst_send # 8 tx1110, rx 0110
.8byte 0x0, 0x00000007, spi_data_wait
.8byte rx_mark, 0x00000005, write32_test
.8byte rx_data, 0x000000C3, read32_test # tx 1110, rx 0111
.8byte rx_data, 0x000000D4, read32_test # tx 1110, rx 1000
.8byte ip, 0x00000003, read32_test # 6 entries
.8byte rx_data, 0x000000A4, read32_test # tx 1110, rx 1001
.8byte ip, 0x00000001, read32_test # 5 entries
.8byte rx_data, 0x000000B4, read32_test # tx 1110, rx 1010
.8byte rx_data, 0x000000A5, read32_test # tx 1110, rx 1011
.8byte rx_mark, 0x00000006, write32_test
.8byte tx_data, 0xD7C7B7A7, spi_burst_send
.8byte 0x0, 0x00000006, spi_data_wait # tx 0010, rx 1011
.8byte tx_mark, 0x00000000, write32_test
.8byte rx_mark, 0x00000000, write32_test
.8byte rx_data, 0x000000B5, read32_test # tx 0010, rx 1100
.8byte rx_data, 0x000000C5, read32_test # tx 0010, rx 1101
.8byte rx_data, 0x000000D5, read32_test # tx 0010, rx 1110
.8byte rx_data, 0x000000A7, read32_test # tx 0010, rx 1111
.8byte rx_data, 0x000000B7, read32_test # tx 0010, rx 0000
.8byte rx_data, 0x000000C7, read32_test # tx 0010, rx 0001
.8byte ip, 0x00000002, read32_test
.8byte rx_data, 0x000000D7, read32_test # tx 0010, rx 1010
.8byte ip, 0x00000000, read32_test
.8byte tx_mark, 0x00000000, write32_test
.8byte rx_mark, 0x00000000, write32_test # reset watermark registers
# =========== Basic read-write ===========
.8byte tx_data, 0x000000011, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000011, read32_test # read rx_data
# =========== Different cs_mode, sck_mode, cs_def, sck_div ===========
# Test sck_div
.8byte sck_div, 0x00000101, write32_test # set sck_div to 0x101
.8byte tx_data, 0x000000FF, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000FF, read32_test # read rx_data
# Test phase
.8byte sck_div, 0x00000003, write32_test # reset sck_div to 0x03 so only sck_mode is different
.8byte sck_mode, 0x00000001, write32_test # change phase to falling edge
.8byte tx_data, 0x000000A0, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000A0, read32_test # read rx_data
# Test polarity
.8byte sck_mode, 0x00000000, write32_test # reset sck phase to rising edge
.8byte sck_mode, 0x00000002, write32_test # set sck polarity active low
.8byte tx_data, 0x0000000B, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x0000000B, read32_test # read rx_data
# Test chip select polarity
.8byte sck_mode, 0x00000000, write32_test # reset sck polarity to active high
.8byte cs_def, 0x0000000E, write32_test # set cs[0] to inactive low
.8byte tx_data, 0x00000079, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000079, read32_test # read rx_data
# Test chip id
.8byte cs_def, 0x0000000F, write32_test # reset all cs to active low
.8byte cs_id, 0x00000001, write32_test # select cs[1]
.8byte tx_data, 0x00000000, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000000, read32_test # read rx_data
# Test cs hold mode
.8byte cs_id, 0x00000000, write32_test # select cs[0]
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to HOLD
.8byte tx_data, 0x000000C0, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000C0, read32_test # read rx_data
# Test cs OFF mode
.8byte cs_mode, 0x00000003, write32_test # set cs_mode to OFF
.8byte tx_data, 0x00000011, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000011, read32_test # read rx_data
# =========== Test delay0 register ===========
# Test cs-sck delay of 0 with sck phase = 0 (implicit half cycle delay)
.8byte cs_mode, 0x00000000, write32_test # reset cs_mode to auto, all cs and sck mode settings should be defualt
.8byte delay0, 0x00010000, write32_test # set cs-sck delay to 0
.8byte tx_data, 0x00000020, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000020, read32_test # read rx_data
# Test cs-sck delay of 0 with sck phase 1 (no delay)
.8byte sck_mode, 0x00000001, write32_test # set sck_mode[0] to 1 (sck phase = 1)
.8byte tx_data, 0x00000032, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000032, read32_test # read rx_data
# Test arbitrary cs-sck delay (sck phase 1)
.8byte delay0, 0x00010005, write32_test # set cs-sck delay to 5 cycles
.8byte tx_data, 0x00000048, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000048, read32_test # read rx_data
# Test arbitrary cs-sck delay (sck phase 0)
.8byte sck_mode, 0x00000000, write32_test # set sck phase to 0
.8byte delay0, 0x00010005, write32_test # set cs-sck delay to AF cycles
.8byte tx_data, 0x000000AF, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000AF, read32_test # read rx_data
# Test sck-cs delay of 0 with sck phase = 0 (no delay)
.8byte delay0, 0x00000001, write32_test # set cs-sck delay to 0
.8byte tx_data, 0x00000050, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000050, read32_test # read rx_data
# Test sck-cs delay of 0 with sck phase 1 (implicit half cycle delay)
.8byte sck_mode, 0x00000001, write32_test # set sck_mode[0] to 1 (sck phase = 1)
.8byte tx_data, 0x0000006B, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x0000006B, read32_test # read rx_data
# Test arbitrary sck-cs delay (sck phase 1)
.8byte delay0, 0x00050001, write32_test # set cs-sck delay to A5 cycles
.8byte tx_data, 0x00000011, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000011, read32_test # read rx_data
# Test arbitrary sck-cs delay (sck phase 0)
.8byte sck_mode, 0x00000000, write32_test # set sck phase to 0
.8byte delay0, 0x00050001, write32_test # set cs-sck delay to 5 cycles
.8byte tx_data, 0x00000015, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000015, read32_test # read rx_data
# =========== Test delay1 register ===========
# Test inter cs delay
.8byte delay0, 0x00010001, write32_test # reset delay0 register
.8byte delay1, 0x00000005, write32_test # set inter_cs delay to 5
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x44332211, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000011, read32_test
.8byte rx_data, 0x00000022, read32_test
.8byte rx_data, 0x00000033, read32_test
.8byte rx_data, 0x00000044, read32_test
#test long inter_cs delay
.8byte delay1, 0x000000A5, write32_test
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x0000007B, write32_test
.8byte 0x0, 0x00000000, spi_data_wait
.8byte rx_data, 0x0000007B, read32_test
# Test inter_cs delay set to 0
.8byte delay1, 0x00000000, write32_test # set inter_cs delay to 5
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x54433221, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000021, read32_test
.8byte rx_data, 0x00000032, read32_test
.8byte rx_data, 0x00000043, read32_test
.8byte rx_data, 0x00000054, read32_test
# Test inter_xfr delay of 0 (maybe change behavior to half-period instead of period)
.8byte delay1, 0x00000001, write32_test # reset inter_cs delay to 1
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to HOLD
.8byte tx_data, 0x99887766, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000066, read32_test
.8byte rx_data, 0x00000077, read32_test
.8byte rx_data, 0x00000088, read32_test
.8byte rx_data, 0x00000099, read32_test
# Test inter_xfr delay 0 with phase = 1
.8byte sck_mode, 0x00000001, write32_test
.8byte tx_data, 0x99887766, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait
.8byte rx_data, 0x00000066, read32_test
.8byte rx_data, 0x00000077, read32_test
.8byte rx_data, 0x00000088, read32_test
.8byte rx_data, 0x00000099, read32_test
# Test arbitrary inter_xfr delay
.8byte delay1, 0x00050001, write32_test # set inter_xfr delay to 5
.8byte sck_mode, 0x00000001, write32_test
.8byte tx_data, 0x98877665, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000065, read32_test
.8byte rx_data, 0x00000076, read32_test
.8byte rx_data, 0x00000087, read32_test
.8byte rx_data, 0x00000098, read32_test
# test long inter_xfr delay
.8byte delay1, 0x00A50001, write32_test
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x00000048, write32_test
.8byte 0x0, 0x00000000, spi_data_wait
.8byte rx_data, 0x00000048, read32_test
# Test cs-sck delay with cs_mode = HOLD
.8byte delay1, 0x00000001, write32_test # set inter_xfr delay to 0
.8byte delay0, 0x00010005, write32_test # set cs-sck delay to 5 (should have no effect because cs is never inactive)
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0xAABBCCDD, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000DD, read32_test # read rx_data
.8byte rx_data, 0x000000CC, read32_test
.8byte rx_data, 0x000000BB, read32_test
.8byte rx_data, 0x000000AA, read32_test
# Test sck-cs delay cs_mode = HOLD
.8byte delay0, 0x00000501, write32_test # set sck-cs delay to 5 (should have no effect because cs is never inactive)
.8byte tx_data, 0xABBCCDDE, spi_burst_send # place 8'h11 into tx_data
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000DE, read32_test # read rx_data
.8byte rx_data, 0x000000CD, read32_test
.8byte rx_data, 0x000000BC, read32_test
.8byte rx_data, 0x000000AB, read32_test
# Test hold mode deassert conditions
.8byte delay1, 0x00000001, write32_test # reset delay1 register
.8byte delay0, 0x00010001, write32_test # reset delay0 register
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
.8byte tx_data, 0x000000CE, write32_test # place data into tx_data
.8byte cs_id, 0x00000001, write32_test #change selected cs pin. should deassert cs[0] in hold mode
.8byte cs_def, 0x0000000D, write32_test # change selected cs pins def value. should deassert cs[1]
.8byte cs_mode, 0x00000000, write32_test # change cs_mode to auto, should deassert cs[1], have now gone through all deassertion conditions
.8byte cs_def, 0x0000000F, write32_test # reset cs_def
.8byte cs_id, 0x00000000, write32_test # reset cs_id
.8byte rx_data, 0x000000CE, read32_test # clear rx_fifo
# =========== Test frame format (fmt) register ===========
# Test frame length of 4
.8byte delay1, 0x00000001, write32_test # reset delay1 register
.8byte delay0, 0x00010001, write32_test # reset delay0 register
.8byte sck_mode, 0x00000000, write32_test #reset sckmode register
.8byte cs_mode, 0x00000000, write32_test # set cs_mode to AUTO
.8byte fmt, 0x00040000, write32_test # set frame length to 4
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000F0, read32_test # read rx_data
# Test frame length of 0
#.8byte fmt, 0x00000000, write32_test # set frame length to 4
#.8byte tx_data, 0x00000077, write32_test # place 8'h11 into tx_data
#.8byte 0x0, 0x0101, spi_data_wait # wait for transmission to end
#.8byte rx_data, 0x00000077, read32_test # read rx_data
# test frame length 1 burst
.8byte fmt, 0x00010000, write32_test
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x80008000, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait
.8byte rx_data, 0x00000000, read32_test
.8byte rx_data, 0x00000080, read32_test
.8byte rx_data, 0x00000000, read32_test
.8byte rx_data, 0x00000080, read32_test
# Test big endian with frame length = 5
.8byte fmt, 0x00050000, write32_test # set frame length to 5, big endian
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000A8, read32_test # read rx_data
# Test big endian burst with frame length = 5
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x03774FFF, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait
.8byte rx_data, 0x000000F8, read32_test
.8byte rx_data, 0x00000048, read32_test
.8byte rx_data, 0x00000070, read32_test
.8byte rx_data, 0x00000000, read32_test
# Test little endian with frame length = 5
.8byte fmt, 0x00050004, write32_test # set frame length to 5, little-endian
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000008, read32_test # read rx_data -> 08
#test little endian burst with frame length = 5
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0xFF4F7703, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait
.8byte rx_data, 0x00000003, read32_test #03
.8byte rx_data, 0x00000017, read32_test #17
.8byte rx_data, 0x0000000F, read32_test #0F
.8byte rx_data, 0x0000001F, read32_test #1F
# Test dual SPI protocol, frame length = 8, big endian
#.8byte fmt, 0x00080001, write32_test # set frame length to 8, big-endian, dual SPI
#.8byte tx_data, 0x000000C8, write32_test # place 8'h11 into tx_data
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.8byte rx_data, 0x00000000, read32_test # read rx_data
# Test dual SPI protocol, frame length = 4
#.8byte fmt, 0x00040001, write32_test # set frame length to 8, big-endian, dual SPI
#.8byte tx_data, 0x000000A2, write32_test # place 8'h11 into tx_data
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.8byte rx_data, 0x000000A0, read32_test # read rx_data
# Test dual SPI protocol, frame length = 5
#.8byte fmt, 0x00050001, write32_test # set frame length to 8, big-endian, dual SPI
#.8byte tx_data, 0x00000075, write32_test # place 8'h11 into tx_data
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.8byte rx_data, 0x00000074, read32_test # read rx_data
# Test dual SPI protocol burst, frame length = 5
#.8byte tx_data, 0x30733FFF, spi_burst_send
#.8byte 0x0, 0x00000003, spi_data_wait
#.8byte rx_data, 0x000000FC, read32_test
#.8byte rx_data, 0x0000003C, read32_test
#.8byte rx_data, 0x00000070, read32_test
#.8byte rx_data, 0x00000030, read32_test
# Test quad SPI protocol, frame length = 5
#.8byte fmt, 0x00050002, write32_test # set frame length to 8, big-endian, dual SPI
#.8byte tx_data, 0x0000003F, write32_test # place 8'h11 into tx_data
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.8byte rx_data, 0x0000003F, read32_test # read rx_data
# Test quad SPI protocol, frame length = 4
#.8byte fmt, 0x00040002, write32_test # set frame length to 8, big-endian, dual SPI
#.8byte tx_data, 0x0000000F, write32_test # place 8'h11 into tx_data
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.8byte rx_data, 0x00000000, read32_test # read rx_data
# Test quad SPI protocol, frame length = 8
#.8byte fmt, 0x00080002, write32_test # set frame length to 8, big-endian, dual SPI
#.8byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.8byte rx_data, 0x000000F0, read32_test # read rx_data
#=========== Test Hardware Interlock ================
# interlock in base case
.8byte fmt, 0x00080000, write32_test # reset fmt register
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x00000062, write32_test # initiate transmission
.8byte sck_mode, 0x00000002, write32_test # flip polarity during transmission
.8byte tx_data, 0x00000026, write32_test # transmit second frame w/ control register updated
.8byte 0x0, 0x00000001, spi_data_wait
.8byte rx_data, 0x00000062, read32_test
.8byte rx_data, 0x00000026, read32_test # clear rx fifo
.8byte sck_mode, 0x00000000, write32_test # reset polarity
# interlock in case where cs_mode is auto, but there is minimal intercs delay
.8byte delay0, 0x00000001, write32_test # set sck-cs delay to 0, with sck.pha 0 there is 0 delay
.8byte tx_data, 0x000000D2, write32_test # initiate transmission
.8byte sck_mode, 0x00000002, write32_test # flip sck polarity
.8byte tx_data, 0x0000002D, write32_test # transmit second frame
.8byte 0x0, 0x00000001, spi_data_wait
.8byte rx_data, 0x000000D2, read32_test
.8byte rx_data, 0x0000002D, read32_test # clear rx fifo
.8byte sck_mode, 0x00000000, write32_test # reset polarity
# interlock in case where cs_mode = hold, 0 intercs delay
.8byte delay0, 0x00010001, write32_test # reset delay0
.8byte sck_mode, 0x00000000, write32_test # reset polarity
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
.8byte tx_data, 0x15263748, spi_burst_send # place 4 frames into tx fifo
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.8byte rx_data, 0x00000048, read32_test
.8byte rx_data, 0x00000037, read32_test
.8byte rx_data, 0x00000026, read32_test
.8byte rx_data, 0x00000015, read32_test #clear rx fifo
# interlock in case where cs_mode = hold, intercs delay
.8byte sck_mode, 0x00000000, write32_test # reset polarity
.8byte delay1, 0x00010001, write32_test # set intercs delay to 1
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x51627384, spi_burst_send # place 4 frames into tx fifo
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.8byte rx_data, 0x00000084, read32_test
.8byte rx_data, 0x00000073, read32_test
.8byte rx_data, 0x00000062, read32_test
.8byte rx_data, 0x00000051, read32_test #clear rx fifo
# repeat previous set of tests with cs_mode = off
.8byte cs_mode, 0x00000003, write32_test # set cs_mode to hold
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x13243546, spi_burst_send # place 4 frames into tx fifo
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.8byte rx_data, 0x00000046, read32_test
.8byte rx_data, 0x00000035, read32_test
.8byte rx_data, 0x00000024, read32_test
.8byte rx_data, 0x00000013, read32_test #clear rx fifo
# interlock in case where cs_mode = hold, intercs delay
.8byte sck_mode, 0x00000000, write32_test # reset polarity
.8byte delay1, 0x00000000, write32_test # set intercs delay to 0
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x31425364, spi_burst_send # place 4 frames into tx fifo
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.8byte rx_data, 0x00000064, read32_test
.8byte rx_data, 0x00000053, read32_test
.8byte rx_data, 0x00000042, read32_test
.8byte rx_data, 0x00000031, read32_test #clear rx fifo
# =========== Test watermark interrupts ===========
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
SETUP_PLIC
.8byte delay1, 0x0000001, write32_test # reset delay1 register
.8byte cs_mode, 0x00000000, write32_test # reset cs_mode
.8byte tx_mark, 0x00000001, write32_test # set transmit watermark to 1 (any entry turns mark off)
#.8byte ie, 0x00000000, write32_test # enable transmit interrupt
.8byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
.8byte 0x0, 0x00000000, readmip_test
.8byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
.8byte ip, 0x00000000, read32_test # tx watermark interupt should be off 125
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
.8byte tx_mark, 0x00000000, write32_test # set tx_mark to 0
.8byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
.8byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
#.8byte ie, 0x0000002, write32_test # enable receive interrupts
.8byte ip, 0x00000000, read32_test # rx interrupts should be low (rx FIFO has 3 entries)
.8byte rx_mark, 0x00000002, write32_test # set recieve watermark to 2
.8byte ip, 0x00000002, read32_test # recieve interrupt should be high
.8byte 0x0, 0x00000000, readmip_test
.8byte rx_data, 0x00000033, read32_test # clear one more entry from recieve FIFO (2 entries)
.8byte ip, 0x00000000, read32_test # receive interrupt should be low
.8byte rx_data, 0x00000044, read32_test
.8byte rx_data, 0x00000055, read32_test # clear rx fifo
.8byte tx_mark, 0x00000001, write32_test # set transmit watermark to 0
.8byte ie, 0x00000001, write32_test # enable transmit interrupt
.8byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
.8byte 0x0, 0x00000800, readmip_test
.8byte ie, 0x00000000, write32_test # disable tx intr
.8byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
.8byte tx_mark, 0x00000000, write32_test
.8byte 0x0, 0x00000000, claim_m_plic_interrupts
.8byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
.8byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
.8byte ie, 0x0000002, write32_test # enable receive interrupts
.8byte ip, 0x00000000, read32_test # rx interrupts should be low (rx FIFO has 3 entries)
.8byte 0x0, 0x00000000, readmip_test
.8byte rx_mark, 0x00000002, write32_test # set recieve watermark to 2
.8byte ip, 0x00000002, read32_test # recieve interrupt should be high
.8byte 0x0, 0x00000800, readmip_test
.8byte rx_data, 0x00000033, read32_test # clear one more entry from recieve FIFO (2 entries)
.8byte 0x0, 0x00000000, claim_m_plic_interrupts
.8byte ip, 0x00000000, read32_test # receive interrupt should be low
.8byte 0x0, 0x00000000, readmip_test
.8byte 0x0, 0x0, terminate_test