mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			145 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/bash
 | 
						|
tcpPort=1238
 | 
						|
imageDir=$RISCV/buildroot/output/images
 | 
						|
tvDir=$RISCV/linux-testvectors
 | 
						|
recordFile="$tvDir/all.qemu"
 | 
						|
traceFile="$tvDir/all.txt"
 | 
						|
 | 
						|
# 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
 | 
						|
 | 
						|
checkPtDir="$tvDir/checkpoint$instrs"
 | 
						|
outTraceFile="$checkPtDir/all.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"
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
    # Identify instruction in trace
 | 
						|
    instr=$(sed "${instrs}q;d" "$traceFile")
 | 
						|
    echo "Found ${instrs}th instr: ${instr}"
 | 
						|
    pc=$(echo $instr | cut -d " " -f1)
 | 
						|
    asm=$(echo $instr | cut -d " " -f2)
 | 
						|
    occurences=$(($(head -$instrs "$traceFile" | grep -c "${pc} ${asm}")-1))
 | 
						|
    echo "It occurs ${occurences} times before the ${instrs}th instr." 
 | 
						|
 | 
						|
    # Create GDB script because GDB is terrible at handling arguments / variables
 | 
						|
    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 \
 | 
						|
    -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 \
 | 
						|
    -gdb tcp::$tcpPort -S \
 | 
						|
     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"
 | 
						|
    echo "Copying over a truncated trace"
 | 
						|
    tail -n+$instrs $traceFile > $outTraceFile
 | 
						|
 | 
						|
    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
 | 
						|
 |