1
0
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:
jand 2005-09-14 09:25:59 +00:00
parent 7f11aadc89
commit 395709cae0
5 changed files with 97 additions and 116 deletions

View File

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

View File

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

View File

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

View File

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

View File

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