Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mnemonic support & Improve Disassembler #21

Open
wants to merge 9 commits into
base: coredsl_exceptions
Choose a base branch
from
131 changes: 131 additions & 0 deletions m2isar/backends/disass/asm_formatter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# SPDX-License-Identifier: Apache-2.0
#
# This file is part of the M2-ISA-R project: https://github.com/tum-ei-eda/M2-ISA-R
#
# Copyright (C) 2022
# Chair of Electrical Design Automation
# Technical University of Munich

"""Fortmatter implementation for CoreDSL assembly strings."""

# Inspired by: https://stackoverflow.com/a/9558001

from string import Formatter

import re
import ast
import operator as op

operators = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
ast.USub: op.neg}

NAMES = {
0: "zero",
1: "ra",
2: "sp",
3: "gp",
4: "tp",
5: "t0",
6: "t1",
7: "t2",
8: "s0",
9: "s1",
10: "a0",
11: "a1",
12: "a2",
13: "a3",
14: "a4",
15: "a5",
16: "a6",
17: "a7",
18: "s2",
19: "s3",
20: "s4",
21: "s5",
22: "s6",
23: "s7",
24: "s8",
25: "s9",
26: "s10",
27: "s11",
28: "t3",
29: "t4",
30: "t5",
31: "t6",
}

FNAMES = {
0: "f0",
1: "f1",
2: "f2",
3: "f3",
4: "f4",
5: "f5",
6: "f6",
7: "f7",
8: "fs0",
9: "fs1",
10: "fa0",
11: "fa1",
12: "fa2",
13: "fa3",
14: "fa4",
15: "fa5",
16: "fa6",
17: "fa7",
18: "fs2",
19: "fs3",
20: "fs4",
21: "fs5",
22: "fs6",
23: "fs7",
24: "fs8",
25: "fs9",
26: "fs10",
27: "fs11",
28: "ft8",
29: "ft9",
30: "ft10",
31: "ft11",
}
Comment on lines +23 to +91
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should be pulled from the actual model, not hardcoded here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea


class AsmFormatter(Formatter):

def get_value(self, key, args, kwargs):
if isinstance(key, int):
return key
assert isinstance(key, str)
try:
value = self.eval_expr(key, args, kwargs)
return value
except ValueError:
pass

return super().get_value(key, args, kwargs)

def get_field(self, field_name, args, kwargs):
return super().get_field(field_name, args, kwargs)

def eval_expr(self, expr, args, kwargs):
return self.eval_(ast.parse(expr, mode='eval').body, args, kwargs)

def eval_(self, node, args, kwargs):
if isinstance(node, ast.Num): # <number>
return node.n
elif isinstance(node, ast.Name): # <name>
return super().get_value(node.id, args, kwargs)
elif isinstance(node, ast.BinOp): # <left> <operator> <right>
return operators[type(node.op)](self.eval_(node.left, args, kwargs), self.eval_(node.right, args, kwargs))
elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1
return operators[type(node.op)](self.eval_(node.operand, args, kwargs))
elif isinstance(node, ast.Call):
if node.func.id == "name":
assert len(node.args) == 1
return NAMES[self.eval_(node.args[0], args, kwargs)]
if node.func.id == "fname":
assert len(node.args) == 1
return FNAMES[self.eval_(node.args[0], args, kwargs)]
assert False
else:
raise TypeError(node)
19 changes: 14 additions & 5 deletions m2isar/backends/disass/disass.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from io import SEEK_CUR

from ...metamodel import arch
from .asm_formatter import AsmFormatter

logger = logging.getLogger("viewer")

Expand Down Expand Up @@ -68,6 +69,7 @@ def main():
parser.add_argument('top_level', help="A .m2isarmodel file containing the models to generate.")
parser.add_argument("core_name")
parser.add_argument('bin')
parser.add_argument("--format", action="store_true", help="Use assembly formatting string and mnemonic")
parser.add_argument("--log", default="info", choices=["critical", "error", "warning", "info", "debug"])
args = parser.parse_args()

Expand Down Expand Up @@ -132,11 +134,18 @@ def main():
# decode instruction operands
else:
operands = decode(ii, found_ins)
assembly = found_ins.assembly
if assembly is None:
assembly = ""
op_str = " | ".join([f"{k}={v}" for k, v in operands.items()])
ins_str = f"{found_ins.name}\t{disass} [{op_str}]"
if args.format:
asm_name = found_ins.mnemonic
assembly = found_ins.assembly
fmt = AsmFormatter()
if assembly is None:
assembly = ""
asm_args = fmt.format(assembly, **operands)
else:
asm_name = found_ins.name
op_str = " | ".join([f"{k}={v}" for k, v in operands.items()])
asm_args = f"[{op_str}]"
ins_str = f"{asm_name}\t{asm_args}"
step = found_ins.size // 8

# print decoded instruction mnemonic
Expand Down