fhdl: new naming system (broken)

This commit is contained in:
Sebastien Bourdeauducq 2012-01-16 18:09:52 +01:00
parent e6bfad498d
commit ab8e08a2ed
6 changed files with 163 additions and 90 deletions

View 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]

142
migen/fhdl/namer.py Normal file
View File

@ -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

View 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)

View 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()

View 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

View 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: