diff --git a/linux/testvector-generation/createGenCheckpointScript.py b/linux/testvector-generation/createGenCheckpointScript.py deleted file mode 100755 index 264a2ee6..00000000 --- a/linux/testvector-generation/createGenCheckpointScript.py +++ /dev/null @@ -1,63 +0,0 @@ -#! /usr/bin/python3 -import sys - -if len(sys.argv) != 8: - sys.exit("""Error createGenCheckpointScript.py expects 7 args: - - - - - - - """) - -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() diff --git a/linux/testvector-generation/genCheckpoint.sh b/linux/testvector-generation/genCheckpoint.sh index 792925b7..1ca309be 100755 --- a/linux/testvector-generation/genCheckpoint.sh +++ b/linux/testvector-generation/genCheckpoint.sh @@ -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" diff --git a/linux/testvector-generation/parsePlicState.py b/linux/testvector-generation/parsePlicState.py new file mode 100755 index 00000000..8655409d --- /dev/null +++ b/linux/testvector-generation/parsePlicState.py @@ -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: ') +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!") diff --git a/linux/testvector-generation/parseState.py b/linux/testvector-generation/parseState.py index 5275597c..abc36fb2 100755 --- a/linux/testvector-generation/parseState.py +++ b/linux/testvector-generation/parseState.py @@ -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!") diff --git a/linux/testvector-generation/parseUartState.py b/linux/testvector-generation/parseUartState.py new file mode 100755 index 00000000..0b7d1cf7 --- /dev/null +++ b/linux/testvector-generation/parseUartState.py @@ -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: ') +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!")