#!/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 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 )