diff --git a/linux/testvector-generation/0001-bens-hack-to-turn-on-logging-mid-execution-using-GDB.patch b/linux/testvector-generation/0001-bens-hack-to-turn-on-logging-mid-execution-using-GDB.patch deleted file mode 100644 index 1b0e1d4aa..000000000 --- a/linux/testvector-generation/0001-bens-hack-to-turn-on-logging-mid-execution-using-GDB.patch +++ /dev/null @@ -1,53 +0,0 @@ -From f9882bd274bde82d8c38a9c31692b6ee33d8cd9a Mon Sep 17 00:00:00 2001 -From: root -Date: Mon, 28 Feb 2022 22:48:29 +0000 -Subject: [PATCH] bens hack to turn on logging mid-execution using GDB - ---- - gdbstub.c | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) - -diff --git a/gdbstub.c b/gdbstub.c -index 141d7bc4ec..98ecce1b67 100644 ---- a/gdbstub.c -+++ b/gdbstub.c -@@ -2317,6 +2317,23 @@ static void handle_set_qemu_phy_mem_mode(GArray *params, void *user_ctx) - } - put_packet("OK"); - } -+ -+static void handle_set_qemu_logging(GArray *params, void *user_ctx) -+{ -+ if (!params->len) { -+ put_packet("E22"); -+ return; -+ } -+ -+ int log_mask; -+ if (!get_param(params, 0)->val_ul) { -+ log_mask = 0; -+ } else { -+ log_mask = CPU_LOG_TB_IN_ASM | CPU_LOG_INT | CPU_LOG_TB_CPU | CPU_LOG_TB_NOCHAIN; -+ } -+ qemu_set_log(log_mask); -+ put_packet("OK"); -+} - #endif - - static const GdbCmdParseEntry gdb_gen_query_set_common_table[] = { -@@ -2430,6 +2447,12 @@ static const GdbCmdParseEntry gdb_gen_set_table[] = { - .cmd_startswith = 1, - .schema = "l0" - }, -+ { -+ .handler = handle_set_qemu_logging, -+ .cmd = "qemu.Logging:", -+ .cmd_startswith = 1, -+ .schema = "l0" -+ }, - #endif - }; - --- -2.27.0 - diff --git a/linux/testvector-generation/Makefile b/linux/testvector-generation/Makefile index 8f3441e5a..c31aae39d 100644 --- a/linux/testvector-generation/Makefile +++ b/linux/testvector-generation/Makefile @@ -1,17 +1,13 @@ SHELL = /bin/sh CFLAG = -Wall -g -CC = clang +CC = gcc -all: fixBinMem silencePipe +all: fixBinMem fixBinMem: fixBinMem.c ${CC} ${CFLAGS} fixBinMem.c -o fixBinMem chmod +x fixBinMem -silencePipe: silencePipe.c - ${CC} ${CFLAGS} silencePipe.c -o silencePipe - chmod +x silencePipe clean: -rm -f fixBinMem - -rm -f silencePipe diff --git a/linux/testvector-generation/checkpointSweep.sh b/linux/testvector-generation/checkpointSweep.sh index 74ed9ecf5..c1543677c 100755 --- a/linux/testvector-generation/checkpointSweep.sh +++ b/linux/testvector-generation/checkpointSweep.sh @@ -1,5 +1,5 @@ for index in {450..500} do instrs=$(($index*1000000)) - echo "y" | nice -n 5 ./genCheckpoint.sh $instrs 0 + echo "y" | nice -n 5 ./genCheckpoint.sh $instrs done diff --git a/linux/testvector-generation/createGenCheckpointScript.py b/linux/testvector-generation/createGenCheckpointScript.py deleted file mode 100755 index 02d1bcc76..000000000 --- a/linux/testvector-generation/createGenCheckpointScript.py +++ /dev/null @@ -1,78 +0,0 @@ -#! /usr/bin/python3 -import sys - -if len(sys.argv) != 9: - 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] -genTrace=sys.argv[8] - -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 -""" -if (genTrace=="1"): - GDBscript+=\ -""" -# Generate Trace Until End -maintenance packet Qqemu.Logging:1 -# Do this by setting an impossible breakpoint -b *0x1000 -del 1 -c -""" -else: - GDBscript+=\ -""" -kill -q -""" -GDBscriptFile = open("genCheckpoint.gdb",'w') -GDBscriptFile.write(GDBscript) -GDBscriptFile.close() diff --git a/linux/testvector-generation/debug.sh b/linux/testvector-generation/debug.sh new file mode 100755 index 000000000..748f6e023 --- /dev/null +++ b/linux/testvector-generation/debug.sh @@ -0,0 +1,21 @@ +#!/bin/bash +imageDir=$RISCV/buildroot/output/images +tvDir=$RISCV/linux-testvectors +tcpPort=1239 + +# QEMU Simulation +(qemu-system-riscv64 \ +-M virt -dtb $imageDir/wally-virt.dtb \ +-nographic \ +-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 \ +> ./qemu-serial \ +-gdb tcp::$tcpPort -S) \ +& riscv64-unknown-elf-gdb -quiet \ +-ex "set pagination off" \ +-ex "set logging overwrite on" \ +-ex "set logging redirect on" \ +-ex "set confirm off" \ +-ex "target extended-remote :$tcpPort" \ +-ex "maintenance packet Qqemu.PhyMemMode:1" \ +-ex "file $imageDir/vmlinux" diff --git a/linux/testvector-generation/genCheckpoint.sh b/linux/testvector-generation/genCheckpoint.sh index 834ef6bb6..8f4d0a111 100755 --- a/linux/testvector-generation/genCheckpoint.sh +++ b/linux/testvector-generation/genCheckpoint.sh @@ -6,12 +6,11 @@ recordFile="$tvDir/all.qemu" traceFile="$tvDir/all.txt" # Parse Commandline Arg -if [ "$#" -ne 2 ]; then - echo "genCheckpoint requires 2 arguments: " >&2 +if [ "$#" -ne 1 ]; then + echo "genCheckpoint requires 1 argument: " >&2 exit 1 fi instrs=$1 -genTrace=$2 if ! [ "$instrs" -eq "$instrs" ] 2> /dev/null then echo "Error expected integer number of instructions, got $instrs" >&2 @@ -20,40 +19,36 @@ 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" -if [ $genTrace -eq "1" ]; then - read -p "This scripts is going to create a checkpoint at $instrs instrs. - AND it's going to start generating a trace at that checkpoint. - Is that what you wanted? (y/n) " -n 1 -r -else - read -p "This scripts is going to create a checkpoint at $instrs instrs. - Is that what you wanted? (y/n) " -n 1 -r -fi +read -p "This scripts is going to create a checkpoint at $instrs instrs. +Is that what you wanted? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]] then echo "Creating checkpoint at $instrs instructions!" + if [ ! -d "$tvDir" ]; then + echo "Error: linux testvector directory $tvDir not found!">&2 + echo "Please create it. For example:">&2 + echo " sudo mkdir -p $tvDir">&2 + exit 1 + fi + test -w $tvDir + if [ ! $? -eq 0 ]; then + echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 + echo "Please chmod it. For example:">&2 + echo " sudo chmod -R a+rw $tvDir">&2 + exit 1 + fi + + mkdir -p $checkPtDir - # Create Output Directory - echo "Elevating permissions to create $checkPtDir and stuff inside it" - sudo mkdir -p $checkPtDir - sudo chown -R cad:users $checkPtDir - sudo chmod -R a+rw $checkPtDir - sudo touch $outTraceFile - sudo chmod a+rw $outTraceFile - sudo touch $interruptsFile - sudo chmod a+rw $interruptsFile - sudo touch $rawStateFile - sudo chmod a+rw $rawStateFile - sudo touch $rawRamFile - sudo chmod a+rw $rawRamFile - sudo touch $ramFile - sudo chmod a+rw $ramFile - # Identify instruction in trace instr=$(sed "${instrs}q;d" "$traceFile") echo "Found ${instrs}th instr: ${instr}" @@ -63,7 +58,60 @@ 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 $genTrace + 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\" + # Save value of LCR + set \$LCR=*0x10000003 & 0xff + set logging file $rawUartStateFile + set logging on + # Change LCR to set DLAB=0 to be able to read RBR and IER + set {char}0x10000003 &= ~0x80 + x/1xb 0x10000000 + x/1xb 0x10000001 + x/1xb 0x10000002 + # But log original value of LCR + printf "0x10000003:\t0x%02x\n", \$LCR + x/1xb 0x10000004 + x/1xb 0x10000005 + x/1xb 0x10000006 + x/1xb 0x10000007 + 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 \ @@ -72,24 +120,25 @@ 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/parseQEMUtoGDB_run.py | ./parseGDBtoTrace/parseGDBtoTrace_run.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 "$checkPtDir" + ./parsePlicState.py "$checkPtDir" echo "Changing Endianness at $(date +%H:%M:%S)" make fixBinMem ./fixBinMem "$rawRamFile" "$ramFile" - if [ $genTrace -ne "1" ]; then - echo "Copying over a truncated trace" - tail -n+$instrs $traceFile > $outTraceFile - fi - read -p "Checkpoint completed at $(date +%H:%M:%S)" -n 1 -r + echo "Copying over a truncated trace" + tail -n+$instrs $traceFile > $outTraceFile - # Cleanup - echo "Elevating permissions to restrict write access to $checkPtDir" - sudo chown -R cad:users $checkPtDir - sudo chmod -R go-w $checkPtDir + echo "Checkpoint completed at $(date +%H:%M:%S)" + echo "You may want to restrict write access to $tvDir now and give cad ownership of it." + echo "Run the following:" + echo " sudo chown -R cad:cad $tvDir" + echo " sudo chmod -R go-w $tvDir" fi diff --git a/linux/testvector-generation/genInitMem.sh b/linux/testvector-generation/genInitMem.sh index 3e0aef83a..27a3f004a 100755 --- a/linux/testvector-generation/genInitMem.sh +++ b/linux/testvector-generation/genInitMem.sh @@ -22,13 +22,15 @@ if [[ $REPLY =~ ^[Yy]$ ]] then if [ ! -d "$tvDir" ]; then echo "Error: linux testvector directory $tvDir not found!">&2 - echo "Please create it.">&2 + echo "Please create it. For example:">&2 + echo " sudo mkdir -p $tvDir">&2 exit 1 fi - test -w $RISCV/linux-testvectors + test -w $tvDir if [ ! $? -eq 0 ]; then echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 - echo "Please chmod it.">&2 + echo "Please chmod it. For example:">&2 + echo " sudo chmod -R a+rw $tvDir">&2 exit 1 fi @@ -62,5 +64,8 @@ then ./fixBinMem "$rawUntrimmedBootmemFile" "$untrimmedBootmemFile" echo "genInitMem.sh completed!" - echo "You may consider restricting write access to $tvDir now." + echo "You may want to restrict write access to $tvDir now and give cad ownership of it." + echo "Run the following:" + echo " sudo chown -R cad:cad $tvDir" + echo " sudo chmod -R go-w $tvDir" fi diff --git a/linux/testvector-generation/genRecording.sh b/linux/testvector-generation/genRecording.sh index d7319413a..f9538e145 100755 --- a/linux/testvector-generation/genRecording.sh +++ b/linux/testvector-generation/genRecording.sh @@ -8,26 +8,30 @@ Would you like to proceed? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]] then - # Create Output Directory - echo "Elevating permissions to create $recordFile" - sudo mkdir -p $tvDir - sudo chown cad $tvDir - sudo touch $recordFile - sudo chmod a+rw $recordFile + if [ ! -d "$tvDir" ]; then + echo "Error: linux testvector directory $tvDir not found!">&2 + echo "Please create it. For example:">&2 + echo " sudo mkdir -p $tvDir">&2 + exit 1 + fi + test -w $tvDir + if [ ! $? -eq 0 ]; then + echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 + echo "Please chmod it. For example:">&2 + echo " sudo chmod -R a+rw $tvDir">&2 + exit 1 + fi - # Compile Devicetree from Source - dtc -I dts -O dtb ../devicetree/wally-virt.dts > ../devicetree/wally-virt.dtb - - # QEMU Simulation - echo "Launching QEMU!" + echo "Launching QEMU in record mode!" qemu-system-riscv64 \ - -M virt -dtb ../devicetree/wally-virt.dtb \ + -M virt -dtb $imageDir/wally-virt.dtb \ -nographic \ -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=record,rrfile=$recordFile - # Cleanup - echo "Elevating permissions to restrict write access to $recordFile" - sudo chown cad $recordFile - sudo chmod o-w $recordFile + echo "genRecording.sh completed!" + echo "You may want to restrict write access to $tvDir now and give cad ownership of it." + echo "Run the following:" + echo " sudo chown -R cad:cad $tvDir" + echo " sudo chmod -R go-w $tvDir" fi diff --git a/linux/testvector-generation/genTrace.sh b/linux/testvector-generation/genTrace.sh index 6c3548be5..5c79ee3d0 100755 --- a/linux/testvector-generation/genTrace.sh +++ b/linux/testvector-generation/genTrace.sh @@ -13,32 +13,36 @@ Would you like to proceed? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]] then - # Create Output Directory - echo "Elevating permissions to create $traceFile, $interruptsFile" - sudo mkdir -p $tvDir - sudo chown cad $tvDir - sudo touch $traceFile - sudo touch $interruptsFile - sudo chmod a+rw $traceFile - sudo chmod a+rw $interruptsFile + if [ ! -d "$tvDir" ]; then + echo "Error: linux testvector directory $tvDir not found!">&2 + echo "Please create it. For example:">&2 + echo " sudo mkdir -p $tvDir">&2 + exit 1 + fi + test -w $tvDir + if [ ! $? -eq 0 ]; then + echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 + echo "Please chmod it. For example:">&2 + echo " sudo chmod -R a+rw $tvDir">&2 + exit 1 + fi - # Compile Devicetree from Source - dtc -I dts -O dtb ../devicetree/wally-virt.dts > ../devicetree/wally-virt.dtb + touch $traceFile + touch $interruptsFile # QEMU Simulation echo "Launching QEMU in replay mode!" (qemu-system-riscv64 \ - -M virt -dtb ../devicetree/wally-virt.dtb \ + -M virt -dtb $imageDir/wally-virt.dtb \ -nographic \ -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 \ -d nochain,cpu,in_asm,int \ - 2>&1 >/dev/null | ./parseQEMUtoGDB.py | ./parseGDBtoTrace.py $interruptsFile | ./remove_dup.awk > $traceFile) + 2>&1 >./qemu-serial | ./parseQEMUtoGDB.py | ./parseGDBtoTrace.py $interruptsFile | ./remove_dup.awk > $traceFile) - # Cleanup - echo "Elevating permissions to restrict write access to $traceFile, $interruptsFile" - sudo chown cad $traceFile - sudo chown cad $interruptsFile - sudo chmod o-w $traceFile - sudo chmod o-w $interruptsFile + echo "genTrace.sh completed!" + echo "You may want to restrict write access to $tvDir now and give cad ownership of it." + echo "Run the following:" + echo " sudo chown -R cad:cad $tvDir" + echo " sudo chmod -R go-w $tvDir" fi diff --git a/linux/testvector-generation/parsePlicState.py b/linux/testvector-generation/parsePlicState.py new file mode 100755 index 000000000..a3c3787c8 --- /dev/null +++ b/linux/testvector-generation/parsePlicState.py @@ -0,0 +1,95 @@ +#! /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 + +def stripZeroes(num): + num = num.strip('0') + if num=='': + return '0' + else: + return num + +############# +# Main Code # +############# +print("Begin parsing PLIC state.") + +# Parse Args +if len(sys.argv) != 2: + sys.exit('Error parsePlicState.py expects 1 arg: ') +outDir = sys.argv[1]+'/' +rawPlicStateFile = outDir+'plicStateGDB.txt' +if not os.path.exists(rawPlicStateFile): + sys.exit('Error input file '+rawPlicStateFile+'not found') + +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(outDir+'checkpoint-PLIC_INT_PRIORITY', 'w') as outFile: + for word in plicIntPriorityArray: + outFile.write(stripZeroes(word[2:])+'\n') +with open(outDir+'checkpoint-PLIC_INT_ENABLE', 'w') as outFile: + for word in plicIntEnable: + outFile.write(stripZeroes(word[2:])) +with open(outDir+'checkpoint-PLIC_THRESHOLD', 'w') as outFile: + for word in plicIntPriorityThreshold: + outFile.write(stripZeroes(word[2:])+'\n') + +print("Finished parsing PLIC state!") diff --git a/linux/testvector-generation/parseState.py b/linux/testvector-generation/parseState.py index 5275597c4..abc36fb2f 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 000000000..611937054 --- /dev/null +++ b/linux/testvector-generation/parseUartState.py @@ -0,0 +1,50 @@ +#! /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) != 2: + sys.exit('Error parseUartState.py expects 1 arg: ') +outDir = sys.argv[1]+'/' +rawUartStateFile = outDir+'uartStateGDB.txt' +if not os.path.exists(rawUartStateFile): + sys.exit('Error input file '+rawUartStateFile+'not found') + +with open(rawUartStateFile, 'r') as rawUartStateFile: + uartBytes = [] + for i in range(0,8): + uartBytes += tokenize(rawUartStateFile.readline())[1:] +with open(outDir+'checkpoint-UART_IER', 'w') as outFile: + outFile.write(uartBytes[1][2:]) +with open(outDir+'checkpoint-UART_LCR', 'w') as outFile: + outFile.write(uartBytes[3][2:]) +with open(outDir+'checkpoint-UART_MCR', 'w') as outFile: + outFile.write(uartBytes[4][2:]) +with open(outDir+'checkpoint-UART_SCR', 'w') as outFile: + outFile.write(uartBytes[7][2:]) + +print("Finished parsing UART state!") diff --git a/linux/testvector-generation/silencePipe.c b/linux/testvector-generation/silencePipe.c deleted file mode 100644 index 3ffeb14b4..000000000 --- a/linux/testvector-generation/silencePipe.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include - -int main(void) -{ - char *line = NULL; - size_t len = 0; - while (1) { - FILE* controlFile = fopen("silencePipe.control", "r"); - char silenceChar = getc(controlFile); - fclose(controlFile); - ssize_t lineSize = getline(&line, &len, stdin); - if (silenceChar!='1') { - printf("%s",line); - } else { - fprintf(stderr,"%s",line); - } - } - free(line); - return 0; -} diff --git a/pipelined/testbench/testbench-linux.sv b/pipelined/testbench/testbench-linux.sv index 0c58f7b72..8723d6b9c 100644 --- a/pipelined/testbench/testbench-linux.sv +++ b/pipelined/testbench/testbench-linux.sv @@ -214,6 +214,15 @@ module testbench; `define STATUS_UIE `CSR_BASE.csrsr.STATUS_UIE `define PRIV dut.core.priv.priv.privmodereg.q `define INSTRET dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2] + `define UART dut.uncore.uart.uart.u + `define UART_IER `UART.IER + `define UART_LCR `UART.LCR + `define UART_MCR `UART.MCR + `define UART_SCR `UART.SCR + `define PLIC dut.uncore.plic.plic + `define PLIC_INT_PRIORITY `PLIC.intPriority + `define PLIC_INT_ENABLE `PLIC.intEn + `define PLIC_THRESHOLD `PLIC.intThreshold // Common Macros `define checkCSR(CSR) \ begin \ @@ -301,6 +310,23 @@ module testbench; `INIT_CHECKPOINT_VAL(SATP, [`XLEN-1:0]); `INIT_CHECKPOINT_VAL(PRIV, [1:0]); `MAKE_CHECKPOINT_INIT_SIGNAL(MSTATUS, [`XLEN-1:0],0,0); + // Many UART registers are difficult to initialize because under the hood + // they are not simple registers. Instead some are generated by interesting + // combinational blocks such that they depend upon a variety of different + // underlying flops. See for example how RBR might be the actual RXBR + // register, but it could also just as well be 0 or the tail of the fifo + // array. + //`INIT_CHECKPOINT_VAL(UART_RBR, [7:0]); + `INIT_CHECKPOINT_VAL(UART_IER, [7:0]); + //`INIT_CHECKPOINT_VAL(UART_IIR, [7:0]); + `INIT_CHECKPOINT_VAL(UART_LCR, [7:0]); + `INIT_CHECKPOINT_VAL(UART_MCR, [4:0]); + //`INIT_CHECKPOINT_VAL(UART_LSR, [7:0]); + //`INIT_CHECKPOINT_VAL(UART_MSR, [7:0]); + `INIT_CHECKPOINT_VAL(UART_SCR, [7:0]); + `INIT_CHECKPOINT_SIMPLE_ARRAY(PLIC_INT_PRIORITY, [2:0],`PLIC_NUM_SRC,1); + `INIT_CHECKPOINT_VAL(PLIC_INT_ENABLE, [`PLIC_NUM_SRC:1]); + `INIT_CHECKPOINT_VAL(PLIC_THRESHOLD, [2:0]); integer memFile; integer readResult; @@ -314,8 +340,8 @@ module testbench; $sformat(checkpointDir,"%s/linux-testvectors/checkpoint%0d/",RISCV_DIR,CHECKPOINT); $readmemb(`TWO_BIT_PRELOAD, dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem); $readmemb(`BTB_PRELOAD, dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem); - ProgramAddrMapFile = {linuxImageDir,"vmlinux.objdump.addr"}; - ProgramLabelMapFile = {linuxImageDir,"vmlinux.objdump.lab"}; + ProgramAddrMapFile = {linuxImageDir,"disassembly/vmlinux.objdump.addr"}; + ProgramLabelMapFile = {linuxImageDir,"disassembly/vmlinux.objdump.lab"}; // initialize bootrom memFile = $fopen({testvectorDir,"bootmem.bin"}, "rb"); readResult = $fread(dut.uncore.bootrom.bootrom.RAM,memFile); diff --git a/setup.sh b/setup.sh index 925d87e83..b3452626d 100755 --- a/setup.sh +++ b/setup.sh @@ -7,7 +7,7 @@ echo "Executing Wally setup.sh" # Path to Wally repository -WALLY=$(dirname ${BASH_SOURCE}) +WALLY=$(dirname ${BASH_SOURCE[0]:-$0}) export WALLY=$(cd "$WALLY" && pwd) echo \$WALLY set to ${WALLY} @@ -15,7 +15,7 @@ echo \$WALLY set to ${WALLY} export RISCV=/opt/riscv # change this if you installed the tools in a different location # Tools -# GCCZ +# GCC export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RISCV/riscv-gnu-toolchain/lib:$RISCV/riscv-gnu-toolchain/riscv64-unknown-elf/lib export PATH=$PATH:$RISCV/riscv-gnu-toolchain/bin:$RISCV/riscv-gnu-toolchain/riscv64-unknown-elf/bin # GCC tools # Spike @@ -26,7 +26,8 @@ export PATH=$WALLY/bin:$PATH # Verilator export PATH=/usr/local/bin/verilator:$PATH # Change this for your path to Verilator # ModelSim/Questa (vsim) -export PATH=/cad/mentor/questa_sim-2021.2_1/questasim/bin:$PATH # Change this for your path to Modelsim +export PATH=/cad/mentor/questa_sim-2021.2_1/questasim/bin:$PATH # Change this for your path to Modelsim, or delete +export PATH=/cad/mentor/questa_sim-2022.1_1/questasim/bin:$PATH # Change this for your path to Modelsim export MGLS_LICENSE_FILE=1717@solidworks.eng.hmc.edu # Change this to your Siemens license server export PATH=/cad/synopsys/SYN/bin:$PATH # Change this for your path to Design Compiler export SNPSLMD_LICENSE_FILE=27020@134.173.38.214 diff --git a/synthDC/Makefile b/synthDC/Makefile index b359046eb..b1452f0e2 100755 --- a/synthDC/Makefile +++ b/synthDC/Makefile @@ -1,6 +1,6 @@ # # Makefile for synthesis -# +# Shreya Sanghai (ssanghai@hmc.edu) 2/28/2022 NAME := synth # defaults @@ -26,6 +26,7 @@ CONFIGFILES ?= $(shell find $(CONFIGDIR) -name rv*_*) CONFIGFILESTRIM = $(notdir $(CONFIGFILES)) print: echo $(CONFIGFILESTRIM) + echo $(DIRS) default: @echo "Basic synthesis procedure for Wally:" @@ -38,10 +39,16 @@ rv%.log: rv% echo $< -DIRS = rv32e rv32gc rv64ic rv64gc rv32ic +DIRS = rv32e #rv32gc rv64ic rv64gc rv32ic # DELDIRS = rv32e rv32gc rv64ic rv64gc rv32ic # CONFIGSUBDIRS = _FPUoff _noMulDiv _noVirtMem _PMP0 _PMP16 _orig +copy: + @$(foreach dir, $(DIRS), rm -rf $(CONFIGDIR)/$(dir)_orig;) + @$(foreach dir, $(DIRS), cp -r $(CONFIGDIR)/$(dir) $(CONFIGDIR)/$(dir)_orig;) + @$(foreach dir, $(DIRS), sed -i 's/WAYSIZEINBYTES.*/WAYSIZEINBYTES 512/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) + @$(foreach dir, $(DIRS), sed -i 's/NUMWAYS.*/NUMWAYS 1/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) + @$(foreach dir, $(DIRS), sed -i "s/RAM_RANGE.*/RAM_RANGE 34\'h01FF/g" $(CONFIGDIR)/$(dir)_orig/wally-config.vh ;) del: @$(foreach dir, $(DIRS), rm -rf $(CONFIGDIR)/$(dir)_orig;) @@ -55,47 +62,37 @@ configs: $(DIRS) $(DIRS): #turn off FPU rm -rf $(CONFIGDIR)/$@_FPUoff - cp -r $(CONFIGDIR)/$@ $(CONFIGDIR)/$@_FPUoff + cp -r $(CONFIGDIR)/$@_orig $(CONFIGDIR)/$@_FPUoff sed -i 's/1 *<< *3/0 << 3/' $(CONFIGDIR)/$@_FPUoff/wally-config.vh sed -i 's/1 *<< *5/0 << 5/' $(CONFIGDIR)/$@_FPUoff/wally-config.vh # PMP 16 rm -rf $(CONFIGDIR)/$@_PMP16 cp -r $(CONFIGDIR)/$@_FPUoff $(CONFIGDIR)/$@_PMP16 - # sed -i 's/1 *<< *3/0 << 3/' $(CONFIGDIR)/$@_PMP16/wally-config.vh - # sed -i 's/1 *<< *5/0 << 5/' $(CONFIGDIR)/$@_PMP16/wally-config.vh sed -i 's/PMP_ENTRIES \(64\|16\|0\)/PMP_ENTRIES 16/' $(CONFIGDIR)/$@_PMP16/wally-config.vh # PMP 0 rm -rf $(CONFIGDIR)/$@_PMP0 cp -r $(CONFIGDIR)/$@_FPUoff $(CONFIGDIR)/$@_PMP0 - # sed -i 's/1 *<< *3/0 << 3/' $(CONFIGDIR)/$@_PMP0/wally-config.vh - # sed -i 's/1 *<< *5/0 << 5/' $(CONFIGDIR)/$@_PMP0/wally-config.vh sed -i 's/PMP_ENTRIES \(64\|16\|0\)/PMP_ENTRIES 0/' $(CONFIGDIR)/$@_PMP0/wally-config.vh # No Virtual Memory rm -rf $(CONFIGDIR)/$@_noVirtMem - # cp -r $(CONFIGDIR)/$@ $(CONFIGDIR)/$@_noVirtMem - # sed -i 's/1 *<< *3/0 <_PMP0< 3/' $(CONFIGDIR)/$@_noVirtMem/wally-config.vh - # sed -i 's/1 *<< *5/0 << 5/' $(CONFIGDIR)/$@_noVirtMem/wally-config.vh - # sed -i 's/PMP_ENTRIES \(64\|16\|0\)/PMP_ENTRIES 0/' $(CONFIGDIR)/$@_noVirtMem/wally-config.vh + cp -r $(CONFIGDIR)/$@_PMP0 $(CONFIGDIR)/$@_noVirtMem sed -i 's/VIRTMEM_SUPPORTED 1/VIRTMEM_SUPPORTED 0/' $(CONFIGDIR)/$@_noVirtMem/wally-config.vh #no muldiv rm -rf $(CONFIGDIR)/$@_noMulDiv cp -r $(CONFIGDIR)/$@_noVirtMem $(CONFIGDIR)/$@_noMulDiv - # sed -i 's/1 *<< *3/0 << 3/' $(CONFIGDIR)/$@_noMulDiv/wally-config.vh - # sed -i 's/1 *<< *5/0 << 5/' $(CONFIGDIR)/$@_noMulDiv/wally-config.vh - # sed -i 's/PMP_ENTRIES \(64\|16\|0\)/PMP_ENTRIES 0/' $(CONFIGDIR)/$@_noMulDiv/wally-config.vh - # sed -i 's/VIRTMEM_SUPPORTED 1/VIRTMEM_SUPPORTED 0/' $(CONFIGDIR)/$@_noMulDiv/wally-config.vh sed -i 's/1 *<< *12/0 << 12/' $(CONFIGDIR)/$@_noMulDiv/wally-config.vh allsynth: $(CONFIGFILESTRIM) $(CONFIGFILESTRIM): - make synth DESIGN=wallypipelinedcore CONFIG=$@ TECH=sky90 FREQ=500 MAXCORES=1 --jobs + make synth DESIGN=wallypipelinedcore CONFIG=$@ TECH=sky90 FREQ=500 MAXCORES=1 + synth: @echo "DC Synthesis" @mkdir -p hdl/ diff --git a/synthDC/extractSummary.py b/synthDC/extractSummary.py old mode 100644 new mode 100755 index e9fa69772..85ab99ec6 --- a/synthDC/extractSummary.py +++ b/synthDC/extractSummary.py @@ -1,8 +1,10 @@ +#!/usr/bin/python3 +# Shreya Sanghai (ssanghai@hmc.edu) 2/28/2022 import glob import re import csv -field_names = [ 'Name', 'Critical Path Length', 'Cell Area'] +field_names = [ 'Name', 'Critical Path Length', 'Cell Area', 'Synth Time'] data = [] for name in glob.glob("/home/ssanghai/riscv-wally/synthDC/runs/*/reports/wallypipelinedcore_qor.rep"): f = open(name, 'r') @@ -13,7 +15,9 @@ for name in glob.glob("/home/ssanghai/riscv-wally/synthDC/runs/*/reports/wallypi pathLen = re.search("Length: *(.*?)\\n", line).group(1) if "Cell Area" in line: area = re.search("Area: *(.*?)\\n", line).group(1) - data += [{'Name' : trimName, 'Critical Path Length': pathLen, 'Cell Area' : area}] + if "Overall Compile Time" in line: + time = re.search("Time: *(.*?)\\n", line).group(1) + data += [{'Name' : trimName, 'Critical Path Length': pathLen, 'Cell Area' : area, 'Synth Time' :time}] with open('Summary.csv', 'w') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=field_names)