mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/openhwgroup/cvw
This commit is contained in:
commit
d2219023c3
36
Makefile
36
Makefile
@ -4,7 +4,11 @@
|
|||||||
|
|
||||||
all:
|
all:
|
||||||
make install
|
make install
|
||||||
make regression
|
make testfloat
|
||||||
|
make riscof
|
||||||
|
make verify
|
||||||
|
make coverage
|
||||||
|
make benchmarks
|
||||||
|
|
||||||
# install copies over the Makefile.include from riscv-isa-sim
|
# install copies over the Makefile.include from riscv-isa-sim
|
||||||
# And corrects the TARGETDIR path and the RISCV_PREFIX
|
# And corrects the TARGETDIR path and the RISCV_PREFIX
|
||||||
@ -18,9 +22,37 @@ install:
|
|||||||
##rm tests/imperas-riscv-tests/riscv-ovpsim-plus/bin/Linux64/riscvOVPsimPlus.exe
|
##rm tests/imperas-riscv-tests/riscv-ovpsim-plus/bin/Linux64/riscvOVPsimPlus.exe
|
||||||
##ln -s ${RISCV}/imperas-riscv-tests/riscv-ovpsim-plus/bin/Linux64/riscvOVPsimPlus.exe tests/imperas-riscv-tests/riscv-ovpsim-plus/bin/Linux64/riscvOVPsimPlus.exe
|
##ln -s ${RISCV}/imperas-riscv-tests/riscv-ovpsim-plus/bin/Linux64/riscvOVPsimPlus.exe tests/imperas-riscv-tests/riscv-ovpsim-plus/bin/Linux64/riscvOVPsimPlus.exe
|
||||||
|
|
||||||
regression:
|
riscof:
|
||||||
make -C sim
|
make -C sim
|
||||||
|
|
||||||
|
testfloat:
|
||||||
|
cd ${WALLY}/addins/SoftFloat-3e/build/Linux-x86_64-GCC; make
|
||||||
|
cd ${WALLY}/addins/TestFloat-3e/build/Linux-x86_64-GCC; make
|
||||||
|
cd ${WALLY}/tests/fp; ./create_all_vectors.sh
|
||||||
|
|
||||||
|
verify:
|
||||||
|
cd ${WALLY}/sim; ./regression-wally
|
||||||
|
cd ${WALLY}/sim; ./sim-testfloat-batch all
|
||||||
|
make imperasdv
|
||||||
|
|
||||||
|
imperasdv:
|
||||||
|
iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m
|
||||||
|
iter-elf.bash --search ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
cd ${WALLY}/sim; ./regresssion-wally -coverage -fp
|
||||||
|
|
||||||
|
benchmarks:
|
||||||
|
make coremark
|
||||||
|
make embench
|
||||||
|
|
||||||
|
coremark:
|
||||||
|
cd ${WALLY}/benchmarks/coremark; make; make run
|
||||||
|
|
||||||
|
embench:
|
||||||
|
cd ${WALLY}/benchmarks/embench; make; make run
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
make clean -C sim
|
make clean -C sim
|
||||||
|
|
||||||
|
@ -11,7 +11,11 @@ sources=$(cmbase)/core_main.c $(cmbase)/core_list_join.c $(cmbase)/coremark.h \
|
|||||||
$(PORT_DIR)/core_portme.h $(PORT_DIR)/core_portme.c $(PORT_DIR)/core_portme.mak \
|
$(PORT_DIR)/core_portme.h $(PORT_DIR)/core_portme.c $(PORT_DIR)/core_portme.mak \
|
||||||
$(PORT_DIR)/crt.S $(PORT_DIR)/encoding.h $(PORT_DIR)/util.h $(PORT_DIR)/syscalls.c
|
$(PORT_DIR)/crt.S $(PORT_DIR)/encoding.h $(PORT_DIR)/util.h $(PORT_DIR)/syscalls.c
|
||||||
ABI := $(if $(findstring "64","$(XLEN)"),lp64,ilp32)
|
ABI := $(if $(findstring "64","$(XLEN)"),lp64,ilp32)
|
||||||
ARCH := rv$(XLEN)gc
|
#ARCH := rv$(XLEN)gc_zba_zbb_zbc_zbs
|
||||||
|
#ARCH := rv$(XLEN)gc
|
||||||
|
ARCH := rv$(XLEN)imc_zicsr
|
||||||
|
#ARCH := rv$(XLEN)im_zicsr
|
||||||
|
#ARCH := rv$(XLEN)i_zicsr
|
||||||
PORT_CFLAGS = -g -mabi=$(ABI) -march=$(ARCH) -static -falign-functions=16 \
|
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 \
|
-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 \
|
-fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 \
|
||||||
|
@ -45,7 +45,7 @@ sudo mkdir -p $RISCV
|
|||||||
# Update and Upgrade tools (see https://itsfoss.com/apt-update-vs-upgrade/)
|
# Update and Upgrade tools (see https://itsfoss.com/apt-update-vs-upgrade/)
|
||||||
sudo apt update -y
|
sudo apt update -y
|
||||||
sudo apt upgrade -y
|
sudo apt upgrade -y
|
||||||
sudo apt install -y git gawk make texinfo bison flex build-essential python3 libz-dev libexpat-dev autoconf device-tree-compiler ninja-build libpixman-1-dev ncurses-base ncurses-bin libncurses5-dev dialog curl wget ftp libgmp-dev libglib2.0-dev python3-pip pkg-config opam z3 zlib1g-dev verilator automake autotools-dev libmpc-dev libmpfr-dev gperf libtool patchutils bc
|
sudo apt install -y git gawk make texinfo bison flex build-essential python3 libz-dev libexpat-dev autoconf device-tree-compiler ninja-build libpixman-1-dev ncurses-base ncurses-bin libncurses5-dev dialog curl wget ftp libgmp-dev libglib2.0-dev python3-pip pkg-config opam z3 zlib1g-dev automake autotools-dev libmpc-dev libmpfr-dev gperf libtool patchutils bc
|
||||||
# Other python libraries used through the book.
|
# Other python libraries used through the book.
|
||||||
sudo pip3 install matplotlib scipy scikit-learn adjustText lief
|
sudo pip3 install matplotlib scipy scikit-learn adjustText lief
|
||||||
|
|
||||||
@ -113,6 +113,23 @@ cd ../arch_test_target/spike/device
|
|||||||
sed -i 's/--isa=rv32ic/--isa=rv32iac/' rv32i_m/privilege/Makefile.include
|
sed -i 's/--isa=rv32ic/--isa=rv32iac/' rv32i_m/privilege/Makefile.include
|
||||||
sed -i 's/--isa=rv64ic/--isa=rv64iac/' rv64i_m/privilege/Makefile.include
|
sed -i 's/--isa=rv64ic/--isa=rv64iac/' rv64i_m/privilege/Makefile.include
|
||||||
|
|
||||||
|
# Wally needs Verilator 5.0 or later.
|
||||||
|
# Verilator needs to be built from scratch to get the latest version
|
||||||
|
# apt-get install verilator installs version 4.028 as of 6/8/23
|
||||||
|
sudo apt-get install -y perl g++ ccache help2man libgoogle-perftools-dev numactl perl-doc zlibc zlib1g
|
||||||
|
sudo apt-get install -y libfl2 libfl-dev # Ubuntu only (ignore if gives error)
|
||||||
|
cd $RISCV
|
||||||
|
git clone https://github.com/verilator/verilator # Only first time
|
||||||
|
unsetenv VERILATOR_ROOT # For csh; ignore error if on bash
|
||||||
|
unset VERILATOR_ROOT # For bash
|
||||||
|
cd verilator
|
||||||
|
git pull # Make sure git repository is up-to-date
|
||||||
|
git checkout master # Use development branch (e.g. recent bug fixes)
|
||||||
|
autoconf # Create ./configure script
|
||||||
|
./configure # Configure and create Makefile
|
||||||
|
make -j NUM_THREADS # Build Verilator itself (if error, try just 'make')
|
||||||
|
sudo make install
|
||||||
|
|
||||||
# Sail (https://github.com/riscv/sail-riscv)
|
# Sail (https://github.com/riscv/sail-riscv)
|
||||||
# Sail is the new golden reference model for RISC-V. Sail is written in OCaml, which
|
# Sail is the new golden reference model for RISC-V. Sail is written in OCaml, which
|
||||||
# is an object-oriented extension of ML, which in turn is a functional programming
|
# is an object-oriented extension of ML, which in turn is a functional programming
|
||||||
|
@ -40,10 +40,16 @@ localparam IEEE754 = 0;
|
|||||||
localparam MISA = (32'h0014112D);
|
localparam MISA = (32'h0014112D);
|
||||||
localparam ZICSR_SUPPORTED = 1;
|
localparam ZICSR_SUPPORTED = 1;
|
||||||
localparam ZIFENCEI_SUPPORTED = 1;
|
localparam ZIFENCEI_SUPPORTED = 1;
|
||||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
localparam ZICNTR_SUPPORTED = 1;
|
||||||
|
localparam ZIHPM_SUPPORTED = 1;
|
||||||
localparam COUNTERS = 12'd32;
|
localparam COUNTERS = 12'd32;
|
||||||
localparam ZFH_SUPPORTED = 0;
|
localparam ZFH_SUPPORTED = 0;
|
||||||
localparam SSTC_SUPPORTED = 0;
|
localparam SSTC_SUPPORTED = 0;
|
||||||
|
localparam ZICBOM_SUPPORTED = 0;
|
||||||
|
localparam ZICBOZ_SUPPORTED = 0;
|
||||||
|
localparam ZICBOP_SUPPORTED = 0;
|
||||||
|
localparam SVPBMT_SUPPORTED = 0;
|
||||||
|
|
||||||
|
|
||||||
// LSU microarchitectural Features
|
// LSU microarchitectural Features
|
||||||
localparam BUS_SUPPORTED = 1;
|
localparam BUS_SUPPORTED = 1;
|
||||||
|
@ -41,9 +41,14 @@ localparam MISA = (32'h00000010);
|
|||||||
localparam ZICSR_SUPPORTED = 0;
|
localparam ZICSR_SUPPORTED = 0;
|
||||||
localparam ZIFENCEI_SUPPORTED = 0;
|
localparam ZIFENCEI_SUPPORTED = 0;
|
||||||
localparam COUNTERS = 12'd0;
|
localparam COUNTERS = 12'd0;
|
||||||
localparam ZICOUNTERS_SUPPORTED = 0;
|
localparam ZICNTR_SUPPORTED = 0;
|
||||||
|
localparam ZIHPM_SUPPORTED = 0;
|
||||||
localparam ZFH_SUPPORTED = 0;
|
localparam ZFH_SUPPORTED = 0;
|
||||||
localparam SSTC_SUPPORTED = 0;
|
localparam SSTC_SUPPORTED = 0;
|
||||||
|
localparam ZICBOM_SUPPORTED = 0;
|
||||||
|
localparam ZICBOZ_SUPPORTED = 0;
|
||||||
|
localparam ZICBOP_SUPPORTED = 0;
|
||||||
|
localparam SVPBMT_SUPPORTED = 0;
|
||||||
|
|
||||||
// LSU microarchitectural Features
|
// LSU microarchitectural Features
|
||||||
localparam BUS_SUPPORTED = 1;
|
localparam BUS_SUPPORTED = 1;
|
||||||
|
@ -42,9 +42,14 @@ localparam MISA = (32'h00000104 | 1 << 20 | 1 << 18 | 1 << 12 | 1 << 0 | 1 <<3 |
|
|||||||
localparam ZICSR_SUPPORTED = 1;
|
localparam ZICSR_SUPPORTED = 1;
|
||||||
localparam ZIFENCEI_SUPPORTED = 1;
|
localparam ZIFENCEI_SUPPORTED = 1;
|
||||||
localparam COUNTERS = 12'd32;
|
localparam COUNTERS = 12'd32;
|
||||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
localparam ZICNTR_SUPPORTED = 1;
|
||||||
|
localparam ZIHPM_SUPPORTED = 1;
|
||||||
localparam ZFH_SUPPORTED = 0;
|
localparam ZFH_SUPPORTED = 0;
|
||||||
localparam SSTC_SUPPORTED = 1;
|
localparam SSTC_SUPPORTED = 1;
|
||||||
|
localparam ZICBOM_SUPPORTED = 0;
|
||||||
|
localparam ZICBOZ_SUPPORTED = 0;
|
||||||
|
localparam ZICBOP_SUPPORTED = 0;
|
||||||
|
localparam SVPBMT_SUPPORTED = 0;
|
||||||
|
|
||||||
// LSU microarchitectural Features
|
// LSU microarchitectural Features
|
||||||
localparam BUS_SUPPORTED = 1;
|
localparam BUS_SUPPORTED = 1;
|
||||||
|
@ -40,10 +40,15 @@ localparam IEEE754 = 0;
|
|||||||
localparam MISA = (32'h00000104);
|
localparam MISA = (32'h00000104);
|
||||||
localparam ZICSR_SUPPORTED = 0;
|
localparam ZICSR_SUPPORTED = 0;
|
||||||
localparam ZIFENCEI_SUPPORTED = 0;
|
localparam ZIFENCEI_SUPPORTED = 0;
|
||||||
localparam COUNTERS = 12'd32;
|
localparam COUNTERS = 0;
|
||||||
localparam ZICOUNTERS_SUPPORTED = 0;
|
localparam ZICNTR_SUPPORTED = 0;
|
||||||
|
localparam ZIHPM_SUPPORTED = 0;
|
||||||
localparam ZFH_SUPPORTED = 0;
|
localparam ZFH_SUPPORTED = 0;
|
||||||
localparam SSTC_SUPPORTED = 0;
|
localparam SSTC_SUPPORTED = 0;
|
||||||
|
localparam ZICBOM_SUPPORTED = 0;
|
||||||
|
localparam ZICBOZ_SUPPORTED = 0;
|
||||||
|
localparam ZICBOP_SUPPORTED = 0;
|
||||||
|
localparam SVPBMT_SUPPORTED = 0;
|
||||||
|
|
||||||
// LSU microarchitectural Features
|
// LSU microarchitectural Features
|
||||||
localparam BUS_SUPPORTED = 0;
|
localparam BUS_SUPPORTED = 0;
|
||||||
|
@ -40,9 +40,14 @@ localparam MISA = (32'h00000104 | 1 << 20 | 1 << 18 | 1 << 12);
|
|||||||
localparam ZICSR_SUPPORTED = 1;
|
localparam ZICSR_SUPPORTED = 1;
|
||||||
localparam ZIFENCEI_SUPPORTED = 1;
|
localparam ZIFENCEI_SUPPORTED = 1;
|
||||||
localparam COUNTERS = 12'd32;
|
localparam COUNTERS = 12'd32;
|
||||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
localparam ZICNTR_SUPPORTED = 1;
|
||||||
|
localparam ZIHPM_SUPPORTED = 1;
|
||||||
localparam ZFH_SUPPORTED = 0;
|
localparam ZFH_SUPPORTED = 0;
|
||||||
localparam SSTC_SUPPORTED = 0;
|
localparam SSTC_SUPPORTED = 0;
|
||||||
|
localparam ZICBOM_SUPPORTED = 0;
|
||||||
|
localparam ZICBOZ_SUPPORTED = 0;
|
||||||
|
localparam ZICBOP_SUPPORTED = 0;
|
||||||
|
localparam SVPBMT_SUPPORTED = 0;
|
||||||
|
|
||||||
// LSU microarchitectural Features
|
// LSU microarchitectural Features
|
||||||
localparam BUS_SUPPORTED = 1;
|
localparam BUS_SUPPORTED = 1;
|
||||||
|
@ -41,9 +41,14 @@ localparam MISA = (32'h00000104 | 1 << 5 | 1 << 3 | 1 << 16 | 1 << 18 | 1 << 20
|
|||||||
localparam ZICSR_SUPPORTED = 1;
|
localparam ZICSR_SUPPORTED = 1;
|
||||||
localparam ZIFENCEI_SUPPORTED = 1;
|
localparam ZIFENCEI_SUPPORTED = 1;
|
||||||
localparam COUNTERS = 12'd32;
|
localparam COUNTERS = 12'd32;
|
||||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
localparam ZICNTR_SUPPORTED = 1;
|
||||||
|
localparam ZIHPM_SUPPORTED = 1;
|
||||||
localparam ZFH_SUPPORTED = 1;
|
localparam ZFH_SUPPORTED = 1;
|
||||||
localparam SSTC_SUPPORTED = 0;
|
localparam SSTC_SUPPORTED = 0;
|
||||||
|
localparam ZICBOM_SUPPORTED = 0;
|
||||||
|
localparam ZICBOZ_SUPPORTED = 0;
|
||||||
|
localparam ZICBOP_SUPPORTED = 0;
|
||||||
|
localparam SVPBMT_SUPPORTED = 0;
|
||||||
|
|
||||||
// LSU microarchitectural Features
|
// LSU microarchitectural Features
|
||||||
localparam BUS_SUPPORTED = 1;
|
localparam BUS_SUPPORTED = 1;
|
||||||
|
@ -44,9 +44,14 @@ localparam MISA = (32'h00000104 | 1 << 5 | 1 << 3 | 1 << 18 | 1 << 20 | 1 << 12
|
|||||||
localparam ZICSR_SUPPORTED = 1;
|
localparam ZICSR_SUPPORTED = 1;
|
||||||
localparam ZIFENCEI_SUPPORTED = 1;
|
localparam ZIFENCEI_SUPPORTED = 1;
|
||||||
localparam COUNTERS = 12'd32;
|
localparam COUNTERS = 12'd32;
|
||||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
localparam ZICNTR_SUPPORTED = 1;
|
||||||
|
localparam ZIHPM_SUPPORTED = 1;
|
||||||
localparam ZFH_SUPPORTED = 0;
|
localparam ZFH_SUPPORTED = 0;
|
||||||
localparam SSTC_SUPPORTED = 1;
|
localparam SSTC_SUPPORTED = 1;
|
||||||
|
localparam ZICBOM_SUPPORTED = 0;
|
||||||
|
localparam ZICBOZ_SUPPORTED = 0;
|
||||||
|
localparam ZICBOP_SUPPORTED = 0;
|
||||||
|
localparam SVPBMT_SUPPORTED = 0;
|
||||||
|
|
||||||
// LSU microarchitectural Features
|
// LSU microarchitectural Features
|
||||||
localparam BUS_SUPPORTED = 1;
|
localparam BUS_SUPPORTED = 1;
|
||||||
|
@ -40,10 +40,15 @@ localparam IEEE754 = 0;
|
|||||||
localparam MISA = (32'h00000104);
|
localparam MISA = (32'h00000104);
|
||||||
localparam ZICSR_SUPPORTED = 0;
|
localparam ZICSR_SUPPORTED = 0;
|
||||||
localparam ZIFENCEI_SUPPORTED = 0;
|
localparam ZIFENCEI_SUPPORTED = 0;
|
||||||
localparam COUNTERS = 12'd32;
|
localparam COUNTERS = 0;
|
||||||
localparam ZICOUNTERS_SUPPORTED = 0;
|
localparam ZICNTR_SUPPORTED = 0;
|
||||||
|
localparam ZIHPM_SUPPORTED = 0;
|
||||||
localparam ZFH_SUPPORTED = 0;
|
localparam ZFH_SUPPORTED = 0;
|
||||||
localparam SSTC_SUPPORTED = 0;
|
localparam SSTC_SUPPORTED = 0;
|
||||||
|
localparam ZICBOM_SUPPORTED = 0;
|
||||||
|
localparam ZICBOZ_SUPPORTED = 0;
|
||||||
|
localparam ZICBOP_SUPPORTED = 0;
|
||||||
|
localparam SVPBMT_SUPPORTED = 0;
|
||||||
|
|
||||||
// LSU microarchitectural Features
|
// LSU microarchitectural Features
|
||||||
localparam BUS_SUPPORTED = 0;
|
localparam BUS_SUPPORTED = 0;
|
||||||
|
@ -11,20 +11,25 @@ parameter cvw_t P = '{
|
|||||||
ZICSR_SUPPORTED : ZICSR_SUPPORTED,
|
ZICSR_SUPPORTED : ZICSR_SUPPORTED,
|
||||||
ZIFENCEI_SUPPORTED : ZIFENCEI_SUPPORTED,
|
ZIFENCEI_SUPPORTED : ZIFENCEI_SUPPORTED,
|
||||||
COUNTERS : COUNTERS,
|
COUNTERS : COUNTERS,
|
||||||
ZICOUNTERS_SUPPORTED : ZICOUNTERS_SUPPORTED,
|
ZICNTR_SUPPORTED : ZICNTR_SUPPORTED,
|
||||||
|
ZIHPM_SUPPORTED : ZIHPM_SUPPORTED,
|
||||||
ZFH_SUPPORTED : ZFH_SUPPORTED,
|
ZFH_SUPPORTED : ZFH_SUPPORTED,
|
||||||
SSTC_SUPPORTED : SSTC_SUPPORTED,
|
SSTC_SUPPORTED : SSTC_SUPPORTED,
|
||||||
VIRTMEM_SUPPORTED : VIRTMEM_SUPPORTED,
|
VIRTMEM_SUPPORTED : VIRTMEM_SUPPORTED,
|
||||||
VECTORED_INTERRUPTS_SUPPORTED : VECTORED_INTERRUPTS_SUPPORTED,
|
VECTORED_INTERRUPTS_SUPPORTED : VECTORED_INTERRUPTS_SUPPORTED,
|
||||||
BIGENDIAN_SUPPORTED : BIGENDIAN_SUPPORTED,
|
BIGENDIAN_SUPPORTED : BIGENDIAN_SUPPORTED,
|
||||||
SVADU_SUPPORTED : SVADU_SUPPORTED,
|
SVADU_SUPPORTED : SVADU_SUPPORTED,
|
||||||
ZMMUL_SUPPORTED : ZMMUL_SUPPORTED,
|
ZMMUL_SUPPORTED : ZMMUL_SUPPORTED,
|
||||||
|
ZICBOM_SUPPORTED : ZICBOM_SUPPORTED,
|
||||||
|
ZICBOZ_SUPPORTED : ZICBOZ_SUPPORTED,
|
||||||
|
ZICBOP_SUPPORTED : ZICBOP_SUPPORTED,
|
||||||
|
SVPBMT_SUPPORTED : SVPBMT_SUPPORTED,
|
||||||
BUS_SUPPORTED : BUS_SUPPORTED,
|
BUS_SUPPORTED : BUS_SUPPORTED,
|
||||||
DCACHE_SUPPORTED : DCACHE_SUPPORTED,
|
DCACHE_SUPPORTED : DCACHE_SUPPORTED,
|
||||||
ICACHE_SUPPORTED : ICACHE_SUPPORTED,
|
ICACHE_SUPPORTED : ICACHE_SUPPORTED,
|
||||||
ITLB_ENTRIES : ITLB_ENTRIES,
|
ITLB_ENTRIES : ITLB_ENTRIES,
|
||||||
DTLB_ENTRIES : DTLB_ENTRIES,
|
DTLB_ENTRIES : DTLB_ENTRIES,
|
||||||
DCACHE_NUMWAYS : DCACHE_NUMWAYS,
|
DCACHE_NUMWAYS : DCACHE_NUMWAYS,
|
||||||
DCACHE_WAYSIZEINBYTES : DCACHE_WAYSIZEINBYTES,
|
DCACHE_WAYSIZEINBYTES : DCACHE_WAYSIZEINBYTES,
|
||||||
DCACHE_LINELENINBITS : DCACHE_LINELENINBITS,
|
DCACHE_LINELENINBITS : DCACHE_LINELENINBITS,
|
||||||
ICACHE_NUMWAYS : ICACHE_NUMWAYS,
|
ICACHE_NUMWAYS : ICACHE_NUMWAYS,
|
||||||
|
60
sim/FPbuild.txt
Normal file
60
sim/FPbuild.txt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
Procedure for Runnning SoftFloat/TestFloat with Wally
|
||||||
|
|
||||||
|
1.) First, compile SoftFloat and TestFloat by going to the addins
|
||||||
|
directory and finding the specific build directory (e.g.,
|
||||||
|
Linux_x86_64-GCC. Currently, we are using v3e of
|
||||||
|
SoftFloat/TestFloat. I am not sure of the order, but I always compile
|
||||||
|
SoftFloat first as I believe TestFloat uses the static library
|
||||||
|
SoftFloat creates.
|
||||||
|
|
||||||
|
2.) Once compiled both, go to the tests/fp directory and run the
|
||||||
|
create_vectors.sh Linux script. In the past, we have automated this,
|
||||||
|
but I believe this has fallen into more of a manual state lately.
|
||||||
|
|
||||||
|
3.) Then, run remove_spaces.sh which will remove spaces from the
|
||||||
|
output and put underscores between vectors (this helps differentiate
|
||||||
|
the vectors that are generated). Again, this can be combined with
|
||||||
|
Step 2.
|
||||||
|
|
||||||
|
4.) TestFloat is run from wally/cvw/sim and sim-testfloat-batch with
|
||||||
|
its respective test. The format is ./sim-testfloat-add add. All of
|
||||||
|
the tests are listed below. This can be augmented or added to for
|
||||||
|
other FP tests given by the great SoftFloat/TestFloat output.
|
||||||
|
|
||||||
|
cvtint - test integer conversion unit (fcvtint)
|
||||||
|
cvtfp - test floating-point conversion unit (fcvtfp)
|
||||||
|
cmp - test comparison unit's LT, LE, EQ opperations (fcmp)
|
||||||
|
add - test addition
|
||||||
|
fma - test fma
|
||||||
|
mul - test mult with fma
|
||||||
|
sub - test subtraction
|
||||||
|
div - test division
|
||||||
|
sqrt - test square root
|
||||||
|
all - test everything
|
||||||
|
|
||||||
|
4a.) Each test will test all its vectors - if you want to test a
|
||||||
|
subset of the vectors (e.g., only binary16), you should modify the
|
||||||
|
cvw/testbench/tests-fp.h and comment out the tests you do not want to
|
||||||
|
test. The best way to do this is to comment out each item out with
|
||||||
|
the // comment option in SV. For example,
|
||||||
|
|
||||||
|
string f128div[] = '{
|
||||||
|
// "f128_div_rne.tv",
|
||||||
|
// "f128_div_rz.tv",
|
||||||
|
// "f128_div_ru.tv",
|
||||||
|
// "f128_div_rd.tv",
|
||||||
|
// "f128_div_rnm.tv"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
3
src/cache/cache.sv
vendored
3
src/cache/cache.sv
vendored
@ -63,7 +63,7 @@ module cache #(parameter PA_BITS, XLEN, LINELEN, NUMLINES, NUMWAYS, LOGBWPL, W
|
|||||||
localparam OFFSETLEN = $clog2(LINEBYTELEN); // Number of bits in offset field
|
localparam OFFSETLEN = $clog2(LINEBYTELEN); // Number of bits in offset field
|
||||||
localparam SETLEN = $clog2(NUMLINES); // Number of set bits
|
localparam SETLEN = $clog2(NUMLINES); // Number of set bits
|
||||||
localparam SETTOP = SETLEN+OFFSETLEN; // Number of set plus offset bits
|
localparam SETTOP = SETLEN+OFFSETLEN; // Number of set plus offset bits
|
||||||
localparam TAGLEN = PA_BITS - SETTOP; // Number of tag bits
|
localparam TAGLEN = PA_BITS - SETTOP; // Number of tag bits
|
||||||
localparam CACHEWORDSPERLINE = LINELEN/WORDLEN;// Number of words in cache line
|
localparam CACHEWORDSPERLINE = LINELEN/WORDLEN;// Number of words in cache line
|
||||||
localparam LOGCWPL = $clog2(CACHEWORDSPERLINE);// Log2 of ^
|
localparam LOGCWPL = $clog2(CACHEWORDSPERLINE);// Log2 of ^
|
||||||
localparam FLUSHADRTHRESHOLD = NUMLINES - 1; // Used to determine when flush is complete
|
localparam FLUSHADRTHRESHOLD = NUMLINES - 1; // Used to determine when flush is complete
|
||||||
@ -182,6 +182,7 @@ module cache #(parameter PA_BITS, XLEN, LINELEN, NUMLINES, NUMWAYS, LOGBWPL, W
|
|||||||
assign LineWriteData = FetchBuffer;
|
assign LineWriteData = FetchBuffer;
|
||||||
assign LineByteMask = '1;
|
assign LineByteMask = '1;
|
||||||
end
|
end
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Flush logic
|
// Flush logic
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
3
src/cache/cacheLRU.sv
vendored
3
src/cache/cacheLRU.sv
vendored
@ -104,8 +104,7 @@ module cacheLRU
|
|||||||
if (node == NUMWAYS-2) begin
|
if (node == NUMWAYS-2) begin
|
||||||
assign LRUUpdate[lchild] = ~WayEncoded[r];
|
assign LRUUpdate[lchild] = ~WayEncoded[r];
|
||||||
assign LRUUpdate[rchild] = WayEncoded[r];
|
assign LRUUpdate[rchild] = WayEncoded[r];
|
||||||
end
|
end else begin
|
||||||
else begin
|
|
||||||
assign LRUUpdate[lchild] = LRUUpdate[node] & ~WayEncoded[r];
|
assign LRUUpdate[lchild] = LRUUpdate[node] & ~WayEncoded[r];
|
||||||
assign LRUUpdate[rchild] = LRUUpdate[node] & WayEncoded[r];
|
assign LRUUpdate[rchild] = LRUUpdate[node] & WayEncoded[r];
|
||||||
end
|
end
|
||||||
|
14
src/cache/cacheway.sv
vendored
14
src/cache/cacheway.sv
vendored
@ -84,8 +84,7 @@ module cacheway #(parameter PA_BITS, XLEN, NUMLINES=512, LINELEN = 256, TAGLEN =
|
|||||||
// nonzero ways will never see SelFlush=0 while FlushWay=1 since FlushWay only advances on a subset of SelFlush assertion cases.
|
// nonzero ways will never see SelFlush=0 while FlushWay=1 since FlushWay only advances on a subset of SelFlush assertion cases.
|
||||||
assign FlushWayEn = FlushWay & SelFlush;
|
assign FlushWayEn = FlushWay & SelFlush;
|
||||||
assign SelNonHit = FlushWayEn | SetValid | SelWriteback;
|
assign SelNonHit = FlushWayEn | SetValid | SelWriteback;
|
||||||
end
|
end else begin:flushlogic // no flush operation for read-only caches.
|
||||||
else begin:flushlogic // no flush operation for read-only caches.
|
|
||||||
assign SelTag = VictimWay;
|
assign SelTag = VictimWay;
|
||||||
assign SelNonHit = SetValid;
|
assign SelNonHit = SetValid;
|
||||||
end
|
end
|
||||||
@ -135,8 +134,7 @@ module cacheway #(parameter PA_BITS, XLEN, NUMLINES=512, LINELEN = 256, TAGLEN =
|
|||||||
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||||
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||||
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
|
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
|
||||||
end
|
end else begin:wordram // no byte-enable needed for i$.
|
||||||
else begin:wordram // no byte-enable needed for i$.
|
|
||||||
ram1p1rwe #(.DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
|
ram1p1rwe #(.DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
|
||||||
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||||
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||||
@ -154,8 +152,8 @@ module cacheway #(parameter PA_BITS, XLEN, NUMLINES=512, LINELEN = 256, TAGLEN =
|
|||||||
always_ff @(posedge clk) begin // Valid bit array,
|
always_ff @(posedge clk) begin // Valid bit array,
|
||||||
if (reset) ValidBits <= #1 '0;
|
if (reset) ValidBits <= #1 '0;
|
||||||
if(CacheEn) begin
|
if(CacheEn) begin
|
||||||
ValidWay <= #1 ValidBits[CacheSet];
|
ValidWay <= #1 ValidBits[CacheSet];
|
||||||
if(InvalidateCache) ValidBits <= #1 '0; // exclusion-tag: dcache invalidateway
|
if(InvalidateCache) ValidBits <= #1 '0; // exclusion-tag: dcache invalidateway
|
||||||
else if (SetValidEN) ValidBits[CacheSet] <= #1 SetValidWay;
|
else if (SetValidEN) ValidBits[CacheSet] <= #1 SetValidWay;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -175,8 +173,4 @@ module cacheway #(parameter PA_BITS, XLEN, NUMLINES=512, LINELEN = 256, TAGLEN =
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else assign Dirty = 1'b0;
|
end else assign Dirty = 1'b0;
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
5
src/cache/subcachelineread.sv
vendored
5
src/cache/subcachelineread.sv
vendored
@ -43,9 +43,8 @@ module subcachelineread #(parameter LINELEN, WORDLEN,
|
|||||||
logic [LINELEN+(WORDLEN-MUXINTERVAL)-1:0] ReadDataLinePad;
|
logic [LINELEN+(WORDLEN-MUXINTERVAL)-1:0] ReadDataLinePad;
|
||||||
logic [WORDLEN-1:0] ReadDataLineSets [(LINELEN/MUXINTERVAL)-1:0];
|
logic [WORDLEN-1:0] ReadDataLineSets [(LINELEN/MUXINTERVAL)-1:0];
|
||||||
|
|
||||||
if (PADLEN > 0) begin
|
if (PADLEN > 0) assign ReadDataLinePad = {{PADLEN{1'b0}}, ReadDataLine};
|
||||||
assign ReadDataLinePad = {{PADLEN{1'b0}}, ReadDataLine};
|
else assign ReadDataLinePad = ReadDataLine;
|
||||||
end else assign ReadDataLinePad = ReadDataLine;
|
|
||||||
|
|
||||||
genvar index;
|
genvar index;
|
||||||
for (index = 0; index < WORDSPERLINE; index++) begin:readdatalinesetsmux
|
for (index = 0; index < WORDSPERLINE; index++) begin:readdatalinesetsmux
|
||||||
|
@ -45,14 +45,14 @@ module ahbcacheinterface #(
|
|||||||
output logic [2:0] HSIZE, // AHB transaction width
|
output logic [2:0] HSIZE, // AHB transaction width
|
||||||
output logic [2:0] HBURST, // AHB burst length
|
output logic [2:0] HBURST, // AHB burst length
|
||||||
// bus interface buses
|
// bus interface buses
|
||||||
input logic [AHBW-1:0] HRDATA, // AHB read data
|
input logic [AHBW-1:0] HRDATA, // AHB read data
|
||||||
output logic [PA_BITS-1:0] HADDR, // AHB address
|
output logic [PA_BITS-1:0] HADDR, // AHB address
|
||||||
output logic [AHBW-1:0] HWDATA, // AHB write data
|
output logic [AHBW-1:0] HWDATA, // AHB write data
|
||||||
output logic [AHBW/8-1:0] HWSTRB, // AHB byte mask
|
output logic [AHBW/8-1:0] HWSTRB, // AHB byte mask
|
||||||
|
|
||||||
// cache interface
|
// cache interface
|
||||||
input logic [PA_BITS-1:0] CacheBusAdr, // Address of cache line
|
input logic [PA_BITS-1:0] CacheBusAdr, // Address of cache line
|
||||||
input logic [LLEN-1:0] CacheReadDataWordM, // One word of cache line during a writeback
|
input logic [LLEN-1:0] CacheReadDataWordM, // One word of cache line during a writeback
|
||||||
input logic CacheableOrFlushCacheM, // Memory operation is cacheable or flushing D$
|
input logic CacheableOrFlushCacheM, // Memory operation is cacheable or flushing D$
|
||||||
input logic Cacheable, // Memory operation is cachable
|
input logic Cacheable, // Memory operation is cachable
|
||||||
input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch
|
input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch
|
||||||
@ -62,8 +62,8 @@ module ahbcacheinterface #(
|
|||||||
output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr
|
output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr
|
||||||
|
|
||||||
// uncached interface
|
// uncached interface
|
||||||
input logic [PA_BITS-1:0] PAdr, // Physical address of uncached memory operation
|
input logic [PA_BITS-1:0] PAdr, // Physical address of uncached memory operation
|
||||||
input logic [LLEN-1:0] WriteDataM, // IEU write data for uncached store
|
input logic [LLEN-1:0] WriteDataM, // IEU write data for uncached store
|
||||||
input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write
|
input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write
|
||||||
input logic [2:0] Funct3, // Size of uncached memory operation
|
input logic [2:0] Funct3, // Size of uncached memory operation
|
||||||
|
|
||||||
@ -75,11 +75,11 @@ module ahbcacheinterface #(
|
|||||||
|
|
||||||
|
|
||||||
localparam BeatCountThreshold = BEATSPERLINE - 1; // Largest beat index
|
localparam BeatCountThreshold = BEATSPERLINE - 1; // Largest beat index
|
||||||
logic [PA_BITS-1:0] LocalHADDR; // Address after selecting between cached and uncached operation
|
logic [PA_BITS-1:0] LocalHADDR; // Address after selecting between cached and uncached operation
|
||||||
logic [AHBWLOGBWPL-1:0] BeatCountDelayed; // Beat within the cache line in the second (Data) cache stage
|
logic [AHBWLOGBWPL-1:0] BeatCountDelayed; // Beat within the cache line in the second (Data) cache stage
|
||||||
logic CaptureEn; // Enable updating the Fetch buffer with valid data from HRDATA
|
logic CaptureEn; // Enable updating the Fetch buffer with valid data from HRDATA
|
||||||
logic [AHBW/8-1:0] BusByteMaskM; // Byte enables within a word. For cache request all 1s
|
logic [AHBW/8-1:0] BusByteMaskM; // Byte enables within a word. For cache request all 1s
|
||||||
logic [AHBW-1:0] PreHWDATA; // AHB Address phase write data
|
logic [AHBW-1:0] PreHWDATA; // AHB Address phase write data
|
||||||
|
|
||||||
genvar index;
|
genvar index;
|
||||||
|
|
||||||
|
@ -36,19 +36,19 @@ module ahbinterface #(
|
|||||||
input logic HREADY, // AHB peripheral ready
|
input logic HREADY, // AHB peripheral ready
|
||||||
output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
|
output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
|
||||||
output logic HWRITE, // AHB 0: Read operation 1: Write operation
|
output logic HWRITE, // AHB 0: Read operation 1: Write operation
|
||||||
input logic [XLEN-1:0] HRDATA, // AHB read data
|
input logic [XLEN-1:0] HRDATA, // AHB read data
|
||||||
output logic [XLEN-1:0] HWDATA, // AHB write data
|
output logic [XLEN-1:0] HWDATA, // AHB write data
|
||||||
output logic [XLEN/8-1:0] HWSTRB, // AHB byte mask
|
output logic [XLEN/8-1:0] HWSTRB, // AHB byte mask
|
||||||
|
|
||||||
// lsu/ifu interface
|
// lsu/ifu interface
|
||||||
input logic Stall, // Core pipeline is stalled
|
input logic Stall, // Core pipeline is stalled
|
||||||
input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting
|
input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting
|
||||||
input logic [1:0] BusRW, // Memory operation read/write control: 10: read, 01: write
|
input logic [1:0] BusRW, // Memory operation read/write control: 10: read, 01: write
|
||||||
input logic [XLEN/8-1:0] ByteMask, // Bytes enables within a word
|
input logic [XLEN/8-1:0] ByteMask, // Bytes enables within a word
|
||||||
input logic [XLEN-1:0] WriteData, // IEU write data for a store
|
input logic [XLEN-1:0] WriteData, // IEU write data for a store
|
||||||
output logic BusStall, // Bus is busy with an in flight memory operation
|
output logic BusStall, // Bus is busy with an in flight memory operation
|
||||||
output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt
|
output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt
|
||||||
output logic [(LSU ? XLEN : 32)-1:0] FetchBuffer // Register to hold HRDATA after arriving from the bus
|
output logic [(LSU ? XLEN : 32)-1:0] FetchBuffer // Register to hold HRDATA after arriving from the bus
|
||||||
);
|
);
|
||||||
|
|
||||||
logic CaptureEn;
|
logic CaptureEn;
|
||||||
|
@ -46,14 +46,14 @@ module controllerinput #(
|
|||||||
input logic HWRITEIn, // Manager input. AHB 0: Read operation 1: Write operation
|
input logic HWRITEIn, // Manager input. AHB 0: Read operation 1: Write operation
|
||||||
input logic [2:0] HSIZEIn, // Manager input. AHB transaction width
|
input logic [2:0] HSIZEIn, // Manager input. AHB transaction width
|
||||||
input logic [2:0] HBURSTIn, // Manager input. AHB burst length
|
input logic [2:0] HBURSTIn, // Manager input. AHB burst length
|
||||||
input logic [PA_BITS-1:0] HADDRIn, // Manager input. AHB address
|
input logic [PA_BITS-1:0] HADDRIn, // Manager input. AHB address
|
||||||
output logic HREADYOut, // Indicate to manager the peripheral is not busy and another manager does not have priority
|
output logic HREADYOut, // Indicate to manager the peripheral is not busy and another manager does not have priority
|
||||||
// controller output
|
// controller output
|
||||||
output logic [1:0] HTRANSOut, // Arbitrated manager transaction. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
|
output logic [1:0] HTRANSOut, // Arbitrated manager transaction. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
|
||||||
output logic HWRITEOut, // Arbitrated manager transaction. AHB 0: Read operation 1: Write operation
|
output logic HWRITEOut, // Arbitrated manager transaction. AHB 0: Read operation 1: Write operation
|
||||||
output logic [2:0] HSIZEOut, // Arbitrated manager transaction. AHB transaction width
|
output logic [2:0] HSIZEOut, // Arbitrated manager transaction. AHB transaction width
|
||||||
output logic [2:0] HBURSTOut, // Arbitrated manager transaction. AHB burst length
|
output logic [2:0] HBURSTOut, // Arbitrated manager transaction. AHB burst length
|
||||||
output logic [PA_BITS-1:0] HADDROut, // Arbitrated manager transaction. AHB address
|
output logic [PA_BITS-1:0] HADDROut, // Arbitrated manager transaction. AHB address
|
||||||
input logic HREADYIn // Peripheral ready
|
input logic HREADYIn // Peripheral ready
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ module controllerinput #(
|
|||||||
logic [2:0] HSIZESave;
|
logic [2:0] HSIZESave;
|
||||||
logic [2:0] HBURSTSave;
|
logic [2:0] HBURSTSave;
|
||||||
logic [1:0] HTRANSSave;
|
logic [1:0] HTRANSSave;
|
||||||
logic [PA_BITS-1:0] HADDRSave;
|
logic [PA_BITS-1:0] HADDRSave;
|
||||||
|
|
||||||
if (SAVE_ENABLED) begin
|
if (SAVE_ENABLED) begin
|
||||||
flopenr #(1+3+3+2+PA_BITS) SaveReg(HCLK, ~HRESETn, Save,
|
flopenr #(1+3+3+2+PA_BITS) SaveReg(HCLK, ~HRESETn, Save,
|
||||||
@ -83,6 +83,3 @@ module controllerinput #(
|
|||||||
assign HREADYOut = HREADYIn & ~Disable;
|
assign HREADYOut = HREADYIn & ~Disable;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,25 +37,25 @@ module ebu #(parameter XLEN, PA_BITS, AHBW)(
|
|||||||
input logic [1:0] IFUHTRANS, // IFU AHB transaction request
|
input logic [1:0] IFUHTRANS, // IFU AHB transaction request
|
||||||
input logic [2:0] IFUHSIZE, // IFU AHB transaction size
|
input logic [2:0] IFUHSIZE, // IFU AHB transaction size
|
||||||
input logic [2:0] IFUHBURST, // IFU AHB burst length
|
input logic [2:0] IFUHBURST, // IFU AHB burst length
|
||||||
input logic [PA_BITS-1:0] IFUHADDR, // IFU AHB address
|
input logic [PA_BITS-1:0] IFUHADDR, // IFU AHB address
|
||||||
output logic IFUHREADY, // AHB peripheral ready gated by possible non-grant
|
output logic IFUHREADY, // AHB peripheral ready gated by possible non-grant
|
||||||
// Signals from LSU
|
// Signals from LSU
|
||||||
input logic [1:0] LSUHTRANS, // LSU AHB transaction request
|
input logic [1:0] LSUHTRANS, // LSU AHB transaction request
|
||||||
input logic LSUHWRITE, // LSU AHB transaction direction. 1: write, 0: read
|
input logic LSUHWRITE, // LSU AHB transaction direction. 1: write, 0: read
|
||||||
input logic [2:0] LSUHSIZE, // LSU AHB size
|
input logic [2:0] LSUHSIZE, // LSU AHB size
|
||||||
input logic [2:0] LSUHBURST, // LSU AHB burst length
|
input logic [2:0] LSUHBURST, // LSU AHB burst length
|
||||||
input logic [PA_BITS-1:0] LSUHADDR, // LSU AHB address
|
input logic [PA_BITS-1:0] LSUHADDR, // LSU AHB address
|
||||||
input logic [XLEN-1:0] LSUHWDATA, // initially support AHBW = XLEN
|
input logic [XLEN-1:0] LSUHWDATA, // initially support AHBW = XLEN
|
||||||
input logic [XLEN/8-1:0] LSUHWSTRB, // AHB byte mask
|
input logic [XLEN/8-1:0] LSUHWSTRB, // AHB byte mask
|
||||||
output logic LSUHREADY, // AHB peripheral. Never gated as LSU always has priority
|
output logic LSUHREADY, // AHB peripheral. Never gated as LSU always has priority
|
||||||
|
|
||||||
// AHB-Lite external signals
|
// AHB-Lite external signals
|
||||||
output logic HCLK, HRESETn,
|
output logic HCLK, HRESETn,
|
||||||
input logic HREADY, // AHB peripheral ready
|
input logic HREADY, // AHB peripheral ready
|
||||||
input logic HRESP, // AHB peripheral response. 0: OK 1: Error
|
input logic HRESP, // AHB peripheral response. 0: OK 1: Error
|
||||||
output logic [PA_BITS-1:0] HADDR, // AHB address to peripheral after arbitration
|
output logic [PA_BITS-1:0] HADDR, // AHB address to peripheral after arbitration
|
||||||
output logic [AHBW-1:0] HWDATA, // AHB Write data after arbitration
|
output logic [AHBW-1:0] HWDATA, // AHB Write data after arbitration
|
||||||
output logic [XLEN/8-1:0] HWSTRB, // AHB byte write enables after arbitration
|
output logic [XLEN/8-1:0] HWSTRB, // AHB byte write enables after arbitration
|
||||||
output logic HWRITE, // AHB transaction direction after arbitration
|
output logic HWRITE, // AHB transaction direction after arbitration
|
||||||
output logic [2:0] HSIZE, // AHB transaction size after arbitration
|
output logic [2:0] HSIZE, // AHB transaction size after arbitration
|
||||||
output logic [2:0] HBURST, // AHB burst length after arbitration
|
output logic [2:0] HBURST, // AHB burst length after arbitration
|
||||||
@ -71,13 +71,13 @@ module ebu #(parameter XLEN, PA_BITS, AHBW)(
|
|||||||
logic IFUDisable;
|
logic IFUDisable;
|
||||||
logic IFUSelect;
|
logic IFUSelect;
|
||||||
|
|
||||||
logic [PA_BITS-1:0] IFUHADDROut;
|
logic [PA_BITS-1:0] IFUHADDROut;
|
||||||
logic [1:0] IFUHTRANSOut;
|
logic [1:0] IFUHTRANSOut;
|
||||||
logic [2:0] IFUHBURSTOut;
|
logic [2:0] IFUHBURSTOut;
|
||||||
logic [2:0] IFUHSIZEOut;
|
logic [2:0] IFUHSIZEOut;
|
||||||
logic IFUHWRITEOut;
|
logic IFUHWRITEOut;
|
||||||
|
|
||||||
logic [PA_BITS-1:0] LSUHADDROut;
|
logic [PA_BITS-1:0] LSUHADDROut;
|
||||||
logic [1:0] LSUHTRANSOut;
|
logic [1:0] LSUHTRANSOut;
|
||||||
logic [2:0] LSUHBURSTOut;
|
logic [2:0] LSUHBURSTOut;
|
||||||
logic [2:0] LSUHSIZEOut;
|
logic [2:0] LSUHSIZEOut;
|
||||||
|
@ -33,7 +33,7 @@ module fclassify import cvw::*; #(parameter cvw_t P) (
|
|||||||
input logic XSubnorm, // is Subnormal
|
input logic XSubnorm, // is Subnormal
|
||||||
input logic XZero, // is zero
|
input logic XZero, // is zero
|
||||||
input logic XInf, // is infinity
|
input logic XInf, // is infinity
|
||||||
output logic [P.XLEN-1:0] ClassRes // classify result
|
output logic [P.XLEN-1:0] ClassRes // classify result
|
||||||
);
|
);
|
||||||
|
|
||||||
logic PInf, PZero, PNorm, PSubnorm; // is the input a positive infinity/zero/normal/subnormal
|
logic PInf, PZero, PNorm, PSubnorm; // is the input a positive infinity/zero/normal/subnormal
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// fcmp.sv
|
// fcmp.sv
|
||||||
//
|
//
|
||||||
@ -36,23 +35,23 @@
|
|||||||
|
|
||||||
module fcmp import cvw::*; #(parameter cvw_t P) (
|
module fcmp import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.FMTBITS-1:0] Fmt, // format of fp number
|
input logic [P.FMTBITS-1:0] Fmt, // format of fp number
|
||||||
input logic [2:0] OpCtrl, // see above table
|
input logic [2:0] OpCtrl, // see above table
|
||||||
input logic Xs, Ys, // input signs
|
input logic Xs, Ys, // input signs
|
||||||
input logic [P.NE-1:0] Xe, Ye, // input exponents
|
input logic [P.NE-1:0] Xe, Ye, // input exponents
|
||||||
input logic [P.NF:0] Xm, Ym, // input mantissa
|
input logic [P.NF:0] Xm, Ym, // input mantissa
|
||||||
input logic XZero, YZero, // is zero
|
input logic XZero, YZero, // is zero
|
||||||
input logic XNaN, YNaN, // is NaN
|
input logic XNaN, YNaN, // is NaN
|
||||||
input logic XSNaN, YSNaN, // is signaling NaN
|
input logic XSNaN, YSNaN, // is signaling NaN
|
||||||
input logic [P.FLEN-1:0] X, Y, // original inputs (before unpacker)
|
input logic [P.FLEN-1:0] X, Y, // original inputs (before unpacker)
|
||||||
output logic CmpNV, // invalid flag
|
output logic CmpNV, // invalid flag
|
||||||
output logic [P.FLEN-1:0] CmpFpRes, // compare floating-point result
|
output logic [P.FLEN-1:0] CmpFpRes, // compare floating-point result
|
||||||
output logic [P.XLEN-1:0] CmpIntRes // compare integer result
|
output logic [P.XLEN-1:0] CmpIntRes // compare integer result
|
||||||
);
|
);
|
||||||
|
|
||||||
logic LTabs, LT, EQ; // is X < or > or = Y
|
logic LTabs, LT, EQ; // is X < or > or = Y
|
||||||
logic [P.FLEN-1:0] NaNRes; // NaN result
|
logic [P.FLEN-1:0] NaNRes; // NaN result
|
||||||
logic BothZero; // are both inputs zero
|
logic BothZero; // are both inputs zero
|
||||||
logic EitherNaN, EitherSNaN; // are either input a (signaling) NaN
|
logic EitherNaN, EitherSNaN; // are either input a (signaling) NaN
|
||||||
|
|
||||||
assign LTabs= {1'b0, Xe, Xm} < {1'b0, Ye, Ym}; // unsigned comparison, treating FP as integers
|
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 LT = (Xs & ~Ys) | (Xs & Ys & ~LTabs & ~EQ) | (~Xs & ~Ys & LTabs); // signed comparison
|
||||||
@ -62,7 +61,6 @@ module fcmp import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign EitherNaN = XNaN|YNaN;
|
assign EitherNaN = XNaN|YNaN;
|
||||||
assign EitherSNaN = XSNaN|YSNaN;
|
assign EitherSNaN = XSNaN|YSNaN;
|
||||||
|
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
// Min/Max - if an input is a signaling NaN set invalid flag
|
// Min/Max - if an input is a signaling NaN set invalid flag
|
||||||
// LT/LE - signaling - sets invalid if NaN input
|
// LT/LE - signaling - sets invalid if NaN input
|
||||||
@ -85,11 +83,11 @@ module fcmp import cvw::*; #(parameter cvw_t P) (
|
|||||||
// select the NaN result
|
// select the NaN result
|
||||||
if (P.FPSIZES == 1)
|
if (P.FPSIZES == 1)
|
||||||
if(P.IEEE754) assign NaNRes = {Xs, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]};
|
if(P.IEEE754) assign NaNRes = {Xs, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]};
|
||||||
else assign NaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}};
|
else assign NaNRes = {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}};
|
||||||
|
|
||||||
else if (P.FPSIZES == 2)
|
else if (P.FPSIZES == 2)
|
||||||
if(P.IEEE754) assign NaNRes = Fmt ? {Xs, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]} : {{P.FLEN-P.LEN1{1'b1}}, Xs, {P.NE1{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.NF1]};
|
if(P.IEEE754) assign NaNRes = Fmt ? {Xs, {P.NE{1'b1}}, 1'b1, Xm[P.NF-2:0]} : {{P.FLEN-P.LEN1{1'b1}}, Xs, {P.NE1{1'b1}}, 1'b1, Xm[P.NF-2:P.NF-P.NF1]};
|
||||||
else assign NaNRes = Fmt ? {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, (P.NF1-1)'(0)};
|
else assign NaNRes = Fmt ? {1'b0, {P.NE{1'b1}}, 1'b1, {P.NF-1{1'b0}}} : {{P.FLEN-P.LEN1{1'b1}}, 1'b0, {P.NE1{1'b1}}, 1'b1, (P.NF1-1)'(0)};
|
||||||
|
|
||||||
else if (P.FPSIZES == 3)
|
else if (P.FPSIZES == 3)
|
||||||
always_comb
|
always_comb
|
||||||
@ -123,7 +121,6 @@ module fcmp import cvw::*; #(parameter cvw_t P) (
|
|||||||
else NaNRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, (P.H_NF-1)'(0)};
|
else NaNRes = {{P.FLEN-P.H_LEN{1'b1}}, 1'b0, {P.H_NE{1'b1}}, 1'b1, (P.H_NF-1)'(0)};
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
|
||||||
// Min/Max
|
// Min/Max
|
||||||
// - outputs the min/max of X and Y
|
// - outputs the min/max of X and Y
|
||||||
// - -0 < 0
|
// - -0 < 0
|
||||||
@ -154,5 +151,4 @@ module fcmp import cvw::*; #(parameter cvw_t P) (
|
|||||||
// - inf = inf and -inf = -inf
|
// - inf = inf and -inf = -inf
|
||||||
// - return 0 if comparison with NaN (unordered)
|
// - return 0 if comparison with NaN (unordered)
|
||||||
assign CmpIntRes = {(P.XLEN-1)'(0), (((EQ|BothZero)&OpCtrl[1])|(LT&OpCtrl[0]&~BothZero))&~EitherNaN};
|
assign CmpIntRes = {(P.XLEN-1)'(0), (((EQ|BothZero)&OpCtrl[1])|(LT&OpCtrl[0]&~BothZero))&~EitherNaN};
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -27,57 +27,57 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module fctrl import cvw::*; #(parameter cvw_t P) (
|
module fctrl import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
// input control signals
|
// input control signals
|
||||||
input logic StallE, StallM, StallW, // stall signals
|
input logic StallE, StallM, StallW, // stall signals
|
||||||
input logic FlushE, FlushM, FlushW, // flush signals
|
input logic FlushE, FlushM, FlushW, // flush signals
|
||||||
input logic IntDivE, // is inteteger division
|
input logic IntDivE, // is inteteger division
|
||||||
input logic [2:0] FRM_REGW, // rounding mode from CSR
|
input logic [2:0] FRM_REGW, // rounding mode from CSR
|
||||||
input logic [1:0] STATUS_FS, // is FPU enabled?
|
input logic [1:0] STATUS_FS, // is FPU enabled?
|
||||||
input logic FDivBusyE, // is the divider busy
|
input logic FDivBusyE, // is the divider busy
|
||||||
// intruction
|
// intruction
|
||||||
input logic [31:0] InstrD, // the full instruction
|
input logic [31:0] InstrD, // the full instruction
|
||||||
input logic [6:0] Funct7D, // bits 31:25 of instruction - may contain percision
|
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 [6:0] OpD, // bits 6:0 of instruction
|
||||||
input logic [4:0] Rs2D, // bits 24:20 of instruction
|
input logic [4:0] Rs2D, // bits 24:20 of instruction
|
||||||
input logic [2:0] Funct3D, Funct3E, // bits 14:12 of instruction - may contain rounding mode
|
input logic [2:0] Funct3D, Funct3E, // bits 14:12 of instruction - may contain rounding mode
|
||||||
// input mux selections
|
// input mux selections
|
||||||
output logic XEnD, YEnD, ZEnD, // enable inputs
|
output logic XEnD, YEnD, ZEnD, // enable inputs
|
||||||
output logic XEnE, YEnE, ZEnE, // enable inputs
|
output logic XEnE, YEnE, ZEnE, // enable inputs
|
||||||
// opperation mux selections
|
// opperation mux selections
|
||||||
output logic FCvtIntE, FCvtIntW, // convert to integer opperation
|
output logic FCvtIntE, FCvtIntW, // convert to integer opperation
|
||||||
output logic [2:0] FrmM, // FP rounding mode
|
output logic [2:0] FrmM, // FP rounding mode
|
||||||
output logic [P.FMTBITS-1:0] FmtE, FmtM, // FP format
|
output logic [P.FMTBITS-1:0] FmtE, FmtM, // FP format
|
||||||
output logic [2:0] OpCtrlE, OpCtrlM, // Select which opperation to do in each component
|
output logic [2:0] OpCtrlE, OpCtrlM, // Select which opperation to do in each component
|
||||||
output logic FpLoadStoreM, // FP load or store instruction
|
output logic FpLoadStoreM, // FP load or store instruction
|
||||||
output logic [1:0] PostProcSelE, PostProcSelM, // select result in the post processing unit
|
output logic [1:0] PostProcSelE, PostProcSelM, // select result in the post processing unit
|
||||||
output logic [1:0] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage
|
output logic [1:0] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage
|
||||||
// register control signals
|
// register control signals
|
||||||
output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable
|
output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable
|
||||||
output logic FWriteIntE, FWriteIntM, // Write to integer register
|
output logic FWriteIntE, FWriteIntM, // Write to integer register
|
||||||
output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input
|
output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input
|
||||||
output logic [4:0] Adr1E, Adr2E, Adr3E, // adresses of each input
|
output logic [4:0] Adr1E, Adr2E, Adr3E, // adresses of each input
|
||||||
// other control signals
|
// other control signals
|
||||||
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||||
output logic FDivStartE, IDivStartE // Start division or squareroot
|
output logic FDivStartE, IDivStartE // Start division or squareroot
|
||||||
);
|
);
|
||||||
|
|
||||||
`define FCTRLW 12
|
`define FCTRLW 12
|
||||||
|
|
||||||
logic [`FCTRLW-1:0] ControlsD; // control signals
|
logic [`FCTRLW-1:0] ControlsD; // control signals
|
||||||
logic FRegWriteD; // FP register write enable
|
logic FRegWriteD; // FP register write enable
|
||||||
logic FDivStartD; // start division/sqrt
|
logic FDivStartD; // start division/sqrt
|
||||||
logic FWriteIntD; // integer register write enable
|
logic FWriteIntD; // integer register write enable
|
||||||
logic [2:0] OpCtrlD; // Select which opperation to do in each component
|
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] PostProcSelD; // select result in the post processing unit
|
||||||
logic [1:0] FResSelD; // Select one of the results that finish in the memory stage
|
logic [1:0] FResSelD; // Select one of the results that finish in the memory stage
|
||||||
logic [2:0] FrmD, FrmE; // FP rounding mode
|
logic [2:0] FrmD, FrmE; // FP rounding mode
|
||||||
logic [P.FMTBITS-1:0] FmtD; // FP format
|
logic [P.FMTBITS-1:0] FmtD; // FP format
|
||||||
logic [1:0] Fmt, Fmt2; // format - before possible reduction
|
logic [1:0] Fmt, Fmt2; // format - before possible reduction
|
||||||
logic SupportedFmt; // is the format supported
|
logic SupportedFmt; // is the format supported
|
||||||
logic SupportedFmt2; // is the source format supported for fp -> fp
|
logic SupportedFmt2; // is the source format supported for fp -> fp
|
||||||
logic FCvtIntD, FCvtIntM; // convert to integer opperation
|
logic FCvtIntD, FCvtIntM; // convert to integer opperation
|
||||||
|
|
||||||
// FPU Instruction Decoder
|
// FPU Instruction Decoder
|
||||||
assign Fmt = Funct7D[1:0];
|
assign Fmt = Funct7D[1:0];
|
||||||
@ -97,7 +97,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
|||||||
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0; // for anything other than loads and stores, check for supported format
|
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0; // for anything other than loads and stores, check for supported format
|
||||||
else begin
|
else begin
|
||||||
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0; // default: non-implemented instruction
|
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0; // default: non-implemented instruction
|
||||||
/* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed
|
/* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed
|
||||||
case(OpD)
|
case(OpD)
|
||||||
7'b0000111: case(Funct3D)
|
7'b0000111: case(Funct3D)
|
||||||
3'b010: ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flw
|
3'b010: ControlsD = `FCTRLW'b1_0_10_00_0xx_0_0_0; // flw
|
||||||
@ -232,8 +232,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [1:0] FmtTmp;
|
logic [1:0] FmtTmp;
|
||||||
assign FmtTmp = ((Funct7D[6:3] == 4'b0100)&OpD[4]) ? Rs2D[1:0] : (~OpD[6]&(&OpD[2:0])) ? {~Funct3D[1], ~(Funct3D[1]^Funct3D[0])} : Funct7D[1:0];
|
assign FmtTmp = ((Funct7D[6:3] == 4'b0100)&OpD[4]) ? Rs2D[1:0] : (~OpD[6]&(&OpD[2:0])) ? {~Funct3D[1], ~(Funct3D[1]^Funct3D[0])} : Funct7D[1:0];
|
||||||
assign FmtD = (P.FMT == FmtTmp);
|
assign FmtD = (P.FMT == FmtTmp);
|
||||||
end
|
end else if (P.FPSIZES == 3|P.FPSIZES == 4)
|
||||||
else if (P.FPSIZES == 3|P.FPSIZES == 4)
|
|
||||||
assign FmtD = ((Funct7D[6:3] == 4'b0100)&OpD[4]) ? Rs2D[1:0] : Funct7D[1:0];
|
assign FmtD = ((Funct7D[6:3] == 4'b0100)&OpD[4]) ? Rs2D[1:0] : Funct7D[1:0];
|
||||||
|
|
||||||
// Enables indicate that a source register is used and may need stalls. Also indicate special cases for infinity or NaN.
|
// Enables indicate that a source register is used and may need stalls. Also indicate special cases for infinity or NaN.
|
||||||
@ -250,12 +249,9 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
|||||||
((FResSelD==2'b11)&(PostProcSelD==2'b00))| // mv float to int
|
((FResSelD==2'b11)&(PostProcSelD==2'b00))| // mv float to int
|
||||||
((FResSelD==2'b01)&((PostProcSelD==2'b00)|((PostProcSelD==2'b01)&OpCtrlD[0])))); // cvt both or sqrt
|
((FResSelD==2'b01)&((PostProcSelD==2'b00)|((PostProcSelD==2'b01)&OpCtrlD[0])))); // cvt both or sqrt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Z - fma ops only
|
// Z - fma ops only
|
||||||
assign ZEnD = (PostProcSelD==2'b10)&(~OpCtrlD[2]|OpCtrlD[1]); // fma, add, sub
|
assign ZEnD = (PostProcSelD==2'b10)&(~OpCtrlD[2]|OpCtrlD[1]); // fma, add, sub
|
||||||
|
|
||||||
|
|
||||||
// Final Res Sel:
|
// Final Res Sel:
|
||||||
// fp int
|
// fp int
|
||||||
// 00 other cmp
|
// 00 other cmp
|
||||||
@ -321,7 +317,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// Integer division on FPU divider
|
// Integer division on FPU divider
|
||||||
if (P.M_SUPPORTED & P.IDIV_ON_FPU) assign IDivStartE = IntDivE;
|
if (P.M_SUPPORTED & P.IDIV_ON_FPU) assign IDivStartE = IntDivE;
|
||||||
else assign IDivStartE = 0;
|
else assign IDivStartE = 0;
|
||||||
|
|
||||||
// E/M pipleine register
|
// E/M pipleine register
|
||||||
flopenrc #(13+int'(P.FMTBITS)) EMCtrlReg (clk, reset, FlushM, ~StallM,
|
flopenrc #(13+int'(P.FMTBITS)) EMCtrlReg (clk, reset, FlushM, ~StallM,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// fcvt.sv
|
// fcvt.sv
|
||||||
//
|
//
|
||||||
@ -96,7 +95,7 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
|||||||
// int -> fp : | positive integer | 00000... (if needed) |
|
// int -> fp : | positive integer | 00000... (if needed) |
|
||||||
// fp -> fp : | fraction | 00000... (if needed) |
|
// fp -> fp : | fraction | 00000... (if needed) |
|
||||||
assign LzcInFull = IntToFp ? {TrimInt, {P.CVTLEN-P.XLEN+1{1'b0}}} :
|
assign LzcInFull = IntToFp ? {TrimInt, {P.CVTLEN-P.XLEN+1{1'b0}}} :
|
||||||
{Xm, {P.CVTLEN-P.NF{1'b0}}};
|
{Xm, {P.CVTLEN-P.NF{1'b0}}};
|
||||||
|
|
||||||
// used as shifter input in postprocessor
|
// used as shifter input in postprocessor
|
||||||
assign LzcIn = LzcInFull[P.CVTLEN-1:0];
|
assign LzcIn = LzcInFull[P.CVTLEN-1:0];
|
||||||
@ -222,5 +221,4 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
|||||||
if(Int64) Cs = Int[P.XLEN-1]&Signed;
|
if(Int64) Cs = Int[P.XLEN-1]&Signed;
|
||||||
else Cs = Int[31]&Signed;
|
else Cs = Int[31]&Signed;
|
||||||
else Cs = Xs;
|
else Cs = Xs;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -50,9 +50,10 @@ module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) (
|
|||||||
else if (P.FPSIZES == 3)
|
else if (P.FPSIZES == 3)
|
||||||
always_comb
|
always_comb
|
||||||
case (FmtE)
|
case (FmtE)
|
||||||
P.FMT: Nf = P.NF;
|
P.FMT: Nf = P.NF;
|
||||||
P.FMT1: Nf = P.NF1;
|
P.FMT1: Nf = P.NF1;
|
||||||
P.FMT2: Nf = P.NF2;
|
P.FMT2: Nf = P.NF2;
|
||||||
|
default: Nf = 'x; // shouldn't happen
|
||||||
endcase
|
endcase
|
||||||
else if (P.FPSIZES == 4)
|
else if (P.FPSIZES == 4)
|
||||||
always_comb
|
always_comb
|
||||||
|
@ -56,7 +56,6 @@ module fhazard(
|
|||||||
// if the needed value is in the writeback stage
|
// if the needed value is in the writeback stage
|
||||||
end else if ((Adr1E == RdW) & FRegWriteW) ForwardXE = 2'b01; // choose FResult64W
|
end else if ((Adr1E == RdW) & FRegWriteW) ForwardXE = 2'b01; // choose FResult64W
|
||||||
|
|
||||||
|
|
||||||
// if the needed value is in the memory stage - input 2
|
// if the needed value is in the memory stage - input 2
|
||||||
if ((Adr2E == RdM) & FRegWriteM) begin
|
if ((Adr2E == RdM) & FRegWriteM) begin
|
||||||
// if the result will be FResM (can be taken from the memory stage)
|
// if the result will be FResM (can be taken from the memory stage)
|
||||||
@ -64,7 +63,6 @@ module fhazard(
|
|||||||
// if the needed value is in the writeback stage
|
// if the needed value is in the writeback stage
|
||||||
end else if ((Adr2E == RdW) & FRegWriteW) ForwardYE = 2'b01; // choose FResult64W
|
end else if ((Adr2E == RdW) & FRegWriteW) ForwardYE = 2'b01; // choose FResult64W
|
||||||
|
|
||||||
|
|
||||||
// if the needed value is in the memory stage - input 3
|
// if the needed value is in the memory stage - input 3
|
||||||
if ((Adr3E == RdM) & FRegWriteM) begin
|
if ((Adr3E == RdM) & FRegWriteM) begin
|
||||||
// if the result will be FResM (can be taken from the memory stage)
|
// if the result will be FResM (can be taken from the memory stage)
|
||||||
@ -72,5 +70,4 @@ module fhazard(
|
|||||||
// if the needed value is in the writeback stage
|
// if the needed value is in the writeback stage
|
||||||
end else if ((Adr3E == RdW) & FRegWriteW) ForwardZE = 2'b01; // choose FResult64W
|
end else if ((Adr3E == RdW) & FRegWriteW) ForwardZE = 2'b01; // choose FResult64W
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
181
src/fpu/fpu.sv
181
src/fpu/fpu.sv
@ -27,40 +27,40 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module fpu import cvw::*; #(parameter cvw_t P) (
|
module fpu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
// Hazards
|
// Hazards
|
||||||
input logic StallE, StallM, StallW, // stall signals (from HZU)
|
input logic StallE, StallM, StallW, // stall signals (from HZU)
|
||||||
input logic FlushE, FlushM, FlushW, // flush signals (from HZU)
|
input logic FlushE, FlushM, FlushW, // flush signals (from HZU)
|
||||||
output logic FPUStallD, // Stall the decode stage (To HZU)
|
output logic FPUStallD, // Stall the decode stage (To HZU)
|
||||||
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU)
|
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU)
|
||||||
// CSRs
|
// CSRs
|
||||||
input logic [1:0] STATUS_FS, // Is floating-point enabled? (From privileged unit)
|
input logic [1:0] STATUS_FS, // Is floating-point enabled? (From privileged unit)
|
||||||
input logic [2:0] FRM_REGW, // Rounding mode (from CSR)
|
input logic [2:0] FRM_REGW, // Rounding mode (from CSR)
|
||||||
// Decode stage
|
// Decode stage
|
||||||
input logic [31:0] InstrD, // instruction (from IFU)
|
input logic [31:0] InstrD, // instruction (from IFU)
|
||||||
// Execute stage
|
// Execute stage
|
||||||
input logic [2:0] Funct3E, // Funct fields of instruction specify type of operations
|
input logic [2:0] Funct3E, // Funct fields of instruction specify type of operations
|
||||||
input logic IntDivE, W64E, // Integer division on FPU
|
input logic IntDivE, W64E, // Integer division on FPU
|
||||||
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Integer input for convert, move, and int div (from IEU)
|
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Integer input for convert, move, and int div (from IEU)
|
||||||
input logic [4:0] RdE, // which FP register to write to (from IEU)
|
input logic [4:0] RdE, // which FP register to write to (from IEU)
|
||||||
output logic FWriteIntE, // integer register write enable (to IEU)
|
output logic FWriteIntE, // integer register write enable (to IEU)
|
||||||
output logic FCvtIntE, // Convert to int (to IEU)
|
output logic FCvtIntE, // Convert to int (to IEU)
|
||||||
// Memory stage
|
// Memory stage
|
||||||
input logic [2:0] Funct3M, // Funct fields of instruction specify type of operations
|
input logic [2:0] Funct3M, // Funct fields of instruction specify type of operations
|
||||||
input logic [4:0] RdM, // which FP register to write to (from IEU)
|
input logic [4:0] RdM, // which FP register to write to (from IEU)
|
||||||
output logic FRegWriteM, // FP register write enable (to privileged unit)
|
output logic FRegWriteM, // FP register write enable (to privileged unit)
|
||||||
output logic FpLoadStoreM, // Fp load instruction? (to LSU)
|
output logic FpLoadStoreM, // Fp load instruction? (to LSU)
|
||||||
output logic [P.FLEN-1:0] FWriteDataM, // Data to be written to memory (to LSU)
|
output logic [P.FLEN-1:0] FWriteDataM, // Data to be written to memory (to LSU)
|
||||||
output logic [P.XLEN-1:0] FIntResM, // data to be written to integer register (to IEU)
|
output logic [P.XLEN-1:0] FIntResM, // data to be written to integer register (to IEU)
|
||||||
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction (to IFU)
|
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction (to IFU)
|
||||||
output logic [4:0] SetFflagsM, // FPU flags (to privileged unit)
|
output logic [4:0] SetFflagsM, // FPU flags (to privileged unit)
|
||||||
// Writeback stage
|
// Writeback stage
|
||||||
input logic [4:0] RdW, // which FP register to write to (from IEU)
|
input logic [4:0] RdW, // which FP register to write to (from IEU)
|
||||||
input logic [P.FLEN-1:0] ReadDataW, // Read data (from LSU)
|
input logic [P.FLEN-1:0] ReadDataW, // Read data (from LSU)
|
||||||
output logic [P.XLEN-1:0] FCvtIntResW, // convert result to to be written to integer register (to IEU)
|
output logic [P.XLEN-1:0] FCvtIntResW, // convert result to to be written to integer register (to IEU)
|
||||||
output logic FCvtIntW, // select FCvtIntRes (to IEU)
|
output logic FCvtIntW, // select FCvtIntRes (to IEU)
|
||||||
output logic [P.XLEN-1:0] FIntDivResultW // Result from integer division (to IEU)
|
output logic [P.XLEN-1:0] FIntDivResultW // Result from integer division (to IEU)
|
||||||
);
|
);
|
||||||
|
|
||||||
// RISC-V FPU specifics:
|
// RISC-V FPU specifics:
|
||||||
@ -68,86 +68,86 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
|||||||
// - RISC-V detects underflow after rounding
|
// - RISC-V detects underflow after rounding
|
||||||
|
|
||||||
// control signals
|
// control signals
|
||||||
logic FRegWriteW; // FP register write enable
|
logic FRegWriteW; // FP register write enable
|
||||||
logic [2:0] FrmM; // FP rounding mode
|
logic [2:0] FrmM; // FP rounding mode
|
||||||
logic [P.FMTBITS-1:0] FmtE, FmtM; // FP precision 0-single 1-double
|
logic [P.FMTBITS-1:0] FmtE, FmtM; // FP precision 0-single 1-double
|
||||||
logic FDivStartE, IDivStartE; // Start division or squareroot
|
logic FDivStartE, IDivStartE; // Start division or squareroot
|
||||||
logic FWriteIntM; // Write to integer register
|
logic FWriteIntM; // Write to integer register
|
||||||
logic [1:0] ForwardXE, ForwardYE, ForwardZE; // forwarding mux control signals
|
logic [1:0] ForwardXE, ForwardYE, ForwardZE; // forwarding mux control signals
|
||||||
logic [2:0] OpCtrlE, OpCtrlM; // Select which opperation to do in each component
|
logic [2:0] OpCtrlE, OpCtrlM; // Select which opperation to do in each component
|
||||||
logic [1:0] FResSelE, FResSelM, FResSelW; // Select one of the results that finish in the memory stage
|
logic [1:0] FResSelE, FResSelM, FResSelW; // Select one of the results that finish in the memory stage
|
||||||
logic [1:0] PostProcSelE, PostProcSelM; // select result in the post processing unit
|
logic [1:0] PostProcSelE, PostProcSelM; // select result in the post processing unit
|
||||||
logic [4:0] Adr1D, Adr2D, Adr3D; // register adresses of each input
|
logic [4:0] Adr1D, Adr2D, Adr3D; // register adresses of each input
|
||||||
logic [4:0] Adr1E, Adr2E, Adr3E; // register adresses of each input
|
logic [4:0] Adr1E, Adr2E, Adr3E; // register adresses of each input
|
||||||
logic XEnD, YEnD, ZEnD; // X, Y, Z inputs used for current operation
|
logic XEnD, YEnD, ZEnD; // X, Y, Z inputs used for current operation
|
||||||
logic XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation
|
logic XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation
|
||||||
logic FRegWriteE; // Write floating-point register
|
logic FRegWriteE; // Write floating-point register
|
||||||
|
|
||||||
// regfile signals
|
// regfile signals
|
||||||
logic [P.FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage
|
logic [P.FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage
|
||||||
logic [P.FLEN-1:0] FRD1E, FRD2E, FRD3E; // Read Data from FP register - execute stage
|
logic [P.FLEN-1:0] FRD1E, FRD2E, FRD3E; // Read Data from FP register - execute stage
|
||||||
logic [P.FLEN-1:0] XE; // Input 1 to the various units (after forwarding)
|
logic [P.FLEN-1:0] XE; // Input 1 to the various units (after forwarding)
|
||||||
logic [P.XLEN-1:0] IntSrcXE; // Input 1 to the various units (after forwarding)
|
logic [P.XLEN-1:0] IntSrcXE; // Input 1 to the various units (after forwarding)
|
||||||
logic [P.FLEN-1:0] PreYE, YE; // Input 2 to the various units (after forwarding)
|
logic [P.FLEN-1:0] PreYE, YE; // Input 2 to the various units (after forwarding)
|
||||||
logic [P.FLEN-1:0] PreZE, ZE; // Input 3 to the various units (after forwarding)
|
logic [P.FLEN-1:0] PreZE, ZE; // Input 3 to the various units (after forwarding)
|
||||||
|
|
||||||
// unpacking signals
|
// unpacking signals
|
||||||
logic XsE, YsE, ZsE; // input's sign - execute stage
|
logic XsE, YsE, ZsE; // input's sign - execute stage
|
||||||
logic XsM, YsM; // input's sign - memory stage
|
logic XsM, YsM; // input's sign - memory stage
|
||||||
logic [P.NE-1:0] XeE, YeE, ZeE; // input's exponent - execute stage
|
logic [P.NE-1:0] XeE, YeE, ZeE; // input's exponent - execute stage
|
||||||
logic [P.NE-1:0] ZeM; // input's exponent - memory stage
|
logic [P.NE-1:0] ZeM; // input's exponent - memory stage
|
||||||
logic [P.NF:0] XmE, YmE, ZmE; // input's significand - execute stage
|
logic [P.NF:0] XmE, YmE, ZmE; // input's significand - execute stage
|
||||||
logic [P.NF:0] XmM, YmM, ZmM; // input's significand - memory stage
|
logic [P.NF:0] XmM, YmM, ZmM; // input's significand - memory stage
|
||||||
logic XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute stage
|
logic XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute stage
|
||||||
logic XNaNM, YNaNM, ZNaNM; // is the input a NaN - memory stage
|
logic XNaNM, YNaNM, ZNaNM; // is the input a NaN - memory stage
|
||||||
logic XSNaNE, YSNaNE, ZSNaNE; // is the input a signaling NaN - execute stage
|
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 XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage
|
||||||
logic XSubnormE; // is the input subnormal
|
logic XSubnormE; // is the input subnormal
|
||||||
logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage
|
logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage
|
||||||
logic XZeroM, YZeroM; // is the input zero - memory stage
|
logic XZeroM, YZeroM; // is the input zero - memory stage
|
||||||
logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage
|
logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage
|
||||||
logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage
|
logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage
|
||||||
logic XExpMaxE; // is the exponent all ones (max value)
|
logic XExpMaxE; // is the exponent all ones (max value)
|
||||||
logic [P.FLEN-1:0] XPostBoxE; // X after fixing bad NaN box. Needed for 1-input operations
|
logic [P.FLEN-1:0] XPostBoxE; // X after fixing bad NaN box. Needed for 1-input operations
|
||||||
|
|
||||||
// Fma Signals
|
// Fma Signals
|
||||||
logic FmaAddSubE; // Multiply by 1.0 when adding or subtracting
|
logic FmaAddSubE; // Multiply by 1.0 when adding or subtracting
|
||||||
logic [1:0] FmaZSelE; // Select Z = Y when adding or subtracting, 0 when multiplying
|
logic [1:0] FmaZSelE; // Select Z = Y when adding or subtracting, 0 when multiplying
|
||||||
logic [3*P.NF+3:0] SmE, SmM; // Sum significand
|
logic [3*P.NF+3:0] SmE, SmM; // Sum significand
|
||||||
logic FmaAStickyE, FmaAStickyM; // FMA addend sticky bit output
|
logic FmaAStickyE, FmaAStickyM; // FMA addend sticky bit output
|
||||||
logic [P.NE+1:0] SeE,SeM; // Sum exponent
|
logic [P.NE+1:0] SeE,SeM; // Sum exponent
|
||||||
logic InvAE, InvAM; // Invert addend
|
logic InvAE, InvAM; // Invert addend
|
||||||
logic AsE, AsM; // Addend sign
|
logic AsE, AsM; // Addend sign
|
||||||
logic PsE, PsM; // Product sign
|
logic PsE, PsM; // Product sign
|
||||||
logic SsE, SsM; // Sum sign
|
logic SsE, SsM; // Sum sign
|
||||||
logic [$clog2(3*P.NF+5)-1:0] SCntE, SCntM; // LZA sum leading zero count
|
logic [$clog2(3*P.NF+5)-1:0] SCntE, SCntM; // LZA sum leading zero count
|
||||||
|
|
||||||
// Cvt Signals
|
// Cvt Signals
|
||||||
logic [P.NE:0] CeE, CeM; // convert intermediate expoent
|
logic [P.NE:0] CeE, CeM; // convert intermediate expoent
|
||||||
logic [P.LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by
|
logic [P.LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by
|
||||||
logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is subnormal
|
logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is subnormal
|
||||||
logic CsE, CsM; // convert result sign
|
logic CsE, CsM; // convert result sign
|
||||||
logic IntZeroE, IntZeroM; // is the integer zero?
|
logic IntZeroE, IntZeroM; // is the integer zero?
|
||||||
logic [P.CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder)
|
logic [P.CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder)
|
||||||
logic [P.XLEN-1:0] FCvtIntResM; // fcvt integer result (for IEU)
|
logic [P.XLEN-1:0] FCvtIntResM; // fcvt integer result (for IEU)
|
||||||
|
|
||||||
// divide signals
|
// divide signals
|
||||||
logic [P.DIVb:0] QmM; // fdivsqrt signifcand
|
logic [P.DIVb:0] QmM; // fdivsqrt signifcand
|
||||||
logic [P.NE+1:0] QeM; // fdivsqrt exponent
|
logic [P.NE+1:0] QeM; // fdivsqrt exponent
|
||||||
logic DivStickyM; // fdivsqrt sticky bit
|
logic DivStickyM; // fdivsqrt sticky bit
|
||||||
logic FDivDoneE, IFDivStartE; // fdivsqrt control signals
|
logic FDivDoneE, IFDivStartE; // fdivsqrt control signals
|
||||||
logic [P.XLEN-1:0] FIntDivResultM; // fdivsqrt integer division result (for IEU)
|
logic [P.XLEN-1:0] FIntDivResultM; // fdivsqrt integer division result (for IEU)
|
||||||
|
|
||||||
// result and flag signals
|
// result and flag signals
|
||||||
logic [P.XLEN-1:0] ClassResE; // classify result
|
logic [P.XLEN-1:0] ClassResE; // classify result
|
||||||
logic [P.FLEN-1:0] CmpFpResE; // compare result to FPU (min/max)
|
logic [P.FLEN-1:0] CmpFpResE; // compare result to FPU (min/max)
|
||||||
logic [P.XLEN-1:0] CmpIntResE; // compare result to IEU (eq/lt/le)
|
logic [P.XLEN-1:0] CmpIntResE; // compare result to IEU (eq/lt/le)
|
||||||
logic CmpNVE; // compare invalid flag (Not Valid)
|
logic CmpNVE; // compare invalid flag (Not Valid)
|
||||||
logic [P.FLEN-1:0] SgnResE; // sign injection result
|
logic [P.FLEN-1:0] SgnResE; // sign injection result
|
||||||
logic [P.XLEN-1:0] FIntResE; // FPU to IEU E-stage result (classify, compare, move)
|
logic [P.XLEN-1:0] FIntResE; // FPU to IEU E-stage result (classify, compare, move)
|
||||||
logic [P.FLEN-1:0] PostProcResM; // Postprocessor output
|
logic [P.FLEN-1:0] PostProcResM; // Postprocessor output
|
||||||
logic [4:0] PostProcFlgM; // Postprocessor flags
|
logic [4:0] PostProcFlgM; // Postprocessor flags
|
||||||
logic PreNVE, PreNVM; // selected flag that is ready in the memory stage
|
logic PreNVE, PreNVM; // selected flag that is ready in the memory stage
|
||||||
logic [P.FLEN-1:0] FpResM, FpResW; // FPU preliminary result
|
logic [P.FLEN-1:0] FpResM, FpResW; // FPU preliminary result
|
||||||
logic [P.FLEN-1:0] PreFpResE, PreFpResM; // selected result that is ready in the memory stage
|
logic [P.FLEN-1:0] PreFpResE, PreFpResM; // selected result that is ready in the memory stage
|
||||||
logic [P.FLEN-1:0] FResultW; // final FP result being written to the FP register
|
logic [P.FLEN-1:0] FResultW; // final FP result being written to the FP register
|
||||||
@ -156,9 +156,9 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [P.FLEN-1:0] AlignedSrcAE; // align SrcA from IEU to the floating point format for fmv
|
logic [P.FLEN-1:0] AlignedSrcAE; // align SrcA from IEU to the floating point format for fmv
|
||||||
logic [P.FLEN-1:0] BoxedZeroE; // Zero value for Z for multiplication, with NaN boxing if needed
|
logic [P.FLEN-1:0] BoxedZeroE; // Zero value for Z for multiplication, with NaN boxing if needed
|
||||||
logic [P.FLEN-1:0] BoxedOneE; // One value for Z for multiplication, with NaN boxing if needed
|
logic [P.FLEN-1:0] BoxedOneE; // One value for Z for multiplication, with NaN boxing if needed
|
||||||
logic StallUnpackedM; // Stall unpacker outputs during multicycle fdivsqrt
|
logic StallUnpackedM; // Stall unpacker outputs during multicycle fdivsqrt
|
||||||
logic [P.FLEN-1:0] SgnExtXE; // Sign-extended X input for move to integer
|
logic [P.FLEN-1:0] SgnExtXE; // Sign-extended X input for move to integer
|
||||||
logic mvsgn; // sign bit for extending move
|
logic mvsgn; // sign bit for extending move
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Decode Stage: fctrl decoder, read register file
|
// Decode Stage: fctrl decoder, read register file
|
||||||
@ -205,15 +205,15 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
|||||||
mux2 #(P.FLEN) fonemux ({{P.FLEN-P.LEN1{1'b1}}, 2'b0, {P.NE1-1{1'b1}}, (P.NF1)'(0)}, {2'b0, {P.NE-1{1'b1}}, (P.NF)'(0)}, FmtE, BoxedOneE); // NaN boxing zeroes
|
mux2 #(P.FLEN) fonemux ({{P.FLEN-P.LEN1{1'b1}}, 2'b0, {P.NE1-1{1'b1}}, (P.NF1)'(0)}, {2'b0, {P.NE-1{1'b1}}, (P.NF)'(0)}, FmtE, BoxedOneE); // NaN boxing zeroes
|
||||||
else if(P.FPSIZES == 3 | P.FPSIZES == 4)
|
else if(P.FPSIZES == 3 | P.FPSIZES == 4)
|
||||||
mux4 #(P.FLEN) fonemux ({{P.FLEN-P.S_LEN{1'b1}}, 2'b0, {P.S_NE-1{1'b1}}, (P.S_NF)'(0)},
|
mux4 #(P.FLEN) fonemux ({{P.FLEN-P.S_LEN{1'b1}}, 2'b0, {P.S_NE-1{1'b1}}, (P.S_NF)'(0)},
|
||||||
{{P.FLEN-P.D_LEN{1'b1}}, 2'b0, {P.D_NE-1{1'b1}}, (P.D_NF)'(0)},
|
{{P.FLEN-P.D_LEN{1'b1}}, 2'b0, {P.D_NE-1{1'b1}}, (P.D_NF)'(0)},
|
||||||
{{P.FLEN-P.H_LEN{1'b1}}, 2'b0, {P.H_NE-1{1'b1}}, (P.H_NF)'(0)},
|
{{P.FLEN-P.H_LEN{1'b1}}, 2'b0, {P.H_NE-1{1'b1}}, (P.H_NF)'(0)},
|
||||||
{2'b0, {P.NE-1{1'b1}}, (P.NF)'(0)}, FmtE, BoxedOneE); // NaN boxing zeroes
|
{2'b0, {P.NE-1{1'b1}}, (P.NF)'(0)}, FmtE, BoxedOneE); // NaN boxing zeroes
|
||||||
assign FmaAddSubE = OpCtrlE[2]&OpCtrlE[1]&(FResSelE==2'b01)&(PostProcSelE==2'b10);
|
assign FmaAddSubE = OpCtrlE[2]&OpCtrlE[1]&(FResSelE==2'b01)&(PostProcSelE==2'b10);
|
||||||
mux2 #(P.FLEN) fyaddmux (PreYE, BoxedOneE, FmaAddSubE, YE); // Force Y to be 1 for add/subtract
|
mux2 #(P.FLEN) fyaddmux (PreYE, BoxedOneE, FmaAddSubE, YE); // Force Y to be 1 for add/subtract
|
||||||
|
|
||||||
// Select NAN-boxed value of Z = 0.0 in proper format for FMA for multiply X*Y+Z
|
// Select NAN-boxed value of Z = 0.0 in proper format for FMA for multiply X*Y+Z
|
||||||
// For add and subtract, Z comes from second source operand
|
// For add and subtract, Z comes from second source operand
|
||||||
if(P.FPSIZES == 1) assign BoxedZeroE = 0;
|
if(P.FPSIZES == 1) assign BoxedZeroE = 0;
|
||||||
else if(P.FPSIZES == 2)
|
else if(P.FPSIZES == 2)
|
||||||
mux2 #(P.FLEN) fmulzeromux ({{P.FLEN-P.LEN1{1'b1}}, {P.LEN1{1'b0}}}, (P.FLEN)'(0), FmtE, BoxedZeroE); // NaN boxing zeroes
|
mux2 #(P.FLEN) fmulzeromux ({{P.FLEN-P.LEN1{1'b1}}, {P.LEN1{1'b0}}}, (P.FLEN)'(0), FmtE, BoxedZeroE); // NaN boxing zeroes
|
||||||
else if(P.FPSIZES == 3 | P.FPSIZES == 4)
|
else if(P.FPSIZES == 3 | P.FPSIZES == 4)
|
||||||
@ -262,7 +262,6 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.ToInt(FWriteIntE), .XZero(XZeroE), .Fmt(FmtE), .Ce(CeE), .ShiftAmt(CvtShiftAmtE),
|
.ToInt(FWriteIntE), .XZero(XZeroE), .Fmt(FmtE), .Ce(CeE), .ShiftAmt(CvtShiftAmtE),
|
||||||
.ResSubnormUf(CvtResSubnormUfE), .Cs(CsE), .IntZero(IntZeroE), .LzcIn(CvtLzcInE));
|
.ResSubnormUf(CvtResSubnormUfE), .Cs(CsE), .IntZero(IntZeroE), .LzcIn(CvtLzcInE));
|
||||||
|
|
||||||
|
|
||||||
// NaN Box SrcA to convert integer to requested FP size
|
// NaN Box SrcA to convert integer to requested FP size
|
||||||
if(P.FPSIZES == 1) assign AlignedSrcAE = {{P.FLEN-P.XLEN{1'b1}}, ForwardedSrcAE};
|
if(P.FPSIZES == 1) assign AlignedSrcAE = {{P.FLEN-P.XLEN{1'b1}}, ForwardedSrcAE};
|
||||||
else if(P.FPSIZES == 2)
|
else if(P.FPSIZES == 2)
|
||||||
@ -334,7 +333,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM));
|
.PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM));
|
||||||
|
|
||||||
// FPU flag selection - to privileged
|
// FPU flag selection - to privileged
|
||||||
mux2 #(5) FPUFlgMux({PreNVM&~FResSelM[1], 4'b0}, PostProcFlgM, ~FResSelM[1]&FResSelM[0], SetFflagsM);
|
mux2 #(5) FPUFlgMux({PreNVM&~FResSelM[1], 4'b0}, PostProcFlgM, ~FResSelM[1]&FResSelM[0], SetFflagsM);
|
||||||
mux2 #(P.FLEN) FPUResMux(PreFpResM, PostProcResM, FResSelM[0], FpResM);
|
mux2 #(P.FLEN) FPUResMux(PreFpResM, PostProcResM, FResSelM[0], FpResM);
|
||||||
|
|
||||||
// M/W pipe registers
|
// M/W pipe registers
|
||||||
|
@ -30,8 +30,8 @@ module fregfile #(parameter FLEN) (
|
|||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic we4, // write enable
|
input logic we4, // write enable
|
||||||
input logic [4:0] a1, a2, a3, a4, // adresses
|
input logic [4:0] a1, a2, a3, a4, // adresses
|
||||||
input logic [FLEN-1:0] wd4, // write data
|
input logic [FLEN-1:0] wd4, // write data
|
||||||
output logic [FLEN-1:0] rd1, rd2, rd3 // read data
|
output logic [FLEN-1:0] rd1, rd2, rd3 // read data
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [FLEN-1:0] rf[31:0];
|
logic [FLEN-1:0] rf[31:0];
|
||||||
@ -51,4 +51,3 @@ module fregfile #(parameter FLEN) (
|
|||||||
assign #2 rd3 = rf[a3];
|
assign #2 rd3 = rf[a3];
|
||||||
|
|
||||||
endmodule // regfile
|
endmodule // regfile
|
||||||
|
|
||||||
|
@ -27,10 +27,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module fsgninj import cvw::*; #(parameter cvw_t P) (
|
module fsgninj import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic Xs, Ys, // X and Y sign bits
|
input logic Xs, Ys, // X and Y sign bits
|
||||||
input logic [P.FLEN-1:0] X, // X
|
input logic [P.FLEN-1:0] X, // X
|
||||||
input logic [P.FMTBITS-1:0] Fmt, // format
|
input logic [P.FMTBITS-1:0] Fmt, // format
|
||||||
input logic [1:0] OpCtrl, // operation control
|
input logic [1:0] OpCtrl, // operation control
|
||||||
output logic [P.FLEN-1:0] SgnRes // result
|
output logic [P.FLEN-1:0] SgnRes // result
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -73,5 +73,4 @@ module fsgninj import cvw::*; #(parameter cvw_t P) (
|
|||||||
endcase
|
endcase
|
||||||
assign SgnRes = {SgnBits[3], X[P.Q_LEN-2:P.D_LEN], SgnBits[2], X[P.D_LEN-2:P.S_LEN], SgnBits[1], X[P.S_LEN-2:P.H_LEN], SgnBits[0], X[P.H_LEN-2:0]};
|
assign SgnRes = {SgnBits[3], X[P.Q_LEN-2:P.D_LEN], SgnBits[2], X[P.D_LEN-2:P.S_LEN], SgnBits[1], X[P.S_LEN-2:P.H_LEN], SgnBits[0], X[P.H_LEN-2:0]};
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -82,7 +82,7 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
|
|||||||
P.FMT: ResNegNF = -($clog2(P.NF)+1)'(P.NF);
|
P.FMT: ResNegNF = -($clog2(P.NF)+1)'(P.NF);
|
||||||
P.FMT1: ResNegNF = -($clog2(P.NF)+1)'(P.NF1);
|
P.FMT1: ResNegNF = -($clog2(P.NF)+1)'(P.NF1);
|
||||||
P.FMT2: ResNegNF = -($clog2(P.NF)+1)'(P.NF2);
|
P.FMT2: ResNegNF = -($clog2(P.NF)+1)'(P.NF2);
|
||||||
default: ResNegNF = 1'bx;
|
default: ResNegNF = 'x;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
end else if (P.FPSIZES == 4) begin
|
end else if (P.FPSIZES == 4) begin
|
||||||
|
@ -28,24 +28,24 @@
|
|||||||
|
|
||||||
module unpackinput import cvw::*; #(parameter cvw_t P) (
|
module unpackinput import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.FLEN-1:0] In, // inputs from register file
|
input logic [P.FLEN-1:0] In, // inputs from register file
|
||||||
input logic En, // enable the input
|
input logic En, // enable the input
|
||||||
input logic [P.FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half
|
input logic [P.FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half
|
||||||
output logic Sgn, // sign bits of the number
|
output logic Sgn, // sign bits of the number
|
||||||
output logic [P.NE-1:0] Exp, // exponent of the number (converted to largest supported precision)
|
output logic [P.NE-1:0] Exp, // exponent of the number (converted to largest supported precision)
|
||||||
output logic [P.NF:0] Man, // mantissa of the number (converted to largest supported precision)
|
output logic [P.NF:0] Man, // mantissa of the number (converted to largest supported precision)
|
||||||
output logic NaN, // is the number a NaN
|
output logic NaN, // is the number a NaN
|
||||||
output logic SNaN, // is the number a signaling NaN
|
output logic SNaN, // is the number a signaling NaN
|
||||||
output logic Zero, // is the number zero
|
output logic Zero, // is the number zero
|
||||||
output logic Inf, // is the number infinity
|
output logic Inf, // is the number infinity
|
||||||
output logic ExpNonZero, // is the exponent not zero
|
output logic ExpNonZero, // is the exponent not zero
|
||||||
output logic FracZero, // is the fraction zero
|
output logic FracZero, // is the fraction zero
|
||||||
output logic ExpMax, // does In have the maximum exponent (NaN or Inf)
|
output logic ExpMax, // does In have the maximum exponent (NaN or Inf)
|
||||||
output logic Subnorm, // is the number subnormal
|
output logic Subnorm, // is the number subnormal
|
||||||
output logic [P.FLEN-1:0] PostBox // Number reboxed correctly as a NaN
|
output logic [P.FLEN-1:0] PostBox // Number reboxed correctly as a NaN
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.NF-1:0] Frac; // Fraction of XYZ
|
logic [P.NF-1:0] Frac; // Fraction of XYZ
|
||||||
logic BadNaNBox; // incorrectly NaN Boxed
|
logic BadNaNBox; // incorrectly NaN Boxed
|
||||||
|
|
||||||
if (P.FPSIZES == 1) begin // if there is only one floating point format supported
|
if (P.FPSIZES == 1) begin // if there is only one floating point format supported
|
||||||
assign BadNaNBox = 0;
|
assign BadNaNBox = 0;
|
||||||
@ -107,7 +107,6 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||||||
// is the exponent all 1's
|
// is the exponent all 1's
|
||||||
assign ExpMax = Fmt ? &In[P.FLEN-2:P.NF] : &In[P.LEN1-2:P.NF1];
|
assign ExpMax = Fmt ? &In[P.FLEN-2:P.NF] : &In[P.LEN1-2:P.NF1];
|
||||||
|
|
||||||
|
|
||||||
end else if (P.FPSIZES == 3) begin // three floating point precsions supported
|
end else if (P.FPSIZES == 3) begin // three floating point precsions supported
|
||||||
|
|
||||||
// largest format | larger format | smallest format
|
// largest format | larger format | smallest format
|
||||||
@ -246,7 +245,6 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||||||
2'b00: Sgn = In[P.S_LEN-1];
|
2'b00: Sgn = In[P.S_LEN-1];
|
||||||
2'b10: Sgn = In[P.H_LEN-1];
|
2'b10: Sgn = In[P.H_LEN-1];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
|
||||||
// extract the fraction
|
// extract the fraction
|
||||||
always_comb
|
always_comb
|
||||||
@ -266,7 +264,6 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||||||
2'b10: ExpNonZero = |In[P.H_LEN-2:P.H_NF];
|
2'b10: ExpNonZero = |In[P.H_LEN-2:P.H_NF];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
|
||||||
// example double to single conversion:
|
// example double to single conversion:
|
||||||
// 1023 = 0011 1111 1111
|
// 1023 = 0011 1111 1111
|
||||||
// 127 = 0000 0111 1111 (subtract this)
|
// 127 = 0000 0111 1111 (subtract this)
|
||||||
@ -284,8 +281,7 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||||||
2'b00: Exp = {In[P.S_LEN-2], {P.Q_NE-P.S_NE{~In[P.S_LEN-2]}}, In[P.S_LEN-3:P.S_NF+1], In[P.S_NF]|~ExpNonZero};
|
2'b00: Exp = {In[P.S_LEN-2], {P.Q_NE-P.S_NE{~In[P.S_LEN-2]}}, In[P.S_LEN-3:P.S_NF+1], In[P.S_NF]|~ExpNonZero};
|
||||||
2'b10: Exp = {In[P.H_LEN-2], {P.Q_NE-P.H_NE{~In[P.H_LEN-2]}}, In[P.H_LEN-3:P.H_NF+1], In[P.H_NF]|~ExpNonZero};
|
2'b10: Exp = {In[P.H_LEN-2], {P.Q_NE-P.H_NE{~In[P.H_LEN-2]}}, In[P.H_LEN-3:P.H_NF+1], In[P.H_NF]|~ExpNonZero};
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
|
||||||
// is the exponent all 1's
|
// is the exponent all 1's
|
||||||
always_comb
|
always_comb
|
||||||
case (Fmt)
|
case (Fmt)
|
||||||
|
@ -33,5 +33,3 @@ module adder #(parameter WIDTH=8) (
|
|||||||
|
|
||||||
assign y = a + b;
|
assign y = a + b;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,5 +36,3 @@ module counter #(parameter WIDTH=8) (
|
|||||||
assign qnext = q + 1;
|
assign qnext = q + 1;
|
||||||
flopenr #(WIDTH) cntrflop(clk, reset, en, qnext, q);
|
flopenr #(WIDTH) cntrflop(clk, reset, en, qnext, q);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,4 +32,3 @@ module neg #(parameter WIDTH = 8) (
|
|||||||
|
|
||||||
assign y = ~a + 1;
|
assign y = ~a + 1;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -48,5 +48,3 @@ module or_rows #(parameter ROWS = 8, COLS=2) (
|
|||||||
/* verilator lint_on UNOPTFLAT */
|
/* verilator lint_on UNOPTFLAT */
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +48,3 @@ module prioritythermometer #(parameter N = 8) (
|
|||||||
end
|
end
|
||||||
/* verilator lint_on UNOPTFLAT */
|
/* verilator lint_on UNOPTFLAT */
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,55 +28,55 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module datapath import cvw::*; #(parameter cvw_t P) (
|
module datapath import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
input logic [2:0] ImmSrcD, // Selects type of immediate extension
|
input logic [2:0] ImmSrcD, // Selects type of immediate extension
|
||||||
input logic [31:0] InstrD, // Instruction in Decode stage
|
input logic [31:0] InstrD, // Instruction in Decode stage
|
||||||
// Execute stage signals
|
// Execute stage signals
|
||||||
input logic [P.XLEN-1:0] PCE, // PC in Execute stage
|
input logic [P.XLEN-1:0] PCE, // PC in Execute stage
|
||||||
input logic [P.XLEN-1:0] PCLinkE, // PC + 4 (of instruction in Execute stage)
|
input logic [P.XLEN-1:0] PCLinkE, // PC + 4 (of instruction in Execute stage)
|
||||||
input logic [2:0] Funct3E, // Funct3 field of instruction in Execute stage
|
input logic [2:0] Funct3E, // Funct3 field of instruction in Execute stage
|
||||||
input logic StallE, FlushE, // Stall, flush Execute stage
|
input logic StallE, FlushE, // Stall, flush Execute stage
|
||||||
input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages
|
input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages
|
||||||
input logic W64E, // W64-type instruction
|
input logic W64E, // W64-type instruction
|
||||||
input logic SubArithE, // Subtraction or arithmetic shift
|
input logic SubArithE, // Subtraction or arithmetic shift
|
||||||
input logic ALUSrcAE, ALUSrcBE, // ALU operands
|
input logic ALUSrcAE, ALUSrcBE, // ALU operands
|
||||||
input logic ALUResultSrcE, // Selects result to pass on to Memory stage
|
input logic ALUResultSrcE, // Selects result to pass on to Memory stage
|
||||||
input logic [2:0] ALUSelectE, // ALU mux select signal
|
input logic [2:0] ALUSelectE, // ALU mux select signal
|
||||||
input logic JumpE, // Is a jump (j) instruction
|
input logic JumpE, // Is a jump (j) instruction
|
||||||
input logic BranchSignedE, // Branch comparison operands are signed (if it's a branch)
|
input logic BranchSignedE, // Branch comparison operands are signed (if it's a branch)
|
||||||
input logic [1:0] BSelectE, // One hot encoding of ZBA_ZBB_ZBC_ZBS instruction
|
input logic [1:0] BSelectE, // One hot encoding of ZBA_ZBB_ZBC_ZBS instruction
|
||||||
input logic [2:0] ZBBSelectE, // ZBB mux select signal
|
input logic [2:0] ZBBSelectE, // ZBB mux select signal
|
||||||
input logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage
|
input logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage
|
||||||
output logic [1:0] FlagsE, // Comparison flags ({eq, lt})
|
output logic [1:0] FlagsE, // Comparison flags ({eq, lt})
|
||||||
output logic [P.XLEN-1:0] IEUAdrE, // Address computed by ALU
|
output logic [P.XLEN-1:0] IEUAdrE, // Address computed by ALU
|
||||||
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU sources before the mux chooses between them and PCE to put in srcA/B
|
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU sources before the mux chooses between them and PCE to put in srcA/B
|
||||||
// Memory stage signals
|
// Memory stage signals
|
||||||
input logic StallM, FlushM, // Stall, flush Memory stage
|
input logic StallM, FlushM, // Stall, flush Memory stage
|
||||||
input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int
|
input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int
|
||||||
input logic [P.XLEN-1:0] FIntResM, // FPU integer result
|
input logic [P.XLEN-1:0] FIntResM, // FPU integer result
|
||||||
output logic [P.XLEN-1:0] SrcAM, // ALU's Source A in Memory stage to privilege unit for CSR writes
|
output logic [P.XLEN-1:0] SrcAM, // ALU's Source A in Memory stage to privilege unit for CSR writes
|
||||||
output logic [P.XLEN-1:0] WriteDataM, // Write data in Memory stage
|
output logic [P.XLEN-1:0] WriteDataM, // Write data in Memory stage
|
||||||
// Writeback stage signals
|
// Writeback stage signals
|
||||||
input logic StallW, FlushW, // Stall, flush Writeback stage
|
input logic StallW, FlushW, // Stall, flush Writeback stage
|
||||||
input logic RegWriteW, IntDivW, // Write register file, integer divide instruction
|
input logic RegWriteW, IntDivW, // Write register file, integer divide instruction
|
||||||
input logic SquashSCW, // Squash a store conditional when a conflict arose
|
input logic SquashSCW, // Squash a store conditional when a conflict arose
|
||||||
input logic [2:0] ResultSrcW, // Select source of result to write back to register file
|
input logic [2:0] ResultSrcW, // Select source of result to write back to register file
|
||||||
input logic [P.XLEN-1:0] FCvtIntResW, // FPU convert fp to integer result
|
input logic [P.XLEN-1:0] FCvtIntResW, // FPU convert fp to integer result
|
||||||
input logic [P.XLEN-1:0] ReadDataW, // Read data from LSU
|
input logic [P.XLEN-1:0] ReadDataW, // Read data from LSU
|
||||||
input logic [P.XLEN-1:0] CSRReadValW, // CSR read result
|
input logic [P.XLEN-1:0] CSRReadValW, // CSR read result
|
||||||
input logic [P.XLEN-1:0] MDUResultW, // MDU (Multiply/divide unit) result
|
input logic [P.XLEN-1:0] MDUResultW, // MDU (Multiply/divide unit) result
|
||||||
input logic [P.XLEN-1:0] FIntDivResultW, // FPU's integer divide result
|
input logic [P.XLEN-1:0] FIntDivResultW, // FPU's integer divide result
|
||||||
// Hazard Unit signals
|
// Hazard Unit signals
|
||||||
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, // Register sources to read in Decode or Execute stage
|
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, // Register sources to read in Decode or Execute stage
|
||||||
output logic [4:0] RdE, RdM, RdW // Register destinations in Execute, Memory, or Writeback stage
|
output logic [4:0] RdE, RdM, RdW // Register destinations in Execute, Memory, or Writeback stage
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fetch stage signals
|
// Fetch stage signals
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
logic [P.XLEN-1:0] R1D, R2D; // Read data from Rs1 (RD1), Rs2 (RD2)
|
logic [P.XLEN-1:0] R1D, R2D; // Read data from Rs1 (RD1), Rs2 (RD2)
|
||||||
logic [P.XLEN-1:0] ImmExtD; // Extended immediate in Decode stage
|
logic [P.XLEN-1:0] ImmExtD; // Extended immediate in Decode stage
|
||||||
logic [4:0] RdD; // Destination register in Decode stage
|
logic [4:0] RdD; // Destination register in Decode stage
|
||||||
// Execute stage signals
|
// Execute stage signals
|
||||||
logic [P.XLEN-1:0] R1E, R2E; // Source operands read from register file
|
logic [P.XLEN-1:0] R1E, R2E; // Source operands read from register file
|
||||||
logic [P.XLEN-1:0] ImmExtE; // Extended immediate in Execute stage
|
logic [P.XLEN-1:0] ImmExtE; // Extended immediate in Execute stage
|
||||||
@ -103,9 +103,9 @@ module datapath import cvw::*; #(parameter cvw_t P) (
|
|||||||
flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E);
|
flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E);
|
||||||
flopenrc #(P.XLEN) RD2EReg(clk, reset, FlushE, ~StallE, R2D, R2E);
|
flopenrc #(P.XLEN) RD2EReg(clk, reset, FlushE, ~StallE, R2D, R2E);
|
||||||
flopenrc #(P.XLEN) ImmExtEReg(clk, reset, FlushE, ~StallE, ImmExtD, ImmExtE);
|
flopenrc #(P.XLEN) ImmExtEReg(clk, reset, FlushE, ~StallE, ImmExtD, ImmExtE);
|
||||||
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
||||||
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
||||||
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
||||||
|
|
||||||
mux3 #(P.XLEN) faemux(R1E, ResultW, IFResultM, ForwardAE, ForwardedSrcAE);
|
mux3 #(P.XLEN) faemux(R1E, ResultW, IFResultM, ForwardAE, ForwardedSrcAE);
|
||||||
mux3 #(P.XLEN) fbemux(R2E, ResultW, IFResultM, ForwardBE, ForwardedSrcBE);
|
mux3 #(P.XLEN) fbemux(R2E, ResultW, IFResultM, ForwardBE, ForwardedSrcBE);
|
||||||
@ -144,5 +144,5 @@ module datapath import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// handle Store Conditional result if atomic extension supported
|
// handle Store Conditional result if atomic extension supported
|
||||||
if (P.A_SUPPORTED) assign SCResultW = {{(P.XLEN-1){1'b0}}, SquashSCW};
|
if (P.A_SUPPORTED) assign SCResultW = {{(P.XLEN-1){1'b0}}, SquashSCW};
|
||||||
else assign SCResultW = 0;
|
else assign SCResultW = 0;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
module extend #(parameter XLEN, A_SUPPORTED) (
|
module extend #(parameter XLEN, A_SUPPORTED) (
|
||||||
input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits)
|
input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits)
|
||||||
input logic [2:0] ImmSrcD, // Select what kind of extension to perform
|
input logic [2:0] ImmSrcD, // Select what kind of extension to perform
|
||||||
output logic [XLEN-1:0 ] ImmExtD); // Extended immediate
|
output logic [XLEN-1:0] ImmExtD); // Extended immediate
|
||||||
|
|
||||||
localparam [XLEN-1:0] undefined = {(XLEN){1'bx}}; // could change to 0 after debug
|
localparam [XLEN-1:0] undefined = {(XLEN){1'bx}}; // could change to 0 after debug
|
||||||
|
|
||||||
@ -45,10 +45,10 @@ module extend #(parameter XLEN, A_SUPPORTED) (
|
|||||||
// J-type (jal)
|
// J-type (jal)
|
||||||
3'b011: ImmExtD = {{(XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
3'b011: ImmExtD = {{(XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
||||||
// U-type (lui, auipc)
|
// U-type (lui, auipc)
|
||||||
3'b100: ImmExtD = {{(XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
3'b100: ImmExtD = {{(XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
||||||
// Store Conditional: zero offset
|
// Store Conditional: zero offset
|
||||||
3'b101: if (A_SUPPORTED) ImmExtD = 0;
|
3'b101: if (A_SUPPORTED) ImmExtD = 0;
|
||||||
else ImmExtD = undefined;
|
else ImmExtD = undefined;
|
||||||
default: ImmExtD = undefined; // undefined
|
default: ImmExtD = undefined; // undefined
|
||||||
endcase
|
endcase
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
// and limitations under the License.
|
// and limitations under the License.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
module ieu import cvw::*; #(parameter cvw_t P) (
|
module ieu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
@ -34,36 +33,36 @@ module ieu import cvw::*; #(parameter cvw_t P) (
|
|||||||
input logic IllegalIEUFPUInstrD, // Illegal instruction
|
input logic IllegalIEUFPUInstrD, // Illegal instruction
|
||||||
output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
|
output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
|
||||||
// Execute stage signals
|
// Execute stage signals
|
||||||
input logic [P.XLEN-1:0] PCE, // PC
|
input logic [P.XLEN-1:0] PCE, // PC
|
||||||
input logic [P.XLEN-1:0] PCLinkE, // PC + 4
|
input logic [P.XLEN-1:0] PCLinkE, // PC + 4
|
||||||
output logic PCSrcE, // Select next PC (between PC+4 and IEUAdrE)
|
output logic PCSrcE, // Select next PC (between PC+4 and IEUAdrE)
|
||||||
input logic FWriteIntE, FCvtIntE, // FPU writes to integer register file, FPU converts float to int
|
input logic FWriteIntE, FCvtIntE, // FPU writes to integer register file, FPU converts float to int
|
||||||
output logic [P.XLEN-1:0] IEUAdrE, // Memory address
|
output logic [P.XLEN-1:0] IEUAdrE, // Memory address
|
||||||
output logic IntDivE, W64E, // Integer divide, RV64 W-type instruction
|
output logic IntDivE, W64E, // Integer divide, RV64 W-type instruction
|
||||||
output logic [2:0] Funct3E, // Funct3 instruction field
|
output logic [2:0] Funct3E, // Funct3 instruction field
|
||||||
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU src inputs before the mux choosing between them and PCE to put in srcA/B
|
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU src inputs before the mux choosing between them and PCE to put in srcA/B
|
||||||
output logic [4:0] RdE, // Destination register
|
output logic [4:0] RdE, // Destination register
|
||||||
// Memory stage signals
|
// Memory stage signals
|
||||||
input logic SquashSCW, // Squash store conditional, from LSU
|
input logic SquashSCW, // Squash store conditional, from LSU
|
||||||
output logic [1:0] MemRWM, // Read/write control goes to LSU
|
output logic [1:0] MemRWM, // Read/write control goes to LSU
|
||||||
output logic [1:0] AtomicM, // Atomic control goes to LSU
|
output logic [1:0] AtomicM, // Atomic control goes to LSU
|
||||||
output logic [P.XLEN-1:0] WriteDataM, // Write data to LSU
|
output logic [P.XLEN-1:0] WriteDataM, // Write data to LSU
|
||||||
output logic [2:0] Funct3M, // Funct3 (size and signedness) to LSU
|
output logic [2:0] Funct3M, // Funct3 (size and signedness) to LSU
|
||||||
output logic [P.XLEN-1:0] SrcAM, // ALU SrcA to Privileged unit and FPU
|
output logic [P.XLEN-1:0] SrcAM, // ALU SrcA to Privileged unit and FPU
|
||||||
output logic [4:0] RdM, // Destination register
|
output logic [4:0] RdM, // Destination register
|
||||||
input logic [P.XLEN-1:0] FIntResM, // Integer result from FPU (fmv, fclass, fcmp)
|
input logic [P.XLEN-1:0] FIntResM, // Integer result from FPU (fmv, fclass, fcmp)
|
||||||
output logic InvalidateICacheM, FlushDCacheM, // Invalidate I$, flush D$
|
output logic InvalidateICacheM, FlushDCacheM, // Invalidate I$, flush D$
|
||||||
output logic InstrValidD, InstrValidE, InstrValidM,// Instruction is valid
|
output logic InstrValidD, InstrValidE, InstrValidM, // Instruction is valid
|
||||||
output logic BranchD, BranchE,
|
output logic BranchD, BranchE,
|
||||||
output logic JumpD, JumpE,
|
output logic JumpD, JumpE,
|
||||||
// Writeback stage signals
|
// Writeback stage signals
|
||||||
input logic [P.XLEN-1:0] FIntDivResultW, // Integer divide result from FPU fdivsqrt)
|
input logic [P.XLEN-1:0] FIntDivResultW, // Integer divide result from FPU fdivsqrt)
|
||||||
input logic [P.XLEN-1:0] CSRReadValW, // CSR read value,
|
input logic [P.XLEN-1:0] CSRReadValW, // CSR read value,
|
||||||
input logic [P.XLEN-1:0] MDUResultW, // multiply/divide unit result
|
input logic [P.XLEN-1:0] MDUResultW, // multiply/divide unit result
|
||||||
input logic [P.XLEN-1:0] FCvtIntResW, // FPU's float to int conversion result
|
input logic [P.XLEN-1:0] FCvtIntResW, // FPU's float to int conversion result
|
||||||
input logic FCvtIntW, // FPU converts float to int
|
input logic FCvtIntW, // FPU converts float to int
|
||||||
output logic [4:0] RdW, // Destination register
|
output logic [4:0] RdW, // Destination register
|
||||||
input logic [P.XLEN-1:0] ReadDataW, // LSU's read data
|
input logic [P.XLEN-1:0] ReadDataW, // LSU's read data
|
||||||
// Hazard unit signals
|
// Hazard unit signals
|
||||||
input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit
|
input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit
|
||||||
input logic FlushD, FlushE, FlushM, FlushW, // Flush signals
|
input logic FlushD, FlushE, FlushM, FlushW, // Flush signals
|
||||||
@ -118,4 +117,3 @@ module ieu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.FCvtIntE, .SCE, .ForwardAE, .ForwardBE,
|
.FCvtIntE, .SCE, .ForwardAE, .ForwardBE,
|
||||||
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD);
|
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -31,10 +31,10 @@ module regfile #(parameter XLEN, E_SUPPORTED) (
|
|||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic we3, // Write enable
|
input logic we3, // Write enable
|
||||||
input logic [4:0] a1, a2, a3, // Source registers to read (a1, a2), destination register to write (a3)
|
input logic [4:0] a1, a2, a3, // Source registers to read (a1, a2), destination register to write (a3)
|
||||||
input logic [XLEN-1:0] wd3, // Write data for port 3
|
input logic [XLEN-1:0] wd3, // Write data for port 3
|
||||||
output logic [XLEN-1:0] rd1, rd2); // Read data for ports 1, 2
|
output logic [XLEN-1:0] rd1, rd2); // Read data for ports 1, 2
|
||||||
|
|
||||||
localparam NUMREGS = E_SUPPORTED ? 16 : 32; // only 16 registers in E mode
|
localparam NUMREGS = E_SUPPORTED ? 16 : 32; // only 16 registers in E mode
|
||||||
|
|
||||||
logic [XLEN-1:0] rf[NUMREGS-1:1];
|
logic [XLEN-1:0] rf[NUMREGS-1:1];
|
||||||
integer i;
|
integer i;
|
||||||
@ -50,7 +50,7 @@ module regfile #(parameter XLEN, E_SUPPORTED) (
|
|||||||
|
|
||||||
always_ff @(negedge clk)
|
always_ff @(negedge clk)
|
||||||
if (reset) for(i=1; i<NUMREGS; i++) rf[i] <= 0;
|
if (reset) for(i=1; i<NUMREGS; i++) rf[i] <= 0;
|
||||||
else if (we3) rf[a3] <= wd3;
|
else if (we3) rf[a3] <= wd3;
|
||||||
|
|
||||||
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;
|
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;
|
||||||
assign #2 rd2 = (a2 != 0) ? rf[a2] : 0;
|
assign #2 rd2 = (a2 != 0) ? rf[a2] : 0;
|
||||||
|
@ -41,7 +41,7 @@ module shifter (
|
|||||||
|
|
||||||
assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension
|
assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension
|
||||||
if (`XLEN==32) begin // rv32
|
if (`XLEN==32) begin // rv32
|
||||||
if (`ZBB_SUPPORTED) begin: rotfunnel32 //rv32 shifter with rotates
|
if (`ZBB_SUPPORTED) begin: rotfunnel32 // rv32 shifter with rotates
|
||||||
always_comb // funnel mux
|
always_comb // funnel mux
|
||||||
case({Right, Rotate})
|
case({Right, Rotate})
|
||||||
2'b00: Z = {A[31:0], 31'b0};
|
2'b00: Z = {A[31:0], 31'b0};
|
||||||
@ -84,5 +84,3 @@ module shifter (
|
|||||||
assign ZShift = Z >> Offset;
|
assign ZShift = Z >> Offset;
|
||||||
assign Y = ZShift[`XLEN-1:0];
|
assign Y = ZShift[`XLEN-1:0];
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
# Kevin Wan kewan@hmc.edu 10/27/2021
|
|
||||||
def read_input(filename): #1
|
|
||||||
"""Takes in a string filename and outputs the parsed verilog code by line into a list
|
|
||||||
such that each element of the list is one line of verilog code as a string."""
|
|
||||||
lineOfCode = []
|
|
||||||
input_file = open(filename, 'r')
|
|
||||||
for line in input_file:
|
|
||||||
lineOfCode.append(line)
|
|
||||||
return lineOfCode
|
|
||||||
###################################################################################
|
|
||||||
def ID_start(GiantString):#2
|
|
||||||
"""takes in the list of sv file lines, outputs the location that variable names should start"""
|
|
||||||
VarLoc = 0
|
|
||||||
VarLineNum = None
|
|
||||||
for lines in GiantString:
|
|
||||||
if ' logic ' in lines and (lines.find("//") == -1 or lines.find("//") > lines.find(' logic ')): # // logic does not proceed. logic proceeds. logic // proceeds.
|
|
||||||
if "[" in lines and "]" in lines:# need to account for these space
|
|
||||||
NowLoc = lines.find(']') + 3# column number in sv code when 1st char of the var name should appear.
|
|
||||||
if NowLoc>VarLoc:
|
|
||||||
VarLoc = NowLoc
|
|
||||||
VarLineNum = GiantString.index(lines) # Update this number if new record is made.
|
|
||||||
else:
|
|
||||||
NowLoc = lines.find('logic') + 7 # same as before.
|
|
||||||
if NowLoc>VarLoc:
|
|
||||||
VarLoc = NowLoc
|
|
||||||
VarLineNum = GiantString.index(lines)
|
|
||||||
#print("Furthest variable appears on line", VarLineNum + 1,VarLoc) # Disable this line after debugging.
|
|
||||||
return VarLoc
|
|
||||||
##################################################################################
|
|
||||||
def modified_logNew(GS,SOV): #3
|
|
||||||
Ind = SOV - 1 # SOV is for human readability, Ind is the character's index in computer, since computers count from 0's we need to correct it.
|
|
||||||
Out = []
|
|
||||||
for l in GS:
|
|
||||||
lines = l.replace('\t',' ')
|
|
||||||
|
|
||||||
if ' logic ' in lines and (lines.find("//") == -1 or lines.find("//") > lines.find(' logic ')): # // logic does not proceed. logic proceeds. logic // proceeds.
|
|
||||||
if "[" in lines and "]" in lines: # the line is an extended declaration.
|
|
||||||
EditLoc = lines.find("]") # Re-finds the string index number of ].
|
|
||||||
VarLoc = FindCharRel(lines[EditLoc+1::]) + EditLoc + 1 # Checks where variable declaration currently is at.
|
|
||||||
#print(VarLoc,lines[VarLoc])# VERIFIED
|
|
||||||
NewLine = Mod_Space_at(lines,VarLoc,VarLoc-Ind)
|
|
||||||
Out.append(NewLine)# Verified0957 10272021
|
|
||||||
else:
|
|
||||||
EditLoc1 = lines.find('c') # Hopefully sees the c in 'logic'
|
|
||||||
|
|
||||||
VarLoc1 = FindCharRel(lines[EditLoc1+1::]) + EditLoc1 + 1
|
|
||||||
NewLine1 = Mod_Space_at(lines,VarLoc1,VarLoc1-Ind)
|
|
||||||
|
|
||||||
Out.append(NewLine1)# Verified 1005 10272021
|
|
||||||
else:
|
|
||||||
Out.append(lines)
|
|
||||||
return Out
|
|
||||||
################################################################################
|
|
||||||
def write_to_output(filename,GiantString,OW=True,Lines_editted=None): #4
|
|
||||||
"""Filename is preferrably passed from the early function calls"""
|
|
||||||
"""GiantString has all the corrected features in the code, each line is a good verilog code line"""
|
|
||||||
newname = filename
|
|
||||||
if not OW or OW =='f': #which means no overwrite (create a new file)
|
|
||||||
Decomposed=filename.split('.')
|
|
||||||
newname = Decomposed[0] + "_AL." + Decomposed[1] # AL for aligned.
|
|
||||||
|
|
||||||
OutFile = open(newname,'w') # This step should create a new file.
|
|
||||||
OutFile.writelines(GiantString)
|
|
||||||
OutFile.close()
|
|
||||||
print("Success! " + newname + " Now contains an aligned file!")
|
|
||||||
return newname
|
|
||||||
#################################################################################
|
|
||||||
|
|
||||||
def FindCharRel(Ln):
|
|
||||||
#returns the computer location of a character's first occurence
|
|
||||||
for num in range(len(Ln)):
|
|
||||||
if Ln[num] != " ":
|
|
||||||
return num
|
|
||||||
|
|
||||||
|
|
||||||
def Mod_Space_at(Ln,loc,diff):
|
|
||||||
#loc is the varLoc from mln, diff is varLoc - Ind
|
|
||||||
if diff > 0: # to delete
|
|
||||||
NewString = Ln[:(loc-diff)] + Ln[loc:]
|
|
||||||
|
|
||||||
if diff < 0: # to add
|
|
||||||
NewString = Ln[:loc] + (-diff)*" " + Ln[loc:]
|
|
||||||
if diff == 0:
|
|
||||||
NewString = Ln
|
|
||||||
|
|
||||||
return NewString
|
|
||||||
|
|
||||||
'''def main_filehandler(overwrite=False):
|
|
||||||
for filename in os.listdir():
|
|
||||||
if ".sv" in filename:
|
|
||||||
GiantString = read_input(filename)
|
|
||||||
SOV = ID_start(GiantString)
|
|
||||||
ModifiedGS = modified_logNew(GiantString,SOV)
|
|
||||||
Newname = write_to_output(filename,ModifiedGS,overwrite)'''
|
|
||||||
def root_filehandler(path,overwrite=False):
|
|
||||||
for f in os.listdir(path):
|
|
||||||
if os.path.isdir(f):
|
|
||||||
root_filehandler(path+"/"+f)
|
|
||||||
else:
|
|
||||||
if ".sv" in f:
|
|
||||||
GiantString = read_input(f)
|
|
||||||
SOV = ID_start(GiantString)
|
|
||||||
ModifiedGS = modified_logNew(GiantString,SOV)
|
|
||||||
Newname = write_to_output(f,ModifiedGS,overwrite)
|
|
||||||
|
|
||||||
|
|
||||||
def driver(overwrite=False):
|
|
||||||
root_filehandler(os.getcwd())
|
|
||||||
|
|
||||||
driver(True)
|
|
@ -191,7 +191,7 @@ module bpred import cvw::*; #(parameter cvw_t P) (
|
|||||||
if(`INSTR_CLASS_PRED) mux2 #(P.XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPWrongM, NextValidPCE);
|
if(`INSTR_CLASS_PRED) mux2 #(P.XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPWrongM, NextValidPCE);
|
||||||
else assign NextValidPCE = PCE;
|
else assign NextValidPCE = PCE;
|
||||||
|
|
||||||
if(P.ZICOUNTERS_SUPPORTED) begin
|
if(P.ZIHPM_SUPPORTED) begin
|
||||||
logic [P.XLEN-1:0] RASPCD, RASPCE;
|
logic [P.XLEN-1:0] RASPCD, RASPCE;
|
||||||
logic BTAWrongE, RASPredPCWrongE;
|
logic BTAWrongE, RASPredPCWrongE;
|
||||||
// performance counters
|
// performance counters
|
||||||
|
@ -181,4 +181,3 @@ module decompress #(parameter XLEN)(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
191
src/ifu/ifu.sv
191
src/ifu/ifu.sv
@ -26,116 +26,115 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module ifu import cvw::*; #(parameter cvw_t P) (
|
module ifu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallF, StallD, StallE, StallM, StallW,
|
input logic StallF, StallD, StallE, StallM, StallW,
|
||||||
input logic FlushD, FlushE, FlushM, FlushW,
|
input logic FlushD, FlushE, FlushM, FlushW,
|
||||||
output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation
|
output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation
|
||||||
// Command from CPU
|
// Command from CPU
|
||||||
input logic InvalidateICacheM, // Clears all instruction cache valid bits
|
input logic InvalidateICacheM, // Clears all instruction cache valid bits
|
||||||
input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE)
|
input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE)
|
||||||
input logic InstrValidD, InstrValidE, InstrValidM,
|
input logic InstrValidD, InstrValidE, InstrValidM,
|
||||||
input logic BranchD, BranchE,
|
input logic BranchD, BranchE,
|
||||||
input logic JumpD, JumpE,
|
input logic JumpD, JumpE,
|
||||||
// Bus interface
|
// Bus interface
|
||||||
output logic [P.PA_BITS-1:0] IFUHADDR, // Bus address from IFU to EBU
|
output logic [P.PA_BITS-1:0] IFUHADDR, // Bus address from IFU to EBU
|
||||||
input logic [P.XLEN-1:0] HRDATA, // Bus read data from IFU to EBU
|
input logic [P.XLEN-1:0] HRDATA, // Bus read data from IFU to EBU
|
||||||
input logic IFUHREADY, // Bus ready from IFU to EBU
|
input logic IFUHREADY, // Bus ready from IFU to EBU
|
||||||
output logic IFUHWRITE, // Bus write operation from IFU to EBU
|
output logic IFUHWRITE, // Bus write operation from IFU to EBU
|
||||||
output logic [2:0] IFUHSIZE, // Bus operation size from IFU to EBU
|
output logic [2:0] IFUHSIZE, // Bus operation size from IFU to EBU
|
||||||
output logic [2:0] IFUHBURST, // Bus burst from IFU to EBU
|
output logic [2:0] IFUHBURST, // Bus burst from IFU to EBU
|
||||||
output logic [1:0] IFUHTRANS, // Bus transaction type from IFU to EBU
|
output logic [1:0] IFUHTRANS, // Bus transaction type from IFU to EBU
|
||||||
|
|
||||||
output logic [P.XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW
|
output logic [P.XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW
|
||||||
// Execute
|
// Execute
|
||||||
output logic [P.XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
output logic [P.XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
||||||
input logic PCSrcE, // Executation stage branch is taken
|
input logic PCSrcE, // Executation stage branch is taken
|
||||||
input logic [P.XLEN-1:0] IEUAdrE, // The branch/jump target address
|
input logic [P.XLEN-1:0] IEUAdrE, // The branch/jump target address
|
||||||
input logic [P.XLEN-1:0] IEUAdrM, // The branch/jump target address
|
input logic [P.XLEN-1:0] IEUAdrM, // The branch/jump target address
|
||||||
output logic [P.XLEN-1:0] PCE, // Execution stage instruction address
|
output logic [P.XLEN-1:0] PCE, // Execution stage instruction address
|
||||||
output logic BPWrongE, // Prediction is wrong
|
output logic BPWrongE, // Prediction is wrong
|
||||||
output logic BPWrongM, // Prediction is wrong
|
output logic BPWrongM, // Prediction is wrong
|
||||||
// Mem
|
// Mem
|
||||||
output logic CommittedF, // I$ or bus memory operation started, delay interrupts
|
output logic CommittedF, // I$ or bus memory operation started, delay interrupts
|
||||||
input logic [P.XLEN-1:0] UnalignedPCNextF, // The next PCF, but not aligned to 2 bytes.
|
input logic [P.XLEN-1:0] UnalignedPCNextF, // The next PCF, but not aligned to 2 bytes.
|
||||||
output logic [P.XLEN-1:0] PC2NextF, // Selected PC between branch prediction and next valid PC if CSRWriteFence
|
output logic [P.XLEN-1:0] PC2NextF, // Selected PC between branch prediction and next valid PC if CSRWriteFence
|
||||||
output logic [31:0] InstrD, // The decoded instruction in Decode stage
|
output logic [31:0] InstrD, // The decoded instruction in Decode stage
|
||||||
output logic [31:0] InstrM, // The decoded instruction in Memory stage
|
output logic [31:0] InstrM, // The decoded instruction in Memory stage
|
||||||
output logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
output logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||||
output logic [P.XLEN-1:0] PCM, // Memory stage instruction address
|
output logic [P.XLEN-1:0] PCM, // Memory stage instruction address
|
||||||
// branch predictor
|
// branch predictor
|
||||||
output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br
|
output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br
|
||||||
output logic BPDirPredWrongM, // Prediction direction is wrong
|
output logic BPDirPredWrongM, // Prediction direction is wrong
|
||||||
output logic BTAWrongM, // Prediction target wrong
|
output logic BTAWrongM, // Prediction target wrong
|
||||||
output logic RASPredPCWrongM, // RAS prediction is wrong
|
output logic RASPredPCWrongM, // RAS prediction is wrong
|
||||||
output logic IClassWrongM, // Class prediction is wrong
|
output logic IClassWrongM, // Class prediction is wrong
|
||||||
output logic ICacheStallF, // I$ busy with multicycle operation
|
output logic ICacheStallF, // I$ busy with multicycle operation
|
||||||
// Faults
|
// Faults
|
||||||
input logic IllegalBaseInstrD, // Illegal non-compressed instruction
|
input logic IllegalBaseInstrD, // Illegal non-compressed instruction
|
||||||
input logic IllegalFPUInstrD, // Illegal FP instruction
|
input logic IllegalFPUInstrD, // Illegal FP instruction
|
||||||
output logic InstrPageFaultF, // Instruction page fault
|
output logic InstrPageFaultF, // Instruction page fault
|
||||||
output logic IllegalIEUFPUInstrD, // Illegal instruction including compressed & FP
|
output logic IllegalIEUFPUInstrD, // Illegal instruction including compressed & FP
|
||||||
output logic InstrMisalignedFaultM, // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
output logic InstrMisalignedFaultM, // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||||
// mmu management
|
// mmu management
|
||||||
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
|
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
|
||||||
input logic [P.XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
|
input logic [P.XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
|
||||||
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
|
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
|
||||||
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
|
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
|
||||||
input logic [P.XLEN-1:0] SATP_REGW, // Location of the root page table and page table configuration
|
input logic [P.XLEN-1:0] SATP_REGW, // Location of the root page table and page table configuration
|
||||||
input logic STATUS_MXR, // Status CSR: make executable page readable
|
input logic STATUS_MXR, // Status CSR: make executable page readable
|
||||||
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
||||||
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
||||||
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
|
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
|
||||||
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
||||||
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||||
output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
||||||
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP address from privileged unit
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],// PMP address from privileged unit
|
||||||
output logic InstrAccessFaultF, // Instruction access fault
|
output logic InstrAccessFaultF, // Instruction access fault
|
||||||
output logic ICacheAccess, // Report I$ read to performance counters
|
output logic ICacheAccess, // Report I$ read to performance counters
|
||||||
output logic ICacheMiss // Report I$ miss to performance counters
|
output logic ICacheMiss // Report I$ miss to performance counters
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
||||||
|
|
||||||
logic [P.XLEN-1:0] PCNextF; // Next PCF, selected from Branch predictor, Privilege, or PC+2/4
|
logic [P.XLEN-1:0] PCNextF; // Next PCF, selected from Branch predictor, Privilege, or PC+2/4
|
||||||
logic BranchMisalignedFaultE; // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
logic BranchMisalignedFaultE; // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||||
logic [P.XLEN-1:0] PCPlus2or4F; // PCF + 2 (CompressedF) or PCF + 4 (Non-compressed)
|
logic [P.XLEN-1:0] PCPlus2or4F; // PCF + 2 (CompressedF) or PCF + 4 (Non-compressed)
|
||||||
logic [P.XLEN-1:0] PCSpillNextF; // Next PCF after possible + 2 to handle spill
|
logic [P.XLEN-1:0] PCSpillNextF; // Next PCF after possible + 2 to handle spill
|
||||||
logic [P.XLEN-1:0] PCLinkD; // PCF2or4F delayed 1 cycle. This is next PC after a control flow instruction (br or j)
|
logic [P.XLEN-1:0] PCLinkD; // PCF2or4F delayed 1 cycle. This is next PC after a control flow instruction (br or j)
|
||||||
logic [P.XLEN-1:2] PCPlus4F; // PCPlus4F is always PCF + 4. Fancy way to compute PCPlus2or4F
|
logic [P.XLEN-1:2] PCPlus4F; // PCPlus4F is always PCF + 4. Fancy way to compute PCPlus2or4F
|
||||||
logic [P.XLEN-1:0] PCD; // Decode stage instruction address
|
logic [P.XLEN-1:0] PCD; // Decode stage instruction address
|
||||||
logic [P.XLEN-1:0] NextValidPCE; // The PC of the next valid instruction in the pipeline after csr write or fence
|
logic [P.XLEN-1:0] NextValidPCE; // The PC of the next valid instruction in the pipeline after csr write or fence
|
||||||
logic [P.XLEN-1:0] PCF; // Fetch stage instruction address
|
logic [P.XLEN-1:0] PCF; // Fetch stage instruction address
|
||||||
logic [P.PA_BITS-1:0] PCPF; // Physical address after address translation
|
logic [P.PA_BITS-1:0] PCPF; // Physical address after address translation
|
||||||
logic [P.XLEN+1:0] PCFExt; //
|
logic [P.XLEN+1:0] PCFExt;
|
||||||
|
|
||||||
logic [31:0] IROMInstrF; // Instruction from the IROM
|
logic [31:0] IROMInstrF; // Instruction from the IROM
|
||||||
logic [31:0] ICacheInstrF; // Instruction from the I$
|
logic [31:0] ICacheInstrF; // Instruction from the I$
|
||||||
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
||||||
logic CompressedF; // The fetched instruction is compressed
|
logic CompressedF; // The fetched instruction is compressed
|
||||||
logic CompressedD; // The decoded instruction is compressed
|
logic CompressedD; // The decoded instruction is compressed
|
||||||
logic CompressedE; // The execution instruction is compressed
|
logic CompressedE; // The execution instruction is compressed
|
||||||
logic CompressedM; // The execution instruction is compressed
|
logic CompressedM; // The execution instruction is compressed
|
||||||
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
||||||
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
||||||
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
||||||
|
|
||||||
logic [1:0] IFURWF; // IFU alreays read IFURWF = 10
|
logic [1:0] IFURWF; // IFU alreays read IFURWF = 10
|
||||||
logic [31:0] InstrE; // Instruction in the Execution stage
|
logic [31:0] InstrE; // Instruction in the Execution stage
|
||||||
logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush
|
logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush
|
||||||
|
|
||||||
|
logic CacheableF; // PMA indicates instruction address is cacheable
|
||||||
logic CacheableF; // PMA indicates instruction address is cacheable
|
logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF
|
||||||
logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF
|
logic BusStall; // Bus interface busy with multicycle operation
|
||||||
logic BusStall; // Bus interface busy with multicycle operation
|
logic IFUCacheBusStallF; // EIther I$ or bus busy with multicycle operation
|
||||||
logic IFUCacheBusStallF; // EIther I$ or bus busy with multicycle operation
|
logic GatedStallD; // StallD gated by selected next spill
|
||||||
logic GatedStallD; // StallD gated by selected next spill
|
|
||||||
// branch predictor signal
|
// branch predictor signal
|
||||||
logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
||||||
logic BusCommittedF; // Bus memory operation in flight, delay interrupts
|
logic BusCommittedF; // Bus memory operation in flight, delay interrupts
|
||||||
logic CacheCommittedF; // I$ memory operation started, delay interrupts
|
logic CacheCommittedF; // I$ memory operation started, delay interrupts
|
||||||
logic SelIROM; // PMA indicates instruction address is in the IROM
|
logic SelIROM; // PMA indicates instruction address is in the IROM
|
||||||
logic [15:0] InstrRawE, InstrRawM;
|
logic [15:0] InstrRawE, InstrRawM;
|
||||||
|
|
||||||
assign PCFExt = {2'b00, PCSpillF};
|
assign PCFExt = {2'b00, PCSpillF};
|
||||||
|
|
||||||
@ -199,6 +198,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Memory
|
// Memory
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// CommittedM tells the CPU's privileged unit the current instruction
|
// CommittedM tells the CPU's privileged unit the current instruction
|
||||||
// in the memory stage is a memory operaton and that memory operation is either completed
|
// in the memory stage is a memory operaton and that memory operation is either completed
|
||||||
// or is partially executed. Partially completed memory operations need to prevent an interrupts.
|
// or is partially executed. Partially completed memory operations need to prevent an interrupts.
|
||||||
@ -206,7 +206,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
// delay the interrupt until the LSU is in a clean state.
|
// delay the interrupt until the LSU is in a clean state.
|
||||||
assign CommittedF = CacheCommittedF | BusCommittedF;
|
assign CommittedF = CacheCommittedF | BusCommittedF;
|
||||||
|
|
||||||
logic IgnoreRequest;
|
logic IgnoreRequest;
|
||||||
assign IgnoreRequest = ITLBMissF | FlushD;
|
assign IgnoreRequest = ITLBMissF | FlushD;
|
||||||
|
|
||||||
// The IROM uses untranslated addresses, so it is not compatible with virtual memory.
|
// The IROM uses untranslated addresses, so it is not compatible with virtual memory.
|
||||||
@ -223,12 +223,12 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam WORDSPERLINE = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/P.XLEN : 1;
|
localparam WORDSPERLINE = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/P.XLEN : 1;
|
||||||
localparam LOGBWPL = P.ICACHE_SUPPORTED ? $clog2(WORDSPERLINE) : 1;
|
localparam LOGBWPL = P.ICACHE_SUPPORTED ? $clog2(WORDSPERLINE) : 1;
|
||||||
if(P.ICACHE_SUPPORTED) begin : icache
|
if(P.ICACHE_SUPPORTED) begin : icache
|
||||||
localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN;
|
localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN;
|
||||||
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
||||||
logic [LINELEN-1:0] FetchBuffer;
|
logic [LINELEN-1:0] FetchBuffer;
|
||||||
logic [P.PA_BITS-1:0] ICacheBusAdr;
|
logic [P.PA_BITS-1:0] ICacheBusAdr;
|
||||||
logic ICacheBusAck;
|
logic ICacheBusAck;
|
||||||
logic [1:0] CacheBusRW, BusRW, CacheRWF;
|
logic [1:0] CacheBusRW, BusRW, CacheRWF;
|
||||||
|
|
||||||
assign BusRW = ~ITLBMissF & ~CacheableF & ~SelIROM ? IFURWF : '0;
|
assign BusRW = ~ITLBMissF & ~CacheableF & ~SelIROM ? IFURWF : '0;
|
||||||
assign CacheRWF = ~ITLBMissF & CacheableF & ~SelIROM ? IFURWF : '0;
|
assign CacheRWF = ~ITLBMissF & CacheableF & ~SelIROM ? IFURWF : '0;
|
||||||
@ -255,7 +255,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.Flush(FlushD), .CacheBusRW, .HSIZE(IFUHSIZE), .HBURST(IFUHBURST), .HTRANS(IFUHTRANS), .HWSTRB(),
|
.Flush(FlushD), .CacheBusRW, .HSIZE(IFUHSIZE), .HBURST(IFUHBURST), .HTRANS(IFUHTRANS), .HWSTRB(),
|
||||||
.Funct3(3'b010), .HADDR(IFUHADDR), .HREADY(IFUHREADY), .HWRITE(IFUHWRITE), .CacheBusAdr(ICacheBusAdr),
|
.Funct3(3'b010), .HADDR(IFUHADDR), .HREADY(IFUHREADY), .HWRITE(IFUHWRITE), .CacheBusAdr(ICacheBusAdr),
|
||||||
.BeatCount(), .Cacheable(CacheableF), .SelBusBeat(), .WriteDataM('0),
|
.BeatCount(), .Cacheable(CacheableF), .SelBusBeat(), .WriteDataM('0),
|
||||||
.CacheBusAck(ICacheBusAck), .HWDATA(), .CacheableOrFlushCacheM(1'b0), .CacheReadDataWordM('0),
|
.CacheBusAck(ICacheBusAck), .HWDATA(), .CacheableOrFlushCacheM(1'b0), .CacheReadDataWordM('0),
|
||||||
.FetchBuffer, .PAdr(PCPF),
|
.FetchBuffer, .PAdr(PCPF),
|
||||||
.BusRW, .Stall(GatedStallD),
|
.BusRW, .Stall(GatedStallD),
|
||||||
.BusStall, .BusCommitted(BusCommittedF));
|
.BusStall, .BusCommitted(BusCommittedF));
|
||||||
@ -321,7 +321,6 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
else PCPlus2or4F = {PCF[P.XLEN-1:2], 2'b10};
|
else PCPlus2or4F = {PCF[P.XLEN-1:2], 2'b10};
|
||||||
else PCPlus2or4F = {PCPlus4F, PCF[1:0]}; // add 4
|
else PCPlus2or4F = {PCPlus4F, PCF[1:0]}; // add 4
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Branch and Jump Predictor
|
// Branch and Jump Predictor
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -341,10 +340,10 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign NextValidPCE = PCE;
|
assign NextValidPCE = PCE;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Decode stage pipeline register and compressed instruction decoding.
|
// Decode stage pipeline register and compressed instruction decoding.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Decode stage pipeline register and logic
|
// Decode stage pipeline register and logic
|
||||||
flopenrc #(P.XLEN) PCDReg(clk, reset, FlushD, ~StallD, PCF, PCD);
|
flopenrc #(P.XLEN) PCDReg(clk, reset, FlushD, ~StallD, PCF, PCD);
|
||||||
|
|
||||||
@ -374,10 +373,10 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// Instruction and PC/PCLink pipeline registers
|
// Instruction and PC/PCLink pipeline registers
|
||||||
// Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0.
|
// Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0.
|
||||||
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
|
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
|
||||||
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
||||||
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
|
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
|
||||||
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
||||||
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
|
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
|
||||||
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
||||||
//flopenr #(P.XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD);
|
//flopenr #(P.XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD);
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module irom import cvw::*; #(parameter cvw_t P) (
|
module irom import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic ce, // Chip Enable. 0: Holds IROMInstrF constant
|
input logic ce, // Chip Enable. 0: Holds IROMInstrF constant
|
||||||
input logic [P.XLEN-1:0] Adr, // PCNextFSpill
|
input logic [P.XLEN-1:0] Adr, // PCNextFSpill
|
||||||
output logic [31:0] IROMInstrF // Instruction read data
|
output logic [31:0] IROMInstrF // Instruction read data
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam XLENBYTES = {{P.PA_BITS-32{1'b0}}, P.XLEN/8}; // XLEN/8, adjusted for width
|
localparam XLENBYTES = {{P.PA_BITS-32{1'b0}}, P.XLEN/8}; // XLEN/8, adjusted for width
|
||||||
@ -36,14 +36,13 @@ module irom import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam OFFSET = $clog2(XLENBYTES);
|
localparam OFFSET = $clog2(XLENBYTES);
|
||||||
|
|
||||||
logic [P.XLEN-1:0] IROMInstrFFull;
|
logic [P.XLEN-1:0] IROMInstrFFull;
|
||||||
logic [31:0] RawIROMInstrF;
|
logic [31:0] RawIROMInstrF;
|
||||||
|
logic [1:0] AdrD;
|
||||||
logic [1:0] AdrD;
|
|
||||||
flopen #(2) AdrReg(clk, ce, Adr[2:1], AdrD);
|
flopen #(2) AdrReg(clk, ce, Adr[2:1], AdrD);
|
||||||
|
|
||||||
rom1p1r #(ADDR_WDITH, P.XLEN) rom(.clk, .ce, .addr(Adr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(IROMInstrFFull));
|
rom1p1r #(ADDR_WDITH, P.XLEN) rom(.clk, .ce, .addr(Adr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(IROMInstrFFull));
|
||||||
if (P.XLEN == 32) assign RawIROMInstrF = IROMInstrFFull;
|
if (P.XLEN == 32) assign RawIROMInstrF = IROMInstrFFull;
|
||||||
else begin
|
else begin
|
||||||
// IROM is aligned to XLEN words, but instructions are 32 bits. Select between the two
|
// IROM is aligned to XLEN words, but instructions are 32 bits. Select between the two
|
||||||
// haves. Adr is the Next PCF not PCF so we delay 1 cycle.
|
// haves. Adr is the Next PCF not PCF so we delay 1 cycle.
|
||||||
assign RawIROMInstrF = AdrD[1] ? IROMInstrFFull[63:32] : IROMInstrFFull[31:0];
|
assign RawIROMInstrF = AdrD[1] ? IROMInstrFFull[63:32] : IROMInstrFFull[31:0];
|
||||||
@ -52,4 +51,3 @@ module irom import cvw::*; #(parameter cvw_t P) (
|
|||||||
// The spill logic will handle merging the two together.
|
// The spill logic will handle merging the two together.
|
||||||
assign IROMInstrF = AdrD[0] ? {16'b0, RawIROMInstrF[31:16]} : RawIROMInstrF;
|
assign IROMInstrF = AdrD[0] ? {16'b0, RawIROMInstrF[31:16]} : RawIROMInstrF;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -32,33 +32,33 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module spill import cvw::*; #(parameter cvw_t P) (
|
module spill import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallD, FlushD,
|
input logic StallD, FlushD,
|
||||||
input logic [P.XLEN-1:0] PCF, // 2 byte aligned PC in Fetch stage
|
input logic [P.XLEN-1:0] PCF, // 2 byte aligned PC in Fetch stage
|
||||||
input logic [P.XLEN-1:2] PCPlus4F, // PCF + 4
|
input logic [P.XLEN-1:2] PCPlus4F, // PCF + 4
|
||||||
input logic [P.XLEN-1:0] PCNextF, // The next PCF
|
input logic [P.XLEN-1:0] PCNextF, // The next PCF
|
||||||
input logic [31:0] InstrRawF, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
|
input logic [31:0] InstrRawF, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
|
||||||
input logic IFUCacheBusStallF, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
|
input logic IFUCacheBusStallF, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
|
||||||
input logic ITLBMissF, // ITLB miss, ignore memory request
|
input logic ITLBMissF, // ITLB miss, ignore memory request
|
||||||
input logic InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
|
input logic InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
|
||||||
output logic [P.XLEN-1:0] PCSpillNextF, // The next PCF for one of the two memory addresses of the spill
|
output logic [P.XLEN-1:0] PCSpillNextF, // The next PCF for one of the two memory addresses of the spill
|
||||||
output logic [P.XLEN-1:0] PCSpillF, // PCF for one of the two memory addresses of the spill
|
output logic [P.XLEN-1:0] PCSpillF, // PCF for one of the two memory addresses of the spill
|
||||||
output logic SelSpillNextF, // During the transition between the two spill operations, the IFU should stall the pipeline
|
output logic SelSpillNextF, // During the transition between the two spill operations, the IFU should stall the pipeline
|
||||||
output logic [31:0] PostSpillInstrRawF,// The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
output logic [31:0] PostSpillInstrRawF,// The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
||||||
output logic CompressedF); // The fetched instruction is compressed
|
output logic CompressedF); // The fetched instruction is compressed
|
||||||
|
|
||||||
// Spill threshold occurs when all the cache offset PC bits are 1 (except [0]). Without a cache this is just PCF[1]
|
// Spill threshold occurs when all the cache offset PC bits are 1 (except [0]). Without a cache this is just PCF[1]
|
||||||
typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype;
|
typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype;
|
||||||
localparam SPILLTHRESHOLD = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/32 : 1;
|
localparam SPILLTHRESHOLD = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/32 : 1;
|
||||||
|
|
||||||
statetype CurrState, NextState;
|
statetype CurrState, NextState;
|
||||||
logic [P.XLEN-1:0] PCPlus2F;
|
logic [P.XLEN-1:0] PCPlus2F;
|
||||||
logic TakeSpillF;
|
logic TakeSpillF;
|
||||||
logic SpillF;
|
logic SpillF;
|
||||||
logic SelSpillF;
|
logic SelSpillF;
|
||||||
logic SpillSaveF;
|
logic SpillSaveF;
|
||||||
logic [15:0] InstrFirstHalfF;
|
logic [15:0] InstrFirstHalfF;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// PC logic
|
// PC logic
|
||||||
@ -71,7 +71,6 @@ module spill import cvw::*; #(parameter cvw_t P) (
|
|||||||
// select between PCF and PCF+2
|
// select between PCF and PCF+2
|
||||||
mux2 #(P.XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCSpillF));
|
mux2 #(P.XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCSpillF));
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Detect spill
|
// Detect spill
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
module amoalu import cvw::*; #(parameter cvw_t P) (
|
module amoalu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.XLEN-1:0] ReadDataM, // LSU's ReadData
|
input logic [P.XLEN-1:0] ReadDataM, // LSU's ReadData
|
||||||
input logic [P.XLEN-1:0] IHWriteDataM, // LSU's WriteData
|
input logic [P.XLEN-1:0] IHWriteDataM, // LSU's WriteData
|
||||||
input logic [6:0] LSUFunct7M, // ALU Operation
|
input logic [6:0] LSUFunct7M, // ALU Operation
|
||||||
input logic [2:0] LSUFunct3M, // Memoy access width
|
input logic [2:0] LSUFunct3M, // Memoy access width
|
||||||
output logic [P.XLEN-1:0] AMOResultM // ALU output
|
output logic [P.XLEN-1:0] AMOResultM // ALU output
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -72,4 +72,3 @@ module amoalu import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -28,24 +28,24 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module atomic import cvw::*; #(parameter cvw_t P) (
|
module atomic import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallW,
|
input logic StallW,
|
||||||
input logic [P.XLEN-1:0] ReadDataM, // LSU ReadData XLEN because FPU does not issue atomic memory operation from FPU registers
|
input logic [P.XLEN-1:0] ReadDataM, // LSU ReadData XLEN because FPU does not issue atomic memory operation from FPU registers
|
||||||
input logic [P.XLEN-1:0] IHWriteDataM, // LSU WriteData XLEN because FPU does not issue atomic memory operation from FPU registers
|
input logic [P.XLEN-1:0] IHWriteDataM, // LSU WriteData XLEN because FPU does not issue atomic memory operation from FPU registers
|
||||||
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
||||||
input logic [6:0] LSUFunct7M, // AMO alu operation gated by HPTW
|
input logic [6:0] LSUFunct7M, // AMO alu operation gated by HPTW
|
||||||
input logic [2:0] LSUFunct3M, // IEU or HPTW memory operation size
|
input logic [2:0] LSUFunct3M, // IEU or HPTW memory operation size
|
||||||
input logic [1:0] LSUAtomicM, // 10: AMO operation, select AMOResultM as the writedata output, 01: LR/SC operation
|
input logic [1:0] LSUAtomicM, // 10: AMO operation, select AMOResultM as the writedata output, 01: LR/SC operation
|
||||||
input logic [1:0] PreLSURWM, // IEU or HPTW Read/Write signal
|
input logic [1:0] PreLSURWM, // IEU or HPTW Read/Write signal
|
||||||
input logic IgnoreRequest, // On FlushM or TLB miss ignore memory operation
|
input logic IgnoreRequest, // On FlushM or TLB miss ignore memory operation
|
||||||
output logic [P.XLEN-1:0] IMAWriteDataM, // IEU, HPTW, or AMO write data
|
output logic [P.XLEN-1:0] IMAWriteDataM, // IEU, HPTW, or AMO write data
|
||||||
output logic SquashSCW, // Store conditional failed disable write to GPR
|
output logic SquashSCW, // Store conditional failed disable write to GPR
|
||||||
output logic [1:0] LSURWM // IEU or HPTW Read/Write signal gated by LR/SC
|
output logic [1:0] LSURWM // IEU or HPTW Read/Write signal gated by LR/SC
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN-1:0] AMOResultM;
|
logic [P.XLEN-1:0] AMOResultM;
|
||||||
logic MemReadM;
|
logic MemReadM;
|
||||||
|
|
||||||
amoalu #(P) amoalu(.ReadDataM, .IHWriteDataM, .LSUFunct7M, .LSUFunct3M, .AMOResultM);
|
amoalu #(P) amoalu(.ReadDataM, .IHWriteDataM, .LSUFunct7M, .LSUFunct3M, .AMOResultM);
|
||||||
|
|
||||||
|
@ -28,17 +28,17 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module dtim import cvw::*; #(parameter cvw_t P) (
|
module dtim import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic FlushW,
|
input logic FlushW,
|
||||||
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
|
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
|
||||||
input logic [1:0] MemRWM, // Read/Write control
|
input logic [1:0] MemRWM, // Read/Write control
|
||||||
input logic [P.PA_BITS-1:0] DTIMAdr, // No stall: Execution stage memory address. Stall: Memory stage memory address
|
input logic [P.PA_BITS-1:0] DTIMAdr, // No stall: Execution stage memory address. Stall: Memory stage memory address
|
||||||
input logic [P.LLEN-1:0] WriteDataM, // Write data from IEU
|
input logic [P.LLEN-1:0] WriteDataM, // Write data from IEU
|
||||||
input logic [P.LLEN/8-1:0] ByteMaskM, // Selects which bytes within a word to write
|
input logic [P.LLEN/8-1:0] ByteMaskM, // Selects which bytes within a word to write
|
||||||
output logic [P.LLEN-1:0] ReadDataWordM // Read data before subword selection
|
output logic [P.LLEN-1:0] ReadDataWordM // Read data before subword selection
|
||||||
);
|
);
|
||||||
|
|
||||||
logic we;
|
logic we;
|
||||||
|
|
||||||
localparam LLENBYTES = P.LLEN/8;
|
localparam LLENBYTES = P.LLEN/8;
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
@ -52,4 +52,3 @@ module dtim import cvw::*; #(parameter cvw_t P) (
|
|||||||
ram1p1rwbe #(.DEPTH(DEPTH), .WIDTH(P.LLEN))
|
ram1p1rwbe #(.DEPTH(DEPTH), .WIDTH(P.LLEN))
|
||||||
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
|
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -29,23 +29,23 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module lrsc import cvw::*; #(parameter cvw_t P) (
|
module lrsc import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallW,
|
input logic StallW,
|
||||||
input logic MemReadM, // Memory read
|
input logic MemReadM, // Memory read
|
||||||
input logic [1:0] PreLSURWM, // Memory operation from the HPTW or IEU [1]: read, [0]: write
|
input logic [1:0] PreLSURWM, // Memory operation from the HPTW or IEU [1]: read, [0]: write
|
||||||
output logic [1:0] LSURWM, // Memory operation after potential squash of SC
|
output logic [1:0] LSURWM, // Memory operation after potential squash of SC
|
||||||
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
||||||
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
||||||
output logic SquashSCW // Squash the store conditional by not allowing rf write
|
output logic SquashSCW // Squash the store conditional by not allowing rf write
|
||||||
);
|
);
|
||||||
|
|
||||||
// possible bug: *** double check if PreLSURWM needs to be flushed by ignorerequest.
|
// possible bug: *** double check if PreLSURWM needs to be flushed by ignorerequest.
|
||||||
// Handle atomic load reserved / store conditional
|
// Handle atomic load reserved / store conditional
|
||||||
logic [P.PA_BITS-1:2] ReservationPAdrW;
|
logic [P.PA_BITS-1:2] ReservationPAdrW;
|
||||||
logic ReservationValidM, ReservationValidW;
|
logic ReservationValidM, ReservationValidW;
|
||||||
logic lrM, scM, WriteAdrMatchM;
|
logic lrM, scM, WriteAdrMatchM;
|
||||||
logic SquashSCM;
|
logic SquashSCM;
|
||||||
|
|
||||||
assign lrM = MemReadM & LSUAtomicM[0];
|
assign lrM = MemReadM & LSUAtomicM[0];
|
||||||
assign scM = PreLSURWM[0] & LSUAtomicM[0];
|
assign scM = PreLSURWM[0] & LSUAtomicM[0];
|
||||||
|
170
src/lsu/lsu.sv
170
src/lsu/lsu.sv
@ -30,63 +30,63 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module lsu import cvw::*; #(parameter cvw_t P) (
|
module lsu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallM, FlushM, StallW, FlushW,
|
input logic StallM, FlushM, StallW, FlushW,
|
||||||
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation
|
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation
|
||||||
// connected to cpu (controls)
|
// connected to cpu (controls)
|
||||||
input logic [1:0] MemRWM, // Read/Write control
|
input logic [1:0] MemRWM, // Read/Write control
|
||||||
input logic [2:0] Funct3M, // Size of memory operation
|
input logic [2:0] Funct3M, // Size of memory operation
|
||||||
input logic [6:0] Funct7M, // Atomic memory operation function
|
input logic [6:0] Funct7M, // Atomic memory operation function
|
||||||
input logic [1:0] AtomicM, // Atomic memory operation
|
input logic [1:0] AtomicM, // Atomic memory operation
|
||||||
input logic FlushDCacheM, // Flush D cache to next level of memory
|
input logic FlushDCacheM, // Flush D cache to next level of memory
|
||||||
output logic CommittedM, // Delay interrupts while memory operation in flight
|
output logic CommittedM, // Delay interrupts while memory operation in flight
|
||||||
output logic SquashSCW, // Store conditional failed disable write to GPR
|
output logic SquashSCW, // Store conditional failed disable write to GPR
|
||||||
output logic DCacheMiss, // D cache miss for performance counters
|
output logic DCacheMiss, // D cache miss for performance counters
|
||||||
output logic DCacheAccess, // D cache memory access for performance counters
|
output logic DCacheAccess, // D cache memory access for performance counters
|
||||||
// address and write data
|
// address and write data
|
||||||
input logic [P.XLEN-1:0] IEUAdrE, // Execution stage memory address
|
input logic [P.XLEN-1:0] IEUAdrE, // Execution stage memory address
|
||||||
output logic [P.XLEN-1:0] IEUAdrM, // Memory stage memory address
|
output logic [P.XLEN-1:0] IEUAdrM, // Memory stage memory address
|
||||||
input logic [P.XLEN-1:0] WriteDataM, // Write data from IEU
|
input logic [P.XLEN-1:0] WriteDataM, // Write data from IEU
|
||||||
output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU
|
output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU
|
||||||
// cpu privilege
|
// cpu privilege
|
||||||
input logic [1:0] PrivilegeModeW, // Current privilege mode
|
input logic [1:0] PrivilegeModeW, // Current privilege mode
|
||||||
input logic BigEndianM, // Swap byte order to big endian
|
input logic BigEndianM, // Swap byte order to big endian
|
||||||
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
||||||
output logic DCacheStallM, // D$ busy with multicycle operation
|
output logic DCacheStallM, // D$ busy with multicycle operation
|
||||||
// fpu
|
// fpu
|
||||||
input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU
|
input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU
|
||||||
input logic FpLoadStoreM, // Selects FPU as store for write data
|
input logic FpLoadStoreM, // Selects FPU as store for write data
|
||||||
// faults
|
// faults
|
||||||
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
|
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
|
||||||
output logic LoadMisalignedFaultM, // Load address misaligned fault
|
output logic LoadMisalignedFaultM, // Load address misaligned fault
|
||||||
output logic LoadAccessFaultM, // Load access fault (PMA)
|
output logic LoadAccessFaultM, // Load access fault (PMA)
|
||||||
output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch
|
output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch
|
||||||
// cpu hazard unit (trap)
|
// cpu hazard unit (trap)
|
||||||
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
|
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
|
||||||
output logic StoreAmoAccessFaultM, // Store or AMO access fault
|
output logic StoreAmoAccessFaultM, // Store or AMO access fault
|
||||||
// connect to ahb
|
// connect to ahb
|
||||||
output logic [P.PA_BITS-1:0] LSUHADDR, // Bus address from LSU to EBU
|
output logic [P.PA_BITS-1:0] LSUHADDR, // Bus address from LSU to EBU
|
||||||
input logic [P.XLEN-1:0] HRDATA, // Bus read data from LSU to EBU
|
input logic [P.XLEN-1:0] HRDATA, // Bus read data from LSU to EBU
|
||||||
output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU
|
output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU
|
||||||
input logic LSUHREADY, // Bus ready from LSU to EBU
|
input logic LSUHREADY, // Bus ready from LSU to EBU
|
||||||
output logic LSUHWRITE, // Bus write operation from LSU to EBU
|
output logic LSUHWRITE, // Bus write operation from LSU to EBU
|
||||||
output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU
|
output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU
|
||||||
output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU
|
output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU
|
||||||
output logic [1:0] LSUHTRANS, // Bus transaction type from LSU to EBU
|
output logic [1:0] LSUHTRANS, // Bus transaction type from LSU to EBU
|
||||||
output logic [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
|
output logic [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
|
||||||
// page table walker
|
// page table walker
|
||||||
input logic [P.XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR
|
input logic [P.XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR
|
||||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
|
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
|
||||||
input logic [1:0] STATUS_MPP, // Machine previous privilege mode
|
input logic [1:0] STATUS_MPP, // Machine previous privilege mode
|
||||||
input logic [P.XLEN-1:0] PCSpillF, // Fetch PC
|
input logic [P.XLEN-1:0] PCSpillF, // Fetch PC
|
||||||
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||||
input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
||||||
output logic [P.XLEN-1:0] PTE, // Page table entry write to ITLB
|
output logic [P.XLEN-1:0] PTE, // Page table entry write to ITLB
|
||||||
output logic [1:0] PageType, // Type of page table entry to write to ITLB
|
output logic [1:0] PageType, // Type of page table entry to write to ITLB
|
||||||
output logic ITLBWriteF, // Write PTE to ITLB
|
output logic ITLBWriteF, // Write PTE to ITLB
|
||||||
output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE
|
output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE
|
||||||
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP address from privileged unit
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP address from privileged unit
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
|
logic [P.XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
|
||||||
@ -94,20 +94,20 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [P.PA_BITS-1:0] PAdrM; // Physical memory address
|
logic [P.PA_BITS-1:0] PAdrM; // Physical memory address
|
||||||
logic [P.XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
|
logic [P.XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
|
||||||
|
|
||||||
logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
|
logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
|
||||||
logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
|
logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
|
||||||
logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
|
logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
|
||||||
logic [6:0] LSUFunct7M; // AMO function gated by HPTW
|
logic [6:0] LSUFunct7M; // AMO function gated by HPTW
|
||||||
logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
|
logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
|
||||||
|
|
||||||
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
|
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
|
||||||
|
|
||||||
logic BusStall; // Bus interface busy with multicycle operation
|
logic BusStall; // Bus interface busy with multicycle operation
|
||||||
logic HPTWStall; // HPTW busy with multicycle operation
|
logic HPTWStall; // HPTW busy with multicycle operation
|
||||||
|
|
||||||
logic CacheableM; // PMA indicates memory address is cacheable
|
logic CacheableM; // PMA indicates memory address is cacheable
|
||||||
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
|
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
|
||||||
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
|
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
|
||||||
|
|
||||||
logic [P.LLEN-1:0] DTIMReadDataWordM; // DTIM read data
|
logic [P.LLEN-1:0] DTIMReadDataWordM; // DTIM read data
|
||||||
logic [P.LLEN-1:0] DCacheReadDataWordM; // D$ read data
|
logic [P.LLEN-1:0] DCacheReadDataWordM; // D$ read data
|
||||||
@ -123,16 +123,15 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [P.LLEN-1:0] LSUWriteDataM; // Final write data
|
logic [P.LLEN-1:0] LSUWriteDataM; // Final write data
|
||||||
logic [(P.LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
|
logic [(P.LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
|
||||||
|
|
||||||
logic DTLBMissM; // DTLB miss causes HPTW walk
|
logic DTLBMissM; // DTLB miss causes HPTW walk
|
||||||
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
||||||
logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
|
logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
|
||||||
logic LSULoadAccessFaultM; // Load acces fault
|
logic LSULoadAccessFaultM; // Load acces fault
|
||||||
logic LSUStoreAmoAccessFaultM; // Store access fault
|
logic LSUStoreAmoAccessFaultM; // Store access fault
|
||||||
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
|
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
|
||||||
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
|
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
|
||||||
logic SelDTIM; // Select DTIM rather than bus or D$
|
logic SelDTIM; // Select DTIM rather than bus or D$
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Pipeline for IEUAdr E to M
|
// Pipeline for IEUAdr E to M
|
||||||
// Zero-extend address to 34 bits for XLEN=32
|
// Zero-extend address to 34 bits for XLEN=32
|
||||||
@ -222,7 +221,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
if (P.DTIM_SUPPORTED) begin : dtim
|
if (P.DTIM_SUPPORTED) begin : dtim
|
||||||
logic [P.PA_BITS-1:0] DTIMAdr;
|
logic [P.PA_BITS-1:0] DTIMAdr;
|
||||||
logic [1:0] DTIMMemRWM;
|
logic [1:0] DTIMMemRWM;
|
||||||
|
|
||||||
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
|
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
|
||||||
mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr);
|
mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr);
|
||||||
@ -237,23 +236,23 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (P.BUS_SUPPORTED) begin : bus
|
if (P.BUS_SUPPORTED) begin : bus
|
||||||
if(P.DCACHE_SUPPORTED) begin : dcache
|
if(P.DCACHE_SUPPORTED) begin : dcache
|
||||||
localparam LLENWORDSPERLINE = P.DCACHE_LINELENINBITS/P.LLEN; // Number of LLEN words in cacheline
|
localparam LLENWORDSPERLINE = P.DCACHE_LINELENINBITS/P.LLEN; // Number of LLEN words in cacheline
|
||||||
localparam LLENLOGBWPL = $clog2(LLENWORDSPERLINE); // Log2 of ^
|
localparam LLENLOGBWPL = $clog2(LLENWORDSPERLINE); // Log2 of ^
|
||||||
localparam BEATSPERLINE = P.DCACHE_LINELENINBITS/P.AHBW; // Number of AHBW words (beats) in cacheline
|
localparam BEATSPERLINE = P.DCACHE_LINELENINBITS/P.AHBW; // Number of AHBW words (beats) in cacheline
|
||||||
localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^
|
localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^
|
||||||
localparam LINELEN = P.DCACHE_LINELENINBITS; // Number of bits in cacheline
|
localparam LINELEN = P.DCACHE_LINELENINBITS; // Number of bits in cacheline
|
||||||
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
||||||
|
|
||||||
logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline
|
logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline
|
||||||
logic [P.PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback.
|
logic [P.PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback.
|
||||||
logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
|
logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
|
||||||
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
|
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
|
||||||
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
|
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
|
||||||
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
||||||
logic [1:0] BusRW; // Uncached bus memory access
|
logic [1:0] BusRW; // Uncached bus memory access
|
||||||
logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
|
logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
|
||||||
logic [1:0] CacheRWM; // Cache read (10), write (01), AMO (11)
|
logic [1:0] CacheRWM; // Cache read (10), write (01), AMO (11)
|
||||||
logic [1:0] CacheAtomicM; // Cache AMO
|
logic [1:0] CacheAtomicM; // Cache AMO
|
||||||
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
||||||
|
|
||||||
assign BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
|
assign BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
|
||||||
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
||||||
@ -320,6 +319,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Atomic operations
|
// Atomic operations
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if (P.A_SUPPORTED) begin:atomic
|
if (P.A_SUPPORTED) begin:atomic
|
||||||
atomic #(P) atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[P.XLEN-1:0]), .IHWriteDataM, .PAdrM,
|
atomic #(P) atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[P.XLEN-1:0]), .IHWriteDataM, .PAdrM,
|
||||||
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
|
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
|
||||||
@ -335,6 +335,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Subword Accesses
|
// Subword Accesses
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
subwordread #(P.LLEN) subwordread(.ReadDataWordMuxM(LittleEndianReadDataWordM), .PAdrM(PAdrM[2:0]), .BigEndianM,
|
subwordread #(P.LLEN) subwordread(.ReadDataWordMuxM(LittleEndianReadDataWordM), .PAdrM(PAdrM[2:0]), .BigEndianM,
|
||||||
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
|
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
|
||||||
subwordwrite #(P.LLEN) subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
|
subwordwrite #(P.LLEN) subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
|
||||||
@ -361,5 +362,4 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign LSUWriteDataM = LittleEndianWriteDataM;
|
assign LSUWriteDataM = LittleEndianWriteDataM;
|
||||||
assign LittleEndianReadDataWordM = ReadDataWordMuxM;
|
assign LittleEndianReadDataWordM = ReadDataWordMuxM;
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -29,12 +29,12 @@
|
|||||||
|
|
||||||
module subwordread #(parameter LLEN)
|
module subwordread #(parameter LLEN)
|
||||||
(
|
(
|
||||||
input logic [LLEN-1:0] ReadDataWordMuxM,
|
input logic [LLEN-1:0] ReadDataWordMuxM,
|
||||||
input logic [2:0] PAdrM,
|
input logic [2:0] PAdrM,
|
||||||
input logic [2:0] Funct3M,
|
input logic [2:0] Funct3M,
|
||||||
input logic FpLoadStoreM,
|
input logic FpLoadStoreM,
|
||||||
input logic BigEndianM,
|
input logic BigEndianM,
|
||||||
output logic [LLEN-1:0] ReadDataM
|
output logic [LLEN-1:0] ReadDataM
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [7:0] ByteM;
|
logic [7:0] ByteM;
|
||||||
@ -89,7 +89,7 @@ module subwordread #(parameter LLEN)
|
|||||||
//3'b100: ReadDataM = FpLoadStoreM ? ReadDataWordMuxM : {{LLEN-8{1'b0}}, ByteM[7:0]}; // lbu/flq - only needed when LLEN=128
|
//3'b100: ReadDataM = FpLoadStoreM ? ReadDataWordMuxM : {{LLEN-8{1'b0}}, ByteM[7:0]}; // lbu/flq - only needed when LLEN=128
|
||||||
3'b101: ReadDataM = {{LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
3'b101: ReadDataM = {{LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
||||||
3'b110: ReadDataM = {{LLEN-32{1'b0}}, WordM[31:0]}; // lwu
|
3'b110: ReadDataM = {{LLEN-32{1'b0}}, WordM[31:0]}; // lwu
|
||||||
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
end else begin:swrmux // 32-bit
|
end else begin:swrmux // 32-bit
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module subwordwrite #(parameter LLEN) (
|
module subwordwrite #(parameter LLEN) (
|
||||||
input logic [2:0] LSUFunct3M,
|
input logic [2:0] LSUFunct3M,
|
||||||
input logic [LLEN-1:0] IMAFWriteDataM,
|
input logic [LLEN-1:0] IMAFWriteDataM,
|
||||||
output logic [LLEN-1:0] LittleEndianWriteDataM
|
output logic [LLEN-1:0] LittleEndianWriteDataM
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -46,18 +46,18 @@ module subwordwrite #(parameter LLEN) (
|
|||||||
end else if (LLEN == 64) begin:sww
|
end else if (LLEN == 64) begin:sww
|
||||||
always_comb
|
always_comb
|
||||||
case(LSUFunct3M[1:0])
|
case(LSUFunct3M[1:0])
|
||||||
2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb
|
2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb
|
||||||
2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh
|
2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh
|
||||||
2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw
|
2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw
|
||||||
2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd
|
2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd
|
||||||
endcase
|
endcase
|
||||||
end else begin:sww // 32-bit
|
end else begin:sww // 32-bit
|
||||||
always_comb
|
always_comb
|
||||||
case(LSUFunct3M[1:0])
|
case(LSUFunct3M[1:0])
|
||||||
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
|
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
|
||||||
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
|
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
|
||||||
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
|
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
|
||||||
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
|
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module swbytemask #(parameter WORDLEN)(
|
module swbytemask #(parameter WORDLEN)(
|
||||||
input logic [2:0] Size,
|
input logic [2:0] Size,
|
||||||
input logic [$clog2(WORDLEN/8)-1:0] Adr,
|
input logic [$clog2(WORDLEN/8)-1:0] Adr,
|
||||||
output logic [WORDLEN/8-1:0] ByteMask
|
output logic [WORDLEN/8-1:0] ByteMask
|
||||||
);
|
);
|
||||||
|
|
||||||
assign ByteMask = ((2**(2**Size))-1) << Adr;
|
assign ByteMask = ((2**(2**Size))-1) << Adr;
|
||||||
|
@ -27,38 +27,38 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module div import cvw::*; #(parameter cvw_t P) (
|
module div import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallM,
|
input logic StallM,
|
||||||
input logic FlushE,
|
input logic FlushE,
|
||||||
input logic IntDivE, // integer division/remainder instruction of any type
|
input logic IntDivE, // integer division/remainder instruction of any type
|
||||||
input logic DivSignedE, // signed division
|
input logic DivSignedE, // signed division
|
||||||
input logic W64E, // W-type instructions (divw, divuw, remw, remuw)
|
input logic W64E, // W-type instructions (divw, divuw, remw, remuw)
|
||||||
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE,// Forwarding mux outputs for Source A and B
|
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Forwarding mux outputs for Source A and B
|
||||||
output logic DivBusyE, // Divide is busy - stall pipeline
|
output logic DivBusyE, // Divide is busy - stall pipeline
|
||||||
output logic [P.XLEN-1:0] QuotM, RemM // Quotient and remainder outputs
|
output logic [P.XLEN-1:0] QuotM, RemM // Quotient and remainder outputs
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam STEPBITS = $clog2(P.XLEN/P.IDIV_BITSPERCYCLE); // Number of steps
|
localparam STEPBITS = $clog2(P.XLEN/P.IDIV_BITSPERCYCLE); // Number of steps
|
||||||
|
|
||||||
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; // division FSM state
|
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; // division FSM state
|
||||||
statetype state;
|
statetype state;
|
||||||
|
|
||||||
logic [P.XLEN-1:0] W[P.IDIV_BITSPERCYCLE:0]; // Residual for each of k steps
|
logic [P.XLEN-1:0] W[P.IDIV_BITSPERCYCLE:0]; // Residual for each of k steps
|
||||||
logic [P.XLEN-1:0] XQ[P.IDIV_BITSPERCYCLE:0]; // dividend/quotient for each of k steps
|
logic [P.XLEN-1:0] XQ[P.IDIV_BITSPERCYCLE:0]; // dividend/quotient for each of k steps
|
||||||
logic [P.XLEN-1:0] WNext, XQNext; // initialized W and XQ going into registers
|
logic [P.XLEN-1:0] WNext, XQNext; // initialized W and XQ going into registers
|
||||||
logic [P.XLEN-1:0] DinE, XinE; // divisor & dividend, possibly truncated to 32 bits
|
logic [P.XLEN-1:0] DinE, XinE; // divisor & dividend, possibly truncated to 32 bits
|
||||||
logic [P.XLEN-1:0] DnE; // DnE = ~DinE
|
logic [P.XLEN-1:0] DnE; // DnE = ~DinE
|
||||||
logic [P.XLEN-1:0] DAbsBE; // absolute value of D
|
logic [P.XLEN-1:0] DAbsBE; // absolute value of D
|
||||||
logic [P.XLEN-1:0] DAbsB; // registered absolute value of D, constant during division
|
logic [P.XLEN-1:0] DAbsB; // registered absolute value of D, constant during division
|
||||||
logic [P.XLEN-1:0] XnE; // DXnE = ~XinE
|
logic [P.XLEN-1:0] XnE; // DXnE = ~XinE
|
||||||
logic [P.XLEN-1:0] XInitE; // |X|, or original X for divide by 0
|
logic [P.XLEN-1:0] XInitE; // |X|, or original X for divide by 0
|
||||||
logic [P.XLEN-1:0] WnM, XQnM; // negated residual W and quotient XQ for postprocessing sign correction
|
logic [P.XLEN-1:0] WnM, XQnM; // negated residual W and quotient XQ for postprocessing sign correction
|
||||||
logic [STEPBITS:0] step; // division step
|
logic [STEPBITS:0] step; // division step
|
||||||
logic Div0E, Div0M; // divide by 0
|
logic Div0E, Div0M; // divide by 0
|
||||||
logic DivStartE; // start integer division
|
logic DivStartE; // start integer division
|
||||||
logic SignXE, SignDE; // sign of dividend and divisor
|
logic SignXE, SignDE; // sign of dividend and divisor
|
||||||
logic NegQE, NegWM, NegQM; // negate quotient or residual during postprocessing
|
logic NegQE, NegWM, NegQM; // negate quotient or residual during postprocessing
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Execute Stage: prepare for division calculation with control logic, W logic and absolute values, initialize W and XQ
|
// Execute Stage: prepare for division calculation with control logic, W logic and absolute values, initialize W and XQ
|
||||||
@ -131,7 +131,7 @@ module div import cvw::*; #(parameter cvw_t P) (
|
|||||||
step <= 1;
|
step <= 1;
|
||||||
if (Div0E) state <= DONE;
|
if (Div0E) state <= DONE;
|
||||||
else state <= BUSY;
|
else state <= BUSY;
|
||||||
end else if (state == BUSY) begin // pause one cycle at beginning of signed operations for absolute value
|
end else if (state == BUSY) begin // pause one cycle at beginning of signed operations for absolute value
|
||||||
if (step[STEPBITS] | (P.XLEN==64) & W64E & step[STEPBITS-1]) begin // complete in half the time for W-type instructions
|
if (step[STEPBITS] | (P.XLEN==64) & W64E & step[STEPBITS-1]) begin // complete in half the time for W-type instructions
|
||||||
state <= DONE;
|
state <= DONE;
|
||||||
end
|
end
|
||||||
|
@ -27,21 +27,21 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module mdu import cvw::*; #(parameter cvw_t P) (
|
module mdu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallM, StallW,
|
input logic StallM, StallW,
|
||||||
input logic FlushE, FlushM, FlushW,
|
input logic FlushE, FlushM, FlushW,
|
||||||
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // inputs A and B from IEU forwarding mux output
|
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // inputs A and B from IEU forwarding mux output
|
||||||
input logic [2:0] Funct3E, Funct3M, // type of MDU operation
|
input logic [2:0] Funct3E, Funct3M, // type of MDU operation
|
||||||
input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
||||||
output logic [P.XLEN-1:0] MDUResultW, // multiply/divide result
|
output logic [P.XLEN-1:0] MDUResultW, // multiply/divide result
|
||||||
output logic DivBusyE // busy signal to stall pipeline in Execute stage
|
output logic DivBusyE // busy signal to stall pipeline in Execute stage
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN*2-1:0] ProdM; // double-width product from mul
|
logic [P.XLEN*2-1:0] ProdM; // double-width product from mul
|
||||||
logic [P.XLEN-1:0] QuotM, RemM; // quotient and remainder from intdivrestoring
|
logic [P.XLEN-1:0] QuotM, RemM; // quotient and remainder from intdivrestoring
|
||||||
logic [P.XLEN-1:0] PrelimResultM; // selected result before W truncation
|
logic [P.XLEN-1:0] PrelimResultM; // selected result before W truncation
|
||||||
logic [P.XLEN-1:0] MDUResultM; // result after W truncation
|
logic [P.XLEN-1:0] MDUResultM; // result after W truncation
|
||||||
logic W64M; // W-type instruction
|
logic W64M; // W-type instruction
|
||||||
|
|
||||||
// Multiplier
|
// Multiplier
|
||||||
mul #(P.XLEN) mul(.clk, .reset, .StallM, .FlushM, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .ProdM);
|
mul #(P.XLEN) mul(.clk, .reset, .StallM, .FlushM, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .ProdM);
|
||||||
@ -64,13 +64,13 @@ module mdu import cvw::*; #(parameter cvw_t P) (
|
|||||||
always_comb
|
always_comb
|
||||||
case (Funct3M)
|
case (Funct3M)
|
||||||
3'b000: PrelimResultM = ProdM[P.XLEN-1:0]; // mul
|
3'b000: PrelimResultM = ProdM[P.XLEN-1:0]; // mul
|
||||||
3'b001: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulh
|
3'b001: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulh
|
||||||
3'b010: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhsu
|
3'b010: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhsu
|
||||||
3'b011: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhu
|
3'b011: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhu
|
||||||
3'b100: PrelimResultM = QuotM; // div
|
3'b100: PrelimResultM = QuotM; // div
|
||||||
3'b101: PrelimResultM = QuotM; // divu
|
3'b101: PrelimResultM = QuotM; // divu
|
||||||
3'b110: PrelimResultM = RemM; // rem
|
3'b110: PrelimResultM = RemM; // rem
|
||||||
3'b111: PrelimResultM = RemM; // remu
|
3'b111: PrelimResultM = RemM; // remu
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// Handle sign extension for W-type instructions
|
// Handle sign extension for W-type instructions
|
||||||
@ -84,5 +84,3 @@ module mdu import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Writeback stage pipeline register
|
// Writeback stage pipeline register
|
||||||
flopenrc #(P.XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW);
|
flopenrc #(P.XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW);
|
||||||
endmodule // mdu
|
endmodule // mdu
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@
|
|||||||
module mul #(parameter XLEN) (
|
module mul #(parameter XLEN) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallM, FlushM,
|
input logic StallM, FlushM,
|
||||||
input logic [XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // source A and B from after Forwarding mux
|
input logic [XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // source A and B from after Forwarding mux
|
||||||
input logic [2:0] Funct3E, // type of multiply
|
input logic [2:0] Funct3E, // type of multiply
|
||||||
output logic [XLEN*2-1:0] ProdM // double-widthproduct
|
output logic [XLEN*2-1:0] ProdM // double-widthproduct
|
||||||
);
|
);
|
||||||
|
|
||||||
// Number systems
|
// Number systems
|
||||||
@ -48,12 +48,12 @@ module mul #(parameter XLEN) (
|
|||||||
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
|
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
|
||||||
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
|
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
|
||||||
|
|
||||||
logic [XLEN-1:0] Aprime, Bprime; // lower bits of source A and B
|
logic [XLEN-1:0] Aprime, Bprime; // lower bits of source A and B
|
||||||
logic MULH, MULHSU; // type of multiply
|
logic MULH, MULHSU; // type of multiply
|
||||||
logic [XLEN-2:0] PA, PB; // product of msb and lsbs
|
logic [XLEN-2:0] PA, PB; // product of msb and lsbs
|
||||||
logic PP; // product of msbs
|
logic PP; // product of msbs
|
||||||
logic [XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E; // partial products
|
logic [XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E; // partial products
|
||||||
logic [XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; // registered partial proudcts
|
logic [XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; // registered partial proudcts
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Execute Stage: Compute partial products
|
// Execute Stage: Compute partial products
|
||||||
@ -90,4 +90,3 @@ module mul #(parameter XLEN) (
|
|||||||
// add up partial products; this multi-input add implies CSAs and a final CPA
|
// add up partial products; this multi-input add implies CSAs and a final CPA
|
||||||
assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
|
assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module adrdec #(parameter PA_BITS) (
|
module adrdec #(parameter PA_BITS) (
|
||||||
input logic [PA_BITS-1:0] PhysicalAddress, // Physical address to decode
|
input logic [PA_BITS-1:0] PhysicalAddress, // Physical address to decode
|
||||||
input logic [PA_BITS-1:0] Base, Range, // Base and range of peripheral addresses
|
input logic [PA_BITS-1:0] Base, Range, // Base and range of peripheral addresses
|
||||||
input logic Supported, // Is this peripheral supported?
|
input logic Supported, // Is this peripheral supported?
|
||||||
input logic AccessValid, // Is the access type valid?
|
input logic AccessValid, // Is the access type valid?
|
||||||
input logic [1:0] Size, // Size of access
|
input logic [1:0] Size, // Size of access
|
||||||
@ -50,4 +50,3 @@ module adrdec #(parameter PA_BITS) (
|
|||||||
// Select this peripheral if the address matches, the peripheral is supported, and the type and size of access is ok
|
// Select this peripheral if the address matches, the peripheral is supported, and the type and size of access is ok
|
||||||
assign Sel = Match & Supported & AccessValid & SizeValid;
|
assign Sel = Match & Supported & AccessValid & SizeValid;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@
|
|||||||
|
|
||||||
module adrdecs import cvw::*; #(parameter cvw_t P) (
|
module adrdecs import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||||
input logic AccessRW, AccessRX, AccessRWX,
|
input logic AccessRW, AccessRX, AccessRWX,
|
||||||
input logic [1:0] Size,
|
input logic [1:0] Size,
|
||||||
output logic [10:0] SelRegions
|
output logic [10:0] SelRegions
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
|
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
|
||||||
// Determine which region of physical memory (if any) is being accessed
|
// Determine which region of physical memory (if any) is being accessed
|
||||||
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[10]);
|
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[10]);
|
||||||
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[9]);
|
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[9]);
|
||||||
|
118
src/mmu/hptw.sv
118
src/mmu/hptw.sv
@ -30,39 +30,39 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
module hptw import cvw::*; #(parameter cvw_t P) (
|
module hptw import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic [P.XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table
|
input logic [P.XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table
|
||||||
input logic [P.XLEN-1:0] PCSpillF, // addresses to translate
|
input logic [P.XLEN-1:0] PCSpillF, // addresses to translate
|
||||||
input logic [P.XLEN+1:0] IEUAdrExtM, // addresses to translate
|
input logic [P.XLEN+1:0] IEUAdrExtM, // addresses to translate
|
||||||
input logic [1:0] MemRWM, AtomicM,
|
input logic [1:0] MemRWM, AtomicM,
|
||||||
// system status
|
// system status
|
||||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
input logic [1:0] STATUS_MPP,
|
input logic [1:0] STATUS_MPP,
|
||||||
input logic [1:0] PrivilegeModeW,
|
input logic [1:0] PrivilegeModeW,
|
||||||
input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU
|
input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU
|
||||||
input logic [P.XLEN-1:0] WriteDataM,
|
input logic [P.XLEN-1:0] WriteDataM,
|
||||||
input logic DCacheStallM, // stall from LSU
|
input logic DCacheStallM, // stall from LSU
|
||||||
input logic [2:0] Funct3M,
|
input logic [2:0] Funct3M,
|
||||||
input logic [6:0] Funct7M,
|
input logic [6:0] Funct7M,
|
||||||
input logic ITLBMissF,
|
input logic ITLBMissF,
|
||||||
input logic DTLBMissM,
|
input logic DTLBMissM,
|
||||||
input logic FlushW,
|
input logic FlushW,
|
||||||
input logic InstrUpdateDAF,
|
input logic InstrUpdateDAF,
|
||||||
input logic DataUpdateDAM,
|
input logic DataUpdateDAM,
|
||||||
output logic [P.XLEN-1:0] PTE, // page table entry to TLBs
|
output logic [P.XLEN-1:0] PTE, // page table entry to TLBs
|
||||||
output logic [1:0] PageType, // page type to TLBs
|
output logic [1:0] PageType, // page type to TLBs
|
||||||
output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
|
output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
|
||||||
output logic [1:0] PreLSURWM,
|
output logic [1:0] PreLSURWM,
|
||||||
output logic [P.XLEN+1:0] IHAdrM,
|
output logic [P.XLEN+1:0] IHAdrM,
|
||||||
output logic [P.XLEN-1:0] IHWriteDataM,
|
output logic [P.XLEN-1:0] IHWriteDataM,
|
||||||
output logic [1:0] LSUAtomicM,
|
output logic [1:0] LSUAtomicM,
|
||||||
output logic [2:0] LSUFunct3M,
|
output logic [2:0] LSUFunct3M,
|
||||||
output logic [6:0] LSUFunct7M,
|
output logic [6:0] LSUFunct7M,
|
||||||
output logic IgnoreRequestTLB,
|
output logic IgnoreRequestTLB,
|
||||||
output logic SelHPTW,
|
output logic SelHPTW,
|
||||||
output logic HPTWStall,
|
output logic HPTWStall,
|
||||||
input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM,
|
input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM,
|
||||||
output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultF
|
output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultF
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef enum logic [3:0] {L0_ADR, L0_RD,
|
typedef enum logic [3:0] {L0_ADR, L0_RD,
|
||||||
@ -72,39 +72,39 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
LEAF, IDLE, UPDATE_PTE,
|
LEAF, IDLE, UPDATE_PTE,
|
||||||
FAULT} statetype;
|
FAULT} statetype;
|
||||||
|
|
||||||
logic DTLBWalk; // register TLBs translation miss requests
|
logic DTLBWalk; // register TLBs translation miss requests
|
||||||
logic [P.PPN_BITS-1:0] BasePageTablePPN;
|
logic [P.PPN_BITS-1:0] BasePageTablePPN;
|
||||||
logic [P.PPN_BITS-1:0] CurrentPPN;
|
logic [P.PPN_BITS-1:0] CurrentPPN;
|
||||||
logic Executable, Writable, Readable, Valid, PTE_U;
|
logic Executable, Writable, Readable, Valid, PTE_U;
|
||||||
logic Misaligned, MegapageMisaligned;
|
logic Misaligned, MegapageMisaligned;
|
||||||
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
|
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
|
||||||
logic StartWalk;
|
logic StartWalk;
|
||||||
logic TLBMiss;
|
logic TLBMiss;
|
||||||
logic PRegEn;
|
logic PRegEn;
|
||||||
logic [1:0] NextPageType;
|
logic [1:0] NextPageType;
|
||||||
logic [P.SVMODE_BITS-1:0] SvMode;
|
logic [P.SVMODE_BITS-1:0] SvMode;
|
||||||
logic [P.XLEN-1:0] TranslationVAdr;
|
logic [P.XLEN-1:0] TranslationVAdr;
|
||||||
logic [P.XLEN-1:0] NextPTE;
|
logic [P.XLEN-1:0] NextPTE;
|
||||||
logic UpdatePTE;
|
logic UpdatePTE;
|
||||||
logic HPTWUpdateDA;
|
logic HPTWUpdateDA;
|
||||||
logic [P.PA_BITS-1:0] HPTWReadAdr;
|
logic [P.PA_BITS-1:0] HPTWReadAdr;
|
||||||
logic SelHPTWAdr;
|
logic SelHPTWAdr;
|
||||||
logic [P.XLEN+1:0] HPTWAdrExt;
|
logic [P.XLEN+1:0] HPTWAdrExt;
|
||||||
logic ITLBMissOrUpdateDAF;
|
logic ITLBMissOrUpdateDAF;
|
||||||
logic DTLBMissOrUpdateDAM;
|
logic DTLBMissOrUpdateDAM;
|
||||||
logic LSUAccessFaultM;
|
logic LSUAccessFaultM;
|
||||||
logic [P.PA_BITS-1:0] HPTWAdr;
|
logic [P.PA_BITS-1:0] HPTWAdr;
|
||||||
logic [1:0] HPTWRW;
|
logic [1:0] HPTWRW;
|
||||||
logic [2:0] HPTWSize; // 32 or 64 bit access
|
logic [2:0] HPTWSize; // 32 or 64 bit access
|
||||||
statetype WalkerState, NextWalkerState, InitialWalkerState;
|
statetype WalkerState, NextWalkerState, InitialWalkerState;
|
||||||
logic HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault;
|
logic HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault;
|
||||||
logic HPTWLoadAccessFaultDelay, HPTWStoreAmoAccessFaultDelay, HPTWInstrAccessFaultDelay;
|
logic HPTWLoadAccessFaultDelay, HPTWStoreAmoAccessFaultDelay, HPTWInstrAccessFaultDelay;
|
||||||
logic HPTWAccessFaultDelay;
|
logic HPTWAccessFaultDelay;
|
||||||
logic TakeHPTWFault, TakeHPTWFaultDelay;
|
logic TakeHPTWFault, TakeHPTWFaultDelay;
|
||||||
|
|
||||||
// map hptw access faults onto either the original LSU load/store fault or instruction access fault
|
// map hptw access faults onto either the original LSU load/store fault or instruction access fault
|
||||||
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
||||||
assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||||
assign HPTWStoreAmoAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
assign HPTWStoreAmoAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
||||||
assign HPTWInstrAccessFault = LSUAccessFaultM & ~DTLBWalk;
|
assign HPTWInstrAccessFault = LSUAccessFaultM & ~DTLBWalk;
|
||||||
|
|
||||||
@ -140,16 +140,16 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
|
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
|
||||||
|
|
||||||
if(P.SVADU_SUPPORTED) begin : hptwwrites
|
if(P.SVADU_SUPPORTED) begin : hptwwrites
|
||||||
logic ReadAccess, WriteAccess;
|
logic ReadAccess, WriteAccess;
|
||||||
logic InvalidRead, InvalidWrite, InvalidOp;
|
logic InvalidRead, InvalidWrite, InvalidOp;
|
||||||
logic UpperBitsUnequal;
|
logic UpperBitsUnequal;
|
||||||
logic OtherPageFault;
|
logic OtherPageFault;
|
||||||
logic [1:0] EffectivePrivilegeMode;
|
logic [1:0] EffectivePrivilegeMode;
|
||||||
logic ImproperPrivilege;
|
logic ImproperPrivilege;
|
||||||
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
||||||
logic [P.PA_BITS-1:0] HPTWWriteAdr;
|
logic [P.PA_BITS-1:0] HPTWWriteAdr;
|
||||||
logic SetDirty;
|
logic SetDirty;
|
||||||
logic Dirty, Accessed;
|
logic Dirty, Accessed;
|
||||||
logic [P.XLEN-1:0] AccessedPTE;
|
logic [P.XLEN-1:0] AccessedPTE;
|
||||||
|
|
||||||
assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
|
assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
|
||||||
@ -194,8 +194,8 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// Enable and select signals based on states
|
// Enable and select signals based on states
|
||||||
assign StartWalk = (WalkerState == IDLE) & TLBMiss;
|
assign StartWalk = (WalkerState == IDLE) & TLBMiss;
|
||||||
assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
|
assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
|
||||||
assign DTLBWriteM = (WalkerState == LEAF & ~HPTWUpdateDA) & DTLBWalk;
|
assign DTLBWriteM = (WalkerState == LEAF & ~HPTWUpdateDA) & DTLBWalk;
|
||||||
assign ITLBWriteF = (WalkerState == LEAF & ~HPTWUpdateDA) & ~DTLBWalk;
|
assign ITLBWriteF = (WalkerState == LEAF & ~HPTWUpdateDA) & ~DTLBWalk;
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// multiplex the outputs to LSU
|
// multiplex the outputs to LSU
|
||||||
if(P.XLEN == 64) assign HPTWAdrExt = {{(P.XLEN+2-P.PA_BITS){1'b0}}, HPTWAdr}; // extend to 66 bits
|
if(P.XLEN == 64) assign HPTWAdrExt = {{(P.XLEN+2-P.PA_BITS){1'b0}}, HPTWAdr}; // extend to 66 bits
|
||||||
else assign HPTWAdrExt = HPTWAdr;
|
else assign HPTWAdrExt = HPTWAdr;
|
||||||
mux2 #(2) rwmux(MemRWM, HPTWRW, SelHPTW, PreLSURWM);
|
mux2 #(2) rwmux(MemRWM, HPTWRW, SelHPTW, PreLSURWM);
|
||||||
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
|
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
|
||||||
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
|
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
|
||||||
|
@ -28,48 +28,48 @@
|
|||||||
|
|
||||||
module mmu import cvw::*; #(parameter cvw_t P,
|
module mmu import cvw::*; #(parameter cvw_t P,
|
||||||
parameter TLB_ENTRIES = 8, IMMU = 0) (
|
parameter TLB_ENTRIES = 8, IMMU = 0) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic [P.XLEN-1:0] SATP_REGW, // Current value of satp CSR (from privileged unit)
|
input logic [P.XLEN-1:0] SATP_REGW, // Current value of satp CSR (from privileged unit)
|
||||||
input logic STATUS_MXR, // Status CSR: make executable page readable
|
input logic STATUS_MXR, // Status CSR: make executable page readable
|
||||||
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
||||||
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
||||||
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
|
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
|
||||||
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
|
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
|
||||||
input logic DisableTranslation, // virtual address translation disabled during D$ flush and HPTW walk that use physical addresses
|
input logic DisableTranslation, // virtual address translation disabled during D$ flush and HPTW walk that use physical addresses
|
||||||
input logic [P.XLEN+1:0] VAdr, // virtual/physical address from IEU or physical address from HPTW
|
input logic [P.XLEN+1:0] VAdr, // virtual/physical address from IEU or physical address from HPTW
|
||||||
input logic [1:0] Size, // access size: 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
|
input logic [1:0] Size, // access size: 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
|
||||||
input logic [P.XLEN-1:0] PTE, // page table entry
|
input logic [P.XLEN-1:0] PTE, // page table entry
|
||||||
input logic [1:0] PageTypeWriteVal, // page type
|
input logic [1:0] PageTypeWriteVal, // page type
|
||||||
input logic TLBWrite, // write TLB entry
|
input logic TLBWrite, // write TLB entry
|
||||||
input logic TLBFlush, // Invalidate all TLB entries
|
input logic TLBFlush, // Invalidate all TLB entries
|
||||||
output logic [P.PA_BITS-1:0] PhysicalAddress, // PAdr when no translation, or translated VAdr (TLBPAdr) when there is translation
|
output logic [P.PA_BITS-1:0] PhysicalAddress, // PAdr when no translation, or translated VAdr (TLBPAdr) when there is translation
|
||||||
output logic TLBMiss, // Miss TLB
|
output logic TLBMiss, // Miss TLB
|
||||||
output logic Cacheable, // PMA indicates memory address is cachable
|
output logic Cacheable, // PMA indicates memory address is cachable
|
||||||
output logic Idempotent, // PMA indicates memory address is idempotent
|
output logic Idempotent, // PMA indicates memory address is idempotent
|
||||||
output logic SelTIM, // Select a tightly integrated memory
|
output logic SelTIM, // Select a tightly integrated memory
|
||||||
// Faults
|
// Faults
|
||||||
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources
|
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources
|
||||||
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources
|
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources
|
||||||
output logic UpdateDA, // page fault due to setting dirty or access bit
|
output logic UpdateDA, // page fault due to setting dirty or access bit
|
||||||
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources
|
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources
|
||||||
// PMA checker signals
|
// PMA checker signals
|
||||||
input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // access type
|
input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // access type
|
||||||
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.PA_BITS-1:0] TLBPAdr; // physical address for TLB
|
logic [P.PA_BITS-1:0] TLBPAdr; // physical address for TLB
|
||||||
logic PMAInstrAccessFaultF; // Instruction access fault from PMA
|
logic PMAInstrAccessFaultF; // Instruction access fault from PMA
|
||||||
logic PMPInstrAccessFaultF; // Instruction access fault from PMP
|
logic PMPInstrAccessFaultF; // Instruction access fault from PMP
|
||||||
logic PMALoadAccessFaultM; // Load access fault from PMA
|
logic PMALoadAccessFaultM; // Load access fault from PMA
|
||||||
logic PMPLoadAccessFaultM; // Load access fault from PMP
|
logic PMPLoadAccessFaultM; // Load access fault from PMP
|
||||||
logic PMAStoreAmoAccessFaultM; // Store or AMO access fault from PMA
|
logic PMAStoreAmoAccessFaultM; // Store or AMO access fault from PMA
|
||||||
logic PMPStoreAmoAccessFaultM; // Store or AMO access fault from PMP
|
logic PMPStoreAmoAccessFaultM; // Store or AMO access fault from PMP
|
||||||
logic DataMisalignedM; // load or store misaligned
|
logic DataMisalignedM; // load or store misaligned
|
||||||
logic Translate; // Translation occurs when virtual memory is active and DisableTranslation is off
|
logic Translate; // Translation occurs when virtual memory is active and DisableTranslation is off
|
||||||
logic TLBHit; // Hit in TLB
|
logic TLBHit; // Hit in TLB
|
||||||
logic TLBPageFault; // Page fault from TLB
|
logic TLBPageFault; // Page fault from TLB
|
||||||
logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults
|
logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults
|
||||||
|
|
||||||
// only instantiate TLB if Virtual Memory is supported
|
// only instantiate TLB if Virtual Memory is supported
|
||||||
if (P.VIRTMEM_SUPPORTED) begin:tlb
|
if (P.VIRTMEM_SUPPORTED) begin:tlb
|
||||||
@ -86,9 +86,9 @@ module mmu import cvw::*; #(parameter cvw_t P,
|
|||||||
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
|
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
|
||||||
.Translate, .TLBPageFault, .UpdateDA);
|
.Translate, .TLBPageFault, .UpdateDA);
|
||||||
end else begin:tlb // just pass address through as physical
|
end else begin:tlb // just pass address through as physical
|
||||||
assign Translate = 0;
|
assign Translate = 0;
|
||||||
assign TLBMiss = 0;
|
assign TLBMiss = 0;
|
||||||
assign TLBHit = 1; // *** is this necessary
|
assign TLBHit = 1; // *** is this necessary
|
||||||
assign TLBPageFault = 0;
|
assign TLBPageFault = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,26 +30,26 @@
|
|||||||
|
|
||||||
module pmachecker import cvw::*; #(parameter cvw_t P) (
|
module pmachecker import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||||
input logic [1:0] Size,
|
input logic [1:0] Size,
|
||||||
input logic AtomicAccessM, // Atomic access
|
input logic AtomicAccessM, // Atomic access
|
||||||
input logic ExecuteAccessF, // Execute access
|
input logic ExecuteAccessF, // Execute access
|
||||||
input logic WriteAccessM, // Write access
|
input logic WriteAccessM, // Write access
|
||||||
input logic ReadAccessM, // Read access
|
input logic ReadAccessM, // Read access
|
||||||
output logic Cacheable, Idempotent, SelTIM,
|
output logic Cacheable, Idempotent, SelTIM,
|
||||||
output logic PMAInstrAccessFaultF,
|
output logic PMAInstrAccessFaultF,
|
||||||
output logic PMALoadAccessFaultM,
|
output logic PMALoadAccessFaultM,
|
||||||
output logic PMAStoreAmoAccessFaultM
|
output logic PMAStoreAmoAccessFaultM
|
||||||
);
|
);
|
||||||
|
|
||||||
logic PMAAccessFault;
|
logic PMAAccessFault;
|
||||||
logic AccessRW, AccessRWX, AccessRX;
|
logic AccessRW, AccessRWX, AccessRX;
|
||||||
logic [10:0] SelRegions;
|
logic [10:0] SelRegions;
|
||||||
logic AtomicAllowed;
|
logic AtomicAllowed;
|
||||||
|
|
||||||
// Determine what type of access is being made
|
// Determine what type of access is being made
|
||||||
assign AccessRW = ReadAccessM | WriteAccessM;
|
assign AccessRW = ReadAccessM | WriteAccessM;
|
||||||
assign AccessRWX = ReadAccessM | WriteAccessM | ExecuteAccessF;
|
assign AccessRWX = ReadAccessM | WriteAccessM | ExecuteAccessF;
|
||||||
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
||||||
|
|
||||||
// Determine which region of physical memory (if any) is being accessed
|
// Determine which region of physical memory (if any) is being accessed
|
||||||
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
|
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
|
||||||
@ -65,9 +65,8 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign SelTIM = SelRegions[10] | SelRegions[9]; // exclusion-tag: unused-tim
|
assign SelTIM = SelRegions[10] | SelRegions[9]; // exclusion-tag: unused-tim
|
||||||
|
|
||||||
// Detect access faults
|
// Detect access faults
|
||||||
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
||||||
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;
|
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;
|
||||||
assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault;
|
assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault;
|
||||||
assign PMAStoreAmoAccessFaultM = WriteAccessM & PMAAccessFault;
|
assign PMAStoreAmoAccessFaultM = WriteAccessM & PMAAccessFault;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -87,4 +87,3 @@ module pmpadrdec import cvw::*; #(parameter cvw_t P) (
|
|||||||
// attempts an 8-byte access to 0x8, the access should fail (see page 60 of privileged specification 20211203). This
|
// attempts an 8-byte access to 0x8, the access should fail (see page 60 of privileged specification 20211203). This
|
||||||
// implementation will not detect the failure.
|
// implementation will not detect the failure.
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ module pmpchecker import cvw::*; #(parameter cvw_t P) (
|
|||||||
// keyword, the compiler warns us that it's interpreting the signal as a var,
|
// keyword, the compiler warns us that it's interpreting the signal as a var,
|
||||||
// which we might not intend.
|
// which we might not intend.
|
||||||
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
|
||||||
input logic ExecuteAccessF, WriteAccessM, ReadAccessM,
|
input logic ExecuteAccessF, WriteAccessM, ReadAccessM,
|
||||||
output logic PMPInstrAccessFaultF,
|
output logic PMPInstrAccessFaultF,
|
||||||
output logic PMPLoadAccessFaultM,
|
output logic PMPLoadAccessFaultM,
|
||||||
@ -48,11 +48,11 @@ module pmpchecker import cvw::*; #(parameter cvw_t P) (
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Bit i is high when the address falls in PMP region i
|
// Bit i is high when the address falls in PMP region i
|
||||||
logic EnforcePMP; // should PMP be checked in this privilege level
|
logic EnforcePMP; // should PMP be checked in this privilege level
|
||||||
logic [P.PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
logic [P.PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
||||||
logic [P.PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
logic [P.PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
||||||
logic [P.PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
logic [P.PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
||||||
logic [P.PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
logic [P.PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
||||||
|
|
||||||
if (P.PMP_ENTRIES > 0) begin: pmp // prevent complaints about array of no elements when PMP_ENTRIES = 0
|
if (P.PMP_ENTRIES > 0) begin: pmp // prevent complaints about array of no elements when PMP_ENTRIES = 0
|
||||||
pmpadrdec #(P) pmpadrdecs[P.PMP_ENTRIES-1:0](
|
pmpadrdec #(P) pmpadrdecs[P.PMP_ENTRIES-1:0](
|
||||||
|
@ -29,100 +29,101 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csr import cvw::*; #(parameter cvw_t P) (
|
module csr import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic FlushM, FlushW,
|
input logic FlushM, FlushW,
|
||||||
input logic StallE, StallM, StallW,
|
input logic StallE, StallM, StallW,
|
||||||
input logic [31:0] InstrM, // current instruction
|
input logic [31:0] InstrM, // current instruction
|
||||||
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||||
input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return logic
|
input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return logic
|
||||||
input logic [P.XLEN-1:0] SrcAM, IEUAdrM, // SrcA and memory address from IEU
|
input logic [P.XLEN-1:0] SrcAM, IEUAdrM, // SrcA and memory address from IEU
|
||||||
input logic CSRReadM, CSRWriteM, // read or write CSR
|
input logic CSRReadM, CSRWriteM, // read or write CSR
|
||||||
input logic TrapM, // trap is occurring
|
input logic TrapM, // trap is occurring
|
||||||
input logic mretM, sretM, wfiM, // return or WFI instruction
|
input logic mretM, sretM, wfiM, // return or WFI instruction
|
||||||
input logic IntPendingM, // at least one interrupt is pending and could occur if enabled
|
input logic IntPendingM, // at least one interrupt is pending and could occur if enabled
|
||||||
input logic InterruptM, // interrupt is occurring
|
input logic InterruptM, // interrupt is occurring
|
||||||
input logic ExceptionM, // interrupt is occurring
|
input logic ExceptionM, // interrupt is occurring
|
||||||
input logic MTimerInt, // timer interrupt
|
input logic MTimerInt, // timer interrupt
|
||||||
input logic MExtInt, SExtInt, // external interrupt (from PLIC)
|
input logic MExtInt, SExtInt, // external interrupt (from PLIC)
|
||||||
input logic MSwInt, // software interrupt
|
input logic MSwInt, // software interrupt
|
||||||
input logic [63:0] MTIME_CLINT, // TIME value from CLINT
|
input logic [63:0] MTIME_CLINT, // TIME value from CLINT
|
||||||
input logic InstrValidM, // current instruction is valid
|
input logic InstrValidM, // current instruction is valid
|
||||||
input logic FRegWriteM, // writes to floating point registers change STATUS.FS
|
input logic FRegWriteM, // writes to floating point registers change STATUS.FS
|
||||||
input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR
|
input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR
|
||||||
input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
|
input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
|
||||||
input logic [1:0] PrivilegeModeW, // current privilege mode
|
input logic [1:0] PrivilegeModeW, // current privilege mode
|
||||||
input logic [3:0] CauseM, // Trap cause
|
input logic [3:0] CauseM, // Trap cause
|
||||||
input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode
|
input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode
|
||||||
// inputs for performance counters
|
// inputs for performance counters
|
||||||
input logic LoadStallD,
|
input logic LoadStallD,
|
||||||
input logic StoreStallD,
|
input logic StoreStallD,
|
||||||
input logic ICacheStallF,
|
input logic ICacheStallF,
|
||||||
input logic DCacheStallM,
|
input logic DCacheStallM,
|
||||||
input logic BPDirPredWrongM,
|
input logic BPDirPredWrongM,
|
||||||
input logic BTAWrongM,
|
input logic BTAWrongM,
|
||||||
input logic RASPredPCWrongM,
|
input logic RASPredPCWrongM,
|
||||||
input logic IClassWrongM,
|
input logic IClassWrongM,
|
||||||
input logic BPWrongM, // branch predictor is wrong
|
input logic BPWrongM, // branch predictor is wrong
|
||||||
input logic [3:0] InstrClassM,
|
input logic [3:0] InstrClassM,
|
||||||
input logic DCacheMiss,
|
input logic DCacheMiss,
|
||||||
input logic DCacheAccess,
|
input logic DCacheAccess,
|
||||||
input logic ICacheMiss,
|
input logic ICacheMiss,
|
||||||
input logic ICacheAccess,
|
input logic ICacheAccess,
|
||||||
input logic sfencevmaM,
|
input logic sfencevmaM,
|
||||||
input logic InvalidateICacheM,
|
input logic InvalidateICacheM,
|
||||||
input logic DivBusyE, // integer divide busy
|
input logic DivBusyE, // integer divide busy
|
||||||
input logic FDivBusyE, // floating point divide busy
|
input logic FDivBusyE, // floating point divide busy
|
||||||
// outputs from CSRs
|
// outputs from CSRs
|
||||||
output logic [1:0] STATUS_MPP,
|
output logic [1:0] STATUS_MPP,
|
||||||
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
|
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
|
||||||
output logic [15:0] MEDELEG_REGW,
|
output logic [15:0] MEDELEG_REGW,
|
||||||
output logic [P.XLEN-1:0] SATP_REGW,
|
output logic [P.XLEN-1:0] SATP_REGW,
|
||||||
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||||
output logic STATUS_MIE, STATUS_SIE,
|
output logic STATUS_MIE, STATUS_SIE,
|
||||||
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
|
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
|
||||||
output logic [1:0] STATUS_FS,
|
output logic [1:0] STATUS_FS,
|
||||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||||
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||||
output logic [2:0] FRM_REGW,
|
output logic [2:0] FRM_REGW,
|
||||||
//
|
//
|
||||||
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
|
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
|
||||||
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns
|
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns
|
||||||
output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level
|
output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level
|
||||||
output logic BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields
|
output logic BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam MIP = 12'h344;
|
localparam MIP = 12'h344;
|
||||||
localparam SIP = 12'h144;
|
localparam SIP = 12'h144;
|
||||||
|
|
||||||
logic [P.XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM;
|
logic [P.XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM;
|
||||||
logic [P.XLEN-1:0] CSRReadValM;
|
logic [P.XLEN-1:0] CSRReadValM;
|
||||||
logic [P.XLEN-1:0] CSRSrcM;
|
logic [P.XLEN-1:0] CSRSrcM;
|
||||||
logic [P.XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
|
logic [P.XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
|
||||||
logic [P.XLEN-1:0] CSRWriteValM;
|
logic [P.XLEN-1:0] CSRWriteValM;
|
||||||
logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW;
|
logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW;
|
||||||
logic [P.XLEN-1:0] STVEC_REGW, MTVEC_REGW;
|
logic [P.XLEN-1:0] STVEC_REGW, MTVEC_REGW;
|
||||||
logic [P.XLEN-1:0] MEPC_REGW, SEPC_REGW;
|
logic [P.XLEN-1:0] MEPC_REGW, SEPC_REGW;
|
||||||
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
|
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
|
||||||
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
|
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
|
||||||
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
|
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
|
||||||
logic UngatedCSRMWriteM;
|
logic UngatedCSRMWriteM;
|
||||||
logic WriteFRMM, WriteFFLAGSM;
|
logic WriteFRMM, WriteFFLAGSM;
|
||||||
logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
|
logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
|
||||||
logic [4:0] NextCauseM;
|
logic [4:0] NextCauseM;
|
||||||
logic [11:0] CSRAdrM;
|
logic [11:0] CSRAdrM;
|
||||||
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM;
|
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM;
|
||||||
logic InsufficientCSRPrivilegeM;
|
logic InsufficientCSRPrivilegeM;
|
||||||
logic IllegalCSRMWriteReadonlyM;
|
logic IllegalCSRMWriteReadonlyM;
|
||||||
logic [P.XLEN-1:0] CSRReadVal2M;
|
logic [P.XLEN-1:0] CSRReadVal2M;
|
||||||
logic [11:0] MIP_REGW_writeable;
|
logic [11:0] MIP_REGW_writeable;
|
||||||
logic [P.XLEN-1:0] TVecM, TrapVectorM, NextFaultMtvalM;
|
logic [P.XLEN-1:0] TVecM, TrapVectorM, NextFaultMtvalM;
|
||||||
logic MTrapM, STrapM;
|
logic MTrapM, STrapM;
|
||||||
logic [P.XLEN-1:0] EPC;
|
logic [P.XLEN-1:0] EPC;
|
||||||
logic RetM;
|
logic RetM;
|
||||||
logic SelMtvecM;
|
logic SelMtvecM;
|
||||||
logic [P.XLEN-1:0] TVecAlignedM;
|
logic [P.XLEN-1:0] TVecAlignedM;
|
||||||
logic InstrValidNotFlushedM;
|
logic InstrValidNotFlushedM;
|
||||||
logic STimerInt;
|
logic STimerInt;
|
||||||
|
logic MENVCFG_STCE;
|
||||||
|
|
||||||
// only valid unflushed instructions can access CSRs
|
// only valid unflushed instructions can access CSRs
|
||||||
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
||||||
@ -179,13 +180,13 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
else CSRReadVal2M = CSRReadValM;
|
else CSRReadVal2M = CSRReadValM;
|
||||||
|
|
||||||
// Compute AND/OR modification
|
// Compute AND/OR modification
|
||||||
CSRRWM = CSRSrcM;
|
CSRRWM = CSRSrcM;
|
||||||
CSRRSM = CSRReadVal2M | CSRSrcM;
|
CSRRSM = CSRReadVal2M | CSRSrcM;
|
||||||
CSRRCM = CSRReadVal2M & ~CSRSrcM;
|
CSRRCM = CSRReadVal2M & ~CSRSrcM;
|
||||||
case (InstrM[13:12])
|
case (InstrM[13:12])
|
||||||
2'b01: CSRWriteValM = CSRRWM;
|
2'b01: CSRWriteValM = CSRRWM;
|
||||||
2'b10: CSRWriteValM = CSRRSM;
|
2'b10: CSRWriteValM = CSRRSM;
|
||||||
2'b11: CSRWriteValM = CSRRCM;
|
2'b11: CSRWriteValM = CSRRCM;
|
||||||
default: CSRWriteValM = CSRReadValM;
|
default: CSRWriteValM = CSRReadValM;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
@ -213,7 +214,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
csri #(P) csri(.clk, .reset,
|
csri #(P) csri(.clk, .reset,
|
||||||
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
|
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
|
||||||
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt,
|
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt,
|
||||||
.MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
|
.MIDELEG_REGW, .MENVCFG_STCE, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
|
||||||
|
|
||||||
csrsr #(P) csrsr(.clk, .reset, .StallW,
|
csrsr #(P) csrsr(.clk, .reset, .StallW,
|
||||||
.WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM,
|
.WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM,
|
||||||
@ -231,7 +232,8 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
.MEPC_REGW, .MCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW,
|
.MEPC_REGW, .MCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW,
|
||||||
.MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
.MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||||
.MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM,
|
.MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM,
|
||||||
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM);
|
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM,
|
||||||
|
.MENVCFG_STCE);
|
||||||
|
|
||||||
|
|
||||||
if (P.S_SUPPORTED) begin:csrs
|
if (P.S_SUPPORTED) begin:csrs
|
||||||
@ -242,7 +244,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
.CSRWriteValM, .PrivilegeModeW,
|
.CSRWriteValM, .PrivilegeModeW,
|
||||||
.CSRSReadValM, .STVEC_REGW, .SEPC_REGW,
|
.CSRSReadValM, .STVEC_REGW, .SEPC_REGW,
|
||||||
.SCOUNTEREN_REGW,
|
.SCOUNTEREN_REGW,
|
||||||
.SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT,
|
.SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .MENVCFG_STCE,
|
||||||
.WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt);
|
.WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt);
|
||||||
end else begin
|
end else begin
|
||||||
assign WriteSSTATUSM = 0;
|
assign WriteSSTATUSM = 0;
|
||||||
@ -266,7 +268,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign IllegalCSRUAccessM = 1;
|
assign IllegalCSRUAccessM = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (P.ZICOUNTERS_SUPPORTED) begin:counters
|
if (P.ZICNTR_SUPPORTED) begin:counters
|
||||||
csrc #(P) counters(.clk, .reset, .StallE, .StallM, .FlushM,
|
csrc #(P) counters(.clk, .reset, .StallE, .StallM, .FlushM,
|
||||||
.InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM,
|
.InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM,
|
||||||
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM,
|
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM,
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// csrc.sv
|
// csrc.sv
|
||||||
//
|
//
|
||||||
@ -31,57 +29,57 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csrc import cvw::*; #(parameter cvw_t P) (
|
module csrc import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallE, StallM,
|
input logic StallE, StallM,
|
||||||
input logic FlushM,
|
input logic FlushM,
|
||||||
input logic InstrValidNotFlushedM, LoadStallD, StoreStallD,
|
input logic InstrValidNotFlushedM, LoadStallD, StoreStallD,
|
||||||
input logic CSRMWriteM, CSRWriteM,
|
input logic CSRMWriteM, CSRWriteM,
|
||||||
input logic BPDirPredWrongM,
|
input logic BPDirPredWrongM,
|
||||||
input logic BTAWrongM,
|
input logic BTAWrongM,
|
||||||
input logic RASPredPCWrongM,
|
input logic RASPredPCWrongM,
|
||||||
input logic IClassWrongM,
|
input logic IClassWrongM,
|
||||||
input logic BPWrongM, // branch predictor is wrong
|
input logic BPWrongM, // branch predictor is wrong
|
||||||
input logic [3:0] InstrClassM,
|
input logic [3:0] InstrClassM,
|
||||||
input logic DCacheMiss,
|
input logic DCacheMiss,
|
||||||
input logic DCacheAccess,
|
input logic DCacheAccess,
|
||||||
input logic ICacheMiss,
|
input logic ICacheMiss,
|
||||||
input logic ICacheAccess,
|
input logic ICacheAccess,
|
||||||
input logic ICacheStallF,
|
input logic ICacheStallF,
|
||||||
input logic DCacheStallM,
|
input logic DCacheStallM,
|
||||||
input logic sfencevmaM,
|
input logic sfencevmaM,
|
||||||
input logic InterruptM,
|
input logic InterruptM,
|
||||||
input logic ExceptionM,
|
input logic ExceptionM,
|
||||||
input logic InvalidateICacheM,
|
input logic InvalidateICacheM,
|
||||||
input logic DivBusyE, // integer divide busy
|
input logic DivBusyE, // integer divide busy
|
||||||
input logic FDivBusyE, // floating point divide busy
|
input logic FDivBusyE, // floating point divide busy
|
||||||
input logic [11:0] CSRAdrM,
|
input logic [11:0] CSRAdrM,
|
||||||
input logic [1:0] PrivilegeModeW,
|
input logic [1:0] PrivilegeModeW,
|
||||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||||
input logic [63:0] MTIME_CLINT,
|
input logic [63:0] MTIME_CLINT,
|
||||||
output logic [P.XLEN-1:0] CSRCReadValM,
|
output logic [P.XLEN-1:0] CSRCReadValM,
|
||||||
output logic IllegalCSRCAccessM
|
output logic IllegalCSRCAccessM
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam MHPMCOUNTERBASE = 12'hB00;
|
localparam MHPMCOUNTERBASE = 12'hB00;
|
||||||
localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul;
|
localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul;
|
||||||
localparam MHPMCOUNTERHBASE = 12'hB80;
|
localparam MHPMCOUNTERHBASE = 12'hB80;
|
||||||
localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault
|
localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault
|
||||||
localparam MHPMEVENTBASE = 12'h320;
|
localparam MHPMEVENTBASE = 12'h320;
|
||||||
localparam HPMCOUNTERBASE = 12'hC00;
|
localparam HPMCOUNTERBASE = 12'hC00;
|
||||||
localparam HPMCOUNTERHBASE = 12'hC80;
|
localparam HPMCOUNTERHBASE = 12'hC80;
|
||||||
localparam TIME = 12'hC01;
|
localparam TIME = 12'hC01;
|
||||||
localparam TIMEH = 12'hC81;
|
localparam TIMEH = 12'hC81;
|
||||||
|
|
||||||
logic [4:0] CounterNumM;
|
logic [4:0] CounterNumM;
|
||||||
logic [P.XLEN-1:0] HPMCOUNTER_REGW[P.COUNTERS-1:0];
|
logic [P.XLEN-1:0] HPMCOUNTER_REGW[P.COUNTERS-1:0];
|
||||||
logic [P.XLEN-1:0] HPMCOUNTERH_REGW[P.COUNTERS-1:0];
|
logic [P.XLEN-1:0] HPMCOUNTERH_REGW[P.COUNTERS-1:0];
|
||||||
logic LoadStallE, LoadStallM;
|
logic LoadStallE, LoadStallM;
|
||||||
logic StoreStallE, StoreStallM;
|
logic StoreStallE, StoreStallM;
|
||||||
logic [P.COUNTERS-1:0] WriteHPMCOUNTERM;
|
logic [P.COUNTERS-1:0] WriteHPMCOUNTERM;
|
||||||
logic [P.COUNTERS-1:0] CounterEvent;
|
logic [P.COUNTERS-1:0] CounterEvent;
|
||||||
logic [63:0] HPMCOUNTERPlusM[P.COUNTERS-1:0];
|
logic [63:0] HPMCOUNTERPlusM[P.COUNTERS-1:0];
|
||||||
logic [P.XLEN-1:0] NextHPMCOUNTERM[P.COUNTERS-1:0];
|
logic [P.XLEN-1:0] NextHPMCOUNTERM[P.COUNTERS-1:0];
|
||||||
genvar i;
|
genvar i;
|
||||||
|
|
||||||
// Interface signals
|
// Interface signals
|
||||||
@ -89,38 +87,38 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
|||||||
flopenrc #(2) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d({StoreStallE, LoadStallE}), .q({StoreStallM, LoadStallM}));
|
flopenrc #(2) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d({StoreStallE, LoadStallE}), .q({StoreStallM, LoadStallM}));
|
||||||
|
|
||||||
// Determine when to increment each counter
|
// Determine when to increment each counter
|
||||||
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
|
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
|
||||||
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
|
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
|
||||||
assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired
|
assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired
|
||||||
if(P.QEMU) begin: cevent // No other performance counters in QEMU
|
if (P.ZIHPM_SUPPORTED) begin: cevent // User-defined counters
|
||||||
assign CounterEvent[P.COUNTERS-1:3] = 0;
|
assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
|
||||||
end else begin: cevent // User-defined counters
|
assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
|
||||||
assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
|
assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
|
||||||
assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
|
assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
|
||||||
assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
|
assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
|
||||||
assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
|
assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
|
||||||
assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
|
assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
|
||||||
assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
|
assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
|
||||||
assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
|
assign CounterEvent[11] = LoadStallM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
|
||||||
assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
|
assign CounterEvent[12] = StoreStallM; // Store Stall
|
||||||
assign CounterEvent[11] = LoadStallM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
|
assign CounterEvent[13] = DCacheAccess & InstrValidNotFlushedM; // data cache access
|
||||||
assign CounterEvent[12] = StoreStallM; // Store Stall
|
assign CounterEvent[14] = DCacheMiss; // data cache miss. Miss asserted 1 cycle at start of cache miss
|
||||||
assign CounterEvent[13] = DCacheAccess & InstrValidNotFlushedM; // data cache access
|
assign CounterEvent[15] = DCacheStallM; // d cache miss cycles
|
||||||
assign CounterEvent[14] = DCacheMiss; // data cache miss. Miss asserted 1 cycle at start of cache miss
|
assign CounterEvent[16] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access
|
||||||
assign CounterEvent[15] = DCacheStallM; // d cache miss cycles
|
assign CounterEvent[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss
|
||||||
assign CounterEvent[16] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access
|
assign CounterEvent[18] = ICacheStallF; // i cache miss cycles
|
||||||
assign CounterEvent[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss
|
assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes
|
||||||
assign CounterEvent[18] = ICacheStallF; // i cache miss cycles
|
assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i
|
||||||
assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes
|
assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma
|
||||||
assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i
|
assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low
|
||||||
assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma
|
assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low
|
||||||
assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low
|
|
||||||
assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low
|
|
||||||
// coverage off
|
// coverage off
|
||||||
// DivBusyE will never be assert high since this configuration uses the FPU to do integer division
|
// DivBusyE will never be assert high since this configuration uses the FPU to do integer division
|
||||||
assign CounterEvent[24] = DivBusyE | FDivBusyE; // division cycles *** RT: might need to be delay until the next cycle
|
assign CounterEvent[24] = DivBusyE | FDivBusyE; // division cycles *** RT: might need to be delay until the next cycle
|
||||||
// coverage on
|
// coverage on
|
||||||
assign CounterEvent[P.COUNTERS-1:25] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
|
assign CounterEvent[P.COUNTERS-1:25] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
|
||||||
|
end else begin: cevent
|
||||||
|
assign CounterEvent[P.COUNTERS-1:3] = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
// Counter update and write logic
|
// Counter update and write logic
|
||||||
@ -158,14 +156,14 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
|||||||
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
||||||
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+P.COUNTERS & CSRAdrM != MTIME)
|
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+P.COUNTERS & CSRAdrM != MTIME)
|
||||||
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||||
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS)
|
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS)
|
||||||
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||||
else begin
|
else begin
|
||||||
CSRCReadValM = 0;
|
CSRCReadValM = 0;
|
||||||
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
|
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
|
||||||
end
|
end
|
||||||
end else begin // 32-bit counter reads
|
end else begin // 32-bit counter reads
|
||||||
// Veri lator doesn't realize this only occurs for XLEN=32
|
// Veril ator doesn't realize this only occurs for XLEN=32
|
||||||
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
||||||
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
|
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
|
||||||
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
|
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
|
||||||
@ -189,4 +187,4 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
// mounteren should only exist if u-mode exists
|
// mounteren should only exist if u-mode exists
|
@ -30,10 +30,11 @@
|
|||||||
module csri import cvw::*; #(parameter cvw_t P) (
|
module csri import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic CSRMWriteM, CSRSWriteM,
|
input logic CSRMWriteM, CSRSWriteM,
|
||||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
input logic [11:0] CSRAdrM,
|
input logic [11:0] CSRAdrM,
|
||||||
input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt,
|
input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt,
|
||||||
input logic [11:0] MIDELEG_REGW,
|
input logic [11:0] MIDELEG_REGW,
|
||||||
|
input logic MENVCFG_STCE,
|
||||||
output logic [11:0] MIP_REGW, MIE_REGW,
|
output logic [11:0] MIP_REGW, MIE_REGW,
|
||||||
output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0
|
output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0
|
||||||
);
|
);
|
||||||
@ -60,7 +61,7 @@ module csri import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (P.S_SUPPORTED) begin:mask
|
if (P.S_SUPPORTED) begin:mask
|
||||||
if (P.SSTC_SUPPORTED) begin
|
if (P.SSTC_SUPPORTED) begin
|
||||||
assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec)
|
assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec)
|
||||||
assign STIP = STimerInt;
|
assign STIP = MENVCFG_STCE ? STimerInt : MIP_REGW_writeable[5];
|
||||||
end else begin
|
end else begin
|
||||||
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9)
|
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9)
|
||||||
assign STIP = MIP_REGW_writeable[5];
|
assign STIP = MIP_REGW_writeable[5];
|
||||||
@ -81,7 +82,6 @@ module csri import cvw::*; #(parameter cvw_t P) (
|
|||||||
else if (WriteMIEM) MIE_REGW <= (CSRWriteValM[11:0] & MIE_WRITE_MASK); // MIE controls M and S fields
|
else if (WriteMIEM) MIE_REGW <= (CSRWriteValM[11:0] & MIE_WRITE_MASK); // MIE controls M and S fields
|
||||||
else if (WriteSIEM) MIE_REGW <= (CSRWriteValM[11:0] & 12'h222 & MIDELEG_REGW) | (MIE_REGW & 12'h888); // only S fields
|
else if (WriteSIEM) MIE_REGW <= (CSRWriteValM[11:0] & 12'h222 & MIDELEG_REGW) | (MIE_REGW & 12'h888); // only S fields
|
||||||
|
|
||||||
|
|
||||||
assign MIP_REGW = {MExtInt, 1'b0, SExtInt|MIP_REGW_writeable[9], 1'b0,
|
assign MIP_REGW = {MExtInt, 1'b0, SExtInt|MIP_REGW_writeable[9], 1'b0,
|
||||||
MTimerInt, 1'b0, STIP, 1'b0,
|
MTimerInt, 1'b0, STIP, 1'b0,
|
||||||
MSwInt, 1'b0, MIP_REGW_writeable[1], 1'b0};
|
MSwInt, 1'b0, MIP_REGW_writeable[1], 1'b0};
|
||||||
|
@ -32,67 +32,74 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csrm import cvw::*; #(parameter cvw_t P) (
|
module csrm import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic UngatedCSRMWriteM, CSRMWriteM, MTrapM,
|
input logic UngatedCSRMWriteM, CSRMWriteM, MTrapM,
|
||||||
input logic [11:0] CSRAdrM,
|
input logic [11:0] CSRAdrM,
|
||||||
input logic [P.XLEN-1:0] NextEPCM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW,
|
input logic [P.XLEN-1:0] NextEPCM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW,
|
||||||
input logic [4:0] NextCauseM,
|
input logic [4:0] NextCauseM,
|
||||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
input logic [11:0] MIP_REGW, MIE_REGW,
|
input logic [11:0] MIP_REGW, MIE_REGW,
|
||||||
output logic [P.XLEN-1:0] CSRMReadValM, MTVEC_REGW,
|
output logic [P.XLEN-1:0] CSRMReadValM, MTVEC_REGW,
|
||||||
output logic [P.XLEN-1:0] MEPC_REGW,
|
output logic [P.XLEN-1:0] MEPC_REGW,
|
||||||
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
|
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
|
||||||
output logic [15:0] MEDELEG_REGW,
|
output logic [15:0] MEDELEG_REGW,
|
||||||
output logic [11:0] MIDELEG_REGW,
|
output logic [11:0] MIDELEG_REGW,
|
||||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||||
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
|
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
|
||||||
output logic WriteMSTATUSM, WriteMSTATUSHM,
|
output logic WriteMSTATUSM, WriteMSTATUSHM,
|
||||||
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM
|
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM,
|
||||||
|
output logic MENVCFG_STCE
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW;
|
logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW;
|
||||||
logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW;
|
logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW;
|
||||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
logic [63:0] MENVCFG_REGW;
|
||||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
logic [P.XLEN-1:0] MENVCFGH_REGW;
|
||||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
logic [63:0] MENVCFG_PreWriteValM, MENVCFG_WriteValM;
|
||||||
|
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||||
|
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||||
|
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||||
|
logic WriteMENVCFGM;
|
||||||
|
|
||||||
// Machine CSRs
|
// Machine CSRs
|
||||||
localparam MVENDORID = 12'hF11;
|
localparam MVENDORID = 12'hF11;
|
||||||
localparam MARCHID = 12'hF12;
|
localparam MARCHID = 12'hF12;
|
||||||
localparam MIMPID = 12'hF13;
|
localparam MIMPID = 12'hF13;
|
||||||
localparam MHARTID = 12'hF14;
|
localparam MHARTID = 12'hF14;
|
||||||
localparam MCONFIGPTR = 12'hF15;
|
localparam MCONFIGPTR = 12'hF15;
|
||||||
localparam MSTATUS = 12'h300;
|
localparam MSTATUS = 12'h300;
|
||||||
localparam MISA_ADR = 12'h301;
|
localparam MISA_ADR = 12'h301;
|
||||||
localparam MEDELEG = 12'h302;
|
localparam MEDELEG = 12'h302;
|
||||||
localparam MIDELEG = 12'h303;
|
localparam MIDELEG = 12'h303;
|
||||||
localparam MIE = 12'h304;
|
localparam MIE = 12'h304;
|
||||||
localparam MTVEC = 12'h305;
|
localparam MTVEC = 12'h305;
|
||||||
localparam MCOUNTEREN = 12'h306;
|
localparam MCOUNTEREN = 12'h306;
|
||||||
localparam MSTATUSH = 12'h310;
|
localparam MENVCFG = 12'h30A;
|
||||||
|
localparam MSTATUSH = 12'h310;
|
||||||
|
localparam MENVCFGH = 12'h31A;
|
||||||
localparam MCOUNTINHIBIT = 12'h320;
|
localparam MCOUNTINHIBIT = 12'h320;
|
||||||
localparam MSCRATCH = 12'h340;
|
localparam MSCRATCH = 12'h340;
|
||||||
localparam MEPC = 12'h341;
|
localparam MEPC = 12'h341;
|
||||||
localparam MCAUSE = 12'h342;
|
localparam MCAUSE = 12'h342;
|
||||||
localparam MTVAL = 12'h343;
|
localparam MTVAL = 12'h343;
|
||||||
localparam MIP = 12'h344;
|
localparam MIP = 12'h344;
|
||||||
localparam MTINST = 12'h34A;
|
localparam MTINST = 12'h34A;
|
||||||
localparam PMPCFG0 = 12'h3A0;
|
localparam PMPCFG0 = 12'h3A0;
|
||||||
// .. up to 15 more at consecutive addresses
|
// .. up to 15 more at consecutive addresses
|
||||||
localparam PMPADDR0 = 12'h3B0;
|
localparam PMPADDR0 = 12'h3B0;
|
||||||
// ... up to 63 more at consecutive addresses
|
// ... up to 63 more at consecutive addresses
|
||||||
localparam TSELECT = 12'h7A0;
|
localparam TSELECT = 12'h7A0;
|
||||||
localparam TDATA1 = 12'h7A1;
|
localparam TDATA1 = 12'h7A1;
|
||||||
localparam TDATA2 = 12'h7A2;
|
localparam TDATA2 = 12'h7A2;
|
||||||
localparam TDATA3 = 12'h7A3;
|
localparam TDATA3 = 12'h7A3;
|
||||||
localparam DCSR = 12'h7B0;
|
localparam DCSR = 12'h7B0;
|
||||||
localparam DPC = 12'h7B1;
|
localparam DPC = 12'h7B1;
|
||||||
localparam DSCRATCH0 = 12'h7B2;
|
localparam DSCRATCH0 = 12'h7B2;
|
||||||
localparam DSCRATCH1 = 12'h7B3;
|
localparam DSCRATCH1 = 12'h7B3;
|
||||||
// Constants
|
// Constants
|
||||||
localparam ZERO = {(P.XLEN){1'b0}};
|
localparam ZERO = {(P.XLEN){1'b0}};
|
||||||
localparam MEDELEG_MASK = 16'hB3FF;
|
localparam MEDELEG_MASK = 16'hB3FF;
|
||||||
localparam MIDELEG_MASK = 12'h222; // we choose to not make machine interrupts delegable
|
localparam MIDELEG_MASK = 12'h222; // we choose to not make machine interrupts delegable
|
||||||
|
|
||||||
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
||||||
genvar i;
|
genvar i;
|
||||||
@ -130,16 +137,17 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign MHARTID_REGW = 0;
|
assign MHARTID_REGW = 0;
|
||||||
|
|
||||||
// Write machine Mode CSRs
|
// Write machine Mode CSRs
|
||||||
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS);
|
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS);
|
||||||
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH)& (P.XLEN==32);
|
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & (P.XLEN==32);
|
||||||
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC);
|
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC);
|
||||||
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG);
|
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG);
|
||||||
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG);
|
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG);
|
||||||
assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH);
|
assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH);
|
||||||
assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC));
|
assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC));
|
||||||
assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE));
|
assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE));
|
||||||
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
||||||
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
||||||
|
assign WriteMENVCFGM = CSRMWriteM & (CSRAdrM == MENVCFG);
|
||||||
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT);
|
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT);
|
||||||
|
|
||||||
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID);
|
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID);
|
||||||
@ -161,6 +169,39 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
|
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
|
||||||
end else assign MCOUNTEREN_REGW = '0;
|
end else assign MCOUNTEREN_REGW = '0;
|
||||||
|
|
||||||
|
// MENVCFG is always 64 bits even for RV32
|
||||||
|
assign MENVCFG_WriteValM = {
|
||||||
|
MENVCFG_PreWriteValM[63] & P.SSTC_SUPPORTED,
|
||||||
|
MENVCFG_PreWriteValM[62] & P.SVPBMT_SUPPORTED,
|
||||||
|
54'b0,
|
||||||
|
MENVCFG_PreWriteValM[7] & P.ZICBOZ_SUPPORTED,
|
||||||
|
MENVCFG_PreWriteValM[6:4] & {3{P.ZICBOM_SUPPORTED}},
|
||||||
|
3'b0,
|
||||||
|
MENVCFG_PreWriteValM[0] & P.S_SUPPORTED & P.VIRTMEM_SUPPORTED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (P.XLEN == 64) begin
|
||||||
|
assign MENVCFG_PreWriteValM = CSRWriteValM;
|
||||||
|
flopenr #(P.XLEN) MENVCFGreg(clk, reset, WriteMENVCFGM, MENVCFG_WriteValM, MENVCFG_REGW);
|
||||||
|
assign MENVCFGH_REGW = 0;
|
||||||
|
end else begin
|
||||||
|
logic WriteMENVCFGHM;
|
||||||
|
assign MENVCFG_PreWriteValM = {CSRWriteValM, CSRWriteValM};
|
||||||
|
assign WriteMENVCFGHM = CSRMWriteM & (CSRAdrM == MENVCFGH) & (P.XLEN==32);
|
||||||
|
flopenr #(P.XLEN) MENVCFGreg(clk, reset, WriteMENVCFGM, MENVCFG_WriteValM[31:0], MENVCFG_REGW[31:0]);
|
||||||
|
flopenr #(P.XLEN) MENVCFGHreg(clk, reset, WriteMENVCFGHM, MENVCFG_WriteValM[63:32], MENVCFG_REGW[63:32]);
|
||||||
|
assign MENVCFGH_REGW = MENVCFG_REGW[63:32];
|
||||||
|
end
|
||||||
|
|
||||||
|
// Extract bit fields
|
||||||
|
assign MENVCFG_STCE = MENVCFG_REGW[63];
|
||||||
|
// Uncomment these other fields when they are defined
|
||||||
|
// assign MENVCFG_PBMTE = MENVCFG_REGW[62];
|
||||||
|
// assign MENVCFG_CBZE = MENVCFG_REGW[7];
|
||||||
|
// assign MENVCFG_CBCFE = MENVCFG_REGW[6];
|
||||||
|
// assign MENVCFG_CBIE = MENVCFG_REGW[5:4];
|
||||||
|
// assign MENVCFG_FIOM = MENVCFG_REGW[0];
|
||||||
|
|
||||||
// Read machine mode CSRs
|
// Read machine mode CSRs
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
logic [5:0] entry;
|
logic [5:0] entry;
|
||||||
@ -181,26 +222,28 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else case (CSRAdrM)
|
else case (CSRAdrM)
|
||||||
MISA_ADR: CSRMReadValM = MISA_REGW;
|
MISA_ADR: CSRMReadValM = MISA_REGW;
|
||||||
MVENDORID: CSRMReadValM = 0;
|
MVENDORID: CSRMReadValM = 0;
|
||||||
MARCHID: CSRMReadValM = 0;
|
MARCHID: CSRMReadValM = 0;
|
||||||
MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation
|
MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation
|
||||||
MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0
|
MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0
|
||||||
MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0
|
MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0
|
||||||
MSTATUS: CSRMReadValM = MSTATUS_REGW;
|
MSTATUS: CSRMReadValM = MSTATUS_REGW;
|
||||||
MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
|
MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
|
||||||
MTVEC: CSRMReadValM = MTVEC_REGW;
|
MTVEC: CSRMReadValM = MTVEC_REGW;
|
||||||
MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW};
|
MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW};
|
||||||
MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW};
|
MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW};
|
||||||
MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW};
|
MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW};
|
||||||
MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW};
|
MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW};
|
||||||
MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
|
MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
|
||||||
MEPC: CSRMReadValM = MEPC_REGW;
|
MEPC: CSRMReadValM = MEPC_REGW;
|
||||||
MCAUSE: CSRMReadValM = MCAUSE_REGW;
|
MCAUSE: CSRMReadValM = MCAUSE_REGW;
|
||||||
MTVAL: CSRMReadValM = MTVAL_REGW;
|
MTVAL: CSRMReadValM = MTVAL_REGW;
|
||||||
MTINST: CSRMReadValM = 0; // implemented as trivial zero
|
MTINST: CSRMReadValM = 0; // implemented as trivial zero
|
||||||
MCOUNTEREN:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW};
|
MCOUNTEREN: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW};
|
||||||
MCOUNTINHIBIT:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
|
MENVCFG: CSRMReadValM = MENVCFG_REGW[P.XLEN-1:0];
|
||||||
|
MENVCFGH: CSRMReadValM = MENVCFGH_REGW;
|
||||||
|
MCOUNTINHIBIT: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
|
||||||
|
|
||||||
default: begin
|
default: begin
|
||||||
CSRMReadValM = 0;
|
CSRMReadValM = 0;
|
||||||
@ -209,4 +252,4 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
// verilator lint_on WIDTH
|
// verilator lint_on WIDTH
|
||||||
endmodule
|
endmodule
|
@ -29,61 +29,69 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csrs import cvw::*; #(parameter cvw_t P) (
|
module csrs import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic CSRSWriteM, STrapM,
|
input logic CSRSWriteM, STrapM,
|
||||||
input logic [11:0] CSRAdrM,
|
input logic [11:0] CSRAdrM,
|
||||||
input logic [P.XLEN-1:0] NextEPCM, NextMtvalM, SSTATUS_REGW,
|
input logic [P.XLEN-1:0] NextEPCM, NextMtvalM, SSTATUS_REGW,
|
||||||
input logic [4:0] NextCauseM,
|
input logic [4:0] NextCauseM,
|
||||||
input logic STATUS_TVM,
|
input logic STATUS_TVM,
|
||||||
input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear
|
input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear
|
||||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
input logic [1:0] PrivilegeModeW,
|
input logic [1:0] PrivilegeModeW,
|
||||||
output logic [P.XLEN-1:0] CSRSReadValM, STVEC_REGW,
|
output logic [P.XLEN-1:0] CSRSReadValM, STVEC_REGW,
|
||||||
output logic [P.XLEN-1:0] SEPC_REGW,
|
output logic [P.XLEN-1:0] SEPC_REGW,
|
||||||
output logic [31:0] SCOUNTEREN_REGW,
|
output logic [31:0] SCOUNTEREN_REGW,
|
||||||
output logic [P.XLEN-1:0] SATP_REGW,
|
output logic [P.XLEN-1:0] SATP_REGW,
|
||||||
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||||
input logic [63:0] MTIME_CLINT,
|
input logic [63:0] MTIME_CLINT,
|
||||||
output logic WriteSSTATUSM,
|
input logic MENVCFG_STCE,
|
||||||
output logic IllegalCSRSAccessM,
|
output logic WriteSSTATUSM,
|
||||||
output logic STimerInt
|
output logic IllegalCSRSAccessM,
|
||||||
|
output logic STimerInt
|
||||||
);
|
);
|
||||||
|
|
||||||
// Supervisor CSRs
|
// Supervisor CSRs
|
||||||
localparam SSTATUS = 12'h100;
|
localparam SSTATUS = 12'h100;
|
||||||
localparam SIE = 12'h104;
|
localparam SIE = 12'h104;
|
||||||
localparam STVEC = 12'h105;
|
localparam STVEC = 12'h105;
|
||||||
localparam SCOUNTEREN = 12'h106;
|
localparam SCOUNTEREN = 12'h106;
|
||||||
localparam SSCRATCH = 12'h140;
|
localparam SENVCFG = 12'h10A;
|
||||||
localparam SEPC = 12'h141;
|
localparam SSCRATCH = 12'h140;
|
||||||
localparam SCAUSE = 12'h142;
|
localparam SEPC = 12'h141;
|
||||||
localparam STVAL = 12'h143;
|
localparam SCAUSE = 12'h142;
|
||||||
localparam SIP= 12'h144;
|
localparam STVAL = 12'h143;
|
||||||
localparam STIMECMP = 12'h14D;
|
localparam SIP = 12'h144;
|
||||||
localparam STIMECMPH = 12'h15D;
|
localparam STIMECMP = 12'h14D;
|
||||||
localparam SATP = 12'h180;
|
localparam STIMECMPH = 12'h15D;
|
||||||
|
localparam SATP = 12'h180;
|
||||||
// Constants
|
// Constants
|
||||||
localparam ZERO = {(P.XLEN){1'b0}};
|
localparam ZERO = {(P.XLEN){1'b0}};
|
||||||
localparam SEDELEG_MASK = ~(ZERO | {{P.XLEN-3{1'b0}}, 3'b111} << 9);
|
localparam SEDELEG_MASK = ~(ZERO | {{P.XLEN-3{1'b0}}, 3'b111} << 9);
|
||||||
|
|
||||||
logic WriteSTVECM;
|
logic WriteSTVECM;
|
||||||
logic WriteSSCRATCHM, WriteSEPCM;
|
logic WriteSSCRATCHM, WriteSEPCM;
|
||||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||||
logic WriteSTIMECMPM, WriteSTIMECMPHM;
|
logic WriteSTIMECMPM, WriteSTIMECMPHM;
|
||||||
logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW;
|
logic WriteSENVCFGM;
|
||||||
|
|
||||||
|
logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW;
|
||||||
|
logic [P.XLEN-1:0] SENVCFG_REGW;
|
||||||
|
logic [P.XLEN-1:0] SENVCFG_WriteValM;
|
||||||
|
|
||||||
logic [63:0] STIMECMP_REGW;
|
logic [63:0] STIMECMP_REGW;
|
||||||
|
|
||||||
// write enables
|
// write enables
|
||||||
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS);
|
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS);
|
||||||
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC);
|
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC);
|
||||||
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH);
|
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH);
|
||||||
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC));
|
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC));
|
||||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE));
|
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE));
|
||||||
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL));
|
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL));
|
||||||
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
|
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
|
||||||
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
|
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
|
||||||
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM);
|
assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG);
|
||||||
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM) & (P.XLEN == 32);
|
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE));
|
||||||
|
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)) & (P.XLEN == 32);
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
|
flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
|
||||||
@ -108,9 +116,27 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Supervisor timer interrupt logic
|
// Supervisor timer interrupt logic
|
||||||
// Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs
|
// Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs
|
||||||
if (P.SSTC_SUPPORTED)
|
if (P.SSTC_SUPPORTED)
|
||||||
assign STimerInt = ({1'b0, MTIME_CLINT} >= {1'b0, STIMECMP_REGW}); // unsigned comparison
|
assign STimerInt = ({1'b0, MTIME_CLINT} >= {1'b0, STIMECMP_REGW}); // unsigned comparison
|
||||||
else
|
else
|
||||||
assign STimerInt = 0;
|
assign STimerInt = 0;
|
||||||
|
|
||||||
|
assign SENVCFG_WriteValM = {
|
||||||
|
{(P.XLEN-8){1'b0}},
|
||||||
|
CSRWriteValM[7] & P.ZICBOZ_SUPPORTED,
|
||||||
|
CSRWriteValM[6:4] & {3{P.ZICBOM_SUPPORTED}},
|
||||||
|
3'b0,
|
||||||
|
CSRWriteValM[0] & P.S_SUPPORTED & P.VIRTMEM_SUPPORTED
|
||||||
|
};
|
||||||
|
|
||||||
|
flopenr #(P.XLEN) SENVCFGreg(clk, reset, WriteSENVCFGM, SENVCFG_WriteValM, SENVCFG_REGW);
|
||||||
|
|
||||||
|
// Extract bit fields
|
||||||
|
// Uncomment these other fields when they are defined
|
||||||
|
// assign SENVCFG_PBMTE = SENVCFG_REGW[62];
|
||||||
|
// assign SENVCFG_CBZE = SENVCFG_REGW[7];
|
||||||
|
// assign SENVCFG_CBCFE = SENVCFG_REGW[6];
|
||||||
|
// assign SENVCFG_CBIE = SENVCFG_REGW[5:4];
|
||||||
|
// assign SENVCFG_FIOM = SENVCFG_REGW[0];
|
||||||
|
|
||||||
// CSR Reads
|
// CSR Reads
|
||||||
always_comb begin:csrr
|
always_comb begin:csrr
|
||||||
@ -130,12 +156,15 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
|||||||
IllegalCSRSAccessM = 1;
|
IllegalCSRSAccessM = 1;
|
||||||
end
|
end
|
||||||
SCOUNTEREN:CSRSReadValM = {{(P.XLEN-32){1'b0}}, SCOUNTEREN_REGW};
|
SCOUNTEREN:CSRSReadValM = {{(P.XLEN-32){1'b0}}, SCOUNTEREN_REGW};
|
||||||
STIMECMP: if (P.SSTC_SUPPORTED & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM)) CSRSReadValM = STIMECMP_REGW[P.XLEN-1:0];
|
SENVCFG: CSRSReadValM = SENVCFG_REGW;
|
||||||
|
STIMECMP: if (P.SSTC_SUPPORTED & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM && MENVCFG_STCE)))
|
||||||
|
CSRSReadValM = STIMECMP_REGW[P.XLEN-1:0];
|
||||||
else begin
|
else begin
|
||||||
CSRSReadValM = 0;
|
CSRSReadValM = 0;
|
||||||
IllegalCSRSAccessM = 1;
|
IllegalCSRSAccessM = 1;
|
||||||
end
|
end
|
||||||
STIMECMPH: if (P.SSTC_SUPPORTED & (P.XLEN == 32) & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM)) CSRSReadValM[31:0] = STIMECMP_REGW[63:32];
|
STIMECMPH: if (P.SSTC_SUPPORTED & (P.XLEN == 32) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM && MENVCFG_STCE)))
|
||||||
|
CSRSReadValM[31:0] = STIMECMP_REGW[63:32];
|
||||||
else begin // not supported for RV64
|
else begin // not supported for RV64
|
||||||
CSRSReadValM = 0;
|
CSRSReadValM = 0;
|
||||||
IllegalCSRSAccessM = 1;
|
IllegalCSRSAccessM = 1;
|
||||||
@ -146,4 +175,4 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
@ -4,7 +4,7 @@
|
|||||||
// Written: David_Harris@hmc.edu 9 January 2021
|
// Written: David_Harris@hmc.edu 9 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Status register
|
// Purpose: Status register (and environment configuration register and others shared across modes)
|
||||||
// See RISC-V Privileged Mode Specification 20190608
|
// See RISC-V Privileged Mode Specification 20190608
|
||||||
//
|
//
|
||||||
// Documentation: RISC-V System on Chip Design Chapter 5
|
// Documentation: RISC-V System on Chip Design Chapter 5
|
||||||
@ -28,22 +28,22 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csrsr import cvw::*; #(parameter cvw_t P) (
|
module csrsr import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset, StallW,
|
input logic clk, reset, StallW,
|
||||||
input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM,
|
input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM,
|
||||||
input logic TrapM, FRegWriteM,
|
input logic TrapM, FRegWriteM,
|
||||||
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
||||||
input logic mretM, sretM,
|
input logic mretM, sretM,
|
||||||
input logic WriteFRMM, WriteFFLAGSM,
|
input logic WriteFRMM, WriteFFLAGSM,
|
||||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
input logic SelHPTW,
|
input logic SelHPTW,
|
||||||
output logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW,
|
output logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW,
|
||||||
output logic [1:0] STATUS_MPP,
|
output logic [1:0] STATUS_MPP,
|
||||||
output logic STATUS_SPP, STATUS_TSR, STATUS_TW,
|
output logic STATUS_SPP, STATUS_TSR, STATUS_TW,
|
||||||
output logic STATUS_MIE, STATUS_SIE,
|
output logic STATUS_MIE, STATUS_SIE,
|
||||||
output logic STATUS_MXR, STATUS_SUM,
|
output logic STATUS_MXR, STATUS_SUM,
|
||||||
output logic STATUS_MPRV, STATUS_TVM,
|
output logic STATUS_MPRV, STATUS_TVM,
|
||||||
output logic [1:0] STATUS_FS,
|
output logic [1:0] STATUS_FS,
|
||||||
output logic BigEndianM
|
output logic BigEndianM
|
||||||
);
|
);
|
||||||
|
|
||||||
logic STATUS_SD, STATUS_TW_INT, STATUS_TSR_INT, STATUS_TVM_INT, STATUS_MXR_INT, STATUS_SUM_INT, STATUS_MPRV_INT;
|
logic STATUS_SD, STATUS_TW_INT, STATUS_TSR_INT, STATUS_TVM_INT, STATUS_MXR_INT, STATUS_SUM_INT, STATUS_MPRV_INT;
|
||||||
@ -56,27 +56,27 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Lower privilege status registers are a subset of the full status register
|
// Lower privilege status registers are a subset of the full status register
|
||||||
// *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable
|
// *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable
|
||||||
if (P.XLEN==64) begin: csrsr64 // RV64
|
if (P.XLEN==64) begin: csrsr64 // RV64
|
||||||
assign MSTATUS_REGW = {STATUS_SD, 25'b0, STATUS_MBE, STATUS_SBE, STATUS_SXL, STATUS_UXL, 9'b0,
|
assign MSTATUS_REGW = {STATUS_SD, 25'b0, STATUS_MBE, STATUS_SBE, STATUS_SXL, STATUS_UXL, 9'b0,
|
||||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
||||||
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0,
|
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0,
|
||||||
STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
|
STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
|
||||||
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ {P.QEMU ? 2'b0 : STATUS_UXL}, /*9'b0, */ 12'b0,
|
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ {P.QEMU ? 2'b0 : STATUS_UXL}, /*9'b0, */ 12'b0,
|
||||||
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
||||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||||
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
||||||
assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
|
assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
|
||||||
end else begin: csrsr32 // RV32
|
end else begin: csrsr32 // RV32
|
||||||
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
||||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
||||||
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0, STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
|
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0, STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
|
||||||
assign MSTATUSH_REGW = {26'b0, STATUS_MBE, STATUS_SBE, 4'b0};
|
assign MSTATUSH_REGW = {26'b0, STATUS_MBE, STATUS_SBE, 4'b0};
|
||||||
assign SSTATUS_REGW = {STATUS_SD, 11'b0,
|
assign SSTATUS_REGW = {STATUS_SD, 11'b0,
|
||||||
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
||||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||||
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -90,21 +90,21 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// harwired STATUS bits
|
// harwired STATUS bits
|
||||||
assign STATUS_TSR = P.S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_TSR = P.S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_TW = (P.S_SUPPORTED | P.U_SUPPORTED) & STATUS_TW_INT; // override register with 0 if only machine mode supported
|
assign STATUS_TW = (P.S_SUPPORTED | P.U_SUPPORTED) & STATUS_TW_INT; // override register with 0 if only machine mode supported
|
||||||
assign STATUS_TVM = P.S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_TVM = P.S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_MXR = P.S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_MXR = P.S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
/* assign STATUS_UBE = 0; // little-endian
|
/* assign STATUS_UBE = 0; // little-endian
|
||||||
assign STATUS_SBE = 0; // little-endian
|
assign STATUS_SBE = 0; // little-endian
|
||||||
assign STATUS_MBE = 0; // little-endian */
|
assign STATUS_MBE = 0; // little-endian */
|
||||||
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
|
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
|
||||||
assign STATUS_SXL = P.S_SUPPORTED ? 2'b10 : 2'b00; // 10 if supervisor mode supported
|
assign STATUS_SXL = P.S_SUPPORTED ? 2'b10 : 2'b00; // 10 if supervisor mode supported
|
||||||
assign STATUS_UXL = P.U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported
|
assign STATUS_UXL = P.U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported
|
||||||
assign STATUS_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_MPRV = P.U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
|
assign STATUS_MPRV = P.U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
|
||||||
assign STATUS_FS = (P.S_SUPPORTED & (P.F_SUPPORTED | P.D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
|
assign STATUS_FS = (P.S_SUPPORTED & (P.F_SUPPORTED | P.D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
|
||||||
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
|
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
|
||||||
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
|
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
if (CSRWriteValM[12:11] == P.U_MODE & P.U_SUPPORTED) STATUS_MPP_NEXT = P.U_MODE;
|
if (CSRWriteValM[12:11] == P.U_MODE & P.U_SUPPORTED) STATUS_MPP_NEXT = P.U_MODE;
|
||||||
@ -122,14 +122,14 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (SelHPTW) EndiannessPrivMode = P.S_MODE;
|
if (SelHPTW) EndiannessPrivMode = P.S_MODE;
|
||||||
//coverage off -item c 1 -feccondrow 1
|
//coverage off -item c 1 -feccondrow 1
|
||||||
// status.MPRV always gets reset upon leaving machine mode, so MPRV will never be high when out of machine mode
|
// status.MPRV always gets reset upon leaving machine mode, so MPRV will never be high when out of machine mode
|
||||||
else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP;
|
else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP;
|
||||||
//coverage on
|
//coverage on
|
||||||
else EndiannessPrivMode = PrivilegeModeW;
|
else EndiannessPrivMode = PrivilegeModeW;
|
||||||
|
|
||||||
case (EndiannessPrivMode)
|
case (EndiannessPrivMode)
|
||||||
P.M_MODE: BigEndianM = STATUS_MBE;
|
P.M_MODE: BigEndianM = STATUS_MBE;
|
||||||
P.S_MODE: BigEndianM = STATUS_SBE;
|
P.S_MODE: BigEndianM = STATUS_SBE;
|
||||||
default: BigEndianM = STATUS_UBE;
|
default: BigEndianM = STATUS_UBE;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end else begin: endianmux
|
end else begin: endianmux
|
||||||
@ -140,22 +140,22 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
// complex register with reset, write enable, and the ability to update other bits in certain cases
|
// complex register with reset, write enable, and the ability to update other bits in certain cases
|
||||||
always_ff @(posedge clk) //, posedge reset)
|
always_ff @(posedge clk) //, posedge reset)
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
STATUS_TSR_INT <= #1 0;
|
STATUS_TSR_INT <= #1 0;
|
||||||
STATUS_TW_INT <= #1 0;
|
STATUS_TW_INT <= #1 0;
|
||||||
STATUS_TVM_INT <= #1 0;
|
STATUS_TVM_INT <= #1 0;
|
||||||
STATUS_MXR_INT <= #1 0;
|
STATUS_MXR_INT <= #1 0;
|
||||||
STATUS_SUM_INT <= #1 0;
|
STATUS_SUM_INT <= #1 0;
|
||||||
STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
|
STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
|
||||||
STATUS_FS_INT <= #1 P.F_SUPPORTED ? 2'b00 : 2'b00; // leave floating-point off until activated, even if F_SUPPORTED
|
STATUS_FS_INT <= #1 P.F_SUPPORTED ? 2'b00 : 2'b00; // leave floating-point off until activated, even if F_SUPPORTED
|
||||||
STATUS_MPP <= #1 0;
|
STATUS_MPP <= #1 0;
|
||||||
STATUS_SPP <= #1 0;
|
STATUS_SPP <= #1 0;
|
||||||
STATUS_MPIE <= #1 0;
|
STATUS_MPIE <= #1 0;
|
||||||
STATUS_SPIE <= #1 0;
|
STATUS_SPIE <= #1 0;
|
||||||
STATUS_MIE <= #1 0;
|
STATUS_MIE <= #1 0;
|
||||||
STATUS_SIE <= #1 0;
|
STATUS_SIE <= #1 0;
|
||||||
STATUS_MBE <= #1 0;
|
STATUS_MBE <= #1 0;
|
||||||
STATUS_SBE <= #1 0;
|
STATUS_SBE <= #1 0;
|
||||||
STATUS_UBE <= #1 0;
|
STATUS_UBE <= #1 0;
|
||||||
end else if (~StallW) begin
|
end else if (~StallW) begin
|
||||||
if (TrapM) begin
|
if (TrapM) begin
|
||||||
// Update interrupt enables per Privileged Spec p. 21
|
// Update interrupt enables per Privileged Spec p. 21
|
||||||
@ -164,54 +164,54 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Modes: 11 = Machine, 01 = Supervisor, 00 = User
|
// Modes: 11 = Machine, 01 = Supervisor, 00 = User
|
||||||
if (NextPrivilegeModeM == P.M_MODE) begin
|
if (NextPrivilegeModeM == P.M_MODE) begin
|
||||||
STATUS_MPIE <= #1 STATUS_MIE;
|
STATUS_MPIE <= #1 STATUS_MIE;
|
||||||
STATUS_MIE <= #1 0;
|
STATUS_MIE <= #1 0;
|
||||||
STATUS_MPP <= #1 PrivilegeModeW;
|
STATUS_MPP <= #1 PrivilegeModeW;
|
||||||
end else begin // supervisor mode
|
end else begin // supervisor mode
|
||||||
STATUS_SPIE <= #1 STATUS_SIE;
|
STATUS_SPIE <= #1 STATUS_SIE;
|
||||||
STATUS_SIE <= #1 0;
|
STATUS_SIE <= #1 0;
|
||||||
STATUS_SPP <= #1 PrivilegeModeW[0];
|
STATUS_SPP <= #1 PrivilegeModeW[0];
|
||||||
end
|
end
|
||||||
end else if (mretM) begin // Privileged 3.1.6.1
|
end else if (mretM) begin // Privileged 3.1.6.1
|
||||||
STATUS_MIE <= #1 STATUS_MPIE; // restore global interrupt enable
|
STATUS_MIE <= #1 STATUS_MPIE; // restore global interrupt enable
|
||||||
STATUS_MPIE <= #1 1; //
|
STATUS_MPIE <= #1 1; //
|
||||||
STATUS_MPP <= #1 P.U_SUPPORTED ? P.U_MODE : P.M_MODE; // set MPP to lowest supported privilege level
|
STATUS_MPP <= #1 P.U_SUPPORTED ? P.U_MODE : P.M_MODE; // set MPP to lowest supported privilege level
|
||||||
STATUS_MPRV_INT <= #1 STATUS_MPRV_INT & (STATUS_MPP == P.M_MODE); // page 21 of privileged spec.
|
STATUS_MPRV_INT <= #1 STATUS_MPRV_INT & (STATUS_MPP == P.M_MODE); // page 21 of privileged spec.
|
||||||
end else if (sretM) begin
|
end else if (sretM) begin
|
||||||
STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable
|
STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable
|
||||||
STATUS_SPIE <= #1 P.S_SUPPORTED;
|
STATUS_SPIE <= #1 P.S_SUPPORTED;
|
||||||
STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs
|
STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs
|
||||||
STATUS_MPRV_INT <= #1 0; // always clear MPRV
|
STATUS_MPRV_INT <= #1 0; // always clear MPRV
|
||||||
end else if (WriteMSTATUSM) begin
|
end else if (WriteMSTATUSM) begin
|
||||||
STATUS_TSR_INT <= #1 CSRWriteValM[22];
|
STATUS_TSR_INT <= #1 CSRWriteValM[22];
|
||||||
STATUS_TW_INT <= #1 CSRWriteValM[21];
|
STATUS_TW_INT <= #1 CSRWriteValM[21];
|
||||||
STATUS_TVM_INT <= #1 CSRWriteValM[20];
|
STATUS_TVM_INT <= #1 CSRWriteValM[20];
|
||||||
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
||||||
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
||||||
STATUS_MPRV_INT <= #1 CSRWriteValM[17];
|
STATUS_MPRV_INT <= #1 CSRWriteValM[17];
|
||||||
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
||||||
STATUS_MPP <= #1 STATUS_MPP_NEXT;
|
STATUS_MPP <= #1 STATUS_MPP_NEXT;
|
||||||
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
||||||
STATUS_MPIE <= #1 CSRWriteValM[7];
|
STATUS_MPIE <= #1 CSRWriteValM[7];
|
||||||
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
||||||
STATUS_MIE <= #1 CSRWriteValM[3];
|
STATUS_MIE <= #1 CSRWriteValM[3];
|
||||||
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
||||||
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||||
STATUS_MBE <= #1 nextMBE;
|
STATUS_MBE <= #1 nextMBE;
|
||||||
STATUS_SBE <= #1 nextSBE;
|
STATUS_SBE <= #1 nextSBE;
|
||||||
// coverage off
|
// coverage off
|
||||||
// MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc
|
// MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc
|
||||||
end else if (WriteMSTATUSHM) begin
|
end else if (WriteMSTATUSHM) begin
|
||||||
STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED;
|
STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED;
|
||||||
STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||||
// coverage on
|
// coverage on
|
||||||
end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits
|
end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits
|
||||||
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
||||||
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
||||||
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
||||||
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
||||||
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
||||||
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
||||||
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||||
end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11;
|
end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -27,40 +27,40 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csru import cvw::*; #(parameter cvw_t P) (
|
module csru import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic InstrValidNotFlushedM,
|
input logic InstrValidNotFlushedM,
|
||||||
input logic CSRUWriteM,
|
input logic CSRUWriteM,
|
||||||
input logic [11:0] CSRAdrM,
|
input logic [11:0] CSRAdrM,
|
||||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
input logic [1:0] STATUS_FS,
|
input logic [1:0] STATUS_FS,
|
||||||
output logic [P.XLEN-1:0] CSRUReadValM,
|
output logic [P.XLEN-1:0] CSRUReadValM,
|
||||||
input logic [4:0] SetFflagsM,
|
input logic [4:0] SetFflagsM,
|
||||||
output logic [2:0] FRM_REGW,
|
output logic [2:0] FRM_REGW,
|
||||||
output logic WriteFRMM, WriteFFLAGSM,
|
output logic WriteFRMM, WriteFFLAGSM,
|
||||||
output logic IllegalCSRUAccessM
|
output logic IllegalCSRUAccessM
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam FFLAGS = 12'h001;
|
localparam FFLAGS = 12'h001;
|
||||||
localparam FRM = 12'h002;
|
localparam FRM = 12'h002;
|
||||||
localparam FCSR = 12'h003;
|
localparam FCSR = 12'h003;
|
||||||
|
|
||||||
logic [4:0] FFLAGS_REGW;
|
logic [4:0] FFLAGS_REGW;
|
||||||
logic [2:0] NextFRMM;
|
logic [2:0] NextFRMM;
|
||||||
logic [4:0] NextFFLAGSM;
|
logic [4:0] NextFFLAGSM;
|
||||||
logic SetOrWriteFFLAGSM;
|
logic SetOrWriteFFLAGSM;
|
||||||
|
|
||||||
// Write enables
|
// Write enables
|
||||||
assign WriteFRMM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FRM | CSRAdrM == FCSR);
|
assign WriteFRMM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FRM | CSRAdrM == FCSR);
|
||||||
assign WriteFFLAGSM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FFLAGS | CSRAdrM == FCSR);
|
assign WriteFFLAGSM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FFLAGS | CSRAdrM == FCSR);
|
||||||
|
|
||||||
// Write Values
|
// Write Values
|
||||||
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
||||||
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
|
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
|
||||||
assign SetOrWriteFFLAGSM = WriteFFLAGSM | (|SetFflagsM & InstrValidNotFlushedM);
|
assign SetOrWriteFFLAGSM = WriteFFLAGSM | (|SetFflagsM & InstrValidNotFlushedM);
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
|
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
|
||||||
flopenr #(5) FFLAGSreg(clk, reset, SetOrWriteFFLAGSM, NextFFLAGSM, FFLAGS_REGW);
|
flopenr #(5) FFLAGSreg(clk, reset, SetOrWriteFFLAGSM, NextFFLAGSM, FFLAGS_REGW);
|
||||||
|
|
||||||
// CSR Reads
|
// CSR Reads
|
||||||
always_comb begin
|
always_comb begin
|
||||||
|
@ -28,91 +28,90 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
module privileged import cvw::*; #(parameter cvw_t P) (
|
module privileged import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallD, StallE, StallM, StallW,
|
input logic StallD, StallE, StallM, StallW,
|
||||||
input logic FlushD, FlushE, FlushM, FlushW,
|
input logic FlushD, FlushE, FlushM, FlushW,
|
||||||
// CSR Reads and Writes, and values needed for traps
|
// CSR Reads and Writes, and values needed for traps
|
||||||
input logic CSRReadM, CSRWriteM, // Read or write CSRs
|
input logic CSRReadM, CSRWriteM, // Read or write CSRs
|
||||||
input logic [P.XLEN-1:0] SrcAM, // GPR register to write
|
input logic [P.XLEN-1:0] SrcAM, // GPR register to write
|
||||||
input logic [31:0] InstrM, // Instruction
|
input logic [31:0] InstrM, // Instruction
|
||||||
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||||
input logic [P.XLEN-1:0] IEUAdrM, // address from IEU
|
input logic [P.XLEN-1:0] IEUAdrM, // address from IEU
|
||||||
input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic
|
input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic
|
||||||
// control signals
|
// control signals
|
||||||
input logic InstrValidM, // Current instruction is valid (not flushed)
|
input logic InstrValidM, // Current instruction is valid (not flushed)
|
||||||
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
|
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
|
||||||
input logic PrivilegedM, // privileged instruction
|
input logic PrivilegedM, // privileged instruction
|
||||||
// processor events for performance counter logging
|
// processor events for performance counter logging
|
||||||
input logic FRegWriteM, // instruction will write floating-point registers
|
input logic FRegWriteM, // instruction will write floating-point registers
|
||||||
input logic LoadStallD, // load instruction is stalling
|
input logic LoadStallD, // load instruction is stalling
|
||||||
input logic StoreStallD, // store instruction is stalling
|
input logic StoreStallD, // store instruction is stalling
|
||||||
input logic ICacheStallF, // I cache stalled
|
input logic ICacheStallF, // I cache stalled
|
||||||
input logic DCacheStallM, // D cache stalled
|
input logic DCacheStallM, // D cache stalled
|
||||||
input logic BPDirPredWrongM, // branch predictor guessed wrong direction
|
input logic BPDirPredWrongM, // branch predictor guessed wrong direction
|
||||||
input logic BTAWrongM, // branch predictor guessed wrong target
|
input logic BTAWrongM, // branch predictor guessed wrong target
|
||||||
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
||||||
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
||||||
input logic BPWrongM, // branch predictor is wrong
|
input logic BPWrongM, // branch predictor is wrong
|
||||||
input logic [3:0] InstrClassM, // actual instruction class
|
input logic [3:0] InstrClassM, // actual instruction class
|
||||||
input logic DCacheMiss, // data cache miss
|
input logic DCacheMiss, // data cache miss
|
||||||
input logic DCacheAccess, // data cache accessed (hit or miss)
|
input logic DCacheAccess, // data cache accessed (hit or miss)
|
||||||
input logic ICacheMiss, // instruction cache miss
|
input logic ICacheMiss, // instruction cache miss
|
||||||
input logic ICacheAccess, // instruction cache access
|
input logic ICacheAccess, // instruction cache access
|
||||||
input logic DivBusyE, // integer divide busy
|
input logic DivBusyE, // integer divide busy
|
||||||
input logic FDivBusyE, // floating point divide busy
|
input logic FDivBusyE, // floating point divide busy
|
||||||
// fault sources
|
// fault sources
|
||||||
input logic InstrAccessFaultF, // instruction access fault
|
input logic InstrAccessFaultF, // instruction access fault
|
||||||
input logic LoadAccessFaultM, StoreAmoAccessFaultM, // load or store access fault
|
input logic LoadAccessFaultM, StoreAmoAccessFaultM, // load or store access fault
|
||||||
input logic HPTWInstrAccessFaultF, // hardware page table access fault while fetching instruction PTE
|
input logic HPTWInstrAccessFaultF, // hardware page table access fault while fetching instruction PTE
|
||||||
input logic InstrPageFaultF, // page faults
|
input logic InstrPageFaultF, // page faults
|
||||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults
|
input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults
|
||||||
input logic InstrMisalignedFaultM, // misaligned instruction fault
|
input logic InstrMisalignedFaultM, // misaligned instruction fault
|
||||||
input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault
|
input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault
|
||||||
input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU
|
input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU
|
||||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources
|
input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources
|
||||||
input logic [63:0] MTIME_CLINT, // timer value from CLINT
|
input logic [63:0] MTIME_CLINT, // timer value from CLINT
|
||||||
input logic [4:0] SetFflagsM, // set FCSR flags from FPU
|
input logic [4:0] SetFflagsM, // set FCSR flags from FPU
|
||||||
input logic SelHPTW, // HPTW in use. Causes system to use S-mode endianness for accesses
|
input logic SelHPTW, // HPTW in use. Causes system to use S-mode endianness for accesses
|
||||||
// CSR outputs
|
// CSR outputs
|
||||||
output logic [P.XLEN-1:0] CSRReadValW, // Value read from CSR
|
output logic [P.XLEN-1:0] CSRReadValW, // Value read from CSR
|
||||||
output logic [1:0] PrivilegeModeW, // current privilege mode
|
output logic [1:0] PrivilegeModeW, // current privilege mode
|
||||||
output logic [P.XLEN-1:0] SATP_REGW, // supervisor address translation register
|
output logic [P.XLEN-1:0] SATP_REGW, // supervisor address translation register
|
||||||
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // status register bits
|
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // status register bits
|
||||||
output logic [1:0] STATUS_MPP, STATUS_FS, // status register bits
|
output logic [1:0] STATUS_MPP, STATUS_FS, // status register bits
|
||||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration entries to MMU
|
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration entries to MMU
|
||||||
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU
|
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU
|
||||||
output logic [2:0] FRM_REGW, // FPU rounding mode
|
output logic [2:0] FRM_REGW, // FPU rounding mode
|
||||||
// PC logic output in privileged unit
|
// PC logic output in privileged unit
|
||||||
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
|
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
|
||||||
// control outputs
|
// control outputs
|
||||||
output logic RetM, TrapM, // return instruction, or trap
|
output logic RetM, TrapM, // return instruction, or trap
|
||||||
output logic sfencevmaM, // sfence.vma instruction
|
output logic sfencevmaM, // sfence.vma instruction
|
||||||
input logic InvalidateICacheM, // fence instruction
|
input logic InvalidateICacheM, // fence instruction
|
||||||
output logic BigEndianM, // Use big endian in current privilege mode
|
output logic BigEndianM, // Use big endian in current privilege mode
|
||||||
// Fault outputs
|
// Fault outputs
|
||||||
output logic BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire
|
output logic BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire
|
||||||
output logic wfiM, IntPendingM // Stall in Memory stage for WFI until interrupt pending or timeout
|
output logic wfiM, IntPendingM // Stall in Memory stage for WFI until interrupt pending or timeout
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [3:0] CauseM; // trap cause
|
logic [3:0] CauseM; // trap cause
|
||||||
logic [15:0] MEDELEG_REGW; // exception delegation CSR
|
logic [15:0] MEDELEG_REGW; // exception delegation CSR
|
||||||
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
|
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
|
||||||
logic sretM, mretM; // supervisor / machine return instruction
|
logic sretM, mretM; // supervisor / machine return instruction
|
||||||
logic IllegalCSRAccessM; // Illegal access to CSR
|
logic IllegalCSRAccessM; // Illegal access to CSR
|
||||||
logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage
|
logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage
|
||||||
logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage
|
logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage
|
||||||
logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages
|
logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages
|
||||||
logic IllegalInstrFaultM; // Illegal instruction fault
|
logic IllegalInstrFaultM; // Illegal instruction fault
|
||||||
logic STATUS_SPP, STATUS_TSR, STATUS_TW, STATUS_TVM; // Status bits needed within privileged unit
|
logic STATUS_SPP, STATUS_TSR, STATUS_TW, STATUS_TVM; // Status bits needed within privileged unit
|
||||||
logic STATUS_MIE, STATUS_SIE; // status bits: interrupt enables
|
logic STATUS_MIE, STATUS_SIE; // status bits: interrupt enables
|
||||||
logic [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
logic [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
||||||
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
||||||
logic DelegateM; // trap should be delegated
|
logic DelegateM; // trap should be delegated
|
||||||
logic InterruptM; // interrupt occuring
|
logic InterruptM; // interrupt occuring
|
||||||
logic ExceptionM; // Memory stage instruction caused a fault
|
logic ExceptionM; // Memory stage instruction caused a fault
|
||||||
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
||||||
|
|
||||||
|
|
||||||
// track the current privilege level
|
// track the current privilege level
|
||||||
privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
|
privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
|
||||||
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
|
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
|
||||||
@ -156,8 +155,3 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||||||
.InstrValidM, .CommittedM, .CommittedF,
|
.InstrValidM, .CommittedM, .CommittedF,
|
||||||
.TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM);
|
.TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,10 +43,10 @@ module privmode import cvw::*; #(parameter cvw_t P) (
|
|||||||
always_comb begin
|
always_comb begin
|
||||||
if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
||||||
if (P.S_SUPPORTED & DelegateM) NextPrivilegeModeM = P.S_MODE;
|
if (P.S_SUPPORTED & DelegateM) NextPrivilegeModeM = P.S_MODE;
|
||||||
else NextPrivilegeModeM = P.M_MODE;
|
else NextPrivilegeModeM = P.M_MODE;
|
||||||
end else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
end else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
||||||
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
||||||
else NextPrivilegeModeM = PrivilegeModeW;
|
else NextPrivilegeModeM = PrivilegeModeW;
|
||||||
end
|
end
|
||||||
|
|
||||||
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, P.M_MODE, PrivilegeModeW);
|
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, P.M_MODE, PrivilegeModeW);
|
||||||
|
@ -63,13 +63,13 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
assign MIntGlobalEnM = (PrivilegeModeW != P.M_MODE) | STATUS_MIE; // if M ints enabled or lower priv 3.1.9
|
assign MIntGlobalEnM = (PrivilegeModeW != P.M_MODE) | STATUS_MIE; // if M ints enabled or lower priv 3.1.9
|
||||||
assign SIntGlobalEnM = (PrivilegeModeW == P.U_MODE) | ((PrivilegeModeW == P.S_MODE) & STATUS_SIE); // if in lower priv mode, or if S ints enabled and not in higher priv mode 3.1.9
|
assign SIntGlobalEnM = (PrivilegeModeW == P.U_MODE) | ((PrivilegeModeW == P.S_MODE) & STATUS_SIE); // if in lower priv mode, or if S ints enabled and not in higher priv mode 3.1.9
|
||||||
assign PendingIntsM = MIP_REGW & MIE_REGW;
|
assign PendingIntsM = MIP_REGW & MIE_REGW;
|
||||||
assign IntPendingM = |PendingIntsM;
|
assign IntPendingM = |PendingIntsM;
|
||||||
assign Committed = CommittedM | CommittedF;
|
assign Committed = CommittedM | CommittedF;
|
||||||
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
||||||
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
||||||
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
|
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
|
||||||
assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
|
assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
|
||||||
(PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);
|
(PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
@ -88,7 +88,7 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
|||||||
LoadAccessFaultM | StoreAmoAccessFaultM;
|
LoadAccessFaultM | StoreAmoAccessFaultM;
|
||||||
// coverage on
|
// coverage on
|
||||||
assign TrapM = ExceptionM | InterruptM;
|
assign TrapM = ExceptionM | InterruptM;
|
||||||
assign RetM = mretM | sretM;
|
assign RetM = mretM | sretM;
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// Cause priority defined in table 3.7 of 20190608 privileged spec
|
// Cause priority defined in table 3.7 of 20190608 privileged spec
|
||||||
|
@ -27,27 +27,27 @@
|
|||||||
|
|
||||||
module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
||||||
parameter PERIPHS = 2) (
|
parameter PERIPHS = 2) (
|
||||||
input logic HCLK, HRESETn,
|
input logic HCLK, HRESETn,
|
||||||
input logic [PERIPHS-1:0] HSEL,
|
input logic [PERIPHS-1:0] HSEL,
|
||||||
input logic [P.PA_BITS-1:0] HADDR,
|
input logic [P.PA_BITS-1:0] HADDR,
|
||||||
input logic [P.XLEN-1:0] HWDATA,
|
input logic [P.XLEN-1:0] HWDATA,
|
||||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||||
input logic HWRITE,
|
input logic HWRITE,
|
||||||
input logic [1:0] HTRANS,
|
input logic [1:0] HTRANS,
|
||||||
input logic HREADY,
|
input logic HREADY,
|
||||||
// input logic [3:0] HPROT, // not used
|
// input logic [3:0] HPROT, // not used
|
||||||
output logic [P.XLEN-1:0] HRDATA,
|
output logic [P.XLEN-1:0] HRDATA,
|
||||||
output logic HRESP, HREADYOUT,
|
output logic HRESP, HREADYOUT,
|
||||||
output logic PCLK, PRESETn,
|
output logic PCLK, PRESETn,
|
||||||
output logic [PERIPHS-1:0] PSEL,
|
output logic [PERIPHS-1:0] PSEL,
|
||||||
output logic PWRITE,
|
output logic PWRITE,
|
||||||
output logic PENABLE,
|
output logic PENABLE,
|
||||||
output logic [31:0] PADDR,
|
output logic [31:0] PADDR,
|
||||||
output logic [P.XLEN-1:0] PWDATA,
|
output logic [P.XLEN-1:0] PWDATA,
|
||||||
// output logic [2:0] PPROT, // not used
|
// output logic [2:0] PPROT, // not used
|
||||||
output logic [P.XLEN/8-1:0] PSTRB,
|
output logic [P.XLEN/8-1:0] PSTRB,
|
||||||
// output logic PWAKEUP // not used
|
// output logic PWAKEUP // not used
|
||||||
input logic [PERIPHS-1:0] PREADY,
|
input logic [PERIPHS-1:0] PREADY,
|
||||||
input var [PERIPHS-1:0][P.XLEN-1:0] PRDATA
|
input var [PERIPHS-1:0][P.XLEN-1:0] PRDATA
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -56,15 +56,15 @@ module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
|||||||
logic PREADYOUT;
|
logic PREADYOUT;
|
||||||
|
|
||||||
// convert AHB to APB signals
|
// convert AHB to APB signals
|
||||||
assign PCLK = HCLK;
|
assign PCLK = HCLK;
|
||||||
assign PRESETn = HRESETn;
|
assign PRESETn = HRESETn;
|
||||||
|
|
||||||
// identify start of a transaction
|
// identify start of a transaction
|
||||||
assign initTrans = HTRANS[1] & HREADY; // start a transaction when the bus is ready and an active transaction is requested
|
assign initTrans = HTRANS[1] & HREADY; // start a transaction when the bus is ready and an active transaction is requested
|
||||||
assign initTransSel = initTrans & |HSEL; // capture data and address if any of the peripherals are selected
|
assign initTransSel = initTrans & |HSEL; // capture data and address if any of the peripherals are selected
|
||||||
|
|
||||||
// delay AHB Address phase signals to align with AHB Data phase because APB expects them at the same time
|
// delay AHB Address phase signals to align with AHB Data phase because APB expects them at the same time
|
||||||
flopen #(32) addrreg(HCLK, HREADY, HADDR[31:0], PADDR);
|
flopen #(32) addrreg(HCLK, HREADY, HADDR[31:0], PADDR);
|
||||||
flopenr #(1) writereg(HCLK, ~HRESETn, HREADY, HWRITE, PWRITE);
|
flopenr #(1) writereg(HCLK, ~HRESETn, HREADY, HWRITE, PWRITE);
|
||||||
flopenr #(PERIPHS) selreg(HCLK, ~HRESETn, HREADY, HSEL & {PERIPHS{initTrans}}, PSEL);
|
flopenr #(PERIPHS) selreg(HCLK, ~HRESETn, HREADY, HSEL & {PERIPHS{initTrans}}, PSEL);
|
||||||
// PPROT[2:0] = {Data/InstrB, Secure, Privileged};
|
// PPROT[2:0] = {Data/InstrB, Secure, Privileged};
|
||||||
@ -73,7 +73,7 @@ module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
// AHB Data phase signal doesn't need delay. Note that they are guaranteed to remain stable until READY is asserted
|
// AHB Data phase signal doesn't need delay. Note that they are guaranteed to remain stable until READY is asserted
|
||||||
assign PWDATA = HWDATA;
|
assign PWDATA = HWDATA;
|
||||||
assign PSTRB = HWSTRB;
|
assign PSTRB = HWSTRB;
|
||||||
|
|
||||||
// enable logic: goes high a cycle after initTrans, then back low on cycle after desired PREADY is asserted
|
// enable logic: goes high a cycle after initTrans, then back low on cycle after desired PREADY is asserted
|
||||||
// cycle1: AHB puts HADDR, HWRITE, HSEL on bus. initTrans is 1, and these are captured
|
// cycle1: AHB puts HADDR, HWRITE, HSEL on bus. initTrans is 1, and these are captured
|
||||||
@ -103,4 +103,3 @@ assign HREADYOUT = PREADYOUT & ~initTransSelD; // don't raise HREADYOUT before a
|
|||||||
// resp logic
|
// resp logic
|
||||||
assign HRESP = 0; // bridge never indicates errors
|
assign HRESP = 0; // bridge never indicates errors
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -31,11 +31,11 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
input logic PCLK, PRESETn,
|
input logic PCLK, PRESETn,
|
||||||
input logic PSEL,
|
input logic PSEL,
|
||||||
input logic [15:0] PADDR,
|
input logic [15:0] PADDR,
|
||||||
input logic [P.XLEN-1:0] PWDATA,
|
input logic [P.XLEN-1:0] PWDATA,
|
||||||
input logic [P.XLEN/8-1:0] PSTRB,
|
input logic [P.XLEN/8-1:0] PSTRB,
|
||||||
input logic PWRITE,
|
input logic PWRITE,
|
||||||
input logic PENABLE,
|
input logic PENABLE,
|
||||||
output logic [P.XLEN-1:0] PRDATA,
|
output logic [P.XLEN-1:0] PRDATA,
|
||||||
output logic PREADY,
|
output logic PREADY,
|
||||||
output logic [63:0] MTIME,
|
output logic [63:0] MTIME,
|
||||||
output logic MTimerInt, MSwInt
|
output logic MTimerInt, MSwInt
|
||||||
@ -48,11 +48,11 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
integer i, j;
|
integer i, j;
|
||||||
|
|
||||||
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||||
assign PREADY = 1'b1; // CLINT never takes >1 cycle to respond
|
assign PREADY = 1'b1; // CLINT never takes >1 cycle to respond
|
||||||
|
|
||||||
// word aligned reads
|
// word aligned reads
|
||||||
if (P.XLEN==64) assign #2 entry = {PADDR[15:3], 3'b000};
|
if (P.XLEN==64) assign #2 entry = {PADDR[15:3], 3'b000};
|
||||||
else assign #2 entry = {PADDR[15:2], 2'b00};
|
else assign #2 entry = {PADDR[15:2], 2'b00};
|
||||||
|
|
||||||
// DH 2/20/21: Eventually allow MTIME to run off a separate clock
|
// DH 2/20/21: Eventually allow MTIME to run off a separate clock
|
||||||
// This will require synchronizing MTIME to the system clock
|
// This will require synchronizing MTIME to the system clock
|
||||||
@ -150,36 +150,36 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module timeregsync import cvw::*; #(parameter cvw_t P) (
|
module timeregsync import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, resetn,
|
input logic clk, resetn,
|
||||||
input logic we0, we1,
|
input logic we0, we1,
|
||||||
input logic [P.XLEN-1:0] wd,
|
input logic [P.XLEN-1:0] wd,
|
||||||
output logic [63:0] q);
|
output logic [63:0] q);
|
||||||
|
|
||||||
if (P.XLEN==64)
|
if (P.XLEN==64)
|
||||||
always_ff @(posedge clk or negedge resetn)
|
always_ff @(posedge clk or negedge resetn)
|
||||||
if (~resetn) q <= 0;
|
if (~resetn) q <= 0;
|
||||||
else if (we0) q <= wd;
|
else if (we0) q <= wd;
|
||||||
else q <= q + 1;
|
else q <= q + 1;
|
||||||
else
|
else
|
||||||
always_ff @(posedge clk or negedge resetn)
|
always_ff @(posedge clk or negedge resetn)
|
||||||
if (~resetn) q <= 0;
|
if (~resetn) q <= 0;
|
||||||
else if (we0) q[31:0] <= wd;
|
else if (we0) q[31:0] <= wd;
|
||||||
else if (we1) q[63:32] <= wd;
|
else if (we1) q[63:32] <= wd;
|
||||||
else q <= q + 1;
|
else q <= q + 1;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module timereg import cvw::*; #(parameter cvw_t P) (
|
module timereg import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic PCLK, PRESETn, TIMECLK,
|
input logic PCLK, PRESETn, TIMECLK,
|
||||||
input logic we0, we1,
|
input logic we0, we1,
|
||||||
input logic [P.XLEN-1:0] PWDATA,
|
input logic [P.XLEN-1:0] PWDATA,
|
||||||
output logic [63:0] MTIME,
|
output logic [63:0] MTIME,
|
||||||
output logic done);
|
output logic done);
|
||||||
|
|
||||||
// if (P.TIMEBASE_SYNC) begin:timereg // use PCLK for MTIME
|
// if (P.TIMEBASE_SYNC) begin:timereg // use PCLK for MTIME
|
||||||
if (1) begin:timereg // use PCLK for MTIME
|
if (1) begin:timereg // use PCLK for MTIME
|
||||||
timregsync timeregsync(.clk(PCLK), .resetn(PRESETn), .we0, .we1, .wd(PWDATA), .q(MTIME));
|
timregsync timeregsync(.clk(PCLK), .resetn(PRESETn), .we0, .we1, .wd(PWDATA), .q(MTIME));
|
||||||
assign done = 1; // immediately completes
|
assign done = 1; // immediately completes
|
||||||
end else begin // use asynchronous TIMECLK
|
end else begin // use asynchronous TIMECLK
|
||||||
// TIME counter runs on TIMECLK but bus interface runs on PCLK
|
// TIME counter runs on TIMECLK but bus interface runs on PCLK
|
||||||
// Need to synchronize reads and writes
|
// Need to synchronize reads and writes
|
||||||
// This is subtle because synchronizing a binary counter on a per-bit basis could give a mix of old and new bits
|
// This is subtle because synchronizing a binary counter on a per-bit basis could give a mix of old and new bits
|
||||||
|
@ -29,78 +29,78 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic PCLK, PRESETn,
|
input logic PCLK, PRESETn,
|
||||||
input logic PSEL,
|
input logic PSEL,
|
||||||
input logic [7:0] PADDR,
|
input logic [7:0] PADDR,
|
||||||
input logic [P.XLEN-1:0] PWDATA,
|
input logic [P.XLEN-1:0] PWDATA,
|
||||||
input logic [P.XLEN/8-1:0] PSTRB,
|
input logic [P.XLEN/8-1:0] PSTRB,
|
||||||
input logic PWRITE,
|
input logic PWRITE,
|
||||||
input logic PENABLE,
|
input logic PENABLE,
|
||||||
output logic [P.XLEN-1:0] PRDATA,
|
output logic [P.XLEN-1:0] PRDATA,
|
||||||
output logic PREADY,
|
output logic PREADY,
|
||||||
input logic [31:0] iof0, iof1,
|
input logic [31:0] iof0, iof1,
|
||||||
input logic [31:0] GPIOIN,
|
input logic [31:0] GPIOIN,
|
||||||
output logic [31:0] GPIOOUT, GPIOEN,
|
output logic [31:0] GPIOOUT, GPIOEN,
|
||||||
output logic GPIOIntr
|
output logic GPIOIntr
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [31:0] input0d, input1d, input2d, input3d;
|
logic [31:0] input0d, input1d, input2d, input3d;
|
||||||
logic [31:0] input_val, input_en, output_en, output_val;
|
logic [31:0] input_val, input_en, output_en, output_val;
|
||||||
logic [31:0] rise_ie, rise_ip, fall_ie, fall_ip, high_ie, high_ip, low_ie, low_ip;
|
logic [31:0] rise_ie, rise_ip, fall_ie, fall_ip, high_ie, high_ip, low_ie, low_ip;
|
||||||
logic [31:0] out_xor, iof_en, iof_sel, iof_out, gpio_out;
|
logic [31:0] out_xor, iof_en, iof_sel, iof_out, gpio_out;
|
||||||
logic [7:0] entry;
|
logic [7:0] entry;
|
||||||
logic [31:0] Din, Dout;
|
logic [31:0] Din, Dout;
|
||||||
logic memwrite;
|
logic memwrite;
|
||||||
|
|
||||||
// APB I/O
|
// APB I/O
|
||||||
assign entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
assign entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
||||||
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||||
assign PREADY = 1'b1; // GPIO never takes >1 cycle to respond
|
assign PREADY = 1'b1; // GPIO never takes >1 cycle to respond
|
||||||
|
|
||||||
// account for subword read/write circuitry
|
// account for subword read/write circuitry
|
||||||
// -- Note GPIO registers are 32 bits no matter what; access them with LW SW.
|
// -- Note GPIO registers are 32 bits no matter what; access them with LW SW.
|
||||||
// (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported")
|
// (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported")
|
||||||
if (P.XLEN == 64) begin
|
if (P.XLEN == 64) begin
|
||||||
assign Din = entry[2] ? PWDATA[63:32] : PWDATA[31:0];
|
assign Din = entry[2] ? PWDATA[63:32] : PWDATA[31:0];
|
||||||
assign PRDATA = entry[2] ? {Dout,32'b0} : {32'b0,Dout};
|
assign PRDATA = entry[2] ? {Dout,32'b0} : {32'b0,Dout};
|
||||||
end else begin // 32-bit
|
end else begin // 32-bit
|
||||||
assign Din = PWDATA[31:0];
|
assign Din = PWDATA[31:0];
|
||||||
assign PRDATA = Dout;
|
assign PRDATA = Dout;
|
||||||
end
|
end
|
||||||
|
|
||||||
// register access
|
// register access
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if (~PRESETn) begin // asynch reset
|
if (~PRESETn) begin // asynch reset
|
||||||
input_en <= 0;
|
input_en <= 0;
|
||||||
output_en <= 0;
|
output_en <= 0;
|
||||||
// *** synch reset not yet implemented [DH: can we delete this comment? Check if a sync reset is required]
|
// *** synch reset not yet implemented [DH: can we delete this comment? Check if a sync reset is required]
|
||||||
output_val <= #1 0;
|
output_val <= #1 0;
|
||||||
rise_ie <= #1 0;
|
rise_ie <= #1 0;
|
||||||
rise_ip <= #1 0;
|
rise_ip <= #1 0;
|
||||||
fall_ie <= #1 0;
|
fall_ie <= #1 0;
|
||||||
fall_ip <= #1 0;
|
fall_ip <= #1 0;
|
||||||
high_ie <= #1 0;
|
high_ie <= #1 0;
|
||||||
high_ip <= #1 0;
|
high_ip <= #1 0;
|
||||||
low_ie <= #1 0;
|
low_ie <= #1 0;
|
||||||
low_ip <= #1 0;
|
low_ip <= #1 0;
|
||||||
iof_en <= #1 0;
|
iof_en <= #1 0;
|
||||||
iof_sel <= #1 0;
|
iof_sel <= #1 0;
|
||||||
out_xor <= #1 0;
|
out_xor <= #1 0;
|
||||||
end else begin // writes
|
end else begin // writes
|
||||||
// According to FE310 spec: Once the interrupt is pending, it will remain set until a 1 is written to the *_ip register at that bit.
|
// According to FE310 spec: Once the interrupt is pending, it will remain set until a 1 is written to the *_ip register at that bit.
|
||||||
/* verilator lint_off CASEINCOMPLETE */
|
/* verilator lint_off CASEINCOMPLETE */
|
||||||
if (memwrite)
|
if (memwrite)
|
||||||
case(entry)
|
case(entry)
|
||||||
8'h04: input_en <= #1 Din;
|
8'h04: input_en <= #1 Din;
|
||||||
8'h08: output_en <= #1 Din;
|
8'h08: output_en <= #1 Din;
|
||||||
8'h0C: output_val <= #1 Din;
|
8'h0C: output_val <= #1 Din;
|
||||||
8'h18: rise_ie <= #1 Din;
|
8'h18: rise_ie <= #1 Din;
|
||||||
8'h20: fall_ie <= #1 Din;
|
8'h20: fall_ie <= #1 Din;
|
||||||
8'h28: high_ie <= #1 Din;
|
8'h28: high_ie <= #1 Din;
|
||||||
8'h30: low_ie <= #1 Din;
|
8'h30: low_ie <= #1 Din;
|
||||||
8'h38: iof_en <= #1 Din;
|
8'h38: iof_en <= #1 Din;
|
||||||
8'h3C: iof_sel <= #1 Din;
|
8'h3C: iof_sel <= #1 Din;
|
||||||
8'h40: out_xor <= #1 Din;
|
8'h40: out_xor <= #1 Din;
|
||||||
endcase
|
endcase
|
||||||
/* verilator lint_on CASEINCOMPLETE */
|
/* verilator lint_on CASEINCOMPLETE */
|
||||||
|
|
||||||
@ -115,21 +115,21 @@ module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
else low_ip <= low_ip | ~input3d;
|
else low_ip <= low_ip | ~input3d;
|
||||||
|
|
||||||
case(entry) // flop to sample inputs
|
case(entry) // flop to sample inputs
|
||||||
8'h00: Dout <= #1 input_val;
|
8'h00: Dout <= #1 input_val;
|
||||||
8'h04: Dout <= #1 input_en;
|
8'h04: Dout <= #1 input_en;
|
||||||
8'h08: Dout <= #1 output_en;
|
8'h08: Dout <= #1 output_en;
|
||||||
8'h0C: Dout <= #1 output_val;
|
8'h0C: Dout <= #1 output_val;
|
||||||
8'h18: Dout <= #1 rise_ie;
|
8'h18: Dout <= #1 rise_ie;
|
||||||
8'h1C: Dout <= #1 rise_ip;
|
8'h1C: Dout <= #1 rise_ip;
|
||||||
8'h20: Dout <= #1 fall_ie;
|
8'h20: Dout <= #1 fall_ie;
|
||||||
8'h24: Dout <= #1 fall_ip;
|
8'h24: Dout <= #1 fall_ip;
|
||||||
8'h28: Dout <= #1 high_ie;
|
8'h28: Dout <= #1 high_ie;
|
||||||
8'h2C: Dout <= #1 high_ip;
|
8'h2C: Dout <= #1 high_ip;
|
||||||
8'h30: Dout <= #1 low_ie;
|
8'h30: Dout <= #1 low_ie;
|
||||||
8'h34: Dout <= #1 low_ip;
|
8'h34: Dout <= #1 low_ip;
|
||||||
8'h38: Dout <= #1 iof_en;
|
8'h38: Dout <= #1 iof_en;
|
||||||
8'h3C: Dout <= #1 iof_sel;
|
8'h3C: Dout <= #1 iof_sel;
|
||||||
8'h40: Dout <= #1 out_xor;
|
8'h40: Dout <= #1 out_xor;
|
||||||
default: Dout <= #1 0;
|
default: Dout <= #1 0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
@ -137,18 +137,17 @@ module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
// chip i/o
|
// chip i/o
|
||||||
// connect OUT to IN for loopback testing
|
// connect OUT to IN for loopback testing
|
||||||
if (P.GPIO_LOOPBACK_TEST) assign input0d = ((output_en & GPIOOUT) | (~output_en & GPIOIN)) & input_en;
|
if (P.GPIO_LOOPBACK_TEST) assign input0d = ((output_en & GPIOOUT) | (~output_en & GPIOIN)) & input_en;
|
||||||
else assign input0d = GPIOIN & input_en;
|
else assign input0d = GPIOIN & input_en;
|
||||||
|
|
||||||
// synchroninzer for inputs
|
// synchroninzer for inputs
|
||||||
flop #(32) sync1(PCLK,input0d,input1d);
|
flop #(32) sync1(PCLK,input0d,input1d);
|
||||||
flop #(32) sync2(PCLK,input1d,input2d);
|
flop #(32) sync2(PCLK,input1d,input2d);
|
||||||
flop #(32) sync3(PCLK,input2d,input3d);
|
flop #(32) sync3(PCLK,input2d,input3d);
|
||||||
assign input_val = input3d;
|
assign input_val = input3d;
|
||||||
assign iof_out = iof_sel & iof1 | ~iof_sel & iof0; // per-bit mux between iof1 and iof0
|
assign iof_out = iof_sel & iof1 | ~iof_sel & iof0; // per-bit mux between iof1 and iof0
|
||||||
assign gpio_out = iof_en & iof_out | ~iof_en & output_val; // per-bit mux between IOF and output_val
|
assign gpio_out = iof_en & iof_out | ~iof_en & output_val; // per-bit mux between IOF and output_val
|
||||||
assign GPIOOUT = gpio_out ^ out_xor; // per-bit flip output polarity
|
assign GPIOOUT = gpio_out ^ out_xor; // per-bit flip output polarity
|
||||||
assign GPIOEN = output_en;
|
assign GPIOEN = output_en;
|
||||||
|
|
||||||
assign GPIOIntr = |{(rise_ip & rise_ie),(fall_ip & fall_ie),(high_ip & high_ie),(low_ip & low_ie)};
|
assign GPIOIntr = |{(rise_ip & rise_ie),(fall_ip & fall_ie),(high_ip & high_ie),(low_ip & low_ie)};
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -41,22 +41,22 @@
|
|||||||
// hardcoded to 2 contexts for now; later upgrade to arbitrary (up to 15872) contexts
|
// hardcoded to 2 contexts for now; later upgrade to arbitrary (up to 15872) contexts
|
||||||
|
|
||||||
module plic_apb import cvw::*; #(parameter cvw_t P) (
|
module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic PCLK, PRESETn,
|
input logic PCLK, PRESETn,
|
||||||
input logic PSEL,
|
input logic PSEL,
|
||||||
input logic [27:0] PADDR,
|
input logic [27:0] PADDR,
|
||||||
input logic [P.XLEN-1:0] PWDATA,
|
input logic [P.XLEN-1:0] PWDATA,
|
||||||
input logic [P.XLEN/8-1:0] PSTRB,
|
input logic [P.XLEN/8-1:0] PSTRB,
|
||||||
input logic PWRITE,
|
input logic PWRITE,
|
||||||
input logic PENABLE,
|
input logic PENABLE,
|
||||||
output logic [P.XLEN-1:0] PRDATA,
|
output logic [P.XLEN-1:0] PRDATA,
|
||||||
output logic PREADY,
|
output logic PREADY,
|
||||||
input logic UARTIntr,GPIOIntr,
|
input logic UARTIntr,GPIOIntr,
|
||||||
output logic MExtInt, SExtInt
|
output logic MExtInt, SExtInt
|
||||||
);
|
);
|
||||||
|
|
||||||
logic memwrite, memread;
|
logic memwrite, memread;
|
||||||
logic [23:0] entry;
|
logic [23:0] entry;
|
||||||
logic [31:0] Din, Dout;
|
logic [31:0] Din, Dout;
|
||||||
|
|
||||||
// context-independent signals
|
// context-independent signals
|
||||||
logic [`N:1] requests;
|
logic [`N:1] requests;
|
||||||
@ -78,9 +78,9 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
// =======
|
// =======
|
||||||
|
|
||||||
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||||
assign memread = ~PWRITE & PSEL; // read at start of access phase. PENABLE hasn't set up before this
|
assign memread = ~PWRITE & PSEL; // read at start of access phase. PENABLE hasn't set up before this
|
||||||
assign PREADY = 1'b1; // PLIC never takes >1 cycle to respond
|
assign PREADY = 1'b1; // PLIC never takes >1 cycle to respond
|
||||||
assign entry = {PADDR[23:2],2'b0};
|
assign entry = {PADDR[23:2],2'b0};
|
||||||
|
|
||||||
// account for subword read/write circuitry
|
// account for subword read/write circuitry
|
||||||
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW.
|
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW.
|
||||||
@ -97,6 +97,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
// ==================
|
// ==================
|
||||||
// Register Interface
|
// Register Interface
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
always @(posedge PCLK) begin
|
always @(posedge PCLK) begin
|
||||||
// resetting
|
// resetting
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
@ -110,19 +111,19 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
casez(entry)
|
casez(entry)
|
||||||
24'h0000??: intPriority[entry[7:2]] <= #1 Din[2:0];
|
24'h0000??: intPriority[entry[7:2]] <= #1 Din[2:0];
|
||||||
`ifdef PLIC_NUM_SRC_LT_32 // eventually switch to a generate for loop so as to deprecate PLIC_NUM_SRC_LT_32 and allow up to 1023 sources
|
`ifdef PLIC_NUM_SRC_LT_32 // eventually switch to a generate for loop so as to deprecate PLIC_NUM_SRC_LT_32 and allow up to 1023 sources
|
||||||
24'h002000: intEn[0][`N:1] <= #1 Din[`N:1];
|
24'h002000: intEn[0][`N:1] <= #1 Din[`N:1];
|
||||||
24'h002080: intEn[1][`N:1] <= #1 Din[`N:1];
|
24'h002080: intEn[1][`N:1] <= #1 Din[`N:1];
|
||||||
`endif
|
`endif
|
||||||
`ifndef PLIC_NUM_SRC_LT_32
|
`ifndef PLIC_NUM_SRC_LT_32
|
||||||
24'h002000: intEn[0][31:1] <= #1 Din[31:1];
|
24'h002000: intEn[0][31:1] <= #1 Din[31:1];
|
||||||
24'h002004: intEn[0][`N:32] <= #1 Din[31:0];
|
24'h002004: intEn[0][`N:32] <= #1 Din[31:0];
|
||||||
24'h002080: intEn[1][31:1] <= #1 Din[31:1];
|
24'h002080: intEn[1][31:1] <= #1 Din[31:1];
|
||||||
24'h002084: intEn[1][`N:32] <= #1 Din[31:0];
|
24'h002084: intEn[1][`N:32] <= #1 Din[31:0];
|
||||||
`endif
|
`endif
|
||||||
24'h200000: intThreshold[0] <= #1 Din[2:0];
|
24'h200000: intThreshold[0] <= #1 Din[2:0];
|
||||||
24'h200004: intInProgress <= #1 intInProgress & ~({{`N-1{1'b0}}, 1'b1} << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
24'h200004: intInProgress <= #1 intInProgress & ~({{`N-1{1'b0}}, 1'b1} << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||||
24'h201000: intThreshold[1] <= #1 Din[2:0];
|
24'h201000: intThreshold[1] <= #1 Din[2:0];
|
||||||
24'h201004: intInProgress <= #1 intInProgress & ~({{`N-1{1'b0}}, 1'b1} << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
24'h201004: intInProgress <= #1 intInProgress & ~({{`N-1{1'b0}}, 1'b1} << (Din[5:0]-1)); // lower "InProgress" to signify completion
|
||||||
endcase
|
endcase
|
||||||
// Read synchronously because a read can have side effect of changing intInProgress
|
// Read synchronously because a read can have side effect of changing intInProgress
|
||||||
if (memread) begin
|
if (memread) begin
|
||||||
@ -245,4 +246,3 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign MExtInt = |(threshMask[0] & priorities_with_irqs[0]);
|
assign MExtInt = |(threshMask[0] & priorities_with_irqs[0]);
|
||||||
assign SExtInt = |(threshMask[1] & priorities_with_irqs[1]);
|
assign SExtInt = |(threshMask[1] & priorities_with_irqs[1]);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -30,33 +30,33 @@
|
|||||||
|
|
||||||
module ram_ahb import cvw::*; #(parameter cvw_t P,
|
module ram_ahb import cvw::*; #(parameter cvw_t P,
|
||||||
parameter BASE=0, RANGE = 65535) (
|
parameter BASE=0, RANGE = 65535) (
|
||||||
input logic HCLK, HRESETn,
|
input logic HCLK, HRESETn,
|
||||||
input logic HSELRam,
|
input logic HSELRam,
|
||||||
input logic [P.PA_BITS-1:0] HADDR,
|
input logic [P.PA_BITS-1:0] HADDR,
|
||||||
input logic HWRITE,
|
input logic HWRITE,
|
||||||
input logic HREADY,
|
input logic HREADY,
|
||||||
input logic [1:0] HTRANS,
|
input logic [1:0] HTRANS,
|
||||||
input logic [P.XLEN-1:0] HWDATA,
|
input logic [P.XLEN-1:0] HWDATA,
|
||||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||||
output logic [P.XLEN-1:0] HREADRam,
|
output logic [P.XLEN-1:0] HREADRam,
|
||||||
output logic HRESPRam, HREADYRam
|
output logic HRESPRam, HREADYRam
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
||||||
localparam OFFSET = $clog2(P.XLEN/8);
|
localparam OFFSET = $clog2(P.XLEN/8);
|
||||||
|
|
||||||
logic [P.XLEN/8-1:0] ByteMask;
|
logic [P.XLEN/8-1:0] ByteMask;
|
||||||
logic [P.PA_BITS-1:0] HADDRD, RamAddr;
|
logic [P.PA_BITS-1:0] HADDRD, RamAddr;
|
||||||
logic initTrans;
|
logic initTrans;
|
||||||
logic memwrite, memwriteD, memread;
|
logic memwrite, memwriteD, memread;
|
||||||
logic nextHREADYRam;
|
logic nextHREADYRam;
|
||||||
logic DelayReady;
|
logic DelayReady;
|
||||||
|
|
||||||
// a new AHB transactions starts when HTRANS requests a transaction,
|
// a new AHB transactions starts when HTRANS requests a transaction,
|
||||||
// the peripheral is selected, and the previous transaction is completing
|
// the peripheral is selected, and the previous transaction is completing
|
||||||
assign initTrans = HREADY & HSELRam & HTRANS[1] ;
|
assign initTrans = HREADY & HSELRam & HTRANS[1] ;
|
||||||
assign memwrite = initTrans & HWRITE;
|
assign memwrite = initTrans & HWRITE;
|
||||||
assign memread = initTrans & ~HWRITE;
|
assign memread = initTrans & ~HWRITE;
|
||||||
|
|
||||||
flopenr #(1) memwritereg(HCLK, ~HRESETn, HREADY, memwrite, memwriteD);
|
flopenr #(1) memwritereg(HCLK, ~HRESETn, HREADY, memwrite, memwriteD);
|
||||||
flopenr #(P.PA_BITS) haddrreg(HCLK, ~HRESETn, HREADY, HADDR, HADDRD);
|
flopenr #(P.PA_BITS) haddrreg(HCLK, ~HRESETn, HREADY, HADDR, HADDRD);
|
||||||
@ -74,7 +74,6 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
|
|||||||
ram1p1rwbe #(.DEPTH(RANGE/8), .WIDTH(P.XLEN)) memory(.clk(HCLK), .ce(1'b1),
|
ram1p1rwbe #(.DEPTH(RANGE/8), .WIDTH(P.XLEN)) memory(.clk(HCLK), .ce(1'b1),
|
||||||
.addr(RamAddr[ADDR_WIDTH+OFFSET-1:OFFSET]), .we(memwriteD), .din(HWDATA), .bwe(HWSTRB), .dout(HREADRam));
|
.addr(RamAddr[ADDR_WIDTH+OFFSET-1:OFFSET]), .we(memwriteD), .din(HWDATA), .bwe(HWSTRB), .dout(HREADRam));
|
||||||
|
|
||||||
|
|
||||||
// use this to add arbitrary latency to ram. Helps test AHB controller correctness
|
// use this to add arbitrary latency to ram. Helps test AHB controller correctness
|
||||||
if(`RAM_LATENCY > 0) begin
|
if(`RAM_LATENCY > 0) begin
|
||||||
logic [7:0] NextCycle, Cycle;
|
logic [7:0] NextCycle, Cycle;
|
||||||
@ -89,15 +88,15 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
always_ff @(posedge HCLK)
|
always_ff @(posedge HCLK)
|
||||||
if (~HRESETn) CurrState <= #1 READY;
|
if (~HRESETn) CurrState <= #1 READY;
|
||||||
else CurrState <= #1 NextState;
|
else CurrState <= #1 NextState;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case(CurrState)
|
case(CurrState)
|
||||||
READY: if(initTrans & ~CycleFlag) NextState = DELAY;
|
READY: if(initTrans & ~CycleFlag) NextState = DELAY;
|
||||||
else NextState = READY;
|
else NextState = READY;
|
||||||
DELAY: if(CycleFlag) NextState = READY;
|
DELAY: if(CycleFlag) NextState = READY;
|
||||||
else NextState = DELAY;
|
else NextState = DELAY;
|
||||||
default: NextState = READY;
|
default: NextState = READY;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -110,4 +109,3 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
|
|||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -28,24 +28,23 @@
|
|||||||
|
|
||||||
module rom_ahb import cvw::*; #(parameter cvw_t P,
|
module rom_ahb import cvw::*; #(parameter cvw_t P,
|
||||||
parameter BASE=0, RANGE = 65535) (
|
parameter BASE=0, RANGE = 65535) (
|
||||||
input logic HCLK, HRESETn,
|
input logic HCLK, HRESETn,
|
||||||
input logic HSELRom,
|
input logic HSELRom,
|
||||||
input logic [P.PA_BITS-1:0] HADDR,
|
input logic [P.PA_BITS-1:0] HADDR,
|
||||||
input logic HREADY,
|
input logic HREADY,
|
||||||
input logic [1:0] HTRANS,
|
input logic [1:0] HTRANS,
|
||||||
output logic [P.XLEN-1:0] HREADRom,
|
output logic [P.XLEN-1:0] HREADRom,
|
||||||
output logic HRESPRom, HREADYRom
|
output logic HRESPRom, HREADYRom
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
||||||
localparam OFFSET = $clog2(P.XLEN/8);
|
localparam OFFSET = $clog2(P.XLEN/8);
|
||||||
|
|
||||||
// Never stalls
|
// Never stalls
|
||||||
assign HREADYRom = 1'b1;
|
assign HREADYRom = 1'b1;
|
||||||
assign HRESPRom = 0; // OK
|
assign HRESPRom = 0; // OK
|
||||||
|
|
||||||
// single-ported ROM
|
// single-ported ROM
|
||||||
rom1p1r #(ADDR_WIDTH, P.XLEN, P.FPGA)
|
rom1p1r #(ADDR_WIDTH, P.XLEN, P.FPGA)
|
||||||
memory(.clk(HCLK), .ce(1'b1), .addr(HADDR[ADDR_WIDTH+OFFSET-1:OFFSET]), .dout(HREADRom));
|
memory(.clk(HCLK), .ce(1'b1), .addr(HADDR[ADDR_WIDTH+OFFSET-1:OFFSET]), .dout(HREADRom));
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
output logic INTR, TXRDYb, RXRDYb, // interrupt and ready lines
|
output logic INTR, TXRDYb, RXRDYb, // interrupt and ready lines
|
||||||
// Clocks
|
// Clocks
|
||||||
output logic BAUDOUTb, // active low baud clock
|
output logic BAUDOUTb, // active low baud clock
|
||||||
input logic RCLK, // usually BAUDOUTb tied to RCLK externally
|
input logic RCLK, // usually BAUDOUTb tied to RCLK externally
|
||||||
// E1A Driver
|
// E1A Driver
|
||||||
input logic SIN, DSRb, DCDb, CTSb, RIb, // UART external serial and flow-control inputs
|
input logic SIN, DSRb, DCDb, CTSb, RIb, // UART external serial and flow-control inputs
|
||||||
output logic SOUT, RTSb, DTRb, OUT1b, OUT2b // UART external serial and flow-control outputs
|
output logic SOUT, RTSb, DTRb, OUT1b, OUT2b // UART external serial and flow-control outputs
|
||||||
@ -71,9 +71,9 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
logic DLAB; // Divisor Latch Access Bit (LCR bit 7)
|
logic DLAB; // Divisor Latch Access Bit (LCR bit 7)
|
||||||
|
|
||||||
// Baud and rx/tx timing
|
// Baud and rx/tx timing
|
||||||
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
|
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
|
||||||
logic [16+UART_PRESCALE-1:0] baudcount;
|
logic [16+UART_PRESCALE-1:0] baudcount;
|
||||||
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
|
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
|
||||||
logic [3:0] rxbitsreceived, txbitssent;
|
logic [3:0] rxbitsreceived, txbitssent;
|
||||||
statetype rxstate, txstate;
|
statetype rxstate, txstate;
|
||||||
|
|
||||||
@ -122,6 +122,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// Input synchronization: 2-stage synchronizer
|
// Input synchronization: 2-stage synchronizer
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
always_ff @(posedge PCLK) begin
|
always_ff @(posedge PCLK) begin
|
||||||
{SINd, DSRbd, DCDbd, CTSbd, RIbd} <= #1 {SIN, DSRb, DCDb, CTSb, RIb};
|
{SINd, DSRbd, DCDbd, CTSbd, RIbd} <= #1 {SIN, DSRb, DCDb, CTSb, RIb};
|
||||||
{SINsync, DSRbsync, DCDbsync, CTSbsync, RIbsync} <= #1 loop ? {SOUTbit, ~MCR[0], ~MCR[3], ~MCR[1], ~MCR[2]} :
|
{SINsync, DSRbsync, DCDbsync, CTSbsync, RIbsync} <= #1 loop ? {SOUTbit, ~MCR[0], ~MCR[3], ~MCR[1], ~MCR[2]} :
|
||||||
@ -132,6 +133,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// Register interface (Table 1, note some are read only and some write only)
|
// Register interface (Table 1, note some are read only and some write only)
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if (~PRESETn) begin // Table 3 Reset Configuration
|
if (~PRESETn) begin // Table 3 Reset Configuration
|
||||||
IER <= #1 4'b0;
|
IER <= #1 4'b0;
|
||||||
@ -162,13 +164,13 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
if (~MEMWb & (A == 3'b101))
|
if (~MEMWb & (A == 3'b101))
|
||||||
LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
|
LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
|
||||||
else begin
|
else begin
|
||||||
LSR[0] <= #1 rxdataready; // Data ready
|
LSR[0] <= #1 rxdataready; // Data ready
|
||||||
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
|
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
|
||||||
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
|
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
|
||||||
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
|
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
|
||||||
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
|
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
|
||||||
LSR[5] <= #1 THRE; // THRE
|
LSR[5] <= #1 THRE; // THRE
|
||||||
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
|
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
|
||||||
if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error
|
if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -208,6 +210,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// Ross Thompson: Found a bug. If the baud rate dividers DLM, and DLL are reloaded
|
// Ross Thompson: Found a bug. If the baud rate dividers DLM, and DLL are reloaded
|
||||||
// the baudcount is not reset to {DLM, DLL, UART_PRESCALE}
|
// the baudcount is not reset to {DLM, DLL, UART_PRESCALE}
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
baudcount <= #1 1;
|
baudcount <= #1 1;
|
||||||
@ -233,17 +236,18 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// receive timing and control
|
// receive timing and control
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
rxoversampledcnt <= #1 0;
|
rxoversampledcnt <= #1 0;
|
||||||
rxstate <= #1 UART_IDLE;
|
rxstate <= #1 UART_IDLE;
|
||||||
rxbitsreceived <= #1 0;
|
rxbitsreceived <= #1 0;
|
||||||
rxtimeoutcnt <= #1 0;
|
rxtimeoutcnt <= #1 0;
|
||||||
end else begin
|
end else begin
|
||||||
if (rxstate == UART_IDLE & ~SINsync) begin // got start bit
|
if (rxstate == UART_IDLE & ~SINsync) begin // got start bit
|
||||||
rxstate <= #1 UART_ACTIVE;
|
rxstate <= #1 UART_ACTIVE;
|
||||||
rxoversampledcnt <= #1 0;
|
rxoversampledcnt <= #1 0;
|
||||||
rxbitsreceived <= #1 0;
|
rxbitsreceived <= #1 0;
|
||||||
if (~rxfifotimeout) rxtimeoutcnt <= #1 0; // reset timeout when new character is arriving. Jacob Pease: Only if the timeout was not already reached. p.16 PC16550D.pdf
|
if (~rxfifotimeout) rxtimeoutcnt <= #1 0; // reset timeout when new character is arriving. Jacob Pease: Only if the timeout was not already reached. p.16 PC16550D.pdf
|
||||||
end else if (rxbaudpulse & (rxstate == UART_ACTIVE)) begin
|
end else if (rxbaudpulse & (rxstate == UART_ACTIVE)) begin
|
||||||
rxoversampledcnt <= #1 rxoversampledcnt + 1; // 16x oversampled counter
|
rxoversampledcnt <= #1 rxoversampledcnt + 1; // 16x oversampled counter
|
||||||
@ -260,13 +264,14 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
|
|
||||||
// ***explain why
|
// ***explain why
|
||||||
if(QEMU) assign rxcentered = rxbaudpulse & (rxoversampledcnt[1:0] == 2'b10); // implies rxstate = UART_ACTIVE
|
if(QEMU) assign rxcentered = rxbaudpulse & (rxoversampledcnt[1:0] == 2'b10); // implies rxstate = UART_ACTIVE
|
||||||
else assign rxcentered = rxbaudpulse & (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE
|
else assign rxcentered = rxbaudpulse & (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE
|
||||||
|
|
||||||
assign rxbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1; // start bit + data bits + (parity bit) + stop bit
|
assign rxbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1; // start bit + data bits + (parity bit) + stop bit
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// receive shift register, buffer register, FIFO
|
// receive shift register, buffer register, FIFO
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if (~PRESETn) rxshiftreg <= #1 10'b0000000001; // initialize so that there is a valid stop bit
|
if (~PRESETn) rxshiftreg <= #1 10'b0000000001; // initialize so that there is a valid stop bit
|
||||||
else if (rxcentered) rxshiftreg <= #1 {rxshiftreg[8:0], SINsync}; // capture bit
|
else if (rxcentered) rxshiftreg <= #1 {rxshiftreg[8:0], SINsync}; // capture bit
|
||||||
@ -282,11 +287,11 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
assign rxdata = LCR[3] ? rxdata9[7:0] : rxdata9[8:1]; // discard parity bit
|
assign rxdata = LCR[3] ? rxdata9[7:0] : rxdata9[8:1]; // discard parity bit
|
||||||
|
|
||||||
// ERROR CONDITIONS
|
// ERROR CONDITIONS
|
||||||
assign rxparity = ^rxdata;
|
assign rxparity = ^rxdata;
|
||||||
assign rxparityerr = (rxparity ^ rxparitybit ^ ~evenparitysel) & LCR[3]; // 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 rxoverrunerr = fifoenabled ? (rxfifoentries == 15) : rxdataready; // overrun if FIFO or receive buffer register full
|
||||||
assign rxframingerr = ~rxstopbit; // framing error if no stop bit
|
assign rxframingerr = ~rxstopbit; // framing error if no stop bit
|
||||||
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
|
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
|
||||||
|
|
||||||
// receive FIFO and register
|
// receive FIFO and register
|
||||||
always_ff @(posedge PCLK)
|
always_ff @(posedge PCLK)
|
||||||
@ -298,7 +303,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
end else if (rxstate == UART_DONE) begin
|
end else if (rxstate == UART_DONE) begin
|
||||||
RXBR <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata}; // load recevive buffer register
|
RXBR <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata}; // load recevive buffer register
|
||||||
if (rxoverrunerr) $warning("UART RX Overrun Err\n");
|
if (rxoverrunerr) $warning("UART RX Overrun Err\n");
|
||||||
if (rxparityerr) $warning("UART RX Parity Err\n");
|
if (rxparityerr) $warning("UART RX Parity Err\n");
|
||||||
if (rxframingerr) $warning("UART RX Framing Err\n");
|
if (rxframingerr) $warning("UART RX Framing Err\n");
|
||||||
if (fifoenabled) begin
|
if (fifoenabled) begin
|
||||||
rxfifo[rxfifohead] <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata};
|
rxfifo[rxfifohead] <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata};
|
||||||
@ -339,14 +344,14 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
else assign rxfullbitunwrapped[i] = ({1'b0,rxfifohead}==i | rxfullbitunwrapped[i-1]) & (rxfifotailunwrapped != i);
|
else assign rxfullbitunwrapped[i] = ({1'b0,rxfifohead}==i | rxfullbitunwrapped[i-1]) & (rxfifotailunwrapped != i);
|
||||||
end
|
end
|
||||||
for (i=0; i<16; i++) begin:rx
|
for (i=0; i<16; i++) begin:rx
|
||||||
assign RXerrbit[i] = |rxfifo[i][10:8]; // are any of the error conditions set?
|
assign RXerrbit[i] = |rxfifo[i][10:8]; // are any of the error conditions set?
|
||||||
assign rxfullbit[i] = rxfullbitunwrapped[i] | rxfullbitunwrapped[i+16];
|
assign rxfullbit[i] = rxfullbitunwrapped[i] | rxfullbitunwrapped[i+16];
|
||||||
/* if (i > 0)
|
/* if (i > 0)
|
||||||
assign rxfullbit[i] = ((rxfifohead==i) | rxfullbit[i-1]) & (rxfifotail != i);
|
assign rxfullbit[i] = ((rxfifohead==i) | rxfullbit[i-1]) & (rxfifotail != i);
|
||||||
else
|
else
|
||||||
assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i);*/
|
assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i);*/
|
||||||
end
|
end
|
||||||
assign rxfifohaserr = |(RXerrbit & rxfullbit);
|
assign rxfifohaserr = |(RXerrbit & rxfullbit);
|
||||||
|
|
||||||
// receive buffer register and ready bit
|
// receive buffer register and ready bit
|
||||||
always_ff @(posedge PCLK, negedge PRESETn) // track rxrdy for DMA mode (FCR3 = FCR0 = 1)
|
always_ff @(posedge PCLK, negedge PRESETn) // track rxrdy for DMA mode (FCR3 = FCR0 = 1)
|
||||||
@ -361,22 +366,23 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
if (fifodmamodesel) RXRDYb = ~rxfifodmaready;
|
if (fifodmamodesel) RXRDYb = ~rxfifodmaready;
|
||||||
else RXRDYb = rxfifoempty;
|
else RXRDYb = rxfifoempty;
|
||||||
end else begin
|
end else begin
|
||||||
RBR = RXBR;
|
RBR = RXBR;
|
||||||
RXRDYb = ~rxdataready;
|
RXRDYb = ~rxdataready;
|
||||||
end
|
end
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// transmit timing and control
|
// transmit timing and control
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
txoversampledcnt <= #1 0;
|
txoversampledcnt <= #1 0;
|
||||||
txstate <= #1 UART_IDLE;
|
txstate <= #1 UART_IDLE;
|
||||||
txbitssent <= #1 0;
|
txbitssent <= #1 0;
|
||||||
end else if ((txstate == UART_IDLE) & txsrfull) begin // start transmitting
|
end else if ((txstate == UART_IDLE) & txsrfull) begin // start transmitting
|
||||||
txstate <= #1 UART_ACTIVE;
|
txstate <= #1 UART_ACTIVE;
|
||||||
txoversampledcnt <= #1 1;
|
txoversampledcnt <= #1 1;
|
||||||
txbitssent <= #1 0;
|
txbitssent <= #1 0;
|
||||||
end else if (txbaudpulse & (txstate == UART_ACTIVE)) begin
|
end else if (txbaudpulse & (txstate == UART_ACTIVE)) begin
|
||||||
txoversampledcnt <= #1 txoversampledcnt + 1;
|
txoversampledcnt <= #1 txoversampledcnt + 1;
|
||||||
if (txnextbit) begin // transmit at end of phase
|
if (txnextbit) begin // transmit at end of phase
|
||||||
@ -390,11 +396,12 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
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
|
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?
|
// *** explain; is this necessary?
|
||||||
if (QEMU) assign txnextbit = txbaudpulse & (txoversampledcnt[1:0] == 2'b00); // implies txstate = UART_ACTIVE
|
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
|
else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// transmit holding register, shift register, FIFO
|
// transmit holding register, shift register, FIFO
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
always_comb begin // compute value for parity and tx holding register
|
always_comb begin // compute value for parity and tx holding register
|
||||||
nexttxdata = fifoenabled ? txfifo[txfifotail] : TXHR; // pick from FIFO or holding register
|
nexttxdata = fifoenabled ? txfifo[txfifotail] : TXHR; // pick from FIFO or holding register
|
||||||
case (LCR[1:0]) // compute parity from appropriate number of bits
|
case (LCR[1:0]) // compute parity from appropriate number of bits
|
||||||
@ -426,9 +433,9 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
if (~MEMWb & A == 3'b000 & ~DLAB) begin // writing transmit holding register or fifo
|
if (~MEMWb & A == 3'b000 & ~DLAB) begin // writing transmit holding register or fifo
|
||||||
if (fifoenabled) begin
|
if (fifoenabled) begin
|
||||||
txfifo[txfifohead] <= #1 Din;
|
txfifo[txfifohead] <= #1 Din;
|
||||||
txfifohead <= #1 txfifohead + 1;
|
txfifohead <= #1 txfifohead + 1;
|
||||||
end else begin
|
end else begin
|
||||||
TXHR <= #1 Din;
|
TXHR <= #1 Din;
|
||||||
txhrfull <= #1 1;
|
txhrfull <= #1 1;
|
||||||
end
|
end
|
||||||
$write("%c",Din); // for testbench
|
$write("%c",Din); // for testbench
|
||||||
@ -436,12 +443,12 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
if (txstate == UART_IDLE) begin // move data into tx shift register if available
|
if (txstate == UART_IDLE) begin // move data into tx shift register if available
|
||||||
if (fifoenabled) begin
|
if (fifoenabled) begin
|
||||||
if (~txfifoempty & ~txsrfull) begin
|
if (~txfifoempty & ~txsrfull) begin
|
||||||
txsr <= #1 txdata;
|
txsr <= #1 txdata;
|
||||||
txfifotail <= #1 txfifotail+1;
|
txfifotail <= #1 txfifotail+1;
|
||||||
txsrfull <= #1 1;
|
txsrfull <= #1 1;
|
||||||
end
|
end
|
||||||
end else if (txhrfull) begin
|
end else if (txhrfull) begin
|
||||||
txsr <= #1 txdata;
|
txsr <= #1 txdata;
|
||||||
txhrfull <= #1 0;
|
txhrfull <= #1 0;
|
||||||
txsrfull <= #1 1;
|
txsrfull <= #1 1;
|
||||||
end
|
end
|
||||||
@ -470,13 +477,13 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
HeadPointerLastMove <= 1'b0;
|
HeadPointerLastMove <= 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign txfifoempty = (txfifohead == txfifotail) & ~HeadPointerLastMove;
|
assign txfifoempty = (txfifohead == txfifotail) & ~HeadPointerLastMove;
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
assign txfifoentries = (txfifohead >= txfifotail) ? (txfifohead-txfifotail) :
|
assign txfifoentries = (txfifohead >= txfifotail) ? (txfifohead-txfifotail) :
|
||||||
(txfifohead + 16 - txfifotail);
|
(txfifohead + 16 - txfifotail);
|
||||||
// verilator lint_on WIDTH
|
// verilator lint_on WIDTH
|
||||||
//assign txfifofull = (txfifoentries == 4'b1111);
|
//assign txfifofull = (txfifoentries == 4'b1111);
|
||||||
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
|
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
|
||||||
|
|
||||||
// transmit buffer ready bit
|
// transmit buffer ready bit
|
||||||
always_ff @(posedge PCLK, negedge PRESETn) // track txrdy for DMA mode (FCR3 = FCR0 = 1)
|
always_ff @(posedge PCLK, negedge PRESETn) // track txrdy for DMA mode (FCR3 = FCR0 = 1)
|
||||||
@ -490,11 +497,12 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
|
|
||||||
// Transmitter pin
|
// Transmitter pin
|
||||||
assign SOUTbit = txsr[11]; // transmit most significant bit
|
assign SOUTbit = txsr[11]; // transmit most significant bit
|
||||||
assign SOUT = loop ? 1 : (LCR[6] ? 0 : SOUTbit); // tied to 1 during loopback or 0 during break
|
assign SOUT = loop ? 1 : (LCR[6] ? 0 : SOUTbit); // tied to 1 during loopback or 0 during break
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// interrupts
|
// interrupts
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
assign RXerr = |LSR[4:1]; // LS interrupt if any of the flags are true
|
assign RXerr = |LSR[4:1]; // LS interrupt if any of the flags are true
|
||||||
assign RXerrIP = RXerr & ~squashRXerrIP; // intr squashed upon reading LSR
|
assign RXerrIP = RXerr & ~squashRXerrIP; // intr squashed upon reading LSR
|
||||||
assign rxdataavailintr = fifoenabled ? rxfifotriggered : rxdataready;
|
assign rxdataavailintr = fifoenabled ? rxfifotriggered : rxdataready;
|
||||||
@ -533,15 +541,15 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
|||||||
// modem control logic
|
// modem control logic
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
assign loop = MCR[4];
|
assign loop = MCR[4];
|
||||||
assign DTRb = ~MCR[0] | loop; // disable modem signals in loopback mode
|
assign DTRb = ~MCR[0] | loop; // disable modem signals in loopback mode
|
||||||
assign RTSb = ~MCR[1] | loop;
|
assign RTSb = ~MCR[1] | loop;
|
||||||
assign OUT1b = ~MCR[2] | loop;
|
assign OUT1b = ~MCR[2] | loop;
|
||||||
assign OUT2b = ~MCR[3] | loop;
|
assign OUT2b = ~MCR[3] | loop;
|
||||||
|
|
||||||
assign DLAB = LCR[7];
|
assign DLAB = LCR[7];
|
||||||
assign evenparitysel = LCR[4];
|
assign evenparitysel = LCR[4];
|
||||||
assign fifoenabled = FCR[0];
|
assign fifoenabled = FCR[0];
|
||||||
assign fifodmamodesel = FCR[3];
|
assign fifodmamodesel = FCR[3];
|
||||||
always_comb
|
always_comb
|
||||||
case (FCR[7:6])
|
case (FCR[7:6])
|
||||||
|
@ -29,18 +29,18 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module uart_apb import cvw::*; #(parameter cvw_t P) (
|
module uart_apb import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic PCLK, PRESETn,
|
input logic PCLK, PRESETn,
|
||||||
input logic PSEL,
|
input logic PSEL,
|
||||||
input logic [2:0] PADDR,
|
input logic [2:0] PADDR,
|
||||||
input logic [P.XLEN-1:0] PWDATA,
|
input logic [P.XLEN-1:0] PWDATA,
|
||||||
input logic [P.XLEN/8-1:0] PSTRB,
|
input logic [P.XLEN/8-1:0] PSTRB,
|
||||||
input logic PWRITE,
|
input logic PWRITE,
|
||||||
input logic PENABLE,
|
input logic PENABLE,
|
||||||
output logic [P.XLEN-1:0] PRDATA,
|
output logic [P.XLEN-1:0] PRDATA,
|
||||||
output logic PREADY,
|
output logic PREADY,
|
||||||
input logic SIN, DSRb, DCDb, CTSb, RIb, // from E1A driver from RS232 interface
|
input logic SIN, DSRb, DCDb, CTSb, RIb, // from E1A driver from RS232 interface
|
||||||
output logic SOUT, RTSb, DTRb, // to E1A driver to RS232 interface
|
output logic SOUT, RTSb, DTRb, // to E1A driver to RS232 interface
|
||||||
output logic OUT1b, OUT2b, INTR, TXRDYb, RXRDYb); // to CPU
|
output logic OUT1b, OUT2b, INTR, TXRDYb, RXRDYb); // to CPU
|
||||||
|
|
||||||
// UART interface signals
|
// UART interface signals
|
||||||
logic [2:0] entry;
|
logic [2:0] entry;
|
||||||
@ -49,10 +49,10 @@ module uart_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
assign memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||||
assign memread = ~PWRITE & PENABLE & PSEL;
|
assign memread = ~PWRITE & PENABLE & PSEL;
|
||||||
assign PREADY = 1'b1; // CLINT never takes >1 cycle to respond
|
assign PREADY = 1'b1; // CLINT never takes >1 cycle to respond
|
||||||
assign entry = PADDR[2:0];
|
assign entry = PADDR[2:0];
|
||||||
assign MEMRb = ~memread;
|
assign MEMRb = ~memread;
|
||||||
assign MEMWb = ~memwrite;
|
assign MEMWb = ~memwrite;
|
||||||
|
|
||||||
if (P.XLEN == 64) begin:uart
|
if (P.XLEN == 64) begin:uart
|
||||||
always_comb begin
|
always_comb begin
|
||||||
@ -97,4 +97,3 @@ module uart_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -29,58 +29,58 @@
|
|||||||
|
|
||||||
module uncore import cvw::*; #(parameter cvw_t P)(
|
module uncore import cvw::*; #(parameter cvw_t P)(
|
||||||
// AHB Bus Interface
|
// AHB Bus Interface
|
||||||
input logic HCLK, HRESETn,
|
input logic HCLK, HRESETn,
|
||||||
input logic TIMECLK,
|
input logic TIMECLK,
|
||||||
input logic [P.PA_BITS-1:0] HADDR,
|
input logic [P.PA_BITS-1:0] HADDR,
|
||||||
input logic [P.AHBW-1:0] HWDATA,
|
input logic [P.AHBW-1:0] HWDATA,
|
||||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||||
input logic HWRITE,
|
input logic HWRITE,
|
||||||
input logic [2:0] HSIZE,
|
input logic [2:0] HSIZE,
|
||||||
input logic [2:0] HBURST,
|
input logic [2:0] HBURST,
|
||||||
input logic [3:0] HPROT,
|
input logic [3:0] HPROT,
|
||||||
input logic [1:0] HTRANS,
|
input logic [1:0] HTRANS,
|
||||||
input logic HMASTLOCK,
|
input logic HMASTLOCK,
|
||||||
input logic [P.AHBW-1:0] HRDATAEXT,
|
input logic [P.AHBW-1:0] HRDATAEXT,
|
||||||
input logic HREADYEXT, HRESPEXT,
|
input logic HREADYEXT, HRESPEXT,
|
||||||
output logic [P.AHBW-1:0] HRDATA,
|
output logic [P.AHBW-1:0] HRDATA,
|
||||||
output logic HREADY, HRESP,
|
output logic HREADY, HRESP,
|
||||||
output logic HSELEXT,
|
output logic HSELEXT,
|
||||||
// peripheral pins
|
// peripheral pins
|
||||||
output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT
|
output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT
|
||||||
output logic MExtInt, SExtInt, // External interrupts from PLIC
|
output logic MExtInt, SExtInt, // External interrupts from PLIC
|
||||||
output logic [63:0] MTIME_CLINT, // MTIME, from CLINT
|
output logic [63:0] MTIME_CLINT, // MTIME, from CLINT
|
||||||
input logic [31:0] GPIOIN, // GPIO pin input value
|
input logic [31:0] GPIOIN, // GPIO pin input value
|
||||||
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
|
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
|
||||||
input logic UARTSin, // UART serial input
|
input logic UARTSin, // UART serial input
|
||||||
output logic UARTSout, // UART serial output
|
output logic UARTSout, // UART serial output
|
||||||
output logic SDCCmdOut, // SD Card command output
|
output logic SDCCmdOut, // SD Card command output
|
||||||
output logic SDCCmdOE, // SD Card command output enable
|
output logic SDCCmdOE, // SD Card command output enable
|
||||||
input logic SDCCmdIn, // SD Card command input
|
input logic SDCCmdIn, // SD Card command input
|
||||||
input logic [3:0] SDCDatIn, // SD Card data input
|
input logic [3:0] SDCDatIn, // SD Card data input
|
||||||
output logic SDCCLK // SD Card clock
|
output logic SDCCLK // SD Card clock
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN-1:0] HREADRam, HREADSDC;
|
logic [P.XLEN-1:0] HREADRam, HREADSDC;
|
||||||
|
|
||||||
logic [10:0] HSELRegions;
|
logic [10:0] HSELRegions;
|
||||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
||||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD;
|
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD;
|
||||||
logic HRESPRam, HRESPSDC;
|
logic HRESPRam, HRESPSDC;
|
||||||
logic HREADYRam, HRESPSDCD;
|
logic HREADYRam, HRESPSDCD;
|
||||||
logic [P.XLEN-1:0] HREADBootRom;
|
logic [P.XLEN-1:0] HREADBootRom;
|
||||||
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
||||||
logic HSELNoneD;
|
logic HSELNoneD;
|
||||||
logic UARTIntr,GPIOIntr;
|
logic UARTIntr,GPIOIntr;
|
||||||
logic SDCIntM;
|
logic SDCIntM;
|
||||||
|
|
||||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||||
logic [3:0] PSEL, PREADY;
|
logic [3:0] PSEL, PREADY;
|
||||||
logic [31:0] PADDR;
|
logic [31:0] PADDR;
|
||||||
logic [P.XLEN-1:0] PWDATA;
|
logic [P.XLEN-1:0] PWDATA;
|
||||||
logic [P.XLEN/8-1:0] PSTRB;
|
logic [P.XLEN/8-1:0] PSTRB;
|
||||||
logic [3:0][P.XLEN-1:0] PRDATA;
|
logic [3:0][P.XLEN-1:0] PRDATA;
|
||||||
logic [P.XLEN-1:0] HREADBRIDGE;
|
logic [P.XLEN-1:0] HREADBRIDGE;
|
||||||
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
|
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
|
||||||
|
|
||||||
// Determine which region of physical memory (if any) is being accessed
|
// Determine which region of physical memory (if any) is being accessed
|
||||||
// Use a trimmed down portion of the PMA checker - only the address decoders
|
// Use a trimmed down portion of the PMA checker - only the address decoders
|
||||||
@ -154,9 +154,9 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
|||||||
.SDCIntM
|
.SDCIntM
|
||||||
);
|
);
|
||||||
end else begin : sdc
|
end else begin : sdc
|
||||||
assign SDCCLK = 0;
|
assign SDCCLK = 0;
|
||||||
assign SDCCmdOut = 0;
|
assign SDCCmdOut = 0;
|
||||||
assign SDCCmdOE = 0;
|
assign SDCCmdOE = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
// AHB Read Multiplexer
|
// AHB Read Multiplexer
|
||||||
@ -189,4 +189,3 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
|||||||
HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELSDCD, HSELNoneD});
|
HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELSDCD, HSELNoneD});
|
||||||
flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED);
|
flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
114
src/wally/cvw.sv
114
src/wally/cvw.sv
@ -47,8 +47,9 @@ typedef struct packed {
|
|||||||
// RISC-V Features
|
// RISC-V Features
|
||||||
logic ZICSR_SUPPORTED;
|
logic ZICSR_SUPPORTED;
|
||||||
logic ZIFENCEI_SUPPORTED;
|
logic ZIFENCEI_SUPPORTED;
|
||||||
logic [11:0] COUNTERS;
|
logic [11:0] COUNTERS;
|
||||||
logic ZICOUNTERS_SUPPORTED;
|
logic ZICNTR_SUPPORTED;
|
||||||
|
logic ZIHPM_SUPPORTED;
|
||||||
logic ZFH_SUPPORTED;
|
logic ZFH_SUPPORTED;
|
||||||
logic SSTC_SUPPORTED;
|
logic SSTC_SUPPORTED;
|
||||||
logic VIRTMEM_SUPPORTED;
|
logic VIRTMEM_SUPPORTED;
|
||||||
@ -56,6 +57,10 @@ typedef struct packed {
|
|||||||
logic BIGENDIAN_SUPPORTED;
|
logic BIGENDIAN_SUPPORTED;
|
||||||
logic SVADU_SUPPORTED;
|
logic SVADU_SUPPORTED;
|
||||||
logic ZMMUL_SUPPORTED;
|
logic ZMMUL_SUPPORTED;
|
||||||
|
logic ZICBOM_SUPPORTED;
|
||||||
|
logic ZICBOZ_SUPPORTED;
|
||||||
|
logic ZICBOP_SUPPORTED;
|
||||||
|
logic SVPBMT_SUPPORTED;
|
||||||
|
|
||||||
// Microarchitectural Features
|
// Microarchitectural Features
|
||||||
logic BUS_SUPPORTED;
|
logic BUS_SUPPORTED;
|
||||||
@ -63,31 +68,31 @@ typedef struct packed {
|
|||||||
logic ICACHE_SUPPORTED;
|
logic ICACHE_SUPPORTED;
|
||||||
|
|
||||||
// TLB configuration. Entries should be a power of 2
|
// TLB configuration. Entries should be a power of 2
|
||||||
int ITLB_ENTRIES;
|
int ITLB_ENTRIES;
|
||||||
int DTLB_ENTRIES;
|
int DTLB_ENTRIES;
|
||||||
|
|
||||||
// Cache configuration. Sizes should be a power of two
|
// Cache configuration. Sizes should be a power of two
|
||||||
// typical configuration 4 ways, 4096 ints per way, 256 bit or more lines
|
// typical configuration 4 ways, 4096 ints per way, 256 bit or more lines
|
||||||
int DCACHE_NUMWAYS;
|
int DCACHE_NUMWAYS;
|
||||||
int DCACHE_WAYSIZEINBYTES;
|
int DCACHE_WAYSIZEINBYTES;
|
||||||
int DCACHE_LINELENINBITS;
|
int DCACHE_LINELENINBITS;
|
||||||
int ICACHE_NUMWAYS;
|
int ICACHE_NUMWAYS;
|
||||||
int ICACHE_WAYSIZEINBYTES;
|
int ICACHE_WAYSIZEINBYTES;
|
||||||
int ICACHE_LINELENINBITS;
|
int ICACHE_LINELENINBITS;
|
||||||
|
|
||||||
// Integer Divider Configuration
|
// Integer Divider Configuration
|
||||||
// IDIV_BITSPERCYCLE must be 1, 2, or 4
|
// IDIV_BITSPERCYCLE must be 1, 2, or 4
|
||||||
int IDIV_BITSPERCYCLE;
|
int IDIV_BITSPERCYCLE;
|
||||||
logic IDIV_ON_FPU;
|
logic IDIV_ON_FPU;
|
||||||
|
|
||||||
// Legal number of PMP entries are 0, 16, or 64
|
// Legal number of PMP entries are 0, 16, or 64
|
||||||
int PMP_ENTRIES;
|
int PMP_ENTRIES;
|
||||||
|
|
||||||
// Address space
|
// Address space
|
||||||
logic [63:0] RESET_VECTOR;
|
logic [63:0] RESET_VECTOR;
|
||||||
|
|
||||||
// WFI Timeout Wait
|
// WFI Timeout Wait
|
||||||
int WFI_TIMEOUT_BIT;
|
int WFI_TIMEOUT_BIT;
|
||||||
|
|
||||||
// Peripheral Addresses
|
// Peripheral Addresses
|
||||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||||
@ -129,24 +134,23 @@ typedef struct packed {
|
|||||||
logic GPIO_LOOPBACK_TEST;
|
logic GPIO_LOOPBACK_TEST;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
int UART_PRESCALE ;
|
int UART_PRESCALE ;
|
||||||
|
|
||||||
// Interrupt configuration
|
// Interrupt configuration
|
||||||
int PLIC_NUM_SRC;
|
int PLIC_NUM_SRC;
|
||||||
logic PLIC_NUM_SRC_LT_32;
|
logic PLIC_NUM_SRC_LT_32;
|
||||||
int PLIC_GPIO_ID;
|
int PLIC_GPIO_ID;
|
||||||
int PLIC_UART_ID;
|
int PLIC_UART_ID;
|
||||||
|
|
||||||
logic BPRED_SUPPORTED;
|
|
||||||
BranchPredictorType BPRED_TYPE;
|
|
||||||
int BPRED_NUM_LHR;
|
|
||||||
int BPRED_SIZE;
|
|
||||||
int BTB_SIZE;
|
|
||||||
|
|
||||||
|
logic BPRED_SUPPORTED;
|
||||||
|
BranchPredictorType BPRED_TYPE;
|
||||||
|
int BPRED_NUM_LHR;
|
||||||
|
int BPRED_SIZE;
|
||||||
|
int BTB_SIZE;
|
||||||
|
|
||||||
// FPU division architecture
|
// FPU division architecture
|
||||||
int RADIX;
|
int RADIX;
|
||||||
int DIVCOPIES;
|
int DIVCOPIES;
|
||||||
|
|
||||||
// bit manipulation
|
// bit manipulation
|
||||||
logic ZBA_SUPPORTED;
|
logic ZBA_SUPPORTED;
|
||||||
@ -199,47 +203,47 @@ typedef struct packed {
|
|||||||
int PMPCFG_ENTRIES;
|
int PMPCFG_ENTRIES;
|
||||||
|
|
||||||
// Floating point constants for Quad, Double, Single, and Half precisions
|
// Floating point constants for Quad, Double, Single, and Half precisions
|
||||||
int Q_LEN;
|
int Q_LEN;
|
||||||
int Q_NE;
|
int Q_NE;
|
||||||
int Q_NF;
|
int Q_NF;
|
||||||
int Q_BIAS;
|
int Q_BIAS;
|
||||||
logic [1:0] Q_FMT;
|
logic [1:0] Q_FMT;
|
||||||
int D_LEN;
|
int D_LEN;
|
||||||
int D_NE;
|
int D_NE;
|
||||||
int D_NF;
|
int D_NF;
|
||||||
int D_BIAS;
|
int D_BIAS;
|
||||||
logic [1:0] D_FMT;
|
logic [1:0] D_FMT;
|
||||||
int S_LEN;
|
int S_LEN;
|
||||||
int S_NE;
|
int S_NE;
|
||||||
int S_NF;
|
int S_NF;
|
||||||
int S_BIAS;
|
int S_BIAS;
|
||||||
logic [1:0] S_FMT;
|
logic [1:0] S_FMT;
|
||||||
int H_LEN;
|
int H_LEN;
|
||||||
int H_NE;
|
int H_NE;
|
||||||
int H_NF;
|
int H_NF;
|
||||||
int H_BIAS;
|
int H_BIAS;
|
||||||
logic [1:0] H_FMT;
|
logic [1:0] H_FMT;
|
||||||
|
|
||||||
// Floating point length FLEN and number of exponent (NE) and fraction (NF) bits
|
// Floating point length FLEN and number of exponent (NE) and fraction (NF) bits
|
||||||
int FLEN;
|
int FLEN;
|
||||||
int NE ;
|
int NE ;
|
||||||
int NF ;
|
int NF ;
|
||||||
logic [1:0] FMT ;
|
logic [1:0] FMT ;
|
||||||
int BIAS;
|
int BIAS;
|
||||||
|
|
||||||
// Floating point constants needed for FPU paramerterization
|
// Floating point constants needed for FPU paramerterization
|
||||||
int FPSIZES;
|
int FPSIZES;
|
||||||
int FMTBITS;
|
int FMTBITS;
|
||||||
int LEN1 ;
|
int LEN1 ;
|
||||||
int NE1 ;
|
int NE1 ;
|
||||||
int NF1 ;
|
int NF1 ;
|
||||||
logic [1:0] FMT1 ;
|
logic [1:0] FMT1 ;
|
||||||
int BIAS1;
|
int BIAS1;
|
||||||
int LEN2 ;
|
int LEN2 ;
|
||||||
int NE2 ;
|
int NE2 ;
|
||||||
int NF2 ;
|
int NF2 ;
|
||||||
logic [1:0] FMT2 ;
|
logic [1:0] FMT2 ;
|
||||||
int BIAS2;
|
int BIAS2;
|
||||||
|
|
||||||
// largest length in IEU/FPU
|
// largest length in IEU/FPU
|
||||||
int CVTLEN;
|
int CVTLEN;
|
||||||
@ -251,7 +255,7 @@ typedef struct packed {
|
|||||||
|
|
||||||
// division constants
|
// division constants
|
||||||
int DIVN ;
|
int DIVN ;
|
||||||
int LOGR;
|
int LOGR ;
|
||||||
int RK ;
|
int RK ;
|
||||||
int LOGRK ;
|
int LOGRK ;
|
||||||
int FPDUR ;
|
int FPDUR ;
|
||||||
|
@ -32,12 +32,12 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt,
|
input logic MTimerInt, MExtInt, SExtInt, MSwInt,
|
||||||
input logic [63:0] MTIME_CLINT,
|
input logic [63:0] MTIME_CLINT,
|
||||||
// Bus Interface
|
// Bus Interface
|
||||||
input logic [P.AHBW-1:0] HRDATA,
|
input logic [P.AHBW-1:0] HRDATA,
|
||||||
input logic HREADY, HRESP,
|
input logic HREADY, HRESP,
|
||||||
output logic HCLK, HRESETn,
|
output logic HCLK, HRESETn,
|
||||||
output logic [P.PA_BITS-1:0] HADDR,
|
output logic [P.PA_BITS-1:0] HADDR,
|
||||||
output logic [P.AHBW-1:0] HWDATA,
|
output logic [P.AHBW-1:0] HWDATA,
|
||||||
output logic [P.XLEN/8-1:0] HWSTRB,
|
output logic [P.XLEN/8-1:0] HWSTRB,
|
||||||
output logic HWRITE,
|
output logic HWRITE,
|
||||||
output logic [2:0] HSIZE,
|
output logic [2:0] HSIZE,
|
||||||
output logic [2:0] HBURST,
|
output logic [2:0] HBURST,
|
||||||
@ -55,15 +55,15 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic IntDivE, W64E;
|
logic IntDivE, W64E;
|
||||||
logic CSRReadM, CSRWriteM, PrivilegedM;
|
logic CSRReadM, CSRWriteM, PrivilegedM;
|
||||||
logic [1:0] AtomicM;
|
logic [1:0] AtomicM;
|
||||||
logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE;
|
logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE;
|
||||||
logic [P.XLEN-1:0] SrcAM;
|
logic [P.XLEN-1:0] SrcAM;
|
||||||
logic [2:0] Funct3E;
|
logic [2:0] Funct3E;
|
||||||
logic [31:0] InstrD;
|
logic [31:0] InstrD;
|
||||||
logic [31:0] InstrM, InstrOrigM;
|
logic [31:0] InstrM, InstrOrigM;
|
||||||
logic [P.XLEN-1:0] PCSpillF, PCE, PCLinkE;
|
logic [P.XLEN-1:0] PCSpillF, PCE, PCLinkE;
|
||||||
logic [P.XLEN-1:0] PCM;
|
logic [P.XLEN-1:0] PCM;
|
||||||
logic [P.XLEN-1:0] CSRReadValW, MDUResultW;
|
logic [P.XLEN-1:0] CSRReadValW, MDUResultW;
|
||||||
logic [P.XLEN-1:0] UnalignedPCNextF, PC2NextF;
|
logic [P.XLEN-1:0] UnalignedPCNextF, PC2NextF;
|
||||||
logic [1:0] MemRWM;
|
logic [1:0] MemRWM;
|
||||||
logic InstrValidD, InstrValidE, InstrValidM;
|
logic InstrValidD, InstrValidE, InstrValidM;
|
||||||
logic InstrMisalignedFaultM;
|
logic InstrMisalignedFaultM;
|
||||||
@ -83,31 +83,31 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [4:0] RdE, RdM, RdW;
|
logic [4:0] RdE, RdM, RdW;
|
||||||
logic FPUStallD;
|
logic FPUStallD;
|
||||||
logic FWriteIntE;
|
logic FWriteIntE;
|
||||||
logic [P.FLEN-1:0] FWriteDataM;
|
logic [P.FLEN-1:0] FWriteDataM;
|
||||||
logic [P.XLEN-1:0] FIntResM;
|
logic [P.XLEN-1:0] FIntResM;
|
||||||
logic [P.XLEN-1:0] FCvtIntResW;
|
logic [P.XLEN-1:0] FCvtIntResW;
|
||||||
logic FCvtIntW;
|
logic FCvtIntW;
|
||||||
logic FDivBusyE;
|
logic FDivBusyE;
|
||||||
logic FRegWriteM;
|
logic FRegWriteM;
|
||||||
logic FCvtIntStallD;
|
logic FCvtIntStallD;
|
||||||
logic FpLoadStoreM;
|
logic FpLoadStoreM;
|
||||||
logic [4:0] SetFflagsM;
|
logic [4:0] SetFflagsM;
|
||||||
logic [P.XLEN-1:0] FIntDivResultW;
|
logic [P.XLEN-1:0] FIntDivResultW;
|
||||||
|
|
||||||
// memory management unit signals
|
// memory management unit signals
|
||||||
logic ITLBWriteF;
|
logic ITLBWriteF;
|
||||||
logic ITLBMissF;
|
logic ITLBMissF;
|
||||||
logic [P.XLEN-1:0] SATP_REGW;
|
logic [P.XLEN-1:0] SATP_REGW;
|
||||||
logic STATUS_MXR, STATUS_SUM, STATUS_MPRV;
|
logic STATUS_MXR, STATUS_SUM, STATUS_MPRV;
|
||||||
logic [1:0] STATUS_MPP, STATUS_FS;
|
logic [1:0] STATUS_MPP, STATUS_FS;
|
||||||
logic [1:0] PrivilegeModeW;
|
logic [1:0] PrivilegeModeW;
|
||||||
logic [P.XLEN-1:0] PTE;
|
logic [P.XLEN-1:0] PTE;
|
||||||
logic [1:0] PageType;
|
logic [1:0] PageType;
|
||||||
logic sfencevmaM;
|
logic sfencevmaM;
|
||||||
logic SelHPTW;
|
logic SelHPTW;
|
||||||
|
|
||||||
// PMA checker signals
|
// PMA checker signals
|
||||||
var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0];
|
var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0];
|
||||||
var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0];
|
var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0];
|
||||||
|
|
||||||
// IMem stalls
|
// IMem stalls
|
||||||
@ -116,14 +116,14 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// cpu lsu interface
|
// cpu lsu interface
|
||||||
logic [2:0] Funct3M;
|
logic [2:0] Funct3M;
|
||||||
logic [P.XLEN-1:0] IEUAdrE;
|
logic [P.XLEN-1:0] IEUAdrE;
|
||||||
logic [P.XLEN-1:0] WriteDataM;
|
logic [P.XLEN-1:0] WriteDataM;
|
||||||
logic [P.XLEN-1:0] IEUAdrM;
|
logic [P.XLEN-1:0] IEUAdrM;
|
||||||
logic [P.LLEN-1:0] ReadDataW;
|
logic [P.LLEN-1:0] ReadDataW;
|
||||||
logic CommittedM;
|
logic CommittedM;
|
||||||
|
|
||||||
// AHB ifu interface
|
// AHB ifu interface
|
||||||
logic [P.PA_BITS-1:0] IFUHADDR;
|
logic [P.PA_BITS-1:0] IFUHADDR;
|
||||||
logic [2:0] IFUHBURST;
|
logic [2:0] IFUHBURST;
|
||||||
logic [1:0] IFUHTRANS;
|
logic [1:0] IFUHTRANS;
|
||||||
logic [2:0] IFUHSIZE;
|
logic [2:0] IFUHSIZE;
|
||||||
@ -131,9 +131,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic IFUHREADY;
|
logic IFUHREADY;
|
||||||
|
|
||||||
// AHB LSU interface
|
// AHB LSU interface
|
||||||
logic [P.PA_BITS-1:0] LSUHADDR;
|
logic [P.PA_BITS-1:0] LSUHADDR;
|
||||||
logic [P.XLEN-1:0] LSUHWDATA;
|
logic [P.XLEN-1:0] LSUHWDATA;
|
||||||
logic [P.XLEN/8-1:0] LSUHWSTRB;
|
logic [P.XLEN/8-1:0] LSUHWSTRB;
|
||||||
logic LSUHWRITE;
|
logic LSUHWRITE;
|
||||||
logic LSUHREADY;
|
logic LSUHREADY;
|
||||||
|
|
||||||
@ -192,12 +192,12 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.PCE, .PCLinkE, .FWriteIntE, .FCvtIntE, .IEUAdrE, .IntDivE, .W64E,
|
.PCE, .PCLinkE, .FWriteIntE, .FCvtIntE, .IEUAdrE, .IntDivE, .W64E,
|
||||||
.Funct3E, .ForwardedSrcAE, .ForwardedSrcBE,
|
.Funct3E, .ForwardedSrcAE, .ForwardedSrcBE,
|
||||||
// Memory stage interface
|
// Memory stage interface
|
||||||
.SquashSCW, // from LSU
|
.SquashSCW, // from LSU
|
||||||
.MemRWM, // read/write control goes to LSU
|
.MemRWM, // read/write control goes to LSU
|
||||||
.AtomicM, // atomic control goes to LSU
|
.AtomicM, // atomic control goes to LSU
|
||||||
.WriteDataM, // Write data to LSU
|
.WriteDataM, // Write data to LSU
|
||||||
.Funct3M, // size and signedness to LSU
|
.Funct3M, // size and signedness to LSU
|
||||||
.SrcAM, // to privilege and fpu
|
.SrcAM, // to privilege and fpu
|
||||||
.RdE, .RdM, .FIntResM, .FlushDCacheM,
|
.RdE, .RdM, .FIntResM, .FlushDCacheM,
|
||||||
.BranchD, .BranchE, .JumpD, .JumpE,
|
.BranchD, .BranchE, .JumpD, .JumpE,
|
||||||
// Writeback stage
|
// Writeback stage
|
||||||
@ -219,24 +219,24 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.LSUHADDR, .HRDATA, .LSUHWDATA, .LSUHWSTRB, .LSUHSIZE,
|
.LSUHADDR, .HRDATA, .LSUHWDATA, .LSUHWSTRB, .LSUHSIZE,
|
||||||
.LSUHBURST, .LSUHTRANS, .LSUHWRITE, .LSUHREADY,
|
.LSUHBURST, .LSUHTRANS, .LSUHWRITE, .LSUHREADY,
|
||||||
// connect to csr or privilege and stay the same.
|
// connect to csr or privilege and stay the same.
|
||||||
.PrivilegeModeW, .BigEndianM, // connects to csr
|
.PrivilegeModeW, .BigEndianM, // connects to csr
|
||||||
.PMPCFG_ARRAY_REGW, // connects to csr
|
.PMPCFG_ARRAY_REGW, // connects to csr
|
||||||
.PMPADDR_ARRAY_REGW, // connects to csr
|
.PMPADDR_ARRAY_REGW, // connects to csr
|
||||||
// hptw keep i/o
|
// hptw keep i/o
|
||||||
.SATP_REGW, // from csr
|
.SATP_REGW, // from csr
|
||||||
.STATUS_MXR, // from csr
|
.STATUS_MXR, // from csr
|
||||||
.STATUS_SUM, // from csr
|
.STATUS_SUM, // from csr
|
||||||
.STATUS_MPRV, // from csr
|
.STATUS_MPRV, // from csr
|
||||||
.STATUS_MPP, // from csr
|
.STATUS_MPP, // from csr
|
||||||
.sfencevmaM, // connects to privilege
|
.sfencevmaM, // connects to privilege
|
||||||
.DCacheStallM, // connects to privilege
|
.DCacheStallM, // connects to privilege
|
||||||
.LoadPageFaultM, // connects to privilege
|
.LoadPageFaultM, // connects to privilege
|
||||||
.StoreAmoPageFaultM, // connects to privilege
|
.StoreAmoPageFaultM, // connects to privilege
|
||||||
.LoadMisalignedFaultM, // connects to privilege
|
.LoadMisalignedFaultM, // connects to privilege
|
||||||
.LoadAccessFaultM, // connects to privilege
|
.LoadAccessFaultM, // connects to privilege
|
||||||
.HPTWInstrAccessFaultF, // connects to privilege
|
.HPTWInstrAccessFaultF, // connects to privilege
|
||||||
.StoreAmoMisalignedFaultM, // connects to privilege
|
.StoreAmoMisalignedFaultM, // connects to privilege
|
||||||
.StoreAmoAccessFaultM, // connects to privilege
|
.StoreAmoAccessFaultM, // connects to privilege
|
||||||
.InstrUpdateDAF,
|
.InstrUpdateDAF,
|
||||||
.PCSpillF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW,
|
.PCSpillF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW,
|
||||||
.LSUStallM);
|
.LSUStallM);
|
||||||
@ -292,14 +292,14 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||||
.FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM);
|
.FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM);
|
||||||
end else begin
|
end else begin
|
||||||
assign CSRReadValW = 0;
|
assign CSRReadValW = 0;
|
||||||
assign UnalignedPCNextF = PC2NextF;
|
assign UnalignedPCNextF = PC2NextF;
|
||||||
assign RetM = 0;
|
assign RetM = 0;
|
||||||
assign TrapM = 0;
|
assign TrapM = 0;
|
||||||
assign wfiM = 0;
|
assign wfiM = 0;
|
||||||
assign IntPendingM = 0;
|
assign IntPendingM = 0;
|
||||||
assign sfencevmaM = 0;
|
assign sfencevmaM = 0;
|
||||||
assign BigEndianM = 0;
|
assign BigEndianM = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
// multiply/divide unit
|
// multiply/divide unit
|
||||||
@ -310,45 +310,45 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.MDUResultW, .DivBusyE);
|
.MDUResultW, .DivBusyE);
|
||||||
end else begin // no M instructions supported
|
end else begin // no M instructions supported
|
||||||
assign MDUResultW = 0;
|
assign MDUResultW = 0;
|
||||||
assign DivBusyE = 0;
|
assign DivBusyE = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
// floating point unit
|
// floating point unit
|
||||||
if (P.F_SUPPORTED) begin:fpu
|
if (P.F_SUPPORTED) begin:fpu
|
||||||
fpu #(P) fpu(
|
fpu #(P) fpu(
|
||||||
.clk, .reset,
|
.clk, .reset,
|
||||||
.FRM_REGW, // Rounding mode from CSR
|
.FRM_REGW, // Rounding mode from CSR
|
||||||
.InstrD, // instruction from IFU
|
.InstrD, // instruction from IFU
|
||||||
.ReadDataW(ReadDataW[P.FLEN-1:0]),// Read data from memory
|
.ReadDataW(ReadDataW[P.FLEN-1:0]), // Read data from memory
|
||||||
.ForwardedSrcAE, // Integer input being processed (from IEU)
|
.ForwardedSrcAE, // Integer input being processed (from IEU)
|
||||||
.StallE, .StallM, .StallW, // stall signals from HZU
|
.StallE, .StallM, .StallW, // stall signals from HZU
|
||||||
.FlushE, .FlushM, .FlushW, // flush signals from HZU
|
.FlushE, .FlushM, .FlushW, // flush signals from HZU
|
||||||
.RdE, .RdM, .RdW, // which FP register to write to (from IEU)
|
.RdE, .RdM, .RdW, // which FP register to write to (from IEU)
|
||||||
.STATUS_FS, // is floating-point enabled?
|
.STATUS_FS, // is floating-point enabled?
|
||||||
.FRegWriteM, // FP register write enable
|
.FRegWriteM, // FP register write enable
|
||||||
.FpLoadStoreM,
|
.FpLoadStoreM,
|
||||||
.ForwardedSrcBE, // Integer input for intdiv
|
.ForwardedSrcBE, // Integer input for intdiv
|
||||||
.Funct3E, .Funct3M, .IntDivE, .W64E, // Integer flags and functions
|
.Funct3E, .Funct3M, .IntDivE, .W64E, // Integer flags and functions
|
||||||
.FPUStallD, // Stall the decode stage
|
.FPUStallD, // Stall the decode stage
|
||||||
.FWriteIntE, .FCvtIntE, // integer register write enable, conversion operation
|
.FWriteIntE, .FCvtIntE, // integer register write enable, conversion operation
|
||||||
.FWriteDataM, // Data to be written to memory
|
.FWriteDataM, // Data to be written to memory
|
||||||
.FIntResM, // data to be written to integer register
|
.FIntResM, // data to be written to integer register
|
||||||
.FCvtIntResW, // fp -> int conversion result to be stored in int register
|
.FCvtIntResW, // fp -> int conversion result to be stored in int register
|
||||||
.FCvtIntW, // fpu result selection
|
.FCvtIntW, // fpu result selection
|
||||||
.FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
|
.FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
|
||||||
.IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
.IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||||
.SetFflagsM, // FPU flags (to privileged unit)
|
.SetFflagsM, // FPU flags (to privileged unit)
|
||||||
.FIntDivResultW);
|
.FIntDivResultW);
|
||||||
end else begin // no F_SUPPORTED or D_SUPPORTED; tie outputs low
|
end else begin // no F_SUPPORTED or D_SUPPORTED; tie outputs low
|
||||||
assign FPUStallD = 0;
|
assign FPUStallD = 0;
|
||||||
assign FWriteIntE = 0;
|
assign FWriteIntE = 0;
|
||||||
assign FCvtIntE = 0;
|
assign FCvtIntE = 0;
|
||||||
assign FIntResM = 0;
|
assign FIntResM = 0;
|
||||||
assign FCvtIntW = 0;
|
assign FCvtIntW = 0;
|
||||||
assign FDivBusyE = 0;
|
assign FDivBusyE = 0;
|
||||||
assign IllegalFPUInstrD = 1;
|
assign IllegalFPUInstrD = 1;
|
||||||
assign SetFflagsM = 0;
|
assign SetFflagsM = 0;
|
||||||
assign FpLoadStoreM = 0;
|
assign FpLoadStoreM = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -48,9 +48,9 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic HREADY,
|
output logic HREADY,
|
||||||
// I/O Interface
|
// I/O Interface
|
||||||
input logic TIMECLK, // optional for CLINT MTIME counter
|
input logic TIMECLK, // optional for CLINT MTIME counter
|
||||||
input logic [31:0] GPIOIN, // inputs from GPIO
|
input logic [31:0] GPIOIN, // inputs from GPIO
|
||||||
output logic [31:0] GPIOOUT, // output values for GPIO
|
output logic [31:0] GPIOOUT, // output values for GPIO
|
||||||
output logic [31:0] GPIOEN, // output enables for GPIO
|
output logic [31:0] GPIOEN, // output enables for GPIO
|
||||||
input logic UARTSin, // UART serial data input
|
input logic UARTSin, // UART serial data input
|
||||||
output logic UARTSout, // UART serial data output
|
output logic UARTSout, // UART serial data output
|
||||||
input logic SDCCmdIn, // SDC Command input
|
input logic SDCCmdIn, // SDC Command input
|
||||||
|
@ -139,6 +139,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
CSRArray[12'h344] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW;
|
CSRArray[12'h344] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW;
|
||||||
CSRArray[12'h304] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW;
|
CSRArray[12'h304] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW;
|
||||||
CSRArray[12'h301] = testbench.dut.core.priv.priv.csr.csrm.MISA_REGW;
|
CSRArray[12'h301] = testbench.dut.core.priv.priv.csr.csrm.MISA_REGW;
|
||||||
|
CSRArray[12'h30A] = testbench.dut.core.priv.priv.csr.csrm.MENVCFG_REGW;
|
||||||
CSRArray[12'hF14] = testbench.dut.core.priv.priv.csr.csrm.MHARTID_REGW;
|
CSRArray[12'hF14] = testbench.dut.core.priv.priv.csr.csrm.MHARTID_REGW;
|
||||||
CSRArray[12'h340] = testbench.dut.core.priv.priv.csr.csrm.MSCRATCH_REGW;
|
CSRArray[12'h340] = testbench.dut.core.priv.priv.csr.csrm.MSCRATCH_REGW;
|
||||||
CSRArray[12'h342] = testbench.dut.core.priv.priv.csr.csrm.MCAUSE_REGW;
|
CSRArray[12'h342] = testbench.dut.core.priv.priv.csr.csrm.MCAUSE_REGW;
|
||||||
@ -157,6 +158,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
CSRArray[12'h105] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW;
|
CSRArray[12'h105] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW;
|
||||||
CSRArray[12'h141] = testbench.dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW;
|
CSRArray[12'h141] = testbench.dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW;
|
||||||
CSRArray[12'h106] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW;
|
CSRArray[12'h106] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW;
|
||||||
|
CSRArray[12'h10A] = testbench.dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW;
|
||||||
CSRArray[12'h180] = testbench.dut.core.priv.priv.csr.csrs.csrs.SATP_REGW;
|
CSRArray[12'h180] = testbench.dut.core.priv.priv.csr.csrs.csrs.SATP_REGW;
|
||||||
CSRArray[12'h140] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW;
|
CSRArray[12'h140] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW;
|
||||||
CSRArray[12'h143] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW;
|
CSRArray[12'h143] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW;
|
||||||
@ -189,6 +191,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
CSRArray[12'h344] = CSRArrayOld[12'h344];
|
CSRArray[12'h344] = CSRArrayOld[12'h344];
|
||||||
CSRArray[12'h304] = CSRArrayOld[12'h304];
|
CSRArray[12'h304] = CSRArrayOld[12'h304];
|
||||||
CSRArray[12'h301] = CSRArrayOld[12'h301];
|
CSRArray[12'h301] = CSRArrayOld[12'h301];
|
||||||
|
CSRArray[12'h30A] = CSRArrayOld[12'h30A];
|
||||||
CSRArray[12'hF14] = CSRArrayOld[12'hF14];
|
CSRArray[12'hF14] = CSRArrayOld[12'hF14];
|
||||||
CSRArray[12'h340] = CSRArrayOld[12'h340];
|
CSRArray[12'h340] = CSRArrayOld[12'h340];
|
||||||
CSRArray[12'h342] = CSRArrayOld[12'h342];
|
CSRArray[12'h342] = CSRArrayOld[12'h342];
|
||||||
@ -207,6 +210,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
CSRArray[12'h105] = CSRArrayOld[12'h105];
|
CSRArray[12'h105] = CSRArrayOld[12'h105];
|
||||||
CSRArray[12'h141] = CSRArrayOld[12'h141];
|
CSRArray[12'h141] = CSRArrayOld[12'h141];
|
||||||
CSRArray[12'h106] = CSRArrayOld[12'h106];
|
CSRArray[12'h106] = CSRArrayOld[12'h106];
|
||||||
|
CSRArray[12'h10A] = CSRArrayOld[12'h10A];
|
||||||
CSRArray[12'h180] = CSRArrayOld[12'h180];
|
CSRArray[12'h180] = CSRArrayOld[12'h180];
|
||||||
CSRArray[12'h140] = CSRArrayOld[12'h140];
|
CSRArray[12'h140] = CSRArrayOld[12'h140];
|
||||||
CSRArray[12'h143] = CSRArrayOld[12'h143];
|
CSRArray[12'h143] = CSRArrayOld[12'h143];
|
||||||
@ -308,6 +312,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
CSRArrayOld[12'h344] = CSRArray[12'h344];
|
CSRArrayOld[12'h344] = CSRArray[12'h344];
|
||||||
CSRArrayOld[12'h304] = CSRArray[12'h304];
|
CSRArrayOld[12'h304] = CSRArray[12'h304];
|
||||||
CSRArrayOld[12'h301] = CSRArray[12'h301];
|
CSRArrayOld[12'h301] = CSRArray[12'h301];
|
||||||
|
CSRArrayOld[12'h30A] = CSRArray[12'h30A];
|
||||||
CSRArrayOld[12'hF14] = CSRArray[12'hF14];
|
CSRArrayOld[12'hF14] = CSRArray[12'hF14];
|
||||||
CSRArrayOld[12'h340] = CSRArray[12'h340];
|
CSRArrayOld[12'h340] = CSRArray[12'h340];
|
||||||
CSRArrayOld[12'h342] = CSRArray[12'h342];
|
CSRArrayOld[12'h342] = CSRArray[12'h342];
|
||||||
@ -326,6 +331,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
CSRArrayOld[12'h105] = CSRArray[12'h105];
|
CSRArrayOld[12'h105] = CSRArray[12'h105];
|
||||||
CSRArrayOld[12'h141] = CSRArray[12'h141];
|
CSRArrayOld[12'h141] = CSRArray[12'h141];
|
||||||
CSRArrayOld[12'h106] = CSRArray[12'h106];
|
CSRArrayOld[12'h106] = CSRArray[12'h106];
|
||||||
|
CSRArrayOld[12'h10A] = CSRArray[12'h10A];
|
||||||
CSRArrayOld[12'h180] = CSRArray[12'h180];
|
CSRArrayOld[12'h180] = CSRArray[12'h180];
|
||||||
CSRArrayOld[12'h140] = CSRArray[12'h140];
|
CSRArrayOld[12'h140] = CSRArray[12'h140];
|
||||||
CSRArrayOld[12'h143] = CSRArray[12'h143];
|
CSRArrayOld[12'h143] = CSRArray[12'h143];
|
||||||
@ -352,6 +358,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
assign #2 CSR_W[12'h305] = (CSRArrayOld[12'h305] != CSRArray[12'h305]) ? 1 : 0;
|
assign #2 CSR_W[12'h305] = (CSRArrayOld[12'h305] != CSRArray[12'h305]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h341] = (CSRArrayOld[12'h341] != CSRArray[12'h341]) ? 1 : 0;
|
assign #2 CSR_W[12'h341] = (CSRArrayOld[12'h341] != CSRArray[12'h341]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h306] = (CSRArrayOld[12'h306] != CSRArray[12'h306]) ? 1 : 0;
|
assign #2 CSR_W[12'h306] = (CSRArrayOld[12'h306] != CSRArray[12'h306]) ? 1 : 0;
|
||||||
|
assign #2 CSR_W[12'h30A] = (CSRArrayOld[12'h30A] != CSRArray[12'h30A]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h320] = (CSRArrayOld[12'h320] != CSRArray[12'h320]) ? 1 : 0;
|
assign #2 CSR_W[12'h320] = (CSRArrayOld[12'h320] != CSRArray[12'h320]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h302] = (CSRArrayOld[12'h302] != CSRArray[12'h302]) ? 1 : 0;
|
assign #2 CSR_W[12'h302] = (CSRArrayOld[12'h302] != CSRArray[12'h302]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h303] = (CSRArrayOld[12'h303] != CSRArray[12'h303]) ? 1 : 0;
|
assign #2 CSR_W[12'h303] = (CSRArrayOld[12'h303] != CSRArray[12'h303]) ? 1 : 0;
|
||||||
@ -374,6 +381,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
assign #2 CSR_W[12'h105] = (CSRArrayOld[12'h105] != CSRArray[12'h105]) ? 1 : 0;
|
assign #2 CSR_W[12'h105] = (CSRArrayOld[12'h105] != CSRArray[12'h105]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h141] = (CSRArrayOld[12'h141] != CSRArray[12'h141]) ? 1 : 0;
|
assign #2 CSR_W[12'h141] = (CSRArrayOld[12'h141] != CSRArray[12'h141]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h106] = (CSRArrayOld[12'h106] != CSRArray[12'h106]) ? 1 : 0;
|
assign #2 CSR_W[12'h106] = (CSRArrayOld[12'h106] != CSRArray[12'h106]) ? 1 : 0;
|
||||||
|
assign #2 CSR_W[12'h10A] = (CSRArrayOld[12'h10A] != CSRArray[12'h10A]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h180] = (CSRArrayOld[12'h180] != CSRArray[12'h180]) ? 1 : 0;
|
assign #2 CSR_W[12'h180] = (CSRArrayOld[12'h180] != CSRArray[12'h180]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h140] = (CSRArrayOld[12'h140] != CSRArray[12'h140]) ? 1 : 0;
|
assign #2 CSR_W[12'h140] = (CSRArrayOld[12'h140] != CSRArray[12'h140]) ? 1 : 0;
|
||||||
assign #2 CSR_W[12'h143] = (CSRArrayOld[12'h143] != CSRArray[12'h143]) ? 1 : 0;
|
assign #2 CSR_W[12'h143] = (CSRArrayOld[12'h143] != CSRArray[12'h143]) ? 1 : 0;
|
||||||
@ -394,6 +402,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
assign rvvi.csr_wb[0][0][12'h303] = CSR_W[12'h303];
|
assign rvvi.csr_wb[0][0][12'h303] = CSR_W[12'h303];
|
||||||
assign rvvi.csr_wb[0][0][12'h344] = CSR_W[12'h344];
|
assign rvvi.csr_wb[0][0][12'h344] = CSR_W[12'h344];
|
||||||
assign rvvi.csr_wb[0][0][12'h304] = CSR_W[12'h304];
|
assign rvvi.csr_wb[0][0][12'h304] = CSR_W[12'h304];
|
||||||
|
assign rvvi.csr_wb[0][0][12'h30A] = CSR_W[12'h30A];
|
||||||
assign rvvi.csr_wb[0][0][12'h301] = CSR_W[12'h301];
|
assign rvvi.csr_wb[0][0][12'h301] = CSR_W[12'h301];
|
||||||
assign rvvi.csr_wb[0][0][12'hF14] = CSR_W[12'hF14];
|
assign rvvi.csr_wb[0][0][12'hF14] = CSR_W[12'hF14];
|
||||||
assign rvvi.csr_wb[0][0][12'h340] = CSR_W[12'h340];
|
assign rvvi.csr_wb[0][0][12'h340] = CSR_W[12'h340];
|
||||||
@ -411,6 +420,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
assign rvvi.csr_wb[0][0][12'h105] = CSR_W[12'h105];
|
assign rvvi.csr_wb[0][0][12'h105] = CSR_W[12'h105];
|
||||||
assign rvvi.csr_wb[0][0][12'h141] = CSR_W[12'h141];
|
assign rvvi.csr_wb[0][0][12'h141] = CSR_W[12'h141];
|
||||||
assign rvvi.csr_wb[0][0][12'h106] = CSR_W[12'h106];
|
assign rvvi.csr_wb[0][0][12'h106] = CSR_W[12'h106];
|
||||||
|
assign rvvi.csr_wb[0][0][12'h10A] = CSR_W[12'h10A];
|
||||||
assign rvvi.csr_wb[0][0][12'h180] = CSR_W[12'h180];
|
assign rvvi.csr_wb[0][0][12'h180] = CSR_W[12'h180];
|
||||||
assign rvvi.csr_wb[0][0][12'h140] = CSR_W[12'h140];
|
assign rvvi.csr_wb[0][0][12'h140] = CSR_W[12'h140];
|
||||||
assign rvvi.csr_wb[0][0][12'h143] = CSR_W[12'h143];
|
assign rvvi.csr_wb[0][0][12'h143] = CSR_W[12'h143];
|
||||||
@ -431,6 +441,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
assign rvvi.csr[0][0][12'h303] = CSRArray[12'h303];
|
assign rvvi.csr[0][0][12'h303] = CSRArray[12'h303];
|
||||||
assign rvvi.csr[0][0][12'h344] = CSRArray[12'h344];
|
assign rvvi.csr[0][0][12'h344] = CSRArray[12'h344];
|
||||||
assign rvvi.csr[0][0][12'h304] = CSRArray[12'h304];
|
assign rvvi.csr[0][0][12'h304] = CSRArray[12'h304];
|
||||||
|
assign rvvi.csr[0][0][12'h30A] = CSRArray[12'h30A];
|
||||||
assign rvvi.csr[0][0][12'h301] = CSRArray[12'h301];
|
assign rvvi.csr[0][0][12'h301] = CSRArray[12'h301];
|
||||||
assign rvvi.csr[0][0][12'hF14] = CSRArray[12'hF14];
|
assign rvvi.csr[0][0][12'hF14] = CSRArray[12'hF14];
|
||||||
assign rvvi.csr[0][0][12'h340] = CSRArray[12'h340];
|
assign rvvi.csr[0][0][12'h340] = CSRArray[12'h340];
|
||||||
@ -448,6 +459,7 @@ module wallyTracer(rvviTrace rvvi);
|
|||||||
assign rvvi.csr[0][0][12'h105] = CSRArray[12'h105];
|
assign rvvi.csr[0][0][12'h105] = CSRArray[12'h105];
|
||||||
assign rvvi.csr[0][0][12'h141] = CSRArray[12'h141];
|
assign rvvi.csr[0][0][12'h141] = CSRArray[12'h141];
|
||||||
assign rvvi.csr[0][0][12'h106] = CSRArray[12'h106];
|
assign rvvi.csr[0][0][12'h106] = CSRArray[12'h106];
|
||||||
|
assign rvvi.csr[0][0][12'h10A] = CSRArray[12'h10A];
|
||||||
assign rvvi.csr[0][0][12'h180] = CSRArray[12'h180];
|
assign rvvi.csr[0][0][12'h180] = CSRArray[12'h180];
|
||||||
assign rvvi.csr[0][0][12'h140] = CSRArray[12'h140];
|
assign rvvi.csr[0][0][12'h140] = CSRArray[12'h140];
|
||||||
assign rvvi.csr[0][0][12'h143] = CSRArray[12'h143];
|
assign rvvi.csr[0][0][12'h143] = CSRArray[12'h143];
|
||||||
|
@ -113,8 +113,6 @@ module testbenchfp;
|
|||||||
|
|
||||||
`include "parameter-defs.vh"
|
`include "parameter-defs.vh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// ||||||||| |||||||| ||||||| ||||||||| ||||||| |||||||| |||
|
// ||||||||| |||||||| ||||||| ||||||||| ||||||| |||||||| |||
|
||||||
@ -680,11 +678,11 @@ module testbenchfp;
|
|||||||
// instantiate devices under test
|
// instantiate devices under test
|
||||||
if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "sub" | TEST === "all") begin : fma
|
if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "sub" | TEST === "all") begin : fma
|
||||||
fma #(P) fma(.Xs(Xs), .Ys(Ys), .Zs(Zs),
|
fma #(P) fma(.Xs(Xs), .Ys(Ys), .Zs(Zs),
|
||||||
.Xe(Xe), .Ye(Ye), .Ze(Ze),
|
.Xe(Xe), .Ye(Ye), .Ze(Ze),
|
||||||
.Xm(Xm), .Ym(Ym), .Zm(Zm),
|
.Xm(Xm), .Ym(Ym), .Zm(Zm),
|
||||||
.XZero, .YZero, .ZZero, .Ss, .Se,
|
.XZero, .YZero, .ZZero, .Ss, .Se,
|
||||||
.OpCtrl(OpCtrlVal), .Sm, .InvA, .SCnt, .As, .Ps,
|
.OpCtrl(OpCtrlVal), .Sm, .InvA, .SCnt, .As, .Ps,
|
||||||
.ASticky);
|
.ASticky);
|
||||||
end
|
end
|
||||||
|
|
||||||
postprocess #(P) postprocess(.Xs(Xs), .Ys(Ys), .PostProcSel(UnitVal[1:0]),
|
postprocess #(P) postprocess(.Xs(Xs), .Ys(Ys), .PostProcSel(UnitVal[1:0]),
|
||||||
@ -699,13 +697,13 @@ module testbenchfp;
|
|||||||
.PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes));
|
.PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes));
|
||||||
|
|
||||||
if (TEST === "cvtfp" | TEST === "cvtint" | TEST === "all") begin : fcvt
|
if (TEST === "cvtfp" | TEST === "cvtint" | TEST === "all") begin : fcvt
|
||||||
fcvt #(P) fcvt (.Xs(Xs), .Xe(Xe), .Xm(Xm), .Int(SrcA), .ToInt(WriteIntVal),
|
fcvt fcvt (.Xs(Xs), .Xe(Xe), .Xm(Xm), .Int(SrcA), .ToInt(WriteIntVal),
|
||||||
.XZero(XZero), .OpCtrl(OpCtrlVal), .IntZero,
|
.XZero(XZero), .OpCtrl(OpCtrlVal), .IntZero,
|
||||||
.Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), .ResSubnormUf(CvtResSubnormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE));
|
.Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), .ResSubnormUf(CvtResSubnormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE));
|
||||||
end
|
end
|
||||||
|
|
||||||
if (TEST === "cmp" | TEST === "all") begin: fcmp
|
if (TEST === "cmp" | TEST === "all") begin: fcmp
|
||||||
fcmp #(P) fcmp (.Fmt(ModFmt), .OpCtrl(OpCtrlVal), .Xs, .Ys, .Xe, .Ye,
|
fcmp fcmp (.Fmt(ModFmt), .OpCtrl(OpCtrlVal), .Xs, .Ys, .Xe, .Ye,
|
||||||
.Xm, .Ym, .XZero, .YZero, .CmpIntRes(CmpRes),
|
.Xm, .Ym, .XZero, .YZero, .CmpIntRes(CmpRes),
|
||||||
.XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes));
|
.XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes));
|
||||||
end
|
end
|
||||||
@ -892,13 +890,13 @@ always @(negedge clk) begin
|
|||||||
// check if result is correct
|
// check if result is correct
|
||||||
// - wait till the division result is done or one extra cylcle for early termination (to simulate the EM pipline stage)
|
// - wait till the division result is done or one extra cylcle for early termination (to simulate the EM pipline stage)
|
||||||
// if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&~((FDivBusyE===1'b1)|DivStart)&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin
|
// if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&~((FDivBusyE===1'b1)|DivStart)&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin
|
||||||
ResMatch = (Res === Ans | NaNGood | NaNGood === 1'bx);
|
assign ResMatch = (Res === Ans | NaNGood | NaNGood === 1'bx);
|
||||||
FlagMatch = (ResFlg === AnsFlg | AnsFlg === 5'bx);
|
assign FlagMatch = (ResFlg === AnsFlg | AnsFlg === 5'bx);
|
||||||
divsqrtop = OpCtrlVal == `SQRT_OPCTRL | OpCtrlVal == `DIV_OPCTRL;
|
assign divsqrtop = OpCtrlVal == `SQRT_OPCTRL | OpCtrlVal == `DIV_OPCTRL;
|
||||||
assign DivDone = OldFDivBusyE & ~FDivBusyE;
|
assign DivDone = OldFDivBusyE & ~FDivBusyE;
|
||||||
|
|
||||||
//assign divsqrtop = OpCtrl[TestNum] == `SQRT_OPCTRL | OpCtrl[TestNum] == `DIV_OPCTRL;
|
//assign divsqrtop = OpCtrl[TestNum] == `SQRT_OPCTRL | OpCtrl[TestNum] == `DIV_OPCTRL;
|
||||||
CheckNow = (DivDone | ~divsqrtop) & (UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT);
|
assign CheckNow = (DivDone | ~divsqrtop) & (UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT);
|
||||||
if(~(ResMatch & FlagMatch) & CheckNow) begin
|
if(~(ResMatch & FlagMatch) & CheckNow) begin
|
||||||
// if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&(DivDone | (TEST != "sqrt" & TEST != "div"))&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin
|
// if(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&(DivDone | (TEST != "sqrt" & TEST != "div"))&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin
|
||||||
errors += 1;
|
errors += 1;
|
||||||
@ -974,10 +972,10 @@ module readvectors (
|
|||||||
output logic [`FLEN-1:0] Ans,
|
output logic [`FLEN-1:0] Ans,
|
||||||
output logic [`XLEN-1:0] SrcA,
|
output logic [`XLEN-1:0] SrcA,
|
||||||
output logic [4:0] AnsFlg,
|
output logic [4:0] AnsFlg,
|
||||||
output logic Xs, Ys, Zs, // sign bits of XYZ
|
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 [`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 [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
|
||||||
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
|
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
|
||||||
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
|
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
|
||||||
output logic XSubnorm, ZSubnorm, // is XYZ denormalized
|
output logic XSubnorm, ZSubnorm, // is XYZ denormalized
|
||||||
output logic XZero, YZero, ZZero, // is XYZ zero
|
output logic XZero, YZero, ZZero, // is XYZ zero
|
||||||
@ -986,6 +984,7 @@ module readvectors (
|
|||||||
output logic DivStart,
|
output logic DivStart,
|
||||||
output logic [`FLEN-1:0] X, Y, Z, XPostBox
|
output logic [`FLEN-1:0] X, Y, Z, XPostBox
|
||||||
);
|
);
|
||||||
|
|
||||||
logic XEn, YEn, ZEn;
|
logic XEn, YEn, ZEn;
|
||||||
|
|
||||||
`include "parameter-defs.vh"
|
`include "parameter-defs.vh"
|
||||||
@ -1346,7 +1345,6 @@ module readvectors (
|
|||||||
assign YEn = ~((Unit == `CVTINTUNIT)|(Unit == `CVTFPUNIT)|((Unit == `DIVUNIT)&OpCtrl[0]));
|
assign YEn = ~((Unit == `CVTINTUNIT)|(Unit == `CVTFPUNIT)|((Unit == `DIVUNIT)&OpCtrl[0]));
|
||||||
assign ZEn = (Unit == `FMAUNIT);
|
assign ZEn = (Unit == `FMAUNIT);
|
||||||
|
|
||||||
|
|
||||||
unpack #(P) unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze,
|
unpack #(P) unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze,
|
||||||
.Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN,
|
.Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN,
|
||||||
.XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf,
|
.XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf,
|
||||||
|
@ -866,10 +866,12 @@ module testbench;
|
|||||||
"medeleg": `checkCSR(`CSR_BASE.csrm.MEDELEG_REGW)
|
"medeleg": `checkCSR(`CSR_BASE.csrm.MEDELEG_REGW)
|
||||||
"mepc": `checkCSR(`CSR_BASE.csrm.MEPC_REGW)
|
"mepc": `checkCSR(`CSR_BASE.csrm.MEPC_REGW)
|
||||||
"mtval": `checkCSR(`CSR_BASE.csrm.MTVAL_REGW)
|
"mtval": `checkCSR(`CSR_BASE.csrm.MTVAL_REGW)
|
||||||
|
"menvcfg": `checkCSR(`CSR_BASE.csrm.MENVCFG_REGW)
|
||||||
"sepc": `checkCSR(`CSR_BASE.csrs.csrs.SEPC_REGW)
|
"sepc": `checkCSR(`CSR_BASE.csrs.csrs.SEPC_REGW)
|
||||||
"scause": `checkCSR(`CSR_BASE.csrs.csrs.SCAUSE_REGW)
|
"scause": `checkCSR(`CSR_BASE.csrs.csrs.SCAUSE_REGW)
|
||||||
"stvec": `checkCSR(`CSR_BASE.csrs.csrs.STVEC_REGW)
|
"stvec": `checkCSR(`CSR_BASE.csrs.csrs.STVEC_REGW)
|
||||||
"stval": `checkCSR(`CSR_BASE.csrs.csrs.STVAL_REGW)
|
"stval": `checkCSR(`CSR_BASE.csrs.csrs.STVAL_REGW)
|
||||||
|
"senvcfg": `checkCSR(`CSR_BASE.csrs.SENVCFG_REGW)
|
||||||
"mip": begin
|
"mip": begin
|
||||||
`checkCSR(`CSR_BASE.csrm.MIP_REGW)
|
`checkCSR(`CSR_BASE.csrm.MIP_REGW)
|
||||||
if(!NO_SPOOFING) begin
|
if(!NO_SPOOFING) begin
|
||||||
|
@ -33,5 +33,8 @@ main:
|
|||||||
csrrw t0, satp, zero
|
csrrw t0, satp, zero
|
||||||
csrrw t0, stvec, zero
|
csrrw t0, stvec, zero
|
||||||
csrrw t0, sscratch, zero
|
csrrw t0, sscratch, zero
|
||||||
|
li t0, -2
|
||||||
|
csrrw t1, menvcfg, t0
|
||||||
|
csrrw t2, senvcfg, t0
|
||||||
|
|
||||||
j done
|
j done
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
FFFFFFFF # stimecmp readback
|
||||||
|
80000000 # menvcfg readback
|
||||||
00000aaa # Test 5.3.1.4: readback value from writing mie to enable interrupts # skipping instruction address fault since they're impossible with compressed instrs enabled
|
00000aaa # Test 5.3.1.4: readback value from writing mie to enable interrupts # skipping instruction address fault since they're impossible with compressed instrs enabled
|
||||||
00000001 # mcause from an instruction access fault
|
00000001 # mcause from an instruction access fault
|
||||||
00000000 # mtval of faulting instruction address (0x0)
|
00000000 # mtval of faulting instruction address (0x0)
|
||||||
|
@ -280,7 +280,7 @@ end_trap_triggers:
|
|||||||
la t4, 0x02004000 // MTIMECMP register in CLINT
|
la t4, 0x02004000 // MTIMECMP register in CLINT
|
||||||
li t5, 0xFFFFFFFF
|
li t5, 0xFFFFFFFF
|
||||||
sw t5, 0(t4) // set mtimecmp to 0xFFFFFFFF to really make sure time interrupts don't go off immediately after being enabled
|
sw t5, 0(t4) // set mtimecmp to 0xFFFFFFFF to really make sure time interrupts don't go off immediately after being enabled
|
||||||
|
|
||||||
j trap_handler_end_\MODE\() // skip the trap handler when it is being defined.
|
j trap_handler_end_\MODE\() // skip the trap handler when it is being defined.
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "WALLY-TEST-LIB-32.h"
|
#include "WALLY-TEST-LIB-32.h"
|
||||||
|
|
||||||
RVTEST_ISA("RV32I_Zicsr")
|
RVTEST_ISA("RV32I_Sstc_Zicsr")
|
||||||
RVTEST_CASE(0,"//check ISA:=regex(.*32.*);check ISA:=regex(.*I.*); def Drvtest_mtrap_routine=True;def TEST_CASE_1=True;def NO_SAIL=True;",trap)
|
RVTEST_CASE(0,"//check ISA:=regex(.*32.*);check ISA:=regex(.*I.*); def Drvtest_mtrap_routine=True;def TEST_CASE_1=True;def NO_SAIL=True;",trap)
|
||||||
|
|
||||||
INIT_TESTS
|
INIT_TESTS
|
||||||
@ -34,8 +34,9 @@ TRAP_HANDLER m, EXT_SIGNATURE=1 // turn on recording mtval and status bits on tr
|
|||||||
|
|
||||||
li x28, 0x8
|
li x28, 0x8
|
||||||
csrs mstatus, x28 // set mstatus.MIE bit to 1
|
csrs mstatus, x28 // set mstatus.MIE bit to 1
|
||||||
WRITE_READ_CSR mie, 0xFFF // Enable interrupts from all sources // *** commented out until I can get the trap handler (and spike for time interrupts) to work correctly with interrupts
|
WRITE_READ_CSR stimecmp, 0xFFFFFFFF // set timer to high value so it doesn't go off immediately
|
||||||
|
WRITE_READ_CSR menvcfgh, 0x80000000 // Enable menvcfg.STCE
|
||||||
|
WRITE_READ_CSR mie, 0xFFF // Enable interrupts from all sources
|
||||||
// test 5.3.1.4 Basic trap tests
|
// test 5.3.1.4 Basic trap tests
|
||||||
|
|
||||||
// instr address misaligned instructions are excluded from this test since they are impossible to cause when compressed instructions are enabled.
|
// instr address misaligned instructions are excluded from this test since they are impossible to cause when compressed instructions are enabled.
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
FFFFFFFF # stimecmp low bits
|
||||||
|
00000000 # stimecmp high bits
|
||||||
|
00000000 # menvcfg low bits
|
||||||
|
80000000 # menvcfg high bits
|
||||||
00000aaa # Test 5.3.1.4: readback value from writing mie to enable interrupts
|
00000aaa # Test 5.3.1.4: readback value from writing mie to enable interrupts
|
||||||
00000000 # skipping instruction address fault since they're impossible with compressed instrs enabled
|
00000000 # skipping instruction address fault since they're impossible with compressed instrs enabled
|
||||||
00000001 # mcause from an instruction access fault
|
00000001 # mcause from an instruction access fault
|
||||||
|
@ -274,7 +274,7 @@ end_trap_triggers:
|
|||||||
la t4, 0x02004000 // MTIMECMP register in CLINT
|
la t4, 0x02004000 // MTIMECMP register in CLINT
|
||||||
li t5, 0xFFFFFFFF
|
li t5, 0xFFFFFFFF
|
||||||
sd t5, 0(t4) // set mtimecmp to 0xFFFFFFFF to really make sure time interrupts don't go off immediately after being enabled
|
sd t5, 0(t4) // set mtimecmp to 0xFFFFFFFF to really make sure time interrupts don't go off immediately after being enabled
|
||||||
|
|
||||||
j trap_handler_end_\MODE\() // skip the trap handler when it is being defined.
|
j trap_handler_end_\MODE\() // skip the trap handler when it is being defined.
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
#include "WALLY-TEST-LIB-64.h"
|
#include "WALLY-TEST-LIB-64.h"
|
||||||
RVTEST_ISA("RV64I_Zicsr")
|
RVTEST_ISA("RV64I_Sstc_Zicsr")
|
||||||
RVTEST_CASE(0,"//check ISA:=regex(.*64.*);check ISA:=regex(.*I.*);def TEST_CASE_1=True;def NO_SAIL=True;",trap)
|
RVTEST_CASE(0,"//check ISA:=regex(.*64.*);check ISA:=regex(.*I.*);def TEST_CASE_1=True;def NO_SAIL=True;",trap)
|
||||||
|
|
||||||
INIT_TESTS
|
INIT_TESTS
|
||||||
@ -33,7 +33,9 @@ TRAP_HANDLER m, EXT_SIGNATURE=1 // turn on recording mtval and status bits on tr
|
|||||||
|
|
||||||
li x28, 0x8
|
li x28, 0x8
|
||||||
csrs mstatus, x28 // set mstatus.MIE bit to 1
|
csrs mstatus, x28 // set mstatus.MIE bit to 1
|
||||||
WRITE_READ_CSR mie, 0xFFF // Enable interrupts from all sources
|
WRITE_READ_CSR stimecmp, 0xFFFFFFFF // set timer to high value so it doesn't go off immediately
|
||||||
|
WRITE_READ_CSR menvcfg, 0x8000000000000000 // Enable menvcfg.STCE
|
||||||
|
WRITE_READ_CSR mie, 0xFFF // Enable interrupts from all sources
|
||||||
|
|
||||||
// test 5.3.1.4 Basic trap tests
|
// test 5.3.1.4 Basic trap tests
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user