coriolis/documentation/examples/AM2901/design.py

239 lines
8.7 KiB
Python
Raw Normal View History

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