coriolis/cumulus/src/tools/px2mpx.py

354 lines
13 KiB
Python
Executable File

#!/usr/bin/env python
try:
import sys
import traceback
import os.path
import optparse
import math
import Cfg
import Hurricane
from Hurricane import DataBase
from Hurricane import DbU
from Hurricane import Transformation
from Hurricane import Box
from Hurricane import UpdateSession
from Hurricane import Breakpoint
from Hurricane import Net
from Hurricane import NetExternalComponents
from Hurricane import BasicLayer
from Hurricane import ContactLayer
from Hurricane import ViaLayer
from Hurricane import RegularLayer
from Hurricane import TransistorLayer
from Hurricane import DiffusionLayer
from Hurricane import Cell
from Hurricane import Instance
from Hurricane import Net
from Hurricane import Contact
from Hurricane import Horizontal
from Hurricane import Vertical
import Viewer
import CRL
from CRL import RoutingLayerGauge
import helpers
from helpers import trace
from helpers.io import ErrorMessage
except ImportError, e:
serror = str(e)
if serror.startswith('No module named'):
module = serror.split()[-1]
print '[ERROR] The <%s> python module or symbol cannot be loaded.' % module
print ' Please check the integrity of the <coriolis> package.'
if str(e).find('cannot open shared object file'):
library = serror.split(':')[0]
print '[ERROR] The <%s> shared library cannot be loaded.' % library
print ' Under RHEL 6, you must be under devtoolset-2.'
print ' (scl enable devtoolset-2 bash)'
sys.exit(1)
except Exception, e:
print '[ERROR] A strange exception occurred while loading the basic Coriolis/Python'
print ' modules. Something may be wrong at Python/C API level.\n'
print ' %s' % e
sys.exit(2)
framework = CRL.AllianceFramework.get()
def getDeltas ( layer ):
#deltas = { 'L_METAL1' : DbU.fromLambda( -1.0 )
# , 'L_METAL2' : DbU.fromLambda( 3.0 )
# , 'L_blockage2': DbU.fromLambda( -1.0 )
# , 'L_blockage4': DbU.fromLambda( -1.0 )
# , 'L_xWell' : DbU.fromLambda( 6.0 )
# , 'L_Trans' : DbU.fromLambda( -3.0 )
# , 'L_Diff' : DbU.fromLambda( -1.0 )
# , 'L_Tie' : DbU.fromLambda( 1.2 )
# , 'W_Diff' : DbU.fromLambda( 0.2 )
# , 'W_xWell' : DbU.fromLambda( 12.0 )
# , 'mW_METAL1' : DbU.fromLambda( 4.0 )
# , 'mW_METAL2' : DbU.fromLambda( 4.0 )
# }
deltas = { 'L_METAL1' : DbU.fromLambda( -1.0 )
, 'L_METAL2' : DbU.fromLambda( 1.5 )
, 'L_blockage2': DbU.fromLambda( -0.5 )
, 'L_blockage4': DbU.fromLambda( -0.5 )
, 'L_xWell' : DbU.fromLambda( 6.0 )
, 'L_Trans' : DbU.fromLambda( -3.0 )
, 'L_Diff' : DbU.fromLambda( -1.0 )
, 'L_Tie' : DbU.fromLambda( 1.2 )
, 'W_Diff' : DbU.fromLambda( 0.2 )
, 'W_xWell' : DbU.fromLambda( 12.0 )
, 'W_blockage2': DbU.fromLambda( -1.0 )
, 'mW_METAL1' : DbU.fromLambda( 4.0 )
, 'mW_METAL2' : DbU.fromLambda( 6.0 )
}
dL = 0
dW = 0
mW = 0
if isinstance(layer,TransistorLayer):
dL = deltas[ 'L_Trans' ]
elif isinstance(layer,RegularLayer):
if layer.getName() == 'METAL1':
dL = deltas[ 'L_METAL1' ]
mW = deltas[ 'mW_METAL1' ]
elif layer.getName() == 'METAL2' or layer.getName() == 'METAL3':
dL = deltas[ 'L_METAL2' ]
mW = deltas[ 'mW_METAL2' ]
elif layer.getName() == 'BLOCKAGE2':
dL = deltas[ 'L_blockage2' ]
elif layer.getName() == 'BLOCKAGE4':
dL = deltas[ 'L_blockage4' ]
elif layer.getName().endswith('WELL'):
dL = deltas[ 'L_xWell' ]
dW = deltas[ 'W_xWell' ]
elif isinstance(layer,DiffusionLayer):
if layer.getName().endswith('DIF'):
dL = deltas[ 'L_Diff' ]
dW = deltas[ 'W_Diff' ]
elif layer.getName().endswith('TIE'):
dL = deltas[ 'L_Tie' ]
return dL, dW, mW
def px2mpx ( editor, pxCell ):
global framework
if pxCell == None:
raise ErrorMessage( 3, 'px2mpx.px2mpx(): Mandatory pxCell argument is None.' )
mpxCell = None
print '\nProcessing', pxCell
UpdateSession.open()
try:
if pxCell.getName() != 'padreal':
mpxCellName = pxCell.getName()[:-2]+'mpx'
else:
mpxCellName = pxCell.getName()+'_mpx'
mpxCell = framework.createCell( mpxCellName )
if editor:
editor.setCell( mpxCell )
Left = 0x0001
Right = 0x0002
Middle = 0x0000
AllSpan = Left|Right
ab = pxCell.getAbutmentBox()
mpxCell.setAbutmentBox( Box( ab.getXMin()*2, ab.getYMin()*2, ab.getXMax()*2, ab.getYMax()*2 ) )
for instance in pxCell.getInstances():
masterCell = instance.getMasterCell()
if masterCell.getName() == 'padreal':
masterCell = framework.getCell( 'padreal_mpx', CRL.Catalog.State.Physical )
originTransf = instance.getTransformation()
mpxInstance = Instance.create( mpxCell
, instance.getName()
, masterCell
, Transformation( originTransf.getTx()*2
, originTransf.getTy()*2
, originTransf.getOrientation() )
)
mpxInstance.setPlacementStatus( Instance.PlacementStatus.PLACED )
for net in pxCell.getNets():
mpxNet = Net.create( mpxCell, net.getName() )
if net.isExternal(): mpxNet.setExternal( True )
if net.isGlobal (): mpxNet.setGlobal( True )
mpxNet.setType ( net.getType () )
mpxNet.setDirection( net.getDirection() )
for component in net.getComponents():
layer = component.getLayer()
dupComponent = None
print ' Processing', component
if isinstance(component,Contact):
dupComponent = Contact.create( mpxNet
, layer
, component.getX ()*2
, component.getY ()*2
, component.getWidth ()*2
, component.getHeight()*2
)
elif isinstance(component,Horizontal):
dL, dW, mW = getDeltas( layer )
dLLeft = dL
dLRight = dL
skipComponent = False
bb = component.getBoundingBox()
if component.getSourceX() > component.getTargetX(): component.invert()
if isinstance(layer,RegularLayer):
if layer.getBasicLayer().getMaterial().getCode() == BasicLayer.Material.blockage:
print ' Blockage BB:%s vs. AB:%s' % (bb, ab)
if layer.getName()[-1] == '2' or layer.getName()[-1] == '4':
state = 0
if bb.getXMin() <= ab.getXMin(): state |= Left
if bb.getXMax() >= ab.getXMax(): state |= Right
if not (state&Left):
print ' Shrink left.'
dLLeft = dL - DbU.fromLambda( 1.5 )
if not(state&Right):
print ' Shrink right.'
dLRight = dL - DbU.fromLambda( 1.5 )
if layer.getName()[-1] == '4' and state == AllSpan:
print ' Skipping component.'
skipComponent = True
width = mW
if component.getWidth() > mW:
width = component.getWidth()*2 + dW
#print DbU.toLambda(bb.getWidth()), DbU.toLambda( dLLeft-dLRight)
if bb.getWidth()*2 > abs(dLLeft+dLRight) and not skipComponent:
dupComponent = Horizontal.create( mpxNet
, layer
, component.getY ()*2
, width
, component.getDxSource()*2 - dLLeft
, component.getDxTarget()*2 + dLRight
)
print ' Copy:', dupComponent
else:
print ' Horizontal component too small *or* skipped, not converted'
elif isinstance(component,Vertical):
dL, dW, mW = getDeltas( component.getLayer() )
dLTop = dL
dLBottom = dL
dX = 0
skipComponent = False
if component.getSourceY() > component.getTargetY(): component.invert()
if isinstance(layer,RegularLayer):
if layer.getBasicLayer().getMaterial().getCode() == BasicLayer.Material.blockage:
if layer.getName()[-1] == '3' or layer.getName()[-1] == '5':
state = 0
bb = component.getBoundingBox()
if bb.getXMin() <= ab.getXMin(): state |= Left
if bb.getXMax() >= ab.getXMax(): state |= Right
if state == Left:
dX = DbU.fromLambda( -2.0 )
dW += DbU.fromLambda( -2.0 )
elif state == Right:
dX = DbU.fromLambda( 2.0 )
dW += DbU.fromLambda( -2.0 )
elif state == 0:
dX = 0
dW += DbU.fromLambda( -4.0 )
if layer.getName()[-1] == '5':
if state == AllSpan:
print ' Skipping component.'
skipComponent = True
else:
dLTop = DbU.fromLambda(120.0) - component.getDyTarget()*2
if dW < component.getWidth() and not skipComponent:
width = mW
if component.getWidth() > mW:
width = component.getWidth()*2 + dW
dupComponent = Vertical.create( mpxNet
, layer
, component.getX ()*2 + dX
, width
, component.getDySource()*2 - dLBottom
, component.getDyTarget()*2 + dLTop
)
else:
print ' Vertical component too small *or* skipped, not converted'
else:
print '[WARNING] Unchanged component:', component
if dupComponent and NetExternalComponents.isExternal( component ):
NetExternalComponents.setExternal( dupComponent )
if editor: editor.fit()
except ErrorMessage, e:
print e; errorCode = e.code
except Exception, e:
print '\n\n', e; errorCode = 1
traceback.print_tb(sys.exc_info()[2])
UpdateSession.close()
return mpxCell
def ScriptMain ( **kw ):
global framework
global padrealCell
helpers.staticInitialization( quiet=True )
#helpers.setTraceLevel( 550 )
pxCell = None
if kw.has_key('cell') and kw['cell']:
pxCell = kw['cell']
editor = None
if kw.has_key('editor') and kw['editor']:
editor = kw['editor']
print ' o Editor detected, running in graphic mode.'
if pxCell == None: pxCell = editor.getCell()
if pxCell:
mpxCell = px2mpx( editor, pxCell )
else:
pxlibDir = '/dsk/l1/jpc/alliance/Linux.slsoc6x/install/cells/pxlib'
if os.path.isdir(pxlibDir):
print ' o <%s> found.' % pxlibDir
for viewFile in os.listdir( pxlibDir ):
if viewFile == 'padreal.ap':
pxCell = framework.getCell( viewFile[:-3], CRL.Catalog.State.Views )
padrealCell = px2mpx( editor, pxCell )
framework.saveCell( padrealCell, CRL.Catalog.State.Physical )
break
for viewFile in os.listdir( pxlibDir ):
if viewFile == 'padreal.ap': continue
if viewFile.endswith('_sp.ap'): continue
#if viewFile != 'pot_px.ap': continue
if viewFile.endswith('.ap'):
pxCell = framework.getCell( viewFile[:-3], CRL.Catalog.State.Views )
mpxCell = px2mpx( editor, pxCell )
framework.saveCell( mpxCell, CRL.Catalog.State.Physical )
else:
print '[WARNING] <%s> not found.' % pxlibDir
return 0
if __name__ == '__main__':
parser = optparse.OptionParser()
parser.add_option( '-c', '--cell', type='string', dest='cell' , help='The name of the chip to build, without extension.')
parser.add_option( '-v', '--verbose' , action='store_true', dest='verbose' , help='First level of verbosity.')
parser.add_option( '-V', '--very-verbose' , action='store_true', dest='veryVerbose', help='Second level of verbosity.')
(options, args) = parser.parse_args()
kw = {}
if options.cell:
kw['cell'] = framework.getCell( options.cell, CRL.Catalog.State.Logical )
if options.verbose: Cfg.getParamBool('misc.verboseLevel1').setBool(True)
if options.veryVerbose: Cfg.getParamBool('misc.verboseLevel2').setBool(True)
success = ScriptMain( **kw )
shellSuccess = 0
if not success: shellSuccess = 1
sys.exit( shellSuccess )