<s> from __future__ import absolute_import <EOL> from __future__ import print_function <EOL> import sys <EOL> import os <EOL> import pyverilog . utils . util as util <EOL> import pyverilog . utils . signaltype as signaltype <EOL> import pyverilog . dataflow . reorder as reorder <EOL> import pyverilog . dataflow . replace as replace <EOL> from pyverilog . dataflow . subset import VerilogSubset <EOL> from pyverilog . dataflow . walker import VerilogDataflowWalker <EOL> from pyverilog . dataflow . dataflow import * <EOL> import pyverilog . controlflow . splitter as splitter <EOL> import pyverilog . controlflow . transition as transition <EOL> class VerilogControlflowAnalyzer ( VerilogSubset ) : <EOL> def __init__ ( self , topmodule , terms , binddict , <EOL> resolved_terms , resolved_binddict , <EOL> constlist , fsm_vars = ( '<STR_LIT>' , '<STR_LIT:state>' , '<STR_LIT:count>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) ) : <EOL> VerilogSubset . __init__ ( self , topmodule , terms , binddict , <EOL> resolved_terms , resolved_binddict , constlist ) <EOL> self . treewalker = VerilogDataflowWalker ( topmodule , terms , binddict , <EOL> resolved_terms , resolved_binddict , constlist ) <EOL> self . fsm_vars = fsm_vars <EOL> def getLoops ( self ) : <EOL> fsms = self . getFiniteStateMachines ( ) <EOL> loops = { } <EOL> for signame , fsm in fsms . items ( ) : <EOL> loop_set = fsm . get_loop ( ) <EOL> if len ( loop_set ) == <NUM_LIT:0> : continue <EOL> if not signame in loops : loops [ signame ] = set ( [ ] ) <EOL> loops [ signame ] . update ( loop_set ) <EOL> return loops , fsms <EOL> def getFiniteStateMachines ( self ) : <EOL> statemachines = { } <EOL> for termname , bindlist in self . resolved_binddict . items ( ) : <EOL> if not self . isFsmVar ( termname ) : continue <EOL> funcdict , delaycnt = self . getFuncdict ( termname ) <EOL> if len ( funcdict ) > <NUM_LIT:0> : print ( "<STR_LIT>" % ( str ( termname ) , len ( funcdict ) ) ) <EOL> fsm = self . getFiniteStateMachine ( termname , funcdict ) <EOL> if fsm . size ( ) > <NUM_LIT:0> : <EOL> fsm . set_delaycnt ( delaycnt ) <EOL> fsm . resolve ( self . optimizer ) <EOL> statemachines [ termname ] = fsm <EOL> return statemachines <EOL> def getFiniteStateMachine ( self , termname , funcdict ) : <EOL> fsm = FiniteStateMachine ( util . toFlatname ( termname ) ) <EOL> if len ( funcdict ) == <NUM_LIT:0> : return fsm <EOL> width = self . getWidth ( termname ) <EOL> for condlist , func in sorted ( funcdict . items ( ) , key = lambda x : len ( x [ <NUM_LIT:0> ] ) ) : <EOL> if not isinstance ( func , DFEvalValue ) : continue <EOL> print ( "<STR_LIT>" % str ( condlist ) ) <EOL> node = transition . walkCondlist ( condlist , termname , width ) <EOL> if node is None : continue <EOL> statenode_list = node . nodelist if isinstance ( node , transition . StateNodeList ) else [ node , ] <EOL> for statenode in statenode_list : fsm . construct ( func . value , statenode ) <EOL> return fsm <EOL> def getFuncdict ( self , termname , delaycnt = <NUM_LIT:0> ) : <EOL> termtype = self . getTermtype ( termname ) <EOL> if not self . isClockEdge ( termname ) : return { } , <NUM_LIT:0> <EOL> if signaltype . isRename ( termtype ) : return { } , <NUM_LIT:0> <EOL> if signaltype . isRegArray ( termtype ) : return { } , <NUM_LIT:0> <EOL> tree = self . makeTree ( termname ) <EOL> funcdict = splitter . split ( tree ) <EOL> funcdict = splitter . remove_reset_condition ( funcdict ) <EOL> if len ( funcdict ) == <NUM_LIT:1> and len ( funcdict . keys ( ) [ <NUM_LIT:0> ] ) == <NUM_LIT:0> : <EOL> next_term = funcdict . values ( ) [ <NUM_LIT:0> ] <EOL> if isinstance ( next_term , DFTerminal ) : <EOL> return self . getFuncdict ( next_term . name , delaycnt + <NUM_LIT:1> ) <EOL> return funcdict , delaycnt <EOL> def isFsmVar ( self , termname ) : <EOL> for v in self . fsm_vars : <EOL> if re . search ( v . lower ( ) , str ( termname ) . lower ( ) ) : return True <EOL> return False <EOL> def getWidth ( self , termname ) : <EOL> term = self . getTerm ( termname ) <EOL> msb = self . optimizer . optimizeConstant ( term . msb ) <EOL> lsb = self . optimizer . optimizeConstant ( term . lsb ) <EOL> width = DFIntConst ( '<STR_LIT>' ) <EOL> if msb is not None and lsb is not None : <EOL> return abs ( self . optimizer . optimizeConstant ( DFOperator ( ( msb , lsb ) , '<STR_LIT>' ) ) . value ) + <NUM_LIT:1> <EOL> return self . optimizer . optimizeConstant ( width ) . value <EOL> def makeTree ( self , termname ) : <EOL> tree = self . getTree ( termname ) <EOL> tree = self . treewalker . walkTree ( tree ) <EOL> tree = reorder . reorder ( tree ) <EOL> tree = self . optimizer . optimize ( tree ) <EOL> tree = replace . replaceUndefined ( tree , termname ) <EOL> return tree <EOL> class FiniteStateMachine ( object ) : <EOL> def __init__ ( self , name ) : <EOL> self . name = name <EOL> self . fsm = { } <EOL> self . any = { } <EOL> self . delaycnt = <NUM_LIT:0> <EOL> def set_delaycnt ( self , delaycnt ) : <EOL> self . delaycnt = delaycnt <EOL> def size ( self ) : <EOL> dstlen = <NUM_LIT:0> <EOL> for src , dstdict in self . fsm . items ( ) : <EOL> dstlen += len ( dstdict ) <EOL> srcs = self . fsm . keys ( ) <EOL> dstlen += len ( srcs ) * len ( self . any ) <EOL> return dstlen <EOL> def label_range ( self ) : <EOL> minval = None <EOL> maxval = None <EOL> for src , dstdict in self . fsm . items ( ) : <EOL> if minval is None : minval = src <EOL> elif src < minval : minval = src <EOL> if maxval is None : maxval = src <EOL> elif src > maxval : maxval = src <EOL> for cond , dst in dstdict . items ( ) : <EOL> if minval is None : minval = dst <EOL> elif dst < minval : minval = dst <EOL> if maxval is None : maxval = dst <EOL> elif dst > maxval : maxval = dst <EOL> return ( minval , maxval ) <EOL> def construct ( self , dst , node ) : <EOL> if node is None : return <EOL> if node . isany : <EOL> transcond = node . transcond <EOL> self . add_any ( dst , transcond ) <EOL> for rp in node . range_pairs : <EOL> transcond = node . transcond <EOL> self . add ( rp , dst , transcond ) <EOL> def add_any ( self , dst , cond ) : <EOL> self . any [ cond ] = dst <EOL> def add ( self , srcs , dst , cond ) : <EOL> sb , se = srcs <EOL> for src in range ( sb , se + <NUM_LIT:1> ) : <EOL> if not src in self . fsm : <EOL> self . fsm [ src ] = { } <EOL> self . fsm [ src ] [ cond ] = dst <EOL> def resolve ( self , evaluate ) : <EOL> new_fsm = { } <EOL> for src , dstdict in sorted ( self . fsm . items ( ) , key = lambda x : x [ <NUM_LIT:0> ] ) : <EOL> dst_cond_dict = { } <EOL> for cond , dst in sorted ( dstdict . items ( ) , key = lambda x : x [ <NUM_LIT:1> ] ) : <EOL> if not dst in dst_cond_dict : <EOL> dst_cond_dict [ dst ] = cond <EOL> else : <EOL> cur_cond = dst_cond_dict [ dst ] <EOL> if cur_cond is None : pass <EOL> elif cond is None : dst_cond_dict [ dst ] = None <EOL> else : dst_cond_dict [ dst ] = evaluate . optimize ( DFOperator ( ( cur_cond , cond ) , '<STR_LIT>' ) ) <EOL> new_dstdict = { } <EOL> for dst , cond in dst_cond_dict . items ( ) : <EOL> if isinstance ( cond , DFEvalValue ) and cond . value > <NUM_LIT:0> : <EOL> new_dstdict [ None ] = dst <EOL> else : <EOL> new_dstdict [ cond ] = dst <EOL> new_fsm [ src ] = new_dstdict <EOL> self . fsm = new_fsm <EOL> def view ( self ) : <EOL> for cond , dst in self . any . items ( ) : <EOL> s = [ ] <EOL> s . append ( '<STR_LIT>' ) <EOL> if cond is not None : s . append ( cond . tocode ( ) ) <EOL> else : s . append ( '<STR_LIT:None>' ) <EOL> s . append ( '<STR_LIT>' % dst ) <EOL> print ( '<STR_LIT>' . join ( s ) ) <EOL> for src , dstdict in self . fsm . items ( ) : <EOL> for cond , dst in dstdict . items ( ) : <EOL> s = [ ] <EOL> s . append ( '<STR_LIT>' % src ) <EOL> if cond is not None : s . append ( cond . tocode ( ) ) <EOL> else : s . append ( '<STR_LIT:None>' ) <EOL> s . append ( '<STR_LIT>' % dst ) <EOL> print ( '<STR_LIT>' . join ( s ) ) <EOL> def tograph ( self , filename = '<STR_LIT>' , nolabel = False ) : <EOL> import pygraphviz as pgv <EOL> graph = pgv . AGraph ( directed = True ) <EOL> for src , dstdict in self . fsm . items ( ) : <EOL> graph . add_node ( str ( src ) , label = str ( src ) ) <EOL> for cond , dst in dstdict . items ( ) : <EOL> graph . add_node ( str ( dst ) , label = str ( dst ) ) <EOL> if nolabel : <EOL> graph . add_edge ( str ( src ) , str ( dst ) , label = '<STR_LIT>' ) <EOL> else : <EOL> graph . add_edge ( str ( src ) , str ( dst ) , label = str ( cond ) ) <EOL> srcs = self . fsm . keys ( ) <EOL> for src in srcs : <EOL> for cond , dst in self . any . items ( ) : <EOL> graph . add_node ( str ( dst ) , label = str ( dst ) ) <EOL> if nolabel : <EOL> graph . add_edge ( str ( src ) , str ( dst ) , label = '<STR_LIT>' ) <EOL> else : <EOL> graph . add_edge ( str ( src ) , str ( dst ) , label = str ( cond ) ) <EOL> graph . write ( '<STR_LIT>' ) <EOL> graph . layout ( prog = '<STR_LIT>' ) <EOL> graph . draw ( filename ) <EOL> def get_loop ( self ) : <EOL> loops = set ( [ ] ) <EOL> loop_node_cnt = { } <EOL> for k in sorted ( self . fsm . keys ( ) ) : <EOL> if not k in self . fsm : <EOL> continue <EOL> if not k in loop_node_cnt : loop_node_cnt [ k ] = <NUM_LIT:0> <EOL> if loop_node_cnt [ k ] >= len ( self . fsm [ k ] . values ( ) ) : <EOL> continue <EOL> paths = self . get_looppath ( k ) <EOL> for path in paths : <EOL> rotated = self . rotate ( path ) <EOL> if rotated not in loops : <EOL> loops . add ( rotated ) <EOL> for r in rotated : <EOL> if not r in loop_node_cnt : loop_node_cnt [ r ] = <NUM_LIT:0> <EOL> loop_node_cnt [ r ] += <NUM_LIT:1> <EOL> return loops <EOL> def rotate ( self , path ) : <EOL> minval = min ( path ) <EOL> minval_pos = path . index ( minval ) <EOL> return path [ minval_pos : ] + path [ : minval_pos ] <EOL> def get_looppath ( self , src ) : <EOL> paths = set ( [ ] ) <EOL> if not src in self . fsm : return paths <EOL> nextnodes = set ( self . fsm [ src ] . values ( ) ) <EOL> for n in nextnodes : <EOL> r = self . _looppath ( src , n , visited = set ( [ n ] ) ) <EOL> if len ( r ) > <NUM_LIT:0> : paths |= r <EOL> return paths <EOL> def _looppath ( self , src , node , visited , cnt = <NUM_LIT:0> ) : <EOL> paths = set ( [ ] ) <EOL> if cnt > <NUM_LIT:50> : <EOL> return paths <EOL> if src == node : <EOL> paths . add ( ( src , ) ) <EOL> return paths <EOL> if not node in self . fsm : <EOL> return paths <EOL> nextnodes = set ( self . fsm [ node ] . values ( ) ) - visited <EOL> for n in nextnodes : <EOL> r = self . _looppath ( src , n , visited = visited | set ( [ node ] ) , cnt = cnt + <NUM_LIT:1> ) <EOL> if len ( r ) > <NUM_LIT:0> : <EOL> for np in r : paths . add ( ( node , ) + np ) <EOL> return paths </s>
