blob: cb7385731bfd3383c80cd8d5343318d8c69ce733 [file] [log] [blame]
# -------------------------------------------------------------------------------
# bindvisitor.py
#
# Binding visitor
#
# Copyright (C) 2013, Shinya Takamaeda-Yamazaki
# License: Apache 2.0
# Contributor: ryosuke fukatani
# -------------------------------------------------------------------------------
from __future__ import absolute_import
from __future__ import print_function
import sys
import os
import re
from pyverilog.vparser.ast import *
import pyverilog.utils.util as util
import pyverilog.utils.verror as verror
import pyverilog.utils.signaltype as signaltype
from pyverilog.utils.scope import ScopeLabel, ScopeChain
from pyverilog.dataflow.dataflow import *
from pyverilog.dataflow.visit import *
from pyverilog.dataflow.optimizer import VerilogOptimizer
import pyverilog.dataflow.reorder as reorder
import pyverilog.dataflow.replace as replace
class BindVisitor(NodeVisitor):
def __init__(self, moduleinfotable, top, frames, noreorder=False):
self.moduleinfotable = moduleinfotable
self.top = top
self.frames = frames
self.labels = Labels()
self.dataflow = DataFlow()
self.optimizer = VerilogOptimizer({}, {})
self.noreorder = noreorder
# set the top frame of top module
self.frames.setCurrent(ScopeChain())
self.stackInstanceFrame(top, top)
self.copyAllFrameInfo()
current = self.frames.getCurrent()
self.copyFrameInfo(current)
self.renamecnt = 0
self.default_nettype = 'wire'
def getDataflows(self):
return self.dataflow
def getFrameTable(self):
return self.frames
def start_visit(self):
return self.visit(self.moduleinfotable.getDefinition(self.top))
def visit_ModuleDef(self, node):
self.default_nettype = node.default_nettype
self.generic_visit(node)
def visit_Input(self, node):
self.addTerm(node)
def visit_Output(self, node):
self.addTerm(node)
def visit_Inout(self, node):
self.addTerm(node)
def visit_Reg(self, node):
self.addTerm(node)
def visit_Wire(self, node):
self.addTerm(node)
def visit_Tri(self, node):
self.addTerm(node)
def visit_Integer(self, node):
self.addTerm(node)
def visit_Parameter(self, node):
self.addTerm(node)
current = self.frames.getCurrent()
name = current + ScopeLabel(node.name, 'signal')
if not self.hasConstant(name):
value = self.optimize(self.getTree(node.value, current))
self.setConstant(name, value)
if len(self.dataflow.getBindlist(name)) == 0:
self.addBind(node.name, node.value, bindtype='parameter')
def visit_Supply(self, node):
self.addTerm(node)
current = self.frames.getCurrent()
name = current + ScopeLabel(node.name, 'signal')
self.addBind(node.name, node.value, bindtype='parameter')
def visit_Localparam(self, node):
self.addTerm(node)
current = self.frames.getCurrent()
name = current + ScopeLabel(node.name, 'signal')
if not self.hasConstant(name):
value = self.optimize(self.getTree(node.value, current))
self.setConstant(name, value)
self.addBind(node.name, node.value, bindtype='localparam')
def visit_Genvar(self, node):
self.addTerm(node)
current = self.frames.getCurrent()
name = self.frames.getCurrent() + ScopeLabel(node.name, 'signal')
value = DFEvalValue(0)
self.setConstant(name, value)
def visit_Function(self, node):
self.frames.setFunctionDef()
self.generic_visit(node)
self.frames.unsetFunctionDef()
def visit_Task(self, node):
self.frames.setTaskDef()
self.generic_visit(node)
self.frames.unsetTaskDef()
def visit_InstanceList(self, node):
for i in node.instances:
self.visit(i)
def visit_Instance(self, node):
if node.array:
return self._visit_Instance_array(node)
nodename = node.name
return self._visit_Instance_body(node, nodename)
def _visit_Instance_array(self, node):
if node.name == '':
raise verror.FormatError("Module %s requires an instance name" % node.module)
current = self.frames.getCurrent()
msb = self.optimize(self.getTree(node.array.msb, current)).value
lsb = self.optimize(self.getTree(node.array.lsb, current)).value
num_of_pins = msb + 1 - lsb
for i in range(lsb, msb + 1):
nodename = node.name + '_' + str(i)
self._visit_Instance_body(node, nodename, arrayindex=i)
def _visit_Instance_body(self, node, nodename, arrayindex=None):
if node.module in primitives:
return self._visit_Instance_primitive(node, arrayindex)
if nodename == '':
raise verror.FormatError("Module %s requires an instance name" % node.module)
current = self.stackInstanceFrame(nodename, node.module)
scope = self.frames.getCurrent()
paramnames = self.moduleinfotable.getParamNames(node.module)
for paramnames_i, param in enumerate(node.parameterlist):
self.addInstanceParameterBind(param, paramnames[paramnames_i])
value = self.optimize(self.getTree(param.argname, current))
paramname = paramnames[paramnames_i] if param.paramname is None else param.paramname
if paramname not in paramnames:
raise verror.FormatError("No such parameter: %s in %s" %
(paramname, nodename))
name = scope + ScopeLabel(paramname, 'signal')
self.setConstant(name, value)
definition = Parameter(paramname, str(value.value))
term = self.makeConstantTerm(name, definition, current)
self.setConstantTerm(name, term)
ioports = self.moduleinfotable.getIOPorts(node.module)
for ioport_i, port in enumerate(node.portlist):
if port.portname is not None and not (port.portname in ioports):
raise verror.FormatError("No such port: %s in %s" %
(port.argname.name, nodename))
self.addInstancePortBind(port, ioports[ioport_i], arrayindex)
new_current = self.frames.getCurrent()
self.copyFrameInfo(new_current)
self.visit(self.moduleinfotable.getDefinition(node.module))
self.frames.setCurrent(current)
def _visit_Instance_primitive(self, node, arrayindex=None):
primitive_type = primitives[node.module]
left = node.portlist[0].argname
if arrayindex is not None:
left = Pointer(left, IntConst(str(arrayindex)))
right = None
if primitive_type == None:
right = (Pointer(node.portlist[1].argname, IntConst('0')) if arrayindex is None else
Pointer(node.portlist[1].argname, IntConst(str(arrayindex))))
elif primitive_type == Unot:
right = (Ulnot(Pointer(node.portlist[1].argname, IntConst('0'))) if arrayindex is None else
Ulnot(Pointer(node.portlist[1].argname, IntConst(str(arrayindex)))))
else:
concat_list = ([Pointer(p.argname, IntConst('0')) for p in node.portlist[1:]] if arrayindex is None else
[Pointer(p.argname, IntConst(str(arrayindex))) for p in node.portlist[1:]])
right = primitive_type(Concat(concat_list))
self.addBind(left, right, bindtype='assign')
def visit_Initial(self, node):
pass
# label = self.labels.get( self.frames.getLabelKey('initial') )
# current = self.stackNextFrame(label, 'initial',
# generate=self.frames.isGenerate(),
# initial=True)
# self.generic_visit(node)
# self.frames.setCurrent(current)
def visit_Always(self, node):
label = self.labels.get(self.frames.getLabelKey('always'))
current = self.stackNextFrame(label, 'always',
generate=self.frames.isGenerate(),
always=True)
(clock_name, clock_edge, clock_bit,
reset_name, reset_edge, reset_bit,
senslist) = self._createAlwaysinfo(node, current)
self.frames.setAlwaysInfo(clock_name, clock_edge, clock_bit,
reset_name, reset_edge, reset_bit, senslist)
self.generic_visit(node)
self.frames.setCurrent(current)
def _get_signal_name(self, n):
if isinstance(n, Identifier):
return n.name
if isinstance(n, Pointer):
return self._get_signal_name(n.var)
if isinstance(n, Partselect):
return self._get_signal_name(n.var)
return None
def _createAlwaysinfo(self, node, scope):
sens = None
senslist = []
clock_edge = None
clock_name = None
clock_bit = None
reset_edge = None
reset_name = None
reset_bit = None
for l in node.sens_list.list:
if l.sig is None:
continue
if isinstance(l.sig, pyverilog.vparser.ast.Pointer):
signame = self._get_signal_name(l.sig.var)
bit = int(l.sig.ptr.value)
else:
signame = self._get_signal_name(l.sig)
bit = 0
if signaltype.isClock(signame):
clock_name = self.searchTerminal(signame, scope)
clock_edge = l.type
clock_bit = bit
elif signaltype.isReset(signame):
reset_name = self.searchTerminal(signame, scope)
reset_edge = l.type
reset_bit = bit
else:
senslist.append(l)
if clock_edge is not None and len(senslist) > 0:
raise verror.FormatError('Illegal sensitivity list')
if reset_edge is not None and len(senslist) > 0:
raise verror.FormatError('Illegal sensitivity list')
return (clock_name, clock_edge, clock_bit, reset_name, reset_edge, reset_bit, senslist)
def visit_IfStatement(self, node):
if self.frames.isFunctiondef() and not self.frames.isFunctioncall():
return
if self.frames.isTaskdef() and not self.frames.isTaskcall():
return
if (self.frames.isGenerate() and
not self.frames.isAlways() and not self.frames.isInitial() and
not self.frames.isFunctioncall() and not self.frames.isTaskcall() and
not self.frames.isFunctiondef() and not self.frames.isTaskdef()):
# generate-if statement
current = self.frames.getCurrent()
tree = self.getTree(node.cond, current)
rslt = self.optimize(tree)
if not isinstance(rslt, DFEvalValue):
raise verror.FormatError("Can not resolve generate-if condition")
if rslt.value > 0:
label = self._if_true(node)
if node.true_statement is not None:
self.copyBlockingAssigns(current + ScopeLabel(label, 'if'), current)
else:
label = self.labels.get(self.frames.getLabelKey('if'))
self._if_false(node, label)
if node.false_statement is not None:
self.copyBlockingAssigns(
current + ScopeLabel(self._toELSE(label), 'if'), current)
return
label = self._if_true(node)
self._if_false(node, label)
current = self.frames.getCurrent()
if node.true_statement is not None:
self.copyBlockingAssigns(current + ScopeLabel(label, 'if'), current)
if node.false_statement is not None:
self.copyBlockingAssigns(current + ScopeLabel(self._toELSE(label), 'if'), current)
def _toELSE(self, label):
return label + '_ELSE'
def _if_true(self, node):
if node.true_statement is None:
return None
label = self.labels.get(self.frames.getLabelKey('if'))
current = self.stackNextFrame(label, 'if',
frametype='ifthen',
condition=node.cond,
functioncall=self.frames.isFunctioncall(),
taskcall=self.frames.isTaskcall(),
generate=self.frames.isGenerate(),
always=self.frames.isAlways(),
initial=self.frames.isInitial())
self.copyPreviousNonblockingAssign(current + ScopeLabel(label, 'if'))
if node.true_statement is not None:
self.visit(node.true_statement)
self.frames.setCurrent(current)
return label
def _if_false(self, node, label):
if node.false_statement is None:
return
label = self._toELSE(label)
current = self.stackNextFrame(label, 'if',
frametype='ifelse',
condition=node.cond,
functioncall=self.frames.isFunctioncall(),
taskcall=self.frames.isTaskcall(),
generate=self.frames.isGenerate(),
always=self.frames.isAlways(),
initial=self.frames.isInitial())
self.copyPreviousNonblockingAssign(current + ScopeLabel(label, 'if'))
if node.false_statement is not None:
self.visit(node.false_statement)
self.frames.setCurrent(current)
return label
def visit_CaseStatement(self, node):
if self.frames.isFunctiondef() and not self.frames.isFunctioncall():
return
if self.frames.isTaskdef() and not self.frames.isTaskcall():
return
start_frame = self.frames.getCurrent()
caseframes = []
self._case(node.comp, node.caselist, caseframes)
self.frames.setCurrent(start_frame)
for f in caseframes:
self.copyBlockingAssigns(f, start_frame)
def visit_CasexStatement(self, node):
return self.visit_CaseStatement(node)
def _case(self, comp, caselist, myframes):
if len(caselist) == 0:
return
case = caselist[0]
cond = IntConst('1')
if case.cond is not None:
if len(case.cond) > 1:
cond = Eq(comp, case.cond[0])
for c in case.cond[1:]:
cond = Lor(cond, Eq(comp, c))
else:
cond = Eq(comp, case.cond[0])
# else: raise Exception
label = self.labels.get(self.frames.getLabelKey('if'))
current = self.stackNextFrame(label, 'if',
frametype='ifthen',
condition=cond,
functioncall=self.frames.isFunctioncall(),
taskcall=self.frames.isTaskcall(),
generate=self.frames.isGenerate(),
always=self.frames.isAlways(),
initial=self.frames.isInitial())
self.copyPreviousNonblockingAssign(current + ScopeLabel(label, 'if'))
myframes.append(self.frames.getCurrent())
if case.statement is not None:
self.visit(case.statement)
self.frames.setCurrent(current)
if len(caselist) == 1:
return
label = self._toELSE(label)
current = self.stackNextFrame(label, 'if',
frametype='ifelse',
condition=cond,
functioncall=self.frames.isFunctioncall(),
taskcall=self.frames.isTaskcall(),
generate=self.frames.isGenerate(),
always=self.frames.isAlways(),
initial=self.frames.isInitial())
self.copyPreviousNonblockingAssign(current + ScopeLabel(label, 'if'))
myframes.append(current + ScopeLabel(label, 'if'))
self._case(comp, caselist[1:], myframes)
def visit_ForStatement(self, node):
if self.frames.isFunctiondef() and not self.frames.isFunctioncall():
return
if self.frames.isTaskdef() and not self.frames.isTaskcall():
return
# pre-statement
current = self.frames.getCurrent()
pre_right = self.getTree(node.pre.right, current)
pre_right_value = self.optimize(pre_right)
loop = pre_right_value.value
self.frames.setForPre()
self.visit(node.pre)
self.frames.unsetForPre()
label = self.labels.get(self.frames.getLabelKey('for'))
#loop = 0
start_frame = self.frames.getCurrent()
while True:
# cond-statement
current = self.frames.getCurrent()
raw_tree = self.getTree(node.cond, current)
rslt = self.optimize(raw_tree)
if not isinstance(rslt, DFEvalValue):
raise verror.FormatError(("Can not process the for-statement. "
"for-condition should be evaluated statically."))
if rslt.value <= 0:
break
# main-statement
current = self.stackNextFrame(label, 'for',
frametype='for',
functioncall=self.frames.isFunctioncall(),
taskcall=self.frames.isTaskcall(),
generate=self.frames.isGenerate(),
always=self.frames.isAlways(),
initial=self.frames.isInitial(),
loop=loop, loop_iter=self.frames.getForIter())
self.visit(node.statement)
self.copyBlockingAssigns(self.frames.getCurrent(), start_frame)
self.frames.setCurrent(current)
# post-statement
current = self.frames.getCurrent()
post_right = self.getTree(node.post.right, current)
post_right_value = self.optimize(post_right)
loop = post_right_value.value
self.frames.setForPost()
self.visit(node.post)
self.frames.unsetForPost()
#loop += 1
def visit_WhileStatement(self, node):
if self.frames.isFunctiondef() and not self.frames.isFunctioncall():
return
if self.frames.isTaskdef() and not self.frames.isTaskcall():
return
label = self.labels.get(self.frames.getLabelKey('while'))
loop = 0
start_frame = self.frames.getCurrent()
while True:
# cond-statement
current = self.frames.getCurrent()
raw_tree = self.getTree(node.cond, current)
rslt = self.optimize(raw_tree)
if not isinstance(rslt, DFEvalValue):
raise verror.FormatError(("Can not process the while-statement. "
"while-condition should be evaluated statically."))
if rslt.value <= 0:
break
# main-statement
current = self.stackNextFrame(label, 'while',
frametype='while',
functioncall=self.frames.isFunctioncall(),
taskcall=self.frames.isTaskcall(),
generate=self.frames.isGenerate(),
always=self.frames.isAlways(),
initial=self.frames.isInitial(),
loop=loop)
self.visit(node.statement)
self.copyBlockingAssigns(self.frames.getCurrent(), start_frame)
self.frames.setCurrent(current)
loop += 1
def visit_GenerateStatement(self, node):
label = self.labels.get(self.frames.getLabelKey('generate'))
current = self.stackNextFrame(label, 'generate',
generate=True)
self.generic_visit(node)
self.frames.setCurrent(current)
def visit_Block(self, node):
label = None
if node.scope is not None:
label = node.scope
else:
label = self.labels.get(self.frames.getLabelKey('block'))
current = self.stackNextFrame(label, 'block',
frametype='block',
functioncall=self.frames.isFunctioncall(),
taskcall=self.frames.isTaskcall(),
generate=self.frames.isGenerate(),
always=self.frames.isAlways(),
initial=self.frames.isInitial())
self.generic_visit(node)
self.frames.setCurrent(current)
if self.frames.isAlways():
self.copyBlockingAssigns(current + ScopeLabel(label, 'block'), current)
def visit_Assign(self, node):
self.addBind(node.left, node.right, bindtype='assign')
def visit_BlockingSubstitution(self, node):
self.addBind(node.left, node.right, self.frames.getAlwaysStatus(), 'blocking')
def visit_NonblockingSubstitution(self, node):
if self.frames.isForpre() or self.frames.isForpost():
raise verror.FormatError(("Non Blocking Substitution is not allowed"
"in for-statement"))
if self.frames.isFunctioncall():
raise verror.FormatError("Non Blocking Substitution is not allowed in function")
self.addBind(node.left, node.right, self.frames.getAlwaysStatus(), 'nonblocking')
def visit_SystemCall(self, node):
print("Warning: Isolated system call is not supported: %s" % node.syscall)
def optimize(self, node):
return self.optimizer.optimize(node)
def stackInstanceFrame(self, instname, modulename):
current = self.frames.getCurrent()
self.frames.setCurrent(current + ScopeLabel(instname, 'module'))
self.copyFrameInfo(current + ScopeLabel(instname, 'module'))
return current
def stackNextFrame(self, label, scopetype,
frametype='none',
alwaysinfo=None, condition=None,
module=False, functioncall=False, taskcall=False,
generate=False, always=False, initial=False, loop=None, loop_iter=None):
current = self.frames.getCurrent()
scopelabel = ScopeLabel(label, scopetype, loop)
nextscope = current + scopelabel
if not self.frames.hasFrame(nextscope):
current = self.frames.addFrame(scopelabel,
frametype=frametype,
alwaysinfo=alwaysinfo, condition=condition,
module=module, functioncall=functioncall, taskcall=taskcall,
generate=generate, always=always, initial=initial,
loop=loop, loop_iter=loop_iter)
self.frames.setCurrent(nextscope)
new_current = self.frames.getCurrent()
self.copyFrameInfo(new_current)
return current
def copyFrameInfo(self, current):
for name, definitions in self.frames.getConsts(current).items():
if len(definitions) > 1:
raise verror.FormatError("Multiple definitions for Constant")
for definition in definitions:
termtype = definition.__class__.__name__
term = Term(name, set([termtype]))
self.dataflow.addTerm(name, term)
for name, definitions in self.frames.getConsts(current).items():
if len(definitions) > 1:
raise verror.FormatError("Multiple definitions for Constant")
for definition in definitions:
cterm = self.makeConstantTerm(name, definition, current)
self.setConstantTerm(name, cterm)
all_passed = False
while not all_passed:
all_passed = True
for name, definitions in self.frames.getConsts(current).items():
if len(definitions) > 1:
raise verror.FormatError("Multiple definitions for Constant")
if self.hasConstant(name):
continue
for definition in definitions:
if isinstance(definition, Genvar):
continue
value = self.optimize(self.getTree(definition.value, current))
if not isinstance(value, DFEvalValue):
all_passed = False
continue
self.setConstant(name, value)
def copyAllFrameInfo(self):
for name, definitions in self.frames.getAllConsts().items():
if len(definitions) > 1:
raise verror.FormatError("Multiple definitions for Constant")
for definition in definitions:
termtype = definition.__class__.__name__
term = Term(name, set([termtype]))
self.dataflow.addTerm(name, term)
for name, definitions in self.frames.getAllSignals().items():
for definition in definitions:
termtype = definition.__class__.__name__
self.dataflow.addTerm(name, Term(name, set([termtype])))
for name, definition in self.frames.getAllFunctions().items():
self.dataflow.addFunction(name, definition.getDefinition())
self.dataflow.addFunctionPorts(name, definition.getIOPorts())
for name, definition in self.frames.getAllTasks().items():
self.dataflow.addTask(name, definition.getDefinition())
self.dataflow.addTaskPorts(name, definition.getIOPorts())
def copyPreviousNonblockingAssign(self, scope):
assign = self.frames.getPreviousNonblockingAssign()
for name, bindlist in assign.items():
for bind in bindlist:
self.frames.addNonblockingAssign(name, bind)
msb = bind.msb
lsb = bind.lsb
ptr = bind.ptr
part_msb = None
part_lsb = None
condlist, flowlist = self.getCondflow(scope)
alwaysinfo = bind.alwaysinfo
raw_tree = bind.tree
new_bind = self.makeBind(name, msb, lsb, ptr, part_msb, part_lsb,
raw_tree, condlist, flowlist,
alwaysinfo=alwaysinfo)
self.dataflow.addBind(name, new_bind)
def copyBlockingAssigns(self, scope_copy_from, scope_copy_to):
assign = self.frames.getBlockingAssignsScope(scope_copy_from)
for name, bindlist in assign.items():
for bind in bindlist:
self.frames.setBlockingAssign(name, bind, scope_copy_to)
def setConstant(self, name, value):
self.optimizer.setConstant(name, value)
def resetConstant(self, name):
self.optimizer.resetConstant(name)
def getConstant(self, name):
return self.optimizer.getConstant(name)
def hasConstant(self, name):
return self.optimizer.hasConstant(name)
def setConstantTerm(self, name, term):
self.optimizer.setTerm(name, term)
def getTerm(self, name):
term = self.dataflow.getTerm(name)
return term
def getTermWidth(self, name):
term = self.dataflow.getTerm(name)
return term.msb, term.lsb
def getTermDims(self, name):
term = self.dataflow.getTerm(name)
return term.dims
def getTermtype(self, name):
term = self.dataflow.getTerm(name)
return term.termtype
def getBindlist(self, name):
return self.dataflow.getBindlist(name)
def renameVar(self, name):
renamedvar = (name[:-1] +
ScopeLabel('_rn' + str(self.renamecnt) +
'_' + name[-1].scopename, 'signal'))
self.renamecnt += 1
return renamedvar
def toScopeChain(self, blocklabel, current):
scopelist = []
for b in blocklabel.labellist:
if b.loop is not None:
loop = self.optimize(self.getTree(b.loop, current))
if not isinstance(loop, DFEvalValue):
raise verror.FormatError('Loop iterator should be constant')
scopelist.append(ScopeLabel('for', 'for', loop.value))
scopelist.append(ScopeLabel(b.name, 'any'))
return ScopeChain(scopelist)
def getModuleScopeChain(self, target):
remove_cnt = 0
length = len(target)
for scope in reversed(target):
if scope.scopetype == 'module':
return target[:length - remove_cnt]
remove_cnt += 1
raise verror.DefinitionError('module not found')
def searchScopeTerminal(self, blocklabel, name, current):
currentmodule = self.getModuleScopeChain(current)
localchain = currentmodule[-1:] + self.toScopeChain(blocklabel, current)
matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain)
varname = currentmodule[:-1] + matchedchain + ScopeLabel(name, 'signal')
if self.dataflow.hasTerm(varname):
return varname
raise verror.DefinitionError('No such signal: %s' % varname)
# def searchScopeConstantDefinition(self, blocklabel, name, current):
# currentmodule = self.getModuleScopeChain(current)
# localchain = currentmodule[-1:] + self.toScopeChain(blocklabel, current)
# matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain)
# constdef = self.frames.getConstantDefinition(matchedchain, name)
# return constdef
# def searchScopeFunction(self, blocklabel, name, current):
# currentmodule = self.getModuleScopeChain(current)
# localchain = currentmodule[-1:] + self.toScopeChain(blocklabel, current)
# matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain)
# varname = currentmodule[:-1] + matchedchain + ScopeLabel(name, 'function')
# if self.dataflow.hasFunction(varname): return self.dataflow.getFunction(varname)
# raise verror.DefinitionError('No such function: %s' % varname)
# def searchScopeTask(self, blocklabel, name, current):
# currentmodule = self.getModuleScopeChain(current)
# localchain = currentmodule[-1:] + self.toScopeChain(blocklabel, current)
# matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain)
# varname = currentmodule[:-1] + matchedchain + ScopeLabel(name, 'task')
# if self.dataflow.hasTask(varname): return self.dataflow.getTask(varname)
# raise verror.DefinitionError('No such task: %s' % varname)
# def searchScopeFunctionPorts(self, blocklabel, name, current):
# currentmodule = self.getModuleScopeChain(current)
# localchain = currentmodule[-1:] + self.toScopeChain(blocklabel, current)
# matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain)
# varname = currentmodule[:-1] + matchedchain + ScopeLabel(name, 'function')
# if self.dataflow.hasFunction(varname):
# return self.dataflow.getFunctionPorts(varname)
# raise verror.DefinitionError('No such function: %s' % varname)
# def searchScopeTaskPorts(self, blocklabel, name, current):
# currentmodule = self.frames.getModuleScopeChain(current)
# localchain = currentmodule[-1:] + self.toScopeChain(blocklabel, current)
# matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain)
# varname = currentmodule[:-1] + matchedchain + ScopeLabel(name, 'task')
# if self.dataflow.hasTask(varname):
# return self.dataflow.getTaskPorts(varname)
# raise verror.DefinitionError('No such task: %s' % varname)
def searchConstantDefinition(self, key, name):
const = self.frames.searchConstantDefinition(key, name)
if const is None:
raise verror.DefinitionError('constant value not found: %s' % name)
return const
def searchTerminal(self, name, scope):
if len(scope) == 0:
return None
varname = scope + ScopeLabel(name, 'signal')
if self.dataflow.hasTerm(varname):
return varname
if self.frames.dict[scope].isModule():
return None
# if self.frames.dict[scope].isFunctioncall(): return None
return self.searchTerminal(name, scope[:-1])
def searchFunction(self, name, scope):
if len(scope) == 0:
return None
varname = scope + ScopeLabel(name, 'function')
if self.dataflow.hasFunction(varname):
return self.dataflow.getFunction(varname)
if self.frames.dict[scope].isModule():
return None
return self.searchFunction(name, scope[:-1])
def searchTask(self, name, scope):
if len(scope) == 0:
return None
varname = scope + ScopeLabel(name, 'task')
if self.dataflow.hasTask(varname):
return self.dataflow.getTask(varname)
if self.frames.dict[scope].isModule():
return None
return self.searchTask(name, scope[:-1])
def searchFunctionPorts(self, name, scope):
if len(scope) == 0:
return ()
varname = scope + ScopeLabel(name, 'function')
if self.dataflow.hasFunction(varname):
return self.dataflow.getFunctionPorts(varname)
if self.frames.dict[scope].isModule():
return ()
return self.searchFunctionPorts(name, scope[:-1])
def searchTaskPorts(self, name, scope):
if len(scope) == 0:
return ()
varname = scope + ScopeLabel(name, 'task')
if self.dataflow.hasTask(varname):
return self.dataflow.getTaskPorts(varname)
if self.frames.dict[scope].isModule():
return ()
return self.searchTaskPorts(name, scope[:-1])
def makeConstantTerm(self, name, node, scope):
termtype = node.__class__.__name__
termtypes = set([termtype])
msb = DFIntConst('31') if node.width is None else self.makeDFTree(node.width.msb, scope)
lsb = DFIntConst('0') if node.width is None else self.makeDFTree(node.width.lsb, scope)
return Term(name, termtypes, msb, lsb)
def addTerm(self, node, rscope=None):
if self.frames.isFunctiondef() and not self.frames.isFunctioncall():
return
if self.frames.isTaskdef() and not self.frames.isTaskcall():
return
scope = self.frames.getCurrent() if rscope is None else rscope
name = scope + ScopeLabel(node.name, 'signal')
termtype = node.__class__.__name__
if self.frames.isFunctioncall():
termtype = 'Function'
if self.frames.isTaskcall():
termtype = 'Task'
termtypes = set([termtype])
if isinstance(node, (Parameter, Localparam)):
msb = DFIntConst('31') if node.width is None else self.makeDFTree(node.width.msb, scope)
else:
msb = DFIntConst('0') if node.width is None else self.makeDFTree(node.width.msb, scope)
lsb = DFIntConst('0') if node.width is None else self.makeDFTree(node.width.lsb, scope)
dims = None
if node.dimensions is not None:
dims = []
for length in node.dimensions.lengths:
l = self.makeDFTree(length.msb, scope)
r = self.makeDFTree(length.lsb, scope)
dims.append((l, r))
dims = tuple(dims)
term = Term(name, termtypes, msb, lsb, dims)
self.dataflow.addTerm(name, term)
self.setConstantTerm(name, term)
def addBind(self, left, right, alwaysinfo=None, bindtype=None):
if self.frames.isFunctiondef() and not self.frames.isFunctioncall():
return
if self.frames.isTaskdef() and not self.frames.isTaskcall():
return
lscope = self.frames.getCurrent()
rscope = lscope
dst = self.getDestinations(left, lscope)
if bindtype == 'blocking':
self.addDataflow_blocking(dst, right, lscope, rscope, alwaysinfo)
else:
self.addDataflow(dst, right, lscope, rscope, alwaysinfo, bindtype)
def addInstanceParameterBind(self, param, name=None):
lscope = self.frames.getCurrent()
rscope = lscope[:-1]
paramname = name if param.paramname is None else param.paramname
dst = self.getDestinations(paramname, lscope)
self.addDataflow(dst, param.argname, lscope, rscope, None, 'parameter')
def addInstancePortBind(self, port, instportname=None, arrayindex=None):
lscope = self.frames.getCurrent()
rscope = lscope[:-1]
portname = instportname if port.portname is None else port.portname
ldst = self.getDestinations(portname, lscope)
if ldst[0][0] is None:
raise verror.DefinitionError('No such port: %s' % portname)
termtype = self.getTermtype(ldst[0][0])
for t in termtype:
if t == 'Input':
if port.argname is None:
continue
portarg = (port.argname if arrayindex is None else
Pointer(port.argname, IntConst(str(arrayindex))))
self.addDataflow(ldst, portarg, lscope, rscope)
elif t == 'Output':
if port.argname is None:
continue
portarg = (port.argname if arrayindex is None else
Pointer(port.argname, IntConst(str(arrayindex))))
rdst = self.getDestinations(portarg, rscope)
self.addDataflow(rdst, portname, rscope, lscope)
elif t == 'Inout':
if port.argname is None:
continue
portarg = (port.argname if arrayindex is None else
Pointer(port.argname, IntConst(str(arrayindex))))
self.addDataflow(ldst, portarg, lscope, rscope)
rdst = self.getDestinations(portarg, rscope)
self.addDataflow(rdst, portname, rscope, lscope)
def addDataflow(self, dst, right, lscope, rscope, alwaysinfo=None, bindtype=None):
condlist, flowlist = self.getCondflow(lscope)
raw_tree = self.getTree(right, rscope)
self.setDataflow(dst, raw_tree, condlist, flowlist, alwaysinfo, bindtype)
def addDataflow_blocking(self, dst, right, lscope, rscope, alwaysinfo):
condlist, flowlist = self.getCondflow(lscope)
raw_tree = self.getTree(right, rscope)
self.setDataflow_rename(dst, raw_tree, condlist, flowlist, lscope, alwaysinfo)
if len(dst) == 1: # set genvar value to the constant table
name = dst[0][0]
if signaltype.isGenvar(self.getTermtype(name)):
value = self.optimize(raw_tree)
self.setConstant(name, value)
else: # for "for-statement"
value = self.optimize(raw_tree)
if isinstance(value, DFEvalValue):
self.setConstant(name, value)
else:
self.resetConstant(name)
def getCondflow(self, scope):
condlist = self.getCondlist(scope)
condlist = self.resolveCondlist(condlist, scope)
flowlist = self.getFlowlist(scope)
return (condlist, flowlist)
def getCondlist(self, scope):
ret = []
s = scope
while s is not None:
frame = self.frames.dict[s]
cond = frame.getCondition()
if cond is not None:
ret.append(self.makeDFTree(cond, self.reduceIfScope(s)))
if frame.isModule():
break
s = frame.previous
ret.reverse()
return tuple(ret)
def getFlowlist(self, scope):
ret = []
s = scope
while s is not None:
frame = self.frames.dict[s]
cond = frame.getCondition()
if cond is not None:
ret.append(not frame.isIfelse())
if frame.isModule():
break
s = frame.previous
ret.reverse()
return tuple(ret)
def getTree(self, node, scope):
expr = node.var if isinstance(node, Rvalue) else node
tree = self.makeDFTree(expr, scope)
tree = self.resolveBlockingAssign(tree, scope)
if not self.noreorder:
tree = reorder.reorder(tree)
return tree
def makeDFTree(self, node, scope):
if isinstance(node, str):
name = self.searchTerminal(node, scope)
return DFTerminal(name)
if isinstance(node, Identifier):
if node.scope is not None:
name = self.searchScopeTerminal(node.scope, node.name, scope)
if name is None:
raise verror.DefinitionError('No such signal: %s' % node.name)
return DFTerminal(name)
name = self.searchTerminal(node.name, scope)
if name is None:
raise verror.DefinitionError('No such signal: %s' % node.name)
return DFTerminal(name)
if isinstance(node, IntConst):
return DFIntConst(node.value)
if isinstance(node, FloatConst):
return DFFloatConst(node.value)
if isinstance(node, StringConst):
return DFStringConst(node.value)
if isinstance(node, Cond):
true_df = self.makeDFTree(node.true_value, scope)
false_df = self.makeDFTree(node.false_value, scope)
cond_df = self.makeDFTree(node.cond, scope)
if isinstance(cond_df, DFBranch):
return reorder.insertCond(cond_df, true_df, false_df)
return DFBranch(cond_df, true_df, false_df)
if isinstance(node, UnaryOperator):
right_df = self.makeDFTree(node.right, scope)
if isinstance(right_df, DFBranch):
return reorder.insertUnaryOp(right_df, node.__class__.__name__)
return DFOperator((right_df,), node.__class__.__name__)
if isinstance(node, Operator):
left_df = self.makeDFTree(node.left, scope)
right_df = self.makeDFTree(node.right, scope)
if isinstance(left_df, DFBranch) or isinstance(right_df, DFBranch):
return reorder.insertOp(left_df, right_df, node.__class__.__name__)
return DFOperator((left_df, right_df,), node.__class__.__name__)
if isinstance(node, Partselect):
var_df = self.makeDFTree(node.var, scope)
msb_df = self.makeDFTree(node.msb, scope)
lsb_df = self.makeDFTree(node.lsb, scope)
if isinstance(var_df, DFBranch):
return reorder.insertPartselect(var_df, msb_df, lsb_df)
return DFPartselect(var_df, msb_df, lsb_df)
if isinstance(node, Pointer):
var_df = self.makeDFTree(node.var, scope)
ptr_df = self.makeDFTree(node.ptr, scope)
if isinstance(var_df, DFTerminal) and self.getTermDims(var_df.name) is not None:
return DFPointer(var_df, ptr_df)
return DFPartselect(var_df, ptr_df, copy.deepcopy(ptr_df))
if isinstance(node, Concat):
nextnodes = []
for n in node.list:
nextnodes.append(self.makeDFTree(n, scope))
for n in nextnodes:
if isinstance(n, DFBranch):
return reorder.insertConcat(tuple(nextnodes))
return DFConcat(tuple(nextnodes))
if isinstance(node, Repeat):
nextnodes = []
times = self.optimize(self.getTree(node.times, scope)).value
value = self.makeDFTree(node.value, scope)
for i in range(int(times)):
nextnodes.append(copy.deepcopy(value))
return DFConcat(tuple(nextnodes))
if isinstance(node, FunctionCall):
func = self.searchFunction(node.name.name, scope)
if func is None:
raise verror.DefinitionError('No such function: %s' % node.name.name)
label = self.labels.get(self.frames.getLabelKey('functioncall'))
save_current = self.frames.getCurrent()
self.frames.setCurrent(scope)
current = self.frames.addFrame(
ScopeLabel(label, 'functioncall'),
functioncall=True, generate=self.frames.isGenerate(),
always=self.frames.isAlways())
varname = self.frames.getCurrent() + ScopeLabel(func.name, 'signal')
self.addTerm(Wire(func.name, func.retwidth))
funcports = self.searchFunctionPorts(node.name.name, scope)
funcargs = node.args
if len(funcports) != len(funcargs):
raise verror.FormatError("%s takes exactly %d arguments. (%d given)" %
(func.name.name, len(funcports), len(funcargs)))
for port in funcports:
self.addTerm(Wire(port.name, port.width))
lscope = self.frames.getCurrent()
rscope = scope
func_i = 0
for port in funcports:
arg = funcargs[func_i]
dst = self.getDestinations(port.name, lscope)
self.addDataflow(dst, arg, lscope, rscope)
func_i += 1
self.visit(func)
self.frames.setCurrent(current)
self.frames.setCurrent(save_current)
return DFTerminal(varname)
if isinstance(node, TaskCall):
task = self.searchTask(node.name.name, scope)
label = self.labels.get(self.frames.getLabelKey('taskcall'))
current = self.frames.addFrame(
ScopeLabel(label, 'taskcall'),
taskcall=True, generate=self.frames.isGenerate(),
always=self.frames.isAlways())
varname = self.frames.getCurrent() + ScopeLabel(task.name, 'signal')
taskports = self.searchTaskPorts(node.name.name, scope)
taskargs = node.args
if len(taskports) != len(taskargs):
raise verror.FormatError("%s takes exactly %d arguments. (%d given)" %
(task.name.name, len(taskports), len(taskargs)))
for port in taskports:
self.addTerm(Wire(port.name, port.width))
lscope = self.frames.getCurrent()
rscope = scope
task_i = 0
for port in taskports:
arg = taskargs[task_i]
dst = self.getDestinations(port.name, lscope)
self.addDataflow(dst, arg, lscope, rscope)
task_i += 1
self.visit(taskargs)
self.frames.setCurrent(current)
return DFTerminal(varname)
if isinstance(node, SystemCall):
if node.syscall == 'unsigned':
return self.makeDFTree(node.args[0], scope)
if node.syscall == 'signed':
return self.makeDFTree(node.args[0], scope)
return DFIntConst('0')
raise verror.FormatError("unsupported AST node type: %s %s" %
(str(type(node)), str(node)))
def reduceIfScope(self, scope):
if len(scope) == 0:
return scope
if scope[-1].scopetype == 'if':
return scope[:-1]
return self.reduceIfScope(scope[:-1])
def resolveCondlist(self, condlist, scope):
resolved_condlist = []
reducedscope = self.reduceIfScope(scope)
for i, c in enumerate(reversed(condlist)):
resolved_condlist.append(self.resolveBlockingAssign(c, reducedscope))
reducedscope = self.reduceIfScope(reducedscope)
return tuple(reversed(resolved_condlist))
def removeOverwrappedCondition(self, tree, current_bindlist, scope):
msb, lsb = self.getTermWidth(tree.name)
merged_tree = self.getFitTree(current_bindlist, msb, lsb)
condlist, flowlist = self.getCondflow(scope)
(merged_tree,
rest_condlist,
rest_flowlist,
match_flowlist) = self.diffBranchTree(merged_tree, condlist, flowlist)
return replace.replaceUndefined(merged_tree, tree.name)
def resolveBlockingAssign(self, tree, scope):
if tree is None:
return None
if isinstance(tree, DFConstant):
return tree
if isinstance(tree, DFEvalValue):
return tree
if isinstance(tree, DFTerminal):
if signaltype.isGenvar(self.getTermtype(tree.name)):
return self.getConstant(tree.name)
current_bindlist = self.frames.getBlockingAssign(tree.name, scope)
if len(current_bindlist) == 0:
return tree
return self.removeOverwrappedCondition(tree, current_bindlist, scope)
if isinstance(tree, DFBranch):
truenode = self.resolveBlockingAssign(tree.truenode, scope)
falsenode = self.resolveBlockingAssign(tree.falsenode, scope)
condnode = self.resolveBlockingAssign(tree.condnode, scope)
if isinstance(condnode, DFBranch):
return reorder.insertBranch(condnode, truenode, falsenode)
return DFBranch(condnode, truenode, falsenode)
if isinstance(tree, DFOperator):
resolvednodes = []
for n in tree.nextnodes:
resolvednodes.append(self.resolveBlockingAssign(n, scope))
for r in resolvednodes:
if isinstance(r, DFBranch):
return reorder.insertOpList(resolvednodes, tree.operator)
return DFOperator(tuple(resolvednodes), tree.operator)
if isinstance(tree, DFConcat):
resolvednodes = []
for n in tree.nextnodes:
resolvednodes.append(self.resolveBlockingAssign(n, scope))
for r in resolvednodes:
if isinstance(r, DFBranch):
return reorder.insertConcat(resolvednodes)
return DFConcat(tuple(resolvednodes))
if isinstance(tree, DFPartselect):
resolved_msb = self.resolveBlockingAssign(tree.msb, scope)
resolved_lsb = self.resolveBlockingAssign(tree.lsb, scope)
resolved_var = self.resolveBlockingAssign(tree.var, scope)
if isinstance(resolved_var, DFBranch):
return reorder.insertPartselect(resolved_var,
resolved_msb, resolved_lsb)
return DFPartselect(resolved_var, resolved_msb, resolved_lsb)
if isinstance(tree, DFPointer):
resolved_ptr = self.resolveBlockingAssign(tree.ptr, scope)
if (isinstance(tree.var, DFTerminal) and
self.getTermDims(tree.var.name) is not None):
current_bindlist = self.frames.getBlockingAssign(tree.var.name, scope)
if len(current_bindlist) == 0:
return DFPointer(tree.var, resolved_ptr)
new_tree = DFPointer(tree.var, resolved_ptr)
for bind in current_bindlist:
new_tree = DFBranch(DFOperator((bind.ptr, resolved_ptr), 'Eq'),
bind.tree, new_tree)
print(("Warning: "
"Overwrting Blocking Assignment with Reg Array is not supported"))
return new_tree
resolved_var = self.resolveBlockingAssign(tree.var, scope)
if isinstance(resolved_var, DFBranch):
return reorder.insertPointer(resolved_var, resolved_ptr)
return DFPointer(resolved_var, resolved_ptr)
raise verror.FormatError("unsupported DFNode type: %s %s" %
(str(type(tree)), str(tree)))
def getFitTree(self, bindlist, msb, lsb):
optimized_msb = self.optimize(msb)
optimized_lsb = self.optimize(lsb)
for bind in bindlist:
if bind.msb is None and bind.lsb is None:
return bind.tree
if (self.optimize(bind.msb) == optimized_msb and
self.optimize(bind.lsb) == optimized_lsb):
return bind.tree
return self.getMergedTree(bindlist)
def getMergedTree(self, bindlist):
concatlist = []
last_msb = -1
last_ptr = -1
def bindkey(x):
lsb = 0 if x.lsb is None else x.lsb.value
ptr = 0 if not isinstance(x.ptr, DFEvalValue) else x.ptr.value
term = self.getTerm(x.dest)
length = (abs(self.optimize(term.msb).value
- self.optimize(term.lsb).value) + 1)
return ptr * length + lsb
for bind in sorted(bindlist, key=bindkey):
lsb = 0 if bind.lsb is None else bind.lsb.value
if last_ptr != (-1 if not isinstance(bind.ptr, DFEvalValue)
else bind.ptr.value):
continue
if last_msb + 1 < lsb:
concatlist.append(DFUndefined(last_msb - lsb - 1))
concatlist.append(bind.tree)
last_msb = -1 if bind.msb is None else bind.msb.value
last_ptr = -1 if not isinstance(bind.ptr, DFEvalValue) else bind.ptr.value
return DFConcat(tuple(reversed(concatlist)))
def getDestinations(self, left, scope):
ret = []
dst = self.getDsts(left, scope)
part_offset = DFIntConst('0')
for name, msb, lsb, ptr in reversed(dst):
if len(dst) == 1:
ret.append((name, msb, lsb, ptr, None, None))
continue
if msb is None and lsb is None:
msb, lsb = self.getTermWidth(name)
diff = reorder.reorder(DFOperator((msb, lsb), 'Minus'))
part_lsb = part_offset
part_msb = reorder.reorder(DFOperator((part_offset, diff), 'Plus'))
part_offset = reorder.reorder(
DFOperator((part_msb, DFIntConst('1')), 'Plus'))
ret.append((name, msb, lsb, ptr, part_msb, part_lsb))
return tuple(ret)
def getDsts(self, left, scope):
if isinstance(left, Lvalue):
return self.getDsts(left.var, scope)
if isinstance(left, LConcat):
dst = []
for n in left.list:
dst.extend(list(self.getDsts(n, scope)))
return tuple(dst)
ret = (self.getDst(left, scope),)
return ret
def getDst(self, left, scope):
if isinstance(left, str): # Parameter
name = self.searchTerminal(left, scope)
return (name, None, None, None)
if isinstance(left, Identifier):
name = self.searchTerminal(left.name, scope)
if name is None:
m = re.search('none', self.default_nettype)
if m:
raise verror.FormatError("No such signal: %s" % left.name)
m = re.search('wire', self.default_nettype)
if m:
self.addTerm(Wire(left.name), rscope=scope)
m = re.search('reg', self.default_nettype)
if m:
self.addTerm(Reg(left.name), rscope=scope)
name = self.searchTerminal(left.name, scope)
if left.scope is not None:
name = left.scope + ScopeLabel(left.name, 'signal')
return (name, None, None, None)
if isinstance(left, Partselect):
if isinstance(left.var, Pointer):
name, msb, lsb, ptr = self.getDst(left.var, scope)
if msb is None and lsb is None:
msb = self.optimize(self.makeDFTree(left.msb, scope))
lsb = self.optimize(self.makeDFTree(left.lsb, scope))
else:
raise verror.FormatError("%s is not array" % str(name))
return (name, msb, lsb, ptr)
name = self.searchTerminal(left.var.name, scope)
if left.var.scope is not None:
name = left.var.scope + ScopeLabel(left.var.name, 'signal')
msb = self.optimize(self.makeDFTree(left.msb, scope))
lsb = self.optimize(self.makeDFTree(left.lsb, scope))
return (name, msb, lsb, None)
if isinstance(left, Pointer):
if isinstance(left.var, Pointer):
name, msb, lsb, ptr = self.getDst(left.var, scope)
if msb is None and lsb is None:
msb = self.optimize(self.makeDFTree(left.ptr, scope))
lsb = copy.deepcopy(msb)
else:
raise verror.FormatError("%s is not array" % str(name))
return (name, msb, lsb, ptr)
name = self.searchTerminal(left.var.name, scope)
if left.var.scope is not None:
name = left.var.scope + ScopeLabel(left.var.name, 'signal')
ptr = self.optimize(self.makeDFTree(left.ptr, scope))
if self.getTermDims(name) is not None:
return (name, None, None, ptr)
return (name, ptr, copy.deepcopy(ptr), None)
raise verror.FormatError("unsupported AST node type: %s %s" %
(str(type(left)), str(left)))
def setDataflow(self, dst, raw_tree, condlist, flowlist,
alwaysinfo=None, bindtype=None):
for name, msb, lsb, ptr, part_msb, part_lsb in dst:
bind = self.makeBind(name, msb, lsb, ptr, part_msb, part_lsb,
raw_tree, condlist, flowlist,
num_dst=len(dst),
alwaysinfo=alwaysinfo,
bindtype=bindtype)
self.dataflow.addBind(name, bind)
if alwaysinfo is not None:
self.setNonblockingAssign(name, dst, raw_tree,
msb, lsb, ptr,
part_msb, part_lsb,
alwaysinfo)
def setDataflow_rename(self, dst, raw_tree, condlist, flowlist,
scope, alwaysinfo=None):
renamed_dst = self.getRenamedDst(dst)
self.setRenamedTree(renamed_dst, raw_tree, alwaysinfo)
self.setRenamedFlow(dst, renamed_dst, condlist, flowlist, scope, alwaysinfo)
def setNonblockingAssign(self, name, dst, raw_tree, msb, lsb, ptr,
part_msb, part_lsb, alwaysinfo):
tree = raw_tree
if len(dst) > 1:
tree = reorder.reorder(DFPartselect(raw_tree, part_msb, part_lsb))
bind = Bind(tree, name, msb, lsb, ptr, alwaysinfo)
self.frames.addNonblockingAssign(name, bind)
def getRenamedDst(self, dst):
renamed_dst = ()
for d in dst:
dname = d[0]
samename_exists = True
while samename_exists:
renamed_dname = self.renameVar(dname)
samename_exists = self.dataflow.hasTerm(renamed_dname)
term = self.dataflow.getTerm(dname)
newterm = copy.deepcopy(term)
newterm.name = renamed_dname
newterm.termtype = set(['Rename'])
self.dataflow.addTerm(renamed_dname, newterm)
newd = (renamed_dname,) + d[1:]
renamed_dst += (newd,)
return renamed_dst
def setRenamedTree(self, renamed_dst, raw_tree, alwaysinfo):
for name, msb, lsb, ptr, part_msb, part_lsb in renamed_dst:
tree = raw_tree
if len(renamed_dst) > 1:
tree = reorder.reorder(
DFPartselect(tree, part_msb, part_lsb))
bind = Bind(tree, name, msb, lsb, ptr)
self.dataflow.addBind(name, bind)
value = self.optimize(tree)
if isinstance(value, DFEvalValue):
self.setConstant(name, value)
msb, lsb = self.getTermWidth(name)
self.setConstantTerm(name, Term(name, set(['Rename']), msb, lsb))
def setRenamedFlow(self, dst, renamed_dst, condlist, flowlist,
scope, alwaysinfo=None):
term_i = 0
for name, msb, lsb, ptr, part_msb, part_lsb in dst:
renamed_term = DFTerminal(renamed_dst[term_i][0])
renamed_bind = self.makeBind(name, msb, lsb, ptr, part_msb, part_lsb,
renamed_term, condlist, flowlist,
num_dst=len(dst), alwaysinfo=alwaysinfo)
self.dataflow.addBind(name, renamed_bind)
self.frames.setBlockingAssign(name, renamed_bind, scope)
term_i += 1
def makeBind(self, name, msb, lsb, ptr, part_msb, part_lsb,
raw_tree, condlist, flowlist,
num_dst=1, alwaysinfo=None, bindtype=None):
current_bindlist = self.getBindlist(name)
current_tree = None
current_msb = None
current_lsb = None
current_ptr = None
if len(current_bindlist) > 0:
for current_bind in current_bindlist:
if (current_bind.msb == msb and
current_bind.lsb == lsb
and current_bind.ptr == ptr ):
current_tree = current_bind.tree
current_msb = current_bind.msb
current_lsb = current_bind.lsb
current_ptr = current_bind.ptr
break
rest_tree = current_tree
rest_condlist = condlist
rest_flowlist = flowlist
match_flowlist = ()
if (current_msb == msb and
current_lsb == lsb
and current_ptr == ptr ):
(rest_tree,
rest_condlist,
rest_flowlist,
match_flowlist) = self.diffBranchTree(current_tree, condlist, flowlist)
add_tree = self.makeBranchTree(rest_condlist, rest_flowlist, raw_tree)
if rest_flowlist and rest_tree is not None:
_rest_flowlist = rest_flowlist[:-1] + (not rest_flowlist[-1], )
add_tree = self.appendBranchTree(add_tree, _rest_flowlist, rest_tree)
tree = reorder.reorder(
self.appendBranchTree(current_tree, match_flowlist, add_tree))
if num_dst > 1:
tree = reorder.reorder(
DFPartselect(tree, part_msb, part_lsb))
return Bind(tree, name, msb, lsb, ptr, alwaysinfo, bindtype)
def diffBranchTree(self, tree, condlist, flowlist, matchflowlist=()):
if len(condlist) == 0:
return (tree, condlist, flowlist, matchflowlist)
if not isinstance(tree, DFBranch):
return (tree, condlist, flowlist, matchflowlist)
if condlist[0] != tree.condnode:
return (tree, condlist, flowlist, matchflowlist)
if flowlist[0]:
return self.diffBranchTree(
tree.truenode, condlist[1:], flowlist[1:],
matchflowlist + (flowlist[0],))
else:
return self.diffBranchTree(
tree.falsenode, condlist[1:], flowlist[1:],
matchflowlist + (flowlist[0],))
def makeBranchTree(self, condlist, flowlist, node):
if len(condlist) == 0 or len(flowlist) == 0:
return node
if len(condlist) == 1:
if flowlist[0]:
return DFBranch(condlist[0], node, None)
else:
return DFBranch(condlist[0], None, node)
else:
if flowlist[0]:
return DFBranch(
condlist[0],
self.makeBranchTree(condlist[1:], flowlist[1:], node),
None)
else:
return DFBranch(
condlist[0],
None,
self.makeBranchTree(condlist[1:], flowlist[1:], node))
def appendBranchTree(self, base, pos, tree):
if len(pos) == 0:
return tree
if len(pos) == 1:
if pos[0]:
return DFBranch(base.condnode, tree, base.falsenode)
else:
return DFBranch(base.condnode, base.truenode, tree)
else:
if pos[0]:
return DFBranch(
base.condnode,
self.appendBranchTree(base.truenode, pos[1:], tree),
base.falsenode)
else:
return DFBranch(
base.condnode,
base.truenode,
self.appendBranchTree(base.falsenode, pos[1:], tree))