From db0d125651bc40e2fa924361aabc32f54dd43cf7 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Thu, 18 Jul 2024 14:21:24 +0200 Subject: [PATCH] adds Debug tools --- .gitignore | 1 - Debug/.gitignore | 5 + Debug/create_reg_traces.py | 154 ++++++++++++++++++++ {scripts => Debug}/makeJitOutputReadable.py | 0 Debug/offsets.txt | 43 ++++++ Debug/simplify_sail_trace.py | 29 ++++ Debug/simplify_tgc_trace.py | 26 ++++ 7 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 Debug/.gitignore create mode 100644 Debug/create_reg_traces.py rename {scripts => Debug}/makeJitOutputReadable.py (100%) create mode 100644 Debug/offsets.txt create mode 100644 Debug/simplify_sail_trace.py create mode 100644 Debug/simplify_tgc_trace.py diff --git a/.gitignore b/.gitignore index 614430a..577e7ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /build/ -/Debug/ .settings /.venv* /Debug-PA/ diff --git a/Debug/.gitignore b/Debug/.gitignore new file mode 100644 index 0000000..25f9233 --- /dev/null +++ b/Debug/.gitignore @@ -0,0 +1,5 @@ +*.log +*.dis +*.asm +*.ll +*tcc_* diff --git a/Debug/create_reg_traces.py b/Debug/create_reg_traces.py new file mode 100644 index 0000000..58d9351 --- /dev/null +++ b/Debug/create_reg_traces.py @@ -0,0 +1,154 @@ +import argparse +import os +import shutil +import subprocess +from pathlib import Path + + +def validate_elf_file(filepath: str) -> str: + if not os.path.isfile(filepath): + raise argparse.ArgumentTypeError(f"{filepath} is not a valid file.") + + # Use the 'file' command to check if it's an ELF file + result = subprocess.run( + ["file", filepath], capture_output=True, text=True, check=False + ) + if "ELF" not in result.stdout: + raise argparse.ArgumentTypeError(f"{filepath} is not a valid ELF file.") + + return filepath + + +def run_test_and_move_output(elf_file: str, backend: str, isa: str = "tgc5c") -> None: + # Call 'test' with the specified backend mode + os.chdir(Path(__file__).parent.parent) + sim_path = "build/Debug/dbt-rise-tgc/tgc-sim" + run_command = [ + sim_path, + "-f", + elf_file, + "--backend", + backend, + "--isa", + isa, + "-p", + "build/Debug/dbt-rise-plugins/pctrace/pctrace.so=dbt-rise-tgc/contrib/instr/TGC5C_instr.yaml", + "-i", + "10000", + ] + print(f"Running: \n{' '.join(run_command)}") + try: + subprocess.run(run_command, check=False, timeout=10) + except subprocess.TimeoutExpired: + print("Execution timed out") + + # Move the output.trc file + if os.path.exists("output.trc"): + shutil.move("output.trc", f"Debug/{backend}.trc") + else: + print( + f"output.trc does not exist after running with backend {backend}, so it cannot be renamed." + ) + + +def create_shortened_diff_files(backend: str) -> None: + file1_path = "Debug/interp.trc" + file2_path = f"Debug/{backend}.trc" + + def validate_file(filepath: str) -> str: + if not os.path.isfile(filepath): + raise ValueError(f"{filepath} is not a valid file.") + return filepath + + file1_path = validate_file(file1_path) + file2_path = validate_file(file2_path) + + with open(file1_path, "r", encoding="utf8") as file1, open( + file2_path, "r", encoding="utf8" + ) as file2: + lines1 = file1.readlines() + lines2 = file2.readlines() + + diff_index = -1 + for index, (line1, line2) in enumerate(zip(lines1, lines2)): + if line1 != line2: + diff_index = index + break + + if diff_index == -1: + print("The files are identical.") + return + + start_index = max(0, diff_index - 5) + end_index = min(len(lines1), diff_index + 6) + + shortened_lines1 = lines1[start_index:end_index] + shortened_lines2 = lines2[start_index:end_index] + + with open("Debug/short_interp.trc", "w", encoding="utf8") as short_file1: + short_file1.writelines(shortened_lines1) + + with open(f"Debug/short_{backend}.trc", "w", encoding="utf8") as short_file2: + short_file2.writelines(shortened_lines2) + + +def create_disassembly(elf_file_path: str) -> None: + def validate_file(filepath: str) -> str: + if not os.path.isfile(filepath): + raise ValueError(f"{filepath} is not a valid file.") + return filepath + + elf_file_path = validate_file(elf_file_path) + + output_file_path = "Debug/dut.dis" + with open(output_file_path, "w", encoding="utf8") as output_file: + subprocess.run( + [ + "riscv64-unknown-elf-objdump", + "-d", + "-Mnumeric", + "-Mno-aliases", + elf_file_path, + ], + stdout=output_file, + check=True, + ) + + +def main(args: argparse.Namespace) -> None: + elf_file = args.elf_file + backend = args.backend + isa = args.isa + + # Set environment variable + os.environ["REGDUMP"] = "True" + + # Run the tests and move the output files + run_test_and_move_output(elf_file, "interp", isa) + run_test_and_move_output(elf_file, backend, isa) + create_shortened_diff_files(backend) + create_disassembly(elf_file) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Process an ELF file with a specified backend. Generates register traces for interp and the specified backend" + ) + parser.add_argument( + "elf_file", type=validate_elf_file, help="The ELF file to be processed." + ) + parser.add_argument( + "--backend", + type=str, + default="amsjit", + help="The backend to be used. Default is amsjit.", + required=False, + ) + parser.add_argument( + "--isa", + type=str, + default="tgc5c", + help="The isa to be used. Default 'tgc5c'", + required=False, + ) + main(args=parser.parse_args()) diff --git a/scripts/makeJitOutputReadable.py b/Debug/makeJitOutputReadable.py similarity index 100% rename from scripts/makeJitOutputReadable.py rename to Debug/makeJitOutputReadable.py diff --git a/Debug/offsets.txt b/Debug/offsets.txt new file mode 100644 index 0000000..89b10f3 --- /dev/null +++ b/Debug/offsets.txt @@ -0,0 +1,43 @@ +X0 (zero) : 0 (0x00) +X1 (ra) : 4 (0x04) +X2 (sp) : 8 (0x08) +X3 (gp) : 12 (0x0c) +X4 (tp) : 16 (0x10) +X5 (t0) : 20 (0x14) +X6 (t1) : 24 (0x18) +X7 (t2) : 28 (0x1c) +X8 (s0/fp): 32 (0x20) +X9 (s1) : 36 (0x24) +X10 (a0) : 40 (0x28) +X11 (a1) : 44 (0x2c) +X12 (a2) : 48 (0x30) +X13 (a3) : 52 (0x34) +X14 (a4) : 56 (0x38) +X15 (a5) : 60 (0x3c) +X16 (a6) : 64 (0x40) +X17 (a7) : 68 (0x44) +X18 (s2) : 72 (0x48) +X19 (s3) : 76 (0x4c) +X20 (s4) : 80 (0x50) +X21 (s5) : 84 (0x54) +X22 (s6) : 88 (0x58) +X23 (s7) : 92 (0x5c) +X24 (s8) : 96 (0x60) +X25 (s9) : 100 (0x64) +X26 (s10) : 104 (0x68) +X27 (s11) : 108 (0x6c) +X28 (t3) : 112 (0x70) +X29 (t4) : 116 (0x74) +X30 (t5) : 120 (0x78) +X31 (t6) : 124 (0x7c) +PC : 128 (0x80) +NEXT_PC : 132 (0x84) +PRIV : 136 (0x88) +DPC : 137 (0x89) +trap_state : 141 (0x8d) +pending_trap : 145 (0x91) +icount : 149 (0x95) +cycle : 157 (0x9d) +instret : 165 (0xa5) +instruction : 173 (0xad) +last_branch : 177 (0xb1) diff --git a/Debug/simplify_sail_trace.py b/Debug/simplify_sail_trace.py new file mode 100644 index 0000000..384ae9c --- /dev/null +++ b/Debug/simplify_sail_trace.py @@ -0,0 +1,29 @@ +import argparse +import re + + +def simplify_trace(input_file, output_file): + with open(input_file, "r") as infile, open(output_file, "w") as outfile: + for line in infile: + # Enhanced regex to match the instruction number, mode, and PC + match = re.search(r"\[\d+\] \[[MI]\]: (0x[0-9A-Fa-f]+)", line) + if match: + pc = match.group(1).lower() + outfile.write(f"{pc}\n") + + +def main(): + parser = argparse.ArgumentParser( + description="Simplify a trace from an instruction set simulator." + ) + parser.add_argument("input_file", type=str, help="The input trace file") + parser.add_argument( + "output_file", type=str, help="The output file for the simplified trace" + ) + + args = parser.parse_args() + simplify_trace(args.input_file, args.output_file) + + +if __name__ == "__main__": + main() diff --git a/Debug/simplify_tgc_trace.py b/Debug/simplify_tgc_trace.py new file mode 100644 index 0000000..004c74c --- /dev/null +++ b/Debug/simplify_tgc_trace.py @@ -0,0 +1,26 @@ +import argparse + + +def simplify_trace(input_file, output_file): + with open(input_file, "r") as infile, open(output_file, "w") as outfile: + for line in infile: + # Split the line by the first comma and take the PC part + pc = line.split(",")[0].strip().lower() + outfile.write(f"{pc}\n") + + +def main(): + parser = argparse.ArgumentParser( + description="Simplify traces from instruction set simulators." + ) + parser.add_argument("input_file", type=str, help="The input trace file") + parser.add_argument( + "output_file", type=str, help="The output file for the simplified trace" + ) + + args = parser.parse_args() + simplify_trace(args.input_file, args.output_file) + + +if __name__ == "__main__": + main()