# Copyright 2024 Thales Silicon Security # # Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 # You may obtain a copy of the License at https://solderpad.org/licenses/ # # Original Author: Côme ALLART - Thales import re import sys re_csrr_minstret = re.compile(r"^csrr\s+\w+,\s*minstret$") re_full = re.compile( r"([a-z]+)\s+0:\s*0x00000000([0-9a-f]+)\s*\(([0-9a-fx]+)\)\s*(\S*)@\s*([0-9]+)\s*(.*)" ) class Trace: def __init__(self, addr, cycle, mnemo, flags): self.addr = addr self.cycle = cycle self.mnemo = mnemo self.flags = flags self.delta = None def report(self): """True if the instruction is a loading instruction""" return f"+{self.delta} {self.flags} 0x{self.addr}: {self.mnemo}" def print_data(name, value): "Prints 'name = data' with alignment of the '='" spaces = ' ' * (24 - len(name)) print(f"{name}{spaces} = {value}") def read_traces(input_file): "Collect stage traces from file" l = [] def filter_add(trace): if not hasattr(filter_add, "accepting"): filter_add.accepting = False if re_csrr_minstret.search(trace.mnemo): filter_add.accepting = not filter_add.accepting return if filter_add.accepting: l.append(trace) with open(input_file, "r", encoding="utf8") as f: for line in [l.strip() for l in f]: found = re_full.search(line) if found: addr = found.group(2) flags = found.group(4) cycle = int(found.group(5)) mnemo = found.group(6) filter_add(Trace(addr, cycle, mnemo, flags)) #l.append(Trace(addr, cycle, mnemo, flags)) return l def write_traces(outfile, traces): "Write all instructions to output file" print("output file:", outfile) with open(outfile, "w", encoding="utf8") as f: for trace in traces: f.write(trace.report() + "\n") def main(input_file: str): "Main function" traces = read_traces(input_file) cycle = traces[0].cycle cycle_number = traces[-1].cycle - cycle + 1 for trace in traces: trace.delta = trace.cycle - cycle cycle = trace.cycle print_data("cycle number", cycle_number) print_data("Coremark/MHz", 1000000 / cycle_number) print_data("instruction number", len(traces)) print_data("IPC", len(traces) / cycle_number) write_traces("traceout.log", traces) if __name__ == "__main__": main(sys.argv[1])