mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge pull request #508 from ross144/main
fixes to branch predictor post processing scripts. ch 21 instructions work in newly cloned repo
This commit is contained in:
commit
d1876f4edb
2
.gitignore
vendored
2
.gitignore
vendored
@ -180,3 +180,5 @@ sim/branch*.log
|
|||||||
benchmarks/embench/wally*.json
|
benchmarks/embench/wally*.json
|
||||||
benchmarks/embench/run*
|
benchmarks/embench/run*
|
||||||
sim/cfi.log
|
sim/cfi.log
|
||||||
|
sim/cfi/*
|
||||||
|
sim/branch/*
|
||||||
|
@ -43,6 +43,7 @@ sim: modelsim_build_memfile modelsim_run speed
|
|||||||
|
|
||||||
# launches modelsim to simulate tests on wally
|
# launches modelsim to simulate tests on wally
|
||||||
modelsim_run:
|
modelsim_run:
|
||||||
|
mkdir -p ../../sim/wkdir
|
||||||
(cd ../../sim/ && vsim -c -do "do wally-batch.do rv32gc embench")
|
(cd ../../sim/ && vsim -c -do "do wally-batch.do rv32gc embench")
|
||||||
cd ../../benchmarks/embench/
|
cd ../../benchmarks/embench/
|
||||||
|
|
||||||
@ -82,4 +83,4 @@ clean:
|
|||||||
allclean: clean
|
allclean: clean
|
||||||
rm -rf $(embench_dir)/logs/
|
rm -rf $(embench_dir)/logs/
|
||||||
|
|
||||||
# riscv64-unknown-elf-gcc -O2 -g -nostartfiles -I/home/harris/riscv-wally/addins/embench-iot/support -I/home/harris/riscv-wally/addins/embench-iot/config/riscv32/boards/ri5cyverilator -I/home/harris/riscv-wally/addins/embench-iot/config/riscv32/chips/generic -I/home/harris/riscv-wally/addins/embench-iot/config/riscv32 -DCPU_MHZ=1 -DWARMUP_HEAT=1 -o main.o /home/harris/riscv-wally/addins/embench-iot/support/main.c
|
# riscv64-unknown-elf-gcc -O2 -g -nostartfiles -I/home/harris/riscv-wally/addins/embench-iot/support -I/home/harris/riscv-wally/addins/embench-iot/config/riscv32/boards/ri5cyverilator -I/home/harris/riscv-wally/addins/embench-iot/config/riscv32/chips/generic -I/home/harris/riscv-wally/addins/embench-iot/config/riscv32 -DCPU_MHZ=1 -DWARMUP_HEAT=1 -o main.o /home/harris/riscv-wally/addins/embench-iot/support/main.c
|
||||||
|
@ -40,18 +40,18 @@ do
|
|||||||
lines=`sim_bp gshare 16 16 $Size 1 $File | tail -5`
|
lines=`sim_bp gshare 16 16 $Size 1 $File | tail -5`
|
||||||
Total=`echo "$lines" | head -1 | awk '{print $5}'`
|
Total=`echo "$lines" | head -1 | awk '{print $5}'`
|
||||||
Miss=`echo "$lines" | tail -2 | head -1 | awk '{print $8}'`
|
Miss=`echo "$lines" | tail -2 | head -1 | awk '{print $8}'`
|
||||||
BMDR=`echo "$Miss / $Total" | bc -l`
|
BMDR=`echo "100.0 * $Miss / $Total" | bc -l`
|
||||||
BMDRArray+=("$BMDR")
|
BMDRArray+=("$BMDR")
|
||||||
if [ $Miss -eq 0 ]; then
|
if [ $Miss -eq 0 ]; then
|
||||||
Product=`echo "scale=200; $Product / $Total" | bc -l`
|
Product=`echo "scale=200; $Product * 100 / $Total" | bc -l`
|
||||||
else
|
else
|
||||||
Product=`echo "scale=200; $Product * $Miss / $Total" | bc -l`
|
Product=`echo "scale=200; $Product * $BMDR" | bc -l`
|
||||||
fi
|
fi
|
||||||
Count=$((Count+1))
|
Count=$((Count+1))
|
||||||
done
|
done
|
||||||
# with such long precision bc outputs onto multiple lines
|
# with such long precision bc outputs onto multiple lines
|
||||||
# must remove \n and \ from string
|
# must remove \n and \ from string
|
||||||
Product=`echo "$Product" | tr -d '\n' | tr -d '\\\'`
|
Product=`echo "$Product" | tr -d '\n' | tr -d '\\\'`
|
||||||
GeoMean=`perl -E "say $Product**(1/$Count) * 100"`
|
GeoMean=`perl -E "say $Product**(1/$Count)"`
|
||||||
echo "$Pred$Size $GeoMean"
|
echo "$Pred$Size $GeoMean"
|
||||||
done
|
done
|
||||||
|
@ -46,7 +46,7 @@ do
|
|||||||
do
|
do
|
||||||
#echo "sim_bp $Pred $Size $Size 18 1 $File | tail -1 | awk '{print $4}'"
|
#echo "sim_bp $Pred $Size $Size 18 1 $File | tail -1 | awk '{print $4}'"
|
||||||
#echo "sim_bp $Pred $SizeString $File | tail -1 | awk '{print $4}'"
|
#echo "sim_bp $Pred $SizeString $File | tail -1 | awk '{print $4}'"
|
||||||
BMDR=`sim_bp $Pred $SizeString $File | tail -1 | awk '{print $4}'`
|
BMDR=`sim_bp -c $Pred $SizeString $File | tail -1 | awk '{print $4}'`
|
||||||
Product=`echo "$Product * $BMDR" | bc`
|
Product=`echo "$Product * $BMDR" | bc`
|
||||||
Count=$((Count+1))
|
Count=$((Count+1))
|
||||||
done
|
done
|
||||||
|
@ -32,12 +32,13 @@ import math
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
RefDataBP = [('twobitCModel6', 'twobitCModel', 64, 9.65280765420711), ('twobitCModel8', 'twobitCModel', 256, 8.75120245829945), ('twobitCModel10', 'twobitCModel', 1024, 8.1318382397263),
|
|
||||||
('twobitCModel12', 'twobitCModel', 4096, 7.53026646633342), ('twobitCModel14', 'twobitCModel', 16384, 6.07679338544009), ('twobitCModel16', 'twobitCModel', 65536, 6.07679338544009),
|
RefDataBP = [('twobitCModel6', 'twobitCModel', 64, 10.0060297551637), ('twobitCModel8', 'twobitCModel', 256, 8.4320392215602), ('twobitCModel10', 'twobitCModel', 1024, 7.29493318805151),
|
||||||
('gshareCModel6', 'gshareCModel', 64, 10.6602835418646), ('gshareCModel8', 'gshareCModel', 256, 8.38384710559667), ('gshareCModel10', 'gshareCModel', 1024, 6.36847432155534),
|
('twobitCModel12', 'twobitCModel', 4096, 6.84739616147794), ('twobitCModel14', 'twobitCModel', 16384, 5.68432926870082), ('twobitCModel16', 'twobitCModel', 65536, 5.68432926870082),
|
||||||
('gshareCModel12', 'gshareCModel', 4096, 3.91108491151983), ('gshareCModel14', 'gshareCModel', 16384, 2.83926519215395), ('gshareCModel16', 'gshareCModel', 65536, .60213659066941)]
|
('gshareCModel6', 'gshareCModel', 64, 11.4737703417701), ('gshareCModel8', 'gshareCModel', 256, 8.52341470761974), ('gshareCModel10', 'gshareCModel', 1024, 6.32975690693015),
|
||||||
RefDataBTB = [('BTBCModel6', 'BTBCModel', 64, 1.11806778745097), ('BTBCModel8', 'BTBCModel', 256, 0.183833943219956), ('BTBCModel10', 'BTBCModel', 1024, 0.0109271020749376),
|
('gshareCModel12', 'gshareCModel', 4096, 4.55424632377659), ('gshareCModel14', 'gshareCModel', 16384, 3.54251547725509), ('gshareCModel16', 'gshareCModel', 65536, 1.90424999467293)]
|
||||||
('BTBCModel12', 'BTBCModel', 4096, 0.00437600802791213), ('BTBCModel14', 'BTBCModel', 16384, 0.00188756234204305), ('BTBCModel16', 'BTBCModel', 65536, 0.00188756234204305)]
|
RefDataBTB = [('BTBCModel6', 'BTBCModel', 64, 1.51480272475844), ('BTBCModel8', 'BTBCModel', 256, 0.209057900418965), ('BTBCModel10', 'BTBCModel', 1024, 0.0117345454469572),
|
||||||
|
('BTBCModel12', 'BTBCModel', 4096, 0.00125540990359826), ('BTBCModel14', 'BTBCModel', 16384, 0.000732471628510962), ('BTBCModel16', 'BTBCModel', 65536, 0.000732471628510962)]
|
||||||
|
|
||||||
def ParseBranchListFile(path):
|
def ParseBranchListFile(path):
|
||||||
'''Take the path to the list of Questa Sim log files containing the performance counters outputs. File
|
'''Take the path to the list of Questa Sim log files containing the performance counters outputs. File
|
||||||
@ -254,9 +255,9 @@ def BarGraph(seriesDict, xlabelList, BenchPerRow, FileName, IncludeLegend):
|
|||||||
fig = plt.subplots(figsize = (EffectiveNumInGroup*BenchPerRow/8, 4))
|
fig = plt.subplots(figsize = (EffectiveNumInGroup*BenchPerRow/8, 4))
|
||||||
colors = ['blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'black', 'black', 'black', 'black', 'black', 'black']
|
colors = ['blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'black', 'black', 'black', 'black', 'black', 'black']
|
||||||
for name in seriesDict:
|
for name in seriesDict:
|
||||||
xpos = np.arange(BenchPerRow)
|
|
||||||
xpos = [x + index*barWidth for x in xpos]
|
|
||||||
values = seriesDict[name]
|
values = seriesDict[name]
|
||||||
|
xpos = np.arange(len(values))
|
||||||
|
xpos = [x + index*barWidth for x in xpos]
|
||||||
plt.bar(xpos, Inversion(values), width=barWidth, edgecolor='grey', label=name, color=colors[index%len(colors)])
|
plt.bar(xpos, Inversion(values), width=barWidth, edgecolor='grey', label=name, color=colors[index%len(colors)])
|
||||||
index += 1
|
index += 1
|
||||||
plt.xticks([r + barWidth*(NumberInGroup/2-0.5) for r in range(0, BenchPerRow)], xlabelList)
|
plt.xticks([r + barWidth*(NumberInGroup/2-0.5) for r in range(0, BenchPerRow)], xlabelList)
|
||||||
@ -275,7 +276,7 @@ def SelectPartition(xlabelListBig, seriesDictBig, group, BenchPerRow):
|
|||||||
return(xlabelListTrunk, seriesDictTrunk)
|
return(xlabelListTrunk, seriesDictTrunk)
|
||||||
|
|
||||||
|
|
||||||
def ReportAsGraph(benchmarkDict, bar):
|
def ReportAsGraph(benchmarkDict, bar, FileName):
|
||||||
def FormatToPlot(currBenchmark):
|
def FormatToPlot(currBenchmark):
|
||||||
names = []
|
names = []
|
||||||
sizes = []
|
sizes = []
|
||||||
@ -329,8 +330,8 @@ def ReportAsGraph(benchmarkDict, bar):
|
|||||||
axes.set_xticks(xdata)
|
axes.set_xticks(xdata)
|
||||||
axes.set_xticklabels(xdata)
|
axes.set_xticklabels(xdata)
|
||||||
axes.grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)
|
axes.grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)
|
||||||
plt.show()
|
if(FileName == None): plt.show()
|
||||||
|
else: plt.savefig(FileName)
|
||||||
|
|
||||||
# if(not args.summary):
|
# if(not args.summary):
|
||||||
# size = len(benchmarkDict)
|
# size = len(benchmarkDict)
|
||||||
@ -389,7 +390,7 @@ def ReportAsGraph(benchmarkDict, bar):
|
|||||||
# on each piece.
|
# on each piece.
|
||||||
for row in range(0, math.ceil(NumBenchmarks / BenchPerRow)):
|
for row in range(0, math.ceil(NumBenchmarks / BenchPerRow)):
|
||||||
(xlabelListTrunk, seriesDictTrunk) = SelectPartition(xlabelListBig, seriesDictBig, row, BenchPerRow)
|
(xlabelListTrunk, seriesDictTrunk) = SelectPartition(xlabelListBig, seriesDictBig, row, BenchPerRow)
|
||||||
FileName = 'barSegment%d.png' % row
|
FileName = 'barSegment%d.svg' % row
|
||||||
groupLen = len(xlabelListTrunk)
|
groupLen = len(xlabelListTrunk)
|
||||||
BarGraph(seriesDictTrunk, xlabelListTrunk, groupLen, FileName, (row == 0))
|
BarGraph(seriesDictTrunk, xlabelListTrunk, groupLen, FileName, (row == 0))
|
||||||
|
|
||||||
@ -414,7 +415,8 @@ displayMode.add_argument('--text', action='store_const', help='Display in text f
|
|||||||
displayMode.add_argument('--table', action='store_const', help='Display in text format only.', default=False, const=True)
|
displayMode.add_argument('--table', action='store_const', help='Display in text format only.', default=False, const=True)
|
||||||
displayMode.add_argument('--gui', action='store_const', help='Display in text format only.', default=False, const=True)
|
displayMode.add_argument('--gui', action='store_const', help='Display in text format only.', default=False, const=True)
|
||||||
displayMode.add_argument('--debug', action='store_const', help='Display in text format only.', default=False, const=True)
|
displayMode.add_argument('--debug', action='store_const', help='Display in text format only.', default=False, const=True)
|
||||||
parser.add_argument('sources', nargs=1)
|
parser.add_argument('sources', nargs=1, help='File lists the input Questa transcripts to process.')
|
||||||
|
parser.add_argument('FileName', metavar='FileName', type=str, nargs='?', help='output graph to file <name>.png If not included outputs to screen.', default=None)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -454,7 +456,7 @@ if(ReportMode == 'text'):
|
|||||||
ReportAsText(benchmarkDict)
|
ReportAsText(benchmarkDict)
|
||||||
|
|
||||||
if(ReportMode == 'gui'):
|
if(ReportMode == 'gui'):
|
||||||
ReportAsGraph(benchmarkDict, args.bar)
|
ReportAsGraph(benchmarkDict, args.bar, args.FileName)
|
||||||
|
|
||||||
# *** this is only needed of -b (no -s)
|
# *** this is only needed of -b (no -s)
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
gshare6.log gshare 6
|
../logs/rv32gc_gshare6.log gshare 6
|
||||||
gshare8.log gshare 8
|
../logs/rv32gc_gshare8.log gshare 8
|
||||||
gshare10.log gshare 10
|
../logs/rv32gc_gshare10.log gshare 10
|
||||||
gshare12.log gshare 12
|
../logs/rv32gc_gshare12.log gshare 12
|
||||||
gshare14.log gshare 14
|
../logs/rv32gc_gshare14.log gshare 14
|
||||||
gshare16.log gshare 16
|
../logs/rv32gc_gshare16.log gshare 16
|
||||||
twobit6.log twobit 6
|
../logs/rv32gc_twobit6.log twobit 6
|
||||||
twobit8.log twobit 8
|
../logs/rv32gc_twobit8.log twobit 8
|
||||||
twobit10.log twobit 10
|
../logs/rv32gc_twobit10.log twobit 10
|
||||||
twobit12.log twobit 12
|
../logs/rv32gc_twobit12.log twobit 12
|
||||||
twobit14.log twobit 14
|
../logs/rv32gc_twobit14.log twobit 14
|
||||||
twobit16.log twobit 16
|
../logs/rv32gc_twobit16.log twobit 16
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
btb6.log btb 6
|
../logs/rv32gc_BTB6.log btb 6
|
||||||
btb8.log btb 8
|
../logs/rv32gc_BTB8.log btb 8
|
||||||
btb10.log btb 10
|
../logs/rv32gc_BTB10.log btb 10
|
||||||
btb12.log btb 12
|
../logs/rv32gc_BTB12.log btb 12
|
||||||
btb14.log btb 14
|
../logs/rv32gc_BTB14.log btb 14
|
||||||
btb16.log btb 16
|
../logs/rv32gc_BTB16.log btb 16
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
class6.log class 6
|
../logs/rv32gc_class6.log class 6
|
||||||
class8.log class 8
|
../logs/rv32gc_class8.log class 8
|
||||||
class10.log class 10
|
../logs/rv32gc_class10.log class 10
|
||||||
class12.log class 12
|
../logs/rv32gc_class12.log class 12
|
||||||
class14.log class 14
|
../logs/rv32gc_class14.log class 14
|
||||||
class16.log class 16
|
../logs/rv32gc_class16.log class 16
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
ras3.log ras 3
|
../logs/rv32gc_RAS3.log ras 3
|
||||||
ras4.log ras 4
|
../logs/rv32gc_RAS4.log ras 4
|
||||||
ras6.log ras 6
|
../logs/rv32gc_RAS6.log ras 6
|
||||||
ras10.log ras 10
|
../logs/rv32gc_RAS10.log ras 10
|
||||||
ras16.log ras 16
|
../logs/rv32gc_RAS16.log ras 16
|
||||||
|
@ -132,7 +132,7 @@ def main():
|
|||||||
# BTB and class size sweep
|
# BTB and class size sweep
|
||||||
bpdSize = [6, 8, 10, 12, 14, 16]
|
bpdSize = [6, 8, 10, 12, 14, 16]
|
||||||
for CurrBPSize in bpdSize:
|
for CurrBPSize in bpdSize:
|
||||||
name = 'BTB'+str(CurrBPSize)
|
name = 'class'+str(CurrBPSize)
|
||||||
configOptions = "+define+INSTR_CLASS_PRED=1 +define+BPRED_OVERRIDE +define+BPRED_TYPE=\`BP_GSHARE" + "+define+BPRED_SIZE=16" + "+define+RAS_SIZE=16+define+BTB_SIZE=" + str(CurrBPSize) + "+define+BTB_OVERRIDE"
|
configOptions = "+define+INSTR_CLASS_PRED=1 +define+BPRED_OVERRIDE +define+BPRED_TYPE=\`BP_GSHARE" + "+define+BPRED_SIZE=16" + "+define+RAS_SIZE=16+define+BTB_SIZE=" + str(CurrBPSize) + "+define+BTB_OVERRIDE"
|
||||||
tc = TestCase(
|
tc = TestCase(
|
||||||
name=name,
|
name=name,
|
||||||
|
@ -63,10 +63,10 @@ if {$2 eq "buildroot"} {
|
|||||||
# start and run simulation
|
# start and run simulation
|
||||||
if { $coverage } {
|
if { $coverage } {
|
||||||
echo "wally-batch buildroot coverage"
|
echo "wally-batch buildroot coverage"
|
||||||
vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G -o testbenchopt +cover=sbecf
|
vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -o testbenchopt +cover=sbecf
|
||||||
vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7 -cover
|
vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7 -cover
|
||||||
} else {
|
} else {
|
||||||
vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G -o testbenchopt
|
vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -o testbenchopt
|
||||||
vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7
|
vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ if {$2 eq "buildroot"} {
|
|||||||
} elseif {$2 eq "buildroot-no-trace"} {
|
} elseif {$2 eq "buildroot-no-trace"} {
|
||||||
vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
|
vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
|
||||||
# start and run simulation
|
# start and run simulation
|
||||||
vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G -G NO_SPOOFING=1 -o testbenchopt
|
vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G NO_SPOOFING=1 -o testbenchopt
|
||||||
vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7
|
vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7
|
||||||
|
|
||||||
#-- Run the Simulation
|
#-- Run the Simulation
|
||||||
|
13
src/cache/cache.sv
vendored
13
src/cache/cache.sv
vendored
@ -98,8 +98,6 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
logic SelWay;
|
logic SelWay;
|
||||||
logic [LINELEN/8-1:0] LineByteMask;
|
logic [LINELEN/8-1:0] LineByteMask;
|
||||||
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
|
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
|
||||||
logic ZeroCacheLine;
|
|
||||||
logic [LINELEN-1:0] PreLineWriteData;
|
|
||||||
genvar index;
|
genvar index;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -161,11 +159,6 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Write Path
|
// Write Path
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
if(P.ZICBOZ_SUPPORTED) begin : cboz_supported
|
|
||||||
mux2 #(LINELEN) WriteDataMux(FetchBuffer, '0, ZeroCacheLine, PreLineWriteData);
|
|
||||||
end else begin
|
|
||||||
assign PreLineWriteData = FetchBuffer;
|
|
||||||
end
|
|
||||||
if(!READ_ONLY_CACHE) begin:WriteSelLogic
|
if(!READ_ONLY_CACHE) begin:WriteSelLogic
|
||||||
logic [LINELEN/8-1:0] DemuxedByteMask, FetchBufferByteSel;
|
logic [LINELEN/8-1:0] DemuxedByteMask, FetchBufferByteSel;
|
||||||
|
|
||||||
@ -185,14 +178,14 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
// Merge write data into fetched cache line for store miss
|
// Merge write data into fetched cache line for store miss
|
||||||
for(index = 0; index < LINELEN/8; index++) begin
|
for(index = 0; index < LINELEN/8; index++) begin
|
||||||
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
|
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
|
||||||
.d1(PreLineWriteData[8*index+7:8*index]), .s(FetchBufferByteSel[index] | ZeroCacheLine), .y(LineWriteData[8*index+7:8*index]));
|
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index] & ~CMOp[3]), .y(LineWriteData[8*index+7:8*index]));
|
||||||
end
|
end
|
||||||
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
|
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin:WriteSelLogic
|
begin:WriteSelLogic
|
||||||
// No need for this mux if the cache does not handle writes.
|
// No need for this mux if the cache does not handle writes.
|
||||||
assign LineWriteData = PreLineWriteData;
|
assign LineWriteData = FetchBuffer;
|
||||||
assign LineByteMask = '1;
|
assign LineByteMask = '1;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -227,7 +220,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
.FlushStage, .CacheRW, .Stall,
|
.FlushStage, .CacheRW, .Stall,
|
||||||
.CacheHit, .LineDirty, .CacheStall, .CacheCommitted,
|
.CacheHit, .LineDirty, .CacheStall, .CacheCommitted,
|
||||||
.CacheMiss, .CacheAccess, .SelAdr, .SelWay,
|
.CacheMiss, .CacheAccess, .SelAdr, .SelWay,
|
||||||
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .ZeroCacheLine, .SelWriteback, .SelFlush,
|
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback, .SelFlush,
|
||||||
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
|
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
|
||||||
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
|
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
|
||||||
.InvalidateCache, .CMOp, .CacheEn, .LRUWriteEn);
|
.InvalidateCache, .CMOp, .CacheEn, .LRUWriteEn);
|
||||||
|
6
src/cache/cachefsm.sv
vendored
6
src/cache/cachefsm.sv
vendored
@ -58,7 +58,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
output logic ClearValid, // Clear the valid bit in the selected way and set
|
output logic ClearValid, // Clear the valid bit in the selected way and set
|
||||||
output logic SetDirty, // Set the dirty bit in the selected way and set
|
output logic SetDirty, // Set the dirty bit in the selected way and set
|
||||||
output logic ClearDirty, // Clear the dirty bit in the selected way and set
|
output logic ClearDirty, // Clear the dirty bit in the selected way and set
|
||||||
output logic ZeroCacheLine, // Write zeros to all bytes of cacheline
|
|
||||||
output logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
|
output logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
|
||||||
output logic LRUWriteEn, // Update the LRU state
|
output logic LRUWriteEn, // Update the LRU state
|
||||||
output logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
|
output logic SelFlush, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
|
||||||
@ -130,8 +129,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
|
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
|
||||||
else NextState = STATE_READY;
|
else NextState = STATE_READY;
|
||||||
// exclusion-tag-start: icache case
|
// exclusion-tag-start: icache case
|
||||||
STATE_WRITEBACK: if (CacheBusAck & (CMOp[1] | CMOp[2])) NextState = STATE_READ_HOLD;
|
STATE_WRITEBACK: if(CacheBusAck & ~CMOp[3]) NextState = STATE_FETCH;
|
||||||
else if(CacheBusAck & ~CMOp[3]) NextState = STATE_FETCH;
|
|
||||||
else if(CacheBusAck) NextState = STATE_READ_HOLD;
|
else if(CacheBusAck) NextState = STATE_READ_HOLD;
|
||||||
else NextState = STATE_WRITEBACK;
|
else NextState = STATE_WRITEBACK;
|
||||||
// eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same time as getting back the bus ack.
|
// eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same time as getting back the bus ack.
|
||||||
@ -175,8 +173,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
|||||||
assign SelWay = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOp[1] | CMOp[2])) | (P.ZICBOZ_SUPPORTED & CacheBusAck & CMOp[3]))) |
|
assign SelWay = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOp[1] | CMOp[2])) | (P.ZICBOZ_SUPPORTED & CacheBusAck & CMOp[3]))) |
|
||||||
(CurrState == STATE_READY & ((AnyMiss & LineDirty) | (P.ZICBOZ_SUPPORTED & CMOZeroNoEviction & ~CacheHit))) |
|
(CurrState == STATE_READY & ((AnyMiss & LineDirty) | (P.ZICBOZ_SUPPORTED & CMOZeroNoEviction & ~CacheHit))) |
|
||||||
(CurrState == STATE_WRITE_LINE);
|
(CurrState == STATE_WRITE_LINE);
|
||||||
assign ZeroCacheLine = P.ZICBOZ_SUPPORTED & ((CurrState == STATE_READY & CMOZeroNoEviction) |
|
|
||||||
(CurrState == STATE_WRITEBACK & (CMOp[3] & CacheBusAck)));
|
|
||||||
assign SelWriteback = (CurrState == STATE_WRITEBACK & (CMOp[1] | CMOp[2] | ~CacheBusAck)) |
|
assign SelWriteback = (CurrState == STATE_WRITEBACK & (CMOp[1] | CMOp[2] | ~CacheBusAck)) |
|
||||||
(CurrState == STATE_READY & AnyMiss & LineDirty);
|
(CurrState == STATE_READY & AnyMiss & LineDirty);
|
||||||
assign SelFlush = (CurrState == STATE_READY & FlushCache) |
|
assign SelFlush = (CurrState == STATE_READY & FlushCache) |
|
||||||
|
16
src/cache/cacheway.sv
vendored
16
src/cache/cacheway.sv
vendored
@ -65,10 +65,10 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
logic [LINELEN-1:0] ReadDataLine;
|
logic [LINELEN-1:0] ReadDataLine;
|
||||||
logic [TAGLEN-1:0] ReadTag;
|
logic [TAGLEN-1:0] ReadTag;
|
||||||
logic Dirty;
|
logic Dirty;
|
||||||
logic SelTag;
|
logic SelDirty;
|
||||||
logic SelectedWriteWordEn;
|
logic SelectedWriteWordEn;
|
||||||
logic [LINELEN/8-1:0] FinalByteMask;
|
logic [LINELEN/8-1:0] FinalByteMask;
|
||||||
logic SetValidEN;
|
logic SetValidEN, ClearValidEN;
|
||||||
logic SetValidWay;
|
logic SetValidWay;
|
||||||
logic ClearValidWay;
|
logic ClearValidWay;
|
||||||
logic SetDirtyWay;
|
logic SetDirtyWay;
|
||||||
@ -78,7 +78,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
if (!READ_ONLY_CACHE) begin:flushlogic
|
if (!READ_ONLY_CACHE) begin:flushlogic
|
||||||
logic FlushWayEn;
|
logic FlushWayEn;
|
||||||
mux2 #(1) seltagmux(VictimWay, FlushWay, SelFlush, SelTag);
|
mux2 #(1) seltagmux(VictimWay, FlushWay, SelFlush, SelDirty);
|
||||||
|
|
||||||
// FlushWay is part of a one hot way selection. Must clear it if FlushWay not selected.
|
// FlushWay is part of a one hot way selection. Must clear it if FlushWay not selected.
|
||||||
// coverage off -item e 1 -fecexprrow 3
|
// coverage off -item e 1 -fecexprrow 3
|
||||||
@ -86,11 +86,11 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
assign FlushWayEn = FlushWay & SelFlush;
|
assign FlushWayEn = FlushWay & SelFlush;
|
||||||
assign SelNonHit = FlushWayEn | SelWay;
|
assign SelNonHit = FlushWayEn | SelWay;
|
||||||
end else begin:flushlogic // no flush operation for read-only caches.
|
end else begin:flushlogic // no flush operation for read-only caches.
|
||||||
assign SelTag = VictimWay;
|
assign SelDirty = VictimWay;
|
||||||
assign SelNonHit = SelWay;
|
assign SelNonHit = SelWay;
|
||||||
end
|
end
|
||||||
|
|
||||||
mux2 #(1) selectedwaymux(HitWay, SelTag, SelNonHit , SelData);
|
mux2 #(1) selectedwaymux(HitWay, SelDirty, SelNonHit , SelData);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Write Enable demux
|
// Write Enable demux
|
||||||
@ -102,6 +102,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
assign ClearDirtyWay = ClearDirty & SelData;
|
assign ClearDirtyWay = ClearDirty & SelData;
|
||||||
assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn
|
assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn
|
||||||
assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN
|
assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN
|
||||||
|
assign ClearValidEN = ClearValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN
|
||||||
|
|
||||||
// If writing the whole line set all write enables to 1, else only set the correct word.
|
// If writing the whole line set all write enables to 1, else only set the correct word.
|
||||||
assign FinalByteMask = SetValidWay ? '1 : LineByteMask; // OR
|
assign FinalByteMask = SetValidWay ? '1 : LineByteMask; // OR
|
||||||
@ -116,7 +117,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
// AND portion of distributed tag multiplexer
|
// AND portion of distributed tag multiplexer
|
||||||
assign TagWay = SelData ? ReadTag : '0; // AND part of AOMux
|
assign TagWay = SelData ? ReadTag : '0; // AND part of AOMux
|
||||||
assign DirtyWay = SelTag & Dirty & ValidWay;
|
assign DirtyWay = SelDirty & Dirty & ValidWay;
|
||||||
assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]);
|
assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -156,7 +157,8 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
if(CacheEn) begin
|
if(CacheEn) begin
|
||||||
ValidWay <= #1 ValidBits[CacheSet];
|
ValidWay <= #1 ValidBits[CacheSet];
|
||||||
if(InvalidateCache) ValidBits <= #1 '0; // exclusion-tag: dcache invalidateway
|
if(InvalidateCache) ValidBits <= #1 '0; // exclusion-tag: dcache invalidateway
|
||||||
else if (SetValidEN | (ClearValidWay & ~FlushStage)) ValidBits[CacheSet] <= #1 SetValidWay;
|
else if (SetValidEN) ValidBits[CacheSet] <= #1 SetValidWay;
|
||||||
|
else if (ClearValidEN) ValidBits[CacheSet] <= #1 '0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(),
|
.InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(),
|
||||||
.InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(),
|
.InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(),
|
||||||
.LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(),
|
.LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(),
|
||||||
.UpdateDA(InstrUpdateDAF),
|
.UpdateDA(InstrUpdateDAF), .CMOp(4'b0),
|
||||||
.AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0),
|
.AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0),
|
||||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
||||||
|
|
||||||
|
@ -148,7 +148,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
|
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
|
||||||
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
|
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
|
||||||
logic SelDTIM; // Select DTIM rather than bus or D$
|
logic SelDTIM; // Select DTIM rather than bus or D$
|
||||||
|
logic [P.XLEN-1:0] WriteDataZM;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Pipeline for IEUAdr E to M
|
// Pipeline for IEUAdr E to M
|
||||||
// Zero-extend address to 34 bits for XLEN=32
|
// Zero-extend address to 34 bits for XLEN=32
|
||||||
@ -176,6 +177,12 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign {SpillStallM, SelStoreDelay} = '0;
|
assign {SpillStallM, SelStoreDelay} = '0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if(P.ZICBOZ_SUPPORTED) begin : cboz
|
||||||
|
mux2 #(P.XLEN) writedatacbozmux(WriteDataM, '0, CMOpM[3], WriteDataZM);
|
||||||
|
end else begin : cboz
|
||||||
|
assign WriteDataZM = WriteDataM;
|
||||||
|
end
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// HPTW (only needed if VM supported)
|
// HPTW (only needed if VM supported)
|
||||||
// MMU include PMP and is needed if any privileged supported
|
// MMU include PMP and is needed if any privileged supported
|
||||||
@ -187,7 +194,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.FlushW, .DCacheStallM, .SATP_REGW, .PCSpillF,
|
.FlushW, .DCacheStallM, .SATP_REGW, .PCSpillF,
|
||||||
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_HADE, .PrivilegeModeW,
|
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_HADE, .PrivilegeModeW,
|
||||||
.ReadDataM(ReadDataM[P.XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
|
.ReadDataM(ReadDataM[P.XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
|
||||||
.WriteDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M,
|
.WriteDataM(WriteDataZM), .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M,
|
||||||
.IEUAdrExtM, .PTE, .IHWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM,
|
.IEUAdrExtM, .PTE, .IHWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM,
|
||||||
.IHAdrM, .HPTWStall, .SelHPTW,
|
.IHAdrM, .HPTWStall, .SelHPTW,
|
||||||
.IgnoreRequestTLB, .LSULoadAccessFaultM, .LSUStoreAmoAccessFaultM,
|
.IgnoreRequestTLB, .LSULoadAccessFaultM, .LSUStoreAmoAccessFaultM,
|
||||||
@ -198,7 +205,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign LSUFunct3M = Funct3M;
|
assign LSUFunct3M = Funct3M;
|
||||||
assign LSUFunct7M = Funct7M;
|
assign LSUFunct7M = Funct7M;
|
||||||
assign LSUAtomicM = AtomicM;
|
assign LSUAtomicM = AtomicM;
|
||||||
assign IHWriteDataM = WriteDataM;
|
assign IHWriteDataM = WriteDataZM;
|
||||||
assign LoadAccessFaultM = LSULoadAccessFaultM;
|
assign LoadAccessFaultM = LSULoadAccessFaultM;
|
||||||
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
|
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
|
||||||
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
|
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
|
||||||
@ -221,7 +228,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic DisableTranslation; // During HPTW walk or D$ flush disable virtual memory address translation
|
logic DisableTranslation; // During HPTW walk or D$ flush disable virtual memory address translation
|
||||||
logic WriteAccessM;
|
logic WriteAccessM;
|
||||||
assign DisableTranslation = SelHPTW | FlushDCacheM;
|
assign DisableTranslation = SelHPTW | FlushDCacheM;
|
||||||
assign WriteAccessM = PreLSURWM[0] | (|CMOpM);
|
assign WriteAccessM = PreLSURWM[0];
|
||||||
mmu #(.P(P), .TLB_ENTRIES(P.DTLB_ENTRIES), .IMMU(0))
|
mmu #(.P(P), .TLB_ENTRIES(P.DTLB_ENTRIES), .IMMU(0))
|
||||||
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_HADE,
|
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_HADE,
|
||||||
.PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]),
|
.PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]),
|
||||||
@ -231,7 +238,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM,
|
.StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM,
|
||||||
.StoreAmoPageFaultM,
|
.StoreAmoPageFaultM,
|
||||||
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw.
|
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw.
|
||||||
.UpdateDA(DataUpdateDAM),
|
.UpdateDA(DataUpdateDAM), .CMOp(CMOpM),
|
||||||
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),
|
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),
|
||||||
.WriteAccessM, .ReadAccessM(PreLSURWM[1]),
|
.WriteAccessM, .ReadAccessM(PreLSURWM[1]),
|
||||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
||||||
@ -294,8 +301,12 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
||||||
logic CacheStall;
|
logic CacheStall;
|
||||||
logic [1:0] CacheBusRWTemp;
|
logic [1:0] CacheBusRWTemp;
|
||||||
|
|
||||||
assign BusRW = ~CacheableM & ~SelDTIM ? LSURWM : '0;
|
if(P.ZICBOZ_SUPPORTED) begin
|
||||||
|
assign BusRW = ~CacheableM & ~SelDTIM ? CMOpM[3] ? 2'b01 : LSURWM : '0;
|
||||||
|
end else begin
|
||||||
|
assign BusRW = ~CacheableM & ~SelDTIM ? LSURWM : '0;
|
||||||
|
end
|
||||||
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
||||||
assign CacheRWM = CacheableM & ~SelDTIM ? LSURWM : '0;
|
assign CacheRWM = CacheableM & ~SelDTIM ? LSURWM : '0;
|
||||||
assign FlushDCache = FlushDCacheM & ~(SelHPTW);
|
assign FlushDCache = FlushDCacheM & ~(SelHPTW);
|
||||||
|
@ -30,18 +30,18 @@
|
|||||||
|
|
||||||
module adrdecs import cvw::*; #(parameter cvw_t P) (
|
module adrdecs import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||||
input logic AccessRW, AccessRX, AccessRWX,
|
input logic AccessRW, AccessRX, AccessRWXZ, AccessRWZ, AccessRXZ,
|
||||||
input logic [1:0] Size,
|
input logic [1:0] Size,
|
||||||
output logic [11:0] SelRegions
|
output logic [11:0] SelRegions
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
|
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
|
||||||
// Determine which region of physical memory (if any) is being accessed
|
// Determine which region of physical memory (if any) is being accessed
|
||||||
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[11]);
|
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRWZ, Size, SUPPORTED_SIZE, SelRegions[11]);
|
||||||
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[10]);
|
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRXZ, Size, SUPPORTED_SIZE, SelRegions[10]);
|
||||||
adrdec #(P.PA_BITS) ddr4dec(PhysicalAddress, P.EXT_MEM_BASE[P.PA_BITS-1:0], P.EXT_MEM_RANGE[P.PA_BITS-1:0], P.EXT_MEM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[9]);
|
adrdec #(P.PA_BITS) ddr4dec(PhysicalAddress, P.EXT_MEM_BASE[P.PA_BITS-1:0], P.EXT_MEM_RANGE[P.PA_BITS-1:0], P.EXT_MEM_SUPPORTED, AccessRWXZ, Size, SUPPORTED_SIZE, SelRegions[9]);
|
||||||
adrdec #(P.PA_BITS) bootromdec(PhysicalAddress, P.BOOTROM_BASE[P.PA_BITS-1:0], P.BOOTROM_RANGE[P.PA_BITS-1:0], P.BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[8]);
|
adrdec #(P.PA_BITS) bootromdec(PhysicalAddress, P.BOOTROM_BASE[P.PA_BITS-1:0], P.BOOTROM_RANGE[P.PA_BITS-1:0], P.BOOTROM_SUPPORTED, AccessRXZ, Size, SUPPORTED_SIZE, SelRegions[8]);
|
||||||
adrdec #(P.PA_BITS) uncoreramdec(PhysicalAddress, P.UNCORE_RAM_BASE[P.PA_BITS-1:0], P.UNCORE_RAM_RANGE[P.PA_BITS-1:0], P.UNCORE_RAM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[7]);
|
adrdec #(P.PA_BITS) uncoreramdec(PhysicalAddress, P.UNCORE_RAM_BASE[P.PA_BITS-1:0], P.UNCORE_RAM_RANGE[P.PA_BITS-1:0], P.UNCORE_RAM_SUPPORTED, AccessRWXZ, Size, SUPPORTED_SIZE, SelRegions[7]);
|
||||||
adrdec #(P.PA_BITS) clintdec(PhysicalAddress, P.CLINT_BASE[P.PA_BITS-1:0], P.CLINT_RANGE[P.PA_BITS-1:0], P.CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[6]);
|
adrdec #(P.PA_BITS) clintdec(PhysicalAddress, P.CLINT_BASE[P.PA_BITS-1:0], P.CLINT_RANGE[P.PA_BITS-1:0], P.CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[6]);
|
||||||
adrdec #(P.PA_BITS) gpiodec(PhysicalAddress, P.GPIO_BASE[P.PA_BITS-1:0], P.GPIO_RANGE[P.PA_BITS-1:0], P.GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[5]);
|
adrdec #(P.PA_BITS) gpiodec(PhysicalAddress, P.GPIO_BASE[P.PA_BITS-1:0], P.GPIO_RANGE[P.PA_BITS-1:0], P.GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[5]);
|
||||||
adrdec #(P.PA_BITS) uartdec(PhysicalAddress, P.UART_BASE[P.PA_BITS-1:0], P.UART_RANGE[P.PA_BITS-1:0], P.UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[4]);
|
adrdec #(P.PA_BITS) uartdec(PhysicalAddress, P.UART_BASE[P.PA_BITS-1:0], P.UART_RANGE[P.PA_BITS-1:0], P.UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[4]);
|
||||||
|
@ -55,6 +55,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
|
|||||||
output logic UpdateDA, // page fault due to setting dirty or access bit
|
output logic UpdateDA, // page fault due to setting dirty or access bit
|
||||||
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources
|
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources
|
||||||
// PMA checker signals
|
// PMA checker signals
|
||||||
|
input logic [3:0] CMOp, // Cache management instructions
|
||||||
input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // access type
|
input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // access type
|
||||||
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses
|
||||||
@ -106,7 +107,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
|
|||||||
// Check physical memory accesses
|
// Check physical memory accesses
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
pmachecker #(P) pmachecker(.PhysicalAddress, .Size,
|
pmachecker #(P) pmachecker(.PhysicalAddress, .Size, .CMOp,
|
||||||
.AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, .PBMemoryType,
|
.AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, .PBMemoryType,
|
||||||
.Cacheable, .Idempotent, .SelTIM,
|
.Cacheable, .Idempotent, .SelTIM,
|
||||||
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);
|
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
module pmachecker import cvw::*; #(parameter cvw_t P) (
|
module pmachecker import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||||
input logic [1:0] Size,
|
input logic [1:0] Size,
|
||||||
|
input logic [3:0] CMOp,
|
||||||
input logic AtomicAccessM, // Atomic access
|
input logic AtomicAccessM, // Atomic access
|
||||||
input logic ExecuteAccessF, // Execute access
|
input logic ExecuteAccessF, // Execute access
|
||||||
input logic WriteAccessM, // Write access
|
input logic WriteAccessM, // Write access
|
||||||
@ -43,18 +44,20 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
|||||||
);
|
);
|
||||||
|
|
||||||
logic PMAAccessFault;
|
logic PMAAccessFault;
|
||||||
logic AccessRW, AccessRWX, AccessRX;
|
logic AccessRW, AccessRWXZ, AccessRX, AccessRWZ, AccessRXZ;
|
||||||
logic [11:0] SelRegions;
|
logic [11:0] SelRegions;
|
||||||
logic AtomicAllowed;
|
logic AtomicAllowed;
|
||||||
logic CacheableRegion, IdempotentRegion;
|
logic CacheableRegion, IdempotentRegion;
|
||||||
|
|
||||||
// Determine what type of access is being made
|
// Determine what type of access is being made
|
||||||
assign AccessRW = ReadAccessM | WriteAccessM;
|
assign AccessRW = ReadAccessM | WriteAccessM;
|
||||||
assign AccessRWX = ReadAccessM | WriteAccessM | ExecuteAccessF;
|
assign AccessRWZ = AccessRW | (P.ZICBOM_SUPPORTED & (|CMOp[2:0]));
|
||||||
|
assign AccessRWXZ = ReadAccessM | WriteAccessM | ExecuteAccessF | (P.ZICBOM_SUPPORTED & (|CMOp[2:0])) | (P.ZICBOZ_SUPPORTED & (CMOp[3]));
|
||||||
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
||||||
|
assign AccessRXZ = AccessRX | (P.ZICBOM_SUPPORTED & (|CMOp[2:0]));
|
||||||
|
|
||||||
// Determine which region of physical memory (if any) is being accessed
|
// Determine which region of physical memory (if any) is being accessed
|
||||||
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
|
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWXZ, AccessRWZ, AccessRXZ, Size, SelRegions);
|
||||||
|
|
||||||
// Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable
|
// Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable
|
||||||
assign CacheableRegion = SelRegions[9] | SelRegions[8] | SelRegions[7]; // exclusion-tag: unused-cachable
|
assign CacheableRegion = SelRegions[9] | SelRegions[8] | SelRegions[7]; // exclusion-tag: unused-cachable
|
||||||
@ -71,7 +74,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign SelTIM = SelRegions[11] | SelRegions[10]; // exclusion-tag: unused-idempotent
|
assign SelTIM = SelRegions[11] | SelRegions[10]; // exclusion-tag: unused-idempotent
|
||||||
|
|
||||||
// Detect access faults
|
// Detect access faults
|
||||||
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
assign PMAAccessFault = (SelRegions[0]) & AccessRWXZ | AtomicAccessM & ~AtomicAllowed;
|
||||||
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;
|
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;
|
||||||
assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault;
|
assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault;
|
||||||
assign PMAStoreAmoAccessFaultM = WriteAccessM & PMAAccessFault;
|
assign PMAStoreAmoAccessFaultM = WriteAccessM & PMAAccessFault;
|
||||||
|
@ -88,7 +88,7 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
|||||||
// Determine which region of physical memory (if any) is being accessed
|
// Determine which region of physical memory (if any) is being accessed
|
||||||
// Use a trimmed down portion of the PMA checker - only the address decoders
|
// Use a trimmed down portion of the PMA checker - only the address decoders
|
||||||
// Set access types to all 1 as don't cares because the MMU has already done access checking
|
// Set access types to all 1 as don't cares because the MMU has already done access checking
|
||||||
adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions);
|
adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions);
|
||||||
|
|
||||||
// unswizzle HSEL signals
|
// unswizzle HSEL signals
|
||||||
assign {HSELDTIM, HSELIROM, HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELEXTSDC, HSELSPI} = HSELRegions[11:1];
|
assign {HSELDTIM, HSELIROM, HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELEXTSDC, HSELSPI} = HSELRegions[11:1];
|
||||||
|
Loading…
Reference in New Issue
Block a user