blob: b8e28dd1a1477609d71abba02a86fad77e76b152 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import struct
import sys
from typing import Dict, List
from shared.elf import read_elf
from shared.insn_yaml import Insn, load_insns_yaml
# Load the insns.yml file at module load time.
try:
INSNS_FILE = load_insns_yaml()
except RuntimeError as err:
sys.stderr.write('{}\n'.format(err))
sys.exit(1)
class OTBNProgram:
def __init__(self, symbols: Dict[str, int], insns: Dict[int, int],
data: Dict[int, int]):
self.symbols = symbols # label -> PC
self.data = data # addr -> data (32b word)
self.insns = {}
for pc, opcode in insns.items():
mnem = INSNS_FILE.mnem_for_word(opcode)
if mnem is None:
raise ValueError(
'No legal decoding for mnemonic: {}'.format(mnem))
insn = INSNS_FILE.mnemonic_to_insn[mnem]
assert insn.encoding is not None
enc_vals = insn.encoding.extract_operands(opcode)
op_vals = insn.enc_vals_to_op_vals(pc, enc_vals)
self.insns[pc] = (insn, op_vals)
def min_pc(self) -> int:
return min(self.insns.keys())
def max_pc(self) -> int:
return max(self.insns.keys())
def get_pc_at_symbol(self, symbol: str) -> int:
if symbol not in self.symbols:
raise ValueError(
'Symbol {} not found in program. Available symbols: {}'.format(
symbol, ', '.join(self.symbols.keys())))
return self.symbols[symbol]
def get_symbols_for_pc(self, pc: int) -> List[str]:
return [s for s, addr in self.symbols.items() if addr == pc]
def get_data_at_addr(self, addr: int) -> int:
return self.data[addr]
def get_insn(self, pc: int) -> Insn:
return self.insns[pc][0]
def get_operands(self, pc: int) -> Dict[str, int]:
return self.insns[pc][1]
def _decode_mem(base_addr: int, data: bytes) -> Dict[int, int]:
'''Interpret memory bytes as a dictionary indexed by address/PC'''
assert len(data) & 3 == 0
return {(base_addr + 4 * offset): int_val[0]
for offset, int_val in enumerate(struct.iter_unpack('<I', data))}
def decode_elf(path: str) -> OTBNProgram:
'''Read ELF file at path and decode contents into an OTBNProgram instance
Returns the OTBNProgram instance representing the program in the ELF file.
'''
(imem_bytes, dmem_bytes, symbols) = read_elf(path)
insns = _decode_mem(0, imem_bytes)
data = _decode_mem(0, dmem_bytes)
return OTBNProgram(symbols, insns, data)