mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			214 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #! /usr/bin/python3
 | |
| import sys, fileinput, re
 | |
| 
 | |
| # Ross Thompson
 | |
| # July 27, 2021
 | |
| # Rewrite of the linux trace parser.
 | |
| 
 | |
| 
 | |
| InstrStartDelim = '=>'
 | |
| InstrEndDelim = '-----'
 | |
| 
 | |
| #InputFile = 'noparse.txt'
 | |
| #InputFile = sys.stdin
 | |
| #InputFile = 'temp.txt'
 | |
| #OutputFile = 'parsedAll.txt'
 | |
| 
 | |
| HUMAN_READABLE = False
 | |
| 
 | |
| def toDict(lst):
 | |
|     'Converts the list of register values to a dictionary'
 | |
|     dct= {}
 | |
|     for item in lst:
 | |
|         regTup = item.split()
 | |
|         dct[regTup[0]] = int(regTup[2], 10)
 | |
|     del dct['pc']
 | |
|     return dct
 | |
| 
 | |
| def whichClass(text, Regs):
 | |
|     'Which instruction class?'
 | |
|     #print(text, Regs)
 | |
|     if text[0:2] == 'ld' or text[0:2] == 'lw' or text[0:2] == 'lh' or text[0:2] == 'lb':
 | |
|         return ('load', WhatAddr(text, Regs), None, WhatMemDestSource(text))
 | |
|     elif text[0:2] == 'sd' or text[0:2] == 'sw' or text[0:2] == 'sh' or text[0:2] == 'sb':
 | |
|         return ('store', WhatAddr(text, Regs), WhatMemDestSource(text), None)
 | |
|     elif text[0:3] == 'amo':
 | |
|         return ('amo', WhatAddrAMO(text, Regs), WhatMemDestSource(text), WhatMemDestSource(text))
 | |
|     elif text[0:2] == 'lr':
 | |
|         return ('lr', WhatAddrLR(text, Regs), None, WhatMemDestSource(text))
 | |
|     elif text[0:2] == 'sc':
 | |
|         return ('sc', WhatAddrSC(text, Regs), WhatMemDestSource(text), None)
 | |
|     else:
 | |
|         return ('other', None, None, None)
 | |
| 
 | |
| def whatChanged(dct0, dct1):
 | |
|     'Compares two dictionaries of instrution registers and indicates which registers changed'
 | |
|     dct = {}
 | |
|     for key in dct0:
 | |
|         if (dct1[key] != dct0[key]):
 | |
|             dct[key] = dct1[key]
 | |
|     return dct
 | |
| 
 | |
| def WhatMemDestSource(text):
 | |
|     ''''What is the destination register. Used to compute where the read data is 
 | |
|     on a load or the write data on a store.'''
 | |
|     return text.split()[1].split(',')[0]
 | |
| 
 | |
| def WhatAddr(text, Regs):
 | |
|     'What is the data memory address?'
 | |
|     Imm = text.split(',')[1]
 | |
|     (Imm, Src) = Imm.split('(')
 | |
|     Imm = int(Imm.strip(), 10)
 | |
|     Src = Src.strip(')').strip()
 | |
|     RegVal = Regs[Src]
 | |
|     return Imm + RegVal
 | |
| 
 | |
| def WhatAddrAMO(text, Regs):
 | |
|     'What is the data memory address?'
 | |
|     Src = text.split('(')[1]
 | |
|     Src = Src.strip(')').strip()
 | |
|     return Regs[Src]
 | |
| 
 | |
| def WhatAddrLR(text, Regs):
 | |
|     'What is the data memory address?'
 | |
|     Src = text.split('(')[1]
 | |
|     Src = Src.strip(')').strip()
 | |
|     return Regs[Src]
 | |
| 
 | |
| def WhatAddrSC(text, Regs):
 | |
|     'What is the data memory address?'
 | |
|     Src = text.split('(')[1]
 | |
|     Src = Src.strip(')').strip()
 | |
|     return Regs[Src]
 | |
| 
 | |
| def PrintInstr(instr, fp):
 | |
|     if instr[2] == None:
 | |
|         return
 | |
|     ChangedRegisters = instr[4]
 | |
|     GPR = ''
 | |
|     CSR = []
 | |
|     for key in ChangedRegisters:
 | |
