forked from Github_Repos/cvw
		
	
		
			
				
	
	
		
			146 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #! /usr/bin/python3
 | |
| import fileinput, sys
 | |
| 
 | |
| parseState = "idle"
 | |
| beginPageFault = 0
 | |
| inPageFault = 0
 | |
| endPageFault = 0
 | |
| CSRs = {}
 | |
| pageFaultCSRs = {}
 | |
| regs = {}
 | |
| pageFaultRegs = {}
 | |
| instrs = {}
 | |
| instrCount = 0
 | |
| returnAdr = 0
 | |
| sys.stderr.write("reminder: parse_qemu.py takes input from stdin\n")
 | |
| 
 | |
| def printPC(l):
 | |
|     global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, instrCount
 | |
|     if not inPageFault:
 | |
|         inst = l.split()
 | |
|         if len(inst) > 3:
 | |
|             print(f'=> {inst[1]}:\t{inst[2]} {inst[3]}')
 | |
|         else:
 | |
|             print(f'=> {inst[1]}:\t{inst[2]}')
 | |
|         print(f'{inst[0]} 0x{inst[1]}')
 | |
|         instrCount += 1
 | |
|         if ((instrCount % 100000) == 0):
 | |
|             sys.stderr.write("QEMU parser reached "+str(instrCount)+" instrs\n")
 | |
| 
 | |
| def printCSRs():
 | |
|     global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs
 | |
|     global interrupt_line
 | |
|     if not inPageFault:
 | |
|         for (csr,val) in CSRs.items():
 | |
|             print('{}{}{:#x}  {}'.format(csr, ' '*(15-len(csr)), val, val))
 | |
|         print('-----') # end of current instruction
 | |
|         if len(interrupt_line)>0: # squish interrupts in between instructions
 | |
|             print(interrupt_line)
 | |
|             interrupt_line=""
 | |
| 
 | |
| def parseCSRs(l):
 | |
|     global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs
 | |
|     if l.strip() and (not l.startswith("Disassembler")) and (not l.startswith("Please")):
 | |
|         # If we've hit the register file
 | |
|         if l.startswith(' x0/zero'): 
 | |
|             parseState = "regFile"
 | |
|             if not inPageFault:
 | |
|                 instr = instrs[CSRs["pc"]]
 | |
|                 printPC(instr)
 | |
|             parseRegs(l)
 | |
|         # If we've hit a CSR
 | |
|         else:
 | |
|             csr = l.split()[0]
 | |
|             val = int(l.split()[1],16)
 | |
|             # Commented out this conditional because the pageFault instrs don't corrupt CSRs
 | |
|             #if inPageFault:
 | |
|                 # Not sure if these CSRs should be updated or not during page fault.
 | |
|                 #if l.startswith("mstatus") or l.startswith("mepc") or l.startswith("mcause") or l.startswith("mtval") or l.startswith("sepc") or l.startswith("scause") or l.startswith("stval"):
 | |
|                     # We do update some CSRs
 | |
|                 #    CSRs[csr] = val
 | |
|                 #else:
 | |
|                     # Others we preserve until changed later
 | |
|                 #    pageFaultCSRs[csr] = val
 | |
|             #elif pageFaultCSRs and (csr in pageFaultCSRs):
 | |
|             #    if (val != pageFaultCSRs[csr]):
 | |
|             #        del pageFaultCSRs[csr]
 | |
|             #        CSRs[csr] = val
 | |
|             #else:
 | |
|             #    CSRs[csr] = val
 | |
|             #
 | |
|             # However SEPC and STVAL do get corrupted upon exiting
 | |
|             if endPageFault and ((csr == 'sepc') or (csr == 'stval')):
 | |
|                 CSRs[csr] = returnAdr
 | |
|                 pageFaultCSRs[csr] = val
 | |
|             elif pageFaultCSRs and (csr in pageFaultCSRs):
 | |
|                 if (val != pageFaultCSRs[csr]):
 | |
|                     del pageFaultCSRs[csr]
 | |
|                     CSRs[csr] = val
 | |
|             else:
 | |
|                 CSRs[csr] = val
 | |
| 
 | |
| def parseRegs(l):
 | |
|     global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, pageFaultRegs
 | |
|     if "pc" in l:
 | |
|         printCSRs()
 | |
|         # New non-disassembled instruction
 | |
|         parseState = "CSRs"
 | |
|         parseCSRs(l)
 | |
|     elif l.startswith('--------'):
 | |
|         # End of disassembled instruction
 | |
|         printCSRs()
 | |
|         parseState = "idle"
 | |
|     else:
 | |
|         s = l.split()
 | |
|         for i in range(0,len(s),2):
 | |
|             if '/' in s[i]:
 | |
|                 reg = s[i].split('/')[1]
 | |
|                 val = int(s[i+1], 16)
 | |
|                 if inPageFault:
 | |
|                     pageFaultRegs[reg] = val
 | |
|                 else:
 | |
|                     if pageFaultRegs and (reg in pageFaultRegs):
 | |
|                         if (val != pageFaultRegs[reg]):
 | |
|                             del pageFaultRegs[reg]
 | |
|                             regs[reg] = val
 | |
|                     else:
 | |
|                         regs[reg] = val
 | |
|                     val = regs[reg]
 | |
|                     print('{}{}{:#x}  {}'.format(reg, ' '*(15-len(reg)), val, val))
 | |
|             else:
 | |
|                 sys.stderr.write("Whoops. Expected a list of reg file regs; got:\n"+l)
 | |
| 
 | |
| #############
 | |
| # Main Code #
 | |
| #############
 | |
| interrupt_line=""
 | |
| for l in fileinput.input():
 | |
|     #sys.stderr.write(l)
 | |
|     if l.startswith('riscv_cpu_do_interrupt'):
 | |
|         sys.stderr.write(l)
 | |
|         interrupt_line = l.strip('\n')
 | |
|     elif l.startswith('qemu-system-riscv64: QEMU: Terminated via GDBstub'):
 | |
|         break
 | |
|     elif l.startswith('IN:'):
 | |
|         # New disassembled instr
 | |
|         parseState = "instr"
 | |
|     elif (parseState == "instr") and l.startswith('0x'):
 | |
|         # New instruction
 | |
|         if "out of bounds" in l:
 | |
|             sys.stderr.write("Detected QEMU page fault error\n")
 | |
|             beginPageFault = not inPageFault
 | |
|             if beginPageFault:
 | |
|                 returnAdr = int(l.split()[0][2:-1], 16)
 | |
|                 sys.stderr.write('Saving SEPC of '+hex(returnAdr)+'\n')
 | |
|             inPageFault = 1
 | |
|         else: 
 | |
|             endPageFault = inPageFault
 | |
|             inPageFault = 0
 | |
|             adr = int(l.split()[0][2:-1], 16)
 | |
|             instrs[adr] = l
 | |
|         parseState = "CSRs"
 | |
|     elif parseState == "CSRs":
 | |
|         parseCSRs(l)
 | |
|     elif parseState == "regFile":
 | |
|         parseRegs(l)
 |