diff --git a/crlcore/etc/cmos/alliance.conf b/crlcore/etc/cmos/alliance.conf index 1ede0f9a..460f1cc8 100644 --- a/crlcore/etc/cmos/alliance.conf +++ b/crlcore/etc/cmos/alliance.conf @@ -1,7 +1,8 @@ # -*- Mode:Python; explicit-buffer-name: "alliance.conf" -*- -cellsTop = '/soc/alliance/cells/' +allianceTop = '/soc/alliance' +cellsTop = allianceTop+'/cells/' allianceConfig = \ @@ -28,6 +29,10 @@ allianceConfig = \ , ( 'GROUND' , 'vss') , ( 'CLOCK' , '^ck.*') , ( 'BLOCKAGE' , '^blockage[Nn]et*') + # The following are only read by the Alliance tool wrappers. + , ( 'MBK_TARGET_LIB' , cellsTop+'sxlib') + , ( 'RDS_TECHNO_NAME' , allianceTop+'/cmos.rds') + , ( 'GRAAL_TECHNO_NAME' , allianceTop+'/graal.rds') ) diff --git a/crlcore/src/crlcore/coriolisInit.py b/crlcore/src/crlcore/coriolisInit.py index c08f22e2..89b28615 100644 --- a/crlcore/src/crlcore/coriolisInit.py +++ b/crlcore/src/crlcore/coriolisInit.py @@ -46,6 +46,7 @@ except Exception, e: sys.exit(2) +helpers.staticInitialization() moduleGlobals = globals() SystemFile = 0x0001 diff --git a/crlcore/src/crlcore/helpers/__init__.py b/crlcore/src/crlcore/helpers/__init__.py index eeac0b08..e4520edb 100644 --- a/crlcore/src/crlcore/helpers/__init__.py +++ b/crlcore/src/crlcore/helpers/__init__.py @@ -137,28 +137,31 @@ class WarningMessage ( Exception ): return formatted -for (modulePath,moduleLine,contextType,lineContent) in traceback.extract_stack(): - if modulePath.endswith('/coriolisInit.py'): - - reSysConfDir = re.compile(r'.*etc\/coriolis2') - print ' o Locating configuration directory:' - - for path in sys.path: - if reSysConfDir.match(path): - sysConfDir = path - print ' - <%s>' % sysConfDir - break - - if not sysConfDir: - coriolisTop = os.getenv('CORIOLIS_TOP') - if coriolisTop == '/usr': - sysConfDir = '/etc/coriolis2' - elif coriolisTop: - sysConfDir = os.path.join(coriolisTop,'/etc/coriolis2') - else: - raise ErrorMessage( 1, [ 'Cannot locate the directoty holding the configuration files.' - , 'The path is something ending by <.../etc/coriolis2>.'] ) - - symbolicDir = os.path.join( sysConfDir, symbolicTechno ) - realDir = os.path.join( sysConfDir, realTechno ) - break +def staticInitialization (): + global sysConfDir + global symbolicDir + global realDir + + reSysConfDir = re.compile(r'.*etc\/coriolis2') + print ' o Locating configuration directory:' + + for path in sys.path: + if reSysConfDir.match(path): + sysConfDir = path + print ' - <%s>' % sysConfDir + break + + if not sysConfDir: + coriolisTop = os.getenv('CORIOLIS_TOP') + if coriolisTop == '/usr': + sysConfDir = '/etc/coriolis2' + elif coriolisTop: + sysConfDir = os.path.join(coriolisTop,'etc/coriolis2') + else: + raise ErrorMessage( 1, [ 'Cannot locate the directoty holding the configuration files.' + , 'The path is something ending by <.../etc/coriolis2>.'] ) + + print ' - <%s>' % sysConfDir + symbolicDir = os.path.join( sysConfDir, symbolicTechno ) + realDir = os.path.join( sysConfDir, realTechno ) + return diff --git a/cumulus/src/Alliance.py b/cumulus/src/Alliance.py new file mode 100644 index 00000000..21c68f98 --- /dev/null +++ b/cumulus/src/Alliance.py @@ -0,0 +1,745 @@ +# -*- Mode:Python; explicit-buffer-name: "Alliance.py" -*- +# +# This file is part of the Coriolis Software. +# Copyright (c) UPMC 2014-2014, All Rights Reserved +# +# +-----------------------------------------------------------------+ +# | C O R I O L I S | +# | C u m u l u s - P y t h o n T o o l s | +# | | +# | Author : Jean-Paul CHAPUT | +# | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +# | =============================================================== | +# | Python : "./plugins/Alliance.py" | +# +-----------------------------------------------------------------+ + + +import os +import os.path +import sys +import time +import stat +import copy +import subprocess +import inspect +import helpers +from helpers import ErrorMessage +from helpers import WarningMessage + + +# Global display flags +ShowCommand = 0x00001000 +ShowLog = 0x00002000 +ForceRun = 0x00004000 + +commandFlags = ShowCommand | ShowLog + + +class RoutingLayerGauge ( object ): + + Horizontal = 1 + Vertical = 2 + PinOnly = 4 + Default = 8 + + +class Environment ( object ): + + DefaultEnv = 0001 + CommandEnv = 0002 + Append = 0004 + + @staticmethod + def splitExtension ( name ): + if name.endswith('_vbe') or name.endswith('_vst'): + return name[:-4], name[-3:] + return None, None + + + def __init__ ( self, flags ): + self.mbkEnv = {} + if flags & Environment.DefaultEnv: + self.mbkEnv[ 'MBK_TARGET_LIB' ] = None + self.mbkEnv[ 'MBK_WORK_LIB' ] = '.' + self.mbkEnv[ 'MBK_CATA_LIB' ] = None + self.mbkEnv[ 'MBK_CATAL_NAME' ] = 'CATAL' + self.mbkEnv[ 'MBK_OUT_LO' ] = 'vst' + self.mbkEnv[ 'MBK_OUT_PH' ] = 'ap' + self.mbkEnv[ 'MBK_IN_LO' ] = 'vst' + self.mbkEnv[ 'MBK_IN_PH' ] = 'ap' + self.mbkEnv[ 'MBK_SEPAR' ] = '_' + self.mbkEnv[ 'MBK_VDD' ] = 'vdd' + self.mbkEnv[ 'MBK_VSS' ] = 'vss' + self.mbkEnv[ 'RDS_TECHNO_NAME' ] = None + self.mbkEnv[ 'GRAAL_TECHNO_NAME' ] = None + else: + self.mbkEnv[ 'MBK_TARGET_LIB' ] = None + self.mbkEnv[ 'MBK_WORK_LIB' ] = None + self.mbkEnv[ 'MBK_CATA_LIB' ] = None + self.mbkEnv[ 'MBK_CATAL_NAME' ] = None + self.mbkEnv[ 'MBK_OUT_LO' ] = None + self.mbkEnv[ 'MBK_OUT_PH' ] = None + self.mbkEnv[ 'MBK_IN_LO' ] = None + self.mbkEnv[ 'MBK_IN_PH' ] = None + self.mbkEnv[ 'MBK_SEPAR' ] = None + self.mbkEnv[ 'MBK_VDD' ] = None + self.mbkEnv[ 'MBK_VSS' ] = None + self.mbkEnv[ 'RDS_TECHNO_NAME' ] = None + self.mbkEnv[ 'GRAAL_TECHNO_NAME' ] = None + return + + + def load ( self, allianceConfig, allianceFile ): + entryNo = 0 + for entry in allianceConfig: + entryNo += 1 + + try: + if len(entry) != 2: + raise ErrorMessage(1,['Malformed entry in .' + ,'Must have exactly two fields ("key", ).' + ,str(entry) + ]) + + key, value = entry + if key == 'GRAAL_TECHNO_NAME': self.mbkEnv[ key ] = value + if key == 'RDS_TECHNO_NAME': self.mbkEnv[ key ] = value + if key == 'CATALOG': self.mbkEnv[ key ] = value + if key == 'SCALE_X': self.mbkEnv[ key ] = value + if key == 'IN_LO': self.mbkEnv[ key ] = value + if key == 'IN_PH': self.mbkEnv[ key ] = value + if key == 'OUT_PH': self.mbkEnv[ key ] = value + if key == 'OUT_LO': self.mbkEnv[ key ] = value + if key == 'POWER': self.mbkEnv[ key ] = value + if key == 'GROUND': self.mbkEnv[ key ] = value + if key == 'MBK_TARGET_LIB': self.mbkEnv[ key ] = value + if key == 'WORKING_LIBRARY': self.mbkEnv[ key ] = value + if key == 'SYSTEM_LIBRARY': + for libraryEntry in value: + if len(libraryEntry) != 2: + raise ErrorMessage(1,['Malformed system library entry in .' + ,'Must have exactly two fields ("path", ).' + ,str(libraryEntry) + ]) + libPath, mode = libraryEntry + if self.mbkEnv['MBK_CATA_LIB']: + self.mbkEnv['MBK_CATA_LIB'] = self.mbkEnv['MBK_CATA_LIB'] + ':' + libPath + else: + self.mbkEnv['MBK_CATA_LIB'] = libPath + + except Exception, e: + ErrorMessage.wrapPrint(e,'In %s: at index %d.' % (allianceFile,entryNo)) + return + + + def clone ( self ): + return copy.deepcopy(self) + + + def toSystemEnv ( self ): + env = os.environ + for key in self.mbkEnv.keys(): + if not self.mbkEnv[key]: + print WarningMessage( 'Environment variable <%s> is not set.' % key ) + continue + env[ key ] = str(self.mbkEnv[ key ]) + return env + + +class EnvironmentWrapper ( object ): + + def __init__ ( self, env ): + self._env = env.clone() + return + + def toSystemEnv ( self ): return self._env.toSystemEnv() + + @property + def env ( self ): return self._env + + @property + def TARGET_LIB ( self ): return self._env.mbkEnv[ 'MBK_TARGET_LIB' ] + @property + def WORK_LIB ( self ): return self._env.mbkEnv[ 'MBK_WORK_LIB'] + @property + def CATA_LIB ( self ): return self._env.mbkEnv[ 'MBK_CATA_LIB'] + @property + def CATAL_NAME ( self ): return self._env.mbkEnv[ 'MBK_CATAL_NAME' ] + @property + def OUT_LO ( self ): return self._env.mbkEnv[ 'MBK_OUT_LO' ] + @property + def OUT_PH ( self ): return self._env.mbkEnv[ 'MBK_OUT_PH' ] + @property + def IN_LO ( self ): return self._env.mbkEnv[ 'MBK_IN_LO' ] + @property + def IN_PH ( self ): return self._env.mbkEnv[ 'MBK_IN_PH' ] + @property + def SEPAR ( self ): return self._env.mbkEnv[ 'MBK_SEPAR' ] + @property + def VDD ( self ): return self._env.mbkEnv[ 'MBK_VDD' ] + @property + def VSS ( self ): return self._env.mbkEnv[ 'MBK_VSS' ] + @property + def RDS_TECHNO_NAME ( self ): return self._env.mbkEnv[ 'RDS_TECHNO_NAME' ] + @property + def GRAAL_TECHNO_NAME ( self ): return self._env.mbkEnv[ 'GRAAL_TECHNO_NAME' ] + + @TARGET_LIB.setter + def TARGET_LIB ( self, value ): self._env.mbkEnv[ 'MBK_TARGET_LIB' ] = value + @WORK_LIB.setter + def WORK_LIB ( self, value ): self._env.mbkEnv[ 'MBK_WORK_LIB'] = value + @CATA_LIB.setter + def CATA_LIB ( self, value ): self._env.mbkEnv[ 'MBK_CATA_LIB'] = value + @CATAL_NAME.setter + def CATAL_NAME ( self, value ): self._env.mbkEnv[ 'MBK_CATAL_NAME' ] = value + @OUT_LO.setter + def OUT_LO ( self, value ): self._env.mbkEnv[ 'MBK_OUT_LO' ] = value + @OUT_PH.setter + def OUT_PH ( self, value ): self._env.mbkEnv[ 'MBK_OUT_PH' ] = value + @IN_LO.setter + def IN_LO ( self, value ): self._env.mbkEnv[ 'MBK_IN_LO' ] = value + @IN_PH.setter + def IN_PH ( self, value ): self._env.mbkEnv[ 'MBK_IN_PH' ] = value + @SEPAR.setter + def SEPAR ( self, value ): self._env.mbkEnv[ 'MBK_SEPAR' ] = value + @VDD.setter + def VDD ( self, value ): self._env.mbkEnv[ 'MBK_VDD' ] = value + @VSS.setter + def VSS ( self, value ): self._env.mbkEnv[ 'MBK_VSS' ] = value + @RDS_TECHNO_NAME.setter + def RDS_TECHNO_NAME ( self, value ): self._env.mbkEnv[ 'RDS_TECHNO_NAME' ] = value + @GRAAL_TECHNO_NAME.setter + def GRAAL_TECHNO_NAME ( self, value ): self._env.mbkEnv[ 'GRAAL_TECHNO_NAME' ] = value + + +class ReportLog ( object ): + + def __init__ ( self, baseName ): + self._reportBase = baseName + self._reportFile = None + self._fd = None + self._lastLine = None + self._chooseName() + return + + def _chooseName ( self ): + index = 0 + timeTag = time.strftime("%Y.%m.%d") + while True: + self._reportFile = "./%s-%s-%02d.log" % (self._reportBase,timeTag,index) + if not os.path.isfile(self._reportFile): + print "Report log: <%s>" % self._reportFile + break + index += 1 + return + + @property + def baseName ( self ): return self._reportBase + @baseName.setter + def baseName ( self, baseName ): self._reportBase = baseName + + def open ( self ): + if self._fd: return + self._fd = open( self._reportFile, "a+" ) + return + + def close ( self ): + if not self._fd: return + self._fd.close() + self._fd = None + return + + def write ( self, line ): + if not self._fd: return + self._lastLine = line + self._fd.write( self._lastLine ) + return + + +moduleGlobals = globals() +env = Environment( Environment.DefaultEnv ) + +def staticInitialization (): + global moduleGlobals + global env + + confFile = helpers.sysConfDir+'/'+helpers.symbolicTechno+'/alliance.conf' + symbol = 'allianceConfig' + + if not os.path.isfile(confFile): + print '[ERROR] Missing mandatory Coriolis2 system file:' + print ' <%s>' % confFile + sys.exit( 1 ) + + try: + print ' - Loading \"%s\".' % helpers.truncPath(confFile) + execfile( confFile, moduleGlobals ) + except Exception, e: + print '[ERROR] An exception occured while loading the configuration file:' + print ' <%s>\n' % (confFile) + print ' You should check for simple python errors in this file.' + print ' Error was:' + print ' %s\n' % e + sys.exit( 1 ) + + if moduleGlobals.has_key(symbol): + env.load( moduleGlobals[symbol], confFile ) + del moduleGlobals[symbol] + else: + print '[ERROR] Mandatory symbol <%s> is missing in system configuration file:' % symbol + print ' <%s>' % confFile + sys.exit( 1 ) + + +helpers.staticInitialization() +staticInitialization() +report = ReportLog( 'alliance' ) + + +class Node ( EnvironmentWrapper ): + + Unreached = -1 + + __allNodes = [] + + @staticmethod + def getAllNodes (): return Node.__allNodes + + def __init__ ( self ): + EnvironmentWrapper.__init__( self, env ) + self._targetName = None + self._dependencies = [] + self._childs = [] + self._depth = Node.Unreached + self._depsReacheds = 0 + Node.__allNodes.append( self ) + return + + @property + def targetName ( self ): return self._targetName + + def setTarget ( self, name ): self._targetName = name + + def setDefaultTargetName ( self ): + if self._dependencies == None: + raise ErrorMessage( 1, 'Node.setDefaultTargetName(): node is neither used nor have dependencies.' ) + self.setTarget( self.getDependency(0)._targetName+'_'+self.toolName.lower() ) + print WarningMessage( 'Node.setDefaultTargetName(): Node is not affected, using: <%s>' % self.targetName ) + return + + def addDependency ( self, dependency ): + if not isinstance(dependency,Node): + raise ErrorMessage( 1, 'Node.addDependency(): Not a node %s.' % str(dependency) ) + self._dependencies.append( dependency ) + dependency.addChild( self ) + return + + def getDependency ( self, i ): return self._dependencies[i] + def getDependencies ( self ): return self._dependencies + + def addChild ( self, child ): + if not child in self._childs: self._childs.append( child ) + return + + def getChilds ( self ): return self._childs + def getDepth ( self ): return self._depth + + def resetOrder ( self ): + self._depth = Node.Unreached + self._depsReacheds = 0 + return + + def incDepsReached ( self, depth ): + if depth > self._depth: self._depth = depth + if self._depsReacheds < len(self._dependencies): + self._depsReacheds += 1 + return self._depsReacheds >= len(self._dependencies) + + def allDepsReached ( self ): + return self._depsReacheds >= len(self._dependencies) + + def checkFile ( self, hardStop=False ): + if not os.path.isfile(self.fileName): + error = ErrorMessage( 1, 'File <%s> of node <%s> has not been created.' + % (self.fileName,self._targetName) ) + if hardStop: + raise error + else: + print error + return + + def isUptodate ( self ): + depsMTime = 0 + for dependency in self.getDependencies(): + dependency.checkFile() + depsMTime = max( depsMTime, dependency.mtime ) + return depsMTime < self.mtime + + @property + def name ( self ): return self._targetName + + @property + def fileName ( self ): + raise ErrorMessage( 1, 'Node.fileName base class attribute must never be called.' ) + return + + @property + def mtime ( self ): + if not os.path.isfile(self.fileName): return 0 + return os.stat( self.fileName )[ stat.ST_MTIME ] + + +class Command ( Node ): + + def __init__ ( self ): + Node.__init__( self ) + self._flags = 0 + return + + @staticmethod + def asString ( command ): + s = '' + for i in range( len(command) ): + if i: s += ' ' + s += command[i] + return s + + @property + def flags ( self ): return self._flags + @flags.setter + def flags ( self, flags ): self._flags = flags + + def _run ( self ): + global commandFlags + + flags = commandFlags + if self._flags: flags = self._flags + + command = self.asCommand() + + if not self.isUptodate() or flags & ForceRun: + if flags & ShowCommand: + print "Executing: %s" % Command.asString(command) + child = subprocess.Popen( command + , env=self.env.toSystemEnv() + , stdout=subprocess.PIPE + , stderr=subprocess.PIPE + ) + + report.open() + report.write( 'Executing command:\n' ) + report.write( ' %s\n' % Command.asString(command) ) + + while True: + line = child.stdout.readline() + if not line: break + + if flags & ShowLog: + print "%s" % (line[:-1]) + sys.stdout.flush() + + report.write( line ) + report.close() + + (pid,status) = os.waitpid(child.pid, 0) + status >>= 8 + if status != 0: + print ErrorMessage( 1, "%s returned status:%d." % (self.toolName,status) ) + else: + if flags & ShowCommand: + print "Up to date: %s" % Command.asString(command) + report.open() + report.write( 'Up to date command:\n' ) + report.write( ' %s\n' % Command.asString(command) ) + report.close() + status = 0 + + return status + + +class Probe ( Command ): + + def __init__ ( self, script ): + Command.__init__( self ) + self._script = script + return + + @property + def toolName ( self ): return self._script + + def asCommand ( self ): + return [ os.path.join(os.getcwd(),self._script) ] + + +class Source ( Node ): + + def __init__ ( self ): + Node.__init__( self ) + self._extension = None + return + + @property + def fileName ( self ): return self.name+'.'+self._extension + + def setTarget ( self, name ): + baseName, extension = Environment.splitExtension( name ) + if baseName: + Node.setTarget( self, baseName ) + self._extension = extension + else: + raise ErrorMessage( 1, 'Invalid file format of Source object <%s>' % name ) + return + + +class Boom ( Command ): + + Verbose = 0x00000001 + Trace = 0x00000002 + ReverseOrder = 0x00000004 + LocalOptimization = 0x00000008 + + AlgorithmS = 's' + AlgorithmJ = 'j' + AlgorithmB = 'b' + AlgorithmG = 'g' + AlgorithmP = 'p' + AlgorithmW = 'w' + AlgorithmT = 't' + AlgorithmM = 'm' + AlgorithmO = 'o' + AlgorithmR = 'r' + AlgorithmN = 'n' + + def __init__ ( self, behavioral ): + Command.__init__( self ) + self._directives = None + self._level = 0 + self._delayPercent = 0 + self._iterations = None + self._bddReorder = None + self._algorithm = None + + self.addDependency( behavioral ) + return + + @property + def toolName ( self ): return 'Boom' + + @property + def fileName ( self ): return self.name+'.vbe' + + @property + def directives ( self ): return self._directives + @directives.setter + def directives ( self, directives ): + self._directives = directives + dependency = Source( 'boom' ) + dependency.setTarget( self._directives ) + self.addDependency( dependency ) + + @property + def level ( self ): return self._level + @property + def delayPercent( self ): return self._delayPercent + @property + def iterations ( self ): return self._iterations + @property + def bddReorder ( self ): return self._bddReorder + @property + def algorithm ( self ): return self._algorithm + + @level.setter + def level ( self, level ): self._level = level + @delayPercent.setter + def delayPercent( self, delayPercent ): self._delayPercent = delayPercent + @iterations.setter + def iterations ( self, iterations ): self._iterations = iterations + @bddReorder.setter + def bddReorder ( self, bddReorder ): self._bddReorder = bddReorder + @algorithm.setter + def algorithm ( self, algorithm ): self._algorithm = algorithm + + def asCommand ( self ): + command = [ 'boom' ] + if self._flags & Boom.Verbose: command += [ '-V' ] + if self._flags & Boom.Trace: command += [ '-T' ] + if self._flags & Boom.ReverseOrder: command += [ '-O' ] + if self._flags & Boom.LocalOptimization: command += [ '-A' ] + + if self._directives: command += [ '-P', self.getDependency(1).fileName ] + if self._level: command += [ '-l', str(self._level) ] + if self._delayPercent: command += [ '-d', str(self._delayPercent) ] + if self._iterations: command += [ '-i', str(self._iterations) ] + if self._bddReorder: command += [ '-a', str(self._bddReorder) ] + if self._algorithm: command += [ '-'+self._algorithm ] + + command += [ self.getDependency(0).name ] + command += [ self.name ] + return command + + +class Boog ( Command ): + + def __init__ ( self, behavioral ): + Command.__init__( self ) + self._optimMode = 5 + self._xschMode = 2 + self._delayPercent = 0 + self._laxFile = None + self._debugFile = None + + self.addDependency( behavioral ) + return + + @property + def toolName ( self ): return 'Boog' + + @property + def fileName ( self ): return self.name+'.vst' + + @property + def laxFile ( self ): return self._laxFile + @laxFile.setter + def laxFile ( self, laxFile ): + self._laxFile = laxFile + dependency = Source( 'boog' ) + dependency.setTarget( self._laxFile ) + self.addDependency( dependency ) + + @property + def optimMode( self ): return self._optimMode + @property + def xschMode ( self ): return self._xschMode + @property + def debugFile( self ): return self._debugFile + + @optimMode.setter + def optimMode( self, optimMode ): self._optimMode = optimMode + @xschMode.setter + def xschMode ( self, xschMode ): self._xschMode = xschMode + @debugFile.setter + def debugFile( self, debugFile ): self._debugFile = debugFile + + def asCommand ( self ): + command = [ 'boog' ] + if self._optimMode < 5: command += [ '-m', str(self._optimMode) ] + if self._xschMode < 2: command += [ '-x', str(self._xschMode) ] + if self._laxFile: command += [ '-l', self.getDependency(1).fileName ] + if self._debugFile: command += [ '-d', self._debugFile ] + + command += [ self.getDependency(0).name ] + command += [ self.name ] + return command + + +class Loon ( Command ): + + def __init__ ( self, structural ): + Command.__init__( self ) + self._optimMode = 5 + self._xschMode = 2 + self._laxFile = None + + self.addDependency( structural ) + return + + @property + def toolName ( self ): return 'Loon' + + @property + def fileName ( self ): return self.name+'.vst' + + @property + def laxFile ( self ): return self._laxFile + @laxFile.setter + def laxFile ( self, laxFile ): + self._laxFile = laxFile + dependency = Source( 'lax' ) + dependency.setTarget( self._laxFile ) + self.addDependency( dependency ) + + @property + def optimMode( self ): return self._optimMode + @property + def xschMode ( self ): return self._xschMode + + @optimMode.setter + def optimMode( self, optimMode ): self._optimMode = optimMode + @xschMode.setter + def xschMode ( self, xschMode ): self._xschMode = xschMode + + def asCommand ( self ): + command = [ 'loon' ] + if self._optimMode < 5: command += [ '-m', str(self._optimMode) ] + if self._xschMode < 2: command += [ '-x', str(self._xschMode) ] + if self._laxFile: command += [ '-l', self.getDependency(1).fileName ] + + command += [ self.getDependency(0).name ] + command += [ self.name ] + return command + + +class Tools ( object ): + + def __init__ ( self ): + self._sourceNodes = [] + self._toolNodes = [] + self._staticOrder = [] + return + + def _findNodes ( self ): + # Three level of stack from the user's script python module. + callerGlobals = inspect.stack()[2][0].f_globals + for symbol in callerGlobals.keys(): + node = callerGlobals[symbol] + if isinstance(node,Boom) \ + or isinstance(node,Boog) \ + or isinstance(node,Loon) \ + or isinstance(node,Probe): + node.setTarget( symbol ) + self._toolNodes.append( node ) + elif isinstance(node,Source): + node.setTarget( symbol ) + self._sourceNodes.append( node ) + + for node in Node.getAllNodes(): + if node.targetName: continue + node.setDefaultTargetName() + if not isinstance(node,Source): + self._toolNodes.append( node ) + return + + def _sortNodes ( self ): + self._staticOrder = [] + + nodeStack = [] + for node in self._sourceNodes: + node._depth = 0 + nodeStack.append( node ) + + while nodeStack: + reacheds = 0 + for inode in range(len(nodeStack)): + if nodeStack[inode].allDepsReached(): + reacheds += 1 + node = nodeStack.pop( inode ) + self._staticOrder.append( node ) + for child in node.getChilds(): + if child.getDepth() < 0: nodeStack.append(child) + child.incDepsReached( node.getDepth()+1 ) + if not reacheds and nodeStack: + raise ErrorMessage( 1, 'Loop in dependency graph.' ) + return + + @staticmethod + def run (): + tool = Tools() + tool._findNodes() + tool._sortNodes() + + for node in tool._staticOrder: + #for dep in node.getDependencies(): + # print dep.name + # print dep.fileName + if not isinstance(node,Source): node._run() + return diff --git a/cumulus/src/CMakeLists.txt b/cumulus/src/CMakeLists.txt index 8ebb24c5..045a3d48 100644 --- a/cumulus/src/CMakeLists.txt +++ b/cumulus/src/CMakeLists.txt @@ -2,6 +2,7 @@ set ( pySources ${CMAKE_CURRENT_SOURCE_DIR}/placeandroute.py ${CMAKE_CURRENT_SOURCE_DIR}/ref.py + ${CMAKE_CURRENT_SOURCE_DIR}/Alliance.py ) set ( pyPlugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins/__init__.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ClockTree.py