mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
5a521e28ee
26
.gitignore
vendored
26
.gitignore
vendored
@ -19,27 +19,19 @@ wlft*
|
|||||||
/imperas-riscv-tests/FunctionRadix.addr
|
/imperas-riscv-tests/FunctionRadix.addr
|
||||||
/imperas-riscv-tests/ProgramMap.txt
|
/imperas-riscv-tests/ProgramMap.txt
|
||||||
/imperas-riscv-tests/logs
|
/imperas-riscv-tests/logs
|
||||||
/wally-pipelined/linux-testgen/qemu_output.txt
|
|
||||||
/wally-pipelined/linux-testgen/qemu_in_gdb_format.txt
|
|
||||||
*.o
|
*.o
|
||||||
*.d
|
*.d
|
||||||
testsBP/*/*/*.elf*
|
testsBP/*/*/*.elf*
|
||||||
testsBP/*/OBJ/*
|
testsBP/*/OBJ/*
|
||||||
testsBP/*/*.a
|
testsBP/*/*.a
|
||||||
wally-pipelined/linux-testgen/linux-testvectors/*
|
tests/linux-testgen/linux-testvectors/*
|
||||||
wally-pipelined/linux-testgen/nohup*
|
!tests/linux-testgen/linux-testvectors/tvCopier.py
|
||||||
wally-pipelined/linux-testgen/x*
|
!tests/linux-testgen/linux-testvectors/tvLinker.sh
|
||||||
!wally-pipelined/linux-testgen/linux-testvectors/tvCopier.py
|
!tests/linux-testgen/linux-testvectors/tvUnlinker.sh
|
||||||
!wally-pipelined/linux-testgen/linux-testvectors/tvLinker.sh
|
tests/linux-testgen/buildroot
|
||||||
!wally-pipelined/linux-testgen/linux-testvectors/tvUnlinker.sh
|
tests/linux-testgen/buildroot-image-output
|
||||||
!wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs
|
tests/linux-testgen/buildroot-config-src/main.config.old
|
||||||
wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs/*
|
tests/linux-testgen/buildroot-config-src/linux.config.old
|
||||||
!wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs/git_create_dir.txt
|
tests/linux-testgen/buildroot-config-src/busybox.config.old
|
||||||
wally-pipelined/linux-testgen/buildroot/
|
|
||||||
wally-pipelined/linux-testgen/buildroot-image-output
|
|
||||||
wally-pipelined/linux-testgen/buildroot-config-src/main.config.old
|
|
||||||
wally-pipelined/linux-testgen/buildroot-config-src/linux.config.old
|
|
||||||
wally-pipelined/linux-testgen/buildroot-config-src/busybox.config.old
|
|
||||||
wally-pipelined/regression/slack-notifier/slack-webhook-url.txt
|
wally-pipelined/regression/slack-notifier/slack-webhook-url.txt
|
||||||
wally-pipelined/regression/logs
|
wally-pipelined/regression/logs
|
||||||
|
|
||||||
|
17
README.md
17
README.md
@ -8,15 +8,15 @@ To use Wally on Linux:
|
|||||||
```
|
```
|
||||||
git clone https://github.com/davidharrishmc/riscv-wally
|
git clone https://github.com/davidharrishmc/riscv-wally
|
||||||
cd riscv-wally
|
cd riscv-wally
|
||||||
cd imperas-riscv-tests
|
cd addins
|
||||||
make
|
*** can these clones be replaced with git submodule commands?
|
||||||
cd ../addins
|
|
||||||
git clone https://github.com/riscv-non-isa/riscv-arch-test
|
git clone https://github.com/riscv-non-isa/riscv-arch-test
|
||||||
git clone https://github.com/riscv-software-src/riscv-isa-sim
|
git clone https://github.com/riscv-software-src/riscv-isa-sim
|
||||||
cd riscv-isa-sim
|
cd riscv-isa-sim
|
||||||
|
*** replace these with a copy from ../install/F and ../install/D containing the Makefile.includes already updated
|
||||||
cp -r arch_test_target/spike/device/rv32i_m/I arch_test_target/spike/device/rv32i_m/F
|
cp -r arch_test_target/spike/device/rv32i_m/I arch_test_target/spike/device/rv32i_m/F
|
||||||
<edit arch_test_target/spike/device/rv32i_m/F/Makefile.include line 35 and change --isa=rv32i to --isa=rv32if>
|
<edit arch_test_target/spike/device/rv32i_m/F/Makefile.include line 35 and change --isa=rv32i to --isa=rv32if>
|
||||||
cp -r arch_test_target/spike/device/rv32i_m/I arch_test_target/spike/device/rv64i_m/D
|
cp -r arch_test_target/spike/device/rv64i_m/I arch_test_target/spike/device/rv64i_m/D
|
||||||
<edit arch_test_target/spike/device/rv64i_m/D/Makefile.include line 35 and change --isa=rv64i to --isa=rv64id>
|
<edit arch_test_target/spike/device/rv64i_m/D/Makefile.include line 35 and change --isa=rv64i to --isa=rv64id>
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
@ -32,6 +32,15 @@ edit Makefile.include
|
|||||||
make
|
make
|
||||||
make XLEN=32
|
make XLEN=32
|
||||||
exe2memfile.pl work/*/*/*.elf # converts ELF files to a format that can be read by Modelsim
|
exe2memfile.pl work/*/*/*.elf # converts ELF files to a format that can be read by Modelsim
|
||||||
|
cd ../../tests
|
||||||
|
cd imperas-riscv-tests
|
||||||
|
make
|
||||||
|
cd ../wally-riscv-arch-test
|
||||||
|
make
|
||||||
|
make XLEN=32
|
||||||
|
exe2memfile.pl work/*/*/*.elf # converts ELF files to a format that can be read by Modelsim
|
||||||
|
cd ../../tests/linux-testgen/linux-testvectors
|
||||||
|
./tvLinker.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
3
tests/linux-testgen/linux-testvectors/tvLinker.sh
Executable file
3
tests/linux-testgen/linux-testvectors/tvLinker.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
echo "Warning: this script will only work if your repo is on Tera"
|
||||||
|
ln -s /courses/e190ax/linux-testvectors-shared/* ./
|
||||||
|
echo "Done!"
|
13
tests/linux-testgen/testvector-generation/Makefile
Normal file
13
tests/linux-testgen/testvector-generation/Makefile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
CFLAG = -Wall -g
|
||||||
|
CC = clang
|
||||||
|
|
||||||
|
all: fixBinMem
|
||||||
|
|
||||||
|
fixBinMem: fixBinMem.c
|
||||||
|
${CC} ${CFLAGS} fixBinMem.c -o fixBinMem
|
||||||
|
chmod +x fixBinMem
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f fixBinMem
|
5
tests/linux-testgen/testvector-generation/checkpointSweep.sh
Executable file
5
tests/linux-testgen/testvector-generation/checkpointSweep.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
for index in {0..105}
|
||||||
|
do
|
||||||
|
instrs=$(((400+$index)*1000000))
|
||||||
|
echo "y" | ./genCheckpoint.sh $instrs
|
||||||
|
done
|
@ -5,6 +5,7 @@ tcpPort=1237
|
|||||||
# Run without GDB
|
# Run without GDB
|
||||||
($customQemu \
|
($customQemu \
|
||||||
-M virt \
|
-M virt \
|
||||||
|
-m 128M \
|
||||||
-nographic \
|
-nographic \
|
||||||
-bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \
|
-bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \
|
||||||
-singlestep -rtc clock=vm -icount shift=1,align=off,sleep=on)
|
-singlestep -rtc clock=vm -icount shift=1,align=off,sleep=on)
|
BIN
tests/linux-testgen/testvector-generation/fixBinMem
Executable file
BIN
tests/linux-testgen/testvector-generation/fixBinMem
Executable file
Binary file not shown.
33
tests/linux-testgen/testvector-generation/fixBinMem.c
Normal file
33
tests/linux-testgen/testvector-generation/fixBinMem.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc < 3){
|
||||||
|
fprintf(stderr, "Expected 2 arguments: <raw GDB dump> <output binary>\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
char* rawGDBfilePath = argv[1];
|
||||||
|
FILE* rawGDBfile;
|
||||||
|
if ((rawGDBfile = fopen(rawGDBfilePath,"rb"))==NULL) {
|
||||||
|
fprintf(stderr, "File not found: %s\n",rawGDBfilePath);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
char* outFilePath = argv[2];
|
||||||
|
FILE* outFile = fopen(outFilePath,"w");
|
||||||
|
uint64_t qemuWord;
|
||||||
|
uint64_t verilogWord;
|
||||||
|
int bytesReturned=0;
|
||||||
|
do {
|
||||||
|
bytesReturned=fread(&qemuWord, 8, 1, rawGDBfile);
|
||||||
|
verilogWord = (((qemuWord>>0 )&0xff)<<56 |
|
||||||
|
((qemuWord>>8 )&0xff)<<48 |
|
||||||
|
((qemuWord>>16)&0xff)<<40 |
|
||||||
|
((qemuWord>>24)&0xff)<<32 |
|
||||||
|
((qemuWord>>32)&0xff)<<24 |
|
||||||
|
((qemuWord>>40)&0xff)<<16 |
|
||||||
|
((qemuWord>>48)&0xff)<<8 |
|
||||||
|
((qemuWord>>56)&0xff)<<0);
|
||||||
|
fwrite(&verilogWord, 8, 1, outFile);
|
||||||
|
} while(bytesReturned!=0);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -13,7 +13,7 @@ define genCheckpoint
|
|||||||
set $checkPC=$arg3
|
set $checkPC=$arg3
|
||||||
set $checkPCoccurences=$arg4
|
set $checkPCoccurences=$arg4
|
||||||
eval "set $statePath = \"%s/stateGDB.txt\"", $statePath
|
eval "set $statePath = \"%s/stateGDB.txt\"", $statePath
|
||||||
eval "set $ramPath = \"%s/ramGDB.txt\"", $ramPath
|
eval "set $ramPath = \"%s/ramGDB.bin\"", $ramPath
|
||||||
|
|
||||||
# Connect to QEMU session
|
# Connect to QEMU session
|
||||||
eval "target extended-remote :%d",$tcpPort
|
eval "target extended-remote :%d",$tcpPort
|
||||||
@ -46,10 +46,7 @@ define genCheckpoint
|
|||||||
|
|
||||||
# Log main memory to a file
|
# Log main memory to a file
|
||||||
printf "GDB storing RAM to %s\n", $ramPath
|
printf "GDB storing RAM to %s\n", $ramPath
|
||||||
eval "set logging file %s", $ramPath
|
eval "dump binary memory %s 0x80000000 0xffffffff", $ramPath
|
||||||
set logging on
|
|
||||||
x/134217728xb 0x80000000
|
|
||||||
set logging off
|
|
||||||
|
|
||||||
kill
|
kill
|
||||||
q
|
q
|
@ -3,36 +3,57 @@
|
|||||||
source genSettings.sh
|
source genSettings.sh
|
||||||
tcpPort=1236
|
tcpPort=1236
|
||||||
|
|
||||||
instrs=480000000
|
# Parse Commandline Arg
|
||||||
|
if [ "$#" -ne 1 ]; then
|
||||||
|
echo "genCheckpoint requires 1 argument: <num instrs>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
instrs=$1
|
||||||
|
if ! [ "$instrs" -eq "$instrs" ] 2> /dev/null
|
||||||
|
then
|
||||||
|
echo "Error expected integer number of instructions, got $instrs" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
checkOutDir="$outDir/checkpoint$instrs"
|
checkOutDir="$outDir/checkpoint$instrs"
|
||||||
checkIntermedDir="$checkOutDir/intermediate-outputs"
|
checkIntermedDir="$checkOutDir/intermediate-outputs"
|
||||||
|
|
||||||
|
|
||||||
read -p "This scripts is going to create a checkpoint at $instrs instrs.
|
read -p "This scripts is going to create a checkpoint at $instrs instrs.
|
||||||
Is that what you wanted? (y/n) " -n 1 -r
|
Is that what you wanted? (y/n) " -n 1 -r
|
||||||
echo
|
echo
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]
|
if [[ $REPLY =~ ^[Yy]$ ]]
|
||||||
then
|
then
|
||||||
|
echo "Creating checkpoint at $instrs instructions!"
|
||||||
mkdir -p $checkOutDir
|
mkdir -p $checkOutDir
|
||||||
mkdir -p $checkIntermedDir
|
mkdir -p $checkIntermedDir
|
||||||
|
|
||||||
|
# Identify instruction in trace
|
||||||
instr=$(sed "${instrs}q;d" "../linux-testvectors/all.txt")
|
instr=$(sed "${instrs}q;d" "../linux-testvectors/all.txt")
|
||||||
echo "Found ${instrs}th instr: ${instr}."
|
echo "Found ${instrs}th instr: ${instr}"
|
||||||
pc=$(echo $instr | cut -d " " -f1)
|
pc=$(echo $instr | cut -d " " -f1)
|
||||||
asm=$(echo $instr | cut -d " " -f2)
|
asm=$(echo $instr | cut -d " " -f2)
|
||||||
occurences=$(($(head -$instrs "../linux-testvectors/all.txt" | grep -c "${pc} ${asm}")-1))
|
occurences=$(($(head -$instrs "../linux-testvectors/all.txt" | grep -c "${pc} ${asm}")-1))
|
||||||
echo "It occurs ${occurences} times before the ${instrs}th instr."
|
echo "It occurs ${occurences} times before the ${instrs}th instr."
|
||||||
# Simulate QEMU, parse QEMU trace, run GDB script which logs a bunch of data at the checkpoint
|
|
||||||
|
# GDB+QEMU
|
||||||
|
echo "Starting QEMU with attached GDB script at $(date +%H:%M:%S)"
|
||||||
($customQemu \
|
($customQemu \
|
||||||
-M virt \
|
-M virt \
|
||||||
-nographic \
|
-nographic \
|
||||||
-bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \
|
-bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \
|
||||||
-singlestep -rtc clock=vm -icount shift=1,align=off,sleep=on,rr=replay,rrfile="$intermedDir/$recordFile" \
|
-singlestep -rtc clock=vm -icount shift=1,align=off,sleep=on,rr=replay,rrfile="$intermedDir/$recordFile" \
|
||||||
-gdb tcp::$tcpPort -S) \
|
-gdb tcp::$tcpPort -S) \
|
||||||
& riscv64-unknown-elf-gdb -x genCheckpoint.gdb -ex "genCheckpoint $tcpPort $instrs \"$checkIntermedDir\" \"$pc\" $occurences"
|
& riscv64-unknown-elf-gdb --quiet \
|
||||||
|
-x genCheckpoint.gdb -ex "genCheckpoint $tcpPort $instrs \"$checkIntermedDir\" \"$pc\" $occurences"
|
||||||
|
echo "Completed GDB script completed at $(date +%H:%M:%S)"
|
||||||
|
|
||||||
# Post-Process GDB outputs
|
# Post-Process GDB outputs
|
||||||
./parseState.py "$checkOutDir"
|
./parseState.py "$checkOutDir"
|
||||||
./fix_mem.py "$checkIntermedDir/ramGDB.txt" "$checkOutDir/ram.txt"
|
echo "Changing Endianness at $(date +%H:%M:%S)"
|
||||||
tail -n+$($instrs+1) "$outDir/$traceFile" > "$checkOutDir/$traceFile"
|
make
|
||||||
|
./fixBinMem "$checkIntermedDir/ramGDB.bin" "$checkOutDir/ram.bin"
|
||||||
|
echo "Creating truncated trace at $(date +%H:%M:%S)"
|
||||||
|
tail -n+$instrs "$outDir/$traceFile" > "$checkOutDir/$traceFile"
|
||||||
|
echo "Checkpoint completed at $(date +%H:%M:%S)"
|
||||||
else
|
else
|
||||||
echo "You can change the number of instructions by editing the \"instrs\" variable in this script."
|
echo "You can change the number of instructions by editing the \"instrs\" variable in this script."
|
||||||
echo "Have a nice day!"
|
echo "Have a nice day!"
|
@ -16,8 +16,8 @@ then
|
|||||||
& riscv64-unknown-elf-gdb -quiet -x genInitMem.gdb -ex "genInitMem $tcpPort \"$intermedDir\""
|
& riscv64-unknown-elf-gdb -quiet -x genInitMem.gdb -ex "genInitMem $tcpPort \"$intermedDir\""
|
||||||
|
|
||||||
echo "Translating Mem from GDB to Questa format"
|
echo "Translating Mem from GDB to Questa format"
|
||||||
./fix_mem.py "$intermedDir/bootmemGDB.txt" "$outDir/bootmem.txt"
|
./fixTxtMem.py "$intermedDir/bootmemGDB.txt" "$outDir/bootmem.txt"
|
||||||
./fix_mem.py "$intermedDir/ramGDB.txt" "$outDir/ram.txt"
|
./fixTxtMem.py "$intermedDir/ramGDB.txt" "$outDir/ram.txt"
|
||||||
echo "Done"
|
echo "Done"
|
||||||
|
|
||||||
echo "Creating debugging objdump of linux image"
|
echo "Creating debugging objdump of linux image"
|
@ -4,7 +4,7 @@
|
|||||||
# *** on the long term we'll want to include QEMU in the addins folder
|
# *** on the long term we'll want to include QEMU in the addins folder
|
||||||
export customQemu="/courses/e190ax/qemu_sim/rv64_initrd/qemu_experimental/qemu/build/qemu-system-riscv64"
|
export customQemu="/courses/e190ax/qemu_sim/rv64_initrd/qemu_experimental/qemu/build/qemu-system-riscv64"
|
||||||
export imageDir="../buildroot-image-output"
|
export imageDir="../buildroot-image-output"
|
||||||
export outDir="../linux-testvectors-experimental"
|
export outDir="../linux-testvectors"
|
||||||
export intermedDir="$outDir/intermediate-outputs"
|
export intermedDir="$outDir/intermediate-outputs"
|
||||||
export traceFile="all.txt"
|
export traceFile="all.txt"
|
||||||
export recordFile="all.qemu"
|
export recordFile="all.qemu"
|
@ -34,7 +34,8 @@ stateGDBpath = outDir+'intermediate-outputs/stateGDB.txt'
|
|||||||
if not os.path.exists(stateGDBpath):
|
if not os.path.exists(stateGDBpath):
|
||||||
sys.exit('Error input file '+stateGDBpath+'not found')
|
sys.exit('Error input file '+stateGDBpath+'not found')
|
||||||
|
|
||||||
singleCSRs = ['pc','mip','mie','mscratch','mcause','mepc','mtvec','medeleg','mideleg','sscratch','scause','sepc','stvec','sedeleg','sideleg','satp','mstatus']
|
singleCSRs = ['pc','mip','mie','mscratch','mcause','mepc','mtvec','medeleg','mideleg','sscratch','scause','sepc','stvec','sedeleg','sideleg','satp','mstatus','priv']
|
||||||
|
# priv (current privilege mode) isn't technically a CSR but we can log it with the same machinery
|
||||||
thirtyTwoBitCSRs = ['mcounteren','scounteren']
|
thirtyTwoBitCSRs = ['mcounteren','scounteren']
|
||||||
listCSRs = ['hpmcounter','pmpaddr']
|
listCSRs = ['hpmcounter','pmpaddr']
|
||||||
pmpcfg = ['pmpcfg']
|
pmpcfg = ['pmpcfg']
|
||||||
@ -75,7 +76,7 @@ with open(stateGDBpath, 'r') as stateGDB:
|
|||||||
outFile = open(outDir+outFileName, 'w')
|
outFile = open(outDir+outFileName, 'w')
|
||||||
outFile.write(val+'\n')
|
outFile.write(val+'\n')
|
||||||
outFile.close()
|
outFile.close()
|
||||||
if name in thirtyTwoBitCSRs:
|
elif name in thirtyTwoBitCSRs:
|
||||||
outFileName = 'checkpoint-'+name.upper()
|
outFileName = 'checkpoint-'+name.upper()
|
||||||
outFile = open(outDir+outFileName, 'w')
|
outFile = open(outDir+outFileName, 'w')
|
||||||
val = int(val,16) & 0xffffffff
|
val = int(val,16) & 0xffffffff
|
@ -31,8 +31,7 @@
|
|||||||
`define BUILDROOT 1
|
`define BUILDROOT 1
|
||||||
`define BUSYBEAR 0
|
`define BUSYBEAR 0
|
||||||
`define LINUX_FIX_READ {'h10000005}
|
`define LINUX_FIX_READ {'h10000005}
|
||||||
`define LINUX_TEST_VECTORS "../linux-testgen/linux-testvectors/"
|
`define LINUX_TEST_VECTORS "../../tests/linux-testgen/linux-testvectors/"
|
||||||
//`define LINUX_TEST_VECTORS "/courses/e190ax/buildroot_boot/"
|
|
||||||
// RV32 or RV64: XLEN = 32 or 64
|
// RV32 or RV64: XLEN = 32 or 64
|
||||||
`define XLEN 64
|
`define XLEN 64
|
||||||
|
|
||||||
@ -114,8 +113,8 @@
|
|||||||
`define PLIC_NUM_SRC 53
|
`define PLIC_NUM_SRC 53
|
||||||
`define PLIC_UART_ID 4
|
`define PLIC_UART_ID 4
|
||||||
|
|
||||||
`define TWO_BIT_PRELOAD "../config/busybear/twoBitPredictor.txt"
|
`define TWO_BIT_PRELOAD "../config/buildroot/twoBitPredictor.txt"
|
||||||
`define BTB_PRELOAD "../config/busybear/BTBPredictor.txt"
|
`define BTB_PRELOAD "../config/buildroot/BTBPredictor.txt"
|
||||||
`define BPRED_ENABLED 1
|
`define BPRED_ENABLED 1
|
||||||
`define BPTYPE "BPGSHARE" // BPLOCALPAg or BPGLOBAL or BPTWOBIT or BPGSHARE
|
`define BPTYPE "BPGSHARE" // BPLOCALPAg or BPGLOBAL or BPTWOBIT or BPGSHARE
|
||||||
`define TESTSBP 0
|
`define TESTSBP 0
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,127 +0,0 @@
|
|||||||
//////////////////////////////////////////
|
|
||||||
// busybear-config.vh
|
|
||||||
//
|
|
||||||
// Written: David_Harris@hmc.edu 4 January 2021
|
|
||||||
// Modified:
|
|
||||||
//
|
|
||||||
// Purpose: Specify which features are configured
|
|
||||||
// Macros to determine which modes are supported based on MISA
|
|
||||||
//
|
|
||||||
// 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 shared configuration
|
|
||||||
`include "wally-shared.vh"
|
|
||||||
|
|
||||||
`define QEMU 0
|
|
||||||
`define BUILDROOT 0
|
|
||||||
`define BUSYBEAR 1
|
|
||||||
`define LINUX_FIX_READ {'h10000005}
|
|
||||||
`define LINUX_TEST_VECTORS "/courses/e190ax/busybear_boot/"
|
|
||||||
//`define LINUX_TEST_VECTORS "../../../busybear_boot/"
|
|
||||||
// RV32 or RV64: XLEN = 32 or 64
|
|
||||||
`define XLEN 64
|
|
||||||
|
|
||||||
`define MISA (32'h0014112D)
|
|
||||||
`define ZICSR_SUPPORTED 1
|
|
||||||
`define ZIFENCEI_SUPPORTED 1
|
|
||||||
`define ZICOUNTERS_SUPPORTED 1
|
|
||||||
`define COUNTERS 32
|
|
||||||
`define DESIGN_COMPILER 0
|
|
||||||
|
|
||||||
// Microarchitectural Features
|
|
||||||
`define UARCH_PIPELINED 1
|
|
||||||
`define UARCH_SUPERSCALR 0
|
|
||||||
`define UARCH_SINGLECYCLE 0
|
|
||||||
`define MEM_DCACHE 1
|
|
||||||
`define MEM_DTIM 1
|
|
||||||
`define MEM_ICACHE 1
|
|
||||||
`define MEM_VIRTMEM 1
|
|
||||||
`define VECTORED_INTERRUPTS_SUPPORTED 1 // Domenico Ottolia 4/15: Support for vectored interrupts in _tvec csrs. Just implemented in src/privileged/trap.sv around line 75. Pretty sure this should be 1.
|
|
||||||
|
|
||||||
// TLB configuration. Entries should be a power of 2
|
|
||||||
`define ITLB_ENTRIES 32
|
|
||||||
`define DTLB_ENTRIES 32
|
|
||||||
|
|
||||||
// Cache configuration. Sizes should be a power of two
|
|
||||||
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks
|
|
||||||
`define DCACHE_NUMWAYS 4
|
|
||||||
`define DCACHE_WAYSIZEINBYTES 2048
|
|
||||||
`define DCACHE_BLOCKLENINBITS 256
|
|
||||||
`define DCACHE_REPLBITS 3
|
|
||||||
`define ICACHE_NUMWAYS 1
|
|
||||||
`define ICACHE_WAYSIZEINBYTES 4096
|
|
||||||
`define ICACHE_BLOCKLENINBITS 256
|
|
||||||
|
|
||||||
// Integer Divider Configuration
|
|
||||||
// DIV_BITSPERCYCLE must be 1, 2, or 4
|
|
||||||
`define DIV_BITSPERCYCLE 4
|
|
||||||
|
|
||||||
// Legal number of PMP entries are 0, 16, or 64
|
|
||||||
`define PMP_ENTRIES 16
|
|
||||||
|
|
||||||
// Address space
|
|
||||||
`define RESET_VECTOR 64'h0000000000001000
|
|
||||||
|
|
||||||
// Peripheral Addresses
|
|
||||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
|
||||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
|
||||||
|
|
||||||
`define BOOTTIM_SUPPORTED 1'b1
|
|
||||||
//`define BOOTTIM_BASE 56'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
|
||||||
//`define BOOTTIM_RANGE 56'h00003FFF
|
|
||||||
`define BOOTTIM_BASE 56'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
|
||||||
`define BOOTTIM_RANGE 56'h00000FFF
|
|
||||||
`define TIM_SUPPORTED 1'b1
|
|
||||||
`define TIM_BASE 56'h80000000
|
|
||||||
`define TIM_RANGE 56'h07FFFFFF
|
|
||||||
`define CLINT_SUPPORTED 1'b1
|
|
||||||
`define CLINT_BASE 56'h02000000
|
|
||||||
`define CLINT_RANGE 56'h0000FFFF
|
|
||||||
`define GPIO_SUPPORTED 1'b1
|
|
||||||
`define GPIO_BASE 56'h10012000
|
|
||||||
`define GPIO_RANGE 56'h000000FF
|
|
||||||
`define UART_SUPPORTED 1'b1
|
|
||||||
`define UART_BASE 56'h10000000
|
|
||||||
`define UART_RANGE 56'h00000007
|
|
||||||
`define PLIC_SUPPORTED 1'b1
|
|
||||||
`define PLIC_BASE 56'h0C000000
|
|
||||||
`define PLIC_RANGE 56'h03FFFFFF
|
|
||||||
|
|
||||||
// Bus Interface width
|
|
||||||
`define AHBW 64
|
|
||||||
|
|
||||||
// Test modes
|
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
|
||||||
`define GPIO_LOOPBACK_TEST 0
|
|
||||||
|
|
||||||
// Hardware configuration
|
|
||||||
//`define UART_PRESCALE 1
|
|
||||||
`define UART_PRESCALE 0
|
|
||||||
|
|
||||||
// Interrupt configuration
|
|
||||||
`define PLIC_NUM_SRC 53
|
|
||||||
`define PLIC_UART_ID 4
|
|
||||||
|
|
||||||
`define TWO_BIT_PRELOAD "../config/busybear/twoBitPredictor.txt"
|
|
||||||
`define BTB_PRELOAD "../config/busybear/BTBPredictor.txt"
|
|
||||||
`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE
|
|
||||||
`define BPRED_ENABLED 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
Many of the scripts to build the linux ram.txt and trace files have changed over the Summer.
|
|
||||||
Specifically the parsed*.txt files have all been replaced by a single all.txt file which contains
|
|
||||||
all of the changes concurrent with a specific instruction.
|
|
||||||
Each line of all.txt is encoded in the following way.
|
|
||||||
|
|
||||||
The tokens are space deliminted (limitation the parsing function in system verilog). This could be
|
|
||||||
improved with some effort.
|
|
||||||
|
|
||||||
<Token> denotes a required token.
|
|
||||||
|
|
||||||
()? is an optional set of tokens. Exactly 0 or 1 of this pattern will occur.
|
|
||||||
The register update, memory operation, and CSR update are all possilbe but not present on all operations.
|
|
||||||
()+ is used to denote a variable number of this pattern with at least 1 instance of the pattern.
|
|
||||||
All integers are in hex and not zero extended.
|
|
||||||
|
|
||||||
<PC> <instruction bits> <instruction text> (<GPR> <Reg Number> <Value>)? (<MemR|MemW|MemRW> <Address> <WriteData if valid> <ReadData if valid>)? (<CSR> (<Name> <Value>)+)?
|
|
||||||
|
|
||||||
Example
|
|
||||||
|
|
||||||
1010 182b283 ld_t0,24(t0) GPR 5 80000000 MemR 1018 0 80000000
|
|
||||||
|
|
||||||
PC = 0x1010
|
|
||||||
Instruction encoding = 0x182_b283
|
|
||||||
instruction pneumonic (text) = ld_t0,24(t0)
|
|
||||||
Updating x5 to 0x8000_0000
|
|
||||||
Memory read at address 0x8000_0000 with read data of 0x8000_0000
|
|
||||||
|
|
||||||
CSR updates can occur in more than once for a single instruction. The multiple sets will appear as pairs of regsiter name followed by value.
|
|
||||||
|
|
||||||
**** This trace is generated using the CreateTrace.sh script.
|
|
||||||
|
|
||||||
Generation of ram.txt has not changed. Still use logBuildrootMem.sh
|
|
||||||
|
|
||||||
Only the all.txt and ram.txt are required to run modelsim's linux simulation. However there are three additional files will aid
|
|
||||||
in the debugging process. logBuildrootMem.sh was modified to also create an object dump from the vmlinux image. Using
|
|
||||||
extractFunctionRadix.sh the objdump is converted into two files vmlinux.objdump.addr and vmlinux.objdump.lab which contain
|
|
||||||
the addresses and labels of global functions in the linux binarary. The linux test bench is configured to uses these two files
|
|
||||||
to tell the user which function is currently being executed in modelsim.
|
|
@ -1,57 +0,0 @@
|
|||||||
If you do not need to update the Linux image, then go to ./linux-testvectors and
|
|
||||||
use tvCopier.py or tvLinker.sh to copy/link premade RAMs and testvectors from Tera.
|
|
||||||
The RAMs are needed for Wally to run the Linux code, and the testvectors are needed
|
|
||||||
to verify Wally is executing the code correctly.
|
|
||||||
|
|
||||||
If you instead wish to regenerate the RAMs and testvectors from a new Linux image,
|
|
||||||
you'll need to build the new Linux image, simulate it, and parse its output,
|
|
||||||
as described below.
|
|
||||||
|
|
||||||
*To build a new Linux image:
|
|
||||||
1. Git clone the Buildroot repository to ./buildroot:
|
|
||||||
git clone https://github.com/buildroot/buildroot.git
|
|
||||||
For reference, Wally (*** will) be proven to work on an image built using
|
|
||||||
Buildroot when the following was the most recent commit to the Buildroot repo:
|
|
||||||
commit 4047e10ed6e20492bae572d4929eaa5d67eed746
|
|
||||||
Author: Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
|
||||||
Date: Wed Jun 30 06:27:10 2021 +0200
|
|
||||||
|
|
||||||
2. If you wish to modify the configs, then in ./buildroot:
|
|
||||||
a. Run "make menuconfig" or "make linux-menuconfig" or "make busybox-menuconfig".
|
|
||||||
b. Use the TUI (terminal UI) to load in the existing configs.
|
|
||||||
|
|
||||||
For menuconfig, you can load in the source file from
|
|
||||||
"../buildroot-config-src/main.config"
|
|
||||||
|
|
||||||
For linux-menuconfig or busybox-menuconfig, load in from
|
|
||||||
"../../../../buildroot-config-src/<type>.config"
|
|
||||||
because for linux and busybox, make traverses down to
|
|
||||||
./buildroot/output/build/<linux or busybox>.
|
|
||||||
|
|
||||||
One annoying thing about the TUI is that if it has a path already loaded,
|
|
||||||
then before you can enter the new path to buildroot-config-src, you need to
|
|
||||||
delete the existing one from the textbox. Doing so requires more than backspace.
|
|
||||||
Once you've deleted as much of the existing path as you can see, arrow left to
|
|
||||||
check if there is more text you need to delete.
|
|
||||||
|
|
||||||
c. Likewise, when you are done editing, tell the TUI to save to the same location.
|
|
||||||
|
|
||||||
3. Finally go to ./buildroot-config-src and run make-buildroot.sh.
|
|
||||||
This script copies ./buildroot-config-src/main.config to ./buildroot/.config
|
|
||||||
and then invokes make. This is clumsy but effective because buildroot
|
|
||||||
sometimes does weird things to .config, like moving it to .config.old and
|
|
||||||
making a new .config -- doing so can really mess up symbolic/hard links.
|
|
||||||
|
|
||||||
4. If you'd like debugging symbols, then reconfigure Buildroot to output "vmlinux"
|
|
||||||
and run make-buildroot again.
|
|
||||||
|
|
||||||
*To generate new RAMs and testvectors from a Linux image:
|
|
||||||
1. sym link ./buildroot-image-output to either your new image in ./buildroot/output/image
|
|
||||||
or the existing image at /courses/e190ax/buildroot-image-output on Tera.
|
|
||||||
This might require first deleting the empty buildroot-image-output directory.
|
|
||||||
2. Then run ./testvector-generation/logBuildrootMem.sh to generate RAMs.
|
|
||||||
3. Then run ./testvector-generation/logAllBuildroot.sh to generate testvectors.
|
|
||||||
|
|
||||||
These latter two steps require QEMU.
|
|
||||||
Note that you can only have one instance of QEMU open at a time!
|
|
||||||
At least on Tera, it seems. Check "ps -ef" to see if anybody else is running QEMU.
|
|
@ -1 +0,0 @@
|
|||||||
This file only exists so that git will create ./.
|
|
@ -1,9 +0,0 @@
|
|||||||
echo "Warning: this script will only work if your repo is on Tera"
|
|
||||||
ln -s /courses/e190ax/buildroot_boot/all.txt all.txt
|
|
||||||
ln -s /courses/e190ax/buildroot_boot/bootmem.txt bootmem.txt
|
|
||||||
ln -s /courses/e190ax/buildroot_boot/ram.txt ram.txt
|
|
||||||
ln -s /courses/e190ax/buildroot_boot/vmlinux.objdump vmlinux.objdump
|
|
||||||
ln -s /courses/e190ax/buildroot_boot/vmlinux.objdump.addr vmlinux.objdump.addr
|
|
||||||
ln -s /courses/e190ax/buildroot_boot/vmlinux.objdump.lab vmlinux.objdump.lab
|
|
||||||
ln -s /courses/e190ax/buildroot_boot/checkpoint8500000 ./checkpoint8500000
|
|
||||||
echo "Done!"
|
|
6
wally-pipelined/regression/Makefile
Normal file
6
wally-pipelined/regression/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
make all:
|
||||||
|
make ../../tests/imperas-riscv-tests/
|
||||||
|
make ../../tests/wally-riscv-arch-test/
|
||||||
|
make XLEN=32 ../../tests/wally-riscv-arch-test/
|
||||||
|
exe2memfile.pl ../../tests/wally-riscv-arch-test/work/*/*/*.elf
|
||||||
|
cd ../../tests/linux-testgen/linux-testvectors/;./tvLinker.sh
|
@ -60,20 +60,26 @@ 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/RdD
|
||||||
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D
|
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 -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D
|
||||||
add wave -noupdate -group {Execution Stage} /testbench/dut/hart/ifu/PCE
|
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE
|
||||||
add wave -noupdate -group {Execution Stage} /testbench/InstrEName
|
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE
|
||||||
add wave -noupdate -group {Execution Stage} /testbench/dut/hart/ifu/InstrE
|
add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName
|
||||||
add wave -noupdate -group {Execution Stage} -color {Cornflower Blue} /testbench/FunctionName/FunctionName
|
add wave -noupdate -expand -group {Execution Stage} /testbench/textE
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/dut/hart/priv/trap/InstrValidM
|
add wave -noupdate -expand -group {Execution Stage} -color {Cornflower Blue} /testbench/FunctionName/FunctionName
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/dut/hart/PCM
|
add wave -noupdate -expand -group {Memory Stage} /testbench/checkInstrM
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/InstrMName
|
add wave -noupdate -expand -group {Memory Stage} /testbench/dut/hart/priv/trap/InstrValidM
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/dut/hart/InstrM
|
add wave -noupdate -expand -group {Memory Stage} /testbench/dut/hart/PCM
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/dut/hart/lsu/MemAdrM
|
add wave -noupdate -expand -group {Memory Stage} /testbench/ExpectedPCM
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/PCW
|
add wave -noupdate -expand -group {Memory Stage} /testbench/dut/hart/InstrM
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/InstrW
|
add wave -noupdate -expand -group {Memory Stage} /testbench/InstrMName
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/InstrWName
|
add wave -noupdate -expand -group {Memory Stage} /testbench/textM
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/InstrValidW
|
add wave -noupdate -expand -group {Memory Stage} /testbench/dut/hart/lsu/MemAdrM
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/checkInstrW
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/checkInstrW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/InstrValidW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/PCW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/ExpectedPCW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/InstrW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/InstrWName
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/textW
|
||||||
add wave -noupdate -group Bpred -color Orange /testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/GHR
|
add wave -noupdate -group Bpred -color Orange /testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/GHR
|
||||||
add wave -noupdate -group Bpred -expand -group {branch update selection inputs} /testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/BPPredF
|
add wave -noupdate -group Bpred -expand -group {branch update selection inputs} /testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/BPPredF
|
||||||
add wave -noupdate -group Bpred -expand -group {branch update selection inputs} {/testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/InstrClassE[0]}
|
add wave -noupdate -group Bpred -expand -group {branch update selection inputs} {/testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/InstrClassE[0]}
|
||||||
@ -484,7 +490,6 @@ add wave -noupdate -group {debug trace} -expand -group mem /testbench/dut/hart/p
|
|||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/checkInstrM
|
add wave -noupdate -group {debug trace} -expand -group mem /testbench/checkInstrM
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/dut/hart/PCM
|
add wave -noupdate -group {debug trace} -expand -group mem /testbench/dut/hart/PCM
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/ExpectedPCM
|
add wave -noupdate -group {debug trace} -expand -group mem /testbench/ExpectedPCM
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/line
|
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/textM
|
add wave -noupdate -group {debug trace} -expand -group mem /testbench/textM
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem -color Brown /testbench/dut/hart/hzu/TrapM
|
add wave -noupdate -group {debug trace} -expand -group mem -color Brown /testbench/dut/hart/hzu/TrapM
|
||||||
add wave -noupdate -group {debug trace} -expand -group wb /testbench/checkInstrW
|
add wave -noupdate -group {debug trace} -expand -group wb /testbench/checkInstrW
|
||||||
@ -510,7 +515,7 @@ add wave -noupdate /testbench/dut/uncore/dtim/memwrite
|
|||||||
add wave -noupdate /testbench/dut/uncore/dtim/HWDATA
|
add wave -noupdate /testbench/dut/uncore/dtim/HWDATA
|
||||||
add wave -noupdate /testbench/dut/uncore/dtim/risingHREADYTim
|
add wave -noupdate /testbench/dut/uncore/dtim/risingHREADYTim
|
||||||
TreeUpdate [SetDefaultTree]
|
TreeUpdate [SetDefaultTree]
|
||||||
WaveRestoreCursors {{Cursor 23} {209183247 ns} 0} {{Cursor 5} {229 ns} 0}
|
WaveRestoreCursors {{Cursor 23} {209183247 ns} 0} {{Cursor 5} {5672440 ns} 0}
|
||||||
quietly wave cursor active 2
|
quietly wave cursor active 2
|
||||||
configure wave -namecolwidth 250
|
configure wave -namecolwidth 250
|
||||||
configure wave -valuecolwidth 314
|
configure wave -valuecolwidth 314
|
||||||
@ -526,4 +531,4 @@ configure wave -griddelta 40
|
|||||||
configure wave -timeline 0
|
configure wave -timeline 0
|
||||||
configure wave -timelineunits ns
|
configure wave -timelineunits ns
|
||||||
update
|
update
|
||||||
WaveRestoreZoom {182 ns} {330 ns}
|
WaveRestoreZoom {5672937 ns} {5673085 ns}
|
||||||
|
@ -32,7 +32,7 @@ configs = [
|
|||||||
]
|
]
|
||||||
def getBuildrootTC(short):
|
def getBuildrootTC(short):
|
||||||
INSTR_LIMIT = 100000 # multiple of 100000
|
INSTR_LIMIT = 100000 # multiple of 100000
|
||||||
MAX_EXPECTED = 3000000
|
MAX_EXPECTED = 14000000
|
||||||
if short:
|
if short:
|
||||||
BRcmd="vsim > {} -c <<!\ndo wally-buildroot-batch.do "+str(INSTR_LIMIT)+" 1 0\n!"
|
BRcmd="vsim > {} -c <<!\ndo wally-buildroot-batch.do "+str(INSTR_LIMIT)+" 1 0\n!"
|
||||||
BRgrepstr=str(INSTR_LIMIT)+" instructions"
|
BRgrepstr=str(INSTR_LIMIT)+" instructions"
|
||||||
@ -87,7 +87,7 @@ def main():
|
|||||||
# max out at a limited number of concurrent processes to not overwhelm the system
|
# max out at a limited number of concurrent processes to not overwhelm the system
|
||||||
|
|
||||||
if '-all' in sys.argv:
|
if '-all' in sys.argv:
|
||||||
TIMEOUT_DUR = 3600
|
TIMEOUT_DUR = 4*3600
|
||||||
configs.append(getBuildrootTC(short=False))
|
configs.append(getBuildrootTC(short=False))
|
||||||
else:
|
else:
|
||||||
TIMEOUT_DUR = 300
|
TIMEOUT_DUR = 300
|
||||||
|
@ -87,12 +87,26 @@ def Mod_Space_at(Ln,loc,diff):
|
|||||||
|
|
||||||
return NewString
|
return NewString
|
||||||
|
|
||||||
def main_filehandler(overwrite=False):
|
'''def main_filehandler(overwrite=False):
|
||||||
for filename in os.listdir():
|
for filename in os.listdir():
|
||||||
if ".py" not in filename:
|
if ".sv" in filename:
|
||||||
GiantString = read_input(filename)
|
GiantString = read_input(filename)
|
||||||
SOV = ID_start(GiantString)
|
SOV = ID_start(GiantString)
|
||||||
ModifiedGS = modified_logNew(GiantString,SOV)
|
ModifiedGS = modified_logNew(GiantString,SOV)
|
||||||
Newname = write_to_output(filename,ModifiedGS,overwrite)
|
Newname = write_to_output(filename,ModifiedGS,overwrite)'''
|
||||||
|
def root_filehandler(path,overwrite=False):
|
||||||
|
for f in os.listdir(path):
|
||||||
|
if os.path.isdir(f):
|
||||||
|
root_filehandler(path+"/"+f)
|
||||||
|
else:
|
||||||
|
if ".sv" in f:
|
||||||
|
GiantString = read_input(f)
|
||||||
|
SOV = ID_start(GiantString)
|
||||||
|
ModifiedGS = modified_logNew(GiantString,SOV)
|
||||||
|
Newname = write_to_output(f,ModifiedGS,overwrite)
|
||||||
|
|
||||||
|
|
||||||
|
def driver(overwrite=False):
|
||||||
|
root_filehandler(os.getcwd())
|
||||||
|
|
||||||
main_filehandler(True)
|
driver(True)
|
@ -103,30 +103,35 @@ module testbench();
|
|||||||
string checkpointDir;
|
string checkpointDir;
|
||||||
logic [1:0] initPriv;
|
logic [1:0] initPriv;
|
||||||
// Signals used to parse the trace file
|
// Signals used to parse the trace file
|
||||||
integer data_file_all;
|
`define DECLARE_TRACE_SCANNER_SIGNALS(STAGE) \
|
||||||
string name;
|
integer traceFile``STAGE; \
|
||||||
integer matchCount;
|
integer matchCount``STAGE; \
|
||||||
string line;
|
string line``STAGE; \
|
||||||
logic [`XLEN-1:0] ExpectedPCM;
|
string token``STAGE; \
|
||||||
logic [31:0] ExpectedInstrM;
|
string ExpectedTokens``STAGE [31:0]; \
|
||||||
string textM;
|
integer index``STAGE; \
|
||||||
string token;
|
integer StartIndex``STAGE, EndIndex``STAGE; \
|
||||||
string ExpectedTokens [31:0];
|
integer TokenIndex``STAGE; \
|
||||||
integer index;
|
integer MarkerIndex``STAGE; \
|
||||||
integer StartIndex, EndIndex;
|
integer NumCSR``STAGE; \
|
||||||
integer TokenIndex;
|
logic [`XLEN-1:0] ExpectedPC``STAGE; \
|
||||||
integer MarkerIndex;
|
logic [31:0] ExpectedInstr``STAGE; \
|
||||||
integer NumCSRM;
|
string text``STAGE; \
|
||||||
|
string MemOp``STAGE; \
|
||||||
|
string RegWrite``STAGE; \
|
||||||
|
integer ExpectedRegAdr``STAGE; \
|
||||||
|
logic [`XLEN-1:0] ExpectedRegValue``STAGE; \
|
||||||
|
logic [`XLEN-1:0] ExpectedMemAdr``STAGE, ExpectedMemReadData``STAGE, ExpectedMemWriteData``STAGE; \
|
||||||
|
string ExpectedCSRArray``STAGE[10:0]; \
|
||||||
|
logic [`XLEN-1:0] ExpectedCSRArrayValue``STAGE[10:0];
|
||||||
|
`DECLARE_TRACE_SCANNER_SIGNALS(E)
|
||||||
|
`DECLARE_TRACE_SCANNER_SIGNALS(M)
|
||||||
|
integer NextMIPexpected;
|
||||||
|
integer NextMepcExpected;
|
||||||
// Memory stage expected values from trace
|
// Memory stage expected values from trace
|
||||||
logic checkInstrM;
|
logic checkInstrM;
|
||||||
integer MIPexpected;
|
integer MIPexpected;
|
||||||
string RegWriteM;
|
string name;
|
||||||
integer ExpectedRegAdrM;
|
|
||||||
logic [`XLEN-1:0] ExpectedRegValueM;
|
|
||||||
string MemOpM;
|
|
||||||
logic [`XLEN-1:0] ExpectedMemAdrM, ExpectedMemReadDataM, ExpectedMemWriteDataM;
|
|
||||||
string ExpectedCSRArrayM[10:0];
|
|
||||||
logic [`XLEN-1:0] ExpectedCSRArrayValueM[10:0];
|
|
||||||
logic [`AHBW-1:0] readDataExpected;
|
logic [`AHBW-1:0] readDataExpected;
|
||||||
// Write back stage expected values from trace
|
// Write back stage expected values from trace
|
||||||
logic checkInstrW;
|
logic checkInstrW;
|
||||||
@ -148,6 +153,11 @@ module testbench();
|
|||||||
integer NumCSRPostWIndex;
|
integer NumCSRPostWIndex;
|
||||||
logic [`XLEN-1:0] InstrCountW;
|
logic [`XLEN-1:0] InstrCountW;
|
||||||
integer RequestDelayedMIP;
|
integer RequestDelayedMIP;
|
||||||
|
integer ForceMIPFuture;
|
||||||
|
integer CSRIndex;
|
||||||
|
longint MepcExpected;
|
||||||
|
integer CheckMIPFutureE;
|
||||||
|
integer CheckMIPFutureM;
|
||||||
// Useful Aliases
|
// Useful Aliases
|
||||||
`define RF dut.hart.ieu.dp.regf.rf
|
`define RF dut.hart.ieu.dp.regf.rf
|
||||||
`define PC dut.hart.ifu.pcreg.q
|
`define PC dut.hart.ifu.pcreg.q
|
||||||
@ -187,7 +197,7 @@ module testbench();
|
|||||||
`define STATUS_MIE `CSR_BASE.csrsr.STATUS_MIE
|
`define STATUS_MIE `CSR_BASE.csrsr.STATUS_MIE
|
||||||
`define STATUS_SIE `CSR_BASE.csrsr.STATUS_SIE
|
`define STATUS_SIE `CSR_BASE.csrsr.STATUS_SIE
|
||||||
`define STATUS_UIE `CSR_BASE.csrsr.STATUS_UIE
|
`define STATUS_UIE `CSR_BASE.csrsr.STATUS_UIE
|
||||||
`define CURR_PRIV dut.hart.priv.privmodereg.q
|
`define PRIV dut.hart.priv.privmodereg.q
|
||||||
`define INSTRET dut.hart.priv.csr.genblk1.counters.genblk1.genblk2.INSTRETreg.q
|
`define INSTRET dut.hart.priv.csr.genblk1.counters.genblk1.genblk2.INSTRETreg.q
|
||||||
// Common Macros
|
// Common Macros
|
||||||
`define checkCSR(CSR) \
|
`define checkCSR(CSR) \
|
||||||
@ -265,6 +275,7 @@ module testbench();
|
|||||||
endgenerate
|
endgenerate
|
||||||
`INIT_CHECKPOINT_VAL(PC, [`XLEN-1:0]);
|
`INIT_CHECKPOINT_VAL(PC, [`XLEN-1:0]);
|
||||||
`INIT_CHECKPOINT_VAL(MEDELEG, [`XLEN-1:0]);
|
`INIT_CHECKPOINT_VAL(MEDELEG, [`XLEN-1:0]);
|
||||||
|
`INIT_CHECKPOINT_VAL(MIDELEG, [`XLEN-1:0]);
|
||||||
`INIT_CHECKPOINT_VAL(MIE, [11:0]);
|
`INIT_CHECKPOINT_VAL(MIE, [11:0]);
|
||||||
`INIT_CHECKPOINT_VAL(MIP, [11:0]);
|
`INIT_CHECKPOINT_VAL(MIP, [11:0]);
|
||||||
`INIT_CHECKPOINT_VAL(MCAUSE, [`XLEN-1:0]);
|
`INIT_CHECKPOINT_VAL(MCAUSE, [`XLEN-1:0]);
|
||||||
@ -278,9 +289,11 @@ module testbench();
|
|||||||
`INIT_CHECKPOINT_VAL(MTVEC, [`XLEN-1:0]);
|
`INIT_CHECKPOINT_VAL(MTVEC, [`XLEN-1:0]);
|
||||||
`INIT_CHECKPOINT_VAL(STVEC, [`XLEN-1:0]);
|
`INIT_CHECKPOINT_VAL(STVEC, [`XLEN-1:0]);
|
||||||
`INIT_CHECKPOINT_VAL(SATP, [`XLEN-1:0]);
|
`INIT_CHECKPOINT_VAL(SATP, [`XLEN-1:0]);
|
||||||
|
`INIT_CHECKPOINT_VAL(PRIV, [1:0]);
|
||||||
`MAKE_CHECKPOINT_INIT_SIGNAL(MSTATUS, [`XLEN-1:0],0,0);
|
`MAKE_CHECKPOINT_INIT_SIGNAL(MSTATUS, [`XLEN-1:0],0,0);
|
||||||
|
|
||||||
assign initPriv = (initPC[0][`XLEN-1]) ? 2'h2 : 2'h3; // *** a hacky way to detect initial privilege level
|
integer ramFile;
|
||||||
|
integer readResult;
|
||||||
initial begin
|
initial begin
|
||||||
force dut.hart.priv.SwIntM = 0;
|
force dut.hart.priv.SwIntM = 0;
|
||||||
force dut.hart.priv.TimerIntM = 0;
|
force dut.hart.priv.TimerIntM = 0;
|
||||||
@ -292,13 +305,18 @@ module testbench();
|
|||||||
ProgramLabelMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.lab"};
|
ProgramLabelMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.lab"};
|
||||||
if (CHECKPOINT==0) begin // normal
|
if (CHECKPOINT==0) begin // normal
|
||||||
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||||
data_file_all = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
|
traceFileM = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
|
||||||
|
traceFileE = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
|
||||||
InstrCountW = '0;
|
InstrCountW = '0;
|
||||||
end else begin // checkpoint
|
end else begin // checkpoint
|
||||||
$sformat(checkpointDir,"checkpoint%0d/",CHECKPOINT);
|
$sformat(checkpointDir,"checkpoint%0d/",CHECKPOINT);
|
||||||
checkpointDir = {`LINUX_TEST_VECTORS,checkpointDir};
|
checkpointDir = {`LINUX_TEST_VECTORS,checkpointDir};
|
||||||
$readmemh({checkpointDir,"ram.txt"}, dut.uncore.dtim.RAM);
|
//$readmemh({checkpointDir,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||||
data_file_all = $fopen({checkpointDir,"all.txt"}, "r");
|
ramFile = $fopen({checkpointDir,"ram.bin"}, "rb");
|
||||||
|
readResult = $fread(dut.uncore.dtim.RAM,ramFile);
|
||||||
|
$fclose(ramFile);
|
||||||
|
traceFileE = $fopen({checkpointDir,"all.txt"}, "r");
|
||||||
|
traceFileM = $fopen({checkpointDir,"all.txt"}, "r");
|
||||||
InstrCountW = CHECKPOINT;
|
InstrCountW = CHECKPOINT;
|
||||||
// manual checkpoint initializations that don't neatly fit into MACRO
|
// manual checkpoint initializations that don't neatly fit into MACRO
|
||||||
force {`STATUS_TSR,`STATUS_TW,`STATUS_TVM,`STATUS_MXR,`STATUS_SUM,`STATUS_MPRV} = initMSTATUS[0][22:17];
|
force {`STATUS_TSR,`STATUS_TW,`STATUS_TVM,`STATUS_MXR,`STATUS_SUM,`STATUS_MPRV} = initMSTATUS[0][22:17];
|
||||||
@ -307,7 +325,6 @@ module testbench();
|
|||||||
force {`STATUS_SPIE,`STATUS_UPIE,`STATUS_MIE} = initMSTATUS[0][5:3];
|
force {`STATUS_SPIE,`STATUS_UPIE,`STATUS_MIE} = initMSTATUS[0][5:3];
|
||||||
force {`STATUS_SIE,`STATUS_UIE} = initMSTATUS[0][1:0];
|
force {`STATUS_SIE,`STATUS_UIE} = initMSTATUS[0][1:0];
|
||||||
force `INSTRET = CHECKPOINT;
|
force `INSTRET = CHECKPOINT;
|
||||||
force `CURR_PRIV = initPriv;
|
|
||||||
while (reset!==1) #1;
|
while (reset!==1) #1;
|
||||||
while (reset!==0) #1;
|
while (reset!==0) #1;
|
||||||
#1;
|
#1;
|
||||||
@ -317,10 +334,13 @@ module testbench();
|
|||||||
release {`STATUS_SPIE,`STATUS_UPIE,`STATUS_MIE};
|
release {`STATUS_SPIE,`STATUS_UPIE,`STATUS_MIE};
|
||||||
release {`STATUS_SIE,`STATUS_UIE};
|
release {`STATUS_SIE,`STATUS_UIE};
|
||||||
release `INSTRET;
|
release `INSTRET;
|
||||||
release `CURR_PRIV;
|
|
||||||
end
|
end
|
||||||
|
// Get the E-stage trace reader ahead of the M-stage trace reader
|
||||||
|
matchCountE = $fgets(lineE,traceFileE);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////// CORE /////////////////////////////////////
|
//////////////////////////////////// CORE /////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -332,93 +352,161 @@ module testbench();
|
|||||||
// on the next falling edge the expected state is compared to the wally state.
|
// on the next falling edge the expected state is compared to the wally state.
|
||||||
|
|
||||||
// step 0: read the expected state
|
// step 0: read the expected state
|
||||||
assign checkInstrM = dut.hart.ieu.InstrValidM & ~dut.hart.priv.trap.InstrPageFaultM & ~dut.hart.priv.trap.InterruptM & ~dut.hart.StallM;
|
assign checkInstrM = dut.hart.ieu.InstrValidM & ~dut.hart.priv.trap.InstrPageFaultM & ~dut.hart.priv.trap.InterruptM & ~dut.hart.StallM;
|
||||||
|
`define SCAN_NEW_INSTR_FROM_TRACE(STAGE) \
|
||||||
|
// always check PC, instruction bits \
|
||||||
|
if (checkInstrM) begin \
|
||||||
|
// read 1 line of the trace file \
|
||||||
|
matchCount``STAGE = $fgets(line``STAGE, traceFile``STAGE); \
|
||||||
|
if(`DEBUG_TRACE >= 5) $display("Time %t, line %x", $time, line``STAGE); \
|
||||||
|
// extract PC, Instr \
|
||||||
|
matchCount``STAGE = $sscanf(line``STAGE, "%x %x %s", ExpectedPC``STAGE, ExpectedInstr``STAGE, text``STAGE); \
|
||||||
|
\
|
||||||
|
// for the life of me I cannot get any build in C or C++ string parsing functions/methods to work. \
|
||||||
|
// strtok was the best idea but it cannot be used correctly as system verilog does not have null \
|
||||||
|
// terminated strings. \
|
||||||
|
\
|
||||||
|
// Just going to do this char by char. \
|
||||||
|
StartIndex``STAGE = 0; \
|
||||||
|
TokenIndex``STAGE = 0; \
|
||||||
|
//$display("len = %d", line``STAGE.len()); \
|
||||||
|
for(index``STAGE = 0; index``STAGE < line``STAGE.len(); index``STAGE++) begin \
|
||||||
|
//$display("char = %s", line``STAGE[index]); \
|
||||||
|
if (line``STAGE[index``STAGE] == " " || line``STAGE[index``STAGE] == "\n") begin \
|
||||||
|
EndIndex``STAGE = index``STAGE; \
|
||||||
|
ExpectedTokens``STAGE[TokenIndex``STAGE] = line``STAGE.substr(StartIndex``STAGE, EndIndex``STAGE-1); \
|
||||||
|
//$display("In Tokenizer %s", line``STAGE.substr(StartIndex, EndIndex-1)); \
|
||||||
|
StartIndex``STAGE = EndIndex``STAGE + 1; \
|
||||||
|
TokenIndex``STAGE++; \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
\
|
||||||
|
MarkerIndex``STAGE = 3; \
|
||||||
|
NumCSR``STAGE = 0; \
|
||||||
|
MemOp``STAGE = ""; \
|
||||||
|
RegWrite``STAGE = ""; \
|
||||||
|
\
|
||||||
|
#2; \
|
||||||
|
\
|
||||||
|
while(TokenIndex``STAGE > MarkerIndex``STAGE) begin \
|
||||||
|
// parse the GPR \
|
||||||
|
if (ExpectedTokens``STAGE[MarkerIndex``STAGE] == "GPR") begin \
|
||||||
|
RegWrite``STAGE = ExpectedTokens``STAGE[MarkerIndex``STAGE]; \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+1], "%d", ExpectedRegAdr``STAGE); \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+2], "%x", ExpectedRegValue``STAGE); \
|
||||||
|
MarkerIndex``STAGE += 3; \
|
||||||
|
// parse memory address, read data, and/or write data \
|
||||||
|
end else if(ExpectedTokens``STAGE[MarkerIndex``STAGE].substr(0, 2) == "Mem") begin \
|
||||||
|
MemOp``STAGE = ExpectedTokens``STAGE[MarkerIndex``STAGE]; \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+1], "%x", ExpectedMemAdr``STAGE); \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+2], "%x", ExpectedMemWriteData``STAGE); \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+3], "%x", ExpectedMemReadData``STAGE); \
|
||||||
|
MarkerIndex``STAGE += 4; \
|
||||||
|
// parse CSRs, because there are 1 or more CSRs after the CSR token \
|
||||||
|
// we check if the CSR token or the number of CSRs is greater than 0. \
|
||||||
|
// if so then we want to parse for a CSR. \
|
||||||
|
end else if(ExpectedTokens``STAGE[MarkerIndex``STAGE] == "CSR" || NumCSR``STAGE > 0) begin \
|
||||||
|
if(ExpectedTokens``STAGE[MarkerIndex``STAGE] == "CSR") begin \
|
||||||
|
// all additional CSR's won't have this token. \
|
||||||
|
MarkerIndex``STAGE++; \
|
||||||
|
end \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE], "%s", ExpectedCSRArray``STAGE[NumCSR``STAGE]); \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+1], "%x", ExpectedCSRArrayValue``STAGE[NumCSR``STAGE]); \
|
||||||
|
MarkerIndex``STAGE += 2; \
|
||||||
|
if(`"STAGE`"=="E") begin \
|
||||||
|
// match MIP to QEMU's because interrupts are imprecise \
|
||||||
|
if(ExpectedCSRArrayE[NumCSRE].substr(0, 2) == "mip") begin \
|
||||||
|
CheckMIPFutureE = 1; \
|
||||||
|
NextMIPexpected = ExpectedCSRArrayValueE[NumCSRE]; \
|
||||||
|
end \
|
||||||
|
// $display("%tn: ExpectedCSRArrayM[7] (MEPC) = %x",$time,ExpectedCSRArrayM[7]); \
|
||||||
|
// $display("%tn: ExpectedPCM = %x",$time,ExpectedPCM); \
|
||||||
|
// // if PC does not equal MEPC, request delayed MIP is True \
|
||||||
|
// if(ExpectedPCM != ExpectedCSRArrayM[7]) begin \
|
||||||
|
// RequestDelayedMIP = 1; \
|
||||||
|
// end else begin \
|
||||||
|
// $display("%tns: Updating MIP to %x",$time,ExpectedCSRArrayValueM[NumCSRM]); \
|
||||||
|
// MIPexpected = ExpectedCSRArrayValueM[NumCSRM]; \
|
||||||
|
// force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected; \
|
||||||
|
// end \
|
||||||
|
// end \
|
||||||
|
// $display("%tns: ExpectedCSRArrayM::: %p",$time,ExpectedCSRArrayM); \
|
||||||
|
if(ExpectedCSRArrayE[NumCSRE].substr(0,3) == "mepc") begin \
|
||||||
|
$display("hello! we are here."); \
|
||||||
|
MepcExpected = ExpectedCSRArrayValueE[NumCSRE]; \
|
||||||
|
$display("%tns: MepcExpected: %x",$time,MepcExpected); \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
\
|
||||||
|
NumCSR``STAGE++; \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
if(`"STAGE`"=="M") begin \
|
||||||
|
// override on special conditions \
|
||||||
|
if (ExpectedMemAdrM == 'h10000005) begin \
|
||||||
|
//$display("%tns, %d instrs: Overwriting read data from CLINT.", $time, InstrCountW); \
|
||||||
|
force dut.hart.ieu.dp.ReadDataM = ExpectedMemReadDataM; \
|
||||||
|
end \
|
||||||
|
if(textM.substr(0,5) == "rdtime") begin \
|
||||||
|
//$display("%tns, %d instrs: Overwrite MTIME_CLINT on read of MTIME in memory stage.", $time, InstrCountW); \
|
||||||
|
force dut.uncore.clint.clint.MTIME = ExpectedRegValueM; \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
|
||||||
always @(negedge clk) begin
|
always @(negedge clk) begin
|
||||||
// always check PC, instruction bits
|
`SCAN_NEW_INSTR_FROM_TRACE(E)
|
||||||
if (checkInstrM) begin
|
end
|
||||||
// read 1 line of the trace file
|
|
||||||
matchCount = $fgets(line, data_file_all);
|
|
||||||
if(`DEBUG_TRACE >= 5) $display("Time %t, line %x", $time, line);
|
|
||||||
// extract PC, Instr
|
|
||||||
matchCount = $sscanf(line, "%x %x %s", ExpectedPCM, ExpectedInstrM, textM);
|
|
||||||
//$display("matchCount %d, PCM %x ExpectedInstrM %x textM %x", matchCount, ExpectedPCM, ExpectedInstrM, textM);
|
|
||||||
|
|
||||||
// for the life of me I cannot get any build in C or C++ string parsing functions/methods to work.
|
always @(negedge clk) begin
|
||||||
// strtok was the best idea but it cannot be used correctly as system verilog does not have null
|
`SCAN_NEW_INSTR_FROM_TRACE(M)
|
||||||
// terminated strings.
|
end
|
||||||
|
|
||||||
// Just going to do this char by char.
|
// MIP spoofing
|
||||||
StartIndex = 0;
|
always @(posedge clk) begin
|
||||||
TokenIndex = 0;
|
#1;
|
||||||
//$display("len = %d", line.len());
|
if(CheckMIPFutureE) CheckMIPFutureE <= 0;
|
||||||
for(index = 0; index < line.len(); index++) begin
|
CheckMIPFutureM <= CheckMIPFutureE;
|
||||||
//$display("char = %s", line[index]);
|
if(CheckMIPFutureM) begin
|
||||||
if (line[index] == " " || line[index] == "\n") begin
|
$display("%tns: ExpectedPCM %x",$time,ExpectedPCM);
|
||||||
EndIndex = index;
|
$display("%tns: ExpectedPCE %x",$time,ExpectedPCE);
|
||||||
ExpectedTokens[TokenIndex] = line.substr(StartIndex, EndIndex-1);
|
$display("%tns: ExpectedPCW %x",$time,ExpectedPCW);
|
||||||
//$display("In Tokenizer %s", line.substr(StartIndex, EndIndex-1));
|
if((ExpectedPCE != MepcExpected) & ((MepcExpected - ExpectedPCE) * (MepcExpected - ExpectedPCE) <= 16)) begin
|
||||||
StartIndex = EndIndex + 1;
|
// if((ExpectedPCM != MepcExpected) & ((MepcExpected - ExpectedPCM) * (MepcExpected - ExpectedPCM) <= 16)) begin
|
||||||
TokenIndex++;
|
RequestDelayedMIP <= 1;
|
||||||
end
|
$display("%tns: Requesting Delayed MIP. Current MEPC value is %x",$time,MepcExpected);
|
||||||
end
|
end else begin // update MIP immediately
|
||||||
|
$display("%tns: Updating MIP to %x",$time,NextMIPexpected);
|
||||||
MarkerIndex = 3;
|
MIPexpected = NextMIPexpected;
|
||||||
NumCSRM = 0;
|
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
||||||
MemOpM = "";
|
|
||||||
RegWriteM = "";
|
|
||||||
|
|
||||||
#2;
|
|
||||||
|
|
||||||
while(TokenIndex > MarkerIndex) begin
|
|
||||||
// parse the GPR
|
|
||||||
if (ExpectedTokens[MarkerIndex] == "GPR") begin
|
|
||||||
RegWriteM = ExpectedTokens[MarkerIndex];
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%d", ExpectedRegAdrM);
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedRegValueM);
|
|
||||||
MarkerIndex += 3;
|
|
||||||
// parse memory address, read data, and/or write data
|
|
||||||
end else if(ExpectedTokens[MarkerIndex].substr(0, 2) == "Mem") begin
|
|
||||||
MemOpM = ExpectedTokens[MarkerIndex];
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedMemAdrM);
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedMemWriteDataM);
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+3], "%x", ExpectedMemReadDataM);
|
|
||||||
MarkerIndex += 4;
|
|
||||||
// parse CSRs, because there are 1 or more CSRs after the CSR token
|
|
||||||
// we check if the CSR token or the number of CSRs is greater than 0.
|
|
||||||
// if so then we want to parse for a CSR.
|
|
||||||
end else if(ExpectedTokens[MarkerIndex] == "CSR" || NumCSRM > 0) begin
|
|
||||||
if(ExpectedTokens[MarkerIndex] == "CSR") begin
|
|
||||||
// all additional CSR's won't have this token.
|
|
||||||
MarkerIndex++;
|
|
||||||
end
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex], "%s", ExpectedCSRArrayM[NumCSRM]);
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedCSRArrayValueM[NumCSRM]);
|
|
||||||
MarkerIndex += 2;
|
|
||||||
// match MIP to QEMU's because interrupts are imprecise
|
|
||||||
if(ExpectedCSRArrayM[NumCSRM].substr(0, 2) == "mip") begin
|
|
||||||
$display("%tn: ExpectedCSRArrayM[7] (MEPC) = %x",$time,ExpectedCSRArrayM[7]);
|
|
||||||
$display("%tn: ExpectedPCM = %x",$time,ExpectedPCM);
|
|
||||||
// if PC does not equal MEPC, request delayed MIP is True
|
|
||||||
if(ExpectedPCM != ExpectedCSRArrayM[7]) begin
|
|
||||||
RequestDelayedMIP = 1;
|
|
||||||
end else begin
|
|
||||||
$display("%tns: Updating MIP to %x",$time,ExpectedCSRArrayValueM[NumCSRM]);
|
|
||||||
MIPexpected = ExpectedCSRArrayValueM[NumCSRM];
|
|
||||||
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
NumCSRM++;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
// override on special conditions
|
|
||||||
if (ExpectedMemAdrM == 'h10000005) begin
|
|
||||||
//$display("%tns, %d instrs: Overwriting read data from CLINT.", $time, InstrCountW);
|
|
||||||
force dut.hart.ieu.dp.ReadDataM = ExpectedMemReadDataM;
|
|
||||||
end
|
|
||||||
if(textM.substr(0,5) == "rdtime") begin
|
|
||||||
//$display("%tns, %d instrs: Overwrite MTIME_CLINT on read of MTIME in memory stage.", $time, InstrCountW);
|
|
||||||
force dut.uncore.clint.clint.MTIME = ExpectedRegValueM;
|
|
||||||
end
|
end
|
||||||
|
$display("%tn: ExpectedCSRArrayM = %p",$time,ExpectedCSRArrayM);
|
||||||
|
$display("%tn: ExpectedCSRArrayValueM = %p",$time,ExpectedCSRArrayValueM);
|
||||||
|
$display("%tn: ExpectedTokens = %p",$time,ExpectedTokensM);
|
||||||
|
$display("%tn: MepcExpected = %x",$time,MepcExpected);
|
||||||
|
$display("%tn: ExpectedPCM = %x",$time,ExpectedPCM);
|
||||||
|
// if PC does not equal MEPC, request delayed MIP is True
|
||||||
|
$display("%tns: Difference/multiplication thing: %x",$time,(MepcExpected - ExpectedPCM) * (MepcExpected - ExpectedPCM));
|
||||||
|
$display("%tn: ExpectedCSRArrayM[NumCSRM] %x",$time,ExpectedCSRArrayM[NumCSRM]);
|
||||||
|
$display("%tn: ExpectedCSRArrayValueM[NumCSRM] %x",$time,ExpectedCSRArrayValueM[NumCSRM]);
|
||||||
|
|
||||||
|
// if((ExpectedPCM != MepcExpected) & ((MepcExpected - ExpectedPCM) * (MepcExpected - ExpectedPCM) <= 16)) begin
|
||||||
|
// RequestDelayedMIP = 1;
|
||||||
|
// $display("%tns: Requesting Delayed MIP. Current MEPC value is %x",$time,MepcExpected);
|
||||||
|
// end else begin
|
||||||
|
// $display("%tns: Updating MIP to %x",$time,NextMIPexpected);
|
||||||
|
// MIPexpected = NextMIPexpected;
|
||||||
|
// force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
||||||
|
// end
|
||||||
|
end
|
||||||
|
if(RequestDelayedMIP) begin
|
||||||
|
$display("%tns: Executing Delayed MIP. Current MEPC value is %x",$time,dut.hart.priv.csr.genblk1.csrm.MEPC_REGW);
|
||||||
|
$display("%tns: Updating MIP to %x",$time,NextMIPexpected);
|
||||||
|
$display("%tns: MepcExpected %x",$time,MepcExpected);
|
||||||
|
MIPexpected = NextMIPexpected;
|
||||||
|
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
||||||
|
$display("%tns: Finished Executing Delayed MIP. Current MEPC value is %x",$time,dut.hart.priv.csr.genblk1.csrm.MEPC_REGW);
|
||||||
|
RequestDelayedMIP = 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -449,7 +537,7 @@ module testbench();
|
|||||||
ExpectedMemWriteDataW <= '0;
|
ExpectedMemWriteDataW <= '0;
|
||||||
ExpectedMemReadDataW <= '0;
|
ExpectedMemReadDataW <= '0;
|
||||||
NumCSRW <= '0;
|
NumCSRW <= '0;
|
||||||
end else begin
|
end else if (dut.hart.ieu.c.InstrValidM) begin
|
||||||
ExpectedPCW <= ExpectedPCM;
|
ExpectedPCW <= ExpectedPCM;
|
||||||
ExpectedInstrW <= ExpectedInstrM;
|
ExpectedInstrW <= ExpectedInstrM;
|
||||||
textW <= textM;
|
textW <= textM;
|
||||||
@ -484,12 +572,6 @@ module testbench();
|
|||||||
// step2: make all checks in the write back stage.
|
// step2: make all checks in the write back stage.
|
||||||
assign checkInstrW = InstrValidW & ~dut.hart.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
|
assign checkInstrW = InstrValidW & ~dut.hart.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
|
||||||
always @(negedge clk) begin
|
always @(negedge clk) begin
|
||||||
if(RequestDelayedMIP) begin
|
|
||||||
$display("%tns: Updating MIP to %x",$time,ExpectedCSRArrayValueW[NumCSRM]);
|
|
||||||
MIPexpected = ExpectedCSRArrayValueW[NumCSRM];
|
|
||||||
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
|
||||||
RequestDelayedMIP = 0;
|
|
||||||
end
|
|
||||||
// always check PC, instruction bits
|
// always check PC, instruction bits
|
||||||
if (checkInstrW) begin
|
if (checkInstrW) begin
|
||||||
InstrCountW += 1;
|
InstrCountW += 1;
|
||||||
@ -521,7 +603,7 @@ module testbench();
|
|||||||
if(MemOpW == "MemR" || MemOpW == "MemRW") begin
|
if(MemOpW == "MemR" || MemOpW == "MemRW") begin
|
||||||
if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
||||||
`checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW)
|
`checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW)
|
||||||
end else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin
|
end else if(MemOpW == "MemW" || MemOpW == "MemRW") begin
|
||||||
if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
|
if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
|
||||||
`checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
|
`checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user