|         # filter out csr which are not checked.
 | |
|         if(key in RegNumber):
 | |
|             if(RegNumber[key] < 32):
 | |
|                 # GPR
 | |
|                 if(HUMAN_READABLE):
 | |
|                     GPR = '{:-2d} {:016x}'.format(RegNumber[key], ChangedRegisters[key])
 | |
|                 else:
 | |
|                     GPR = '{:d} {:x}'.format(RegNumber[key], ChangedRegisters[key])
 | |
|             else:
 | |
|                 if(HUMAN_READABLE):
 | |
|                     CSR.extend([key, '{:016x}'.format(ChangedRegisters[key])])
 | |
|                 else:
 | |
|                     CSR.extend([key, '{:x}'.format(ChangedRegisters[key])])                
 | |
| 
 | |
|     CSRStr = ' '.join(CSR)
 | |
| 
 | |
|     #print(instr)
 | |
| 
 | |
|     if (HUMAN_READABLE == True):
 | |
|         fp.write('{:016x} {:08x} {:25s}'.format(instr[0], instr[1], instr[2]))
 | |
|         if(len(GPR) != 0):
 | |
|             fp.write(' GPR {}'.format(GPR))
 | |
|         if(instr[3] == 'load' or instr[3] == 'lr'):
 | |
|             fp.write(' MemR {:016x} {:016x} {:016x}'.format(instr[5], 0, instr[7]))
 | |
|         if(instr[3] == 'store'):
 | |
|             fp.write('\t\t\t    MemW {:016x} {:016x} {:016x}'.format(instr[5], instr[6], 0))
 | |
| 
 | |
|         if(len(CSR) != 0):
 | |
|             fp.write(' CSR {}'.format(CSRStr))
 | |
|     else:
 | |
|         fp.write('{:x} {:x} {:s}'.format(instr[0], instr[1], instr[2].replace(' ', '_')))
 | |
|         if(len(GPR) != 0):
 | |
|             fp.write(' GPR {}'.format(GPR))
 | |
|         if(instr[3] == 'load' or instr[3] == 'lr'):
 | |
|             fp.write(' MemR {:x} {:x} {:x}'.format(instr[5], 0, instr[7]))
 | |
|         if(instr[3] == 'store'):
 | |
|             fp.write(' MemW {:x} {:x} {:x}'.format(instr[5], instr[6], 0))
 | |
| 
 | |
|         if(len(CSR) != 0):
 | |
|             fp.write(' CSR {}'.format(CSRStr))
 | |
|     fp.write('\n')
 | |
| 
 | |
| # reg number
 | |
| RegNumber = {'zero': 0, 'ra': 1, 'sp': 2, 'gp': 3, 'tp': 4, 't0': 5, 't1': 6, 't2': 7, 's0': 8, 's1': 9, 'a0': 10, 'a1': 11, 'a2': 12, 'a3': 13, 'a4': 14, 'a5': 15, 'a6': 16, 'a7': 17, 's2': 18, 's3': 19, 's4': 20, 's5': 21, 's6': 22, 's7': 23, 's8': 24, 's9': 25, 's10': 26, 's11': 27, 't3': 28, 't4': 29, 't5': 30, 't6': 31, 'mhartid': 32, 'mstatus': 33, 'mip': 34, 'mie': 35, 'mideleg': 36, 'medeleg': 37, 'mtvec': 38, 'stvec': 39, 'mepc': 40, 'sepc': 41, 'mcause': 42, 'scause': 43, 'mtval': 44, 'stval': 45}
 | |
| # initial state
 | |
| CurrentInstr = ['0', '0', None, 'other', {'zero': 0, 'ra': 0, 'sp': 0, 'gp': 0, 'tp': 0, 't0': 0, 't1': 0, 't2': 0, 's0': 0, 's1': 0, 'a0': 0, 'a1': 0, 'a2': 0, 'a3': 0, 'a4': 0, 'a5': 0, 'a6': 0, 'a7': 0, 's2': 0, 's3': 0, 's4': 0, 's5': 0, 's6': 0, 's7': 0, 's8': 0, 's9': 0, 's10': 0, 's11': 0, 't3': 0, 't4': 0, 't5': 0, 't6': 0, 'mhartid': 0, 'mstatus': 0, 'mip': 0, 'mie': 0, 'mideleg': 0, 'medeleg': 0, 'mtvec': 0, 'stvec': 0, 'mepc': 0, 'sepc': 0, 'mcause': 0, 'scause': 0, 'mtval': 0, 'stval': 0}, {}, None, None, None]
 | |
