mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-04-22 12:57:23 -04:00
Merge pull request #1345 from stineje/main
add Python script used to analyze an ELF file to see instructions from ELF file
This commit is contained in:
commit
e43f41be48
1 changed files with 83 additions and 0 deletions
83
bin/analyze_riscv_elf.py
Executable file
83
bin/analyze_riscv_elf.py
Executable file
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
###########################################
|
||||
## analyze_riscv_elf.py
|
||||
##
|
||||
## Written: james.stine@okstate.edu
|
||||
## Created: April 7, 2025
|
||||
##
|
||||
## Purpose: Analyze a RISC-V ELF file and report which instructions are used,
|
||||
## along with their frequency. The script disassembles the ELF using
|
||||
## riscv64-unknown-elf-objdump, filters real instructions (excluding
|
||||
## pseudo-ops and section headers), and displays a histogram of
|
||||
## instruction use.Simulate a L1 D$ or I$ for comparison with Wally
|
||||
##
|
||||
## A component of the CORE-V-WALLY configurable RISC-V project.
|
||||
## https://github.com/openhwgroup/cvw
|
||||
##
|
||||
## Copyright (C) 2021-25 Harvey Mudd College & Oklahoma State University
|
||||
##
|
||||
## SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
##
|
||||
## Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
|
||||
## except in compliance with the License, or, at your option, the Apache License version 2.0. You
|
||||
## may obtain a copy of the License at
|
||||
##
|
||||
## https:##solderpad.org/licenses/SHL-2.1/
|
||||
##
|
||||
## Unless required by applicable law or agreed to in writing, any work distributed under the
|
||||
## License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
## either express or implied. See the License for the specific language governing permissions
|
||||
## and limitations under the License.
|
||||
################################################################################################
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
|
||||
def disassemble_elf(elf_path):
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["riscv64-unknown-elf-objdump", "-d", "-M", "no-aliases", elf_path],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
return result.stdout
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error running objdump: {e.stderr}")
|
||||
sys.exit(1)
|
||||
|
||||
def extract_instructions(disassembly):
|
||||
instructions = []
|
||||
for line in disassembly.splitlines():
|
||||
# Match instruction lines only: address: machine-code instruction [operands...]
|
||||
match = re.match(r'^\s*[0-9a-f]+:\s+([0-9a-f]{8}|\s{8})\s+(\S+)', line)
|
||||
if match:
|
||||
instr = match.group(2)
|
||||
instructions.append(instr)
|
||||
return instructions
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python3 analyze_riscv_elf.py <file.elf>")
|
||||
sys.exit(1)
|
||||
|
||||
elf_path = sys.argv[1]
|
||||
disassembly = disassemble_elf(elf_path)
|
||||
instructions = extract_instructions(disassembly)
|
||||
counter = Counter(instructions)
|
||||
|
||||
print(f"\nInstruction usage in {elf_path}:\n")
|
||||
if not counter:
|
||||
print("No instructions found (did you use the correct target ELF file?)")
|
||||
else:
|
||||
for instr, count in counter.most_common():
|
||||
count_str = f"{count:,}" # Add comma as thousands separator
|
||||
print(f"{instr:<10} {count_str}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue