blob: 5b6935811bac143f97c70e898f890fd53f8fad3e [file] [log] [blame]
# -------------------------------------------------------------------------------
# walker.py
#
# Dataflow graph walker
#
# Copyright (C) 2013, Shinya Takamaeda-Yamazaki
# License: Apache 2.0
# -------------------------------------------------------------------------------
from __future__ import absolute_import
from __future__ import print_function
import sys
import os
import pyverilog.utils.util as util
import pyverilog.utils.verror as verror
import pyverilog.utils.signaltype as signaltype
import pyverilog.dataflow.replace as replace
from pyverilog.dataflow.dataflow import *
from pyverilog.dataflow.visit import *
from pyverilog.dataflow.merge import VerilogDataflowMerge
class VerilogDataflowWalker(VerilogDataflowMerge):
def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist):
VerilogDataflowMerge.__init__(self, topmodule, terms, binddict,
resolved_terms, resolved_binddict, constlist)
def walkBind(self, name, step=0):
termname = util.toTermname(name)
if not termname in self.terms:
raise verror.DefinitionError('No such signals: %s' % str(name))
tree = self.getTree(termname)
walked_tree = self.walkTree(tree, visited=set(), step=step)
return replace.replaceUndefined(walked_tree, termname)
def walkTree(self, tree, visited=set([]), step=0, delay=False, msb=None, lsb=None, ptr=None):
if tree is None:
return DFUndefined(32)
if isinstance(tree, DFUndefined):
return tree
if isinstance(tree, DFHighImpedance):
return tree
if isinstance(tree, DFConstant):
return tree
if isinstance(tree, DFEvalValue):
return tree
if isinstance(tree, DFTerminal):
scope = util.getScope(tree.name)
termname = tree.name
if termname in visited:
return tree
termtype = self.getTermtype(termname)
if util.isTopmodule(scope) and signaltype.isInput(termtype):
return tree
nptr = None
if self.getTermDims(termname) is not None:
if ptr is None:
raise verror.FormatError('Array variable requires an pointer.')
if msb is not None and lsb is not None:
return tree
nptr = ptr
nextstep = step
if signaltype.isReg(termtype):
if (not self.isCombination(termname) and
not signaltype.isRename(termtype) and
nextstep == 0):
return tree
if (not self.isCombination(termname)
and not signaltype.isRename(termtype)):
nextstep -= 1
return self.walkTree(self.getTree(termname, nptr),
visited | set([termname, ]), nextstep, delay)
if isinstance(tree, DFBranch):
condnode = self.walkTree(tree.condnode, visited, step, delay)
truenode = self.walkTree(tree.truenode, visited, step, delay)
falsenode = self.walkTree(tree.falsenode, visited, step, delay)
return DFBranch(condnode, truenode, falsenode)
if isinstance(tree, DFOperator):
nextnodes = []
for n in tree.nextnodes:
nextnodes.append(self.walkTree(n, visited, step, delay))
return DFOperator(tuple(nextnodes), tree.operator)
if isinstance(tree, DFPartselect):
msb = self.walkTree(tree.msb, visited, step, delay)
lsb = self.walkTree(tree.lsb, visited, step, delay)
var = self.walkTree(tree.var, visited, step, delay, msb=msb, lsb=lsb)
if isinstance(var, DFPartselect):
child_lsb = self.getTerm(str(tree.var)).lsb.eval()
return DFPartselect(var.var, DFIntConst(str(msb.eval() + var.lsb.eval() - child_lsb)),
DFIntConst(str(lsb.eval() + var.lsb.eval() - child_lsb)))
return DFPartselect(var, msb, lsb)
if isinstance(tree, DFPointer):
ptr = self.walkTree(tree.ptr, visited, step, delay)
var = self.walkTree(tree.var, visited, step, delay, ptr=ptr)
if isinstance(tree.var, DFTerminal):
if (self.getTermDims(tree.var.name) is not None and
not (isinstance(var, DFTerminal) and var.name == tree.var.name)):
return var
return DFPointer(var, ptr)
if isinstance(tree, DFConcat):
nextnodes = []
for n in tree.nextnodes:
nextnodes.append(self.walkTree(n, visited, step, delay))
return DFConcat(tuple(nextnodes))
raise verror.DefinitionError(
'Undefined Node Type: %s : %s' % (str(type(tree)), str(tree)))