| 
 | |
| #with open (InputFile, 'r') as InputFileFP:
 | |
| #lines = InputFileFP.readlines()
 | |
| lineNum = 0
 | |
| StartLine = 0
 | |
| EndLine = 0
 | |
| numInstrs = 0
 | |
| #instructions = []
 | |
| MemAdr = 0
 | |
| lines = []
 | |
| for line in fileinput.input('-'):
 | |
|     lines.insert(lineNum, line)
 | |
|     if InstrStartDelim in line:
 | |
|         lineNum = 0
 | |
|         StartLine = lineNum
 | |
|     elif InstrEndDelim in line:
 | |
|         EndLine = lineNum
 | |
|         (InstrBits, text) = lines[StartLine].split(':')
 | |
|         InstrBits = int(InstrBits.strip('=> '), 16)
 | |
|         text = text.strip()
 | |
|         PC = int(lines[StartLine+1].split(':')[0][2:], 16)
 | |
|         Regs = toDict(lines[StartLine+2:EndLine])
 | |
|         (Class, Addr, WriteReg, ReadReg) = whichClass(text, Regs)
 | |
|         #print("CWR", Class, WriteReg, ReadReg)
 | |
|         PreviousInstr = CurrentInstr
 | |
| 
 | |
|         Changed = whatChanged(PreviousInstr[4], Regs)
 | |
| 
 | |
|         if (ReadReg !=None): ReadData = ReadReg
 | |
|         else: ReadData = None
 | |
| 
 | |
|         if (WriteReg !=None): WriteData = WriteReg
 | |
|         else: WriteData = None
 | |
| 
 | |
|         CurrentInstr = [PC, InstrBits, text, Class, Regs, Changed, Addr, WriteData, ReadData]
 | |
| 
 | |
|         #print(CurrentInstr[0:4], PreviousInstr[5], CurrentInstr[6:7], PreviousInstr[8])
 | |
| 
 | |
|         # pc, instrbits, text and class come from the last line.
 | |
|         MoveInstrToRegWriteLst = PreviousInstr[0:4]
 | |
|         # updated registers come from the current line.
 | |
|         MoveInstrToRegWriteLst.append(CurrentInstr[5])   # destination regs
 | |
|         # memory address if present comes from the last line.
 | |
|         MoveInstrToRegWriteLst.append(PreviousInstr[6])  # MemAdrM
 | |
|         # write data from the previous line
 | |
|         #MoveInstrToRegWriteLst.append(PreviousInstr[7])   # WriteDataM
 | |
| 
 | |
|         if (PreviousInstr[7] != None):
 | |
|             MoveInstrToRegWriteLst.append(Regs[PreviousInstr[7]])   # WriteDataM
 | |
|         else:
 | |
|             MoveInstrToRegWriteLst.append(None)
 | |
| 
 | |
|         # read data from the current line
 | |
|         #MoveInstrToRegWriteLst.append(PreviousInstr[8])   # ReadDataM
 | |
|         if (PreviousInstr[8] != None):
 | |
|             MoveInstrToRegWriteLst.append(Regs[PreviousInstr[8]])   # ReadDataM
 | |
|         else:
 | |
|             MoveInstrToRegWriteLst.append(None)
 | |
| 
 | |
|         lines.clear()
 | |
|         #instructions.append(MoveInstrToRegWriteLst)
 | |
|         PrintInstr(MoveInstrToRegWriteLst, sys.stdout)
 | |
|         numInstrs +=1
 | |
|         if (numInstrs % 1e4 == 0):
 | |
|             sys.stderr.write('Trace parser reached '+str(numInstrs/1.0e6)+' million instrs.\n')
 | |
|             sys.stderr.flush()
 | |
|     lineNum += 1
 | |
| 
 | |
| 
 | |
| #for instruction in instructions[1::]:
 | |
| 
 | |
| 
 | |
| #with open(OutputFile, 'w') as OutputFileFP:
 | |
| #    print('opened file')
 | |
| 
 | |
| 
 | |
| 
 |