litex/migen/fhdl/tracer.py
2012-09-09 12:27:32 +02:00

74 lines
1.7 KiB
Python

import inspect
from opcode import opname
def get_var_name(frame):
code = frame.f_code
call_index = frame.f_lasti
if opname[code.co_code[call_index]] != "CALL_FUNCTION":
return None
index = call_index+3
while True:
opc = opname[code.co_code[index]]
if opc == "STORE_NAME" or opc == "STORE_ATTR":
name_index = int(code.co_code[index+1])
return code.co_names[name_index]
elif opc == "STORE_FAST":
name_index = int(code.co_code[index+1])
return code.co_varnames[name_index]
elif opc == "STORE_DEREF":
name_index = int(code.co_code[index+1])
return code.co_cellvars[name_index]
elif opc == "LOAD_GLOBAL" or opc == "LOAD_ATTR" or opc == "LOAD_FAST":
index += 3
elif opc == "DUP_TOP":
index += 1
else:
return None
classname_to_objs = dict()
def index_id(l, obj):
for n, e in enumerate(l):
if id(e) == id(obj):
return n
raise ValueError
def trace_back(name=None):
l = []
frame = inspect.currentframe().f_back.f_back
while frame is not None:
if name is None:
name = get_var_name(frame)
if name is not None:
l.insert(0, name)
try:
obj = frame.f_locals["self"]
except KeyError:
obj = None
if hasattr(obj, "__del__"):
obj = None
if obj is None:
modules = frame.f_globals["__name__"]
modules = modules.split(".")
objname = modules[len(modules)-1]
else:
classname = obj.__class__.__name__.lower()
try:
objs = classname_to_objs[classname]
except KeyError:
classname_to_objs[classname] = [obj]
idx = 0
else:
try:
idx = index_id(objs, obj)
except ValueError:
idx = len(objs)
objs.append(obj)
objname = classname + str(idx)
l.insert(0, objname)
name = None
frame = frame.f_back
return l