From 318ac42b88cbdaaba65344d09e1d47e678fff485 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 26 Aug 2024 18:26:51 +0200 Subject: [PATCH] util: Get rid of `spike-dasm` in favor of `llvm-mc` --- iis-setup.sh | 8 ----- target/common/common.mk | 3 +- util/trace/gen_trace.py | 66 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/iis-setup.sh b/iis-setup.sh index 1fd813f66a..c78b67ae75 100755 --- a/iis-setup.sh +++ b/iis-setup.sh @@ -25,11 +25,3 @@ rm -rf tmp # Install local packages in editable mode. pip install -e . - -# Install spike-dasm -mkdir tools/ -cd tools/ -wget https://raw.githubusercontent.com/pulp-platform/riscv-isa-sim/snitch/iis-install-spike-dasm.sh -chmod +x iis-install-spike-dasm.sh && ./iis-install-spike-dasm.sh && rm iis-install-spike-dasm.sh -cd - -export PATH=$(pwd)/tools:$PATH diff --git a/target/common/common.mk b/target/common/common.mk index 70afd80c2c..4cfdbe2c7b 100644 --- a/target/common/common.mk +++ b/target/common/common.mk @@ -21,7 +21,6 @@ VERILATOR_SEPP ?= # External executables BENDER ?= bender -DASM ?= spike-dasm VLT ?= $(VERILATOR_SEPP) verilator VCS ?= $(VCS_SEPP) vcs VERIBLE_FMT ?= verible-verilog-format @@ -228,7 +227,7 @@ clean-visual-trace: rm -f $(VISUAL_TRACE) $(addprefix $(LOGS_DIR)/,trace_hart_%.txt hart_%_perf.json dma_%_perf.json): $(LOGS_DIR)/trace_hart_%.dasm $(GENTRACE_PY) - $(DASM) < $< | $(GENTRACE_PY) --permissive --dma-trace $(SIM_DIR)/dma_trace_$*_00000.log --dump-hart-perf $(LOGS_DIR)/hart_$*_perf.json --dump-dma-perf $(LOGS_DIR)/dma_$*_perf.json -o $(LOGS_DIR)/trace_hart_$*.txt + $(GENTRACE_PY) < $< --permissive --dma-trace $(SIM_DIR)/dma_trace_$*_00000.log --dump-hart-perf $(LOGS_DIR)/hart_$*_perf.json --dump-dma-perf $(LOGS_DIR)/dma_$*_perf.json -o $(LOGS_DIR)/trace_hart_$*.txt # Generate source-code interleaved traces for all harts. Reads the binary from # the logs/.rtlbinary file that is written at start of simulation in the vsim script diff --git a/util/trace/gen_trace.py b/util/trace/gen_trace.py index db094ad7e6..57cb9b97ac 100755 --- a/util/trace/gen_trace.py +++ b/util/trace/gen_trace.py @@ -36,6 +36,7 @@ import sys import re import argparse +import subprocess import json import ast from ctypes import c_int32, c_uint32 @@ -43,12 +44,15 @@ from pathlib import Path import traceback from itertools import tee, islice, chain +from functools import lru_cache EXTRA_WB_WARN = 'WARNING: {} transactions still in flight for {}.' GENERAL_WARN = """WARNING: Inconsistent final state; performance metrics may be inaccurate. Is this trace complete?\n""" +DASM_IN_REGEX = r'DASM\(([0-9a-fA-F]+)\)' + TRACE_IN_REGEX = r'(\d+)\s+(\d+)\s+(\d+)\s+(0x[0-9A-Fa-fz]+)\s+([^#;]*)(\s*#;\s*(.*))?' TRACE_OUT_FMT = '{:>8} {:>8} {:>8} {:>10} {:<30}' @@ -351,6 +355,25 @@ def load_opcodes(): _cached_opcodes[insn_name] = vec_params +@lru_cache +def disasm_inst(hex_inst, mc_exec="llvm-mc", mc_flags="-mcpu=snitch"): + """Disassemble a single RISC-V instruction using llvm-mc.""" + # Reverse the endianness of the hex instruction + inst_fmt = " ".join( + [f"0x{hex_inst[i:i+2]}" for i in range(0, len(hex_inst), 2)][::-1] + ) + + # Use llvm-mc to disassemble the binary instruction + result = subprocess.run( + f"echo {inst_fmt} | {mc_exec} -disassemble {mc_flags}", + shell=True, + capture_output=True, + ) + + # Extract disassembled instruction from llvm-mc output + return result.stdout.decode().splitlines()[-1].strip().replace("\t", " ") + + def flt_op_vlen(insn: str, op_type: str) -> int: """Get the vector length of a floating-point instruction operand. @@ -883,6 +906,8 @@ def annotate_insn( fseq_info: dict, # Info on the sequencer to properly map tunneled instruction PCs perf_metrics: list, # A list performance metric dicts + mc_exec: str, # Path to the llvm-mc executable + mc_flags: str, # Flags to pass to the llvm-mc executable dupl_time_info: bool = True, # Show sim time and cycle again if same as previous line? last_time_info: @@ -894,7 +919,16 @@ def annotate_insn( dma_trans: list = [] ) -> (str, tuple, bool ): # Return time info, whether trace line contains no info, and fseq_len - match = re.search(TRACE_IN_REGEX, line.strip('\n')) + + # Disassemble instruction + match = re.search(DASM_IN_REGEX, line) + if match is not None: + line = re.sub( + DASM_IN_REGEX, + disasm_inst(match.groups()[0], mc_exec, mc_flags), + line, + ) + match = re.search(TRACE_IN_REGEX, line.strip("\n")) if match is None: raise ValueError('Not a valid trace line:\n{}'.format(line)) time_str, cycle_str, priv_lvl, pc_str, insn, _, extras_str = match.groups() @@ -1104,6 +1138,16 @@ def main(): '--dump-dma-perf', help='Dump DMA performance metrics as json text.' ) + parser.add_argument( + '--llvm-mc-exec', + default='llvm-mc', + help='Path to the llvm-mc executable' + ) + parser.add_argument( + '--llvm-mc-flags', + default='-mcpu=snitch', + help='Flags to pass to the llvm-mc executable' + ) args = parser.parse_args() line_iter = iter(args.infile.readline, b'') @@ -1130,9 +1174,21 @@ def main(): if line: try: ann_insn, time_info, empty = annotate_insn( - line, gpr_wb_info, fpr_wb_info, fseq_info, perf_metrics, False, - time_info, args.offl, not args.saddr, args.permissive, dma_trans) - if perf_metrics[0]['start'] is None: + line, + gpr_wb_info, + fpr_wb_info, + fseq_info, + perf_metrics, + args.llvm_mc_exec, + args.llvm_mc_flags, + False, + time_info, + args.offl, + not args.saddr, + args.permissive, + dma_trans, + ) + if perf_metrics[0]["start"] is None: perf_metrics[0]['tstart'] = time_info[0] / 1000 perf_metrics[0]['start'] = time_info[1] if not empty: @@ -1142,7 +1198,7 @@ def main(): if not nextl: message += 'last line. Did the simulation terminate?' else: - message += 'line {lineno}.' + message += f'line {lineno}.' print(traceback.format_exc(), file=sys.stderr) print(message, file=sys.stderr) return 1