| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- #!/bin/env python3
- import os
- import sys
- import argparse
- from prettytable import *
- import json
- HPM_EVENTS= [
- ["Reserved", "Cycle count", "Retired instruction count", "Integer load instruction (includes LR)",
- "Integer store instruction (includes SC)", "Atomic memory operation (do not include LR and SC)",
- "System instruction", "Integer computational instruction(excluding multiplication/division/remainder)",
- "Conditional branch", "Taken conditional branch", "JAL instruction", "JALR instruction", "Return instruction",
- "Control transfer instruction (CBR+JAL+JALR)", "Fence instruction(Not include fence.i)", "Integer multiplication instruction",
- "Integer division/remainder instruction", "Floating-point load instruction", "Floating-point store instruction",
- "Floating-point addition/subtraction", "Floating-point multiplication",
- "Floating-point fused multiply-add (FMADD, FMSUB, FNMSUB, FNMADD)", "Floating-point division or square-root",
- "Other floating-point instruction", "Conditional branch prediction fail", "JALR prediction fail",
- "POP predication fail", "FENCEI instruction", "SFENCE instruction", "ECALL instruction",
- "EXCEPTION instruction", "INTERRUPT instruction"],
- ["Reserved", "Icache miss", "Dcache miss", "ITLB miss", "DTLB miss", "Main TLB miss",
- "Reserved", "Reserved", "L2-Cache access count", "L2-Cache miss count",
- "Memory bus request count", "IFU stall cycle count", "EXU stall cycle count", "Timer count"],
- ["Reserved", "Reserved", "Branch instruction commit count", "Branch predict fail count"],
- ["Dcache read count", "Dcache read miss count", "Dcache write count", "Dcache write miss count",
- "Dcache prefetch count", "Dcache prefetch miss count", "Icache read count", "Reserved",
- "Icache prefetch count", "Icache prefetch miss count", "L2-Cache read hit count",
- "L2-Cache read miss count", "L2-Cache write hit count", "L2-Cache write miss count",
- "L2-Cache prefetch hit count", "L2-Cache prefetch miss count", "DTLB read count",
- "DTLB read miss count", "DTLB write count", "DTLB write miss count", "ITLB read count",
- "Reserved", "BTB read count", "BTB read miss count", "BTB write count", "BTB write miss count"]
- ]
- HPM_MEVENT_ENABLE = 0x8
- HPM_SEVENT_ENABLE = 0x4
- HPM_UEVENT_ENABLE = 0x1
- def get_hpm_evmode(ena):
- evmode = ""
- if ena & HPM_MEVENT_ENABLE:
- evmode += "M"
- if ena & HPM_SEVENT_ENABLE:
- evmode += "S"
- if ena & HPM_UEVENT_ENABLE:
- evmode += "U"
- return evmode
- def get_hpm_event(sel, idx):
- if sel >= len(HPM_EVENTS):
- return "INVAILD"
- if idx >= len(HPM_EVENTS[sel]):
- return "INVAILD"
- return HPM_EVENTS[sel][idx]
- def parse_hpm(logfile):
- if os.path.isfile(logfile) == False:
- return dict()
- hpmrecords = dict()
- with open(logfile, "r") as lf:
- for line in lf.readlines():
- if line.startswith("HPM"):
- hpmkey, proc, hpmcount = line.split(",")
- hpmkey = hpmkey.strip()
- proc = proc.strip()
- hpmcount = hpmcount.strip()
- if proc not in hpmrecords:
- hpmrecords[proc] = dict()
- hpmrecords[proc][hpmkey] = hpmcount
- return hpmrecords
- def analyze_hpm(records):
- x = PrettyTable()
- x.set_style(MARKDOWN)
- x.field_names = ["Process", "HPM", "Mode", "Event", "Counts"]
- parsed_hpm = dict()
- csv_hpm = [x.field_names]
- for proc in records:
- parsed_hpm[proc] = dict()
- for hpmkey in records[proc]:
- hpmcounter, hpmevent = hpmkey.split(":")
- hpmevent = int(hpmevent, 16)
- # event_sel: 3:0
- event_sel = hpmevent & 0xF
- # event_idx: 8:4
- event_idx = (hpmevent >> 4) & 0x1F
- # event_ena: m/rsv/s/u 31:28
- event_ena = (hpmevent >> 28) & 0xF
- event_name = get_hpm_event(event_sel, event_idx)
- event_mode = get_hpm_evmode(event_ena)
- event_count = int(records[proc][hpmkey])
- x.add_row([proc, hpmcounter, event_mode, event_name, event_count])
- csv_hpm.append([proc, hpmcounter, event_mode, event_name, event_count])
- if hpmcounter not in parsed_hpm[proc]:
- parsed_hpm[proc][hpmcounter] = list()
- parsed_hpm[proc][hpmcounter].append((event_mode, event_name, event_count))
- return parsed_hpm, csv_hpm, x
- def save_csv(csvlist, csvfile):
- with open(csvfile, "w") as cf:
- for csvline in csvlist:
- line = ",".join(map(str, csvline))
- cf.write(line + "\n")
- pass
- if __name__ == '__main__':
- parser = argparse.ArgumentParser(description="Nuclei SDK HPM Log Parsing")
- parser.add_argument('--logfile', required=True, help="log file of hpm running")
- args = parser.parse_args()
- hpmrecords = parse_hpm(args.logfile)
- if len(hpmrecords) == 0:
- print("None records found in %s!" % (args.logfile))
- sys.exit(1)
- parsedhpm, csv_hpm, table = analyze_hpm(hpmrecords)
- print(table)
- hpmresult = {"records": hpmrecords, "parsed": parsedhpm}
- hpmrstfile = args.logfile + ".json"
- with open(hpmrstfile, "w") as cf:
- json.dump(hpmresult, cf, indent=4)
- print("\nParsed HPM event saved into %s" %(hpmrstfile))
- hpmcsvfile = args.logfile + ".csv"
- save_csv(csv_hpm, hpmcsvfile)
- print("Save HPM CSV to %s" % (hpmcsvfile))
- sys.exit(0)
|