239 lines
8.7 KiB
Python
239 lines
8.7 KiB
Python
|
#!/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
|
||
|
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 <coriolis> 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() == Hurricane.PlacementStatusUNPLACED:
|
||
|
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 <coeur>.'
|
||
|
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 <chip>.'
|
||
|
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
|
||
|
, Hurricane.OrientationID ) )
|
||
|
instanceCoeur.setPlacementStatus( Hurricane.PlacementStatusPLACED )
|
||
|
|
||
|
# 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, Hurricane.OrientationMY) )
|
||
|
|
||
|
# east
|
||
|
if key == 'east' :
|
||
|
xpad = abutmentBoxChip.getXMax() - padHeight
|
||
|
ypad = padHeight + padWidth + ipad*(padWidth)
|
||
|
pad.setTransformation( Hurricane.Transformation( xpad, ypad, Hurricane.OrientationR3) )
|
||
|
|
||
|
# north
|
||
|
if key == 'north' :
|
||
|
xpad = padHeight + ipad*(padWidth)
|
||
|
ypad = abutmentBoxChip.getYMax() - padHeight
|
||
|
pad.setTransformation( Hurricane.Transformation( xpad, ypad, Hurricane.OrientationID) )
|
||
|
|
||
|
# west
|
||
|
if key == 'west' :
|
||
|
xpad = padHeight
|
||
|
ypad = padHeight + ipad*(padWidth)
|
||
|
pad.setTransformation( Hurricane.Transformation( xpad, ypad, Hurricane.OrientationR1) )
|
||
|
|
||
|
pad.setPlacementStatus( Hurricane.PlacementStatusPLACED )
|
||
|
|
||
|
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)
|