mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
b53ab27b26
17
bin/elf2hex.sh
Executable file
17
bin/elf2hex.sh
Executable 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) (
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -1,3 +1,3 @@
|
||||
vsim -c <<!
|
||||
do wally-pipelined-batch.do rv64gc imperas64i
|
||||
do wally-pipelined-batch.do rv32gc wally32priv
|
||||
!
|
||||
|
@ -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
269
pipelined/src/cache/cache.sv
vendored
Normal 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
398
pipelined/src/cache/cachefsm.sv
vendored
Normal 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
|
||||
|
165
pipelined/src/cache/cachereplacementpolicy.sv
vendored
165
pipelined/src/cache/cachereplacementpolicy.sv
vendored
@ -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
|
||||
|
||||
|
||||
|
63
pipelined/src/cache/cacheway.sv
vendored
63
pipelined/src/cache/cacheway.sv
vendored
@ -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
|
||||
|
||||
|
||||
|
140
pipelined/src/cache/dcache.sv
vendored
140
pipelined/src/cache/dcache.sv
vendored
@ -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);
|
||||
|
14
pipelined/src/cache/dcachefsm.sv
vendored
14
pipelined/src/cache/dcachefsm.sv
vendored
@ -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
|
||||
|
86
pipelined/src/cache/icache.sv
vendored
86
pipelined/src/cache/icache.sv
vendored
@ -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}}};
|
||||
|
||||
|
4
pipelined/src/cache/icachefsm.sv
vendored
4
pipelined/src/cache/icachefsm.sv
vendored
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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}}} :
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
(
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user