New naming system: second attempt

This commit is contained in:
Sebastien Bourdeauducq 2012-01-19 18:25:25 +01:00
parent a1043d11c0
commit 4eac60d181
2 changed files with 79 additions and 97 deletions

View File

@ -31,110 +31,92 @@ def trace_back(name=None):
frame = frame.f_back frame = frame.f_back
return l return l
def obj_name(obj): class _StepNamer():
def __init__(self):
self.name_to_ids = {}
def basename(self, obj):
if isinstance(obj, str): if isinstance(obj, str):
return obj return obj
else: else:
return obj.__class__.__name__.lower() n = obj.__class__.__name__.lower()
try:
class TreeNode: l = self.name_to_ids[n]
def __init__(self, name): except KeyError:
self.name = name self.name_to_ids[n] = [id(obj)]
self.ids = {} return n + "0"
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: else:
node = TreeNode(n) try:
root.children.append(node) idx = l.index(id(obj))
if not isinstance(step[0], str) and id(step[0]) not in node.ids: except ValueError:
node.ids[id(step[0])] = len(node.ids) idx = len(l)
root = node l.append(id(obj))
return n + str(idx)
def build_tree(signals): def name(self, step):
t = TreeNode("root") n = self.basename(step[0])
for signal in signals: if step[1] is not None:
if signal.name_override is None: n += "_" + step[1]
add_to_tree(t, signal.backtrace) return n
return t
def name_backtrace(root, backtrace): def _bin(sn, sig_iters):
parts = [] terminals = []
for step in backtrace[:-1]: bins = {}
n = obj_name(step[0]) for signal, it in sig_iters:
found = list(filter(lambda x: x.name == n, root.children)) try:
node = found[0] step = it.__next__()
if node.include_context: except StopIteration:
if len(node.ids) > 1: terminals.append(signal)
parts.append(node.name + str(node.ids[id(step[0])]))
else: else:
parts.append(node.name) step_name = sn.name(step)
if node.include_varname and step[1] is not None: if step_name not in bins:
parts.append(step[1]) bins[step_name] = []
root = node bins[step_name].append((signal, it))
last = backtrace[-1] return terminals, bins
if last[1] is not None:
parts.append(last[1]) def _r_build_pnd(sn, sig_iters):
terminals, bins = _bin(sn, sig_iters)
bins_named = [(k, _r_build_pnd(sn, v)) for k, v in bins.items()]
name_sets = [set(sub_pnd.values()) for prefix, sub_pnd in bins_named]
if name_sets:
intersection = set.intersection(*name_sets)
else: else:
parts.append(obj_name(last[0])) intersection = set()
return "_".join(parts) r = {}
if intersection:
def _include_divergence(root, bt1, bt2): for prefix, sub_pnd in bins_named:
for step1, step2 in zip(bt1, bt2): for s, n in sub_pnd.items():
n1, n2 = obj_name(step1[0]), obj_name(step2[0]) if n:
node1 = list(filter(lambda x: x.name == n1, root.children))[0] r[s] = prefix + "_" + n
node2 = list(filter(lambda x: x.name == n2, root.children))[0]
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.backtrace) == name_backtrace(root, s2.backtrace):
_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: else:
return name_backtrace(root, sig.backtrace) r[s] = prefix
else:
for prefix, sub_pnd in bins_named:
r.update(sub_pnd)
for t in terminals:
r[t] = ""
return r
def build_pnd(signals):
sig_iters = [(signal, iter(signal.backtrace))
for signal in signals]
return _r_build_pnd(_StepNamer(), sig_iters)
class Namespace: class Namespace:
def __init__(self, tree): def __init__(self, pnd):
self.counts = {} self.counts = {}
self.sigs = {} self.sigs = {}
self.tree = tree self.pnd = pnd
def get_name(self, sig): def get_name(self, sig):
sig_name = signal_name(self.tree, sig) if sig.name_override is not None:
sig_name = sig.name_override
else:
sig_name = self.pnd[sig]
if not sig_name:
sig_name = "anonymous"
try: try:
n = self.sigs[sig] n = self.sigs[sig]
if n:
return sig_name + "_" + str(n)
else:
return sig_name
except KeyError: except KeyError:
try: try:
n = self.counts[sig_name] n = self.counts[sig_name]

View File

@ -3,7 +3,7 @@ from functools import partial
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.structure import _Operator, _Slice, _Assign, _StatementList from migen.fhdl.structure import _Operator, _Slice, _Assign, _StatementList
from migen.fhdl.tools import * from migen.fhdl.tools import *
from migen.fhdl.namer import Namespace, build_tree_res from migen.fhdl.namer import Namespace, build_pnd
def _printsig(ns, s): def _printsig(ns, s):
if s.bv.signed: if s.bv.signed:
@ -213,7 +213,7 @@ def convert(f, ios=set(), name="top", clk_signal=None, rst_signal=None, return_n
if rst_signal is None: if rst_signal is None:
rst_signal = Signal(name_override="sys_rst") rst_signal = Signal(name_override="sys_rst")
ios.add(rst_signal) ios.add(rst_signal)
ns = Namespace(namer.build_tree_res(list_signals(f))) ns = Namespace(namer.build_pnd(list_signals(f)))
ios |= f.pads ios |= f.pads