This commit is contained in:
Kip Macsai-Goren 2022-01-05 18:38:29 +00:00
commit b53ab27b26
84 changed files with 2747 additions and 3945 deletions

17
bin/elf2hex.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
# james.stine@okstate.edu 4 Jan 2022
# Script to run elf2hex for memfile for
# Imperas and riscv-arch-test benchmarks
for file in work/rv64i_m/*/*.elf ; do
memfile=${file%.elf}.elf.memfile
echo riscv64-unknown-elf-elf2hex --bit-width 64 --input "$file" --output "$memfile"
riscv64-unknown-elf-elf2hex --bit-width 64 --input "$file" --output "$memfile"
done
for file in work/rv32i_m/*/*.elf ; do
memfile=${file%.elf}.elf.memfile
echo riscv64-unknown-elf-elf2hex --bit-width 32 --input "$file" --output "$memfile"
riscv64-unknown-elf-elf2hex --bit-width 32 --input "$file" --output "$memfile"
done

View File

@ -62,14 +62,14 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -60,14 +60,14 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 2048
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 1
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -62,14 +62,14 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 2048
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 1
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -63,13 +63,13 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -62,14 +62,14 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -61,14 +61,14 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -61,14 +61,14 @@
`define DTLB_ENTRIES 0
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -63,14 +63,14 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 64

View File

@ -62,14 +62,14 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -62,14 +62,14 @@
`define DTLB_ENTRIES 32
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_BLOCKLENINBITS 256
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_BLOCKLENINBITS 256
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4

View File

@ -153,7 +153,7 @@ fma2 UUT2(.XSgnM(XSgnE), .YSgnM(YSgnE), .XExpM(XExpE), .YExpM(YExpE), .ZExpM(ZEx
.FmtM(FmtE), .FrmM(FrmE), .FMAFlgM, .FMAResM);
// generate clock
// produce clock
always
begin
clk = 1; #5; clk = 0; #5;

View File

@ -45,14 +45,12 @@ endmodule
module INVX2(input logic a, output logic y);
generate
if (LIB == SKY130)
sky130_osu_sc_12T_ms__inv_2 inv(a, y);
else if (LIB == SKL90)
scc9gena_inv_2 inv(a, y)
else if (LIB == GF14)
INV_X2N_A10P5PP84TSL_C14(a, y)
endgenerate
if (LIB == SKY130)
sky130_osu_sc_12T_ms__inv_2 inv(a, y);
else if (LIB == SKL90)
scc9gena_inv_2 inv(a, y)
else if (LIB == GF14)
INV_X2N_A10P5PP84TSL_C14(a, y)
endmodule
module driver #(parameter WDITH=1) (

View File

@ -3,11 +3,16 @@ make all:
make -C ../../addins/riscv-arch-test
make -C ../../addins/riscv-arch-test XLEN=32
exe2memfile.pl ../../addins/riscv-arch-test/work/*/*/*.elf
# extractFunctionRadix. ***
# Build wally-riscv-arch-test
make -C ../../tests/wally-riscv-arch-test/
make -C ../../tests/wally-riscv-arch-test/ XLEN=32
exe2memfile.pl ../../tests/wally-riscv-arch-test/work/*/*/*.elf
# ***extractFunctionRadix
# *** use elf2hex
# *** add optional imperas tests
# Link Linux test vectors (fix this later***)
#cd ../../tests/linux-testgen/linux-testvectors/;./tvLinker.sh

View File

@ -51,7 +51,7 @@ tc = TestCase(
grepstr="400100000 instructions")
configs.append(tc)
tests64gc = ["arch64i", "arch64priv", "arch64c", "arch64m", "arch64d", "imperas64i", "imperas64f", "imperas64d", "imperas64p", "imperas64m", "imperas64a", "imperas64c", "wally64priv", "imperas64mmu"] # "wally64i", #, "testsBP64"]
tests64gc = ["arch64i", "arch64priv", "arch64c", "arch64m", "arch64d", "imperas64i", "imperas64f", "imperas64d", "imperas64p", "imperas64m", "imperas64a", "imperas64c", "wally64priv"] # , "imperas64mmu" "wally64i", #, "testsBP64"]
for test in tests64gc:
tc = TestCase(
name=test,
@ -59,7 +59,7 @@ for test in tests64gc:
cmd="vsim > {} -c <<!\ndo wally-pipelined-batch.do rv64gc "+test+"\n!",
grepstr="All tests ran without failures")
configs.append(tc)
tests32gc = ["arch32i", "arch32priv", "arch32c", "arch32m", "arch32f", "imperas32i", "imperas32f", "imperas32p", "imperas32m", "imperas32a", "imperas32c", "wally32priv", "imperas32mmu"] #"wally32i",
tests32gc = ["arch32i", "arch32priv", "arch32c", "arch32m", "arch32f", "imperas32i", "imperas32f", "imperas32p", "imperas32m", "imperas32a", "imperas32c", "wally32priv"] #, "imperas32mmu""wally32i",
for test in tests32gc:
tc = TestCase(
name=test,

View File

@ -1,3 +1,3 @@
vsim -c <<!
do wally-pipelined-batch.do rv64gc imperas64i
do wally-pipelined-batch.do rv32gc wally32priv
!

View File

@ -176,182 +176,183 @@ add wave -noupdate -group AHB /testbench/dut/hart/ebu/HMASTLOCK
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HADDRD
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HSIZED
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HWRITED
add wave -noupdate -group lsu -color Gold /testbench/dut/hart/lsu/MEM_VIRTMEM/interlockfsm/InterlockCurrState
add wave -noupdate -group lsu /testbench/dut/hart/lsu/SelHPTW
add wave -noupdate -group lsu /testbench/dut/hart/lsu/InterlockStall
add wave -noupdate -group lsu /testbench/dut/hart/lsu/LSUStall
add wave -noupdate -group lsu /testbench/dut/hart/lsu/ReadDataWordMuxM
add wave -noupdate -group lsu /testbench/dut/hart/lsu/ReadDataM
add wave -noupdate -group lsu /testbench/dut/hart/lsu/WriteDataM
add wave -noupdate -group lsu /testbench/dut/hart/lsu/SelUncachedAdr
add wave -noupdate -group lsu -expand -group bus -color Gold /testbench/dut/hart/lsu/busfsm/BusCurrState
add wave -noupdate -group lsu -expand -group bus /testbench/dut/hart/lsu/BusStall
add wave -noupdate -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusRead
add wave -noupdate -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusWrite
add wave -noupdate -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusAdr
add wave -noupdate -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusAck
add wave -noupdate -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusHWDATA
add wave -noupdate -group lsu -expand -group dcache -color Gold /testbench/dut/hart/lsu/dcache/dcache/dcachefsm/CurrState
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/WayHit
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMBlockWriteEnableM
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMWordWriteEnableM
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMWayWriteEnable
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMWordEnable
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMBlockWayWriteEnableM
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SelAdrM
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/MEM_VIRTMEM/SelReplayCPURequest
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/IEUAdrE
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/IEUAdrM
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/RAdr
add wave -noupdate -group lsu -expand -group dcache -group flush -radix unsigned /testbench/dut/hart/lsu/dcache/dcache/FlushAdr
add wave -noupdate -group lsu -expand -group dcache -group flush /testbench/dut/hart/lsu/dcache/dcache/FlushWay
add wave -noupdate -group lsu -expand -group dcache -group flush /testbench/dut/hart/lsu/dcache/dcache/VictimDirtyWay
add wave -noupdate -group lsu -expand -group dcache -group flush /testbench/dut/hart/lsu/dcache/dcache/VictimTag
add wave -noupdate -group lsu -expand -group dcache -group flush /testbench/dut/hart/lsu/dcache/dcache/CacheableM
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/DCacheMemWriteData
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/SetValid}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/SetDirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -label TAG {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/CacheTagMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/DirtyBits}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/ValidBits}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[0]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[0]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -expand -group Way0Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[1]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -expand -group Way0Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[1]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -expand -group Way0Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[2]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -expand -group Way0Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[2]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -expand -group Way0Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[3]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way0 -expand -group Way0Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[3]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/DirtyBits}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/ValidBits}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/SetDirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/WriteWordEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -label TAG {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/CacheTagMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -expand -group Way1Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[0]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -expand -group Way1Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[0]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -expand -group Way1Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[1]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -expand -group Way1Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[1]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -expand -group Way1Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[2]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -expand -group Way1Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[2]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -expand -group Way1Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[3]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 -expand -group Way1Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[3]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/SetValid}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/SetDirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -label TAG {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/CacheTagMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/DirtyBits}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/ValidBits}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -expand -group Way2Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[0]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -expand -group Way2Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[0]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -expand -group Way2Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[1]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -expand -group Way2Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[1]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -expand -group Way2Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[2]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -expand -group Way2Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[2]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -expand -group Way2Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[3]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group way2 -expand -group Way2Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[3]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/SetValid}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/SetDirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/ClearDirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/VDWriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -label TAG {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/CacheTagMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/DirtyBits}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/ValidBits}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[0]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[0]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[1]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[1]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[2]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[2]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[3]/CacheDataMem/WriteEnable}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[3]/CacheDataMem/StoredData}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group valid/dirty /testbench/dut/hart/lsu/dcache/dcache/SetValid
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group valid/dirty /testbench/dut/hart/lsu/dcache/dcache/ClearValid
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group valid/dirty /testbench/dut/hart/lsu/dcache/dcache/SetDirty
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM writes} -group valid/dirty /testbench/dut/hart/lsu/dcache/dcache/ClearDirty
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} /testbench/dut/hart/lsu/dcache/dcache/RAdr
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/WayHit}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/Valid}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/Dirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/ReadTag}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/WayHit}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/Valid}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/Dirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/ReadTag}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/WayHit}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/Valid}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/Dirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/ReadTag}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/WayHit}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/Valid}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/Dirty}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/ReadTag}
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} /testbench/dut/hart/lsu/dcache/dcache/WayHit
add wave -noupdate -group lsu -expand -group dcache -group {Cache SRAM read} /testbench/dut/hart/lsu/dcache/dcache/ReadDataWordM
add wave -noupdate -group lsu -expand -group dcache -group Victim /testbench/dut/hart/lsu/dcache/dcache/VictimTag
add wave -noupdate -group lsu -expand -group dcache -group Victim /testbench/dut/hart/lsu/dcache/dcache/VictimWay
add wave -noupdate -group lsu -expand -group dcache -group Victim /testbench/dut/hart/lsu/dcache/dcache/VictimDirtyWay
add wave -noupdate -group lsu -expand -group dcache -group Victim /testbench/dut/hart/lsu/dcache/dcache/VictimDirty
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/LsuRWM
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/LsuAdrE
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/LsuPAdrM
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/LsuAtomicM
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/CacheableM
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/FlushDCacheM
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/DCacheStall
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/ReadDataWordM
add wave -noupdate -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/FinalWriteDataM
add wave -noupdate -group lsu -expand -group dcache -group status /testbench/dut/hart/lsu/dcache/dcache/WayHit
add wave -noupdate -group lsu -expand -group dcache -group status -color {Medium Orchid} /testbench/dut/hart/lsu/dcache/dcache/CacheHit
add wave -noupdate -group lsu -expand -group dcache -expand -group {Memory Side} /testbench/dut/hart/lsu/dcache/dcache/DCacheFetchLine
add wave -noupdate -group lsu -expand -group dcache -expand -group {Memory Side} /testbench/dut/hart/lsu/dcache/dcache/DCacheWriteLine
add wave -noupdate -group lsu -expand -group dcache -expand -group {Memory Side} /testbench/dut/hart/lsu/dcache/dcache/DCacheMemWriteData
add wave -noupdate -group lsu -expand -group dcache -expand -group {Memory Side} /testbench/dut/hart/lsu/dcache/dcache/DCacheBusAck
add wave -noupdate -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/FlushWay
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/VAdr
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/tlbcontrol/EffectivePrivilegeMode
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/PTE
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/HitPageType
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/tlbcontrol/Translate
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/tlbcontrol/DisableTranslation
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/TLBMiss
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/TLBHit
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/PhysicalAddress
add wave -noupdate -group lsu -group dtlb -expand -group faults /testbench/dut/hart/lsu/dmmu/dmmu/TLBPageFault
add wave -noupdate -group lsu -group dtlb -expand -group faults /testbench/dut/hart/lsu/dmmu/dmmu/LoadAccessFaultM
add wave -noupdate -group lsu -group dtlb -expand -group faults /testbench/dut/hart/lsu/dmmu/dmmu/StoreAccessFaultM
add wave -noupdate -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/TLBPAdr
add wave -noupdate -group lsu -group dtlb -expand -group write /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/PTE
add wave -noupdate -group lsu -group dtlb -expand -group write /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/PageTypeWriteVal
add wave -noupdate -group lsu -group dtlb -expand -group write /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/TLBWrite
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/pmachecker/PhysicalAddress
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/pmachecker/SelRegions
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/Cacheable
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/Idempotent
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/AtomicAllowed
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/pmachecker/PMAAccessFault
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/PMAInstrAccessFaultF
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/PMALoadAccessFaultM
add wave -noupdate -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/PMAStoreAccessFaultM
add wave -noupdate -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/PhysicalAddress
add wave -noupdate -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/ReadAccessM
add wave -noupdate -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/WriteAccessM
add wave -noupdate -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/PMPADDR_ARRAY_REGW
add wave -noupdate -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/PMPCFG_ARRAY_REGW
add wave -noupdate -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/PMPInstrAccessFaultF
add wave -noupdate -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/PMPLoadAccessFaultM
add wave -noupdate -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/PMPStoreAccessFaultM
add wave -noupdate -group lsu -group ptwalker -color Gold /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/WalkerState
add wave -noupdate -group lsu -group ptwalker /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/PCF
add wave -noupdate -group lsu -group ptwalker /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/HPTWReadPTE
add wave -noupdate -group lsu -group ptwalker /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/HPTWAdr
add wave -noupdate -group lsu -group ptwalker /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/PTE
add wave -noupdate -group lsu -group ptwalker -group types /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/ITLBMissF
add wave -noupdate -group lsu -group ptwalker -group types /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/DTLBMissM
add wave -noupdate -group lsu -group ptwalker -group types /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/ITLBWriteF
add wave -noupdate -group lsu -group ptwalker -group types /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/DTLBWriteM
add wave -noupdate -expand -group lsu -color Gold /testbench/dut/hart/lsu/MEM_VIRTMEM/interlockfsm/InterlockCurrState
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/SelHPTW
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/InterlockStall
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/LSUStall
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/ReadDataWordMuxM
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/ReadDataM
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/WriteDataM
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/SelUncachedAdr
add wave -noupdate -expand -group lsu -expand -group bus -color Gold /testbench/dut/hart/lsu/busfsm/BusCurrState
add wave -noupdate -expand -group lsu -expand -group bus /testbench/dut/hart/lsu/BusStall
add wave -noupdate -expand -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusRead
add wave -noupdate -expand -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusWrite
add wave -noupdate -expand -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusAdr
add wave -noupdate -expand -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusAck
add wave -noupdate -expand -group lsu -expand -group bus /testbench/dut/hart/lsu/LsuBusHWDATA
add wave -noupdate -expand -group lsu -expand -group dcache -color Gold /testbench/dut/hart/lsu/dcache/dcache/dcachefsm/CurrState
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/WayHit
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMBlockWriteEnableM
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMWordWriteEnableM
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMWayWriteEnable
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMWordEnable
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SRAMBlockWayWriteEnableM
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/SelAdrM
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/MEM_VIRTMEM/SelReplayCPURequest
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/IEUAdrE
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/IEUAdrM
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/RAdr
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush -radix unsigned /testbench/dut/hart/lsu/dcache/dcache/FlushAdr
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush -radix unsigned /testbench/dut/hart/lsu/dcache/dcache/FlushAdrQ
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/hart/lsu/dcache/dcache/FlushWay
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/hart/lsu/dcache/dcache/VictimDirtyWay
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/hart/lsu/dcache/dcache/VictimTag
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/hart/lsu/dcache/dcache/CacheableM
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/DCacheMemWriteData
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/SetValid}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/SetDirty}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -label TAG {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/CacheTagMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/DirtyBits}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/ValidBits}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[0]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[0]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[1]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[1]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[2]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[2]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[3]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/word[3]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/DirtyBits}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/ValidBits}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/SetDirty}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/WriteWordEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -label TAG {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/CacheTagMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -expand -group Way1Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[0]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -expand -group Way1Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[0]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -expand -group Way1Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[1]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -expand -group Way1Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[1]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -expand -group Way1Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[2]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -expand -group Way1Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[2]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -expand -group Way1Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[3]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way1 -expand -group Way1Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/word[3]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/SetValid}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/SetDirty}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -label TAG {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/CacheTagMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/DirtyBits}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/ValidBits}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -expand -group Way2Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[0]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -expand -group Way2Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[0]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -expand -group Way2Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[1]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -expand -group Way2Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[1]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -expand -group Way2Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[2]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -expand -group Way2Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[2]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -expand -group Way2Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[3]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -expand -group way2 -expand -group Way2Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/word[3]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/SetValid}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/SetDirty}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/ClearDirty}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/VDWriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -label TAG {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/CacheTagMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/DirtyBits}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/ValidBits}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -expand -group Way3Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[0]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -expand -group Way3Word0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[0]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -expand -group Way3Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[1]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -expand -group Way3Word1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[1]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -expand -group Way3Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[2]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -expand -group Way3Word2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[2]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -expand -group Way3Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[3]/CacheDataMem/WriteEnable}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group way3 -expand -group Way3Word3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/word[3]/CacheDataMem/StoredData}
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group valid/dirty /testbench/dut/hart/lsu/dcache/dcache/SetValid
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group valid/dirty /testbench/dut/hart/lsu/dcache/dcache/ClearValid
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group valid/dirty /testbench/dut/hart/lsu/dcache/dcache/SetDirty
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Cache SRAM writes} -group valid/dirty /testbench/dut/hart/lsu/dcache/dcache/ClearDirty
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} /testbench/dut/hart/lsu/dcache/dcache/RAdr
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/WayHit}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/Valid}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/Dirty}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way0 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[0]/ReadTag}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/WayHit}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/Valid}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/Dirty}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way1 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[1]/ReadTag}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/WayHit}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/Valid}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/Dirty}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way2 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[2]/ReadTag}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/WayHit}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/Valid}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/Dirty}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} -expand -group way3 {/testbench/dut/hart/lsu/dcache/dcache/MemWay[3]/ReadTag}
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} /testbench/dut/hart/lsu/dcache/dcache/WayHit
add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM read} /testbench/dut/hart/lsu/dcache/dcache/ReadDataWordM
add wave -noupdate -expand -group lsu -expand -group dcache -group Victim /testbench/dut/hart/lsu/dcache/dcache/VictimTag
add wave -noupdate -expand -group lsu -expand -group dcache -group Victim /testbench/dut/hart/lsu/dcache/dcache/VictimWay
add wave -noupdate -expand -group lsu -expand -group dcache -group Victim /testbench/dut/hart/lsu/dcache/dcache/VictimDirtyWay
add wave -noupdate -expand -group lsu -expand -group dcache -group Victim /testbench/dut/hart/lsu/dcache/dcache/VictimDirty
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/LsuRWM
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/LsuAdrE
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/LsuPAdrM
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/LsuAtomicM
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/CacheableM
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/FlushDCacheM
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/dcache/dcache/DCacheStall
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/ReadDataWordM
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/hart/lsu/FinalWriteDataM
add wave -noupdate -expand -group lsu -expand -group dcache -group status /testbench/dut/hart/lsu/dcache/dcache/WayHit
add wave -noupdate -expand -group lsu -expand -group dcache -group status -color {Medium Orchid} /testbench/dut/hart/lsu/dcache/dcache/CacheHit
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Memory Side} /testbench/dut/hart/lsu/dcache/dcache/DCacheFetchLine
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Memory Side} /testbench/dut/hart/lsu/dcache/dcache/DCacheWriteLine
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Memory Side} /testbench/dut/hart/lsu/dcache/dcache/DCacheMemWriteData
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {Memory Side} /testbench/dut/hart/lsu/dcache/dcache/DCacheBusAck
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/hart/lsu/dcache/dcache/FlushWay
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/VAdr
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/tlbcontrol/EffectivePrivilegeMode
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/PTE
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/HitPageType
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/tlbcontrol/Translate
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/tlbcontrol/DisableTranslation
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/TLBMiss
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/TLBHit
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/PhysicalAddress
add wave -noupdate -expand -group lsu -group dtlb -expand -group faults /testbench/dut/hart/lsu/dmmu/dmmu/TLBPageFault
add wave -noupdate -expand -group lsu -group dtlb -expand -group faults /testbench/dut/hart/lsu/dmmu/dmmu/LoadAccessFaultM
add wave -noupdate -expand -group lsu -group dtlb -expand -group faults /testbench/dut/hart/lsu/dmmu/dmmu/StoreAccessFaultM
add wave -noupdate -expand -group lsu -group dtlb /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/TLBPAdr
add wave -noupdate -expand -group lsu -group dtlb -expand -group write /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/PTE
add wave -noupdate -expand -group lsu -group dtlb -expand -group write /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/PageTypeWriteVal
add wave -noupdate -expand -group lsu -group dtlb -expand -group write /testbench/dut/hart/lsu/dmmu/dmmu/tlb/tlb/TLBWrite
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/pmachecker/PhysicalAddress
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/pmachecker/SelRegions
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/Cacheable
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/Idempotent
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/AtomicAllowed
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/pmachecker/PMAAccessFault
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/PMAInstrAccessFaultF
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/PMALoadAccessFaultM
add wave -noupdate -expand -group lsu -group pma /testbench/dut/hart/lsu/dmmu/dmmu/PMAStoreAccessFaultM
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/PhysicalAddress
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/ReadAccessM
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/WriteAccessM
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/PMPADDR_ARRAY_REGW
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/pmpchecker/PMPCFG_ARRAY_REGW
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/PMPInstrAccessFaultF
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/PMPLoadAccessFaultM
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/hart/lsu/dmmu/dmmu/PMPStoreAccessFaultM
add wave -noupdate -expand -group lsu -group ptwalker -color Gold /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/WalkerState
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/PCF
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/HPTWReadPTE
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/HPTWAdr
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/PTE
add wave -noupdate -expand -group lsu -group ptwalker -group types /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/ITLBMissF
add wave -noupdate -expand -group lsu -group ptwalker -group types /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/DTLBMissM
add wave -noupdate -expand -group lsu -group ptwalker -group types /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/ITLBWriteF
add wave -noupdate -expand -group lsu -group ptwalker -group types /testbench/dut/hart/lsu/MEM_VIRTMEM/hptw/DTLBWriteM
add wave -noupdate -group plic /testbench/dut/uncore/plic/plic/HCLK
add wave -noupdate -group plic /testbench/dut/uncore/plic/plic/HSELPLIC
add wave -noupdate -group plic /testbench/dut/uncore/plic/plic/HADDR
@ -432,37 +433,30 @@ add wave -noupdate /testbench/dut/hart/lsu/LocalLsuBusAdr
add wave -noupdate /testbench/dut/hart/lsu/busfsm/BusNextState
add wave -noupdate /testbench/dut/hart/lsu/busfsm/DCacheFetchLine
add wave -noupdate /testbench/dut/hart/lsu/busfsm/DCacheWriteLine
add wave -noupdate -expand -group ifu -color Gold /testbench/dut/hart/ifu/busfsm/BusCurrState
add wave -noupdate -expand -group ifu /testbench/dut/hart/ifu/busfsm/LsuBusAck
add wave -noupdate -expand -group ifu -expand -group icache -color Gold /testbench/dut/hart/ifu/icache/icache/icachefsm/CurrState
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/icachefsm/NextState
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/ITLBMissF
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/ITLBWriteF
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/ReadLineF
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/SelAdr
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/PCNextF
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/PCPF
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/PCPSpillF
add wave -noupdate -expand -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/hit
add wave -noupdate -expand -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/spill
add wave -noupdate -expand -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/ICacheStallF
add wave -noupdate -expand -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/spillSave
add wave -noupdate -expand -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/spillSave
add wave -noupdate -expand -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/PreCntEn
add wave -noupdate -expand -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/FinalInstrRawF
add wave -noupdate -expand -group ifu -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/icache/ICacheBusAdr
add wave -noupdate -expand -group ifu -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/icache/icachefsm/ICacheBusAck
add wave -noupdate -expand -group ifu -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/icache/icachefsm/ICacheMemWriteEnable
add wave -noupdate -expand -group ifu -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/icache/ICacheMemWriteData
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/ICacheMemReadData
add wave -noupdate -expand -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/SpillDataBlock0
add wave -noupdate -expand -group ifu -group itlb /testbench/dut/hart/ifu/immu/TLBWrite
add wave -noupdate -expand -group ifu -group itlb /testbench/dut/hart/ifu/ITLBMissF
add wave -noupdate -expand -group ifu -group itlb /testbench/dut/hart/ifu/immu/PhysicalAddress
add wave -noupdate -group ifu -color Gold /testbench/dut/hart/ifu/busfsm/BusCurrState
add wave -noupdate -group ifu /testbench/dut/hart/ifu/busfsm/LsuBusAck
add wave -noupdate -group ifu -expand -group icache -color Gold /testbench/dut/hart/ifu/icache/icache/icachefsm/CurrState
add wave -noupdate -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/icachefsm/NextState
add wave -noupdate -group ifu -expand -group icache /testbench/dut/hart/ifu/ITLBMissF
add wave -noupdate -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/ReadLineF
add wave -noupdate -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/SelAdr
add wave -noupdate -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/PCNextF
add wave -noupdate -group ifu -expand -group icache /testbench/dut/hart/ifu/icache/icache/PCPF
add wave -noupdate -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/hit
add wave -noupdate -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/ICacheStallF
add wave -noupdate -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/icachefsm/PreCntEn
add wave -noupdate -group ifu -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/icache/FinalInstrRawF
add wave -noupdate -group ifu -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/icache/ICacheBusAdr
add wave -noupdate -group ifu -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/icache/icachefsm/ICacheBusAck
add wave -noupdate -group ifu -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/icache/icachefsm/ICacheMemWriteEnable
add wave -noupdate -group ifu -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/icache/ICacheMemWriteData
add wave -noupdate -group ifu -group itlb /testbench/dut/hart/ifu/immu/TLBWrite
add wave -noupdate -group ifu -group itlb /testbench/dut/hart/ifu/ITLBMissF
add wave -noupdate -group ifu -group itlb /testbench/dut/hart/ifu/immu/PhysicalAddress
add wave -noupdate /testbench/dut/hart/ifu/IfuBusRead
add wave -noupdate /testbench/dut/hart/ifu/icache/icache/ICacheFetchLine
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 7} {36865 ns} 1} {{Cursor 5} {49445 ns} 1} {{Cursor 3} {1239086 ns} 0} {{Cursor 4} {49574 ns} 1}
WaveRestoreCursors {{Cursor 7} {36865 ns} 1} {{Cursor 5} {49445 ns} 1} {{Cursor 3} {38453 ns} 0} {{Cursor 4} {49574 ns} 1}
quietly wave cursor active 3
configure wave -namecolwidth 250
configure wave -valuecolwidth 314
@ -478,4 +472,4 @@ configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {1238897 ns} {1239273 ns}
WaveRestoreZoom {38413 ns} {39039 ns}

269
pipelined/src/cache/cache.sv vendored Normal file
View File

