mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-04-22 12:57:23 -04:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
0e75142ef4
61 changed files with 3844 additions and 1437 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -7,12 +7,8 @@ __pycache__/
|
|||
.vscode/
|
||||
|
||||
#External repos
|
||||
addins
|
||||
addins/riscv-arch-test/Makefile.include
|
||||
addins/riscv-tests/target
|
||||
addins/coremark/work/*
|
||||
addins/embench/bd_speed/*
|
||||
addins/embench/bd_size/*
|
||||
benchmarks/embench/wally*.json
|
||||
|
||||
#vsim work files to ignore
|
||||
|
|
1
.gitmodules
vendored
1
.gitmodules
vendored
|
@ -17,6 +17,7 @@
|
|||
[submodule "addins/embench-iot"]
|
||||
path = addins/embench-iot
|
||||
url = https://github.com/embench/embench-iot
|
||||
branch = embench-1.0-branch
|
||||
[submodule "addins/coremark"]
|
||||
path = addins/coremark
|
||||
url = https://github.com/eembc/coremark
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# Wally Coremark Makefile
|
||||
# Daniel Torres & David Harris 28 July 2022
|
||||
|
||||
PORT_DIR = $(CURDIR)/riscv64-baremetal
|
||||
cmbase=../../addins/coremark
|
||||
# cmbase= ../riscv-coremark/coremark
|
||||
work_dir= ../../benchmarks/coremark/work
|
||||
XLEN ?=64
|
||||
sources=$(cmbase)/core_main.c $(cmbase)/core_list_join.c $(cmbase)/coremark.h \
|
||||
|
@ -9,22 +11,12 @@ sources=$(cmbase)/core_main.c $(cmbase)/core_list_join.c $(cmbase)/coremark.h \
|
|||
$(PORT_DIR)/crt.S $(PORT_DIR)/encoding.h $(PORT_DIR)/util.h $(PORT_DIR)/syscalls.c
|
||||
ABI := $(if $(findstring "64","$(XLEN)"),lp64,ilp32)
|
||||
ARCH := rv$(XLEN)im
|
||||
PORT_CFLAGS = -g -march=rv$(XLEN)im -mabi=$(ABI) -march=$(ARCH) -static -falign-functions=16 \
|
||||
-mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-3-series -O3 -funroll-all-loops -finline-functions -falign-jumps=4 \
|
||||
PORT_CFLAGS = -g -mabi=$(ABI) -march=$(ARCH) -static -falign-functions=16 \
|
||||
-mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-3-series -O3 -finline-functions -falign-jumps=4 \
|
||||
-fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 \
|
||||
-funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta \
|
||||
-nostdlib -nostartfiles -ffreestanding -mstrict-align \
|
||||
-DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 -DPERFORMANCE_RUN=1 -DXLEN=$(XLEN)
|
||||
|
||||
# flags that cause build errors mcmodel=medlow
|
||||
|
||||
# -static -mcmodel=medlow -mtune=sifive-7-series \
|
||||
# -O3 -falign-functions=16 -funroll-all-loops -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET
|
||||
# -finline-functions -falign-jumps=4 \
|
||||
# -nostdlib -nostartfiles -ffreestanding -mstrict-align \
|
||||
# -DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 \
|
||||
# -DPERFORMANCE_RUN=1
|
||||
# "-march=rv$(XLEN)im -mabi=$(ABI) -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta "
|
||||
-DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 -DPERFORMANCE_RUN=1 -DITERATIONS=10 -DXLEN=$(XLEN)
|
||||
|
||||
all: $(work_dir)/coremark.bare.riscv.elf.memfile
|
||||
|
||||
|
@ -38,9 +30,7 @@ $(work_dir)/coremark.bare.riscv.elf.memfile: $(work_dir)/coremark.bare.riscv
|
|||
extractFunctionRadix.sh $<.elf.objdump
|
||||
|
||||
$(work_dir)/coremark.bare.riscv: $(sources) Makefile
|
||||
# These flags were used by WD on CoreMark
|
||||
make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV)/riscv-gnu-toolchain XCFLAGS="$(PORT_CFLAGS)"
|
||||
# -fno-toplevel-reorder --param=max-inline-insns-size=128 " # adding this bit caused a compiler error
|
||||
mkdir -p $(work_dir)
|
||||
mv $(cmbase)/coremark.bare.riscv $(work_dir)
|
||||
|
||||
|
@ -50,14 +40,3 @@ clean:
|
|||
rm -f $(work_dir)/*
|
||||
|
||||
|
||||
|
||||
# # PORT_CFLAGS = -g -march=$(XLEN)im -mabi=$(ABI) -static -mcmodel=medlow -mtune=sifive-3-series \
|
||||
# # -O3 -falign-functions=16 -funroll-all-loops \
|
||||
# # -finline-functions -falign-jumps=4 \
|
||||
# # -nostdlib -nostartfiles -ffreestanding -mstrict-align \
|
||||
# # -DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 \
|
||||
# # -DPERFORMANCE_RUN=1
|
||||
|
||||
# make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV)/riscv-gnu-toolchain XCFLAGS="-march=rv$(XLEN)im -mabi=$(ABI) -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta "
|
||||
# make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=/opt/riscv/riscv-gnu-toolchain XCFLAGS="-march=rv64imd -mabi=lp64d -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fno-toplevel-reorder --param=max-inline-insns-size=128 -fipa-pta"
|
||||
# make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV)/riscv-gnu-toolchain XCFLAGS="-march=rv64imd -mabi=lp64d -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta "
|
|
@ -114,7 +114,12 @@ void portable_free(void *p) {
|
|||
#define read_csr(reg) ({ unsigned long __tmp; \
|
||||
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
||||
__tmp; })
|
||||
#define GETMYTIME(_t) (_t = *(volatile unsigned long long*)0x0200BFF8)
|
||||
// #if (XLEN==64)
|
||||
// typedef unsigned long long ee_ptr_int;
|
||||
// #else
|
||||
// typedef unsigned long ee_ptr_int;
|
||||
// #endif
|
||||
#define GETMYTIME(_t) (_t = *(volatile ee_ptr_int*)0x0200BFF8)
|
||||
#define MYTIMEDIFF(fin,ini) ((fin)-(ini))
|
||||
// Changing TIMER_RES_DIVIDER to 1000000 sets EE_TICKS_PER_SEC to 1000 (now counting ticks per ms)
|
||||
#define TIMER_RES_DIVIDER 10000
|
||||
|
@ -196,8 +201,8 @@ void stop_time(void) {
|
|||
CORE_TICKS get_time(void) {
|
||||
CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
|
||||
unsigned long instructions = minstretDiff();
|
||||
long long cm100 = 1000000000 / elapsed; // coremark score * 100
|
||||
long long cpi100 = elapsed*100/instructions; // CPI * 100
|
||||
ee_ptr_int cm100 = 1000000000 / elapsed; // coremark score * 100
|
||||
ee_ptr_int cpi100 = elapsed*100/instructions; // CPI * 100
|
||||
ee_printf(" WALLY CoreMark Results (from get_time)\n");
|
||||
ee_printf(" Elapsed MTIME: %u\n", elapsed);
|
||||
ee_printf(" Elapsed MINSTRET: %lu\n", instructions);
|
||||
|
|
|
@ -69,14 +69,16 @@ typedef clock_t CORE_TICKS;
|
|||
// #elif (XLEN==32)
|
||||
// #include <sys/types.h>
|
||||
// typedef ee_u32 CORE_TICKS;
|
||||
#else
|
||||
/* Configuration: size_t and clock_t
|
||||
Note these need to match the size of the clock output and the xLen the processor supports
|
||||
*/
|
||||
#elif (XLEN==64)
|
||||
typedef unsigned long int size_t;
|
||||
typedef unsigned long int clock_t;
|
||||
typedef clock_t CORE_TICKS;
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
typedef clock_t CORE_TICKS;
|
||||
|
||||
/* Definitions: COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
|
||||
Initialize these strings per platform
|
||||
|
@ -92,7 +94,7 @@ typedef clock_t CORE_TICKS;
|
|||
#define COMPILER_FLAGS FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */
|
||||
#endif
|
||||
#ifndef MEM_LOCATION
|
||||
#define MEM_LOCATION "Please put data memory location here\n\t\t\t(e.g. code in flash, data on heap etc)"
|
||||
#define MEM_LOCATION "Code and Data in external RAM"
|
||||
#define MEM_LOCATION_UNSPEC 1
|
||||
#endif
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
embench_dir = ../../addins/embench-iot
|
||||
|
||||
all: build sim size
|
||||
all: build
|
||||
run: size sim
|
||||
|
||||
allClean: clean all
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
`define CORRSHIFTSZ ((`DIVRESLEN+`NF) > (3*`NF+8) ? (`DIVRESLEN+`NF) : (3*`NF+6))
|
||||
|
||||
// division constants
|
||||
`define RADIX 32'h2
|
||||
`define RADIX 32'h4
|
||||
`define DIVCOPIES 32'h1
|
||||
`define DIVLEN ((`NF < `XLEN) ? (`XLEN) : (`NF + 3))
|
||||
`define EXTRAFRACBITS ((`NF<(`XLEN)) ? (`XLEN - `NF) : 3)
|
||||
|
|
|
@ -1 +1 @@
|
|||
vsim -c -do "do wally-pipelined-batch.do rv32gc wally32d"
|
||||
vsim -c -do "do wally-pipelined-batch.do rv32gc wally32periph"
|
||||
|
|
|
@ -33,7 +33,7 @@ add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/intera
|
|||
# add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/otfc/otfc2/*
|
||||
# add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/qsel/qsel2/*
|
||||
add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srtpreproc/*
|
||||
add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srt/expcalc/*
|
||||
# add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srt/expcalc/*
|
||||
add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srtfsm/*
|
||||
add wave -group {Testbench} -noupdate /testbenchfp/*
|
||||
add wave -group {Testbench} -noupdate /testbenchfp/readvectors/*
|
||||
|
|
|
@ -60,10 +60,11 @@ module cvtshiftcalc(
|
|||
// - otherwise:
|
||||
// | LzcInM | 0's if nessisary |
|
||||
// change to int shift to the left one
|
||||
assign CvtShiftIn = ToInt ? {{`XLEN{1'b0}}, Xm[`NF]&~CvtCe[`NE], Xm[`NF-1]|(CvtCe[`NE]&Xm[`NF]), Xm[`NF-2:0], {`CVTLEN-`XLEN{1'b0}}} :
|
||||
CvtResDenormUf ? {{`NF-1{1'b0}}, Xm, {`CVTLEN-`NF+1{1'b0}}} :
|
||||
{CvtLzcIn, {`NF+1{1'b0}}};
|
||||
|
||||
|
||||
always_comb
|
||||
if (ToInt) CvtShiftIn = {{`XLEN{1'b0}}, Xm[`NF]&~CvtCe[`NE], Xm[`NF-1]|(CvtCe[`NE]&Xm[`NF]), Xm[`NF-2:0], {`CVTLEN-`XLEN{1'b0}}};
|
||||
else if (CvtResDenormUf) CvtShiftIn = {{`NF-1{1'b0}}, Xm, {`CVTLEN-`NF+1{1'b0}}};
|
||||
else CvtShiftIn = {CvtLzcIn, {`NF+1{1'b0}}};
|
||||
|
||||
// choose the negative of the fraction size
|
||||
if (`FPSIZES == 1) begin
|
||||
|
|
|
@ -34,20 +34,21 @@ module divsqrt(
|
|||
input logic clk,
|
||||
input logic reset,
|
||||
input logic [`FMTBITS-1:0] FmtE,
|
||||
input logic [`NF:0] XManE, YManE,
|
||||
input logic [`NE-1:0] XExpE, YExpE,
|
||||
input logic [`NF:0] XmE, YmE,
|
||||
input logic [`NE-1:0] XeE, YeE,
|
||||
input logic XInfE, YInfE,
|
||||
input logic XZeroE, YZeroE,
|
||||
input logic XNaNE, YNaNE,
|
||||
input logic DivStartE,
|
||||
input logic StallM,
|
||||
input logic StallE,
|
||||
output logic DivStickyM,
|
||||
input logic StallE,
|
||||
input logic SqrtE, SqrtM,
|
||||
output logic DivSM,
|
||||
output logic DivBusy,
|
||||
output logic DivDone,
|
||||
output logic [`NE+1:0] DivCalcExpM,
|
||||
output logic [`NE+1:0] QeM,
|
||||
output logic [`DURLEN-1:0] EarlyTermShiftM,
|
||||
output logic [`QLEN-1-(`RADIX/4):0] QuotM
|
||||
output logic [`QLEN-1-(`RADIX/4):0] QmM
|
||||
// output logic [`XLEN-1:0] RemM,
|
||||
);
|
||||
|
||||
|
@ -55,15 +56,15 @@ module divsqrt(
|
|||
logic [`DIVLEN+3:0] WS, WC;
|
||||
logic [`DIVLEN+3:0] StickyWSA;
|
||||
logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt;
|
||||
logic [`DIVLEN-1:0] X;
|
||||
logic [`DIVLEN-1:0] Dpreproc;
|
||||
logic [`DIVLEN+3:0] X;
|
||||
logic [`DIVLEN+3:0] Dpreproc;
|
||||
logic [`DURLEN-1:0] Dur;
|
||||
logic NegSticky;
|
||||
|
||||
srtpreproc srtpreproc(.Xm(XManE), .Dur, .Ym(YManE), .X,.Dpreproc, .XZeroCnt, .YZeroCnt);
|
||||
srtpreproc srtpreproc(.clk, .DivStart(DivStartE), .Xm(XmE), .QeM, .Xe(XeE), .Fmt(FmtE), .Ye(YeE), .Sqrt(SqrtE), .Dur, .Ym(YmE), .XZero(XZeroE), .X, .Dpreproc, .XZeroCnt, .YZeroCnt);
|
||||
|
||||
srtfsm srtfsm(.reset, .NextWSN, .NextWCN, .WS, .WC, .Dur, .DivBusy, .clk, .DivStart(DivStartE),.StallE, .StallM, .DivDone, .XZeroE, .YZeroE, .DivStickyE(DivStickyM), .XNaNE, .YNaNE,
|
||||
srtfsm srtfsm(.reset, .NextWSN, .NextWCN, .WS, .WC, .Dur, .DivBusy, .clk, .DivStart(DivStartE),.StallE, .StallM, .DivDone, .XZeroE, .YZeroE, .DivSE(DivSM), .XNaNE, .YNaNE,
|
||||
.StickyWSA, .XInfE, .YInfE, .NegSticky(NegSticky), .EarlyTermShiftE(EarlyTermShiftM));
|
||||
srt srt(.clk, .FmtE, .X,.Dpreproc, .NegSticky, .XZeroCnt, .YZeroCnt, .FirstWS(WS), .FirstWC(WC), .NextWSN, .NextWCN, .DivStart(DivStartE), .Xe(XExpE), .Ye(YExpE), .XZeroE, .YZeroE,
|
||||
.StickyWSA, .DivBusy, .Quot(QuotM), .Rem(), .DivCalcExpM);
|
||||
srt srt(.clk, .Sqrt(SqrtM), .X,.Dpreproc, .NegSticky, .XZeroCnt, .YZeroCnt, .FirstWS(WS), .FirstWC(WC), .NextWSN, .NextWCN, .DivStart(DivStartE), .Xe(XeE), .Ye(YeE), .XZeroE, .YZeroE,
|
||||
.StickyWSA, .DivBusy, .Qm(QmM), .Rem());
|
||||
endmodule
|
|
@ -29,29 +29,29 @@
|
|||
`include "wally-config.vh"
|
||||
|
||||
module fclassify (
|
||||
input logic XSgnE, // sign bit
|
||||
input logic XNaNE, // is NaN
|
||||
input logic XSNaNE, // is signaling NaN
|
||||
input logic XDenormE, // is denormal
|
||||
input logic XZeroE, // is zero
|
||||
input logic XInfE, // is infinity
|
||||
output logic [`XLEN-1:0] ClassResE // classify result
|
||||
);
|
||||
input logic Xs, // sign bit
|
||||
input logic XNaN, // is NaN
|
||||
input logic XSNaN, // is signaling NaN
|
||||
input logic XDenorm,// is denormal
|
||||
input logic XZero, // is zero
|
||||
input logic XInf, // is infinity
|
||||
output logic [`XLEN-1:0] ClassRes// classify result
|
||||
);
|
||||
|
||||
logic PInf, PZero, PNorm, PDenorm;
|
||||
logic NInf, NZero, NNorm, NDenorm;
|
||||
logic XNormE;
|
||||
logic XNorm;
|
||||
|
||||
// determine the sub categories
|
||||
assign XNormE = ~(XNaNE | XInfE | XDenormE | XZeroE);
|
||||
assign PInf = ~XSgnE&XInfE;
|
||||
assign NInf = XSgnE&XInfE;
|
||||
assign PNorm = ~XSgnE&XNormE;
|
||||
assign NNorm = XSgnE&XNormE;
|
||||
assign PDenorm = ~XSgnE&XDenormE;
|
||||
assign NDenorm = XSgnE&XDenormE;
|
||||
assign PZero = ~XSgnE&XZeroE;
|
||||
assign NZero = XSgnE&XZeroE;
|
||||
assign XNorm= ~(XNaN | XInf| XDenorm| XZero);
|
||||
assign PInf = ~Xs&XInf;
|
||||
assign NInf = Xs&XInf;
|
||||
assign PNorm = ~Xs&XNorm;
|
||||
assign NNorm = Xs&XNorm;
|
||||
assign PDenorm = ~Xs&XDenorm;
|
||||
assign NDenorm = Xs&XDenorm;
|
||||
assign PZero = ~Xs&XZero;
|
||||
assign NZero = Xs&XZero;
|
||||
|
||||
// determine sub category and combine into the result
|
||||
// bit 0 - -Inf
|
||||
|
@ -64,6 +64,6 @@ module fclassify (
|
|||
// bit 7 - +Inf
|
||||
// bit 8 - signaling NaN
|
||||
// bit 9 - quiet NaN
|
||||
assign ClassResE = {{`XLEN-10{1'b0}}, XNaNE&~XSNaNE, XSNaNE, PInf, PNorm, PDenorm, PZero, NZero, NDenorm, NNorm, NInf};
|
||||
assign ClassRes = {{`XLEN-10{1'b0}}, XNaN&~XSNaN, XSNaN, PInf, PNorm, PDenorm, PZero, NZero, NDenorm, NNorm, NInf};
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -27,9 +27,10 @@
|
|||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
// OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
// FOpCtrlE values
|
||||
// OpCtrl values
|
||||
// 110 min
|
||||
// 101 max
|
||||
// 010 equal
|
||||
|
@ -37,36 +38,32 @@
|
|||
// 011 less than or equal
|
||||
|
||||
module fcmp (
|
||||
input logic [`FMTBITS-1:0] FmtE, // precision 1 = double 0 = single
|
||||
input logic [2:0] FOpCtrlE, // see above table
|
||||
input logic XSgnE, YSgnE, // input signs
|
||||
input logic [`NE-1:0] XExpE, YExpE, // input exponents
|
||||
input logic [`NF:0] XManE, YManE, // input mantissa
|
||||
input logic XZeroE, YZeroE, // is zero
|
||||
input logic XNaNE, YNaNE, // is NaN
|
||||
input logic XSNaNE, YSNaNE, // is signaling NaN
|
||||
input logic [`FLEN-1:0] FSrcXE, FSrcYE, // original, non-converted to double, inputs
|
||||
output logic CmpNVE, // invalid flag
|
||||
output logic [`FLEN-1:0] CmpFpResE, // compare resilt
|
||||
output logic [`XLEN-1:0] CmpIntResE // compare resilt
|
||||
input logic [`FMTBITS-1:0] Fmt, // format of fp number
|
||||
input logic [2:0] OpCtrl, // see above table
|
||||
input logic Xs, Ys, // input signs
|
||||
input logic [`NE-1:0] Xe, Ye, // input exponents
|
||||
input logic [`NF:0] Xm, Ym, // input mantissa
|
||||
input logic XZero, YZero, // is zero
|
||||
input logic XNaN, YNaN, // is NaN
|
||||
input logic XSNaN, YSNaN, // is signaling NaN
|
||||
input logic [`FLEN-1:0] X, Y, // original inputs (before unpacker)
|
||||
output logic CmpNV, // invalid flag
|
||||
output logic [`FLEN-1:0] CmpFpRes, // compare floating-point result
|
||||
output logic [`XLEN-1:0] CmpIntRes // compare integer result
|
||||
);
|
||||
|
||||
logic LTabs, LT, EQ; // is X < or > or = Y
|
||||
logic [`FLEN-1:0] NaNRes;
|
||||
logic BothZero, EitherNaN, EitherSNaN;
|
||||
logic LTabs, LT, EQ; // is X < or > or = Y
|
||||
logic [`FLEN-1:0] NaNRes; // NaN result
|
||||
logic BothZero; // are both inputs zero
|
||||
logic EitherNaN, EitherSNaN; // are either input a (signaling) NaN
|
||||
|
||||
assign LTabs= {1'b0, XExpE, XManE} < {1'b0, YExpE, YManE}; // unsigned comparison, treating FP as integers
|
||||
assign LT = (XSgnE & ~YSgnE) | (XSgnE & YSgnE & ~LTabs & ~EQ) | (~XSgnE & ~YSgnE & LTabs);
|
||||
// assign LT = {~XSgnE, XExpE, XManE[`NF-1:0]} < {~YSgnE, YExpE, YManE[`NF-1:0]}; // *** James look at whether we can simplify to this, but it fails regression
|
||||
assign LTabs= {1'b0, Xe, Xm} < {1'b0, Ye, Ym}; // unsigned comparison, treating FP as integers
|
||||
assign LT = (Xs & ~Ys) | (Xs & Ys & ~LTabs & ~EQ) | (~Xs & ~Ys & LTabs); // signed comparison
|
||||
assign EQ = (X == Y);
|
||||
|
||||
//assign LT = $signed({XSgnE, XExpE, XManE[`NF-1:0]}) < $signed({YSgnE, YExpE, YManE[`NF-1:0]});
|
||||
//assign LT = XInt < YInt;
|
||||
// assign LT = XSgnE^YSgnE ? XSgnE : XExpE==YExpE ? ((XManE<YManE)^XSgnE)&~EQ : (XExpE<YExpE)^XSgnE;
|
||||
assign EQ = (FSrcXE == FSrcYE);
|
||||
|
||||
assign BothZero = XZeroE&YZeroE;
|
||||
assign EitherNaN = XNaNE|YNaNE;
|
||||
assign EitherSNaN = XSNaNE|YSNaNE;
|
||||
assign BothZero = XZero&YZero;
|
||||
assign EitherNaN = XNaN|YNaN;
|
||||
assign EitherSNaN = XSNaN|YSNaN;
|
||||
|
||||
|
||||
// flags
|
||||
|
@ -74,78 +71,91 @@ module fcmp (
|
|||
// LT/LE - signaling - sets invalid if NaN input
|
||||
// EQ - quiet - sets invalid if signaling NaN input
|
||||
always_comb begin
|
||||
case (FOpCtrlE[2:0])
|
||||
3'b110: CmpNVE = EitherSNaN;//min
|
||||
3'b101: CmpNVE = EitherSNaN;//max
|
||||
3'b010: CmpNVE = EitherSNaN;//equal
|
||||
3'b001: CmpNVE = EitherNaN;//less than
|
||||
3'b011: CmpNVE = EitherNaN;//less than or equal
|
||||
default: CmpNVE = 1'bx;
|
||||
case (OpCtrl[2:0])
|
||||
3'b110: CmpNV = EitherSNaN;//min
|
||||
3'b101: CmpNV = EitherSNaN;//max
|
||||
3'b010: CmpNV = EitherSNaN;//equal
|
||||
3'b001: CmpNV = EitherNaN;//less than
|
||||
3'b011: CmpNV = EitherNaN;//less than or equal
|
||||
default: CmpNV = 1'bx;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Min/Max
|
||||
// - outputs the min/max of X and Y
|
||||
// - -0 < 0
|
||||
// - if both are NaN return quiet X
|
||||
// - if one is a NaN output the non-NaN
|
||||
// LT/LE/EQ
|
||||
// - -0 = 0
|
||||
// - inf = inf and -inf = -inf
|
||||
// - return 0 if comparison with NaN (unordered)
|
||||
|
||||
// fmin/fmax of two NaNs returns a quiet NaN of the appropriate size
|
||||
// for IEEE, return the payload of X
|
||||
// for RISC-V, return the canonical NaN
|
||||
|
||||
|
||||
// select the NaN result
|
||||
if (`FPSIZES == 1)
|
||||
if(`IEEE754) assign NaNRes = {XSgnE, {`NE{1'b1}}, 1'b1, XManE[`NF-2:0]};
|
||||
if(`IEEE754) assign NaNRes = {Xs, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]};
|
||||
else assign NaNRes = {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}};
|
||||
|
||||
else if (`FPSIZES == 2)
|
||||
if(`IEEE754) assign NaNRes = FmtE ? {XSgnE, {`NE{1'b1}}, 1'b1, XManE[`NF-2:0]} : {{`FLEN-`LEN1{1'b1}}, XSgnE, {`NE1{1'b1}}, 1'b1, XManE[`NF-2:`NF-`NF1]};
|
||||
else assign NaNRes = FmtE ? {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, (`NF1-1)'(0)};
|
||||
if(`IEEE754) assign NaNRes = Fmt ? {Xs, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]} : {{`FLEN-`LEN1{1'b1}}, Xs, {`NE1{1'b1}}, 1'b1, Xm[`NF-2:`NF-`NF1]};
|
||||
else assign NaNRes = Fmt ? {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, (`NF1-1)'(0)};
|
||||
|
||||
else if (`FPSIZES == 3)
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
`FMT:
|
||||
if(`IEEE754) NaNRes = {XSgnE, {`NE{1'b1}}, 1'b1, XManE[`NF-2:0]};
|
||||
if(`IEEE754) NaNRes = {Xs, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]};
|
||||
else NaNRes = {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}};
|
||||
`FMT1:
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`LEN1{1'b1}}, XSgnE, {`NE1{1'b1}}, 1'b1, XManE[`NF-2:`NF-`NF1]};
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`LEN1{1'b1}}, Xs, {`NE1{1'b1}}, 1'b1, Xm[`NF-2:`NF-`NF1]};
|
||||
else NaNRes = {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, (`NF1-1)'(0)};
|
||||
`FMT2:
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`LEN2{1'b1}}, XSgnE, {`NE2{1'b1}}, 1'b1, XManE[`NF-2:`NF-`NF2]};
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`LEN2{1'b1}}, Xs, {`NE2{1'b1}}, 1'b1, Xm[`NF-2:`NF-`NF2]};
|
||||
else NaNRes = {{`FLEN-`LEN2{1'b1}}, 1'b0, {`NE2{1'b1}}, 1'b1, (`NF2-1)'(0)};
|
||||
default: NaNRes = {`FLEN{1'bx}};
|
||||
endcase
|
||||
|
||||
else if (`FPSIZES == 4)
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
2'h3:
|
||||
if(`IEEE754) NaNRes = {XSgnE, {`NE{1'b1}}, 1'b1, XManE[`NF-2:0]};
|
||||
if(`IEEE754) NaNRes = {Xs, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]};
|
||||
else NaNRes = {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}};
|
||||
2'h1:
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`D_LEN{1'b1}}, XSgnE, {`D_NE{1'b1}}, 1'b1, XManE[`NF-2:`NF-`D_NF]};
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`D_LEN{1'b1}}, Xs, {`D_NE{1'b1}}, 1'b1, Xm[`NF-2:`NF-`D_NF]};
|
||||
else NaNRes = {{`FLEN-`D_LEN{1'b1}}, 1'b0, {`D_NE{1'b1}}, 1'b1, (`D_NF-1)'(0)};
|
||||
2'h0:
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`S_LEN{1'b1}}, XSgnE, {`S_NE{1'b1}}, 1'b1, XManE[`NF-2:`NF-`S_NF]};
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`S_LEN{1'b1}}, Xs, {`S_NE{1'b1}}, 1'b1, Xm[`NF-2:`NF-`S_NF]};
|
||||
else NaNRes = {{`FLEN-`S_LEN{1'b1}}, 1'b0, {`S_NE{1'b1}}, 1'b1, (`S_NF-1)'(0)};
|
||||
2'h2:
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`H_LEN{1'b1}}, XSgnE, {`H_NE{1'b1}}, 1'b1, XManE[`NF-2:`NF-`H_NF]};
|
||||
if(`IEEE754) NaNRes = {{`FLEN-`H_LEN{1'b1}}, Xs, {`H_NE{1'b1}}, 1'b1, Xm[`NF-2:`NF-`H_NF]};
|
||||
else NaNRes = {{`FLEN-`H_LEN{1'b1}}, 1'b0, {`H_NE{1'b1}}, 1'b1, (`H_NF-1)'(0)};
|
||||
endcase
|
||||
|
||||
// when one input is a NaN -output the non-NaN
|
||||
assign CmpFpResE = FOpCtrlE[0] ? XNaNE ? YNaNE ? NaNRes : FSrcYE // Max
|
||||
: YNaNE ? FSrcXE : LT ? FSrcYE : FSrcXE :
|
||||
XNaNE ? YNaNE ? NaNRes : FSrcYE // Min
|
||||
: YNaNE ? FSrcXE : LT ? FSrcXE : FSrcYE;
|
||||
|
||||
|
||||
assign CmpIntResE = {(`XLEN-1)'(0), (((EQ|BothZero)&FOpCtrlE[1])|(LT&FOpCtrlE[0]&~BothZero))&~EitherNaN};
|
||||
// Min/Max
|
||||
// - outputs the min/max of X and Y
|
||||
// - -0 < 0
|
||||
// - if both are NaN return quiet X
|
||||
// - if one is a NaN output the non-NaN
|
||||
always_comb
|
||||
if(OpCtrl[0]) // MAX
|
||||
if(XNaN)
|
||||
if(YNaN) CmpFpRes = NaNRes; // X = NaN Y = NaN
|
||||
else CmpFpRes = Y; // X = NaN Y != NaN
|
||||
else
|
||||
if(YNaN) CmpFpRes = X; // X != NaN Y = NaN
|
||||
else // X,Y != NaN
|
||||
if(LT) CmpFpRes = Y; // X < Y
|
||||
else CmpFpRes = X; // X > Y
|
||||
else // MIN
|
||||
if(XNaN)
|
||||
if(YNaN) CmpFpRes = NaNRes; // X = NaN Y = NaN
|
||||
else CmpFpRes = Y; // X = NaN Y != NaN
|
||||
else
|
||||
if(YNaN) CmpFpRes = X; // X != NaN Y = NaN
|
||||
else // X,Y != NaN
|
||||
if(LT) CmpFpRes = X; // X < Y
|
||||
else CmpFpRes = Y; // X > Y
|
||||
|
||||
// LT/LE/EQ
|
||||
// - -0 = 0
|
||||
// - inf = inf and -inf = -inf
|
||||
// - return 0 if comparison with NaN (unordered)
|
||||
assign CmpIntRes = {(`XLEN-1)'(0), (((EQ|BothZero)&OpCtrl[1])|(LT&OpCtrl[0]&~BothZero))&~EitherNaN};
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -29,25 +29,44 @@
|
|||
`include "wally-config.vh"
|
||||
|
||||
module fctrl (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallE, StallM, StallW, // stall signals
|
||||
input logic FlushE, FlushM, FlushW, // flush signals
|
||||
input logic [31:0] InstrD,
|
||||
input logic [6:0] Funct7D, // bits 31:25 of instruction - may contain percision
|
||||
input logic [6:0] OpD, // bits 6:0 of instruction
|
||||
input logic [4:0] Rs2D, // bits 24:20 of instruction
|
||||
input logic [2:0] Funct3D, // bits 14:12 of instruction - may contain rounding mode
|
||||
input logic [2:0] FRM_REGW, // rounding mode from CSR
|
||||
input logic [1:0] STATUS_FS, // is FPU enabled?
|
||||
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||
output logic FRegWriteD, // FP register write enable
|
||||
output logic FDivStartD, // Start division or squareroot
|
||||
output logic [1:0] FResSelD, // select result to be written to fp register
|
||||
output logic [2:0] FOpCtrlD, // chooses which opperation to do - specifics shown at bottom of module and in each unit
|
||||
output logic [1:0] PostProcSelD,
|
||||
output logic [`FMTBITS-1:0] FmtD, // precision - single-0 double-1
|
||||
output logic [2:0] FrmD, // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude
|
||||
output logic FWriteIntD // is the result written to the integer register
|
||||
input logic FDivBusyE, // is the divider busy
|
||||
output logic IllegalFPUInstrD, IllegalFPUInstrM, // Is the instruction an illegal fpu instruction
|
||||
output logic FRegWriteM, FRegWriteW, // FP register write enable
|
||||
output logic [2:0] FrmM, // FP rounding mode
|
||||
output logic [`FMTBITS-1:0] FmtE, FmtM, // FP format
|
||||
output logic DivStartE, // Start division or squareroot
|
||||
output logic XEnE, YEnE, ZEnE,
|
||||
output logic YEnForwardE, ZEnForwardE,
|
||||
output logic FWriteIntE, FWriteIntM, // Write to integer register
|
||||
output logic [2:0] OpCtrlE, OpCtrlM, // Select which opperation to do in each component
|
||||
output logic [1:0] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage
|
||||
output logic [1:0] PostProcSelE, PostProcSelM, // select result in the post processing unit
|
||||
output logic [4:0] Adr1E, Adr2E, Adr3E // adresses of each input
|
||||
);
|
||||
|
||||
`define FCTRLW 11
|
||||
logic [`FCTRLW-1:0] ControlsD;
|
||||
logic IllegalFPUInstrE;
|
||||
logic FRegWriteD; // FP register write enable
|
||||
logic DivStartD; // integer register write enable
|
||||
logic FWriteIntD; // integer register write enable
|
||||
logic FRegWriteE; // FP register write enable
|
||||
logic [2:0] OpCtrlD; // Select which opperation to do in each component
|
||||
logic [1:0] PostProcSelD; // select result in the post processing unit
|
||||
logic [1:0] FResSelD; // Select one of the results that finish in the memory stage
|
||||
logic [2:0] FrmD, FrmE; // FP rounding mode
|
||||
logic [`FMTBITS-1:0] FmtD; // FP format
|
||||
//*** will putting x for don't cares reduce area in synthisis???
|
||||
// FPU Instruction Decoder
|
||||
always_comb
|
||||
|
@ -130,7 +149,7 @@ module fctrl (
|
|||
endcase
|
||||
|
||||
// unswizzle control bits
|
||||
assign {FRegWriteD, FWriteIntD, FResSelD, PostProcSelD, FOpCtrlD, FDivStartD, IllegalFPUInstrD} = ControlsD;
|
||||
assign {FRegWriteD, FWriteIntD, FResSelD, PostProcSelD, OpCtrlD, DivStartD, IllegalFPUInstrD} = ControlsD;
|
||||
|
||||
// rounding modes:
|
||||
// 000 - round to nearest, ties to even
|
||||
|
@ -155,6 +174,20 @@ module fctrl (
|
|||
else if (`FPSIZES == 3|`FPSIZES == 4)
|
||||
assign FmtD = ((Funct7D[6:3] == 4'b0100)&OpD[4]) ? Rs2D[1:0] : Funct7D[1:0];
|
||||
|
||||
|
||||
|
||||
// enables:
|
||||
// X - all except int->fp, store, load, mv int->fp
|
||||
// Y - all except cvt, mv, load, class
|
||||
// Z - fma ops only
|
||||
// load/store mv int->fp cvt int->fp
|
||||
assign XEnE = ~(((FResSelE==2'b10)&~FWriteIntE)|((FResSelE==2'b11)&FRegWriteE)|((FResSelE==2'b01)&(PostProcSelE==2'b00)&OpCtrlE[2]));
|
||||
// load/class mv cvt
|
||||
assign YEnE = ~(((FResSelE==2'b10)&(FWriteIntE|FRegWriteE))|(FResSelE==2'b11)|((FResSelE==2'b01)&(PostProcSelE==2'b00)));
|
||||
assign ZEnE = (PostProcSelE==2'b10)&(FResSelE==2'b01)&(~OpCtrlE[2]|OpCtrlE[1]);
|
||||
assign YEnForwardE = ~(((FResSelE==2'b10)&(FWriteIntE|FRegWriteE))|(FResSelE==2'b11)|((FResSelE==2'b01)&(PostProcSelE==2'b00)));
|
||||
assign ZEnForwardE = (PostProcSelE==2'b10)&(FResSelE==2'b01)&~OpCtrlE[2];
|
||||
|
||||
// Final Res Sel:
|
||||
// fp int
|
||||
// 00 other cmp
|
||||
|
@ -168,7 +201,7 @@ module fctrl (
|
|||
// 10 fma
|
||||
|
||||
// Other Sel:
|
||||
// Ctrl signal = {FOpCtrl[2], &FOpctrl[1:0]}
|
||||
// Ctrl signal = {OpCtrl[2], &FOpctrl[1:0]}
|
||||
// 000 - sign 00
|
||||
// 001 - negate sign 00
|
||||
// 010 - xor sign 00
|
||||
|
@ -186,8 +219,8 @@ module fctrl (
|
|||
// 110 - add
|
||||
// 111 - sub
|
||||
// Div:
|
||||
// 0 - ???
|
||||
// 1 - ???
|
||||
// 0 - div
|
||||
// 1 - sqrt
|
||||
// Cvt Int: {Int to Fp?, 64 bit int?, signed int?}
|
||||
// Cvt Fp: output format
|
||||
// 10 - to half
|
||||
|
@ -205,5 +238,24 @@ module fctrl (
|
|||
// 01 - negate sign
|
||||
// 10 - xor sign
|
||||
|
||||
// D/E pipleine register
|
||||
flopenrc #(12+`FMTBITS) DECtrlReg3(clk, reset, FlushE, ~StallE,
|
||||
{FRegWriteD, PostProcSelD, FResSelD, FrmD, FmtD, OpCtrlD, FWriteIntD},
|
||||
{FRegWriteE, PostProcSelE, FResSelE, FrmE, FmtE, OpCtrlE, FWriteIntE});
|
||||
flopenrc #(15) DEAdrReg(clk, reset, FlushE, ~StallE, {InstrD[19:15], InstrD[24:20], InstrD[31:27]},
|
||||
{Adr1E, Adr2E, Adr3E});
|
||||
flopenrc #(1) DEDivStartReg(clk, reset, FlushE, ~StallE|FDivBusyE, DivStartD, DivStartE);
|
||||
if(`FLEN>`XLEN)
|
||||
flopenrc #(1) DEIllegalReg(clk, reset, FlushE, ~StallE, IllegalFPUInstrD, IllegalFPUInstrE);
|
||||
// E/M pipleine register
|
||||
flopenrc #(12+int'(`FMTBITS)) EMCtrlReg (clk, reset, FlushM, ~StallM,
|
||||
{FRegWriteE, FResSelE, PostProcSelE, FrmE, FmtE, OpCtrlE, FWriteIntE},
|
||||
{FRegWriteM, FResSelM, PostProcSelM, FrmM, FmtM, OpCtrlM, FWriteIntM});
|
||||
if(`FLEN>`XLEN)
|
||||
flopenrc #(1) EMIllegalReg(clk, reset, FlushM, ~StallM, IllegalFPUInstrE, IllegalFPUInstrM);
|
||||
// M/W pipleine register
|
||||
flopenrc #(3) MWCtrlReg(clk, reset, FlushW, ~StallW,
|
||||
{FRegWriteM, FResSelM},
|
||||
{FRegWriteW, FResSelW});
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -35,7 +35,7 @@ module fcvt (
|
|||
input logic [`NE-1:0] Xe, // input's exponent
|
||||
input logic [`NF:0] Xm, // input's fraction
|
||||
input logic [`XLEN-1:0] Int, // integer input - from IEU
|
||||
input logic [2:0] FOpCtrl, // choose which opperation (look below for values)
|
||||
input logic [2:0] OpCtrl, // choose which opperation (look below for values)
|
||||
input logic ToInt, // is fp->int (since it's writting to the integer register)
|
||||
input logic XZero, // is the input zero
|
||||
input logic XDenorm, // is the input denormalized
|
||||
|
@ -73,17 +73,17 @@ module fcvt (
|
|||
|
||||
|
||||
// seperate OpCtrl for code readability
|
||||
assign Signed = FOpCtrl[0];
|
||||
assign Int64 = FOpCtrl[1];
|
||||
assign IntToFp = FOpCtrl[2];
|
||||
assign Signed = OpCtrl[0];
|
||||
assign Int64 = OpCtrl[1];
|
||||
assign IntToFp = OpCtrl[2];
|
||||
|
||||
// choose the ouptut format depending on the opperation
|
||||
// - fp -> fp: OpCtrl contains the percision of the output
|
||||
// - int -> fp: Fmt contains the percision of the output
|
||||
if (`FPSIZES == 2)
|
||||
assign OutFmt = IntToFp ? Fmt : (FOpCtrl[1:0] == `FMT);
|
||||
assign OutFmt = IntToFp ? Fmt : (OpCtrl[1:0] == `FMT);
|
||||
else if (`FPSIZES == 3 | `FPSIZES == 4)
|
||||
assign OutFmt = IntToFp ? Fmt : FOpCtrl[1:0];
|
||||
assign OutFmt = IntToFp ? Fmt : OpCtrl[1:0];
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -103,7 +103,7 @@ module fcvt (
|
|||
// choose the input to the leading zero counter i.e. priority encoder
|
||||
// int -> fp : | positive integer | 00000... (if needed) |
|
||||
// fp -> fp : | fraction | 00000... (if needed) |
|
||||
assign LzcInFull = IntToFp ? {1'b0, TrimInt, {`CVTLEN-`XLEN{1'b0}}} :
|
||||
assign LzcInFull = IntToFp ? {TrimInt, {`CVTLEN-`XLEN+1{1'b0}}} :
|
||||
{Xm, {`CVTLEN-`NF{1'b0}}};
|
||||
assign LzcIn = LzcInFull[`CVTLEN-1:0];
|
||||
|
||||
|
@ -125,9 +125,10 @@ module fcvt (
|
|||
// - only shift fp -> fp if the intital value is denormalized
|
||||
// - this is a problem because the input to the lzc was the fraction rather than the mantissa
|
||||
// - rather have a few and-gates than an extra bit in the priority encoder??? *** is this true?
|
||||
assign ShiftAmt = ToInt ? Ce[`LOGCVTLEN-1:0]&{`LOGCVTLEN{~Ce[`NE]}} :
|
||||
ResDenormUf&~IntToFp ? (`LOGCVTLEN)'(`NF-1)+Ce[`LOGCVTLEN-1:0] :
|
||||
(LeadingZeros);
|
||||
always_comb
|
||||
if(ToInt) ShiftAmt = Ce[`LOGCVTLEN-1:0]&{`LOGCVTLEN{~Ce[`NE]}};
|
||||
else if (ResDenormUf&~IntToFp) ShiftAmt = (`LOGCVTLEN)'(`NF-1)+Ce[`LOGCVTLEN-1:0];
|
||||
else ShiftAmt = LeadingZeros;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// exp calculations
|
||||
|
@ -150,7 +151,9 @@ module fcvt (
|
|||
assign NewBias = ToInt ? (`NE-1)'(1) : (`NE-1)'(`BIAS);
|
||||
|
||||
end else if (`FPSIZES == 2) begin
|
||||
assign NewBias = ToInt ? (`NE-1)'(1) : OutFmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1);
|
||||
logic [`NE-2:0] NewBiasToFp;
|
||||
assign NewBiasToFp = OutFmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1);
|
||||
assign NewBias = ToInt ? (`NE-1)'(1) : NewBiasToFp;
|
||||
|
||||
end else if (`FPSIZES == 3) begin
|
||||
logic [`NE-2:0] NewBiasToFp;
|
||||
|
@ -177,7 +180,7 @@ module fcvt (
|
|||
// select the old exponent
|
||||
// int -> fp : largest bias + XLEN
|
||||
// fp -> ??? : XExp
|
||||
assign OldExp = IntToFp ? (`NE)'(`BIAS)+(`NE)'(`XLEN) : Xe;
|
||||
assign OldExp = IntToFp ? (`NE)'(`BIAS)+(`NE)'(`XLEN-1) : Xe;
|
||||
|
||||
// calculate CalcExp
|
||||
// fp -> fp :
|
||||
|
@ -222,7 +225,11 @@ module fcvt (
|
|||
// - if 64-bit : check the msb of the 64-bit integer input and if it's signed
|
||||
// - if 32-bit : check the msb of the 32-bit integer input and if it's signed
|
||||
// - otherwise: the floating point input's sign
|
||||
assign Cs = IntToFp ? Int64 ? Int[`XLEN-1]&Signed : Int[31]&Signed : Xs;
|
||||
always_comb
|
||||
if(IntToFp)
|
||||
if(Int64) Cs = Int[`XLEN-1]&Signed;
|
||||
else Cs = Int[31]&Signed;
|
||||
else Cs = Xs;
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -31,49 +31,51 @@
|
|||
`include "wally-config.vh"
|
||||
|
||||
module fhazard(
|
||||
input logic [4:0] Adr1E, Adr2E, Adr3E, // read data adresses
|
||||
input logic FRegWriteM, FRegWriteW, // is the fp register being written to
|
||||
input logic [4:0] RdM, RdW, // the adress being written to
|
||||
input logic [1:0] FResSelM, // the result being selected
|
||||
input logic [4:0] Adr1E, Adr2E, Adr3E, // read data adresses
|
||||
input logic FRegWriteM, FRegWriteW, // is the fp register being written to
|
||||
input logic [4:0] RdM, RdW, // the adress being written to
|
||||
input logic [1:0] FResSelM, // the result being selected
|
||||
input logic XEnE, YEnE, ZEnE,
|
||||
output logic FStallD, // stall the decode stage
|
||||
output logic [1:0] FForwardXE, FForwardYE, FForwardZE // select a forwarded value
|
||||
output logic [1:0] ForwardXE, ForwardYE, ForwardZE // select a forwarded value
|
||||
);
|
||||
|
||||
|
||||
always_comb begin
|
||||
// set defaults
|
||||
FForwardXE = 2'b00; // choose FRD1E
|
||||
FForwardYE = 2'b00; // choose FRD2E
|
||||
FForwardZE = 2'b00; // choose FRD3E
|
||||
ForwardXE = 2'b00; // choose FRD1E
|
||||
ForwardYE = 2'b00; // choose FRD2E
|
||||
ForwardZE = 2'b00; // choose FRD3E
|
||||
FStallD = 0;
|
||||
|
||||
//*** this hazard unit is waiting for all three inputs, change so that if an input isnt used then don't wait
|
||||
|
||||
// if the needed value is in the memory stage - input 1
|
||||
if ((Adr1E == RdM) & FRegWriteM)
|
||||
// if the result will be FResM (can be taken from the memory stage)
|
||||
if(FResSelM == 2'b00) FForwardXE = 2'b10; // choose FResM
|
||||
else FStallD = 1; // otherwise stall
|
||||
// if the needed value is in the writeback stage
|
||||
else if ((Adr1E == RdW) & FRegWriteW) FForwardXE = 2'b01; // choose FPUResult64W
|
||||
if(XEnE)
|
||||
if ((Adr1E == RdM) & FRegWriteM)
|
||||
// if the result will be FResM (can be taken from the memory stage)
|
||||
if(FResSelM == 2'b00) ForwardXE = 2'b10; // choose FResM
|
||||
else FStallD = 1; // otherwise stall
|
||||
// if the needed value is in the writeback stage
|
||||
else if ((Adr1E == RdW) & FRegWriteW) ForwardXE = 2'b01; // choose FPUResult64W
|
||||
|
||||
|
||||
// if the needed value is in the memory stage - input 2
|
||||
if ((Adr2E == RdM) & FRegWriteM)
|
||||
// if the result will be FResM (can be taken from the memory stage)
|
||||
if(FResSelM == 2'b00) FForwardYE = 2'b10; // choose FResM
|
||||
else FStallD = 1; // otherwise stall
|
||||
// if the needed value is in the writeback stage
|
||||
else if ((Adr2E == RdW) & FRegWriteW) FForwardYE = 2'b01; // choose FPUResult64W
|
||||
if(YEnE)
|
||||
if ((Adr2E == RdM) & FRegWriteM)
|
||||
// if the result will be FResM (can be taken from the memory stage)
|
||||
if(FResSelM == 2'b00) ForwardYE = 2'b10; // choose FResM
|
||||
else FStallD = 1; // otherwise stall
|
||||
// if the needed value is in the writeback stage
|
||||
else if ((Adr2E == RdW) & FRegWriteW) ForwardYE = 2'b01; // choose FPUResult64W
|
||||
|
||||
|
||||
// if the needed value is in the memory stage - input 3
|
||||
if ((Adr3E == RdM) & FRegWriteM)
|
||||
// if the result will be FResM (can be taken from the memory stage)
|
||||
if(FResSelM == 2'b00) FForwardZE = 2'b10; // choose FResM
|
||||
else FStallD = 1; // otherwise stall
|
||||
// if the needed value is in the writeback stage
|
||||
else if ((Adr3E == RdW) & FRegWriteW) FForwardZE = 2'b01; // choose FPUResult64W
|
||||
if(ZEnE)
|
||||
if ((Adr3E == RdM) & FRegWriteM)
|
||||
// if the result will be FResM (can be taken from the memory stage)
|
||||
if(FResSelM == 2'b00) ForwardZE = 2'b10; // choose FResM
|
||||
else FStallD = 1; // otherwise stall
|
||||
// if the needed value is in the writeback stage
|
||||
else if ((Adr3E == RdW) & FRegWriteW) ForwardZE = 2'b01; // choose FPUResult64W
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ module flags(
|
|||
input logic NaNIn, // is a NaN input being used
|
||||
input logic [`FMTBITS-1:0] OutFmt, // output format
|
||||
input logic XZero, YZero, // inputs are zero
|
||||
input logic XNaN, YNaN, // inputs are NaN
|
||||
input logic Sqrt, // Sqrt?
|
||||
input logic ToInt, // convert to integer
|
||||
input logic IntToFp, // convert integer to floating point
|
||||
|
@ -153,11 +152,11 @@ module flags(
|
|||
// | | | | or the res rounds up out of bounds
|
||||
// | | | | and the res didn't underflow
|
||||
// | | | | |
|
||||
assign IntInvalid = XNaN|XInf|(ShiftGtIntSz&~FullRe[`NE+1])|((Xs&~Signed)&(~((CvtCe[`NE]|(~|CvtCe))&~Plus1)))|(CvtNegResMsbs[1]^CvtNegResMsbs[0]);
|
||||
assign IntInvalid = NaNIn|InfIn|(ShiftGtIntSz&~FullRe[`NE+1])|((Xs&~Signed)&(~((CvtCe[`NE]|(~|CvtCe))&~Plus1)))|(CvtNegResMsbs[1]^CvtNegResMsbs[0]);
|
||||
// |
|
||||
// or when the positive res rounds up out of range
|
||||
assign SigNaN = (XSNaN&~(IntToFp&CvtOp)) | (YSNaN&~CvtOp) | (ZSNaN&FmaOp);
|
||||
assign FmaInvalid = ((XInf | YInf) & ZInf & (FmaPs ^ FmaAs) & ~XNaN & ~YNaN) | (XZero & YInf) | (YZero & XInf);
|
||||
assign FmaInvalid = ((XInf | YInf) & ZInf & (FmaPs ^ FmaAs) & ~NaNIn) | (XZero & YInf) | (YZero & XInf);
|
||||
assign DivInvalid = ((XInf & YInf) | (XZero & YZero))&~Sqrt | (Xs&Sqrt);
|
||||
|
||||
assign Invalid = SigNaN | (FmaInvalid&FmaOp) | (DivInvalid&DivOp);
|
||||
|
|
|
@ -34,7 +34,7 @@ module fma(
|
|||
input logic [`NE-1:0] Xe, Ye, Ze, // input's biased exponents in B(NE.0) format
|
||||
input logic [`NF:0] Xm, Ym, Zm, // input's significands in U(0.NF) format
|
||||
input logic XZero, YZero, ZZero, // is the input zero
|
||||
input logic [2:0] FOpCtrl, // 000 = fmadd (X*Y)+Z, 001 = fmsub (X*Y)-Z, 010 = fnmsub -(X*Y)+Z, 011 = fnmadd -(X*Y)-Z, 100 = fmul (X*Y)
|
||||
input logic [2:0] OpCtrl, // 000 = fmadd (X*Y)+Z, 001 = fmsub (X*Y)-Z, 010 = fnmsub -(X*Y)+Z, 011 = fnmadd -(X*Y)-Z, 100 = fmul (X*Y)
|
||||
input logic [`FMTBITS-1:0] Fmt, // format of the result single double half or quad
|
||||
output logic [`NE+1:0] Pe, // the product's exponent B(NE+2.0) format; adds 2 bits to allow for size of number and negative sign
|
||||
output logic ZmSticky, // sticky bit that is calculated during alignment
|
||||
|
@ -44,7 +44,9 @@ module fma(
|
|||
output logic InvA, // Was A inverted for effective subtraction (P-A or -P+A)
|
||||
output logic As, // the aligned addend's sign (modified Z sign for other opperations)
|
||||
output logic Ps, // the product's sign
|
||||
output logic [$clog2(3*`NF+7)-1:0] NCnt // normalization shift count
|
||||
output logic Ss, // the sum's sign
|
||||
output logic [`NE+1:0] Se,
|
||||
output logic [$clog2(3*`NF+7)-1:0] SCnt // normalization shift count
|
||||
);
|
||||
|
||||
logic [2*`NF+1:0] Pm; // the product's significand in U(2.2Nf) format
|
||||
|
@ -70,7 +72,7 @@ module fma(
|
|||
// Alignment shifter
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// calculate the signs and take the opperation into account
|
||||
sign sign(.FOpCtrl, .Xs, .Ys, .Zs, .Ps, .As);
|
||||
sign sign(.OpCtrl, .Xs, .Ys, .Zs, .Ps, .As);
|
||||
|
||||
align align(.Ze, .Zm, .XZero, .YZero, .ZZero, .Xe, .Ye,
|
||||
.Am, .ZmSticky, .KillProd);
|
||||
|
@ -81,9 +83,9 @@ module fma(
|
|||
// // Addition/LZA
|
||||
// ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
add add(.Am, .Pm, .Ps, .As, .KillProd, .ZmSticky, .AmInv, .PmKilled, .NegSum, .InvA, .Sm);
|
||||
add add(.Am, .Pm, .Ze, .Pe, .Ps, .As, .KillProd, .ZmSticky, .AmInv, .PmKilled, .NegSum, .InvA, .Sm, .Se, .Ss);
|
||||
|
||||
loa loa(.A(AmInv+{(3*`NF+6)'(0),InvA&~((ZmSticky&~KillProd))}), .P({PmKilled, 1'b0, InvA&Ps&ZmSticky&KillProd}), .NCnt);
|
||||
loa loa(.A(AmInv+{(3*`NF+6)'(0),InvA&~((ZmSticky&~KillProd))}), .P({PmKilled, 1'b0, InvA&Ps&ZmSticky&KillProd}), .SCnt);
|
||||
endmodule
|
||||
|
||||
|
||||
|
@ -118,7 +120,7 @@ endmodule
|
|||
|
||||
|
||||
module sign(
|
||||
input logic [2:0] FOpCtrl, // opperation contol
|
||||
input logic [2:0] OpCtrl, // opperation contol
|
||||
input logic Xs, Ys, Zs, // sign of the inputs
|
||||
output logic Ps, // the product's sign - takes opperation into account
|
||||
output logic As // aligned addend sign used in fma - takes opperation into account
|
||||
|
@ -128,9 +130,9 @@ module sign(
|
|||
// Negate product's sign if FNMADD or FNMSUB
|
||||
|
||||
// flip is negation opperation
|
||||
assign Ps = Xs ^ Ys ^ (FOpCtrl[1]&~FOpCtrl[2]);
|
||||
assign Ps = Xs ^ Ys ^ (OpCtrl[1]&~OpCtrl[2]);
|
||||
// flip if subtraction
|
||||
assign As = Zs^FOpCtrl[0];
|
||||
assign As = Zs^OpCtrl[0];
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -222,10 +224,14 @@ module add(
|
|||
input logic Ps, As,// the product sign and the alligend addeded's sign (Modified Z sign for other opperations)
|
||||
input logic KillProd, // should the product be set to 0
|
||||
input logic ZmSticky,
|
||||
input logic [`NE-1:0] Ze,
|
||||
input logic [`NE+1:0] Pe,
|
||||
output logic [3*`NF+6:0] AmInv, // aligned addend possibly inverted
|
||||
output logic [2*`NF+1:0] PmKilled, // the product's mantissa possibly killed
|
||||
output logic NegSum, // was the sum negitive
|
||||
output logic InvA, // do you invert the aligned addend
|
||||
output logic Ss,
|
||||
output logic [`NE+1:0] Se,
|
||||
output logic [3*`NF+5:0] Sm // the positive sum
|
||||
);
|
||||
logic [3*`NF+6:0] PreSum, NegPreSum; // possibly negitive sum
|
||||
|
@ -257,13 +263,19 @@ module add(
|
|||
|
||||
// Choose the positive sum and accompanying LZA result.
|
||||
assign Sm = NegSum ? NegPreSum[3*`NF+5:0] : PreSum[3*`NF+5:0];
|
||||
// is the result negitive
|
||||
// if p - z is the Sum negitive
|
||||
// if -p + z is the Sum positive
|
||||
// if -p - z then the Sum is negitive
|
||||
assign Ss = NegSum^Ps; //*** move to execute stage
|
||||
assign Se = KillProd ? {2'b0, Ze} : Pe;
|
||||
endmodule
|
||||
|
||||
|
||||
module loa( // [Schmookler & Nowka, Leading zero anticipation and detection, IEEE Sym. Computer Arithmetic, 2001]
|
||||
input logic [3*`NF+6:0] A, // addend
|
||||
input logic [2*`NF+3:0] P, // product
|
||||
output logic [$clog2(3*`NF+7)-1:0] NCnt // normalization shift count for the positive result
|
||||
output logic [$clog2(3*`NF+7)-1:0] SCnt // normalization shift count for the positive result
|
||||
);
|
||||
|
||||
logic [3*`NF+6:0] T;
|
||||
|
@ -288,6 +300,6 @@ module loa( // [Schmookler & Nowka, Leading zero anticipation and detection, IEE
|
|||
|
||||
|
||||
|
||||
lzc #(3*`NF+7) lzc (.num(f), .ZeroCnt(NCnt));
|
||||
lzc #(3*`NF+7) lzc (.num(f), .ZeroCnt(SCnt));
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -32,17 +32,18 @@ module fmashiftcalc(
|
|||
input logic [3*`NF+5:0] FmaSm, // the positive sum
|
||||
input logic [`NE-1:0] Ze, // exponent of Z
|
||||
input logic [`NE+1:0] FmaPe, // X exponent + Y exponent - bias
|
||||
input logic [$clog2(3*`NF+7)-1:0] FmaNCnt, // normalization shift count
|
||||
input logic [$clog2(3*`NF+7)-1:0] FmaSCnt, // normalization shift count
|
||||
input logic [`FMTBITS-1:0] Fmt, // precision 1 = double 0 = single
|
||||
input logic FmaKillProd, // is the product set to zero
|
||||
output logic [`NE+1:0] FmaNe, // exponent of the normalized sum not taking into account denormal or zero results
|
||||
input logic [`NE+1:0] FmaSe,
|
||||
output logic [`NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account denormal or zero results
|
||||
output logic FmaSZero, // is the result denormalized - calculated before LZA corection
|
||||
output logic FmaPreResultDenorm, // is the result denormalized - calculated before LZA corection
|
||||
output logic [$clog2(3*`NF+7)-1:0] FmaShiftAmt, // normalization shift count
|
||||
output logic [3*`NF+8:0] FmaShiftIn // is the sum zero
|
||||
);
|
||||
logic [$clog2(3*`NF+7)-1:0] DenormShift; // right shift if the result is denormalized //***change this later
|
||||
logic [`NE+1:0] NormSumExp; // the exponent of the normalized sum with the `FLEN bias
|
||||
logic [`NE+1:0] PreNormSumExp; // the exponent of the normalized sum with the `FLEN bias
|
||||
logic [`NE+1:0] BiasCorr;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Normalization
|
||||
|
@ -50,37 +51,38 @@ module fmashiftcalc(
|
|||
//*** insert bias-bias simplification in fcvt.sv/phone pictures
|
||||
// Determine if the sum is zero
|
||||
assign FmaSZero = ~(|FmaSm);
|
||||
|
||||
// calculate the sum's exponent
|
||||
// ProdExp - NormCnt - 1 + NF+4 = ProdExp + ~NormCnt + 1 - 1 + NF+4 = ProdExp + ~NormCnt + NF+4
|
||||
assign NormSumExp = (FmaKillProd ? {2'b0, Ze} : FmaPe) + {{`NE+2-$unsigned($clog2(3*`NF+7)){1'b1}}, ~FmaNCnt} + (`NE+2)'(`NF+4);
|
||||
assign PreNormSumExp = FmaSe + {{`NE+2-$unsigned($clog2(3*`NF+7)){1'b1}}, ~FmaSCnt} + (`NE+2)'(`NF+4);
|
||||
|
||||
//convert the sum's exponent into the proper percision
|
||||
if (`FPSIZES == 1) begin
|
||||
assign FmaNe = NormSumExp;
|
||||
assign NormSumExp = PreNormSumExp;
|
||||
|
||||
end else if (`FPSIZES == 2) begin
|
||||
assign FmaNe = Fmt ? NormSumExp : (NormSumExp-(`NE+2)'(`BIAS)+(`NE+2)'(`BIAS1))&{`NE+2{|NormSumExp}};
|
||||
|
||||
assign BiasCorr = Fmt ? (`NE+2)'(0) : (`NE+2)'(`BIAS1-`BIAS);
|
||||
assign NormSumExp = PreNormSumExp+BiasCorr;
|
||||
|
||||
end else if (`FPSIZES == 3) begin
|
||||
always_comb begin
|
||||
case (Fmt)
|
||||
`FMT: FmaNe = NormSumExp;
|
||||
`FMT1: FmaNe = (NormSumExp-(`NE+2)'(`BIAS)+(`NE+2)'(`BIAS1))&{`NE+2{|NormSumExp}};
|
||||
`FMT2: FmaNe = (NormSumExp-(`NE+2)'(`BIAS)+(`NE+2)'(`BIAS2))&{`NE+2{|NormSumExp}};
|
||||
default: FmaNe = {`NE+2{1'bx}};
|
||||
`FMT: BiasCorr = '0;
|
||||
`FMT1: BiasCorr = (`NE+2)'(`BIAS1-`BIAS);
|
||||
`FMT2: BiasCorr = (`NE+2)'(`BIAS2-`BIAS);
|
||||
default: BiasCorr = 'x;
|
||||
endcase
|
||||
end
|
||||
assign NormSumExp = PreNormSumExp+BiasCorr;
|
||||
|
||||
end else if (`FPSIZES == 4) begin
|
||||
always_comb begin
|
||||
case (Fmt)
|
||||
2'h3: FmaNe = NormSumExp;
|
||||
2'h1: FmaNe = (NormSumExp-(`NE+2)'(`BIAS)+(`NE+2)'(`D_BIAS))&{`NE+2{|NormSumExp}};
|
||||
2'h0: FmaNe = (NormSumExp-(`NE+2)'(`BIAS)+(`NE+2)'(`S_BIAS))&{`NE+2{|NormSumExp}};
|
||||
2'h2: FmaNe = (NormSumExp-(`NE+2)'(`BIAS)+(`NE+2)'(`H_BIAS))&{`NE+2{|NormSumExp}};
|
||||
2'h3: BiasCorr = '0;
|
||||
2'h1: BiasCorr = (`NE+2)'(`D_BIAS-`Q_BIAS);
|
||||
2'h0: BiasCorr = (`NE+2)'(`S_BIAS-`Q_BIAS);
|
||||
2'h2: BiasCorr = (`NE+2)'(`H_BIAS-`Q_BIAS);
|
||||
endcase
|
||||
end
|
||||
assign NormSumExp = PreNormSumExp+BiasCorr;
|
||||
|
||||
end
|
||||
|
||||
|
@ -88,26 +90,26 @@ module fmashiftcalc(
|
|||
|
||||
if (`FPSIZES == 1) begin
|
||||
logic Sum0LEZ, Sum0GEFL;
|
||||
assign Sum0LEZ = NormSumExp[`NE+1] | ~|NormSumExp;
|
||||
assign Sum0GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`NF)-(`NE+2)'(2));
|
||||
assign Sum0LEZ = PreNormSumExp[`NE+1] | ~|PreNormSumExp;
|
||||
assign Sum0GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`NF-2));
|
||||
assign FmaPreResultDenorm = Sum0LEZ & Sum0GEFL & ~FmaSZero;
|
||||
|
||||
end else if (`FPSIZES == 2) begin
|
||||
logic Sum0LEZ, Sum0GEFL, Sum1LEZ, Sum1GEFL;
|
||||
assign Sum0LEZ = NormSumExp[`NE+1] | ~|NormSumExp;
|
||||
assign Sum0GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`NF)-(`NE+2)'(2));
|
||||
assign Sum1LEZ = $signed(NormSumExp) <= $signed( (`NE+2)'(`BIAS)-(`NE+2)'(`BIAS1));
|
||||
assign Sum1GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`NF1+2)+(`NE+2)'(`BIAS)-(`NE+2)'(`BIAS1)) | ~|NormSumExp;
|
||||
assign Sum0LEZ = PreNormSumExp[`NE+1] | ~|PreNormSumExp;
|
||||
assign Sum0GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`NF-2));
|
||||
assign Sum1LEZ = $signed(PreNormSumExp) <= $signed((`NE+2)'(`BIAS-`BIAS1));
|
||||
assign Sum1GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`NF1-2+`BIAS-`BIAS1)) | ~|PreNormSumExp;
|
||||
assign FmaPreResultDenorm = (Fmt ? Sum0LEZ : Sum1LEZ) & (Fmt ? Sum0GEFL : Sum1GEFL) & ~FmaSZero;
|
||||
|
||||
end else if (`FPSIZES == 3) begin
|
||||
logic Sum0LEZ, Sum0GEFL, Sum1LEZ, Sum1GEFL, Sum2LEZ, Sum2GEFL;
|
||||
assign Sum0LEZ = NormSumExp[`NE+1] | ~|NormSumExp;
|
||||
assign Sum0GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`NF)-(`NE+2)'(2));
|
||||
assign Sum1LEZ = $signed(NormSumExp) <= $signed( (`NE+2)'(`BIAS)-(`NE+2)'(`BIAS1));
|
||||
assign Sum1GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`NF1+2)+(`NE+2)'(`BIAS)-(`NE+2)'(`BIAS1)) | ~|NormSumExp;
|
||||
assign Sum2LEZ = $signed(NormSumExp) <= $signed( (`NE+2)'(`BIAS)-(`NE+2)'(`BIAS2));
|
||||
assign Sum2GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`NF2+2)+(`NE+2)'(`BIAS)-(`NE+2)'(`BIAS2)) | ~|NormSumExp;
|
||||
assign Sum0LEZ = PreNormSumExp[`NE+1] | ~|PreNormSumExp;
|
||||
assign Sum0GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`NF-2));
|
||||
assign Sum1LEZ = $signed(PreNormSumExp) <= $signed((`NE+2)'(`BIAS-`BIAS1));
|
||||
assign Sum1GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`NF1-2+`BIAS-`BIAS1)) | ~|PreNormSumExp;
|
||||
assign Sum2LEZ = $signed(PreNormSumExp) <= $signed((`NE+2)'(`BIAS-`BIAS2));
|
||||
assign Sum2GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`NF2-2+`BIAS-`BIAS2)) | ~|PreNormSumExp;
|
||||
always_comb begin
|
||||
case (Fmt)
|
||||
`FMT: FmaPreResultDenorm = Sum0LEZ & Sum0GEFL & ~FmaSZero;
|
||||
|
@ -119,21 +121,21 @@ module fmashiftcalc(
|
|||
|
||||
end else if (`FPSIZES == 4) begin
|
||||
logic Sum0LEZ, Sum0GEFL, Sum1LEZ, Sum1GEFL, Sum2LEZ, Sum2GEFL, Sum3LEZ, Sum3GEFL;
|
||||
assign Sum0LEZ = NormSumExp[`NE+1] | ~|NormSumExp;
|
||||
assign Sum0GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`NF )-(`NE+2)'(2));
|
||||
assign Sum1LEZ = $signed(NormSumExp) <= $signed( (`NE+2)'(`BIAS)-(`NE+2)'(`D_BIAS));
|
||||
assign Sum1GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`D_NF+2)+(`NE+2)'(`BIAS)-(`NE+2)'(`D_BIAS)) | ~|NormSumExp;
|
||||
assign Sum2LEZ = $signed(NormSumExp) <= $signed( (`NE+2)'(`BIAS)-(`NE+2)'(`S_BIAS));
|
||||
assign Sum2GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`S_NF+2)+(`NE+2)'(`BIAS)-(`NE+2)'(`S_BIAS)) | ~|NormSumExp;
|
||||
assign Sum3LEZ = $signed(NormSumExp) <= $signed( (`NE+2)'(`BIAS)-(`NE+2)'(`H_BIAS));
|
||||
assign Sum3GEFL = $signed(NormSumExp) >= $signed(-(`NE+2)'(`H_NF+2)+(`NE+2)'(`BIAS)-(`NE+2)'(`H_BIAS)) | ~|NormSumExp;
|
||||
assign Sum0LEZ = PreNormSumExp[`NE+1] | ~|PreNormSumExp;
|
||||
assign Sum0GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`NF-2));
|
||||
assign Sum1LEZ = $signed(PreNormSumExp) <= $signed((`NE+2)'(`BIAS-`D_BIAS));
|
||||
assign Sum1GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`D_NF-2+`BIAS-`D_BIAS)) | ~|PreNormSumExp;
|
||||
assign Sum2LEZ = $signed(PreNormSumExp) <= $signed((`NE+2)'(`BIAS-`S_BIAS));
|
||||
assign Sum2GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`S_NF-2+`BIAS-`S_BIAS)) | ~|PreNormSumExp;
|
||||
assign Sum3LEZ = $signed(PreNormSumExp) <= $signed((`NE+2)'(`BIAS-`H_BIAS));
|
||||
assign Sum3GEFL = $signed(PreNormSumExp) >= $signed((`NE+2)'(-`H_NF-2+`BIAS-`H_BIAS)) | ~|PreNormSumExp;
|
||||
always_comb begin
|
||||
case (Fmt)
|
||||
2'h3: FmaPreResultDenorm = Sum0LEZ & Sum0GEFL & ~FmaSZero;
|
||||
2'h1: FmaPreResultDenorm = Sum1LEZ & Sum1GEFL & ~FmaSZero;
|
||||
2'h0: FmaPreResultDenorm = Sum2LEZ & Sum2GEFL & ~FmaSZero;
|
||||
2'h2: FmaPreResultDenorm = Sum3LEZ & Sum3GEFL & ~FmaSZero;
|
||||
endcase // *** remove checking to see if it's underflowed and only check for less than zero for denorm checking
|
||||
endcase
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -144,13 +146,13 @@ module fmashiftcalc(
|
|||
// - if kill prod dont add to exp
|
||||
|
||||
// Determine if the result is denormal
|
||||
// assign FmaPreResultDenorm = $signed(FmaNe)<=0 & ($signed(FmaNe)>=$signed(-FracLen)) & ~FmaSZero;
|
||||
// assign FmaPreResultDenorm = $signed(NormSumExp)<=0 & ($signed(NormSumExp)>=$signed(-FracLen)) & ~FmaSZero;
|
||||
|
||||
// Determine the shift needed for denormal results
|
||||
// - if not denorm add 1 to shift out the leading 1
|
||||
assign DenormShift = FmaPreResultDenorm ? FmaNe[$clog2(3*`NF+7)-1:0] : 1;
|
||||
// set and calculate the shift input and amount
|
||||
// - shift once if killing a product and the result is denormalized
|
||||
assign FmaShiftIn = {3'b0, FmaSm};
|
||||
assign FmaShiftAmt = FmaNCnt+DenormShift;
|
||||
if (`FPSIZES == 1)
|
||||
assign FmaShiftAmt = FmaPreResultDenorm ? FmaSe[$clog2(3*`NF+7)-1:0]+($clog2(3*`NF+7))'(`NF+3): FmaSCnt+1;
|
||||
else
|
||||
assign FmaShiftAmt = FmaPreResultDenorm ? FmaSe[$clog2(3*`NF+7)-1:0]+($clog2(3*`NF+7))'(`NF+3)+BiasCorr[$clog2(3*`NF+7)-1:0]: FmaSCnt+1;
|
||||
endmodule
|
||||
|
|
|
@ -30,28 +30,28 @@
|
|||
`include "wally-config.vh"
|
||||
|
||||
module fpu (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic [2:0] FRM_REGW, // Rounding mode from CSR
|
||||
input logic [31:0] InstrD, // instruction from IFU
|
||||
input logic [`FLEN-1:0] ReadDataW,// Read data from memory
|
||||
input logic [`XLEN-1:0] ForwardedSrcAE, // Integer input being processed (from IEU)
|
||||
input logic StallE, StallM, StallW, // stall signals from HZU
|
||||
input logic FlushE, FlushM, FlushW, // flush signals from HZU
|
||||
input logic [4:0] RdM, RdW, // which FP register to write to (from IEU)
|
||||
input logic [1:0] STATUS_FS, // Is floating-point enabled?
|
||||
output logic FRegWriteM, // FP register write enable
|
||||
output logic FpLoadStoreM, // Fp load instruction?
|
||||
output logic FStore2,
|
||||
output logic FStallD, // Stall the decode stage
|
||||
output logic FWriteIntE, // integer register write enables
|
||||
output logic [`XLEN-1:0] FWriteDataE, // Data to be written to memory
|
||||
output logic [`FLEN-1:0] FWriteDataM, // Data to be written to memory
|
||||
output logic [`XLEN-1:0] FIntResM, // data to be written to integer register
|
||||
output logic [`XLEN-1:0] FCvtIntResW, // data to be written to integer register
|
||||
output logic [1:0] FResSelW,
|
||||
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
|
||||
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic [2:0] FRM_REGW, // Rounding mode (from CSR)
|
||||
input logic [31:0] InstrD, // instruction (from IFU)
|
||||
input logic [`FLEN-1:0] ReadDataW, // Read data (from LSU)
|
||||
input logic [`XLEN-1:0] ForwardedSrcAE, // Integer input (from IEU)
|
||||
input logic StallE, StallM, StallW, // stall signals (from HZU)
|
||||
input logic FlushE, FlushM, FlushW, // flush signals (from HZU)
|
||||
input logic [4:0] RdM, RdW, // which FP register to write to (from IEU)
|
||||
input logic [1:0] STATUS_FS, // Is floating-point enabled? (From privileged unit)
|
||||
output logic FRegWriteM, // FP register write enable (to privileged unit)
|
||||
output logic FpLoadStoreM, // Fp load instruction? (to LSU)
|
||||
output logic FStore2, // store two words into memory (to LSU)
|
||||
output logic FStallD, // Stall the decode stage (To HZU)
|
||||
output logic FWriteIntE, // integer register write enable (to IEU)
|
||||
output logic [`XLEN-1:0] FWriteDataE, // Data to be written to memory (to IEU) - only used if `XLEN >`FLEN
|
||||
output logic [`FLEN-1:0] FWriteDataM, // Data to be written to memory (to IEU) - only used if `XLEN <`FLEN
|
||||
output logic [`XLEN-1:0] FIntResM, // data to be written to integer register (to IEU)
|
||||
output logic [`XLEN-1:0] FCvtIntResW, // convert result to to be written to integer register (to IEU)
|
||||
output logic [1:0] FResSelW, // final result selection (to IEU)
|
||||
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU)
|
||||
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction (to privileged unit)
|
||||
output logic [4:0] SetFflagsM // FPU flags (to privileged unit)
|
||||
);
|
||||
|
||||
|
@ -62,97 +62,91 @@ module fpu (
|
|||
// - sets the underflow after rounding
|
||||
|
||||
// control signals
|
||||
logic FRegWriteD, FRegWriteE, FRegWriteW; // FP register write enable
|
||||
logic [2:0] FrmD, FrmE, FrmM; // FP rounding mode
|
||||
logic [`FMTBITS-1:0] FmtD, FmtE, FmtM, FmtW; // FP precision 0-single 1-double
|
||||
logic FDivStartD, FDivStartE; // Start division or squareroot
|
||||
logic FWriteIntD; // Write to integer register
|
||||
logic FWriteIntM; // Write to integer register
|
||||
logic [1:0] FForwardXE, FForwardYE, FForwardZE; // forwarding mux control signals
|
||||
logic [2:0] FOpCtrlD, FOpCtrlE, FOpCtrlM; // Select which opperation to do in each component
|
||||
logic [1:0] FResSelD, FResSelE, FResSelM; // Select one of the results that finish in the memory stage
|
||||
logic [1:0] PostProcSelD, PostProcSelE, PostProcSelM; // select result in the post processing unit
|
||||
logic [4:0] Adr1E, Adr2E, Adr3E; // adresses of each input
|
||||
logic FRegWriteW; // FP register write enable
|
||||
logic [2:0] FrmM; // FP rounding mode
|
||||
logic [`FMTBITS-1:0] FmtE, FmtM; // FP precision 0-single 1-double
|
||||
logic DivStartE; // Start division or squareroot
|
||||
logic FWriteIntM; // Write to integer register
|
||||
logic [1:0] ForwardXE, ForwardYE, ForwardZE; // forwarding mux control signals
|
||||
logic [2:0] OpCtrlE, OpCtrlM; // Select which opperation to do in each component
|
||||
logic [1:0] FResSelE, FResSelM; // Select one of the results that finish in the memory stage
|
||||
logic [1:0] PostProcSelE, PostProcSelM; // select result in the post processing unit
|
||||
logic [4:0] Adr1E, Adr2E, Adr3E; // adresses of each input
|
||||
logic IllegalFPUInstrM;
|
||||
logic XEnE, YEnE, ZEnE;
|
||||
logic YEnForwardE, ZEnForwardE;
|
||||
|
||||
// regfile signals
|
||||
logic [`FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage
|
||||
logic [`FLEN-1:0] FRD1E, FRD2E, FRD3E; // Read Data from FP register - execute stage
|
||||
logic [`FLEN-1:0] FSrcXE; // Input 1 to the various units (after forwarding)
|
||||
logic [`XLEN-1:0] IntSrcXE; // Input 1 to the various units (after forwarding)
|
||||
logic [`FLEN-1:0] FPreSrcYE, FSrcYE; // Input 2 to the various units (after forwarding)
|
||||
logic [`FLEN-1:0] FPreSrcZE, FSrcZE; // Input 3 to the various units (after forwarding)
|
||||
logic [`FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage
|
||||
logic [`FLEN-1:0] FRD1E, FRD2E, FRD3E; // Read Data from FP register - execute stage
|
||||
logic [`FLEN-1:0] XE; // Input 1 to the various units (after forwarding)
|
||||
logic [`XLEN-1:0] IntSrcXE; // Input 1 to the various units (after forwarding)
|
||||
logic [`FLEN-1:0] PreYE, YE; // Input 2 to the various units (after forwarding)
|
||||
logic [`FLEN-1:0] PreZE, ZE; // Input 3 to the various units (after forwarding)
|
||||
|
||||
// unpacking signals
|
||||
logic XSgnE, YSgnE, ZSgnE; // input's sign - execute stage
|
||||
logic XSgnM, YSgnM; // input's sign - memory stage
|
||||
logic [`NE-1:0] XExpE, YExpE, ZExpE; // input's exponent - execute stage
|
||||
logic [`NE-1:0] ZExpM; // input's exponent - memory stage
|
||||
logic [`NF:0] XManE, YManE, ZManE; // input's fraction - execute stage
|
||||
logic [`NF:0] XManM, YManM, ZManM; // input's fraction - memory stage
|
||||
logic XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute stage
|
||||
logic XNaNM, YNaNM, ZNaNM; // is the input a NaN - memory stage
|
||||
logic XNaNQ, YNaNQ; // is the input a NaN - divide
|
||||
logic XSNaNE, YSNaNE, ZSNaNE; // is the input a signaling NaN - execute stage
|
||||
logic XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage
|
||||
logic XDenormE, ZDenormE, ZDenormM; // is the input denormalized
|
||||
logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage
|
||||
logic XZeroM, YZeroM, ZZeroM; // is the input zero - memory stage
|
||||
logic XZeroQ, YZeroQ; // is the input zero - divide
|
||||
logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage
|
||||
logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage
|
||||
logic XInfQ, YInfQ; // is the input infinity - divide
|
||||
logic XExpMaxE; // is the exponent all ones (max value)
|
||||
logic FmtQ;
|
||||
logic FOpCtrlQ;
|
||||
logic XsE, YsE, ZsE; // input's sign - execute stage
|
||||
logic XsM, YsM; // input's sign - memory stage
|
||||
logic [`NE-1:0] XeE, YeE, ZeE; // input's exponent - execute stage
|
||||
logic [`NE-1:0] ZeM; // input's exponent - memory stage
|
||||
logic [`NF:0] XmE, YmE, ZmE; // input's fraction - execute stage
|
||||
logic [`NF:0] XmM, YmM, ZmM; // input's fraction - memory stage
|
||||
logic XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute stage
|
||||
logic XNaNM, YNaNM, ZNaNM; // is the input a NaN - memory stage
|
||||
logic XNaNQ, YNaNQ; // is the input a NaN - divide
|
||||
logic XSNaNE, YSNaNE, ZSNaNE; // is the input a signaling NaN - execute stage
|
||||
logic XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage
|
||||
logic XDenormE, ZDenormE, ZDenormM; // is the input denormalized
|
||||
logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage
|
||||
logic XZeroM, YZeroM, ZZeroM; // is the input zero - memory stage
|
||||
logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage
|
||||
logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage
|
||||
logic XExpMaxE; // is the exponent all ones (max value)
|
||||
|
||||
// Fma Signals
|
||||
logic [3*`NF+5:0] SumE, SumM;
|
||||
logic [`NE+1:0] ProdExpE, ProdExpM;
|
||||
logic AddendStickyE, AddendStickyM;
|
||||
logic KillProdE, KillProdM;
|
||||
logic InvAE, InvAM;
|
||||
logic NegSumE, NegSumM;
|
||||
logic ZSgnEffE, ZSgnEffM;
|
||||
logic PSgnE, PSgnM;
|
||||
logic [$clog2(3*`NF+7)-1:0] FmaNormCntE, FmaNormCntM;
|
||||
logic [3*`NF+5:0] SmE, SmM;
|
||||
logic [`NE+1:0] PeE, PeM;
|
||||
logic ZmStickyE, ZmStickyM;
|
||||
logic [`NE+1:0] SeE,SeM;
|
||||
logic KillProdE, KillProdM;
|
||||
logic InvAE, InvAM;
|
||||
logic NegSumE, NegSumM;
|
||||
logic AsE, AsM;
|
||||
logic PsE, PsM;
|
||||
logic SsE, SsM;
|
||||
logic [$clog2(3*`NF+7)-1:0] SCntE, SCntM;
|
||||
|
||||
// Cvt Signals
|
||||
logic [`NE:0] CvtCalcExpE, CvtCalcExpM; // the calculated expoent
|
||||
logic [`LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by
|
||||
logic [`NE:0] CeE, CeM; // the calculated expoent
|
||||
logic [`LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by
|
||||
logic CvtResDenormUfE, CvtResDenormUfM;// does the result underflow or is denormalized
|
||||
logic CvtResSgnE, CvtResSgnM; // the result's sign
|
||||
logic CsE, CsM; // the result's sign
|
||||
logic IntZeroE, IntZeroM; // is the integer zero?
|
||||
logic [`CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder)
|
||||
logic [`CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder)
|
||||
|
||||
//divide signals
|
||||
logic [`QLEN-1-(`RADIX/4):0] QuotM;
|
||||
logic [`NE+1:0] DivCalcExpE, DivCalcExpM;
|
||||
logic DivStickyE, DivStickyM;
|
||||
logic DivDoneM;
|
||||
logic [`DURLEN-1:0] EarlyTermShiftM;
|
||||
logic [`QLEN-1-(`RADIX/4):0] QmM;
|
||||
logic [`NE+1:0] QeE, QeM;
|
||||
logic DivSE, DivSM;
|
||||
logic DivDoneM;
|
||||
logic [`DURLEN-1:0] EarlyTermShiftM;
|
||||
|
||||
// result and flag signals
|
||||
logic [63:0] FDivResM, FDivResW; // divide/squareroot result
|
||||
logic [4:0] FDivFlgM; // divide/squareroot flags
|
||||
logic [`FLEN-1:0] ReadResW; // read result (load instruction)
|
||||
logic [`XLEN-1:0] ClassResE; // classify result
|
||||
logic [`XLEN-1:0] FIntResE; // classify result
|
||||
logic [`FLEN-1:0] FpResM, FpResW; // classify result
|
||||
logic [`FLEN-1:0] PostProcResM; // classify result
|
||||
logic [4:0] PostProcFlgM; // classify result
|
||||
logic [`XLEN-1:0] ClassResE; // classify result
|
||||
logic [`XLEN-1:0] FIntResE; // classify result
|
||||
logic [`FLEN-1:0] FpResM, FpResW; // classify result
|
||||
logic [`FLEN-1:0] PostProcResM; // classify result
|
||||
logic [4:0] PostProcFlgM; // classify result
|
||||
logic [`XLEN-1:0] FCvtIntResM;
|
||||
logic [`FLEN-1:0] CmpFpResE; // compare result
|
||||
logic [`XLEN-1:0] CmpIntResE; // compare result
|
||||
logic CmpNVE; // compare invalid flag (Not Valid)
|
||||
logic [`FLEN-1:0] SgnResE; // sign injection result
|
||||
logic [`FLEN-1:0] PreFpResE, PreFpResM, PreFpResW; // selected result that is ready in the memory stage
|
||||
logic PreNVE, PreNVM; // selected flag that is ready in the memory stage
|
||||
logic [`FLEN-1:0] FPUResultW; // final FP result being written to the FP register
|
||||
logic [`FLEN-1:0] CmpFpResE; // compare result
|
||||
logic [`XLEN-1:0] CmpIntResE; // compare result
|
||||
logic CmpNVE; // compare invalid flag (Not Valid)
|
||||
logic [`FLEN-1:0] SgnResE; // sign injection result
|
||||
logic [`FLEN-1:0] PreFpResE, PreFpResM; // selected result that is ready in the memory stage
|
||||
logic PreNVE, PreNVM; // selected flag that is ready in the memory stage
|
||||
logic [`FLEN-1:0] FPUResultW; // final FP result being written to the FP register
|
||||
// other signals
|
||||
logic FDivSqrtDoneE; // is divide done
|
||||
logic [63:0] DivInput1E, DivInput2E; // inputs to divide/squareroot unit
|
||||
logic load_preload; // enable for FF on fpdivsqrt
|
||||
logic [`FLEN-1:0] AlignedSrcAE; // align SrcA to the floating point format
|
||||
logic [`FLEN-1:0] AlignedSrcAE; // align SrcA to the floating point format
|
||||
logic [`FLEN-1:0] BoxedZeroE; // Zero value for Z for multiplication, with NaN boxing if needed
|
||||
logic [`FLEN-1:0] BoxedOneE; // Zero value for Z for multiplication, with NaN boxing if needed
|
||||
|
||||
|
@ -169,9 +163,11 @@ module fpu (
|
|||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// calculate FP control signals
|
||||
fctrl fctrl (.Funct7D(InstrD[31:25]), .OpD(InstrD[6:0]), .Rs2D(InstrD[24:20]), .Funct3D(InstrD[14:12]), .FRM_REGW, .STATUS_FS,
|
||||
.IllegalFPUInstrD, .FRegWriteD, .FDivStartD, .FResSelD, .FOpCtrlD, .PostProcSelD,
|
||||
.FmtD, .FrmD, .FWriteIntD);
|
||||
fctrl fctrl (.Funct7D(InstrD[31:25]), .OpD(InstrD[6:0]), .Rs2D(InstrD[24:20]), .Funct3D(InstrD[14:12]), .InstrD,
|
||||
.StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, .FRM_REGW, .STATUS_FS, .FDivBusyE,
|
||||
.reset, .clk, .IllegalFPUInstrD, .FRegWriteM, .FRegWriteW, .FrmM, .FmtE, .FmtM, .YEnForwardE, .ZEnForwardE,
|
||||
.DivStartE, .FWriteIntE, .FWriteIntM, .OpCtrlE, .OpCtrlM, .IllegalFPUInstrM, .XEnE, .YEnE, .ZEnE,
|
||||
.FResSelE, .FResSelM, .FResSelW, .PostProcSelE, .PostProcSelM, .Adr1E, .Adr2E, .Adr3E);
|
||||
|
||||
// FP register file
|
||||
fregfile fregfile (.clk, .reset, .we4(FRegWriteW),
|
||||
|
@ -183,12 +179,6 @@ module fpu (
|
|||
flopenrc #(`FLEN) DEReg1(clk, reset, FlushE, ~StallE, FRD1D, FRD1E);
|
||||
flopenrc #(`FLEN) DEReg2(clk, reset, FlushE, ~StallE, FRD2D, FRD2E);
|
||||
flopenrc #(`FLEN) DEReg3(clk, reset, FlushE, ~StallE, FRD3D, FRD3E);
|
||||
flopenrc #(15) DEAdrReg(clk, reset, FlushE, ~StallE, {InstrD[19:15], InstrD[24:20], InstrD[31:27]},
|
||||
{Adr1E, Adr2E, Adr3E});
|
||||
flopenrc #(12+`FMTBITS) DECtrlReg3(clk, reset, FlushE, ~StallE,
|
||||
{FRegWriteD, PostProcSelD, FResSelD, FrmD, FmtD, FOpCtrlD, FWriteIntD},
|
||||
{FRegWriteE, PostProcSelE, FResSelE, FrmE, FmtE, FOpCtrlE, FWriteIntE});
|
||||
flopenrc #(1) DEDivStartReg(clk, reset, FlushE, ~StallE|FDivBusyE, FDivStartD, FDivStartE);
|
||||
|
||||
// EXECUTION STAGE
|
||||
|
||||
|
@ -205,12 +195,12 @@ module fpu (
|
|||
// Hazard unit for FPU
|
||||
// - determines if any forwarding or stalls are needed
|
||||
fhazard fhazard(.Adr1E, .Adr2E, .Adr3E, .FRegWriteM, .FRegWriteW, .RdM, .RdW, .FResSelM,
|
||||
.FStallD, .FForwardXE, .FForwardYE, .FForwardZE);
|
||||
.XEnE, .YEnE(YEnForwardE), .ZEnE(ZEnForwardE), .FStallD, .ForwardXE, .ForwardYE, .ForwardZE);
|
||||
|
||||
// forwarding muxs
|
||||
mux3 #(`FLEN) fxemux (FRD1E, FPUResultW, PreFpResM, FForwardXE, FSrcXE);
|
||||
mux3 #(`FLEN) fyemux (FRD2E, FPUResultW, PreFpResM, FForwardYE, FPreSrcYE);
|
||||
mux3 #(`FLEN) fzemux (FRD3E, FPUResultW, PreFpResM, FForwardZE, FPreSrcZE);
|
||||
mux3 #(`FLEN) fxemux (FRD1E, FPUResultW, PreFpResM, ForwardXE, XE);
|
||||
mux3 #(`FLEN) fyemux (FRD2E, FPUResultW, PreFpResM, ForwardYE, PreYE);
|
||||
mux3 #(`FLEN) fzemux (FRD3E, FPUResultW, PreFpResM, ForwardZE, PreZE);
|
||||
|
||||
|
||||
generate
|
||||
|
@ -225,7 +215,7 @@ module fpu (
|
|||
endgenerate
|
||||
|
||||
|
||||
mux2 #(`FLEN) fyaddmux (FPreSrcYE, BoxedOneE, FOpCtrlE[2]&FOpCtrlE[1]&(FResSelE==2'b01)&(PostProcSelE==2'b10), FSrcYE); // Force Z to be 0 for multiply instructions
|
||||
mux2 #(`FLEN) fyaddmux (PreYE, BoxedOneE, OpCtrlE[2]&OpCtrlE[1]&(FResSelE==2'b01)&(PostProcSelE==2'b10), YE); // Force Z to be 0 for multiply instructions
|
||||
|
||||
// Force Z to be 0 for multiply instructions
|
||||
generate
|
||||
|
@ -239,80 +229,76 @@ module fpu (
|
|||
(`FLEN)'(0), FmtE, BoxedZeroE); // NaN boxing zeroes
|
||||
endgenerate
|
||||
|
||||
mux3 #(`FLEN) fzmulmux (FPreSrcZE, BoxedZeroE, FPreSrcYE, {FOpCtrlE[2]&FOpCtrlE[1], FOpCtrlE[2]&~FOpCtrlE[1]}, FSrcZE);
|
||||
mux3 #(`FLEN) fzmulmux (PreZE, BoxedZeroE, PreYE, {OpCtrlE[2]&OpCtrlE[1], OpCtrlE[2]&~OpCtrlE[1]}, ZE);
|
||||
|
||||
// unpack unit
|
||||
// - splits FP inputs into their various parts
|
||||
// - does some classifications (SNaN, NaN, Denorm, Norm, Zero, Infifnity)
|
||||
unpack unpack (.X(FSrcXE), .Y(FSrcYE), .Z(FSrcZE), .FmtE,
|
||||
.XSgnE, .YSgnE, .ZSgnE, .XExpE, .YExpE, .ZExpE, .XManE, .YManE, .ZManE,
|
||||
.XNaNE, .YNaNE, .ZNaNE, .XSNaNE, .YSNaNE, .ZSNaNE, .XDenormE, .ZDenormE,
|
||||
.XZeroE, .YZeroE, .ZZeroE, .XInfE, .YInfE, .ZInfE, .XExpMaxE);
|
||||
unpack unpack (.X(XE), .Y(YE), .Z(ZE), .Fmt(FmtE), .Xs(XsE), .Ys(YsE), .Zs(ZsE),
|
||||
.Xe(XeE), .Ye(YeE), .Ze(ZeE), .Xm(XmE), .Ym(YmE), .Zm(ZmE), .YEn(YEnE),
|
||||
.XNaN(XNaNE), .YNaN(YNaNE), .ZNaN(ZNaNE), .XSNaN(XSNaNE), .XEn(XEnE),
|
||||
.YSNaN(YSNaNE), .ZSNaN(ZSNaNE), .XDenorm(XDenormE), .ZDenorm(ZDenormE),
|
||||
.XZero(XZeroE), .YZero(YZeroE), .ZZero(ZZeroE), .XInf(XInfE), .YInf(YInfE),
|
||||
.ZEn(ZEnE), .ZInf(ZInfE), .XExpMax(XExpMaxE));
|
||||
|
||||
// fma - does multiply, add, and multiply-add instructions
|
||||
fma fma (.Xs(XSgnE), .Ys(YSgnE), .Zs(ZSgnE),
|
||||
.Xe(XExpE), .Ye(YExpE), .Ze(ZExpE),
|
||||
.Xm(XManE), .Ym(YManE), .Zm(ZManE),
|
||||
// fused multiply add
|
||||
// - fadd/fsub
|
||||
// - fmul
|
||||
// - fmadd/fnmadd/fmsub/fnmsub
|
||||
fma fma (.Xs(XsE), .Ys(YsE), .Zs(ZsE),
|
||||
.Xe(XeE), .Ye(YeE), .Ze(ZeE),
|
||||
.Xm(XmE), .Ym(YmE), .Zm(ZmE),
|
||||
.XZero(XZeroE), .YZero(YZeroE), .ZZero(ZZeroE),
|
||||
.FOpCtrl(FOpCtrlE), .Fmt(FmtE),
|
||||
.As(ZSgnEffE), .Ps(PSgnE),
|
||||
.Sm(SumE), .Pe(ProdExpE),
|
||||
.NegSum(NegSumE), .InvA(InvAE), .NCnt(FmaNormCntE),
|
||||
.ZmSticky(AddendStickyE), .KillProd(KillProdE));
|
||||
.OpCtrl(OpCtrlE), .Fmt(FmtE),
|
||||
.As(AsE), .Ps(PsE), .Ss(SsE), .Se(SeE),
|
||||
.Sm(SmE), .Pe(PeE),
|
||||
.NegSum(NegSumE), .InvA(InvAE), .SCnt(SCntE),
|
||||
.ZmSticky(ZmStickyE), .KillProd(KillProdE));
|
||||
|
||||
// // fpdivsqrt using Goldschmidt's iteration
|
||||
// if(`FLEN == 64) begin
|
||||
// flopenrc #(64) reg_input1 (.d({FSrcXE[63:0]}), .q(DivInput1E),
|
||||
// .clear(FDivSqrtDoneE), .en(load_preload),
|
||||
// .reset(reset), .clk(clk));
|
||||
// flopenrc #(64) reg_input2 (.d({FSrcYE[63:0]}), .q(DivInput2E),
|
||||
// .clear(FDivSqrtDoneE), .en(load_preload),
|
||||
// .reset(reset), .clk(clk));
|
||||
// end
|
||||
// else if (`FLEN == 32) begin
|
||||
// flopenrc #(64) reg_input1 (.d({32'b0, FSrcXE[31:0]}), .q(DivInput1E),
|
||||
// .clear(FDivSqrtDoneE), .en(load_preload),
|
||||
// .reset(reset), .clk(clk));
|
||||
// flopenrc #(64) reg_input2 (.d({32'b0, FSrcYE[31:0]}), .q(DivInput2E),
|
||||
// .clear(FDivSqrtDoneE), .en(load_preload),
|
||||
// .reset(reset), .clk(clk));
|
||||
// end
|
||||
// flopenrc #(8) reg_input3 (.d({XNaNE, YNaNE, XInfE, YInfE, XZeroE, YZeroE, FmtE[0], FOpCtrlE[0]}),
|
||||
// .q({XNaNQ, YNaNQ, XInfQ, YInfQ, XZeroQ, YZeroQ, FmtQ, FOpCtrlQ}),
|
||||
// .clear(FDivSqrtDoneE), .en(load_preload),
|
||||
// .reset(reset), .clk(clk));
|
||||
// fpdiv_pipe fdivsqrt (.op1(DivInput1E[63:0]), .op2(DivInput2E[63:0]), .rm(FrmE[1:0]), .op_type(FOpCtrlQ),
|
||||
// .reset, .clk(clk), .start(FDivStartE), .P(~FmtQ), .OvEn(1'b1), .UnEn(1'b1),
|
||||
// .XNaNQ, .YNaNQ, .XInfQ, .YInfQ, .XZeroQ, .YZeroQ, .load_preload,
|
||||
// .FDivBusyE, .done(FDivSqrtDoneE), .AS_Result(FDivResM), .Flags(FDivFlgM));
|
||||
divsqrt divsqrt(.clk, .reset, .FmtE, .XManE, .YManE, .XExpE, .YExpE,
|
||||
.XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .DivStartE(FDivStartE),
|
||||
.StallE, .StallM, .DivStickyM, .DivBusy(FDivBusyE), .DivCalcExpM, //***change divbusyE to M signal
|
||||
.EarlyTermShiftM, .QuotM, .DivDone(DivDoneM));
|
||||
// other FP execution units
|
||||
fcmp fcmp (.FmtE, .FOpCtrlE, .XSgnE, .YSgnE, .XExpE, .YExpE, .XManE, .YManE,
|
||||
.XZeroE, .YZeroE, .XNaNE, .YNaNE, .XSNaNE, .YSNaNE, .FSrcXE, .FSrcYE, .CmpNVE, .CmpFpResE, .CmpIntResE);
|
||||
fsgninj fsgninj(.SgnOpCodeE(FOpCtrlE[1:0]), .XSgnE, .YSgnE, .FSrcXE, .FmtE, .SgnResE);
|
||||
fclassify fclassify (.XSgnE, .XDenormE, .XZeroE, .XNaNE, .XInfE, .XSNaNE, .ClassResE);
|
||||
// divide and squareroot
|
||||
// - fdiv
|
||||
// - fsqrt
|
||||
// *** add other opperations
|
||||
divsqrt divsqrt(.clk, .reset, .FmtE, .XmE, .YmE, .XeE, .YeE, .SqrtE(OpCtrlE[0]), .SqrtM(OpCtrlM[0]),
|
||||
.XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .DivStartE(DivStartE),
|
||||
.StallE, .StallM, .DivSM, .DivBusy(FDivBusyE), .QeM, //***change divbusyE to M signal
|
||||
.EarlyTermShiftM, .QmM, .DivDone(DivDoneM));
|
||||
// compare
|
||||
// - fmin/fmax
|
||||
// - flt/fle/feq
|
||||
fcmp fcmp (.Fmt(FmtE), .OpCtrl(OpCtrlE), .Xs(XsE), .Ys(YsE), .Xe(XeE), .Ye(YeE),
|
||||
.Xm(XmE), .Ym(YmE), .XZero(XZeroE), .YZero(YZeroE), .XNaN(XNaNE), .YNaN(YNaNE),
|
||||
.XSNaN(XSNaNE), .YSNaN(YSNaNE), .X(XE), .Y(YE), .CmpNV(CmpNVE),
|
||||
.CmpFpRes(CmpFpResE), .CmpIntRes(CmpIntResE));
|
||||
// sign injection
|
||||
// - fsgnj/fsgnjx/fsgnjn
|
||||
fsgninj fsgninj(.OpCtrl(OpCtrlE[1:0]), .Xs(XsE), .Ys(YsE), .X(XE), .Fmt(FmtE), .SgnRes(SgnResE));
|
||||
|
||||
fcvt fcvt (.Xs(XSgnE), .Xe(XExpE), .Xm(XManE), .Int(ForwardedSrcAE), .FOpCtrl(FOpCtrlE),
|
||||
.ToInt(FWriteIntE), .XZero(XZeroE), .XDenorm(XDenormE), .Fmt(FmtE), .Ce(CvtCalcExpE),
|
||||
.ShiftAmt(CvtShiftAmtE), .ResDenormUf(CvtResDenormUfE), .Cs(CvtResSgnE), .IntZero(IntZeroE),
|
||||
// classify
|
||||
// - fclass
|
||||
fclassify fclassify (.Xs(XsE), .XDenorm(XDenormE), .XZero(XZeroE), .XNaN(XNaNE),
|
||||
.XInf(XInfE), .XSNaN(XSNaNE), .ClassRes(ClassResE));
|
||||
|
||||
// convert
|
||||
// - fcvt.*.*
|
||||
fcvt fcvt (.Xs(XsE), .Xe(XeE), .Xm(XmE), .Int(ForwardedSrcAE), .OpCtrl(OpCtrlE),
|
||||
.ToInt(FWriteIntE), .XZero(XZeroE), .XDenorm(XDenormE), .Fmt(FmtE), .Ce(CeE),
|
||||
.ShiftAmt(CvtShiftAmtE), .ResDenormUf(CvtResDenormUfE), .Cs(CsE), .IntZero(IntZeroE),
|
||||
.LzcIn(CvtLzcInE));
|
||||
|
||||
// data to be stored in memory - to IEU
|
||||
// - FP uses NaN-blocking format
|
||||
// - if there are any unsused bits the most significant bits are filled with 1s
|
||||
if (`LLEN==`XLEN) begin
|
||||
assign FWriteDataE = FSrcYE[`XLEN-1:0];
|
||||
assign FWriteDataE = YE[`XLEN-1:0];
|
||||
end else begin
|
||||
logic [`FLEN-1:0] FWriteDataE;
|
||||
if(`FMTBITS == 2) assign FStore2 = FmtM == `FMT;
|
||||
else assign FStore2 = FmtM;
|
||||
if(`FMTBITS == 2) assign FStore2 = (FmtM == `FMT)&~IllegalFPUInstrM;
|
||||
else assign FStore2 = FmtM&~IllegalFPUInstrM;
|
||||
|
||||
if (`FPSIZES==1) assign FWriteDataE = FSrcYE;
|
||||
else if (`FPSIZES==2) assign FWriteDataE = FmtE ? FSrcYE : {2{FSrcYE[`LEN1-1:0]}};
|
||||
else assign FWriteDataE = FmtE == `FMT ? FSrcYE : {2{FSrcYE[`LEN1-1:0]}};
|
||||
if (`FPSIZES==1) assign FWriteDataE = YE;
|
||||
else if (`FPSIZES==2) assign FWriteDataE = FmtE ? YE : {2{YE[`LEN1-1:0]}};
|
||||
else assign FWriteDataE = FmtE == `FMT ? YE : {2{YE[`LEN1-1:0]}};
|
||||
|
||||
flopenrc #(`FLEN) EMWriteDataReg (clk, reset, FlushM, ~StallM, FWriteDataE, FWriteDataM);
|
||||
end
|
||||
|
@ -329,14 +315,14 @@ module fpu (
|
|||
{{`FLEN-`XLEN{1'b1}}, ForwardedSrcAE}, FmtE, AlignedSrcAE); // NaN boxing zeroes
|
||||
endgenerate
|
||||
// select a result that may be written to the FP register
|
||||
mux3 #(`FLEN) FResMux(SgnResE, AlignedSrcAE, CmpFpResE, {FOpCtrlE[2], &FOpCtrlE[1:0]}, PreFpResE);
|
||||
assign PreNVE = CmpNVE&(FOpCtrlE[2]|FWriteIntE);
|
||||
mux3 #(`FLEN) FResMux(SgnResE, AlignedSrcAE, CmpFpResE, {OpCtrlE[2], &OpCtrlE[1:0]}, PreFpResE);
|
||||
assign PreNVE = CmpNVE&(OpCtrlE[2]|FWriteIntE);
|
||||
|
||||
// select the result that may be written to the integer register - to IEU
|
||||
if (`FLEN>`XLEN)
|
||||
assign IntSrcXE = FSrcXE[`XLEN-1:0];
|
||||
assign IntSrcXE = XE[`XLEN-1:0];
|
||||
else
|
||||
assign IntSrcXE = {{`XLEN-`FLEN{FSrcXE[`FLEN-1:0]}}, FSrcXE};
|
||||
assign IntSrcXE = {{`XLEN-`FLEN{XE[`FLEN-1:0]}}, XE};
|
||||
|
||||
mux3 #(`XLEN) IntResMux (ClassResE, IntSrcXE, CmpIntResE, {~FResSelE[1], FResSelE[0]}, FIntResE);
|
||||
// *** DH 5/25/22: CvtRes will move to mem stage. Premux in execute to save area, then make sure stalls are ok
|
||||
|
@ -344,27 +330,24 @@ module fpu (
|
|||
|
||||
// E/M pipe registers
|
||||
|
||||
// flopenrc #(64) EMFpReg1(clk, reset, FlushM, ~StallM, FSrcXE, FSrcXM);
|
||||
flopenrc #(`NF+2) EMFpReg2 (clk, reset, FlushM, ~StallM, {XSgnE,XManE}, {XSgnM,XManM});
|
||||
flopenrc #(`NF+2) EMFpReg3 (clk, reset, FlushM, ~StallM, {YSgnE,YManE}, {YSgnM,YManM});
|
||||
flopenrc #(`FLEN) EMFpReg4 (clk, reset, FlushM, ~StallM, {ZExpE,ZManE}, {ZExpM,ZManM});
|
||||
// flopenrc #(64) EMFpReg1(clk, reset, FlushM, ~StallM, XE, FSrcXM);
|
||||
flopenrc #(`NF+2) EMFpReg2 (clk, reset, FlushM, ~StallM, {XsE,XmE}, {XsM,XmM});
|
||||
flopenrc #(`NF+2) EMFpReg3 (clk, reset, FlushM, ~StallM, {YsE,YmE}, {YsM,YmM});
|
||||
flopenrc #(`FLEN) EMFpReg4 (clk, reset, FlushM, ~StallM, {ZeE,ZmE}, {ZeM,ZmM});
|
||||
flopenrc #(`XLEN) EMFpReg6 (clk, reset, FlushM, ~StallM, FIntResE, FIntResM);
|
||||
flopenrc #(`FLEN) EMFpReg7 (clk, reset, FlushM, ~StallM, PreFpResE, PreFpResM);
|
||||
flopenrc #(13) EMFpReg5 (clk, reset, FlushM, ~StallM,
|
||||
{XZeroE, YZeroE, ZZeroE, XInfE, YInfE, ZInfE, XNaNE, YNaNE, ZNaNE, XSNaNE, YSNaNE, ZSNaNE, ZDenormE},
|
||||
{XZeroM, YZeroM, ZZeroM, XInfM, YInfM, ZInfM, XNaNM, YNaNM, ZNaNM, XSNaNM, YSNaNM, ZSNaNM, ZDenormM});
|
||||
flopenrc #(1) EMRegCmpFlg (clk, reset, FlushM, ~StallM, PreNVE, PreNVM);
|
||||
flopenrc #(12+int'(`FMTBITS)) EMCtrlReg (clk, reset, FlushM, ~StallM,
|
||||
{FRegWriteE, FResSelE, PostProcSelE, FrmE, FmtE, FOpCtrlE, FWriteIntE},
|
||||
{FRegWriteM, FResSelM, PostProcSelM, FrmM, FmtM, FOpCtrlM, FWriteIntM});
|
||||
flopenrc #(3*`NF+6) EMRegFma2(clk, reset, FlushM, ~StallM, SumE, SumM);
|
||||
flopenrc #(`NE+2) EMRegFma3(clk, reset, FlushM, ~StallM, ProdExpE, ProdExpM);
|
||||
flopenrc #($clog2(3*`NF+7)+6) EMRegFma4(clk, reset, FlushM, ~StallM,
|
||||
{AddendStickyE, KillProdE, InvAE, FmaNormCntE, NegSumE, ZSgnEffE, PSgnE},
|
||||
{AddendStickyM, KillProdM, InvAM, FmaNormCntM, NegSumM, ZSgnEffM, PSgnM});
|
||||
flopenrc #(3*`NF+6) EMRegFma2(clk, reset, FlushM, ~StallM, SmE, SmM);
|
||||
flopenrc #(`NE+2) EMRegFma3(clk, reset, FlushM, ~StallM, PeE, PeM);
|
||||
flopenrc #($clog2(3*`NF+7)+9+`NE) EMRegFma4(clk, reset, FlushM, ~StallM,
|
||||
{ZmStickyE, KillProdE, InvAE, SCntE, NegSumE, AsE, PsE, SsE, SeE},
|
||||
{ZmStickyM, KillProdM, InvAM, SCntM, NegSumM, AsM, PsM, SsM, SeM});
|
||||
flopenrc #(`NE+`LOGCVTLEN+`CVTLEN+4) EMRegCvt(clk, reset, FlushM, ~StallM,
|
||||
{CvtCalcExpE, CvtShiftAmtE, CvtResDenormUfE, CvtResSgnE, IntZeroE, CvtLzcInE},
|
||||
{CvtCalcExpM, CvtShiftAmtM, CvtResDenormUfM, CvtResSgnM, IntZeroM, CvtLzcInM});
|
||||
{CeE, CvtShiftAmtE, CvtResDenormUfE, CsE, IntZeroE, CvtLzcInE},
|
||||
{CeM, CvtShiftAmtM, CvtResDenormUfM, CsM, IntZeroM, CvtLzcInM});
|
||||
|
||||
// BEGIN MEMORY STAGE
|
||||
|
||||
|
@ -380,11 +363,11 @@ module fpu (
|
|||
|
||||
assign FpLoadStoreM = FResSelM[1];
|
||||
|
||||
postprocess postprocess(.Xs(XSgnM), .Ys(YSgnM), .Ze(ZExpM), .Xm(XManM), .Ym(YManM), .Zm(ZManM), .Frm(FrmM), .Fmt(FmtM), .FmaPe(ProdExpM), .DivEarlyTermShift(EarlyTermShiftM),
|
||||
.FmaZmS(AddendStickyM), .FmaKillProd(KillProdM), .XZero(XZeroM), .YZero(YZeroM), .ZZero(ZZeroM), .XInf(XInfM), .YInf(YInfM), .DivQm(QuotM),
|
||||
.ZInf(ZInfM), .XNaN(XNaNM), .YNaN(YNaNM), .ZNaN(ZNaNM), .XSNaN(XSNaNM), .YSNaN(YSNaNM), .ZSNaN(ZSNaNM), .FmaSm(SumM), .DivQe(DivCalcExpM), .DivDone(DivDoneM),
|
||||
.FmaNegSum(NegSumM), .FmaInvA(InvAM), .ZDenorm(ZDenormM), .FmaAs(ZSgnEffM), .FmaPs(PSgnM), .FOpCtrl(FOpCtrlM), .FmaNCnt(FmaNormCntM),
|
||||
.CvtCe(CvtCalcExpM), .CvtResDenormUf(CvtResDenormUfM),.CvtShiftAmt(CvtShiftAmtM), .CvtCs(CvtResSgnM), .ToInt(FWriteIntM), .DivS(DivStickyM),
|
||||
postprocess postprocess(.Xs(XsM), .Ys(YsM), .Ze(ZeM), .Xm(XmM), .Ym(YmM), .Zm(ZmM), .Frm(FrmM), .Fmt(FmtM), .FmaPe(PeM), .DivEarlyTermShift(EarlyTermShiftM),
|
||||
.FmaZmS(ZmStickyM), .FmaKillProd(KillProdM), .XZero(XZeroM), .YZero(YZeroM), .ZZero(ZZeroM), .XInf(XInfM), .YInf(YInfM), .DivQm(QmM), .FmaSs(SsM),
|
||||
.ZInf(ZInfM), .XNaN(XNaNM), .YNaN(YNaNM), .ZNaN(ZNaNM), .XSNaN(XSNaNM), .YSNaN(YSNaNM), .ZSNaN(ZSNaNM), .FmaSm(SmM), .DivQe(QeM), .DivDone(DivDoneM),
|
||||
.FmaNegSum(NegSumM), .FmaInvA(InvAM), .ZDenorm(ZDenormM), .FmaAs(AsM), .FmaPs(PsM), .OpCtrl(OpCtrlM), .FmaSCnt(SCntM), .FmaSe(SeM),
|
||||
.CvtCe(CeM), .CvtResDenormUf(CvtResDenormUfM),.CvtShiftAmt(CvtShiftAmtM), .CvtCs(CsM), .ToInt(FWriteIntM), .DivS(DivSM),
|
||||
.CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM), .PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM));
|
||||
|
||||
// FPU flag selection - to privileged
|
||||
|
@ -394,9 +377,6 @@ module fpu (
|
|||
// M/W pipe registers
|
||||
flopenrc #(`FLEN) MWRegFp(clk, reset, FlushW, ~StallW, FpResM, FpResW);
|
||||
flopenrc #(`XLEN) MWRegInt(clk, reset, FlushW, ~StallW, FCvtIntResM, FCvtIntResW);
|
||||
flopenrc #(4+int'(`FMTBITS-1)) MWCtrlReg(clk, reset, FlushW, ~StallW,
|
||||
{FRegWriteM, FResSelM, FmtM},
|
||||
{FRegWriteW, FResSelW, FmtW});
|
||||
|
||||
// BEGIN WRITEBACK STAGE
|
||||
|
||||
|
|
|
@ -26,60 +26,59 @@
|
|||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
// OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module fsgninj (
|
||||
input logic XSgnE, YSgnE, // X and Y sign bits
|
||||
input logic [`FLEN-1:0] FSrcXE, // X
|
||||
input logic [`FMTBITS-1:0] FmtE, // precision 1 = double 0 = single
|
||||
input logic [1:0] SgnOpCodeE, // operation control
|
||||
output logic [`FLEN-1:0] SgnResE // result
|
||||
input logic Xs, Ys, // X and Y sign bits
|
||||
input logic [`FLEN-1:0] X, // X
|
||||
input logic [`FMTBITS-1:0] Fmt, // format
|
||||
input logic [1:0] OpCtrl, // operation control
|
||||
output logic [`FLEN-1:0] SgnRes // result
|
||||
);
|
||||
|
||||
logic ResSgn;
|
||||
|
||||
//op code designation:
|
||||
//
|
||||
//00 - fsgnj - directly copy over sign value of FSrcYE
|
||||
//01 - fsgnjn - negate sign value of FSrcYE
|
||||
//10 - fsgnjx - XOR sign values of FSrcXE & FSrcYE
|
||||
//
|
||||
// OpCtrl:
|
||||
// 00 - fsgnj - directly copy over sign value of Y
|
||||
// 01 - fsgnjn - negate sign value of Y
|
||||
// 10 - fsgnjx - XOR sign values of X and Y
|
||||
|
||||
// calculate the result's sign
|
||||
assign ResSgn = (SgnOpCodeE[1] ? XSgnE : SgnOpCodeE[0]) ^ YSgnE;
|
||||
assign ResSgn = (OpCtrl[1] ? Xs : OpCtrl[0]) ^ Ys;
|
||||
|
||||
// format final result based on precision
|
||||
// - uses NaN-blocking format
|
||||
// - if there are any unsused bits the most significant bits are filled with 1s
|
||||
|
||||
if (`FPSIZES == 1)
|
||||
assign SgnResE = {ResSgn, FSrcXE[`FLEN-2:0]};
|
||||
assign SgnRes = {ResSgn, X[`FLEN-2:0]};
|
||||
|
||||
else if (`FPSIZES == 2)
|
||||
assign SgnResE = {~FmtE|ResSgn, FSrcXE[`FLEN-2:`LEN1], FmtE ? FSrcXE[`LEN1-1] : ResSgn, FSrcXE[`LEN1-2:0]};
|
||||
assign SgnRes = {~Fmt|ResSgn, X[`FLEN-2:`LEN1], Fmt ? X[`LEN1-1] : ResSgn, X[`LEN1-2:0]};
|
||||
|
||||
else if (`FPSIZES == 3) begin
|
||||
logic [2:0] SgnBits;
|
||||
always_comb
|
||||
case (FmtE)
|
||||
`FMT: SgnBits = {ResSgn, FSrcXE[`LEN1-1], FSrcXE[`LEN2-1]};
|
||||
`FMT1: SgnBits = {1'b1, ResSgn, FSrcXE[`LEN2-1]};
|
||||
case (Fmt)
|
||||
`FMT: SgnBits = {ResSgn, X[`LEN1-1], X[`LEN2-1]};
|
||||
`FMT1: SgnBits = {1'b1, ResSgn, X[`LEN2-1]};
|
||||
`FMT2: SgnBits = {2'b11, ResSgn};
|
||||
default: SgnBits = {3{1'bx}};
|
||||
endcase
|
||||
assign SgnResE = {SgnBits[2], FSrcXE[`FLEN-2:`LEN1], SgnBits[1], FSrcXE[`LEN1-2:`LEN2], SgnBits[0], FSrcXE[`LEN2-2:0]};
|
||||
assign SgnRes = {SgnBits[2], X[`FLEN-2:`LEN1], SgnBits[1], X[`LEN1-2:`LEN2], SgnBits[0], X[`LEN2-2:0]};
|
||||
|
||||
|
||||
end else if (`FPSIZES == 4) begin
|
||||
logic [3:0] SgnBits;
|
||||
always_comb
|
||||
case (FmtE)
|
||||
`Q_FMT: SgnBits = {ResSgn, FSrcXE[`D_LEN-1], FSrcXE[`S_LEN-1], FSrcXE[`H_LEN-1]};
|
||||
`D_FMT: SgnBits = {1'b1, ResSgn, FSrcXE[`S_LEN-1], FSrcXE[`H_LEN-1]};
|
||||
`S_FMT: SgnBits = {2'b11, ResSgn, FSrcXE[`H_LEN-1]};
|
||||
case (Fmt)
|
||||
`Q_FMT: SgnBits = {ResSgn, X[`D_LEN-1], X[`S_LEN-1], X[`H_LEN-1]};
|
||||
`D_FMT: SgnBits = {1'b1, ResSgn, X[`S_LEN-1], X[`H_LEN-1]};
|
||||
`S_FMT: SgnBits = {2'b11, ResSgn, X[`H_LEN-1]};
|
||||
`H_FMT: SgnBits = {3'b111, ResSgn};
|
||||
endcase
|
||||
assign SgnResE = {SgnBits[3], FSrcXE[`Q_LEN-2:`D_LEN], SgnBits[2], FSrcXE[`D_LEN-2:`S_LEN], SgnBits[1], FSrcXE[`S_LEN-2:`H_LEN], SgnBits[0], FSrcXE[`H_LEN-2:0]};
|
||||
assign SgnRes = {SgnBits[3], X[`Q_LEN-2:`D_LEN], SgnBits[2], X[`D_LEN-2:`S_LEN], SgnBits[1], X[`S_LEN-2:`H_LEN], SgnBits[0], X[`H_LEN-2:0]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -42,7 +42,12 @@ module negateintres(
|
|||
// round and negate the positive res if needed
|
||||
assign CvtNegRes = Xs ? -({2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1}) : {2'b0, Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`XLEN]}+{{`XLEN+1{1'b0}}, Plus1};
|
||||
|
||||
assign CvtNegResMsbs = Signed ? Int64 ? CvtNegRes[`XLEN:`XLEN-1] : CvtNegRes[32:31] :
|
||||
Int64 ? CvtNegRes[`XLEN+1:`XLEN] : CvtNegRes[33:32];
|
||||
always_comb
|
||||
if(Signed)
|
||||
if(Int64) CvtNegResMsbs = CvtNegRes[`XLEN:`XLEN-1];
|
||||
else CvtNegResMsbs = CvtNegRes[32:31];
|
||||
else
|
||||
if(Int64) CvtNegResMsbs = CvtNegRes[`XLEN+1:`XLEN];
|
||||
else CvtNegResMsbs = CvtNegRes[33:32];
|
||||
|
||||
endmodule
|
|
@ -58,6 +58,41 @@ module otfc2 (
|
|||
|
||||
endmodule
|
||||
|
||||
///////////////////////////////
|
||||
// Square Root OTFC, Radix 2 //
|
||||
///////////////////////////////
|
||||
module sotfc2(
|
||||
input logic clk,
|
||||
input logic Start,
|
||||
input logic sp, sn,
|
||||
input logic Sqrt,
|
||||
input logic [`DIVLEN+3:0] C,
|
||||
output logic [`DIVLEN-2:0] Sq,
|
||||
output logic [`DIVLEN+3:0] S, SM
|
||||
);
|
||||
// The on-the-fly converter transfers the square root
|
||||
// bits to the quotient as they come.
|
||||
// Use this otfc for division and square root.
|
||||
logic [`DIVLEN+3:0] SNext, SMNext, SMux;
|
||||
|
||||
flopr #(`DIVLEN+4) SMreg(clk, Start, SMNext, SM);
|
||||
mux2 #(`DIVLEN+4) Smux(SNext, {3'b000, Sqrt, {(`DIVLEN){1'b0}}}, Start, SMux);
|
||||
flop #(`DIVLEN+4) Sreg(clk, SMux, S);
|
||||
|
||||
always_comb begin
|
||||
if (sp) begin
|
||||
SNext = S | (C & ~(C << 1));
|
||||
SMNext = S;
|
||||
end else if (sn) begin
|
||||
SNext = SM | (C & ~(C << 1));
|
||||
SMNext = SM;
|
||||
end else begin // If sp and sn are not true, then sz is
|
||||
SNext = S;
|
||||
SMNext = SM | (C & ~(C << 1));
|
||||
end
|
||||
end
|
||||
assign Sq = S[`DIVLEN] ? S[`DIVLEN-1:1] : S[`DIVLEN-2:0];
|
||||
endmodule
|
||||
|
||||
module otfc4 (
|
||||
input logic [3:0] q,
|
||||
|
@ -107,6 +142,41 @@ module otfc4 (
|
|||
QMNext = {QMR, 2'b11};
|
||||
end
|
||||
end
|
||||
// Final Quoteint is in the range [.5, 2)
|
||||
// Final Qmeint is in the range [.5, 2)
|
||||
|
||||
endmodule
|
||||
|
||||
///////////////////////////////
|
||||
// Square Root OTFC, Radix 4 //
|
||||
///////////////////////////////
|
||||
module sotfc4(
|
||||
input logic [3:0] s,
|
||||
input logic Sqrt,
|
||||
input logic [`DIVLEN+3:0] S, SM,
|
||||
input logic [`DIVLEN+3:0] C,
|
||||
output logic [`DIVLEN+3:0] SNext, SMNext
|
||||
);
|
||||
// The on-the-fly converter transfers the square root
|
||||
// bits to the quotient as they come.
|
||||
// Use this otfc for division and square root.
|
||||
|
||||
always_comb begin
|
||||
if (s[3]) begin
|
||||
SNext = S | ((C << 1)&~(C << 2));
|
||||
SMNext = S | (C&~(C << 1));
|
||||
end else if (s[2]) begin
|
||||
SNext = S | (C&~(C << 1));
|
||||
SMNext = S;
|
||||
end else if (s[1]) begin
|
||||
SNext = SM | (C&~(C << 2));
|
||||
SMNext = SM | ((C << 1)&~(C << 2));
|
||||
end else if (s[0]) begin
|
||||
SNext = SM | ((C << 1)&~(C << 2));
|
||||
SMNext = SM | (C&~(C << 1));
|
||||
end else begin // If sp and sn are not true, then sz is
|
||||
SNext = S;
|
||||
SMNext = SM | (C & ~(C << 2));
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -36,7 +36,7 @@ module postprocess (
|
|||
input logic [`NF:0] Xm, Ym, Zm, // input mantissas
|
||||
input logic [2:0] Frm, // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude
|
||||
input logic [`FMTBITS-1:0] Fmt, // precision 1 = double 0 = single
|
||||
input logic [2:0] FOpCtrl, // choose which opperation (look below for values)
|
||||
input logic [2:0] OpCtrl, // choose which opperation (look below for values)
|
||||
input logic XZero, YZero, ZZero, // inputs are zero
|
||||
input logic XInf, YInf, ZInf, // inputs are infinity
|
||||
input logic XNaN, YNaN, ZNaN, // inputs are NaN
|
||||
|
@ -46,13 +46,15 @@ module postprocess (
|
|||
//fma signals
|
||||
input logic FmaAs, // the modified Z sign - depends on instruction
|
||||
input logic FmaPs, // the product's sign
|
||||
input logic [`NE+1:0] FmaSe,
|
||||
input logic [`NE+1:0] FmaPe, // Product exponent
|
||||
input logic [3*`NF+5:0] FmaSm, // the positive sum
|
||||
input logic FmaZmS, // sticky bit that is calculated during alignment
|
||||
input logic FmaKillProd, // set the product to zero before addition if the product is too small to matter
|
||||
input logic FmaNegSum, // was the sum negitive
|
||||
input logic FmaInvA, // do you invert Z
|
||||
input logic [$clog2(3*`NF+7)-1:0] FmaNCnt, // the normalization shift count
|
||||
input logic FmaSs,
|
||||
input logic [$clog2(3*`NF+7)-1:0] FmaSCnt, // the normalization shift count
|
||||
//divide signals
|
||||
input logic [`DURLEN-1:0] DivEarlyTermShift,
|
||||
input logic DivS,
|
||||
|
@ -92,10 +94,10 @@ module postprocess (
|
|||
logic UfL;
|
||||
logic [`FMTBITS-1:0] OutFmt;
|
||||
// fma signals
|
||||
logic [`NE+1:0] FmaSe; // exponent of the normalized sum
|
||||
logic [`NE+1:0] FmaMe; // exponent of the normalized sum
|
||||
logic FmaSZero; // is the sum zero
|
||||
logic [3*`NF+8:0] FmaShiftIn; // shift input
|
||||
logic [`NE+1:0] FmaNe; // exponent of the normalized sum not taking into account denormal or zero results
|
||||
logic [`NE+1:0] NormSumExp; // exponent of the normalized sum not taking into account denormal or zero results
|
||||
logic FmaPreResultDenorm; // is the result denormalized - calculated before LZA corection
|
||||
logic [$clog2(3*`NF+7)-1:0] FmaShiftAmt; // normalization shift count
|
||||
// division singals
|
||||
|
@ -123,26 +125,26 @@ module postprocess (
|
|||
logic Sqrt;
|
||||
|
||||
// signals to help readability
|
||||
assign Signed = FOpCtrl[0];
|
||||
assign Int64 = FOpCtrl[1];
|
||||
assign IntToFp = FOpCtrl[2];
|
||||
assign Mult = FOpCtrl[2]&~FOpCtrl[1]&~FOpCtrl[0];
|
||||
assign Signed = OpCtrl[0];
|
||||
assign Int64 = OpCtrl[1];
|
||||
assign IntToFp = OpCtrl[2];
|
||||
assign Mult = OpCtrl[2]&~OpCtrl[1]&~OpCtrl[0];
|
||||
assign CvtOp = (PostProcSel == 2'b00);
|
||||
assign FmaOp = (PostProcSel == 2'b10);
|
||||
assign DivOp = (PostProcSel == 2'b01)&DivDone;
|
||||
assign Sqrt = FOpCtrl[0];
|
||||
assign Sqrt = OpCtrl[0];
|
||||
|
||||
// is there an input of infinity or NaN being used
|
||||
assign InfIn = (XInf&~(IntToFp&CvtOp))|(YInf&~CvtOp)|(ZInf&FmaOp);
|
||||
assign NaNIn = (XNaN&~(IntToFp&CvtOp))|(YNaN&~CvtOp)|(ZNaN&FmaOp);
|
||||
assign InfIn = XInf|YInf|ZInf;
|
||||
assign NaNIn = XNaN|YNaN|ZNaN;
|
||||
|
||||
// choose the ouptut format depending on the opperation
|
||||
// - fp -> fp: OpCtrl contains the percision of the output
|
||||
// - otherwise: Fmt contains the percision of the output
|
||||
if (`FPSIZES == 2)
|
||||
assign OutFmt = IntToFp|~CvtOp ? Fmt : (FOpCtrl[1:0] == `FMT);
|
||||
assign OutFmt = IntToFp|~CvtOp ? Fmt : (OpCtrl[1:0] == `FMT);
|
||||
else if (`FPSIZES == 3 | `FPSIZES == 4)
|
||||
assign OutFmt = IntToFp|~CvtOp ? Fmt : FOpCtrl[1:0];
|
||||
assign OutFmt = IntToFp|~CvtOp ? Fmt : OpCtrl[1:0];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Normalization
|
||||
|
@ -150,7 +152,7 @@ module postprocess (
|
|||
|
||||
cvtshiftcalc cvtshiftcalc(.ToInt, .CvtCe, .CvtResDenormUf, .Xm, .CvtLzcIn,
|
||||
.XZero, .IntToFp, .OutFmt, .CvtResUf, .CvtShiftIn);
|
||||
fmashiftcalc fmashiftcalc(.FmaSm, .Ze, .FmaPe, .FmaNCnt, .Fmt, .FmaKillProd, .FmaNe,
|
||||
fmashiftcalc fmashiftcalc(.FmaSm, .Ze, .FmaPe, .FmaSCnt, .Fmt, .FmaKillProd, .NormSumExp, .FmaSe,
|
||||
.FmaSZero, .FmaPreResultDenorm, .FmaShiftAmt, .FmaShiftIn);
|
||||
divshiftcalc divshiftcalc(.Fmt, .DivQe, .DivQm, .DivEarlyTermShift, .DivResDenorm, .DivDenormShift, .DivShiftAmt, .DivShiftIn);
|
||||
|
||||
|
@ -181,9 +183,9 @@ module postprocess (
|
|||
|
||||
normshift normshift (.ShiftIn, .ShiftAmt, .Shifted);
|
||||
|
||||
shiftcorrection shiftcorrection(.FmaOp, .FmaPreResultDenorm, .FmaNe,
|
||||
shiftcorrection shiftcorrection(.FmaOp, .FmaPreResultDenorm, .NormSumExp,
|
||||
.DivResDenorm, .DivDenormShift, .DivOp, .DivQe,
|
||||
.Qe, .FmaSZero, .Shifted, .FmaSe, .Mf);
|
||||
.Qe, .FmaSZero, .Shifted, .FmaMe, .Mf);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Rounding
|
||||
|
@ -197,10 +199,10 @@ module postprocess (
|
|||
|
||||
|
||||
roundsign roundsign(.FmaPs, .FmaAs, .FmaInvA, .FmaOp, .DivOp, .CvtOp, .FmaNegSum,
|
||||
.Xs, .Ys, .CvtCs, .Ms);
|
||||
.FmaSs, .Xs, .Ys, .CvtCs, .Ms);
|
||||
|
||||
round round(.OutFmt, .Frm, .S, .FmaZmS, .Plus1, .PostProcSel, .CvtCe, .Qe,
|
||||
.Ms, .FmaSe, .FmaOp, .CvtOp, .CvtResDenormUf, .Mf, .ToInt, .CvtResUf,
|
||||
.Ms, .FmaMe, .FmaOp, .CvtOp, .CvtResDenormUf, .Mf, .ToInt, .CvtResUf,
|
||||
.DivS, .DivDone,
|
||||
.DivOp, .UfPlus1, .FullRe, .Rf, .Re, .R, .UfL, .Me);
|
||||
|
||||
|
@ -208,7 +210,7 @@ module postprocess (
|
|||
// Sign calculation
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
resultsign resultsign(.Frm, .FmaPs, .FmaAs, .FmaSe, .R, .S,
|
||||
resultsign resultsign(.Frm, .FmaPs, .FmaAs, .FmaMe, .R, .S,
|
||||
.FmaOp, .ZInf, .InfIn, .FmaSZero, .Mult, .Ms, .Ws);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -217,7 +219,7 @@ module postprocess (
|
|||
|
||||
flags flags(.XSNaN, .YSNaN, .ZSNaN, .XInf, .YInf, .ZInf, .InfIn, .XZero, .YZero,
|
||||
.Xs, .Sqrt, .ToInt, .IntToFp, .Int64, .Signed, .OutFmt, .CvtCe,
|
||||
.XNaN, .YNaN, .NaNIn, .FmaAs, .FmaPs, .R, .IntInvalid, .DivByZero,
|
||||
.NaNIn, .FmaAs, .FmaPs, .R, .IntInvalid, .DivByZero,
|
||||
.UfL, .S, .UfPlus1, .CvtOp, .DivOp, .FmaOp, .FullRe, .Plus1,
|
||||
.Me, .CvtNegResMsbs, .Invalid, .Overflow, .PostProcFlg);
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ module qsel2 ( // *** eventually just change to 4 bits
|
|||
// for efficiency. You can probably optimize your logic to
|
||||
// select the proper divisor with less delay.
|
||||
|
||||
// Quotient equations from EE371 lecture notes 13-20
|
||||
// Qmient equations from EE371 lecture notes 13-20
|
||||
assign p = ps ^ pc;
|
||||
assign g = ps & pc;
|
||||
|
||||
|
@ -62,9 +62,36 @@ module qsel2 ( // *** eventually just change to 4 bits
|
|||
// assign #1 qn = magnitude & sign;
|
||||
endmodule
|
||||
|
||||
////////////////////////////////////
|
||||
// Adder Input Generation, Radix 2 //
|
||||
////////////////////////////////////
|
||||
module fgen2 (
|
||||
input logic sp, sn,
|
||||
input logic [`DIVLEN+3:0] C, S, SM,
|
||||
output logic [`DIVLEN+3:0] F
|
||||
);
|
||||
logic [`DIVLEN+3:0] FP, FN, FZ;
|
||||
|
||||
// Generate for both positive and negative bits
|
||||
assign FP = ~(S << 1) & C;
|
||||
assign FN = (SM << 1) | (C & (~C << 2));
|
||||
assign FZ = '0;
|
||||
|
||||
// Choose which adder input will be used
|
||||
|
||||
always_comb
|
||||
if (sp) F = FP;
|
||||
else if (sn) F = FN;
|
||||
else F = FZ;
|
||||
|
||||
// assign F = sp ? FP : (sn ? FN : FZ);
|
||||
|
||||
endmodule
|
||||
|
||||
module qsel4 (
|
||||
input logic [`DIVLEN+3:0] D,
|
||||
input logic [`DIVLEN+3:0] WS, WC,
|
||||
input logic Sqrt,
|
||||
output logic [3:0] q
|
||||
);
|
||||
logic [6:0] Wmsbs;
|
||||
|
@ -91,45 +118,77 @@ module qsel4 (
|
|||
else if(w2>=4) QSel4[i] = 4'b0100;
|
||||
else if(w2>=-4) QSel4[i] = 4'b0000;
|
||||
else if(w2>=-13) QSel4[i] = 4'b0010;
|
||||
else QSel4[i] = 4'b0001;
|
||||
else QSel4[i] = 4'b0001;
|
||||
1: if(w2>=14) QSel4[i] = 4'b1000;
|
||||
else if(w2>=4) QSel4[i] = 4'b0100;
|
||||
else if(w2>=-6) QSel4[i] = 4'b0000;
|
||||
else if(w2>=-15) QSel4[i] = 4'b0010;
|
||||
else QSel4[i] = 4'b0001;
|
||||
else if(w2>=-5) QSel4[i] = 4'b0000; // was -6
|
||||
else if(~Sqrt&(w2>=-15)) QSel4[i] = 4'b0010; // divide case
|
||||
else if( Sqrt&(w2>=-14)) QSel4[i] = 4'b0010; // sqrt case
|
||||
else QSel4[i] = 4'b0001;
|
||||
2: if(w2>=15) QSel4[i] = 4'b1000;
|
||||
else if(w2>=4) QSel4[i] = 4'b0100;
|
||||
else if(w2>=-6) QSel4[i] = 4'b0000;
|
||||
else if(w2>=-16) QSel4[i] = 4'b0010;
|
||||
else QSel4[i] = 4'b0001;
|
||||
else QSel4[i] = 4'b0001;
|
||||
3: if(w2>=16) QSel4[i] = 4'b1000;
|
||||
else if(w2>=4) QSel4[i] = 4'b0100;
|
||||
else if(w2>=-6) QSel4[i] = 4'b0000;
|
||||
else if(w2>=-18) QSel4[i] = 4'b0010;
|
||||
else QSel4[i] = 4'b0001;
|
||||
else if(w2>=-17) QSel4[i] = 4'b0010; // was -18
|
||||
else QSel4[i] = 4'b0001;
|
||||
4: if(w2>=18) QSel4[i] = 4'b1000;
|
||||
else if(w2>=6) QSel4[i] = 4'b0100;
|
||||
else if(w2>=-8) QSel4[i] = 4'b0000;
|
||||
else if(w2>=-20) QSel4[i] = 4'b0010;
|
||||
else QSel4[i] = 4'b0001;
|
||||
else if(w2>=-6) QSel4[i] = 4'b0000; // was -8
|
||||
else if(~Sqrt&(w2>=-20)) QSel4[i] = 4'b0010; // divide case
|
||||
else if( Sqrt&(w2>=-18)) QSel4[i] = 4'b0010; // sqrt case
|
||||
else QSel4[i] = 4'b0001;
|
||||
5: if(w2>=20) QSel4[i] = 4'b1000;
|
||||
else if(w2>=6) QSel4[i] = 4'b0100;
|
||||
else if(w2>=-8) QSel4[i] = 4'b0000;
|
||||
else if(w2>=-20) QSel4[i] = 4'b0010;
|
||||
else QSel4[i] = 4'b0001;
|
||||
else QSel4[i] = 4'b0001;
|
||||
6: if(w2>=20) QSel4[i] = 4'b1000;
|
||||
else if(w2>=8) QSel4[i] = 4'b0100;
|
||||
else if(w2>=-8) QSel4[i] = 4'b0000;
|
||||
else if(w2>=-22) QSel4[i] = 4'b0010;
|
||||
else QSel4[i] = 4'b0001;
|
||||
7: if(w2>=24) QSel4[i] = 4'b1000;
|
||||
else QSel4[i] = 4'b0001;
|
||||
7: if(w2>=22) QSel4[i] = 4'b1000; // was 24
|
||||
else if(w2>=8) QSel4[i] = 4'b0100;
|
||||
else if(w2>=-8) QSel4[i] = 4'b0000;
|
||||
else if(w2>=-24) QSel4[i] = 4'b0010;
|
||||
else QSel4[i] = 4'b0001;
|
||||
else if(w2>=-23) QSel4[i] = 4'b0010; // was -24
|
||||
else QSel4[i] = 4'b0001;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
assign q = QSel4[{Dmsbs,Wmsbs}];
|
||||
|
||||
endmodule
|
||||
|
||||
////////////////////////////////////
|
||||
// Adder Input Generation, Radix 4 //
|
||||
////////////////////////////////////
|
||||
module fgen4 (
|
||||
input logic [3:0] s,
|
||||
input logic [`DIVLEN+3:0] C, S, SM,
|
||||
output logic [`DIVLEN+3:0] F
|
||||
);
|
||||
logic [`DIVLEN+3:0] F2, F1, F0, FN1, FN2;
|
||||
|
||||
// Generate for both positive and negative bits
|
||||
assign F2 = (~S << 2) & (C << 2);
|
||||
assign F1 = ~(S << 1) & C;
|
||||
assign F0 = '0;
|
||||
assign FN1 = (SM << 1) | (C & ~(C << 2));
|
||||
assign FN2 = (SM << 2) | ((C << 2)&~(C <<4));
|
||||
|
||||
// Choose which adder input will be used
|
||||
|
||||
always_comb
|
||||
if (s[3]) F = F2;
|
||||
else if (s[2]) F = F1;
|
||||
else if (s[1]) F = FN1;
|
||||
else if (s[0]) F = FN2;
|
||||
else F = F0;
|
||||
|
||||
// assign F = sp ? FP : (sn ? FN : FZ);
|
||||
|
||||
endmodule
|
|
@ -34,7 +34,7 @@ module resultsign(
|
|||
input logic ZInf,
|
||||
input logic InfIn,
|
||||
input logic FmaOp,
|
||||
input logic [`NE+1:0] FmaSe,
|
||||
input logic [`NE+1:0] FmaMe,
|
||||
input logic FmaSZero,
|
||||
input logic Mult,
|
||||
input logic R,
|
||||
|
@ -46,11 +46,21 @@ module resultsign(
|
|||
logic Zeros;
|
||||
logic Infs;
|
||||
|
||||
// Determine the sign if the sum is zero
|
||||
// if cancelation then 0 unless round to -infinity
|
||||
// if multiply then Psgn
|
||||
// otherwise psign
|
||||
assign Zeros = (FmaPs^FmaAs)&~(FmaSe[`NE+1] | ((FmaSe == 0) & (R|S)))&~Mult ? Frm[1:0] == 2'b10 : FmaPs;
|
||||
// The IEEE754-2019 standard specifies:
|
||||
// - the sign of an exact zero sum (with operands of diffrent signs) should be positive unless rounding toward negitive infinity
|
||||
// - when the exact result of an FMA opperation is non-zero, but is zero due to rounding, use the sign of the exact result
|
||||
// - if x = +0 or -0 then x+x=x and x-(-x)=x
|
||||
// - the sign of a product is the exclisive or or the opperand's signs
|
||||
// Zero sign will only be selected if:
|
||||
// - P=Z and a cancelation occurs - exact zero
|
||||
// - Z is zero and P is zero - exact zero
|
||||
// - P is killed and Z is zero - Psgn
|
||||
// - Z is killed and P is zero - impossible
|
||||
// Zero sign calculation:
|
||||
// - if a multiply opperation is done, then use the products sign(Ps)
|
||||
// - if the zero sum is not exactly zero i.e. R|S use the sign of the exact result (which is the product's sign)
|
||||
// - if an effective addition occurs (P+A or -P+-A or P--A) then use the product's sign
|
||||
assign Zeros = (FmaPs^FmaAs)&~(R|S)&~Mult ? Frm[1:0] == 2'b10 : FmaPs;
|
||||
|
||||
|
||||
// is the result negitive
|
||||
|
@ -58,6 +68,9 @@ module resultsign(
|
|||
// if -p + z is the Sum positive
|
||||
// if -p - z then the Sum is negitive
|
||||
assign Infs = ZInf ? FmaAs : FmaPs;
|
||||
assign Ws = InfIn&FmaOp ? Infs : FmaSZero&FmaOp ? Zeros : Ms;
|
||||
always_comb
|
||||
if(InfIn&FmaOp) Ws = Infs;
|
||||
else if(FmaSZero&FmaOp) Ws = Zeros;
|
||||
else Ws = Ms;
|
||||
|
||||
endmodule
|
|
@ -48,7 +48,7 @@ module round(
|
|||
input logic CvtResUf,
|
||||
input logic [`CORRSHIFTSZ-1:0] Mf,
|
||||
input logic FmaZmS, // addend's sticky bit
|
||||
input logic [`NE+1:0] FmaSe, // exponent of the normalized sum
|
||||
input logic [`NE+1:0] FmaMe, // exponent of the normalized sum
|
||||
input logic Ms, // the result's sign
|
||||
input logic [`NE:0] CvtCe, // the calculated expoent
|
||||
input logic [`NE+1:0] Qe, // the calculated expoent
|
||||
|
@ -176,7 +176,7 @@ module round(
|
|||
|
||||
// only add the Addend sticky if doing an FMA opperation
|
||||
// - the shifter shifts too far left when there's an underflow (shifting out all possible sticky bits)
|
||||
assign UfS = FmaZmS&FmaOp | NormS | CvtResUf&CvtOp | FmaSe[`NE+1]&FmaOp | DivS&DivOp;
|
||||
assign UfS = FmaZmS&FmaOp | NormS | CvtResUf&CvtOp | FmaMe[`NE+1]&FmaOp | DivS&DivOp;
|
||||
|
||||
// determine round and LSB of the rounded value
|
||||
// - underflow round bit is used to determint the underflow flag
|
||||
|
@ -299,7 +299,7 @@ module round(
|
|||
|
||||
always_comb
|
||||
case(PostProcSel)
|
||||
2'b10: Me = FmaSe; // fma
|
||||
2'b10: Me = FmaMe; // fma
|
||||
2'b00: Me = {CvtCe[`NE], CvtCe}&{`NE+2{~CvtResDenormUf|CvtResUf}}; // cvt
|
||||
2'b01: Me = DivDone ? Qe : '0; // divide
|
||||
default: Me = '0;
|
||||
|
|
|
@ -38,23 +38,15 @@ module roundsign(
|
|||
input logic DivOp,
|
||||
input logic CvtOp,
|
||||
input logic CvtCs,
|
||||
input logic FmaSs,
|
||||
output logic Ms
|
||||
);
|
||||
|
||||
logic FmaResSgnTmp;
|
||||
logic Qs;
|
||||
|
||||
// is the result negitive
|
||||
// if p - z is the Sum negitive
|
||||
// if -p + z is the Sum positive
|
||||
// if -p - z then the Sum is negitive
|
||||
assign FmaResSgnTmp = FmaNegSum^FmaPs; //*** move to execute stage
|
||||
|
||||
// assign FmaResSgnTmp = FmaInvA&(FmaAs)&FmaNegSum | FmaInvA&FmaPs&~FmaNegSum | (FmaAs&FmaPs);
|
||||
|
||||
assign Qs = Xs^Ys;
|
||||
|
||||
// Sign for rounding calulation
|
||||
assign Ms = (FmaResSgnTmp&FmaOp) | (CvtCs&CvtOp) | (Qs&DivOp);
|
||||
assign Ms = (FmaSs&FmaOp) | (CvtCs&CvtOp) | (Qs&DivOp);
|
||||
|
||||
endmodule
|
|
@ -35,15 +35,15 @@ module shiftcorrection(
|
|||
input logic DivResDenorm,
|
||||
input logic [`NE+1:0] DivQe,
|
||||
input logic [`NE+1:0] DivDenormShift,
|
||||
input logic [`NE+1:0] FmaNe, // exponent of the normalized sum not taking into account denormal or zero results
|
||||
input logic [`NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account denormal or zero results
|
||||
input logic FmaPreResultDenorm, // is the result denormalized - calculated before LZA corection
|
||||
input logic FmaSZero,
|
||||
output logic [`CORRSHIFTSZ-1:0] Mf, // the shifted sum before LZA correction
|
||||
output logic [`NE+1:0] Qe,
|
||||
output logic [`NE+1:0] FmaSe // exponent of the normalized sum
|
||||
output logic [`NE+1:0] FmaMe // exponent of the normalized sum
|
||||
);
|
||||
logic [3*`NF+5:0] CorrSumShifted; // the shifted sum after LZA correction
|
||||
logic [`CORRSHIFTSZ-1:0] CorrQuotShifted;
|
||||
logic [`CORRSHIFTSZ-1:0] CorrQmShifted;
|
||||
logic ResDenorm; // is the result denormalized
|
||||
logic LZAPlus1, LZAPlus2; // add one or two to the sum's exponent due to LZA correction
|
||||
|
||||
|
@ -53,12 +53,15 @@ module shiftcorrection(
|
|||
// the only possible mantissa for a plus two is all zeroes - a one has to propigate all the way through a sum. so we can leave the bottom statement alone
|
||||
assign CorrSumShifted = LZAPlus1 ? Shifted[`NORMSHIFTSZ-3:1] : Shifted[`NORMSHIFTSZ-4:0];
|
||||
// if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Denorm)
|
||||
assign CorrQuotShifted = (LZAPlus2|(DivQe==1&~LZAPlus2)) ? Shifted[`NORMSHIFTSZ-2:`NORMSHIFTSZ-`CORRSHIFTSZ-1] : Shifted[`NORMSHIFTSZ-3:`NORMSHIFTSZ-`CORRSHIFTSZ-2];
|
||||
assign CorrQmShifted = (LZAPlus2|(DivQe==1&~LZAPlus2)) ? Shifted[`NORMSHIFTSZ-2:`NORMSHIFTSZ-`CORRSHIFTSZ-1] : Shifted[`NORMSHIFTSZ-3:`NORMSHIFTSZ-`CORRSHIFTSZ-2];
|
||||
// if the result of the divider was calculated to be denormalized, then the result was correctly normalized, so select the top shifted bits
|
||||
assign Mf = FmaOp ? {CorrSumShifted, {`CORRSHIFTSZ-(3*`NF+6){1'b0}}} : DivOp&~DivResDenorm ? CorrQuotShifted : Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ];
|
||||
always_comb
|
||||
if(FmaOp) Mf = {CorrSumShifted, {`CORRSHIFTSZ-(3*`NF+6){1'b0}}};
|
||||
else if (DivOp&~DivResDenorm) Mf = CorrQmShifted;
|
||||
else Mf = Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ];
|
||||
// Determine sum's exponent
|
||||
// if plus1 If plus2 if said denorm but norm plus 1 if said denorm but norm plus 2
|
||||
assign FmaSe = (FmaNe+{{`NE+1{1'b0}}, LZAPlus1}+{{`NE{1'b0}}, LZAPlus2, 1'b0}+{{`NE+1{1'b0}}, ~ResDenorm&FmaPreResultDenorm}+{{`NE+1{1'b0}}, &FmaNe&Shifted[3*`NF+6]}) & {`NE+2{~(FmaSZero|ResDenorm)}};
|
||||
assign FmaMe = (NormSumExp+{{`NE+1{1'b0}}, LZAPlus1}+{{`NE{1'b0}}, LZAPlus2, 1'b0}+{{`NE+1{1'b0}}, ~ResDenorm&FmaPreResultDenorm}+{{`NE+1{1'b0}}, &NormSumExp&Shifted[3*`NF+6]}) & {`NE+2{~(FmaSZero|ResDenorm)}};
|
||||
// recalculate if the result is denormalized
|
||||
assign ResDenorm = FmaPreResultDenorm&~Shifted[`NORMSHIFTSZ-3]&~Shifted[`NORMSHIFTSZ-2];
|
||||
|
||||
|
|
|
@ -95,9 +95,14 @@ module specialcase(
|
|||
end else begin
|
||||
assign InvalidRes = OutFmt ? {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, (`NF1-1)'(0)};
|
||||
end
|
||||
|
||||
assign OfRes = OutFmt ? OfResMax ? {Ws, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : {Ws, {`NE{1'b1}}, {`NF{1'b0}}} :
|
||||
OfResMax ? {{`FLEN-`LEN1{1'b1}}, Ws, {`NE1-1{1'b1}}, 1'b0, {`NF1{1'b1}}} : {{`FLEN-`LEN1{1'b1}}, Ws, {`NE1{1'b1}}, (`NF1)'(0)};
|
||||
|
||||
always_comb
|
||||
if(OutFmt)
|
||||
if(OfResMax) OfRes = {Ws, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}};
|
||||
else OfRes = {Ws, {`NE{1'b1}}, {`NF{1'b0}}};
|
||||
else
|
||||
if(OfResMax) OfRes = {{`FLEN-`LEN1{1'b1}}, Ws, {`NE1-1{1'b1}}, 1'b0, {`NF1{1'b1}}};
|
||||
else OfRes = {{`FLEN-`LEN1{1'b1}}, Ws, {`NE1{1'b1}}, (`NF1)'(0)};
|
||||
assign UfRes = OutFmt ? {Ws, (`FLEN-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)} : {{`FLEN-`LEN1{1'b1}}, Ws, (`LEN1-2)'(0), Plus1&Frm[1]&~(DivOp&YInf)};
|
||||
assign NormRes = OutFmt ? {Ws, Re, Rf} : {{`FLEN-`LEN1{1'b1}}, Ws, Re[`NE1-1:0], Rf[`NF-1:`NF-`NF1]};
|
||||
|
||||
|
@ -234,20 +239,21 @@ module specialcase(
|
|||
assign KillRes = CvtOp ? (CvtResUf|(XZero&~IntToFp)|(IntZero&IntToFp)) : FullRe[`NE+1] | (((YInf&~XInf)|XZero)&DivOp);//Underflow & ~ResDenorm & (Re!=1);
|
||||
assign SelOfRes = Overflow|DivByZero|(InfIn&~(YInf&DivOp));
|
||||
// output infinity with result sign if divide by zero
|
||||
if(`IEEE754) begin
|
||||
assign PostProcRes = XNaN&~(IntToFp&CvtOp) ? XNaNRes :
|
||||
YNaN&~CvtOp ? YNaNRes :
|
||||
ZNaN&FmaOp ? ZNaNRes :
|
||||
Invalid ? InvalidRes :
|
||||
SelOfRes ? OfRes :
|
||||
KillRes ? UfRes :
|
||||
NormRes;
|
||||
end else begin
|
||||
assign PostProcRes = NaNIn|Invalid ? InvalidRes :
|
||||
SelOfRes ? OfRes :
|
||||
KillRes ? UfRes :
|
||||
NormRes;
|
||||
end
|
||||
if(`IEEE754)
|
||||
always_comb
|
||||
if(XNaN&~(IntToFp&CvtOp)) PostProcRes = XNaNRes;
|
||||
else if(YNaN&~CvtOp) PostProcRes = YNaNRes;
|
||||
else if(ZNaN&FmaOp) PostProcRes = ZNaNRes;
|
||||
else if(Invalid) PostProcRes = InvalidRes;
|
||||
else if(SelOfRes) PostProcRes = OfRes;
|
||||
else if(KillRes) PostProcRes = UfRes;
|
||||
else PostProcRes = NormRes;
|
||||
else
|
||||
always_comb
|
||||
if(NaNIn|Invalid) PostProcRes = InvalidRes;
|
||||
else if(SelOfRes) PostProcRes = OfRes;
|
||||
else if(KillRes) PostProcRes = UfRes;
|
||||
else PostProcRes = NormRes;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -272,10 +278,17 @@ module specialcase(
|
|||
// unsigned | 2^32-1 | 2^64-1 |
|
||||
//
|
||||
// other: 32 bit unsinged res should be sign extended as if it were a signed number
|
||||
assign OfIntRes = Signed ? Xs&~XNaN ? Int64 ? {1'b1, {`XLEN-1{1'b0}}} : {{`XLEN-32{1'b1}}, 1'b1, {31{1'b0}}} : // signed negitive
|
||||
Int64 ? {1'b0, {`XLEN-1{1'b1}}} : {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}} : // signed positive
|
||||
Xs&~XNaN ? {`XLEN{1'b0}} : // unsigned negitive
|
||||
{`XLEN{1'b1}};// unsigned positive
|
||||
always_comb
|
||||
if(Signed)
|
||||
if(Xs&~NaNIn) // signed negitive
|
||||
if(Int64) OfIntRes = {1'b1, {`XLEN-1{1'b0}}};
|
||||
else OfIntRes = {{`XLEN-32{1'b1}}, 1'b1, {31{1'b0}}};
|
||||
else // signed positive
|
||||
if(Int64) OfIntRes = {1'b0, {`XLEN-1{1'b1}}};
|
||||
else OfIntRes = {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}};
|
||||
else
|
||||
if(Xs&~NaNIn) OfIntRes = {`XLEN{1'b0}}; // unsigned negitive
|
||||
else OfIntRes = {`XLEN{1'b1}}; // unsigned positive
|
||||
|
||||
|
||||
// select the integer output
|
||||
|
@ -284,7 +297,11 @@ module specialcase(
|
|||
// - if rounding and signed opperation and negitive input, output -1
|
||||
// - otherwise output a rounded 0
|
||||
// - otherwise output the normal res (trmined and sign extended if nessisary)
|
||||
assign FCvtIntRes = IntInvalid ? OfIntRes :
|
||||
CvtCe[`NE] ? Xs&Signed&Plus1 ? {{`XLEN{1'b1}}} : {{`XLEN-1{1'b0}}, Plus1} : //CalcExp has to come after invalid ***swap to actual mux at some point??
|
||||
Int64 ? CvtNegRes[`XLEN-1:0] : {{`XLEN-32{CvtNegRes[31]}}, CvtNegRes[31:0]};
|
||||
always_comb
|
||||
if(IntInvalid) FCvtIntRes = OfIntRes;
|
||||
else if(CvtCe[`NE])
|
||||
if(Xs&Signed&Plus1) FCvtIntRes = {{`XLEN{1'b1}}};
|
||||
else FCvtIntRes = {{`XLEN-1{1'b0}}, Plus1};
|
||||
else if(Int64) FCvtIntRes = CvtNegRes[`XLEN-1:0];
|
||||
else FCvtIntRes = {{`XLEN-32{CvtNegRes[31]}}, CvtNegRes[31:0]};
|
||||
endmodule
|
|
@ -34,18 +34,17 @@ module srt(
|
|||
input logic clk,
|
||||
input logic DivStart,
|
||||
input logic DivBusy,
|
||||
input logic [`FMTBITS-1:0] FmtE,
|
||||
input logic [`NE-1:0] Xe, Ye,
|
||||
input logic XZeroE, YZeroE,
|
||||
input logic [`DIVLEN-1:0] X,
|
||||
input logic [`DIVLEN-1:0] Dpreproc,
|
||||
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
|
||||
input logic NegSticky,
|
||||
output logic [`QLEN-1-(`RADIX/4):0] Quot,
|
||||
input logic Sqrt,
|
||||
input logic [`DIVLEN+3:0] X,
|
||||
input logic [`DIVLEN+3:0] Dpreproc,
|
||||
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
|
||||
input logic NegSticky,
|
||||
output logic [`QLEN-1-(`RADIX/4):0] Qm,
|
||||
output logic [`DIVLEN+3:0] NextWSN, NextWCN,
|
||||
output logic [`DIVLEN+3:0] StickyWSA,
|
||||
output logic [`DIVLEN+3:0] FirstWS, FirstWC,
|
||||
output logic [`NE+1:0] DivCalcExpM,
|
||||
output logic [`XLEN-1:0] Rem
|
||||
);
|
||||
|
||||
|
@ -59,13 +58,19 @@ module srt(
|
|||
logic [`QLEN-1:0] QM[`DIVCOPIES-1:0];
|
||||
logic [`QLEN-1:0] QNext[`DIVCOPIES-1:0];
|
||||
logic [`QLEN-1:0] QMNext[`DIVCOPIES-1:0];
|
||||
logic [`DIVLEN+3:0] S[`DIVCOPIES-1:0]; //***change to QLEN???
|
||||
logic [`DIVLEN+3:0] SM[`DIVCOPIES-1:0];
|
||||
logic [`DIVLEN+3:0] SNext[`DIVCOPIES-1:0];
|
||||
logic [`DIVLEN+3:0] SMNext[`DIVCOPIES-1:0];
|
||||
logic [`DIVLEN+3:0] C[`DIVCOPIES-1:0];
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
logic [`DIVLEN+3:0] WSN, WCN;
|
||||
logic [`DIVLEN+3:0] D, DBar, D2, DBar2;
|
||||
logic [`NE+1:0] DivCalcExp;
|
||||
logic [$clog2(`XLEN+1)-1:0] intExp;
|
||||
logic intSign;
|
||||
logic [`QLEN-1:0] QMMux;
|
||||
logic [`DIVLEN+3:0] CMux;
|
||||
logic [`DIVLEN+3:0] SMux;
|
||||
|
||||
// Top Muxes and Registers
|
||||
// When start is asserted, the inputs are loaded into the divider.
|
||||
|
@ -83,13 +88,13 @@ module srt(
|
|||
assign NextWCN = {WCA[`DIVCOPIES-1][`DIVLEN+1:0], 2'b0};
|
||||
end
|
||||
|
||||
mux2 #(`DIVLEN+4) wsmux(NextWSN, {3'b000, ~XZeroE, X}, DivStart, WSN);
|
||||
mux2 #(`DIVLEN+4) wsmux(NextWSN, X, DivStart, WSN);
|
||||
flopen #(`DIVLEN+4) wsflop(clk, DivStart|DivBusy, WSN, WS[0]);
|
||||
mux2 #(`DIVLEN+4) wcmux(NextWCN, {`DIVLEN+4{1'b0}}, DivStart, WCN);
|
||||
flopen #(`DIVLEN+4) wcflop(clk, DivStart|DivBusy, WCN, WC[0]);
|
||||
flopen #(`DIVLEN+4) dflop(clk, DivStart, {4'b0001, Dpreproc}, D);
|
||||
flopen #(`NE+2) expflop(clk, DivStart, DivCalcExp, DivCalcExpM);
|
||||
|
||||
flopen #(`DIVLEN+4) dflop(clk, DivStart, Dpreproc, D);
|
||||
mux2 #(`DIVLEN+4) Cmux({2'b11, C[`DIVCOPIES-1][`DIVLEN+3:2]}, {5'b11111, Sqrt, {(`DIVLEN-2){1'b0}}}, DivStart, CMux);
|
||||
flop #(`DIVLEN+4) cflop(clk, CMux, C[0]);
|
||||
|
||||
// Divisor Selections
|
||||
// - choose the negitive version of what's being selected
|
||||
|
@ -102,8 +107,9 @@ module srt(
|
|||
genvar i;
|
||||
generate
|
||||
for(i=0; $unsigned(i)<`DIVCOPIES; i++) begin : interations
|
||||
divinteration divinteration(.D, .DBar, .D2, .DBar2,
|
||||
.WS(WS[i]), .WC(WC[i]), .WSA(WSA[i]), .WCA(WCA[i]), .Q(Q[i]), .QM(QM[i]), .QNext(QNext[i]), .QMNext(QMNext[i]));
|
||||
divinteration divinteration(.D, .DBar, .D2, .DBar2, .Sqrt,
|
||||
.WS(WS[i]), .WC(WC[i]), .WSA(WSA[i]), .WCA(WCA[i]), .Q(Q[i]), .QM(QM[i]), .QNext(QNext[i]), .QMNext(QMNext[i]),
|
||||
.C(C[i]), .S(S[i]), .SM(SM[i]), .SNext(SNext[i]), .SMNext(SMNext[i]));
|
||||
if(i<(`DIVCOPIES-1)) begin
|
||||
if (`RADIX==2)begin
|
||||
assign WS[i+1] = {WSA[i][`DIVLEN+1:0], 1'b0};
|
||||
|
@ -111,9 +117,12 @@ module srt(
|
|||
end else begin
|
||||
assign WS[i+1] = {WSA[i][`DIVLEN+1:0], 2'b0};
|
||||
assign WC[i+1] = {WCA[i][`DIVLEN+1:0], 2'b0};
|
||||
assign C[i+1] = {2'b11, C[i][`DIVLEN+3:2]};
|
||||
end
|
||||
assign Q[i+1] = QNext[i];
|
||||
assign QM[i+1] = QMNext[i];
|
||||
assign S[i+1] = SNext[i];
|
||||
assign SM[i+1] = SMNext[i];
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
@ -123,16 +132,27 @@ module srt(
|
|||
flopenr #(`QLEN) Qreg(clk, DivStart, DivBusy, QNext[`DIVCOPIES-1], Q[0]);
|
||||
flopen #(`QLEN) QMreg(clk, DivBusy, QMMux, QM[0]);
|
||||
|
||||
assign Quot = NegSticky ? QM[0][`QLEN-1-(`RADIX/4):0] : Q[0][`QLEN-1-(`RADIX/4):0];
|
||||
flopr #(`DIVLEN+4) SMreg(clk, DivStart, SMNext[`DIVCOPIES-1], SM[0]);
|
||||
mux2 #(`DIVLEN+4) Smux(SNext[`DIVCOPIES-1], {3'b000, Sqrt, {(`DIVLEN){1'b0}}}, DivStart, SMux);
|
||||
flop #(`DIVLEN+4) Sreg(clk, SMux, S[0]);
|
||||
|
||||
always_comb
|
||||
if(Sqrt)
|
||||
if(NegSticky) Qm = SM[0][`QLEN-1-(`RADIX/4):0];
|
||||
else Qm = S[0][`QLEN-1-(`RADIX/4):0];
|
||||
else
|
||||
if(NegSticky) Qm = QM[0][`QLEN-1-(`RADIX/4):0];
|
||||
else Qm = Q[0][`QLEN-1-(`RADIX/4):0];
|
||||
|
||||
assign FirstWS = WS[0];
|
||||
assign FirstWC = WC[0];
|
||||
|
||||
if(`RADIX==2)
|
||||
if (`DIVCOPIES == 1)
|
||||
assign StickyWSA = {WSA[0][`DIVLEN+2:0], 1'b0};
|
||||
else
|
||||
assign StickyWSA = {WSA[1][`DIVLEN+2:0], 1'b0};
|
||||
|
||||
expcalc expcalc(.FmtE, .Xe, .Ye, .XZeroE, .XZeroCnt, .YZeroCnt, .DivCalcExp);
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -145,8 +165,12 @@ module divinteration (
|
|||
input logic [`DIVLEN+3:0] D,
|
||||
input logic [`DIVLEN+3:0] DBar, D2, DBar2,
|
||||
input logic [`QLEN-1:0] Q, QM,
|
||||
input logic [`DIVLEN+3:0] S, SM,
|
||||
input logic [`DIVLEN+3:0] WS, WC,
|
||||
input logic [`DIVLEN+3:0] C,
|
||||
input logic Sqrt,
|
||||
output logic [`QLEN-1:0] QNext, QMNext,
|
||||
output logic [`DIVLEN+3:0] SNext, SMNext,
|
||||
output logic [`DIVLEN+3:0] WSA, WCA
|
||||
);
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
|
@ -154,8 +178,10 @@ module divinteration (
|
|||
logic [`DIVLEN+3:0] Dsel;
|
||||
logic [3:0] q;
|
||||
logic qp, qz;//, qn;
|
||||
logic [`DIVLEN+3:0] F;
|
||||
logic [`DIVLEN+3:0] AddIn;
|
||||
|
||||
// Quotient Selection logic
|
||||
// Qmient Selection logic
|
||||
// Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
|
||||
// q encoding:
|
||||
// 1000 = +2
|
||||
|
@ -166,7 +192,8 @@ module divinteration (
|
|||
if(`RADIX == 2) begin : qsel
|
||||
qsel2 qsel2(WS[`DIVLEN+3:`DIVLEN], WC[`DIVLEN+3:`DIVLEN], qp, qz);//, qn);
|
||||
end else begin
|
||||
qsel4 qsel4(.D, .WS, .WC, .q);
|
||||
qsel4 qsel4(.D, .WS, .WC, .Sqrt, .q);
|
||||
fgen4 fgen4(.s(q), .C, .S, .SM, .F);
|
||||
end
|
||||
|
||||
if(`RADIX == 2) begin : dsel
|
||||
|
@ -184,16 +211,18 @@ module divinteration (
|
|||
end
|
||||
// Partial Product Generation
|
||||
// WSA, WCA = WS + WC - qD
|
||||
assign AddIn = Sqrt ? F : Dsel;
|
||||
if (`RADIX == 2) begin : csa
|
||||
csa #(`DIVLEN+4) csa(WS, WC, Dsel, qp, WSA, WCA);
|
||||
csa #(`DIVLEN+4) csa(WS, WC, AddIn, qp, WSA, WCA);
|
||||
end else begin
|
||||
csa #(`DIVLEN+4) csa(WS, WC, Dsel, |q[3:2], WSA, WCA);
|
||||
csa #(`DIVLEN+4) csa(WS, WC, AddIn, |q[3:2], WSA, WCA);
|
||||
end
|
||||
|
||||
if (`RADIX == 2) begin : otfc
|
||||
otfc2 otfc2(.qp, .qz, .Q, .QM, .QNext, .QMNext);
|
||||
end else begin
|
||||
otfc4 otfc4(.q, .Q, .QM, .QNext, .QMNext);
|
||||
sotfc4 sotfc4(.s(q), .Sqrt, .C, .S, .SM, .SNext, .SMNext);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -220,40 +249,3 @@ module csa #(parameter N=69) (
|
|||
assign out2 = {in1[N-2:0] & (in2[N-2:0] | in3[N-2:0]) |
|
||||
(in2[N-2:0] & in3[N-2:0]), cin};
|
||||
endmodule
|
||||
|
||||
module expcalc(
|
||||
input logic [`FMTBITS-1:0] FmtE,
|
||||
input logic [`NE-1:0] Xe, Ye,
|
||||
input logic XZeroE,
|
||||
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
|
||||
output logic [`NE+1:0] DivCalcExp
|
||||
);
|
||||
logic [`NE-2:0] Bias;
|
||||
|
||||
if (`FPSIZES == 1) begin
|
||||
assign Bias = (`NE-1)'(`BIAS);
|
||||
|
||||
end else if (`FPSIZES == 2) begin
|
||||
assign Bias = FmtE ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1);
|
||||
|
||||
end else if (`FPSIZES == 3) begin
|
||||
always_comb
|
||||
case (FmtE)
|
||||
`FMT: Bias = (`NE-1)'(`BIAS);
|
||||
`FMT1: Bias = (`NE-1)'(`BIAS1);
|
||||
`FMT2: Bias = (`NE-1)'(`BIAS2);
|
||||
default: Bias = 'x;
|
||||
endcase
|
||||
|
||||
end else if (`FPSIZES == 4) begin
|
||||
always_comb
|
||||
case (FmtE)
|
||||
2'h3: Bias = (`NE-1)'(`Q_BIAS);
|
||||
2'h1: Bias = (`NE-1)'(`D_BIAS);
|
||||
2'h0: Bias = (`NE-1)'(`S_BIAS);
|
||||
2'h2: Bias = (`NE-1)'(`H_BIAS);
|
||||
endcase
|
||||
end
|
||||
// correct exponent for denormalized input's normalization shifts
|
||||
assign DivCalcExp = ({2'b0, Xe} - {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, XZeroCnt} - {2'b0, Ye} + {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, YZeroCnt} + {3'b0, Bias})&{`NE+2{~XZeroE}};
|
||||
endmodule
|
|
@ -43,7 +43,7 @@ module srtfsm(
|
|||
input logic [`DIVLEN+3:0] StickyWSA,
|
||||
input logic [`DURLEN-1:0] Dur,
|
||||
output logic [`DURLEN-1:0] EarlyTermShiftE,
|
||||
output logic DivStickyE,
|
||||
output logic DivSE,
|
||||
output logic DivDone,
|
||||
output logic NegSticky,
|
||||
output logic DivBusy
|
||||
|
@ -65,9 +65,9 @@ module srtfsm(
|
|||
// this is only a problem on radix 2 (and pssibly maximally redundant 4) since minimally redundant
|
||||
// radix-4 division can't create a QM that continually adds 0's
|
||||
if (`RADIX == 2)
|
||||
assign DivStickyE = |W&~(StickyWSA == WS);
|
||||
assign DivSE = |W&~(StickyWSA == WS);
|
||||
else
|
||||
assign DivStickyE = |W;
|
||||
assign DivSE = |W;
|
||||
assign DivDone = (state == DONE);
|
||||
assign W = WC+WS;
|
||||
assign NegSticky = W[`DIVLEN+3]; //*** is there a better way to do this???
|
||||
|
|
|
@ -31,16 +31,25 @@
|
|||
`include "wally-config.vh"
|
||||
|
||||
module srtpreproc (
|
||||
input logic clk,
|
||||
input logic DivStart,
|
||||
input logic [`NF:0] Xm, Ym,
|
||||
output logic [`DIVLEN-1:0] X,
|
||||
output logic [`DIVLEN-1:0] Dpreproc,
|
||||
input logic [`NE-1:0] Xe, Ye,
|
||||
input logic [`FMTBITS-1:0] Fmt,
|
||||
input logic Sqrt,
|
||||
input logic XZero,
|
||||
output logic [`NE+1:0] QeM,
|
||||
output logic [`DIVLEN+3:0] X,
|
||||
output logic [`DIVLEN+3:0] Dpreproc,
|
||||
output logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
|
||||
output logic [`DURLEN-1:0] Dur
|
||||
);
|
||||
// logic [`XLEN-1:0] PosA, PosB;
|
||||
// logic [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY;
|
||||
logic [`DIVLEN-1:0] PreprocA, PreprocX;
|
||||
logic [`DIVLEN-1:0] PreprocB, PreprocY;
|
||||
logic [`NF-1:0] PreprocA, PreprocX;
|
||||
logic [`NF-1:0] PreprocB, PreprocY;
|
||||
logic [`NF+3:0] SqrtX;
|
||||
logic [`NE+1:0] Qe;
|
||||
|
||||
// assign PosA = (Signed & SrcA[`XLEN - 1]) ? -SrcA : SrcA;
|
||||
// assign PosB = (Signed & SrcB[`XLEN - 1]) ? -SrcB : SrcB;
|
||||
|
@ -49,23 +58,22 @@ module srtpreproc (
|
|||
|
||||
// ***can probably merge X LZC with conversion
|
||||
// cout the number of leading zeros
|
||||
lzc #(`NF+1) lzcA (Xm, XZeroCnt);
|
||||
lzc #(`NF+1) lzcB (Ym, YZeroCnt);
|
||||
lzc #(`NF+1) lzcX (Xm, XZeroCnt);
|
||||
lzc #(`NF+1) lzcY (Ym, YZeroCnt);
|
||||
|
||||
// assign ExtraA = {PosA, {`DIVLEN-`XLEN{1'b0}}};
|
||||
// assign ExtraB = {PosB, {`DIVLEN-`XLEN{1'b0}}};
|
||||
|
||||
// assign PreprocA = ExtraA << zeroCntA;
|
||||
// assign PreprocB = ExtraB << (zeroCntB + 1);
|
||||
assign PreprocX = {Xm[`NF-1:0]<<XZeroCnt, {`DIVLEN-`NF{1'b0}}};
|
||||
assign PreprocY = {Ym[`NF-1:0]<<YZeroCnt, {`DIVLEN-`NF{1'b0}}};
|
||||
assign PreprocX = Xm[`NF-1:0]<<XZeroCnt;
|
||||
assign PreprocY = Ym[`NF-1:0]<<YZeroCnt;
|
||||
|
||||
|
||||
assign X = PreprocX;
|
||||
assign Dpreproc = PreprocY;
|
||||
assign SqrtX = Xe[0] ? {3'b110, ~XZero, PreprocX} : {2'b11, ~XZero, PreprocX, 1'b0};
|
||||
assign X = Sqrt ? {SqrtX, {`DIVLEN-`NF{1'b0}}} : {3'b000, ~XZero, PreprocX, {`DIVLEN-`NF{1'b0}}};
|
||||
assign Dpreproc = {4'b0001, /*Int ? PreprocB : */PreprocY, {`DIVLEN-`NF{1'b0}}};
|
||||
assign Dur = (`DURLEN)'(`FPDUR);
|
||||
// assign intExp = zeroCntB - zeroCntA + 1;
|
||||
// assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]);
|
||||
|
||||
// radix 2 radix 4
|
||||
// 1 copies DIVLEN+2 DIVLEN+2/2
|
||||
|
@ -76,6 +84,52 @@ module srtpreproc (
|
|||
// DIVRESLEN = DIVLEN or DIVLEN+2
|
||||
// r = 1 or 2
|
||||
// DIVRESLEN/(r*`DIVCOPIES)
|
||||
flopen #(`NE+2) expflop(clk, DivStart, Qe, QeM);
|
||||
expcalc expcalc(.Fmt, .Xe, .Ye, .Sqrt, .XZero, .XZeroCnt, .YZeroCnt, .Qe);
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
module expcalc(
|
||||
input logic [`FMTBITS-1:0] Fmt,
|
||||
input logic [`NE-1:0] Xe, Ye,
|
||||
input logic Sqrt,
|
||||
input logic XZero,
|
||||
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
|
||||
output logic [`NE+1:0] Qe
|
||||
);
|
||||
logic [`NE-2:0] Bias;
|
||||
logic [`NE-1:0] SExp, SXExp;
|
||||
logic [`NE+1:0] DExp;
|
||||
|
||||
if (`FPSIZES == 1) begin
|
||||
assign Bias = (`NE-1)'(`BIAS);
|
||||
|
||||
end else if (`FPSIZES == 2) begin
|
||||
assign Bias = Fmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1);
|
||||
|
||||
end else if (`FPSIZES == 3) begin
|
||||
always_comb
|
||||
case (Fmt)
|
||||
`FMT: Bias = (`NE-1)'(`BIAS);
|
||||
`FMT1: Bias = (`NE-1)'(`BIAS1);
|
||||
`FMT2: Bias = (`NE-1)'(`BIAS2);
|
||||
default: Bias = 'x;
|
||||
endcase
|
||||
|
||||
end else if (`FPSIZES == 4) begin
|
||||
always_comb
|
||||
case (Fmt)
|
||||
2'h3: Bias = (`NE-1)'(`Q_BIAS);
|
||||
2'h1: Bias = (`NE-1)'(`D_BIAS);
|
||||
2'h0: Bias = (`NE-1)'(`S_BIAS);
|
||||
2'h2: Bias = (`NE-1)'(`H_BIAS);
|
||||
endcase
|
||||
end
|
||||
assign SXExp = Xe - (`NE)'(`BIAS);
|
||||
assign SExp = {1'b0, SXExp[`NE-1:1]} + Bias;
|
||||
// correct exponent for denormalized input's normalization shifts
|
||||
assign DExp = ({2'b0, Xe} - {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, XZeroCnt} - {2'b0, Ye} + {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, YZeroCnt} + {3'b0, Bias})&{`NE+2{~XZero}};
|
||||
|
||||
assign Qe = Sqrt ? {2'b0, SExp} : DExp;
|
||||
endmodule
|
|
@ -30,35 +30,35 @@
|
|||
|
||||
module unpack (
|
||||
input logic [`FLEN-1:0] X, Y, Z, // inputs from register file
|
||||
input logic [`FMTBITS-1:0] FmtE, // format signal 00 - single 01 - double 11 - quad 10 - half
|
||||
output logic XSgnE, YSgnE, ZSgnE, // sign bits of XYZ
|
||||
output logic [`NE-1:0] XExpE, YExpE, ZExpE, // exponents of XYZ (converted to largest supported precision)
|
||||
output logic [`NF:0] XManE, YManE, ZManE, // mantissas of XYZ (converted to largest supported precision)
|
||||
output logic XNaNE, YNaNE, ZNaNE, // is XYZ a NaN
|
||||
output logic XSNaNE, YSNaNE, ZSNaNE, // is XYZ a signaling NaN
|
||||
output logic XDenormE, ZDenormE, // is XYZ denormalized
|
||||
output logic XZeroE, YZeroE, ZZeroE, // is XYZ zero
|
||||
output logic XInfE, YInfE, ZInfE, // is XYZ infinity
|
||||
output logic XExpMaxE // does X have the maximum exponent (NaN or Inf)
|
||||
input logic [`FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half
|
||||
input logic XEn, YEn, ZEn,
|
||||
output logic Xs, Ys, Zs, // sign bits of XYZ
|
||||
output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
|
||||
output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
|
||||
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
|
||||
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
|
||||
output logic XDenorm, ZDenorm, // is XYZ denormalized
|
||||
output logic XZero, YZero, ZZero, // is XYZ zero
|
||||
output logic XInf, YInf, ZInf, // is XYZ infinity
|
||||
output logic XExpMax // does X have the maximum exponent (NaN or Inf)
|
||||
);
|
||||
|
||||
logic [`NF-1:0] XFracE, YFracE, ZFracE; //Fraction of XYZ
|
||||
logic XExpNonZero, YExpNonZero, ZExpNonZero; // is the exponent of XYZ non-zero
|
||||
logic XFracZero, YFracZero, ZFracZero; // is the fraction zero
|
||||
logic YExpMaxE, ZExpMaxE; // is the exponent all 1s
|
||||
logic YExpMax, ZExpMax; // is the exponent all 1s
|
||||
|
||||
unpackinput unpackinputX (.In(X), .FmtE, .Sgn(XSgnE), .Exp(XExpE), .Man(XManE),
|
||||
.NaN(XNaNE), .SNaN(XSNaNE), .ExpNonZero(XExpNonZero),
|
||||
.Zero(XZeroE), .Inf(XInfE), .ExpMax(XExpMaxE), .FracZero(XFracZero));
|
||||
unpackinput unpackinputX (.In(X), .Fmt, .Sgn(Xs), .Exp(Xe), .Man(Xm), .En(XEn),
|
||||
.NaN(XNaN), .SNaN(XSNaN), .ExpNonZero(XExpNonZero),
|
||||
.Zero(XZero), .Inf(XInf), .ExpMax(XExpMax), .FracZero(XFracZero));
|
||||
|
||||
unpackinput unpackinputY (.In(Y), .FmtE, .Sgn(YSgnE), .Exp(YExpE), .Man(YManE),
|
||||
.NaN(YNaNE), .SNaN(YSNaNE), .ExpNonZero(YExpNonZero),
|
||||
.Zero(YZeroE), .Inf(YInfE), .ExpMax(YExpMaxE), .FracZero(YFracZero));
|
||||
unpackinput unpackinputY (.In(Y), .Fmt, .Sgn(Ys), .Exp(Ye), .Man(Ym), .En(YEn),
|
||||
.NaN(YNaN), .SNaN(YSNaN), .ExpNonZero(YExpNonZero),
|
||||
.Zero(YZero), .Inf(YInf), .ExpMax(YExpMax), .FracZero(YFracZero));
|
||||
|
||||
unpackinput unpackinputZ (.In(Z), .FmtE, .Sgn(ZSgnE), .Exp(ZExpE), .Man(ZManE),
|
||||
.NaN(ZNaNE), .SNaN(ZSNaNE), .ExpNonZero(ZExpNonZero),
|
||||
.Zero(ZZeroE), .Inf(ZInfE), .ExpMax(ZExpMaxE), .FracZero(ZFracZero));
|
||||
unpackinput unpackinputZ (.In(Z), .Fmt, .Sgn(Zs), .Exp(Ze), .Man(Zm), .En(ZEn),
|
||||
.NaN(ZNaN), .SNaN(ZSNaN), .ExpNonZero(ZExpNonZero),
|
||||
.Zero(ZZero), .Inf(ZInf), .ExpMax(ZExpMax), .FracZero(ZFracZero));
|
||||
// is the input denormalized
|
||||
assign XDenormE = ~XExpNonZero & ~XFracZero;
|
||||
assign ZDenormE = ~ZExpNonZero & ~ZFracZero;
|
||||
assign XDenorm = ~XExpNonZero & ~XFracZero;
|
||||
assign ZDenorm = ~ZExpNonZero & ~ZFracZero;
|
||||
endmodule
|
|
@ -30,7 +30,8 @@
|
|||
|
||||
module unpackinput (
|
||||
input logic [`FLEN-1:0] In, // inputs from register file
|
||||
input logic [`FMTBITS-1:0] FmtE, // format signal 00 - single 01 - double 11 - quad 10 - half
|
||||
input logic En, // enable the input
|
||||
input logic [`FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half
|
||||
output logic Sgn, // sign bits of XYZ
|
||||
output logic [`NE-1:0] Exp, // exponents of XYZ (converted to largest supported precision)
|
||||
output logic [`NF:0] Man, // mantissas of XYZ (converted to largest supported precision)
|
||||
|
@ -74,16 +75,16 @@ module unpackinput (
|
|||
// quad and half
|
||||
// double and half
|
||||
|
||||
assign BadNaNBox = ~(FmtE|(&In[`FLEN-1:`LEN1])); // Check NaN boxing
|
||||
assign BadNaNBox = ~(Fmt|(&In[`FLEN-1:`LEN1])); // Check NaN boxing
|
||||
|
||||
// choose sign bit depending on format - 1=larger precsion 0=smaller precision
|
||||
assign Sgn = FmtE ? In[`FLEN-1] : In[`LEN1-1];
|
||||
assign Sgn = Fmt ? In[`FLEN-1] : In[`LEN1-1];
|
||||
|
||||
// extract the fraction, add trailing zeroes to the mantissa if nessisary
|
||||
assign Frac = FmtE ? In[`NF-1:0] : {In[`NF1-1:0], (`NF-`NF1)'(0)};
|
||||
assign Frac = Fmt ? In[`NF-1:0] : {In[`NF1-1:0], (`NF-`NF1)'(0)};
|
||||
|
||||
// is the exponent non-zero
|
||||
assign ExpNonZero = FmtE ? |In[`FLEN-2:`NF] : |In[`LEN1-2:`NF1];
|
||||
assign ExpNonZero = Fmt ? |In[`FLEN-2:`NF] : |In[`LEN1-2:`NF1];
|
||||
|
||||
// example double to single conversion:
|
||||
// 1023 = 0011 1111 1111
|
||||
|
@ -95,10 +96,10 @@ module unpackinput (
|
|||
|
||||
// extract the exponent, converting the smaller exponent into the larger precision if nessisary
|
||||
// - if the original precision had a denormal number convert the exponent value 1
|
||||
assign Exp = FmtE ? {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero} : {In[`LEN1-2], {`NE-`NE1{~In[`LEN1-2]}}, In[`LEN1-3:`NF1+1], In[`NF1]|~ExpNonZero};
|
||||
assign Exp = Fmt ? {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero} : {In[`LEN1-2], {`NE-`NE1{~In[`LEN1-2]}}, In[`LEN1-3:`NF1+1], In[`NF1]|~ExpNonZero};
|
||||
|
||||
// is the exponent all 1's
|
||||
assign ExpMax = FmtE ? &In[`FLEN-2:`NF] : &In[`LEN1-2:`NF1];
|
||||
assign ExpMax = Fmt ? &In[`FLEN-2:`NF] : &In[`LEN1-2:`NF1];
|
||||
|
||||
|
||||
end else if (`FPSIZES == 3) begin // three floating point precsions supported
|
||||
|
@ -122,7 +123,7 @@ module unpackinput (
|
|||
|
||||
// Check NaN boxing
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
`FMT: BadNaNBox = 0;
|
||||
`FMT1: BadNaNBox = ~&In[`FLEN-1:`LEN1];
|
||||
`FMT2: BadNaNBox = ~&In[`FLEN-1:`LEN2];
|
||||
|
@ -131,7 +132,7 @@ module unpackinput (
|
|||
|
||||
// extract the sign bit
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
`FMT: Sgn = In[`FLEN-1];
|
||||
`FMT1: Sgn = In[`LEN1-1];
|
||||
`FMT2: Sgn = In[`LEN2-1];
|
||||
|
@ -140,7 +141,7 @@ module unpackinput (
|
|||
|
||||
// extract the fraction
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
`FMT: Frac = In[`NF-1:0];
|
||||
`FMT1: Frac = {In[`NF1-1:0], (`NF-`NF1)'(0)};
|
||||
`FMT2: Frac = {In[`NF2-1:0], (`NF-`NF2)'(0)};
|
||||
|
@ -149,7 +150,7 @@ module unpackinput (
|
|||
|
||||
// is the exponent non-zero
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
`FMT: ExpNonZero = |In[`FLEN-2:`NF]; // if input is largest precision (`FLEN - ie quad or double)
|
||||
`FMT1: ExpNonZero = |In[`LEN1-2:`NF1]; // if input is larger precsion (`LEN1 - double or single)
|
||||
`FMT2: ExpNonZero = |In[`LEN2-2:`NF2]; // if input is smallest precsion (`LEN2 - single or half)
|
||||
|
@ -166,7 +167,7 @@ module unpackinput (
|
|||
|
||||
// convert the larger precision's exponent to use the largest precision's bias
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
`FMT: Exp = {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero};
|
||||
`FMT1: Exp = {In[`LEN1-2], {`NE-`NE1{~In[`LEN1-2]}}, In[`LEN1-3:`NF1+1], In[`NF1]|~ExpNonZero};
|
||||
`FMT2: Exp = {In[`LEN2-2], {`NE-`NE2{~In[`LEN2-2]}}, In[`LEN2-3:`NF2+1], In[`NF2]|~ExpNonZero};
|
||||
|
@ -175,7 +176,7 @@ module unpackinput (
|
|||
|
||||
// is the exponent all 1's
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
`FMT: ExpMax = &In[`FLEN-2:`NF];
|
||||
`FMT1: ExpMax = &In[`LEN1-2:`NF1];
|
||||
`FMT2: ExpMax = &In[`LEN2-2:`NF2];
|
||||
|
@ -194,7 +195,7 @@ module unpackinput (
|
|||
|
||||
// Check NaN boxing
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
2'b11: BadNaNBox = 0;
|
||||
2'b01: BadNaNBox = ~&In[`Q_LEN-1:`D_LEN];
|
||||
2'b00: BadNaNBox = ~&In[`Q_LEN-1:`S_LEN];
|
||||
|
@ -203,7 +204,7 @@ module unpackinput (
|
|||
|
||||
// extract sign bit
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
2'b11: Sgn = In[`Q_LEN-1];
|
||||
2'b01: Sgn = In[`D_LEN-1];
|
||||
2'b00: Sgn = In[`S_LEN-1];
|
||||
|
@ -213,7 +214,7 @@ module unpackinput (
|
|||
|
||||
// extract the fraction
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
2'b11: Frac = In[`Q_NF-1:0];
|
||||
2'b01: Frac = {In[`D_NF-1:0], (`Q_NF-`D_NF)'(0)};
|
||||
2'b00: Frac = {In[`S_NF-1:0], (`Q_NF-`S_NF)'(0)};
|
||||
|
@ -222,7 +223,7 @@ module unpackinput (
|
|||
|
||||
// is the exponent non-zero
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
2'b11: ExpNonZero = |In[`Q_LEN-2:`Q_NF];
|
||||
2'b01: ExpNonZero = |In[`D_LEN-2:`D_NF];
|
||||
2'b00: ExpNonZero = |In[`S_LEN-2:`S_NF];
|
||||
|
@ -240,7 +241,7 @@ module unpackinput (
|
|||
|
||||
// convert the double precsion exponent into quad precsion
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
2'b11: Exp = {In[`Q_LEN-2:`Q_NF+1], In[`Q_NF]|~ExpNonZero};
|
||||
2'b01: Exp = {In[`D_LEN-2], {`Q_NE-`D_NE{~In[`D_LEN-2]}}, In[`D_LEN-3:`D_NF+1], In[`D_NF]|~ExpNonZero};
|
||||
2'b00: Exp = {In[`S_LEN-2], {`Q_NE-`S_NE{~In[`S_LEN-2]}}, In[`S_LEN-3:`S_NF+1], In[`S_NF]|~ExpNonZero};
|
||||
|
@ -250,7 +251,7 @@ module unpackinput (
|
|||
|
||||
// is the exponent all 1's
|
||||
always_comb
|
||||
case (FmtE)
|
||||
case (Fmt)
|
||||
2'b11: ExpMax = &In[`Q_LEN-2:`Q_NF];
|
||||
2'b01: ExpMax = &In[`D_LEN-2:`D_NF];
|
||||
2'b00: ExpMax = &In[`S_LEN-2:`S_NF];
|
||||
|
@ -262,8 +263,8 @@ module unpackinput (
|
|||
// Output logic
|
||||
assign FracZero = ~|Frac; // is the fraction zero?
|
||||
assign Man = {ExpNonZero, Frac}; // add the assumed one (or zero if denormal or zero) to create the significand
|
||||
assign NaN = (ExpMax & ~FracZero)|BadNaNBox; // is the input a NaN?
|
||||
assign NaN = ((ExpMax & ~FracZero)|BadNaNBox)&En; // is the input a NaN?
|
||||
assign SNaN = NaN&~Frac[`NF-1]&~BadNaNBox; // is the input a singnaling NaN?
|
||||
assign Inf = ExpMax & FracZero; // is the input infinity?
|
||||
assign Inf = ExpMax & FracZero &En; // is the input infinity?
|
||||
assign Zero = ~ExpNonZero & FracZero; // is the input zero?
|
||||
endmodule
|
|
@ -165,6 +165,7 @@ module uartPC16550D(
|
|||
SCR <= #1 8'b0; // not strictly necessary to reset
|
||||
end else begin
|
||||
if (~MEMWb) begin
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
case (A)
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
3'b000: if (DLAB) DLL <= #1 Din; // else TXHR <= #1 Din; // TX handled in TX register/FIFO section
|
||||
|
@ -177,34 +178,42 @@ module uartPC16550D(
|
|||
// freq /baud / 16 = div
|
||||
//3'b000: if (DLAB) DLL <= #1 8'd38; //else TXHR <= #1 Din; // TX handled in TX register/FIFO section
|
||||
//3'b000: if (DLAB) DLL <= #1 8'd11; //else TXHR <= #1 Din; // TX handled in
|
||||
3'b000: if (DLAB) DLL <= #1 8'd8; //else TXHR <= #1 Din; // TX handled in
|
||||
3'b000: if (DLAB) DLL <= #1 8'd8; //else TXHR <= #1 Din; // TX handled in
|
||||
3'b001: if (DLAB) DLM <= #1 8'b0; else IER <= #1 Din[3:0];
|
||||
|
||||
3'b010: FCR <= #1 {Din[7:6], 2'b0, Din[3], 2'b0, Din[0]}; // Write only FIFO Control Register; 4:5 reserved and 2:1 self-clearing
|
||||
3'b011: LCR <= #1 Din;
|
||||
3'b100: MCR <= #1 Din[4:0];
|
||||
3'b101: LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
|
||||
3'b110: MSR <= #1 Din[3:0];
|
||||
3'b111: SCR <= #1 Din;
|
||||
endcase
|
||||
/* verilator lint_on CASEINCOMPLETE */
|
||||
end
|
||||
|
||||
|
||||
// Line Status Register (8.6.3)
|
||||
// Ben 6/9/21 I don't like how this is a register. A lot of the individual bits have clocked components, so this just adds unecessary delay.
|
||||
LSR[0] <= #1 rxdataready; // Data ready
|
||||
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
|
||||
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
|
||||
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
|
||||
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
|
||||
LSR[5] <= #1 THRE; // THRE
|
||||
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
|
||||
if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error
|
||||
// Ben 6/9/21 I don't like how this is a register. A lot of the individual bits have clocked components, so this just adds unecessary delay.
|
||||
if (~MEMWb & (A == 3'b101))
|
||||
LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
|
||||
else begin
|
||||
LSR[0] <= #1 rxdataready; // Data ready
|
||||
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
|
||||
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
|
||||
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
|
||||
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
|
||||
LSR[5] <= #1 THRE; // THRE
|
||||
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
|
||||
if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error
|
||||
end
|
||||
|
||||
// Modem Status Register (8.6.8)
|
||||
MSR[0] <= #1 MSR[0] | CTSb2 ^ CTSbsync; // Delta Clear to Send
|
||||
MSR[1] <= #1 MSR[1] | DSRb2 ^ DSRbsync; // Delta Data Set Ready
|
||||
MSR[2] <= #1 MSR[2] | (~RIb2 & RIbsync); // Trailing Edge of Ring Indicator
|
||||
MSR[3] <= #1 MSR[3] | DCDb2 ^ DCDbsync; // Delta Data Carrier Detect
|
||||
if (~MEMWb & (A == 3'b110))
|
||||
MSR <= #1 Din[3:0];
|
||||
else if (~MEMRb & (A == 3'b110))
|
||||
MSR <= #1 4'b0; // Reading MSR clears the flags in MSR bits 3:0
|
||||
else begin
|
||||
MSR[0] <= #1 MSR[0] | CTSb2 ^ CTSbsync; // Delta Clear to Send
|
||||
MSR[1] <= #1 MSR[1] | DSRb2 ^ DSRbsync; // Delta Data Set Ready
|
||||
MSR[2] <= #1 MSR[2] | (~RIb2 & RIbsync); // Trailing Edge of Ring Indicator
|
||||
MSR[3] <= #1 MSR[3] | DCDb2 ^ DCDbsync; // Delta Data Carrier Detect
|
||||
end
|
||||
end
|
||||
always_comb
|
||||
if (~MEMRb)
|
||||
|
@ -215,7 +224,8 @@ module uartPC16550D(
|
|||
3'b011: Dout = LCR;
|
||||
3'b100: Dout = {3'b000, MCR};
|
||||
3'b101: Dout = LSR;
|
||||
3'b110: Dout = {~CTSbsync, ~DSRbsync, ~RIbsync, ~DCDbsync, MSR[3:0]};
|
||||
// 3'b110: Dout = {~CTSbsync, ~DSRbsync, ~RIbsync, ~DCDbsync, MSR[3:0]};
|
||||
3'b110: Dout = {~DCDbsync, ~RIbsync, ~DSRbsync, ~CTSbsync, MSR[3:0]};
|
||||
3'b111: Dout = SCR;
|
||||
endcase
|
||||
else Dout = 8'b0;
|
||||
|
@ -304,7 +314,7 @@ module uartPC16550D(
|
|||
|
||||
// ERROR CONDITIONS
|
||||
assign rxparity = ^rxdata;
|
||||
assign rxparityerr = rxparity ^ rxparitybit ^ ~evenparitysel; // Check even/odd parity (*** check if LCR needs to be inverted)
|
||||
assign rxparityerr = (rxparity ^ rxparitybit ^ ~evenparitysel) & LCR[3]; // Check even/odd parity (*** check if LCR needs to be inverted)
|
||||
assign rxoverrunerr = fifoenabled ? (rxfifoentries == 15) : rxdataready; // overrun if FIFO or receive buffer register full
|
||||
assign rxframingerr = ~rxstopbit; // framing error if no stop bit
|
||||
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
|
||||
|
@ -405,7 +415,7 @@ module uartPC16550D(
|
|||
txstate <= #1 UART_IDLE;
|
||||
end
|
||||
|
||||
assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s)
|
||||
assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s) - 1
|
||||
// *** explain; is this necessary?
|
||||
if (`QEMU) assign txnextbit = txbaudpulse & (txoversampledcnt[1:0] == 2'b00); // implies txstate = UART_ACTIVE
|
||||
else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
all: exptestgen testgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 sqrttestgen
|
||||
all: exptestgen testgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 sqrttestgen modtestgen
|
||||
|
||||
sqrttestgen: sqrttestgen.c
|
||||
gcc sqrttestgen.c -o sqrttestgen -lm
|
||||
|
@ -28,6 +28,10 @@ inttestgen: inttestgen.c
|
|||
gcc -lm -o inttestgen inttestgen.c
|
||||
./inttestgen
|
||||
|
||||
modtestgen: modtestgen.c
|
||||
gcc -lm -o modtestgen modtestgen.c
|
||||
./modtestgen
|
||||
|
||||
clean:
|
||||
rm -f testgen exptestgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 sqrttestgen
|
||||
rm -f testgen exptestgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 sqrttestgen modtestgen
|
||||
|
||||
|
|
|
@ -96,10 +96,6 @@ void output(FILE *fptr, int aSign, int aExp, double aFrac, int bSign, int bExp,
|
|||
// Print r in standard double format
|
||||
fprintf(fptr, "%03x", rExp|(rSign<<11));
|
||||
printhex(fptr, rFrac);
|
||||
fprintf(fptr, "_");
|
||||
|
||||
// Spacing for testbench, value doesn't matter
|
||||
fprintf(fptr, "%016x", 0);
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1,9 +1,8 @@
|
|||
/* testgen.c */
|
||||
|
||||
/* Written 10/31/96 by David Harris
|
||||
/* Written 7/21/2022 by Cedar Turek
|
||||
|
||||
This program creates test vectors for mantissa component
|
||||
of an IEEE floating point divider.
|
||||
This program creates test vectors for integer divide.
|
||||
*/
|
||||
|
||||
/* #includes */
|
||||
|
@ -19,7 +18,7 @@
|
|||
|
||||
/* Prototypes */
|
||||
|
||||
void output(FILE *fptr, long a, long b, long r, long rem);
|
||||
void output(FILE *fptr, long a, long b, long r);
|
||||
void printhex(FILE *fptr, long x);
|
||||
double random_input(void);
|
||||
|
||||
|
@ -28,7 +27,7 @@ double random_input(void);
|
|||
void main(void)
|
||||
{
|
||||
FILE *fptr;
|
||||
long a, b, r, rem;
|
||||
long a, b, r;
|
||||
long list[ENTRIES] = {1, 3, 5, 18, 25, 33, 42, 65, 103, 255};
|
||||
int i, j;
|
||||
|
||||
|
@ -42,32 +41,22 @@ void main(void)
|
|||
for (j=0; j<ENTRIES; j++) {
|
||||
a = list[j];
|
||||
r = a/b;
|
||||
rem = a%b;
|
||||
output(fptr, a, b, r, rem);
|
||||
output(fptr, a, b, r);
|
||||
}
|
||||
}
|
||||
|
||||
// for (i = 0; i< RANDOM_VECS; i++) {
|
||||
// a = random_input();
|
||||
// b = random_input();
|
||||
// r = a/b;
|
||||
// output(fptr, a, b, r);
|
||||
// }
|
||||
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
/* Functions */
|
||||
|
||||
void output(FILE *fptr, long a, long b, long r, long rem)
|
||||
void output(FILE *fptr, long a, long b, long r)
|
||||
{
|
||||
printhex(fptr, a);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, b);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, r);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, rem);
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
|
||||
|
|
BIN
pipelined/srt/modtestgen
Executable file
BIN
pipelined/srt/modtestgen
Executable file
Binary file not shown.
73
pipelined/srt/modtestgen.c
Normal file
73
pipelined/srt/modtestgen.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* testgen.c */
|
||||
|
||||
/* Written 7/21/2022 by Cedar Turek
|
||||
|
||||
This program creates test vectors for modulo
|
||||
calculation from integer divide.
|
||||
*/
|
||||
|
||||
/* #includes */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define ENTRIES 10
|
||||
#define RANDOM_VECS 500
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
void output(FILE *fptr, long a, long b, long rem);
|
||||
void printhex(FILE *fptr, long x);
|
||||
double random_input(void);
|
||||
|
||||
/* Main */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
FILE *fptr;
|
||||
long a, b, rem;
|
||||
long list[ENTRIES] = {1, 3, 5, 18, 25, 33, 42, 65, 103, 255};
|
||||
int i, j;
|
||||
|
||||
if ((fptr = fopen("modtestvectors","w")) == NULL) {
|
||||
fprintf(stderr, "Couldn't write testvectors file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i=0; i<ENTRIES; i++) {
|
||||
b = list[i];
|
||||
for (j=0; j<ENTRIES; j++) {
|
||||
a = list[j];
|
||||
rem = a%b;
|
||||
output(fptr, a, b, rem);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
/* Functions */
|
||||
|
||||
void output(FILE *fptr, long a, long b, long rem)
|
||||
{
|
||||
printhex(fptr, a);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, b);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, rem);
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
|
||||
void printhex(FILE *fptr, long m)
|
||||
{
|
||||
fprintf(fptr, "%016llx", m);
|
||||
}
|
||||
|
||||
double random_input(void)
|
||||
{
|
||||
return 1.0 + rand()/32767.0;
|
||||
}
|
||||
|
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
/* sqrttestgen.c */
|
||||
|
||||
/* Written 19 October 2021 David_Harris@hmc.edu
|
||||
/* Written 7/22/2022 by Cedar Turek
|
||||
|
||||
This program creates test vectors for mantissa component
|
||||
of an IEEE floating point square root.
|
||||
|
@ -15,6 +15,7 @@
|
|||
/* Constants */
|
||||
|
||||
#define ENTRIES 17
|
||||
#define BIGENT 1000
|
||||
#define RANDOM_VECS 500
|
||||
|
||||
/* Prototypes */
|
||||
|
@ -34,6 +35,9 @@ void main(void)
|
|||
1.75, 1.875, 1.99999,
|
||||
1.1, 1.5, 1.01, 1.001, 1.0001,
|
||||
2/1.1, 2/1.5, 2/1.25, 2/1.125};
|
||||
|
||||
double bigtest[BIGENT];
|
||||
|
||||
double exps[ENTRIES] = {0, 0, 2, 3, 4, 5, 6, 7, 8, 1, 10,
|
||||
11, 12, 13, 14, 15, 16};
|
||||
int i;
|
||||
|
@ -44,13 +48,14 @@ void main(void)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
for (i=0; i<ENTRIES; i++) {
|
||||
aFrac = mans[i];
|
||||
aExp = exps[i] + bias;
|
||||
rFrac = sqrt(aFrac * pow(2, exps[i]));
|
||||
rExp = (int) (log(rFrac)/log(2) + bias);
|
||||
output(fptr, aExp, aFrac, rExp, rFrac);
|
||||
}
|
||||
// Small Test
|
||||
// for (i=0; i<ENTRIES; i++) {
|
||||
// aFrac = mans[i];
|
||||
// aExp = exps[i] + bias;
|
||||
// rFrac = sqrt(aFrac * pow(2, exps[i]));
|
||||
// rExp = (int) (log(rFrac)/log(2) + bias);
|
||||
// output(fptr, aExp, aFrac, rExp, rFrac);
|
||||
// }
|
||||
|
||||
// WS
|
||||
// Test 1: sqrt(1) = 1 0000 0000 0000 00
|
||||
|
@ -67,6 +72,16 @@ void main(void)
|
|||
// output(fptr, a, r);
|
||||
// }
|
||||
|
||||
// Big Test
|
||||
for (i=0; i<BIGENT; i++) {
|
||||
bigtest[i] = random_input();
|
||||
aFrac = bigtest[i];
|
||||
aExp = (i - BIGENT/2) + bias;
|
||||
rFrac = sqrt(aFrac * pow(2, (i - BIGENT/2)));
|
||||
rExp = (int) (log(rFrac)/log(2) + bias);
|
||||
output(fptr, aExp, aFrac, rExp, rFrac);
|
||||
}
|
||||
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
|
@ -86,10 +101,6 @@ void output(FILE *fptr, int aExp, double aFrac, int rExp, double rFrac)
|
|||
// Print r in standard double format
|
||||
fprintf(fptr, "%03x", rExp);
|
||||
printhex(fptr, rFrac);
|
||||
fprintf(fptr, "_");
|
||||
|
||||
// Spacing for testbench, value doesn't matter
|
||||
fprintf(fptr, "%016x", 0);
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
|
||||
|
@ -109,6 +120,6 @@ void printhex(FILE *fptr, double m)
|
|||
|
||||
double random_input(void)
|
||||
{
|
||||
return 1.0 + rand()/32767.0;
|
||||
return 1.0 + ((rand() % 32768)/32767.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,4 +2,6 @@ add wave -noupdate /testbench/*
|
|||
add wave -noupdate /testbench/srt/*
|
||||
add wave -noupdate /testbench/srt/sotfc2/*
|
||||
add wave -noupdate /testbench/srt/preproc/*
|
||||
add wave -noupdate /testbench/srt/postproc/*
|
||||
add wave -noupdate /testbench/srt/expcalc/*
|
||||
add wave -noupdate /testbench/srt/divcounter/*
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// srt.sv
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 13 January 2022
|
||||
// Modified: cturek@hmc.edu June 2022
|
||||
// Modified: cturek@hmc.edu July 2022
|
||||
//
|
||||
// Purpose: Combined Divide and Square Root Floating Point and Integer Unit
|
||||
//
|
||||
|
@ -35,33 +35,36 @@ module srt (
|
|||
input logic Start,
|
||||
input logic Stall, // *** multiple pipe stages
|
||||
input logic Flush, // *** multiple pipe stages
|
||||
// Floating Point Inputs
|
||||
// later add exponents, signs, special cases
|
||||
// Floating Point
|
||||
input logic XSign, YSign,
|
||||
input logic [`NE-1:0] XExp, YExp,
|
||||
input logic [`NF-1:0] SrcXFrac, SrcYFrac,
|
||||
// Integer
|
||||
input logic [`XLEN-1:0] SrcA, SrcB,
|
||||
// Customization
|
||||
input logic [1:0] Fmt, // Floats: 00 = 16 bit, 01 = 32 bit, 10 = 64 bit, 11 = 128 bit
|
||||
input logic W64, // 32-bit ints on XLEN=64
|
||||
// Selection
|
||||
input logic Signed, // Interpret integers as signed 2's complement
|
||||
input logic Int, // Choose integer inputs
|
||||
input logic Mod, // perform remainder calculation (modulo) instead of divide
|
||||
input logic Sqrt, // perform square root, not divide
|
||||
output logic rsign, done,
|
||||
output logic [`DIVLEN-2:0] Rem, Quot, // *** later handle integers
|
||||
output logic [`DIVLEN-1:0] Result,
|
||||
output logic [`NE-1:0] rExp,
|
||||
output logic [3:0] Flags
|
||||
);
|
||||
|
||||
logic qp, qz, qn; // quotient is +1, 0, or -1
|
||||
logic qp, qz, qn; // result bits are +1, 0, or -1
|
||||
logic [`NE-1:0] calcExp;
|
||||
logic calcSign;
|
||||
logic [`DIVLEN+3:0] X, Dpreproc, C, F, AddIn;
|
||||
logic [`DIVLEN+3:0] X, Dpreproc, C, F, S, SM, AddIn;
|
||||
logic [`DIVLEN+3:0] WS, WSA, WSN, WC, WCA, WCN, D, Db, Dsel;
|
||||
logic [$clog2(`XLEN+1)-1:0] intExp, dur, calcDur;
|
||||
logic [$clog2(`XLEN+1)-1:0] zeroCntD, intExp, dur, calcDur;
|
||||
logic intSign;
|
||||
logic cin;
|
||||
|
||||
srtpreproc preproc(SrcA, SrcB, SrcXFrac, SrcYFrac, XExp, Fmt, W64, Signed, Int, Sqrt, X, Dpreproc, intExp, calcDur, intSign);
|
||||
srtpreproc preproc(SrcA, SrcB, SrcXFrac, SrcYFrac, XExp, Fmt, W64, Signed, Int, Mod, Sqrt, X, Dpreproc, zeroCntD, intExp, calcDur, intSign);
|
||||
|
||||
// Top Muxes and Registers
|
||||
// When start is asserted, the inputs are loaded into the divider.
|
||||
|
@ -75,7 +78,7 @@ module srt (
|
|||
|
||||
// Quotient Selection logic
|
||||
// Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
|
||||
qsel2 qsel2(WS[`DIVLEN+3:`DIVLEN-1], WC[`DIVLEN+3:`DIVLEN-1], Sqrt, qp, qz, qn);
|
||||
qsel2 qsel2(WS[`DIVLEN+3:`DIVLEN], WC[`DIVLEN+3:`DIVLEN], Sqrt, qp, qz, qn);
|
||||
|
||||
flopen #(`NE) expflop(clk, Start, calcExp, rExp);
|
||||
flopen #(1) signflop(clk, Start, calcSign, rsign);
|
||||
|
@ -90,8 +93,9 @@ module srt (
|
|||
// If only implementing division, use divide otfc
|
||||
// otfc2 #(`DIVLEN) otfc2(clk, Start, qp, qz, qn, Quot);
|
||||
// otherwise use sotfc
|
||||
creg sotfcC(clk, Start, C);
|
||||
sotfc2 sotfc2(clk, Start, qp, qn, C, Quot, F);
|
||||
creg sotfcC(clk, Start, Sqrt, C);
|
||||
sotfc2 sotfc2(clk, Start, qp, qn, Sqrt, C, S, SM);
|
||||
fsel2 fsel(qp, qn, C, S, SM, F);
|
||||
|
||||
// Adder input selection
|
||||
assign AddIn = Sqrt ? F : Dsel;
|
||||
|
@ -102,7 +106,7 @@ module srt (
|
|||
|
||||
expcalc expcalc(.XExp, .YExp, .calcExp, .Sqrt);
|
||||
|
||||
signcalc signcalc(.XSign, .YSign, .calcSign);
|
||||
srtpostproc postproc(.WS, .WC, .X, .D, .S, .SM, .dur, .zeroCntD, .XSign, .YSign, .Signed, .Int, .Mod, .Result, .calcSign);
|
||||
endmodule
|
||||
|
||||
////////////////
|
||||
|
@ -120,13 +124,14 @@ module srtpreproc (
|
|||
input logic W64, // 32-bit ints on XLEN=64
|
||||
input logic Signed, // Interpret integers as signed 2's complement
|
||||
input logic Int, // Choose integer inputs
|
||||
input logic Mod, // perform remainder calculation (modulo) instead of divide
|
||||
input logic Sqrt, // perform square root, not divide
|
||||
output logic [`DIVLEN+3:0] X, D,
|
||||
output logic [$clog2(`XLEN+1)-1:0] intExp, dur, // Quotient integer exponent
|
||||
output logic [$clog2(`XLEN+1)-1:0] zeroCntB, intExp, dur, // Quotient integer exponent
|
||||
output logic intSign // Quotient integer sign
|
||||
);
|
||||
|
||||
logic [$clog2(`XLEN+1)-1:0] zeroCntA, zeroCntB;
|
||||
logic [$clog2(`XLEN+1)-1:0] zeroCntA;
|
||||
logic [`XLEN-1:0] PosA, PosB;
|
||||
logic [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY, DivX;
|
||||
logic [`NF+4:0] SqrtX;
|
||||
|
@ -153,12 +158,12 @@ module srtpreproc (
|
|||
|
||||
// Selecting correct divider inputs
|
||||
assign DivX = Int ? PreprocA : PreprocX;
|
||||
assign SqrtX = XExp[0] ? {4'b0000, SrcXFrac, 1'b0} : {5'b11111, SrcXFrac};
|
||||
assign SqrtX = XExp[0] ? {5'b11101, SrcXFrac} : {4'b1111, SrcXFrac, 1'b0};
|
||||
assign X = Sqrt ? {SqrtX, {(`EXTRAFRACBITS-1){1'b0}}} : {4'b0001, DivX};
|
||||
assign D = {4'b0001, Int ? PreprocB : PreprocY};
|
||||
|
||||
// Integer exponent and sign calculations
|
||||
assign intExp = zeroCntB - zeroCntA + 1;
|
||||
assign intExp = zeroCntB - zeroCntA - Mod + (PreprocA >= PreprocB);
|
||||
assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]);
|
||||
|
||||
// Number of cycles of divider
|
||||
|
@ -168,13 +173,13 @@ endmodule
|
|||
/////////////////////////////////
|
||||
// Quotient Selection, Radix 2 //
|
||||
/////////////////////////////////
|
||||
module qsel2 ( // *** eventually just change to 4 bits
|
||||
input logic [`DIVLEN+3:`DIVLEN-1] ps, pc,
|
||||
module qsel2 (
|
||||
input logic [`DIVLEN+3:`DIVLEN] ps, pc,
|
||||
input logic Sqrt,
|
||||
output logic qp, qz, qn
|
||||
);
|
||||
|
||||
logic [`DIVLEN+3:`DIVLEN-1] p, g;
|
||||
logic [`DIVLEN+3:`DIVLEN] p, g;
|
||||
logic magnitude, sign, cout;
|
||||
|
||||
// The quotient selection logic is presented for simplicity, not
|
||||
|
@ -185,8 +190,8 @@ module qsel2 ( // *** eventually just change to 4 bits
|
|||
assign p = ps ^ pc;
|
||||
assign g = ps & pc;
|
||||
|
||||
assign #1 magnitude = ~(&p[`DIVLEN+2:`DIVLEN-1]);
|
||||
assign #1 cout = g[`DIVLEN+2] | (p[`DIVLEN+2] & (g[`DIVLEN+1] | p[`DIVLEN+1] & (g[`DIVLEN] | (Sqrt & (p[`DIVLEN] & g[`DIVLEN-1])))));
|
||||
assign #1 magnitude = ~(&p[`DIVLEN+2:`DIVLEN]);
|
||||
assign #1 cout = g[`DIVLEN+2] | (p[`DIVLEN+2] & (g[`DIVLEN+1] | p[`DIVLEN+1] & (g[`DIVLEN])));
|
||||
assign #1 sign = p[`DIVLEN+3] ^ cout;
|
||||
/* assign #1 magnitude = ~((ps[54]^pc[54]) & (ps[53]^pc[53]) &
|
||||
(ps[52]^pc[52]));
|
||||
|
@ -212,13 +217,18 @@ module fsel2 (
|
|||
logic [`DIVLEN+3:0] FP, FN, FZ;
|
||||
|
||||
// Generate for both positive and negative bits
|
||||
assign FP = ~S & C;
|
||||
assign FN = SM | (C & (~C << 2));
|
||||
assign FZ = {(`DIVLEN+4){1'b0}};
|
||||
assign FP = ~(S << 1) & C;
|
||||
assign FN = (SM << 1) | (C & (~C << 2));
|
||||
assign FZ = '0;
|
||||
|
||||
// Choose which adder input will be used
|
||||
|
||||
assign F = sp ? FP : (sn ? FN : FZ);
|
||||
always_comb
|
||||
if (sp) F = FP;
|
||||
else if (sn) F = FN;
|
||||
else F = FZ;
|
||||
|
||||
// assign F = sp ? FP : (sn ? FN : FZ);
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -229,7 +239,7 @@ module otfc2 #(parameter N=66) (
|
|||
input logic clk,
|
||||
input logic Start,
|
||||
input logic qp, qz, qn,
|
||||
output logic [N-3:0] r
|
||||
output logic [N-3:0] Result
|
||||
);
|
||||
// The on-the-fly converter transfers the quotient
|
||||
// bits to the quotient as they come.
|
||||
|
@ -255,7 +265,7 @@ module otfc2 #(parameter N=66) (
|
|||
QMNext = {QMR, 1'b0};
|
||||
end
|
||||
end
|
||||
assign r = Q[N] ? Q[N-1:2] : Q[N-2:1];
|
||||
assign Result = Q[N] ? Q[N-1:2] : Q[N-2:1];
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -266,35 +276,31 @@ module sotfc2(
|
|||
input logic clk,
|
||||
input logic Start,
|
||||
input logic sp, sn,
|
||||
input logic Sqrt,
|
||||
input logic [`DIVLEN+3:0] C,
|
||||
output logic [`DIVLEN-2:0] Sq,
|
||||
output logic [`DIVLEN+3:0] F
|
||||
output logic [`DIVLEN+3:0] S, SM
|
||||
);
|
||||
// The on-the-fly converter transfers the square root
|
||||
// bits to the quotient as they come.
|
||||
// Use this otfc for division and square root.
|
||||
logic [`DIVLEN+3:0] S, SM, SNext, SMNext, SMux;
|
||||
logic [`DIVLEN+3:0] SNext, SMNext, SMux;
|
||||
|
||||
flopr #(`DIVLEN+4) SMreg(clk, Start, SMNext, SM);
|
||||
mux2 #(`DIVLEN+4) Smux(SNext, {4'b0001, {(`DIVLEN){1'b0}}}, Start, SMux);
|
||||
mux2 #(`DIVLEN+4) Smux(SNext, {3'b000, Sqrt, {(`DIVLEN){1'b0}}}, Start, SMux);
|
||||
flop #(`DIVLEN+4) Sreg(clk, SMux, S);
|
||||
|
||||
always_comb begin
|
||||
if (sp) begin
|
||||
SNext = S | ((C << 1) & ~(C << 2));
|
||||
SNext = S | (C & ~(C << 1));
|
||||
SMNext = S;
|
||||
end else if (sn) begin
|
||||
SNext = SM | ((C << 1) & ~(C << 2));
|
||||
SNext = SM | (C & ~(C << 1));
|
||||
SMNext = SM;
|
||||
end else begin // If sp and sn are not true, then sz is
|
||||
SNext = S;
|
||||
SMNext = SM | ((C << 1) & ~(C << 2));
|
||||
SMNext = SM | (C & ~(C << 1));
|
||||
end
|
||||
end
|
||||
assign Sq = S[`DIVLEN] ? S[`DIVLEN-1:1] : S[`DIVLEN-2:0];
|
||||
|
||||
fsel2 fsel(sp, sn, C, S, SM, F);
|
||||
|
||||
endmodule
|
||||
|
||||
//////////////////////////
|
||||
|
@ -302,11 +308,12 @@ endmodule
|
|||
//////////////////////////
|
||||
module creg(input logic clk,
|
||||
input logic Start,
|
||||
input logic Sqrt,
|
||||
output logic [`DIVLEN+3:0] C
|
||||
);
|
||||
logic [`DIVLEN+3:0] CMux;
|
||||
|
||||
mux2 #(`DIVLEN+4) Cmux({1'b1, C[`DIVLEN+3:1]}, {6'b111111, {(`DIVLEN-2){1'b0}}}, Start, CMux);
|
||||
mux2 #(`DIVLEN+4) Cmux({1'b1, C[`DIVLEN+3:1]}, {4'b1111, Sqrt, {(`DIVLEN-1){1'b0}}}, Start, CMux);
|
||||
flop #(`DIVLEN+4) cflop(clk, CMux, C);
|
||||
endmodule
|
||||
|
||||
|
@ -382,22 +389,86 @@ module expcalc(
|
|||
input logic Sqrt,
|
||||
output logic [`NE-1:0] calcExp
|
||||
);
|
||||
logic [`NE-1:0] SExp, DExp, SXExp;
|
||||
assign SXExp = XExp - (`NE)'(`BIAS);
|
||||
assign SExp = {1'b0, SXExp[`NE-1:1]} + (`NE)'(`BIAS);
|
||||
assign DExp = XExp - YExp + (`NE)'(`BIAS);
|
||||
assign calcExp = Sqrt ? SExp : DExp;
|
||||
logic [`NE+1:0] SExp, DExp, SXExp;
|
||||
assign SXExp = {2'b00, XExp} - (`NE+2)'(`BIAS);
|
||||
assign SExp = (SXExp >> 1) + (`NE+2)'(`BIAS);
|
||||
assign DExp = {2'b00, XExp} - {2'b00, YExp} + (`NE+2)'(`BIAS);
|
||||
assign calcExp = Sqrt ? SExp[`NE-1:0] : DExp[`NE-1:0];
|
||||
|
||||
endmodule
|
||||
|
||||
//////////////
|
||||
// signcalc //
|
||||
//////////////
|
||||
module signcalc(
|
||||
input logic XSign, YSign,
|
||||
module srtpostproc(
|
||||
input logic [`DIVLEN+3:0] WS, WC, X, D, S, SM,
|
||||
input logic [$clog2(`XLEN+1)-1:0] dur, zeroCntD,
|
||||
input logic XSign, YSign, Signed, Int, Mod,
|
||||
output logic [`DIVLEN-1:0] Result,
|
||||
output logic calcSign
|
||||
);
|
||||
logic [`DIVLEN+3:0] W, shiftRem, intRem, intS;
|
||||
logic [`DIVLEN-1:0] floatRes, intRes;
|
||||
logic WSign;
|
||||
|
||||
assign W = WS + WC;
|
||||
assign WSign = W[`DIVLEN+3];
|
||||
// Remainder handling
|
||||
always_comb begin
|
||||
if (zeroCntD == ($clog2(`XLEN+1))'(`XLEN)) begin
|
||||
intRem = X;
|
||||
intS = -1;
|
||||
end
|
||||
else if (~Signed) begin
|
||||
if (WSign) begin
|
||||
intRem = W + D;
|
||||
intS = SM;
|
||||
end else begin
|
||||
intRem = W;
|
||||
intS = S;
|
||||
end
|
||||
end
|
||||
else case ({YSign, XSign, WSign})
|
||||
3'b000: begin
|
||||
intRem = W;
|
||||
intS = S;
|
||||
end
|
||||
3'b001: begin
|
||||
intRem = W + D;
|
||||
intS = SM;
|
||||
end
|
||||
3'b010: begin
|
||||
intRem = W - D;
|
||||
intS = ~S;
|
||||
end
|
||||
3'b011: begin
|
||||
intRem = W;
|
||||
intS = ~SM;
|
||||
end
|
||||
3'b100: begin
|
||||
intRem = W;
|
||||
intS = ~SM;
|
||||
end
|
||||
3'b101: begin
|
||||
intRem = W + D;
|
||||
intS = ~SM + 1;
|
||||
end
|
||||
3'b110: begin
|
||||
intRem = W - D;
|
||||
intS = S + 1;
|
||||
end
|
||||
3'b111: begin
|
||||
intRem = W;
|
||||
intS = S;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
assign floatRes = S[`DIVLEN] ? S[`DIVLEN:1] : S[`DIVLEN-1:0];
|
||||
assign intRes = intS[`DIVLEN] ? intS[`DIVLEN:1] : intS[`DIVLEN-1:0];
|
||||
assign shiftRem = (intRem >> (zeroCntD));
|
||||
always_comb begin
|
||||
if (Int) begin
|
||||
if (Mod) Result = shiftRem[`DIVLEN-1:0];
|
||||
else Result = intRes >> (`DIVLEN - dur);
|
||||
end else Result = floatRes;
|
||||
end
|
||||
assign calcSign = XSign ^ YSign;
|
||||
endmodule
|
||||
|
||||
endmodule
|
|
@ -42,24 +42,23 @@ module testbench;
|
|||
logic clk;
|
||||
logic req;
|
||||
logic done;
|
||||
logic Int;
|
||||
logic Int, Sqrt, Mod;
|
||||
logic [`XLEN-1:0] a, b;
|
||||
logic [`NF-1:0] afrac, bfrac;
|
||||
logic [`NE-1:0] aExp, bExp;
|
||||
logic asign, bsign;
|
||||
logic [`NF-1:0] r;
|
||||
logic [`XLEN-1:0] rInt;
|
||||
logic [`DIVLEN-2:0] Quot;
|
||||
logic [`DIVLEN-1:0] Quot;
|
||||
|
||||
// Test parameters
|
||||
parameter MEM_SIZE = 40000;
|
||||
parameter MEM_WIDTH = 64+64+64+64;
|
||||
parameter MEM_WIDTH = 64+64+64;
|
||||
|
||||
// Test sizes
|
||||
`define memrem 63:0
|
||||
`define memr 127:64
|
||||
`define memb 191:128
|
||||
`define mema 255:192
|
||||
`define memr 63:0
|
||||
`define memb 127:64
|
||||
`define mema 191:128
|
||||
|
||||
// Test logicisters
|
||||
logic [MEM_WIDTH-1:0] Tests [0:MEM_SIZE]; // Space for input file
|
||||
|
@ -70,8 +69,9 @@ module testbench;
|
|||
logic rsign;
|
||||
integer testnum, errors;
|
||||
|
||||
// Equip Int test or Sqrt test
|
||||
assign Int = 1'b0;
|
||||
// Equip Int, Sqrt, or IntMod test
|
||||
assign Int = 1'b0;
|
||||
assign Mod = 1'b0;
|
||||
assign Sqrt = 1'b1;
|
||||
|
||||
// Divider
|
||||
|
@ -81,8 +81,8 @@ module testbench;
|
|||
.XSign(asign), .YSign(bsign), .rsign,
|
||||
.SrcXFrac(afrac), .SrcYFrac(bfrac),
|
||||
.SrcA(a), .SrcB(b), .Fmt(2'b00),
|
||||
.W64(1'b1), .Signed(1'b0), .Int, .Sqrt,
|
||||
.Quot, .Rem(), .Flags(), .done);
|
||||
.W64(1'b1), .Signed(1'b0), .Int, .Mod, .Sqrt,
|
||||
.Result(Quot), .Flags(), .done);
|
||||
|
||||
// Counter
|
||||
// counter counter(clk, req, done);
|
||||
|
@ -109,7 +109,7 @@ module testbench;
|
|||
{bsign, bExp, bfrac} = b;
|
||||
nextr = Vec[`memr];
|
||||
r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)];
|
||||
rInt = {1'b1, Quot};
|
||||
rInt = Quot;
|
||||
req <= #5 1;
|
||||
end
|
||||
|
||||
|
@ -117,9 +117,9 @@ module testbench;
|
|||
|
||||
always @(posedge clk) begin
|
||||
r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)];
|
||||
rInt = {1'b1, Quot};
|
||||
rInt = Quot;
|
||||
if (done) begin
|
||||
if (~Int & ~Sqrt) begin
|
||||
if (~Int & ~Sqrt) begin // This test case checks floating point division
|
||||
req <= #5 1;
|
||||
diffp = correctr[51:0] - r;
|
||||
diffn = r - correctr[51:0];
|
||||
|
@ -135,23 +135,21 @@ module testbench;
|
|||
$display("%d Tests completed successfully", testnum);
|
||||
$stop;
|
||||
end
|
||||
end else if (~Sqrt) begin
|
||||
end else if (~Sqrt) begin // This test case works for both integer divide and integer modulo
|
||||
req <= #5 1;
|
||||
diffp = correctr[63:0] - rInt;
|
||||
diffn = rInt - correctr[63:0];
|
||||
if (($signed(diffn) > 1) | ($signed(diffp) > 1) | (diffn === 64'bx) | (diffp === 64'bx)) // check if accurate to 1 ulp
|
||||
if (($signed(diffp) != 0) | (diffp === 64'bx)) // check if accurate to 1 ulp
|
||||
begin
|
||||
errors = errors+1;
|
||||
$display("result was %h, should be %h %h %h\n", rInt, correctr, diffn, diffp);
|
||||
$display("result was %h, should be %h %h\n", rInt, correctr, diffp);
|
||||
$display("failed\n");
|
||||
$stop;
|
||||
end
|
||||
if (afrac === 52'hxxxxxxxxxxxxx)
|
||||
begin
|
||||
$display("%d Tests completed successfully", testnum);
|
||||
$display("%d Tests completed successfully", testnum - errors);
|
||||
$stop;
|
||||
end
|
||||
end else begin
|
||||
end else begin // This test case verifies square root
|
||||
req <= #5 1;
|
||||
diffp = correctr[51:0] - r;
|
||||
diffn = r - correctr[51:0];
|
||||
|
|
|
@ -66,9 +66,9 @@ module testbenchfp;
|
|||
logic [`XLEN-1:0] IntRes, CmpRes; // Results from each unit
|
||||
logic [4:0] FmaFlg, CvtFlg, DivFlg, CmpFlg; // Outputed flags
|
||||
logic AnsNaN, ResNaN, NaNGood;
|
||||
logic XSgn, YSgn, ZSgn; // sign of the inputs
|
||||
logic [`NE-1:0] XExp, YExp, ZExp; // exponent of the inputs
|
||||
logic [`NF:0] XMan, YMan, ZMan; // mantissas of the inputs
|
||||
logic Xs, Ys, Zs; // sign of the inputs
|
||||
logic [`NE-1:0] Xe, Ye, Ze; // exponent of the inputs
|
||||
logic [`NF:0] Xm, Ym, Zm; // mantissas of the inputs
|
||||
logic XNaN, YNaN, ZNaN; // is the input NaN
|
||||
logic XSNaN, YSNaN, ZSNaN; // is the input a signaling NaN
|
||||
logic XDenorm, ZDenorm; // is the input denormalized
|
||||
|
@ -94,10 +94,12 @@ module testbenchfp;
|
|||
|
||||
// in-between FMA signals
|
||||
logic Mult;
|
||||
logic Ss;
|
||||
logic [`NE+1:0] Pe;
|
||||
logic [`NE+1:0] Se;
|
||||
logic ZmSticky;
|
||||
logic KillProd;
|
||||
logic [$clog2(3*`NF+7)-1:0] NCnt;
|
||||
logic [$clog2(3*`NF+7)-1:0] SCnt;
|
||||
logic [3*`NF+5:0] Sm;
|
||||
logic InvA;
|
||||
logic NegSum;
|
||||
|
@ -648,14 +650,14 @@ module testbenchfp;
|
|||
|
||||
// extract the inputs (X, Y, Z, SrcA) and the output (Ans, AnsFlg) from the current test vector
|
||||
readvectors readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]), .VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA,
|
||||
.XSgnE(XSgn), .YSgnE(YSgn), .ZSgnE(ZSgn), .Unit (UnitVal),
|
||||
.XExpE(XExp), .YExpE(YExp), .ZExpE(ZExp), .TestNum, .OpCtrl(OpCtrlVal),
|
||||
.XManE(XMan), .YManE(YMan), .ZManE(ZMan), .DivStart,
|
||||
.XNaNE(XNaN), .YNaNE(YNaN), .ZNaNE(ZNaN),
|
||||
.XSNaNE(XSNaN), .YSNaNE(YSNaN), .ZSNaNE(ZSNaN),
|
||||
.XDenormE(XDenorm), .ZDenormE(ZDenorm),
|
||||
.XZeroE(XZero), .YZeroE(YZero), .ZZeroE(ZZero),
|
||||
.XInfE(XInf), .YInfE(YInf), .ZInfE(ZInf), .XExpMaxE(XExpMax),
|
||||
.Xs, .Ys, .Zs, .Unit(UnitVal),
|
||||
.Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal),
|
||||
.Xm, .Ym, .Zm, .DivStart,
|
||||
.XNaN, .YNaN, .ZNaN,
|
||||
.XSNaN, .YSNaN, .ZSNaN,
|
||||
.XDenorm, .ZDenorm,
|
||||
.XZero, .YZero, .ZZero,
|
||||
.XInf, .YInf, .ZInf, .XExpMax,
|
||||
.X, .Y, .Z);
|
||||
|
||||
|
||||
|
@ -671,34 +673,34 @@ module testbenchfp;
|
|||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// instantiate devices under test
|
||||
fma fma(.Xs(XSgn), .Ys(YSgn), .Zs(ZSgn),
|
||||
.Xe(XExp), .Ye(YExp), .Ze(ZExp),
|
||||
.Xm(XMan), .Ym(YMan), .Zm(ZMan),
|
||||
.XZero, .YZero, .ZZero,
|
||||
.FOpCtrl(OpCtrlVal), .Fmt(ModFmt), .Sm, .NegSum, .InvA, .NCnt, .As, .Ps,
|
||||
fma fma(.Xs(Xs), .Ys(Ys), .Zs(Zs),
|
||||
.Xe(Xe), .Ye(Ye), .Ze(Ze),
|
||||
.Xm(Xm), .Ym(Ym), .Zm(Zm),
|
||||
.XZero, .YZero, .ZZero, .Ss, .Se,
|
||||
.OpCtrl(OpCtrlVal), .Fmt(ModFmt), .Sm, .NegSum, .InvA, .SCnt, .As, .Ps,
|
||||
.Pe, .ZmSticky, .KillProd);
|
||||
|
||||
postprocess postprocess(.Xs(XSgn), .Ys(YSgn), .PostProcSel(UnitVal[1:0]),
|
||||
.Ze(ZExp), .ZDenorm(ZDenorm), .FOpCtrl(OpCtrlVal), .DivQm(Quot), .DivQe(DivCalcExp),
|
||||
.Xm(XMan), .Ym(YMan), .Zm(ZMan), .CvtCe(CvtCalcExpE), .DivS(DivSticky),
|
||||
postprocess postprocess(.Xs(Xs), .Ys(Ys), .PostProcSel(UnitVal[1:0]),
|
||||
.Ze(Ze), .ZDenorm(ZDenorm), .OpCtrl(OpCtrlVal), .DivQm(Quot), .DivQe(DivCalcExp),
|
||||
.Xm(Xm), .Ym(Ym), .Zm(Zm), .CvtCe(CvtCalcExpE), .DivS(DivSticky), .FmaSs(Ss),
|
||||
.XNaN(XNaN), .YNaN(YNaN), .ZNaN(ZNaN), .CvtResDenormUf(CvtResDenormUfE),
|
||||
.XZero(XZero), .YZero(YZero), .ZZero(ZZero), .CvtShiftAmt(CvtShiftAmtE),
|
||||
.XInf(XInf), .YInf(YInf), .ZInf(ZInf), .CvtCs(CvtResSgnE), .ToInt(WriteIntVal),
|
||||
.XSNaN(XSNaN), .YSNaN(YSNaN), .ZSNaN(ZSNaN), .CvtLzcIn(CvtLzcInE), .IntZero,
|
||||
.FmaKillProd(KillProd), .FmaZmS(ZmSticky), .FmaPe(Pe), .DivDone,
|
||||
.FmaSm(Sm), .FmaNegSum(NegSum), .FmaInvA(InvA), .FmaNCnt(NCnt), .DivEarlyTermShift(EarlyTermShift), .FmaAs(As), .FmaPs(Ps), .Fmt(ModFmt), .Frm(FrmVal),
|
||||
.FmaKillProd(KillProd), .FmaZmS(ZmSticky), .FmaPe(Pe), .DivDone, .FmaSe(Se),
|
||||
.FmaSm(Sm), .FmaNegSum(NegSum), .FmaInvA(InvA), .FmaSCnt(SCnt), .DivEarlyTermShift(EarlyTermShift), .FmaAs(As), .FmaPs(Ps), .Fmt(ModFmt), .Frm(FrmVal),
|
||||
.PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes));
|
||||
|
||||
fcvt fcvt (.Xs(XSgn), .Xe(XExp), .Xm(XMan), .Int(SrcA), .ToInt(WriteIntVal),
|
||||
.XZero(XZero), .XDenorm(XDenorm), .FOpCtrl(OpCtrlVal), .IntZero,
|
||||
fcvt fcvt (.Xs(Xs), .Xe(Xe), .Xm(Xm), .Int(SrcA), .ToInt(WriteIntVal),
|
||||
.XZero(XZero), .XDenorm(XDenorm), .OpCtrl(OpCtrlVal), .IntZero,
|
||||
.Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), .ResDenormUf(CvtResDenormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE));
|
||||
fcmp fcmp (.FmtE(ModFmt), .FOpCtrlE(OpCtrlVal), .XSgnE(XSgn), .YSgnE(YSgn), .XExpE(XExp), .YExpE(YExp),
|
||||
.XManE(XMan), .YManE(YMan), .XZeroE(XZero), .YZeroE(YZero), .CmpIntResE(CmpRes),
|
||||
.XNaNE(XNaN), .YNaNE(YNaN), .XSNaNE(XSNaN), .YSNaNE(YSNaN), .FSrcXE(X), .FSrcYE(Y), .CmpNVE(CmpFlg[4]), .CmpFpResE(FpCmpRes));
|
||||
divsqrt divsqrt(.clk, .reset, .FmtE(ModFmt), .XManE(XMan), .YManE(YMan), .XExpE(XExp), .YExpE(YExp),
|
||||
fcmp fcmp (.Fmt(ModFmt), .OpCtrl(OpCtrlVal), .Xs, .Ys, .Xe, .Ye,
|
||||
.Xm, .Ym, .XZero, .YZero, .CmpIntRes(CmpRes),
|
||||
.XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes));
|
||||
divsqrt divsqrt(.clk, .reset, .FmtE(ModFmt), .XmE(Xm), .YmE(Ym), .XeE(Xe), .YeE(Ye), .SqrtE(1'b0), .SqrtM(1'b0),
|
||||
.XInfE(XInf), .YInfE(YInf), .XZeroE(XZero), .YZeroE(YZero), .XNaNE(XNaN), .YNaNE(YNaN), .DivStartE(DivStart),
|
||||
.StallE(1'b0), .StallM(1'b0), .DivStickyM(DivSticky), .DivBusy, .DivCalcExpM(DivCalcExp),
|
||||
.EarlyTermShiftM(EarlyTermShift), .QuotM(Quot), .DivDone);
|
||||
.StallE(1'b0), .StallM(1'b0), .DivSM(DivSticky), .DivBusy, .QeM(DivCalcExp),
|
||||
.EarlyTermShiftM(EarlyTermShift), .QmM(Quot), .DivDone);
|
||||
|
||||
assign CmpFlg[3:0] = 0;
|
||||
|
||||
|
@ -866,10 +868,10 @@ end
|
|||
|
||||
// Testfloat outputs 800... for both the largest integer values for both positive and negitive numbers but
|
||||
// the riscv spec specifies 2^31-1 for positive values out of range and NaNs ie 7fff...
|
||||
else if ((UnitVal === `CVTINTUNIT) & ~(((WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&XSgn&(Res[`XLEN-1:0] === (`XLEN)'(0))) |
|
||||
(WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~XSgn|XNaN)&OpCtrlVal[1]&(Res[`XLEN-1:0] === {1'b0, {`XLEN-1{1'b1}}})) |
|
||||
(WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~XSgn|XNaN)&~OpCtrlVal[1]&(Res[`XLEN-1:0] === {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}})) |
|
||||
(~(WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&XSgn&~XNaN)&(Res === Ans | NaNGood | NaNGood === 1'bx))) & (ResFlg === AnsFlg | AnsFlg === 5'bx))) begin
|
||||
else if ((UnitVal === `CVTINTUNIT) & ~(((WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&Xs&(Res[`XLEN-1:0] === (`XLEN)'(0))) |
|
||||
(WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~Xs|XNaN)&OpCtrlVal[1]&(Res[`XLEN-1:0] === {1'b0, {`XLEN-1{1'b1}}})) |
|
||||
(WriteIntVal&OpCtrlVal[0]&AnsFlg[4]&(~Xs|XNaN)&~OpCtrlVal[1]&(Res[`XLEN-1:0] === {{`XLEN-32{1'b0}}, 1'b0, {31{1'b1}}})) |
|
||||
(~(WriteIntVal&~OpCtrlVal[0]&AnsFlg[4]&Xs&~XNaN)&(Res === Ans | NaNGood | NaNGood === 1'bx))) & (ResFlg === AnsFlg | AnsFlg === 5'bx))) begin
|
||||
errors += 1;
|
||||
$display("There is an error in %s", Tests[TestNum]);
|
||||
$display("inputs: %h %h %h\nSrcA: %h\n Res: %h %h\n Ans: %h %h", X, Y, Z, SrcA, Res, ResFlg, Ans, AnsFlg);
|
||||
|
@ -922,18 +924,19 @@ module readvectors (
|
|||
output logic [`FLEN-1:0] Ans,
|
||||
output logic [`XLEN-1:0] SrcA,
|
||||
output logic [4:0] AnsFlg,
|
||||
output logic XSgnE, YSgnE, ZSgnE, // sign bits of XYZ
|
||||
output logic [`NE-1:0] XExpE, YExpE, ZExpE, // exponents of XYZ (converted to largest supported precision)
|
||||
output logic [`NF:0] XManE, YManE, ZManE, // mantissas of XYZ (converted to largest supported precision)
|
||||
output logic XNaNE, YNaNE, ZNaNE, // is XYZ a NaN
|
||||
output logic XSNaNE, YSNaNE, ZSNaNE, // is XYZ a signaling NaN
|
||||
output logic XDenormE, ZDenormE, // is XYZ denormalized
|
||||
output logic XZeroE, YZeroE, ZZeroE, // is XYZ zero
|
||||
output logic XInfE, YInfE, ZInfE, // is XYZ infinity
|
||||
output logic XExpMaxE,
|
||||
output logic Xs, Ys, Zs, // sign bits of XYZ
|
||||
output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
|
||||
output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
|
||||
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
|
||||
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
|
||||
output logic XDenorm, ZDenorm, // is XYZ denormalized
|
||||
output logic XZero, YZero, ZZero, // is XYZ zero
|
||||
output logic XInf, YInf, ZInf, // is XYZ infinity
|
||||
output logic XExpMax,
|
||||
output logic DivStart,
|
||||
output logic [`FLEN-1:0] X, Y, Z
|
||||
);
|
||||
logic XEn, YEn, ZEn;
|
||||
|
||||
// apply test vectors on rising edge of clk
|
||||
// Format of vectors Inputs(1/2/3)_AnsFlg
|
||||
|
@ -1255,8 +1258,12 @@ module readvectors (
|
|||
endcase
|
||||
end
|
||||
|
||||
unpack unpack(.X, .Y, .Z, .FmtE(ModFmt), .XSgnE, .YSgnE, .ZSgnE, .XExpE, .YExpE, .ZExpE,
|
||||
.XManE, .YManE, .ZManE, .XNaNE, .YNaNE, .ZNaNE, .XSNaNE, .YSNaNE, .ZSNaNE,
|
||||
.XDenormE, .ZDenormE, .XZeroE, .YZeroE, .ZZeroE, .XInfE, .YInfE, .ZInfE,
|
||||
.XExpMaxE);
|
||||
assign XEn = ~((Unit == `CVTINTUNIT)&OpCtrl[2]);
|
||||
assign YEn = ~((Unit == `CVTINTUNIT)|(Unit == `CVTFPUNIT));
|
||||
assign ZEn = (Unit == `FMAUNIT);
|
||||
|
||||
unpack unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze,
|
||||
.Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN,
|
||||
.XDenorm, .ZDenorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf,
|
||||
.XEn, .YEn, .ZEn, .XExpMax);
|
||||
endmodule
|
File diff suppressed because it is too large
Load diff
|
@ -17,13 +17,20 @@ root:
|
|||
mkdir -p $(wally_workdir)
|
||||
sed 's,{0},$(current_dir),g;s,{1},$(XLEN)$(if $(findstring 64,$(XLEN)),gc,imc),g' config.ini > config$(XLEN).ini
|
||||
|
||||
build_arch:
|
||||
fsd_fld_tempfix:
|
||||
# this is a temporary fix, there's a typo on the rv64i_m/D/src/d_fsd-align-01.S and rv64i_m/D/src/d_fld-align-01.S tests
|
||||
# https://github.com/riscv-non-isa/riscv-arch-test/issues/266
|
||||
find ../../addins/riscv-arch-test/riscv-test-suite -type f -name "*d_fld-align*.S" | xargs -I{} sed -i 's,regex(\.\*32\.\*),regex(\.\*64\.\*),g' {}
|
||||
find ../../addins/riscv-arch-test/riscv-test-suite -type f -name "*d_fsd-align*.S" | xargs -I{} sed -i 's,regex(\.\*32\.\*),regex(\.\*64\.\*),g' {}
|
||||
|
||||
build_arch: fsd_fld_tempfix
|
||||
riscof run --work-dir=$(work_dir) --config=config$(XLEN).ini --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env --no-browser
|
||||
rm -rf $(arch_workdir)/rv$(XLEN)i_m
|
||||
mv -f $(work_dir)/rv$(XLEN)i_m $(arch_workdir)/
|
||||
rsync -a $(work_dir)/rv32i_m/ $(arch_workdir)/rv$(XLEN)i_m/ || echo "error suppressed"
|
||||
rsync -a $(work_dir)/rv64i_m/ $(arch_workdir)/rv$(XLEN)i_m/ || echo "error suppressed"
|
||||
|
||||
build_wally:
|
||||
riscof --verbose debug run --work-dir=$(work_dir) --config=config$(XLEN).ini --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run
|
||||
riscof --verbose debug run --work-dir=$(work_dir) --config=config$(XLEN).ini --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run 2>&1 | tee log.txt
|
||||
rm -rf $(wally_workdir)/rv$(XLEN)i_m
|
||||
mv -f $(work_dir)/rv$(XLEN)i_m $(wally_workdir)/
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ class sail_cSim(pluginTemplate):
|
|||
|
||||
execute = "@cd "+testentry['work_dir']+";"
|
||||
|
||||
cmd = self.compile_cmd.format(testentry['isa'].lower(), self.xlen) + ' ' + test + ' -o ' + elf
|
||||
cmd = self.compile_cmd.format(testentry['isa'].lower().replace('zicsr', ' ', 1), self.xlen) + ' ' + test + ' -o ' + elf
|
||||
compile_cmd = cmd + ' -D' + " -D".join(testentry['macros'])
|
||||
execute+=compile_cmd+";"
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ class spike(pluginTemplate):
|
|||
|
||||
# substitute all variables in the compile command that we created in the initialize
|
||||
# function
|
||||
cmd = self.compile_cmd.format(testentry['isa'].lower(), self.xlen, test, elf, compile_macros)
|
||||
cmd = self.compile_cmd.format(testentry['isa'].lower().replace('zicsr', ' ', 2), self.xlen, test, elf, compile_macros)
|
||||
|
||||
# if the user wants to disable running the tests and only compile the tests, then
|
||||
# the "else" clause is executed below assigning the sim command to simple no action
|
||||
|
|
|
@ -55,6 +55,8 @@ target_tests_nosim = \
|
|||
WALLY-status-tw-01 \
|
||||
WALLY-gpio-01 \
|
||||
WALLY-clint-01 \
|
||||
WALLY-plic-01 \
|
||||
WALLY-uart-01 \
|
||||
|
||||
|
||||
rv32i_tests = $(addsuffix .elf, $(rv32i_sc_tests))
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
00000000 # read empty MIP (1.0.0)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000000 # Claim gives no interrupt due to zero priority
|
||||
00000008 # interrupt still pending due to no claim
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set due to PLIC priority (1.0.1)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (1.0.2)
|
||||
00000000 # check GPIO interrupt pending on intPending0
|
||||
00000000 # claim gives no interrupt due to no intPending
|
||||
00000000 # no interrupts pending after clear
|
||||
00000000 # still no interrupts after clear
|
||||
00000000 # read empty MIP (1.1.0)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # Claim gives 3 for ID of GPIO
|
||||
00000000 # interrupt still pending due to no claim
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set due to PLIC priority (1.1.1)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (1.2.0)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # Claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set due to PLIC priority (1.2.1)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (1.3.0)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # Claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set due to PLIC priority (1.3.1)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (1.4.0)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # Claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set due to PLIC priority (1.4.1)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (1.5.0)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # Claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set due to PLIC priority (1.5.1)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (1.6.0)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # Claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set due to PLIC priority (1.6.1)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (1.7.0)
|
||||
00000008 # check GPIO interrupt pending on intPending0
|
||||
00000003 # Claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set (2.0)
|
||||
00000408 # gpio and uart pending
|
||||
00000003 # claim gpio
|
||||
00000400 # gpio no longer pending
|
||||
00000000 # no interrupts pending
|
||||
00000800 # MEIP set (2.1)
|
||||
00000408 # gpio and uart pending
|
||||
00000003 # claim gpio
|
||||
00000400 # gpio no longer pending
|
||||
00000000 # no interrupts pending
|
||||
00000800 # MEIP set (2.2)
|
||||
00000408 # gpio and uart pending
|
||||
0000000A # claim uart
|
||||
00000008 # uart no longer pending
|
||||
00000000 # no interrupts pending
|
||||
00000800 # MEIP set (2.3)
|
||||
00000408 # gpio and uart pending
|
||||
0000000A # claim uart
|
||||
00000008 # uart no longer pending
|
||||
00000000 # no interrupts pending
|
||||
00000000 # MEIP empty (2.4)
|
||||
00000408 # gpio and uart pending
|
||||
0000000A # claim none
|
||||
00000008 # gpio and uart still pending
|
||||
00000000 # no interrupts pending
|
||||
00000A00 # MEIP and SEIP set (3.0)
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000400 # check GPIO interrupt pending cleared after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # SEIP set (3.1)
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000400 # check GPIO interrupt pending cleared after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # SEIP set (3.2)
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
0000000A # claim UART
|
||||
00000008 # GPIO interrupt pending after UART claimcomp
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (3.3)
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
0000000A # claim UART
|
||||
00000008 # check UART interrupt pending cleared after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000A00 # MEIP and SEIP set (4.0)
|
||||
00000400 # UART interrupt pending
|
||||
0000000A # claim UART
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # SEIP set (4.1)
|
||||
00000400 # UART interrupt pending
|
||||
00000000 # nothing in claim register
|
||||
00000400 # UART interrupt pending
|
||||
00000000 # check no interrupts pending
|
||||
00000A00 # MEIP and SEIP set (4.2)
|
||||
00000400 # UART interrupt pending
|
||||
0000000A # claim UART
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set (4.3)
|
||||
00000400 # UART interrupt pending
|
||||
0000000A # claim UART
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set (4.4)
|
||||
00000400 # UART interrupt pending
|
||||
0000000A # claim UART
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # SEIP set (4.5)
|
||||
00000400 # UART interrupt pending
|
||||
00000000 # nothing in claim register
|
||||
00000400 # UART interrupt pending
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # All disabled (4.6)
|
||||
00000400 # UART interrupt pending
|
||||
00000000 # nothing in claim register
|
||||
00000400 # UART interrupt pending
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # SEIP set (5.0)
|
||||
00000008 # GPIO interrupt pending
|
||||
00000000 # nothing in claim register
|
||||
00000008 # GPIO interrupt pending
|
||||
00000000 # check no interrupts pending
|
||||
00000A00 # MEIP and SEIP set (5.1)
|
||||
00000008 # GPIO interrupt pending
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set (5.2)
|
||||
00000008 # GPIO interrupt pending
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000A00 # MEIP and SEIP set (5.3)
|
||||
00000008 # GPIO interrupt pending
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set (5.4)
|
||||
00000008 # GPIO interrupt pending
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # SEIP set (5.5)
|
||||
00000008 # GPIO interrupt pending
|
||||
00000000 # nothing in claim register
|
||||
00000008 # GPIO interrupt pending
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read empty MIP (5.6)
|
||||
00000008 # GPIO interrupt pending
|
||||
00000000 # nothing in claim register
|
||||
00000008 # GPIO interrupt pending
|
||||
00000000 # check no interrupts pending
|
||||
0000000b # written due to goto_s_mode
|
||||
00000200 # read sip (7.0)
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000400 # check GPIO interrupt pending cleared after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # read sip (7.1)
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000400 # check GPIO interrupt pending cleared after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # read sip (7.2)
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
0000000A # claim UART
|
||||
00000008 # GPIO interrupt pending after UART claimcomp
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # read sip (7.3)
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000400 # check GPIO interrupt pending cleared after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read sip
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000000 # nothing in claim register
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000000 # check no interrupts pending
|
||||
00000200 # read sip
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000400 # check GPIO interrupt pending cleared after claim
|
||||
00000000 # check no interrupts pending
|
||||
00000000 # read sip
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000000 # nothing in claim register
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
00000000 # check no interrupts pending
|
||||
00000009 # output from ecall in supervisor mode
|
||||
00000800 # MEIP set
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
0000000A # claim UART
|
||||
00000008 # GPIO interrupt pending after UART claimcomp
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # read empty MIP # no interrupts, meip is low
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set
|
||||
00000008 # GPIO interrupt pending after complete
|
||||
00000003 # claim gives 3 for ID of GPIO
|
||||
00000000 # read empty MIP # meip is zeroed
|
||||
00000000 # check no interrupts pending
|
||||
00000800 # MEIP set
|
||||
00000400 # check GPIO interrupt pending cleared after claim
|
||||
00000800 # MEIP set
|
||||
00000408 # check GPIO and UART interrupt pending on intPending0
|
||||
0000000A # claim UART
|
|
@ -0,0 +1,33 @@
|
|||
00000000 # Reset tests
|
||||
00000001 # 00000000 *** commented because LCR should reset to zero but resets to 3 due to the FPGA
|
||||
00000000
|
||||
00000060
|
||||
00000000
|
||||
00000060 # read-write test
|
||||
00000020 # transmitter register empty but shift register not
|
||||
00000101 # transmitter is not empty when done transmitting 5 bits
|
||||
00000000
|
||||
00000060
|
||||
00000101 # Multi-bit transmission: 5 bits
|
||||
00000015
|
||||
00000101 # Transmit 6 bits
|
||||
0000002A
|
||||
00000101 # Transmit 7 bits
|
||||
0000007F
|
||||
00000101 # Transmit 8 bits
|
||||
00000080
|
||||
00000002 # Transmission interrupt tests
|
||||
00000401 # Interrupt generated by finished transmission
|
||||
00000004
|
||||
00000006 # IIR return LSR intr and LSR has an overflow error
|
||||
00000063
|
||||
00000004
|
||||
00000001
|
||||
00000001 # MODEM interrupt tests
|
||||
00000000
|
||||
00000011
|
||||
00000001
|
||||
|
||||
|
||||
|
||||
0000000b # ecall from test termination
|
|
@ -965,6 +965,17 @@ read08_test:
|
|||
// address to read in t3, expected 8 bit value in t4 (unused, but there for your perusal).
|
||||
li t2, 0xBAD // bad value that will be overwritten on good reads.
|
||||
lb t2, 0(t3)
|
||||
andi t2, t2, 0xFF // mask to lower 8 bits
|
||||
sw t2, 0(t1)
|
||||
addi t1, t1, 4
|
||||
addi a6, a6, 4
|
||||
j test_loop // go to next test case
|
||||
|
||||
read04_test:
|
||||
// address to read in t3, expected 8 bit value in t4 (unused, but there for your perusal).
|
||||
li t2, 0xBAD // bad value that will be overwritten on good reads.
|
||||
lb t2, 0(t3)
|
||||
andi t2, t2, 15 // mask lower 4 bits
|
||||
sw t2, 0(t1)
|
||||
addi t1, t1, 4
|
||||
addi a6, a6, 4
|
||||
|
@ -984,6 +995,103 @@ readsip_test: // read the MIP into the signature
|
|||
addi a6, a6, 4
|
||||
j test_loop // go to next test case
|
||||
|
||||
claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||
li t2, 0x0C00000C // GPIO priority
|
||||
li t3, 7
|
||||
lw t4, 0(t2)
|
||||
sw t3, 0(t2)
|
||||
sw t4, -4(sp)
|
||||
addi sp, sp, -4
|
||||
li t2, 0x0C000028 // UART 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
|
||||
lw t6, 0(t2) // save current enable status
|
||||
sw t4, 0(t2) // enable all relevant interrupts on PLIC
|
||||
lw t5, 0(t3) // make PLIC claim
|
||||
sw t5, 0(t3) // complete claim made
|
||||
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)
|
||||
j test_loop
|
||||
|
||||
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||
li t2, 0x0C00000C // GPIO priority
|
||||
li t3, 7
|
||||
lw t4, 0(t2)
|
||||
sw t3, 0(t2)
|
||||
sw t4, -4(sp)
|
||||
addi sp, sp, -4
|
||||
li t2, 0x0C000028 // UART priority
|
||||
li t3, 7
|
||||
lw t4, 0(t2)
|
||||
sw t3, 0(t2)
|
||||
sw t4, -4(sp)
|
||||
addi sp, sp, -4
|
||||
li t2, 0x0C002080
|
||||
li t3, 0x0C201004
|
||||
li t4, 0xFFF
|
||||
lw t6, 0(t2) // save current enable status
|
||||
sw t4, 0(t2) // enable all relevant interrupts on PLIC
|
||||
lw t5, 0(t3) // make PLIC claim
|
||||
sw t5, 0(t3) // complete claim made
|
||||
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)
|
||||
j test_loop
|
||||
|
||||
uart_lsr_intr_wait: // waits for interrupts to be ready
|
||||
li t2, 0x10000002 // IIR
|
||||
li t4, 0x6
|
||||
uart_lsr_intr_loop:
|
||||
lb t3, 0(t2)
|
||||
andi t3, t3, 0x7
|
||||
bne t3, t4, uart_lsr_intr_loop
|
||||
sw t3, 0(t1)
|
||||
addi t1, t1, 4
|
||||
addi a6, a6, 4
|
||||
j test_loop
|
||||
|
||||
uart_data_wait:
|
||||
li t2, 0x10000005 // LSR
|
||||
li t3, 0x10000002 // IIR
|
||||
li a4, 0x61
|
||||
uart_read_LSR_IIR:
|
||||
lb t4, 0(t3) // save IIR before potential clear
|
||||
lb t5, 0(t2)
|
||||
andi t6, t5, 0x61 // only care if all transmissions are done
|
||||
bne a4, t6, uart_read_LSR_IIR
|
||||
|
||||
uart_data_ready:
|
||||
li t2, 0
|
||||
sw t2, 0(t1) // clear entry deadbeef from memory
|
||||
andi t5, t5, 0x9F // mask THRE and TEMT from signature
|
||||
sb t4, 1(t1) // IIR
|
||||
sb t5, 0(t1) // LSR
|
||||
addi t1, t1, 4
|
||||
addi a6, a6, 4
|
||||
j test_loop
|
||||
|
||||
uart_clearmodemintr:
|
||||
li t2, 0x10000006
|
||||
lb t2, 0(t2)
|
||||
j test_loop
|
||||
|
||||
goto_s_mode:
|
||||
// return to address in t3,
|
||||
li a0, 3 // Trap handler behavior (go to supervisor mode)
|
||||
|
|
|
@ -143,18 +143,22 @@ SETUP_PLIC
|
|||
.4byte high_ie, 0x00020000, write32_test # enable high interrupt on bit 17, which is pending
|
||||
.4byte 0x0, 0x00000800, readmip_test # MEIP should be raised
|
||||
.4byte high_ie, 0x00000000, write32_test # disable high interrupt on bit 17
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear PLIC pending interrupts
|
||||
.4byte 0x0, 0x00000000, readmip_test # MEIP should be released
|
||||
.4byte low_ie, 0x00010000, write32_test # enable low interrupt on bit 16, which is pending
|
||||
.4byte 0x0, 0x00000800, readmip_test # MEIP should be raised
|
||||
.4byte low_ie, 0x00000000, write32_test # disable low interrupt on bit 16
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear PLIC pending interrupts
|
||||
.4byte 0x0, 0x00000000, readmip_test # MEIP should be released
|
||||
.4byte rise_ie, 0x00200000, write32_test # enable rise interrupt on bit 21, which is pending
|
||||
.4byte 0x0, 0x00000800, readmip_test # MEIP should be raised
|
||||
.4byte rise_ie, 0x00000000, write32_test # disable rise interrupt on bit 21, which is pending
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear PLIC pending interrupts
|
||||
.4byte 0x0, 0x00000000, readmip_test # MEIP should be released
|
||||
.4byte fall_ie, 0x01000000, write32_test # enable high interrupt on bit 24, which is pending
|
||||
.4byte 0x0, 0x00000800, readmip_test # MEIP should be raised
|
||||
.4byte fall_ie, 0x00000000, write32_test # disable high interrupt on bit 24, which is pending
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear PLIC pending interrupts
|
||||
.4byte 0x0, 0x00000000, readmip_test # MEIP should be released
|
||||
|
||||
.4byte 0x0, 0x0, terminate_test # terminate tests
|
||||
|
|
|
@ -0,0 +1,951 @@
|
|||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-plic
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Nicholas Lucio <nlucio@hmc.edu>
|
||||
//
|
||||
// Created 2022-06-16
|
||||
//
|
||||
// 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"
|
||||
|
||||
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
|
||||
#
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
# =========== Define PLIC registers ===========
|
||||
|
||||
.equ PLIC, 0x0C000000
|
||||
.equ PLIC_INTPRI_GPIO, (PLIC+0x00000C) # GPIO is interrupt 3
|
||||
.equ PLIC_INTPRI_UART, (PLIC+0x000028) # UART is interrupt 10
|
||||
.equ PLIC_INTPENDING0, (PLIC+0x001000) # intPending0 register
|
||||
.equ PLIC_INTEN00, (PLIC+0x002000) # interrupt enables for context 0 (machine mode) sources 31:1
|
||||
.equ PLIC_INTEN10, (PLIC+0x002080) # interrupt enables for context 1 (supervisor mode) sources 31:1
|
||||
.equ PLIC_THRESH0, (PLIC+0x200000) # Priority threshold for context 0 (machine mode)
|
||||
.equ PLIC_CLAIM0, (PLIC+0x200004) # Claim/Complete register for context 0
|
||||
.equ PLIC_THRESH1, (PLIC+0x201000) # Priority threshold for context 1 (supervisor mode)
|
||||
.equ PLIC_CLAIM1, (PLIC+0x201004) # Claim/Complete register for context 1
|
||||
|
||||
# =========== Define GPIO registers ===========
|
||||
|
||||
.equ GPIO, 0x10060000
|
||||
.equ input_val, (GPIO+0x00)
|
||||
.equ input_en, (GPIO+0x04)
|
||||
.equ output_en, (GPIO+0x08)
|
||||
.equ output_val, (GPIO+0x0C)
|
||||
.equ rise_ie, (GPIO+0x18)
|
||||
.equ rise_ip, (GPIO+0x1C)
|
||||
.equ fall_ie, (GPIO+0x20)
|
||||
.equ fall_ip, (GPIO+0x24)
|
||||
.equ high_ie, (GPIO+0x28)
|
||||
.equ high_ip, (GPIO+0x2C)
|
||||
.equ low_ie, (GPIO+0x30)
|
||||
.equ low_ip, (GPIO+0x34)
|
||||
.equ iof_en, (GPIO+0x38)
|
||||
.equ iof_sel, (GPIO+0x3C)
|
||||
.equ out_xor, (GPIO+0x40)
|
||||
|
||||
# =========== Define UART registers ===========
|
||||
|
||||
.equ UART, 0x10000000
|
||||
.equ UART_IER, (UART+0x01)
|
||||
.equ UART_MCR, (UART+0x04)
|
||||
.equ UART_MSR, (UART+0x06)
|
||||
|
||||
# =========== Initialize UART and GPIO ===========
|
||||
|
||||
# GPIO Initialization
|
||||
.4byte input_en, 0x00000001, write32_test # enable bit 0 of input_en
|
||||
.4byte output_en, 0x00000001, write32_test # enable bit 0 of output_en
|
||||
.4byte output_val, 0x00000000, write32_test # make sure output_val is 0
|
||||
.4byte rise_ie, 0x00000001, write32_test # enable rise interrupts
|
||||
|
||||
# =========== Initialize relevant PLIC registers ===========
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000000, write32_test # set GPIO priority to zero
|
||||
.4byte PLIC_INTPRI_UART, 0x00000000, write32_test # set UART priority to zero
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable s-mode interrupts
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
.4byte PLIC_THRESH1, 0x00000007, write32_test # set s-mode threshold to max
|
||||
|
||||
# =========== Machine-Mode Priority Testing (1.T.X) ===========
|
||||
|
||||
# Test 1.0.0: GPIO int lacks priority (0 = 0)
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.0.1: GPIO int has priority (1 > 0)
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # let GPIO cause interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.0.2: meip and c/c clear without interrupt pending
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # expect no interrupt pending
|
||||
.4byte PLIC_CLAIM0, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.1.0: GPIO lacks priority (1 = 1)
|
||||
.4byte PLIC_THRESH0, 0x00000001, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim from earlier
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.1.1: GPIO int has priority (2 > 1)
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000002, write32_test # let GPIO cause interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.2.0: GPIO int lacks priority (2 = 2)
|
||||
.4byte PLIC_THRESH0, 0x00000002, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim from earlier
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.2.1: GPIO int has priority (3 > 2)
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000003, write32_test # let GPIO cause interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.3.0: GPIO int lacks priority (3 = 3)
|
||||
.4byte PLIC_THRESH0, 0x00000003, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim from earlier
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.3.1: GPIO int has priority (4 > 3)
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000004, write32_test # let GPIO cause interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.4.0: GPIO int lacks priority (4 = 4)
|
||||
.4byte PLIC_THRESH0, 0x00000004, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim from earlier
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.4.1: GPIO int has priority (5 > 4)
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000005, write32_test # let GPIO cause interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.5.0: GPIO int lacks priority (5 = 5)
|
||||
.4byte PLIC_THRESH0, 0x00000005, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim from earlier
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.5.1: GPIO int has priority (6 > 5)
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000006, write32_test # let GPIO cause interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.6.0: GPIO int lacks priority (6 = 6)
|
||||
.4byte PLIC_THRESH0, 0x00000006, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim from earlier
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.6.1: GPIO int has priority (7 > 6)
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000007, write32_test # let GPIO cause interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# Test 1.7.0: GPIO int lacks priority (7 = 7)
|
||||
.4byte PLIC_THRESH0, 0x00000007, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim from earlier
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
|
||||
# =========== UART vs GPIO priority (2.X) ===========
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable s-mode interrupts
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
.4byte PLIC_THRESH1, 0x00000007, write32_test # set s-mode threshold to max
|
||||
# UART Initialization
|
||||
.4byte UART_IER, 0x08, write08_test # enable modem status interrupts from CTS
|
||||
.4byte UART_MCR, 0x10, write08_test # enable loopback mode, RTS = 0
|
||||
.4byte UART_MSR, 0x00, write08_test # disable UART interrupt
|
||||
|
||||
# Test 2.0: GPIO Priority = UART Priority
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # GPIOPriority = 1
|
||||
.4byte PLIC_INTPRI_UART, 0x00000001, write32_test # UARTPriority = 1
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 2.1: GPIO Priority > UART Priority
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000003, write32_test # GPIOPriority = 3
|
||||
.4byte PLIC_INTPRI_UART, 0x00000002, write32_test # UARTPriority = 2
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 2.2: GPIO Priority < UART Priority
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000004, write32_test # GPIOPriority = 4
|
||||
.4byte PLIC_INTPRI_UART, 0x00000005, write32_test # UARTPriority = 5
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending cleared for UART
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 2.3: GPIO Priority < UART Priority
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000006, write32_test # GPIOPriority = 6
|
||||
.4byte PLIC_INTPRI_UART, 0x00000007, write32_test # UARTPriority = 7
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending cleared for UART
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 2.4: Interrupts don't have enough priority
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000004, write32_test # GPIOPriority = 4
|
||||
.4byte PLIC_INTPRI_UART, 0x00000005, write32_test # UARTPriority = 5
|
||||
.4byte PLIC_THRESH0, 0x00000006, write32_test # set m-mode threshold to 6
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# =========== SEIP tests (3.X) ===========
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable s-mode interrupts
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
.4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
|
||||
# Test 3.0: Cause machine and supervisor interrupts
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # GPIOPriority = 1
|
||||
.4byte PLIC_INTPRI_UART, 0x00000001, write32_test # UARTPriority = 1
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
.4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000A00, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 3.1: Suppress machine mode interrupts
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000003, write32_test # GPIOPriority = 3
|
||||
.4byte PLIC_INTPRI_UART, 0x00000002, write32_test # UARTPriority = 2
|
||||
.4byte PLIC_THRESH0, 0x00000007, write32_test # set m-mode threshold to 7
|
||||
.4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 3.2: Cause SEIP with UART first
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000006, write32_test # GPIOPriority = 6
|
||||
.4byte PLIC_INTPRI_UART, 0x00000007, write32_test # UARTPriority = 7
|
||||
.4byte PLIC_THRESH0, 0x00000007, write32_test # set m-mode threshold to 7
|
||||
.4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 3.3: Low SEIP due to insufficient priority
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000002, write32_test # GPIOPriority = 2
|
||||
.4byte PLIC_INTPRI_UART, 0x00000003, write32_test # UARTPriority = 3
|
||||
.4byte PLIC_THRESH0, 0x00000004, write32_test # set m-mode threshold to 4
|
||||
.4byte PLIC_THRESH1, 0x00000005, write32_test # set s-mode threshold to 5
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# =========== UART interrupt enable tests (4.X) ===========
|
||||
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
.4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # GPIO Priority = 1
|
||||
.4byte PLIC_INTPRI_UART, 0x00000001, write32_test # UART Priority = 1
|
||||
|
||||
# Test 4.0: GPIO m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000400, write32_test # disable GPIO m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000A00, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 4.1: UART m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000008, write32_test # disable UART m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000000, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 4.2: GPIO s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000400, write32_test # enable all s-mode interrupts
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000A00, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 4.3: UART s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000008, write32_test # enable all s-mode interrupts
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 4.4: GPIO and UART s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # enable all s-mode interrupts
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 4.5: GPIO and UART m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000000, write32_test # disable GPIO interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000000, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 4.6: GPIO and UART fully disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000000, write32_test # disable GPIO interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # enable all s-mode interrupts
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000000, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# =========== GPIO interrupt enable tests (5.X) ===========
|
||||
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
.4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # GPIO Priority = 1
|
||||
.4byte PLIC_INTPRI_UART, 0x00000001, write32_test # UART Priority = 1
|
||||
|
||||
# Test 5.0: GPIO m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000400, write32_test # disable GPIO m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte 0x0, 0x00000200, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000000, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 5.1: UART m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000008, write32_test # disable UART m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte 0x0, 0x00000A00, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 5.2: GPIO s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000400, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 5.3: UART s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000008, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte 0x0, 0x00000A00, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 5.4: GPIO and UART s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 5.5: GPIO and UART m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000000, write32_test # disable GPIO interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte 0x0, 0x00000200, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000000, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 5.6: GPIO and UART fully disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000000, write32_test # disable GPIO interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM0, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte PLIC_CLAIM0, 0x00000000, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_m_plic_interrupts # clear interrupt two
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x0, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# =========== S-mode enable tests (7.X) ===========
|
||||
|
||||
.4byte 0x0, 0x0, goto_s_mode # go to s-mode. 0xb written to output
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
.4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # GPIO Priority = 1
|
||||
.4byte PLIC_INTPRI_UART, 0x00000001, write32_test # UART Priority = 1
|
||||
|
||||
# Test 7.0: GPIO m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000400, write32_test # disable GPIO m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readsip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM1, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM1, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 7.1: UART m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000008, write32_test # disable UART m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readsip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM1, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM1, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 7.2: GPIO s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000400, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readsip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM1, 0x0000000A, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM1, 0x0000000A, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 7.3: UART s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000008, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readsip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM1, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM1, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 7.4: GPIO and UART s-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000000, readsip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM1, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM1, 0x00000000, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 7.5: GPIO and UART m-mode disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000000, write32_test # disable GPIO interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000200, readsip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM1, 0x00000003, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM1, 0x00000003, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# Test 7.6: GPIO and UART fully disabled
|
||||
|
||||
.4byte PLIC_INTEN00, 0x00000000, write32_test # disable GPIO interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # enable all s-mode interrupts
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000000, readsip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
.4byte PLIC_CLAIM1, 0x00000000, read32_test # read claim register
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending cleared for GPIO
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000001, write32_test # clear GPIO interrupt
|
||||
.4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
.4byte PLIC_CLAIM1, 0x00000000, write32_test # complete claim made earlier
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt one
|
||||
.4byte 0x0, 0x00000000, claim_s_plic_interrupts # clear interrupt two
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupts pending
|
||||
|
||||
# =========== Special claim tests (8) ===========
|
||||
|
||||
.4byte 0x0, 0x0, goto_m_mode # write 0x9 to output
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000006, write32_test # GPIO Priority = 6
|
||||
.4byte PLIC_INTPRI_UART, 0x00000007, write32_test # UART Priority = 7
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable all m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # enable all s-mode interrupts
|
||||
.4byte PLIC_THRESH0, 0x00000005, write32_test # set m-mode threshold to 5
|
||||
|
||||
# Test 8
|
||||
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte UART_MSR, 0x0F, write08_test # cause UART interrupt
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # read interrupt pending
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # claim UART
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # UART interrupt cleared
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # claim GPIO
|
||||
.4byte 0x0, 0x00000000, readmip_test # no interrupts, meip is low
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # both interrupts claimed
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete GPIO
|
||||
.4byte 0x0, 0x00000800, readmip_test # GPIO interrupt sets MEIP
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # GPIO bit is set
|
||||
.4byte PLIC_CLAIM0, 0x00000003, read32_test # claim GPIO again
|
||||
.4byte 0x0, 0x00000000, readmip_test # meip is zeroed
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # both interrupts claimed
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, write32_test # complete UART claim
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000400, read32_test # UART pending
|
||||
.4byte PLIC_CLAIM0, 0x00000003, write32_test # complete GPIO claim
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000408, read32_test # GPIO and UART pending
|
||||
.4byte PLIC_CLAIM0, 0x0000000A, read32_test # claim UART
|
||||
|
||||
.4byte 0x0, 0x0, terminate_test # terminate tests
|
|
@ -0,0 +1,493 @@
|
|||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-gpio
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Nicholas Lucio <nlucio@hmc.edu>
|
||||
//
|
||||
// Created 2022-06-16
|
||||
//
|
||||
// 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"
|
||||
|
||||
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
|
||||
#
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
# =========== Define PLIC registers ===========
|
||||
|
||||
.equ PLIC, 0x0C000000
|
||||
.equ PLIC_INTPRI_GPIO, (PLIC+0x00000C) # GPIO is interrupt 3
|
||||
.equ PLIC_INTPRI_UART, (PLIC+0x000028) # UART is interrupt 10
|
||||
.equ PLIC_INTPENDING0, (PLIC+0x001000) # intPending0 register
|
||||
.equ PLIC_INTEN00, (PLIC+0x002000) # interrupt enables for context 0 (machine mode) sources 31:1
|
||||
.equ PLIC_INTEN10, (PLIC+0x002080) # interrupt enables for context 1 (supervisor mode) sources 31:1
|
||||
.equ PLIC_THRESH0, (PLIC+0x200000) # Priority threshold for context 0 (machine mode)
|
||||
.equ PLIC_CLAIM0, (PLIC+0x200004) # Claim/Complete register for context 0
|
||||
.equ PLIC_THRESH1, (PLIC+0x201000) # Priority threshold for context 1 (supervisor mode)
|
||||
.equ PLIC_CLAIM1, (PLIC+0x201004) # Claim/Complete register for context 1
|
||||
|
||||
# =========== Define GPIO registers ===========
|
||||
|
||||
.equ GPIO, 0x10060000
|
||||
.equ input_val, (GPIO+0x00)
|
||||
.equ input_en, (GPIO+0x04)
|
||||
.equ output_en, (GPIO+0x08)
|
||||
.equ output_val, (GPIO+0x0C)
|
||||
.equ rise_ie, (GPIO+0x18)
|
||||
.equ rise_ip, (GPIO+0x1C)
|
||||
.equ fall_ie, (GPIO+0x20)
|
||||
.equ fall_ip, (GPIO+0x24)
|
||||
.equ high_ie, (GPIO+0x28)
|
||||
.equ high_ip, (GPIO+0x2C)
|
||||
.equ low_ie, (GPIO+0x30)
|
||||
.equ low_ip, (GPIO+0x34)
|
||||
.equ iof_en, (GPIO+0x38)
|
||||
.equ iof_sel, (GPIO+0x3C)
|
||||
.equ out_xor, (GPIO+0x40)
|
||||
|
||||
# =========== Define UART registers ===========
|
||||
|
||||
.equ UART, 0x10000000
|
||||
.equ UART_IER, (UART+0x01)
|
||||
.equ UART_MCR, (UART+0x04)
|
||||
.equ UART_MSR, (UART+0x06)
|
||||
|
||||
# =========== Initialize UART and GPIO ===========
|
||||
|
||||
# GPIO Initialization
|
||||
.4byte input_en, 0x00000001, write32_test # enable bit 0 of input_en
|
||||
.4byte output_en, 0x00000001, write32_test # enable bit 0 of output_en
|
||||
.4byte output_val, 0x00000000, write32_test # make sure output_val is 0
|
||||
.4byte rise_ie, 0x00000001, write32_test # enable rise interrupts
|
||||
|
||||
# UART Initialization
|
||||
.4byte UART_IER, 0x08, write08_test # enable modem status interrupts from CTS
|
||||
.4byte UART_MCR, 0x10, write08_test # enable loopback mode, RTS = 0
|
||||
.4byte UART_MSR, 0x00, write08_test # disable UART interrupt
|
||||
|
||||
# =========== Initialize relevant PLIC registers ===========
|
||||
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000000, write32_test # set GPIO priority to zero
|
||||
.4byte PLIC_INTPRI_UART, 0x00000000, write32_test # set UART priority to zero
|
||||
.4byte PLIC_INTEN00, 0x00000408, write32_test # enable m-mode interrupts
|
||||
.4byte PLIC_INTEN10, 0x00000408, write32_test # enable s-mode interrupts
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
.4byte PLIC_THRESH1, 0x00000007, write32_test # set s-mode threshold to max
|
||||
|
||||
# =========== Machine-Mode Priority Testing (1.T.X) ===========
|
||||
|
||||
# Test 1.0.0: GPIO int lacks priority (0 = 0)
|
||||
.4byte PLIC_THRESH0, 0x00000000, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect no interrupt pending *** pending bug?????
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.0.1: GPIO int has priority (1 > 0)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # let GPIO cause interrupts
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte 0x0, 0x00000003, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.0.2: meip and c/c clear without interrupt pending
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
|
||||
# Test 1.1.0: GPIO lacks priority (1 = 1)
|
||||
.4byte PLIC_THRESH0, 0x00000001, write32_test # change threshold
|
||||
.4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # expect no interrupt pending
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.1.1: GPIO int has priority (2 > 1)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000002, write32_test # let GPIO cause interrupts
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte 0x0, 0x00000003, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.2.0: GPIO int lacks priority (2 = 2)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_THRESH0, 0x00000002, write32_test # change threshold
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # expect no interrupt pending
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.2.1: GPIO int has priority (3 > 2)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000003, write32_test # let GPIO cause interrupts
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte 0x0, 0x00000003, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.3.0: GPIO int lacks priority (3 = 3)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_THRESH0, 0x00000003, write32_test # change threshold
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # expect no interrupt pending
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.3.1: GPIO int has priority (4 > 3)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000004, write32_test # let GPIO cause interrupts
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte 0x0, 0x00000003, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.4.0: GPIO int lacks priority (4 = 4)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_THRESH0, 0x00000004, write32_test # change threshold
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # expect no interrupt pending
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.4.1: GPIO int has priority (5 > 4)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000005, write32_test # let GPIO cause interrupts
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte 0x0, 0x00000003, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.5.0: GPIO int lacks priority (5 = 5)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_THRESH0, 0x00000005, write32_test # change threshold
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # expect no interrupt pending
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.5.1: GPIO int has priority (6 > 5)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000006, write32_test # let GPIO cause interrupts
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte 0x0, 0x00000003, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.6.0: GPIO int lacks priority (6 = 6)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_THRESH0, 0x00000006, write32_test # change threshold
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # expect no interrupt pending
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.6.1: GPIO int has priority (7 > 6)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_INTPRI_GPIO, 0x00000007, write32_test # let GPIO cause interrupts
|
||||
.4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000008, read32_test # expect interrupt pending on bit 3
|
||||
.4byte 0x0, 0x00000003, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# Test 1.7.0: GPIO int lacks priority (7 = 7)
|
||||
.4byte output_val, 0x00000001, write32_test # set GPIO rise_ip high
|
||||
.4byte PLIC_THRESH0, 0x00000007, write32_test # change threshold
|
||||
.4byte 0x0, 0x00000000, readmip_test # read mip
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # expect no interrupt pending
|
||||
.4byte 0x0, 0x00000000, readmclaimcomplete_test # read and clear claimcomplete
|
||||
.4byte PLIC_INTPENDING0, 0x00000000, read32_test # interrupt pending was cleared
|
||||
.4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
.4byte rise_ip, 0x00000000, write32_test # clear interrupt
|
||||
|
||||
# # =========== UART vs GPIO priority (2.X) =========== ***
|
||||
|
||||
# .4byte PLIC_INTEN00, 0x00000408, write32_test # enable m-mode interrupts
|
||||
# .4byte PLIC_INTEN10, 0x00000408, write32_test # enable s-mode interrupts
|
||||
# .4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
# .4byte PLIC_THRESH1, 0x00000007, write32_test # set s-mode threshold to max
|
||||
|
||||
# # Test 2.0: GPIO Priority = UART Priority
|
||||
|
||||
# .4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # GPIOPriority = 1
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000001, write32_test # UARTPriority = 1
|
||||
# .4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
# .4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
# .4byte 0x0, 0x00000003, readmclaimcomplete_test # GPIO claim/complete process
|
||||
# .4byte PLIC_INTPENDING0, 0x00000200, read32_test # GPIO interrupt was cleared
|
||||
# .4byte 0x0, 0x00000800, readmip_test # expect mip to remain high
|
||||
# .4byte 0x0, 0x0000000A, readmclaimcomplete_test # UART claim/complete process
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # UART interrupt pending was cleared
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # Test 2.1: GPIO Priority < UART Priority
|
||||
|
||||
# .4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000002, write32_test # GPIO Priority = 2
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000003, write32_test # UART Priority = 3
|
||||
# .4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
# .4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for UART and GPIO
|
||||
# .4byte 0x0, 0x0000000A, readmclaimcomplete_test # UART claim/complete process
|
||||
# .4byte PLIC_INTPENDING0, 0x00000008, read32_test # UART interrupt was cleared
|
||||
# .4byte 0x0, 0x00000800, readmip_test # expect mip to remain high
|
||||
# .4byte 0x0, 0x00000003, readmclaimcomplete_test # GPIO claim/complete process
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # GPIO interrupt pending was cleared
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # Test 2.2: GPIO Priority > UART Priority
|
||||
|
||||
# .4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000005, write32_test # GPIO Priority = 5
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000004, write32_test # UART Priority = 4
|
||||
# .4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
# .4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
# .4byte 0x0, 0x00000003, readmclaimcomplete_test # GPIO claim/complete process
|
||||
# .4byte PLIC_INTPENDING0, 0x00000200, read32_test # GPIO interrupt was cleared
|
||||
# .4byte 0x0, 0x00000800, readmip_test # expect mip to remain high
|
||||
# .4byte 0x0, 0x0000000A, readmclaimcomplete_test # UART claim/complete process
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # UART interrupt pending was cleared
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # Test 2.3: GPIO Priority < UART Priority (2)
|
||||
|
||||
# .4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000006, write32_test # GPIO Priority = 6
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000007, write32_test # UART Priority = 7
|
||||
# .4byte 0x0, 0x00000800, readmip_test # read mip
|
||||
# .4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for UART and GPIO
|
||||
# .4byte 0x0, 0x0000000A, readmclaimcomplete_test # UART claim/complete process
|
||||
# .4byte PLIC_INTPENDING0, 0x00000008, read32_test # UART interrupt was cleared
|
||||
# .4byte 0x0, 0x00000800, readmip_test # expect mip to remain high
|
||||
# .4byte 0x0, 0x00000003, readmclaimcomplete_test # GPIO claim/complete process
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # GPIO interrupt pending was cleared
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # Test 2.4: Interrupts disabled (Thresh0 = 7)
|
||||
|
||||
# .4byte output_val, 0x00000001, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_THRESH0, 0x00000007, write32_test # Disable m-mode interrupts
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000007, write32_test # GPIO Priority = 7
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000007, write32_test # UART Priority = 7
|
||||
# .4byte 0x0, 0x00000000, readmip_test, # read mip
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
# .4byte 0x0, 0x00000000, readmclaimcomplete_test # no interrupt pending
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # =========== SEIP tests (3.X) ===========
|
||||
|
||||
# .4byte PLIC_INTEN00, 0x00000408, write32_test # enable m-mode interrupts
|
||||
# .4byte PLIC_INTEN10, 0x00000408, write32_test # enable s-mode interrupts
|
||||
# .4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
# .4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
|
||||
# # Test 3.0: Cause machine and supervisor interrupts
|
||||
|
||||
# .4byte output_val, 0x00000000, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # GPIO Priority = 1
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000001, write32_test # UART Priority = 1
|
||||
# .4byte 0x0, 0x00000A00, readmip_test # Expect high on MEIP and SEIP
|
||||
# .4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
# .4byte 0x0, 0x00000003, readmclaimcomplete_test # Expect GPIO on claim/complete
|
||||
# .4byte 0x0, 0x00000A00, readmip_test # Still expect high on MEIP and SEIP
|
||||
# .4byte PLIC_INTPENDING0, 0x00000200, read32_test # GPIO interrupt was cleared
|
||||
# .4byte 0x0, 0x0000000A, readmclaimcomplete_test # Expect UART on claim/complete
|
||||
# .4byte 0x0, 0x00000000, readmip_test # all interrupts were cleared
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # Pending should also be clear
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # Test 3.1: Suppress machine mode interrupts
|
||||
|
||||
# .4byte output_val, 0x00000000, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000003, write32_test # GPIO Priority = 3
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000002, write32_test # UART Priority = 2
|
||||
# .4byte PLIC_THRESH0, 0x00000007, write32_test # set m-mode threshold to 7
|
||||
# .4byte 0x0, 0x00000200, readmip_test # Expect high on SEIP only
|
||||
# .4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
# .4byte 0x0, 0x00000003, readmclaimcomplete_test # Expect GPIO on claim/complete
|
||||
# .4byte 0x0, 0x00000200, readmip_test # Expect high on SEIP only
|
||||
# .4byte PLIC_INTPENDING0, 0x00000200, read32_test # GPIO interrupt was cleared
|
||||
# .4byte 0x0, 0x0000000A, readmclaimcomplete_test # Expect UART on claim/complete
|
||||
# .4byte 0x0, 0x00000000, readmip_test # all interrupts were cleared
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # Pending should also be clear
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # Test 3.2: Cause SEIP with UART first
|
||||
|
||||
# .4byte output_val, 0x00000000, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000006, write32_test # GPIO Priority = 6
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000007, write32_test # UART Priority = 7
|
||||
# .4byte 0x0, 0x00000200, readmip_test # Expect high on SEIP only
|
||||
# .4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
# .4byte 0x0, 0x0000000A, readmclaimcomplete_test # Expect UART on claim/complete
|
||||
# .4byte 0x0, 0x00000200, readmip_test # Expect high on SEIP only
|
||||
# .4byte PLIC_INTPENDING0, 0x00000008, read32_test # UART interrupt was cleared
|
||||
# .4byte 0x0, 0x00000003, readmclaimcomplete_test # Expect GPIO on claim/complete
|
||||
# .4byte 0x0, 0x00000000, readmip_test # all interrupts were cleared
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # Pending should also be clear
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # Test 3.3: Low SEIP due to insufficient priority
|
||||
|
||||
# .4byte output_val, 0x00000000, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000002, write32_test # GPIO Priority = 2
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000003, write32_test # UART Priority = 3
|
||||
# .4byte PLIC_THRESH0, 0x00000004, write32_test # set m-mode threshold to 7
|
||||
# .4byte PLIC_THRESH1, 0x00000005, write32_test # set s-mode threshold to 7
|
||||
# .4byte 0x0, 0x00000000, readmip_test # no interrupt pending
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # no interrupt pending
|
||||
# .4byte 0x0, 0x00000000, readmclaimcomplete_test # Expect nothing on claim/complete
|
||||
# .4byte output_val, 0x00000000, write32_test # clear output_val
|
||||
# .4byte rise_ip, 0x00000000, write32_test # clear GPIO interrupt
|
||||
# .4byte UART_MSR, 0x00000000, write08_test # clear UART interrupt
|
||||
|
||||
# # =========== UART interrupt enable tests (4.X) ===========
|
||||
|
||||
# .4byte PLIC_THRESH0, 0x00000000, write32_test # set m-mode threshold to 0
|
||||
# .4byte PLIC_THRESH1, 0x00000000, write32_test # set s-mode threshold to 0
|
||||
# .4byte PLIC_INTPRI_GPIO, 0x00000001, write32_test # GPIO Priority = 1
|
||||
# .4byte PLIC_INTPRI_UART, 0x00000001, write32_test # UART Priority = 1
|
||||
|
||||
# # Test 4.0: GPIO m-mode disabled
|
||||
|
||||
# .4byte output_val, 0x00000000, write32_test # cause rise_ip to go high
|
||||
# .4byte UART_MSR, 0x00000010, write08_test # step 1 of UART interrupt
|
||||
# .4byte UART_MSR, 0x00000012, write08_test # step 2 of UART interrupt
|
||||
# .4byte PLIC_INTEN00, 0x000000200, write32_test # GPIO m-mode interrupt disabled
|
||||
# .4byte PLIC_INTEN00, 0x000000208, write32_test # No s-mode interrupt disabled
|
||||
# .4byte 0x0, 0x00000A00, readmip_test # Expect high on MEIP from UART and SEIP from GPIO
|
||||
# .4byte PLIC_INTPENDING0, 0x00000408, read32_test # interrupt pending for GPIO and UART
|
||||
# .4byte 0x0, 0x00000003, readmclaimcomplete_test # Expect GPIO on claim/complete
|
||||
# .4byte 0x0, 0x00000200, readmip_test # Expect high on MEIP and SEIP from UART
|
||||
# .4byte PLIC_INTPENDING0, 0x00000200, read32_test # interrupt pending for GPIO and UART
|
||||
# .4byte 0x0, 0x0000000A, readmclaimcomplete_test # Expect UART on claim/complete
|
||||
# .4byte 0x0, 0x00000000, readmip_test # all interrupts were cleared
|
||||
# .4byte PLIC_INTPENDING0, 0x00000000, read32_test # Pending should also be clear
|
||||
|
||||
# Test 4.1: UART m-mode disabled
|
||||
|
||||
|
||||
|
||||
# Test 4.2: GPIO s-mode disabled
|
||||
|
||||
|
||||
|
||||
# Test 4.3: UART s-mode disabled
|
||||
|
||||
|
||||
|
||||
# Test 4.4: GPIO and UART s-mode disabled
|
||||
|
||||
|
||||
|
||||
# Test 4.5: GPIO and UART m-mode disabled
|
||||
|
||||
|
||||
|
||||
# Test 4.6: GPIO and UART fully disabled
|
||||
|
||||
.4byte 0x0, 0x0, terminate_test # terminate tests
|
|
@ -0,0 +1,140 @@
|
|||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-uart
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Nicholas Lucio <nlucio@hmc.edu>
|
||||
//
|
||||
// Created 2022-06-16
|
||||
//
|
||||
// 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"
|
||||
|
||||
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
|
||||
|
||||
.equ UART, 0x10000000
|
||||
.equ UART_RBR, (UART)
|
||||
.equ UART_THR, (UART)
|
||||
.equ UART_IER, (UART+0x01)
|
||||
.equ UART_IIR, (UART+0x02)
|
||||
.equ UART_FCR, (UART+0x02)
|
||||
.equ UART_LCR, (UART+0x03)
|
||||
.equ UART_MCR, (UART+0x04)
|
||||
.equ UART_LSR, (UART+0x05)
|
||||
.equ UART_MSR, (UART+0x06)
|
||||
.equ UART_Scr, (UART+0x07)
|
||||
|
||||
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
|
||||
#
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
# =========== UART resets to correct values on master reset ===========
|
||||
|
||||
.4byte UART_IER, 0x00, read08_test
|
||||
.4byte UART_IIR, 0x01, read08_test # IIR resets to 1
|
||||
# .4byte UART_LCR, 0x00, read08_test *** commented out because LCR should reset to zero but resets to 3
|
||||
.4byte UART_MCR, 0x00, read08_test
|
||||
.4byte UART_LSR, 0x60, read08_test # LSR resets with transmit status bits set
|
||||
.4byte UART_MSR, 0x00, read04_test
|
||||
|
||||
# =========== Basic read-write ===========
|
||||
|
||||
.4byte UART_LCR, 0x00, write08_test # set LCR to reset value *** remove if UART resets to correct value
|
||||
.4byte UART_MCR, 0x10, write08_test # put UART into loopback for MSR test
|
||||
.4byte UART_LSR, 0x60, read08_test
|
||||
.4byte UART_THR, 0x00, write08_test # write value to UART
|
||||
.4byte UART_LSR, 0x00, read08_test # data not ready and transmitter is not empty
|
||||
.4byte 0x0, 0x0101, uart_data_wait # wait for data to become ready then output IIR and LSR
|
||||
.4byte UART_RBR, 0x00, read08_test # read written value
|
||||
.4byte UART_LSR, 0x60, read08_test # read LSR
|
||||
|
||||
# =========== Different size read-write ===========
|
||||
|
||||
# Transmit 5 bits
|
||||
|
||||
.4byte UART_LCR, 0x00, write08_test # set LCR to transmit 5 bits
|
||||
.4byte UART_THR, 0x55, write08_test # write value to UART
|
||||
.4byte 0x0, 0x0101, uart_data_wait # wait for data to become ready then output IIR and then LSR
|
||||
.4byte UART_RBR, 0x15, read08_test # read written value without bits 5-7
|
||||
|
||||
# Transmit 6 bits
|
||||
|
||||
.4byte UART_LCR, 0x01, write08_test # set LCR to transmit six bits
|
||||
.4byte UART_THR, 0xAA, write08_test # write value to UART
|
||||
.4byte 0x0, 0x0101, uart_data_wait # wait for data to become ready then output IIR and then LSR
|
||||
.4byte UART_RBR, 0x2A, read08_test # read written value without bits 6 & 7
|
||||
|
||||
# Transmit 7 bits
|
||||
|
||||
.4byte UART_LCR, 0x02, write08_test # set LCR to transmit seven bits
|
||||
.4byte UART_THR, 0xFF, write08_test # write value to UART
|
||||
.4byte 0x0, 0x0101, uart_data_wait # wait for data to become ready then output IIR and then LSR
|
||||
.4byte UART_RBR, 0x7F, read08_test # read written value without bit 7
|
||||
|
||||
# Transmit 8 bits
|
||||
|
||||
.4byte UART_LCR, 0x03, write08_test # set LCR to transmit seven bits
|
||||
.4byte UART_THR, 0x80, write08_test # write value to UART
|
||||
.4byte 0x0, 0x0101, uart_data_wait # wait for data to become ready then output IIR and then LSR
|
||||
.4byte UART_RBR, 0x80, read08_test # read full written value + sign extension
|
||||
|
||||
# =========== Transmit-related interrupts ===========
|
||||
|
||||
.4byte UART_IER, 0x07, write08_test # enable data available, buffer empty, and line status interrupts
|
||||
.4byte UART_IIR, 0x02, read08_test # buffer should be empty, causing interrupt
|
||||
.4byte UART_THR, 0x00, write08_test # write zeroes to transmitter
|
||||
.4byte 0x0, 0x0401, uart_data_wait # IIR should have data ready interrupt
|
||||
.4byte UART_THR, 0x01, write08_test # write 1 to transmitter buffer
|
||||
.4byte UART_IIR, 0x04, read08_test # data interrupt should still be high
|
||||
.4byte 0x0, 0x06, uart_lsr_intr_wait # wait for transmission to complete, IIR should throw error due to overrun error.
|
||||
.4byte UART_LSR, 0x63, read08_test # read overrun error from LSR
|
||||
.4byte UART_IIR, 0x04, read08_test # check that LSR interrupt was cleared
|
||||
.4byte UART_RBR, 0x01, read08_test # read previous value from UART
|
||||
|
||||
# =========== MODEM interrupts ===========
|
||||
|
||||
.4byte UART_MSR, 0x00, write08_test # clear MSR
|
||||
.4byte UART_IER, 0x08, write08_test # enable MODEM Status interrupts
|
||||
.4byte UART_IIR, 0x01, read08_test # no interrupts pending
|
||||
.4byte UART_MCR, 0x02, write08_test # Cause DCTS interrupt
|
||||
.4byte UART_IIR, 0x00, read08_test # MODEM interrupt
|
||||
.4byte UART_MSR, 0x11, read08_test # Read MSR to clear interrupt
|
||||
.4byte UART_IIR, 0x01, read08_test # interrupt cleared by reading MSR
|
||||
|
||||
.4byte 0x0, 0x0, terminate_test
|
Loading…
Add table
Add a link
Reference in a new issue