def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist, filename, withcolor=False): self.topmodule = topmodule self.terms = terms self.binddict = binddict self.resolved_terms = resolved_terms self.resolved_binddict = resolved_binddict self.graph = pgv.AGraph( directed=True) # pgv.AGraph(strict=False, directed=True) self.filename = filename self.withcolor = withcolor self.renamecounter = 0 self.identical = False self.treewalker = VerilogDataflowWalker(self.topmodule, self.terms, self.binddict, self.resolved_terms, self.resolved_binddict, constlist) self.optimizer = VerilogOptimizer(terms, constlist)
def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist): self.topmodule = topmodule self.terms = terms self.binddict = binddict self.resolved_terms = resolved_terms self.resolved_binddict = resolved_binddict self.constlist = constlist self.optimizer = VerilogOptimizer(terms, constlist)
def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist): self.topmodule = topmodule self.terms = terms self.binddict = binddict self.resolved_terms = resolved_terms self.resolved_binddict = resolved_binddict self.constlist = constlist self.optimizer = VerilogOptimizer(terms, constlist)
def __init__(self, moduleinfotable, top): self.moduleinfotable = moduleinfotable self.top = top self.frames = FrameTable() self.labels = Labels() self.optimizer = VerilogOptimizer({}, {}) # set the top frame of top module self.stackInstanceFrame(top, top)
def __init__(self, moduleinfotable, top): self.moduleinfotable = moduleinfotable self.top = top self.frames = FrameTable() self.labels = Labels() self.optimizer = VerilogOptimizer({}, {}) # set the top frame of top module self.stackInstanceFrame(top, top)
def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist, filename, withcolor=False): self.topmodule = topmodule self.terms = terms self.binddict = binddict self.resolved_terms = resolved_terms self.resolved_binddict = resolved_binddict self.graph = pgv.AGraph(directed=True) #pgv.AGraph(strict=False, directed=True) self.filename = filename self.withcolor = withcolor self.renamecounter = 0 self.identical = False self.treewalker = VerilogDataflowWalker(self.topmodule, self.terms, self.binddict, self.resolved_terms, self.resolved_binddict, constlist) self.optimizer = VerilogOptimizer(terms, constlist)
class VerilogGraphGenerator(object): def visit(self, node, parent, color='black', edge_label=None): method = 'visit_' + node.__class__.__name__ visitor = getattr(self, method, self.generic_visit) return visitor(node, parent, color=color, edge_label=edge_label) def generic_visit(self, node, parent, color='black', edge_label=None): if node is None: return for c in node.children(): self.visit(c, parent, color=color, edge_label=edge_label) def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist, filename, withcolor=False): self.topmodule = topmodule self.terms = terms self.binddict = binddict self.resolved_terms = resolved_terms self.resolved_binddict = resolved_binddict self.graph = pgv.AGraph(directed=True) # pgv.AGraph(strict=False, directed=True) self.filename = filename self.withcolor = withcolor self.renamecounter = 0 self.identical = False self.treewalker = VerilogDataflowWalker(self.topmodule, self.terms, self.binddict, self.resolved_terms, self.resolved_binddict, constlist) self.optimizer = VerilogOptimizer(terms, constlist) def generate(self, signalname, identical=False, walk=True, step=1, do_reorder=False, delay=False): termname = util.toTermname(signalname) tree = self.treewalker.getTree(termname) if tree is None: raise verror.DefinitionError('No such signals: %s' % str(signalname)) if walk: tree = self.treewalker.walkTree(tree, visited=set(), step=step, delay=delay) if do_reorder: tree = reorder.reorder(tree) tree = self.optimizer.optimize(tree) if do_reorder: tree = reorder.reorder(tree) tree = replace.replaceUndefined(tree, termname) name = self.rename(signalname) self.identical = identical self.add_node(name, label=signalname) self.visit(tree, name) def draw(self, filename=None): fn = filename if fn is None: fn = self.filename self.graph.write('file.dot') self.graph.layout(prog='dot') self.graph.draw(fn) def visit_DFOperator(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) self.generic_visit(node, name, color=color, edge_label=None) def visit_DFPartselect(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) if node.var is not None: self.visit(node.var, name, color=color, edge_label='VAR') if node.msb is not None: self.visit(node.msb, name, color='orange', edge_label='MSB') if node.lsb is not None: self.visit(node.lsb, name, color='orange', edge_label='LSB') def visit_DFPointer(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) if node.var is not None: self.visit(node.var, name, color=color, edge_label='VAR') if node.ptr is not None: self.visit(node.ptr, name, color='orange', edge_label='PTR') def visit_DFConcat(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) self.generic_visit(node, name, color=color) def visit_DFBranch(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) if node.condnode is not None: self.visit(node.condnode, name, color='blue', edge_label='COND') if node.truenode is not None: self.visit(node.truenode, name, color='green', edge_label='TRUE') if node.falsenode is not None: self.visit(node.falsenode, name, color='red', edge_label='FALSE') def visit_DFTerminal(self, node, parent, color='black', edge_label=None): if self.identical: self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) else: self.add_DF(node, parent, color=color, edge_label=edge_label) def visit_DFIntConst(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFFloatConst(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFStringConst(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFEvalValue(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFUndefined(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFHighImpedance(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFDelay(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) if node.nextnode is not None: self.visit(node.nextnode, name, color=color) def add_DF(self, node, parent, color='black', edge_label=None): #name = node.__repr__() name = node.tolabel() self.add_node(name, color=color) if edge_label: self.add_edge(parent, name, color=color, label=edge_label) else: self.add_edge(parent, name, color=color) return name def add_RenamedDF(self, node, parent, color='black', edge_label=None): #mylabel = node.__repr__() mylabel = node.tolabel() name = self.rename(mylabel) self.add_node(name, label=mylabel, color=color) if edge_label: self.add_edge(parent, name, color=color, label=edge_label) else: self.add_edge(parent, name, color=color) return name def rename(self, name): ret = name + '_graphrename_' + str(self.renamecounter) self.renamecounter += 1 return ret def add_node(self, node, label=None, color='black'): if not self.withcolor: color = 'black' if label is None: self.graph.add_node(str(node), color=color) else: self.graph.add_node(str(node), label=label, color=color) def add_edge(self, start, end, color='black', label=None): if not self.withcolor: color = 'black' if label: self.graph.add_edge(str(start), str(end), color=color, label=label) else: self.graph.add_edge(str(start), str(end), color=color)
class VerilogDataflowMerge(object): def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist): self.topmodule = topmodule self.terms = terms self.binddict = binddict self.resolved_terms = resolved_terms self.resolved_binddict = resolved_binddict self.constlist = constlist self.optimizer = VerilogOptimizer(terms, constlist) ############################################################################ def getTerm(self, termname): if not termname in self.terms: return None return self.terms[termname] def getBindlist(self, termname): if not termname in self.binddict: return () return self.binddict[termname] def getResolvedTerm(self, termname): if not termname in self.resolved_terms: return None return self.resolved_terms[termname] def getResolvedBindlist(self, termname): if not termname in self.resolved_binddict: return () return self.resolved_binddict[termname] ############################################################################ def getTermtype(self, termname): term = self.getTerm(termname) if term is None: raise verror.DefinitionError('No such Term: %s' % termname) return term.termtype ############################################################################ def getAssignType(self, termname, bind): termtype = self.getTermtype(termname) if signaltype.isWire(termtype): return 'assign' if signaltype.isWireArray(termtype): return 'assign' if signaltype.isReg(termtype): if bind.isClockEdge(): return 'clockedge' return 'combination' if signaltype.isRegArray(termtype): if bind.isClockEdge(): return 'clockedge' return 'combination' if signaltype.isInteger(termtype): if bind.isClockEdge(): return 'clockedge' return 'combination' if signaltype.isParameter(termtype): return 'parameter' if signaltype.isLocalparam(termtype): return 'localparam' if signaltype.isOutput(termtype): return 'assign' if signaltype.isInput(termtype): return 'assign' if signaltype.isFunction(termtype): return 'assign' if signaltype.isRename(termtype): return 'assign' if signaltype.isGenvar(termtype): return 'genvar' raise verror.DefinitionError('Unexpected Assignment Type: %s : %s' % (str(termname), str(termtype))) ############################################################################ def isCombination(self,termname): bindlist = self.getBindlist(termname) if bindlist is None: return False for bind in bindlist: if bind.isCombination(): return True return False ############################################################################ def getTree(self, termname, ptr=None): bindlist = self.getResolvedBindlist(termname) bindlist = self.getOptimizedBindlist(bindlist) if bindlist is None: return None if len(bindlist) == 0: return None termtype = self.getTermtype(termname) if signaltype.isRegArray(termtype) or signaltype.isWireArray(termtype): discretebinds = {} for bind in bindlist: if isinstance(bind.ptr, DFEvalValue): ptrval = bind.ptr.value if not ptrval in discretebinds: discretebinds[ptrval] = [] discretebinds[ptrval] += [bind] else: if not 'any' in discretebinds: discretebinds['any'] = [] discretebinds['any'] += [bind] if 'any' in discretebinds: return DFTerminal(termname) if isinstance(ptr, DFEvalValue): if len(discretebinds[ptr.value]) == 0: return None if len(discretebinds[ptr.value]) == 1: return discretebinds[ptr.value][0].tree return self.getMergedTree(discretebinds[ptr.value]) minptr = min(list(discretebinds.keys())) maxptr = max(list(discretebinds.keys())) ret = None for c in range(minptr, maxptr+1): truetree = None if len(discretebinds[c]) == 0: continue if len(discretebinds[c]) == 1: truetree = discretebinds[c][0].tree else: truetree = self.getMergedTree(discretebinds[c]) ret = DFBranch(DFOperator((DFEvalValue(c), ptr),'Eq'), truetree, ret) return ret if len(bindlist) == 1: return bindlist[0].tree new_tree = self.getMergedTree(bindlist) return self.optimizer.optimize(new_tree) def getResolvedTree(self, termname, ptr=None): raise verror.ImplementationError() ############################################################################ def isClockEdge(self, termname, msb=None, lsb=None, ptr=None): bind = self.binddict[termname] return bind[0].isClockEdge() ############################################################################ def getSources(self, tree): if tree is None: return set() if isinstance(tree, DFConstant): return set() if isinstance(tree, DFUndefined): return set() if isinstance(tree, DFEvalValue): return set() if isinstance(tree, DFTerminal): return set( [tree.name,] ) if isinstance(tree, DFBranch): ret = set() ret |= self.getSources(tree.condnode) ret |= self.getSources(tree.truenode) ret |= self.getSources(tree.falsenode) return ret if isinstance(tree, DFOperator): nextnodes = [] for n in tree.nextnodes: nextnodes.extend(self.getSources(n)) return set(nextnodes) if isinstance(tree, DFPartselect): ret = set() ret |= self.getSources(tree.var) ret |= self.getSources(tree.msb) ret |= self.getSources(tree.lsb) return ret if isinstance(tree, DFPointer): ret = set() ret |= self.getSources(tree.var) ret |= self.getSources(tree.ptr) return ret if isinstance(tree, DFConcat): nextnodes = [] for n in tree.nextnodes: nextnodes.extend(self.getSources(n)) return set(nextnodes) if isinstance(tree, DFDelay): ret = set() ret |= self.getSources(tree.nextnode) return ret raise verror.DefinitionError('Undefined Node Type: %s : %s' % (str(type(tree)), str(tree))) ################################################################################ def getBindSources(self, termname): sources = set() sources |= self.getTermSources(termname) sources |= self.getBindinfoSources(termname) return sources ################################################################################ def getTermSources(self, termname): term = self.getTerm(termname) if term is None: return set() sources = set() sources |= self.getTreeSources(term.msb) sources |= self.getTreeSources(term.lsb) sources |= self.getTreeSources(term.lenmsb) sources |= self.getTreeSources(term.lenlsb) return sources def getBindinfoSources(self, termname): bindlist = self.getBindlist(termname) sources = set() for bind in bindlist: sources |= self.getTreeSources(bind.msb) sources |= self.getTreeSources(bind.lsb) sources |= self.getTreeSources(bind.ptr) sources |= self.getTreeSources(bind.tree) return sources def getTreeSources(self, tree): if tree is None: return set() if isinstance(tree, DFConstant): return set() if isinstance(tree, DFUndefined): return set() if isinstance(tree, DFEvalValue): return set() if isinstance(tree, DFTerminal): return set( [tree.name,] ) if isinstance(tree, DFBranch): ret = set() ret |= self.getTreeSources(tree.condnode) ret |= self.getTreeSources(tree.truenode) ret |= self.getTreeSources(tree.falsenode) return ret if isinstance(tree, DFOperator): ret = set() for n in tree.nextnodes: ret |= self.getTreeSources(n) return ret if isinstance(tree, DFPartselect): ret = set() ret |= self.getTreeSources(tree.var) ret |= self.getTreeSources(tree.msb) ret |= self.getTreeSources(tree.lsb) return ret if isinstance(tree, DFPointer): ret = set() ret |= self.getTreeSources(tree.var) ret |= self.getTreeSources(tree.ptr) return ret if isinstance(tree, DFConcat): ret = set() for n in tree.nextnodes: ret |= self.getTreeSources(n) return ret raise verror.DefinitionError('Undefined Node Type: %s : %s' % (str(type(tree)), str(tree))) ################################################################################ def getMergedTree(self, optimized_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.optimizer.optimize(term.msb).value - self.optimizer.optimize(term.lsb).value) + 1 return ptr * length + lsb for bind in sorted(optimized_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 getOptimizedBindlist(self, bindlist): if len(bindlist) == 0: return () new_bindlist = [] for bind in bindlist: tree = self.optimizer.optimize(bind.tree) msb = self.optimizer.optimize(bind.msb) lsb = self.optimizer.optimize(bind.lsb) ptr = self.optimizer.optimize(bind.ptr) new_bind = copy.deepcopy(bind) new_bind.tree = tree new_bind.msb = msb new_bind.lsb = lsb new_bind.ptr = ptr new_bindlist.append(new_bind) if len(new_bindlist) == 1: return (new_bindlist[0],) split_positions = self.splitPositions(tuple(new_bindlist)) new_bindlist = self.splitBindlist(tuple(new_bindlist), split_positions) return self.mergeBindlist(tuple(new_bindlist)) def mergeBindlist(self, bindlist): merged_bindlist = [] last_bind = None 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.optimizer.optimize(term.msb).value - self.optimizer.optimize(term.lsb).value) + 1 return ptr * length + lsb for bind in sorted(bindlist, key=bindkey): if last_bind is None: merged_bindlist.append(copy.deepcopy(bind)) last_bind = copy.deepcopy(bind) elif isinstance(last_bind.ptr, DFEvalValue) and isinstance(bind.ptr, DFEvalValue) and last_bind.ptr.value != bind.ptr.value: merged_bindlist.append(copy.deepcopy(bind)) last_bind = copy.deepcopy(bind) elif last_bind.lsb is None or bind.lsb is None or last_bind is None or bind.msb is None: merged_bindlist.append(copy.deepcopy(bind)) last_bind = copy.deepcopy(bind) elif last_bind.lsb.value == bind.lsb.value and last_bind.msb.value == bind.msb.value: new_tree = self.mergeTree(last_bind.tree, bind.tree) new_tree = self.optimizer.optimize(new_tree) merged_bindlist.pop() new_bind = copy.deepcopy(bind) new_bind.tree = new_tree merged_bindlist.append(new_bind) last_bind = copy.deepcopy(new_bind) else: merged_bindlist.append(copy.deepcopy(bind)) last_bind = copy.deepcopy(bind) return tuple(merged_bindlist) def mergeTree(self, first, second): if isinstance(first, DFBranch) and isinstance(second, DFBranch): cond_fst = self.optimizer.optimize(first.condnode) cond_snd = self.optimizer.optimize(second.condnode) if cond_fst == cond_snd: return DFBranch(cond_fst, self.mergeTree(first.truenode, second.truenode), self.mergeTree(first.falsenode, second.falsenode)) appended = copy.deepcopy(first) return DFBranch(cond_snd, self.appendTail(appended, second.truenode), self.appendTail(appended, second.falsenode)) if first is not None and second is None: return first if first is None and second is not None: return second if isinstance(first, DFBranch) and second is None: return first if first is None and isinstance(second, DFBranch): return second if isinstance(first, DFBranch) and not isinstance(second, DFBranch): cond_fst = self.optimizer.optimize(first.condnode) appended = copy.deepcopy(second) return DFBranch(cond_fst, self.appendTail(appended, first.truenode), self.appendTail(appended, first.falsenode)) if not isinstance(first, DFBranch) and isinstance(second, DFBranch): cond_snd = self.optimizer.optimize(second.condnode) appended = copy.deepcopy(first) return DFBranch(cond_snd, self.appendTail(appended, second.truenode), self.appendTail(appended, second.falsenode)) if not isinstance(first, DFBranch) and not isinstance(second, DFBranch): return second raise verror.FormatError('Can not merge trees.') def appendTail(self, appended, target): if target is None: return copy.deepcopy(appended) if isinstance(target, DFBranch): return DFBranch(target.condnode, self.appendTail(appended, target.truenode), self.appendTail(appended, target.falsenode)) return target def splitBindlist(self, bindlist, split_positions): if len(bindlist) == 0: return () return self.splitBindPositions(bindlist[0], split_positions) + self.splitBindlist(bindlist[1:], split_positions) def splitBindPositions(self, bind, split_positions): if len(split_positions) == 0: return (copy.deepcopy(bind),) if bind is None: return (copy.deepcopy(bind),) bind_left, bind_right = self.splitBind(bind, split_positions[0]) ret = () if bind_right is None else (bind_right,) return ret + self.splitBindPositions(bind_left, split_positions[1:]) def splitBind(self, bind, splitpos): tree = bind.tree msb = self.optimizer.optimizeConstant(bind.msb) lsb = self.optimizer.optimizeConstant(bind.lsb) ptr = self.optimizer.optimizeConstant(bind.ptr) if ptr is not None and msb is None or lsb is None: termtype = self.getTermtype(bind.dest) if signaltype.isRegArray(termtype) or signaltype.isWireArray(termtype): msb = self.optimizer.optimizeConstant(copy.deepcopy(term.msb)) lsb = self.optimizer.optimizeConstant(copy.deepcopy(term.lsb)) else: msb = copy.deepcopy(ptr) lsb = copy.deepcopy(ptr) if ptr is None and msb is None or lsb is None: term = self.getTerm(bind.dest) msb = self.optimizer.optimizeConstant(copy.deepcopy(term.msb)) lsb = self.optimizer.optimizeConstant(copy.deepcopy(term.lsb)) if splitpos > lsb.value and splitpos <= msb.value: # split right_lsb = lsb.value right_msb = splitpos - 1 right_width = splitpos - lsb.value left_lsb = splitpos left_msb = msb.value left_width = msb.value - splitpos + 1 right_tree = reorder.reorder(DFPartselect(copy.deepcopy(tree), DFEvalValue(right_width-1), DFEvalValue(0))) left_tree = reorder.reorder(DFPartselect(copy.deepcopy(tree), DFEvalValue(msb.value), DFEvalValue(msb.value-left_width+1))) right_tree = self.optimizer.optimize(right_tree) left_tree = self.optimizer.optimize(left_tree) left_bind = copy.deepcopy(bind) left_bind.tree = left_tree left_bind.msb = DFEvalValue(left_msb) left_bind.lsb = DFEvalValue(left_lsb) right_bind = copy.deepcopy(bind) right_bind.tree = right_tree right_bind.msb = DFEvalValue(right_msb) right_bind.lsb = DFEvalValue(right_lsb) return left_bind, right_bind return bind, None def splitPositions(self, bindlist): split_positions = set([]) assigned_range = [] # (msb, lsb, ptr) for bind in bindlist: ptr = self.optimizer.optimizeConstant(bind.ptr) msb = self.optimizer.optimizeConstant(bind.msb) lsb = self.optimizer.optimizeConstant(bind.lsb) if msb is None and lsb is None: term = self.getTerm(bind.dest) msb = self.optimizer.optimizeConstant(term.msb) lsb = self.optimizer.optimizeConstant(term.lsb) elif not isinstance(msb, DFEvalValue) or not isinstance(lsb, DFEvalValue): raise FormatError('MSB and LSB should be constant.') if ptr is None or isinstance(ptr, DFEvalValue): ptrval = None if ptr is None else ptr.value matched_range = self.matchedRange(tuple(assigned_range), msb.value, lsb.value, ptrval) unmatched_range = self.unmatchedRange(tuple(matched_range), msb.value, lsb.value, ptrval) split_positions |= self.getPositionsFromRange(matched_range, ptrval) assigned_range += matched_range + unmatched_range return tuple(sorted(list(split_positions))) def getPositionsFromRange(self, matched_range, search_ptr): positions = set([]) for msb, lsb, ptr in matched_range: if search_ptr is not None and search != ptr: continue positions.add(lsb) positions.add(msb+1) return positions def matchedRange(self, assigned_range, search_msb, search_lsb, search_ptr): matched_range = [] for msb, lsb, ptr in assigned_range: match = False if search_ptr is not None and ptr != search_ptr: continue if lsb <= search_lsb and search_lsb <= msb: match = True match_lsb = search_lsb else: match_lsb = lsb if lsb <= search_msb and search_msb <= msb: match = True match_msb = search_msb else: match_msb = msb if match: matched_range.append( (match_msb, match_lsb, search_ptr) ) return tuple(matched_range) def unmatchedRange(self, matched_range, search_msb, search_lsb, search_ptr): unmatched_range = [] minval = None maxval = None last_msb = None for msb, lsb, ptr in sorted(matched_range, key=lambda x:x[0]): if search_ptr is not None and ptr != search_ptr: continue if minval is None or lsb < minval: minval = lsb if maxval is None or msb > maxval: maxval = msb if last_msb is not None and last_msb + 1 > lsb: unmatched_range.append( (last_msb + 1, lsb - 1, ptr) ) last_msb = msb if minval is None and maxval is None: return ( (search_msb, search_lsb, search_ptr), ) if search_lsb < minval: unmatched_range.append( (search_lsb, minval - 1, search_ptr) ) if maxval < search_msb: unmatched_range.append( (maxval + 1, search_msb, search_ptr) ) return tuple(unmatched_range)
class VerilogGraphGenerator(object): def visit(self, node, parent, color='black', edge_label=None): method = 'visit_' + node.__class__.__name__ visitor = getattr(self, method, self.generic_visit) return visitor(node, parent, color=color, edge_label=edge_label) def generic_visit(self, node, parent, color='black', edge_label=None): if node is None: return for c in node.children(): self.visit(c, parent, color=color, edge_label=edge_label) def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist, filename, withcolor=False): self.topmodule = topmodule self.terms = terms self.binddict = binddict self.resolved_terms = resolved_terms self.resolved_binddict = resolved_binddict self.graph = pgv.AGraph(directed=True) #pgv.AGraph(strict=False, directed=True) self.filename = filename self.withcolor = withcolor self.renamecounter = 0 self.identical = False self.treewalker = VerilogDataflowWalker(self.topmodule, self.terms, self.binddict, self.resolved_terms, self.resolved_binddict, constlist) self.optimizer = VerilogOptimizer(terms, constlist) def generate(self, signalname, identical=False, walk=True, step=1, reorder=False, delay=False): termname = util.toTermname(signalname) tree = self.treewalker.getTree(termname) if tree is None: raise verror.DefinitionError('No such signals: %s' % str(signalname)) if walk: tree = self.treewalker.walkTree(tree, visited=set(), step=step, delay=delay) if reorder: tree = reorder.reorder(tree) tree = self.optimizer.optimize(tree) if reorder: tree = reorder.reorder(tree) tree = replace.replaceUndefined(tree, termname) name = self.rename(signalname) self.identical = identical self.add_node(name, label=signalname) self.visit(tree, name) def draw(self, filename=None): fn = filename if fn is None: fn = self.filename self.graph.write('file.dot') self.graph.layout(prog='dot') self.graph.draw(fn) ############################################################################ def visit_DFOperator(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) self.generic_visit(node, name, color=color, edge_label=None) def visit_DFPartselect(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) if node.var is not None: self.visit(node.var, name, color=color, edge_label='VAR') if node.msb is not None: self.visit(node.msb, name, color='orange', edge_label='MSB') if node.lsb is not None: self.visit(node.lsb, name, color='orange', edge_label='LSB') def visit_DFPointer(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) if node.var is not None: self.visit(node.var, name, color=color, edge_label='VAR') if node.ptr is not None: self.visit(node.ptr, name, color='orange', edge_label='PTR') def visit_DFConcat(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) self.generic_visit(node, name, color=color) def visit_DFBranch(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) if node.condnode is not None: self.visit(node.condnode, name, color='blue', edge_label='COND') if node.truenode is not None: self.visit(node.truenode, name, color='green', edge_label='TRUE') if node.falsenode is not None: self.visit(node.falsenode, name, color='red', edge_label='FALSE') def visit_DFTerminal(self, node, parent, color='black', edge_label=None): if self.identical: self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) else: self.add_DF(node, parent, color=color, edge_label=edge_label) def visit_DFIntConst(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFFloatConst(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFStringConst(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFEvalValue(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFUndefined(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFHighImpedance(self, node, parent, color='black', edge_label=None): self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) def visit_DFDelay(self, node, parent, color='black', edge_label=None): name = self.add_RenamedDF(node, parent, color=color, edge_label=edge_label) if node.nextnode is not None: self.visit(node.nextnode, name, color=color) ############################################################################ def add_DF(self, node, parent, color='black', edge_label=None): #name = node.__repr__() name = node.tolabel() self.add_node(name, color=color) if edge_label: self.add_edge(parent, name, color=color, label=edge_label) else: self.add_edge(parent, name, color=color) return name def add_RenamedDF(self, node, parent, color='black', edge_label=None): #mylabel = node.__repr__() mylabel = node.tolabel() name = self.rename(mylabel) self.add_node(name, label=mylabel, color=color) if edge_label: self.add_edge(parent, name, color=color, label=edge_label) else: self.add_edge(parent, name, color=color) return name ############################################################################ def rename(self, name): ret = name + '_graphrename_' + str(self.renamecounter) self.renamecounter += 1 return ret ############################################################################ def add_node(self, node, label=None, color='black'): if not self.withcolor: color='black' if label is None: self.graph.add_node(str(node), color=color) else: self.graph.add_node(str(node), label=label, color=color) def add_edge(self, start, end, color='black', label=None): if not self.withcolor: color='black' if label: self.graph.add_edge(str(start), str(end), color=color, label=label) else: self.graph.add_edge(str(start), str(end), color=color)
class VerilogDataflowMerge(object): def __init__(self, topmodule, terms, binddict, resolved_terms, resolved_binddict, constlist): self.topmodule = topmodule self.terms = terms self.binddict = binddict self.resolved_terms = resolved_terms self.resolved_binddict = resolved_binddict self.constlist = constlist self.optimizer = VerilogOptimizer(terms, constlist) ############################################################################ def getTerm(self, termname): if isinstance(termname, str): for scope in self.terms.keys(): if termname == str(scope): return self.terms[scope] if not termname in self.terms: return None return self.terms[termname] def getBindlist(self, termname): if not termname in self.binddict: return () return self.binddict[termname] def getResolvedTerm(self, termname): if not termname in self.resolved_terms: return None return self.resolved_terms[termname] def getResolvedBindlist(self, termname): if not termname in self.resolved_binddict: return () return self.resolved_binddict[termname] ############################################################################ def getTermtype(self, termname): term = self.getTerm(termname) if term is None: raise verror.DefinitionError('No such Term: %s' % termname) return term.termtype ############################################################################ def getAssignType(self, termname, bind): termtype = self.getTermtype(termname) if signaltype.isWire(termtype): return 'assign' if signaltype.isWireArray(termtype): return 'assign' if signaltype.isReg(termtype): if bind.isClockEdge(): return 'clockedge' return 'combination' if signaltype.isRegArray(termtype): if bind.isClockEdge(): return 'clockedge' return 'combination' if signaltype.isInteger(termtype): if bind.isClockEdge(): return 'clockedge' return 'combination' if signaltype.isParameter(termtype): return 'parameter' if signaltype.isLocalparam(termtype): return 'localparam' if signaltype.isOutput(termtype): return 'assign' if signaltype.isInput(termtype): return 'assign' if signaltype.isFunction(termtype): return 'assign' if signaltype.isRename(termtype): return 'assign' if signaltype.isGenvar(termtype): return 'genvar' raise verror.DefinitionError('Unexpected Assignment Type: %s : %s' % (str(termname), str(termtype))) ############################################################################ def isCombination(self, termname): bindlist = self.getBindlist(termname) if bindlist is None: return False for bind in bindlist: if bind.isCombination(): return True return False ############################################################################ def getTree(self, termname, ptr=None): bindlist = self.getResolvedBindlist(termname) bindlist = self.getOptimizedBindlist(bindlist) if bindlist is None: return None if len(bindlist) == 0: return None termtype = self.getTermtype(termname) if signaltype.isRegArray(termtype) or signaltype.isWireArray(termtype): discretebinds = {} for bind in bindlist: if isinstance(bind.ptr, DFEvalValue): ptrval = bind.ptr.value if not ptrval in discretebinds: discretebinds[ptrval] = [] discretebinds[ptrval] += [bind] else: if not 'any' in discretebinds: discretebinds['any'] = [] discretebinds['any'] += [bind] if 'any' in discretebinds: return DFTerminal(termname) if isinstance(ptr, DFEvalValue): if len(discretebinds[ptr.value]) == 0: return None if len(discretebinds[ptr.value]) == 1: return discretebinds[ptr.value][0].tree return self.getMergedTree(discretebinds[ptr.value]) minptr = min(list(discretebinds.keys())) maxptr = max(list(discretebinds.keys())) ret = None for c in range(minptr, maxptr + 1): truetree = None if len(discretebinds[c]) == 0: continue if len(discretebinds[c]) == 1: truetree = discretebinds[c][0].tree else: truetree = self.getMergedTree(discretebinds[c]) ret = DFBranch(DFOperator((DFEvalValue(c), ptr), 'Eq'), truetree, ret) return ret if len(bindlist) == 1: return bindlist[0].tree new_tree = self.getMergedTree(bindlist) return self.optimizer.optimize(new_tree) def getResolvedTree(self, termname, ptr=None): raise verror.ImplementationError() ############################################################################ def isClockEdge(self, termname, msb=None, lsb=None, ptr=None): bind = self.binddict[termname] return bind[0].isClockEdge() ############################################################################ def getSources(self, tree): if tree is None: return set() if isinstance(tree, DFConstant): return set() if isinstance(tree, DFUndefined): return set() if isinstance(tree, DFEvalValue): return set() if isinstance(tree, DFTerminal): return set([ tree.name, ]) if isinstance(tree, DFBranch): ret = set() ret |= self.getSources(tree.condnode) ret |= self.getSources(tree.truenode) ret |= self.getSources(tree.falsenode) return ret if isinstance(tree, DFOperator): nextnodes = [] for n in tree.nextnodes: nextnodes.extend(self.getSources(n)) return set(nextnodes) if isinstance(tree, DFPartselect): ret = set() ret |= self.getSources(tree.var) ret |= self.getSources(tree.msb) ret |= self.getSources(tree.lsb) return ret if isinstance(tree, DFPointer): ret = set() ret |= self.getSources(tree.var) ret |= self.getSources(tree.ptr) return ret if isinstance(tree, DFConcat): nextnodes = [] for n in tree.nextnodes: nextnodes.extend(self.getSources(n)) return set(nextnodes) if isinstance(tree, DFDelay): ret = set() ret |= self.getSources(tree.nextnode) return ret raise verror.DefinitionError('Undefined Node Type: %s : %s' % (str(type(tree)), str(tree))) ################################################################################ def getBindSources(self, termname): sources = set() sources |= self.getTermSources(termname) sources |= self.getBindinfoSources(termname) return sources ################################################################################ def getTermSources(self, termname): term = self.getTerm(termname) if term is None: return set() sources = set() sources |= self.getTreeSources(term.msb) sources |= self.getTreeSources(term.lsb) sources |= self.getTreeSources(term.lenmsb) sources |= self.getTreeSources(term.lenlsb) return sources def getBindinfoSources(self, termname): bindlist = self.getBindlist(termname) sources = set() for bind in bindlist: sources |= self.getTreeSources(bind.msb) sources |= self.getTreeSources(bind.lsb) sources |= self.getTreeSources(bind.ptr) sources |= self.getTreeSources(bind.tree) return sources def getTreeSources(self, tree): if tree is None: return set() if isinstance(tree, DFConstant): return set() if isinstance(tree, DFUndefined): return set() if isinstance(tree, DFEvalValue): return set() if isinstance(tree, DFTerminal): return set([ tree.name, ]) if isinstance(tree, DFBranch): ret = set() ret |= self.getTreeSources(tree.condnode) ret |= self.getTreeSources(tree.truenode) ret |= self.getTreeSources(tree.falsenode) return ret if isinstance(tree, DFOperator): ret = set() for n in tree.nextnodes: ret |= self.getTreeSources(n) return ret if isinstance(tree, DFPartselect): ret = set() ret |= self.getTreeSources(tree.var) ret |= self.getTreeSources(tree.msb) ret |= self.getTreeSources(tree.lsb) return ret if isinstance(tree, DFPointer): ret = set() ret |= self.getTreeSources(tree.var) ret |= self.getTreeSources(tree.ptr) return ret if isinstance(tree, DFConcat): ret = set() for n in tree.nextnodes: ret |= self.getTreeSources(n) return ret raise verror.DefinitionError('Undefined Node Type: %s : %s' % (str(type(tree)), str(tree))) ################################################################################ def getMergedTree(self, optimized_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.optimizer.optimize(term.msb).value - self.optimizer.optimize(term.lsb).value) + 1 return ptr * length + lsb for bind in sorted(optimized_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 getOptimizedBindlist(self, bindlist): if len(bindlist) == 0: return () new_bindlist = [] for bind in bindlist: tree = self.optimizer.optimize(bind.tree) msb = self.optimizer.optimize(bind.msb) lsb = self.optimizer.optimize(bind.lsb) ptr = self.optimizer.optimize(bind.ptr) new_bind = copy.deepcopy(bind) new_bind.tree = tree new_bind.msb = msb new_bind.lsb = lsb new_bind.ptr = ptr new_bindlist.append(new_bind) if len(new_bindlist) == 1: return (new_bindlist[0], ) split_positions = self.splitPositions(tuple(new_bindlist)) new_bindlist = self.splitBindlist(tuple(new_bindlist), split_positions) return self.mergeBindlist(tuple(new_bindlist)) def mergeBindlist(self, bindlist): merged_bindlist = [] last_bind = None 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.optimizer.optimize(term.msb).value - self.optimizer.optimize(term.lsb).value) + 1 return ptr * length + lsb for bind in sorted(bindlist, key=bindkey): if last_bind is None: merged_bindlist.append(copy.deepcopy(bind)) last_bind = copy.deepcopy(bind) elif isinstance(last_bind.ptr, DFEvalValue) and isinstance( bind.ptr, DFEvalValue) and last_bind.ptr.value != bind.ptr.value: merged_bindlist.append(copy.deepcopy(bind)) last_bind = copy.deepcopy(bind) elif last_bind.lsb is None or bind.lsb is None or last_bind is None or bind.msb is None: merged_bindlist.append(copy.deepcopy(bind)) last_bind = copy.deepcopy(bind) elif last_bind.lsb.value == bind.lsb.value and last_bind.msb.value == bind.msb.value: new_tree = self.mergeTree(last_bind.tree, bind.tree) new_tree = self.optimizer.optimize(new_tree) merged_bindlist.pop() new_bind = copy.deepcopy(bind) new_bind.tree = new_tree merged_bindlist.append(new_bind) last_bind = copy.deepcopy(new_bind) else: merged_bindlist.append(copy.deepcopy(bind)) last_bind = copy.deepcopy(bind) return tuple(merged_bindlist) def mergeTree(self, first, second): if isinstance(first, DFBranch) and isinstance(second, DFBranch): cond_fst = self.optimizer.optimize(first.condnode) cond_snd = self.optimizer.optimize(second.condnode) if cond_fst == cond_snd: return DFBranch( cond_fst, self.mergeTree(first.truenode, second.truenode), self.mergeTree(first.falsenode, second.falsenode)) appended = copy.deepcopy(first) return DFBranch(cond_snd, self.appendTail(appended, second.truenode), self.appendTail(appended, second.falsenode)) if first is not None and second is None: return first if first is None and second is not None: return second if isinstance(first, DFBranch) and second is None: return first if first is None and isinstance(second, DFBranch): return second if isinstance(first, DFBranch) and not isinstance(second, DFBranch): cond_fst = self.optimizer.optimize(first.condnode) appended = copy.deepcopy(second) return DFBranch(cond_fst, self.appendTail(appended, first.truenode), self.appendTail(appended, first.falsenode)) if not isinstance(first, DFBranch) and isinstance(second, DFBranch): cond_snd = self.optimizer.optimize(second.condnode) appended = copy.deepcopy(first) return DFBranch(cond_snd, self.appendTail(appended, second.truenode), self.appendTail(appended, second.falsenode)) if not isinstance(first, DFBranch) and not isinstance( second, DFBranch): return second raise verror.FormatError('Can not merge trees.') def appendTail(self, appended, target): if target is None: return copy.deepcopy(appended) if isinstance(target, DFBranch): return DFBranch(target.condnode, self.appendTail(appended, target.truenode), self.appendTail(appended, target.falsenode)) return target def splitBindlist(self, bindlist, split_positions): if len(bindlist) == 0: return () return self.splitBindPositions(bindlist[0], split_positions) + self.splitBindlist( bindlist[1:], split_positions) def splitBindPositions(self, bind, split_positions): if len(split_positions) == 0: return (copy.deepcopy(bind), ) if bind is None: return (copy.deepcopy(bind), ) bind_left, bind_right = self.splitBind(bind, split_positions[0]) ret = () if bind_right is None else (bind_right, ) return ret + self.splitBindPositions(bind_left, split_positions[1:]) def splitBind(self, bind, splitpos): tree = bind.tree msb = self.optimizer.optimizeConstant(bind.msb) lsb = self.optimizer.optimizeConstant(bind.lsb) ptr = self.optimizer.optimizeConstant(bind.ptr) if ptr is not None and msb is None or lsb is None: termtype = self.getTermtype(bind.dest) if signaltype.isRegArray(termtype) or signaltype.isWireArray( termtype): msb = self.optimizer.optimizeConstant(copy.deepcopy(term.msb)) lsb = self.optimizer.optimizeConstant(copy.deepcopy(term.lsb)) else: msb = copy.deepcopy(ptr) lsb = copy.deepcopy(ptr) if ptr is None and msb is None or lsb is None: term = self.getTerm(bind.dest) msb = self.optimizer.optimizeConstant(copy.deepcopy(term.msb)) lsb = self.optimizer.optimizeConstant(copy.deepcopy(term.lsb)) if splitpos > lsb.value and splitpos <= msb.value: # split right_lsb = lsb.value right_msb = splitpos - 1 right_width = splitpos - lsb.value left_lsb = splitpos left_msb = msb.value left_width = msb.value - splitpos + 1 right_tree = reorder.reorder( DFPartselect(copy.deepcopy(tree), DFEvalValue(right_width - 1), DFEvalValue(0))) left_tree = reorder.reorder( DFPartselect(copy.deepcopy(tree), DFEvalValue(msb.value), DFEvalValue(msb.value - left_width + 1))) right_tree = self.optimizer.optimize(right_tree) left_tree = self.optimizer.optimize(left_tree) left_bind = copy.deepcopy(bind) left_bind.tree = left_tree left_bind.msb = DFEvalValue(left_msb) left_bind.lsb = DFEvalValue(left_lsb) right_bind = copy.deepcopy(bind) right_bind.tree = right_tree right_bind.msb = DFEvalValue(right_msb) right_bind.lsb = DFEvalValue(right_lsb) return left_bind, right_bind return bind, None def splitPositions(self, bindlist): split_positions = set([]) assigned_range = [] # (msb, lsb, ptr) for bind in bindlist: ptr = self.optimizer.optimizeConstant(bind.ptr) msb = self.optimizer.optimizeConstant(bind.msb) lsb = self.optimizer.optimizeConstant(bind.lsb) if msb is None and lsb is None: term = self.getTerm(bind.dest) msb = self.optimizer.optimizeConstant(term.msb) lsb = self.optimizer.optimizeConstant(term.lsb) elif not isinstance(msb, DFEvalValue) or not isinstance( lsb, DFEvalValue): raise FormatError('MSB and LSB should be constant.') if ptr is None or isinstance(ptr, DFEvalValue): ptrval = None if ptr is None else ptr.value matched_range = self.matchedRange(tuple(assigned_range), msb.value, lsb.value, ptrval) unmatched_range = self.unmatchedRange(tuple(matched_range), msb.value, lsb.value, ptrval) split_positions |= self.getPositionsFromRange( matched_range, ptrval) assigned_range += matched_range + unmatched_range return tuple(sorted(list(split_positions))) def getPositionsFromRange(self, matched_range, search_ptr): positions = set([]) for msb, lsb, ptr in matched_range: if search_ptr is not None and search != ptr: continue positions.add(lsb) positions.add(msb + 1) return positions def matchedRange(self, assigned_range, search_msb, search_lsb, search_ptr): matched_range = [] for msb, lsb, ptr in assigned_range: match = False if search_ptr is not None and ptr != search_ptr: continue if lsb <= search_lsb and search_lsb <= msb: match = True match_lsb = search_lsb else: match_lsb = lsb if lsb <= search_msb and search_msb <= msb: match = True match_msb = search_msb else: match_msb = msb if match: matched_range.append((match_msb, match_lsb, search_ptr)) return tuple(matched_range) def unmatchedRange(self, matched_range, search_msb, search_lsb, search_ptr): unmatched_range = [] minval = None maxval = None last_msb = None for msb, lsb, ptr in sorted(matched_range, key=lambda x: x[0]): if search_ptr is not None and ptr != search_ptr: continue if minval is None or lsb < minval: minval = lsb if maxval is None or msb > maxval: maxval = msb if last_msb is not None and last_msb + 1 > lsb: unmatched_range.append((last_msb + 1, lsb - 1, ptr)) last_msb = msb if minval is None and maxval is None: return ((search_msb, search_lsb, search_ptr), ) if search_lsb < minval: unmatched_range.append((search_lsb, minval - 1, search_ptr)) if maxval < search_msb: unmatched_range.append((maxval + 1, search_msb, search_ptr)) return tuple(unmatched_range)
class SignalVisitor(NodeVisitor): def __init__(self, moduleinfotable, top): self.moduleinfotable = moduleinfotable self.top = top self.frames = FrameTable() self.labels = Labels() self.optimizer = VerilogOptimizer({}, {}) # set the top frame of top module self.stackInstanceFrame(top, top) ################################################################################ def getFrameTable(self): return self.frames ################################################################################ def start_visit(self): return self.visit(self.moduleinfotable.getDefinition(self.top)) def visit_Input(self, node): self.frames.addSignal(node) def visit_Output(self, node): self.frames.addSignal(node) def visit_Inout(self, node): self.frames.addSignal(node) def visit_Reg(self, node): self.frames.addSignal(node) def visit_Wire(self, node): self.frames.addSignal(node) def visit_Supply(self, node): self.frames.addSignal(node) def visit_RegArray(self, node): self.frames.addSignal(node) def visit_WireArray(self, node): self.frames.addSignal(node) def visit_Tri(self, node): self.frames.addSignal(node) def visit_Integer(self, node): self.frames.addSignal(node) def visit_Parameter(self, node): self.frames.addConst(node) name = self.frames.getCurrent() + ScopeLabel(node.name, 'signal') if not self.hasConstant(name): value = self.optimize(self.getTree(node.value, self.frames.getCurrent())) self.setConstant(name, value) def visit_Localparam(self, node): self.frames.addConst(node) name = self.frames.getCurrent() + ScopeLabel(node.name, 'signal') if not self.hasConstant(name): value = self.optimize(self.getTree(node.value, self.frames.getCurrent())) self.setConstant(name, value) def visit_Genvar(self, node): self.frames.addConst(node) name = self.frames.getCurrent() + ScopeLabel(node.name, 'signal') if not self.hasConstant(name): value = DFEvalValue(0) self.setConstant(name, value) def visit_Function(self, node): self.frames.addFunction(node) self.frames.setFunctionDef() self.generic_visit(node) self.frames.unsetFunctionDef() def visit_Task(self, node): self.frames.addTask(node) self.frames.setTaskDef() self.generic_visit(node) self.frames.unsetTaskDef() def visit_Initial(self, node): pass #label = self.labels.get( self.frames.getLabelKey('initial') ) #current = self.frames.addFrame(ScopeLabel(label, 'initial'), # generate=self.frames.isGenerate(), # initial=True) #self.generic_visit(node) #self.frames.setCurrent(current) 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 for i in range(lsb, msb+1): nodename = node.name + '_' + str(i) self._visit_Instance_body(node, nodename) def _visit_Instance_body(self, node, nodename): if node.module in primitives: return self._visit_Instance_primitive(node) if nodename == '': raise verror.FormatError("Module %s requires an instance name" % node.module) current = self.stackInstanceFrame(nodename, node.module) self.setInstanceSimpleConstantTerms() scope = self.frames.getCurrent() paramnames = self.moduleinfotable.getParamNames(node.module) for paramnames_i, param in enumerate(node.parameterlist): 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)) value = self.optimize(self.getTree(param.argname, current)) name, definition = self.searchConstantDefinition(scope, paramname) self.setConstant(name, value) self.setInstanceConstants() self.setInstanceConstantTerms() self.visit(self.moduleinfotable.getDefinition(node.module)) self.frames.setCurrent(current) def _visit_Instance_primitive(self, node): pass def visit_Always(self, node): label = self.labels.get( self.frames.getLabelKey('always') ) current = self.frames.addFrame(ScopeLabel(label, 'always'), generate=self.frames.isGenerate(), always=True) self.generic_visit(node) self.frames.setCurrent(current) def visit_IfStatement(self, node): 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) else: label = self.labels.get( self.frames.getLabelKey('if') ) self._if_false(node, label) return label = self._if_true(node) self._if_false(node, label) 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.frames.addFrame(ScopeLabel(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.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.frames.addFrame(ScopeLabel(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.visit(node.false_statement) self.frames.setCurrent(current) return label def visit_CaseStatement(self, node): start_frame = self.frames.getCurrent() self._case(node.comp, node.caselist) self.frames.setCurrent(start_frame) def visit_CasexStatement(self, node): return self.visit_CaseStatement(node) def _case(self, comp, caselist): 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]) label = self.labels.get( self.frames.getLabelKey('if') ) current = self.frames.addFrame(ScopeLabel(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()) 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.frames.addFrame(ScopeLabel(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._case(comp, caselist[1:]) def visit_ForStatement(self, node): ## 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 while True: ## cond-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 process the for-statement. " "for-condition should be evaluated statically.")) # loop termination if rslt.value <= 0: break ## main-statement current = self.frames.addFrame(ScopeLabel(label, 'for', loop), 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.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): pass def visit_GenerateStatement(self, node): label = self.labels.get( self.frames.getLabelKey('generate') ) current = self.frames.addFrame(ScopeLabel(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.frames.addFrame(ScopeLabel(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) def visit_Assign(self, node): pass def visit_BlockingSubstitution(self, node): if self.frames.isForpre() or self.frames.isForpost(): current = self.frames.getCurrent() name, definition = self.searchConstantDefinition(current, node.left.var.name) value = self.optimize(self.getTree(node.right.var, current)) self.setConstant(name, value) self.frames.setForIter(name) def visit_NonblockingSubstitution(self, node): pass ############################################################################ def optimize(self, node): return self.optimizer.optimize(node) def stackInstanceFrame(self, instname, modulename): current = self.frames.addFrame(ScopeLabel(instname, 'module'), module=True, modulename=modulename) self.frames.updateSignal(self.moduleinfotable.getSignals(modulename)) self.frames.updateConst(self.moduleinfotable.getConsts(modulename)) return current def setInstanceSimpleConstantTerms(self): current = self.frames.getCurrent() for name, definitions in self.frames.getConsts(current).items(): if len(definitions) > 1: raise verror.FormatError("Multiple definitions for Constant") for definition in definitions: simple_definition = copy.deepcopy(definition) if simple_definition.width is not None: simple_definition.width.msb = None simple_definition.width.lsb = None term = self.makeConstantTerm(name, simple_definition, current) self.setConstantTerm(name, term) def setInstanceConstantTerms(self): current = self.frames.getCurrent() for name, definitions in self.frames.getConsts(current).items(): if len(definitions) > 1: raise verror.FormatError("Multiple definitions for Constant") for definition in definitions: term = self.makeConstantTerm(name, definition, current) self.setConstantTerm(name, term) def setInstanceConstants(self): current = self.frames.getCurrent() 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 setConstant(self, name, value): self.optimizer.setConstant(name, value) 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 hasConstantTerm(self, name): self.optimizer.hasTerm(name) ############################################################################ def toScopeChain(self, blocklabel): scopelist = [] for b in blocklabel.labellist: if b.loop is not None: loop = self.optimize(b.loop) if not isinstance(loop, DFEvalValue): raise verror.FormatError('Loop iterator should be constant') scopelist.append( ScopeLabel(b.name, 'for', loop) ) scopelsit.append( ScopeLabel(b.name, 'any') ) return ScopeChain( scopelist ) def searchScopeConstantValue(self, blocklabel, name): currentmodule = self.frames.getCurrentModuleScopeChain() localchain = currentmodule[-1:] + self.toScopeChain(blocklabel) matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain) varname = currentmodule[:-1] + matchedchain + ScopeLabel(name, 'signal') const = self.getConstant(varname) return const #def searchScopeConstantDefinition(self, blocklabel, name): # currentmodule = self.frames.getCurrentModuleScopeChain() # localchain = currentmodule[-1:] + self.toScopeChain(blocklabel) # matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain) # constdef = self.frames.getConstantDefinition(matchedchain, name) # return constdef def searchConstantDefinition(self, key, name): foundkey, founddef = self.frames.searchConstantDefinition(key, name) if foundkey is not None: return foundkey + ScopeLabel(name, 'signal'), founddef foundkey, founddef = self.frames.searchSignalDefinition(key, name) if foundkey is not None: return foundkey + ScopeLabel(name, 'signal'), founddef if foundkey is None: raise verror.DefinitionError('constant value not found: %s' % name) def searchConstantValue(self, key, name): foundkey, founddef = self.searchConstantDefinition(key, name) const = self.getConstant(foundkey) return const ############################################################################ 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 getTree(self, node, scope): expr = node.var if isinstance(node, Rvalue) else node return self.makeDFTree(expr, scope) def makeDFTree(self, node, scope): if isinstance(node, str): return self.searchConstantValue(scope, node) if isinstance(node, Identifier): if node.scope is not None: const = self.searchScopeConstantValue(node.scope, node.name) return const return self.searchConstantValue(scope, node.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 (signaltype.isRegArray(self.getTermtype(var_df.name)) or signaltype.isWireArray(self.getTermtype(var_df.name)))): 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, SystemCall): if node.syscall == 'unsigned': return self.makeDFTree(node.args[0]) if node.syscall == 'signed': return self.makeDFTree(node.args[0]) return DFIntConst('0') raise verror.FormatError("unsupported AST node type: %s %s" % (str(type(node)), str(node)))