2014-07-27 09:23:27 -05:00
|
|
|
# -*- Mode:Python; explicit-buffer-name: "Alliance.py<cumulus>" -*-
|
|
|
|
#
|
|
|
|
# This file is part of the Coriolis Software.
|
2018-01-06 10:55:44 -06:00
|
|
|
# Copyright (c) UPMC 2014-2018, All Rights Reserved
|
2014-07-27 09:23:27 -05:00
|
|
|
#
|
|
|
|
# +-----------------------------------------------------------------+
|
|
|
|
# | 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
|
Support for mixing real pads & symbolic core. Wrapper around s2r.
* Change: In Hurricane::Error constructors disable the backtrace generation.
(*very* slow).
* Change: In Hurricane::Library::getHierarchicalname(), more compact
naming. Remove the name of the root library.
* New: In Hurricane::Net, new type "FUSED", for component with no net.
More efficient than having one net for each.
* Change: In CellViewer, BreakpointWidget, use Angry Birds icons.
* Change: In CellWidget::State, use the hierarchical name (cached) as key
to the state. This allow to load two cells with the same name but from
different libraries in the widget history.
* Change: In PyGraphics, export "isEnabled()" and "isHighDpi()" functions.
* Change: In CRL/etc/symbolic/cmos/plugin.conf, and
CRL/etc/common/plugin.conf use the physical dimensions converters.
* Change: In CRL/etc/symbolic/cmos/technology.conf, make the GDS layer
table coherent with the default Alliance cmos.rds.
* New: CRL/python/helpers/io.py, put ErrorMessage new implementation here,
along with a new ErrorWidget written in PyQt4. It seems finally that
PyQt4 can be used alongside Coriolis Qt widgets.
New ErrorMessage.catch() static function to manage all exceptions
in except clauses.
* Change: In CRL/python/helpers/, no longer use ErrorMessage.wrapPrint(),
directly print it.
Rewrite the utilities to display Python stack traces "textStacktrace()"
and "showStacktrace()".
* Change: In CRL::AllianceFramework, shorten the names of the libraries.
* Change: In CRL::ApParser & CRL::ApDriver, more accurate translation between
Alliance connectors (C record) and Hurricane::Pin objects. Pin are no
longer made square but thin and oriented in the connecting direction.
Use the new fused net for unnamed components.
* New: In CRL::GdsParser, implementation of SREF parsing, i.e. instances.
Due to the unordered nature of the GDS stream, instances creation are
delayed until the whole stream has been parsed and only then are they
created.
For the sake of reading back Alliance s2r GDS, we assume that any
TEXT following a boundary is the Net name the boundary (component)
belongs to.
Create abutment box for Cells, computed from the bounding box, so
the Hurricane QuadTree could work properly.
Make use of the fused net for unnamed components.
* New: In Cumulus/plugins/chip, complete rewrite of the I/O pad management.
Now we can mix real (foundry) pads and a symbolic core.
To cleanly support the de-coupling between the real part and the
symbolic one we introduce a new intermediary hierarchical level, the
corona. We have now:
Chip --> Pads + Corona --> Core.
At chip level (and if we are using real pads) the layout is fully
real (excepting the corona).
The Corona contains everything that is symbolic. It has symbolic
wires extending outward the abutment box to make contact with the
real wires coming from the pads.
In the pad ring we can use corners instances (or not), pad spacers
or directly draw wires between connectors ring pads.
Provide two flavors: placement only or full place & route.
WARNING: If routing in a second step, *do not route* the *Chip* but
the *Corona*.
* Change: In Cumulus/plugins/clocktree, give the modified Cell an
additional extension of "_cts" (Clock Tree Synthesis) instead of
"_clocked", to follow the common convention.
* New: In cumulus/plugins/S2R.py, encapsulate call to Alliance S2R and
reload the translated Cell in the editor.
* New: In cumulus/plugins/core2chip, provide an utility to automatically
create a chip from a core. To work this plugins must have a basic
understanding of the pad functionalities which may differs from
foundry to foundry. So a base class CoreToChip is created, then for
each supported pad foundry a derived class is added. Currently we
support AMS c35b4 and Alliance symbolic cmos.
* Bug: In Anabatic::Configuration, read the right configuration parameter
"anabatic.topRoutinglayer" (Katana), and not the one for Katabatic...
* Change: In Unicorn/cgt.py, process the plugins in alphabetical order
to ensure a reproductible ordering of the menus...
2019-05-22 07:34:32 -05:00
|
|
|
from helpers.io import ErrorMessage
|
|
|
|
from helpers.io import WarningMessage
|
|
|
|
from helpers import Dots
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
|
|
|
|
# Global display flags
|
|
|
|
ShowCommand = 0x00001000
|
|
|
|
ShowLog = 0x00002000
|
2014-08-15 12:05:27 -05:00
|
|
|
ShowDots = 0x00004000
|
|
|
|
ForceRun = 0x00008000
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
commandFlags = ShowCommand | ShowLog
|
|
|
|
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
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()
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Environment ( object ):
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
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' ]
|
|
|
|
}
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@staticmethod
|
2014-08-15 12:05:27 -05:00
|
|
|
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:]
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
return None, None
|
2014-08-15 12:05:27 -05:00
|
|
|
|
|
|
|
@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
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
|
|
|
|
def __init__ ( self, flags ):
|
|
|
|
self.mbkEnv = {}
|
|
|
|
if flags & Environment.DefaultEnv:
|
2014-08-15 12:05:27 -05:00
|
|
|
self.mbkEnv[ 'ALLIANCE_TOP' ] = None
|
|
|
|
self.mbkEnv[ 'LD_LIBRARY_PATH' ] = None
|
2014-07-27 09:23:27 -05:00
|
|
|
self.mbkEnv[ 'MBK_TARGET_LIB' ] = None
|
|
|
|
self.mbkEnv[ 'MBK_WORK_LIB' ] = '.'
|
2014-08-15 12:05:27 -05:00
|
|
|
self.mbkEnv[ 'MBK_CATA_LIB' ] = SearchPath()
|
2014-07-27 09:23:27 -05:00
|
|
|
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:
|
2014-08-15 12:05:27 -05:00
|
|
|
self.mbkEnv[ 'ALLIANCE_TOP' ] = None
|
|
|
|
self.mbkEnv[ 'LD_LIBRARY_PATH' ] = None
|
2014-07-27 09:23:27 -05:00
|
|
|
self.mbkEnv[ 'MBK_TARGET_LIB' ] = None
|
|
|
|
self.mbkEnv[ 'MBK_WORK_LIB' ] = None
|
2014-08-15 12:05:27 -05:00
|
|
|
self.mbkEnv[ 'MBK_CATA_LIB' ] = SearchPath()
|
2014-07-27 09:23:27 -05:00
|
|
|
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
|
2014-08-15 12:05:27 -05:00
|
|
|
if key == 'ALLIANCE_TOP': self.mbkEnv[ key ] = value
|
2014-07-27 09:23:27 -05:00
|
|
|
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
|
2014-08-15 12:05:27 -05:00
|
|
|
self.mbkEnv['MBK_CATA_LIB'].add( libPath, mode )
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
except Exception, e:
|
Support for mixing real pads & symbolic core. Wrapper around s2r.
* Change: In Hurricane::Error constructors disable the backtrace generation.
(*very* slow).
* Change: In Hurricane::Library::getHierarchicalname(), more compact
naming. Remove the name of the root library.
* New: In Hurricane::Net, new type "FUSED", for component with no net.
More efficient than having one net for each.
* Change: In CellViewer, BreakpointWidget, use Angry Birds icons.
* Change: In CellWidget::State, use the hierarchical name (cached) as key
to the state. This allow to load two cells with the same name but from
different libraries in the widget history.
* Change: In PyGraphics, export "isEnabled()" and "isHighDpi()" functions.
* Change: In CRL/etc/symbolic/cmos/plugin.conf, and
CRL/etc/common/plugin.conf use the physical dimensions converters.
* Change: In CRL/etc/symbolic/cmos/technology.conf, make the GDS layer
table coherent with the default Alliance cmos.rds.
* New: CRL/python/helpers/io.py, put ErrorMessage new implementation here,
along with a new ErrorWidget written in PyQt4. It seems finally that
PyQt4 can be used alongside Coriolis Qt widgets.
New ErrorMessage.catch() static function to manage all exceptions
in except clauses.
* Change: In CRL/python/helpers/, no longer use ErrorMessage.wrapPrint(),
directly print it.
Rewrite the utilities to display Python stack traces "textStacktrace()"
and "showStacktrace()".
* Change: In CRL::AllianceFramework, shorten the names of the libraries.
* Change: In CRL::ApParser & CRL::ApDriver, more accurate translation between
Alliance connectors (C record) and Hurricane::Pin objects. Pin are no
longer made square but thin and oriented in the connecting direction.
Use the new fused net for unnamed components.
* New: In CRL::GdsParser, implementation of SREF parsing, i.e. instances.
Due to the unordered nature of the GDS stream, instances creation are
delayed until the whole stream has been parsed and only then are they
created.
For the sake of reading back Alliance s2r GDS, we assume that any
TEXT following a boundary is the Net name the boundary (component)
belongs to.
Create abutment box for Cells, computed from the bounding box, so
the Hurricane QuadTree could work properly.
Make use of the fused net for unnamed components.
* New: In Cumulus/plugins/chip, complete rewrite of the I/O pad management.
Now we can mix real (foundry) pads and a symbolic core.
To cleanly support the de-coupling between the real part and the
symbolic one we introduce a new intermediary hierarchical level, the
corona. We have now:
Chip --> Pads + Corona --> Core.
At chip level (and if we are using real pads) the layout is fully
real (excepting the corona).
The Corona contains everything that is symbolic. It has symbolic
wires extending outward the abutment box to make contact with the
real wires coming from the pads.
In the pad ring we can use corners instances (or not), pad spacers
or directly draw wires between connectors ring pads.
Provide two flavors: placement only or full place & route.
WARNING: If routing in a second step, *do not route* the *Chip* but
the *Corona*.
* Change: In Cumulus/plugins/clocktree, give the modified Cell an
additional extension of "_cts" (Clock Tree Synthesis) instead of
"_clocked", to follow the common convention.
* New: In cumulus/plugins/S2R.py, encapsulate call to Alliance S2R and
reload the translated Cell in the editor.
* New: In cumulus/plugins/core2chip, provide an utility to automatically
create a chip from a core. To work this plugins must have a basic
understanding of the pad functionalities which may differs from
foundry to foundry. So a base class CoreToChip is created, then for
each supported pad foundry a derived class is added. Currently we
support AMS c35b4 and Alliance symbolic cmos.
* Bug: In Anabatic::Configuration, read the right configuration parameter
"anabatic.topRoutinglayer" (Katana), and not the one for Katabatic...
* Change: In Unicorn/cgt.py, process the plugins in alphabetical order
to ensure a reproductible ordering of the menus...
2019-05-22 07:34:32 -05:00
|
|
|
e = ErrorMessage( e )
|
|
|
|
e.addMessage( 'In %s:<Alliance> at index %d.' % (allianceFile,entryNo) )
|
|
|
|
print e
|
2014-08-15 12:05:27 -05:00
|
|
|
|
|
|
|
self.mbkEnv[ 'LD_LIBRARY_PATH' ] = self.mbkEnv[ 'ALLIANCE_TOP' ] + '/lib'
|
2014-07-27 09:23:27 -05:00
|
|
|
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:
|
2014-08-15 12:05:27 -05:00
|
|
|
print ' o Running configuration hook: Alliance.staticInitialization().'
|
|
|
|
print ' - Loading \"%s\".' % helpers.truncPath(confFile)
|
2014-07-27 09:23:27 -05:00
|
|
|
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 )
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
print
|
|
|
|
return
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
helpers.staticInitialization()
|
|
|
|
staticInitialization()
|
2014-08-15 12:05:27 -05:00
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
report = ReportLog( 'alliance' )
|
|
|
|
|
|
|
|
|
|
|
|
class Node ( EnvironmentWrapper ):
|
|
|
|
|
|
|
|
Unreached = -1
|
|
|
|
|
|
|
|
__allNodes = []
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def getAllNodes (): return Node.__allNodes
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
@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
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
def __init__ ( self ):
|
|
|
|
EnvironmentWrapper.__init__( self, env )
|
2014-08-15 12:05:27 -05:00
|
|
|
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]
|
2014-07-27 09:23:27 -05:00
|
|
|
Node.__allNodes.append( self )
|
|
|
|
return
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
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
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
@property
|
|
|
|
def targetName ( self ): return self._targetName
|
|
|
|
|
|
|
|
def setDefaultTargetName ( self ):
|
2014-08-15 12:05:27 -05:00
|
|
|
if self._dependencies == []:
|
2014-07-27 09:23:27 -05:00
|
|
|
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)
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
def checkFile ( self, hardStop=False, errorMessage=[] ):
|
2014-07-27 09:23:27 -05:00
|
|
|
if not os.path.isfile(self.fileName):
|
|
|
|
error = ErrorMessage( 1, 'File <%s> of node <%s> has not been created.'
|
|
|
|
% (self.fileName,self._targetName) )
|
2014-08-15 12:05:27 -05:00
|
|
|
if errorMessage:
|
|
|
|
print
|
|
|
|
for line in errorMessage: print line
|
2014-07-27 09:23:27 -05:00
|
|
|
if hardStop:
|
|
|
|
raise error
|
|
|
|
else:
|
|
|
|
print error
|
|
|
|
return
|
|
|
|
|
|
|
|
def isUptodate ( self ):
|
|
|
|
depsMTime = 0
|
2014-08-15 12:05:27 -05:00
|
|
|
#print ' Target: %-30s %d' % (self.fileName, self.mtime)
|
2014-07-27 09:23:27 -05:00
|
|
|
for dependency in self.getDependencies():
|
|
|
|
dependency.checkFile()
|
|
|
|
depsMTime = max( depsMTime, dependency.mtime )
|
2014-08-15 12:05:27 -05:00
|
|
|
#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()
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name ( self ): return self._targetName
|
|
|
|
|
|
|
|
@property
|
2014-08-15 12:05:27 -05:00
|
|
|
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
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@property
|
|
|
|
def mtime ( self ):
|
|
|
|
if not os.path.isfile(self.fileName): return 0
|
|
|
|
return os.stat( self.fileName )[ stat.ST_MTIME ]
|
|
|
|
|
|
|
|
|
|
|
|
class Command ( Node ):
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
commandTypes = []
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
def __init__ ( self ):
|
|
|
|
Node.__init__( self )
|
|
|
|
self._flags = 0
|
2014-08-15 12:05:27 -05:00
|
|
|
Command.commandTypes.append( type(self) )
|
2014-07-27 09:23:27 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def asString ( command ):
|
|
|
|
s = ''
|
|
|
|
for i in range( len(command) ):
|
|
|
|
if i: s += ' '
|
|
|
|
s += command[i]
|
|
|
|
return s
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
@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
|
2014-07-27 09:23:27 -05:00
|
|
|
@property
|
|
|
|
def flags ( self ): return self._flags
|
|
|
|
@flags.setter
|
|
|
|
def flags ( self, flags ): self._flags = flags
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
def _run ( self, checkFile=True ):
|
2014-07-27 09:23:27 -05:00
|
|
|
global commandFlags
|
|
|
|
|
|
|
|
flags = commandFlags
|
|
|
|
if self._flags: flags = self._flags
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
command = self.asCommand()
|
|
|
|
ruleName = "<%s>" % self.ruleName
|
2014-07-27 09:23:27 -05:00
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
if self.isActive() and (not self.isUptodate() or flags & ForceRun):
|
2014-07-27 09:23:27 -05:00
|
|
|
if flags & ShowCommand:
|
2014-08-15 12:05:27 -05:00
|
|
|
print "Executing | %-30s%s" % (ruleName,Command.indent(command,42))
|
2014-07-27 09:23:27 -05:00
|
|
|
child = subprocess.Popen( command
|
|
|
|
, env=self.env.toSystemEnv()
|
|
|
|
, stdout=subprocess.PIPE
|
|
|
|
, stderr=subprocess.PIPE
|
|
|
|
)
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
dots = Dots( ' '*42+'| ', 109 )
|
2014-07-27 09:23:27 -05:00
|
|
|
report.open()
|
2014-08-15 12:05:27 -05:00
|
|
|
report.write( 'Executing command: %s \n' % ruleName )
|
2014-07-27 09:23:27 -05:00
|
|
|
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()
|
2014-08-15 12:05:27 -05:00
|
|
|
elif flags & ShowDots:
|
|
|
|
dots.dot()
|
|
|
|
|
|
|
|
report.write( line )
|
|
|
|
|
|
|
|
errorLines = []
|
|
|
|
while True:
|
|
|
|
line = child.stderr.readline()
|
|
|
|
if not line: break
|
2014-07-27 09:23:27 -05:00
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
errorLines.append( line[:-1] )
|
|
|
|
sys.stderr.flush()
|
2014-07-27 09:23:27 -05:00
|
|
|
report.write( line )
|
2014-08-15 12:05:27 -05:00
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
report.close()
|
2014-08-15 12:05:27 -05:00
|
|
|
dots.reset()
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
(pid,status) = os.waitpid(child.pid, 0)
|
|
|
|
status >>= 8
|
|
|
|
if status != 0:
|
2014-08-15 12:05:27 -05:00
|
|
|
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 )
|
2014-07-27 09:23:27 -05:00
|
|
|
else:
|
2014-08-15 12:05:27 -05:00
|
|
|
if self.isActive(): action = 'Up to date'
|
|
|
|
else: action = 'Inactive'
|
2014-07-27 09:23:27 -05:00
|
|
|
if flags & ShowCommand:
|
2014-08-15 12:05:27 -05:00
|
|
|
print "%-10s| %-30s%s" % (action,ruleName,Command.indent(command,42))
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
report.open()
|
2014-08-15 12:05:27 -05:00
|
|
|
report.write( '%s command:\n' % action )
|
2014-07-27 09:23:27 -05:00
|
|
|
report.write( ' %s\n' % Command.asString(command) )
|
|
|
|
report.close()
|
|
|
|
status = 0
|
|
|
|
|
|
|
|
return status
|
|
|
|
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
class Probe ( Command ):
|
|
|
|
|
|
|
|
def __init__ ( self, script ):
|
|
|
|
Command.__init__( self )
|
2014-08-15 12:05:27 -05:00
|
|
|
self.addDependency( script )
|
2014-07-27 09:23:27 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
@property
|
2014-08-15 12:05:27 -05:00
|
|
|
def toolName ( self ): return self.getDependency(0).name+'_'+self.getDependency(0).extension
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
def asCommand ( self ):
|
2014-08-15 12:05:27 -05:00
|
|
|
return [ os.path.join(os.getcwd(),self.getDependency(0).fileName) ]
|
|
|
|
|
|
|
|
def _run ( self ):
|
|
|
|
Command._run( self, checkFile=False )
|
|
|
|
return
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
|
|
|
|
class Source ( Node ):
|
|
|
|
|
|
|
|
def __init__ ( self ):
|
|
|
|
Node.__init__( self )
|
|
|
|
return
|
|
|
|
|
|
|
|
@property
|
2014-08-15 12:05:27 -05:00
|
|
|
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
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
def setTarget ( self, name ):
|
2014-08-15 12:05:27 -05:00
|
|
|
self._targetName = name
|
2014-07-27 09:23:27 -05:00
|
|
|
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
|
2014-08-15 12:05:27 -05:00
|
|
|
def fileName ( self ): return self.name+'.'+self.extension
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@property
|
|
|
|
def directives ( self ): return self._directives
|
|
|
|
@directives.setter
|
|
|
|
def directives ( self, directives ):
|
|
|
|
self._directives = directives
|
2014-08-15 12:05:27 -05:00
|
|
|
self.addDependency( self._directives )
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@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
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
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
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
def asCommand ( self ):
|
|
|
|
command = [ 'boom' ]
|
2014-08-15 12:05:27 -05:00
|
|
|
#command = [ './boom.sh' ]
|
2014-07-27 09:23:27 -05:00
|
|
|
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' ]
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
if self._directives: command += [ '-P', self.getDependency(1).name ]
|
2014-07-27 09:23:27 -05:00
|
|
|
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
|
2014-08-15 12:05:27 -05:00
|
|
|
def fileName ( self ): return self.name+'.'+self.extension
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@property
|
2014-08-15 12:05:27 -05:00
|
|
|
def laxFile ( self ): return self._laxNode
|
2014-07-27 09:23:27 -05:00
|
|
|
@laxFile.setter
|
2014-08-15 12:05:27 -05:00
|
|
|
def laxFile ( self, laxNode ):
|
|
|
|
self._laxNode = laxNode
|
|
|
|
self.addDependency( self._laxNode )
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@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
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
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
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
def asCommand ( self ):
|
|
|
|
command = [ 'boog' ]
|
|
|
|
if self._optimMode < 5: command += [ '-m', str(self._optimMode) ]
|
|
|
|
if self._xschMode < 2: command += [ '-x', str(self._xschMode) ]
|
2014-08-15 12:05:27 -05:00
|
|
|
if self._laxFile: command += [ '-l', self.getDependency(1).name ]
|
2014-07-27 09:23:27 -05:00
|
|
|
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
|
2014-08-15 12:05:27 -05:00
|
|
|
def fileName ( self ): return self.name+'.'+self.OUT_LO
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@property
|
|
|
|
def laxFile ( self ): return self._laxFile
|
|
|
|
@laxFile.setter
|
|
|
|
def laxFile ( self, laxFile ):
|
|
|
|
self._laxFile = laxFile
|
2014-08-15 12:05:27 -05:00
|
|
|
self.addDependency( self._laxFile )
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
@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
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
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
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
class Tools ( object ):
|
|
|
|
|
|
|
|
def __init__ ( self ):
|
|
|
|
self._sourceNodes = []
|
|
|
|
self._toolNodes = []
|
2014-08-15 12:05:27 -05:00
|
|
|
self._ruleNodes = []
|
2014-07-27 09:23:27 -05:00
|
|
|
self._staticOrder = []
|
|
|
|
return
|
|
|
|
|
|
|
|
def _findNodes ( self ):
|
2014-08-15 12:05:27 -05:00
|
|
|
Node.findSelfSymbols()
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
for node in Node.getAllNodes():
|
2014-08-15 12:05:27 -05:00
|
|
|
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 )
|
2014-07-27 09:23:27 -05:00
|
|
|
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 )
|
2014-08-15 12:05:27 -05:00
|
|
|
break
|
2014-07-27 09:23:27 -05:00
|
|
|
if not reacheds and nodeStack:
|
|
|
|
raise ErrorMessage( 1, 'Loop in dependency graph.' )
|
|
|
|
return
|
|
|
|
|
2014-08-15 12:05:27 -05:00
|
|
|
def _setMbkEnv ( self ):
|
|
|
|
for node in self._staticOrder:
|
|
|
|
node.setMbkEnv()
|
|
|
|
return
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
@staticmethod
|
2014-08-15 12:05:27 -05:00
|
|
|
def run ( args=[] ):
|
|
|
|
tool = Tools()
|
2014-07-27 09:23:27 -05:00
|
|
|
tool._findNodes()
|
|
|
|
tool._sortNodes()
|
2014-08-15 12:05:27 -05:00
|
|
|
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 "----------+-------------------------------+--------------------------------------------"
|
2014-07-27 09:23:27 -05:00
|
|
|
|
|
|
|
for node in tool._staticOrder:
|
|
|
|
#for dep in node.getDependencies():
|
|
|
|
# print dep.name
|
|
|
|
# print dep.fileName
|
2014-08-15 12:05:27 -05:00
|
|
|
if not isinstance(node,Source) and not isinstance(node,Rule):
|
|
|
|
if node._run(): break
|
|
|
|
|
|
|
|
if commandFlags & ShowCommand and not (commandFlags & ShowLog):
|
|
|
|
print "----------+-------------------------------+--------------------------------------------"
|
|
|
|
|
2014-07-27 09:23:27 -05:00
|
|
|
return
|