fhdl/namer: use execution order indices for variable names as well
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 9 Sep 2012 15:31:35 +0000 (17:31 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 9 Sep 2012 15:31:35 +0000 (17:31 +0200)
migen/fhdl/namer.py
migen/fhdl/tracer.py

index e274e3c977d95e47f6e83266bb352259cda0a56f..9d32a9ad46101821ee7f30ed1b56d01a33a2917c 100644 (file)
@@ -1,43 +1,80 @@
 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):
index 030513152dcc1e1b66a568ce02ef9dcb95a1e75d..765dea8f90e80a83666fcf1d51770896d90b5724 100644 (file)
@@ -1,5 +1,6 @@
 import inspect
 from opcode import opname
+from collections import defaultdict
 
 def get_var_name(frame):
        code = frame.f_code
@@ -25,6 +26,7 @@ def get_var_name(frame):
                else:
                        return None
 
+name_to_idx = defaultdict(int)
 classname_to_objs = dict()
 
 def index_id(l, obj):
@@ -33,14 +35,15 @@ 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"]
@@ -50,9 +53,13 @@ def trace_back(name=None):
                        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:
@@ -66,9 +73,8 @@ def trace_back(name=None):
                                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