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:
|
||||
make install
|
||||
make regression
|
||||
make testfloat
|
||||
make riscof
|
||||
make verify
|
||||
make coverage
|
||||
make benchmarks
|
||||
|
||||
# install copies over the Makefile.include from riscv-isa-sim
|
||||
# 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
|
||||
##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
|
||||
|
||||
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:
|
||||
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)/crt.S $(PORT_DIR)/encoding.h $(PORT_DIR)/util.h $(PORT_DIR)/syscalls.c
|
||||
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 \
|
||||
-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 \
|
||||
|
@ -45,7 +45,7 @@ sudo mkdir -p $RISCV
|
||||
# Update and Upgrade tools (see https://itsfoss.com/apt-update-vs-upgrade/)
|
||||
sudo apt update -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.
|
||||
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=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 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
|
||||
|
@ -40,10 +40,16 @@ localparam IEEE754 = 0;
|
||||
localparam MISA = (32'h0014112D);
|
||||
localparam ZICSR_SUPPORTED = 1;
|
||||
localparam ZIFENCEI_SUPPORTED = 1;
|
||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
||||
localparam ZICNTR_SUPPORTED = 1;
|
||||
localparam ZIHPM_SUPPORTED = 1;
|
||||
localparam COUNTERS = 12'd32;
|
||||
localparam ZFH_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
|
||||
localparam BUS_SUPPORTED = 1;
|
||||
|
@ -41,9 +41,14 @@ localparam MISA = (32'h00000010);
|
||||
localparam ZICSR_SUPPORTED = 0;
|
||||
localparam ZIFENCEI_SUPPORTED = 0;
|
||||
localparam COUNTERS = 12'd0;
|
||||
localparam ZICOUNTERS_SUPPORTED = 0;
|
||||
localparam ZICNTR_SUPPORTED = 0;
|
||||
localparam ZIHPM_SUPPORTED = 0;
|
||||
localparam ZFH_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
|
||||
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 ZIFENCEI_SUPPORTED = 1;
|
||||
localparam COUNTERS = 12'd32;
|
||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
||||
localparam ZICNTR_SUPPORTED = 1;
|
||||
localparam ZIHPM_SUPPORTED = 1;
|
||||
localparam ZFH_SUPPORTED = 0;
|
||||
localparam SSTC_SUPPORTED = 1;
|
||||
localparam ZICBOM_SUPPORTED = 0;
|
||||
localparam ZICBOZ_SUPPORTED = 0;
|
||||
localparam ZICBOP_SUPPORTED = 0;
|
||||
localparam SVPBMT_SUPPORTED = 0;
|
||||
|
||||
// LSU microarchitectural Features
|
||||
localparam BUS_SUPPORTED = 1;
|
||||
|
@ -40,10 +40,15 @@ localparam IEEE754 = 0;
|
||||
localparam MISA = (32'h00000104);
|
||||
localparam ZICSR_SUPPORTED = 0;
|
||||
localparam ZIFENCEI_SUPPORTED = 0;
|
||||
localparam COUNTERS = 12'd32;
|
||||
localparam ZICOUNTERS_SUPPORTED = 0;
|
||||
localparam COUNTERS = 0;
|
||||
localparam ZICNTR_SUPPORTED = 0;
|
||||
localparam ZIHPM_SUPPORTED = 0;
|
||||
localparam ZFH_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
|
||||
localparam BUS_SUPPORTED = 0;
|
||||
|
@ -40,9 +40,14 @@ localparam MISA = (32'h00000104 | 1 << 20 | 1 << 18 | 1 << 12);
|
||||
localparam ZICSR_SUPPORTED = 1;
|
||||
localparam ZIFENCEI_SUPPORTED = 1;
|
||||
localparam COUNTERS = 12'd32;
|
||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
||||
localparam ZICNTR_SUPPORTED = 1;
|
||||
localparam ZIHPM_SUPPORTED = 1;
|
||||
localparam ZFH_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
|
||||
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 ZIFENCEI_SUPPORTED = 1;
|
||||
localparam COUNTERS = 12'd32;
|
||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
||||
localparam ZICNTR_SUPPORTED = 1;
|
||||
localparam ZIHPM_SUPPORTED = 1;
|
||||
localparam ZFH_SUPPORTED = 1;
|
||||
localparam SSTC_SUPPORTED = 0;
|
||||
localparam ZICBOM_SUPPORTED = 0;
|
||||
localparam ZICBOZ_SUPPORTED = 0;
|
||||
localparam ZICBOP_SUPPORTED = 0;
|
||||
localparam SVPBMT_SUPPORTED = 0;
|
||||
|
||||
// LSU microarchitectural Features
|
||||
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 ZIFENCEI_SUPPORTED = 1;
|
||||
localparam COUNTERS = 12'd32;
|
||||
localparam ZICOUNTERS_SUPPORTED = 1;
|
||||
localparam ZICNTR_SUPPORTED = 1;
|
||||
localparam ZIHPM_SUPPORTED = 1;
|
||||
localparam ZFH_SUPPORTED = 0;
|
||||
localparam SSTC_SUPPORTED = 1;
|
||||
localparam ZICBOM_SUPPORTED = 0;
|
||||
localparam ZICBOZ_SUPPORTED = 0;
|
||||
localparam ZICBOP_SUPPORTED = 0;
|
||||
localparam SVPBMT_SUPPORTED = 0;
|
||||
|
||||
// LSU microarchitectural Features
|
||||
localparam BUS_SUPPORTED = 1;
|
||||
|
@ -40,10 +40,15 @@ localparam IEEE754 = 0;
|
||||
localparam MISA = (32'h00000104);
|
||||
localparam ZICSR_SUPPORTED = 0;
|
||||
localparam ZIFENCEI_SUPPORTED = 0;
|
||||
localparam COUNTERS = 12'd32;
|
||||
localparam ZICOUNTERS_SUPPORTED = 0;
|
||||
localparam COUNTERS = 0;
|
||||
localparam ZICNTR_SUPPORTED = 0;
|
||||
localparam ZIHPM_SUPPORTED = 0;
|
||||
localparam ZFH_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
|
||||
localparam BUS_SUPPORTED = 0;
|
||||
|
@ -11,20 +11,25 @@ parameter cvw_t P = '{
|
||||
ZICSR_SUPPORTED : ZICSR_SUPPORTED,
|
||||
ZIFENCEI_SUPPORTED : ZIFENCEI_SUPPORTED,
|
||||
COUNTERS : COUNTERS,
|
||||
ZICOUNTERS_SUPPORTED : ZICOUNTERS_SUPPORTED,
|
||||
ZICNTR_SUPPORTED : ZICNTR_SUPPORTED,
|
||||
ZIHPM_SUPPORTED : ZIHPM_SUPPORTED,
|
||||
ZFH_SUPPORTED : ZFH_SUPPORTED,
|
||||
SSTC_SUPPORTED : SSTC_SUPPORTED,
|
||||
VIRTMEM_SUPPORTED : VIRTMEM_SUPPORTED,
|
||||
VECTORED_INTERRUPTS_SUPPORTED : VECTORED_INTERRUPTS_SUPPORTED,
|
||||
BIGENDIAN_SUPPORTED : BIGENDIAN_SUPPORTED,
|
||||
SVADU_SUPPORTED : SVADU_SUPPORTED,
|
||||
ZMMUL_SUPPORTED : ZMMUL_SUPPORTED,
|
||||
VIRTMEM_SUPPORTED : VIRTMEM_SUPPORTED,
|
||||
VECTORED_INTERRUPTS_SUPPORTED : VECTORED_INTERRUPTS_SUPPORTED,
|
||||
BIGENDIAN_SUPPORTED : BIGENDIAN_SUPPORTED,
|
||||
SVADU_SUPPORTED : SVADU_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,
|
||||
DCACHE_SUPPORTED : DCACHE_SUPPORTED,
|
||||
ICACHE_SUPPORTED : ICACHE_SUPPORTED,
|
||||
ITLB_ENTRIES : ITLB_ENTRIES,
|
||||
DTLB_ENTRIES : DTLB_ENTRIES,
|
||||
DCACHE_NUMWAYS : DCACHE_NUMWAYS,
|
||||
DCACHE_SUPPORTED : DCACHE_SUPPORTED,
|
||||
ICACHE_SUPPORTED : ICACHE_SUPPORTED,
|
||||
ITLB_ENTRIES : ITLB_ENTRIES,
|
||||
DTLB_ENTRIES : DTLB_ENTRIES,
|
||||
DCACHE_NUMWAYS : DCACHE_NUMWAYS,
|
||||
DCACHE_WAYSIZEINBYTES : DCACHE_WAYSIZEINBYTES,
|
||||
DCACHE_LINELENINBITS : DCACHE_LINELENINBITS,
|
||||
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 SETLEN = $clog2(NUMLINES); // Number of set 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 LOGCWPL = $clog2(CACHEWORDSPERLINE);// Log2 of ^
|
||||
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 LineByteMask = '1;
|
||||
end
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
assign LRUUpdate[lchild] = ~WayEncoded[r];
|
||||
assign LRUUpdate[rchild] = WayEncoded[r];
|
||||
end
|
||||
else begin
|
||||
end else begin
|
||||
assign LRUUpdate[lchild] = LRUUpdate[node] & ~WayEncoded[r];
|
||||
assign LRUUpdate[rchild] = LRUUpdate[node] & WayEncoded[r];
|
||||
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.
|
||||
assign FlushWayEn = FlushWay & SelFlush;
|
||||
assign SelNonHit = FlushWayEn | SetValid | SelWriteback;
|
||||
end
|
||||
else begin:flushlogic // no flush operation for read-only caches.
|
||||
end else begin:flushlogic // no flush operation for read-only caches.
|
||||
assign SelTag = VictimWay;
|
||||
assign SelNonHit = SetValid;
|
||||
end
|
||||
@ -135,8 +134,7 @@ module cacheway #(parameter PA_BITS, XLEN, NUMLINES=512, LINELEN = 256, TAGLEN =
|
||||
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
|
||||
end
|
||||
else begin:wordram // no byte-enable needed for i$.
|
||||
end else begin:wordram // no byte-enable needed for i$.
|
||||
ram1p1rwe #(.DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
|
||||
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||
@ -154,8 +152,8 @@ module cacheway #(parameter PA_BITS, XLEN, NUMLINES=512, LINELEN = 256, TAGLEN =
|
||||
always_ff @(posedge clk) begin // Valid bit array,
|
||||
if (reset) ValidBits <= #1 '0;
|
||||
if(CacheEn) begin
|
||||
ValidWay <= #1 ValidBits[CacheSet];
|
||||
if(InvalidateCache) ValidBits <= #1 '0; // exclusion-tag: dcache invalidateway
|
||||
ValidWay <= #1 ValidBits[CacheSet];
|
||||
if(InvalidateCache) ValidBits <= #1 '0; // exclusion-tag: dcache invalidateway
|
||||
else if (SetValidEN) ValidBits[CacheSet] <= #1 SetValidWay;
|
||||
end
|
||||
end
|
||||
@ -175,8 +173,4 @@ module cacheway #(parameter PA_BITS, XLEN, NUMLINES=512, LINELEN = 256, TAGLEN =
|
||||
end
|
||||
end
|
||||
end else assign Dirty = 1'b0;
|
||||
|
||||
|
||||
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 [WORDLEN-1:0] ReadDataLineSets [(LINELEN/MUXINTERVAL)-1:0];
|
||||
|
||||
if (PADLEN > 0) begin
|
||||
assign ReadDataLinePad = {{PADLEN{1'b0}}, ReadDataLine};
|
||||
end else assign ReadDataLinePad = ReadDataLine;
|
||||
if (PADLEN > 0) assign ReadDataLinePad = {{PADLEN{1'b0}}, ReadDataLine};
|
||||
else assign ReadDataLinePad = ReadDataLine;
|
||||
|
||||
genvar index;
|
||||
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] HBURST, // AHB burst length
|
||||
// bus interface buses
|
||||
input logic [AHBW-1:0] HRDATA, // AHB read data
|
||||
output logic [PA_BITS-1:0] HADDR, // AHB address
|
||||
output logic [AHBW-1:0] HWDATA, // AHB write data
|
||||
output logic [AHBW/8-1:0] HWSTRB, // AHB byte mask
|
||||
input logic [AHBW-1:0] HRDATA, // AHB read data
|
||||
output logic [PA_BITS-1:0] HADDR, // AHB address
|
||||
output logic [AHBW-1:0] HWDATA, // AHB write data
|
||||
output logic [AHBW/8-1:0] HWSTRB, // AHB byte mask
|
||||
|
||||
// cache interface
|
||||
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 [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 CacheableOrFlushCacheM, // Memory operation is cacheable or flushing D$
|
||||
input logic Cacheable, // Memory operation is cachable
|
||||
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
|
||||
|
||||
// uncached interface
|
||||
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 [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 [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write
|
||||
input logic [2:0] Funct3, // Size of uncached memory operation
|
||||
|
||||
@ -75,11 +75,11 @@ module ahbcacheinterface #(
|
||||
|
||||
|
||||
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 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-1:0] PreHWDATA; // AHB Address phase write data
|
||||
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
|
||||
|
||||
genvar index;
|
||||
|
||||
|
@ -36,19 +36,19 @@ module ahbinterface #(
|
||||
input logic HREADY, // AHB peripheral ready
|
||||
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
|
||||
input logic [XLEN-1:0] HRDATA, // AHB read data
|
||||
output logic [XLEN-1:0] HWDATA, // AHB write data
|
||||
output logic [XLEN/8-1:0] HWSTRB, // AHB byte mask
|
||||
input logic [XLEN-1:0] HRDATA, // AHB read data
|
||||
output logic [XLEN-1:0] HWDATA, // AHB write data
|
||||
output logic [XLEN/8-1:0] HWSTRB, // AHB byte mask
|
||||
|
||||
// lsu/ifu interface
|
||||
input logic Stall, // Core pipeline is stalled
|
||||
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 [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/8-1:0] ByteMask, // Bytes enables within a word
|
||||
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 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;
|
||||
|
@ -46,14 +46,14 @@ module controllerinput #(
|
||||
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] 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
|
||||
// controller output
|
||||
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 [2:0] HSIZEOut, // Arbitrated manager transaction. AHB transaction width
|
||||
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
|
||||
);
|
||||
|
||||
@ -61,7 +61,7 @@ module controllerinput #(
|
||||
logic [2:0] HSIZESave;
|
||||
logic [2:0] HBURSTSave;
|
||||
logic [1:0] HTRANSSave;
|
||||
logic [PA_BITS-1:0] HADDRSave;
|
||||
logic [PA_BITS-1:0] HADDRSave;
|
||||
|
||||
if (SAVE_ENABLED) begin
|
||||
flopenr #(1+3+3+2+PA_BITS) SaveReg(HCLK, ~HRESETn, Save,
|
||||
@ -83,6 +83,3 @@ module controllerinput #(
|
||||
assign HREADYOut = HREADYIn & ~Disable;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
@ -37,25 +37,25 @@ module ebu #(parameter XLEN, PA_BITS, AHBW)(
|
||||
input logic [1:0] IFUHTRANS, // IFU AHB transaction request
|
||||
input logic [2:0] IFUHSIZE, // IFU AHB transaction size
|
||||
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
|
||||
// Signals from LSU
|
||||
input logic [1:0] LSUHTRANS, // LSU AHB transaction request
|
||||
input logic LSUHWRITE, // LSU AHB transaction direction. 1: write, 0: read
|
||||
input logic [2:0] LSUHSIZE, // LSU AHB size
|
||||
input logic [2:0] LSUHBURST, // LSU AHB burst length
|
||||
input logic [PA_BITS-1:0] LSUHADDR, // LSU AHB address
|
||||
input logic [XLEN-1:0] LSUHWDATA, // initially support AHBW = XLEN
|
||||
input logic [XLEN/8-1:0] LSUHWSTRB, // AHB byte mask
|
||||
input logic [PA_BITS-1:0] LSUHADDR, // LSU AHB address
|
||||
input logic [XLEN-1:0] LSUHWDATA, // initially support AHBW = XLEN
|
||||
input logic [XLEN/8-1:0] LSUHWSTRB, // AHB byte mask
|
||||
output logic LSUHREADY, // AHB peripheral. Never gated as LSU always has priority
|
||||
|
||||
// AHB-Lite external signals
|
||||
output logic HCLK, HRESETn,
|
||||
input logic HREADY, // AHB peripheral ready
|
||||
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 [AHBW-1:0] HWDATA, // AHB Write data after arbitration
|
||||
output logic [XLEN/8-1:0] HWSTRB, // AHB byte write enables 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 [XLEN/8-1:0] HWSTRB, // AHB byte write enables after arbitration
|
||||
output logic HWRITE, // AHB transaction direction after arbitration
|
||||
output logic [2:0] HSIZE, // AHB transaction size 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 IFUSelect;
|
||||
|
||||
logic [PA_BITS-1:0] IFUHADDROut;
|
||||
logic [PA_BITS-1:0] IFUHADDROut;
|
||||
logic [1:0] IFUHTRANSOut;
|
||||
logic [2:0] IFUHBURSTOut;
|
||||
logic [2:0] IFUHSIZEOut;
|
||||
logic IFUHWRITEOut;
|
||||
|
||||
logic [PA_BITS-1:0] LSUHADDROut;
|
||||
logic [PA_BITS-1:0] LSUHADDROut;
|
||||
logic [1:0] LSUHTRANSOut;
|
||||
logic [2:0] LSUHBURSTOut;
|
||||
logic [2:0] LSUHSIZEOut;
|
||||
|
@ -33,7 +33,7 @@ module fclassify import cvw::*; #(parameter cvw_t P) (
|
||||
input logic XSubnorm, // is Subnormal
|
||||
input logic XZero, // is zero
|
||||
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
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
///////////////////////////////////////////
|
||||
// fcmp.sv
|
||||
//
|
||||
@ -36,23 +35,23 @@
|
||||
|
||||
module fcmp import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.FMTBITS-1:0] Fmt, // format of fp number
|
||||
input logic [2:0] OpCtrl, // see above table
|
||||
input logic Xs, Ys, // input signs
|
||||
input logic [2:0] OpCtrl, // see above table
|
||||
input logic Xs, Ys, // input signs
|
||||
input logic [P.NE-1:0] Xe, Ye, // input exponents
|
||||
input logic [P.NF:0] Xm, Ym, // input mantissa
|
||||
input logic XZero, YZero, // is zero
|
||||
input logic XNaN, YNaN, // is NaN
|
||||
input logic XSNaN, YSNaN, // is signaling NaN
|
||||
input logic XZero, YZero, // is zero
|
||||
input logic XNaN, YNaN, // is NaN
|
||||
input logic XSNaN, YSNaN, // is signaling NaN
|
||||
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.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 BothZero; // are both inputs zero
|
||||
logic EitherNaN, EitherSNaN; // are either input a (signaling) NaN
|
||||
logic BothZero; // are both inputs zero
|
||||
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 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 EitherSNaN = XSNaN|YSNaN;
|
||||
|
||||
|
||||
// flags
|
||||
// Min/Max - if an input is a signaling NaN set invalid flag
|
||||
// LT/LE - signaling - sets invalid if NaN input
|
||||
@ -85,11 +83,11 @@ module fcmp import cvw::*; #(parameter cvw_t P) (
|
||||
// select the NaN result
|
||||
if (P.FPSIZES == 1)
|
||||
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)
|
||||
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)
|
||||
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)};
|
||||
endcase
|
||||
|
||||
|
||||
// Min/Max
|
||||
// - outputs the min/max of X and Y
|
||||
// - -0 < 0
|
||||
@ -154,5 +151,4 @@ module fcmp import cvw::*; #(parameter cvw_t P) (
|
||||
// - inf = inf and -inf = -inf
|
||||
// - return 0 if comparison with NaN (unordered)
|
||||
assign CmpIntRes = {(P.XLEN-1)'(0), (((EQ|BothZero)&OpCtrl[1])|(LT&OpCtrl[0]&~BothZero))&~EitherNaN};
|
||||
|
||||
endmodule
|
||||
|
@ -27,57 +27,57 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module fctrl import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
// input control signals
|
||||
input logic StallE, StallM, StallW, // stall signals
|
||||
input logic FlushE, FlushM, FlushW, // flush signals
|
||||
input logic IntDivE, // is inteteger division
|
||||
input logic [2:0] FRM_REGW, // rounding mode from CSR
|
||||
input logic [1:0] STATUS_FS, // is FPU enabled?
|
||||
input logic FDivBusyE, // is the divider busy
|
||||
input logic StallE, StallM, StallW, // stall signals
|
||||
input logic FlushE, FlushM, FlushW, // flush signals
|
||||
input logic IntDivE, // is inteteger division
|
||||
input logic [2:0] FRM_REGW, // rounding mode from CSR
|
||||
input logic [1:0] STATUS_FS, // is FPU enabled?
|
||||
input logic FDivBusyE, // is the divider busy
|
||||
// intruction
|
||||
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] OpD, // bits 6:0 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 [31:0] InstrD, // the full instruction
|
||||
input logic [6:0] Funct7D, // bits 31:25 of instruction - may contain percision
|
||||
input logic [6:0] OpD, // bits 6:0 of instruction
|
||||
input logic [4:0] Rs2D, // bits 24:20 of instruction
|
||||
input logic [2:0] Funct3D, Funct3E, // bits 14:12 of instruction - may contain rounding mode
|
||||
// input mux selections
|
||||
output logic XEnD, YEnD, ZEnD, // enable inputs
|
||||
output logic XEnE, YEnE, ZEnE, // enable inputs
|
||||
output logic XEnD, YEnD, ZEnD, // enable inputs
|
||||
output logic XEnE, YEnE, ZEnE, // enable inputs
|
||||
// opperation mux selections
|
||||
output logic FCvtIntE, FCvtIntW, // convert to integer opperation
|
||||
output logic [2:0] FrmM, // FP rounding mode
|
||||
output logic FCvtIntE, FCvtIntW, // convert to integer opperation
|
||||
output logic [2:0] FrmM, // FP rounding mode
|
||||
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 FpLoadStoreM, // FP load or store instruction
|
||||
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 [2:0] OpCtrlE, OpCtrlM, // Select which opperation to do in each component
|
||||
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] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage
|
||||
// register control signals
|
||||
output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable
|
||||
output logic FWriteIntE, FWriteIntM, // Write to integer register
|
||||
output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input
|
||||
output logic [4:0] Adr1E, Adr2E, Adr3E, // adresses of each input
|
||||
output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable
|
||||
output logic FWriteIntE, FWriteIntM, // Write to integer register
|
||||
output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input
|
||||
output logic [4:0] Adr1E, Adr2E, Adr3E, // adresses of each input
|
||||
// other control signals
|
||||
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||
output logic FDivStartE, IDivStartE // Start division or squareroot
|
||||
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||
output logic FDivStartE, IDivStartE // Start division or squareroot
|
||||
);
|
||||
|
||||
`define FCTRLW 12
|
||||
|
||||
logic [`FCTRLW-1:0] ControlsD; // control signals
|
||||
logic FRegWriteD; // FP register write enable
|
||||
logic FDivStartD; // start division/sqrt
|
||||
logic FWriteIntD; // integer register write enable
|
||||
logic [2:0] OpCtrlD; // Select which opperation to do in each component
|
||||
logic [1:0] PostProcSelD; // select result in the post processing unit
|
||||
logic [1:0] FResSelD; // Select one of the results that finish in the memory stage
|
||||
logic [2:0] FrmD, FrmE; // FP rounding mode
|
||||
logic [P.FMTBITS-1:0] FmtD; // FP format
|
||||
logic [1:0] Fmt, Fmt2; // format - before possible reduction
|
||||
logic SupportedFmt; // is the format supported
|
||||
logic SupportedFmt2; // is the source format supported for fp -> fp
|
||||
logic FCvtIntD, FCvtIntM; // convert to integer opperation
|
||||
logic [`FCTRLW-1:0] ControlsD; // control signals
|
||||
logic FRegWriteD; // FP register write enable
|
||||
logic FDivStartD; // start division/sqrt
|
||||
logic FWriteIntD; // integer register write enable
|
||||
logic [2:0] OpCtrlD; // Select which opperation to do in each component
|
||||
logic [1:0] PostProcSelD; // select result in the post processing unit
|
||||
logic [1:0] FResSelD; // Select one of the results that finish in the memory stage
|
||||
logic [2:0] FrmD, FrmE; // FP rounding mode
|
||||
logic [P.FMTBITS-1:0] FmtD; // FP format
|
||||
logic [1:0] Fmt, Fmt2; // format - before possible reduction
|
||||
logic SupportedFmt; // is the format supported
|
||||
logic SupportedFmt2; // is the source format supported for fp -> fp
|
||||
logic FCvtIntD, FCvtIntM; // convert to integer opperation
|
||||
|
||||
// FPU Instruction Decoder
|
||||
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
|
||||
else begin
|
||||
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)
|
||||
7'b0000111: case(Funct3D)
|
||||
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;
|
||||
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);
|
||||
end
|
||||
else if (P.FPSIZES == 3|P.FPSIZES == 4)
|
||||
end else if (P.FPSIZES == 3|P.FPSIZES == 4)
|
||||
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.
|
||||
@ -250,12 +249,9 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
||||
((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
|
||||
|
||||
|
||||
|
||||
// Z - fma ops only
|
||||
assign ZEnD = (PostProcSelD==2'b10)&(~OpCtrlD[2]|OpCtrlD[1]); // fma, add, sub
|
||||
|
||||
|
||||
// Final Res Sel:
|
||||
// fp int
|
||||
// 00 other cmp
|
||||
@ -321,7 +317,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// Integer division on FPU divider
|
||||
if (P.M_SUPPORTED & P.IDIV_ON_FPU) assign IDivStartE = IntDivE;
|
||||
else assign IDivStartE = 0;
|
||||
else assign IDivStartE = 0;
|
||||
|
||||
// E/M pipleine register
|
||||
flopenrc #(13+int'(P.FMTBITS)) EMCtrlReg (clk, reset, FlushM, ~StallM,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
///////////////////////////////////////////
|
||||
// fcvt.sv
|
||||
//
|
||||
@ -96,7 +95,7 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
||||
// int -> fp : | positive integer | 00000... (if needed) |
|
||||
// fp -> fp : | fraction | 00000... (if needed) |
|
||||
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
|
||||
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;
|
||||
else Cs = Int[31]&Signed;
|
||||
else Cs = Xs;
|
||||
|
||||
endmodule
|
||||
|
@ -50,9 +50,10 @@ module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) (
|
||||
else if (P.FPSIZES == 3)
|
||||
always_comb
|
||||
case (FmtE)
|
||||
P.FMT: Nf = P.NF;
|
||||
P.FMT1: Nf = P.NF1;
|
||||
P.FMT2: Nf = P.NF2;
|
||||
P.FMT: Nf = P.NF;
|
||||
P.FMT1: Nf = P.NF1;
|
||||
P.FMT2: Nf = P.NF2;
|
||||
default: Nf = 'x; // shouldn't happen
|
||||
endcase
|
||||
else if (P.FPSIZES == 4)
|
||||
always_comb
|
||||
|
@ -56,7 +56,6 @@ module fhazard(
|
||||
// if the needed value is in the writeback stage
|
||||
end else if ((Adr1E == RdW) & FRegWriteW) ForwardXE = 2'b01; // choose FResult64W
|
||||
|
||||
|
||||
// if the needed value is in the memory stage - input 2
|
||||
if ((Adr2E == RdM) & FRegWriteM) begin
|
||||
// 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
|
||||
end else if ((Adr2E == RdW) & FRegWriteW) ForwardYE = 2'b01; // choose FResult64W
|
||||
|
||||
|
||||
// if the needed value is in the memory stage - input 3
|
||||
if ((Adr3E == RdM) & FRegWriteM) begin
|
||||
// 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
|
||||
end else if ((Adr3E == RdW) & FRegWriteW) ForwardZE = 2'b01; // choose FResult64W
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
181
src/fpu/fpu.sv
181
src/fpu/fpu.sv
@ -27,40 +27,40 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module fpu import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
// Hazards
|
||||
input logic StallE, StallM, StallW, // stall signals (from HZU)
|
||||
input logic FlushE, FlushM, FlushW, // flush signals (from HZU)
|
||||
output logic FPUStallD, // Stall the decode stage (To HZU)
|
||||
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU)
|
||||
input logic StallE, StallM, StallW, // stall signals (from HZU)
|
||||
input logic FlushE, FlushM, FlushW, // flush signals (from HZU)
|
||||
output logic FPUStallD, // Stall the decode stage (To HZU)
|
||||
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU)
|
||||
// CSRs
|
||||
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 [1:0] STATUS_FS, // Is floating-point enabled? (From privileged unit)
|
||||
input logic [2:0] FRM_REGW, // Rounding mode (from CSR)
|
||||
// Decode stage
|
||||
input logic [31:0] InstrD, // instruction (from IFU)
|
||||
input logic [31:0] InstrD, // instruction (from IFU)
|
||||
// Execute stage
|
||||
input logic [2:0] Funct3E, // Funct fields of instruction specify type of operations
|
||||
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 [4:0] RdE, // which FP register to write to (from IEU)
|
||||
output logic FWriteIntE, // integer register write enable (to IEU)
|
||||
output logic FCvtIntE, // Convert to int (to IEU)
|
||||
input logic [2:0] Funct3E, // Funct fields of instruction specify type of operations
|
||||
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 [4:0] RdE, // which FP register to write to (from IEU)
|
||||
output logic FWriteIntE, // integer register write enable (to IEU)
|
||||
output logic FCvtIntE, // Convert to int (to IEU)
|
||||
// Memory stage
|
||||
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)
|
||||
output logic FRegWriteM, // FP register write enable (to privileged unit)
|
||||
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.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 [4:0] SetFflagsM, // FPU flags (to privileged unit)
|
||||
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)
|
||||
output logic FRegWriteM, // FP register write enable (to privileged unit)
|
||||
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.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 [4:0] SetFflagsM, // FPU flags (to privileged unit)
|
||||
// Writeback stage
|
||||
input logic [4:0] RdW, // which FP register to write to (from IEU)
|
||||
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 FCvtIntW, // select FCvtIntRes (to IEU)
|
||||
output logic [P.XLEN-1:0] FIntDivResultW // Result from integer division (to 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)
|
||||
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 [P.XLEN-1:0] FIntDivResultW // Result from integer division (to IEU)
|
||||
);
|
||||
|
||||
// RISC-V FPU specifics:
|
||||
@ -68,86 +68,86 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
||||
// - RISC-V detects underflow after rounding
|
||||
|
||||
// control signals
|
||||
logic FRegWriteW; // FP register write enable
|
||||
logic [2:0] FrmM; // FP rounding mode
|
||||
logic [P.FMTBITS-1:0] FmtE, FmtM; // FP precision 0-single 1-double
|
||||
logic FDivStartE, IDivStartE; // Start division or squareroot
|
||||
logic FWriteIntM; // Write to integer register
|
||||
logic [1:0] ForwardXE, ForwardYE, ForwardZE; // forwarding mux control signals
|
||||
logic [2:0] OpCtrlE, OpCtrlM; // Select which opperation to do in each component
|
||||
logic [1:0] FResSelE, FResSelM, 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 [4:0] Adr1D, Adr2D, Adr3D; // 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 XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation
|
||||
logic FRegWriteE; // Write floating-point register
|
||||
logic FRegWriteW; // FP register write enable
|
||||
logic [2:0] FrmM; // FP rounding mode
|
||||
logic [P.FMTBITS-1:0] FmtE, FmtM; // FP precision 0-single 1-double
|
||||
logic FDivStartE, IDivStartE; // Start division or squareroot
|
||||
logic FWriteIntM; // Write to integer register
|
||||
logic [1:0] ForwardXE, ForwardYE, ForwardZE; // forwarding mux control signals
|
||||
logic [2:0] OpCtrlE, OpCtrlM; // Select which opperation to do in each component
|
||||
logic [1:0] FResSelE, FResSelM, 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 [4:0] Adr1D, Adr2D, Adr3D; // 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 XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation
|
||||
logic FRegWriteE; // Write floating-point register
|
||||
|
||||
// regfile signals
|
||||
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] 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.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] 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] 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.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)
|
||||
|
||||
// unpacking signals
|
||||
logic XsE, YsE, ZsE; // input's sign - execute 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] ZeM; // input's exponent - memory 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 XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute 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 XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage
|
||||
logic XSubnormE; // is the input subnormal
|
||||
logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage
|
||||
logic XZeroM, YZeroM; // is the input zero - memory stage
|
||||
logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage
|
||||
logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage
|
||||
logic XExpMaxE; // is the exponent all ones (max value)
|
||||
logic [P.FLEN-1:0] XPostBoxE; // X after fixing bad NaN box. Needed for 1-input operations
|
||||
logic XsE, YsE, ZsE; // input's sign - execute 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] ZeM; // input's exponent - memory 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 XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute 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 XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage
|
||||
logic XSubnormE; // is the input subnormal
|
||||
logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage
|
||||
logic XZeroM, YZeroM; // is the input zero - memory stage
|
||||
logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage
|
||||
logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage
|
||||
logic XExpMaxE; // is the exponent all ones (max value)
|
||||
logic [P.FLEN-1:0] XPostBoxE; // X after fixing bad NaN box. Needed for 1-input operations
|
||||
|
||||
// Fma Signals
|
||||
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 [3*P.NF+3:0] SmE, SmM; // Sum significand
|
||||
logic FmaAStickyE, FmaAStickyM; // FMA addend sticky bit output
|
||||
logic [P.NE+1:0] SeE,SeM; // Sum exponent
|
||||
logic InvAE, InvAM; // Invert addend
|
||||
logic AsE, AsM; // Addend sign
|
||||
logic PsE, PsM; // Product sign
|
||||
logic SsE, SsM; // Sum sign
|
||||
logic [$clog2(3*P.NF+5)-1:0] SCntE, SCntM; // LZA sum leading zero count
|
||||
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 [3*P.NF+3:0] SmE, SmM; // Sum significand
|
||||
logic FmaAStickyE, FmaAStickyM; // FMA addend sticky bit output
|
||||
logic [P.NE+1:0] SeE,SeM; // Sum exponent
|
||||
logic InvAE, InvAM; // Invert addend
|
||||
logic AsE, AsM; // Addend sign
|
||||
logic PsE, PsM; // Product sign
|
||||
logic SsE, SsM; // Sum sign
|
||||
logic [$clog2(3*P.NF+5)-1:0] SCntE, SCntM; // LZA sum leading zero count
|
||||
|
||||
// Cvt Signals
|
||||
logic [P.NE:0] CeE, CeM; // convert intermediate expoent
|
||||
logic [P.LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by
|
||||
logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is subnormal
|
||||
logic CsE, CsM; // convert result sign
|
||||
logic IntZeroE, IntZeroM; // is the integer zero?
|
||||
logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is subnormal
|
||||
logic CsE, CsM; // convert result sign
|
||||
logic IntZeroE, IntZeroM; // is the integer zero?
|
||||
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)
|
||||
|
||||
// divide signals
|
||||
logic [P.DIVb:0] QmM; // fdivsqrt signifcand
|
||||
logic [P.NE+1:0] QeM; // fdivsqrt exponent
|
||||
logic DivStickyM; // fdivsqrt sticky bit
|
||||
logic FDivDoneE, IFDivStartE; // fdivsqrt control signals
|
||||
logic DivStickyM; // fdivsqrt sticky bit
|
||||
logic FDivDoneE, IFDivStartE; // fdivsqrt control signals
|
||||
logic [P.XLEN-1:0] FIntDivResultM; // fdivsqrt integer division result (for IEU)
|
||||
|
||||
// result and flag signals
|
||||
logic [P.XLEN-1:0] ClassResE; // classify result
|
||||
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 CmpNVE; // compare invalid flag (Not Valid)
|
||||
logic CmpNVE; // compare invalid flag (Not Valid)
|
||||
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.FLEN-1:0] PostProcResM; // Postprocessor output
|
||||
logic [4:0] PostProcFlgM; // Postprocessor flags
|
||||
logic PreNVE, PreNVM; // selected flag that is ready in the memory stage
|
||||
logic [4:0] PostProcFlgM; // Postprocessor flags
|
||||
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] 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
|
||||
@ -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] 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 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 mvsgn; // sign bit for extending move
|
||||
logic mvsgn; // sign bit for extending move
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
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)},
|
||||
{{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)},
|
||||
{2'b0, {P.NE-1{1'b1}}, (P.NF)'(0)}, FmtE, BoxedOneE); // NaN boxing zeroes
|
||||
{{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)},
|
||||
{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);
|
||||
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
|
||||
// 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)
|
||||
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)
|
||||
@ -262,7 +262,6 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
||||
.ToInt(FWriteIntE), .XZero(XZeroE), .Fmt(FmtE), .Ce(CeE), .ShiftAmt(CvtShiftAmtE),
|
||||
.ResSubnormUf(CvtResSubnormUfE), .Cs(CsE), .IntZero(IntZeroE), .LzcIn(CvtLzcInE));
|
||||
|
||||
|
||||
// NaN Box SrcA to convert integer to requested FP size
|
||||
if(P.FPSIZES == 1) assign AlignedSrcAE = {{P.FLEN-P.XLEN{1'b1}}, ForwardedSrcAE};
|
||||
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));
|
||||
|
||||
// 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);
|
||||
|
||||
// M/W pipe registers
|
||||
|
@ -30,8 +30,8 @@ module fregfile #(parameter FLEN) (
|
||||
input logic clk, reset,
|
||||
input logic we4, // write enable
|
||||
input logic [4:0] a1, a2, a3, a4, // adresses
|
||||
input logic [FLEN-1:0] wd4, // write data
|
||||
output logic [FLEN-1:0] rd1, rd2, rd3 // read data
|
||||
input logic [FLEN-1:0] wd4, // write data
|
||||
output logic [FLEN-1:0] rd1, rd2, rd3 // read data
|
||||
);
|
||||
|
||||
logic [FLEN-1:0] rf[31:0];
|
||||
@ -51,4 +51,3 @@ module fregfile #(parameter FLEN) (
|
||||
assign #2 rd3 = rf[a3];
|
||||
|
||||
endmodule // regfile
|
||||
|
||||
|
@ -27,10 +27,10 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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.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
|
||||
);
|
||||
|
||||
@ -73,5 +73,4 @@ module fsgninj import cvw::*; #(parameter cvw_t P) (
|
||||
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]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -82,7 +82,7 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
P.FMT: ResNegNF = -($clog2(P.NF)+1)'(P.NF);
|
||||
P.FMT1: ResNegNF = -($clog2(P.NF)+1)'(P.NF1);
|
||||
P.FMT2: ResNegNF = -($clog2(P.NF)+1)'(P.NF2);
|
||||
default: ResNegNF = 1'bx;
|
||||
default: ResNegNF = 'x;
|
||||
endcase
|
||||
|
||||
end else if (P.FPSIZES == 4) begin
|
||||
|
@ -28,24 +28,24 @@
|
||||
|
||||
module unpackinput import cvw::*; #(parameter cvw_t P) (
|
||||
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
|
||||
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.NF:0] Man, // mantissa of the number (converted to largest supported precision)
|
||||
output logic NaN, // is the number a NaN
|
||||
output logic SNaN, // is the number a signaling NaN
|
||||
output logic Zero, // is the number zero
|
||||
output logic Inf, // is the number infinity
|
||||
output logic ExpNonZero, // is the exponent not zero
|
||||
output logic FracZero, // is the fraction zero
|
||||
output logic ExpMax, // does In have the maximum exponent (NaN or Inf)
|
||||
output logic Subnorm, // is the number subnormal
|
||||
output logic NaN, // is the number a NaN
|
||||
output logic SNaN, // is the number a signaling NaN
|
||||
output logic Zero, // is the number zero
|
||||
output logic Inf, // is the number infinity
|
||||
output logic ExpNonZero, // is the exponent not zero
|
||||
output logic FracZero, // is the fraction zero
|
||||
output logic ExpMax, // does In have the maximum exponent (NaN or Inf)
|
||||
output logic Subnorm, // is the number subnormal
|
||||
output logic [P.FLEN-1:0] PostBox // Number reboxed correctly as a NaN
|
||||
);
|
||||
|
||||
logic [P.NF-1:0] Frac; // Fraction of XYZ
|
||||
logic BadNaNBox; // incorrectly NaN Boxed
|
||||
logic [P.NF-1:0] Frac; // Fraction of XYZ
|
||||
logic BadNaNBox; // incorrectly NaN Boxed
|
||||
|
||||
if (P.FPSIZES == 1) begin // if there is only one floating point format supported
|
||||
assign BadNaNBox = 0;
|
||||
@ -107,7 +107,6 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
||||
// is the exponent all 1's
|
||||
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
|
||||
|
||||
// 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'b10: Sgn = In[P.H_LEN-1];
|
||||
endcase
|
||||
|
||||
|
||||
// extract the fraction
|
||||
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];
|
||||
endcase
|
||||
|
||||
|
||||
// example double to single conversion:
|
||||
// 1023 = 0011 1111 1111
|
||||
// 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'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
|
||||
|
||||
|
||||
|
||||
// is the exponent all 1's
|
||||
always_comb
|
||||
case (Fmt)
|
||||
|
@ -33,5 +33,3 @@ module adder #(parameter WIDTH=8) (
|
||||
|
||||
assign y = a + b;
|
||||
endmodule
|
||||
|
||||
|
||||
|
@ -36,5 +36,3 @@ module counter #(parameter WIDTH=8) (
|
||||
assign qnext = q + 1;
|
||||
flopenr #(WIDTH) cntrflop(clk, reset, en, qnext, q);
|
||||
endmodule
|
||||
|
||||
|
||||
|
@ -32,4 +32,3 @@ module neg #(parameter WIDTH = 8) (
|
||||
|
||||
assign y = ~a + 1;
|
||||
endmodule
|
||||
|
||||
|
@ -48,5 +48,3 @@ module or_rows #(parameter ROWS = 8, COLS=2) (
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
|
@ -48,6 +48,3 @@ module prioritythermometer #(parameter N = 8) (
|
||||
end
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
@ -28,55 +28,55 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module datapath import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic clk, reset,
|
||||
// Decode stage signals
|
||||
input logic [2:0] ImmSrcD, // Selects type of immediate extension
|
||||
input logic [31:0] InstrD, // Instruction in Decode stage
|
||||
input logic [2:0] ImmSrcD, // Selects type of immediate extension
|
||||
input logic [31:0] InstrD, // Instruction in Decode stage
|
||||
// Execute stage signals
|
||||
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 [2:0] Funct3E, // Funct3 field of instruction in Execute stage
|
||||
input logic StallE, FlushE, // Stall, flush Execute stage
|
||||
input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages
|
||||
input logic W64E, // W64-type instruction
|
||||
input logic SubArithE, // Subtraction or arithmetic shift
|
||||
input logic ALUSrcAE, ALUSrcBE, // ALU operands
|
||||
input logic ALUResultSrcE, // Selects result to pass on to Memory stage
|
||||
input logic [2:0] ALUSelectE, // ALU mux select signal
|
||||
input logic JumpE, // Is a jump (j) instruction
|
||||
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 [2:0] ZBBSelectE, // ZBB mux select signal
|
||||
input logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage
|
||||
output logic [1:0] FlagsE, // Comparison flags ({eq, lt})
|
||||
input logic [2:0] Funct3E, // Funct3 field of instruction in Execute stage
|
||||
input logic StallE, FlushE, // Stall, flush Execute stage
|
||||
input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages
|
||||
input logic W64E, // W64-type instruction
|
||||
input logic SubArithE, // Subtraction or arithmetic shift
|
||||
input logic ALUSrcAE, ALUSrcBE, // ALU operands
|
||||
input logic ALUResultSrcE, // Selects result to pass on to Memory stage
|
||||
input logic [2:0] ALUSelectE, // ALU mux select signal
|
||||
input logic JumpE, // Is a jump (j) instruction
|
||||
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 [2:0] ZBBSelectE, // ZBB mux select signal
|
||||
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 [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
|
||||
// Memory stage signals
|
||||
input logic StallM, FlushM, // Stall, flush Memory stage
|
||||
input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int
|
||||
input logic StallM, FlushM, // Stall, flush Memory stage
|
||||
input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int
|
||||
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] WriteDataM, // Write data in Memory stage
|
||||
// Writeback stage signals
|
||||
input logic StallW, FlushW, // Stall, flush Writeback stage
|
||||
input logic RegWriteW, IntDivW, // Write register file, integer divide instruction
|
||||
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 StallW, FlushW, // Stall, flush Writeback stage
|
||||
input logic RegWriteW, IntDivW, // Write register file, integer divide instruction
|
||||
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 [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] CSRReadValW, // CSR read 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
|
||||
// Hazard Unit signals
|
||||
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] 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
|
||||
);
|
||||
|
||||
// Fetch stage signals
|
||||
// Decode stage signals
|
||||
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 [4:0] RdD; // Destination register in Decode stage
|
||||
logic [4:0] RdD; // Destination register in Decode stage
|
||||
// Execute stage signals
|
||||
logic [P.XLEN-1:0] R1E, R2E; // Source operands read from register file
|
||||
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) RD2EReg(clk, reset, FlushE, ~StallE, R2D, R2E);
|
||||
flopenrc #(P.XLEN) ImmExtEReg(clk, reset, FlushE, ~StallE, ImmExtD, ImmExtE);
|
||||
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
||||
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
||||
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
||||
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
||||
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
||||
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
||||
|
||||
mux3 #(P.XLEN) faemux(R1E, ResultW, IFResultM, ForwardAE, ForwardedSrcAE);
|
||||
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
|
||||
if (P.A_SUPPORTED) assign SCResultW = {{(P.XLEN-1){1'b0}}, SquashSCW};
|
||||
else assign SCResultW = 0;
|
||||
else assign SCResultW = 0;
|
||||
endmodule
|
||||
|
@ -30,7 +30,7 @@
|
||||
module extend #(parameter XLEN, A_SUPPORTED) (
|
||||
input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits)
|
||||
input logic [2:0] ImmSrcD, // Select what kind of extension to perform
|
||||
output logic [XLEN-1:0 ] ImmExtD); // Extended immediate
|
||||
output logic [XLEN-1:0] ImmExtD); // Extended immediate
|
||||
|
||||
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)
|
||||
3'b011: ImmExtD = {{(XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
||||
// U-type (lui, auipc)
|
||||
3'b100: ImmExtD = {{(XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
||||
3'b100: ImmExtD = {{(XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
||||
// Store Conditional: zero offset
|
||||
3'b101: if (A_SUPPORTED) ImmExtD = 0;
|
||||
else ImmExtD = undefined;
|
||||
else ImmExtD = undefined;
|
||||
default: ImmExtD = undefined; // undefined
|
||||
endcase
|
||||
endmodule
|
||||
|
@ -26,7 +26,6 @@
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
module ieu import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
// Decode stage signals
|
||||
@ -34,36 +33,36 @@ module ieu import cvw::*; #(parameter cvw_t P) (
|
||||
input logic IllegalIEUFPUInstrD, // Illegal instruction
|
||||
output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
|
||||
// Execute stage signals
|
||||
input logic [P.XLEN-1:0] PCE, // PC
|
||||
input logic [P.XLEN-1:0] PCLinkE, // PC + 4
|
||||
input logic [P.XLEN-1:0] PCE, // PC
|
||||
input logic [P.XLEN-1:0] PCLinkE, // PC + 4
|
||||
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
|
||||
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 [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
|
||||
// Memory stage signals
|
||||
input logic SquashSCW, // Squash store conditional, from LSU
|
||||
output logic [1:0] MemRWM, // Read/write 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 [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
|
||||
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 InstrValidD, InstrValidE, InstrValidM,// Instruction is valid
|
||||
output logic InstrValidD, InstrValidE, InstrValidM, // Instruction is valid
|
||||
output logic BranchD, BranchE,
|
||||
output logic JumpD, JumpE,
|
||||
// Writeback stage signals
|
||||
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] 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] FIntDivResultW, // Integer divide result from FPU fdivsqrt)
|
||||
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] FCvtIntResW, // FPU's float to int conversion result
|
||||
input logic FCvtIntW, // FPU converts float to int
|
||||
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
|
||||
input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit
|
||||
input logic FlushD, FlushE, FlushM, FlushW, // Flush signals
|
||||
@ -118,4 +117,3 @@ module ieu import cvw::*; #(parameter cvw_t P) (
|
||||
.FCvtIntE, .SCE, .ForwardAE, .ForwardBE,
|
||||
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD);
|
||||
endmodule
|
||||
|
||||
|
@ -31,10 +31,10 @@ module regfile #(parameter XLEN, E_SUPPORTED) (
|
||||
input logic clk, reset,
|
||||
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 [XLEN-1:0] wd3, // Write data for port 3
|
||||
output logic [XLEN-1:0] rd1, rd2); // Read data for ports 1, 2
|
||||
input logic [XLEN-1:0] wd3, // Write data for port 3
|
||||
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];
|
||||
integer i;
|
||||
@ -50,7 +50,7 @@ module regfile #(parameter XLEN, E_SUPPORTED) (
|
||||
|
||||
always_ff @(negedge clk)
|
||||
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 rd2 = (a2 != 0) ? rf[a2] : 0;
|
||||
|
@ -41,7 +41,7 @@ module shifter (
|
||||
|
||||
assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension
|
||||
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
|
||||
case({Right, Rotate})
|
||||
2'b00: Z = {A[31:0], 31'b0};
|
||||
@ -84,5 +84,3 @@ module shifter (
|
||||
assign ZShift = Z >> Offset;
|
||||
assign Y = ZShift[`XLEN-1:0];
|
||||
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);
|
||||
else assign NextValidPCE = PCE;
|
||||
|
||||
if(P.ZICOUNTERS_SUPPORTED) begin
|
||||
if(P.ZIHPM_SUPPORTED) begin
|
||||
logic [P.XLEN-1:0] RASPCD, RASPCE;
|
||||
logic BTAWrongE, RASPredPCWrongE;
|
||||
// performance counters
|
||||
|
@ -181,4 +181,3 @@ module decompress #(parameter XLEN)(
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
191
src/ifu/ifu.sv
191
src/ifu/ifu.sv
@ -26,116 +26,115 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation
|
||||
input logic clk, reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation
|
||||
// Command from CPU
|
||||
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 InstrValidD, InstrValidE, InstrValidM,
|
||||
input logic BranchD, BranchE,
|
||||
input logic JumpD, JumpE,
|
||||
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 InstrValidD, InstrValidE, InstrValidM,
|
||||
input logic BranchD, BranchE,
|
||||
input logic JumpD, JumpE,
|
||||
// Bus interface
|
||||
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 IFUHREADY, // Bus ready 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] IFUHBURST, // Bus burst from IFU to EBU
|
||||
output logic [1:0] IFUHTRANS, // Bus transaction type 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 [2:0] IFUHSIZE, // Bus operation size 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 [P.XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW
|
||||
// Execute
|
||||
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] IEUAdrM, // The branch/jump target address
|
||||
output logic [P.XLEN-1:0] PCE, // Execution stage instruction address
|
||||
output logic BPWrongE, // Prediction is wrong
|
||||
output logic BPWrongM, // Prediction is wrong
|
||||
output logic BPWrongE, // Prediction is wrong
|
||||
output logic BPWrongM, // Prediction is wrong
|
||||
// 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.
|
||||
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] 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] InstrD, // The decoded instruction in Decode 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 [P.XLEN-1:0] PCM, // Memory stage instruction address
|
||||
// branch predictor
|
||||
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 BTAWrongM, // Prediction target wrong
|
||||
output logic RASPredPCWrongM, // RAS prediction is wrong
|
||||
output logic IClassWrongM, // Class prediction is wrong
|
||||
output logic ICacheStallF, // I$ busy with multicycle operation
|
||||
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 BTAWrongM, // Prediction target wrong
|
||||
output logic RASPredPCWrongM, // RAS prediction is wrong
|
||||
output logic IClassWrongM, // Class prediction is wrong
|
||||
output logic ICacheStallF, // I$ busy with multicycle operation
|
||||
// Faults
|
||||
input logic IllegalBaseInstrD, // Illegal non-compressed instruction
|
||||
input logic IllegalFPUInstrD, // Illegal FP instruction
|
||||
output logic InstrPageFaultF, // Instruction page fault
|
||||
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)
|
||||
input logic IllegalBaseInstrD, // Illegal non-compressed instruction
|
||||
input logic IllegalFPUInstrD, // Illegal FP instruction
|
||||
output logic InstrPageFaultF, // Instruction page fault
|
||||
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)
|
||||
// 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 [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
|
||||
input logic ITLBWriteF, // Writes PTE and 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 [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_SUM, // Status CSR: Supervisor access to user memory
|
||||
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
||||
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
|
||||
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
||||
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||
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 [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 ICacheAccess, // Report I$ read to performance counters
|
||||
output logic ICacheMiss // Report I$ miss to performance counters
|
||||
input logic STATUS_MXR, // Status CSR: make executable page readable
|
||||
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
||||
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
||||
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
|
||||
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
||||
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||
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 [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 ICacheAccess, // Report I$ read 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 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] 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: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] 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.PA_BITS-1:0] PCPF; // Physical address after address translation
|
||||
logic [P.XLEN+1:0] PCFExt; //
|
||||
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 [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] 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: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] PCF; // Fetch stage instruction address
|
||||
logic [P.PA_BITS-1:0] PCPF; // Physical address after address translation
|
||||
logic [P.XLEN+1:0] PCFExt;
|
||||
|
||||
logic [31:0] IROMInstrF; // Instruction from the IROM
|
||||
logic [31:0] ICacheInstrF; // Instruction from the I$
|
||||
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
||||
logic CompressedF; // The fetched instruction is compressed
|
||||
logic CompressedD; // The decoded instruction is compressed
|
||||
logic CompressedE; // The execution instruction is compressed
|
||||
logic CompressedM; // The execution instruction is compressed
|
||||
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
||||
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
||||
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
||||
logic [31:0] IROMInstrF; // Instruction from the IROM
|
||||
logic [31:0] ICacheInstrF; // Instruction from the I$
|
||||
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
||||
logic CompressedF; // The fetched instruction is compressed
|
||||
logic CompressedD; // The decoded instruction is compressed
|
||||
logic CompressedE; // The execution instruction is compressed
|
||||
logic CompressedM; // The execution instruction is compressed
|
||||
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
||||
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
||||
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
||||
|
||||
logic [1:0] IFURWF; // IFU alreays read IFURWF = 10
|
||||
logic [31:0] InstrE; // Instruction in the Execution stage
|
||||
logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush
|
||||
logic [1:0] IFURWF; // IFU alreays read IFURWF = 10
|
||||
logic [31:0] InstrE; // Instruction in the Execution stage
|
||||
logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush
|
||||
|
||||
|
||||
logic CacheableF; // PMA indicates instruction address is cacheable
|
||||
logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF
|
||||
logic BusStall; // Bus interface busy with multicycle operation
|
||||
logic IFUCacheBusStallF; // EIther I$ or bus busy with multicycle operation
|
||||
logic GatedStallD; // StallD gated by selected next spill
|
||||
logic CacheableF; // PMA indicates instruction address is cacheable
|
||||
logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF
|
||||
logic BusStall; // Bus interface busy with multicycle operation
|
||||
logic IFUCacheBusStallF; // EIther I$ or bus busy with multicycle operation
|
||||
logic GatedStallD; // StallD gated by selected next spill
|
||||
// branch predictor signal
|
||||
logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
||||
logic BusCommittedF; // Bus memory operation in flight, delay interrupts
|
||||
logic CacheCommittedF; // I$ memory operation started, delay interrupts
|
||||
logic SelIROM; // PMA indicates instruction address is in the IROM
|
||||
logic [15:0] InstrRawE, InstrRawM;
|
||||
logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
||||
logic BusCommittedF; // Bus memory operation in flight, delay interrupts
|
||||
logic CacheCommittedF; // I$ memory operation started, delay interrupts
|
||||
logic SelIROM; // PMA indicates instruction address is in the IROM
|
||||
logic [15:0] InstrRawE, InstrRawM;
|
||||
|
||||
assign PCFExt = {2'b00, PCSpillF};
|
||||
|
||||
@ -199,6 +198,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Memory
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
assign CommittedF = CacheCommittedF | BusCommittedF;
|
||||
|
||||
logic IgnoreRequest;
|
||||
logic IgnoreRequest;
|
||||
assign IgnoreRequest = ITLBMissF | FlushD;
|
||||
|
||||
// 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 LOGBWPL = P.ICACHE_SUPPORTED ? $clog2(WORDSPERLINE) : 1;
|
||||
if(P.ICACHE_SUPPORTED) begin : icache
|
||||
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)
|
||||
logic [LINELEN-1:0] FetchBuffer;
|
||||
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)
|
||||
logic [LINELEN-1:0] FetchBuffer;
|
||||
logic [P.PA_BITS-1:0] ICacheBusAdr;
|
||||
logic ICacheBusAck;
|
||||
logic [1:0] CacheBusRW, BusRW, CacheRWF;
|
||||
logic ICacheBusAck;
|
||||
logic [1:0] CacheBusRW, BusRW, CacheRWF;
|
||||
|
||||
assign BusRW = ~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(),
|
||||
.Funct3(3'b010), .HADDR(IFUHADDR), .HREADY(IFUHREADY), .HWRITE(IFUHWRITE), .CacheBusAdr(ICacheBusAdr),
|
||||
.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),
|
||||
.BusRW, .Stall(GatedStallD),
|
||||
.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 = {PCPlus4F, PCF[1:0]}; // add 4
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Branch and Jump Predictor
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -341,10 +340,10 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
assign NextValidPCE = PCE;
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Decode stage pipeline register and compressed instruction decoding.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Decode stage pipeline register and logic
|
||||
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
|
||||
// Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0.
|
||||
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
|
||||
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
||||
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
|
||||
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
||||
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
|
||||
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
||||
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
|
||||
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
||||
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
|
||||
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
||||
//flopenr #(P.XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD);
|
||||
|
@ -25,10 +25,10 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module irom import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk,
|
||||
input logic ce, // Chip Enable. 0: Holds IROMInstrF constant
|
||||
input logic clk,
|
||||
input logic ce, // Chip Enable. 0: Holds IROMInstrF constant
|
||||
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
|
||||
@ -36,14 +36,13 @@ module irom import cvw::*; #(parameter cvw_t P) (
|
||||
localparam OFFSET = $clog2(XLENBYTES);
|
||||
|
||||
logic [P.XLEN-1:0] IROMInstrFFull;
|
||||
logic [31:0] RawIROMInstrF;
|
||||
|
||||
logic [1:0] AdrD;
|
||||
logic [31:0] RawIROMInstrF;
|
||||
logic [1:0] 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));
|
||||
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
|
||||
// haves. Adr is the Next PCF not PCF so we delay 1 cycle.
|
||||
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.
|
||||
assign IROMInstrF = AdrD[0] ? {16'b0, RawIROMInstrF[31:16]} : RawIROMInstrF;
|
||||
endmodule
|
||||
|
||||
|
@ -32,33 +32,33 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module spill import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallD, FlushD,
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallD, FlushD,
|
||||
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: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 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 InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
|
||||
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 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)
|
||||
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 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 CompressedF); // The fetched instruction is compressed
|
||||
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 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]
|
||||
typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype;
|
||||
localparam SPILLTHRESHOLD = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/32 : 1;
|
||||
typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype;
|
||||
localparam SPILLTHRESHOLD = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/32 : 1;
|
||||
|
||||
statetype CurrState, NextState;
|
||||
statetype CurrState, NextState;
|
||||
logic [P.XLEN-1:0] PCPlus2F;
|
||||
logic TakeSpillF;
|
||||
logic SpillF;
|
||||
logic SelSpillF;
|
||||
logic SpillSaveF;
|
||||
logic [15:0] InstrFirstHalfF;
|
||||
logic TakeSpillF;
|
||||
logic SpillF;
|
||||
logic SelSpillF;
|
||||
logic SpillSaveF;
|
||||
logic [15:0] InstrFirstHalfF;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PC logic
|
||||
@ -71,7 +71,6 @@ module spill import cvw::*; #(parameter cvw_t P) (
|
||||
// select between PCF and PCF+2
|
||||
mux2 #(P.XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCSpillF));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Detect spill
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -30,8 +30,8 @@
|
||||
module amoalu import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.XLEN-1:0] ReadDataM, // LSU's ReadData
|
||||
input logic [P.XLEN-1:0] IHWriteDataM, // LSU's WriteData
|
||||
input logic [6:0] LSUFunct7M, // ALU Operation
|
||||
input logic [2:0] LSUFunct3M, // Memoy access width
|
||||
input logic [6:0] LSUFunct7M, // ALU Operation
|
||||
input logic [2:0] LSUFunct3M, // Memoy access width
|
||||
output logic [P.XLEN-1:0] AMOResultM // ALU output
|
||||
);
|
||||
|
||||
@ -72,4 +72,3 @@ module amoalu import cvw::*; #(parameter cvw_t P) (
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
@ -28,24 +28,24 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module atomic import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallW,
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
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] 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 [6:0] LSUFunct7M, // AMO alu operation gated by HPTW
|
||||
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] PreLSURWM, // IEU or HPTW Read/Write signal
|
||||
input logic IgnoreRequest, // On FlushM or TLB miss ignore memory operation
|
||||
input logic [6:0] LSUFunct7M, // AMO alu operation gated by HPTW
|
||||
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] PreLSURWM, // IEU or HPTW Read/Write signal
|
||||
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 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 SquashSCW, // Store conditional failed disable write to GPR
|
||||
output logic [1:0] LSURWM // IEU or HPTW Read/Write signal gated by LR/SC
|
||||
);
|
||||
|
||||
logic [P.XLEN-1:0] AMOResultM;
|
||||
logic MemReadM;
|
||||
logic MemReadM;
|
||||
|
||||
amoalu #(P) amoalu(.ReadDataM, .IHWriteDataM, .LSUFunct7M, .LSUFunct3M, .AMOResultM);
|
||||
|
||||
|
@ -28,17 +28,17 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module dtim import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk,
|
||||
input logic FlushW,
|
||||
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
|
||||
input logic [1:0] MemRWM, // Read/Write control
|
||||
input logic clk,
|
||||
input logic FlushW,
|
||||
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
|
||||
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.LLEN-1:0] WriteDataM, // Write data from IEU
|
||||
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
|
||||
);
|
||||
|
||||
logic we;
|
||||
logic we;
|
||||
|
||||
localparam LLENBYTES = P.LLEN/8;
|
||||
// verilator lint_off WIDTH
|
||||
@ -52,4 +52,3 @@ module dtim import cvw::*; #(parameter cvw_t P) (
|
||||
ram1p1rwbe #(.DEPTH(DEPTH), .WIDTH(P.LLEN))
|
||||
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
|
||||
endmodule
|
||||
|
||||
|
@ -29,23 +29,23 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module lrsc import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallW,
|
||||
input logic MemReadM, // Memory read
|
||||
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
|
||||
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallW,
|
||||
input logic MemReadM, // Memory read
|
||||
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
|
||||
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
||||
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.
|
||||
// Handle atomic load reserved / store conditional
|
||||
logic [P.PA_BITS-1:2] ReservationPAdrW;
|
||||
logic ReservationValidM, ReservationValidW;
|
||||
logic lrM, scM, WriteAdrMatchM;
|
||||
logic SquashSCM;
|
||||
logic ReservationValidM, ReservationValidW;
|
||||
logic lrM, scM, WriteAdrMatchM;
|
||||
logic SquashSCM;
|
||||
|
||||
assign lrM = MemReadM & 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) (
|
||||
input logic clk, reset,
|
||||
input logic StallM, FlushM, StallW, FlushW,
|
||||
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation
|
||||
input logic clk, reset,
|
||||
input logic StallM, FlushM, StallW, FlushW,
|
||||
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation
|
||||
// connected to cpu (controls)
|
||||
input logic [1:0] MemRWM, // Read/Write control
|
||||
input logic [2:0] Funct3M, // Size of memory operation
|
||||
input logic [6:0] Funct7M, // Atomic memory operation function
|
||||
input logic [1:0] AtomicM, // Atomic memory operation
|
||||
input logic FlushDCacheM, // Flush D cache to next level of memory
|
||||
output logic CommittedM, // Delay interrupts while memory operation in flight
|
||||
output logic SquashSCW, // Store conditional failed disable write to GPR
|
||||
output logic DCacheMiss, // D cache miss for performance counters
|
||||
output logic DCacheAccess, // D cache memory access for performance counters
|
||||
input logic [1:0] MemRWM, // Read/Write control
|
||||
input logic [2:0] Funct3M, // Size of memory operation
|
||||
input logic [6:0] Funct7M, // Atomic memory operation function
|
||||
input logic [1:0] AtomicM, // Atomic memory operation
|
||||
input logic FlushDCacheM, // Flush D cache to next level of memory
|
||||
output logic CommittedM, // Delay interrupts while memory operation in flight
|
||||
output logic SquashSCW, // Store conditional failed disable write to GPR
|
||||
output logic DCacheMiss, // D cache miss for performance counters
|
||||
output logic DCacheAccess, // D cache memory access for performance counters
|
||||
// address and write data
|
||||
input logic [P.XLEN-1:0] IEUAdrE, // Execution 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
|
||||
output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU
|
||||
input logic [P.XLEN-1:0] IEUAdrE, // Execution 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
|
||||
output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU
|
||||
// cpu privilege
|
||||
input logic [1:0] PrivilegeModeW, // Current privilege mode
|
||||
input logic BigEndianM, // Swap byte order to big endian
|
||||
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
||||
output logic DCacheStallM, // D$ busy with multicycle operation
|
||||
input logic [1:0] PrivilegeModeW, // Current privilege mode
|
||||
input logic BigEndianM, // Swap byte order to big endian
|
||||
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
||||
output logic DCacheStallM, // D$ busy with multicycle operation
|
||||
// fpu
|
||||
input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU
|
||||
input logic FpLoadStoreM, // Selects FPU as store for write data
|
||||
input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU
|
||||
input logic FpLoadStoreM, // Selects FPU as store for write data
|
||||
// faults
|
||||
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
|
||||
output logic LoadMisalignedFaultM, // Load address misaligned fault
|
||||
output logic LoadAccessFaultM, // Load access fault (PMA)
|
||||
output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch
|
||||
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
|
||||
output logic LoadMisalignedFaultM, // Load address misaligned fault
|
||||
output logic LoadAccessFaultM, // Load access fault (PMA)
|
||||
output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch
|
||||
// cpu hazard unit (trap)
|
||||
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
|
||||
output logic StoreAmoAccessFaultM, // Store or AMO access fault
|
||||
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
|
||||
output logic StoreAmoAccessFaultM, // Store or AMO access fault
|
||||
// connect to ahb
|
||||
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
|
||||
output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data 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 [2:0] LSUHSIZE, // Bus operation size 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 [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables 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
|
||||
output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data 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 [2:0] LSUHSIZE, // Bus operation size 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 [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
|
||||
// page table walker
|
||||
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 [1:0] STATUS_MPP, // Machine previous privilege mode
|
||||
input logic [P.XLEN-1:0] PCSpillF, // Fetch PC
|
||||
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||
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 [1:0] PageType, // Type of page table entry to write to ITLB
|
||||
output logic ITLBWriteF, // Write PTE to ITLB
|
||||
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 [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP address from privileged unit
|
||||
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 [1:0] STATUS_MPP, // Machine previous privilege mode
|
||||
input logic [P.XLEN-1:0] PCSpillF, // Fetch PC
|
||||
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||
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 [1:0] PageType, // Type of page table entry to write to ITLB
|
||||
output logic ITLBWriteF, // Write PTE to ITLB
|
||||
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 [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
|
||||
@ -94,20 +94,20 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
logic [P.PA_BITS-1:0] PAdrM; // Physical 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] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
|
||||
logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
|
||||
logic [6:0] LSUFunct7M; // AMO function gated by HPTW
|
||||
logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
|
||||
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 [2:0] LSUFunct3M; // IEU or HPTW memory operation size
|
||||
logic [6:0] LSUFunct7M; // AMO function 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 HPTWStall; // HPTW busy with multicycle operation
|
||||
logic BusStall; // Bus interface busy with multicycle operation
|
||||
logic HPTWStall; // HPTW busy with multicycle operation
|
||||
|
||||
logic CacheableM; // PMA indicates memory address is cacheable
|
||||
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
|
||||
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
|
||||
logic CacheableM; // PMA indicates memory address is cacheable
|
||||
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
|
||||
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
|
||||
|
||||
logic [P.LLEN-1:0] DTIMReadDataWordM; // DTIM 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)/8:0] ByteMaskM; // Selects which bytes within a word to write
|
||||
|
||||
logic DTLBMissM; // DTLB miss causes HPTW walk
|
||||
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
||||
logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
|
||||
logic LSULoadAccessFaultM; // Load acces fault
|
||||
logic LSUStoreAmoAccessFaultM; // Store access fault
|
||||
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 SelDTIM; // Select DTIM rather than bus or D$
|
||||
logic DTLBMissM; // DTLB miss causes HPTW walk
|
||||
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
||||
logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
|
||||
logic LSULoadAccessFaultM; // Load acces fault
|
||||
logic LSUStoreAmoAccessFaultM; // Store access fault
|
||||
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 SelDTIM; // Select DTIM rather than bus or D$
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Pipeline for IEUAdr E to M
|
||||
// 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
|
||||
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.
|
||||
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.DCACHE_SUPPORTED) begin : dcache
|
||||
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 AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^
|
||||
localparam LINELEN = P.DCACHE_LINELENINBITS; // Number of bits in cacheline
|
||||
localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^
|
||||
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)
|
||||
|
||||
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 [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
|
||||
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
|
||||
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
|
||||
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
||||
logic [1:0] BusRW; // Uncached bus memory access
|
||||
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] CacheAtomicM; // Cache AMO
|
||||
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
||||
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 [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
|
||||
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
|
||||
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
|
||||
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
||||
logic [1:0] BusRW; // Uncached bus memory access
|
||||
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] CacheAtomicM; // Cache AMO
|
||||
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
||||
|
||||
assign BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
|
||||
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
||||
@ -320,6 +319,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Atomic operations
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (P.A_SUPPORTED) begin:atomic
|
||||
atomic #(P) atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[P.XLEN-1:0]), .IHWriteDataM, .PAdrM,
|
||||
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
|
||||
@ -335,6 +335,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Subword Accesses
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
subwordread #(P.LLEN) subwordread(.ReadDataWordMuxM(LittleEndianReadDataWordM), .PAdrM(PAdrM[2:0]), .BigEndianM,
|
||||
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
|
||||
subwordwrite #(P.LLEN) subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
|
||||
@ -361,5 +362,4 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
assign LSUWriteDataM = LittleEndianWriteDataM;
|
||||
assign LittleEndianReadDataWordM = ReadDataWordMuxM;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -29,12 +29,12 @@
|
||||
|
||||
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] Funct3M,
|
||||
input logic FpLoadStoreM,
|
||||
input logic BigEndianM,
|
||||
output logic [LLEN-1:0] ReadDataM
|
||||
output logic [LLEN-1:0] ReadDataM
|
||||
);
|
||||
|
||||
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'b101: ReadDataM = {{LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
||||
3'b110: ReadDataM = {{LLEN-32{1'b0}}, WordM[31:0]}; // lwu
|
||||
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||
endcase
|
||||
|
||||
end else begin:swrmux // 32-bit
|
||||
|
@ -28,8 +28,8 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module subwordwrite #(parameter LLEN) (
|
||||
input logic [2:0] LSUFunct3M,
|
||||
input logic [LLEN-1:0] IMAFWriteDataM,
|
||||
input logic [2:0] LSUFunct3M,
|
||||
input logic [LLEN-1:0] IMAFWriteDataM,
|
||||
output logic [LLEN-1:0] LittleEndianWriteDataM
|
||||
);
|
||||
|
||||
@ -46,18 +46,18 @@ module subwordwrite #(parameter LLEN) (
|
||||
end else if (LLEN == 64) begin:sww
|
||||
always_comb
|
||||
case(LSUFunct3M[1:0])
|
||||
2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb
|
||||
2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh
|
||||
2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw
|
||||
2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd
|
||||
2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb
|
||||
2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh
|
||||
2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw
|
||||
2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd
|
||||
endcase
|
||||
end else begin:sww // 32-bit
|
||||
always_comb
|
||||
case(LSUFunct3M[1:0])
|
||||
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
|
||||
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
|
||||
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
|
||||
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
|
||||
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
|
||||
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
|
||||
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
|
||||
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
@ -28,9 +28,9 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module swbytemask #(parameter WORDLEN)(
|
||||
input logic [2:0] Size,
|
||||
input logic [$clog2(WORDLEN/8)-1:0] Adr,
|
||||
output logic [WORDLEN/8-1:0] ByteMask
|
||||
input logic [2:0] Size,
|
||||
input logic [$clog2(WORDLEN/8)-1:0] Adr,
|
||||
output logic [WORDLEN/8-1:0] ByteMask
|
||||
);
|
||||
|
||||
assign ByteMask = ((2**(2**Size))-1) << Adr;
|
||||
|
@ -27,38 +27,38 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module div import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallM,
|
||||
input logic FlushE,
|
||||
input logic IntDivE, // integer division/remainder instruction of any type
|
||||
input logic DivSignedE, // signed division
|
||||
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
|
||||
output logic DivBusyE, // Divide is busy - stall pipeline
|
||||
output logic [P.XLEN-1:0] QuotM, RemM // Quotient and remainder outputs
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallM,
|
||||
input logic FlushE,
|
||||
input logic IntDivE, // integer division/remainder instruction of any type
|
||||
input logic DivSignedE, // signed division
|
||||
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
|
||||
output logic DivBusyE, // Divide is busy - stall pipeline
|
||||
output logic [P.XLEN-1:0] QuotM, RemM // Quotient and remainder outputs
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
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] 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] DnE; // DnE = ~DinE
|
||||
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] XnE; // DXnE = ~XinE
|
||||
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 [STEPBITS:0] step; // division step
|
||||
logic Div0E, Div0M; // divide by 0
|
||||
logic DivStartE; // start integer division
|
||||
logic SignXE, SignDE; // sign of dividend and divisor
|
||||
logic NegQE, NegWM, NegQM; // negate quotient or residual during postprocessing
|
||||
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] DnE; // DnE = ~DinE
|
||||
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] XnE; // DXnE = ~XinE
|
||||
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 [STEPBITS:0] step; // division step
|
||||
logic Div0E, Div0M; // divide by 0
|
||||
logic DivStartE; // start integer division
|
||||
logic SignXE, SignDE; // sign of dividend and divisor
|
||||
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
|
||||
@ -131,7 +131,7 @@ module div import cvw::*; #(parameter cvw_t P) (
|
||||
step <= 1;
|
||||
if (Div0E) state <= DONE;
|
||||
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
|
||||
state <= DONE;
|
||||
end
|
||||
|
@ -27,21 +27,21 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module mdu import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic StallM, StallW,
|
||||
input logic FlushE, FlushM, FlushW,
|
||||
input logic clk, reset,
|
||||
input logic StallM, StallW,
|
||||
input logic FlushE, FlushM, FlushW,
|
||||
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 IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
||||
input logic [2:0] Funct3E, Funct3M, // type of MDU operation
|
||||
input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
||||
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-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] MDUResultM; // result after W truncation
|
||||
logic W64M; // W-type instruction
|
||||
logic W64M; // W-type instruction
|
||||
|
||||
// Multiplier
|
||||
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
|
||||
case (Funct3M)
|
||||
3'b000: PrelimResultM = ProdM[P.XLEN-1:0]; // mul
|
||||
3'b001: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulh
|
||||
3'b010: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhsu
|
||||
3'b011: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhu
|
||||
3'b100: PrelimResultM = QuotM; // div
|
||||
3'b101: PrelimResultM = QuotM; // divu
|
||||
3'b110: PrelimResultM = RemM; // rem
|
||||
3'b111: PrelimResultM = RemM; // remu
|
||||
3'b001: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulh
|
||||
3'b010: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhsu
|
||||
3'b011: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhu
|
||||
3'b100: PrelimResultM = QuotM; // div
|
||||
3'b101: PrelimResultM = QuotM; // divu
|
||||
3'b110: PrelimResultM = RemM; // rem
|
||||
3'b111: PrelimResultM = RemM; // remu
|
||||
endcase
|
||||
|
||||
// Handle sign extension for W-type instructions
|
||||
@ -84,5 +84,3 @@ module mdu import cvw::*; #(parameter cvw_t P) (
|
||||
// Writeback stage pipeline register
|
||||
flopenrc #(P.XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW);
|
||||
endmodule // mdu
|
||||
|
||||
|
||||
|
@ -29,9 +29,9 @@
|
||||
module mul #(parameter XLEN) (
|
||||
input logic clk, reset,
|
||||
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
|
||||
output logic [XLEN*2-1:0] ProdM // double-widthproduct
|
||||
output logic [XLEN*2-1:0] ProdM // double-widthproduct
|
||||
);
|
||||
|
||||
// Number systems
|
||||
@ -48,12 +48,12 @@ module mul #(parameter XLEN) (
|
||||
// Signed * 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 [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 [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] PP1E, PP2E, PP3E, PP4E; // partial products
|
||||
logic [XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; // registered partial proudcts
|
||||
|
||||
//////////////////////////////
|
||||
// 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
|
||||
assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
|
||||
endmodule
|
||||
|
||||
|
@ -27,8 +27,8 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module adrdec #(parameter PA_BITS) (
|
||||
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] PhysicalAddress, // Physical address to decode
|
||||
input logic [PA_BITS-1:0] Base, Range, // Base and range of peripheral addresses
|
||||
input logic Supported, // Is this peripheral supported?
|
||||
input logic AccessValid, // Is the access type valid?
|
||||
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
|
||||
assign Sel = Match & Supported & AccessValid & SizeValid;
|
||||
endmodule
|
||||
|
||||
|
@ -30,12 +30,12 @@
|
||||
|
||||
module adrdecs import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||
input logic AccessRW, AccessRX, AccessRWX,
|
||||
input logic [1:0] Size,
|
||||
output logic [10:0] SelRegions
|
||||
input logic AccessRW, AccessRX, AccessRWX,
|
||||
input logic [1:0] Size,
|
||||
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
|
||||
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]);
|
||||
|
118
src/mmu/hptw.sv
118
src/mmu/hptw.sv
@ -30,39 +30,39 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
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] PCSpillF, // 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
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU
|
||||
input logic [P.XLEN-1:0] WriteDataM,
|
||||
input logic DCacheStallM, // stall from LSU
|
||||
input logic [2:0] Funct3M,
|
||||
input logic [6:0] Funct7M,
|
||||
input logic ITLBMissF,
|
||||
input logic DTLBMissM,
|
||||
input logic FlushW,
|
||||
input logic InstrUpdateDAF,
|
||||
input logic DataUpdateDAM,
|
||||
input logic DCacheStallM, // stall from LSU
|
||||
input logic [2:0] Funct3M,
|
||||
input logic [6:0] Funct7M,
|
||||
input logic ITLBMissF,
|
||||
input logic DTLBMissM,
|
||||
input logic FlushW,
|
||||
input logic InstrUpdateDAF,
|
||||
input logic DataUpdateDAM,
|
||||
output logic [P.XLEN-1:0] PTE, // page table entry to TLBs
|
||||
output logic [1:0] PageType, // page type to TLBs
|
||||
output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
|
||||
output logic [1:0] PreLSURWM,
|
||||
output logic [1:0] PageType, // page type to TLBs
|
||||
output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
|
||||
output logic [1:0] PreLSURWM,
|
||||
output logic [P.XLEN+1:0] IHAdrM,
|
||||
output logic [P.XLEN-1:0] IHWriteDataM,
|
||||
output logic [1:0] LSUAtomicM,
|
||||
output logic [2:0] LSUFunct3M,
|
||||
output logic [6:0] LSUFunct7M,
|
||||
output logic IgnoreRequestTLB,
|
||||
output logic SelHPTW,
|
||||
output logic HPTWStall,
|
||||
input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM,
|
||||
output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultF
|
||||
output logic [1:0] LSUAtomicM,
|
||||
output logic [2:0] LSUFunct3M,
|
||||
output logic [6:0] LSUFunct7M,
|
||||
output logic IgnoreRequestTLB,
|
||||
output logic SelHPTW,
|
||||
output logic HPTWStall,
|
||||
input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM,
|
||||
output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultF
|
||||
);
|
||||
|
||||
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,
|
||||
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] CurrentPPN;
|
||||
logic Executable, Writable, Readable, Valid, PTE_U;
|
||||
logic Misaligned, MegapageMisaligned;
|
||||
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
|
||||
logic StartWalk;
|
||||
logic TLBMiss;
|
||||
logic PRegEn;
|
||||
logic [1:0] NextPageType;
|
||||
logic Executable, Writable, Readable, Valid, PTE_U;
|
||||
logic Misaligned, MegapageMisaligned;
|
||||
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
|
||||
logic StartWalk;
|
||||
logic TLBMiss;
|
||||
logic PRegEn;
|
||||
logic [1:0] NextPageType;
|
||||
logic [P.SVMODE_BITS-1:0] SvMode;
|
||||
logic [P.XLEN-1:0] TranslationVAdr;
|
||||
logic [P.XLEN-1:0] NextPTE;
|
||||
logic UpdatePTE;
|
||||
logic HPTWUpdateDA;
|
||||
logic UpdatePTE;
|
||||
logic HPTWUpdateDA;
|
||||
logic [P.PA_BITS-1:0] HPTWReadAdr;
|
||||
logic SelHPTWAdr;
|
||||
logic SelHPTWAdr;
|
||||
logic [P.XLEN+1:0] HPTWAdrExt;
|
||||
logic ITLBMissOrUpdateDAF;
|
||||
logic DTLBMissOrUpdateDAM;
|
||||
logic LSUAccessFaultM;
|
||||
logic ITLBMissOrUpdateDAF;
|
||||
logic DTLBMissOrUpdateDAM;
|
||||
logic LSUAccessFaultM;
|
||||
logic [P.PA_BITS-1:0] HPTWAdr;
|
||||
logic [1:0] HPTWRW;
|
||||
logic [2:0] HPTWSize; // 32 or 64 bit access
|
||||
statetype WalkerState, NextWalkerState, InitialWalkerState;
|
||||
logic HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault;
|
||||
logic HPTWLoadAccessFaultDelay, HPTWStoreAmoAccessFaultDelay, HPTWInstrAccessFaultDelay;
|
||||
logic HPTWAccessFaultDelay;
|
||||
logic TakeHPTWFault, TakeHPTWFaultDelay;
|
||||
logic [1:0] HPTWRW;
|
||||
logic [2:0] HPTWSize; // 32 or 64 bit access
|
||||
statetype WalkerState, NextWalkerState, InitialWalkerState;
|
||||
logic HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault;
|
||||
logic HPTWLoadAccessFaultDelay, HPTWStoreAmoAccessFaultDelay, HPTWInstrAccessFaultDelay;
|
||||
logic HPTWAccessFaultDelay;
|
||||
logic TakeHPTWFault, TakeHPTWFaultDelay;
|
||||
|
||||
// map hptw access faults onto either the original LSU load/store fault or instruction access fault
|
||||
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
||||
assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
||||
assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||
assign HPTWStoreAmoAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
||||
assign HPTWInstrAccessFault = LSUAccessFaultM & ~DTLBWalk;
|
||||
|
||||
@ -140,16 +140,16 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
||||
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
|
||||
|
||||
if(P.SVADU_SUPPORTED) begin : hptwwrites
|
||||
logic ReadAccess, WriteAccess;
|
||||
logic InvalidRead, InvalidWrite, InvalidOp;
|
||||
logic UpperBitsUnequal;
|
||||
logic OtherPageFault;
|
||||
logic [1:0] EffectivePrivilegeMode;
|
||||
logic ImproperPrivilege;
|
||||
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
||||
logic ReadAccess, WriteAccess;
|
||||
logic InvalidRead, InvalidWrite, InvalidOp;
|
||||
logic UpperBitsUnequal;
|
||||
logic OtherPageFault;
|
||||
logic [1:0] EffectivePrivilegeMode;
|
||||
logic ImproperPrivilege;
|
||||
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
||||
logic [P.PA_BITS-1:0] HPTWWriteAdr;
|
||||
logic SetDirty;
|
||||
logic Dirty, Accessed;
|
||||
logic SetDirty;
|
||||
logic Dirty, Accessed;
|
||||
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
|
||||
@ -194,8 +194,8 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
||||
end
|
||||
|
||||
// Enable and select signals based on states
|
||||
assign StartWalk = (WalkerState == IDLE) & TLBMiss;
|
||||
assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
|
||||
assign StartWalk = (WalkerState == IDLE) & TLBMiss;
|
||||
assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
|
||||
assign DTLBWriteM = (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
|
||||
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 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
|
||||
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
|
||||
|
@ -28,48 +28,48 @@
|
||||
|
||||
module mmu import cvw::*; #(parameter cvw_t P,
|
||||
parameter TLB_ENTRIES = 8, IMMU = 0) (
|
||||
input logic clk, reset,
|
||||
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_SUM, // Status CSR: Supervisor access to user memory
|
||||
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] 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 [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 [P.XLEN-1:0] PTE, // page table entry
|
||||
input logic [1:0] PageTypeWriteVal, // page type
|
||||
input logic TLBWrite, // write TLB entry
|
||||
input logic TLBFlush, // Invalidate all TLB entries
|
||||
input logic clk, reset,
|
||||
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_SUM, // Status CSR: Supervisor access to user memory
|
||||
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] 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 [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 [P.XLEN-1:0] PTE, // page table entry
|
||||
input logic [1:0] PageTypeWriteVal, // page type
|
||||
input logic TLBWrite, // write TLB entry
|
||||
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 TLBMiss, // Miss TLB
|
||||
output logic Cacheable, // PMA indicates memory address is cachable
|
||||
output logic Idempotent, // PMA indicates memory address is idempotent
|
||||
output logic SelTIM, // Select a tightly integrated memory
|
||||
output logic TLBMiss, // Miss TLB
|
||||
output logic Cacheable, // PMA indicates memory address is cachable
|
||||
output logic Idempotent, // PMA indicates memory address is idempotent
|
||||
output logic SelTIM, // Select a tightly integrated memory
|
||||
// Faults
|
||||
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources
|
||||
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources
|
||||
output logic UpdateDA, // page fault due to setting dirty or access bit
|
||||
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources
|
||||
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources
|
||||
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources
|
||||
output logic UpdateDA, // page fault due to setting dirty or access bit
|
||||
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources
|
||||
// PMA checker signals
|
||||
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 [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses
|
||||
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 [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 PMAInstrAccessFaultF; // Instruction access fault from PMA
|
||||
logic PMPInstrAccessFaultF; // Instruction access fault from PMP
|
||||
logic PMALoadAccessFaultM; // Load access fault from PMA
|
||||
logic PMPLoadAccessFaultM; // Load access fault from PMP
|
||||
logic PMAStoreAmoAccessFaultM; // Store or AMO access fault from PMA
|
||||
logic PMPStoreAmoAccessFaultM; // Store or AMO access fault from PMP
|
||||
logic DataMisalignedM; // load or store misaligned
|
||||
logic Translate; // Translation occurs when virtual memory is active and DisableTranslation is off
|
||||
logic TLBHit; // Hit in TLB
|
||||
logic TLBPageFault; // Page fault from TLB
|
||||
logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults
|
||||
logic [P.PA_BITS-1:0] TLBPAdr; // physical address for TLB
|
||||
logic PMAInstrAccessFaultF; // Instruction access fault from PMA
|
||||
logic PMPInstrAccessFaultF; // Instruction access fault from PMP
|
||||
logic PMALoadAccessFaultM; // Load access fault from PMA
|
||||
logic PMPLoadAccessFaultM; // Load access fault from PMP
|
||||
logic PMAStoreAmoAccessFaultM; // Store or AMO access fault from PMA
|
||||
logic PMPStoreAmoAccessFaultM; // Store or AMO access fault from PMP
|
||||
logic DataMisalignedM; // load or store misaligned
|
||||
logic Translate; // Translation occurs when virtual memory is active and DisableTranslation is off
|
||||
logic TLBHit; // Hit in TLB
|
||||
logic TLBPageFault; // Page fault from TLB
|
||||
logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults
|
||||
|
||||
// only instantiate TLB if Virtual Memory is supported
|
||||
if (P.VIRTMEM_SUPPORTED) begin:tlb
|
||||
@ -86,9 +86,9 @@ module mmu import cvw::*; #(parameter cvw_t P,
|
||||
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
|
||||
.Translate, .TLBPageFault, .UpdateDA);
|
||||
end else begin:tlb // just pass address through as physical
|
||||
assign Translate = 0;
|
||||
assign TLBMiss = 0;
|
||||
assign TLBHit = 1; // *** is this necessary
|
||||
assign Translate = 0;
|
||||
assign TLBMiss = 0;
|
||||
assign TLBHit = 1; // *** is this necessary
|
||||
assign TLBPageFault = 0;
|
||||
end
|
||||
|
||||
|
@ -30,26 +30,26 @@
|
||||
|
||||
module pmachecker import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||
input logic [1:0] Size,
|
||||
input logic AtomicAccessM, // Atomic access
|
||||
input logic ExecuteAccessF, // Execute access
|
||||
input logic WriteAccessM, // Write access
|
||||
input logic ReadAccessM, // Read access
|
||||
output logic Cacheable, Idempotent, SelTIM,
|
||||
output logic PMAInstrAccessFaultF,
|
||||
output logic PMALoadAccessFaultM,
|
||||
output logic PMAStoreAmoAccessFaultM
|
||||
input logic [1:0] Size,
|
||||
input logic AtomicAccessM, // Atomic access
|
||||
input logic ExecuteAccessF, // Execute access
|
||||
input logic WriteAccessM, // Write access
|
||||
input logic ReadAccessM, // Read access
|
||||
output logic Cacheable, Idempotent, SelTIM,
|
||||
output logic PMAInstrAccessFaultF,
|
||||
output logic PMALoadAccessFaultM,
|
||||
output logic PMAStoreAmoAccessFaultM
|
||||
);
|
||||
|
||||
logic PMAAccessFault;
|
||||
logic AccessRW, AccessRWX, AccessRX;
|
||||
logic [10:0] SelRegions;
|
||||
logic AtomicAllowed;
|
||||
logic PMAAccessFault;
|
||||
logic AccessRW, AccessRWX, AccessRX;
|
||||
logic [10:0] SelRegions;
|
||||
logic AtomicAllowed;
|
||||
|
||||
// Determine what type of access is being made
|
||||
assign AccessRW = ReadAccessM | WriteAccessM;
|
||||
assign AccessRW = ReadAccessM | WriteAccessM;
|
||||
assign AccessRWX = ReadAccessM | WriteAccessM | ExecuteAccessF;
|
||||
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
||||
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
||||
|
||||
// Determine which region of physical memory (if any) is being accessed
|
||||
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
|
||||
|
||||
// Detect access faults
|
||||
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
||||
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;
|
||||
assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault;
|
||||
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
||||
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;
|
||||
assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault;
|
||||
assign PMAStoreAmoAccessFaultM = WriteAccessM & PMAAccessFault;
|
||||
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
|
||||
// implementation will not detect the failure.
|
||||
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,
|
||||
// which we might not intend.
|
||||
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,
|
||||
output logic PMPInstrAccessFaultF,
|
||||
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
|
||||
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] 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] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
||||
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] 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] 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
|
||||
pmpadrdec #(P) pmpadrdecs[P.PMP_ENTRIES-1:0](
|
||||
|
@ -29,100 +29,101 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module csr import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic FlushM, FlushW,
|
||||
input logic StallE, StallM, StallW,
|
||||
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 [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 CSRReadM, CSRWriteM, // read or write CSR
|
||||
input logic TrapM, // trap is occurring
|
||||
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 InterruptM, // interrupt is occurring
|
||||
input logic ExceptionM, // interrupt is occurring
|
||||
input logic MTimerInt, // timer interrupt
|
||||
input logic MExtInt, SExtInt, // external interrupt (from PLIC)
|
||||
input logic MSwInt, // software interrupt
|
||||
input logic [63:0] MTIME_CLINT, // TIME value from CLINT
|
||||
input logic InstrValidM, // current instruction is valid
|
||||
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 [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
|
||||
input logic [1:0] PrivilegeModeW, // current privilege mode
|
||||
input logic [3:0] CauseM, // Trap cause
|
||||
input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode
|
||||
input logic clk, reset,
|
||||
input logic FlushM, FlushW,
|
||||
input logic StallE, StallM, StallW,
|
||||
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 [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 CSRReadM, CSRWriteM, // read or write CSR
|
||||
input logic TrapM, // trap is occurring
|
||||
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 InterruptM, // interrupt is occurring
|
||||
input logic ExceptionM, // interrupt is occurring
|
||||
input logic MTimerInt, // timer interrupt
|
||||
input logic MExtInt, SExtInt, // external interrupt (from PLIC)
|
||||
input logic MSwInt, // software interrupt
|
||||
input logic [63:0] MTIME_CLINT, // TIME value from CLINT
|
||||
input logic InstrValidM, // current instruction is valid
|
||||
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 [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
|
||||
input logic [1:0] PrivilegeModeW, // current privilege mode
|
||||
input logic [3:0] CauseM, // Trap cause
|
||||
input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode
|
||||
// inputs for performance counters
|
||||
input logic LoadStallD,
|
||||
input logic StoreStallD,
|
||||
input logic ICacheStallF,
|
||||
input logic DCacheStallM,
|
||||
input logic BPDirPredWrongM,
|
||||
input logic BTAWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic IClassWrongM,
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic ICacheMiss,
|
||||
input logic ICacheAccess,
|
||||
input logic sfencevmaM,
|
||||
input logic InvalidateICacheM,
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
input logic LoadStallD,
|
||||
input logic StoreStallD,
|
||||
input logic ICacheStallF,
|
||||
input logic DCacheStallM,
|
||||
input logic BPDirPredWrongM,
|
||||
input logic BTAWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic IClassWrongM,
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic ICacheMiss,
|
||||
input logic ICacheAccess,
|
||||
input logic sfencevmaM,
|
||||
input logic InvalidateICacheM,
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
// outputs from CSRs
|
||||
output logic [1:0] STATUS_MPP,
|
||||
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
|
||||
output logic [15:0] MEDELEG_REGW,
|
||||
output logic [P.XLEN-1:0] SATP_REGW,
|
||||
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||
output logic STATUS_MIE, STATUS_SIE,
|
||||
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
|
||||
output logic [1:0] STATUS_FS,
|
||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||
output logic [1:0] STATUS_MPP,
|
||||
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
|
||||
output logic [15:0] MEDELEG_REGW,
|
||||
output logic [P.XLEN-1:0] SATP_REGW,
|
||||
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||
output logic STATUS_MIE, STATUS_SIE,
|
||||
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
|
||||
output logic [1:0] STATUS_FS,
|
||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||
output logic [2:0] FRM_REGW,
|
||||
output logic [2:0] FRM_REGW,
|
||||
//
|
||||
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 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 [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 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
|
||||
);
|
||||
|
||||
localparam MIP = 12'h344;
|
||||
localparam SIP = 12'h144;
|
||||
|
||||
logic [P.XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM;
|
||||
logic [P.XLEN-1:0] CSRReadValM;
|
||||
logic [P.XLEN-1:0] CSRSrcM;
|
||||
logic [P.XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
|
||||
logic [P.XLEN-1:0] CSRWriteValM;
|
||||
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] MEPC_REGW, SEPC_REGW;
|
||||
logic [P.XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM;
|
||||
logic [P.XLEN-1:0] CSRReadValM;
|
||||
logic [P.XLEN-1:0] CSRSrcM;
|
||||
logic [P.XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
|
||||
logic [P.XLEN-1:0] CSRWriteValM;
|
||||
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] MEPC_REGW, SEPC_REGW;
|
||||
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
|
||||
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
|
||||
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
|
||||
logic UngatedCSRMWriteM;
|
||||
logic WriteFRMM, WriteFFLAGSM;
|
||||
logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
|
||||
logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
|
||||
logic [4:0] NextCauseM;
|
||||
logic [11:0] CSRAdrM;
|
||||
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM;
|
||||
logic InsufficientCSRPrivilegeM;
|
||||
logic IllegalCSRMWriteReadonlyM;
|
||||
logic [P.XLEN-1:0] CSRReadVal2M;
|
||||
logic [P.XLEN-1:0] CSRReadVal2M;
|
||||
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 [P.XLEN-1:0] EPC;
|
||||
logic [P.XLEN-1:0] EPC;
|
||||
logic RetM;
|
||||
logic SelMtvecM;
|
||||
logic [P.XLEN-1:0] TVecAlignedM;
|
||||
logic [P.XLEN-1:0] TVecAlignedM;
|
||||
logic InstrValidNotFlushedM;
|
||||
logic STimerInt;
|
||||
logic MENVCFG_STCE;
|
||||
|
||||
// only valid unflushed instructions can access CSRs
|
||||
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
||||
@ -179,13 +180,13 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
||||
else CSRReadVal2M = CSRReadValM;
|
||||
|
||||
// Compute AND/OR modification
|
||||
CSRRWM = CSRSrcM;
|
||||
CSRRSM = CSRReadVal2M | CSRSrcM;
|
||||
CSRRCM = CSRReadVal2M & ~CSRSrcM;
|
||||
CSRRWM = CSRSrcM;
|
||||
CSRRSM = CSRReadVal2M | CSRSrcM;
|
||||
CSRRCM = CSRReadVal2M & ~CSRSrcM;
|
||||
case (InstrM[13:12])
|
||||
2'b01: CSRWriteValM = CSRRWM;
|
||||
2'b10: CSRWriteValM = CSRRSM;
|
||||
2'b11: CSRWriteValM = CSRRCM;
|
||||
2'b01: CSRWriteValM = CSRRWM;
|
||||
2'b10: CSRWriteValM = CSRRSM;
|
||||
2'b11: CSRWriteValM = CSRRCM;
|
||||
default: CSRWriteValM = CSRReadValM;
|
||||
endcase
|
||||
end
|
||||
@ -213,7 +214,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
||||
csri #(P) csri(.clk, .reset,
|
||||
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
|
||||
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt,
|
||||
.MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
|
||||
.MIDELEG_REGW, .MENVCFG_STCE, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
|
||||
|
||||
csrsr #(P) csrsr(.clk, .reset, .StallW,
|
||||
.WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM,
|
||||
@ -231,7 +232,8 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
||||
.MEPC_REGW, .MCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW,
|
||||
.MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||
.MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM,
|
||||
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM);
|
||||
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM,
|
||||
.MENVCFG_STCE);
|
||||
|
||||
|
||||
if (P.S_SUPPORTED) begin:csrs
|
||||
@ -242,7 +244,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
||||
.CSRWriteValM, .PrivilegeModeW,
|
||||
.CSRSReadValM, .STVEC_REGW, .SEPC_REGW,
|
||||
.SCOUNTEREN_REGW,
|
||||
.SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT,
|
||||
.SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .MENVCFG_STCE,
|
||||
.WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt);
|
||||
end else begin
|
||||
assign WriteSSTATUSM = 0;
|
||||
@ -266,7 +268,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
||||
assign IllegalCSRUAccessM = 1;
|
||||
end
|
||||
|
||||
if (P.ZICOUNTERS_SUPPORTED) begin:counters
|
||||
if (P.ZICNTR_SUPPORTED) begin:counters
|
||||
csrc #(P) counters(.clk, .reset, .StallE, .StallM, .FlushM,
|
||||
.InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM,
|
||||
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM,
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// csrc.sv
|
||||
//
|
||||
@ -31,57 +29,57 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module csrc import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic StallE, StallM,
|
||||
input logic FlushM,
|
||||
input logic InstrValidNotFlushedM, LoadStallD, StoreStallD,
|
||||
input logic CSRMWriteM, CSRWriteM,
|
||||
input logic BPDirPredWrongM,
|
||||
input logic BTAWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic IClassWrongM,
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic ICacheMiss,
|
||||
input logic ICacheAccess,
|
||||
input logic ICacheStallF,
|
||||
input logic DCacheStallM,
|
||||
input logic sfencevmaM,
|
||||
input logic InterruptM,
|
||||
input logic ExceptionM,
|
||||
input logic InvalidateICacheM,
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic clk, reset,
|
||||
input logic StallE, StallM,
|
||||
input logic FlushM,
|
||||
input logic InstrValidNotFlushedM, LoadStallD, StoreStallD,
|
||||
input logic CSRMWriteM, CSRWriteM,
|
||||
input logic BPDirPredWrongM,
|
||||
input logic BTAWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic IClassWrongM,
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic ICacheMiss,
|
||||
input logic ICacheAccess,
|
||||
input logic ICacheStallF,
|
||||
input logic DCacheStallM,
|
||||
input logic sfencevmaM,
|
||||
input logic InterruptM,
|
||||
input logic ExceptionM,
|
||||
input logic InvalidateICacheM,
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
output logic [P.XLEN-1:0] CSRCReadValM,
|
||||
output logic IllegalCSRCAccessM
|
||||
output logic IllegalCSRCAccessM
|
||||
);
|
||||
|
||||
localparam MHPMCOUNTERBASE = 12'hB00;
|
||||
localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul;
|
||||
localparam MHPMCOUNTERBASE = 12'hB00;
|
||||
localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul;
|
||||
localparam MHPMCOUNTERHBASE = 12'hB80;
|
||||
localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault
|
||||
localparam MHPMEVENTBASE = 12'h320;
|
||||
localparam HPMCOUNTERBASE = 12'hC00;
|
||||
localparam HPMCOUNTERHBASE = 12'hC80;
|
||||
localparam TIME = 12'hC01;
|
||||
localparam TIMEH = 12'hC81;
|
||||
localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault
|
||||
localparam MHPMEVENTBASE = 12'h320;
|
||||
localparam HPMCOUNTERBASE = 12'hC00;
|
||||
localparam HPMCOUNTERHBASE = 12'hC80;
|
||||
localparam TIME = 12'hC01;
|
||||
localparam TIMEH = 12'hC81;
|
||||
|
||||
logic [4:0] CounterNumM;
|
||||
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] HPMCOUNTER_REGW[P.COUNTERS-1:0];
|
||||
logic [P.XLEN-1:0] HPMCOUNTERH_REGW[P.COUNTERS-1:0];
|
||||
logic LoadStallE, LoadStallM;
|
||||
logic StoreStallE, StoreStallM;
|
||||
logic [P.COUNTERS-1:0] WriteHPMCOUNTERM;
|
||||
logic [P.COUNTERS-1:0] CounterEvent;
|
||||
logic [P.COUNTERS-1:0] WriteHPMCOUNTERM;
|
||||
logic [P.COUNTERS-1:0] CounterEvent;
|
||||
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;
|
||||
|
||||
// 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}));
|
||||
|
||||
// Determine when to increment each counter
|
||||
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
|
||||
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
|
||||
assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired
|
||||
if(P.QEMU) begin: cevent // No other performance counters in QEMU
|
||||
assign CounterEvent[P.COUNTERS-1:3] = 0;
|
||||
end else begin: cevent // User-defined counters
|
||||
assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
|
||||
assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
|
||||
assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
|
||||
assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
|
||||
assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
|
||||
assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
|
||||
assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
|
||||
assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
|
||||
assign CounterEvent[11] = LoadStallM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
|
||||
assign CounterEvent[12] = StoreStallM; // Store Stall
|
||||
assign CounterEvent[13] = DCacheAccess & InstrValidNotFlushedM; // data cache access
|
||||
assign CounterEvent[14] = DCacheMiss; // data cache miss. Miss asserted 1 cycle at start of cache miss
|
||||
assign CounterEvent[15] = DCacheStallM; // d cache miss cycles
|
||||
assign CounterEvent[16] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access
|
||||
assign CounterEvent[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss
|
||||
assign CounterEvent[18] = ICacheStallF; // i cache miss cycles
|
||||
assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes
|
||||
assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i
|
||||
assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma
|
||||
assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low
|
||||
assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low
|
||||
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
|
||||
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
|
||||
assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired
|
||||
if (P.ZIHPM_SUPPORTED) begin: cevent // User-defined counters
|
||||
assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
|
||||
assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
|
||||
assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
|
||||
assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
|
||||
assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
|
||||
assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
|
||||
assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
|
||||
assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
|
||||
assign CounterEvent[11] = LoadStallM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
|
||||
assign CounterEvent[12] = StoreStallM; // Store Stall
|
||||
assign CounterEvent[13] = DCacheAccess & InstrValidNotFlushedM; // data cache access
|
||||
assign CounterEvent[14] = DCacheMiss; // data cache miss. Miss asserted 1 cycle at start of cache miss
|
||||
assign CounterEvent[15] = DCacheStallM; // d cache miss cycles
|
||||
assign CounterEvent[16] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access
|
||||
assign CounterEvent[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss
|
||||
assign CounterEvent[18] = ICacheStallF; // i cache miss cycles
|
||||
assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes
|
||||
assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i
|
||||
assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma
|
||||
assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low
|
||||
assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low
|
||||
// coverage off
|
||||
// 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
|
||||
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
|
||||
|
||||
// Counter update and write logic
|
||||
@ -158,14 +156,14 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
||||
/* verilator lint_on WIDTH */
|
||||
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+P.COUNTERS & CSRAdrM != MTIME)
|
||||
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS)
|
||||
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS)
|
||||
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||
else begin
|
||||
CSRCReadValM = 0;
|
||||
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
|
||||
end
|
||||
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 */
|
||||
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];
|
||||
@ -189,4 +187,4 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
||||
end
|
||||
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) (
|
||||
input logic clk, reset,
|
||||
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 MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt,
|
||||
input logic [11:0] MIDELEG_REGW,
|
||||
input logic MENVCFG_STCE,
|
||||
output logic [11:0] MIP_REGW, MIE_REGW,
|
||||
output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0
|
||||
);
|
||||
@ -60,7 +61,7 @@ module csri import cvw::*; #(parameter cvw_t P) (
|
||||
if (P.S_SUPPORTED) begin:mask
|
||||
if (P.SSTC_SUPPORTED) begin
|
||||
assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec)
|
||||
assign STIP = STimerInt;
|
||||
assign STIP = MENVCFG_STCE ? STimerInt : MIP_REGW_writeable[5];
|
||||
end else begin
|
||||
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9)
|
||||
assign STIP = MIP_REGW_writeable[5];
|
||||
@ -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 (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,
|
||||
MTimerInt, 1'b0, STIP, 1'b0,
|
||||
MSwInt, 1'b0, MIP_REGW_writeable[1], 1'b0};
|
||||
|
@ -32,67 +32,74 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module csrm import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic UngatedCSRMWriteM, CSRMWriteM, MTrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic clk, reset,
|
||||
input logic UngatedCSRMWriteM, CSRMWriteM, MTrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
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 [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] MEPC_REGW,
|
||||
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
|
||||
output logic [15:0] MEDELEG_REGW,
|
||||
output logic [11:0] MIDELEG_REGW,
|
||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
|
||||
output logic [15:0] MEDELEG_REGW,
|
||||
output logic [11:0] MIDELEG_REGW,
|
||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
|
||||
output logic WriteMSTATUSM, WriteMSTATUSHM,
|
||||
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM
|
||||
output logic WriteMSTATUSM, WriteMSTATUSHM,
|
||||
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM,
|
||||
output logic MENVCFG_STCE
|
||||
);
|
||||
|
||||
logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW;
|
||||
logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW;
|
||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||
logic [63:0] MENVCFG_REGW;
|
||||
logic [P.XLEN-1:0] MENVCFGH_REGW;
|
||||
logic [63:0] MENVCFG_PreWriteValM, MENVCFG_WriteValM;
|
||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||
logic WriteMENVCFGM;
|
||||
|
||||
// Machine CSRs
|
||||
localparam MVENDORID = 12'hF11;
|
||||
localparam MARCHID = 12'hF12;
|
||||
localparam MIMPID = 12'hF13;
|
||||
localparam MHARTID = 12'hF14;
|
||||
localparam MCONFIGPTR = 12'hF15;
|
||||
localparam MSTATUS = 12'h300;
|
||||
localparam MISA_ADR = 12'h301;
|
||||
localparam MEDELEG = 12'h302;
|
||||
localparam MIDELEG = 12'h303;
|
||||
localparam MIE = 12'h304;
|
||||
localparam MTVEC = 12'h305;
|
||||
localparam MCOUNTEREN = 12'h306;
|
||||
localparam MSTATUSH = 12'h310;
|
||||
localparam MVENDORID = 12'hF11;
|
||||
localparam MARCHID = 12'hF12;
|
||||
localparam MIMPID = 12'hF13;
|
||||
localparam MHARTID = 12'hF14;
|
||||
localparam MCONFIGPTR = 12'hF15;
|
||||
localparam MSTATUS = 12'h300;
|
||||
localparam MISA_ADR = 12'h301;
|
||||
localparam MEDELEG = 12'h302;
|
||||
localparam MIDELEG = 12'h303;
|
||||
localparam MIE = 12'h304;
|
||||
localparam MTVEC = 12'h305;
|
||||
localparam MCOUNTEREN = 12'h306;
|
||||
localparam MENVCFG = 12'h30A;
|
||||
localparam MSTATUSH = 12'h310;
|
||||
localparam MENVCFGH = 12'h31A;
|
||||
localparam MCOUNTINHIBIT = 12'h320;
|
||||
localparam MSCRATCH = 12'h340;
|
||||
localparam MEPC = 12'h341;
|
||||
localparam MCAUSE = 12'h342;
|
||||
localparam MTVAL = 12'h343;
|
||||
localparam MIP = 12'h344;
|
||||
localparam MTINST = 12'h34A;
|
||||
localparam PMPCFG0 = 12'h3A0;
|
||||
localparam MSCRATCH = 12'h340;
|
||||
localparam MEPC = 12'h341;
|
||||
localparam MCAUSE = 12'h342;
|
||||
localparam MTVAL = 12'h343;
|
||||
localparam MIP = 12'h344;
|
||||
localparam MTINST = 12'h34A;
|
||||
localparam PMPCFG0 = 12'h3A0;
|
||||
// .. up to 15 more at consecutive addresses
|
||||
localparam PMPADDR0 = 12'h3B0;
|
||||
localparam PMPADDR0 = 12'h3B0;
|
||||
// ... up to 63 more at consecutive addresses
|
||||
localparam TSELECT = 12'h7A0;
|
||||
localparam TDATA1 = 12'h7A1;
|
||||
localparam TDATA2 = 12'h7A2;
|
||||
localparam TDATA3 = 12'h7A3;
|
||||
localparam DCSR = 12'h7B0;
|
||||
localparam DPC = 12'h7B1;
|
||||
localparam DSCRATCH0 = 12'h7B2;
|
||||
localparam DSCRATCH1 = 12'h7B3;
|
||||
localparam TSELECT = 12'h7A0;
|
||||
localparam TDATA1 = 12'h7A1;
|
||||
localparam TDATA2 = 12'h7A2;
|
||||
localparam TDATA3 = 12'h7A3;
|
||||
localparam DCSR = 12'h7B0;
|
||||
localparam DPC = 12'h7B1;
|
||||
localparam DSCRATCH0 = 12'h7B2;
|
||||
localparam DSCRATCH1 = 12'h7B3;
|
||||
// Constants
|
||||
localparam ZERO = {(P.XLEN){1'b0}};
|
||||
localparam MEDELEG_MASK = 16'hB3FF;
|
||||
localparam MIDELEG_MASK = 12'h222; // we choose to not make machine interrupts delegable
|
||||
localparam MEDELEG_MASK = 16'hB3FF;
|
||||
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
|
||||
genvar i;
|
||||
@ -130,16 +137,17 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
||||
assign MHARTID_REGW = 0;
|
||||
|
||||
// Write machine Mode CSRs
|
||||
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS);
|
||||
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH)& (P.XLEN==32);
|
||||
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC);
|
||||
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG);
|
||||
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG);
|
||||
assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH);
|
||||
assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC));
|
||||
assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE));
|
||||
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
||||
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
||||
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS);
|
||||
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & (P.XLEN==32);
|
||||
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC);
|
||||
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG);
|
||||
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG);
|
||||
assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH);
|
||||
assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC));
|
||||
assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE));
|
||||
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
||||
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
||||
assign WriteMENVCFGM = CSRMWriteM & (CSRAdrM == MENVCFG);
|
||||
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT);
|
||||
|
||||
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);
|
||||
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
|
||||
// verilator lint_off WIDTH
|
||||
logic [5:0] entry;
|
||||
@ -181,26 +222,28 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
||||
end
|
||||
end
|
||||
else case (CSRAdrM)
|
||||
MISA_ADR: CSRMReadValM = MISA_REGW;
|
||||
MVENDORID: CSRMReadValM = 0;
|
||||
MARCHID: CSRMReadValM = 0;
|
||||
MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation
|
||||
MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0
|
||||
MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0
|
||||
MSTATUS: CSRMReadValM = MSTATUS_REGW;
|
||||
MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
|
||||
MTVEC: CSRMReadValM = MTVEC_REGW;
|
||||
MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW};
|
||||
MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW};
|
||||
MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW};
|
||||
MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW};
|
||||
MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
|
||||
MEPC: CSRMReadValM = MEPC_REGW;
|
||||
MCAUSE: CSRMReadValM = MCAUSE_REGW;
|
||||
MTVAL: CSRMReadValM = MTVAL_REGW;
|
||||
MTINST: CSRMReadValM = 0; // implemented as trivial zero
|
||||
MCOUNTEREN:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW};
|
||||
MCOUNTINHIBIT:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
|
||||
MISA_ADR: CSRMReadValM = MISA_REGW;
|
||||
MVENDORID: CSRMReadValM = 0;
|
||||
MARCHID: CSRMReadValM = 0;
|
||||
MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation
|
||||
MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0
|
||||
MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0
|
||||
MSTATUS: CSRMReadValM = MSTATUS_REGW;
|
||||
MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
|
||||
MTVEC: CSRMReadValM = MTVEC_REGW;
|
||||
MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW};
|
||||
MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW};
|
||||
MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW};
|
||||
MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW};
|
||||
MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
|
||||
MEPC: CSRMReadValM = MEPC_REGW;
|
||||
MCAUSE: CSRMReadValM = MCAUSE_REGW;
|
||||
MTVAL: CSRMReadValM = MTVAL_REGW;
|
||||
MTINST: CSRMReadValM = 0; // implemented as trivial zero
|
||||
MCOUNTEREN: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW};
|
||||
MENVCFG: CSRMReadValM = MENVCFG_REGW[P.XLEN-1:0];
|
||||
MENVCFGH: CSRMReadValM = MENVCFGH_REGW;
|
||||
MCOUNTINHIBIT: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
|
||||
|
||||
default: begin
|
||||
CSRMReadValM = 0;
|
||||
@ -209,4 +252,4 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
||||
endcase
|
||||
end
|
||||
// verilator lint_on WIDTH
|
||||
endmodule
|
||||
endmodule
|
@ -29,61 +29,69 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module csrs import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic CSRSWriteM, STrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic clk, reset,
|
||||
input logic CSRSWriteM, STrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [P.XLEN-1:0] NextEPCM, NextMtvalM, SSTATUS_REGW,
|
||||
input logic [4:0] NextCauseM,
|
||||
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 [4:0] NextCauseM,
|
||||
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 [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] SEPC_REGW,
|
||||
output logic [31:0] SCOUNTEREN_REGW,
|
||||
output logic [31:0] SCOUNTEREN_REGW,
|
||||
output logic [P.XLEN-1:0] SATP_REGW,
|
||||
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
output logic WriteSSTATUSM,
|
||||
output logic IllegalCSRSAccessM,
|
||||
output logic STimerInt
|
||||
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
input logic MENVCFG_STCE,
|
||||
output logic WriteSSTATUSM,
|
||||
output logic IllegalCSRSAccessM,
|
||||
output logic STimerInt
|
||||
);
|
||||
|
||||
// Supervisor CSRs
|
||||
localparam SSTATUS = 12'h100;
|
||||
localparam SIE = 12'h104;
|
||||
localparam STVEC = 12'h105;
|
||||
localparam SSTATUS = 12'h100;
|
||||
localparam SIE = 12'h104;
|
||||
localparam STVEC = 12'h105;
|
||||
localparam SCOUNTEREN = 12'h106;
|
||||
localparam SSCRATCH = 12'h140;
|
||||
localparam SEPC = 12'h141;
|
||||
localparam SCAUSE = 12'h142;
|
||||
localparam STVAL = 12'h143;
|
||||
localparam SIP= 12'h144;
|
||||
localparam STIMECMP = 12'h14D;
|
||||
localparam STIMECMPH = 12'h15D;
|
||||
localparam SATP = 12'h180;
|
||||
localparam SENVCFG = 12'h10A;
|
||||
localparam SSCRATCH = 12'h140;
|
||||
localparam SEPC = 12'h141;
|
||||
localparam SCAUSE = 12'h142;
|
||||
localparam STVAL = 12'h143;
|
||||
localparam SIP = 12'h144;
|
||||
localparam STIMECMP = 12'h14D;
|
||||
localparam STIMECMPH = 12'h15D;
|
||||
localparam SATP = 12'h180;
|
||||
// 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);
|
||||
|
||||
logic WriteSTVECM;
|
||||
logic WriteSSCRATCHM, WriteSEPCM;
|
||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||
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;
|
||||
|
||||
// write enables
|
||||
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS);
|
||||
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC);
|
||||
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH);
|
||||
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC));
|
||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE));
|
||||
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL));
|
||||
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
|
||||
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS);
|
||||
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC);
|
||||
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH);
|
||||
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC));
|
||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE));
|
||||
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL));
|
||||
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
|
||||
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
|
||||
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM);
|
||||
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM) & (P.XLEN == 32);
|
||||
assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG);
|
||||
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE));
|
||||
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)) & (P.XLEN == 32);
|
||||
|
||||
// CSRs
|
||||
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
|
||||
// Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs
|
||||
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
|
||||
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
|
||||
always_comb begin:csrr
|
||||
@ -130,12 +156,15 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
||||
IllegalCSRSAccessM = 1;
|
||||
end
|
||||
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
|
||||
CSRSReadValM = 0;
|
||||
IllegalCSRSAccessM = 1;
|
||||
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
|
||||
CSRSReadValM = 0;
|
||||
IllegalCSRSAccessM = 1;
|
||||
@ -146,4 +175,4 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
endmodule
|
@ -4,7 +4,7 @@
|
||||
// Written: David_Harris@hmc.edu 9 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Status register
|
||||
// Purpose: Status register (and environment configuration register and others shared across modes)
|
||||
// See RISC-V Privileged Mode Specification 20190608
|
||||
//
|
||||
// Documentation: RISC-V System on Chip Design Chapter 5
|
||||
@ -28,22 +28,22 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module csrsr import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset, StallW,
|
||||
input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM,
|
||||
input logic TrapM, FRegWriteM,
|
||||
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
||||
input logic mretM, sretM,
|
||||
input logic WriteFRMM, WriteFFLAGSM,
|
||||
input logic clk, reset, StallW,
|
||||
input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM,
|
||||
input logic TrapM, FRegWriteM,
|
||||
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
||||
input logic mretM, sretM,
|
||||
input logic WriteFRMM, WriteFFLAGSM,
|
||||
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 [1:0] STATUS_MPP,
|
||||
output logic STATUS_SPP, STATUS_TSR, STATUS_TW,
|
||||
output logic STATUS_MIE, STATUS_SIE,
|
||||
output logic STATUS_MXR, STATUS_SUM,
|
||||
output logic STATUS_MPRV, STATUS_TVM,
|
||||
output logic [1:0] STATUS_FS,
|
||||
output logic BigEndianM
|
||||
output logic [1:0] STATUS_MPP,
|
||||
output logic STATUS_SPP, STATUS_TSR, STATUS_TW,
|
||||
output logic STATUS_MIE, STATUS_SIE,
|
||||
output logic STATUS_MXR, STATUS_SUM,
|
||||
output logic STATUS_MPRV, STATUS_TVM,
|
||||
output logic [1:0] STATUS_FS,
|
||||
output logic BigEndianM
|
||||
);
|
||||
|
||||
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
|
||||
// *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable
|
||||
if (P.XLEN==64) begin: csrsr64 // RV64
|
||||
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_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};
|
||||
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ {P.QEMU ? 2'b0 : STATUS_UXL}, /*9'b0, */ 12'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_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};
|
||||
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_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||
/*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.
|
||||
end else begin: csrsr32 // RV32
|
||||
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
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};
|
||||
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
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};
|
||||
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_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
||||
end
|
||||
|
||||
@ -90,21 +90,21 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
||||
end
|
||||
|
||||
// harwired STATUS bits
|
||||
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_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_UBE = 0; // little-endian
|
||||
assign STATUS_SBE = 0; // little-endian
|
||||
assign STATUS_MBE = 0; // little-endian */
|
||||
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_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_UBE = 0; // little-endian
|
||||
assign STATUS_SBE = 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
|
||||
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_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not 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_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_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_XS = 2'b00; // No additional user-mode state to be dirty
|
||||
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_XS = 2'b00; // No additional user-mode state to be dirty
|
||||
|
||||
always_comb
|
||||
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;
|
||||
//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
|
||||
else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP;
|
||||
else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP;
|
||||
//coverage on
|
||||
else EndiannessPrivMode = PrivilegeModeW;
|
||||
|
||||
case (EndiannessPrivMode)
|
||||
P.M_MODE: BigEndianM = STATUS_MBE;
|
||||
P.S_MODE: BigEndianM = STATUS_SBE;
|
||||
default: BigEndianM = STATUS_UBE;
|
||||
default: BigEndianM = STATUS_UBE;
|
||||
endcase
|
||||
end
|
||||
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
|
||||
always_ff @(posedge clk) //, posedge reset)
|
||||
if (reset) begin
|
||||
STATUS_TSR_INT <= #1 0;
|
||||
STATUS_TW_INT <= #1 0;
|
||||
STATUS_TVM_INT <= #1 0;
|
||||
STATUS_MXR_INT <= #1 0;
|
||||
STATUS_SUM_INT <= #1 0;
|
||||
STATUS_TSR_INT <= #1 0;
|
||||
STATUS_TW_INT <= #1 0;
|
||||
STATUS_TVM_INT <= #1 0;
|
||||
STATUS_MXR_INT <= #1 0;
|
||||
STATUS_SUM_INT <= #1 0;
|
||||
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_MPP <= #1 0;
|
||||
STATUS_SPP <= #1 0;
|
||||
STATUS_MPIE <= #1 0;
|
||||
STATUS_SPIE <= #1 0;
|
||||
STATUS_MIE <= #1 0;
|
||||
STATUS_SIE <= #1 0;
|
||||
STATUS_MBE <= #1 0;
|
||||
STATUS_SBE <= #1 0;
|
||||
STATUS_UBE <= #1 0;
|
||||
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_SPP <= #1 0;
|
||||
STATUS_MPIE <= #1 0;
|
||||
STATUS_SPIE <= #1 0;
|
||||
STATUS_MIE <= #1 0;
|
||||
STATUS_SIE <= #1 0;
|
||||
STATUS_MBE <= #1 0;
|
||||
STATUS_SBE <= #1 0;
|
||||
STATUS_UBE <= #1 0;
|
||||
end else if (~StallW) begin
|
||||
if (TrapM) begin
|
||||
// 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
|
||||
if (NextPrivilegeModeM == P.M_MODE) begin
|
||||
STATUS_MPIE <= #1 STATUS_MIE;
|
||||
STATUS_MIE <= #1 0;
|
||||
STATUS_MPP <= #1 PrivilegeModeW;
|
||||
STATUS_MIE <= #1 0;
|
||||
STATUS_MPP <= #1 PrivilegeModeW;
|
||||
end else begin // supervisor mode
|
||||
STATUS_SPIE <= #1 STATUS_SIE;
|
||||
STATUS_SIE <= #1 0;
|
||||
STATUS_SPP <= #1 PrivilegeModeW[0];
|
||||
STATUS_SIE <= #1 0;
|
||||
STATUS_SPP <= #1 PrivilegeModeW[0];
|
||||
end
|
||||
end else if (mretM) begin // Privileged 3.1.6.1
|
||||
STATUS_MIE <= #1 STATUS_MPIE; // restore global interrupt enable
|
||||
STATUS_MPIE <= #1 1; //
|
||||
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_MIE <= #1 STATUS_MPIE; // restore global interrupt enable
|
||||
STATUS_MPIE <= #1 1; //
|
||||
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.
|
||||
end else if (sretM) begin
|
||||
STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable
|
||||
STATUS_SPIE <= #1 P.S_SUPPORTED;
|
||||
STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs
|
||||
STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable
|
||||
STATUS_SPIE <= #1 P.S_SUPPORTED;
|
||||
STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs
|
||||
STATUS_MPRV_INT <= #1 0; // always clear MPRV
|
||||
end else if (WriteMSTATUSM) begin
|
||||
STATUS_TSR_INT <= #1 CSRWriteValM[22];
|
||||
STATUS_TW_INT <= #1 CSRWriteValM[21];
|
||||
STATUS_TVM_INT <= #1 CSRWriteValM[20];
|
||||
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
||||
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
||||
STATUS_TSR_INT <= #1 CSRWriteValM[22];
|
||||
STATUS_TW_INT <= #1 CSRWriteValM[21];
|
||||
STATUS_TVM_INT <= #1 CSRWriteValM[20];
|
||||
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
||||
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
||||
STATUS_MPRV_INT <= #1 CSRWriteValM[17];
|
||||
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
||||
STATUS_MPP <= #1 STATUS_MPP_NEXT;
|
||||
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
||||
STATUS_MPIE <= #1 CSRWriteValM[7];
|
||||
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
||||
STATUS_MIE <= #1 CSRWriteValM[3];
|
||||
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
||||
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||
STATUS_MBE <= #1 nextMBE;
|
||||
STATUS_SBE <= #1 nextSBE;
|
||||
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
||||
STATUS_MPP <= #1 STATUS_MPP_NEXT;
|
||||
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
||||
STATUS_MPIE <= #1 CSRWriteValM[7];
|
||||
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
||||
STATUS_MIE <= #1 CSRWriteValM[3];
|
||||
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
||||
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||
STATUS_MBE <= #1 nextMBE;
|
||||
STATUS_SBE <= #1 nextSBE;
|
||||
// coverage off
|
||||
// MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc
|
||||
end else if (WriteMSTATUSHM) begin
|
||||
STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED;
|
||||
STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||
STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED;
|
||||
STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||
// coverage on
|
||||
end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits
|
||||
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
||||
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
||||
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
||||
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
||||
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
||||
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
||||
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
||||
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
||||
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
||||
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
||||
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
||||
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
||||
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||
end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11;
|
||||
end
|
||||
endmodule
|
||||
|
@ -27,40 +27,40 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module csru import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic InstrValidNotFlushedM,
|
||||
input logic CSRUWriteM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic clk, reset,
|
||||
input logic InstrValidNotFlushedM,
|
||||
input logic CSRUWriteM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
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,
|
||||
input logic [4:0] SetFflagsM,
|
||||
output logic [2:0] FRM_REGW,
|
||||
output logic WriteFRMM, WriteFFLAGSM,
|
||||
output logic IllegalCSRUAccessM
|
||||
input logic [4:0] SetFflagsM,
|
||||
output logic [2:0] FRM_REGW,
|
||||
output logic WriteFRMM, WriteFFLAGSM,
|
||||
output logic IllegalCSRUAccessM
|
||||
);
|
||||
|
||||
localparam FFLAGS = 12'h001;
|
||||
localparam FRM = 12'h002;
|
||||
localparam FCSR = 12'h003;
|
||||
localparam FRM = 12'h002;
|
||||
localparam FCSR = 12'h003;
|
||||
|
||||
logic [4:0] FFLAGS_REGW;
|
||||
logic [2:0] NextFRMM;
|
||||
logic [4:0] NextFFLAGSM;
|
||||
logic SetOrWriteFFLAGSM;
|
||||
logic [4:0] FFLAGS_REGW;
|
||||
logic [2:0] NextFRMM;
|
||||
logic [4:0] NextFFLAGSM;
|
||||
logic SetOrWriteFFLAGSM;
|
||||
|
||||
// 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);
|
||||
|
||||
// Write Values
|
||||
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
||||
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
|
||||
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
||||
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
|
||||
assign SetOrWriteFFLAGSM = WriteFFLAGSM | (|SetFflagsM & InstrValidNotFlushedM);
|
||||
|
||||
// CSRs
|
||||
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
|
||||
always_comb begin
|
||||
|
@ -28,91 +28,90 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
module privileged import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
// 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 [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] InstrM, // Instruction
|
||||
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] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic
|
||||
// control signals
|
||||
input logic InstrValidM, // Current instruction is valid (not flushed)
|
||||
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
|
||||
input logic PrivilegedM, // privileged instruction
|
||||
input logic InstrValidM, // Current instruction is valid (not flushed)
|
||||
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
|
||||
input logic PrivilegedM, // privileged instruction
|
||||
// processor events for performance counter logging
|
||||
input logic FRegWriteM, // instruction will write floating-point registers
|
||||
input logic LoadStallD, // load instruction is stalling
|
||||
input logic StoreStallD, // store instruction is stalling
|
||||
input logic ICacheStallF, // I cache stalled
|
||||
input logic DCacheStallM, // D cache stalled
|
||||
input logic BPDirPredWrongM, // branch predictor guessed wrong direction
|
||||
input logic BTAWrongM, // branch predictor guessed wrong target
|
||||
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
||||
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM, // actual instruction class
|
||||
input logic DCacheMiss, // data cache miss
|
||||
input logic DCacheAccess, // data cache accessed (hit or miss)
|
||||
input logic ICacheMiss, // instruction cache miss
|
||||
input logic ICacheAccess, // instruction cache access
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
input logic FRegWriteM, // instruction will write floating-point registers
|
||||
input logic LoadStallD, // load instruction is stalling
|
||||
input logic StoreStallD, // store instruction is stalling
|
||||
input logic ICacheStallF, // I cache stalled
|
||||
input logic DCacheStallM, // D cache stalled
|
||||
input logic BPDirPredWrongM, // branch predictor guessed wrong direction
|
||||
input logic BTAWrongM, // branch predictor guessed wrong target
|
||||
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
||||
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM, // actual instruction class
|
||||
input logic DCacheMiss, // data cache miss
|
||||
input logic DCacheAccess, // data cache accessed (hit or miss)
|
||||
input logic ICacheMiss, // instruction cache miss
|
||||
input logic ICacheAccess, // instruction cache access
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
// fault sources
|
||||
input logic InstrAccessFaultF, // instruction 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 InstrPageFaultF, // page faults
|
||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults
|
||||
input logic InstrMisalignedFaultM, // misaligned instruction fault
|
||||
input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault
|
||||
input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU
|
||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources
|
||||
input logic [63:0] MTIME_CLINT, // timer value from CLINT
|
||||
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 InstrAccessFaultF, // instruction 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 InstrPageFaultF, // page faults
|
||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults
|
||||
input logic InstrMisalignedFaultM, // misaligned instruction fault
|
||||
input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault
|
||||
input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU
|
||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources
|
||||
input logic [63:0] MTIME_CLINT, // timer value from CLINT
|
||||
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
|
||||
// CSR outputs
|
||||
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 STATUS_MXR, STATUS_SUM, STATUS_MPRV, // 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 [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 STATUS_MXR, STATUS_SUM, STATUS_MPRV, // 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 [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
|
||||
// PC logic output in privileged unit
|
||||
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
|
||||
// control outputs
|
||||
output logic RetM, TrapM, // return instruction, or trap
|
||||
output logic sfencevmaM, // sfence.vma instruction
|
||||
input logic InvalidateICacheM, // fence instruction
|
||||
output logic BigEndianM, // Use big endian in current privilege mode
|
||||
output logic RetM, TrapM, // return instruction, or trap
|
||||
output logic sfencevmaM, // sfence.vma instruction
|
||||
input logic InvalidateICacheM, // fence instruction
|
||||
output logic BigEndianM, // Use big endian in current privilege mode
|
||||
// Fault outputs
|
||||
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 BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire
|
||||
output logic wfiM, IntPendingM // Stall in Memory stage for WFI until interrupt pending or timeout
|
||||
);
|
||||
|
||||
logic [3:0] CauseM; // trap cause
|
||||
logic [15:0] MEDELEG_REGW; // exception delegation CSR
|
||||
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
|
||||
logic sretM, mretM; // supervisor / machine return instruction
|
||||
logic IllegalCSRAccessM; // Illegal access to CSR
|
||||
logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage
|
||||
logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage
|
||||
logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages
|
||||
logic IllegalInstrFaultM; // Illegal instruction fault
|
||||
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 [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
||||
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
||||
logic DelegateM; // trap should be delegated
|
||||
logic InterruptM; // interrupt occuring
|
||||
logic ExceptionM; // Memory stage instruction caused a fault
|
||||
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
||||
logic [3:0] CauseM; // trap cause
|
||||
logic [15:0] MEDELEG_REGW; // exception delegation CSR
|
||||
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
|
||||
logic sretM, mretM; // supervisor / machine return instruction
|
||||
logic IllegalCSRAccessM; // Illegal access to CSR
|
||||
logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage
|
||||
logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage
|
||||
logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages
|
||||
logic IllegalInstrFaultM; // Illegal instruction fault
|
||||
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 [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
||||
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
||||
logic DelegateM; // trap should be delegated
|
||||
logic InterruptM; // interrupt occuring
|
||||
logic ExceptionM; // Memory stage instruction caused a fault
|
||||
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
||||
|
||||
|
||||
// track the current privilege level
|
||||
privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
|
||||
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
|
||||
@ -156,8 +155,3 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
||||
.InstrValidM, .CommittedM, .CommittedF,
|
||||
.TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM);
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -43,10 +43,10 @@ module privmode import cvw::*; #(parameter cvw_t P) (
|
||||
always_comb begin
|
||||
if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
||||
if (P.S_SUPPORTED & DelegateM) NextPrivilegeModeM = P.S_MODE;
|
||||
else NextPrivilegeModeM = P.M_MODE;
|
||||
end else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
||||
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
||||
else NextPrivilegeModeM = PrivilegeModeW;
|
||||
else NextPrivilegeModeM = P.M_MODE;
|
||||
end else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
||||
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
||||
else NextPrivilegeModeM = PrivilegeModeW;
|
||||
end
|
||||
|
||||
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 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 IntPendingM = |PendingIntsM;
|
||||
assign Committed = CommittedM | CommittedF;
|
||||
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
||||
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
||||
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 PendingIntsM = MIP_REGW & MIE_REGW;
|
||||
assign IntPendingM = |PendingIntsM;
|
||||
assign Committed = CommittedM | CommittedF;
|
||||
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
||||
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
||||
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]) &
|
||||
(PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);
|
||||
|
||||
///////////////////////////////////////////
|
||||
@ -88,7 +88,7 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
||||
LoadAccessFaultM | StoreAmoAccessFaultM;
|
||||
// coverage on
|
||||
assign TrapM = ExceptionM | InterruptM;
|
||||
assign RetM = mretM | sretM;
|
||||
assign RetM = mretM | sretM;
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Cause priority defined in table 3.7 of 20190608 privileged spec
|
||||
|
@ -27,27 +27,27 @@
|
||||
|
||||
module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
||||
parameter PERIPHS = 2) (
|
||||
input logic HCLK, HRESETn,
|
||||
input logic [PERIPHS-1:0] HSEL,
|
||||
input logic HCLK, HRESETn,
|
||||
input logic [PERIPHS-1:0] HSEL,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic [P.XLEN-1:0] HWDATA,
|
||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||
input logic HWRITE,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HREADY,
|
||||
input logic HWRITE,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HREADY,
|
||||
// input logic [3:0] HPROT, // not used
|
||||
output logic [P.XLEN-1:0] HRDATA,
|
||||
output logic HRESP, HREADYOUT,
|
||||
output logic PCLK, PRESETn,
|
||||
output logic [PERIPHS-1:0] PSEL,
|
||||
output logic PWRITE,
|
||||
output logic PENABLE,
|
||||
output logic [31:0] PADDR,
|
||||
output logic HRESP, HREADYOUT,
|
||||
output logic PCLK, PRESETn,
|
||||
output logic [PERIPHS-1:0] PSEL,
|
||||
output logic PWRITE,
|
||||
output logic PENABLE,
|
||||
output logic [31:0] PADDR,
|
||||
output logic [P.XLEN-1:0] PWDATA,
|
||||
// output logic [2:0] PPROT, // not used
|
||||
output logic [P.XLEN/8-1:0] PSTRB,
|
||||
// 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
|
||||
);
|
||||
|
||||
@ -56,15 +56,15 @@ module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
||||
logic PREADYOUT;
|
||||
|
||||
// convert AHB to APB signals
|
||||
assign PCLK = HCLK;
|
||||
assign PCLK = HCLK;
|
||||
assign PRESETn = HRESETn;
|
||||
|
||||
// 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
|
||||
|
||||
// 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 #(PERIPHS) selreg(HCLK, ~HRESETn, HREADY, HSEL & {PERIPHS{initTrans}}, PSEL);
|
||||
// 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
|
||||
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
|
||||
// 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
|
||||
assign HRESP = 0; // bridge never indicates errors
|
||||
endmodule
|
||||
|
||||
|
@ -31,11 +31,11 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [15:0] PADDR,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
output logic [63:0] MTIME,
|
||||
output logic MTimerInt, MSwInt
|
||||
@ -48,11 +48,11 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
||||
integer i, j;
|
||||
|
||||
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
|
||||
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
|
||||
// This will require synchronizing MTIME to the system clock
|
||||
@ -150,36 +150,36 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
||||
endmodule
|
||||
|
||||
module timeregsync import cvw::*; #(parameter cvw_t P) (
|
||||
input logic clk, resetn,
|
||||
input logic we0, we1,
|
||||
input logic clk, resetn,
|
||||
input logic we0, we1,
|
||||
input logic [P.XLEN-1:0] wd,
|
||||
output logic [63:0] q);
|
||||
output logic [63:0] q);
|
||||
|
||||
if (P.XLEN==64)
|
||||
always_ff @(posedge clk or negedge resetn)
|
||||
if (~resetn) q <= 0;
|
||||
if (~resetn) q <= 0;
|
||||
else if (we0) q <= wd;
|
||||
else q <= q + 1;
|
||||
else
|
||||
always_ff @(posedge clk or negedge resetn)
|
||||
if (~resetn) q <= 0;
|
||||
if (~resetn) q <= 0;
|
||||
else if (we0) q[31:0] <= wd;
|
||||
else if (we1) q[63:32] <= wd;
|
||||
else q <= q + 1;
|
||||
endmodule
|
||||
|
||||
module timereg import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn, TIMECLK,
|
||||
input logic we0, we1,
|
||||
input logic PCLK, PRESETn, TIMECLK,
|
||||
input logic we0, we1,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
output logic [63:0] MTIME,
|
||||
output logic done);
|
||||
output logic [63:0] MTIME,
|
||||
output logic done);
|
||||
|
||||
// if (P.TIMEBASE_SYNC) 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));
|
||||
assign done = 1; // immediately completes
|
||||
end else begin // use asynchronous TIMECLK
|
||||
assign done = 1; // immediately completes
|
||||
end else begin // use asynchronous TIMECLK
|
||||
// TIME counter runs on TIMECLK but bus interface runs on PCLK
|
||||
// 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
|
||||
|
@ -29,78 +29,78 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [7:0] PADDR,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [7:0] PADDR,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic [31:0] iof0, iof1,
|
||||
input logic [31:0] GPIOIN,
|
||||
output logic [31:0] GPIOOUT, GPIOEN,
|
||||
output logic GPIOIntr
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic [31:0] iof0, iof1,
|
||||
input logic [31:0] GPIOIN,
|
||||
output logic [31:0] GPIOOUT, GPIOEN,
|
||||
output logic GPIOIntr
|
||||
);
|
||||
|
||||
logic [31:0] input0d, input1d, input2d, input3d;
|
||||
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] out_xor, iof_en, iof_sel, iof_out, gpio_out;
|
||||
logic [7:0] entry;
|
||||
logic [31:0] Din, Dout;
|
||||
logic memwrite;
|
||||
logic [31:0] input0d, input1d, input2d, input3d;
|
||||
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] out_xor, iof_en, iof_sel, iof_out, gpio_out;
|
||||
logic [7:0] entry;
|
||||
logic [31:0] Din, Dout;
|
||||
logic memwrite;
|
||||
|
||||
// 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 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
|
||||
// -- 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")
|
||||
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};
|
||||
end else begin // 32-bit
|
||||
assign Din = PWDATA[31:0];
|
||||
assign Din = PWDATA[31:0];
|
||||
assign PRDATA = Dout;
|
||||
end
|
||||
|
||||
// register access
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) begin // asynch reset
|
||||
input_en <= 0;
|
||||
input_en <= 0;
|
||||
output_en <= 0;
|
||||
// *** synch reset not yet implemented [DH: can we delete this comment? Check if a sync reset is required]
|
||||
output_val <= #1 0;
|
||||
rise_ie <= #1 0;
|
||||
rise_ip <= #1 0;
|
||||
fall_ie <= #1 0;
|
||||
fall_ip <= #1 0;
|
||||
high_ie <= #1 0;
|
||||
high_ip <= #1 0;
|
||||
low_ie <= #1 0;
|
||||
low_ip <= #1 0;
|
||||
iof_en <= #1 0;
|
||||
iof_sel <= #1 0;
|
||||
out_xor <= #1 0;
|
||||
rise_ie <= #1 0;
|
||||
rise_ip <= #1 0;
|
||||
fall_ie <= #1 0;
|
||||
fall_ip <= #1 0;
|
||||
high_ie <= #1 0;
|
||||
high_ip <= #1 0;
|
||||
low_ie <= #1 0;
|
||||
low_ip <= #1 0;
|
||||
iof_en <= #1 0;
|
||||
iof_sel <= #1 0;
|
||||
out_xor <= #1 0;
|
||||
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.
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
if (memwrite)
|
||||
case(entry)
|
||||
8'h04: input_en <= #1 Din;
|
||||
8'h08: output_en <= #1 Din;
|
||||
8'h04: input_en <= #1 Din;
|
||||
8'h08: output_en <= #1 Din;
|
||||
8'h0C: output_val <= #1 Din;
|
||||
8'h18: rise_ie <= #1 Din;
|
||||
8'h20: fall_ie <= #1 Din;
|
||||
8'h28: high_ie <= #1 Din;
|
||||
8'h30: low_ie <= #1 Din;
|
||||
8'h38: iof_en <= #1 Din;
|
||||
8'h3C: iof_sel <= #1 Din;
|
||||
8'h40: out_xor <= #1 Din;
|
||||
8'h18: rise_ie <= #1 Din;
|
||||
8'h20: fall_ie <= #1 Din;
|
||||
8'h28: high_ie <= #1 Din;
|
||||
8'h30: low_ie <= #1 Din;
|
||||
8'h38: iof_en <= #1 Din;
|
||||
8'h3C: iof_sel <= #1 Din;
|
||||
8'h40: out_xor <= #1 Din;
|
||||
endcase
|
||||
/* verilator lint_on CASEINCOMPLETE */
|
||||
|
||||
@ -115,21 +115,21 @@ module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
||||
else low_ip <= low_ip | ~input3d;
|
||||
|
||||
case(entry) // flop to sample inputs
|
||||
8'h00: Dout <= #1 input_val;
|
||||
8'h04: Dout <= #1 input_en;
|
||||
8'h08: Dout <= #1 output_en;
|
||||
8'h0C: Dout <= #1 output_val;
|
||||
8'h18: Dout <= #1 rise_ie;
|
||||
8'h1C: Dout <= #1 rise_ip;
|
||||
8'h20: Dout <= #1 fall_ie;
|
||||
8'h24: Dout <= #1 fall_ip;
|
||||
8'h28: Dout <= #1 high_ie;
|
||||
8'h2C: Dout <= #1 high_ip;
|
||||
8'h30: Dout <= #1 low_ie;
|
||||
8'h34: Dout <= #1 low_ip;
|
||||
8'h38: Dout <= #1 iof_en;
|
||||
8'h3C: Dout <= #1 iof_sel;
|
||||
8'h40: Dout <= #1 out_xor;
|
||||
8'h00: Dout <= #1 input_val;
|
||||
8'h04: Dout <= #1 input_en;
|
||||
8'h08: Dout <= #1 output_en;
|
||||
8'h0C: Dout <= #1 output_val;
|
||||
8'h18: Dout <= #1 rise_ie;
|
||||
8'h1C: Dout <= #1 rise_ip;
|
||||
8'h20: Dout <= #1 fall_ie;
|
||||
8'h24: Dout <= #1 fall_ip;
|
||||
8'h28: Dout <= #1 high_ie;
|
||||
8'h2C: Dout <= #1 high_ip;
|
||||
8'h30: Dout <= #1 low_ie;
|
||||
8'h34: Dout <= #1 low_ip;
|
||||
8'h38: Dout <= #1 iof_en;
|
||||
8'h3C: Dout <= #1 iof_sel;
|
||||
8'h40: Dout <= #1 out_xor;
|
||||
default: Dout <= #1 0;
|
||||
endcase
|
||||
end
|
||||
@ -137,18 +137,17 @@ module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
||||
// chip i/o
|
||||
// connect OUT to IN for loopback testing
|
||||
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
|
||||
flop #(32) sync1(PCLK,input0d,input1d);
|
||||
flop #(32) sync2(PCLK,input1d,input2d);
|
||||
flop #(32) sync3(PCLK,input2d,input3d);
|
||||
assign input_val = input3d;
|
||||
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 GPIOOUT = gpio_out ^ out_xor; // per-bit flip output polarity
|
||||
assign GPIOEN = output_en;
|
||||
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 GPIOOUT = gpio_out ^ out_xor; // per-bit flip output polarity
|
||||
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
|
||||
|
||||
|
@ -41,22 +41,22 @@
|
||||
// hardcoded to 2 contexts for now; later upgrade to arbitrary (up to 15872) contexts
|
||||
|
||||
module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [27:0] PADDR,
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [27:0] PADDR,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic UARTIntr,GPIOIntr,
|
||||
output logic MExtInt, SExtInt
|
||||
output logic PREADY,
|
||||
input logic UARTIntr,GPIOIntr,
|
||||
output logic MExtInt, SExtInt
|
||||
);
|
||||
|
||||
logic memwrite, memread;
|
||||
logic [23:0] entry;
|
||||
logic [31:0] Din, Dout;
|
||||
logic memwrite, memread;
|
||||
logic [23:0] entry;
|
||||
logic [31:0] Din, Dout;
|
||||
|
||||
// context-independent signals
|
||||
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 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 entry = {PADDR[23:2],2'b0};
|
||||
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 entry = {PADDR[23:2],2'b0};
|
||||
|
||||
// account for subword read/write circuitry
|
||||
// -- 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
|
||||
// ==================
|
||||
|
||||
always @(posedge PCLK) begin
|
||||
// resetting
|
||||
if (~PRESETn) begin
|
||||
@ -110,19 +111,19 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||
casez(entry)
|
||||
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
|
||||
24'h002000: intEn[0][`N:1] <= #1 Din[`N:1];
|
||||
24'h002080: intEn[1][`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];
|
||||
`endif
|
||||
`ifndef PLIC_NUM_SRC_LT_32
|
||||
24'h002000: intEn[0][31:1] <= #1 Din[31:1];
|
||||
24'h002004: intEn[0][`N:32] <= #1 Din[31:0];
|
||||
24'h002080: intEn[1][31:1] <= #1 Din[31:1];
|
||||
24'h002084: intEn[1][`N:32] <= #1 Din[31:0];
|
||||
24'h002000: intEn[0][31:1] <= #1 Din[31:1];
|
||||
24'h002004: intEn[0][`N:32] <= #1 Din[31:0];
|
||||
24'h002080: intEn[1][31:1] <= #1 Din[31:1];
|
||||
24'h002084: intEn[1][`N:32] <= #1 Din[31:0];
|
||||
`endif
|
||||
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'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'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'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
|
||||
endcase
|
||||
// Read synchronously because a read can have side effect of changing intInProgress
|
||||
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 SExtInt = |(threshMask[1] & priorities_with_irqs[1]);
|
||||
endmodule
|
||||
|
||||
|
@ -30,33 +30,33 @@
|
||||
|
||||
module ram_ahb import cvw::*; #(parameter cvw_t P,
|
||||
parameter BASE=0, RANGE = 65535) (
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELRam,
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELRam,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic HWRITE,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HWRITE,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic [P.XLEN-1:0] HWDATA,
|
||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||
output logic [P.XLEN-1:0] HREADRam,
|
||||
output logic HRESPRam, HREADYRam
|
||||
output logic HRESPRam, HREADYRam
|
||||
);
|
||||
|
||||
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
||||
localparam OFFSET = $clog2(P.XLEN/8);
|
||||
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
||||
localparam OFFSET = $clog2(P.XLEN/8);
|
||||
|
||||
logic [P.XLEN/8-1:0] ByteMask;
|
||||
logic [P.PA_BITS-1:0] HADDRD, RamAddr;
|
||||
logic initTrans;
|
||||
logic memwrite, memwriteD, memread;
|
||||
logic nextHREADYRam;
|
||||
logic DelayReady;
|
||||
logic initTrans;
|
||||
logic memwrite, memwriteD, memread;
|
||||
logic nextHREADYRam;
|
||||
logic DelayReady;
|
||||
|
||||
// a new AHB transactions starts when HTRANS requests a transaction,
|
||||
// the peripheral is selected, and the previous transaction is completing
|
||||
assign initTrans = HREADY & HSELRam & HTRANS[1] ;
|
||||
assign memwrite = initTrans & HWRITE;
|
||||
assign memread = initTrans & ~HWRITE;
|
||||
assign memwrite = initTrans & HWRITE;
|
||||
assign memread = initTrans & ~HWRITE;
|
||||
|
||||
flopenr #(1) memwritereg(HCLK, ~HRESETn, HREADY, memwrite, memwriteD);
|
||||
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),
|
||||
.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
|
||||
if(`RAM_LATENCY > 0) begin
|
||||
logic [7:0] NextCycle, Cycle;
|
||||
@ -89,15 +88,15 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
|
||||
|
||||
always_ff @(posedge HCLK)
|
||||
if (~HRESETn) CurrState <= #1 READY;
|
||||
else CurrState <= #1 NextState;
|
||||
else CurrState <= #1 NextState;
|
||||
|
||||
always_comb begin
|
||||
case(CurrState)
|
||||
READY: if(initTrans & ~CycleFlag) NextState = DELAY;
|
||||
else NextState = READY;
|
||||
DELAY: if(CycleFlag) NextState = READY;
|
||||
else NextState = DELAY;
|
||||
default: NextState = READY;
|
||||
else NextState = READY;
|
||||
DELAY: if(CycleFlag) NextState = READY;
|
||||
else NextState = DELAY;
|
||||
default: NextState = READY;
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -110,4 +109,3 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -28,24 +28,23 @@
|
||||
|
||||
module rom_ahb import cvw::*; #(parameter cvw_t P,
|
||||
parameter BASE=0, RANGE = 65535) (
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELRom,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
output logic [P.XLEN-1:0] HREADRom,
|
||||
output logic HRESPRom, HREADYRom
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELRom,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
output logic [P.XLEN-1:0] HREADRom,
|
||||
output logic HRESPRom, HREADYRom
|
||||
);
|
||||
|
||||
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
||||
localparam OFFSET = $clog2(P.XLEN/8);
|
||||
localparam OFFSET = $clog2(P.XLEN/8);
|
||||
|
||||
// Never stalls
|
||||
assign HREADYRom = 1'b1;
|
||||
assign HRESPRom = 0; // OK
|
||||
assign HRESPRom = 0; // OK
|
||||
|
||||
// single-ported ROM
|
||||
rom1p1r #(ADDR_WIDTH, P.XLEN, P.FPGA)
|
||||
memory(.clk(HCLK), .ce(1'b1), .addr(HADDR[ADDR_WIDTH+OFFSET-1:OFFSET]), .dout(HREADRom));
|
||||
endmodule
|
||||
|
||||
|
@ -45,7 +45,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
output logic INTR, TXRDYb, RXRDYb, // interrupt and ready lines
|
||||
// Clocks
|
||||
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
|
||||
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
|
||||
@ -71,9 +71,9 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
logic DLAB; // Divisor Latch Access Bit (LCR bit 7)
|
||||
|
||||
// Baud and rx/tx timing
|
||||
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
|
||||
logic [16+UART_PRESCALE-1:0] baudcount;
|
||||
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
|
||||
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
|
||||
logic [16+UART_PRESCALE-1:0] baudcount;
|
||||
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
|
||||
logic [3:0] rxbitsreceived, txbitssent;
|
||||
statetype rxstate, txstate;
|
||||
|
||||
@ -122,6 +122,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
///////////////////////////////////////////
|
||||
// Input synchronization: 2-stage synchronizer
|
||||
///////////////////////////////////////////
|
||||
|
||||
always_ff @(posedge PCLK) begin
|
||||
{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]} :
|
||||
@ -132,6 +133,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
///////////////////////////////////////////
|
||||
// Register interface (Table 1, note some are read only and some write only)
|
||||
///////////////////////////////////////////
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) begin // Table 3 Reset Configuration
|
||||
IER <= #1 4'b0;
|
||||
@ -162,13 +164,13 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
if (~MEMWb & (A == 3'b101))
|
||||
LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
|
||||
else begin
|
||||
LSR[0] <= #1 rxdataready; // Data ready
|
||||
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
|
||||
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
|
||||
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
|
||||
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
|
||||
LSR[5] <= #1 THRE; // THRE
|
||||
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
|
||||
LSR[0] <= #1 rxdataready; // Data ready
|
||||
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
|
||||
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
|
||||
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
|
||||
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
|
||||
LSR[5] <= #1 THRE; // THRE
|
||||
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
|
||||
if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error
|
||||
end
|
||||
|
||||
@ -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
|
||||
// the baudcount is not reset to {DLM, DLL, UART_PRESCALE}
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
baudcount <= #1 1;
|
||||
@ -233,17 +236,18 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
///////////////////////////////////////////
|
||||
// receive timing and control
|
||||
///////////////////////////////////////////
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
rxoversampledcnt <= #1 0;
|
||||
rxstate <= #1 UART_IDLE;
|
||||
rxbitsreceived <= #1 0;
|
||||
rxtimeoutcnt <= #1 0;
|
||||
rxoversampledcnt <= #1 0;
|
||||
rxstate <= #1 UART_IDLE;
|
||||
rxbitsreceived <= #1 0;
|
||||
rxtimeoutcnt <= #1 0;
|
||||
end else begin
|
||||
if (rxstate == UART_IDLE & ~SINsync) begin // got start bit
|
||||
rxstate <= #1 UART_ACTIVE;
|
||||
rxstate <= #1 UART_ACTIVE;
|
||||
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
|
||||
end else if (rxbaudpulse & (rxstate == UART_ACTIVE)) begin
|
||||
rxoversampledcnt <= #1 rxoversampledcnt + 1; // 16x oversampled counter
|
||||
@ -260,13 +264,14 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
|
||||
// ***explain why
|
||||
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
|
||||
|
||||
///////////////////////////////////////////
|
||||
// receive shift register, buffer register, FIFO
|
||||
///////////////////////////////////////////
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
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
|
||||
@ -282,11 +287,11 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
assign rxdata = LCR[3] ? rxdata9[7:0] : rxdata9[8:1]; // discard parity bit
|
||||
|
||||
// ERROR CONDITIONS
|
||||
assign rxparity = ^rxdata;
|
||||
assign rxparityerr = (rxparity ^ rxparitybit ^ ~evenparitysel) & LCR[3]; // Check even/odd parity (*** check if LCR needs to be inverted)
|
||||
assign rxparity = ^rxdata;
|
||||
assign rxparityerr = (rxparity ^ rxparitybit ^ ~evenparitysel) & LCR[3]; // Check even/odd parity (*** check if LCR needs to be inverted)
|
||||
assign rxoverrunerr = fifoenabled ? (rxfifoentries == 15) : rxdataready; // overrun if FIFO or receive buffer register full
|
||||
assign rxframingerr = ~rxstopbit; // framing error if no stop bit
|
||||
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
|
||||
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
|
||||
|
||||
// receive FIFO and register
|
||||
always_ff @(posedge PCLK)
|
||||
@ -298,7 +303,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
end else if (rxstate == UART_DONE) begin
|
||||
RXBR <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata}; // load recevive buffer register
|
||||
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 (fifoenabled) begin
|
||||
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);
|
||||
end
|
||||
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];
|
||||
/* if (i > 0)
|
||||
assign rxfullbit[i] = ((rxfifohead==i) | rxfullbit[i-1]) & (rxfifotail != i);
|
||||
else
|
||||
assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i);*/
|
||||
end
|
||||
assign rxfifohaserr = |(RXerrbit & rxfullbit);
|
||||
assign rxfifohaserr = |(RXerrbit & rxfullbit);
|
||||
|
||||
// receive buffer register and ready bit
|
||||
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;
|
||||
else RXRDYb = rxfifoempty;
|
||||
end else begin
|
||||
RBR = RXBR;
|
||||
RBR = RXBR;
|
||||
RXRDYb = ~rxdataready;
|
||||
end
|
||||
|
||||
///////////////////////////////////////////
|
||||
// transmit timing and control
|
||||
///////////////////////////////////////////
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
txoversampledcnt <= #1 0;
|
||||
txstate <= #1 UART_IDLE;
|
||||
txbitssent <= #1 0;
|
||||
txstate <= #1 UART_IDLE;
|
||||
txbitssent <= #1 0;
|
||||
end else if ((txstate == UART_IDLE) & txsrfull) begin // start transmitting
|
||||
txstate <= #1 UART_ACTIVE;
|
||||
txstate <= #1 UART_ACTIVE;
|
||||
txoversampledcnt <= #1 1;
|
||||
txbitssent <= #1 0;
|
||||
txbitssent <= #1 0;
|
||||
end else if (txbaudpulse & (txstate == UART_ACTIVE)) begin
|
||||
txoversampledcnt <= #1 txoversampledcnt + 1;
|
||||
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
|
||||
// *** explain; is this necessary?
|
||||
if (QEMU) assign txnextbit = txbaudpulse & (txoversampledcnt[1:0] == 2'b00); // implies txstate = UART_ACTIVE
|
||||
else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE
|
||||
else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE
|
||||
|
||||
///////////////////////////////////////////
|
||||
// transmit holding register, shift register, FIFO
|
||||
///////////////////////////////////////////
|
||||
|
||||
always_comb begin // compute value for parity and tx holding register
|
||||
nexttxdata = fifoenabled ? txfifo[txfifotail] : TXHR; // pick from FIFO or holding register
|
||||
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 (fifoenabled) begin
|
||||
txfifo[txfifohead] <= #1 Din;
|
||||
txfifohead <= #1 txfifohead + 1;
|
||||
txfifohead <= #1 txfifohead + 1;
|
||||
end else begin
|
||||
TXHR <= #1 Din;
|
||||
TXHR <= #1 Din;
|
||||
txhrfull <= #1 1;
|
||||
end
|
||||
$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 (fifoenabled) begin
|
||||
if (~txfifoempty & ~txsrfull) begin
|
||||
txsr <= #1 txdata;
|
||||
txsr <= #1 txdata;
|
||||
txfifotail <= #1 txfifotail+1;
|
||||
txsrfull <= #1 1;
|
||||
txsrfull <= #1 1;
|
||||
end
|
||||
end else if (txhrfull) begin
|
||||
txsr <= #1 txdata;
|
||||
txsr <= #1 txdata;
|
||||
txhrfull <= #1 0;
|
||||
txsrfull <= #1 1;
|
||||
end
|
||||
@ -470,13 +477,13 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
HeadPointerLastMove <= 1'b0;
|
||||
end
|
||||
|
||||
assign txfifoempty = (txfifohead == txfifotail) & ~HeadPointerLastMove;
|
||||
assign txfifoempty = (txfifohead == txfifotail) & ~HeadPointerLastMove;
|
||||
// verilator lint_off WIDTH
|
||||
assign txfifoentries = (txfifohead >= txfifotail) ? (txfifohead-txfifotail) :
|
||||
(txfifohead + 16 - txfifotail);
|
||||
// verilator lint_on WIDTH
|
||||
//assign txfifofull = (txfifoentries == 4'b1111);
|
||||
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
|
||||
//assign txfifofull = (txfifoentries == 4'b1111);
|
||||
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
|
||||
|
||||
// transmit buffer ready bit
|
||||
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
|
||||
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
|
||||
///////////////////////////////////////////
|
||||
|
||||
assign RXerr = |LSR[4:1]; // LS interrupt if any of the flags are true
|
||||
assign RXerrIP = RXerr & ~squashRXerrIP; // intr squashed upon reading LSR
|
||||
assign rxdataavailintr = fifoenabled ? rxfifotriggered : rxdataready;
|
||||
@ -533,15 +541,15 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
|
||||
// modem control logic
|
||||
///////////////////////////////////////////
|
||||
|
||||
assign loop = MCR[4];
|
||||
assign loop = MCR[4];
|
||||
assign DTRb = ~MCR[0] | loop; // disable modem signals in loopback mode
|
||||
assign RTSb = ~MCR[1] | loop;
|
||||
assign OUT1b = ~MCR[2] | loop;
|
||||
assign OUT2b = ~MCR[3] | loop;
|
||||
|
||||
assign DLAB = LCR[7];
|
||||
assign evenparitysel = LCR[4];
|
||||
assign fifoenabled = FCR[0];
|
||||
assign evenparitysel = LCR[4];
|
||||
assign fifoenabled = FCR[0];
|
||||
assign fifodmamodesel = FCR[3];
|
||||
always_comb
|
||||
case (FCR[7:6])
|
||||
|
@ -29,18 +29,18 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module uart_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [2:0] PADDR,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [2:0] PADDR,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
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 OUT1b, OUT2b, INTR, TXRDYb, RXRDYb); // to CPU
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
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 OUT1b, OUT2b, INTR, TXRDYb, RXRDYb); // to CPU
|
||||
|
||||
// UART interface signals
|
||||
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 memread = ~PWRITE & PENABLE & PSEL;
|
||||
assign PREADY = 1'b1; // CLINT never takes >1 cycle to respond
|
||||
assign entry = PADDR[2:0];
|
||||
assign MEMRb = ~memread;
|
||||
assign MEMWb = ~memwrite;
|
||||
assign PREADY = 1'b1; // CLINT never takes >1 cycle to respond
|
||||
assign entry = PADDR[2:0];
|
||||
assign MEMRb = ~memread;
|
||||
assign MEMWb = ~memwrite;
|
||||
|
||||
if (P.XLEN == 64) begin:uart
|
||||
always_comb begin
|
||||
@ -97,4 +97,3 @@ module uart_apb import cvw::*; #(parameter cvw_t P) (
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -29,58 +29,58 @@
|
||||
|
||||
module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
// AHB Bus Interface
|
||||
input logic HCLK, HRESETn,
|
||||
input logic TIMECLK,
|
||||
input logic HCLK, HRESETn,
|
||||
input logic TIMECLK,
|
||||
input logic [P.PA_BITS-1:0] HADDR,
|
||||
input logic [P.AHBW-1:0] HWDATA,
|
||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||
input logic HWRITE,
|
||||
input logic [2:0] HSIZE,
|
||||
input logic [2:0] HBURST,
|
||||
input logic [3:0] HPROT,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HMASTLOCK,
|
||||
input logic HWRITE,
|
||||
input logic [2:0] HSIZE,
|
||||
input logic [2:0] HBURST,
|
||||
input logic [3:0] HPROT,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HMASTLOCK,
|
||||
input logic [P.AHBW-1:0] HRDATAEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
output logic [P.AHBW-1:0] HRDATA,
|
||||
output logic HREADY, HRESP,
|
||||
output logic HSELEXT,
|
||||
output logic HREADY, HRESP,
|
||||
output logic HSELEXT,
|
||||
// peripheral pins
|
||||
output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT
|
||||
output logic MExtInt, SExtInt, // External interrupts from PLIC
|
||||
output logic [63:0] MTIME_CLINT, // MTIME, from CLINT
|
||||
input logic [31:0] GPIOIN, // GPIO pin input value
|
||||
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
|
||||
input logic UARTSin, // UART serial input
|
||||
output logic UARTSout, // UART serial output
|
||||
output logic SDCCmdOut, // SD Card command output
|
||||
output logic SDCCmdOE, // SD Card command output enable
|
||||
input logic SDCCmdIn, // SD Card command input
|
||||
input logic [3:0] SDCDatIn, // SD Card data input
|
||||
output logic SDCCLK // SD Card clock
|
||||
output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT
|
||||
output logic MExtInt, SExtInt, // External interrupts from PLIC
|
||||
output logic [63:0] MTIME_CLINT, // MTIME, from CLINT
|
||||
input logic [31:0] GPIOIN, // GPIO pin input value
|
||||
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
|
||||
input logic UARTSin, // UART serial input
|
||||
output logic UARTSout, // UART serial output
|
||||
output logic SDCCmdOut, // SD Card command output
|
||||
output logic SDCCmdOE, // SD Card command output enable
|
||||
input logic SDCCmdIn, // SD Card command input
|
||||
input logic [3:0] SDCDatIn, // SD Card data input
|
||||
output logic SDCCLK // SD Card clock
|
||||
);
|
||||
|
||||
logic [P.XLEN-1:0] HREADRam, HREADSDC;
|
||||
|
||||
logic [10:0] HSELRegions;
|
||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD;
|
||||
logic HRESPRam, HRESPSDC;
|
||||
logic HREADYRam, HRESPSDCD;
|
||||
logic [10:0] HSELRegions;
|
||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD;
|
||||
logic HRESPRam, HRESPSDC;
|
||||
logic HREADYRam, HRESPSDCD;
|
||||
logic [P.XLEN-1:0] HREADBootRom;
|
||||
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
||||
logic HSELNoneD;
|
||||
logic UARTIntr,GPIOIntr;
|
||||
logic SDCIntM;
|
||||
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
||||
logic HSELNoneD;
|
||||
logic UARTIntr,GPIOIntr;
|
||||
logic SDCIntM;
|
||||
|
||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||
logic [3:0] PSEL, PREADY;
|
||||
logic [31:0] PADDR;
|
||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||
logic [3:0] PSEL, PREADY;
|
||||
logic [31:0] PADDR;
|
||||
logic [P.XLEN-1:0] PWDATA;
|
||||
logic [P.XLEN/8-1:0] PSTRB;
|
||||
logic [3:0][P.XLEN-1:0] PRDATA;
|
||||
logic [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
|
||||
// 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
|
||||
);
|
||||
end else begin : sdc
|
||||
assign SDCCLK = 0;
|
||||
assign SDCCLK = 0;
|
||||
assign SDCCmdOut = 0;
|
||||
assign SDCCmdOE = 0;
|
||||
assign SDCCmdOE = 0;
|
||||
end
|
||||
|
||||
// AHB Read Multiplexer
|
||||
@ -189,4 +189,3 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELSDCD, HSELNoneD});
|
||||
flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED);
|
||||
endmodule
|
||||
|
||||
|
114
src/wally/cvw.sv
114
src/wally/cvw.sv
@ -47,8 +47,9 @@ typedef struct packed {
|
||||
// RISC-V Features
|
||||
logic ZICSR_SUPPORTED;
|
||||
logic ZIFENCEI_SUPPORTED;
|
||||
logic [11:0] COUNTERS;
|
||||
logic ZICOUNTERS_SUPPORTED;
|
||||
logic [11:0] COUNTERS;
|
||||
logic ZICNTR_SUPPORTED;
|
||||
logic ZIHPM_SUPPORTED;
|
||||
logic ZFH_SUPPORTED;
|
||||
logic SSTC_SUPPORTED;
|
||||
logic VIRTMEM_SUPPORTED;
|
||||
@ -56,6 +57,10 @@ typedef struct packed {
|
||||
logic BIGENDIAN_SUPPORTED;
|
||||
logic SVADU_SUPPORTED;
|
||||
logic ZMMUL_SUPPORTED;
|
||||
logic ZICBOM_SUPPORTED;
|
||||
logic ZICBOZ_SUPPORTED;
|
||||
logic ZICBOP_SUPPORTED;
|
||||
logic SVPBMT_SUPPORTED;
|
||||
|
||||
// Microarchitectural Features
|
||||
logic BUS_SUPPORTED;
|
||||
@ -63,31 +68,31 @@ typedef struct packed {
|
||||
logic ICACHE_SUPPORTED;
|
||||
|
||||
// TLB configuration. Entries should be a power of 2
|
||||
int ITLB_ENTRIES;
|
||||
int DTLB_ENTRIES;
|
||||
int ITLB_ENTRIES;
|
||||
int DTLB_ENTRIES;
|
||||
|
||||
// Cache configuration. Sizes should be a power of two
|
||||
// typical configuration 4 ways, 4096 ints per way, 256 bit or more lines
|
||||
int DCACHE_NUMWAYS;
|
||||
int DCACHE_WAYSIZEINBYTES;
|
||||
int DCACHE_LINELENINBITS;
|
||||
int ICACHE_NUMWAYS;
|
||||
int ICACHE_WAYSIZEINBYTES;
|
||||
int ICACHE_LINELENINBITS;
|
||||
int DCACHE_NUMWAYS;
|
||||
int DCACHE_WAYSIZEINBYTES;
|
||||
int DCACHE_LINELENINBITS;
|
||||
int ICACHE_NUMWAYS;
|
||||
int ICACHE_WAYSIZEINBYTES;
|
||||
int ICACHE_LINELENINBITS;
|
||||
|
||||
// Integer Divider Configuration
|
||||
// IDIV_BITSPERCYCLE must be 1, 2, or 4
|
||||
int IDIV_BITSPERCYCLE;
|
||||
int IDIV_BITSPERCYCLE;
|
||||
logic IDIV_ON_FPU;
|
||||
|
||||
// Legal number of PMP entries are 0, 16, or 64
|
||||
int PMP_ENTRIES;
|
||||
int PMP_ENTRIES;
|
||||
|
||||
// Address space
|
||||
logic [63:0] RESET_VECTOR;
|
||||
|
||||
// WFI Timeout Wait
|
||||
int WFI_TIMEOUT_BIT;
|
||||
int WFI_TIMEOUT_BIT;
|
||||
|
||||
// Peripheral Addresses
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
@ -129,24 +134,23 @@ typedef struct packed {
|
||||
logic GPIO_LOOPBACK_TEST;
|
||||
|
||||
// Hardware configuration
|
||||
int UART_PRESCALE ;
|
||||
int UART_PRESCALE ;
|
||||
|
||||
// Interrupt configuration
|
||||
int PLIC_NUM_SRC;
|
||||
int PLIC_NUM_SRC;
|
||||
logic PLIC_NUM_SRC_LT_32;
|
||||
int PLIC_GPIO_ID;
|
||||
int PLIC_UART_ID;
|
||||
|
||||
logic BPRED_SUPPORTED;
|
||||
BranchPredictorType BPRED_TYPE;
|
||||
int BPRED_NUM_LHR;
|
||||
int BPRED_SIZE;
|
||||
int BTB_SIZE;
|
||||
int PLIC_GPIO_ID;
|
||||
int PLIC_UART_ID;
|
||||
|
||||
logic BPRED_SUPPORTED;
|
||||
BranchPredictorType BPRED_TYPE;
|
||||
int BPRED_NUM_LHR;
|
||||
int BPRED_SIZE;
|
||||
int BTB_SIZE;
|
||||
|
||||
// FPU division architecture
|
||||
int RADIX;
|
||||
int DIVCOPIES;
|
||||
int RADIX;
|
||||
int DIVCOPIES;
|
||||
|
||||
// bit manipulation
|
||||
logic ZBA_SUPPORTED;
|
||||
@ -199,47 +203,47 @@ typedef struct packed {
|
||||
int PMPCFG_ENTRIES;
|
||||
|
||||
// Floating point constants for Quad, Double, Single, and Half precisions
|
||||
int Q_LEN;
|
||||
int Q_NE;
|
||||
int Q_NF;
|
||||
int Q_BIAS;
|
||||
int Q_LEN;
|
||||
int Q_NE;
|
||||
int Q_NF;
|
||||
int Q_BIAS;
|
||||
logic [1:0] Q_FMT;
|
||||
int D_LEN;
|
||||
int D_NE;
|
||||
int D_NF;
|
||||
int D_BIAS;
|
||||
int D_LEN;
|
||||
int D_NE;
|
||||
int D_NF;
|
||||
int D_BIAS;
|
||||
logic [1:0] D_FMT;
|
||||
int S_LEN;
|
||||
int S_NE;
|
||||
int S_NF;
|
||||
int S_BIAS;
|
||||
int S_LEN;
|
||||
int S_NE;
|
||||
int S_NF;
|
||||
int S_BIAS;
|
||||
logic [1:0] S_FMT;
|
||||
int H_LEN;
|
||||
int H_NE;
|
||||
int H_NF;
|
||||
int H_BIAS;
|
||||
int H_LEN;
|
||||
int H_NE;
|
||||
int H_NF;
|
||||
int H_BIAS;
|
||||
logic [1:0] H_FMT;
|
||||
|
||||
// Floating point length FLEN and number of exponent (NE) and fraction (NF) bits
|
||||
int FLEN;
|
||||
int NE ;
|
||||
int NF ;
|
||||
int NE ;
|
||||
int NF ;
|
||||
logic [1:0] FMT ;
|
||||
int BIAS;
|
||||
int BIAS;
|
||||
|
||||
// Floating point constants needed for FPU paramerterization
|
||||
int FPSIZES;
|
||||
int FMTBITS;
|
||||
int LEN1 ;
|
||||
int NE1 ;
|
||||
int NF1 ;
|
||||
int FPSIZES;
|
||||
int FMTBITS;
|
||||
int LEN1 ;
|
||||
int NE1 ;
|
||||
int NF1 ;
|
||||
logic [1:0] FMT1 ;
|
||||
int BIAS1;
|
||||
int LEN2 ;
|
||||
int NE2 ;
|
||||
int NF2 ;
|
||||
int BIAS1;
|
||||
int LEN2 ;
|
||||
int NE2 ;
|
||||
int NF2 ;
|
||||
logic [1:0] FMT2 ;
|
||||
int BIAS2;
|
||||
int BIAS2;
|
||||
|
||||
// largest length in IEU/FPU
|
||||
int CVTLEN;
|
||||
@ -251,7 +255,7 @@ typedef struct packed {
|
||||
|
||||
// division constants
|
||||
int DIVN ;
|
||||
int LOGR;
|
||||
int LOGR ;
|
||||
int RK ;
|
||||
int LOGRK ;
|
||||
int FPDUR ;
|
||||
|
@ -32,12 +32,12 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
// Bus Interface
|
||||
input logic [P.AHBW-1:0] HRDATA,
|
||||
input logic [P.AHBW-1:0] HRDATA,
|
||||
input logic HREADY, HRESP,
|
||||
output logic HCLK, HRESETn,
|
||||
output logic [P.PA_BITS-1:0] HADDR,
|
||||
output logic [P.AHBW-1:0] HWDATA,
|
||||
output logic [P.XLEN/8-1:0] HWSTRB,
|
||||
output logic [P.PA_BITS-1:0] HADDR,
|
||||
output logic [P.AHBW-1:0] HWDATA,
|
||||
output logic [P.XLEN/8-1:0] HWSTRB,
|
||||
output logic HWRITE,
|
||||
output logic [2:0] HSIZE,
|
||||
output logic [2:0] HBURST,
|
||||
@ -55,15 +55,15 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
logic IntDivE, W64E;
|
||||
logic CSRReadM, CSRWriteM, PrivilegedM;
|
||||
logic [1:0] AtomicM;
|
||||
logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE;
|
||||
logic [P.XLEN-1:0] SrcAM;
|
||||
logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE;
|
||||
logic [P.XLEN-1:0] SrcAM;
|
||||
logic [2:0] Funct3E;
|
||||
logic [31:0] InstrD;
|
||||
logic [31:0] InstrM, InstrOrigM;
|
||||
logic [P.XLEN-1:0] PCSpillF, PCE, PCLinkE;
|
||||
logic [P.XLEN-1:0] PCM;
|
||||
logic [P.XLEN-1:0] CSRReadValW, MDUResultW;
|
||||
logic [P.XLEN-1:0] UnalignedPCNextF, PC2NextF;
|
||||
logic [P.XLEN-1:0] PCSpillF, PCE, PCLinkE;
|
||||
logic [P.XLEN-1:0] PCM;
|
||||
logic [P.XLEN-1:0] CSRReadValW, MDUResultW;
|
||||
logic [P.XLEN-1:0] UnalignedPCNextF, PC2NextF;
|
||||
logic [1:0] MemRWM;
|
||||
logic InstrValidD, InstrValidE, InstrValidM;
|
||||
logic InstrMisalignedFaultM;
|
||||
@ -83,31 +83,31 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
logic [4:0] RdE, RdM, RdW;
|
||||
logic FPUStallD;
|
||||
logic FWriteIntE;
|
||||
logic [P.FLEN-1:0] FWriteDataM;
|
||||
logic [P.XLEN-1:0] FIntResM;
|
||||
logic [P.XLEN-1:0] FCvtIntResW;
|
||||
logic [P.FLEN-1:0] FWriteDataM;
|
||||
logic [P.XLEN-1:0] FIntResM;
|
||||
logic [P.XLEN-1:0] FCvtIntResW;
|
||||
logic FCvtIntW;
|
||||
logic FDivBusyE;
|
||||
logic FRegWriteM;
|
||||
logic FCvtIntStallD;
|
||||
logic FpLoadStoreM;
|
||||
logic [4:0] SetFflagsM;
|
||||
logic [P.XLEN-1:0] FIntDivResultW;
|
||||
logic [P.XLEN-1:0] FIntDivResultW;
|
||||
|
||||
// memory management unit signals
|
||||
logic ITLBWriteF;
|
||||
logic ITLBMissF;
|
||||
logic [P.XLEN-1:0] SATP_REGW;
|
||||
logic [P.XLEN-1:0] SATP_REGW;
|
||||
logic STATUS_MXR, STATUS_SUM, STATUS_MPRV;
|
||||
logic [1:0] STATUS_MPP, STATUS_FS;
|
||||
logic [1:0] PrivilegeModeW;
|
||||
logic [P.XLEN-1:0] PTE;
|
||||
logic [P.XLEN-1:0] PTE;
|
||||
logic [1:0] PageType;
|
||||
logic sfencevmaM;
|
||||
logic SelHPTW;
|
||||
|
||||
// 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];
|
||||
|
||||
// IMem stalls
|
||||
@ -116,14 +116,14 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// cpu lsu interface
|
||||
logic [2:0] Funct3M;
|
||||
logic [P.XLEN-1:0] IEUAdrE;
|
||||
logic [P.XLEN-1:0] WriteDataM;
|
||||
logic [P.XLEN-1:0] IEUAdrM;
|
||||
logic [P.LLEN-1:0] ReadDataW;
|
||||
logic [P.XLEN-1:0] IEUAdrE;
|
||||
logic [P.XLEN-1:0] WriteDataM;
|
||||
logic [P.XLEN-1:0] IEUAdrM;
|
||||
logic [P.LLEN-1:0] ReadDataW;
|
||||
logic CommittedM;
|
||||
|
||||
// AHB ifu interface
|
||||
logic [P.PA_BITS-1:0] IFUHADDR;
|
||||
logic [P.PA_BITS-1:0] IFUHADDR;
|
||||
logic [2:0] IFUHBURST;
|
||||
logic [1:0] IFUHTRANS;
|
||||
logic [2:0] IFUHSIZE;
|
||||
@ -131,9 +131,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
logic IFUHREADY;
|
||||
|
||||
// AHB LSU interface
|
||||
logic [P.PA_BITS-1:0] LSUHADDR;
|
||||
logic [P.XLEN-1:0] LSUHWDATA;
|
||||
logic [P.XLEN/8-1:0] LSUHWSTRB;
|
||||
logic [P.PA_BITS-1:0] LSUHADDR;
|
||||
logic [P.XLEN-1:0] LSUHWDATA;
|
||||
logic [P.XLEN/8-1:0] LSUHWSTRB;
|
||||
logic LSUHWRITE;
|
||||
logic LSUHREADY;
|
||||
|
||||
@ -192,12 +192,12 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
.PCE, .PCLinkE, .FWriteIntE, .FCvtIntE, .IEUAdrE, .IntDivE, .W64E,
|
||||
.Funct3E, .ForwardedSrcAE, .ForwardedSrcBE,
|
||||
// Memory stage interface
|
||||
.SquashSCW, // from LSU
|
||||
.MemRWM, // read/write control goes to LSU
|
||||
.AtomicM, // atomic control goes to LSU
|
||||
.SquashSCW, // from LSU
|
||||
.MemRWM, // read/write control goes to LSU
|
||||
.AtomicM, // atomic control goes to LSU
|
||||
.WriteDataM, // Write data to LSU
|
||||
.Funct3M, // size and signedness to LSU
|
||||
.SrcAM, // to privilege and fpu
|
||||
.Funct3M, // size and signedness to LSU
|
||||
.SrcAM, // to privilege and fpu
|
||||
.RdE, .RdM, .FIntResM, .FlushDCacheM,
|
||||
.BranchD, .BranchE, .JumpD, .JumpE,
|
||||
// Writeback stage
|
||||
@ -219,24 +219,24 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
.LSUHADDR, .HRDATA, .LSUHWDATA, .LSUHWSTRB, .LSUHSIZE,
|
||||
.LSUHBURST, .LSUHTRANS, .LSUHWRITE, .LSUHREADY,
|
||||
// connect to csr or privilege and stay the same.
|
||||
.PrivilegeModeW, .BigEndianM, // connects to csr
|
||||
.PMPCFG_ARRAY_REGW, // connects to csr
|
||||
.PMPADDR_ARRAY_REGW, // connects to csr
|
||||
.PrivilegeModeW, .BigEndianM, // connects to csr
|
||||
.PMPCFG_ARRAY_REGW, // connects to csr
|
||||
.PMPADDR_ARRAY_REGW, // connects to csr
|
||||
// hptw keep i/o
|
||||
.SATP_REGW, // from csr
|
||||
.STATUS_MXR, // from csr
|
||||
.STATUS_SUM, // from csr
|
||||
.STATUS_MPRV, // from csr
|
||||
.STATUS_MPP, // from csr
|
||||
.sfencevmaM, // connects to privilege
|
||||
.DCacheStallM, // connects to privilege
|
||||
.LoadPageFaultM, // connects to privilege
|
||||
.StoreAmoPageFaultM, // connects to privilege
|
||||
.LoadMisalignedFaultM, // connects to privilege
|
||||
.LoadAccessFaultM, // connects to privilege
|
||||
.HPTWInstrAccessFaultF, // connects to privilege
|
||||
.StoreAmoMisalignedFaultM, // connects to privilege
|
||||
.StoreAmoAccessFaultM, // connects to privilege
|
||||
.SATP_REGW, // from csr
|
||||
.STATUS_MXR, // from csr
|
||||
.STATUS_SUM, // from csr
|
||||
.STATUS_MPRV, // from csr
|
||||
.STATUS_MPP, // from csr
|
||||
.sfencevmaM, // connects to privilege
|
||||
.DCacheStallM, // connects to privilege
|
||||
.LoadPageFaultM, // connects to privilege
|
||||
.StoreAmoPageFaultM, // connects to privilege
|
||||
.LoadMisalignedFaultM, // connects to privilege
|
||||
.LoadAccessFaultM, // connects to privilege
|
||||
.HPTWInstrAccessFaultF, // connects to privilege
|
||||
.StoreAmoMisalignedFaultM, // connects to privilege
|
||||
.StoreAmoAccessFaultM, // connects to privilege
|
||||
.InstrUpdateDAF,
|
||||
.PCSpillF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW,
|
||||
.LSUStallM);
|
||||
@ -292,14 +292,14 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||
.FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM);
|
||||
end else begin
|
||||
assign CSRReadValW = 0;
|
||||
assign CSRReadValW = 0;
|
||||
assign UnalignedPCNextF = PC2NextF;
|
||||
assign RetM = 0;
|
||||
assign TrapM = 0;
|
||||
assign wfiM = 0;
|
||||
assign IntPendingM = 0;
|
||||
assign sfencevmaM = 0;
|
||||
assign BigEndianM = 0;
|
||||
assign RetM = 0;
|
||||
assign TrapM = 0;
|
||||
assign wfiM = 0;
|
||||
assign IntPendingM = 0;
|
||||
assign sfencevmaM = 0;
|
||||
assign BigEndianM = 0;
|
||||
end
|
||||
|
||||
// multiply/divide unit
|
||||
@ -310,45 +310,45 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
.MDUResultW, .DivBusyE);
|
||||
end else begin // no M instructions supported
|
||||
assign MDUResultW = 0;
|
||||
assign DivBusyE = 0;
|
||||
assign DivBusyE = 0;
|
||||
end
|
||||
|
||||
// floating point unit
|
||||
if (P.F_SUPPORTED) begin:fpu
|
||||
fpu #(P) fpu(
|
||||
.clk, .reset,
|
||||
.FRM_REGW, // Rounding mode from CSR
|
||||
.InstrD, // instruction from IFU
|
||||
.ReadDataW(ReadDataW[P.FLEN-1:0]),// Read data from memory
|
||||
.ForwardedSrcAE, // Integer input being processed (from IEU)
|
||||
.StallE, .StallM, .StallW, // stall signals from HZU
|
||||
.FlushE, .FlushM, .FlushW, // flush signals from HZU
|
||||
.RdE, .RdM, .RdW, // which FP register to write to (from IEU)
|
||||
.STATUS_FS, // is floating-point enabled?
|
||||
.FRegWriteM, // FP register write enable
|
||||
.FRM_REGW, // Rounding mode from CSR
|
||||
.InstrD, // instruction from IFU
|
||||
.ReadDataW(ReadDataW[P.FLEN-1:0]), // Read data from memory
|
||||
.ForwardedSrcAE, // Integer input being processed (from IEU)
|
||||
.StallE, .StallM, .StallW, // stall signals from HZU
|
||||
.FlushE, .FlushM, .FlushW, // flush signals from HZU
|
||||
.RdE, .RdM, .RdW, // which FP register to write to (from IEU)
|
||||
.STATUS_FS, // is floating-point enabled?
|
||||
.FRegWriteM, // FP register write enable
|
||||
.FpLoadStoreM,
|
||||
.ForwardedSrcBE, // Integer input for intdiv
|
||||
.ForwardedSrcBE, // Integer input for intdiv
|
||||
.Funct3E, .Funct3M, .IntDivE, .W64E, // Integer flags and functions
|
||||
.FPUStallD, // Stall the decode stage
|
||||
.FWriteIntE, .FCvtIntE, // integer register write enable, conversion operation
|
||||
.FWriteDataM, // Data to be written to memory
|
||||
.FIntResM, // data to be written to integer register
|
||||
.FCvtIntResW, // fp -> int conversion result to be stored in int register
|
||||
.FCvtIntW, // fpu result selection
|
||||
.FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
|
||||
.IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||
.SetFflagsM, // FPU flags (to privileged unit)
|
||||
.FPUStallD, // Stall the decode stage
|
||||
.FWriteIntE, .FCvtIntE, // integer register write enable, conversion operation
|
||||
.FWriteDataM, // Data to be written to memory
|
||||
.FIntResM, // data to be written to integer register
|
||||
.FCvtIntResW, // fp -> int conversion result to be stored in int register
|
||||
.FCvtIntW, // fpu result selection
|
||||
.FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
|
||||
.IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||
.SetFflagsM, // FPU flags (to privileged unit)
|
||||
.FIntDivResultW);
|
||||
end else begin // no F_SUPPORTED or D_SUPPORTED; tie outputs low
|
||||
assign FPUStallD = 0;
|
||||
assign FWriteIntE = 0;
|
||||
assign FCvtIntE = 0;
|
||||
assign FIntResM = 0;
|
||||
assign FCvtIntW = 0;
|
||||
assign FDivBusyE = 0;
|
||||
end else begin // no F_SUPPORTED or D_SUPPORTED; tie outputs low
|
||||
assign FPUStallD = 0;
|
||||
assign FWriteIntE = 0;
|
||||
assign FCvtIntE = 0;
|
||||
assign FIntResM = 0;
|
||||
assign FCvtIntW = 0;
|
||||
assign FDivBusyE = 0;
|
||||
assign IllegalFPUInstrD = 1;
|
||||
assign SetFflagsM = 0;
|
||||
assign FpLoadStoreM = 0;
|
||||
assign SetFflagsM = 0;
|
||||
assign FpLoadStoreM = 0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -48,9 +48,9 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
||||
output logic HREADY,
|
||||
// I/O Interface
|
||||
input logic TIMECLK, // optional for CLINT MTIME counter
|
||||
input logic [31:0] GPIOIN, // inputs from GPIO
|
||||
output logic [31:0] GPIOOUT, // output values for GPIO
|
||||
output logic [31:0] GPIOEN, // output enables for GPIO
|
||||
input logic [31:0] GPIOIN, // inputs from GPIO
|
||||
output logic [31:0] GPIOOUT, // output values for GPIO
|
||||
output logic [31:0] GPIOEN, // output enables for GPIO
|
||||
input logic UARTSin, // UART serial data input
|
||||
output logic UARTSout, // UART serial data output
|
||||
input logic 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'h304] = testbench.dut.core.priv.priv.csr.csrm.MIE_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'h340] = testbench.dut.core.priv.priv.csr.csrm.MSCRATCH_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'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'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'h140] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_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'h304] = CSRArrayOld[12'h304];
|
||||
CSRArray[12'h301] = CSRArrayOld[12'h301];
|
||||
CSRArray[12'h30A] = CSRArrayOld[12'h30A];
|
||||
CSRArray[12'hF14] = CSRArrayOld[12'hF14];
|
||||
CSRArray[12'h340] = CSRArrayOld[12'h340];
|
||||
CSRArray[12'h342] = CSRArrayOld[12'h342];
|
||||
@ -207,6 +210,7 @@ module wallyTracer(rvviTrace rvvi);
|
||||
CSRArray[12'h105] = CSRArrayOld[12'h105];
|
||||
CSRArray[12'h141] = CSRArrayOld[12'h141];
|
||||
CSRArray[12'h106] = CSRArrayOld[12'h106];
|
||||
CSRArray[12'h10A] = CSRArrayOld[12'h10A];
|
||||
CSRArray[12'h180] = CSRArrayOld[12'h180];
|
||||
CSRArray[12'h140] = CSRArrayOld[12'h140];
|
||||
CSRArray[12'h143] = CSRArrayOld[12'h143];
|
||||
@ -308,6 +312,7 @@ module wallyTracer(rvviTrace rvvi);
|
||||
CSRArrayOld[12'h344] = CSRArray[12'h344];
|
||||
CSRArrayOld[12'h304] = CSRArray[12'h304];
|
||||
CSRArrayOld[12'h301] = CSRArray[12'h301];
|
||||
CSRArrayOld[12'h30A] = CSRArray[12'h30A];
|
||||
CSRArrayOld[12'hF14] = CSRArray[12'hF14];
|
||||
CSRArrayOld[12'h340] = CSRArray[12'h340];
|
||||
CSRArrayOld[12'h342] = CSRArray[12'h342];
|
||||
@ -326,6 +331,7 @@ module wallyTracer(rvviTrace rvvi);
|
||||
CSRArrayOld[12'h105] = CSRArray[12'h105];
|
||||
CSRArrayOld[12'h141] = CSRArray[12'h141];
|
||||
CSRArrayOld[12'h106] = CSRArray[12'h106];
|
||||
CSRArrayOld[12'h10A] = CSRArray[12'h10A];
|
||||
CSRArrayOld[12'h180] = CSRArray[12'h180];
|
||||
CSRArrayOld[12'h140] = CSRArray[12'h140];
|
||||
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'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'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'h302] = (CSRArrayOld[12'h302] != CSRArray[12'h302]) ? 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'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'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'h140] = (CSRArrayOld[12'h140] != CSRArray[12'h140]) ? 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'h344] = CSR_W[12'h344];
|
||||
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'hF14] = CSR_W[12'hF14];
|
||||
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'h141] = CSR_W[12'h141];
|
||||
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'h140] = CSR_W[12'h140];
|
||||
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'h344] = CSRArray[12'h344];
|
||||
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'hF14] = CSRArray[12'hF14];
|
||||
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'h141] = CSRArray[12'h141];
|
||||
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'h140] = CSRArray[12'h140];
|
||||
assign rvvi.csr[0][0][12'h143] = CSRArray[12'h143];
|
||||
|
@ -113,8 +113,6 @@ module testbenchfp;
|
||||
|
||||
`include "parameter-defs.vh"
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ||||||||| |||||||| ||||||| ||||||||| ||||||| |||||||| |||
|
||||
@ -680,11 +678,11 @@ module testbenchfp;
|
||||
// instantiate devices under test
|
||||
if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "sub" | TEST === "all") begin : fma
|
||||
fma #(P) fma(.Xs(Xs), .Ys(Ys), .Zs(Zs),
|
||||
.Xe(Xe), .Ye(Ye), .Ze(Ze),
|
||||
.Xm(Xm), .Ym(Ym), .Zm(Zm),
|
||||
.XZero, .YZero, .ZZero, .Ss, .Se,
|
||||
.OpCtrl(OpCtrlVal), .Sm, .InvA, .SCnt, .As, .Ps,
|
||||
.ASticky);
|
||||
.Xe(Xe), .Ye(Ye), .Ze(Ze),
|
||||
.Xm(Xm), .Ym(Ym), .Zm(Zm),
|
||||
.XZero, .YZero, .ZZero, .Ss, .Se,
|
||||
.OpCtrl(OpCtrlVal), .Sm, .InvA, .SCnt, .As, .Ps,
|
||||
.ASticky);
|
||||
end
|
||||
|
||||
postprocess #(P) postprocess(.Xs(Xs), .Ys(Ys), .PostProcSel(UnitVal[1:0]),
|
||||
@ -699,13 +697,13 @@ module testbenchfp;
|
||||
.PostProcFlg(Flg), .PostProcRes(FpRes), .FCvtIntRes(IntRes));
|
||||
|
||||
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,
|
||||
.Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), .ResSubnormUf(CvtResSubnormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE));
|
||||
end
|
||||
|
||||
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),
|
||||
.XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes));
|
||||
end
|
||||
@ -892,13 +890,13 @@ always @(negedge clk) begin
|
||||
// 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)
|
||||
// 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);
|
||||
FlagMatch = (ResFlg === AnsFlg | AnsFlg === 5'bx);
|
||||
divsqrtop = OpCtrlVal == `SQRT_OPCTRL | OpCtrlVal == `DIV_OPCTRL;
|
||||
assign ResMatch = (Res === Ans | NaNGood | NaNGood === 1'bx);
|
||||
assign FlagMatch = (ResFlg === AnsFlg | AnsFlg === 5'bx);
|
||||
assign divsqrtop = OpCtrlVal == `SQRT_OPCTRL | OpCtrlVal == `DIV_OPCTRL;
|
||||
assign DivDone = OldFDivBusyE & ~FDivBusyE;
|
||||
|
||||
//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(~((Res === Ans | NaNGood | NaNGood === 1'bx) & (ResFlg === AnsFlg | AnsFlg === 5'bx))&(DivDone | (TEST != "sqrt" & TEST != "div"))&(UnitVal !== `CVTINTUNIT)&(UnitVal !== `CMPUNIT)) begin
|
||||
errors += 1;
|
||||
@ -974,10 +972,10 @@ module readvectors (
|
||||
output logic [`FLEN-1:0] Ans,
|
||||
output logic [`XLEN-1:0] SrcA,
|
||||
output logic [4:0] AnsFlg,
|
||||
output logic Xs, Ys, Zs, // sign bits of XYZ
|
||||
output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
|
||||
output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
|
||||
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
|
||||
output logic Xs, Ys, Zs, // sign bits of XYZ
|
||||
output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
|
||||
output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
|
||||
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
|
||||
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
|
||||
output logic XSubnorm, ZSubnorm, // is XYZ denormalized
|
||||
output logic XZero, YZero, ZZero, // is XYZ zero
|
||||
@ -986,6 +984,7 @@ module readvectors (
|
||||
output logic DivStart,
|
||||
output logic [`FLEN-1:0] X, Y, Z, XPostBox
|
||||
);
|
||||
|
||||
logic XEn, YEn, ZEn;
|
||||
|
||||
`include "parameter-defs.vh"
|
||||
@ -1346,7 +1345,6 @@ module readvectors (
|
||||
assign YEn = ~((Unit == `CVTINTUNIT)|(Unit == `CVTFPUNIT)|((Unit == `DIVUNIT)&OpCtrl[0]));
|
||||
assign ZEn = (Unit == `FMAUNIT);
|
||||
|
||||
|
||||
unpack #(P) unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze,
|
||||
.Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN,
|
||||
.XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf,
|
||||
|
@ -866,10 +866,12 @@ module testbench;
|
||||
"medeleg": `checkCSR(`CSR_BASE.csrm.MEDELEG_REGW)
|
||||
"mepc": `checkCSR(`CSR_BASE.csrm.MEPC_REGW)
|
||||
"mtval": `checkCSR(`CSR_BASE.csrm.MTVAL_REGW)
|
||||
"menvcfg": `checkCSR(`CSR_BASE.csrm.MENVCFG_REGW)
|
||||
"sepc": `checkCSR(`CSR_BASE.csrs.csrs.SEPC_REGW)
|
||||
"scause": `checkCSR(`CSR_BASE.csrs.csrs.SCAUSE_REGW)
|
||||
"stvec": `checkCSR(`CSR_BASE.csrs.csrs.STVEC_REGW)
|
||||
"stval": `checkCSR(`CSR_BASE.csrs.csrs.STVAL_REGW)
|
||||
"senvcfg": `checkCSR(`CSR_BASE.csrs.SENVCFG_REGW)
|
||||
"mip": begin
|
||||
`checkCSR(`CSR_BASE.csrm.MIP_REGW)
|
||||
if(!NO_SPOOFING) begin
|
||||
|
@ -33,5 +33,8 @@ main:
|
||||
csrrw t0, satp, zero
|
||||
csrrw t0, stvec, zero
|
||||
csrrw t0, sscratch, zero
|
||||
li t0, -2
|
||||
csrrw t1, menvcfg, t0
|
||||
csrrw t2, senvcfg, t0
|
||||
|
||||
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
|
||||
00000001 # mcause from an instruction access fault
|
||||
00000000 # mtval of faulting instruction address (0x0)
|
||||
|
@ -280,7 +280,7 @@ end_trap_triggers:
|
||||
la t4, 0x02004000 // MTIMECMP register in CLINT
|
||||
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
|
||||
|
||||
|
||||
j trap_handler_end_\MODE\() // skip the trap handler when it is being defined.
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#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)
|
||||
|
||||
INIT_TESTS
|
||||
@ -34,8 +34,9 @@ TRAP_HANDLER m, EXT_SIGNATURE=1 // turn on recording mtval and status bits on tr
|
||||
|
||||
li x28, 0x8
|
||||
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
|
||||
|
||||
// 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
|
||||
00000000 # skipping instruction address fault since they're impossible with compressed instrs enabled
|
||||
00000001 # mcause from an instruction access fault
|
||||
|
@ -274,7 +274,7 @@ end_trap_triggers:
|
||||
la t4, 0x02004000 // MTIMECMP register in CLINT
|
||||
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
|
||||
|
||||
|
||||
j trap_handler_end_\MODE\() // skip the trap handler when it is being defined.
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
@ -22,7 +22,7 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
#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)
|
||||
|
||||
INIT_TESTS
|
||||
@ -33,7 +33,9 @@ TRAP_HANDLER m, EXT_SIGNATURE=1 // turn on recording mtval and status bits on tr
|
||||
|
||||
li x28, 0x8
|
||||
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user