@ -0,0 +1,269 @@
///////////////////////////////////////////
// cache (data cache)
//
// Written: ross1728@gmail.com July 07, 2021
// Implements the L1 data cache
//
// Purpose: Storage for data and meta data.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module cache #(parameter integer LINELEN,
parameter integer NUMLINES,
parameter integer NUMWAYS,
parameter integer DCACHE = 1)
(input logic clk,
input logic reset,
input logic CPUBusy,
// cpu side
input logic [1:0] RW,
input logic [1:0] Atomic,
input logic FlushCache,
input logic [11:0] LsuAdrE, // virtual address, but we only use the lower 12 bits.
input logic [`PA_BITS-1:0] LsuPAdrM, // physical address
input logic [11:0] PreLsuPAdrM, // physical or virtual address
input logic [`XLEN-1:0] FinalWriteData,
output logic [`XLEN-1:0] ReadDataWord,
output logic CacheCommitted,
// Bus fsm interface
input logic IgnoreRequest,
output logic CacheFetchLine,
output logic CacheWriteLine,
input logic CacheBusAck,
output logic [`PA_BITS-1:0] CacheBusAdr,
input logic [LINELEN-1:0] CacheMemWriteData,
output logic [`XLEN-1:0] ReadDataLineSets [(LINELEN/`XLEN)-1:0],
output logic CacheStall,
// to performance counters
output logic CacheMiss,
output logic CacheAccess,
input logic InvalidateCacheM
);
localparam integer LINEBYTELEN = LINELEN/8;
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
localparam integer INDEXLEN = $clog2(NUMLINES);
localparam integer TAGLEN = `PA_BITS - OFFSETLEN - INDEXLEN;
localparam integer WORDSPERLINE = LINELEN/`XLEN;
localparam integer LOGWPL = $clog2(WORDSPERLINE);
localparam integer LOGXLENBYTES = $clog2(`XLEN/8);
localparam integer FlushAdrThreshold = NUMLINES;
logic [1:0] SelAdrM;
logic [INDEXLEN-1:0] RAdr;
logic [LINELEN-1:0] SRAMWriteData;
logic SetValid, ClearValid;
logic SetDirty, ClearDirty;
logic [LINELEN-1:0] ReadDataLineWayMasked [NUMWAYS-1:0];
logic [NUMWAYS-1:0] WayHit;
logic CacheHit;
logic [LINELEN-1:0] ReadDataLineM;
logic [WORDSPERLINE-1:0] SRAMWordEnable;
logic SRAMWordWriteEnableM;
logic SRAMLineWriteEnableM;
logic [NUMWAYS-1:0] SRAMLineWayWriteEnableM;
logic [NUMWAYS-1:0] SRAMWayWriteEnable;
logic [NUMWAYS-1:0] VictimWay;
logic [NUMWAYS-1:0] VictimDirtyWay;
logic VictimDirty;
logic [2**LOGWPL-1:0] MemPAdrDecodedW;
logic [TAGLEN-1:0] VictimTagWay [NUMWAYS-1:0];
logic [TAGLEN-1:0] VictimTag;
logic [INDEXLEN-1:0] FlushAdr;
logic [INDEXLEN-1:0] FlushAdrP1;
logic [INDEXLEN-1:0] FlushAdrQ;
logic FlushAdrCntEn;
logic FlushAdrCntRst;
logic FlushAdrFlag;
logic [NUMWAYS-1:0] FlushWay;
logic [NUMWAYS-1:0] NextFlushWay;
logic FlushWayCntEn;
logic FlushWayCntRst;
logic VDWriteEnable;
logic SelEvict;
logic LRUWriteEn;
logic [NUMWAYS-1:0] VDWriteEnableWay;
logic SelFlush;
// Read Path CPU (IEU) side
mux3 #(INDEXLEN)
AdrSelMux(.d0(LsuAdrE[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
.d1(PreLsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
.d2(FlushAdr),
.s(SelAdrM),
.y(RAdr));
cacheway #(.NUMLINES(NUMLINES), .LINELEN(LINELEN), .TAGLEN(TAGLEN),
.OFFSETLEN(OFFSETLEN), .INDEXLEN(INDEXLEN))
MemWay[NUMWAYS-1:0](.clk, .reset, .RAdr,
.PAdr(LsuPAdrM),
.WriteEnable(SRAMWayWriteEnable),
.VDWriteEnable(VDWriteEnableWay),
.WriteWordEnable(SRAMWordEnable),
.TagWriteEnable(SRAMLineWayWriteEnableM),
.WriteData(SRAMWriteData),
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .SelEvict,
.VictimWay, .FlushWay, .SelFlush,
.ReadDataLineWayMasked,
.WayHit, .VictimDirtyWay, .VictimTagWay,
.InvalidateAll(InvalidateCacheM));
if(NUMWAYS > 1) begin:vict
cachereplacementpolicy #(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
cachereplacementpolicy(.clk, .reset,
.WayHit,
.VictimWay,
.LsuPAdrM(LsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
.RAdr,
.LRUWriteEn);
end else begin:vict
assign VictimWay = 1'b1; // one hot.
end
assign CacheHit = | WayHit;
assign VictimDirty = | VictimDirtyWay;
// ReadDataLineWayMaskedM is a 2d array of cache line len by number of ways.
// Need to OR together each way in a bitwise manner.
// Final part of the AO Mux. First is the AND in the cacheway.
or_rows #(NUMWAYS, LINELEN) ReadDataAOMux(.a(ReadDataLineWayMasked), .y(ReadDataLineM));
or_rows #(NUMWAYS, TAGLEN) VictimTagAOMux(.a(VictimTagWay), .y(VictimTag));
// Convert the Read data bus ReadDataSelectWay into sets of XLEN so we can
// easily build a variable input mux.
// *** consider using a limited range shift to do this final muxing.
genvar index;
if(DCACHE == 1) begin: readdata
for (index = 0; index < WORDSPERLINE; index++) begin:readdatalinesetsmux
assign ReadDataLineSets[index] = ReadDataLineM[((index+1)*`XLEN)-1: (index*`XLEN)];
end
// variable input mux
assign ReadDataWord = ReadDataLineSets[LsuPAdrM[LOGWPL + LOGXLENBYTES - 1 : LOGXLENBYTES]];
end else begin: readdata
logic [31:0] ReadLineSetsF [LINELEN/16-1:0];
logic [31:0] FinalInstrRawF;
for(index = 0; index < LINELEN / 16 - 1; index++)
assign ReadLineSetsF[index] = ReadDataLineM[((index+1)*16)+16-1 : (index*16)];
assign ReadLineSetsF[LINELEN/16-1] = {16'b0, ReadDataLineM[LINELEN-1:LINELEN-16]};
assign FinalInstrRawF = ReadLineSetsF[LsuPAdrM[$clog2(LINELEN / 32) + 1 : 1]];
if (`XLEN == 64) assign ReadDataWord = {32'b0, FinalInstrRawF};
else assign ReadDataWord = FinalInstrRawF;
end
// Write Path CPU (IEU) side
onehotdecoder #(LOGWPL)
adrdec(.bin(LsuPAdrM[LOGWPL+LOGXLENBYTES-1:LOGXLENBYTES]),
.decoded(MemPAdrDecodedW));
assign SRAMWordEnable = SRAMLineWriteEnableM ? '1 : MemPAdrDecodedW;
assign SRAMLineWayWriteEnableM = SRAMLineWriteEnableM ? VictimWay : '0;
mux2 #(NUMWAYS) WriteEnableMux(.d0(SRAMWordWriteEnableM ? WayHit : '0),
.d1(SRAMLineWayWriteEnableM),
.s(SRAMLineWriteEnableM),
.y(SRAMWayWriteEnable));
mux2 #(LINELEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteData}}),
.d1(CacheMemWriteData),
.s(SRAMLineWriteEnableM),
.y(SRAMWriteData));
mux3 #(`PA_BITS) BaseAdrMux(.d0({LsuPAdrM[`PA_BITS-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}}),
.d1({VictimTag, LsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}}),
.d2({VictimTag, FlushAdrQ, {{OFFSETLEN}{1'b0}}}),
.s({SelFlush, SelEvict}),
.y(CacheBusAdr));
// flush address and way generation.
// increment on 2nd to last way
flopenr #(INDEXLEN)
FlushAdrReg(.clk,
.reset(reset | FlushAdrCntRst),
.en(FlushAdrCntEn & FlushWay[NUMWAYS-2]),
.d(FlushAdrP1),
.q(FlushAdr));
assign FlushAdrP1 = FlushAdr + 1'b1;
flopenr #(INDEXLEN)
FlushAdrQReg(.clk,
.reset(reset | FlushAdrCntRst),
.en(FlushAdrCntEn),
.d(FlushAdr),
.q(FlushAdrQ));
flopenl #(NUMWAYS)
FlushWayReg(.clk,
.load(reset | FlushWayCntRst),
.en(FlushWayCntEn),
.val({{NUMWAYS-1{1'b0}}, 1'b1}),
.d(NextFlushWay),
.q(FlushWay));
assign VDWriteEnableWay = FlushWay & {NUMWAYS{VDWriteEnable}};
assign NextFlushWay = {FlushWay[NUMWAYS-2:0], FlushWay[NUMWAYS-1]};
assign FlushAdrFlag = FlushAdr == FlushAdrThreshold[INDEXLEN-1:0] & FlushWay[NUMWAYS-1];
// controller
// *** fixme
logic CacheableM;
assign CacheableM = 1;
cachefsm cachefsm(.clk, .reset, .CacheFetchLine, .CacheWriteLine, .CacheBusAck,
.RW, .Atomic, .CPUBusy, .CacheableM, .IgnoreRequest,
.CacheHit, .VictimDirty, .CacheStall, .CacheCommitted,
.CacheMiss, .CacheAccess, .SelAdrM, .SetValid,
.ClearValid, .SetDirty, .ClearDirty, .SRAMWordWriteEnableM,
.SRAMLineWriteEnableM, .SelEvict, .SelFlush,
.FlushAdrCntEn, .FlushWayCntEn, .FlushAdrCntRst,
.FlushWayCntRst, .FlushAdrFlag, .FlushCache,
.VDWriteEnable, .LRUWriteEn);
endmodule // dcache

398
pipelined/src/cache/cachefsm.sv vendored Normal file
View File

@ -0,0 +1,398 @@
///////////////////////////////////////////
// dcache (data cache) fsm
//
// Written: ross1728@gmail.com August 25, 2021
// Implements the L1 data cache fsm
//
// Purpose: Controller for the dcache fsm
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module cachefsm
(input logic clk,
input logic reset,
// inputs from IEU
input logic [1:0] RW,
input logic [1:0] Atomic,
input logic FlushCache,
// hazard inputs
input logic CPUBusy,
input logic CacheableM,
// interlock fsm
input logic IgnoreRequest,
// Bus inputs
input logic CacheBusAck,
// dcache internals
input logic CacheHit,
input logic VictimDirty,
input logic FlushAdrFlag,
// hazard outputs
output logic CacheStall,
// counter outputs
output logic CacheMiss,
output logic CacheAccess,
// Bus outputs
output logic CacheCommitted,
output logic CacheWriteLine,
output logic CacheFetchLine,
// dcache internals
output logic [1:0] SelAdrM,
output logic SetValid,
output logic ClearValid,
output logic SetDirty,
output logic ClearDirty,
output logic SRAMWordWriteEnableM,
output logic SRAMLineWriteEnableM,
output logic SelEvict,
output logic LRUWriteEn,
output logic SelFlush,
output logic FlushAdrCntEn,
output logic FlushWayCntEn,
output logic FlushAdrCntRst,
output logic FlushWayCntRst,
output logic VDWriteEnable
);
logic AnyCPUReqM;
typedef enum {STATE_READY,
STATE_MISS_FETCH_WDV,
STATE_MISS_FETCH_DONE,
STATE_MISS_EVICT_DIRTY,
STATE_MISS_WRITE_CACHE_LINE,
STATE_MISS_READ_WORD,
STATE_MISS_READ_WORD_DELAY,
STATE_MISS_WRITE_WORD,
STATE_CPU_BUSY,
STATE_CPU_BUSY_FINISH_AMO,
STATE_FLUSH,
STATE_FLUSH_WRITE_BACK,
STATE_FLUSH_CLEAR_DIRTY} statetype;
(* mark_debug = "true" *) statetype CurrState, NextState;
assign AnyCPUReqM = |RW | (|Atomic);
// outputs for the performance counters.
assign CacheAccess = AnyCPUReqM & CacheableM & CurrState == STATE_READY;
assign CacheMiss = CacheAccess & CacheableM & ~CacheHit;
always_ff @(posedge clk)
if (reset) CurrState <= #1 STATE_READY;
else CurrState <= #1 NextState;
// next state logic and some state ouputs.
always_comb begin
CacheStall = 1'b0;
SelAdrM = 2'b00;
SetValid = 1'b0;
ClearValid = 1'b0;
SetDirty = 1'b0;
ClearDirty = 1'b0;
SRAMWordWriteEnableM = 1'b0;
SRAMLineWriteEnableM = 1'b0;
SelEvict = 1'b0;
LRUWriteEn = 1'b0;
SelFlush = 1'b0;
FlushAdrCntEn = 1'b0;
FlushWayCntEn = 1'b0;
FlushAdrCntRst = 1'b0;
FlushWayCntRst = 1'b0;
VDWriteEnable = 1'b0;
NextState = STATE_READY;
CacheFetchLine = 1'b0;
CacheWriteLine = 1'b0;
case (CurrState)
STATE_READY: begin
CacheStall = 1'b0;
SelAdrM = 2'b00;
SRAMWordWriteEnableM = 1'b0;
SetDirty = 1'b0;
LRUWriteEn = 1'b0;
// TLB Miss
if(IgnoreRequest) begin
// the LSU arbiter has not yet selected the PTW.
// The CPU needs to be stalled until that happens.
// If we set CacheStall for 1 cycle before going to
// PTW ready the CPU will stall.
// The page table walker asserts it's control 1 cycle
// after the TLBs miss.
SelAdrM = 2'b01;
NextState = STATE_READY;
end
// Flush dcache to next level of memory
else if(FlushCache) begin
NextState = STATE_FLUSH;
CacheStall = 1'b1;
SelAdrM = 2'b10;
FlushAdrCntRst = 1'b1;
FlushWayCntRst = 1'b1;
end
// amo hit
else if(Atomic[1] & (&RW) & CacheableM & CacheHit) begin
SelAdrM = 2'b01;
CacheStall = 1'b0;
if(CPUBusy) begin
NextState = STATE_CPU_BUSY_FINISH_AMO;
SelAdrM = 2'b01;
end
else begin
SRAMWordWriteEnableM = 1'b1;
SetDirty = 1'b1;
LRUWriteEn = 1'b1;
NextState = STATE_READY;
end
end
// read hit valid cached
else if(RW[1] & CacheableM & CacheHit) begin
CacheStall = 1'b0;
LRUWriteEn = 1'b1;
if(CPUBusy) begin
NextState = STATE_CPU_BUSY;
SelAdrM = 2'b01;
end
else begin
NextState = STATE_READY;
end
end
// write hit valid cached
else if (RW[0] & CacheableM & CacheHit) begin
SelAdrM = 2'b01;
CacheStall = 1'b0;
SRAMWordWriteEnableM = 1'b1;
SetDirty = 1'b1;
LRUWriteEn = 1'b1;
if(CPUBusy) begin
NextState = STATE_CPU_BUSY;
SelAdrM = 2'b01;
end
else begin
NextState = STATE_READY;
end
end
// read or write miss valid cached
else if((|RW) & CacheableM & ~CacheHit) begin
NextState = STATE_MISS_FETCH_WDV;
CacheStall = 1'b1;
CacheFetchLine = 1'b1;
end
else NextState = STATE_READY;
end
STATE_MISS_FETCH_WDV: begin
CacheStall = 1'b1;
SelAdrM = 2'b01;
if (CacheBusAck) begin
NextState = STATE_MISS_FETCH_DONE;
end else begin
NextState = STATE_MISS_FETCH_WDV;
end
end
STATE_MISS_FETCH_DONE: begin
CacheStall = 1'b1;
SelAdrM = 2'b01;
if(VictimDirty) begin
NextState = STATE_MISS_EVICT_DIRTY;
CacheWriteLine = 1'b1;
end else begin
NextState = STATE_MISS_WRITE_CACHE_LINE;
end
end
STATE_MISS_WRITE_CACHE_LINE: begin
SRAMLineWriteEnableM = 1'b1;
CacheStall = 1'b1;
NextState = STATE_MISS_READ_WORD;
SelAdrM = 2'b01;
SetValid = 1'b1;
ClearDirty = 1'b1;
//LRUWriteEn = 1'b1; // DO not update LRU on SRAM fetch update. Wait for subsequent read/write
end
STATE_MISS_READ_WORD: begin
SelAdrM = 2'b01;
CacheStall = 1'b1;
if (RW[0] & ~Atomic[1]) begin // handles stores and amo write.
NextState = STATE_MISS_WRITE_WORD;
end else begin
NextState = STATE_MISS_READ_WORD_DELAY;
// delay state is required as the read signal RW[1] is still high when we
// return to the ready state because the cache is stalling the cpu.
end
end
STATE_MISS_READ_WORD_DELAY: begin
//SelAdrM = 2'b01;
SRAMWordWriteEnableM = 1'b0;
SetDirty = 1'b0;
LRUWriteEn = 1'b0;
if(&RW & Atomic[1]) begin // amo write
SelAdrM = 2'b01;
if(CPUBusy) begin
NextState = STATE_CPU_BUSY_FINISH_AMO;
end
else begin
SRAMWordWriteEnableM = 1'b1;
SetDirty = 1'b1;
LRUWriteEn = 1'b1;
NextState = STATE_READY;
end
end else begin
LRUWriteEn = 1'b1;
if(CPUBusy) begin
NextState = STATE_CPU_BUSY;
SelAdrM = 2'b01;
end
else begin
NextState = STATE_READY;
end
end
end
STATE_MISS_WRITE_WORD: begin
SRAMWordWriteEnableM = 1'b1;
SetDirty = 1'b1;
SelAdrM = 2'b01;
LRUWriteEn = 1'b1;
if(CPUBusy) begin
NextState = STATE_CPU_BUSY;
SelAdrM = 2'b01;
end
else begin
NextState = STATE_READY;
end
end
STATE_MISS_EVICT_DIRTY: begin
CacheStall = 1'b1;
SelAdrM = 2'b01;
SelEvict = 1'b1;
if(CacheBusAck) begin
NextState = STATE_MISS_WRITE_CACHE_LINE;
end else begin
NextState = STATE_MISS_EVICT_DIRTY;
end
end
STATE_CPU_BUSY: begin
SelAdrM = 2'b00;
if(CPUBusy) begin
NextState = STATE_CPU_BUSY;
SelAdrM = 2'b01;
end
else begin
NextState = STATE_READY;
end
end
STATE_CPU_BUSY_FINISH_AMO: begin
SelAdrM = 2'b01;
SRAMWordWriteEnableM = 1'b0;
SetDirty = 1'b0;
LRUWriteEn = 1'b0;
if(CPUBusy) begin
NextState = STATE_CPU_BUSY_FINISH_AMO;
end
else begin
SRAMWordWriteEnableM = 1'b1;
SetDirty = 1'b1;
LRUWriteEn = 1'b1;
NextState = STATE_READY;
end
end
STATE_FLUSH: begin
CacheStall = 1'b1;
SelAdrM = 2'b10;
SelFlush = 1'b1;
FlushAdrCntEn = 1'b1;
FlushWayCntEn = 1'b1;
if(VictimDirty) begin
NextState = STATE_FLUSH_WRITE_BACK;
FlushAdrCntEn = 1'b0;
FlushWayCntEn = 1'b0;
CacheWriteLine = 1'b1;
end else if (FlushAdrFlag) begin
NextState = STATE_READY;
CacheStall = 1'b0;
FlushAdrCntEn = 1'b0;
FlushWayCntEn = 1'b0;
end else begin
NextState = STATE_FLUSH;
end
end
STATE_FLUSH_WRITE_BACK: begin
CacheStall = 1'b1;
SelAdrM = 2'b10;
SelFlush = 1'b1;
if(CacheBusAck) begin
NextState = STATE_FLUSH_CLEAR_DIRTY;
end else begin
NextState = STATE_FLUSH_WRITE_BACK;
end
end
STATE_FLUSH_CLEAR_DIRTY: begin
CacheStall = 1'b1;
ClearDirty = 1'b1;
VDWriteEnable = 1'b1;
SelFlush = 1'b1;
SelAdrM = 2'b10;
FlushAdrCntEn = 1'b0;
FlushWayCntEn = 1'b0;
if(FlushAdrFlag) begin
NextState = STATE_READY;
CacheStall = 1'b0;
SelAdrM = 2'b00;
end else begin
NextState = STATE_FLUSH;
FlushAdrCntEn = 1'b1;
FlushWayCntEn = 1'b1;
end
end
default: begin
NextState = STATE_READY;
end
endcase
end
assign CacheCommitted = CurrState != STATE_READY;
endmodule // cachefsm

View File

@ -40,7 +40,7 @@ module cachereplacementpolicy
logic [NUMWAYS-2:0] LRUEn, LRUMask;
logic [$clog2(NUMWAYS)-1:0] EncVicWay;
logic [NUMWAYS-2:0] ReplacementBits [NUMLINES-1:0];
logic [NUMWAYS-2:0] BlockReplacementBits;
logic [NUMWAYS-2:0] LineReplacementBits;
logic [NUMWAYS-2:0] NewReplacement;
logic [NUMWAYS-2:0] NewReplacementD;
@ -69,112 +69,109 @@ module cachereplacementpolicy
end
/* verilator lint_on BLKLOOPINIT */
assign BlockReplacementBits = ReplacementBits[RAdrD];
assign LineReplacementBits = ReplacementBits[RAdrD];
genvar index;
generate
if(NUMWAYS == 2) begin : TwoWay
assign LRUEn[0] = 1'b0;
if(NUMWAYS == 2) begin : TwoWay
assign LRUEn[0] = 1'b0;
assign NewReplacement[0] = WayHit[1];
assign NewReplacement[0] = WayHit[1];
assign VictimWay[1] = ~BlockReplacementBits[0];
assign VictimWay[0] = BlockReplacementBits[0];
end else if (NUMWAYS == 4) begin : FourWay
assign VictimWay[1] = ~LineReplacementBits[0];
assign VictimWay[0] = LineReplacementBits[0];
end else if (NUMWAYS == 4) begin : FourWay
// VictimWay is a function only of the current value of the LRU.
// binary encoding
//assign VictimWay[0] = BlockReplacementBits[2] ? BlockReplacementBits[1] : BlockReplacementBits[0];
//assign VictimWay[1] = BlockReplacementBits[2];
// VictimWay is a function only of the current value of the LRU.
// binary encoding
//assign VictimWay[0] = LineReplacementBits[2] ? LineReplacementBits[1] : LineReplacementBits[0];
//assign VictimWay[1] = LineReplacementBits[2];
// 1 hot encoding
//| WayHit | LRU 2 | LRU 1 | LRU 0 |
//|--------+-------+-------+-------|
//| 0000 | - | - | - |
//| 0001 | 1 | - | 1 |
//| 0010 | 1 | - | 0 |
//| 0100 | 0 | 1 | - |
//| 1000 | 0 | 0 | - |
// 1 hot encoding
//| WayHit | LRU 2 | LRU 1 | LRU 0 |
//|--------+-------+-------+-------|
//| 0000 | - | - | - |
//| 0001 | 1 | - | 1 |
//| 0010 | 1 | - | 0 |
//| 0100 | 0 | 1 | - |
//| 1000 | 0 | 0 | - |
assign VictimWay[0] = ~BlockReplacementBits[2] & ~BlockReplacementBits[0];
assign VictimWay[1] = ~BlockReplacementBits[2] & BlockReplacementBits[0];
assign VictimWay[2] = BlockReplacementBits[2] & ~BlockReplacementBits[1];
assign VictimWay[3] = BlockReplacementBits[2] & BlockReplacementBits[1];
assign VictimWay[0] = ~LineReplacementBits[2] & ~LineReplacementBits[0];
assign VictimWay[1] = ~LineReplacementBits[2] & LineReplacementBits[0];
assign VictimWay[2] = LineReplacementBits[2] & ~LineReplacementBits[1];
assign VictimWay[3] = LineReplacementBits[2] & LineReplacementBits[1];
// New LRU bits which are updated is function only of the WayHit.
// However the not updated bits come from the old LRU.
assign LRUEn[2] = |WayHit;
assign LRUEn[1] = WayHit[3] | WayHit[2];
assign LRUEn[0] = WayHit[1] | WayHit[0];
// New LRU bits which are updated is function only of the WayHit.
// However the not updated bits come from the old LRU.
assign LRUEn[2] = |WayHit;
assign LRUEn[1] = WayHit[3] | WayHit[2];
assign LRUEn[0] = WayHit[1] | WayHit[0];
assign LRUMask[2] = WayHit[1] | WayHit[0];
assign LRUMask[1] = WayHit[2];
assign LRUMask[0] = WayHit[0];
assign LRUMask[2] = WayHit[1] | WayHit[0];
assign LRUMask[1] = WayHit[2];
assign LRUMask[0] = WayHit[0];
/* -----\/----- EXCLUDED -----\/-----
// selects
assign LRUEn[2] = 1'b1;
assign LRUEn[1] = WayHit[3];
assign LRUEn[0] = WayHit[3] | WayHit[2];
// selects
assign LRUEn[2] = 1'b1;
assign LRUEn[1] = WayHit[3];
assign LRUEn[0] = WayHit[3] | WayHit[2];
// mask
assign LRUMask[0] = WayHit[1];
assign LRUMask[1] = WayHit[3];
assign LRUMask[2] = WayHit[3] | WayHit[2];
-----/\----- EXCLUDED -----/\----- */
// mask
assign LRUMask[0] = WayHit[1];
assign LRUMask[1] = WayHit[3];
assign LRUMask[2] = WayHit[3] | WayHit[2];
-----/\----- EXCLUDED -----/\----- */
for(index = 0; index < NUMWAYS-1; index++)
assign NewReplacement[index] = LRUEn[index] ? LRUMask[index] : BlockReplacementBits[index];
for(index = 0; index < NUMWAYS-1; index++)
assign NewReplacement[index] = LRUEn[index] ? LRUMask[index] : LineReplacementBits[index];
/* -----\/----- EXCLUDED -----\/-----
assign EncVicWay[1] = BlockReplacementBits[2];
assign EncVicWay[0] = BlockReplacementBits[2] ? BlockReplacementBits[0] : BlockReplacementBits[1];
assign EncVicWay[1] = LineReplacementBits[2];
assign EncVicWay[0] = LineReplacementBits[2] ? LineReplacementBits[0] : LineReplacementBits[1];
onehotdecoder #(2)
waydec(.bin(EncVicWay),
.decoded({VictimWay[0], VictimWay[1], VictimWay[2], VictimWay[3]}));
-----/\----- EXCLUDED -----/\----- */
onehotdecoder #(2)
waydec(.bin(EncVicWay),
.decoded({VictimWay[0], VictimWay[1], VictimWay[2], VictimWay[3]}));
-----/\----- EXCLUDED -----/\----- */
end else if (NUMWAYS == 8) begin : EightWay
end else if (NUMWAYS == 8) begin : EightWay
// selects
assign LRUEn[6] = 1'b1;
assign LRUEn[5] = WayHit[7] | WayHit[6] | WayHit[5] | WayHit[4];
assign LRUEn[4] = WayHit[7] | WayHit[6];
assign LRUEn[3] = WayHit[5] | WayHit[4];
assign LRUEn[2] = WayHit[3] | WayHit[2] | WayHit[1] | WayHit[0];
assign LRUEn[1] = WayHit[3] | WayHit[2];
assign LRUEn[0] = WayHit[1] | WayHit[0];
// selects
assign LRUEn[6] = 1'b1;
assign LRUEn[5] = WayHit[7] | WayHit[6] | WayHit[5] | WayHit[4];
assign LRUEn[4] = WayHit[7] | WayHit[6];
assign LRUEn[3] = WayHit[5] | WayHit[4];
assign LRUEn[2] = WayHit[3] | WayHit[2] | WayHit[1] | WayHit[0];
assign LRUEn[1] = WayHit[3] | WayHit[2];
assign LRUEn[0] = WayHit[1] | WayHit[0];
// mask
assign LRUMask[6] = WayHit[7] | WayHit[6] | WayHit[5] | WayHit[4];
assign LRUMask[5] = WayHit[7] | WayHit[6];
assign LRUMask[4] = WayHit[7];
assign LRUMask[3] = WayHit[5];
assign LRUMask[2] = WayHit[3] | WayHit[2];
assign LRUMask[1] = WayHit[2];
assign LRUMask[0] = WayHit[0];
// mask
assign LRUMask[6] = WayHit[7] | WayHit[6] | WayHit[5] | WayHit[4];
assign LRUMask[5] = WayHit[7] | WayHit[6];
assign LRUMask[4] = WayHit[7];
assign LRUMask[3] = WayHit[5];
assign LRUMask[2] = WayHit[3] | WayHit[2];
assign LRUMask[1] = WayHit[2];
assign LRUMask[0] = WayHit[0];
for(index = 0; index < NUMWAYS-1; index++)
assign NewReplacement[index] = LRUEn[index] ? LRUMask[index] : BlockReplacementBits[index];
for(index = 0; index < NUMWAYS-1; index++)
assign NewReplacement[index] = LRUEn[index] ? LRUMask[index] : LineReplacementBits[index];
assign EncVicWay[2] = BlockReplacementBits[6];
assign EncVicWay[1] = BlockReplacementBits[6] ? BlockReplacementBits[5] : BlockReplacementBits[2];
assign EncVicWay[0] = BlockReplacementBits[6] ? BlockReplacementBits[5] ? BlockReplacementBits[4] : BlockReplacementBits[3] :
BlockReplacementBits[2] ? BlockReplacementBits[1] : BlockReplacementBits[0];
assign EncVicWay[2] = LineReplacementBits[6];
assign EncVicWay[1] = LineReplacementBits[6] ? LineReplacementBits[5] : LineReplacementBits[2];
assign EncVicWay[0] = LineReplacementBits[6] ? LineReplacementBits[5] ? LineReplacementBits[4] : LineReplacementBits[3] :
LineReplacementBits[2] ? LineReplacementBits[1] : LineReplacementBits[0];
onehotdecoder #(3)
waydec(.bin(EncVicWay),
.decoded({VictimWay[0], VictimWay[1], VictimWay[2], VictimWay[3],
VictimWay[4], VictimWay[5], VictimWay[6], VictimWay[7]}));
end
endgenerate
onehotdecoder #(3)
waydec(.bin(EncVicWay),
.decoded({VictimWay[0], VictimWay[1], VictimWay[2], VictimWay[3],
VictimWay[4], VictimWay[5], VictimWay[6], VictimWay[7]}));
end
endmodule

View File

@ -25,7 +25,7 @@
`include "wally-config.vh"
module cacheway #(parameter NUMLINES=512, parameter BLOCKLEN = 256, TAGLEN = 26,
module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
parameter OFFSETLEN = 5, parameter INDEXLEN = 9, parameter DIRTY_BITS = 1)
(input logic clk,
input logic reset,
@ -34,9 +34,9 @@ module cacheway #(parameter NUMLINES=512, parameter BLOCKLEN = 256, TAGLEN = 26,
input logic [`PA_BITS-1:0] PAdr,
input logic WriteEnable,
input logic VDWriteEnable,
input logic [BLOCKLEN/`XLEN-1:0] WriteWordEnable,
input logic [LINELEN/`XLEN-1:0] WriteWordEnable,
input logic TagWriteEnable,
input logic [BLOCKLEN-1:0] WriteData,
input logic [LINELEN-1:0] WriteData,
input logic SetValid,
input logic ClearValid,
input logic SetDirty,
@ -47,7 +47,7 @@ module cacheway #(parameter NUMLINES=512, parameter BLOCKLEN = 256, TAGLEN = 26,
input logic SelFlush,
input logic FlushWay,
output logic [BLOCKLEN-1:0] ReadDataLineWayMasked,
output logic [LINELEN-1:0] ReadDataLineWayMasked,
output logic WayHit,
output logic VictimDirtyWay,
output logic [TAGLEN-1:0] VictimTagWay
@ -55,7 +55,7 @@ module cacheway #(parameter NUMLINES=512, parameter BLOCKLEN = 256, TAGLEN = 26,
logic [NUMLINES-1:0] ValidBits;
logic [NUMLINES-1:0] DirtyBits;
logic [BLOCKLEN-1:0] ReadDataBlockWay;
logic [LINELEN-1:0] ReadDataLineWay;
logic [TAGLEN-1:0] ReadTag;
logic Valid;
logic Dirty;
@ -72,16 +72,13 @@ module cacheway #(parameter NUMLINES=512, parameter BLOCKLEN = 256, TAGLEN = 26,
genvar words;
generate
for(words = 0; words < BLOCKLEN/`XLEN; words++) begin : word
sram1rw #(.DEPTH(`XLEN), .WIDTH(NUMLINES))
CacheDataMem(.clk(clk), .Addr(RAdr),
.ReadData(ReadDataBlockWay[(words+1)*`XLEN-1:words*`XLEN] ),
.WriteData(WriteData[(words+1)*`XLEN-1:words*`XLEN]),
.WriteEnable(WriteEnable & WriteWordEnable[words]));
end
endgenerate
for(words = 0; words < LINELEN/`XLEN; words++) begin: word
sram1rw #(.DEPTH(`XLEN), .WIDTH(NUMLINES))
CacheDataMem(.clk(clk), .Addr(RAdr),
.ReadData(ReadDataLineWay[(words+1)*`XLEN-1:words*`XLEN] ),
.WriteData(WriteData[(words+1)*`XLEN-1:words*`XLEN]),
.WriteEnable(WriteEnable & WriteWordEnable[words]));
end
sram1rw #(.DEPTH(TAGLEN), .WIDTH(NUMLINES))
CacheTagMem(.clk(clk),
@ -93,7 +90,7 @@ module cacheway #(parameter NUMLINES=512, parameter BLOCKLEN = 256, TAGLEN = 26,
assign WayHit = Valid & (ReadTag == PAdr[`PA_BITS-1:OFFSETLEN+INDEXLEN]);
assign SelectedWay = SelFlush ? FlushWay :
SelEvict ? VictimWay : WayHit;
assign ReadDataLineWayMasked = SelectedWay ? ReadDataBlockWay : '0; // first part of AO mux.
assign ReadDataLineWayMasked = SelectedWay ? ReadDataLineWay : '0; // first part of AO mux.
assign VictimDirtyWay = SelFlush ? FlushWay & Dirty & Valid :
VictimWay & Dirty & Valid;
@ -123,27 +120,21 @@ module cacheway #(parameter NUMLINES=512, parameter BLOCKLEN = 256, TAGLEN = 26,
assign Valid = ValidBits[RAdrD];
generate
if(DIRTY_BITS) begin:dirty
always_ff @(posedge clk) begin
if (reset)
DirtyBits <= {NUMLINES{1'b0}};
else if (SetDirtyD & (WriteEnableD | VDWriteEnableD)) DirtyBits[RAdrD] <= 1'b1;
else if (ClearDirtyD & (WriteEnableD | VDWriteEnableD)) DirtyBits[RAdrD] <= 1'b0;
end
always_ff @(posedge clk) begin
SetDirtyD <= SetDirty;
ClearDirtyD <= ClearDirty;
end
assign Dirty = DirtyBits[RAdrD];
end else begin:dirty
assign Dirty = 1'b0;
// Dirty bits
if(DIRTY_BITS) begin:dirty
always_ff @(posedge clk) begin
if (reset) DirtyBits <= {NUMLINES{1'b0}};
else if (SetDirtyD & (WriteEnableD | VDWriteEnableD)) DirtyBits[RAdrD] <= 1'b1;
else if (ClearDirtyD & (WriteEnableD | VDWriteEnableD)) DirtyBits[RAdrD] <= 1'b0;
end
endgenerate
always_ff @(posedge clk) begin
SetDirtyD <= SetDirty;
ClearDirtyD <= ClearDirty;
end
assign Dirty = DirtyBits[RAdrD];
end else begin:dirty
assign Dirty = 1'b0;
end
endmodule // DCacheMemWay

View File

@ -25,71 +25,70 @@
`include "wally-config.vh"
module dcache
module dcache #(parameter integer LINELEN,
parameter integer NUMLINES,
parameter integer NUMWAYS)
(input logic clk,
input logic reset,
input logic CPUBusy,
input logic reset,
input logic CPUBusy,
// mmu
input logic CacheableM,
input logic CacheableM,
// cpu side
input logic [1:0] LsuRWM,
input logic [1:0] LsuAtomicM,
input logic FlushDCacheM,
input logic [11:0] LsuAdrE, // virtual address, but we only use the lower 12 bits.
input logic [`PA_BITS-1:0] LsuPAdrM, // physical address
input logic [11:0] PreLsuPAdrM, // physical or virtual address
input logic [`XLEN-1:0] FinalWriteDataM,
output logic [`XLEN-1:0] ReadDataWordM,
output logic DCacheCommittedM,
input logic [1:0] LsuRWM,
input logic [1:0] LsuAtomicM,
input logic FlushDCacheM,
input logic [11:0] LsuAdrE, // virtual address, but we only use the lower 12 bits.
input logic [`PA_BITS-1:0] LsuPAdrM, // physical address
input logic [11:0] PreLsuPAdrM, // physical or virtual address
input logic [`XLEN-1:0] FinalWriteDataM,
output logic [`XLEN-1:0] ReadDataWordM,
output logic DCacheCommittedM,
// Bus fsm interface
input logic IgnoreRequest,
output logic DCacheFetchLine,
output logic DCacheWriteLine,
input logic IgnoreRequest,
output logic DCacheFetchLine,
output logic DCacheWriteLine,
input logic DCacheBusAck,
output logic [`PA_BITS-1:0] DCacheBusAdr,
input logic DCacheBusAck,
output logic [`PA_BITS-1:0] DCacheBusAdr,
input logic [`DCACHE_BLOCKLENINBITS-1:0] DCacheMemWriteData,
output logic [`XLEN-1:0] ReadDataBlockSetsM [(`DCACHE_BLOCKLENINBITS/`XLEN)-1:0],
input logic [LINELEN-1:0] DCacheMemWriteData,
output logic [`XLEN-1:0] ReadDataLineSetsM [(LINELEN/`XLEN)-1:0],
output logic DCacheStall,
output logic DCacheStall,
// to performance counters
output logic DCacheMiss,
output logic DCacheAccess
output logic DCacheMiss,
output logic DCacheAccess
);
localparam integer BLOCKLEN = `DCACHE_BLOCKLENINBITS;
localparam integer NUMLINES = `DCACHE_WAYSIZEINBYTES*8/BLOCKLEN;
localparam integer NUMWAYS = `DCACHE_NUMWAYS;
localparam integer BLOCKBYTELEN = BLOCKLEN/8;
localparam integer OFFSETLEN = $clog2(BLOCKBYTELEN);
localparam integer LINEBYTELEN = LINELEN/8;
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
localparam integer INDEXLEN = $clog2(NUMLINES);
localparam integer TAGLEN = `PA_BITS - OFFSETLEN - INDEXLEN;
localparam integer WORDSPERLINE = BLOCKLEN/`XLEN;
localparam integer WORDSPERLINE = LINELEN/`XLEN;
localparam integer LOGWPL = $clog2(WORDSPERLINE);
localparam integer LOGXLENBYTES = $clog2(`XLEN/8);
localparam integer FlushAdrThreshold = NUMLINES - 1;
localparam integer FlushAdrThreshold = NUMLINES;
logic [1:0] SelAdrM;
logic [INDEXLEN-1:0] RAdr;
logic [BLOCKLEN-1:0] SRAMWriteData;
logic [LINELEN-1:0] SRAMWriteData;
logic SetValid, ClearValid;
logic SetDirty, ClearDirty;
logic [BLOCKLEN-1:0] ReadDataLineWayMasked [NUMWAYS-1:0];
logic [LINELEN-1:0] ReadDataLineWayMasked [NUMWAYS-1:0];
logic [NUMWAYS-1:0] WayHit;
logic CacheHit;
logic [BLOCKLEN-1:0] ReadDataLineM;
logic [LINELEN-1:0] ReadDataLineM;
logic [WORDSPERLINE-1:0] SRAMWordEnable;
logic SRAMWordWriteEnableM;
logic SRAMBlockWriteEnableM;
logic [NUMWAYS-1:0] SRAMBlockWayWriteEnableM;
logic SRAMLineWriteEnableM;
logic [NUMWAYS-1:0] SRAMLineWayWriteEnableM;
logic [NUMWAYS-1:0] SRAMWayWriteEnable;
@ -104,6 +103,7 @@ module dcache
logic [INDEXLEN-1:0] FlushAdr;
logic [INDEXLEN-1:0] FlushAdrP1;
logic [INDEXLEN-1:0] FlushAdrQ;
logic FlushAdrCntEn;
logic FlushAdrCntRst;
logic FlushAdrFlag;
@ -127,15 +127,15 @@ module dcache
.d2(FlushAdr),
.s(SelAdrM),
.y(RAdr));
cacheway #(.NUMLINES(NUMLINES), .BLOCKLEN(BLOCKLEN), .TAGLEN(TAGLEN),
cacheway #(.NUMLINES(NUMLINES), .LINELEN(LINELEN), .TAGLEN(TAGLEN),
.OFFSETLEN(OFFSETLEN), .INDEXLEN(INDEXLEN))
MemWay[NUMWAYS-1:0](.clk, .reset, .RAdr,
.PAdr(LsuPAdrM),
.WriteEnable(SRAMWayWriteEnable),
.VDWriteEnable(VDWriteEnableWay),
.WriteWordEnable(SRAMWordEnable),
.TagWriteEnable(SRAMBlockWayWriteEnableM),
.TagWriteEnable(SRAMLineWayWriteEnableM),
.WriteData(SRAMWriteData),
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .SelEvict,
.VictimWay, .FlushWay, .SelFlush,
@ -143,28 +143,26 @@ module dcache
.WayHit, .VictimDirtyWay, .VictimTagWay,
.InvalidateAll(1'b0));
generate
if(NUMWAYS > 1) begin:vict
cachereplacementpolicy #(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
cachereplacementpolicy(.clk, .reset,
.WayHit,
.VictimWay,
.LsuPAdrM(LsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
.RAdr,
.LRUWriteEn);
end else begin:vict
assign VictimWay = 1'b1; // one hot.
end
endgenerate
if(NUMWAYS > 1) begin:vict
cachereplacementpolicy #(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
cachereplacementpolicy(.clk, .reset,
.WayHit,
.VictimWay,
.LsuPAdrM(LsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
.RAdr,
.LRUWriteEn);
end else begin:vict
assign VictimWay = 1'b1; // one hot.
end
assign CacheHit = | WayHit;
assign VictimDirty = | VictimDirtyWay;
// ReadDataLineWayMaskedM is a 2d array of cache block len by number of ways.
// ReadDataLineWayMaskedM is a 2d array of cache line len by number of ways.
// Need to OR together each way in a bitwise manner.
// Final part of the AO Mux. First is the AND in the cacheway.
or_rows #(NUMWAYS, BLOCKLEN) ReadDataAOMux(.a(ReadDataLineWayMasked), .y(ReadDataLineM));
or_rows #(NUMWAYS, LINELEN) ReadDataAOMux(.a(ReadDataLineWayMasked), .y(ReadDataLineM));
or_rows #(NUMWAYS, TAGLEN) VictimTagAOMux(.a(VictimTagWay), .y(VictimTag));
@ -172,15 +170,12 @@ module dcache
// easily build a variable input mux.
// *** consider using a limited range shift to do this final muxing.
genvar index;
generate
for (index = 0; index < WORDSPERLINE; index++) begin:readdatablocksetsmux
assign ReadDataBlockSetsM[index] = ReadDataLineM[((index+1)*`XLEN)-1: (index*`XLEN)];
end
endgenerate
for (index = 0; index < WORDSPERLINE; index++)
assign ReadDataLineSetsM[index] = ReadDataLineM[((index+1)*`XLEN)-1: (index*`XLEN)];
// variable input mux
assign ReadDataWordM = ReadDataBlockSetsM[LsuPAdrM[LOGWPL + LOGXLENBYTES - 1 : LOGXLENBYTES]];
assign ReadDataWordM = ReadDataLineSetsM[LsuPAdrM[LOGWPL + LOGXLENBYTES - 1 : LOGXLENBYTES]];
// Write Path CPU (IEU) side
@ -188,39 +183,46 @@ module dcache
adrdec(.bin(LsuPAdrM[LOGWPL+LOGXLENBYTES-1:LOGXLENBYTES]),
.decoded(MemPAdrDecodedW));
assign SRAMWordEnable = SRAMBlockWriteEnableM ? '1 : MemPAdrDecodedW;
assign SRAMWordEnable = SRAMLineWriteEnableM ? '1 : MemPAdrDecodedW;
assign SRAMBlockWayWriteEnableM = SRAMBlockWriteEnableM ? VictimWay : '0;
assign SRAMLineWayWriteEnableM = SRAMLineWriteEnableM ? VictimWay : '0;
mux2 #(NUMWAYS) WriteEnableMux(.d0(SRAMWordWriteEnableM ? WayHit : '0),
.d1(SRAMBlockWayWriteEnableM),
.s(SRAMBlockWriteEnableM),
.d1(SRAMLineWayWriteEnableM),
.s(SRAMLineWriteEnableM),
.y(SRAMWayWriteEnable));
mux2 #(BLOCKLEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteDataM}}),
mux2 #(LINELEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteDataM}}),
.d1(DCacheMemWriteData),
.s(SRAMBlockWriteEnableM),
.s(SRAMLineWriteEnableM),
.y(SRAMWriteData));
mux3 #(`PA_BITS) BaseAdrMux(.d0({LsuPAdrM[`PA_BITS-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}}),
.d1({VictimTag, LsuPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}}),
.d2({VictimTag, FlushAdr, {{OFFSETLEN}{1'b0}}}),
.d2({VictimTag, FlushAdrQ, {{OFFSETLEN}{1'b0}}}),
.s({SelFlush, SelEvict}),
.y(DCacheBusAdr));
// flush address and way generation.
// increment on 2nd to last way
flopenr #(INDEXLEN)
FlushAdrReg(.clk,
.reset(reset | FlushAdrCntRst),
.en(FlushAdrCntEn & FlushWay[NUMWAYS-1]),
.en(FlushAdrCntEn & FlushWay[NUMWAYS-2]),
.d(FlushAdrP1),
.q(FlushAdr));
assign FlushAdrP1 = FlushAdr + 1'b1;
flopenr #(INDEXLEN)
FlushAdrQReg(.clk,
.reset(reset | FlushAdrCntRst),
.en(FlushAdrCntEn),
.d(FlushAdr),
.q(FlushAdrQ));
flopenl #(NUMWAYS)
FlushWayReg(.clk,
@ -243,7 +245,7 @@ module dcache
.CacheHit, .VictimDirty, .DCacheStall, .DCacheCommittedM,
.DCacheMiss, .DCacheAccess, .SelAdrM, .SetValid,
.ClearValid, .SetDirty, .ClearDirty, .SRAMWordWriteEnableM,
.SRAMBlockWriteEnableM, .SelEvict, .SelFlush,
.SRAMLineWriteEnableM, .SelEvict, .SelFlush,
.FlushAdrCntEn, .FlushWayCntEn, .FlushAdrCntRst,
.FlushWayCntRst, .FlushAdrFlag, .FlushDCacheM,
.VDWriteEnable, .LRUWriteEn);

View File

@ -61,7 +61,7 @@ module dcachefsm
output logic SetDirty,
output logic ClearDirty,
output logic SRAMWordWriteEnableM,
output logic SRAMBlockWriteEnableM,
output logic SRAMLineWriteEnableM,
output logic SelEvict,
output logic LRUWriteEn,
output logic SelFlush,
@ -80,7 +80,7 @@ module dcachefsm
STATE_MISS_FETCH_WDV,
STATE_MISS_FETCH_DONE,
STATE_MISS_EVICT_DIRTY,
STATE_MISS_WRITE_CACHE_BLOCK,
STATE_MISS_WRITE_CACHE_LINE,
STATE_MISS_READ_WORD,
STATE_MISS_READ_WORD_DELAY,
STATE_MISS_WRITE_WORD,
@ -113,7 +113,7 @@ module dcachefsm
SetDirty = 1'b0;
ClearDirty = 1'b0;
SRAMWordWriteEnableM = 1'b0;
SRAMBlockWriteEnableM = 1'b0;
SRAMLineWriteEnableM = 1'b0;
SelEvict = 1'b0;
LRUWriteEn = 1'b0;
SelFlush = 1'b0;
@ -228,12 +228,12 @@ module dcachefsm
NextState = STATE_MISS_EVICT_DIRTY;
DCacheWriteLine = 1'b1;
end else begin
NextState = STATE_MISS_WRITE_CACHE_BLOCK;
NextState = STATE_MISS_WRITE_CACHE_LINE;
end
end
STATE_MISS_WRITE_CACHE_BLOCK: begin
SRAMBlockWriteEnableM = 1'b1;
STATE_MISS_WRITE_CACHE_LINE: begin
SRAMLineWriteEnableM = 1'b1;
DCacheStall = 1'b1;
NextState = STATE_MISS_READ_WORD;
SelAdrM = 2'b01;
@ -301,7 +301,7 @@ module dcachefsm
SelAdrM = 2'b01;
SelEvict = 1'b1;
if(DCacheBusAck) begin
NextState = STATE_MISS_WRITE_CACHE_BLOCK;
NextState = STATE_MISS_WRITE_CACHE_LINE;
end else begin
NextState = STATE_MISS_EVICT_DIRTY;
end

View File

@ -25,31 +25,32 @@
`include "wally-config.vh"
module icache
module icache #(parameter integer LINELEN,
parameter integer NUMLINES,
parameter integer NUMWAYS)
(
// Basic pipeline stuff
input logic clk, reset,
input logic CPUBusy,
input logic clk, reset,
input logic CPUBusy,
// mmu
//input logic CacheableF,
input logic [1:0] IfuRWF,
input logic [1:0] IfuRWF,
// cpu side
input logic InvalidateICacheM,
input logic [11:0] PCNextF,
input logic [`PA_BITS-1:0] PCPF,
input logic [`XLEN-1:0] PCF,
input logic InvalidateICacheM,
input logic [11:0] PCNextF,
input logic [`PA_BITS-1:0] PCPF,
input logic [`XLEN-1:0] PCF,
// bus fsm interface
input logic IgnoreRequest,
input logic [`ICACHE_BLOCKLENINBITS-1:0] ICacheMemWriteData,
output logic ICacheFetchLine,
input logic IgnoreRequest,
input logic [LINELEN-1:0] ICacheMemWriteData,
output logic ICacheFetchLine,
(* mark_debug = "true" *) input logic ICacheBusAck,
(* mark_debug = "true" *) input logic ICacheBusAck,
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] ICacheBusAdr,
// High if the icache is requesting a stall
output logic ICacheStallF,
output logic ICacheStallF,
// The raw (not decompressed) instruction that was requested
// If this instruction is compressed, upper 16 bits may be the next 16 bits or may be zeros
@ -57,25 +58,23 @@ module icache
);
// Configuration parameters
localparam integer BLOCKLEN = `ICACHE_BLOCKLENINBITS;
localparam integer NUMLINES = `ICACHE_WAYSIZEINBYTES*8/`ICACHE_BLOCKLENINBITS;
localparam integer BLOCKBYTELEN = BLOCKLEN/8;
localparam integer LINEBYTELEN = LINELEN/8;
localparam integer OFFSETLEN = $clog2(BLOCKBYTELEN);
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
localparam integer INDEXLEN = $clog2(NUMLINES);
localparam integer TAGLEN = `PA_BITS - OFFSETLEN - INDEXLEN;
// *** not used?
localparam WORDSPERLINE = BLOCKLEN/`XLEN;
localparam WORDSPERLINE = LINELEN/`XLEN;
localparam LOGWPL = $clog2(WORDSPERLINE);
localparam integer NUMWAYS = `ICACHE_NUMWAYS;
// Input signals to cache memory
logic ICacheMemWriteEnable;
// Output signals from cache memory
logic [BLOCKLEN-1:0] ReadLineF;
logic [LINELEN-1:0] ReadLineF;
logic SelAdr;
logic [INDEXLEN-1:0] RAdr;
logic [NUMWAYS-1:0] VictimWay;
@ -84,9 +83,9 @@ module icache
logic hit;
logic [BLOCKLEN-1:0] ReadDataLineWayMasked [NUMWAYS-1:0];
logic [LINELEN-1:0] ReadDataLineWayMasked [NUMWAYS-1:0];
logic [31:0] ReadLineSetsF [`ICACHE_BLOCKLENINBITS/16-1:0];
logic [31:0] ReadLineSetsF [LINELEN/16-1:0];
logic [NUMWAYS-1:0] SRAMWayWriteEnable;
@ -98,13 +97,13 @@ module icache
.y(RAdr));
cacheway #(.NUMLINES(NUMLINES), .BLOCKLEN(BLOCKLEN), .TAGLEN(TAGLEN),
cacheway #(.NUMLINES(NUMLINES), .LINELEN(LINELEN), .TAGLEN(TAGLEN),
.OFFSETLEN(OFFSETLEN), .INDEXLEN(INDEXLEN), .DIRTY_BITS(0))
MemWay[NUMWAYS-1:0](.clk, .reset, .RAdr,
.PAdr(PCPF),
.WriteEnable(SRAMWayWriteEnable),
.VDWriteEnable(1'b0),
.WriteWordEnable({{(BLOCKLEN/`XLEN){1'b1}}}),
.WriteWordEnable({{(LINELEN/`XLEN){1'b1}}}),
.TagWriteEnable(SRAMWayWriteEnable),
.WriteData(ICacheMemWriteData),
.SetValid(ICacheMemWriteEnable),
@ -115,36 +114,31 @@ module icache
.VictimDirtyWay(), .VictimTagWay(),
.InvalidateAll(InvalidateICacheM));
generate
if(NUMWAYS > 1) begin:vict
cachereplacementpolicy #(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
cachereplacementpolicy(.clk, .reset,
.WayHit,
.VictimWay,
.LsuPAdrM(PCPF[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
.RAdr,
.LRUWriteEn);
end else begin:vict
assign VictimWay = 1'b1; // one hot.
end
endgenerate
if(NUMWAYS > 1) begin:vict
cachereplacementpolicy #(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
cachereplacementpolicy(.clk, .reset,
.WayHit,
.VictimWay,
.LsuPAdrM(PCPF[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
.RAdr,
.LRUWriteEn);
end else begin:vict
assign VictimWay = 1'b1; // one hot.
end
assign hit = | WayHit;
// ReadDataLineWayMasked is a 2d array of cache block len by number of ways.
// ReadDataLineWayMasked is a 2d array of cache line len by number of ways.
// Need to OR together each way in a bitwise manner.
// Final part of the AO Mux. First is the AND in the cacheway.
or_rows #(NUMWAYS, BLOCKLEN) ReadDataAOMux(.a(ReadDataLineWayMasked), .y(ReadLineF));
or_rows #(NUMWAYS, LINELEN) ReadDataAOMux(.a(ReadDataLineWayMasked), .y(ReadLineF));
genvar index;
generate
for(index = 0; index < BLOCKLEN / 16 - 1; index++) begin:readlinesetsmux
for(index = 0; index < LINELEN / 16 - 1; index++)
assign ReadLineSetsF[index] = ReadLineF[((index+1)*16)+16-1 : (index*16)];
end
assign ReadLineSetsF[BLOCKLEN/16-1] = {16'b0, ReadLineF[BLOCKLEN-1:BLOCKLEN-16]};
endgenerate
assign ReadLineSetsF[LINELEN/16-1] = {16'b0, ReadLineF[LINELEN-1:LINELEN-16]};
assign FinalInstrRawF = ReadLineSetsF[PCPF[$clog2(BLOCKLEN / 32) + 1 : 1]];
assign FinalInstrRawF = ReadLineSetsF[PCPF[$clog2(LINELEN / 32) + 1 : 1]];
assign ICacheBusAdr = {PCPF[`PA_BITS-1:OFFSETLEN], {{OFFSETLEN}{1'b0}}};

View File

@ -59,8 +59,8 @@ module icachefsm
STATE_MISS_FETCH_WDV, // aligned miss, issue read to AHB and wait for data.
STATE_MISS_FETCH_DONE, // write data into SRAM/LUT
STATE_MISS_READ, // read block 1 from SRAM/LUT
STATE_MISS_READ_DELAY, // read block 1 from SRAM/LUT
STATE_MISS_READ, // read line 1 from SRAM/LUT
STATE_MISS_READ_DELAY, // read line 1 from SRAM/LUT
STATE_CPU_BUSY
} statetype;

View File

@ -56,25 +56,22 @@ module amoalu (
endcase
// sign extend if necessary
generate
if (`XLEN == 32) begin:sext
assign a = srca;
assign b = srcb;
assign result = y;
end else begin:sext // `XLEN = 64
always_comb
if (width == 2'b10) begin // sign-extend word-length operations
// *** it would be more efficient to look at carry out of bit 31 to determine comparisons than do this big mux on and b
a = {{32{srca[31]}}, srca[31:0]};
b = {{32{srcb[31]}}, srcb[31:0]};
result = {{32{y[31]}}, y[31:0]};
end else begin
a = srca;
b = srcb;
result = y;
end
end
endgenerate
if (`XLEN == 32) begin:sext
assign a = srca;
assign b = srcb;
assign result = y;
end else begin:sext // `XLEN = 64
always_comb
if (width == 2'b10) begin // sign-extend word-length operations
// *** it would be more efficient to look at carry out of bit 31 to determine comparisons than do this big mux on and b
a = {{32{srca[31]}}, srca[31:0]};
b = {{32{srcb[31]}}, srcb[31:0]};
result = {{32{y[31]}}, y[31:0]};
end else begin
a = srca;
b = srcb;
result = y;
end
end
endmodule

View File

@ -157,7 +157,7 @@ module cvtfp (
// Result Selection
///////////////////////////////////////////////////////////////////////////////
generate if(`IEEE754) begin
if(`IEEE754) begin
// select the double to single precision result
assign DSRes = XNaNE ? {XSgnE, {8{1'b1}}, 1'b1, XManE[50:29]} :
Underflow & ~Denorm ? {XSgnE, 30'b0, CalcPlus1&(|FrmE[1:0]|Shift)} :
@ -178,8 +178,6 @@ module cvtfp (
// select the final result based on the opperation
assign CvtFpResE = FmtE ? {{32{1'b1}},DSRes} : {XSgnE&~XNaNE, SDExp, SDFrac[51]|XNaNE, SDFrac[50:0]&{51{~XNaNE}}};
end
endgenerate
endmodule // fpadd

View File

@ -174,3 +174,20 @@ module divconv_pipe (q1, qm1, qp1, q0, qm0, qp0, rega_out, regb_out, regc_out, r
flopenr #(60) regk (clk, reset, regs_pipe2, {qp_out0[59:35], (qp_out0[34:6] & {29{~P_pipe}}), 6'h0}, qp0);
endmodule // divconv
// *** rewrote behaviorally dh 5 Jan 2021 for speed
module csa #(parameter WIDTH=8) (
input logic [WIDTH-1:0] a, b, c,
output logic [WIDTH-1:0] sum, carry);
assign sum = a ^ b ^ c;
assign carry = (a & (b | c)) | (b & c);
/*
logic [WIDTH:0] carry_temp;
genvar i;
for (i=0;i<WIDTH;i=i+1) begin : genbit
fa fa_inst (a[i], b[i], c[i], sum[i], carry_temp[i+1]);
end
assign carry = {carry_temp[WIDTH-1:1], 1'b0};
*/
endmodule // csa

View File

@ -71,15 +71,14 @@ module fcmp (
// - return 0 if comparison with NaN (unordered)
logic [`FLEN-1:0] QNaNX, QNaNY;
generate if(`IEEE754) begin
if(`IEEE754) begin
assign QNaNX = FmtE ? {XSgnE, XExpE, 1'b1, XManE[`NF-2:0]} : {{32{1'b1}}, XSgnE, XExpE[7:0], 1'b1, XManE[50:29]};
assign QNaNY = FmtE ? {YSgnE, YExpE, 1'b1, YManE[`NF-2:0]} : {{32{1'b1}}, YSgnE, YExpE[7:0], 1'b1, YManE[50:29]};
end else begin
assign QNaNX = FmtE ? {1'b0, XExpE, 1'b1, 51'b0} : {{32{1'b1}}, 1'b0, XExpE[7:0], 1'b1, 22'b0};
assign QNaNY = FmtE ? {1'b0, YExpE, 1'b1, 51'b0} : {{32{1'b1}}, 1'b0, YExpE[7:0], 1'b1, 22'b0};
end
endgenerate
always_comb begin
case (FOpCtrlE[2:0])
3'b111: CmpResE = XNaNE ? YNaNE ? QNaNX : FSrcYE // Min

View File

@ -173,7 +173,7 @@ module fcvt (
// - only set invalid flag for out-of-range vales
// - set inexact if in representable range and not exact
generate if(`IEEE754) begin // checks before rounding
if(`IEEE754) begin // checks before rounding
assign Invalid = (Of | Uf)&FOpCtrlE[0];
assign Inexact = (Guard|Round|Sticky)&~(&FOpCtrlE[1:0]&(XSgnE|Of))&~((Of|Uf)&~FOpCtrlE[1]&FOpCtrlE[0]);
assign CvtFlgE = {Invalid&~Inexact, 3'b0, Inexact};
@ -182,10 +182,6 @@ module fcvt (
assign Inexact = (Guard|Round|Sticky)&~(&FOpCtrlE[1:0]&((XSgnE&~(ShiftCnt[12]&~Plus1))|Of))&~((Of|Uf)&~FOpCtrlE[1]&FOpCtrlE[0]);
assign CvtFlgE = {Invalid&~Inexact, 3'b0, Inexact};
end
endgenerate
endmodule // fpadd

View File

@ -814,21 +814,18 @@ module resultselect(
);
logic [`FLEN-1:0] XNaNResult, YNaNResult, ZNaNResult, InvalidResult, OverflowResult, KillProdResult, UnderflowResult; // possible results
generate
if(`IEEE754) begin:nan
if(`IEEE754) begin
assign XNaNResult = FmtM ? {XSgnM, XExpM, 1'b1, XManM[`NF-2:0]} : {{32{1'b1}}, XSgnM, XExpM[7:0], 1'b1, XManM[50:29]};
assign YNaNResult = FmtM ? {YSgnM, YExpM, 1'b1, YManM[`NF-2:0]} : {{32{1'b1}}, YSgnM, YExpM[7:0], 1'b1, YManM[50:29]};
assign ZNaNResult = FmtM ? {ZSgnEffM, ZExpM, 1'b1, ZManM[`NF-2:0]} : {{32{1'b1}}, ZSgnEffM, ZExpM[7:0], 1'b1, ZManM[50:29]};
assign InvalidResult = FmtM ? {ResultSgn, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}} : {{32{1'b1}}, ResultSgn, 8'hff, 1'b1, 22'b0};
end else begin:nan
end else begin
assign XNaNResult = FmtM ? {1'b0, XExpM, 1'b1, 51'b0} : {{32{1'b1}}, 1'b0, XExpM[7:0], 1'b1, 22'b0};
assign YNaNResult = FmtM ? {1'b0, YExpM, 1'b1, 51'b0} : {{32{1'b1}}, 1'b0, YExpM[7:0], 1'b1, 22'b0};
assign ZNaNResult = FmtM ? {1'b0, ZExpM, 1'b1, 51'b0} : {{32{1'b1}}, 1'b0, ZExpM[7:0], 1'b1, 22'b0};
assign InvalidResult = FmtM ? {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}} : {{32{1'b1}}, 1'b0, 8'hff, 1'b1, 22'b0};
end
endgenerate
assign OverflowResult = FmtM ? ((FrmM[1:0]==2'b01) | (FrmM[1:0]==2'b10&~ResultSgn) | (FrmM[1:0]==2'b11&ResultSgn)) ? {ResultSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} :
{ResultSgn, {`NE{1'b1}}, {`NF{1'b0}}} :
((FrmM[1:0]==2'b01) | (FrmM[1:0]==2'b10&~ResultSgn) | (FrmM[1:0]==2'b11&ResultSgn)) ? {{32{1'b1}}, ResultSgn, 8'hfe, {23{1'b1}}} :

View File

@ -37,22 +37,17 @@ module redundantmul #(parameter WIDTH =8)(
input logic [WIDTH-1:0] a,b,
output logic [2*WIDTH-1:0] out0, out1);
//
generate
if (`DESIGN_COMPILER == 1) begin:mul
logic [2*WIDTH-1+2:0] tmp_out0;
logic [2*WIDTH-1+2:0] tmp_out1;
DW02_multp #(WIDTH, WIDTH, 2*WIDTH+2) mul(.a, .b, .tc(1'b0), .out0(tmp_out0), .out1(tmp_out1));
assign out0 = tmp_out0[2*WIDTH-1:0];
assign out1 = tmp_out1[2*WIDTH-1:0];
end else begin:mul // force a nonredunant multipler. This will simulate properly and also is appropriate for FPGAs.
assign out0 = a * b;
assign out1 = 0;
end
endgenerate
if (`DESIGN_COMPILER == 1) begin:mul
logic [2*WIDTH-1+2:0] tmp_out0;
logic [2*WIDTH-1+2:0] tmp_out1;
DW02_multp #(WIDTH, WIDTH, 2*WIDTH+2) mul(.a, .b, .tc(1'b0), .out0(tmp_out0), .out1(tmp_out1));
assign out0 = tmp_out0[2*WIDTH-1:0];
assign out1 = tmp_out1[2*WIDTH-1:0];
end else begin:mul // force a nonredunant multipler. This will simulate properly and also is appropriate for FPGAs.
assign out0 = a * b;
assign out1 = 0;
end
endmodule

View File

@ -1,195 +0,0 @@
///////////////////////////////////////////
// lzd.sv
//
// Written: James.Stine@okstate.edu 1 February 2021
// Modified:
//
// Purpose: Integer Divide instructions
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
/* verilator lint_off DECLFILENAME */
// Original idea came from V. G. Oklobdzija, "An algorithmic and novel
// design of a leading zero detector circuit: comparison with logic
// synthesis," in IEEE Transactions on Very Large Scale Integration
// (VLSI) Systems, vol. 2, no. 1, pp. 124-128, March 1994, doi:
// 10.1109/92.273153.
// Modified to be more hierarchical
module lzd2 (P, V, B);
input logic [1:0] B;
output logic P;
output logic V;
assign V = B[0] | B[1];
assign P = B[0] & ~B[1];
endmodule // lzd2
module lzd_hier #(parameter WIDTH=8)
(input logic [WIDTH-1:0] B,
output logic [$clog2(WIDTH)-1:0] ZP,
output logic ZV);
if (WIDTH == 128)
lzd128 lz127 (ZP, ZV, B);
else if (WIDTH == 64)
lzd64 lz64 (ZP, ZV, B);
else if (WIDTH == 32)
lzd32 lz32 (ZP, ZV, B);
else if (WIDTH == 16)
lzd16 lz16 (ZP, ZV, B);
else if (WIDTH == 8)
lzd8 lz8 (ZP, ZV, B);
else if (WIDTH == 4)
lzd4 lz4 (ZP, ZV, B);
endmodule // lzd_hier
module lzd4 (ZP, ZV, B);
input logic [3:0] B;
logic ZPa;
logic ZPb;
logic ZVa;
logic ZVb;
output logic [1:0] ZP;
output logic ZV;
lzd2 l1(ZPa, ZVa, B[1:0]);
lzd2 l2(ZPb, ZVb, B[3:2]);
assign ZP[0] = ZVb ? ZPb : ZPa;
assign ZP[1] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd4
module lzd8 (ZP, ZV, B);
input logic [7:0] B;
logic [1:0] ZPa;
logic [1:0] ZPb;
logic ZVa;
logic ZVb;
output logic [2:0] ZP;
output logic ZV;
lzd4 l1(ZPa, ZVa, B[3:0]);
lzd4 l2(ZPb, ZVb, B[7:4]);
assign ZP[1:0] = ZVb ? ZPb : ZPa;
assign ZP[2] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd8
module lzd16 (ZP, ZV, B);
input logic [15:0] B;
logic [2:0] ZPa;
logic [2:0] ZPb;
logic ZVa;
logic ZVb;
output logic [3:0] ZP;
output logic ZV;
lzd8 l1(ZPa, ZVa, B[7:0]);
lzd8 l2(ZPb, ZVb, B[15:8]);
assign ZP[2:0] = ZVb ? ZPb : ZPa;
assign ZP[3] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd16
module lzd32 (ZP, ZV, B);
input logic [31:0] B;
logic [3:0] ZPa;
logic [3:0] ZPb;
logic ZVa;
logic ZVb;
output logic [4:0] ZP;
output logic ZV;
lzd16 l1(ZPa, ZVa, B[15:0]);
lzd16 l2(ZPb, ZVb, B[31:16]);
assign ZP[3:0] = ZVb ? ZPb : ZPa;
assign ZP[4] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd32
module lzd64 (ZP, ZV, B);
input logic [63:0] B;
logic [4:0] ZPa;
logic [4:0] ZPb;
logic ZVa;
logic ZVb;
output logic [5:0] ZP;
output logic ZV;
lzd32 l1(ZPa, ZVa, B[31:0]);
lzd32 l2(ZPb, ZVb, B[63:32]);
assign ZP[4:0] = ZVb ? ZPb : ZPa;
assign ZP[5] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd64
module lzd128 (ZP, ZV, B);
input logic [127:0] B;
logic [5:0] ZPa;
logic [5:0] ZPb;
logic ZVa;
logic ZVb;
output logic [6:0] ZP;
output logic ZV;
lzd64 l1(ZPa, ZVa, B[64:0]);
lzd64 l2(ZPb, ZVb, B[127:63]);
assign ZP[5:0] = ZVb ? ZPb : ZPa;
assign ZP[6] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd128
/* verilator lint_on DECLFILENAME */

View File

@ -33,18 +33,16 @@ module or_rows #(parameter ROWS = 8, COLS=2) (
input var logic [COLS-1:0] a[ROWS-1:0],
output logic [COLS-1:0] y);
logic [COLS-1:0] mid[ROWS-1:1];
genvar row, col;
generate
if(ROWS == 1)
assign y = a[0];
else begin
assign mid[1] = a[0] | a[1];
for (row=2; row < ROWS; row++)
assign mid[row] = mid[row-1] | a[row];
assign y = mid[ROWS-1];
end
endgenerate
genvar row;
if(ROWS == 1)
assign y = a[0];
else begin
logic [COLS-1:0] mid[ROWS-1:1];
assign mid[1] = a[0] | a[1];
for (row=2; row < ROWS; row++)
assign mid[row] = mid[row-1] | a[row];
assign y = mid[ROWS-1];
end
endmodule
/* verilator lint_on UNOPTFLAT */

View File

@ -1,74 +0,0 @@
///////////////////////////////////////////
// shifters.sv
//
// Written: James.Stine@okstate.edu 1 February 2021
// Modified:
//
// Purpose: Integer Divide instructions
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
/* verilator lint_off DECLFILENAME */
/* verilator lint_off UNOPTFLAT */
module shift_right #(parameter WIDTH=8)
(input logic [WIDTH-1:0] A,
input logic [$clog2(WIDTH)-1:0] Shift,
output logic [WIDTH-1:0] Z);
logic [WIDTH-1:0] stage [$clog2(WIDTH):0];
logic sign;
genvar i;
assign stage[0] = A;
generate
for (i=0;i<$clog2(WIDTH);i=i+1) begin : genbit
mux2 #(WIDTH) mux_inst (stage[i],
{{(WIDTH/(2**(i+1))){1'b0}}, stage[i][WIDTH-1:WIDTH/(2**(i+1))]},
Shift[$clog2(WIDTH)-i-1],
stage[i+1]);
end
endgenerate
assign Z = stage[$clog2(WIDTH)];
endmodule // shift_right
module shift_left #(parameter WIDTH=8)
(input logic [WIDTH-1:0] A,
input logic [$clog2(WIDTH)-1:0] Shift,
output logic [WIDTH-1:0] Z);
logic [WIDTH-1:0] stage [$clog2(WIDTH):0];
genvar i;
assign stage[0] = A;
generate
for (i=0;i<$clog2(WIDTH);i=i+1) begin : genbit
mux2 #(WIDTH) mux_inst (stage[i],
{stage[i][WIDTH-1-WIDTH/(2**(i+1)):0], {(WIDTH/(2**(i+1))){1'b0}}},
Shift[$clog2(WIDTH)-i-1],
stage[i+1]);
end
endgenerate
assign Z = stage[$clog2(WIDTH)];
endmodule // shift_left
/* verilator lint_on DECLFILENAME */
/* verilator lint_on UNOPTFLAT */

View File

@ -78,9 +78,7 @@ module alu #(parameter WIDTH=32) (
endcase
// support W-type RV64I ADDW/SUBW/ADDIW/Shifts that sign-extend 32-bit result to 64 bits
generate
if (WIDTH==64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
else assign Result = FullResult;
endgenerate
if (WIDTH==64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
else assign Result = FullResult;
endmodule

View File

@ -109,55 +109,53 @@ module controller(
assign Rs1D = InstrD[19:15];
// Main Instruction Decoder
generate
always_comb
case(OpD)
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MulDiv_Atomic_Illegal
7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // illegal instruction
7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw
7'b0001111: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
7'b0011011: if (`XLEN == 64)
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // sw
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // fsw
7'b0101111: if (`A_SUPPORTED) begin
if (InstrD[31:27] == 5'b00010)
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr
else if (InstrD[31:27] == 5'b00011)
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc
else
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0;; // amo
end else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
else if (Funct7D == 7'b0000001 & `M_SUPPORTED)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/Divide
else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
//7'b1010011: ControlsD = `CTRLW'b0_000_00_00_101_0_00_0_0_0_0_0_0_0_00_1; // FP
7'b1100011: ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
7'b1100111: ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
7'b1110011: if (Funct3D == 3'b000)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
else
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
endcase
endgenerate
always_comb
case(OpD)
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MulDiv_Atomic_Illegal
7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // illegal instruction
7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw
7'b0001111: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
7'b0011011: if (`XLEN == 64)
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // sw
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // fsw
7'b0101111: if (`A_SUPPORTED) begin
if (InstrD[31:27] == 5'b00010)
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr
else if (InstrD[31:27] == 5'b00011)
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc
else
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0;; // amo
end else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
else if (Funct7D == 7'b0000001 & `M_SUPPORTED)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/Divide
else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
//7'b1010011: ControlsD = `CTRLW'b0_000_00_00_101_0_00_0_0_0_0_0_0_0_00_1; // FP
7'b1100011: ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
7'b1100111: ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
7'b1110011: if (Funct3D == 3'b000)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
else
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
endcase
// unswizzle control bits
// squash control signals if coming from an illegal compressed instruction
@ -181,17 +179,15 @@ module controller(
// Fences
// Ordinary fence is presently a nop
// FENCE.I flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
generate
if (`ZIFENCEI_SUPPORTED & `MEM_ICACHE) begin:fencei
logic FenceID;
assign FenceID = FenceD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
assign InvalidateICacheD = FenceID;
assign FlushDCacheD = FenceID;
end else begin:fencei
assign InvalidateICacheD = 0;
assign FlushDCacheD = 0;
end
endgenerate
if (`ZIFENCEI_SUPPORTED & `MEM_ICACHE) begin:fencei
logic FenceID;
assign FenceID = FenceD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
assign InvalidateICacheD = FenceID;
assign FlushDCacheD = FenceID;
end else begin:fencei
assign InvalidateICacheD = 0;
assign FlushDCacheD = 0;
end
// Decocde stage pipeline control register
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD);

View File

@ -124,19 +124,15 @@ module datapath (
mux5 #(`XLEN) resultmuxW(ResultW, ReadDataW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, WriteDataW);
// floating point interactions: fcvt, fp stores
generate
if (`F_SUPPORTED) begin:fpmux
mux2 #(`XLEN) resultmuxM(IEUResultM, FIntResM, FWriteIntM, ResultM);
mux2 #(`XLEN) writedatamux(ForwardedSrcBE, FWriteDataE, ~IllegalFPUInstrE, WriteDataE);
end else begin:fpmux
assign ResultM = IEUResultM;
assign WriteDataE = ForwardedSrcBE;
end
endgenerate
if (`F_SUPPORTED) begin:fpmux
mux2 #(`XLEN) resultmuxM(IEUResultM, FIntResM, FWriteIntM, ResultM);
mux2 #(`XLEN) writedatamux(ForwardedSrcBE, FWriteDataE, ~IllegalFPUInstrE, WriteDataE);
end else begin:fpmux
assign ResultM = IEUResultM;
assign WriteDataE = ForwardedSrcBE;
end
// handle Store Conditional result if atomic extension supported
generate
if (`A_SUPPORTED) assign SCResultW = {{(`XLEN-1){1'b0}}, SquashSCW};
else assign SCResultW = 0;
endgenerate
if (`A_SUPPORTED) assign SCResultW = {{(`XLEN-1){1'b0}}, SquashSCW};
else assign SCResultW = 0;
endmodule

View File

@ -32,23 +32,24 @@ module extend (
localparam [`XLEN-1:0] undefined = {(`XLEN){1'bx}}; // could change to 0 after debug
// generate
always_comb
case(ImmSrcD)
// I-type
3'b000: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:20]};
// S-type (stores)
3'b001: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
// B-type (branches)
3'b010: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
// J-type (jal)
3'b011: ExtImmD = {{(`XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
// U-type (lui, auipc)
3'b100: ExtImmD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
// Store Conditional: zero offset
3'b101: if (`A_SUPPORTED) ExtImmD = 0;
else ExtImmD = undefined;
default: ExtImmD = undefined; // undefined
endcase
// endgenerate
always_comb
case(ImmSrcD)
// I-type
3'b000: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:20]};
// S-type (stores)
3'b001: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
// B-type (branches)
3'b010: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
// J-type (jal)
3'b011: ExtImmD = {{(`XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
// U-type (lui, auipc)
3'b100: ExtImmD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
// Store Conditional: zero offset
3'b101: if (`A_SUPPORTED) ExtImmD = 0;
else ExtImmD = undefined;
default: begin
ExtImmD = undefined; // undefined
$error("Invalid ImmSrcD in extend");
end
endcase
endmodule

View File

@ -39,30 +39,28 @@ module shifter (
// For RV64, 32 and 64-bit shifts are needed, with sign extension.
// funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong)
generate
if (`XLEN==32) begin:shifter // RV32
always_comb // funnel mux
if (Right)
if (Arith) z = {{31{A[31]}}, A};
else z = {31'b0, A};
else z = {A, 31'b0};
assign amttrunc = Amt; // shift amount
end else begin:shifter // RV64
always_comb // funnel mux
if (W64) begin // 32-bit shifts
if (Right)
if (Arith) z = {64'b0, {31{A[31]}}, A[31:0]};
else z = {95'b0, A[31:0]};
else z = {32'b0, A[31:0], 63'b0};
end else begin
if (Right)
if (Arith) z = {{63{A[63]}}, A};
else z = {63'b0, A};
else z = {A, 63'b0};
end
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32 or 64-bit shift
end
endgenerate
if (`XLEN==32) begin:shifter // RV32
always_comb // funnel mux
if (Right)
if (Arith) z = {{31{A[31]}}, A};
else z = {31'b0, A};
else z = {A, 31'b0};
assign amttrunc = Amt; // shift amount
end else begin:shifter // RV64
always_comb // funnel mux
if (W64) begin // 32-bit shifts
if (Right)
if (Arith) z = {64'b0, {31{A[31]}}, A[31:0]};
else z = {95'b0, A[31:0]};
else z = {32'b0, A[31:0], 63'b0};
end else begin
if (Right)
if (Arith) z = {{63{A[63]}}, A};
else z = {63'b0, A};
else z = {A, 63'b0};
end
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32 or 64-bit shift
end
// opposite offset for right shfits
assign offset = Right ? amttrunc : ~amttrunc;

View File

@ -92,20 +92,17 @@ module SRAM2P1R1W
.q(WD1Q));
// read port
assign RD1 = mem[RA1Q];
genvar index;
// write port
generate
for (index = 0; index < WIDTH; index = index + 1) begin:bitwrite
always_ff @ (posedge clk) begin
if (WEN1Q & BitWEN1[index]) begin
mem[WA1Q][index] <= WD1Q[index];
end
genvar index;
for (index = 0; index < WIDTH; index = index + 1) begin:bitwrite
always_ff @(posedge clk) begin
if (WEN1Q & BitWEN1[index]) begin
mem[WA1Q][index] <= WD1Q[index];
end
end
endgenerate
end
endmodule

View File

@ -70,74 +70,72 @@ module bpred
// Part 1 branch direction prediction
generate
if (`BPTYPE == "BPTWOBIT") begin:Predictor
twoBitPredictor DirPredictor(.clk(clk),
.reset(reset),
.StallF(StallF),
.LookUpPC(PCNextF),
.Prediction(BPPredF),
// update
.UpdatePC(PCE),
.UpdateEN(InstrClassE[0] & ~StallE),
.UpdatePrediction(UpdateBPPredE));
if (`BPTYPE == "BPTWOBIT") begin:Predictor
twoBitPredictor DirPredictor(.clk(clk),
.reset(reset),
.StallF(StallF),
.LookUpPC(PCNextF),
.Prediction(BPPredF),
// update
.UpdatePC(PCE),
.UpdateEN(InstrClassE[0] & ~StallE),
.UpdatePrediction(UpdateBPPredE));
end else if (`BPTYPE == "BPGLOBAL") begin:Predictor
end else if (`BPTYPE == "BPGLOBAL") begin:Predictor
globalHistoryPredictor DirPredictor(.clk(clk),
.reset(reset),
.*, // Stalls and flushes
.PCNextF(PCNextF),
.BPPredF(BPPredF),
// update
.InstrClassE(InstrClassE),
.BPInstrClassE(BPInstrClassE),
.BPPredDirWrongE(BPPredDirWrongE),
.PCE(PCE),
.PCSrcE(PCSrcE),
.UpdateBPPredE(UpdateBPPredE));
end else if (`BPTYPE == "BPGSHARE") begin:Predictor
globalHistoryPredictor DirPredictor(.clk(clk),
.reset(reset),
.*, // Stalls and flushes
.PCNextF(PCNextF),
.BPPredF(BPPredF),
// update
.InstrClassE(InstrClassE),
.BPInstrClassE(BPInstrClassE),
.BPPredDirWrongE(BPPredDirWrongE),
.PCE(PCE),
.PCSrcE(PCSrcE),
.UpdateBPPredE(UpdateBPPredE));
end else if (`BPTYPE == "BPGSHARE") begin:Predictor
gsharePredictor DirPredictor(.clk(clk),
.reset(reset),
.*, // Stalls and flushes
.PCNextF(PCNextF),
.BPPredF(BPPredF),
// update
.InstrClassE(InstrClassE),
.BPInstrClassE(BPInstrClassE),
.BPPredDirWrongE(BPPredDirWrongE),
.PCE(PCE),
.PCSrcE(PCSrcE),
.UpdateBPPredE(UpdateBPPredE));
end
else if (`BPTYPE == "BPLOCALPAg") begin:Predictor
gsharePredictor DirPredictor(.clk(clk),
.reset(reset),
.*, // Stalls and flushes
.PCNextF(PCNextF),
.BPPredF(BPPredF),
// update
.InstrClassE(InstrClassE),
.BPInstrClassE(BPInstrClassE),
.BPPredDirWrongE(BPPredDirWrongE),
.PCE(PCE),
.PCSrcE(PCSrcE),
.UpdateBPPredE(UpdateBPPredE));
end
else if (`BPTYPE == "BPLOCALPAg") begin:Predictor
localHistoryPredictor DirPredictor(.clk(clk),
.reset(reset),
.*, // Stalls and flushes
.LookUpPC(PCNextF),
.Prediction(BPPredF),
// update
.UpdatePC(PCE),
.UpdateEN(InstrClassE[0] & ~StallE),
.PCSrcE(PCSrcE),
.UpdatePrediction(UpdateBPPredE));
end
else if (`BPTYPE == "BPLOCALPAg") begin:Predictor
localHistoryPredictor DirPredictor(.clk(clk),
.reset(reset),
.*, // Stalls and flushes
.LookUpPC(PCNextF),
.Prediction(BPPredF),
// update
.UpdatePC(PCE),
.UpdateEN(InstrClassE[0] & ~StallE),
.PCSrcE(PCSrcE),
.UpdatePrediction(UpdateBPPredE));
end
else if (`BPTYPE == "BPLOCALPAg") begin:Predictor
localHistoryPredictor DirPredictor(.clk(clk),
.reset(reset),
.*, // Stalls and flushes
.LookUpPC(PCNextF),
.Prediction(BPPredF),
// update
.UpdatePC(PCE),
.UpdateEN(InstrClassE[0] & ~StallE),
.PCSrcE(PCSrcE),
.UpdatePrediction(UpdateBPPredE));
end
endgenerate
localHistoryPredictor DirPredictor(.clk(clk),
.reset(reset),
.*, // Stalls and flushes
.LookUpPC(PCNextF),
.Prediction(BPPredF),
// update
.UpdatePC(PCE),
.UpdateEN(InstrClassE[0] & ~StallE),
.PCSrcE(PCSrcE),
.UpdatePrediction(UpdateBPPredE));
end
// this predictor will have two pieces of data,

View File

@ -38,141 +38,139 @@ module decompress (
logic [1:0] op;
// if the system handles compressed instructions, decode appropriately
generate
if (!(`C_SUPPORTED)) begin:decompress // no compressed mode
assign InstrD = InstrRawD;
assign IllegalCompInstrD = 0;
end else begin : decompress // COMPRESSED mode supported
assign instr16 = InstrRawD[15:0]; // instruction is alreay aligned
assign op = instr16[1:0];
assign rds1 = instr16[11:7];
assign rs2 = instr16[6:2];
assign rs1p = {2'b01, instr16[9:7]};
assign rds1p = {2'b01, instr16[9:7]};
assign rs2p = {2'b01, instr16[4:2]};
assign rdp = {2'b01, instr16[4:2]};
// many compressed immediate formats
assign immCILSP = {4'b0000, instr16[3:2], instr16[12], instr16[6:4], 2'b00};
assign immCILSPD = {3'b000, instr16[4:2], instr16[12], instr16[6:5], 3'b000};
assign immCSS = {4'b0000, instr16[8:7], instr16[12:9], 2'b00};
assign immCSSD = {3'b000, instr16[9:7], instr16[12:10], 3'b000};
assign immCL = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
assign immCLD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
assign immCS = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
assign immCSD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}};
assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]};
assign immCI = {{7{instr16[12]}}, instr16[6:2]};
assign immCILUI = {{15{instr16[12]}}, instr16[6:2]};
assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000};
assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00};
assign immSH = {instr16[12], instr16[6:2]};
if (!(`C_SUPPORTED)) begin:decompress // no compressed mode
assign InstrD = InstrRawD;
assign IllegalCompInstrD = 0;
end else begin : decompress // COMPRESSED mode supported
assign instr16 = InstrRawD[15:0]; // instruction is alreay aligned
assign op = instr16[1:0];
assign rds1 = instr16[11:7];
assign rs2 = instr16[6:2];
assign rs1p = {2'b01, instr16[9:7]};
assign rds1p = {2'b01, instr16[9:7]};
assign rs2p = {2'b01, instr16[4:2]};
assign rdp = {2'b01, instr16[4:2]};
// many compressed immediate formats
assign immCILSP = {4'b0000, instr16[3:2], instr16[12], instr16[6:4], 2'b00};
assign immCILSPD = {3'b000, instr16[4:2], instr16[12], instr16[6:5], 3'b000};
assign immCSS = {4'b0000, instr16[8:7], instr16[12:9], 2'b00};
assign immCSSD = {3'b000, instr16[9:7], instr16[12:10], 3'b000};
assign immCL = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
assign immCLD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
assign immCS = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
assign immCSD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}};
assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]};
assign immCI = {{7{instr16[12]}}, instr16[6:2]};
assign immCILUI = {{15{instr16[12]}}, instr16[6:2]};
assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000};
assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00};
assign immSH = {instr16[12], instr16[6:2]};
// only for RV128
// assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000};
// assign immCSSQ = {2{instr16[10]}, instr16[10:7], instr16[12:11], 4'b0000};
// assign immCLQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000};
// assign immCSQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000};
always_comb
if (op == 2'b11) begin // noncompressed instruction
InstrD = InstrRawD;
IllegalCompInstrD = 0;
end else begin // convert compressed instruction into uncompressed
IllegalCompInstrD = 0;
case ({op, instr16[15:13]})
5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
else begin // illegal instruction
always_comb
if (op == 2'b11) begin // noncompressed instruction
InstrD = InstrRawD;
IllegalCompInstrD = 0;
end else begin // convert compressed instruction into uncompressed
IllegalCompInstrD = 0;
case ({op, instr16[15:13]})
5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
else begin // illegal instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
5'b00011: if (`XLEN==32)
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
else
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld;
5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
5'b00111: if (`XLEN==32)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
else
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
5'b01001: if (`XLEN==32)
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal
else
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
5'b01011: if (rds1 != 5'b00010)
InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui
else
InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
5'b01100: if (instr16[11:10] == 2'b00)
InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli
else if (instr16[11:10] == 2'b01)
InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai
else if (instr16[11:10] == 2'b10)
InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
else if (instr16[12:10] == 3'b011)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else if (instr16[6:5] == 2'b10)
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
else // if (instr16[6:5] == 2'b11)
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
else if (instr16[12:10] == 3'b111 & `XLEN > 32)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
else begin // reserved
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
5'b00011: if (`XLEN==32)
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
else begin // illegal instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli
5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
5'b10011: if (`XLEN == 32)
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
else
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10100: if (instr16[12] == 0)
if (instr16[6:2] == 5'b00000)
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
else
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld;
5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
5'b00111: if (`XLEN==32)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
else
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
5'b01001: if (`XLEN==32)
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal
else
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
5'b01011: if (rds1 != 5'b00010)
InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui
else
InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
5'b01100: if (instr16[11:10] == 2'b00)
InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli
else if (instr16[11:10] == 2'b01)
InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai
else if (instr16[11:10] == 2'b10)
InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
else if (instr16[12:10] == 3'b011)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else if (instr16[6:5] == 2'b10)
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
else // if (instr16[6:5] == 2'b11)
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
else if (instr16[12:10] == 3'b111 & `XLEN > 32)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
else begin // reserved
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else begin // illegal instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli
5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
5'b10011: if (`XLEN == 32)
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
else
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10100: if (instr16[12] == 0)
if (instr16[6:2] == 5'b00000)
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv
else
if (rs2 == 5'b00000)
if (rds1 == 5'b00000)
InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
else
InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
else
if (rs2 == 5'b00000)
if (rds1 == 5'b00000)
InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
else
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
else
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
5'b10111: if (`XLEN==32)
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
else
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
default: begin // illegal instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
endcase
end
end
endgenerate
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
5'b10111: if (`XLEN==32)
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
else
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
default: begin // illegal instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
endcase
end
end
endmodule

View File

@ -111,12 +111,11 @@ module ifu (
logic [31:0] PostSpillInstrRawF;
generate
if(`C_SUPPORTED) begin : SpillSupport
logic [`XLEN-1:0] PCFp2;
logic Spill;
logic SelSpill, SpillSave;
logic [15:0] SpillDataBlock0;
logic [15:0] SpillDataLine0;
// this exists only if there are compressed instructions.
assign PCFp2 = PCF + `XLEN'b10;
@ -124,7 +123,7 @@ module ifu (
assign PCNextFMux = SelNextSpill ? PCFp2[11:0] : PCNextF[11:0];
assign PCFMux = SelSpill ? PCFp2 : PCF;
assign Spill = &PCF[$clog2(`ICACHE_BLOCKLENINBITS/32)+1:1];
assign Spill = &PCF[$clog2(`ICACHE_LINELENINBITS/32)+1:1];
typedef enum {STATE_SPILL_READY, STATE_SPILL_SPILL} statetype;
(* mark_debug = "true" *) statetype CurrState, NextState;
@ -154,19 +153,18 @@ module ifu (
.en(SpillSave),
.reset(reset),
.d(InstrRawF[15:0]),
.q(SpillDataBlock0));
.q(SpillDataLine0));
assign PostSpillInstrRawF = Spill ? {InstrRawF[15:0], SpillDataBlock0} : InstrRawF;
assign PostSpillInstrRawF = Spill ? {InstrRawF[15:0], SpillDataLine0} : InstrRawF;
assign CompressedF = PostSpillInstrRawF[1:0] != 2'b11;
// end of spill support
end else begin : NoSpillSupport // block: SpillSupport
end else begin : NoSpillSupport // line: SpillSupport
assign PCNextFMux = PCNextF[11:0];
assign PCFMux = PCF;
assign SelNextSpill = 0;
assign PostSpillInstrRawF = InstrRawF;
end
endgenerate
assign PCFExt = {2'b00, PCFMux};
@ -220,30 +218,30 @@ module ifu (
// 2. cache // `MEM_ICACHE
// 3. wire pass-through
localparam integer WORDSPERLINE = `MEM_ICACHE ? `ICACHE_BLOCKLENINBITS/`XLEN : 1;
localparam integer WORDSPERLINE = `MEM_ICACHE ? `ICACHE_LINELENINBITS/`XLEN : 1;
localparam integer LOGWPL = `MEM_ICACHE ? $clog2(WORDSPERLINE) : 1;
localparam integer BLOCKLEN = `MEM_ICACHE ? `ICACHE_BLOCKLENINBITS : `XLEN;
localparam integer LINELEN = `MEM_ICACHE ? `ICACHE_LINELENINBITS : `XLEN;
localparam integer WordCountThreshold = `MEM_ICACHE ? WORDSPERLINE - 1 : 0;
localparam integer BLOCKBYTELEN = BLOCKLEN/8;
localparam integer OFFSETLEN = $clog2(BLOCKBYTELEN);
localparam integer LINEBYTELEN = LINELEN/8;
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
logic [LOGWPL-1:0] WordCount;
logic [BLOCKLEN-1:0] ICacheMemWriteData;
logic [LINELEN-1:0] ICacheMemWriteData;
logic ICacheBusAck;
logic [`PA_BITS-1:0] LocalIfuBusAdr;
logic [`PA_BITS-1:0] ICacheBusAdr;
logic SelUncachedAdr;
generate
if(`MEM_ICACHE) begin : icache
logic [1:0] IfuRWF;
assign IfuRWF = CacheableF ? 2'b10 : 2'b00;
icache icache(.clk, .reset, .CPUBusy, .IgnoreRequest, .ICacheMemWriteData , .ICacheBusAck,
/* -----\/----- EXCLUDED -----\/-----
icache #(.LINELEN(`ICACHE_LINELENINBITS),
.NUMLINES(`ICACHE_WAYSIZEINBYTES*8/`ICACHE_LINELENINBITS),
.NUMWAYS(`ICACHE_NUMWAYS))
icache(.clk, .reset, .CPUBusy, .IgnoreRequest, .ICacheMemWriteData , .ICacheBusAck,
.ICacheBusAdr, .ICacheStallF, .FinalInstrRawF,
.ICacheFetchLine,
.IfuRWF(IfuRWF), //aways read
@ -251,15 +249,38 @@ module ifu (
.PCPF(PCPF),
.PCF(PCFMux),
.InvalidateICacheM);
-----/\----- EXCLUDED -----/\----- */
end else begin : passthrough
logic [`XLEN-1:0] FinalInstrRawF_FIXME;
cache #(.LINELEN(`ICACHE_LINELENINBITS),
.NUMLINES(`ICACHE_WAYSIZEINBYTES*8/`ICACHE_LINELENINBITS),
.NUMWAYS(`ICACHE_NUMWAYS), .DCACHE(0))
icache(.clk, .reset, .CPUBusy, .IgnoreRequest, .CacheMemWriteData(ICacheMemWriteData) , .CacheBusAck(ICacheBusAck),
.CacheBusAdr(ICacheBusAdr), .CacheStall(ICacheStallF), .ReadDataWord(FinalInstrRawF_FIXME),
.CacheFetchLine(ICacheFetchLine),
.CacheWriteLine(),
.ReadDataLineSets(),
.CacheMiss(),
.CacheAccess(),
.FinalWriteData('0),
.RW(IfuRWF), //aways read
.Atomic(2'b00),
.FlushCache(1'b0),
.LsuAdrE(PCNextFMux), // fixme
.LsuPAdrM(PCPF), // fixme
.PreLsuPAdrM(PCFMux[11:0]), //fixme
.CacheCommitted(),
.InvalidateCacheM(InvalidateICacheM));
assign FinalInstrRawF = FinalInstrRawF_FIXME[31:0];
end else begin
assign ICacheFetchLine = 0;
assign ICacheBusAdr = 0;
//assign CompressedF = 0; //?
assign ICacheStallF = 0;
assign FinalInstrRawF = 0;
end
endgenerate
// select between dcache and direct from the BUS. Always selected if no dcache.
// handled in the busfsm.
@ -270,14 +291,12 @@ module ifu (
// always present
genvar index;
generate
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
flopen #(`XLEN) fb(.clk(clk),
.en(IfuBusAck & IfuBusRead & (index == WordCount)),
.d(IfuBusHRDATA),
.q(ICacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
end
endgenerate
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
flopen #(`XLEN) fb(.clk(clk),
.en(IfuBusAck & IfuBusRead & (index == WordCount)),
.d(IfuBusHRDATA),
.q(ICacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
end
assign LocalIfuBusAdr = SelUncachedAdr ? PCPF : ICacheBusAdr;
assign IfuBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalIfuBusAdr;
@ -351,25 +370,23 @@ module ifu (
flopenl #(`XLEN) pcreg(clk, reset, ~StallF & ~ICacheStallF, PCNextF, `RESET_VECTOR, PCF);
// branch and jump predictor
generate
if (`BPRED_ENABLED == 1) begin : bpred
bpred bpred(.clk, .reset,
.StallF, .StallD, .StallE,
.FlushF, .FlushD, .FlushE,
.PCNextF, .BPPredPCF, .SelBPPredF, .PCE, .PCSrcE, .IEUAdrE,
.PCD, .PCLinkE, .InstrClassE, .BPPredWrongE, .BPPredDirWrongE,
.BTBPredPCWrongE, .RASPredPCWrongE, .BPPredClassNonCFIWrongE);
end else begin : bpred
assign BPPredPCF = {`XLEN{1'b0}};
assign SelBPPredF = 1'b0;
assign BPPredWrongE = PCSrcE;
assign BPPredDirWrongE = 1'b0;
assign BTBPredPCWrongE = 1'b0;
assign RASPredPCWrongE = 1'b0;
assign BPPredClassNonCFIWrongE = 1'b0;
end
endgenerate
if (`BPRED_ENABLED == 1) begin : bpred
bpred bpred(.clk, .reset,
.StallF, .StallD, .StallE,
.FlushF, .FlushD, .FlushE,
.PCNextF, .BPPredPCF, .SelBPPredF, .PCE, .PCSrcE, .IEUAdrE,
.PCD, .PCLinkE, .InstrClassE, .BPPredWrongE, .BPPredDirWrongE,
.BTBPredPCWrongE, .RASPredPCWrongE, .BPPredClassNonCFIWrongE);
end else begin : bpred
assign BPPredPCF = {`XLEN{1'b0}};
assign SelBPPredF = 1'b0;
assign BPPredWrongE = PCSrcE;
assign BPPredDirWrongE = 1'b0;
assign BTBPredPCWrongE = 1'b0;
assign RASPredPCWrongE = 1'b0;
assign BPPredClassNonCFIWrongE = 1'b0;
end
// The true correct target is IEUAdrE if PCSrcE is 1 else it is the fall through PCLinkE.
assign PCCorrectE = PCSrcE ? IEUAdrE : PCLinkE;

View File

@ -66,16 +66,10 @@ module localHistoryPredictor
// .BitWEN1(2'b11));
genvar index;
generate
for (index = 0; index < 2**m; index = index +1) begin:localhist
flopenr #(k) LocalHistoryRegister(.clk(clk),
.reset(reset),
.en(UpdateEN & (index == UpdatePCIndex)),
.d(LHRFNext),
.q(LHRNextF[index]));
end
endgenerate
for (index = 0; index < 2**m; index = index +1) begin:localhist
flopenr #(k) LocalHistoryRegister(.clk, .reset, .en(UpdateEN & (index == UpdatePCIndex)),
.d(LHRFNext), .q(LHRNextF[index]));
end
// need to forward when updating to the same address as reading.
// first we compare to see if the update and lookup addreses are the same

View File

@ -120,75 +120,73 @@ module lsu
flopenrc #(`XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
assign IEUAdrExtM = {2'b00, IEUAdrM};
generate
if(`MEM_VIRTMEM) begin : MEM_VIRTMEM
logic AnyCPUReqM;
logic [`PA_BITS-1:0] HPTWAdr;
logic HPTWRead;
logic [2:0] HPTWSize;
logic SelReplayCPURequest;
if(`MEM_VIRTMEM) begin : MEM_VIRTMEM
logic AnyCPUReqM;
logic [`PA_BITS-1:0] HPTWAdr;
logic HPTWRead;
logic [2:0] HPTWSize;
logic SelReplayCPURequest;
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
interlockfsm interlockfsm (.clk, .reset, .AnyCPUReqM, .ITLBMissF, .ITLBWriteF,
.DTLBMissM, .DTLBWriteM, .ExceptionM, .PendingInterruptM, .DCacheStall,
.InterlockStall, .SelReplayCPURequest, .SelHPTW,
.IgnoreRequest);
hptw hptw(.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM,
.ITLBMissF(ITLBMissF & ~PendingInterruptM),
.DTLBMissM(DTLBMissM & ~PendingInterruptM),
.MemRWM, .PTE, .PageType, .ITLBWriteF, .DTLBWriteM,
.HPTWReadPTE(ReadDataM),
.DCacheStall, .HPTWAdr, .HPTWRead, .HPTWSize, .AnyCPUReqM);
interlockfsm interlockfsm (.clk, .reset, .AnyCPUReqM, .ITLBMissF, .ITLBWriteF,
.DTLBMissM, .DTLBWriteM, .ExceptionM, .PendingInterruptM, .DCacheStall,
.InterlockStall, .SelReplayCPURequest, .SelHPTW,
.IgnoreRequest);
hptw hptw(.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM,
.ITLBMissF(ITLBMissF & ~PendingInterruptM),
.DTLBMissM(DTLBMissM & ~PendingInterruptM),
.MemRWM, .PTE, .PageType, .ITLBWriteF, .DTLBWriteM,
.HPTWReadPTE(ReadDataM),
.DCacheStall, .HPTWAdr, .HPTWRead, .HPTWSize, .AnyCPUReqM);
// arbiter between IEU and hptw
// multiplex the outputs to LSU
mux2 #(2) rwmux(MemRWM, {HPTWRead, 1'b0}, SelHPTW, PreLsuRWM);
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LsuFunct3M);
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LsuAtomicM);
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, PreLsuAdrE);
mux2 #(`PA_BITS) lsupadrmux(IEUAdrExtM[`PA_BITS-1:0], HPTWAdr, SelHPTW, PreLsuPAdrM);
// arbiter between IEU and hptw
// multiplex the outputs to LSU
mux2 #(2) rwmux(MemRWM, {HPTWRead, 1'b0}, SelHPTW, PreLsuRWM);
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LsuFunct3M);
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LsuAtomicM);
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, PreLsuAdrE);
mux2 #(`PA_BITS) lsupadrmux(IEUAdrExtM[`PA_BITS-1:0], HPTWAdr, SelHPTW, PreLsuPAdrM);
// always block interrupts when using the hardware page table walker.
assign CPUBusy = StallW & ~SelHPTW;
// It is not possible to pipeline hptw as the following load will depend on the previous load's
// data. Therefore we don't need a pipeline register
//flop #(`PA_BITS) HPTWAdrMReg(clk, HPTWAdr, HPTWAdrM); // delay HPTWAdrM by a cycle
// always block interrupts when using the hardware page table walker.
assign CPUBusy = StallW & ~SelHPTW;
// It is not possible to pipeline hptw as the following load will depend on the previous load's
// data. Therefore we don't need a pipeline register
//flop #(`PA_BITS) HPTWAdrMReg(clk, HPTWAdr, HPTWAdrM); // delay HPTWAdrM by a cycle
// Specify which type of page fault is occurring
assign DTLBLoadPageFaultM = DTLBPageFaultM & PreLsuRWM[1];
assign DTLBStorePageFaultM = DTLBPageFaultM & PreLsuRWM[0];
// Specify which type of page fault is occurring
assign DTLBLoadPageFaultM = DTLBPageFaultM & PreLsuRWM[1];
assign DTLBStorePageFaultM = DTLBPageFaultM & PreLsuRWM[0];
// When replaying CPU memory request after PTW select the IEUAdrM for correct address.
assign LsuAdrE = SelReplayCPURequest ? IEUAdrM[11:0] : PreLsuAdrE;
// When replaying CPU memory request after PTW select the IEUAdrM for correct address.
assign LsuAdrE = SelReplayCPURequest ? IEUAdrM[11:0] : PreLsuAdrE;
end // if (`MEM_VIRTMEM)
else begin
assign InterlockStall = 1'b0;
assign LsuAdrE = PreLsuAdrE;
assign SelHPTW = 1'b0;
assign IgnoreRequest = 1'b0;
end // if (`MEM_VIRTMEM)
else begin
assign InterlockStall = 1'b0;
assign LsuAdrE = PreLsuAdrE;
assign SelHPTW = 1'b0;
assign IgnoreRequest = 1'b0;
assign PTE = '0;
assign PageType = '0;
assign DTLBWriteM = 1'b0;
assign ITLBWriteF = 1'b0;
assign PreLsuRWM = MemRWM;
assign LsuFunct3M = Funct3M;
assign LsuAtomicM = AtomicM;
assign PreLsuAdrE = IEUAdrE[11:0];
assign PreLsuPAdrM = IEUAdrExtM;
assign CPUBusy = StallW;
assign DTLBLoadPageFaultM = 1'b0;
assign DTLBStorePageFaultM = 1'b0;
end
endgenerate
assign PTE = '0;
assign PageType = '0;
assign DTLBWriteM = 1'b0;
assign ITLBWriteF = 1'b0;
assign PreLsuRWM = MemRWM;
assign LsuFunct3M = Funct3M;
assign LsuAtomicM = AtomicM;
assign PreLsuAdrE = IEUAdrE[11:0];
assign PreLsuPAdrM = IEUAdrExtM;
assign CPUBusy = StallW;
assign DTLBLoadPageFaultM = 1'b0;
assign DTLBStorePageFaultM = 1'b0;
end
// **** look into this confusing signal.
// This signal is confusing. CommittedM tells the CPU's trap unit the current instruction
@ -200,72 +198,66 @@ module lsu
// to flush the memory operation at that time.
assign CommittedM = SelHPTW | DCacheCommittedM | BusCommittedM;
generate
if(`ZICSR_SUPPORTED == 1) begin : dmmu
logic DataMisalignedM;
if(`ZICSR_SUPPORTED == 1) begin : dmmu
logic DataMisalignedM;
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PrivilegeModeW, .DisableTranslation(SelHPTW),
.PAdr(PreLsuPAdrM),
.VAdr(IEUAdrM),
.Size(LsuFunct3M[1:0]),
.PTE,
.PageTypeWriteVal(PageType),
.TLBWrite(DTLBWriteM),
.TLBFlush(DTLBFlushM),
.PhysicalAddress(LsuPAdrM),
.TLBMiss(DTLBMissM),
.Cacheable(CacheableM),
.Idempotent(), .AtomicAllowed(),
.TLBPageFault(DTLBPageFaultM),
.InstrAccessFaultF(), .LoadAccessFaultM, .StoreAccessFaultM,
.AtomicAccessM(1'b0), .ExecuteAccessF(1'b0), /// atomicaccessm is probably a bug
.WriteAccessM(PreLsuRWM[0]), .ReadAccessM(PreLsuRWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW
); // *** the pma/pmp instruction access faults don't really matter here. is it possible to parameterize which outputs exist?
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PrivilegeModeW, .DisableTranslation(SelHPTW),
.PAdr(PreLsuPAdrM),
.VAdr(IEUAdrM),
.Size(LsuFunct3M[1:0]),
.PTE,
.PageTypeWriteVal(PageType),
.TLBWrite(DTLBWriteM),
.TLBFlush(DTLBFlushM),
.PhysicalAddress(LsuPAdrM),
.TLBMiss(DTLBMissM),
.Cacheable(CacheableM),
.Idempotent(), .AtomicAllowed(),
.TLBPageFault(DTLBPageFaultM),
.InstrAccessFaultF(), .LoadAccessFaultM, .StoreAccessFaultM,
.AtomicAccessM(1'b0), .ExecuteAccessF(1'b0), /// atomicaccessm is probably a bug
.WriteAccessM(PreLsuRWM[0]), .ReadAccessM(PreLsuRWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW
); // *** the pma/pmp instruction access faults don't really matter here. is it possible to parameterize which outputs exist?
// Determine if an Unaligned access is taking place
// hptw guarantees alignment, only check inputs from IEU.
always_comb
case(Funct3M[1:0])
2'b00: DataMisalignedM = 0; // lb, sb, lbu
2'b01: DataMisalignedM = IEUAdrM[0]; // lh, sh, lhu
2'b10: DataMisalignedM = IEUAdrM[1] | IEUAdrM[0]; // lw, sw, flw, fsw, lwu
2'b11: DataMisalignedM = |IEUAdrM[2:0]; // ld, sd, fld, fsd
endcase
// Determine if an Unaligned access is taking place
// hptw guarantees alignment, only check inputs from IEU.
always_comb
case(Funct3M[1:0])
2'b00: DataMisalignedM = 0; // lb, sb, lbu
2'b01: DataMisalignedM = IEUAdrM[0]; // lh, sh, lhu
2'b10: DataMisalignedM = IEUAdrM[1] | IEUAdrM[0]; // lw, sw, flw, fsw, lwu
2'b11: DataMisalignedM = |IEUAdrM[2:0]; // ld, sd, fld, fsd
endcase
// If the CPU's (not HPTW's) request is a page fault.
assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1];
assign StoreMisalignedFaultM = DataMisalignedM & MemRWM[0];
end else begin
assign LsuPAdrM = PreLsuPAdrM;
assign DTLBMissM = 0;
assign CacheableM = 1;
assign DTLBPageFaultM = 0;
assign LoadAccessFaultM = 0;
assign StoreAccessFaultM = 0;
assign LoadMisalignedFaultM = 0;
assign StoreMisalignedFaultM = 0;
end
endgenerate
// If the CPU's (not HPTW's) request is a page fault.
assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1];
assign StoreMisalignedFaultM = DataMisalignedM & MemRWM[0];
end else begin
assign LsuPAdrM = PreLsuPAdrM;
assign DTLBMissM = 0;
assign CacheableM = 1;
assign DTLBPageFaultM = 0;
assign LoadAccessFaultM = 0;
assign StoreAccessFaultM = 0;
assign LoadMisalignedFaultM = 0;
assign StoreMisalignedFaultM = 0;
end
assign LSUStall = DCacheStall | InterlockStall | BusStall;
// Move generate from lrsc to outside this module.
// use PreLsu as prefix for lrsc
generate
if (`A_SUPPORTED) begin:lrsc
assign MemReadM = PreLsuRWM[1] & ~(IgnoreRequest) & ~DTLBMissM;
lrsc lrsc(.clk, .reset, .FlushW, .CPUBusy, .MemReadM, .PreLsuRWM, .LsuAtomicM, .LsuPAdrM,
.SquashSCW, .LsuRWM);
end else begin:lrsc
assign SquashSCW = 0;
assign LsuRWM = PreLsuRWM;
end
endgenerate
if (`A_SUPPORTED) begin:lrsc
assign MemReadM = PreLsuRWM[1] & ~(IgnoreRequest) & ~DTLBMissM;
lrsc lrsc(.clk, .reset, .FlushW, .CPUBusy, .MemReadM, .PreLsuRWM, .LsuAtomicM, .LsuPAdrM,
.SquashSCW, .LsuRWM);
end else begin:lrsc
assign SquashSCW = 0;
assign LsuRWM = PreLsuRWM;
end
// conditional
@ -273,20 +265,20 @@ module lsu
// 2. cache `MEM_DCACHE
// 3. wire pass-through
localparam integer WORDSPERLINE = `MEM_DCACHE ? `DCACHE_BLOCKLENINBITS/`XLEN : 1;
localparam integer WORDSPERLINE = `MEM_DCACHE ? `DCACHE_LINELENINBITS/`XLEN : 1;
localparam integer LOGWPL = `MEM_DCACHE ? $clog2(WORDSPERLINE) : 1;
localparam integer BLOCKLEN = `MEM_DCACHE ? `DCACHE_BLOCKLENINBITS : `XLEN;
localparam integer LINELEN = `MEM_DCACHE ? `DCACHE_LINELENINBITS : `XLEN;
localparam integer WordCountThreshold = `MEM_DCACHE ? WORDSPERLINE - 1 : 0;
localparam integer BLOCKBYTELEN = BLOCKLEN/8;
localparam integer OFFSETLEN = $clog2(BLOCKBYTELEN);
localparam integer LINEBYTELEN = LINELEN/8;
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
// temp
logic [`XLEN-1:0] FinalAMOWriteDataM, FinalWriteDataM;
(* mark_debug = "true" *) logic [`XLEN-1:0] PreLsuBusHWDATA;
logic [`XLEN-1:0] ReadDataWordM;
logic [BLOCKLEN-1:0] DCacheMemWriteData;
logic [LINELEN-1:0] DCacheMemWriteData;
// keep
logic [`XLEN-1:0] ReadDataWordMuxM;
@ -294,7 +286,7 @@ module lsu
logic [`PA_BITS-1:0] DCacheBusAdr;
logic [`XLEN-1:0] ReadDataBlockSetsM [WORDSPERLINE-1:0];
logic [`XLEN-1:0] ReadDataLineSetsM [WORDSPERLINE-1:0];
@ -304,27 +296,28 @@ module lsu
logic SelUncachedAdr;
generate
if(`MEM_DCACHE) begin : dcache
dcache dcache(.clk, .reset, .CPUBusy,
.LsuRWM, .FlushDCacheM, .LsuAtomicM, .LsuAdrE, .LsuPAdrM, .PreLsuPAdrM(PreLsuPAdrM[11:0]), // still don't like this name PreLsuPAdrM, not always physical
.FinalWriteDataM, .ReadDataWordM, .DCacheStall,
.DCacheMiss, .DCacheAccess,
.IgnoreRequest, .CacheableM, .DCacheCommittedM,
.DCacheBusAdr, .ReadDataBlockSetsM, .DCacheMemWriteData,
.DCacheFetchLine, .DCacheWriteLine,.DCacheBusAck);
end else begin : passthrough
assign ReadDataWordM = 0;
assign DCacheStall = 0;
assign DCacheMiss = 1;
assign DCacheAccess = CacheableM;
assign DCacheCommittedM = 0;
assign DCacheWriteLine = 0;
assign DCacheFetchLine = 0;
assign DCacheBusAdr = 0;
assign ReadDataBlockSetsM[0] = 0;
end
endgenerate
if(`MEM_DCACHE) begin : dcache
cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(`DCACHE_NUMWAYS), .DCACHE(1))
dcache(.clk, .reset, .CPUBusy,
.RW(CacheableM ? LsuRWM : 2'b00), .FlushCache(FlushDCacheM), .Atomic(CacheableM ? LsuAtomicM : 2'b00),
.LsuAdrE, .LsuPAdrM, .PreLsuPAdrM(PreLsuPAdrM[11:0]), // still don't like this name PreLsuPAdrM, not always physical
.FinalWriteData(FinalWriteDataM), .ReadDataWord(ReadDataWordM), .CacheStall(DCacheStall),
.CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
.IgnoreRequest, .CacheCommitted(DCacheCommittedM),
.CacheBusAdr(DCacheBusAdr), .ReadDataLineSets(ReadDataLineSetsM), .CacheMemWriteData(DCacheMemWriteData),
.CacheFetchLine(DCacheFetchLine), .CacheWriteLine(DCacheWriteLine), .CacheBusAck(DCacheBusAck), .InvalidateCacheM(1'b0));
end else begin : passthrough
assign ReadDataWordM = 0;
assign DCacheStall = 0;
assign DCacheMiss = 1;
assign DCacheAccess = CacheableM;
assign DCacheCommittedM = 0;
assign DCacheWriteLine = 0;
assign DCacheFetchLine = 0;
assign DCacheBusAdr = 0;
assign ReadDataLineSetsM[0] = 0;
end
// select between dcache and direct from the BUS. Always selected if no dcache.
@ -340,15 +333,13 @@ module lsu
.Funct3M(LsuFunct3M),
.ReadDataM);
generate
if (`A_SUPPORTED) begin : amo
logic [`XLEN-1:0] AMOResult;
amoalu amoalu(.srca(ReadDataM), .srcb(WriteDataM), .funct(Funct7M), .width(LsuFunct3M[1:0]),
.result(AMOResult));
mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, LsuAtomicM[1], FinalAMOWriteDataM);
end else
assign FinalAMOWriteDataM = WriteDataM;
endgenerate
if (`A_SUPPORTED) begin : amo
logic [`XLEN-1:0] AMOResult;
amoalu amoalu(.srca(ReadDataM), .srcb(WriteDataM), .funct(Funct7M), .width(LsuFunct3M[1:0]),
.result(AMOResult));
mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, LsuAtomicM[1], FinalAMOWriteDataM);
end else
assign FinalAMOWriteDataM = WriteDataM;
// this might only get instantiated if there is a dcache or dtim.
// There is a copy in the ebu.
@ -365,24 +356,20 @@ module lsu
logic [LOGWPL-1:0] WordCount;
genvar index;
generate
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
flopen #(`XLEN) fb(.clk(clk),
.en(LsuBusAck & LsuBusRead & (index == WordCount)),
.d(LsuBusHRDATA),
.q(DCacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
end
endgenerate
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
flopen #(`XLEN) fb(.clk,
.en(LsuBusAck & LsuBusRead & (index == WordCount)),
.d(LsuBusHRDATA),
.q(DCacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
end
assign LocalLsuBusAdr = SelUncachedAdr ? LsuPAdrM : DCacheBusAdr ;
assign LsuBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalLsuBusAdr;
assign PreLsuBusHWDATA = ReadDataBlockSetsM[WordCount];
assign PreLsuBusHWDATA = ReadDataLineSetsM[WordCount];
assign LsuBusHWDATA = SelUncachedAdr ? WriteDataM : PreLsuBusHWDATA; // *** why is this not FinalWriteDataM? which does not work.
generate
if (`XLEN == 32) assign LsuBusSize = SelUncachedAdr ? LsuFunct3M : 3'b010;
else assign LsuBusSize = SelUncachedAdr ? LsuFunct3M : 3'b011;
endgenerate;
if (`XLEN == 32) assign LsuBusSize = SelUncachedAdr ? LsuFunct3M : 3'b010;
else assign LsuBusSize = SelUncachedAdr ? LsuFunct3M : 3'b011;
busfsm #(WordCountThreshold, LOGWPL, `MEM_DCACHE)
busfsm(.clk, .reset, .IgnoreRequest, .LsuRWM, .DCacheFetchLine, .DCacheWriteLine,

View File

@ -38,77 +38,75 @@ module subwordread
// Funct3M[2] is the unsigned bit. mask upper bits.
// Funct3M[1:0] is the size of the memory access.
generate
if (`XLEN == 64) begin:swrmux
// ByteMe mux
always_comb
case(LsuPAdrM[2:0])
3'b000: ByteM = ReadDataWordMuxM[7:0];
3'b001: ByteM = ReadDataWordMuxM[15:8];
3'b010: ByteM = ReadDataWordMuxM[23:16];
3'b011: ByteM = ReadDataWordMuxM[31:24];
3'b100: ByteM = ReadDataWordMuxM[39:32];
3'b101: ByteM = ReadDataWordMuxM[47:40];
3'b110: ByteM = ReadDataWordMuxM[55:48];
3'b111: ByteM = ReadDataWordMuxM[63:56];
endcase
if (`XLEN == 64) begin:swrmux
// ByteMe mux
always_comb
case(LsuPAdrM[2:0])
3'b000: ByteM = ReadDataWordMuxM[7:0];
3'b001: ByteM = ReadDataWordMuxM[15:8];
3'b010: ByteM = ReadDataWordMuxM[23:16];
3'b011: ByteM = ReadDataWordMuxM[31:24];
3'b100: ByteM = ReadDataWordMuxM[39:32];
3'b101: ByteM = ReadDataWordMuxM[47:40];
3'b110: ByteM = ReadDataWordMuxM[55:48];
3'b111: ByteM = ReadDataWordMuxM[63:56];
endcase
// halfword mux
always_comb
case(LsuPAdrM[2:1])
2'b00: HalfwordM = ReadDataWordMuxM[15:0];
2'b01: HalfwordM = ReadDataWordMuxM[31:16];
2'b10: HalfwordM = ReadDataWordMuxM[47:32];
2'b11: HalfwordM = ReadDataWordMuxM[63:48];
endcase
// halfword mux
always_comb
case(LsuPAdrM[2:1])
2'b00: HalfwordM = ReadDataWordMuxM[15:0];
2'b01: HalfwordM = ReadDataWordMuxM[31:16];
2'b10: HalfwordM = ReadDataWordMuxM[47:32];
2'b11: HalfwordM = ReadDataWordMuxM[63:48];
endcase
logic [31:0] WordM;
always_comb
case(LsuPAdrM[2])
1'b0: WordM = ReadDataWordMuxM[31:0];
1'b1: WordM = ReadDataWordMuxM[63:32];
endcase
// sign extension
always_comb
case(Funct3M)
3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb
3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw
3'b011: ReadDataM = ReadDataWordMuxM; // ld
3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu
3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
endcase
end else begin :swrmux // 32-bit
// byte mux
always_comb
case(LsuPAdrM[1:0])
2'b00: ByteM = ReadDataWordMuxM[7:0];
2'b01: ByteM = ReadDataWordMuxM[15:8];
2'b10: ByteM = ReadDataWordMuxM[23:16];
2'b11: ByteM = ReadDataWordMuxM[31:24];
endcase
logic [31:0] WordM;
// halfword mux
always_comb
case(LsuPAdrM[1])
1'b0: HalfwordM = ReadDataWordMuxM[15:0];
1'b1: HalfwordM = ReadDataWordMuxM[31:16];
always_comb
case(LsuPAdrM[2])
1'b0: WordM = ReadDataWordMuxM[31:0];
1'b1: WordM = ReadDataWordMuxM[63:32];
endcase
// sign extension
always_comb
case(Funct3M)
3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb
3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: ReadDataM = ReadDataWordMuxM; // lw
3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu
default: ReadDataM = ReadDataWordMuxM;
endcase
end
endgenerate
// sign extension
always_comb
case(Funct3M)
3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb
3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw
3'b011: ReadDataM = ReadDataWordMuxM; // ld
3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu
3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
endcase
end else begin:swrmux // 32-bit
// byte mux
always_comb
case(LsuPAdrM[1:0])
2'b00: ByteM = ReadDataWordMuxM[7:0];
2'b01: ByteM = ReadDataWordMuxM[15:8];
2'b10: ByteM = ReadDataWordMuxM[23:16];
2'b11: ByteM = ReadDataWordMuxM[31:24];
endcase
// halfword mux
always_comb
case(LsuPAdrM[1])
1'b0: HalfwordM = ReadDataWordMuxM[15:0];
1'b1: HalfwordM = ReadDataWordMuxM[31:16];
endcase
// sign extension
always_comb
case(Funct3M)
3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb
3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: ReadDataM = ReadDataWordMuxM; // lw
3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu
default: ReadDataM = ReadDataWordMuxM;
endcase
end
endmodule

View File

@ -52,7 +52,7 @@ module hptw
L1_ADR, L1_RD,
L2_ADR, L2_RD,
L3_ADR, L3_RD,
LEAF, IDLE} statetype; // *** placed outside generate statement to remove synthesis errors
LEAF, IDLE} statetype;
logic DTLBWalk; // register TLBs translation miss requests
logic [`PPN_BITS-1:0] BasePageTablePPN;

View File

@ -90,27 +90,25 @@ module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries
// only instantiate TLB if Virtual Memory is supported
generate
if (`MEM_VIRTMEM) begin:tlb
logic ReadAccess, WriteAccess;
assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages
assign WriteAccess = WriteAccessM;
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU))
tlb(.clk, .reset,
.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]),
.SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]),
.VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PrivilegeModeW, .ReadAccess, .WriteAccess,
.DisableTranslation, .PTE, .PageTypeWriteVal,
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
.Translate, .TLBPageFault);
end else begin:tlb// just pass address through as physical
assign Translate = 0;
assign TLBMiss = 0;
assign TLBHit = 1; // *** is this necessary
assign TLBPageFault = 0;
end
endgenerate
if (`MEM_VIRTMEM) begin:tlb
logic ReadAccess, WriteAccess;
assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages
assign WriteAccess = WriteAccessM;
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU))
tlb(.clk, .reset,
.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]),
.SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]),
.VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PrivilegeModeW, .ReadAccess, .WriteAccess,
.DisableTranslation, .PTE, .PageTypeWriteVal,
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
.Translate, .TLBPageFault);
end else begin:tlb// just pass address through as physical
assign Translate = 0;
assign TLBMiss = 0;
assign TLBHit = 1; // *** is this necessary
assign TLBPageFault = 0;
end
// If translation is occuring, select translated physical address from TLB
mux2 #(`PA_BITS) addressmux(PAdr, TLBPAdr, Translate, PhysicalAddress);

View File

@ -68,7 +68,7 @@ module pmpadrdec (
assign NAMask[1:0] = {2'b11};
assign NAMask[`PA_BITS-1:2] = (PMPAdr[`PA_BITS-3:0] + {{(`PA_BITS-3){1'b0}}, (AdrMode == NAPOT)}) ^ PMPAdr[`PA_BITS-3:0];
// generates a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region.
// form a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region.
// This assumes we're using at least an NA4 region, but works for any size NAPOT region.
assign NABase = {(PMPAdr[`PA_BITS-3:0] & ~NAMask[`PA_BITS-1:2]), 2'b00}; // base physical address of the pmp.

View File

@ -47,37 +47,34 @@ module pmpchecker (
output logic PMPStoreAccessFaultM
);
generate
if (`PMP_ENTRIES > 0) begin: pmpchecker
// Bit i is high when the address falls in PMP region i
logic EnforcePMP;
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
.PhysicalAddress,
.PMPCfg(PMPCFG_ARRAY_REGW),
.PMPAdr(PMPADDR_ARRAY_REGW),
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
.PAgePMPAdrOut(PAgePMPAdr),
.FirstMatch, .Match, .Active, .L, .X, .W, .R);
if (`PMP_ENTRIES > 0) begin: pmpchecker
// Bit i is high when the address falls in PMP region i
logic EnforcePMP;
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
.PhysicalAddress,
.PMPCfg(PMPCFG_ARRAY_REGW),
.PMPAdr(PMPADDR_ARRAY_REGW),
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
.PAgePMPAdrOut(PAgePMPAdr),
.FirstMatch, .Match, .Active, .L, .X, .W, .R);
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active;
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X;
assign PMPStoreAccessFaultM = EnforcePMP & WriteAccessM & ~|W;
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R;
end else begin: pmpchecker // no checker
assign PMPInstrAccessFaultF = 0;
assign PMPLoadAccessFaultM = 0;
assign PMPStoreAccessFaultM = 0;
end
endgenerate
//assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM;
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active;
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X;
assign PMPStoreAccessFaultM = EnforcePMP & WriteAccessM & ~|W;
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R;
end else begin: pmpchecker // no checker
assign PMPInstrAccessFaultF = 0;
assign PMPLoadAccessFaultM = 0;
assign PMPStoreAccessFaultM = 0;
end
endmodule

View File

@ -34,25 +34,9 @@ module priorityonehot #(parameter ENTRIES = 8) (
input logic [ENTRIES-1:0] a,
output logic [ENTRIES-1:0] y
);
/* verilator lint_off UNOPTFLAT */
logic [ENTRIES-1:0] nolower;
// generate thermometer code mask
// create thermometer code mask
prioritythermometer #(ENTRIES) maskgen(.a({a[ENTRIES-2:0], 1'b1}), .y(nolower));
// genvar i;
// generate
// assign nolower[0] = 1'b1;
// for (i=1; i<ENTRIES; i++) begin:therm
// assign nolower[i] = nolower[i-1] & ~a[i-1];
// end
// endgenerate
// *** replace mask generation logic ^^^ with priority thermometer
assign y = a & nolower;
/* verilator lint_on UNOPTFLAT */
endmodule

View File

@ -37,20 +37,15 @@ module prioritythermometer #(parameter N = 8) (
output logic [N-1:0] y
);
// Carefully crafted so design compiler would synthesize into a fast tree structure
// Carefully crafted so design compiler will synthesize into a fast tree structure
// Rather than linear.
// generate thermometer code mask
// create thermometer code mask
genvar i;
generate
assign y[0] = a[0];
for (i=1; i<N; i++) begin:therm
assign y[i] = y[i-1] & ~a[i]; // *** made to be the same as onehot (without the inverter) to see if the probelme is something weird with synthesis
// assign y[i] = y[i-1] & a[i];
end
endgenerate
assign y[0] = a[0];
for (i=1; i<N; i++) begin:therm
assign y[i] = y[i-1] & ~a[i];
end
endmodule

View File

@ -60,38 +60,36 @@ module tlbcamline #(parameter KEY_BITS = 20,
assign MatchASID = (SATP_ASID == Key_ASID) | PTE_G;
generate
if (`XLEN == 32) begin:match
if (`XLEN == 32) begin: match
assign {Key_ASID, Key1, Key0} = Key;
assign {Query1, Query0} = VPN;
assign {Key_ASID, Key1, Key0} = Key;
assign {Query1, Query0} = VPN;
// Calculate the actual match value based on the input vpn and the page type.
// For example, a megapage in SV32 only cares about VPN[1], so VPN[0]
// should automatically match.
assign Match0 = (Query0 == Key0) | (PageType[0]); // least signifcant section
assign Match1 = (Query1 == Key1);
// Calculate the actual match value based on the input vpn and the page type.
// For example, a megapage in SV32 only cares about VPN[1], so VPN[0]
// should automatically match.
assign Match0 = (Query0 == Key0) | (PageType[0]); // least signifcant section
assign Match1 = (Query1 == Key1);
assign Match = Match0 & Match1 & MatchASID & Valid;
end else begin:match
assign Match = Match0 & Match1 & MatchASID & Valid;
end else begin: match
logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3;
logic Match2, Match3;
logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3;
logic Match2, Match3;
assign {Query3, Query2, Query1, Query0} = VPN;
assign {Key_ASID, Key3, Key2, Key1, Key0} = Key;
assign {Query3, Query2, Query1, Query0} = VPN;
assign {Key_ASID, Key3, Key2, Key1, Key0} = Key;
// Calculate the actual match value based on the input vpn and the page type.
// For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1]
// should automatically match.
assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section
assign Match1 = (Query1 == Key1) | (PageType > 2'd1);
assign Match2 = (Query2 == Key2) | (PageType > 2'd2);
assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used
assign Match = Match0 & Match1 & Match2 & Match3 & MatchASID & Valid;
end
endgenerate
// Calculate the actual match value based on the input vpn and the page type.
// For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1]
// should automatically match.
assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section
assign Match1 = (Query1 == Key1) | (PageType > 2'd1);
assign Match2 = (Query2 == Key2) | (PageType > 2'd2);
assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used
assign Match = Match0 & Match1 & Match2 & Match3 & MatchASID & Valid;
end
// On a write, update the type of the page referred to by this line.
flopenr #(2) pagetypeflop(clk, reset, WriteEnable, PageTypeWriteVal, PageType);

View File

@ -60,65 +60,59 @@ module tlbcontrol #(parameter ITLB = 0) (
logic UpperBitsUnequalPageFault;
logic DAPageFault;
logic TLBAccess;
logic ImproperPrivilege;
// Grab the sv mode from SATP and determine whether translation should occur
assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1
assign Translate = (SATP_MODE != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~DisableTranslation;
generate
if (`XLEN==64) begin:rv64
assign SV39Mode = (SATP_MODE == `SV39);
// generate page fault if upper bits aren't all the same
logic UpperEqual39, UpperEqual48;
assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]);
assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48;
end else begin
assign SV39Mode = 0;
assign UpperBitsUnequalPageFault = 0;
end
endgenerate
if (`XLEN==64) begin:rv64
assign SV39Mode = (SATP_MODE == `SV39);
// page fault if upper bits aren't all the same
logic UpperEqual39, UpperEqual48;
assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]);
assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48;
end else begin
assign SV39Mode = 0;
assign UpperBitsUnequalPageFault = 0;
end
// Determine whether TLB is being used
assign TLBAccess = ReadAccess | WriteAccess;
// Check whether upper bits of virtual addresss are all equal
// unswizzle useful PTE bits
assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0];
// Check whether the access is allowed, page faulting if not.
generate
if (ITLB == 1) begin:itlb // Instruction TLB fault checking
logic ImproperPrivilege;
if (ITLB == 1) begin:itlb // Instruction TLB fault checking
// User mode may only execute user mode pages, and supervisor mode may
// only execute non-user mode pages.
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U);
// fault for software handling if access bit is off
assign DAPageFault = ~PTE_A;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
end else begin:dtlb // Data TLB fault checking
logic InvalidRead, InvalidWrite;
// User mode may only execute user mode pages, and supervisor mode may
// only execute non-user mode pages.
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U);
// fault for software handling if access bit is off
assign DAPageFault = ~PTE_A;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
end else begin:dtlb // Data TLB fault checking
logic ImproperPrivilege, InvalidRead, InvalidWrite;
// User mode may only load/store from user mode pages, and supervisor mode
// may only access user mode pages when STATUS_SUM is low.
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U & ~STATUS_SUM);
// Check for read error. Reads are invalid when the page is not readable
// (and executable pages are not readable) or when the page is neither
// readable nor executable (and executable pages are readable).
assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X);
// Check for write error. Writes are invalid when the page's write bit is
// low.
assign InvalidWrite = WriteAccess & ~PTE_W;
// Fault for software handling if access bit is off or writing a page with dirty bit off
assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
end
endgenerate
// User mode may only load/store from user mode pages, and supervisor mode
// may only access user mode pages when STATUS_SUM is low.
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U & ~STATUS_SUM);
// Check for read error. Reads are invalid when the page is not readable
// (and executable pages are not readable) or when the page is neither
// readable nor executable (and executable pages are readable).
assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X);
// Check for write error. Writes are invalid when the page's write bit is
// low.
assign InvalidWrite = WriteAccess & ~PTE_W;
// Fault for software handling if access bit is off or writing a page with dirty bit off
assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
end
assign TLBHit = CAMHit & TLBAccess;
assign TLBMiss = (~CAMHit | TLBFlush) & Translate & TLBAccess;

View File

@ -43,18 +43,16 @@ module tlbmixer (
logic [`PPN_BITS-1:0] PPNMixed;
// produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages
generate
if (`XLEN == 32)
// kilopage: 22 bits of PPN, 0 bits of VPN
// megapage: 12 bits of PPN, 10 bits of VPN
mux2 #(22) pnm(22'h000000, 22'h0003FF, HitPageType[0], PageNumberMask);
else
// kilopage: 44 bits of PPN, 0 bits of VPN
// megapage: 35 bits of PPN, 9 bits of VPN
// gigapage: 26 bits of PPN, 18 bits of VPN
// terapage: 17 bits of PPN, 27 bits of VPN
mux4 #(44) pnm(44'h00000000000, 44'h000000001FF, 44'h0000003FFFF, 44'h00007FFFFFF, HitPageType, PageNumberMask);
endgenerate
if (`XLEN == 32)
// kilopage: 22 bits of PPN, 0 bits of VPN
// megapage: 12 bits of PPN, 10 bits of VPN
mux2 #(22) pnm(22'h000000, 22'h0003FF, HitPageType[0], PageNumberMask);
else
// kilopage: 44 bits of PPN, 0 bits of VPN
// megapage: 35 bits of PPN, 9 bits of VPN
// gigapage: 26 bits of PPN, 18 bits of VPN
// terapage: 17 bits of PPN, 27 bits of VPN
mux4 #(44) pnm(44'h00000000000, 44'h000000001FF, 44'h0000003FFFF, 44'h00007FFFFFF, HitPageType, PageNumberMask);
// merge low segments of VPN with high segments of PPN decided by the pagetype.
assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN.

File diff suppressed because it is too large Load Diff

View File

@ -60,15 +60,13 @@ module intdivrestoring (
assign DivBusyE = (state == BUSY) | DivStartE;
// Handle sign extension for W-type instructions
generate
if (`XLEN == 64) begin:rv64 // RV64 has W-type instructions
mux2 #(`XLEN) xinmux(ForwardedSrcAE, {ForwardedSrcAE[31:0], 32'b0}, W64E, XinE);
mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE);
end else begin // RV32 has no W-type instructions
assign XinE = ForwardedSrcAE;
assign DinE = ForwardedSrcBE;
if (`XLEN == 64) begin:rv64 // RV64 has W-type instructions
mux2 #(`XLEN) xinmux(ForwardedSrcAE, {ForwardedSrcAE[31:0], 32'b0}, W64E, XinE);
mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE);
end else begin // RV32 has no W-type instructions
assign XinE = ForwardedSrcAE;
assign DinE = ForwardedSrcBE;
end
endgenerate
// Extract sign bits and check fo division by zero
assign SignDE = DivSignedE & DinE[`XLEN-1];
@ -97,11 +95,9 @@ module intdivrestoring (
flopen #(3) Div0eMReg(clk, DivStartE, {Div0E, NegQE, SignXE}, {Div0M, NegQM, NegWM});
// one copy of divstep for each bit produced per cycle
generate
genvar i;
for (i=0; i<`DIV_BITSPERCYCLE; i = i+1)
intdivrestoringstep divstep(WM[i], XQM[i], DAbsBM, WM[i+1], XQM[i+1]);
endgenerate
genvar i;
for (i=0; i<`DIV_BITSPERCYCLE; i = i+1)
intdivrestoringstep divstep(WM[i], XQM[i], DAbsBM, WM[i+1], XQM[i+1]);
// On final setp of signed operations, negate outputs as needed to get correct sign
neg #(`XLEN) qneg(XQM[0], XQnM);

View File

@ -49,8 +49,8 @@ module mul (
// 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*2-1:0] PP0E, PP1E, PP2E, PP3E, PP4E;
logic [`XLEN*2-1:0] PP0M, PP1M, PP2M, PP3M, PP4M;
logic [`XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E;
logic [`XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M;
logic [`XLEN-2:0] PA, PB;
logic PP;
logic MULH, MULHSU;
@ -62,7 +62,7 @@ module mul (
assign Aprime = {1'b0, ForwardedSrcAE[`XLEN-2:0]};
assign Bprime = {1'b0, ForwardedSrcBE[`XLEN-2:0]};
redundantmul #(`XLEN) bigmul(.a(Aprime), .b(Bprime), .out0(PP0E), .out1(PP1E));
assign PP1E = Aprime * Bprime;
assign PA = {(`XLEN-1){ForwardedSrcAE[`XLEN-1]}} & ForwardedSrcBE[`XLEN-2:0];
assign PB = {(`XLEN-1){ForwardedSrcBE[`XLEN-1]}} & ForwardedSrcAE[`XLEN-2:0];
assign PP = ForwardedSrcAE[`XLEN-1] & ForwardedSrcBE[`XLEN-1];
@ -83,12 +83,11 @@ module mul (
// Memory Stage: Sum partial proudcts
//////////////////////////////
flopenrc #(`XLEN*2) PP0Reg(clk, reset, FlushM, ~StallM, PP0E, PP0M);
flopenrc #(`XLEN*2) PP1Reg(clk, reset, FlushM, ~StallM, PP1E, PP1M);
flopenrc #(`XLEN*2) PP2Reg(clk, reset, FlushM, ~StallM, PP2E, PP2M);
flopenrc #(`XLEN*2) PP3Reg(clk, reset, FlushM, ~StallM, PP3E, PP3M);
flopenrc #(`XLEN*2) PP4Reg(clk, reset, FlushM, ~StallM, PP4E, PP4M);
assign ProdM = PP0M + PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
endmodule

View File

@ -74,13 +74,11 @@ module muldiv (
// Handle sign extension for W-type instructions
flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M);
generate
if (`XLEN == 64) begin:resmux // RV64 has W-type instructions
assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
end else begin:resmux // RV32 has no W-type instructions
assign MulDivResultM = PrelimResultM;
end
endgenerate
if (`XLEN == 64) begin:resmux // RV64 has W-type instructions
assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
end else begin:resmux // RV32 has no W-type instructions
assign MulDivResultM = PrelimResultM;
end
// Writeback stage pipeline register
flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);

View File

@ -56,111 +56,109 @@ module csrc #(parameter
output logic IllegalCSRCAccessM
);
generate
if (`ZICOUNTERS_SUPPORTED) begin:counters
(* mark_debug = "true" *) logic [63:0] CYCLE_REGW, INSTRET_REGW;
logic [63:0] CYCLEPlusM, INSTRETPlusM;
logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM;
logic WriteCYCLEM, WriteINSTRETM;
logic [4:0] CounterNumM;
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
logic InstrValidNotFlushedM;
logic LoadStallE, LoadStallM;
logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
logic [`COUNTERS-1:0] CounterEvent;
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0];
genvar i;
if (`ZICOUNTERS_SUPPORTED) begin:counters
(* mark_debug = "true" *) logic [63:0] CYCLE_REGW, INSTRET_REGW;
logic [63:0] CYCLEPlusM, INSTRETPlusM;
logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM;
logic WriteCYCLEM, WriteINSTRETM;
logic [4:0] CounterNumM;
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
logic InstrValidNotFlushedM;
logic LoadStallE, LoadStallM;
logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
logic [`COUNTERS-1:0] CounterEvent;
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0];
genvar i;
// Interface signals
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall.
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
// Determine when to increment each counter
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist
assign CounterEvent[2] = InstrValidNotFlushedM;
if(`QEMU) begin // No other performance counters in QEMU
assign CounterEvent[`COUNTERS-1:3] = 0;
end else begin // User-defined counters
assign CounterEvent[3] = LoadStallM; // don't want to suppress on flush as this only happens if flushed.
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM;
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM;
assign CounterEvent[11] = DCacheAccess;
assign CounterEvent[12] = DCacheMiss;
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
end
// Counter update and write logic
for (i = 0; i < `COUNTERS; i = i+1) begin
assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i);
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0;
else HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
if (`XLEN==32) begin // write high and low separately
logic [`COUNTERS-1:0] WriteHPMCOUNTERHM;
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0];
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i);
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0;
else HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
end else begin // XLEN=64; write entire register
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
end
end
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
always_comb
if (PrivilegeModeW == `M_MODE |
MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0;
if (`XLEN==64) begin // 64-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=64
/* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`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
/* 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];
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
end
end
end else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // no privileges for this csr
end
end else begin
assign CSRCReadValM = 0;
assign IllegalCSRCAccessM = 1; // counters aren't enabled
// Interface signals
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall.
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
// Determine when to increment each counter
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist
assign CounterEvent[2] = InstrValidNotFlushedM;
if(`QEMU) begin: cevent // No other performance counters in QEMU
assign CounterEvent[`COUNTERS-1:3] = 0;
end else begin: cevent // User-defined counters
assign CounterEvent[3] = LoadStallM; // don't want to suppress on flush as this only happens if flushed.
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM;
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM;
assign CounterEvent[11] = DCacheAccess;
assign CounterEvent[12] = DCacheMiss;
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
end
endgenerate
// Counter update and write logic
for (i = 0; i < `COUNTERS; i = i+1) begin:cntr
assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i);
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0;
else HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
if (`XLEN==32) begin // write high and low separately
logic [`COUNTERS-1:0] WriteHPMCOUNTERHM;
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0];
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i);
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0;
else HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
end else begin // XLEN=64; write entire register
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
end
end
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
always_comb
if (PrivilegeModeW == `M_MODE |
MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0;
if (`XLEN==64) begin // 64-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=64
/* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`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
/* 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];
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
end
end
end else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // no privileges for this csr
end
end else begin
assign CSRCReadValM = 0;
assign IllegalCSRCAccessM = 1; // counters aren't enabled
end
endmodule
// To Do:

View File

@ -66,58 +66,54 @@ module csri #(parameter
assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP) & ~StallW;
assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE) & ~StallW;
// Interrupt Pending and Enable Registers
// MEIP, MTIP, MSIP are read-only
// SEIP, STIP, SSIP is writable in MIP if S mode exists
// SSIP is writable in SIP if S mode exists
generate
if (`S_SUPPORTED) begin:mask
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writable in MIP (20210108-draft 3.1.9)
assign SIP_WRITE_MASK = 12'h002; // SSIP is writable in SIP (privileged 20210108-draft 4.1.3)
end else begin:mask
assign MIP_WRITE_MASK = 12'h000;
assign SIP_WRITE_MASK = 12'h000;
end
always @(posedge clk) //, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21
if (reset) IP_REGW_writeable <= 10'b0;
else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
// Interrupt Pending and Enable Registers
// MEIP, MTIP, MSIP are read-only
// SEIP, STIP, SSIP is writable in MIP if S mode exists
// SSIP is writable in SIP if S mode exists
if (`S_SUPPORTED) begin:mask
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writable in MIP (20210108-draft 3.1.9)
assign SIP_WRITE_MASK = 12'h002; // SSIP is writable in SIP (privileged 20210108-draft 4.1.3)
end else begin:mask
assign MIP_WRITE_MASK = 12'h000;
assign SIP_WRITE_MASK = 12'h000;
end
always @(posedge clk) //, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21
if (reset) IP_REGW_writeable <= 10'b0;
else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
// else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable
else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
always @(posedge clk) //, posedge reset) begin
if (reset) IE_REGW <= 12'b0;
else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields
else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields
else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
always @(posedge clk) //, posedge reset) begin
if (reset) IE_REGW <= 12'b0;
else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields
else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields
// else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field
endgenerate
// restricted views of registers
generate
always_comb begin:regs
// Add MEIP read-only signal
IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable};
always_comb begin:regs
// Add MEIP read-only signal
IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable};
// Machine Mode
MIP_REGW = IP_REGW;
MIE_REGW = IE_REGW;
// Machine Mode
MIP_REGW = IP_REGW;
MIE_REGW = IE_REGW;
// Supervisor mode
if (`S_SUPPORTED) begin
SIP_REGW = IP_REGW & MIDELEG_REGW[11:0] & 'h222; // only delegated interrupts visible
SIE_REGW = IE_REGW & MIDELEG_REGW[11:0] & 'h222;
end else begin
SIP_REGW = 12'b0;
SIE_REGW = 12'b0;
end
// User Modes iterrupts depricated
/*if (`U_SUPPORTED & `N_SUPPORTED) begin
UIP_REGW = IP_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
UIE_REGW = IE_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
end else begin
UIP_REGW = 12'b0;
UIE_REGW = 12'b0;
end */
// Supervisor mode
if (`S_SUPPORTED) begin
SIP_REGW = IP_REGW & MIDELEG_REGW[11:0] & 'h222; // only delegated interrupts visible
SIE_REGW = IE_REGW & MIDELEG_REGW[11:0] & 'h222;
end else begin
SIP_REGW = 12'b0;
SIE_REGW = 12'b0;
end
endgenerate
// User Modes iterrupts depricated
/*if (`U_SUPPORTED & `N_SUPPORTED) begin
UIP_REGW = IP_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
UIE_REGW = IE_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
end else begin
UIP_REGW = 12'b0;
UIE_REGW = 12'b0;
end */
end
endmodule

View File

@ -92,32 +92,30 @@ module csrm #(parameter
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
genvar i;
generate
if (`PMP_ENTRIES > 0) begin:pmp
logic [`PMP_ENTRIES-1:0] WritePMPCFGM;
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ;
logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
for(i=0; i<`PMP_ENTRIES; i++) begin
// when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR
// also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR
assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7];
if (i == `PMP_ENTRIES-1)
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7];
else
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i];
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
if (`XLEN==64) begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
end else begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
end
if (`PMP_ENTRIES > 0) begin:pmp
logic [`PMP_ENTRIES-1:0] WritePMPCFGM;
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ;
logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
for(i=0; i<`PMP_ENTRIES; i++) begin
// when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR
// also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR
assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7];
if (i == `PMP_ENTRIES-1)
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7];
else
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i];
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
if (`XLEN==64) begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
end else begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
end
end
endgenerate
end
localparam MISA_26 = (`MISA) & 32'h03ffffff;
@ -143,28 +141,24 @@ module csrm #(parameter
// CSRs
flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); //busybear: changed reset value to 0
generate
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin:deleg // DELEG registers should exist
flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, MEDELEG_REGW);
flopenr #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, MIDELEG_REGW);
end else begin
assign MEDELEG_REGW = 0;
assign MIDELEG_REGW = 0;
end
endgenerate
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin:deleg // DELEG registers should exist
flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, MEDELEG_REGW);
flopenr #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, MIDELEG_REGW);
end else begin
assign MEDELEG_REGW = 0;
assign MIDELEG_REGW = 0;
end
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
if(`QEMU) assign MTVAL_REGW = `XLEN'b0;
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
generate // *** needs comment about bit 1
if (`BUSYBEAR == 1) begin:counters
if (`BUSYBEAR == 1) begin:counters // counter 1 (TIME) enable tied to 0 to match simulator***
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, MCOUNTEREN_REGW);
end else begin:counters
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
end
endgenerate
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW);

View File

@ -49,52 +49,50 @@ module csrn #(parameter
);
// User mode CSRs below only needed when user mode traps are supported
generate
if (`N_SUPPORTED) begin:nmode
logic WriteUTVECM;
logic WriteUSCRATCHM, WriteUEPCM;
logic WriteUCAUSEM, WriteUTVALM;
logic [`XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW;
logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW;
// Write enables
assign WriteUSTATUSM = CSRNWriteM & (CSRAdrM == USTATUS) & ~StallW;
assign WriteUTVECM = CSRNWriteM & (CSRAdrM == UTVEC) & ~StallW;
assign WriteUEPCM = UTrapM | (CSRNWriteM & (CSRAdrM == UEPC)) & ~StallW;
assign WriteUCAUSEM = UTrapM | (CSRNWriteM & (CSRAdrM == UCAUSE)) & ~StallW;
assign WriteUTVALM = UTrapM | (CSRNWriteM & (CSRAdrM == UTVAL)) & ~StallW;
if (`N_SUPPORTED) begin:nmode // depricated; consider removing***
logic WriteUTVECM;
logic WriteUSCRATCHM, WriteUEPCM;
logic WriteUCAUSEM, WriteUTVALM;
logic [`XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW;
logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW;
// Write enables
assign WriteUSTATUSM = CSRNWriteM & (CSRAdrM == USTATUS) & ~StallW;
assign WriteUTVECM = CSRNWriteM & (CSRAdrM == UTVEC) & ~StallW;
assign WriteUEPCM = UTrapM | (CSRNWriteM & (CSRAdrM == UEPC)) & ~StallW;
assign WriteUCAUSEM = UTrapM | (CSRNWriteM & (CSRAdrM == UCAUSE)) & ~StallW;
assign WriteUTVALM = UTrapM | (CSRNWriteM & (CSRAdrM == UTVAL)) & ~StallW;
// CSRs
flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `RESET_VECTOR, UTVEC_REGW);
flopenr #(`XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW);
flopenr #(`XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW);
flopenr #(`XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW);
flopenr #(`XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW);
// CSRs
flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `RESET_VECTOR, UTVEC_REGW);
flopenr #(`XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW);
flopenr #(`XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW);
flopenr #(`XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW);
flopenr #(`XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW);
// CSR Reads
always_comb begin
IllegalCSRNAccessM = 0;
case (CSRAdrM)
USTATUS: CSRNReadValM = USTATUS_REGW;
UTVEC: CSRNReadValM = UTVEC_REGW;
UIP: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIP_REGW};
UIE: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIE_REGW};
USCRATCH: CSRNReadValM = USCRATCH_REGW;
UEPC: CSRNReadValM = UEPC_REGW;
UCAUSE: CSRNReadValM = UCAUSE_REGW;
UTVAL: CSRNReadValM = UTVAL_REGW;
default: begin
CSRNReadValM = 0;
IllegalCSRNAccessM = 1;
end
endcase
end
end else begin // if not supported
assign WriteUSTATUSM = 0;
assign CSRNReadValM = 0;
assign UEPC_REGW = 0;
assign UTVEC_REGW = 0;
assign IllegalCSRNAccessM = 1;
// CSR Reads
always_comb begin
IllegalCSRNAccessM = 0;
case (CSRAdrM)
USTATUS: CSRNReadValM = USTATUS_REGW;
UTVEC: CSRNReadValM = UTVEC_REGW;
UIP: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIP_REGW};
UIE: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIE_REGW};
USCRATCH: CSRNReadValM = USCRATCH_REGW;
UEPC: CSRNReadValM = UEPC_REGW;
UCAUSE: CSRNReadValM = UCAUSE_REGW;
UTVAL: CSRNReadValM = UTVAL_REGW;
default: begin
CSRNReadValM = 0;
IllegalCSRNAccessM = 1;
end
endcase
end
endgenerate
endmodule
end else begin // if not supported
assign WriteUSTATUSM = 0;
assign CSRNReadValM = 0;
assign UEPC_REGW = 0;
assign UTVEC_REGW = 0;
assign IllegalCSRNAccessM = 1;
end
endmodule

View File

@ -69,89 +69,87 @@ module csrs #(parameter
//logic [`XLEN-1:0] SEDELEG_MASK = ~(zero | 3'b111 << 9); // sedeleg[11:9] hardwired to zero per Privileged Spec 3.1.8
// Supervisor mode CSRs sometimes supported
generate
if (`S_SUPPORTED) begin:csrs
logic WriteSTVECM;
logic WriteSSCRATCHM, WriteSEPCM;
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW;
(* mark_debug = "true" *) logic [`XLEN-1:0] SCAUSE_REGW;
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & ~StallW;
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & ~StallW;
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & ~StallW;
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & ~StallW;
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & ~StallW;
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & ~StallW;
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & ~StallW;
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & ~StallW;
if (`S_SUPPORTED) begin:csrs
logic WriteSTVECM;
logic WriteSSCRATCHM, WriteSEPCM;
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW;
(* mark_debug = "true" *) logic [`XLEN-1:0] SCAUSE_REGW;
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & ~StallW;
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & ~StallW;
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & ~StallW;
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & ~StallW;
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & ~StallW;
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & ~StallW;
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & ~StallW;
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & ~StallW;
// CSRs
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); //busybear: change reset to 0
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW);
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
if (`MEM_VIRTMEM)
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
else
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
if (`BUSYBEAR == 1) begin:scounteren
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, SCOUNTEREN_REGW);
end else if (`BUILDROOT == 1) begin:scounteren
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
end else begin:scounteren
flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
end
if (`N_SUPPORTED) begin:nregs
logic WriteSEDELEGM, WriteSIDELEGM;
assign WriteSEDELEGM = CSRSWriteM & (CSRAdrM == SEDELEG);
assign WriteSIDELEGM = CSRSWriteM & (CSRAdrM == SIDELEG);
flopenr #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, SEDELEG_REGW);
flopenr #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, SIDELEG_REGW);
end else begin
assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0;
end
// CSR Reads
always_comb begin:csrr
IllegalCSRSAccessM = !(`N_SUPPORTED) & (CSRAdrM == SEDELEG | CSRAdrM == SIDELEG); // trap on DELEG register access when no N-mode
case (CSRAdrM)
SSTATUS: CSRSReadValM = SSTATUS_REGW;
STVEC: CSRSReadValM = STVEC_REGW;
// SIDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIDELEG_REGW};
// SEDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SEDELEG_REGW};
SIDELEG: CSRSReadValM = SIDELEG_REGW;
SEDELEG: CSRSReadValM = SEDELEG_REGW;
SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIP_REGW};
SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIE_REGW};
SSCRATCH: CSRSReadValM = SSCRATCH_REGW;
SEPC: CSRSReadValM = SEPC_REGW;
SCAUSE: CSRSReadValM = SCAUSE_REGW;
STVAL: CSRSReadValM = STVAL_REGW;
SATP: if (`MEM_VIRTMEM & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
else begin
CSRSReadValM = 0;
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
end
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
default: begin
CSRSReadValM = 0;
IllegalCSRSAccessM = 1;
end
endcase
end
// CSRs
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); //busybear: change reset to 0
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW);
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
if (`MEM_VIRTMEM)
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
else
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
if (`BUSYBEAR == 1) begin:scounteren
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, SCOUNTEREN_REGW);
end else if (`BUILDROOT == 1) begin:scounteren
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
end else begin:scounteren
flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
end
if (`N_SUPPORTED) begin:nregs
logic WriteSEDELEGM, WriteSIDELEGM;
assign WriteSEDELEGM = CSRSWriteM & (CSRAdrM == SEDELEG);
assign WriteSIDELEGM = CSRSWriteM & (CSRAdrM == SIDELEG);
flopenr #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, SEDELEG_REGW);
flopenr #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, SIDELEG_REGW);
end else begin
assign WriteSSTATUSM = 0;
assign CSRSReadValM = 0;
assign SEPC_REGW = 0;
assign STVEC_REGW = 0;
assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0;
assign SCOUNTEREN_REGW = 0;
assign SATP_REGW = 0;
assign IllegalCSRSAccessM = 1;
end
endgenerate
// CSR Reads
always_comb begin:csrr
IllegalCSRSAccessM = !(`N_SUPPORTED) & (CSRAdrM == SEDELEG | CSRAdrM == SIDELEG); // trap on DELEG register access when no N-mode
case (CSRAdrM)
SSTATUS: CSRSReadValM = SSTATUS_REGW;
STVEC: CSRSReadValM = STVEC_REGW;
// SIDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIDELEG_REGW};
// SEDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SEDELEG_REGW};
SIDELEG: CSRSReadValM = SIDELEG_REGW;
SEDELEG: CSRSReadValM = SEDELEG_REGW;
SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIP_REGW};
SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIE_REGW};
SSCRATCH: CSRSReadValM = SSCRATCH_REGW;
SEPC: CSRSReadValM = SEPC_REGW;
SCAUSE: CSRSReadValM = SCAUSE_REGW;
STVAL: CSRSReadValM = STVAL_REGW;
SATP: if (`MEM_VIRTMEM & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
else begin
CSRSReadValM = 0;
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
end
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
default: begin
CSRSReadValM = 0;
IllegalCSRSAccessM = 1;
end
endcase
end
end else begin
assign WriteSSTATUSM = 0;
assign CSRSReadValM = 0;
assign SEPC_REGW = 0;
assign STVEC_REGW = 0;
assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0;
assign SCOUNTEREN_REGW = 0;
assign SATP_REGW = 0;
assign IllegalCSRSAccessM = 1;
end
endmodule

View File

@ -50,54 +50,50 @@ module csrsr (
// See Privileged Spec Section 3.1.6
// Lower privilege status registers are a subset of the full status register
// *** consider adding MBE, SBE, UBE fields later from 20210108 draft spec
generate
if (`XLEN==64) begin: csrsr64 // RV64
assign MSTATUS_REGW = {STATUS_SD, 27'b0, 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, 1'b0, STATUS_SPIE, STATUS_UPIE,
STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ 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*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
assign USTATUS_REGW = {/*STATUS_SD, */ 59'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
/* STATUS_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
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, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
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*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
assign USTATUS_REGW = {/*STATUS_SD, */ 27'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
/*STATUS_XS, STATUS_FS, STATUS_MPP, 8'b0, */
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
end
endgenerate
if (`XLEN==64) begin: csrsr64 // RV64
assign MSTATUS_REGW = {STATUS_SD, 27'b0, 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, 1'b0, STATUS_SPIE, STATUS_UPIE,
STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ 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*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
assign USTATUS_REGW = {/*STATUS_SD, */ 59'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
/* STATUS_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
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, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
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*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
assign USTATUS_REGW = {/*STATUS_SD, */ 27'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
/*STATUS_XS, STATUS_FS, STATUS_MPP, 8'b0, */
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
end
// harwired STATUS bits
generate
assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported
assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
assign STATUS_SXL = `S_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if supervisor mode supported
assign STATUS_UXL = `U_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if user mode supported
assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
endgenerate
assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported
assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
assign STATUS_SXL = `S_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if supervisor mode supported
assign STATUS_UXL = `U_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if user mode supported
assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `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

View File

@ -44,42 +44,40 @@ module csru #(parameter
);
// Floating Point CSRs in User Mode only needed if Floating Point is supported
generate
if (`F_SUPPORTED | `D_SUPPORTED) begin:csru
logic [4:0] FFLAGS_REGW;
logic [2:0] NextFRMM;
logic [4:0] NextFFLAGSM;
// Write enables
//assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & ~StallW;
assign WriteFRMM = (CSRUWriteM & (CSRAdrM == FRM | CSRAdrM == FCSR)) & ~StallW;
assign WriteFFLAGSM = (CSRUWriteM & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & ~StallW;
// Write Values
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
if (`F_SUPPORTED | `D_SUPPORTED) begin:csru
logic [4:0] FFLAGS_REGW;
logic [2:0] NextFRMM;
logic [4:0] NextFFLAGSM;
// Write enables
//assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & ~StallW;
assign WriteFRMM = (CSRUWriteM & (CSRAdrM == FRM | CSRAdrM == FCSR)) & ~StallW;
assign WriteFFLAGSM = (CSRUWriteM & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & ~StallW;
// Write Values
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
// CSRs
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW);
// CSRs
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW);
// CSR Reads
always_comb begin
IllegalCSRUAccessM = 0;
case (CSRAdrM)
FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW};
FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW};
FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW};
default: begin
CSRUReadValM = 0;
IllegalCSRUAccessM = 1;
end
endcase
end
end else begin // if not supported
assign FRM_REGW = 0;
assign CSRUReadValM = 0;
assign IllegalCSRUAccessM = 1;
// CSR Reads
always_comb begin
IllegalCSRUAccessM = 0;
case (CSRAdrM)
FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW};
FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW};
FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW};
default: begin
CSRUReadValM = 0;
IllegalCSRUAccessM = 1;
end
endcase
end
endgenerate
end else begin // if not supported
assign FRM_REGW = 0;
assign CSRUReadValM = 0;
assign IllegalCSRUAccessM = 1;
end
endmodule

View File

@ -103,18 +103,16 @@ module trap (
// > implemented without a hardware adder circuit.
// For example, we could require m/stvec be aligned on 7 bits to let us replace the adder directly below with
// [untested] PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:7], CauseM[3:0], 4'b0000}
generate
if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec
always_comb
if (PrivilegedTrapVector[1:0] == 2'b01 & CauseM[`XLEN-1] == 1)
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00};
else
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
end
else begin
assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
end
endgenerate
if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec
always_comb
if (PrivilegedTrapVector[1:0] == 2'b01 & CauseM[`XLEN-1] == 1)
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00};
else
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
end
else begin
assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
end
always_comb
if (mretM) PrivilegedNextPCM = MEPC_REGW;

View File

@ -55,12 +55,8 @@ module clint (
assign HREADYCLINT = 1'b1; // *** needs to depend on DONE during accesses
// word aligned reads
generate
if (`XLEN==64)
assign #2 entry = {HADDR[15:3], 3'b000};
else
assign #2 entry = {HADDR[15:2], 2'b00};
endgenerate
if (`XLEN==64) assign #2 entry = {HADDR[15:3], 3'b000};
else assign #2 entry = {HADDR[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
@ -69,74 +65,72 @@ module clint (
// Use req and ack signals synchronized across the clock domains.
// register access
generate
if (`XLEN==64) begin:clint // 64-bit
always @(posedge HCLK) begin
case(entry)
16'h0000: HREADCLINT <= {63'b0, MSIP};
16'h4000: HREADCLINT <= MTIMECMP;
16'hBFF8: HREADCLINT <= MTIME;
default: HREADCLINT <= 0;
endcase
end
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MSIP <= 0;
MTIMECMP <= 0;
// MTIMECMP is not reset
end else if (memwrite) begin
if (entryd == 16'h0000) MSIP <= HWDATA[0];
if (entryd == 16'h4000) MTIMECMP <= HWDATA;
end
// eventually replace MTIME logic below with timereg
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), 1'b0, HWDATA, MTIME, done);
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MTIME <= 0;
// MTIMECMP is not reset
end else if (memwrite & entryd == 16'hBFF8) begin
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
MTIME <= HWDATA;
end else MTIME <= MTIME + 1;
end else begin:clint // 32-bit
always @(posedge HCLK) begin
case(entry)
16'h0000: HREADCLINT <= {31'b0, MSIP};
16'h4000: HREADCLINT <= MTIMECMP[31:0];
16'h4004: HREADCLINT <= MTIMECMP[63:32];
16'hBFF8: HREADCLINT <= MTIME[31:0];
16'hBFFC: HREADCLINT <= MTIME[63:32];
default: HREADCLINT <= 0;
endcase
end
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MSIP <= 0;
MTIMECMP <= 0;
// MTIMECMP is not reset ***?
end else if (memwrite) begin
if (entryd == 16'h0000) MSIP <= HWDATA[0];
if (entryd == 16'h4000) MTIMECMP[31:0] <= HWDATA;
if (entryd == 16'h4004) MTIMECMP[63:32] <= HWDATA;
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
end
if (`XLEN==64) begin:clint // 64-bit
always @(posedge HCLK) begin
case(entry)
16'h0000: HREADCLINT <= {63'b0, MSIP};
16'h4000: HREADCLINT <= MTIMECMP;
16'hBFF8: HREADCLINT <= MTIME;
default: HREADCLINT <= 0;
endcase
end
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MSIP <= 0;
MTIMECMP <= 0;
// MTIMECMP is not reset
end else if (memwrite) begin
if (entryd == 16'h0000) MSIP <= HWDATA[0];
if (entryd == 16'h4000) MTIMECMP <= HWDATA;
end
// eventually replace MTIME logic below with timereg
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), memwrite & (entryd == 16'hBFFC), HWDATA, MTIME, done);
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MTIME <= 0;
// MTIMECMP is not reset
end else if (memwrite & (entryd == 16'hBFF8)) begin
MTIME[31:0] <= HWDATA;
end else if (memwrite & (entryd == 16'hBFFC)) begin
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
MTIME[63:32]<= HWDATA;
end else MTIME <= MTIME + 1;
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), 1'b0, HWDATA, MTIME, done);
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MTIME <= 0;
// MTIMECMP is not reset
end else if (memwrite & entryd == 16'hBFF8) begin
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
MTIME <= HWDATA;
end else MTIME <= MTIME + 1;
end else begin:clint // 32-bit
always @(posedge HCLK) begin
case(entry)
16'h0000: HREADCLINT <= {31'b0, MSIP};
16'h4000: HREADCLINT <= MTIMECMP[31:0];
16'h4004: HREADCLINT <= MTIMECMP[63:32];
16'hBFF8: HREADCLINT <= MTIME[31:0];
16'hBFFC: HREADCLINT <= MTIME[63:32];
default: HREADCLINT <= 0;
endcase
end
endgenerate
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MSIP <= 0;
MTIMECMP <= 0;
// MTIMECMP is not reset ***?
end else if (memwrite) begin
if (entryd == 16'h0000) MSIP <= HWDATA[0];
if (entryd == 16'h4000) MTIMECMP[31:0] <= HWDATA;
if (entryd == 16'h4004) MTIMECMP[63:32] <= HWDATA;
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
end
// eventually replace MTIME logic below with timereg
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), memwrite & (entryd == 16'hBFFC), HWDATA, MTIME, done);
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MTIME <= 0;
// MTIMECMP is not reset
end else if (memwrite & (entryd == 16'hBFF8)) begin
MTIME[31:0] <= HWDATA;
end else if (memwrite & (entryd == 16'hBFFC)) begin
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
MTIME[63:32]<= HWDATA;
end else MTIME <= MTIME + 1;
end
// Software interrupt when MSIP is set
assign SwIntM = MSIP;
@ -234,13 +228,9 @@ module graytobinary #(parameter N = `XLEN) (
// B[N-1] = G[N-1]; B[i] = G[i] ^ B[i+1] for 0 <= i < N-1
// requires rippling through N-1 XOR gates
generate
begin
genvar i;
assign b[N-1] = g[N-1];
for (i=N-2; i >= 0; i--) begin:g2b
assign b[i] = g[i] ^ b[i+1];
end
genvar i;
assign b[N-1] = g[N-1];
for (i=N-2; i >= 0; i--) begin:g2b
assign b[i] = g[i] ^ b[i+1];
end
endgenerate
endmodule

View File

@ -61,23 +61,13 @@ module gpio (
// 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")
generate
if (`XLEN == 64) begin:gpio
always_comb
if (entryd[2]) begin
Din = HWDATA[63:32];
HREADGPIO = {Dout,32'b0};
end else begin
Din = HWDATA[31:0];
HREADGPIO = {32'b0,Dout};
end
end else begin:gpio // 32-bit
always_comb begin
Din = HWDATA[31:0];
HREADGPIO = Dout;
end
end
endgenerate
if (`XLEN == 64) begin
assign Din = entryd[2] ? HWDATA[63:32] : HWDATA[31:0];
assign HREADGPIO = entryd[2] ? {Dout,32'b0} : {32'b0,Dout};
end else begin // 32-bit
assign Din = HWDATA[31:0];
assign HREADGPIO = Dout;
end
// register access
always_ff @(posedge HCLK, negedge HRESETn) begin
@ -150,12 +140,9 @@ module gpio (
end
// chip i/o
generate
if (`GPIO_LOOPBACK_TEST) // connect OUT to IN for loopback testing
assign input0d = GPIOPinsOut & input_en & output_en;
else
assign input0d = GPIOPinsIn & input_en;
endgenerate
// connect OUT to IN for loopback testing
if (`GPIO_LOOPBACK_TEST) assign input0d = GPIOPinsOut & input_en & output_en;
else assign input0d = GPIOPinsIn & input_en;
flop #(32) sync1(HCLK,input0d,input1d);
flop #(32) sync2(HCLK,input1d,input2d);
flop #(32) sync3(HCLK,input2d,input3d);

View File

@ -77,23 +77,13 @@ module plic (
// account for subword read/write circuitry
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW.
generate
if (`XLEN == 64) begin:plic
always_comb
if (entryd[2]) begin
Din = HWDATA[63:32];
HREADPLIC = {Dout,32'b0};
end else begin
Din = HWDATA[31:0];
HREADPLIC = {32'b0,Dout};
end
end else begin:plic // 32-bit
always_comb begin
Din = HWDATA[31:0];
HREADPLIC = Dout;
end
end
endgenerate
if (`XLEN == 64) begin
assign Din = entryd[2] ? HWDATA[63:32] : HWDATA[31:0];
assign HREADPLIC = entryd[2] ? {Dout,32'b0} : {32'b0,Dout};
end else begin // 32-bit
assign Din = HWDATA[31:0];
assign HREADPLIC = Dout;
end
// ==================
// Register Interface
@ -165,14 +155,11 @@ module plic (
// pending array - indexed by priority_lvl x source_ID
genvar i, j;
generate
for (j=1; j<=7; j++) begin: pending
for (i=1; i<=N; i=i+1) begin: pendingbit
// *** make sure that this synthesizes into N decoders, not 7*N 3-bit equality comparators (right?)
assign pendingArray[j][i] = (intPriority[i]==j) & intEn[i] & intPending[i];
end
for (j=1; j<=7; j++) begin: pending
for (i=1; i<=N; i=i+1) begin: pendingbit
assign pendingArray[j][i] = (intPriority[i]==j) & intEn[i] & intPending[i];
end
endgenerate
end
// pending array, except grouped by priority
assign pendingPGrouped[7:1] = {|pendingArray[7],
|pendingArray[6],
@ -200,8 +187,7 @@ module plic (
| ({N{pendingMaxP[2]}} & pendingArray[2])
| ({N{pendingMaxP[1]}} & pendingArray[1]);
// find the lowest ID amongst active interrupts at the highest priority
int k;
// *** verify that this synthesizes to a reasonable priority encoder and that k doesn't actually exist in hardware
int k; // *** rewrite as priority encoder
always_comb begin
intClaim = 6'b0;
for(k=N; k>0; k=k-1) begin

View File

@ -49,56 +49,53 @@ module ram #(parameter BASE=0, RANGE = 65535) (
logic memwrite;
logic [3:0] busycount;
generate
if(`FPGA) begin:ram
initial begin
//$readmemh(PRELOAD, RAM);
// FPGA only
RAM[0] = 64'h94e1819300002197;
RAM[1] = 64'h4281420141014081;
RAM[2] = 64'h4481440143814301;
RAM[3] = 64'h4681460145814501;
RAM[4] = 64'h4881480147814701;
RAM[5] = 64'h4a814a0149814901;
RAM[6] = 64'h4c814c014b814b01;
RAM[7] = 64'h4e814e014d814d01;
RAM[8] = 64'h0110011b4f814f01;
RAM[9] = 64'h059b45011161016e;
RAM[10] = 64'h0004063705fe0010;
RAM[11] = 64'h05a000ef8006061b;
RAM[12] = 64'h0ff003930000100f;
RAM[13] = 64'h4e952e3110012e37;
RAM[14] = 64'hc602829b0053f2b7;
RAM[15] = 64'h2023fe02dfe312fd;
RAM[16] = 64'h829b0053f2b7007e;
RAM[17] = 64'hfe02dfe312fdc602;
RAM[18] = 64'h4de31efd000e2023;
RAM[19] = 64'h059bf1402573fdd0;
RAM[20] = 64'h0000061705e20870;
RAM[21] = 64'h0010029b01260613;
RAM[22] = 64'h11010002806702fe;
RAM[23] = 64'h84b2842ae426e822;
RAM[24] = 64'h892ee04aec064505;
RAM[25] = 64'h06e000ef07e000ef;
RAM[26] = 64'h979334fd02905563;
RAM[27] = 64'h07930177d4930204;
RAM[28] = 64'h4089093394be2004;
RAM[29] = 64'h04138522008905b3;
RAM[30] = 64'h19e3014000ef2004;
RAM[31] = 64'h64a2644260e2fe94;
RAM[32] = 64'h6749808261056902;
RAM[33] = 64'hdfed8b8510472783;
RAM[34] = 64'h2423479110a73823;
RAM[35] = 64'h10472783674910f7;
RAM[36] = 64'h20058693ffed8b89;
RAM[37] = 64'h05a1118737836749;
RAM[38] = 64'hfed59be3fef5bc23;
RAM[39] = 64'h1047278367498082;
RAM[40] = 64'h67c98082dfed8b85;
RAM[41] = 64'h0000808210a7a023;
end // initial begin
end // if (FPGA)
endgenerate
if(`FPGA) begin:ram
initial begin
//$readmemh(PRELOAD, RAM);
RAM[0] = 64'h94e1819300002197;
RAM[1] = 64'h4281420141014081;
RAM[2] = 64'h4481440143814301;
RAM[3] = 64'h4681460145814501;
RAM[4] = 64'h4881480147814701;
RAM[5] = 64'h4a814a0149814901;
RAM[6] = 64'h4c814c014b814b01;
RAM[7] = 64'h4e814e014d814d01;
RAM[8] = 64'h0110011b4f814f01;
RAM[9] = 64'h059b45011161016e;
RAM[10] = 64'h0004063705fe0010;
RAM[11] = 64'h05a000ef8006061b;
RAM[12] = 64'h0ff003930000100f;
RAM[13] = 64'h4e952e3110012e37;
RAM[14] = 64'hc602829b0053f2b7;
RAM[15] = 64'h2023fe02dfe312fd;
RAM[16] = 64'h829b0053f2b7007e;
RAM[17] = 64'hfe02dfe312fdc602;
RAM[18] = 64'h4de31efd000e2023;
RAM[19] = 64'h059bf1402573fdd0;
RAM[20] = 64'h0000061705e20870;
RAM[21] = 64'h0010029b01260613;
RAM[22] = 64'h11010002806702fe;
RAM[23] = 64'h84b2842ae426e822;
RAM[24] = 64'h892ee04aec064505;
RAM[25] = 64'h06e000ef07e000ef;
RAM[26] = 64'h979334fd02905563;
RAM[27] = 64'h07930177d4930204;
RAM[28] = 64'h4089093394be2004;
RAM[29] = 64'h04138522008905b3;
RAM[30] = 64'h19e3014000ef2004;
RAM[31] = 64'h64a2644260e2fe94;
RAM[32] = 64'h6749808261056902;
RAM[33] = 64'hdfed8b8510472783;
RAM[34] = 64'h2423479110a73823;
RAM[35] = 64'h10472783674910f7;
RAM[36] = 64'h20058693ffed8b89;
RAM[37] = 64'h05a1118737836749;
RAM[38] = 64'hfed59be3fef5bc23;
RAM[39] = 64'h1047278367498082;
RAM[40] = 64'h67c98082dfed8b85;
RAM[41] = 64'h0000808210a7a023;
end // initial begin
end // if (FPGA)
assign initTrans = HREADY & HSELRam & (HTRANS != 2'b00);
@ -144,26 +141,23 @@ module ram #(parameter BASE=0, RANGE = 65535) (
-----/\----- EXCLUDED -----/\----- */
/* verilator lint_off WIDTH */
generate
if (`XLEN == 64) begin:ramrd
always_ff @(posedge HCLK) begin
HWADDR <= #1 A;
HREADRam0 <= #1 RAM[A[31:3]];
if (memwrite & risingHREADYRam) RAM[HWADDR[31:3]] <= #1 HWDATA;
end
end else begin
always_ff @(posedge HCLK) begin:ramrd
HWADDR <= #1 A;
HREADRam0 <= #1 RAM[A[31:2]];
if (memwrite & risingHREADYRam) RAM[HWADDR[31:2]] <= #1 HWDATA;
end
if (`XLEN == 64) begin:ramrw
always_ff @(posedge HCLK) begin
HWADDR <= #1 A;
HREADRam0 <= #1 RAM[A[31:3]];
if (memwrite & risingHREADYRam) RAM[HWADDR[31:3]] <= #1 HWDATA;
end
endgenerate
end else begin
always_ff @(posedge HCLK) begin:ramrw
HWADDR <= #1 A;
HREADRam0 <= #1 RAM[A[31:2]];
if (memwrite & risingHREADYRam) RAM[HWADDR[31:2]] <= #1 HWDATA;
end
end
/* verilator lint_on WIDTH */
//assign HREADRam = HREADYRam ? HREADRam0 : `XLEN'bz;
// *** Ross Thompson: removed tristate as fpga synthesis removes.
assign HREADRam = HREADRam0;
endmodule

View File

@ -156,17 +156,15 @@ module SDC
flopenl #(3) CommandReg(HCLK, ~HRESETn, (HADDRDelay == 'h8 & RegWrite) | (CommandCompleted),
CommandCompleted ? '0 : HWDATA[2:0], '0, Command);
generate
if (`XLEN == 64) begin
flopenr #(64-9) AddressReg(HCLK, ~HRESETn, (HADDRDelay == 'h10 & RegWrite),
HWDATA[`XLEN-1:9], Address);
end else begin
flopenr #(32-9) AddressLowReg(HCLK, ~HRESETn, (HADDRDelay == 'h10 & RegWrite),
HWDATA[`XLEN-1:9], Address[31:9]);
flopenr #(32) AddressHighReg(HCLK, ~HRESETn, (HADDRDelay == 'h14 & RegWrite),
HWDATA, Address[63:32]);
end
endgenerate
if (`XLEN == 64) begin
flopenr #(64-9) AddressReg(HCLK, ~HRESETn, (HADDRDelay == 'h10 & RegWrite),
HWDATA[`XLEN-1:9], Address);
end else begin
flopenr #(32-9) AddressLowReg(HCLK, ~HRESETn, (HADDRDelay == 'h10 & RegWrite),
HWDATA[`XLEN-1:9], Address[31:9]);
flopenr #(32) AddressHighReg(HCLK, ~HRESETn, (HADDRDelay == 'h14 & RegWrite),
HWDATA, Address[63:32]);
end
flopen #(`XLEN) DataReg(HCLK, (HADDRDelay == 'h18 & RegWrite),
HWDATA, SDCWriteData);
@ -175,7 +173,6 @@ module SDC
assign Status = {ErrorCode, InvalidCommand, SDCBusy, SDCInitialized};
generate
if(`XLEN == 64) begin
always_comb
case(HADDRDelay[4:0])
@ -200,16 +197,14 @@ module SDC
default: HREADSDC = {24'b0, CLKDiv};
endcase
end
endgenerate
for(index = 0; index < 4096/`XLEN; index++) begin
assign ReadData512ByteWords[index] = ReadData512Byte[(index+1)*`XLEN-1:index*`XLEN];
end
assign SDCReadDataPreNibbleSwap = ReadData512ByteWords[WordCount];
generate
if(`XLEN == 64) begin
if(`XLEN == 64) begin
assign SDCReadData = {SDCReadDataPreNibbleSwap[59:56], SDCReadDataPreNibbleSwap[63:60],
SDCReadDataPreNibbleSwap[51:48], SDCReadDataPreNibbleSwap[55:52],
SDCReadDataPreNibbleSwap[43:40], SDCReadDataPreNibbleSwap[47:44],
@ -224,7 +219,6 @@ module SDC
SDCReadDataPreNibbleSwap[11:8], SDCReadDataPreNibbleSwap[15:12],
SDCReadDataPreNibbleSwap[3:0], SDCReadDataPreNibbleSwap[7:4]};
end
endgenerate
flopenr #($clog2(4096/`XLEN)) WordCountReg
(.clk(HCLK),

View File

@ -88,17 +88,6 @@ module clkdivider #(parameter integer g_COUNT_WIDTH)
assign w_fd_D = ~ r_fd_Q;
generate
if(`FPGA) begin
BUFGMUX
clkMux(.I1(r_fd_Q),
.I0(i_CLK),
.S(i_EN),
.O(o_CLK));
end else begin
assign o_CLK = i_EN ? r_fd_Q : i_CLK;
end
endgenerate
if(`FPGA) BUFGMUX clkMux(.I1(r_fd_Q), .I0(i_CLK), .S(i_EN), .O(o_CLK));
else assign o_CLK = i_EN ? r_fd_Q : i_CLK;
endmodule

View File

@ -35,75 +35,72 @@ module subwordwrite (
logic [`XLEN-1:0] WriteDataSubwordDuplicated;
generate
if (`XLEN == 64) begin:sww
logic [7:0] ByteMaskM;
// Compute write mask
always_comb
case(HSIZED[1:0])
2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDRD[2:0]] = 1; end // sb
2'b01: case (HADDRD[2:1])
2'b00: ByteMaskM = 8'b00000011;
2'b01: ByteMaskM = 8'b00001100;
2'b10: ByteMaskM = 8'b00110000;
2'b11: ByteMaskM = 8'b11000000;
endcase
2'b10: if (HADDRD[2]) ByteMaskM = 8'b11110000;
else ByteMaskM = 8'b00001111;
2'b11: ByteMaskM = 8'b11111111;
endcase
if (`XLEN == 64) begin:sww
logic [7:0] ByteMaskM;
// Compute write mask
always_comb
case(HSIZED[1:0])
2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDRD[2:0]] = 1; end // sb
2'b01: case (HADDRD[2:1])
2'b00: ByteMaskM = 8'b00000011;
2'b01: ByteMaskM = 8'b00001100;
2'b10: ByteMaskM = 8'b00110000;
2'b11: ByteMaskM = 8'b11000000;
endcase
2'b10: if (HADDRD[2]) ByteMaskM = 8'b11110000;
else ByteMaskM = 8'b00001111;
2'b11: ByteMaskM = 8'b11111111;
endcase
// Handle subword writes
always_comb
case(HSIZED[1:0])
2'b00: WriteDataSubwordDuplicated = {8{HWDATAIN[7:0]}}; // sb
2'b01: WriteDataSubwordDuplicated = {4{HWDATAIN[15:0]}}; // sh
2'b10: WriteDataSubwordDuplicated = {2{HWDATAIN[31:0]}}; // sw
2'b11: WriteDataSubwordDuplicated = HWDATAIN; // sw
endcase
// Handle subword writes
always_comb
case(HSIZED[1:0])
2'b00: WriteDataSubwordDuplicated = {8{HWDATAIN[7:0]}}; // sb
2'b01: WriteDataSubwordDuplicated = {4{HWDATAIN[15:0]}}; // sh
2'b10: WriteDataSubwordDuplicated = {2{HWDATAIN[31:0]}}; // sw
2'b11: WriteDataSubwordDuplicated = HWDATAIN; // sw
endcase
always_comb begin
HWDATA=HRDATA;
if (ByteMaskM[0]) HWDATA[7:0] = WriteDataSubwordDuplicated[7:0];
if (ByteMaskM[1]) HWDATA[15:8] = WriteDataSubwordDuplicated[15:8];
if (ByteMaskM[2]) HWDATA[23:16] = WriteDataSubwordDuplicated[23:16];
if (ByteMaskM[3]) HWDATA[31:24] = WriteDataSubwordDuplicated[31:24];
if (ByteMaskM[4]) HWDATA[39:32] = WriteDataSubwordDuplicated[39:32];
if (ByteMaskM[5]) HWDATA[47:40] = WriteDataSubwordDuplicated[47:40];
if (ByteMaskM[6]) HWDATA[55:48] = WriteDataSubwordDuplicated[55:48];
if (ByteMaskM[7]) HWDATA[63:56] = WriteDataSubwordDuplicated[63:56];
end
always_comb begin
HWDATA=HRDATA;
if (ByteMaskM[0]) HWDATA[7:0] = WriteDataSubwordDuplicated[7:0];
if (ByteMaskM[1]) HWDATA[15:8] = WriteDataSubwordDuplicated[15:8];
if (ByteMaskM[2]) HWDATA[23:16] = WriteDataSubwordDuplicated[23:16];
if (ByteMaskM[3]) HWDATA[31:24] = WriteDataSubwordDuplicated[31:24];
if (ByteMaskM[4]) HWDATA[39:32] = WriteDataSubwordDuplicated[39:32];
if (ByteMaskM[5]) HWDATA[47:40] = WriteDataSubwordDuplicated[47:40];
if (ByteMaskM[6]) HWDATA[55:48] = WriteDataSubwordDuplicated[55:48];
if (ByteMaskM[7]) HWDATA[63:56] = WriteDataSubwordDuplicated[63:56];
end
end else begin:sww // 32-bit
logic [3:0] ByteMaskM;
// Compute write mask
always_comb
case(HSIZED[1:0])
2'b00: begin ByteMaskM = 4'b0000; ByteMaskM[HADDRD[1:0]] = 1; end // sb
2'b01: if (HADDRD[1]) ByteMaskM = 4'b1100;
else ByteMaskM = 4'b0011;
2'b10: ByteMaskM = 4'b1111;
default: ByteMaskM = 4'b111; // shouldn't happen
endcase
end else begin:sww // 32-bit
logic [3:0] ByteMaskM;
// Compute write mask
always_comb
case(HSIZED[1:0])
2'b00: begin ByteMaskM = 4'b0000; ByteMaskM[HADDRD[1:0]] = 1; end // sb
2'b01: if (HADDRD[1]) ByteMaskM = 4'b1100;
else ByteMaskM = 4'b0011;
2'b10: ByteMaskM = 4'b1111;
default: ByteMaskM = 4'b111; // shouldn't happen
endcase
// Handle subword writes
always_comb
case(HSIZED[1:0])
2'b00: WriteDataSubwordDuplicated = {4{HWDATAIN[7:0]}}; // sb
2'b01: WriteDataSubwordDuplicated = {2{HWDATAIN[15:0]}}; // sh
2'b10: WriteDataSubwordDuplicated = HWDATAIN; // sw
default: WriteDataSubwordDuplicated = HWDATAIN; // shouldn't happen
endcase
// Handle subword writes
always_comb
case(HSIZED[1:0])
2'b00: WriteDataSubwordDuplicated = {4{HWDATAIN[7:0]}}; // sb
2'b01: WriteDataSubwordDuplicated = {2{HWDATAIN[15:0]}}; // sh
2'b10: WriteDataSubwordDuplicated = HWDATAIN; // sw
default: WriteDataSubwordDuplicated = HWDATAIN; // shouldn't happen
endcase
always_comb begin
HWDATA=HRDATA;
if (ByteMaskM[0]) HWDATA[7:0] = WriteDataSubwordDuplicated[7:0];
if (ByteMaskM[1]) HWDATA[15:8] = WriteDataSubwordDuplicated[15:8];
if (ByteMaskM[2]) HWDATA[23:16] = WriteDataSubwordDuplicated[23:16];
if (ByteMaskM[3]) HWDATA[31:24] = WriteDataSubwordDuplicated[31:24];
end
end
endgenerate
always_comb begin
HWDATA=HRDATA;
if (ByteMaskM[0]) HWDATA[7:0] = WriteDataSubwordDuplicated[7:0];
if (ByteMaskM[1]) HWDATA[15:8] = WriteDataSubwordDuplicated[15:8];
if (ByteMaskM[2]) HWDATA[23:16] = WriteDataSubwordDuplicated[23:16];
if (ByteMaskM[3]) HWDATA[31:24] = WriteDataSubwordDuplicated[31:24];
end
end
endmodule

View File

@ -54,33 +54,31 @@ module uart (
assign HRESPUART = 0; // OK
assign HREADYUART = 1; // should idle high during address phase and respond high when done; will need to be modified if UART ever needs more than 1 cycle to do something
generate
if (`XLEN == 64) begin:uart
always_comb begin
HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
case (A)
3'b000: Din = HWDATA[7:0];
3'b001: Din = HWDATA[15:8];
3'b010: Din = HWDATA[23:16];
3'b011: Din = HWDATA[31:24];
3'b100: Din = HWDATA[39:32];
3'b101: Din = HWDATA[47:40];
3'b110: Din = HWDATA[55:48];
3'b111: Din = HWDATA[63:56];
endcase
end
end else begin:uart // 32-bit
always_comb begin
HREADUART = {Dout, Dout, Dout, Dout};
case (A[1:0])
2'b00: Din = HWDATA[7:0];
2'b01: Din = HWDATA[15:8];
2'b10: Din = HWDATA[23:16];
2'b11: Din = HWDATA[31:24];
endcase
end
if (`XLEN == 64) begin:uart
always_comb begin
HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
case (A)
3'b000: Din = HWDATA[7:0];
3'b001: Din = HWDATA[15:8];
3'b010: Din = HWDATA[23:16];
3'b011: Din = HWDATA[31:24];
3'b100: Din = HWDATA[39:32];
3'b101: Din = HWDATA[47:40];
3'b110: Din = HWDATA[55:48];
3'b111: Din = HWDATA[63:56];
endcase
end
end else begin:uart // 32-bit
always_comb begin
HREADUART = {Dout, Dout, Dout, Dout};
case (A[1:0])
2'b00: Din = HWDATA[7:0];
2'b01: Din = HWDATA[15:8];
2'b10: Din = HWDATA[23:16];
2'b11: Din = HWDATA[31:24];
endcase
end
endgenerate
end
logic BAUDOUTb; // loop tx clock BAUDOUTb back to rx clock RCLK
// *** make sure reads don't occur on UART unless fully selected because they could change state. This applies to all peripherals

View File

@ -257,13 +257,10 @@ module uartPC16550D(
else if (fifoenabled & ~rxfifoempty & rxbaudpulse & ~rxfifotimeout) rxtimeoutcnt <= #1 rxtimeoutcnt+1; // *** not right
end
generate
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
endgenerate
// ***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
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
///////////////////////////////////////////
@ -325,22 +322,20 @@ module uartPC16550D(
// detect any errors in rx fifo
// although rxfullbit looks like a combinational loop, in one bit rxfifotail == i and breaks the loop
// tail is normally higher than head, but might wrap around. unwrapped variable adds 16 to eliminate wrapping
generate
assign rxfifotailunwrapped = rxfifotail < rxfifohead ? {1'b1, rxfifotail} : {1'b0, rxfifotail};
genvar i;
for (i=0; i<32; i++) begin:rxfull
if (i == 0) assign rxfullbitunwrapped[i] = (rxfifohead==0) & (rxfifotail != 0);
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 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
endgenerate
assign rxfifotailunwrapped = rxfifotail < rxfifohead ? {1'b1, rxfifotail} : {1'b0, rxfifotail};
genvar i;
for (i=0; i<32; i++) begin:rxfull
if (i == 0) assign rxfullbitunwrapped[i] = (rxfifohead==0) & (rxfifotail != 0);
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 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);
// receive buffer register and ready bit
@ -383,13 +378,9 @@ module uartPC16550D(
end
assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s)
generate
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
endgenerate
// *** 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
///////////////////////////////////////////
// transmit holding register, shift register, FIFO

View File

@ -304,88 +304,84 @@ module wallypipelinedhart (
.FlushF, .FlushD, .FlushE, .FlushM, .FlushW
); // global stall and flush control
generate
if (`ZICSR_SUPPORTED) begin:priv
privileged priv(
.clk, .reset,
.FlushD, .FlushE, .FlushM, .FlushW,
.StallD, .StallE, .StallM, .StallW,
.CSRReadM, .CSRWriteM, .SrcAM, .PCM,
.InstrM, .CSRReadValW, .PrivilegedNextPCM,
.RetM, .TrapM,
.ITLBFlushF, .DTLBFlushM,
.InstrValidM, .CommittedM,
.FRegWriteM, .LoadStallD,
.BPPredDirWrongM, .BTBPredPCWrongM,
.RASPredPCWrongM, .BPPredClassNonCFIWrongM,
.InstrClassM, .DCacheMiss, .DCacheAccess, .PrivilegedM,
.ITLBInstrPageFaultF, .DTLBLoadPageFaultM, .DTLBStorePageFaultM,
.InstrMisalignedFaultM, .IllegalIEUInstrFaultD, .IllegalFPUInstrD,
.LoadMisalignedFaultM, .StoreMisalignedFaultM,
.TimerIntM, .ExtIntM, .SwIntM,
.MTIME_CLINT,
.InstrMisalignedAdrM, .IEUAdrM,
.SetFflagsM,
// Trap signals from pmp/pma in mmu
// *** do these need to be split up into one for dmem and one for ifu?
// instead, could we only care about the instr and F pins that come from ifu and only care about the load/store and m pins that come from dmem?
.InstrAccessFaultF, .LoadAccessFaultM, .StoreAccessFaultM,
.ExceptionM, .PendingInterruptM, .IllegalFPUInstrE,
.PrivilegeModeW, .SATP_REGW,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.FRM_REGW,.BreakpointFaultM, .EcallFaultM
);
end else begin
assign CSRReadValW = 0;
assign PrivilegedNextPCM = 0;
assign RetM = 0;
assign TrapM = 0;
assign ITLBFlushF = 0;
assign DTLBFlushM = 0;
end
if (`M_SUPPORTED) begin:mdu
muldiv mdu(
.clk, .reset,
.ForwardedSrcAE, .ForwardedSrcBE,
.Funct3E, .Funct3M, .MulDivE, .W64E,
.MulDivResultW, .DivBusyE,
.StallM, .StallW, .FlushM, .FlushW
);
end else begin // no M instructions supported
assign MulDivResultW = 0;
assign DivBusyE = 0;
end
if (`ZICSR_SUPPORTED) begin:priv
privileged priv(
.clk, .reset,
.FlushD, .FlushE, .FlushM, .FlushW,
.StallD, .StallE, .StallM, .StallW,
.CSRReadM, .CSRWriteM, .SrcAM, .PCM,
.InstrM, .CSRReadValW, .PrivilegedNextPCM,
.RetM, .TrapM,
.ITLBFlushF, .DTLBFlushM,
.InstrValidM, .CommittedM,
.FRegWriteM, .LoadStallD,
.BPPredDirWrongM, .BTBPredPCWrongM,
.RASPredPCWrongM, .BPPredClassNonCFIWrongM,
.InstrClassM, .DCacheMiss, .DCacheAccess, .PrivilegedM,
.ITLBInstrPageFaultF, .DTLBLoadPageFaultM, .DTLBStorePageFaultM,
.InstrMisalignedFaultM, .IllegalIEUInstrFaultD, .IllegalFPUInstrD,
.LoadMisalignedFaultM, .StoreMisalignedFaultM,
.TimerIntM, .ExtIntM, .SwIntM,
.MTIME_CLINT,
.InstrMisalignedAdrM, .IEUAdrM,
.SetFflagsM,
// Trap signals from pmp/pma in mmu
// *** do these need to be split up into one for dmem and one for ifu?
// instead, could we only care about the instr and F pins that come from ifu and only care about the load/store and m pins that come from dmem?
.InstrAccessFaultF, .LoadAccessFaultM, .StoreAccessFaultM,
.ExceptionM, .PendingInterruptM, .IllegalFPUInstrE,
.PrivilegeModeW, .SATP_REGW,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.FRM_REGW,.BreakpointFaultM, .EcallFaultM
);
end else begin
assign CSRReadValW = 0;
assign PrivilegedNextPCM = 0;
assign RetM = 0;
assign TrapM = 0;
assign ITLBFlushF = 0;
assign DTLBFlushM = 0;
end
if (`M_SUPPORTED) begin:mdu
muldiv mdu(
.clk, .reset,
.ForwardedSrcAE, .ForwardedSrcBE,
.Funct3E, .Funct3M, .MulDivE, .W64E,
.MulDivResultW, .DivBusyE,
.StallM, .StallW, .FlushM, .FlushW
);
end else begin // no M instructions supported
assign MulDivResultW = 0;
assign DivBusyE = 0;
end
if (`F_SUPPORTED) begin:fpu
fpu fpu(
.clk, .reset,
.FRM_REGW, // Rounding mode from CSR
.InstrD, // instruction from IFU
.ReadDataW,// 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
.RdM, .RdW, // which FP register to write to (from IEU)
.FRegWriteM, // FP register write enable
.FStallD, // Stall the decode stage
.FWriteIntE, // integer register write enable
.FWriteDataE, // Data to be written to memory
.FIntResM, // data to be written to integer register
.FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
.IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
.SetFflagsM // FPU flags (to privileged unit)
); // floating point unit
end else begin // no F_SUPPORTED or D_SUPPORTED; tie outputs low
assign FStallD = 0;
assign FWriteIntE = 0;
assign FWriteDataE = 0;
assign FIntResM = 0;
assign FDivBusyE = 0;
assign IllegalFPUInstrD = 1;
assign SetFflagsM = 0;
end
endgenerate
// Priveleged block operates in M and W stages, handling CSRs and exceptions
if (`F_SUPPORTED) begin:fpu
fpu fpu(
.clk, .reset,
.FRM_REGW, // Rounding mode from CSR
.InstrD, // instruction from IFU
.ReadDataW,// 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
.RdM, .RdW, // which FP register to write to (from IEU)
.FRegWriteM, // FP register write enable
.FStallD, // Stall the decode stage
.FWriteIntE, // integer register write enable
.FWriteDataE, // Data to be written to memory
.FIntResM, // data to be written to integer register
.FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
.IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
.SetFflagsM // FPU flags (to privileged unit)
); // floating point unit
end else begin // no F_SUPPORTED or D_SUPPORTED; tie outputs low
assign FStallD = 0;
assign FWriteIntE = 0;
assign FWriteDataE = 0;
assign FIntResM = 0;
assign FDivBusyE = 0;
assign IllegalFPUInstrD = 1;
assign SetFflagsM = 0;
end
endmodule

View File

@ -1,10 +0,0 @@
module logging(
input logic clk, reset,
input logic [31:0] HADDR,
input logic [1:0] HTRANS);
always @(posedge clk)
if (HTRANS != 2'b00 & HADDR == 0)
$display("%t Warning: access to memory address 0\n", $realtime);
endmodule

View File

@ -121,11 +121,9 @@ module sdModel
integer sdModel_file_desc;
genvar i;
generate
for(i=0; i<4; i=i+1) begin:CRC_16_gen
sd_crc_16 CRC_16_i (crcDat_in[i],crcDat_en, sdClk, crcDat_rst, crcDat_out[i]);
end
endgenerate
for(i=0; i<4; i=i+1) begin:CRC_16_gen
sd_crc_16 CRC_16_i (crcDat_in[i],crcDat_en, sdClk, crcDat_rst, crcDat_out[i]);
end
sd_crc_7 crc_7
(

View File

@ -763,17 +763,12 @@ string tests32f[] = '{
.done(DCacheFlushDone));
generate
// initialize the branch predictor
if (`BPRED_ENABLED == 1) begin : bpred
initial begin
$readmemb(`TWO_BIT_PRELOAD, dut.wallypipelinedsoc.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem);
$readmemb(`BTB_PRELOAD, dut.wallypipelinedsoc.hart.ifu.bpred.bpred.TargetPredictor.memory.mem);
end
// initialize the branch predictor
if (`BPRED_ENABLED == 1)
initial begin
$readmemb(`TWO_BIT_PRELOAD, dut.wallypipelinedsoc.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem);
$readmemb(`BTB_PRELOAD, dut.wallypipelinedsoc.hart.ifu.bpred.bpred.TargetPredictor.memory.mem);
end
endgenerate
endmodule
module riscvassertions();
@ -783,14 +778,14 @@ module riscvassertions();
assert (`F_SUPPORTED | ~`D_SUPPORTED) else $error("Can't support double without supporting float");
assert (`XLEN == 64 | ~`D_SUPPORTED) else $error("Wally does not yet support D extensions on RV32");
assert (`DCACHE_WAYSIZEINBYTES <= 4096 | `MEM_DCACHE == 0 | `MEM_VIRTMEM == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
assert (`DCACHE_BLOCKLENINBITS >= 128 | `MEM_DCACHE == 0) else $error("DCACHE_BLOCKLENINBITS must be at least 128 when caches are enabled");
assert (`DCACHE_BLOCKLENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_BLOCKLENINBITS must be smaller than way size");
assert (`DCACHE_LINELENINBITS >= 128 | `MEM_DCACHE == 0) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled");
assert (`DCACHE_LINELENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size");
assert (`ICACHE_WAYSIZEINBYTES <= 4096 | `MEM_ICACHE == 0 | `MEM_VIRTMEM == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
assert (`ICACHE_BLOCKLENINBITS >= 32 | `MEM_ICACHE == 0) else $error("ICACHE_BLOCKLENINBITS must be at least 32 when caches are enabled");
assert (`ICACHE_BLOCKLENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_BLOCKLENINBITS must be smaller than way size");
assert (2**$clog2(`DCACHE_BLOCKLENINBITS) == `DCACHE_BLOCKLENINBITS) else $error("DCACHE_BLOCKLENINBITS must be a power of 2");
assert (`ICACHE_LINELENINBITS >= 32 | `MEM_ICACHE == 0) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled");
assert (`ICACHE_LINELENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size");
assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS) else $error("DCACHE_LINELENINBITS must be a power of 2");
assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2");
assert (2**$clog2(`ICACHE_BLOCKLENINBITS) == `ICACHE_BLOCKLENINBITS) else $error("ICACHE_BLOCKLENINBITS must be a power of 2");
assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS) else $error("ICACHE_LINELENINBITS must be a power of 2");
assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2");
assert (`ICACHE_NUMWAYS == 1 | `MEM_ICACHE == 0) else $warning("Multiple Instruction Cache ways not yet implemented");
assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES) else $error("ITLB_ENTRIES must be a power of 2");
@ -811,12 +806,12 @@ module DCacheFlushFSM
localparam integer numlines = testbench.dut.wallypipelinedsoc.hart.lsu.dcache.NUMLINES;
localparam integer numways = testbench.dut.wallypipelinedsoc.hart.lsu.dcache.NUMWAYS;
localparam integer blockbytelen = testbench.dut.wallypipelinedsoc.hart.lsu.dcache.BLOCKBYTELEN;
localparam integer numwords = testbench.dut.wallypipelinedsoc.hart.lsu.dcache.BLOCKLEN/`XLEN;
localparam integer linebytelen = testbench.dut.wallypipelinedsoc.hart.lsu.dcache.LINEBYTELEN;
localparam integer numwords = testbench.dut.wallypipelinedsoc.hart.lsu.dcache.LINELEN/`XLEN;
localparam integer lognumlines = $clog2(numlines);
localparam integer logblockbytelen = $clog2(blockbytelen);
localparam integer loglinebytelen = $clog2(linebytelen);
localparam integer lognumways = $clog2(numways);
localparam integer tagstart = lognumlines + logblockbytelen;
localparam integer tagstart = lognumlines + loglinebytelen;
@ -830,29 +825,26 @@ module DCacheFlushFSM
logic [`XLEN-1:0] ShadowRAM[`RAM_BASE>>(1+`XLEN/32):(`RAM_RANGE+`RAM_BASE)>>1+(`XLEN/32)];
generate
for(index = 0; index < numlines; index++) begin
for(way = 0; way < numways; way++) begin
for(cacheWord = 0; cacheWord < numwords; cacheWord++) begin
copyShadow #(.tagstart(tagstart),
.logblockbytelen(logblockbytelen))
copyShadow(.clk,
.start,
.tag(testbench.dut.wallypipelinedsoc.hart.lsu.dcache.MemWay[way].CacheTagMem.StoredData[index]),
.valid(testbench.dut.wallypipelinedsoc.hart.lsu.dcache.MemWay[way].ValidBits[index]),
.dirty(testbench.dut.wallypipelinedsoc.hart.lsu.dcache.MemWay[way].DirtyBits[index]),
.data(testbench.dut.wallypipelinedsoc.hart.lsu.dcache.MemWay[way].word[cacheWord].CacheDataMem.StoredData[index]),
.index(index),
.cacheWord(cacheWord),
.CacheData(CacheData[way][index][cacheWord]),
.CacheAdr(CacheAdr[way][index][cacheWord]),
.CacheTag(CacheTag[way][index][cacheWord]),
.CacheValid(CacheValid[way][index][cacheWord]),
.CacheDirty(CacheDirty[way][index][cacheWord]));
end
for(index = 0; index < numlines; index++) begin
for(way = 0; way < numways; way++) begin
for(cacheWord = 0; cacheWord < numwords; cacheWord++) begin
copyShadow #(.tagstart(tagstart), .loglinebytelen(loglinebytelen))
copyShadow(.clk,
.start,
.tag(testbench.dut.wallypipelinedsoc.hart.lsu.dcache.MemWay[way].CacheTagMem.StoredData[index]),
.valid(testbench.dut.wallypipelinedsoc.hart.lsu.dcache.MemWay[way].ValidBits[index]),
.dirty(testbench.dut.wallypipelinedsoc.hart.lsu.dcache.MemWay[way].DirtyBits[index]),
.data(testbench.dut.wallypipelinedsoc.hart.lsu.dcache.MemWay[way].word[cacheWord].CacheDataMem.StoredData[index]),
.index(index),
.cacheWord(cacheWord),
.CacheData(CacheData[way][index][cacheWord]),
.CacheAdr(CacheAdr[way][index][cacheWord]),
.CacheTag(CacheTag[way][index][cacheWord]),
.CacheValid(CacheValid[way][index][cacheWord]),
.CacheDirty(CacheDirty[way][index][cacheWord]));
end
end
endgenerate
end
integer i, j, k;
@ -879,7 +871,7 @@ module DCacheFlushFSM
endmodule
module copyShadow
#(parameter tagstart, logblockbytelen)
#(parameter tagstart, loglinebytelen)
(input logic clk,
input logic start,
input logic [`PA_BITS-1:tagstart] tag,
@ -900,7 +892,7 @@ module copyShadow
CacheValid = valid;
CacheDirty = dirty;
CacheData = data;
CacheAdr = (tag << tagstart) + (index << logblockbytelen) + (cacheWord << $clog2(`XLEN/8));
CacheAdr = (tag << tagstart) + (index << loglinebytelen) + (cacheWord << $clog2(`XLEN/8));
end
end

View File

@ -22,7 +22,7 @@
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// When letting Wally go for it, let wally generate own interrupts
// When letting Wally go for it, let wally make own interrupts
///////////////////////////////////////////
`include "wally-config.vh"
@ -36,7 +36,7 @@
// 4: print memory accesses whenever they happen
// 5: print everything
module testbench();
module testbench;
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// CONFIG ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@ -280,13 +280,6 @@ module testbench();
`INIT_CHECKPOINT_SIMPLE_ARRAY(RF, [`XLEN-1:0],31,1);
`INIT_CHECKPOINT_SIMPLE_ARRAY(HPMCOUNTER, [`XLEN-1:0],`COUNTERS-1,3);
generate
genvar i;
/* -----\/----- EXCLUDED -----\/-----
`INIT_CHECKPOINT_GENBLK_ARRAY(PMP_BASE, PMPCFG, [7:0],`PMP_ENTRIES-1,0);
`INIT_CHECKPOINT_GENBLK_ARRAY(PMP_BASE, PMPADDR, [`XLEN-1:0],`PMP_ENTRIES-1,0);
-----/\----- EXCLUDED -----/\----- */
endgenerate
`INIT_CHECKPOINT_VAL(PC, [`XLEN-1:0]);
`INIT_CHECKPOINT_VAL(MEDELEG, [`XLEN-1:0]);
`INIT_CHECKPOINT_VAL(MIDELEG, [`XLEN-1:0]);

View File

@ -71,7 +71,6 @@ logic [3:0] dummy;
// check assertions for a legal configuration
riscvassertions riscvassertions();
logging logging(clk, reset, dut.uncore.HADDR, dut.uncore.HTRANS);
// pick tests based on modes supported
initial begin
@ -88,7 +87,7 @@ logic [3:0] dummy;
"arch64d": if (`D_SUPPORTED) tests = arch64d;
"imperas64i": tests = imperas64i;
"imperas64p": tests = imperas64p;
"imperas64mmu": if (`MEM_VIRTMEM) tests = imperas64mmu;
// "imperas64mmu": if (`MEM_VIRTMEM) tests = imperas64mmu;
"imperas64f": if (`F_SUPPORTED) tests = imperas64f;
"imperas64d": if (`D_SUPPORTED) tests = imperas64d;
"imperas64m": if (`M_SUPPORTED) tests = imperas64m;
@ -111,7 +110,7 @@ logic [3:0] dummy;
"arch32f": if (`F_SUPPORTED) tests = arch32f;
"imperas32i": tests = imperas32i;
"imperas32p": tests = imperas32p;
"imperas32mmu": if (`MEM_VIRTMEM) tests = imperas32mmu;
// "imperas32mmu": if (`MEM_VIRTMEM) tests = imperas32mmu;
"imperas32f": if (`F_SUPPORTED) tests = imperas32f;
"imperas32m": if (`M_SUPPORTED) tests = imperas32m;
"imperas32a": if (`A_SUPPORTED) tests = imperas32a;
@ -297,13 +296,8 @@ logic [3:0] dummy;
// or sw gp, -56(t0)
// or on a jump to self infinite loop (6f) for RISC-V Arch tests
logic ecf; // remove this once we don't rely on old Imperas tests with Ecalls
generate
if (`ZICSR_SUPPORTED) begin
assign ecf = dut.hart.priv.priv.EcallFaultM;
end else begin
assign ecf = 0;
end
endgenerate
if (`ZICSR_SUPPORTED) assign ecf = dut.hart.priv.priv.EcallFaultM;
else assign ecf = 0;
assign DCacheFlushStart = ecf &
(dut.hart.ieu.dp.regf.rf[3] == 1 |
(dut.hart.ieu.dp.regf.we3 &
@ -311,24 +305,17 @@ logic [3:0] dummy;
dut.hart.ieu.dp.regf.wd3 == 1)) |
(dut.hart.ifu.InstrM == 32'h6f | dut.hart.ifu.InstrM == 32'hfc32a423 | dut.hart.ifu.InstrM == 32'hfc32a823) & dut.hart.ieu.c.InstrValidM;
// **** Fix when the check in the shadow ram is fixed.
DCacheFlushFSM DCacheFlushFSM(.clk(clk),
.reset(reset),
.start(DCacheFlushStart),
.done(DCacheFlushDone));
generate
// initialize the branch predictor
if (`BPRED_ENABLED == 1) begin : bpred
initial begin
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem);
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.mem);
end
end
endgenerate
// initialize the branch predictor
if (`BPRED_ENABLED == 1)
initial begin
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem);
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.mem);
end
endmodule
module riscvassertions;
@ -339,14 +326,14 @@ module riscvassertions;
assert (`F_SUPPORTED | ~`D_SUPPORTED) else $error("Can't support double (D) without supporting float (F)");
assert (`XLEN == 64 | ~`D_SUPPORTED) else $error("Wally does not yet support D extensions on RV32");
assert (`DCACHE_WAYSIZEINBYTES <= 4096 | `MEM_DCACHE == 0 | `MEM_VIRTMEM == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
assert (`DCACHE_BLOCKLENINBITS >= 128 | `MEM_DCACHE == 0) else $error("DCACHE_BLOCKLENINBITS must be at least 128 when caches are enabled");
assert (`DCACHE_BLOCKLENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_BLOCKLENINBITS must be smaller than way size");
assert (`DCACHE_LINELENINBITS >= 128 | `MEM_DCACHE == 0) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled");
assert (`DCACHE_LINELENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size");
assert (`ICACHE_WAYSIZEINBYTES <= 4096 | `MEM_ICACHE == 0 | `MEM_VIRTMEM == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
assert (`ICACHE_BLOCKLENINBITS >= 32 | `MEM_ICACHE == 0) else $error("ICACHE_BLOCKLENINBITS must be at least 32 when caches are enabled");
assert (`ICACHE_BLOCKLENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_BLOCKLENINBITS must be smaller than way size");
assert (2**$clog2(`DCACHE_BLOCKLENINBITS) == `DCACHE_BLOCKLENINBITS | `MEM_DCACHE==0) else $error("DCACHE_BLOCKLENINBITS must be a power of 2");
assert (`ICACHE_LINELENINBITS >= 32 | `MEM_ICACHE == 0) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled");
assert (`ICACHE_LINELENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size");
assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS | `MEM_DCACHE==0) else $error("DCACHE_LINELENINBITS must be a power of 2");
assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES | `MEM_DCACHE==0) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2");
assert (2**$clog2(`ICACHE_BLOCKLENINBITS) == `ICACHE_BLOCKLENINBITS | `MEM_ICACHE==0) else $error("ICACHE_BLOCKLENINBITS must be a power of 2");
assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS | `MEM_ICACHE==0) else $error("ICACHE_LINELENINBITS must be a power of 2");
assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES | `MEM_ICACHE==0) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2");
assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES | `MEM_VIRTMEM==0) else $error("ITLB_ENTRIES must be a power of 2");
assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES | `MEM_VIRTMEM==0) else $error("DTLB_ENTRIES must be a power of 2");
@ -371,16 +358,15 @@ module DCacheFlushFSM
logic [`XLEN-1:0] ShadowRAM[`RAM_BASE>>(1+`XLEN/32):(`RAM_RANGE+`RAM_BASE)>>1+(`XLEN/32)];
generate
if(`MEM_DCACHE) begin
localparam integer numlines = testbench.dut.hart.lsu.dcache.dcache.NUMLINES;
localparam integer numways = testbench.dut.hart.lsu.dcache.dcache.NUMWAYS;
localparam integer blockbytelen = testbench.dut.hart.lsu.dcache.dcache.BLOCKBYTELEN;
localparam integer numwords = testbench.dut.hart.lsu.dcache.dcache.BLOCKLEN/`XLEN;
localparam integer linebytelen = testbench.dut.hart.lsu.dcache.dcache.LINEBYTELEN;
localparam integer numwords = testbench.dut.hart.lsu.dcache.dcache.LINELEN/`XLEN;
localparam integer lognumlines = $clog2(numlines);
localparam integer logblockbytelen = $clog2(blockbytelen);
localparam integer loglinebytelen = $clog2(linebytelen);
localparam integer lognumways = $clog2(numways);
localparam integer tagstart = lognumlines + logblockbytelen;
localparam integer tagstart = lognumlines + loglinebytelen;
@ -394,7 +380,7 @@ module DCacheFlushFSM
for(way = 0; way < numways; way++) begin
for(cacheWord = 0; cacheWord < numwords; cacheWord++) begin
copyShadow #(.tagstart(tagstart),
.logblockbytelen(logblockbytelen))
.loglinebytelen(loglinebytelen))
copyShadow(.clk,
.start,
.tag(testbench.dut.hart.lsu.dcache.dcache.MemWay[way].CacheTagMem.StoredData[index]),
@ -431,19 +417,11 @@ module DCacheFlushFSM
end
endgenerate
flop #(1) doneReg(.clk(clk),
.d(start),
.q(done));
flop #(1) doneReg(.clk, .d(start), .q(done));
endmodule
module copyShadow
#(parameter tagstart, logblockbytelen)
#(parameter tagstart, loglinebytelen)
(input logic clk,
input logic start,
input logic [`PA_BITS-1:tagstart] tag,
@ -464,7 +442,7 @@ module copyShadow
CacheValid = valid;
CacheDirty = dirty;
CacheData = data;
CacheAdr = (tag << tagstart) + (index << logblockbytelen) + (cacheWord << $clog2(`XLEN/8));
CacheAdr = (tag << tagstart) + (index << loglinebytelen) + (cacheWord << $clog2(`XLEN/8));
end
end

View File

@ -36,6 +36,7 @@ string tvpaths[] = '{
"../../tests/imperas-riscv-tests/work/"
};
// *** make sure these are somewhere
string imperas64a[] = '{
`MYIMPERASTEST,
"rv64a/WALLY-AMO", "2110",
@ -48,7 +49,7 @@ string tvpaths[] = '{
"rv32a/WALLY-LRSC", "2110"
};
string imperas32mmu[] = '{
/* string imperas32mmu[] = '{
`MYIMPERASTEST,
"rv32mmu/WALLY-MMU-SV32", "3000",
"rv32mmu/WALLY-PMP", "3000"
@ -61,7 +62,7 @@ string tvpaths[] = '{
"rv64mmu/WALLY-MMU-SV39", "3000",
"rv64mmu/WALLY-PMP", "3000"
//"rv64mmu/WALLY-PMA", "3000"
};
}; */
// *** restore CSR tests from Imperas old