forked from Github_Repos/cvw
change checkpoint generation to integrate GDB scripting more cleanly and save UART and PLIC state
This commit is contained in:
parent
409dd48706
commit
097301635a
@ -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"
|
||||
outTraceFile="$checkPtDir/all.txt"
|
||||
interruptsFile="$checkPtDir/interrupts.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"
|
||||
ramFile="$checkPtDir/ram.bin"
|
||||
|
||||
@ -55,7 +58,48 @@ then
|
||||
echo "It occurs ${occurences} times before the ${instrs}th instr."
|
||||
|
||||
# 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
|
||||
echo "Starting QEMU in replay mode with attached GDB script at $(date +%H:%M:%S)"
|
||||
(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 \
|
||||
-singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \
|
||||
-gdb tcp::$tcpPort -S \
|
||||
2>&1 1>./qemu-serial | ./parseQEMUtoGDB.py | ./parseGDBtoTrace.py $interruptsFile | ./remove_dup.awk > $outTraceFile) \
|
||||
& riscv64-unknown-elf-gdb --quiet -ex "source genCheckpoint.gdb"
|
||||
1>./qemu-serial) \
|
||||
& riscv64-unknown-elf-gdb --quiet -x genCheckpoint.gdb
|
||||
|
||||
echo "Completed GDB script at $(date +%H:%M:%S)"
|
||||
|
||||
# Post-Process GDB outputs
|
||||
./parseState.py "$checkPtDir"
|
||||
./parseUartState.py "$rawUartStateFile" "$uartStateFile"
|
||||
./parsePlicState.py "$rawPlicStateFile" "$plicStateFile"
|
||||
echo "Changing Endianness at $(date +%H:%M:%S)"
|
||||
make fixBinMem
|
||||
./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 #
|
||||
#############
|
||||
print("Begin parsing state.")
|
||||
print("Begin parsing CPU state.")
|
||||
|
||||
# Parse Args
|
||||
if len(sys.argv) != 2:
|
||||
@ -96,4 +96,4 @@ with open(stateGDBpath, 'r') as stateGDB:
|
||||
outFile.write(hex(byte)[2:]+'\n')
|
||||
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