#!/usr/bin/env python try: import sys import traceback import os.path import optparse import Cfg import Hurricane from Hurricane import DbU from Hurricane import UpdateSession from Hurricane import Breakpoint from Hurricane import Transformation from Hurricane import Instance import Viewer import CRL from helpers import ErrorMessage import Nimbus import Metis import Mauka import Katabatic import Kite import Unicorn import placeandroute except ImportError, e: module = str(e).split()[-1] print '[ERROR] The <%s> python module or symbol cannot be loaded.' % module print ' Please check the integrity of the package.' 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) # Check that all the instances have been placed by Mauka. def checkForUnplaceds ( cell ): unplaceds = [] for instance in cell.getInstances(): if instance.getPlacementStatus() == Instance.PlacementStatus.UNPLACED: unplaceds += [ instance ] if unplaceds: message = [ 'Some instances are still unplaceds:' ] for instance in unplaceds: message += [ '<%s> of model <%s>'%(str(instance.getName()) ,str(instance.getMasterCell().getName())) ] raise ErrorMessage( 3, message ) return # Small wrapper to display breakpoints, when in graphic mode only. def breakpoint ( editor, level, message ): if editor: editor.fit() editor.refresh() Breakpoint.stop( level, message ) return def ScriptMain ( cell=None ): # Force removal of any previouly generated placement (.ap files) # as they would prevent the the placer to run again. # This is a little bit inconvenient, but will change in the future. print ' o Cleaning up any previous run.' for fileName in os.listdir('.'): if fileName.endswith('.ap'): print ' - <%s>' % fileName os.unlink(fileName) editor = None if globals().has_key('__editor'): print ' o Editor detected, running in graphic mode.' editor = __editor Cfg.Configuration.pushDefaultPriority(Cfg.Parameter.Priority.CommandLine) Cfg.getParamBool('misc.verboseLevel1').setBool(True) Cfg.getParamBool('misc.verboseLevel2').setBool(True) Cfg.Configuration.popDefaultPriority() errorCode = 0 framework = CRL.AllianceFramework.get() padHeight = DbU.fromLambda( 400.0) padWidth = DbU.fromLambda( 200.0) coreSide = DbU.fromLambda(1400.0) # Cell must be loaded *before* opening the UpdateSession. print ' o Placing .' modelCoeur = framework.getCell('coeur',CRL.Catalog.State.Logical) UpdateSession.open() try: modelCoeur.setAbutmentBox( Hurricane.Box( DbU.fromLambda(0) , DbU.fromLambda(0) , coreSide , coreSide ) ) # Cannot place a rail if at least one instance is placed. # (to compute the orientation of the cells rows) #placeandroute.pyAlimVerticalRail( modelCoeur, coreSide/DbU.fromLambda(5.0*2) ) except Exception, e: print e; errorCode = 1 # For the geometrical modifications to be taken into account, we must # close this UpdateSession now. So the chip will see the core correctly. UpdateSession.close() if errorCode: sys.exit(errorCode) print ' o Placing .' amd2901 = framework.getCell('amd2901',CRL.Catalog.State.Logical) if editor: editor.setCell(amd2901) UpdateSession.open() try: chipSide = 11*padWidth + 2*padHeight # Le chip est carre, avec 11 plots par face. abutmentBoxChip = Hurricane.Box( DbU.fromLambda(0.0) , DbU.fromLambda(0.0) , chipSide , chipSide ) amd2901.setAbutmentBox( abutmentBoxChip ) instanceCoeur = amd2901.getInstance( 'core' ) instanceCoeur.setTransformation(Hurricane.Transformation( (chipSide-coreSide)/2 , (chipSide-coreSide)/2 , Transformation.Orientation.ID ) ) instanceCoeur.setPlacementStatus( Instance.PlacementStatus.PLACED ) # Placing Pads southPads = [ 'p_a3' , 'p_a2', 'p_a1', 'p_r0', 'p_vddick0', 'p_vssick0', 'p_a0' , 'p_i6', 'p_i8' , 'p_i7' , 'p_r3' ] eastPads = [ 'p_zero', 'p_i0', 'p_i1', 'p_i2', 'p_vddeck0', 'p_vsseck0', 'p_q3' , 'p_b0', 'p_b1' , 'p_b2' , 'p_b3' ] northPads = [ 'p_noe' , 'p_y3', 'p_y2', 'p_y1', 'p_y0' , 'p_vddeck1', 'p_vsseck1', 'p_np', 'p_ovr', 'p_cout', 'p_ng' ] westPads = [ 'p_cin' , 'p_i4', 'p_i5', 'p_i3', 'p_ck' , 'p_d0' , 'p_d1' , 'p_d2', 'p_d3' , 'p_q0' , 'p_f3' ] for (key,listPads) in {'south':southPads, 'east':eastPads, 'north':northPads, 'west':westPads}.iteritems(): print ' o Pads on %s side:' %key for ipad in range(len(listPads)): pad = amd2901.getInstance( listPads[ipad] ) print ' - Placing pad: <%s> (model:<%s>).' % (listPads[ipad],str(pad.getMasterCell().getName())) # south if key == 'south' : xpad = abutmentBoxChip.getXMin() + padHeight + ipad*(padWidth) ypad = abutmentBoxChip.getYMin() + padHeight pad.setTransformation( Hurricane.Transformation( xpad, ypad, Transformation.Orientation.MY) ) # east if key == 'east' : xpad = abutmentBoxChip.getXMax() - padHeight ypad = padHeight + padWidth + ipad*(padWidth) pad.setTransformation( Hurricane.Transformation( xpad, ypad, Transformation.Orientation.R3) ) # north if key == 'north' : xpad = padHeight + ipad*(padWidth) ypad = abutmentBoxChip.getYMax() - padHeight pad.setTransformation( Hurricane.Transformation( xpad, ypad, Transformation.Orientation.ID) ) # west if key == 'west' : xpad = padHeight ypad = padHeight + ipad*(padWidth) pad.setTransformation( Hurricane.Transformation( xpad, ypad, Transformation.Orientation.R1) ) pad.setPlacementStatus( Instance.PlacementStatus.PLACED ) 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() if errorCode: sys.exit(errorCode) breakpoint( editor, 1, 'Chip After Pad Placement' ) try: # Now run the tools. coeur = framework.getCell('coeur',CRL.Catalog.State.Logical) mauka = Mauka.MaukaEngine.create(coeur) mauka.run() mauka.destroy() breakpoint( editor, 1, 'Core After Standard Cell Placement' ) placeandroute.pyAlimConnectors(coeur) # This is gross. It's the ghost of Wu Yifei and his demonic code... # Will not be needed in the future (dynamic detection based on the # transformations). for pad in southPads: placeandroute.pad_south += [ amd2901.getInstance(pad) ] for pad in northPads: placeandroute.pad_north += [ amd2901.getInstance(pad) ] for pad in eastPads: placeandroute.pad_east += [ amd2901.getInstance(pad) ] for pad in westPads: placeandroute.pad_west += [ amd2901.getInstance(pad) ] placeandroute.pyPowerRing( amd2901, amd2901.getInstance('core'), 3 ) placeandroute.pyRouteCk ( amd2901, amd2901.getNet('ckc') ) breakpoint( editor, 1, 'Core After Clock & Power Routing' ) kite = Kite.KiteEngine.create( amd2901 ) kite.runGlobalRouter( Kite.KtBuildGlobalRouting ) kite.loadGlobalRouting( Katabatic.EngineLoadGrByNet, [] ) kite.layerAssign( Katabatic.EngineNoNetLayerAssign ) kite.runNegociate() breakpoint( editor, 1, 'Routing done, but router still active for inspection.' ) kite.finalizeLayout() kite.destroy() # Write back layout to disk if everything has gone fine. # Must write all the sub-blocks of the core but *not* the # standard cell (mainly the feed-through). for instance in modelCoeur.getInstances(): masterCell = instance.getMasterCell() if not masterCell.isTerminal(): framework.saveCell( masterCell, CRL.Catalog.State.Physical ) framework.saveCell( modelCoeur, CRL.Catalog.State.Physical ) framework.saveCell( amd2901 , CRL.Catalog.State.Physical ) except ErrorMessage, e: print e; errorCode = e.code except Exception, e: print '\n\n', e; errorCode = 1 traceback.print_tb(sys.exc_info()[2]) if editor: editor.setCell(amd2901) return 0 if __name__ == '__main__': ScriptMain() sys.exit(0)