diff --git a/.gitignore b/.gitignore index 3f254d133..8692d6bc3 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ transcript vsim.wlf wally-pipelined/wlft* wlft* +/imperas-riscv-tests/FunctionRadix_32.addr +/imperas-riscv-tests/FunctionRadix_64.addr +/imperas-riscv-tests/ProgramMap.txt diff --git a/wally-pipelined/bin/extractFunctionRadix.sh b/wally-pipelined/bin/extractFunctionRadix.sh index 0cec0972d..f5de782d7 100755 --- a/wally-pipelined/bin/extractFunctionRadix.sh +++ b/wally-pipelined/bin/extractFunctionRadix.sh @@ -1,47 +1,78 @@ #!/bin/bash -allProgramRadixFile="FunctionRadix" +###################### +# extractFunctionRadix.sh +# +# Written: Ross Thompson +# email: ross1728@gmail.com +# Created: March 1, 2021 +# Modified: March 10, 2021 +# +# Purpose: Processes all compiled object files into 2 types of files which assist in debuging applications. +# File 1: .addr: A sorted list of function starting addresses. +# When a the PCE is greater than or equal to the function's starting address, the label will be associated with this address. +# File 2: .lab: A sorted list of funciton labels. The names of functions. Modelsim will display these names rather than the function address. +# +# 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. +###################### + + +function processProgram { + local objDumpFile=$1 + local numBits=$2 + local size=$(($numBits/4)) + local index=$3 + + # when size = 16 => 64 bit + # when size = 8 => 32 bit + local listOfAddr=`egrep -i "^[0-9]{$size} <[0-9a-zA-Z_]+>" $objDumpFile` + + # skip if the wrong bit width. + if [ -z "$listOfAddr" ]; then + return 0 + fi + + # parse out the addresses and the labels + local addresses=`echo "$listOfAddr" | awk '{print $1}'` + local labels=`echo "$listOfAddr" | awk '{print "\""$2"\"", "-color \"SpringGreen\","}' | tr -d '<>:'` + local labelsName=`echo "$listOfAddr" | awk '{print ""$2""}' | tr -d '<>:'` + + # output per program function address list + echo "$addresses" > $objDumpFile.addr + echo "$labelsName" > $objDumpFile.lab + + # need to add some formatting to each line + local numLines=`echo "$listOfAddr" | wc -l` + + return 0 +} + index=0 for objDumpFile in "$@"; do - # get the lines with named labels from the obj files. - # 64 bit addresses - listOfAddr16=`egrep -i '^[0-9]{16} <[0-9a-zA-Z_]+>' $objDumpFile` - # 32 bit addresses - listOfAddr8=`egrep -i '^[0-9]{8} <[0-9a-zA-Z_]+>' $objDumpFile` - listOfAddr=`echo "$listOfAddr16" "$listOfAddr8"` - # parse out the addresses and the labels - addresses=`echo "$listOfAddr" | awk '{print $1}'` - labels=`echo "$listOfAddr" | awk '{print "\""$2"\"", "-color \"SpringGreen\","}' | tr -d '<>:'` - - echo "$addresses" > $objDumpFile.addr - - # need to add some formatting to each line - numLines=`echo "$listOfAddr" | wc -l` - prefix=`yes " 16#" | head -n $numLines` - midfix=`yes "# " | head -n $numLines` - - # paste echos each of the 4 parts on a per line basis. - #-d'\0' sets no delimiter - temp=`paste -d'\0' <(echo "$prefix") <(echo "$addresses") <(echo "$midfix") <(echo "$labels")` - - # remove the last comma - temp2=${temp::-1} - - echo "radix define Functions {" > $objDumpFile.do - echo "$temp2" >> $objDumpFile.do - echo " -default hex -color green" >> $objDumpFile.do - echo "}" >> $objDumpFile.do - - # now create the all in one version - # put the index at the begining of each line - allAddresses=`paste -d'\0' <(printf "%04x" "$index") <(echo "$addresses")` - - printf "%04x%s" "$index" "$addresses" >> $allProgramRadixFile.addr + processProgram "$objDumpFile" 32 "$index" + processProgram "$objDumpFile" 64 "$index" index=$(($index+1)) done + +exit 0 + diff --git a/wally-pipelined/config/busybear/wally-constants.vh b/wally-pipelined/config/busybear/wally-constants.vh new file mode 100644 index 000000000..55fb4e947 --- /dev/null +++ b/wally-pipelined/config/busybear/wally-constants.vh @@ -0,0 +1,31 @@ +////////////////////////////////////////// +// wally-constants.vh +// +// Written: tfleming@hmc.edu 4 March 2021 +// Modified: +// +// Purpose: Specify certain constants defined in the RISC-V 64-bit architecture. +// These macros should not be changed, except in the event of an +// update to the architecture or particularly special circumstances. +// +// 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. +/////////////////////////////////////////// + +// Virtual Memory Constants (sv39) +`define VPN_BITS 27 +`define PPN_BITS 44 +`define PA_BITS 56 diff --git a/wally-pipelined/config/coremark/wally-constants.vh b/wally-pipelined/config/coremark/wally-constants.vh new file mode 100644 index 000000000..55fb4e947 --- /dev/null +++ b/wally-pipelined/config/coremark/wally-constants.vh @@ -0,0 +1,31 @@ +////////////////////////////////////////// +// wally-constants.vh +// +// Written: tfleming@hmc.edu 4 March 2021 +// Modified: +// +// Purpose: Specify certain constants defined in the RISC-V 64-bit architecture. +// These macros should not be changed, except in the event of an +// update to the architecture or particularly special circumstances. +// +// 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. +/////////////////////////////////////////// + +// Virtual Memory Constants (sv39) +`define VPN_BITS 27 +`define PPN_BITS 44 +`define PA_BITS 56 diff --git a/wally-pipelined/config/rv32ic/wally-constants.vh b/wally-pipelined/config/rv32ic/wally-constants.vh new file mode 100644 index 000000000..ffa26727a --- /dev/null +++ b/wally-pipelined/config/rv32ic/wally-constants.vh @@ -0,0 +1,31 @@ +////////////////////////////////////////// +// wally-constants.vh +// +// Written: tfleming@hmc.edu 4 March 2021 +// Modified: +// +// Purpose: Specify certain constants defined in the RISC-V 64-bit architecture. +// These macros should not be changed, except in the event of an +// update to the architecture or particularly special circumstances. +// +// 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. +/////////////////////////////////////////// + +// Virtual Memory Constants (sv32) +`define VPN_BITS 20 +`define PPN_BITS 22 +`define PA_BITS 34 diff --git a/wally-pipelined/config/rv64ic/wally-constants.vh b/wally-pipelined/config/rv64ic/wally-constants.vh new file mode 100644 index 000000000..55fb4e947 --- /dev/null +++ b/wally-pipelined/config/rv64ic/wally-constants.vh @@ -0,0 +1,31 @@ +////////////////////////////////////////// +// wally-constants.vh +// +// Written: tfleming@hmc.edu 4 March 2021 +// Modified: +// +// Purpose: Specify certain constants defined in the RISC-V 64-bit architecture. +// These macros should not be changed, except in the event of an +// update to the architecture or particularly special circumstances. +// +// 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. +/////////////////////////////////////////// + +// Virtual Memory Constants (sv39) +`define VPN_BITS 27 +`define PPN_BITS 44 +`define PA_BITS 56 diff --git a/wally-pipelined/config/rv64icfd/wally-constants.vh b/wally-pipelined/config/rv64icfd/wally-constants.vh new file mode 100644 index 000000000..55fb4e947 --- /dev/null +++ b/wally-pipelined/config/rv64icfd/wally-constants.vh @@ -0,0 +1,31 @@ +////////////////////////////////////////// +// wally-constants.vh +// +// Written: tfleming@hmc.edu 4 March 2021 +// Modified: +// +// Purpose: Specify certain constants defined in the RISC-V 64-bit architecture. +// These macros should not be changed, except in the event of an +// update to the architecture or particularly special circumstances. +// +// 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. +/////////////////////////////////////////// + +// Virtual Memory Constants (sv39) +`define VPN_BITS 27 +`define PPN_BITS 44 +`define PA_BITS 56 diff --git a/wally-pipelined/regression/regression-wally.sh b/wally-pipelined/regression/regression-wally.sh new file mode 100755 index 000000000..39d821024 --- /dev/null +++ b/wally-pipelined/regression/regression-wally.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +check_test () { + output=$(timeout 2m ./"$1" 2>/dev/null) + found=$(echo $output | grep -c "$2") + echo "$found" +} +echo "-----------------------" +echo "starting all regression tests!" +echo "note: this could take up to 3 minutes to run" +echo "-----------------------" +echo "checking verilator" +verilator_out=$(cd ..; ./lint-wally 2>&1) +[[ -z $verilator_out ]] && echo "verilator passed" || echo "verilator failed" +echo "starting Imperas rv64ic" +sleep 1 +exec 3< <(check_test "sim-wally-batch" "All tests ran without failures.") +#echo "starting Imperas rv32ic" +#sleep 1 +#exec 5< <(check_test "sim-wally-rv32ic" "All tests ran without failures.") +#echo "starting busybear" +sleep 1 +exec 4< <(check_test "sim-busybear-batch" "loaded 100000 instructions") +echo "-----------------------" +echo "waiting for tests to finish..." +echo "-----------------------" +rv64_out=$(cat <&3) +[[ $rv64_out -eq 1 ]] && echo "rv64ic passed" || echo "rv64ic failed" +#rv32_out=$(cat <&5) +#[[ $rv32_out -eq 1 ]] && echo "rv32ic passed" || echo "rv32ic failed" +busybear_out=$(cat <&4) +[[ $busybear_out -eq 1 ]] && echo "busybear passed" || echo "busybear failed" + +[[ -z $verilator_out && $rv64_out -eq 1 && $busybear_out -eq 1 ]] && echo "all passed" || echo "not all passed" +#[[ -z $verilator_out && $rv32_out -eq 1 && $rv64_out -eq 1 && $busybear_out -eq 1 ]] && echo "all passed" || echo "not all passed" diff --git a/wally-pipelined/regression/sim-wally-rv32ic b/wally-pipelined/regression/sim-wally-rv32ic new file mode 100755 index 000000000..a254c8246 --- /dev/null +++ b/wally-pipelined/regression/sim-wally-rv32ic @@ -0,0 +1,3 @@ +vsim -c < -add wave -noupdate /testbench/dut/hart/ebu/IReadF -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD add wave -noupdate -group Bpred -expand -group direction -divider Update add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/UpdatePC add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/UpdateEN add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/UpdatePCIndex add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/UpdatePrediction add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory -add wave -noupdate -group InstrClass /testbench/dut/hart/ifu/bpred/InstrClassF -add wave -noupdate -group InstrClass /testbench/dut/hart/ifu/bpred/InstrClassD -add wave -noupdate -group InstrClass /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF -add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD -add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM -add wave -noupdate /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -group Bpred -group BTB -divider Update +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget +add wave -noupdate -group Bpred -group BTB -divider Lookup +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid +add wave -noupdate -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF +add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD +add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE +add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNextF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCPlus2or4F @@ -45,30 +55,12 @@ add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext1F add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/SelBPPredF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredWrongE add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PrivilegedChangePCM -add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/ValidBits -add wave -noupdate /testbench/dut/hart/ifu/bpred/BPPredF -add wave -noupdate /testbench/dut/hart/ifu/bpred/BTBValidF -add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/LookUpPCIndexQ -add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ -add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/LookUpPC -add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE -add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE -add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE -add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE -add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -group BTB -divider Update -add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN -add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC -add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget -add wave -noupdate -group BTB -divider Lookup -add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC -add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid -add wave -noupdate /testbench/dut/hart/ifu/bpred/BTBPredPCF -add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC -add wave -noupdate /testbench/dut/hart/ifu/bpred/CorrectPCE -add wave -noupdate /testbench/dut/hart/ifu/bpred/FlushF -add wave -noupdate /testbench/dut/hart/FlushF +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ifu/InstrD +add wave -noupdate -group {Decode Stage} /testbench/InstrDName +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 @@ -83,19 +75,23 @@ add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/ add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW -add wave -noupdate /testbench/dut/hart/ieu/c/RegWriteE -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ifu/InstrD -add wave -noupdate -group {Decode Stage} /testbench/InstrDName -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/a +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/b +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/result +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/flags +add wave -noupdate -expand -group alu -divider internals +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/overflow +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/carry +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/zero +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/neg +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/lt +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate /testbench/InstrFName -add wave -noupdate -expand -group dcache /testbench/dut/hart/MemAdrM -add wave -noupdate -expand -group dcache /testbench/dut/hart/MemPAdrM -add wave -noupdate -expand -group dcache /testbench/dut/hart/WriteDataM -add wave -noupdate -expand -group dcache /testbench/dut/hart/ReadDataM -add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemRWM +add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM +add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM +add wave -noupdate -group dcache /testbench/dut/hart/WriteDataM +add wave -noupdate -group dcache /testbench/dut/hart/dmem/MemRWM add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1E @@ -109,16 +105,35 @@ add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/RegWriteW add wave -noupdate -group Forward -color Thistle /testbench/dut/hart/ieu/fw/ForwardAE add wave -noupdate -group Forward -color Thistle /testbench/dut/hart/ieu/fw/ForwardBE add wave -noupdate -group Forward -color Thistle /testbench/dut/hart/ieu/fw/LoadStallD -add wave -noupdate -expand -group {alu execution stage} /testbench/dut/hart/ieu/dp/WriteDataE -add wave -noupdate -expand -group {alu execution stage} /testbench/dut/hart/ieu/dp/ALUResultE -add wave -noupdate -expand -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcAE -add wave -noupdate -expand -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcBE +add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/WriteDataE +add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/ALUResultE +add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcAE +add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcBE add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultM +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/reset +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapLineCount +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapLine +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapFP +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapFile +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapLineCount +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapLine +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapFP +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapFile +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/pc +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrIndex +add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionName +add wave -noupdate -expand -group PCS /testbench/dut/hart/PCF +add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCD +add wave -noupdate -expand -group PCS /testbench/dut/hart/PCE +add wave -noupdate -expand -group PCS /testbench/dut/hart/PCM +add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCW TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {231033 ns} 0} {{Cursor 3} {1276117 ns} 0} +WaveRestoreCursors {{Cursor 2} {3758805 ns} 0} {{Cursor 3} {4351471 ns} 0} quietly wave cursor active 2 configure wave -namecolwidth 250 -configure wave -valuecolwidth 518 +configure wave -valuecolwidth 229 configure wave -justifyvalue left configure wave -signalnamewidth 1 configure wave -snapdistance 10 @@ -131,4 +146,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {1276094 ns} {1276208 ns} +WaveRestoreZoom {4351320 ns} {4351862 ns} diff --git a/wally-pipelined/src/dmem/dmem.sv b/wally-pipelined/src/dmem/dmem.sv index 547663fce..9bc4a6a09 100644 --- a/wally-pipelined/src/dmem/dmem.sv +++ b/wally-pipelined/src/dmem/dmem.sv @@ -37,7 +37,7 @@ module dmem ( input logic [2:0] Funct3M, //input logic [`XLEN-1:0] ReadDataW, input logic [`XLEN-1:0] WriteDataM, - input logic AtomicM, + input logic [1:0] AtomicM, output logic [`XLEN-1:0] MemPAdrM, output logic MemReadM, MemWriteM, output logic DataMisalignedM, @@ -51,25 +51,19 @@ module dmem ( output logic StoreMisalignedFaultM, StoreAccessFaultM, // TLB management //input logic [`XLEN-1:0] PageTableEntryM, + input logic [`XLEN-1:0] SATP_REGW, //input logic DTLBWriteM, DTLBFlushM, - // *** satp value will come from CSRs - // input logic [`XLEN-1:0] SATP, output logic DTLBMissM, DTLBHitM ); logic SquashSCM; - // Initially no MMU - // *** temporary hack until we can figure out how to get actual satp value - // from priv unit -- Thomas F - logic [`XLEN-1:0] SATP = '0; // *** temporary hack until walker is hooked up -- Thomas F logic [`XLEN-1:0] PageTableEntryM = '0; logic DTLBFlushM = '0; logic DTLBWriteM = '0; - tlb #(3) dtlb(clk, reset, SATP, MemAdrM, PageTableEntryM, DTLBWriteM, + tlb #(3) dtlb(clk, reset, SATP_REGW, MemAdrM, PageTableEntryM, DTLBWriteM, DTLBFlushM, MemPAdrM, DTLBMissM, DTLBHitM); - //assign MemPAdrM = MemAdrM; // Determine if an Unaligned access is taking place always_comb @@ -98,8 +92,8 @@ module dmem ( logic ReservationValidM, ReservationValidW; logic lrM, scM, WriteAdrMatchM; - assign lrM = MemReadM && AtomicM; - assign scM = MemRWM[0] && AtomicM; + assign lrM = MemReadM && AtomicM[0]; + assign scM = MemRWM[0] && AtomicM[0]; assign WriteAdrMatchM = MemRWM[0] && (MemPAdrM[`XLEN-1:2] == ReservationPAdrW) && ReservationValidW; assign SquashSCM = scM && ~WriteAdrMatchM; always_comb begin // ReservationValidM (next valiue of valid reservation) diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index ad604be54..ed353595c 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -35,6 +35,8 @@ module ahblite ( input logic StallW, FlushW, // Load control input logic UnsignedLoadM, + input logic [1:0] AtomicM, + input logic [6:0] Funct7M, // Signals from Instruction Cache input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram input logic InstrReadF, @@ -44,6 +46,8 @@ module ahblite ( input logic MemReadM, MemWriteM, input logic [`XLEN-1:0] WriteDataM, input logic [1:0] MemSizeM, + // Signals from MMU *** + // MMUPAdr; // Return from bus output logic [`XLEN-1:0] ReadDataW, // AHB-Lite external signals @@ -64,36 +68,41 @@ module ahblite ( output logic HWRITED, // Stalls output logic InstrStall,/*InstrUpdate, */DataStall + // *** add a chip-level ready signal as part of handshake ); logic GrantData; logic [2:0] ISize; - logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataPreW; + logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataPreW, WriteData; logic IReady, DReady; logic CaptureDataM; assign HCLK = clk; assign HRESETn = ~reset; - // *** initially support HABW = XLEN + // *** initially support AHBW = XLEN // track bus state // Data accesses have priority over instructions. However, if a data access comes // while an instruction read is occuring, the instruction read finishes before // the data access can take place. - typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADMEMPENDING} statetype; + typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADMEMPENDING, ATOMICREAD, ATOMICWRITE} statetype; statetype BusState, NextBusState; - always_ff @(posedge HCLK, negedge HRESETn) - if (~HRESETn) BusState <= #1 IDLE; - else BusState <= #1 NextBusState; + flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState); always_comb case (BusState) - IDLE: if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions + IDLE: if (AtomicM[1]) NextBusState = ATOMICREAD; + else if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions else if (MemWriteM) NextBusState = MEMWRITE; else if (InstrReadF) NextBusState = INSTRREAD; else NextBusState = IDLE; + ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD; + else NextBusState = ATOMICWRITE; + ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; MEMREAD: if (~HREADY) NextBusState = MEMREAD; else if (InstrReadF) NextBusState = INSTRREAD; else NextBusState = IDLE; @@ -109,17 +118,14 @@ module ahblite ( endcase // stall signals - assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || (NextBusState == INSTRREADMEMPENDING); + assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || + (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) || + (NextBusState == INSTRREADMEMPENDING); assign #1 InstrStall = (NextBusState == INSTRREAD); - - // DH 2/20/22: A cyclic path presently exists - // HREADY->NextBusState->GrantData->HSIZE->HSELUART->HREADY - // This is because the peripherals assert HREADY on the same cycle - // When memory is working, also fix the peripherals to respond on the subsequent cycle - // and this path should be fixed. - + // bus outputs - assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE); + assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || + (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0]; assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway assign #1 HSIZE = GrantData ? {1'b0, MemSizeM} : ISize; @@ -127,9 +133,9 @@ module ahblite ( assign HPROT = 4'b0011; // not used; see Section 3.7 assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise assign HMASTLOCK = 0; // no locking supported - assign HWRITE = (NextBusState == MEMWRITE); + assign HWRITE = (NextBusState == MEMWRITE) || (NextBusState == ATOMICWRITE); // delay write data by one cycle for - flop #(`XLEN) wdreg(HCLK, WriteDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN + flop #(`XLEN) wdreg(HCLK, WriteData, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN // delay signals for subword writes flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD); flop #(4) sizereg(HCLK, {UnsignedLoadM, HSIZE}, HSIZED); @@ -140,11 +146,26 @@ module ahblite ( assign InstrRData = HRDATA; assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021 - assign CaptureDataM = (BusState == MEMREAD) && (NextBusState != MEMREAD); + assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) || + ((BusState == ATOMICREAD) && (NextBusState == ATOMICWRITE)); + // *** check if this introduces an unnecessary cycle of latency in memory accesses flopenr #(`XLEN) ReadDataPreWReg(clk, reset, CaptureDataM, ReadDataM, ReadDataPreW); // *** this may break when there is no instruction read after data read flopenr #(`XLEN) ReadDataWReg(clk, reset, ~StallW, ReadDataPreW, ReadDataW); + // Extract and sign-extend subwords if necessary subwordread swr(.*); -endmodule + // Handle AMO instructions if applicable + generate + if (`A_SUPPORTED) begin + logic [`XLEN-1:0] AMOResult; +// amoalu amoalu(.a(HRDATA), .b(WriteDataM), .funct(Funct7M), .width(MemSizeM), +// .result(AMOResult)); + amoalu amoalu(.srca(ReadDataPreW), .srcb(WriteDataM), .funct(Funct7M), .width(MemSizeM), + .result(AMOResult)); + mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, AtomicM[1], WriteData); + end else + assign WriteData = WriteDataM; + endgenerate +endmodule diff --git a/wally-pipelined/src/ebu/amoalu.sv b/wally-pipelined/src/ebu/amoalu.sv new file mode 100644 index 000000000..8acba98cc --- /dev/null +++ b/wally-pipelined/src/ebu/amoalu.sv @@ -0,0 +1,78 @@ +/////////////////////////////////////////// +// amoalu.sv +// +// Written: David_Harris@hmc.edu 10 March 2021 +// Modified: +// +// Purpose: Performs AMO operations +// +// 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 amoalu ( + input logic [`XLEN-1:0] srca, srcb, + input logic [6:0] funct, + input logic [1:0] width, + output logic [`XLEN-1:0] result); + + logic [`XLEN-1:0] a, b, y; + + // *** can this be muxed into the regular ALU to avoid needing a second one? Only a good + // idea if the regular ALU is not the critical path + + // *** see how synthesis generates this and optimize more structurally if necessary to share hardware + // a single carry chain should be shared for + and the four min/max + // and the same mux can be used to select b for swap. + always_comb + case (funct[6:2]) + 5'b00001: y = b; // amoswap + 5'b00000: y = a + b; // amoadd + 5'b00100: y = a ^ b; // amoxor + 5'b01100: y = a & b; // amoand + 5'b01000: y = a | b; // amoor + 5'b10000: y = ($signed(a) < $signed(b)) ? a : b; // amomin + 5'b10100: y = ($signed(a) >= $signed(b)) ? a : b; // amomax + 5'b11000: y = ($unsigned(a) < $unsigned(b)) ? a : b; // amominu + 5'b11100: y = ($unsigned(a) >= $unsigned(b)) ? a : b; // amomaxu + default: y = 'bx; // undefined; *** could change to b for efficiency + endcase + + // sign extend if necessary + generate + if (`XLEN == 32) begin + assign a = srca; + assign b = srcb; + assign result = y; + end else begin // `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 + +endmodule + diff --git a/wally-pipelined/src/ebu/pagetablewalker.sv_dev b/wally-pipelined/src/ebu/pagetablewalker.sv_dev new file mode 100644 index 000000000..eaed09482 --- /dev/null +++ b/wally-pipelined/src/ebu/pagetablewalker.sv_dev @@ -0,0 +1,106 @@ +/////////////////////////////////////////// +// pagetablewalker.sv +// +// Written: tfleming@hmc.edu 2 March 2021 +// Modified: +// +// Purpose: Page Table Walker +// Part of the Memory Management Unit (MMU) +// +// 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 pagetablewalker ( + input logic clk, reset, + + input logic [`XLEN-1:0] SATP_REGW, + + input logic ITLBMissF, DTLBMissM, + input logic [`XLEN-1:0] TranslationVAdr, + + input logic HCLK, HRESETn, + + input logic HREADY, + + output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM, + output logic ITLBWriteF, DTLBWriteM, + output logic TranslationComplete +); + + /* + generate + if (`XLEN == 32) begin + logic Sv_Mode = satp[31] + end else begin + logic Sv_Mode [3:0] = satp[63:60] + end + endgenerate + */ + + logic Sv_Mode = SATP_REGW[31]; + logic BasePageTablePPN [21:0] = SATP_REGW[21:0]; + + logic VPN1 [9:0] = TranslationVAdr[31:22]; + logic VPN0 [9:0] = TranslationVAdr[21:12]; // *** could optimize by not passing offset? + + logic TranslationPAdr [33:0]; + + typedef enum {IDLE, DATA_LEVEL1, DATA_LEVEL0, DATA_LEAF, DATA FAULT} statetype; + statetype WalkerState, NextWalkerState; + + always_ff @(posedge HCLK, negedge HRESETn) + if (~HRESETn) WalkerState <= #1 IDLE; + else WalkerState <= #1 NextWalkerState; + + always_comb begin + NextWalkerState = 'X; + case (WalkerState) + IDLE: if (TLBMissM) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; + LEVEL1: if (HREADY && ValidEntry) NextWalkerState = LEVEL0; + else if (HREADY) NextWalkerState = FAULT; + else NextWalkerState = LEVEL1; + LEVEL2: if (HREADY && ValidEntry) NextWalkerState = LEAF; + else if (HREADY) NextWalkerState = FAULT; + else NextWalkerState = LEVEL2; + LEAF: NextWalkerState = IDLE; + endcase + end + + always_ff @(posedge HCLK, negedge HRESETn) + if (~HRESETn) begin + TranslationPAdr <= '0; + PageTableEntryF <= '0; + TranslationComplete <= '0; + end else begin + // default values + case (NextWalkerState) + LEVEL1: TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00}; + LEVEL2: TranslationPAdr <= {CurrentPPN, VPN0, 2'b00}; + LEAF: begin + PageTableEntryF <= CurrentPageTableEntry; + TranslationComplete <= '1; + end + endcase + end + + assign #1 Translate = (NextWalkerState == LEVEL1); + + +endmodule \ No newline at end of file diff --git a/wally-pipelined/src/generic/flop.sv b/wally-pipelined/src/generic/flop.sv index 7e954a8f8..a5636c6f4 100644 --- a/wally-pipelined/src/generic/flop.sv +++ b/wally-pipelined/src/generic/flop.sv @@ -82,11 +82,11 @@ module flopenr #(parameter WIDTH = 8) ( endmodule // flop with enable, asynchronous load -module flopenl #(parameter WIDTH = 8) ( - input logic clk, load, en, - input logic [WIDTH-1:0] d, - input logic [WIDTH-1:0] val, - output logic [WIDTH-1:0] q); +module flopenl #(parameter WIDTH = 8, parameter type TYPE=logic [WIDTH-1:0]) ( + input logic clk, load, en, + input TYPE d, + input TYPE val, + output TYPE q); always_ff @(posedge clk, posedge load) if (load) q <= #1 val; diff --git a/wally-pipelined/src/ieu/controller.sv b/wally-pipelined/src/ieu/controller.sv index dc4f16d5b..a1be47ad9 100644 --- a/wally-pipelined/src/ieu/controller.sv +++ b/wally-pipelined/src/ieu/controller.sv @@ -48,7 +48,7 @@ module controller( input logic StallM, FlushM, output logic [1:0] MemRWM, output logic CSRReadM, CSRWriteM, PrivilegedM, - output logic AtomicM, + output logic [1:0] AtomicM, output logic [2:0] Funct3M, output logic RegWriteM, // for Hazard Unit // Writeback stage control signals @@ -65,6 +65,8 @@ module controller( logic [6:0] Funct7D; logic [4:0] Rs1D; + `define CTRLW 23 + // pipelined control signals logic RegWriteD, RegWriteE; logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM; @@ -77,11 +79,11 @@ module controller( logic TargetSrcD, W64D, MulDivD; logic CSRZeroSrcD; logic CSRReadD; - logic AtomicD, AtomicE; + logic [1:0] AtomicD, AtomicE; logic CSRWriteD, CSRWriteE; logic InstrValidE, InstrValidM; logic PrivilegedD, PrivilegedE; - logic [21:0] ControlsD; + logic [`CTRLW-1:0] ControlsD; logic aluc3D; logic subD, sraD, sltD, sltuD; logic BranchTakenE; @@ -100,48 +102,47 @@ module controller( generate always_comb case(OpD) - // *** Atomic p. 132 assembly encodings, defs 48 // RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_TargetSrc_W64_CSRRead_Privileged_MulDiv_Atomic_Illegal - 7'b0000000: ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_0_1; // illegal instruction - 7'b0000011: ControlsD = 22'b1_000_01_10_001_0_00_0_0_0_0_0_0_0_0; // lw - 7'b0001111: ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_0_0; // fence = nop - 7'b0010011: ControlsD = 22'b1_000_01_00_000_0_10_0_0_0_0_0_0_0_0; // I-type ALU - 7'b0010111: ControlsD = 22'b1_100_11_00_000_0_00_0_0_0_0_0_0_0_0; // auipc + 7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_00_0_0_0_0_0_0_00_1; // illegal instruction + 7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_00_0_0_0_0_0_0_00_0; // lw + 7'b0001111: ControlsD = `CTRLW'b0_000_00_00_000_0_00_0_0_0_0_0_0_00_0; // fence = nop + 7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_10_0_0_0_0_0_0_00_0; // I-type ALU + 7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_00_0_0_0_0_0_0_00_0; // auipc 7'b0011011: if (`XLEN == 64) - ControlsD = 22'b1_000_01_00_000_0_10_0_0_1_0_0_0_0_0; // IW-type ALU for RV64i + ControlsD = `CTRLW'b1_000_01_00_000_0_10_0_0_1_0_0_0_00_0; // IW-type ALU for RV64i else - ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_0_1; // non-implemented instruction - 7'b0100011: ControlsD = 22'b0_001_01_01_000_0_00_0_0_0_0_0_0_0_0; // sw + ControlsD = `CTRLW'b0_000_00_00_000_0_00_0_0_0_0_0_0_00_1; // non-implemented instruction + 7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_00_0_0_0_0_0_0_00_0; // sw 7'b0101111: if (`A_SUPPORTED) begin if (InstrD[31:27] == 5'b00010) - ControlsD = 22'b1_000_00_10_001_0_00_0_0_0_0_0_0_1_0; // lr + ControlsD = `CTRLW'b1_000_00_10_001_0_00_0_0_0_0_0_0_01_0; // lr else if (InstrD[31:27] == 5'b00011) - ControlsD = 22'b1_101_01_01_101_0_00_0_0_0_0_0_0_1_0; // sc + ControlsD = `CTRLW'b1_101_01_01_101_0_00_0_0_0_0_0_0_01_0; // sc else - ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_1_0; // other atomic; decode later + ControlsD = `CTRLW'b1_101_01_11_001_0_00_0_0_0_0_0_0_10_0;; // amo end else - ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_0_1; // non-implemented instruction + ControlsD = `CTRLW'b0_000_00_00_000_0_00_0_0_0_0_0_0_00_1; // non-implemented instruction 7'b0110011: if (Funct7D == 7'b0000000 || Funct7D == 7'b0100000) - ControlsD = 22'b1_000_00_00_000_0_10_0_0_0_0_0_0_0_0; // R-type + ControlsD = `CTRLW'b1_000_00_00_000_0_10_0_0_0_0_0_0_00_0; // R-type else if (Funct7D == 7'b0000001 && `M_SUPPORTED) - ControlsD = 22'b1_000_00_00_100_0_00_0_0_0_0_0_1_0_0; // Multiply/Divide + ControlsD = `CTRLW'b1_000_00_00_100_0_00_0_0_0_0_0_1_00_0; // Multiply/Divide else - ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_0_1; // non-implemented instruction - 7'b0110111: ControlsD = 22'b1_100_01_00_000_0_11_0_0_0_0_0_0_0_0; // lui + ControlsD = `CTRLW'b0_000_00_00_000_0_00_0_0_0_0_0_0_00_1; // non-implemented instruction + 7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_11_0_0_0_0_0_0_00_0; // lui 7'b0111011: if ((Funct7D == 7'b0000000 || Funct7D == 7'b0100000) && `XLEN == 64) - ControlsD = 22'b1_000_00_00_000_0_10_0_0_1_0_0_0_0_0; // R-type W instructions for RV64i + ControlsD = `CTRLW'b1_000_00_00_000_0_10_0_0_1_0_0_0_00_0; // R-type W instructions for RV64i else if (Funct7D == 7'b0000001 && `M_SUPPORTED && `XLEN == 64) - ControlsD = 22'b1_000_00_00_100_0_00_0_0_1_0_0_1_0_0; // W-type Multiply/Divide + ControlsD = `CTRLW'b1_000_00_00_100_0_00_0_0_1_0_0_1_00_0; // W-type Multiply/Divide else - ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_0_1; // non-implemented instruction - 7'b1100011: ControlsD = 22'b0_010_00_00_000_1_01_0_0_0_0_0_0_0_0; // beq - 7'b1100111: ControlsD = 22'b1_000_00_00_010_0_00_1_1_0_0_0_0_0_0; // jalr - 7'b1101111: ControlsD = 22'b1_011_00_00_010_0_00_1_0_0_0_0_0_0_0; // jal + ControlsD = `CTRLW'b0_000_00_00_000_0_00_0_0_0_0_0_0_00_1; // non-implemented instruction + 7'b1100011: ControlsD = `CTRLW'b0_010_00_00_000_1_01_0_0_0_0_0_0_00_0; // beq + 7'b1100111: ControlsD = `CTRLW'b1_000_00_00_010_0_00_1_1_0_0_0_0_00_0; // jalr + 7'b1101111: ControlsD = `CTRLW'b1_011_00_00_010_0_00_1_0_0_0_0_0_00_0; // jal 7'b1110011: if (Funct3D == 3'b000) - ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_1_0_0_0; // privileged; decoded further in priveleged modules + ControlsD = `CTRLW'b0_000_00_00_000_0_00_0_0_0_0_1_0_00_0; // privileged; decoded further in priveleged modules else - ControlsD = 22'b1_000_00_00_011_0_00_0_0_0_1_0_0_0_0; // csrs - default: ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_0_1; // non-implemented instruction + ControlsD = `CTRLW'b1_000_00_00_011_0_00_0_0_0_1_0_0_00_0; // csrs + default: ControlsD = `CTRLW'b0_000_00_00_000_0_00_0_0_0_0_0_0_00_1; // non-implemented instruction endcase endgenerate @@ -173,7 +174,7 @@ module controller( endcase // Execute stage pipeline control register and logic - flopenrc #(26) controlregE(clk, reset, FlushE, ~StallE, + flopenrc #(27) controlregE(clk, reset, FlushE, ~StallE, {RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, TargetSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MulDivD, AtomicD, 1'b1}, {RegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MulDivE, AtomicE, InstrValidE}); @@ -196,7 +197,7 @@ module controller( assign MemReadE = MemRWE[1]; // Memory stage pipeline control register - flopenrc #(14) controlregM(clk, reset, FlushM, ~StallM, + flopenrc #(15) controlregM(clk, reset, FlushM, ~StallM, {RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, AtomicE, InstrValidE}, {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, AtomicM, InstrValidM}); diff --git a/wally-pipelined/src/ieu/ieu.sv b/wally-pipelined/src/ieu/ieu.sv index d021bca62..f408fbd9d 100644 --- a/wally-pipelined/src/ieu/ieu.sv +++ b/wally-pipelined/src/ieu/ieu.sv @@ -43,7 +43,7 @@ module ieu ( input logic DataAccessFaultM, input logic SquashSCW, output logic [1:0] MemRWM, - output logic AtomicM, + output logic [1:0] AtomicM, output logic [`XLEN-1:0] MemAdrM, WriteDataM, output logic [`XLEN-1:0] SrcAM, output logic [2:0] Funct3M, diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index 613120c0a..35ac6cfb5 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -124,30 +124,30 @@ module bpred flopenrc #(2) BPPredRegD(.clk(clk), .reset(reset), - .en(~StallF), - .clear(FlushF), + .en(~StallD), + .clear(FlushD), .d(BPPredF), .q(BPPredD)); flopenrc #(2) BPPredRegE(.clk(clk), .reset(reset), - .en(~StallD), - .clear(FlushD), + .en(~StallE), + .clear(FlushE), .d(BPPredD), .q(BPPredE)); // pipeline the class flopenrc #(4) InstrClassRegD(.clk(clk), .reset(reset), - .en(~StallF), - .clear(FlushF), + .en(~StallD), + .clear(FlushD), .d(BPInstrClassF), .q(BPInstrClassD)); flopenrc #(4) InstrClassRegE(.clk(clk), .reset(reset), - .en(~StallD), - .clear(FlushD), + .en(~StallE), + .clear(FlushE), .d(BPInstrClassD), .q(BPInstrClassE)); diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 14ce4280e..2fe212dde 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -57,8 +57,8 @@ module ifu ( output logic [`XLEN-1:0] InstrMisalignedAdrM, // TLB management //input logic [`XLEN-1:0] PageTableEntryF, + input logic [`XLEN-1:0] SATP_REGW, //input logic ITLBWriteF, ITLBFlushF, - // *** satp value will come from CSRs // input logic [`XLEN-1:0] SATP, output logic ITLBMissF, ITLBHitF ); @@ -73,14 +73,11 @@ module ifu ( logic [31:0] nop = 32'h00000013; // instruction for NOP logic [`XLEN-1:0] ITLBInstrPAdrF, ICacheInstrPAdrF; - // *** temporary hack until we can figure out how to get actual satp value - // from priv unit -- Thomas F - logic [`XLEN-1:0] SATP = '0; // *** temporary hack until walker is hooked up -- Thomas F logic [`XLEN-1:0] PageTableEntryF = '0; logic ITLBFlushF = '0; logic ITLBWriteF = '0; - tlb #(3) itlb(clk, reset, SATP, PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF, + tlb #(3) itlb(clk, reset, SATP_REGW, PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF, ITLBInstrPAdrF, ITLBMissF, ITLBHitF); // branch predictor signals @@ -195,8 +192,8 @@ module ifu ( flopenrc #(4) InstrClassRegE(.clk(clk), .reset(reset), - .en(~StallD), - .clear(FlushD), + .en(~StallE), + .clear(FlushE), .d(InstrClassD), .q(InstrClassE)); diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 7be0f0b75..4d4e46a37 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -25,6 +25,7 @@ /////////////////////////////////////////// `include "wally-config.vh" +`include "wally-constants.vh" /** * sv32 specs @@ -57,7 +58,7 @@ module tlb #(parameter ENTRY_BITS = 3) ( input clk, reset, // Current value of satp CSR (from privileged unit) - input [`XLEN-1:0] SATP, // *** How do we get this? + input [`XLEN-1:0] SATP_REGW, // Virtual address input input [`XLEN-1:0] VirtualAddress, @@ -75,32 +76,29 @@ module tlb #(parameter ENTRY_BITS = 3) ( output TLBHit ); + logic SvMode; + generate - if (`XLEN == 32) begin: ARCH - localparam VPN_BITS = 20; - localparam PPN_BITS = 22; - localparam PA_BITS = 34; - - logic SvMode; - assign SvMode = SATP[31]; // *** change to an enum somehow? - end else begin: ARCH - localparam VPN_BITS = 27; - localparam PPN_BITS = 44; - localparam PA_BITS = 56; - - logic SvMode; // currently just a boolean whether translation enabled - assign SvMode = SATP[63]; // *** change to an enum somehow? + if (`XLEN == 32) begin + assign SvMode = SATP_REGW[31]; // *** change to an enum somehow? + end else begin + assign SvMode = SATP_REGW[63]; // currently just a boolean whether translation enabled end endgenerate + // *** If we want to support multiple virtual memory modes (ie sv39 AND sv48), + // we could have some muxes that control which parameters are current. + // Although then some of the signals are not big enough. But that's a problem + // for much later. + // Index (currently random) to write the next TLB entry logic [ENTRY_BITS-1:0] WriteIndex; // Sections of the virtual and physical addresses - logic [ARCH.VPN_BITS-1:0] VirtualPageNumber; - logic [ARCH.PPN_BITS-1:0] PhysicalPageNumber; - logic [11:0] PageOffset; - logic [ARCH.PA_BITS-1:0] PhysicalAddressFull; + logic [`VPN_BITS-1:0] VirtualPageNumber; + logic [`PPN_BITS-1:0] PhysicalPageNumber; + logic [11:0] PageOffset; + logic [`PA_BITS-1:0] PhysicalAddressFull; // Pattern and pattern location in the CAM logic [ENTRY_BITS-1:0] VPNIndex; @@ -111,7 +109,7 @@ module tlb #(parameter ENTRY_BITS = 3) ( // Page table entry matching the virtual address logic [`XLEN-1:0] PageTableEntry; - assign VirtualPageNumber = VirtualAddress[ARCH.VPN_BITS+11:12]; + assign VirtualPageNumber = VirtualAddress[`VPN_BITS+11:12]; assign PageOffset = VirtualAddress[11:0]; // Choose a read or write location to the entry list @@ -121,28 +119,28 @@ module tlb #(parameter ENTRY_BITS = 3) ( tlb_rand rdm(.*); tlb_ram #(ENTRY_BITS) ram(.*); - tlb_cam #(ENTRY_BITS, ARCH.VPN_BITS) cam(.*); + tlb_cam #(ENTRY_BITS, `VPN_BITS) cam(.*); always_comb begin - assign PhysicalPageNumber = PageTableEntry[ARCH.PPN_BITS+9:10]; + assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10]; if (TLBHit) begin assign PhysicalAddressFull = {PhysicalPageNumber, PageOffset}; end else begin - assign PhysicalAddressFull = 8'b0; // *** Actual behavior; disabled until walker functioning + assign PhysicalAddressFull = '0; // *** Actual behavior; disabled until walker functioning //assign PhysicalAddressFull = {2'b0, VirtualPageNumber, PageOffset} // *** pass through should be removed as soon as walker ready end end generate if (`XLEN == 32) begin - mux2 #(`XLEN) addressmux(VirtualAddress, PhysicalAddressFull[31:0], ARCH.SvMode, PhysicalAddress); + mux2 #(`XLEN) addressmux(VirtualAddress, PhysicalAddressFull[31:0], SvMode, PhysicalAddress); end else begin - mux2 #(`XLEN) addressmux(VirtualAddress, {8'b0, PhysicalAddressFull}, ARCH.SvMode, PhysicalAddress); + mux2 #(`XLEN) addressmux(VirtualAddress, {8'b0, PhysicalAddressFull}, SvMode, PhysicalAddress); end endgenerate - assign TLBMiss = ~TLBHit & ~(TLBWrite | TLBFlush) & ARCH.SvMode; + assign TLBMiss = ~TLBHit & ~(TLBWrite | TLBFlush) & SvMode; endmodule module tlb_ram #(parameter ENTRY_BITS = 3) ( @@ -217,13 +215,13 @@ module tlb_cam #(parameter ENTRY_BITS = 3, initial begin for (int i = 0; i < NENTRIES; i++) - ram[i] <= '0; + ram[i] = '0; end endmodule module tlb_rand #(parameter ENTRY_BITS = 3) ( - input clk, reset, + input clk, reset, output [ENTRY_BITS-1:0] WriteIndex ); diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index f1f16ac97..5d3c24a49 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -40,6 +40,7 @@ module csr ( output logic STATUS_SPP, STATUS_TSR, output logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW, output logic [`XLEN-1:0] MEDELEG_REGW, MIDELEG_REGW, SEDELEG_REGW, SIDELEG_REGW, + output logic [`XLEN-1:0] SATP_REGW, output logic [11:0] MIP_REGW, MIE_REGW, output logic STATUS_MIE, STATUS_SIE, input logic [4:0] SetFflagsM, @@ -126,6 +127,7 @@ module csr ( assign MIDELEG_REGW = 0; assign SEDELEG_REGW = 0; assign SIDELEG_REGW = 0; + assign SATP_REGW = 0; assign MIP_REGW = 0; assign MIE_REGW = 0; assign STATUS_MIE = 0; diff --git a/wally-pipelined/src/privileged/csrs.sv b/wally-pipelined/src/privileged/csrs.sv index 19d533c89..8b851e07e 100644 --- a/wally-pipelined/src/privileged/csrs.sv +++ b/wally-pipelined/src/privileged/csrs.sv @@ -48,6 +48,7 @@ module csrs #(parameter output logic [`XLEN-1:0] CSRSReadValM, SEPC_REGW, STVEC_REGW, output logic [31:0] SCOUNTEREN_REGW, output logic [`XLEN-1:0] SEDELEG_REGW, SIDELEG_REGW, + output logic [`XLEN-1:0] SATP_REGW, input logic [11:0] SIP_REGW, SIE_REGW, output logic WriteSSTATUSM, output logic IllegalCSRSAccessM @@ -63,7 +64,7 @@ module csrs #(parameter logic WriteSTVECM; logic WriteSSCRATCHM, WriteSEPCM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; - logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW, SATP_REGW; + logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW; assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS); assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC); @@ -127,6 +128,7 @@ module csrs #(parameter assign SEDELEG_REGW = 0; assign SIDELEG_REGW = 0; assign SCOUNTEREN_REGW = 0; + assign SATP_REGW = 0; assign IllegalCSRSAccessM = 1; end endgenerate diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 71b905865..a01fa557c 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -44,6 +44,7 @@ module privileged ( input logic TimerIntM, ExtIntM, SwIntM, input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM, input logic [4:0] SetFflagsM, + output logic [`XLEN-1:0] SATP_REGW, output logic [2:0] FRM_REGW, input logic FlushD, FlushE, FlushM, StallD, StallW ); diff --git a/wally-pipelined/src/uncore/clint.sv b/wally-pipelined/src/uncore/clint.sv index 71770323e..e672a7692 100644 --- a/wally-pipelined/src/uncore/clint.sv +++ b/wally-pipelined/src/uncore/clint.sv @@ -45,9 +45,7 @@ module clint ( assign memread = HSELCLINT & ~HWRITE; assign memwrite = HSELCLINT & HWRITE; assign HRESPCLINT = 0; // OK -// assign HREADYCLINT = 1; // Respond immediately - always_ff @(posedge HCLK) // delay response - HREADYCLINT <= memread | memwrite; + assign HREADYCLINT = 1'b1; // will need to be modified if CLINT ever needs more than 1 cycle to do something // word aligned reads generate diff --git a/wally-pipelined/src/uncore/dtim.sv b/wally-pipelined/src/uncore/dtim.sv index 3634b022e..d9e0d81cb 100644 --- a/wally-pipelined/src/uncore/dtim.sv +++ b/wally-pipelined/src/uncore/dtim.sv @@ -64,7 +64,7 @@ module dtim #(parameter BASE=0, RANGE = 65535) ( busycount <= 0; HREADYTim <= #1 0; end else if (~HREADYTim) begin - if (busycount == 2) begin // TIM latency, for testing purposes + if (busycount == 2) begin // TIM latency, for testing purposes. *** test with different values HREADYTim <= #1 1; end else begin busycount <= busycount + 1; diff --git a/wally-pipelined/src/uncore/imem.sv b/wally-pipelined/src/uncore/imem.sv index 4ce2e4666..64f3a0d64 100644 --- a/wally-pipelined/src/uncore/imem.sv +++ b/wally-pipelined/src/uncore/imem.sv @@ -37,12 +37,12 @@ module imem ( logic [`XLEN-1:0] bootram[`BOOTTIMBASE>>(1+`XLEN/32):(`BOOTTIMRANGE+`BOOTTIMBASE)>>(1+`XLEN/32)]; `endif /* verilator lint_on UNDRIVEN */ - logic [28:0] adrbits; + logic [31:0] adrbits; // needs to be 32 bits to index RAM logic [`XLEN-1:0] rd; // logic [15:0] rd2; generate - if (`XLEN==32) assign adrbits = AdrF[30:2]; + if (`XLEN==32) assign adrbits = AdrF[31:2]; else assign adrbits = AdrF[31:3]; endgenerate diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 455a911fd..74279bf54 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -60,7 +60,8 @@ module wallypipelinedhart ( // new signals that must connect through DP logic MulDivE, W64E; - logic CSRReadM, CSRWriteM, PrivilegedM, AtomicM; + logic CSRReadM, CSRWriteM, PrivilegedM; + logic [1:0] AtomicM; logic [`XLEN-1:0] SrcAE, SrcBE; logic [`XLEN-1:0] SrcAM; logic [2:0] Funct3E; @@ -88,8 +89,12 @@ module wallypipelinedhart ( logic SquashSCW; // memory management unit signals + logic ITLBWriteF, DTLBWriteM; logic ITLBMissF, ITLBHitF; logic DTLBMissM, DTLBHitM; + logic [`XLEN-1:0] SATP_REGW; + + logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM; // ICache stalls logic ICacheStallF; @@ -116,8 +121,11 @@ module wallypipelinedhart ( //.InstrReadF(1'b0), //.InstrRData(InstrF), // hook up InstrF later .MemSizeM(Funct3M[1:0]), .UnsignedLoadM(Funct3M[2]), + .Funct7M(InstrM[31:25]), .*); + // walker walker(.*); *** // can send addresses to ahblite, send out pagetablestall + // *** can connect to hazard unit // changing from this to the line above breaks the program. auipc at 104 fails; seems to be flushed. // Would need to insertinstruction as InstrD, not InstrF /*ahblite ebu( diff --git a/wally-pipelined/testbench/function_radix.sv b/wally-pipelined/testbench/function_radix.sv index 4e6d2ae40..b5c34c2b5 100644 --- a/wally-pipelined/testbench/function_radix.sv +++ b/wally-pipelined/testbench/function_radix.sv @@ -4,6 +4,7 @@ // Written: Ross Thompson // email: ross1728@gmail.com // Created: November 9, 2019 +// Modified: March 04, 2021 // // Purpose: Finds the current function or global assembly label based on PCE. // @@ -26,83 +27,125 @@ `include "wally-config.vh" -module function_radix(); +module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); + + input logic reset; + input string ProgramAddrMapFile; + input string ProgramLabelMapFile; - parameter PRELOAD_FILE = "funct_addr.txt"; + logic [`XLEN-1:0] ProgramAddrMapMemory []; + string ProgramLabelMapMemory [integer]; + string FunctionName; + - integer memory_bank []; - integer index; + logic [`XLEN-1:0] pc, FunctionAddr; + integer ProgramAddrIndex; - logic [`XLEN-1:0] pc; - - initial begin - $init_signal_spy("/riscv_mram_tb/dut/pc", "/riscv_mram_tb/function_radix/pc"); - end + // *** I should look into the system verilog objects instead of signal spy. + initial begin + $init_signal_spy("/testbench/dut/hart/PCE", "/testbench/functionRadix/function_radix/pc"); + end - task automatic bin_search_min; - input integer pc; - input integer length; - ref integer array []; - output integer minval; + task automatic bin_search_min; + input logic [`XLEN-1:0] pc; + input logic [`XLEN-1:0] length; + ref logic [`XLEN-1:0] array []; + output logic [`XLEN-1:0] minval; + output logic [`XLEN-1:0] mid; - integer left, right; - integer mid; + logic [`XLEN-1:0] left, right; - begin - left = 0; - right = length; - while (left <= right) begin - mid = left + ((right - left) / 2); - if (array[mid] == pc) begin - minval = array[mid]; - return; - end - if (array[mid] < pc) begin - left = mid + 1; - end else begin - right = mid -1; - end - end // while (left <= right) - // if the element pc is now found, right and left will be equal at this point. - // we need to check if pc is less than the array at left or greather. - // if it is less than pc, then we select left as the index. - // if it is greather we want 1 less than left. - if (array[left] < pc) begin - minval = array[left]; - return; - end else begin - minval = array[left-1]; - return; - end + begin + if ( pc == 0 ) begin + // *** want to keep the old value for mid and minval + mid = 0; + return; end - endtask - - - // preload - initial $readmemh(PRELOAD_FILE, memory_bank); - - // we need to count the number of lines in the file so we can set line_count. - integer fp; - integer line_count = 0; - logic [31:0] line; - initial begin - fp = $fopen(PRELOAD_FILE, "r"); - // read line by line to count lines - if (fp) begin - while (! $feof(fp)) begin - $fscanf(fp, "%h\n", line); - line_count = line_count + 1; - end + left = 0; + right = length; + while (left <= right) begin + mid = left + ((right - left) / 2); + if (array[mid] == pc) begin + minval = array[mid]; + return; + end + if (array[mid] < pc) begin + left = mid + 1; + end else if( array[mid] > pc) begin + right = mid -1; + end else begin + $display("Critical Error in function radix. PC, %x not found.", pc); + return; + //$stop(); + end + end // while (left <= right) + // if the element pc is now found, right and left will be equal at this point. + // we need to check if pc is less than the array at left or greather. + // if it is less than pc, then we select left as the index. + // if it is greather we want 1 less than left. + if (array[left] < pc) begin + minval = array[left]; + return; end else begin - $display("Cannot open file %s for reading.", PRELOAD_FILE); - $stop; + minval = array[left-1]; + return; end - end + end + endtask // bin_search_min - always @(pc) begin - bin_search_min(pc, line_count, memory_bank, index); - - end + integer ProgramAddrMapFP, ProgramLabelMapFP; + integer ProgramAddrMapLineCount, ProgramLabelMapLineCount; + longint ProgramAddrMapLine; + string ProgramLabelMapLine; + + // preload +// initial begin + always @ (posedge reset) begin + $readmemh(ProgramAddrMapFile, ProgramAddrMapMemory); + // we need to count the number of lines in the file so we can set FunctionRadixLineCount. + + ProgramAddrMapLineCount = 0; + ProgramAddrMapFP = $fopen(ProgramAddrMapFile, "r"); + + // read line by line to count lines + if (ProgramAddrMapFP) begin + while (! $feof(ProgramAddrMapFP)) begin + $fscanf(ProgramAddrMapFP, "%h\n", ProgramAddrMapLine); + + ProgramAddrMapLineCount = ProgramAddrMapLineCount + 1; + end + end else begin + $display("Cannot open file %s for reading.", ProgramAddrMapFile); + end + $fclose(ProgramAddrMapFP); + + // ProgramIndexFile maps the program name to the compile index. + // The compile index is then used to inditify the application + // in the custom radix. + // Build an associative array to convert the name to an index. + ProgramLabelMapLineCount = 0; + ProgramLabelMapFP = $fopen(ProgramLabelMapFile, "r"); + + if (ProgramLabelMapFP) begin + while (! $feof(ProgramLabelMapFP)) begin + $fscanf(ProgramLabelMapFP, "%s\n", ProgramLabelMapLine); + ProgramLabelMapMemory[ProgramLabelMapLineCount] = ProgramLabelMapLine; + ProgramLabelMapLineCount = ProgramLabelMapLineCount + 1; + end + end else begin + $display("Cannot open file %s for reading.", ProgramLabelMapFile); + end + $fclose(ProgramLabelMapFP); + + end + + always @(pc) begin + bin_search_min(pc, ProgramAddrMapLineCount, ProgramAddrMapMemory, FunctionAddr, ProgramAddrIndex); + end + + + assign FunctionName = ProgramLabelMapMemory[ProgramAddrIndex]; + endmodule // function_radix diff --git a/wally-pipelined/testbench/testbench-busybear.sv b/wally-pipelined/testbench/testbench-busybear.sv index e4c9c9e39..ababf7e42 100644 --- a/wally-pipelined/testbench/testbench-busybear.sv +++ b/wally-pipelined/testbench/testbench-busybear.sv @@ -294,7 +294,7 @@ module testbench_busybear(); `CHECK_CSR(MTVEC) //`CHECK_CSR2(PMPADDR0, `CSRM) //`CHECK_CSR2(PMdut.PCFG0, `CSRM) - `CHECK_CSR2(SATP, `CSRS) + `CHECK_CSR(SATP) `CHECK_CSR2(SCAUSE, `CSRS) `CHECK_CSR(SCOUNTEREN) `CHECK_CSR(SEPC) diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index b59d54534..8ee8db49d 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -27,6 +27,8 @@ `include "wally-config.vh" module testbench(); + parameter DEBUG = 0; + logic clk; logic reset; @@ -38,6 +40,7 @@ module testbench(); //logic [31:0] InstrW; logic [`XLEN-1:0] meminit; string tests64a[] = '{ + "rv64a/WALLY-AMO", "2110", "rv64a/WALLY-LRSC", "2110" }; string tests64m[] = '{ @@ -189,6 +192,10 @@ string tests64iNOc[] = { "rv64i/WALLY-CSRRCI", "4000" }; + string tests32a[] = '{ + "rv64a/WALLY-AMO", "2110", + "rv64a/WALLY-LRSC", "2110" + }; string tests32m[] = '{ "rv32m/I-MUL-01", "2000", "rv32m/I-MULH-01", "2000", @@ -307,6 +314,7 @@ string tests32i[] = { }; string tests[]; + string ProgramAddrMapFile, ProgramLabelMapFile; logic [`AHBW-1:0] HRDATAEXT; logic HREADYEXT, HRESPEXT; logic [31:0] HADDR; @@ -334,6 +342,7 @@ string tests32i[] = { if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic}; else tests = {tests, tests32iNOc}; if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m}; + if (`A_SUPPORTED) tests = {tests, tests32a}; end string signame, memfilename; @@ -372,6 +381,8 @@ string tests32i[] = { memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; $readmemh(memfilename, dut.imem.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM); + ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"}; + ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"}; $display("Read memfile %s", memfilename); reset = 1; # 42; reset = 0; end @@ -446,13 +457,19 @@ string tests32i[] = { $readmemh(memfilename, dut.imem.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM); $display("Read memfile %s", memfilename); + ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"}; + ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"}; reset = 1; # 17; reset = 0; end end end // always @ (negedge clk) - // track the current function or label - //function_rfunction_radix function_radix(); + // track the current function or global label + if (DEBUG == 1) begin : functionRadix + function_radix function_radix(.reset(reset), + .ProgramAddrMapFile(ProgramAddrMapFile), + .ProgramLabelMapFile(ProgramLabelMapFile)); + end endmodule