import migen in litex/gen
[litex.git] / litex / gen / migen / fhdl / tracer.py
1 import inspect
2 from opcode import opname
3 from collections import defaultdict
4
5
6 def get_var_name(frame):
7 code = frame.f_code
8 call_index = frame.f_lasti
9 call_opc = opname[code.co_code[call_index]]
10 if call_opc != "CALL_FUNCTION" and call_opc != "CALL_FUNCTION_VAR":
11 return None
12 index = call_index+3
13 while True:
14 opc = opname[code.co_code[index]]
15 if opc == "STORE_NAME" or opc == "STORE_ATTR":
16 name_index = int(code.co_code[index+1])
17 return code.co_names[name_index]
18 elif opc == "STORE_FAST":
19 name_index = int(code.co_code[index+1])
20 return code.co_varnames[name_index]
21 elif opc == "STORE_DEREF":
22 name_index = int(code.co_code[index+1])
23 return code.co_cellvars[name_index]
24 elif opc == "LOAD_GLOBAL" or opc == "LOAD_ATTR" or opc == "LOAD_FAST" or opc == "LOAD_DEREF":
25 index += 3
26 elif opc == "DUP_TOP":
27 index += 1
28 elif opc == "BUILD_LIST":
29 index += 3
30 else:
31 return None
32
33
34 def remove_underscore(s):
35 if len(s) > 2 and s[0] == "_" and s[1] != "_":
36 s = s[1:]
37 return s
38
39
40 def get_obj_var_name(override=None, default=None):
41 if override:
42 return override
43
44 frame = inspect.currentframe().f_back
45 # We can be called via derived classes. Go back the stack frames
46 # until we reach the first class that does not inherit from us.
47 ourclass = frame.f_locals["self"].__class__
48 while "self" in frame.f_locals and isinstance(frame.f_locals["self"], ourclass):
49 frame = frame.f_back
50
51 vn = get_var_name(frame)
52 if vn is None:
53 vn = default
54 else:
55 vn = remove_underscore(vn)
56 return vn
57
58 name_to_idx = defaultdict(int)
59 classname_to_objs = dict()
60
61
62 def index_id(l, obj):
63 for n, e in enumerate(l):
64 if id(e) == id(obj):
65 return n
66 raise ValueError
67
68
69 def trace_back(varname=None):
70 l = []
71 frame = inspect.currentframe().f_back.f_back
72 while frame is not None:
73 if varname is None:
74 varname = get_var_name(frame)
75 if varname is not None:
76 varname = remove_underscore(varname)
77 l.insert(0, (varname, name_to_idx[varname]))
78 name_to_idx[varname] += 1
79
80 try:
81 obj = frame.f_locals["self"]
82 except KeyError:
83 obj = None
84 if hasattr(obj, "__del__"):
85 obj = None
86
87 if obj is None:
88 if varname is not None:
89 coname = frame.f_code.co_name
90 if coname == "<module>":
91 modules = frame.f_globals["__name__"]
92 modules = modules.split(".")
93 coname = modules[len(modules)-1]
94 coname = remove_underscore(coname)
95 l.insert(0, (coname, name_to_idx[coname]))
96 name_to_idx[coname] += 1
97 else:
98 classname = obj.__class__.__name__.lower()
99 try:
100 objs = classname_to_objs[classname]
101 except KeyError:
102 classname_to_objs[classname] = [obj]
103 idx = 0
104 else:
105 try:
106 idx = index_id(objs, obj)
107 except ValueError:
108 idx = len(objs)
109 objs.append(obj)
110 classname = remove_underscore(classname)
111 l.insert(0, (classname, idx))
112
113 varname = None
114 frame = frame.f_back
115 return l