| import os |
| import json |
| from tqdm import tqdm |
| import itertools as it |
| import sympy as sp |
|
|
| from .disassemble import DisassemblerARM32 |
| from .parser import sympy_to_prefix, isint |
|
|
| def match_constants(exprconst, asmconst, constsym, eps=1e-5): |
| def _close(a, b): |
| return abs(a - b) <= eps |
| mapping = {} |
| mapped = set() |
|
|
| for ec in exprconst: |
| ecf = float(exprconst[ec]) |
| ecsym = constsym[ec] |
| if abs(ecf) < eps: |
| continue |
| for ac in asmconst: |
| acf = asmconst[ac] |
| acsym = constsym[ac] |
| if _close(acf, ecf): |
| mapping[ecsym] = acsym |
| mapped.add(ec) |
| break |
| if _close(acf, 1/ecf): |
| mapping[ecsym] = 1/acsym |
| mapped.add(ec) |
| break |
| if _close(acf, -ecf): |
| mapping[ecsym] = -acsym |
| mapped.add(ec) |
| break |
| return mapping, mapped |
|
|
| def replace_naming(pref): |
| ret = [] |
| for p in pref: |
| if p == "x0": |
| ret.append("x") |
| elif p[0] == "c" and isint(p[1:]): |
| |
| ret.append("k"+p[1:]) |
| else: |
| ret.append(p) |
| return ret |
|
|
|
|
| if __name__ == "__main__": |
| import argparse |
| parser = argparse.ArgumentParser("Pre-process assembly to replace constants and dump") |
| parser.add_argument("--list", required=True) |
| parser.add_argument("--prefix", required=True) |
| args = parser.parse_args() |
| |
| with open(args.list, "r") as f: |
| mdllist = list(f) |
| opts = ["O0", "O1", "O2", "O3"] |
|
|
| asmf = open(args.prefix + ".asm", "w") |
| eqnf = open(args.prefix + ".eqn", "w") |
| constf = open(args.prefix + ".const.jsonl", "w") |
|
|
| basedir = os.path.dirname(args.list) |
| for mdl in tqdm(mdllist): |
| mdl = mdl.strip() |
| mdlname = os.path.basename(mdl) |
| with open(os.path.join(basedir, mdl, "expressions.json")) as f: |
| expressions = json.load(f) |
| yexpr = expressions["expressions"]["y"] |
| exprconsts = {c: float(expressions["constants"][c]) for c in expressions["constants"]} |
| if len(exprconsts) > 4: |
| continue |
| yexpr = sp.parse_expr(yexpr) |
| exprconstsym = {c: sp.Symbol(c) for c in expressions["constants"]} |
| |
| for opt in opts: |
| funcname = f"{mdlname}_run" |
| binf = os.path.join(basedir, mdl, opt, f"c_bin.elf") |
| D = DisassemblerARM32(binf) |
| diss = D.disassemble(funcname) |
| constants = D.constants |
| if len(constants) > 3: |
| continue |
|
|
| exprconstsym.update({c: sp.Symbol(f"c{c}") for c in constants}) |
| mapping, mapped = match_constants(exprconsts, constants, exprconstsym) |
| if len(mapped) != len(constants): |
| continue |
|
|
| exprsubs = yexpr.subs(mapping) |
| exprprefix = replace_naming(sympy_to_prefix(exprsubs)) |
|
|
| asmf.write(diss + "\n") |
| eqnf.write(" ".join(exprprefix) + "\n") |
| constf.write(json.dumps(constants) + "\n") |
|
|
| asmf.close() |
| eqnf.close() |
| constf.close() |
|
|