from itertools import combinations
+from collections import defaultdict
from migen.fhdl.structure import *
+from migen.fhdl.tracer import index_id
def _bin(sig_iters):
+ # advance by one in the trace of each signal
status = []
for signal, it in sig_iters:
- step, last = next(it)
- status.append((signal, it, step, last))
- terminals = []
- bins = {}
- for signal, it, step, last in status:
+ if it is not None:
+ step, last = next(it)
+ status.append((signal, it, step, last))
+
+ # build bins accordingly
+ bins = defaultdict(list)
+ for signal, it, (stepname, stepidx), last in status:
if last:
- terminals.append((step, signal))
- else:
- if step not in bins:
- bins[step] = []
- bins[step].append((signal, it))
- return terminals, bins
+ it = None
+ bins[stepname].append((stepidx, signal, it))
+ return bins
def _sets_disjoint(l):
for s1, s2 in combinations(l, 2):
if not s1.isdisjoint(s2):
return False
return True
-
+
+# sig_iters contains a list of tuples (signal, iterator on the current trace position)
def _r_build_pnd(sig_iters):
- terminals, bins = _bin(sig_iters)
- bins_named = [(k, _r_build_pnd(v)) for k, v in bins.items()]
+ bins = _bin(sig_iters)
+
+ subnames = {}
+ mentions = defaultdict(list)
+ bins_named = []
+ stepindices = {}
+
+ for stepname, next_steps in bins.items():
+ bin_content = []
+ for stepidx, signal, it in next_steps:
+ if it is None:
+ mentions[stepname].append(signal)
+ else:
+ bin_content.append((signal, it))
+ stepindices[signal] = stepidx
+ if bin_content:
+ bins_named.append((stepname, _r_build_pnd(bin_content)))
+
name_sets = [set(sub_pnd.values()) for prefix, sub_pnd in bins_named]
- r = {}
if not _sets_disjoint(name_sets):
for prefix, sub_pnd in bins_named:
- for s, n in sub_pnd.items():
- r[s] = prefix + "_" + n
+ for signal, subname in sub_pnd.items():
+ subname = prefix + "_" + subname
+ subnames[signal] = subname
+ mentions[subname].append(signal)
else:
for prefix, sub_pnd in bins_named:
- r.update(sub_pnd)
- for n, s in terminals:
- r[s] = n
+ for signal, subname in sub_pnd.items():
+ subnames[signal] = subname
+ mentions[subname].append(signal)
+
+ # Sort lists of mentions by step indices
+ for v in mentions.values():
+ v.sort(key=lambda x: stepindices[x])
+
+ r = {}
+ for stepname, next_steps in bins.items():
+ for stepidx, signal, it in next_steps:
+ if it is None:
+ name = stepname
+ else:
+ name = subnames[signal]
+ if len(mentions[name]) > 1:
+ r[signal] = name + str(index_id(mentions[name], signal))
+ else:
+ r[signal] = name
+
return r
def last_flagged(seq):
import inspect
from opcode import opname
+from collections import defaultdict
def get_var_name(frame):
code = frame.f_code
else:
return None
+name_to_idx = defaultdict(int)
classname_to_objs = dict()
def index_id(l, obj):
return n
raise ValueError
-def trace_back(name=None):
+def trace_back(varname=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)
+ if varname is None:
+ varname = get_var_name(frame)
+ if varname is not None:
+ l.insert(0, (varname, name_to_idx[varname]))
+ name_to_idx[varname] += 1
try:
obj = frame.f_locals["self"]
obj = None
if obj is None:
- modules = frame.f_globals["__name__"]
- modules = modules.split(".")
- objname = modules[len(modules)-1]
+ if varname is not None:
+ coname = frame.f_code.co_name
+ if coname == "<module>":
+ modules = frame.f_globals["__name__"]
+ modules = modules.split(".")
+ coname = modules[len(modules)-1]
+ l.insert(0, (coname, -1))
else:
classname = obj.__class__.__name__.lower()
try:
except ValueError:
idx = len(objs)
objs.append(obj)
- objname = classname + str(idx)
- l.insert(0, objname)
+ l.insert(0, (classname, idx))
- name = None
+ varname = None
frame = frame.f_back
return l