mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
simplified hierarchy extraction
get rid of findInstanceName
This commit is contained in:
parent
7f11aadc89
commit
395709cae0
@ -70,10 +70,6 @@ class _MemInfo(object):
|
||||
self.depth = len(mem)
|
||||
self.elObj = mem[0]
|
||||
|
||||
## def _registerMem(mem):
|
||||
## key = id(mem)
|
||||
## if key not in _memInfoMap:
|
||||
## _memInfoMap[key] = _memInfo()
|
||||
|
||||
def _getMemInfo(mem):
|
||||
return _memInfoMap[id(mem)]
|
||||
@ -110,54 +106,22 @@ class _CallFuncVisitor(object):
|
||||
def visitName(self, node):
|
||||
self.lineno = node.lineno
|
||||
|
||||
|
||||
def _findInstanceName(framerec):
|
||||
fr = framerec[0]
|
||||
fn = framerec[1]
|
||||
ln = framerec[2]
|
||||
if not _filelinemap.has_key(fn):
|
||||
tree = compiler.parseFile(fn)
|
||||
v = _CallFuncVisitor()
|
||||
compiler.walk(tree, v)
|
||||
linemap = _filelinemap[fn] = v.linemap
|
||||
else:
|
||||
linemap = _filelinemap[fn]
|
||||
if not linemap.has_key(ln):
|
||||
return None
|
||||
nln = linemap[ln]
|
||||
cl = linecache.getline(fn, nln)
|
||||
m = rex_assign.match(cl)
|
||||
name = None
|
||||
if m:
|
||||
basename, index = m.groups()
|
||||
if index:
|
||||
il = []
|
||||
for i in index[1:-1].split("]["):
|
||||
try:
|
||||
s = str(eval(i, fr.f_globals, fr.f_locals))
|
||||
except:
|
||||
break
|
||||
il.append(s)
|
||||
else:
|
||||
name = basename + '[' + "][".join(il) + ']'
|
||||
else:
|
||||
name = basename
|
||||
return name
|
||||
|
||||
|
||||
class _HierExtr(object):
|
||||
|
||||
def __init__(self, name, dut, *args, **kwargs):
|
||||
|
||||
global _profileFunc
|
||||
global _memInfoMap
|
||||
_memInfoMap = {}
|
||||
self.skipNames = ('always_comb', 'instances', 'processes')
|
||||
self.skip = 0
|
||||
self.names = []
|
||||
self.instNamesStack = [Set()]
|
||||
self.hierarchy = hierarchy = []
|
||||
self.genNames = genNames = {}
|
||||
self.absnames = absnames = {}
|
||||
self.level = 0
|
||||
self.returned = Set()
|
||||
|
||||
# handle special case of a top-level generator separately
|
||||
if _isGenFunc(dut):
|
||||
_top = dut(*args, **kwargs)
|
||||
@ -169,8 +133,9 @@ class _HierExtr(object):
|
||||
gsigdict[n] = v
|
||||
if _isListOfSigs(v):
|
||||
gmemdict[n] = _makeMemInfo(v)
|
||||
inst = [1, name, gsigdict, gmemdict]
|
||||
inst = [1, (_top, ()), gsigdict, gmemdict]
|
||||
self.hierarchy.append(inst)
|
||||
# the normal case
|
||||
else:
|
||||
_profileFunc = self.extractor
|
||||
sys.setprofile(_profileFunc)
|
||||
@ -178,71 +143,89 @@ class _HierExtr(object):
|
||||
sys.setprofile(None)
|
||||
if not hierarchy:
|
||||
raise ExtractHierarchyError(_error.NoInstances)
|
||||
|
||||
self.top = _top
|
||||
hierarchy.reverse()
|
||||
hierarchy[0][1] = name
|
||||
linecache.clearcache()
|
||||
|
||||
# streamline hierarchy
|
||||
hierarchy.reverse()
|
||||
# walk the hierarchy to define relative and absolute names
|
||||
# in this case, we'll use the names from the lowest levels
|
||||
names = {}
|
||||
obj, subs = hierarchy[0][1]
|
||||
names[id(obj)] = name
|
||||
absnames[id(obj)] = '_' + name
|
||||
for m in hierarchy:
|
||||
obj, subs = m[1]
|
||||
assert id(obj) in names
|
||||
tn = absnames[id(obj)]
|
||||
for sn, so in subs:
|
||||
names[id(so)] = sn
|
||||
absnames[id(so)] = "%s_%s" % (tn, sn)
|
||||
if isinstance(so, (tuple, list)):
|
||||
for i, soi in enumerate(so):
|
||||
names[id(soi)] = "%s[%s]" % (sn, i)
|
||||
absnames[id(soi)] = "%s_%s_%s" % (tn, sn, i)
|
||||
m[1] = names[id(obj)]
|
||||
|
||||
|
||||
|
||||
def extractor(self, frame, event, arg):
|
||||
|
||||
if event == "call":
|
||||
|
||||
func_name = frame.f_code.co_name
|
||||
if func_name in self.skipNames:
|
||||
self.skip = 1
|
||||
if not self.skip:
|
||||
outer = getouterframes(frame)[1]
|
||||
name = _findInstanceName(outer)
|
||||
self.names.append(name)
|
||||
if name:
|
||||
self.instNamesStack[-1].add(name)
|
||||
self.level += 1
|
||||
self.instNamesStack.append(Set())
|
||||
elif event == "return":
|
||||
truenames = [n for n in self.names[1:] if n is not None]
|
||||
prefix = '_'.join(truenames)
|
||||
if not self.skip:
|
||||
name = self.names.pop()
|
||||
if name:
|
||||
if _isGenSeq(arg):
|
||||
sigdict = {}
|
||||
memdict = {}
|
||||
for dict in (frame.f_globals, frame.f_locals):
|
||||
for n, v in dict.items():
|
||||
if isinstance(v, Signal):
|
||||
sigdict[n] = v
|
||||
if _isListOfSigs(v):
|
||||
memdict[n] = _makeMemInfo(v)
|
||||
# check locally named generators
|
||||
# those are not visited by the profiler mechanism
|
||||
instNames = self.instNamesStack[-1]
|
||||
gens = _getGens(arg)
|
||||
for gname, g in frame.f_locals.items():
|
||||
if type(g) is _AlwaysComb:
|
||||
g = g.gen
|
||||
if type(g) is GeneratorType and \
|
||||
g in gens and gname not in instNames:
|
||||
gsigdict = {}
|
||||
gmemdict = {}
|
||||
for dict in (g.gi_frame.f_globals,
|
||||
g.gi_frame.f_locals):
|
||||
for n, v in dict.items():
|
||||
if isinstance(v, Signal):
|
||||
gsigdict[n] = v
|
||||
if _isListOfSigs(v):
|
||||
gmemdict[n] = _makeMemInfo(v)
|
||||
inst = [self.level+1, gname, gsigdict, gmemdict]
|
||||
self.hierarchy.append(inst)
|
||||
absgname = gname
|
||||
if prefix:
|
||||
absgname = prefix + "_" + gname
|
||||
self.genNames[id(g)] = absgname
|
||||
inst = [self.level, name, sigdict, memdict]
|
||||
self.hierarchy.append(inst)
|
||||
self.level -= 1
|
||||
self.instNamesStack.pop()
|
||||
func_name = frame.f_code.co_name
|
||||
if func_name in self.skipNames:
|
||||
self.skip = 0
|
||||
self.level += 1
|
||||
|
||||
elif event == "return":
|
||||
|
||||
if not self.skip:
|
||||
if _isGenSeq(arg):
|
||||
sigdict = {}
|
||||
memdict = {}
|
||||
for dict in (frame.f_globals, frame.f_locals):
|
||||
for n, v in dict.items():
|
||||
if isinstance(v, Signal):
|
||||
sigdict[n] = v
|
||||
if _isListOfSigs(v):
|
||||
memdict[n] = _makeMemInfo(v)
|
||||
l = []
|
||||
for n, o in frame.f_locals.items():
|
||||
for e in _inferArgs(arg):
|
||||
if e is o:
|
||||
l.append((n, o))
|
||||
for n, o in l:
|
||||
if type(o) is _AlwaysComb:
|
||||
g = o.gen
|
||||
else:
|
||||
g = o
|
||||
# special handling of locally defined generators
|
||||
# outside the profiling mechanism
|
||||
if id(o) not in self.returned and \
|
||||
type(g) is GeneratorType:
|
||||
gsigdict = {}
|
||||
gmemdict = {}
|
||||
for dict in (g.gi_frame.f_globals,
|
||||
g.gi_frame.f_locals):
|
||||
for n, v in dict.items():
|
||||
if isinstance(v, Signal):
|
||||
gsigdict[n] = v
|
||||
if _isListOfSigs(v):
|
||||
gmemdict[n] = _makeMemInfo(v)
|
||||
inst = [self.level+1, (o, ()), gsigdict, gmemdict]
|
||||
self.hierarchy.append(inst)
|
||||
self.returned.add(id(arg))
|
||||
inst = [self.level, (arg, l), sigdict, memdict]
|
||||
self.hierarchy.append(inst)
|
||||
self.level -= 1
|
||||
|
||||
func_name = frame.f_code.co_name
|
||||
if func_name in self.skipNames:
|
||||
self.skip = 0
|
||||
|
||||
|
||||
|
||||
def _getGens(arg):
|
||||
if type(arg) is GeneratorType:
|
||||
@ -259,7 +242,12 @@ def _getGens(arg):
|
||||
return l
|
||||
|
||||
|
||||
|
||||
def _inferArgs(arg):
|
||||
c = [arg]
|
||||
if isinstance(arg, (tuple, list)):
|
||||
c += list(arg)
|
||||
return c
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -110,7 +110,7 @@ def _analyzeSigs(hierarchy):
|
||||
|
||||
|
||||
|
||||
def _analyzeGens(top, genNames):
|
||||
def _analyzeGens(top, absnames):
|
||||
genlist = []
|
||||
for g in top:
|
||||
if type(g) is _AlwaysComb:
|
||||
@ -130,7 +130,7 @@ def _analyzeGens(top, genNames):
|
||||
assert isinstance(obj, (int, long, Signal)) or \
|
||||
_isMem(obj)
|
||||
ast.symdict[n] = obj
|
||||
ast.name = genNames.get(id(g.gen), _Label("BLOCK"))
|
||||
ast.name = absnames.get(id(g), _Label("BLOCK"))
|
||||
v = _NotSupportedVisitor(ast)
|
||||
compiler.walk(ast, v)
|
||||
v = _AnalyzeAlwaysCombVisitor(ast, g.senslist)
|
||||
@ -138,9 +138,7 @@ def _analyzeGens(top, genNames):
|
||||
else:
|
||||
f = g.gi_frame
|
||||
s = inspect.getsource(f)
|
||||
#print s
|
||||
s = s.lstrip()
|
||||
#print s
|
||||
ast = compiler.parse(s)
|
||||
#print ast
|
||||
ast.sourcefile = inspect.getsourcefile(f)
|
||||
@ -148,7 +146,7 @@ def _analyzeGens(top, genNames):
|
||||
ast.symdict = f.f_globals.copy()
|
||||
ast.symdict.update(f.f_locals)
|
||||
ast.callstack = []
|
||||
ast.name = genNames.get(id(g), _Label("BLOCK"))
|
||||
ast.name = absnames.get(id(g), _Label("BLOCK"))
|
||||
v = _NotSupportedVisitor(ast)
|
||||
compiler.walk(ast, v)
|
||||
v = _AnalyzeBlockVisitor(ast)
|
||||
|
@ -97,7 +97,7 @@ class _ToVerilogConvertor(object):
|
||||
siglist, memlist = _analyzeSigs(h.hierarchy)
|
||||
arglist = _flatten(h.top)
|
||||
_checkArgs(arglist)
|
||||
genlist = _analyzeGens(arglist, h.genNames)
|
||||
genlist = _analyzeGens(arglist, h.absnames)
|
||||
intf = _analyzeTopFunc(func, *args, **kwargs)
|
||||
intf.name = name
|
||||
|
||||
|
@ -29,13 +29,13 @@ import unittest
|
||||
import test_bin2gray, test_inc, test_fsm, test_ops, test_NotSupported, \
|
||||
test_inc_initial, test_hec, test_loops, test_infer, test_errors, \
|
||||
test_RandomScrambler, test_beh, test_GrayInc, test_misc, \
|
||||
test_ram, test_rom
|
||||
test_ram, test_rom, test_always_comb
|
||||
|
||||
|
||||
modules = (test_bin2gray, test_inc, test_fsm, test_ops, test_NotSupported, \
|
||||
test_inc_initial, test_hec, test_loops, test_infer, test_errors, \
|
||||
test_RandomScrambler, test_beh, test_GrayInc, test_misc, \
|
||||
test_ram, test_rom
|
||||
test_ram, test_rom, test_always_comb
|
||||
)
|
||||
|
||||
|
||||
|
@ -34,6 +34,8 @@ from unittest import TestCase
|
||||
|
||||
from myhdl import *
|
||||
|
||||
from util import setupCosimulation
|
||||
|
||||
QUIET = 1
|
||||
|
||||
def design1(a, b, c, d, p, q, r):
|
||||
@ -74,15 +76,8 @@ def design5(a, b, c, d, p, q, r):
|
||||
return always_comb(logic)
|
||||
|
||||
|
||||
objfile = "design.o"
|
||||
analyze_cmd = "iverilog -o %s design_inst.v tb_design_inst.v" % objfile
|
||||
simulate_cmd = "vvp -m ../../../cosimulation/icarus/myhdl.vpi %s" % objfile
|
||||
|
||||
def design_v(a, b, c, d, p, q, r):
|
||||
if path.exists(objfile):
|
||||
os.remove(objfile)
|
||||
os.system(analyze_cmd)
|
||||
return Cosimulation(simulate_cmd, **locals())
|
||||
def design_v(name, a, b, c, d, p, q, r):
|
||||
return setupCosimulation(**locals())
|
||||
|
||||
|
||||
class AlwaysCombSimulationTest(TestCase):
|
||||
@ -105,7 +100,7 @@ class AlwaysCombSimulationTest(TestCase):
|
||||
random.shuffle(vectors)
|
||||
|
||||
design_inst = toVerilog(design, a, b, c, d, p, q, r)
|
||||
design_v_inst = design_v(a, b, c, d, p_v, q_v, r_v)
|
||||
design_v_inst = design_v(design.func_name, a, b, c, d, p_v, q_v, r_v)
|
||||
|
||||
def clkGen():
|
||||
while 1:
|
||||
|
Loading…
x
Reference in New Issue
Block a user