mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
change checkpoint generation to integrate GDB scripting more cleanly and save UART and PLIC state
This commit is contained in:
parent
a93f36824d
commit
52bfd65fd3
@ -1,63 +0,0 @@
|
|||||||
#! /usr/bin/python3
|
|
||||||
import sys
|
|
||||||
|
|
||||||
if len(sys.argv) != 8:
|
|
||||||
sys.exit("""Error createGenCheckpointScript.py expects 7 args:
|
|
||||||
<TCP port number>
|
|
||||||
<path to vmlinux>
|
|
||||||
<checkpoint instruction count>
|
|
||||||
<path to GDB checkpoint state dump>
|
|
||||||
<path to GDB ram dump>
|
|
||||||
<checkpoint pc address>
|
|
||||||
<number of times pc has already been hit before checkpoint>""")
|
|
||||||
|
|
||||||
tcpPort=sys.argv[1]
|
|
||||||
vmlinux=sys.argv[2]
|
|
||||||
instrCount=sys.argv[3]
|
|
||||||
statePath=sys.argv[4]
|
|
||||||
ramPath=sys.argv[5]
|
|
||||||
checkPC=sys.argv[6]
|
|
||||||
checkPCoccurences=sys.argv[7]
|
|
||||||
|
|
||||||
GDBscript = f"""
|
|
||||||
# GDB config
|
|
||||||
set pagination off
|
|
||||||
set logging overwrite on
|
|
||||||
set logging redirect on
|
|
||||||
set confirm off
|
|
||||||
|
|
||||||
# Connect to QEMU session
|
|
||||||
target extended-remote :{tcpPort}
|
|
||||||
|
|
||||||
# QEMU Config
|
|
||||||
maintenance packet Qqemu.PhyMemMode:1
|
|
||||||
|
|
||||||
# Symbol file
|
|
||||||
file {vmlinux}
|
|
||||||
|
|
||||||
# Step over reset vector into actual code
|
|
||||||
stepi 100
|
|
||||||
# Proceed to checkpoint
|
|
||||||
print "GDB proceeding to checkpoint at {instrCount} instrs, pc {checkPC}\\n"
|
|
||||||
b *0x{checkPC}
|
|
||||||
ignore 1 {checkPCoccurences}
|
|
||||||
c
|
|
||||||
print "Reached checkpoint at {instrCount} instrs\\n"
|
|
||||||
|
|
||||||
# Log all registers to a file
|
|
||||||
printf "GDB storing state to {statePath}\\n"
|
|
||||||
set logging file {statePath}
|
|
||||||
set logging on
|
|
||||||
info all-registers
|
|
||||||
set logging off
|
|
||||||
|
|
||||||
# Log main memory to a file
|
|
||||||
print "GDB storing RAM to {ramPath}\\n"
|
|
||||||
dump binary memory {ramPath} 0x80000000 0xffffffff
|
|
||||||
|
|
||||||
kill
|
|
||||||
q
|
|
||||||
"""
|
|
||||||
GDBscriptFile = open("genCheckpoint.gdb",'w')
|
|
||||||
GDBscriptFile.write(GDBscript)
|
|
||||||
GDBscriptFile.close()
|
|
@ -19,8 +19,11 @@ fi
|
|||||||
|
|
||||||
checkPtDir="$tvDir/checkpoint$instrs"
|
checkPtDir="$tvDir/checkpoint$instrs"
|
||||||
outTraceFile="$checkPtDir/all.txt"
|
outTraceFile="$checkPtDir/all.txt"
|
||||||
interruptsFile="$checkPtDir/interrupts.txt"
|
|
||||||
rawStateFile="$checkPtDir/stateGDB.txt"
|
rawStateFile="$checkPtDir/stateGDB.txt"
|
||||||
|
rawUartStateFile="$checkPtDir/uartStateGDB.txt"
|
||||||
|
uartStateFile="$checkPtDir/checkpoint-UART"
|
||||||
|
rawPlicStateFile="$checkPtDir/plicStateGDB.txt"
|
||||||
|
plicStateFile="$checkPtDir/checkpoint-PLIC"
|
||||||
rawRamFile="$checkPtDir/ramGDB.bin"
|
rawRamFile="$checkPtDir/ramGDB.bin"
|
||||||
ramFile="$checkPtDir/ram.bin"
|
ramFile="$checkPtDir/ram.bin"
|
||||||
|
|
||||||
@ -55,7 +58,48 @@ then
|
|||||||
echo "It occurs ${occurences} times before the ${instrs}th instr."
|
echo "It occurs ${occurences} times before the ${instrs}th instr."
|
||||||
|
|
||||||
# Create GDB script because GDB is terrible at handling arguments / variables
|
# Create GDB script because GDB is terrible at handling arguments / variables
|
||||||
./createGenCheckpointScript.py $tcpPort $imageDir/vmlinux $instrs $rawStateFile $rawRamFile $pc $occurences
|
cat > genCheckpoint.gdb <<- end_of_script
|
||||||
|
set pagination off
|
||||||
|
set logging overwrite on
|
||||||
|
set logging redirect on
|
||||||
|
set confirm off
|
||||||
|
target extended-remote :$tcpPort
|
||||||
|
maintenance packet Qqemu.PhyMemMode:1
|
||||||
|
file $imageDir/vmlinux
|
||||||
|
# Step over reset vector into actual code
|
||||||
|
stepi 100
|
||||||
|
shell echo \"GDB proceeding to checkpoint at $instrs instrs, pc $pc\"
|
||||||
|
b *0x$pc
|
||||||
|
ignore 1 $occurences
|
||||||
|
c
|
||||||
|
shell echo \"Reached checkpoint at $instrs instrs\"
|
||||||
|
shell echo \"GDB storing CPU state to $rawStateFile\"
|
||||||
|
set logging file $rawStateFile
|
||||||
|
set logging on
|
||||||
|
info all-registers
|
||||||
|
set logging off
|
||||||
|
shell echo \"GDB storing UART state to $rawUartStateFile\"
|
||||||
|
set logging file $rawUartStateFile
|
||||||
|
set logging on
|
||||||
|
x/8xb 0x10000000
|
||||||
|
set logging off
|
||||||
|
shell echo \"GDB storing PLIC state to $rawPlicStateFile\"
|
||||||
|
shell echo \"Note: this dumping assumes a maximum of 63 PLIC sources\"
|
||||||
|
set logging file $rawPlicStateFile
|
||||||
|
set logging on
|
||||||
|
# Priority Levels for sources 1 thru 63
|
||||||
|
x/63xw 0x0C000004
|
||||||
|
# Interrupt Enables
|
||||||
|
x/2xw 0x0C020000
|
||||||
|
# Global Priority Threshold
|
||||||
|
x/1xw 0x0C200000
|
||||||
|
set logging off
|
||||||
|
shell echo \"GDB storing RAM to $rawRamFile\"
|
||||||
|
dump binary memory $rawRamFile 0x80000000 0xffffffff
|
||||||
|
kill
|
||||||
|
q
|
||||||
|
end_of_script
|
||||||
|
|
||||||
# GDB+QEMU
|
# GDB+QEMU
|
||||||
echo "Starting QEMU in replay mode with attached GDB script at $(date +%H:%M:%S)"
|
echo "Starting QEMU in replay mode with attached GDB script at $(date +%H:%M:%S)"
|
||||||
(qemu-system-riscv64 \
|
(qemu-system-riscv64 \
|
||||||
@ -64,12 +108,15 @@ then
|
|||||||
-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=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \
|
-singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \
|
||||||
-gdb tcp::$tcpPort -S \
|
-gdb tcp::$tcpPort -S \
|
||||||
2>&1 1>./qemu-serial | ./parseQEMUtoGDB.py | ./parseGDBtoTrace.py $interruptsFile | ./remove_dup.awk > $outTraceFile) \
|
1>./qemu-serial) \
|
||||||
& riscv64-unknown-elf-gdb --quiet -ex "source genCheckpoint.gdb"
|
& riscv64-unknown-elf-gdb --quiet -x genCheckpoint.gdb
|
||||||
|
|
||||||
echo "Completed GDB script at $(date +%H:%M:%S)"
|
echo "Completed GDB script at $(date +%H:%M:%S)"
|
||||||
|
|
||||||
# Post-Process GDB outputs
|
# Post-Process GDB outputs
|
||||||
./parseState.py "$checkPtDir"
|
./parseState.py "$checkPtDir"
|
||||||
|
./parseUartState.py "$rawUartStateFile" "$uartStateFile"
|
||||||
|
./parsePlicState.py "$rawPlicStateFile" "$plicStateFile"
|
||||||
echo "Changing Endianness at $(date +%H:%M:%S)"
|
echo "Changing Endianness at $(date +%H:%M:%S)"
|
||||||
make fixBinMem
|
make fixBinMem
|
||||||
./fixBinMem "$rawRamFile" "$ramFile"
|
./fixBinMem "$rawRamFile" "$ramFile"
|
||||||
|
87
linux/testvector-generation/parsePlicState.py
Executable file
87
linux/testvector-generation/parsePlicState.py
Executable file
@ -0,0 +1,87 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
################
|
||||||
|
# Helper Funcs #
|
||||||
|
################
|
||||||
|
|
||||||
|
def tokenize(string):
|
||||||
|
tokens = []
|
||||||
|
token = ''
|
||||||
|
whitespace = 0
|
||||||
|
prevWhitespace = 0
|
||||||
|
for char in string:
|
||||||
|
prevWhitespace = whitespace
|
||||||
|
whitespace = char in ' \t\n'
|
||||||
|
if (whitespace):
|
||||||
|
if ((not prevWhitespace) and (token != '')):
|
||||||
|
tokens.append(token)
|
||||||
|
token = ''
|
||||||
|
else:
|
||||||
|
token = token + char
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Main Code #
|
||||||
|
#############
|
||||||
|
print("Begin parsing PLIC state.")
|
||||||
|
|
||||||
|
# Parse Args
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
sys.exit('Error parsePlicState.py expects 2 args: <raw GDB state dump> <output state file>')
|
||||||
|
rawPlicStateFile=sys.argv[1]
|
||||||
|
outPlicStateFile=sys.argv[2]
|
||||||
|
if not os.path.exists(rawPlicStateFile):
|
||||||
|
sys.exit('Error input file '+rawPlicStateFile+'not found')
|
||||||
|
|
||||||
|
# Main Loop
|
||||||
|
with open(rawPlicStateFile, 'r') as rawPlicStateFile:
|
||||||
|
plicIntPriorityArray=[]
|
||||||
|
# 0x0C000004 thru 0x0C000010
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000014 thru 0x0C000020
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000024 thru 0x0C000030
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000034 thru 0x0C000040
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000044 thru 0x0C000050
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000054 thru 0x0C000060
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000064 thru 0x0C000070
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000074 thru 0x0C000080
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000084 thru 0x0C000090
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C000094 thru 0x0C0000a0
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C0000a4 thru 0x0C0000b0
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C0000b4 thru 0x0C0000c0
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C0000c4 thru 0x0C0000d0
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C0000d4 thru 0x0C0000e0
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C0000e4 thru 0x0C0000f0
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
# 0x0C0000f4 thru 0x0C0000fc
|
||||||
|
plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
|
||||||
|
# 0x0C020000 thru 0x0C020004
|
||||||
|
plicIntEnable = tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
|
||||||
|
# 0x0C200000
|
||||||
|
plicIntPriorityThreshold = tokenize(rawPlicStateFile.readline())[1:]
|
||||||
|
|
||||||
|
with open(outPlicStateFile, 'w') as outPlicStateFile:
|
||||||
|
for word in plicIntPriorityArray:
|
||||||
|
outPlicStateFile.write(word[2:]+'\n')
|
||||||
|
for word in plicIntEnable:
|
||||||
|
outPlicStateFile.write(word[2:]+'\n')
|
||||||
|
for word in plicIntPriorityThreshold:
|
||||||
|
outPlicStateFile.write(word[2:]+'\n')
|
||||||
|
|
||||||
|
print("Finished parsing PLIC state!")
|
@ -24,7 +24,7 @@ def tokenize(string):
|
|||||||
#############
|
#############
|
||||||
# Main Code #
|
# Main Code #
|
||||||
#############
|
#############
|
||||||
print("Begin parsing state.")
|
print("Begin parsing CPU state.")
|
||||||
|
|
||||||
# Parse Args
|
# Parse Args
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
@ -96,4 +96,4 @@ with open(stateGDBpath, 'r') as stateGDB:
|
|||||||
outFile.write(hex(byte)[2:]+'\n')
|
outFile.write(hex(byte)[2:]+'\n')
|
||||||
outFile.close()
|
outFile.close()
|
||||||
|
|
||||||
print("Finished parsing state!")
|
print("Finished parsing CPU state!")
|
||||||
|
53
linux/testvector-generation/parseUartState.py
Executable file
53
linux/testvector-generation/parseUartState.py
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
################
|
||||||
|
# Helper Funcs #
|
||||||
|
################
|
||||||
|
|
||||||
|
def tokenize(string):
|
||||||
|
tokens = []
|
||||||
|
token = ''
|
||||||
|
whitespace = 0
|
||||||
|
prevWhitespace = 0
|
||||||
|
for char in string:
|
||||||
|
prevWhitespace = whitespace
|
||||||
|
whitespace = char in ' \t\n'
|
||||||
|
if (whitespace):
|
||||||
|
if ((not prevWhitespace) and (token != '')):
|
||||||
|
tokens.append(token)
|
||||||
|
token = ''
|
||||||
|
else:
|
||||||
|
token = token + char
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Main Code #
|
||||||
|
#############
|
||||||
|
print("Begin parsing UART state.")
|
||||||
|
|
||||||
|
# Parse Args
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
sys.exit('Error parseUartState.py expects 2 args: <raw GDB state dump> <output state file>')
|
||||||
|
rawUartStateFile=sys.argv[1]
|
||||||
|
outUartStateFile=sys.argv[2]
|
||||||
|
if not os.path.exists(rawUartStateFile):
|
||||||
|
sys.exit('Error input file '+rawUartStateFile+'not found')
|
||||||
|
|
||||||
|
# Main Loop
|
||||||
|
with open(rawUartStateFile, 'r') as rawUartStateFile:
|
||||||
|
with open(outUartStateFile, 'w') as outUartStateFile:
|
||||||
|
uartBytes = tokenize(rawUartStateFile.readline())[1:]
|
||||||
|
# Stores
|
||||||
|
# 0: RBR / Divisor Latch Low
|
||||||
|
# 1: IER / Divisor Latch High
|
||||||
|
# 2: IIR
|
||||||
|
# 3: LCR
|
||||||
|
# 4: MCR
|
||||||
|
# 5: LSR
|
||||||
|
# 6: MSR
|
||||||
|
# 7: SCR
|
||||||
|
for uartByte in uartBytes:
|
||||||
|
outUartStateFile.write(uartByte[2:]+'\n')
|
||||||
|
|
||||||
|
print("Finished parsing UART state!")
|
Loading…
Reference in New Issue
Block a user