fhdl: new naming system (broken)
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 16 Jan 2012 17:09:52 +0000 (18:09 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 16 Jan 2012 17:09:52 +0000 (18:09 +0100)
migen/corelogic/record.py
migen/fhdl/namer.py [new file with mode: 0644]
migen/fhdl/structure.py
migen/fhdl/tools.py
migen/fhdl/verilog.py
migen/flow/actor.py

index 2bbe47cf8445b55dba6e0ec6e5ed0dc4bdbb671f..eadeb0a22bb814dfbce761d4a54cf9924ee23a5b 100644 (file)
@@ -1,9 +1,8 @@
 from migen.fhdl.structure import *
-from migen.fhdl.structure import _make_signal_name
 
 class Record:
        def __init__(self, layout, name=None):
-               self.name = name or _make_signal_name()
+               self.name = name or "anonymous"
                self.field_order = []
                for f in layout:
                        if isinstance(f, tuple):
@@ -34,7 +33,7 @@ class Record:
                return l
        
        def copy(self, name=None):
-               return Record(self.layout(), name or _make_signal_name())
+               return Record(self.layout(), name)
        
        def get_alignment(self, name):
                return list(filter(lambda x: x[0] == name, self.field_order))[0][1]
diff --git a/migen/fhdl/namer.py b/migen/fhdl/namer.py
new file mode 100644 (file)
index 0000000..cdd2a99
--- /dev/null
@@ -0,0 +1,142 @@
+import inspect
+import re
+from itertools import combinations
+
+class NoContext:
+       pass
+
+def trace_back(name=None):
+       l = []
+       frame = inspect.currentframe().f_back.f_back
+       while frame is not None:
+               try:
+                       obj = frame.f_locals["self"]
+               except KeyError:
+                       obj = None
+               if obj is None or isinstance(obj, NoContext):
+                       modules = frame.f_globals["__name__"]
+                       modules = modules.split(".")
+                       obj = modules[len(modules)-1]
+               
+               if name is None:
+                       line = inspect.getframeinfo(frame).code_context[0]
+                       m = re.match("[\t ]*([0-9A-Za-z_\.]+)[\t ]*=", line)
+                       if m is None:
+                               name = None
+                       else:
+                               names = m.group(1).split(".")
+                               name = names[len(names)-1]
+               l.insert(0, (obj, name))
+               name = None
+               frame = frame.f_back
+       return l
+
+def obj_name(obj):
+       if isinstance(obj, str):
+               return obj
+       else:
+               return obj.__class__.__name__.lower()
+
+class TreeNode:
+       def __init__(self, name):
+               self.name = name
+               self.ids = {}
+               self.children = []
+               self.include_context = False
+               self.include_varname = False
+       
+def add_to_tree(root, backtrace):
+       for step in backtrace:
+               n = obj_name(step[0])
+               found = list(filter(lambda x: x.name == n, root.children))
+               if found:
+                       node = found[0]
+               else:
+                       node = TreeNode(n)
+                       root.children.append(node)
+               if not isinstance(step[0], str) and id(step[0]) not in node.ids:
+                       node.ids[id(step[0])] = len(node.ids)
+               root = node
+
+def build_tree(signals):
+       t = TreeNode("root")
+       for signal in signals:
+               if signal.name_override is None:
+                       add_to_tree(t, signal.backtrace)
+       return t
+
+def name_backtrace(root, backtrace):
+       parts = []
+       for step in backtrace:
+               n = obj_name(step[0])
+               found = list(filter(lambda x: x.name == n, root.children))
+               node = found[0]
+               if node.include_context:
+                       if len(node.ids) > 1:
+                               parts.append(node.name + str(node.ids[id(step[0])]))
+                       else:
+                               parts.append(node.name)
+               if node.include_varname and step[1] is not None:
+                       parts.append(step[1])
+       return "_".join(parts)
+
+def _include_divergence(root, bt1, bt2):
+       for step1, step2 in zip(bt1, bt2):
+               n1, n2 = obj_name(step1[0]), obj_name(step2[0])
+               node1 = list(filter(lambda x: x.name == n1, root.children))
+               node2 = list(filter(lambda x: x.name == n2, root.children))
+               if node1 != node2:
+                       node1.include_context = True
+                       node2.include_context = True
+                       return
+               if not isinstance(step1[0], str) and not isinstance(step2[0], str) \
+                 and id(step1[0]) != id(step2[0]):
+                       node1.include_context = True
+                       return
+               if step1[1] is not None and step2[1] is not None \
+                 and step1[1] != step2[1]:
+                         node1.include_varname = True
+                         return
+               root = node1
+
+def resolve_conflicts(root, signals):
+       for s1, s2 in combinations(signals, 2):
+               if name_backtrace(root, s1) == name_backtrace(root, s2):
+                       _include_divergence(root, s1.backtrace, s2.backtrace)
+
+def build_tree_res(signals):
+       t = build_tree(signals)
+       resolve_conflicts(t, signals)
+       return t
+
+def signal_name(root, sig):
+       if sig.name_override is not None:
+               return sig.name_override
+       else:
+               return name_backtrace(root, sig.backtrace)
+
+class Namespace:
+       def __init__(self, tree):
+               self.counts = {}
+               self.sigs = {}
+               self.tree = tree
+       
+       def get_name(self, sig):
+               sig_name = signal_name(self.tree, sig)
+               try:
+                       n = self.sigs[sig]
+                       if n:
+                               return sig_name + "_" + str(n)
+                       else:
+                               return sig_name
+               except KeyError:
+                       try:
+                               n = self.counts[sig_name]
+                       except KeyError:
+                               n = 0
+                       self.sigs[sig] = n
+                       self.counts[sig_name] = n + 1
+                       if n:
+                               return sig_name + "_" + str(n)
+                       else:
+                               return sig_name
index c32ac8427e3b57263df2089b2ae798f26b0d820a..3dabbc6b6ed4b9ada0c7d5fd76c4094de6df7a5a 100644 (file)
@@ -2,6 +2,8 @@ import math
 import inspect
 import re
 
+from migen.fhdl import namer
+
 def bits_for(n):
        if isinstance(n, Constant):
                return n.bv.width
@@ -131,61 +133,13 @@ def _cst(x):
        else:
                return x
 
-_forbidden_prefixes = {'inst', 'source', 'sink', 'fsm'}
-
-def _try_class_name(frame):
-       while frame is not None:
-               try:
-                       cl = frame.f_locals['self']
-                       prefix = cl.__class__.__name__.lower()
-                       if prefix not in _forbidden_prefixes:
-                               return prefix
-               except KeyError:
-                       pass
-               frame = frame.f_back
-       return None
-
-def _try_module_name(frame):
-       modules = frame.f_globals["__name__"]
-       if modules != "__main__":
-               modules = modules.split('.')
-               prefix = modules[len(modules)-1]
-               return prefix
-       else:
-               return None
-       
-def _make_signal_name(name=None, back=2):
-       frame = inspect.currentframe()
-       for i in range(back):
-               frame = frame.f_back
-       
-       if name is None:
-               line = inspect.getframeinfo(frame).code_context[0]
-               m = re.match('[\t ]*([0-9A-Za-z_\.]+)[\t ]*=', line)
-               if m is None:
-                       name = "anonymous"
-               else:
-                       names = m.group(1).split('.')
-                       name = names[len(names)-1]
-       
-       prefix = _try_class_name(frame)
-       if prefix is None:
-               prefix = _try_module_name(frame)
-       if prefix is None:
-               prefix = ""
-       else:
-               prefix += "_"
-       
-       return prefix + name
-
 class Signal(Value):
-       def __init__(self, bv=BV(), name=None, variable=False, reset=0, namer=None):
+       def __init__(self, bv=BV(), name=None, variable=False, reset=0, name_override=None):
                self.bv = bv
                self.variable = variable
-               self.name = name
-               if self.name is None:
-                       self.name = _make_signal_name(namer)
                self.reset = Constant(reset, bv)
+               self.name_override = name_override
+               self.backtrace = namer.trace_back(name)
 
        def __hash__(self):
                return id(self)
index cd94d4fa86779dfad5e3e13e6fa491831f4d4c70..6ba4372dd908b79b6a79261f81e2ac398c709008 100644 (file)
@@ -1,30 +1,6 @@
 from migen.fhdl.structure import *
 from migen.fhdl.structure import _Operator, _Slice, _Assign, _StatementList
 
-class Namespace:
-       def __init__(self):
-               self.counts = {}
-               self.sigs = {}
-       
-       def get_name(self, sig):
-               try:
-                       n = self.sigs[sig]
-                       if n:
-                               return sig.name + "_" + str(n)
-                       else:
-                               return sig.name
-               except KeyError:
-                       try:
-                               n = self.counts[sig.name]
-                       except KeyError:
-                               n = 0
-                       self.sigs[sig] = n
-                       self.counts[sig.name] = n + 1
-                       if n:
-                               return sig.name + "_" + str(n)
-                       else:
-                               return sig.name
-
 def list_signals(node):
        if node is None:
                return set()
index 349b6d7a0a70e5eb9b346dc6fb2a09d2be34a334..1842b20ae9b9f896175931bb8ebf236c1b14a138 100644 (file)
@@ -3,6 +3,7 @@ from functools import partial
 from migen.fhdl.structure import *
 from migen.fhdl.structure import _Operator, _Slice, _Assign, _StatementList
 from migen.fhdl.tools import *
+from migen.fhdl.namer import Namespace, build_tree_res
 
 def _printsig(ns, s):
        if s.bv.signed:
@@ -205,15 +206,14 @@ def _printinstances(ns, i, clk, rst):
                r += ");\n\n"
        return r
 
-def convert(f, ios=set(), name="top", clk_signal=None, rst_signal=None, ns=None):
+def convert(f, ios=set(), name="top", clk_signal=None, rst_signal=None, return_ns=False):
        if clk_signal is None:
-               clk_signal = Signal(name="sys_clk")
+               clk_signal = Signal(name_override="sys_clk")
                ios.add(clk_signal)
        if rst_signal is None:
-               rst_signal = Signal(name="sys_rst")
+               rst_signal = Signal(name_override="sys_rst")
                ios.add(rst_signal)
-       if ns is None:
-               ns = Namespace()
+       ns = Namespace(namer.build_tree_res(list_signals(f)))
 
        ios |= f.pads
        
@@ -225,4 +225,7 @@ def convert(f, ios=set(), name="top", clk_signal=None, rst_signal=None, ns=None)
        
        r += "endmodule\n"
        
-       return r
+       if return_ns:
+               return r, ns
+       else:
+               return r
index e6024bdfb263584adc5d412d584d23442491a06d..7203083ab7b92e29233ef0fbc79dfe24c6624848 100644 (file)
@@ -1,5 +1,4 @@
 from migen.fhdl.structure import *
-from migen.fhdl.structure import _make_signal_name
 from migen.corelogic.misc import optree
 from migen.corelogic.record import *
 
@@ -26,11 +25,11 @@ class Endpoint:
        def __init__(self, token):
                self.token = token
                if isinstance(self, Sink):
-                       self.stb = Signal(namer="stb_i")
-                       self.ack = Signal(namer="ack_o")
+                       self.stb = Signal(name="stb_i")
+                       self.ack = Signal(name="ack_o")
                else:
-                       self.stb = Signal(namer="stb_o")
-                       self.ack = Signal(namer="ack_i")
+                       self.stb = Signal(name="stb_o")
+                       self.ack = Signal(name="ack_i")
        
        def token_signal(self):
                sigs = self.token.flatten()
@@ -108,7 +107,7 @@ class Actor:
                                if isinstance(desc[2], Record):
                                        token = desc[2]
                                else:
-                                       token = Record(desc[2], name=_make_signal_name(desc[0], 1))
+                                       token = Record(desc[2])
                                ep = desc[1](token)
                                self.endpoints[desc[0]] = ep
                else: