1464 lines
47 KiB
Python
1464 lines
47 KiB
Python
# -*- Mode:Python; explicit-buffer-name: "Alliance.py<cumulus>" -*-
|
|
#
|
|
# This file is part of the Coriolis Software.
|
|
# Copyright (c) UPMC 2014-2016, 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
|
|
from helpers import Dots
|
|
|
|
|
|
# Global display flags
|
|
ShowCommand = 0x00001000
|
|
ShowLog = 0x00002000
|
|
ShowDots = 0x00004000
|
|
ForceRun = 0x00008000
|
|
|
|
commandFlags = ShowCommand | ShowLog
|
|
|
|
|
|
class AddMode ( object ):
|
|
|
|
Append = 1
|
|
Prepend = 2
|
|
Replace = 3
|
|
|
|
|
|
class Gauge ( object ):
|
|
|
|
Horizontal = 1
|
|
Vertical = 2
|
|
PinOnly = 4
|
|
Default = 8
|
|
|
|
|
|
class SearchPath ( object ):
|
|
|
|
def __init__ ( self ):
|
|
self._pathes = []
|
|
return
|
|
|
|
def add ( self, path, mode ):
|
|
name = os.path.basename(path)
|
|
if mode == AddMode.Append:
|
|
self._pathes.append( (name,path) )
|
|
elif mode == AddMode.Prepend:
|
|
self._pathes.insert( 0, (name,path) )
|
|
elif mode == AddMode.Replace:
|
|
for ipath in range(len(self._pathes)):
|
|
if self._pathes[ipath][0] == name:
|
|
self._pathes[ipath] = (name, path)
|
|
return
|
|
self._pathes.append( (name,path) )
|
|
return
|
|
|
|
def toUnix ( self ):
|
|
if not len(self._pathes): return ''
|
|
|
|
s = ''
|
|
for ipath in range(len(self._pathes)):
|
|
if ipath > 0: s += ':'
|
|
s += self._pathes[ipath][1]
|
|
return s
|
|
|
|
def __str__ ( self ):
|
|
return self.toUnix()
|
|
|
|
|
|
|
|
class Environment ( object ):
|
|
|
|
DefaultEnv = 0x0001
|
|
CommandEnv = 0x0002
|
|
Append = 0x0004
|
|
|
|
BehavioralExt = 0x0001
|
|
StructuralExt = 0x0002
|
|
PhysicalExt = 0x0004
|
|
ScriptExt = 0x0008
|
|
CSourceExt = 0x0010
|
|
DirectiveExt = 0x0020
|
|
IocExt = 0x0040
|
|
PatExt = 0x0080
|
|
AllExt = 0x00ff
|
|
|
|
extTable = { BehavioralExt : [ 'vbe' ]
|
|
, StructuralExt : [ 'vst', 'al' ]
|
|
, PhysicalExt : [ 'ap' , 'cp' ]
|
|
, ScriptExt : [ 'sh' , 'py' ]
|
|
, CSourceExt : [ 'c' ]
|
|
, IocExt : [ 'ioc' ]
|
|
, DirectiveExt : [ 'lax', 'boom', 'dly' ]
|
|
, PatExt : [ 'pat' ]
|
|
}
|
|
|
|
|
|
@staticmethod
|
|
def symbolToFilename ( name, eflags ):
|
|
extensions = []
|
|
for iflag in range(0,len(Environment.extTable)):
|
|
if eflags & pow(2,iflag): extensions += Environment.extTable[ pow(2,iflag) ]
|
|
|
|
for extension in extensions:
|
|
if name.endswith('_'+extension):
|
|
l = len(extension)
|
|
return name[:-l-1], name[-l:]
|
|
|
|
return None, None
|
|
|
|
@staticmethod
|
|
def isExt ( ext, eflags ):
|
|
extensions = []
|
|
for iflag in range(0,len(Environment.extTable)):
|
|
if eflags & pow(2,iflag): extensions += Environment.extTable[ pow(2,iflag) ]
|
|
|
|
if ext in extensions: return True
|
|
return False
|
|
|
|
|
|
def __init__ ( self, flags ):
|
|
self.mbkEnv = {}
|
|
if flags & Environment.DefaultEnv:
|
|
self.mbkEnv[ 'ALLIANCE_TOP' ] = None
|
|
self.mbkEnv[ 'LD_LIBRARY_PATH' ] = None
|
|
self.mbkEnv[ 'MBK_TARGET_LIB' ] = None
|
|
self.mbkEnv[ 'MBK_WORK_LIB' ] = '.'
|
|
self.mbkEnv[ 'MBK_CATA_LIB' ] = SearchPath()
|
|
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[ 'ALLIANCE_TOP' ] = None
|
|
self.mbkEnv[ 'LD_LIBRARY_PATH' ] = None
|
|
self.mbkEnv[ 'MBK_TARGET_LIB' ] = None
|
|
self.mbkEnv[ 'MBK_WORK_LIB' ] = None
|
|
self.mbkEnv[ 'MBK_CATA_LIB' ] = SearchPath()
|
|
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 <allianceConfig>.'
|
|
,'Must have exactly two fields ("key", <value>).'
|
|
,str(entry)
|
|
])
|
|
|
|
key, value = entry
|
|
if key == 'ALLIANCE_TOP': self.mbkEnv[ key ] = value
|
|
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 <allianceConfig>.'
|
|
,'Must have exactly two fields ("path", <mode>).'
|
|
,str(libraryEntry)
|
|
])
|
|
libPath, mode = libraryEntry
|
|
self.mbkEnv['MBK_CATA_LIB'].add( libPath, mode )
|
|
|
|
except Exception, e:
|
|
ErrorMessage.wrapPrint(e,'In %s:<Alliance> at index %d.' % (allianceFile,entryNo))
|
|
|
|
self.mbkEnv[ 'LD_LIBRARY_PATH' ] = self.mbkEnv[ 'ALLIANCE_TOP' ] + '/lib'
|
|
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 ' o Running configuration hook: Alliance.staticInitialization().'
|
|
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 )
|
|
|
|
print
|
|
return
|
|
|
|
|
|
helpers.staticInitialization()
|
|
staticInitialization()
|
|
|
|
report = ReportLog( 'alliance' )
|
|
|
|
|
|
class Node ( EnvironmentWrapper ):
|
|
|
|
Unreached = -1
|
|
|
|
__allNodes = []
|
|
|
|
@staticmethod
|
|
def getAllNodes (): return Node.__allNodes
|
|
|
|
@staticmethod
|
|
def lookup ( symbol ):
|
|
for node in Node.__allNodes:
|
|
if node.ruleName == symbol:
|
|
return node
|
|
return None
|
|
|
|
@staticmethod
|
|
def allClean ():
|
|
for node in Node.__allNodes: node.clean()
|
|
return
|
|
|
|
@staticmethod
|
|
def findSelfSymbols ():
|
|
for node in Node.__allNodes: node._findSelfSymbol()
|
|
return
|
|
|
|
def __init__ ( self ):
|
|
EnvironmentWrapper.__init__( self, env )
|
|
self._targetName = None
|
|
self._extension = None
|
|
self._dependencies = []
|
|
self._childs = []
|
|
self._depth = Node.Unreached
|
|
self._depsReacheds = 0
|
|
self._active = False
|
|
self._frame = inspect.stack()[self.frameDepth]
|
|
Node.__allNodes.append( self )
|
|
return
|
|
|
|
def _findSelfSymbol ( self ):
|
|
callerGlobals = self._frame[0].f_globals
|
|
for symbol in callerGlobals.keys():
|
|
if self == callerGlobals[symbol]:
|
|
self.setTarget( symbol )
|
|
return
|
|
|
|
self.setDefaultTargetName()
|
|
#raise ErrorMessage( 1, 'Node cannot find its symbol in parent frame.' )
|
|
return
|
|
|
|
def setTarget ( self, name ):
|
|
baseName, extension = Environment.symbolToFilename( name, Environment.AllExt )
|
|
if baseName:
|
|
self._targetName = baseName
|
|
self._extension = extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Invalid file format of Node object <%s>' % name )
|
|
return
|
|
|
|
@property
|
|
def targetName ( self ): return self._targetName
|
|
|
|
def setDefaultTargetName ( self ):
|
|
if self._dependencies == []:
|
|
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, errorMessage=[] ):
|
|
if not os.path.isfile(self.fileName):
|
|
error = ErrorMessage( 1, 'File <%s> of node <%s> has not been created.'
|
|
% (self.fileName,self._targetName) )
|
|
if errorMessage:
|
|
print
|
|
for line in errorMessage: print line
|
|
if hardStop:
|
|
raise error
|
|
else:
|
|
print error
|
|
return
|
|
|
|
def isUptodate ( self ):
|
|
depsMTime = 0
|
|
#print ' Target: %-30s %d' % (self.fileName, self.mtime)
|
|
for dependency in self.getDependencies():
|
|
dependency.checkFile()
|
|
depsMTime = max( depsMTime, dependency.mtime )
|
|
#print ' | Dep: %-31s %d' % (dependency.fileName, dependency.mtime)
|
|
return depsMTime <= self.mtime
|
|
|
|
def setActive ( self ):
|
|
self._active = True
|
|
for dependency in self.getDependencies():
|
|
dependency.setActive()
|
|
|
|
def isActive ( self ): return self._active
|
|
|
|
def setMbkEnv ( self ): return
|
|
|
|
def clean ( self ):
|
|
if not isinstance(self,Source) \
|
|
and not isinstance(self,Probe) \
|
|
and not isinstance(self,Rule):
|
|
print 'Clean | %-30s| rm %s' % ( "<%s>"%self.ruleName, self.fileName )
|
|
|
|
report.open()
|
|
report.write( 'Clean <%s>: (%s)\n' % (self.ruleName, self.fileName) )
|
|
if os.path.isfile(self.fileName):
|
|
report.write( ' rm %s\n' % self.fileName )
|
|
os.unlink( self.fileName )
|
|
return
|
|
report.close()
|
|
|
|
@property
|
|
def name ( self ): return self._targetName
|
|
|
|
@property
|
|
def extension ( self ): return self._extension
|
|
|
|
@property
|
|
def fileName ( self ): return self._targetName+'.'+self._extension
|
|
|
|
@property
|
|
def ruleName ( self ):
|
|
if self._extension:
|
|
return self._targetName+'_'+self._extension
|
|
return self._targetName
|
|
|
|
|
|
@property
|
|
def mtime ( self ):
|
|
if not os.path.isfile(self.fileName): return 0
|
|
return os.stat( self.fileName )[ stat.ST_MTIME ]
|
|
|
|
|
|
class Command ( Node ):
|
|
|
|
commandTypes = []
|
|
|
|
def __init__ ( self ):
|
|
Node.__init__( self )
|
|
self._flags = 0
|
|
Command.commandTypes.append( type(self) )
|
|
return
|
|
|
|
@staticmethod
|
|
def asString ( command ):
|
|
s = ''
|
|
for i in range( len(command) ):
|
|
if i: s += ' '
|
|
s += command[i]
|
|
return s
|
|
|
|
@staticmethod
|
|
def indent ( command, indent, width=109 ):
|
|
lines = []
|
|
lines.append( '|' )
|
|
|
|
for i in range(len(command)):
|
|
lines[-1] += ' ' + command[i]
|
|
if (len(lines) == 1 and len(lines[0]) >= width-indent) \
|
|
or len(lines[-1]) >= width:
|
|
if i < len(command)-1:
|
|
lines.append( ' '*indent + '|' + ' '*(len(command[0])+1) )
|
|
|
|
s = lines[0]
|
|
for line in lines[1:]:
|
|
s += '\n' + line
|
|
return s
|
|
|
|
#s = ''
|
|
#l = '|'
|
|
#for i in range(len(command)):
|
|
# l += ' ' + command[i]
|
|
# if len(l) >= width-indent:
|
|
# if len(s): s += '\n'
|
|
# s += l
|
|
# if i < len(command)-1:
|
|
# l = ' '*indent + '|' + ' '*(len(command[0])+1)
|
|
# else:
|
|
# return s
|
|
#if len(s): s += '\n'
|
|
#s += l
|
|
#return s
|
|
|
|
@property
|
|
def frameDepth ( self ): return 3
|
|
@property
|
|
def flags ( self ): return self._flags
|
|
@flags.setter
|
|
def flags ( self, flags ): self._flags = flags
|
|
|
|
def _run ( self, checkFile=True ):
|
|
global commandFlags
|
|
|
|
flags = commandFlags
|
|
if self._flags: flags = self._flags
|
|
|
|
command = self.asCommand()
|
|
ruleName = "<%s>" % self.ruleName
|
|
|
|
if self.isActive() and (not self.isUptodate() or flags & ForceRun):
|
|
if flags & ShowCommand:
|
|
print "Executing | %-30s%s" % (ruleName,Command.indent(command,42))
|
|
child = subprocess.Popen( command
|
|
, env=self.env.toSystemEnv()
|
|
, stdout=subprocess.PIPE
|
|
, stderr=subprocess.PIPE
|
|
)
|
|
|
|
dots = Dots( ' '*42+'| ', 109 )
|
|
report.open()
|
|
report.write( 'Executing command: %s \n' % ruleName )
|
|
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()
|
|
elif flags & ShowDots:
|
|
dots.dot()
|
|
|
|
report.write( line )
|
|
|
|
errorLines = []
|
|
while True:
|
|
line = child.stderr.readline()
|
|
if not line: break
|
|
|
|
errorLines.append( line[:-1] )
|
|
sys.stderr.flush()
|
|
report.write( line )
|
|
|
|
report.close()
|
|
dots.reset()
|
|
|
|
(pid,status) = os.waitpid(child.pid, 0)
|
|
status >>= 8
|
|
if status != 0:
|
|
print
|
|
for line in errorLines: print line
|
|
raise ErrorMessage( 1, "%s returned status:%d." % (self.toolName,status) )
|
|
if checkFile:
|
|
self.checkFile( hardStop=True, errorMessage=errorLines )
|
|
else:
|
|
if self.isActive(): action = 'Up to date'
|
|
else: action = 'Inactive'
|
|
if flags & ShowCommand:
|
|
print "%-10s| %-30s%s" % (action,ruleName,Command.indent(command,42))
|
|
|
|
report.open()
|
|
report.write( '%s command:\n' % action )
|
|
report.write( ' %s\n' % Command.asString(command) )
|
|
report.close()
|
|
status = 0
|
|
|
|
return status
|
|
|
|
|
|
class StampCommand ( Command ):
|
|
|
|
def __init__ ( self ):
|
|
Command.__init__( self )
|
|
return
|
|
|
|
def setTarget ( self, name ):
|
|
if not name.startswith('stamp_'):
|
|
raise ErrorMessage( 1, 'Target of stamp commands must start with "stamp_" (<%s>)' % name )
|
|
|
|
self._targetName = 'stamp.' + name[6:]
|
|
return
|
|
|
|
@property
|
|
def frameDepth ( self ): return 4
|
|
@property
|
|
def fileName ( self ): return self._targetName
|
|
|
|
def _run ( self ):
|
|
Command._run( self, checkFile=False )
|
|
if self.isActive():
|
|
with file(self.fileName,'a'): os.utime(self.fileName,None)
|
|
return
|
|
|
|
|
|
class Probe ( Command ):
|
|
|
|
def __init__ ( self, script ):
|
|
Command.__init__( self )
|
|
self.addDependency( script )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return self.getDependency(0).name+'_'+self.getDependency(0).extension
|
|
|
|
def asCommand ( self ):
|
|
return [ os.path.join(os.getcwd(),self.getDependency(0).fileName) ]
|
|
|
|
def _run ( self ):
|
|
Command._run( self, checkFile=False )
|
|
return
|
|
|
|
|
|
class Source ( Node ):
|
|
|
|
def __init__ ( self ):
|
|
Node.__init__( self )
|
|
return
|
|
|
|
@property
|
|
def frameDepth ( self ): return 2
|
|
|
|
|
|
class Rule ( Node ):
|
|
|
|
def __init__ ( self, *dependencies ):
|
|
Node.__init__( self )
|
|
for dependency in dependencies:
|
|
self.addDependency( dependency )
|
|
return
|
|
|
|
@property
|
|
def frameDepth ( self ): return 2
|
|
@property
|
|
def mtime ( self ): return 0
|
|
|
|
def setTarget ( self, name ):
|
|
self._targetName = 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+'.'+self.extension
|
|
|
|
@property
|
|
def directives ( self ): return self._directives
|
|
@directives.setter
|
|
def directives ( self, directives ):
|
|
self._directives = directives
|
|
self.addDependency( self._directives )
|
|
|
|
@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 setMbkEnv ( self ):
|
|
if self.extension != 'vbe':
|
|
raise ErrorMessage( 1, 'Boom(): Optimized file format/ext must be <vbe>, not <%s>.'
|
|
% self.extension )
|
|
if self.getDependency(0).extension != 'vbe':
|
|
raise ErrorMessage( 1, 'Boom(): Behavioral source file format/ext must be <vbe>, not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
if self._directives and self._directives.extension != 'boom':
|
|
raise ErrorMessage( 1, 'Boom(): Directive file format/ext must be <boom>, not <%s>.'
|
|
% self._directives.extension )
|
|
self.IN_LO = 'vst'
|
|
self.OUT_LO = 'vst'
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'boom' ]
|
|
#command = [ './boom.sh' ]
|
|
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).name ]
|
|
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+'.'+self.extension
|
|
|
|
@property
|
|
def laxFile ( self ): return self._laxNode
|
|
@laxFile.setter
|
|
def laxFile ( self, laxNode ):
|
|
self._laxNode = laxNode
|
|
self.addDependency( self._laxNode )
|
|
|
|
@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 setMbkEnv ( self ):
|
|
if Environment.isExt(self.extension,Environment.StructuralExt):
|
|
self.OUT_LO = self.extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Boog(): Invalid structural (netlist) file format/ext <%s>.'
|
|
% self.extension )
|
|
if self.getDependency(0).extension != 'vbe':
|
|
raise ErrorMessage( 1, 'Boog(): Behavioral source file format/ext must be <vbe>, not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
if self._laxFile and self._laxFile.extension != 'lax':
|
|
raise ErrorMessage( 1, 'Boog(): Lax file format/ext must be <lax>, not <%s>.'
|
|
% self._directives.extension )
|
|
self.IN_LO = 'vst'
|
|
return
|
|
|
|
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).name ]
|
|
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+'.'+self.OUT_LO
|
|
|
|
@property
|
|
def laxFile ( self ): return self._laxFile
|
|
@laxFile.setter
|
|
def laxFile ( self, laxFile ):
|
|
self._laxFile = laxFile
|
|
self.addDependency( self._laxFile )
|
|
|
|
@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 setMbkEnv ( self ):
|
|
if Environment.isExt(self.extension,Environment.StructuralExt):
|
|
self.OUT_LO = self.extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Loon(): Invalid output structural (netlist) file format/ext <%s>.'
|
|
% self.extension )
|
|
if Environment.isExt(self.getDependency(0).extension,Environment.StructuralExt):
|
|
self.IN_LO = self.getDependency(0).extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Loon(): Invalid input structural (netlist) file format/ext <%s>.'
|
|
% self.getDependency(0).extension )
|
|
if self._laxFile and self._laxFile.extension != 'lax':
|
|
raise ErrorMessage( 1, 'Loon(): Lax file format/ext must be <lax>, not <%s>.'
|
|
% self._directives.extension )
|
|
return
|
|
|
|
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 Genlib ( Command ):
|
|
|
|
def __init__ ( self, csource ):
|
|
Command.__init__( self )
|
|
self.addDependency( csource )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return 'Genlib'
|
|
|
|
@property
|
|
def fileName ( self ): return self.name+'.'+self.OUT_LO
|
|
|
|
def setMbkEnv ( self ):
|
|
if not Environment.isExt(self.extension,Environment.StructuralExt|Environment.PhysicalExt):
|
|
raise ErrorMessage( 1, 'Genlib(): Invalid output netlist or layout file format/ext <%s>.'
|
|
% self.extension )
|
|
if not Environment.isExt(self.getDependency(0).extension,Environment.CSourceExt):
|
|
raise ErrorMessage( 1, 'Genlib(): Input file format/ext must be <c>, not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
|
|
if Environment.isExt(self.extension,Environment.StructuralExt): self.OUT_LO = self.extension
|
|
if Environment.isExt(self.extension,Environment.PhysicalExt): self.OUT_PH = self.extension
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'genlib', '-v', '-k' ]
|
|
command += [ self.getDependency(0).name ]
|
|
return command
|
|
|
|
|
|
class Genpat ( Command ):
|
|
|
|
def __init__ ( self, csource ):
|
|
Command.__init__( self )
|
|
self.addDependency( csource )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return 'Genpat'
|
|
|
|
@property
|
|
def fileName ( self ): return self.name+'.pat'
|
|
|
|
def setMbkEnv ( self ):
|
|
if self.extension != 'pat':
|
|
raise ErrorMessage( 1, 'Genpat(): Invalid output pattern file format/ext <%s>, must be <pat>.'
|
|
% self.extension )
|
|
if not Environment.isExt(self.getDependency(0).extension,Environment.CSourceExt):
|
|
raise ErrorMessage( 1, 'Genpat(): Input file format/ext must be <c>, not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'genpat', '-v' ]
|
|
command += [ self.getDependency(0).name ]
|
|
return command
|
|
|
|
|
|
class Asimut ( Command ):
|
|
|
|
RootIsBehavioral = 0x00000001
|
|
UseBdd = 0x00000002
|
|
CompileOnly = 0x00000004
|
|
ZeroDelay = 0x00000008
|
|
|
|
def __init__ ( self, model, patterns ):
|
|
Command.__init__( self )
|
|
self._backdelay = None
|
|
|
|
self.addDependency( patterns )
|
|
self.addDependency( model )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return 'Asimut'
|
|
|
|
@property
|
|
def fileName ( self ): return self.name+'.pat'
|
|
|
|
@property
|
|
def backdelay ( self ): return self._backdelay
|
|
@backdelay.setter
|
|
def backdelay ( self, backdelay ):
|
|
self._backdelay = backdelay
|
|
self.addDependency( self._backdelay )
|
|
|
|
def setMbkEnv ( self ):
|
|
if self.flags & Asimut.RootIsBehavioral:
|
|
if not Environment.isExt(self.getDependency(1).extension,Environment.BehavioralExt):
|
|
raise ErrorMessage( 1, 'Asimut(): Invalid input behavioral file format/ext <%s>, must be <vbe>.'
|
|
% self.getDependency(1).extension )
|
|
else:
|
|
if Environment.isExt(self.getDependency(1).extension,Environment.StructuralExt):
|
|
self.IN_LO = self.getDependency(1).extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Asimut(): Invalid input structural (netlist) file format/ext <%s>.'
|
|
% self.getDependency(1).extension )
|
|
|
|
if self.extension != 'pat':
|
|
raise ErrorMessage( 1, 'Asimut(): Invalid output pattern file format/ext <%s>, must be <pat>.'
|
|
% self.extension )
|
|
if self.getDependency(0).extension != 'pat':
|
|
raise ErrorMessage( 1, 'Asimut(): Invalid input pattern file format/ext <%s>, must be <pat>.'
|
|
% self.getDependency(0).extension )
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'asimut' ]
|
|
if self.flags & Asimut.RootIsBehavioral: command += [ '-b' ]
|
|
if self.flags & Asimut.UseBdd: command += [ '-bdd' ]
|
|
if self.flags & Asimut.CompileOnly: command += [ '-c' ]
|
|
if self.flags & Asimut.ZeroDelay: command += [ '-zd' ]
|
|
if self._backdelay: command += [ '-backdelay', self.getDependency(1).name ]
|
|
|
|
command += [ self.getDependency(1).name ]
|
|
command += [ self.getDependency(0).name ]
|
|
command += [ self.name ]
|
|
return command
|
|
|
|
|
|
class Ocp ( Command ):
|
|
|
|
Ring = 0x00000001
|
|
Gnuplot = 0x00000002
|
|
|
|
def __init__ ( self, netlist ):
|
|
Command.__init__( self )
|
|
self._partial = None
|
|
self._ioc = None
|
|
self._margin = -1
|
|
|
|
self.addDependency( netlist )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return 'Ocp'
|
|
|
|
@property
|
|
def fileName ( self ): return self.name+'.'+self._extension
|
|
|
|
@property
|
|
def partial ( self ): return self._partial
|
|
@partial.setter
|
|
def partial ( self, partial ):
|
|
self._partial = partial
|
|
self.addDependency( self._partial )
|
|
|
|
@property
|
|
def ioc ( self ): return self._ioc
|
|
@ioc.setter
|
|
def ioc ( self, ioc ):
|
|
self._ioc = ioc
|
|
self.addDependency( self._ioc )
|
|
|
|
@property
|
|
def margin ( self ): return self._margin
|
|
@margin.setter
|
|
def margin ( self, margin ):
|
|
if margin < 0 or margin > 100:
|
|
raise ErrorMessage( 1, 'Ocp: Margin must be between 0 and 100% (%d)' % margin )
|
|
self._margin = margin
|
|
|
|
def setMbkEnv ( self ):
|
|
if Environment.isExt(self.extension,Environment.PhysicalExt):
|
|
self.OUT_PH = self.extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Ocp(): Invalid output layout file format/ext <%s>.'
|
|
% self.extension )
|
|
|
|
if Environment.isExt(self.getDependency(0).extension,Environment.StructuralExt):
|
|
self.IN_LO = self.getDependency(0).extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Ocp(): Input file format/ext must be structural, not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
|
|
if Environment.isExt(self._partial.extension,Environment.PhysicalExt):
|
|
self.IN_PH = self._partial.extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Ocp(): Invalid input layout file format/ext <%s> for partial placement.'
|
|
% self._partial.extension )
|
|
if self._ioc.extension != 'ioc':
|
|
raise ErrorMessage( 1, 'Ocp(): Invalid IOC file format/ext <%s>, must be <ioc>.'
|
|
% self._ioc.extension )
|
|
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'ocp', '-v' ]
|
|
if self.flags & Ocp.Ring: command += [ '-ring' ]
|
|
if self.flags & Ocp.Gnuplot: command += [ '-gnuplot' ]
|
|
if self._margin > 0: command += [ '-margin' , str(self._margin) ]
|
|
if self._partial: command += [ '-partial', self._partial.name ]
|
|
if self._ioc: command += [ '-ioc' , self._ioc.name ]
|
|
|
|
command += [ self.getDependency(0).name ]
|
|
command += [ self.name ]
|
|
return command
|
|
|
|
|
|
class Nero ( Command ):
|
|
|
|
ForceGlobalOff = 0x00000001
|
|
ForceGlobalOn = 0x00000002
|
|
Use2Layers = 0x00000004
|
|
Use3Layers = 0x00000008
|
|
Use4Layers = 0x00000010
|
|
Use5Layers = 0x00000020
|
|
Use6Layers = 0x00000040
|
|
|
|
def __init__ ( self, netlist ):
|
|
Command.__init__( self )
|
|
self._placement = None
|
|
self.addDependency( netlist )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return 'Nero'
|
|
|
|
@property
|
|
def fileName ( self ): return self.name+'.'+self._extension
|
|
|
|
@property
|
|
def placement ( self ): return self._placement
|
|
@placement.setter
|
|
def placement ( self, placement ):
|
|
self._placement = placement
|
|
self.addDependency( self._placement )
|
|
|
|
def setMbkEnv ( self ):
|
|
if Environment.isExt(self.extension,Environment.PhysicalExt):
|
|
self.OUT_PH = self.extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Nero(): Invalid output layout file format/ext <%s>.'
|
|
% self.extension )
|
|
|
|
if Environment.isExt(self.getDependency(0).extension,Environment.StructuralExt):
|
|
self.IN_LO = self.getDependency(0).extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Nero(): Input file format/ext must be structural, not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
|
|
if Environment.isExt(self._placement.extension,Environment.PhysicalExt):
|
|
self.IN_PH = self._placement.extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Nero(): Invalid input layout file format/ext <%s> for placement placement.'
|
|
% self._placement.extension )
|
|
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'nero', '-V' ]
|
|
if self.flags & Nero.ForceGlobalOff: command += [ '-L' ]
|
|
if self.flags & Nero.ForceGlobalOn: command += [ '-G' ]
|
|
if self.flags & Nero.Use2Layers: command += [ '-2' ]
|
|
if self.flags & Nero.Use3Layers: command += [ '-3' ]
|
|
if self.flags & Nero.Use4Layers: command += [ '-4' ]
|
|
if self.flags & Nero.Use5Layers: command += [ '-5' ]
|
|
if self.flags & Nero.Use6Layers: command += [ '-6' ]
|
|
if self._placement: command += [ '-p', self._placement.name ]
|
|
|
|
command += [ self.getDependency(0).name ]
|
|
command += [ self.name ]
|
|
return command
|
|
|
|
|
|
class Cougar ( Command ):
|
|
|
|
TransistorFlatten = 0x00000001
|
|
CatalogFlatten = 0x00000002
|
|
CapaToGround = 0x00000004
|
|
RCToGround = 0x00000008
|
|
|
|
def __init__ ( self, layout ):
|
|
Command.__init__( self )
|
|
self.addDependency( layout )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return 'Cougar'
|
|
|
|
@property
|
|
def fileName ( self ): return self.name+'.'+self._extension
|
|
|
|
def setMbkEnv ( self ):
|
|
if Environment.isExt(self.extension,Environment.StructuralExt):
|
|
self.OUT_LO = self.extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Cougar(): Invalid output netlist file format/ext <%s>.'
|
|
% self.extension )
|
|
|
|
if Environment.isExt(self.getDependency(0).extension,Environment.PhysicalExt):
|
|
self.IN_PH = self.getDependency(0).extension
|
|
else:
|
|
raise ErrorMessage( 1, 'Cougar(): Input file format/ext must be physical, not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'cougar', '-v' ]
|
|
if self.flags & Cougar.TransistorFlatten: command += [ '-t' ]
|
|
if self.flags & Cougar.CatalogFlatten: command += [ '-f' ]
|
|
if self.flags & Cougar.CapaToGround: command += [ '-ac' ]
|
|
if self.flags & Cougar.RCToGround: command += [ '-ar' ]
|
|
|
|
command += [ self.getDependency(0).name ]
|
|
command += [ self.name ]
|
|
return command
|
|
|
|
|
|
class Lvx ( StampCommand ):
|
|
|
|
MergeSupplies = 0x00000001
|
|
OrderConnectors = 0x00000002
|
|
CheckUnassigneds = 0x00000004
|
|
CatalogFlatten = 0x00000008
|
|
|
|
def __init__ ( self, netlist1, netlist2 ):
|
|
StampCommand.__init__( self )
|
|
self.addDependency( netlist1 )
|
|
self.addDependency( netlist2 )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return 'Lvx'
|
|
|
|
def setMbkEnv ( self ):
|
|
if not Environment.isExt(self.getDependency(0).extension,Environment.StructuralExt):
|
|
raise ErrorMessage( 1, 'Lvx(): Input file 1 format/ext must be structural (netlist), not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
if not Environment.isExt(self.getDependency(1).extension,Environment.StructuralExt):
|
|
raise ErrorMessage( 1, 'Lvx(): Input file 2 format/ext must be structural (netlist), not <%s>.'
|
|
% self.getDependency(1).extension )
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'lvx' ]
|
|
command += [ self.getDependency(0).extension ]
|
|
command += [ self.getDependency(1).extension ]
|
|
command += [ self.getDependency(0).name ]
|
|
command += [ self.getDependency(1).name ]
|
|
|
|
if self.flags & Lvx.MergeSupplies: command += [ '-a' ]
|
|
if self.flags & Lvx.CheckUnassigneds: command += [ '-u' ]
|
|
if self.flags & Lvx.CatalogFlatten: command += [ '-f' ]
|
|
return command
|
|
|
|
|
|
class Druc ( StampCommand ):
|
|
|
|
def __init__ ( self, layout ):
|
|
StampCommand.__init__( self )
|
|
self.addDependency( layout )
|
|
return
|
|
|
|
@property
|
|
def toolName ( self ): return 'Druc'
|
|
|
|
def setMbkEnv ( self ):
|
|
if not Environment.isExt(self.getDependency(0).extension,Environment.PhysicalExt):
|
|
raise ErrorMessage( 1, 'Druc(): Input file format/ext must be physical (layout), not <%s>.'
|
|
% self.getDependency(0).extension )
|
|
return
|
|
|
|
def asCommand ( self ):
|
|
command = [ 'druc', '-v' ]
|
|
command += [ self.getDependency(0).name ]
|
|
return command
|
|
|
|
|
|
class Tools ( object ):
|
|
|
|
def __init__ ( self ):
|
|
self._sourceNodes = []
|
|
self._toolNodes = []
|
|
self._ruleNodes = []
|
|
self._staticOrder = []
|
|
return
|
|
|
|
def _findNodes ( self ):
|
|
Node.findSelfSymbols()
|
|
|
|
for node in Node.getAllNodes():
|
|
isCommand = False
|
|
for commandType in Command.commandTypes:
|
|
if isinstance(node,commandType):
|
|
self._toolNodes.append( node )
|
|
isCommand = True
|
|
break
|
|
|
|
if not isCommand:
|
|
if isinstance(node,Source): self._sourceNodes.append( node )
|
|
if isinstance(node,Rule ): self._ruleNodes.append( node )
|
|
|
|
|
|
# Three level of stack from the user's script python module.
|
|
#callerGlobals = inspect.stack()[2][0].f_globals
|
|
#for symbol in callerGlobals.keys():
|
|
# isCommand = False
|
|
# node = callerGlobals[symbol]
|
|
# for commandType in Command.commandTypes:
|
|
# if isinstance(node,commandType):
|
|
# node.setTarget( symbol )
|
|
# self._toolNodes.append( node )
|
|
# isCommand = True
|
|
# break
|
|
#
|
|
# if not isCommand \
|
|
# and ( isinstance(node,Source)
|
|
# or isinstance(node,Rule )):
|
|
# 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 )
|
|
break
|
|
if not reacheds and nodeStack:
|
|
raise ErrorMessage( 1, 'Loop in dependency graph.' )
|
|
return
|
|
|
|
def _setMbkEnv ( self ):
|
|
for node in self._staticOrder:
|
|
node.setMbkEnv()
|
|
return
|
|
|
|
@staticmethod
|
|
def run ( args=[] ):
|
|
tool = Tools()
|
|
tool._findNodes()
|
|
tool._sortNodes()
|
|
tool._setMbkEnv()
|
|
|
|
doClean = False
|
|
for arg in args:
|
|
if arg == 'clean': doClean = True
|
|
else:
|
|
node = Node.lookup( arg )
|
|
if node: node.setActive()
|
|
|
|
if commandFlags & ShowCommand and not (commandFlags & ShowLog):
|
|
print "==========+===============================+============================================"
|
|
print " ACTION | TARGET/RULE | COMMAND"
|
|
print "==========+===============================+============================================"
|
|
|
|
if doClean:
|
|
Node.allClean()
|
|
if commandFlags & ShowCommand and not (commandFlags & ShowLog):
|
|
print "----------+-------------------------------+--------------------------------------------"
|
|
|
|
for node in tool._staticOrder:
|
|
#for dep in node.getDependencies():
|
|
# print dep.name
|
|
# print dep.fileName
|
|
if not isinstance(node,Source) and not isinstance(node,Rule):
|
|
if node._run(): break
|
|
|
|
if commandFlags & ShowCommand and not (commandFlags & ShowLog):
|
|
print "----------+-------------------------------+--------------------------------------------"
|
|
|
|
return
|