coriolis/cumulus/src/placeandroute.py

2416 lines
104 KiB
Python

import os
import re
import Cfg
from Hurricane import *
from helpers.io import ErrorMessage
import CRL
#import Mauka
#import Knik
#import Kite
#import Zephyr
#import Lightning
#import Zephiros
#from Anemometer import *
#from Metisse import *
#from Mistral import *
#from Nimbus import *
from math import *
missingCORIOLIS_TOP = "Missing environment variable CORIOLIS_TOP"
global POWER, OCCUPIED, FREE
POWER = 2
OCCUPIED = 1
FREE = 0
global PITCH, SLICE
PITCH = 5
SLICE = 50
global RING_WIDTH
RING_WIDTH = 12
global RING_INTERVAL
RING_INTERVAL = 3
global standard_instances_masque
global standard_instances_list
standard_instances_list = []
global pad_north, pad_south, pad_east, pad_west
pad_north = []
pad_south = []
pad_east = []
pad_west = []
global nb_alims_verticales
nb_alims_verticales = 0
global nb_vdd_pins, nb_vss_pins
nb_vdd_pins = 0
nb_vss_pins = 0
global ck_contact_list_to_create
ck_contact_list_to_create = []
def getNetFromPlug ( plug ):
net = plug.getNet()
if net: return net
masterNet = plug.getMasterNet()
if masterNet.getName() in [ 'vddi', 'vssi', 'vdde', 'vsse' ]:
cell = plug.getCell()
net = cell.getNet(masterNet.getName())
return net
##################
## PlaceCentric ##
##################
def pyPlaceCentric ( cell, instance ) :
'''This function places an instance in the middle of the abutment box of a cell'''
UpdateSession.open()
if not instance :
raise ErrorMessage(2,"PlaceCentric: the instance does not exist.")
w = cell.getAbutmentBox().getWidth()
h = cell.getAbutmentBox().getHeight()
if ( w < instance.getAbutmentBox().getWidth() ) or ( h < instance.getAbutmentBox().getHeight() ) :
raise ErrorMessage(2,"PlaceCentric : the instance's size is greater than this model.")
XCenter = cell.getAbutmentBox().getXCenter()
YCenter = cell.getAbutmentBox().getYCenter()
New_Xmin = XCenter - instance.getAbutmentBox().getWidth() / 2
New_Ymin = YCenter - instance.getAbutmentBox().getHeight() / 2
# One must place the cell on a pitch grid
New_Xmin = New_Xmin - ( New_Xmin % DbU_lambda(PITCH) )
New_Ymin = New_Ymin - ( New_Ymin % DbU_lambda(PITCH) )
Tx = New_Xmin - instance.getAbutmentBox().getXMin()
Ty = New_Ymin - instance.getAbutmentBox().getYMin()
instance.setTransformation ( Transformation ( Tx, Ty ).getTransformation ( instance.getTransformation() ) )
instance.setPlacementStatus ( Instance.PlacementStatus.PLACED )
UpdateSession.close()
#######################
## PlaceGlue ##
#######################
def pyPlaceGlue ( cell ) :
'''This function places the glue (unplaced leaf instances) in current cell.
The placement will be made in the region given by the core argument:
- if core is None, the placement region will be the cell abox.
- if core is a cell sub-instance, the placement region will be the sub-instance abox.'''
mauka = Mauka.MaukaEngine.create ( cell )
mauka.run ()
temporarySave ()
#############
## RouteCk ##
#############
def pyRouteCk ( cell, netCk ) :
'''This function route signel Ck to standard cells'''
global pad_north, pad_south, pad_east, pad_west
UpdateSession.open()
# Error if Pads have not already been placed
if pad_north == [] : raise ErrorMessage(2,"RouteCk : Pads in the north haven't been placed.")
if pad_south == [] : raise ErrorMessage(2,"RouteCk : Pads in the south haven't been placed.")
if pad_east == [] : raise ErrorMessage(2,"RouteCk : Pads in the east haven't been placed.")
if pad_west == [] : raise ErrorMessage(2,"RouteCk : Pads in the west haven't been placed.")
# pad_list contains all pads
pad_list = []
pad_list.extend ( pad_north )
pad_list.extend ( pad_south )
pad_list.extend ( pad_east )
pad_list.extend ( pad_west )
net_list = dict()
for ins in pad_list :
# For each pad that is a clock pad -> adding corresponding net in net_list if not already existing
if isInternalClockPad ( ins ) or isExternalClockPad ( ins ):
clockPlug = None
for plug in ins.getPlugs():
if plug.getNet() == netCk :
clockPlug = plug
break
if clockPlug and not net_list.has_key ( str ( clockPlug.getNet().getName() ) ) : net_list[str ( clockPlug.getNet().getName() )] = ( clockPlug.getNet(), cell )
map ( createGrid, net_list.values() )
UpdateSession.close()
######################
## AlimVerticalRail ##
######################
def pyAlimVerticalRail ( cell, xcoord ) :
'''x is in pitch, it is where the vertical alimentation call back are placed'''
global PITCH, SLICE
global standard_instances_list, nb_alims_verticales, nb_lignes, standard_instances_masque
global nb_vdd_pins, nb_vss_pins
UpdateSession.open()
box = cell.getAbutmentBox()
# Error message if wrong abutment box
if ( box.getXMin() == box.getXMax() ) or ( box.getYMin() == box.getYMax() ) :
message = "AlimVerticalRail : Can't place the rail vertical in the abutment box of model %s." %str(cell.getName()) \
+ " The abutment box doesn't exist !" \
+ " Maybe you should use DefAb function or ResizeAb function to define un box before the placement of Rail Vertical."
raise ErrorMessage(2,message)
# Check the value of x
nb_col = cell.getAbutmentBox().getWidth() / DbU_lambda(PITCH)
if ( xcoord >= nb_col ) or ( xcoord < 0 ) :
print 'This is it'
message = "AlimVerticalRail : Illegal argument x , x must be between %d and %d\n" % ( 0, nb_col )
raise ErrorMessage(2,message)
# To get the informations about the placement
reference = getStandardInstancesMasque ( cell )
if not reference :
message = "AlimVerticalRail : No instance is placed in the model " + str(cell.getName()) + ".\n" \
+ "Please place some instances before the placement of Rail Vertical.\n"
raise ErrorMessage(2,message)
# Placement verification
#verifyPlacement ( cell ) # NON !!
# delete elements in standard_instances_list
del standard_instances_list[0:]
# get YMin of reference
Ymin = reference[1]
# get orientation code
orientation = reference[2]
nb_alims_verticales += 1
# get the opposite of orientation ID=>MY MY=>ID
if orientation in [Transformation.Orientation.ID, Transformation.Orientation.MX] :
inv_orientation = Transformation.Orientation.MY
orientation = Transformation.Orientation.ID
elif orientation in [Transformation.Orientation.MY, Transformation.Orientation.R2] :
inv_orientation = Transformation.Orientation.ID
orientation = Transformation.Orientation.MY
else :
raise ErrorMessage(2,"AlimVerticalRail : Strawberry.")
# print "Placement of vertical rail"
# print "Reference ", reference
power_cell = CRL.AllianceFramework.get().getCell ( "powmid_x0", CRL.Catalog.State.Views )
Height_power = power_cell.getAbutmentBox().getHeight()
Width_power = power_cell.getAbutmentBox().getWidth()
nb_slices = Height_power / DbU_lambda(SLICE)
nb_pitchs = Width_power / DbU_lambda(PITCH)
# skim through column of index x
for i in range ( nb_lignes ) :
espace_enough = True
# check the space left
for j in range ( nb_slices ) :
for k in range ( nb_pitchs ) :
if standard_instances_masque[i + j][xcoord + k] != FREE :
espace_enough = False
break
if espace_enough :
# avoir le nombre de slices entre la reference
distance = Ymin / DbU_lambda(SLICE) - i
if distance < 0 : distance = -distance
name_inst = "powmid_%d_%d" % ( nb_alims_verticales , i )
Powmid = create_inst ( "powmid_x0", name_inst, cell )
x = xcoord * DbU_lambda(PITCH)
y = i * DbU_lambda(SLICE)
if distance % 2 : my_orientation = inv_orientation
else : my_orientation = orientation
place ( Powmid, int(x), int(y), my_orientation )
# place pins (connectors) in metal3 on top and bottom
metal3 = DataBase.getDB().getTechnology().getLayer( "METAL3" )
powerNet = None
for net in cell.getPowerNets():
if powerNet:
raise ErrorMessage(2,"AlimVerticalRail : more than 1 Power Net found !")
powerNet = net
if not powerNet:
raise ErrorMessage(2,"AlimVerticalRail : no Power Net found !")
groundNet = None
for net in cell.getGroundNets():
if groundNet:
raise ErrorMessage(2,"AlimVerticalRail : more than 1 Ground Net found !")
groundNet = net
if not groundNet:
raise ErrorMessage(2,"AlimVerticalRail : no Ground Net found !")
pin_height = 10
pin_width = 10
pin_x1 = xcoord * DbU_lambda(PITCH) + DbU_lambda(10)
pin_x2 = xcoord * DbU_lambda(PITCH) + DbU_lambda(25)
pin_y1 = ( nb_lignes * DbU_lambda(SLICE) ) - DbU_lambda(pin_height/4)
pin_y2 = 0 + DbU_lambda(pin_height/4)
# Top
if standard_instances_masque[nb_lignes-1][xcoord] == FREE :
pin_name = str(powerNet.getName()) + "." + str(nb_vdd_pins)
pin = Pin.create ( powerNet, pin_name, 1, 2, metal3, pin_x1, pin_y1, DbU_lambda(pin_width), DbU_lambda(pin_height) )
nb_vdd_pins += 1
pin_name = str(groundNet.getName()) + "." + str(nb_vss_pins)
pin = Pin.create ( groundNet, pin_name, 1, 2, metal3, pin_x2, pin_y1, DbU_lambda(pin_width), DbU_lambda(pin_height) )
nb_vss_pins += 1
# Bottom
if standard_instances_masque[0][xcoord] == FREE :
pin_name = str(powerNet.getName()) + "." + str(nb_vdd_pins)
pin = Pin.create ( powerNet, pin_name, 2 , 2, metal3, pin_x1, pin_y2, DbU_lambda(pin_width), DbU_lambda(pin_height) )
nb_vdd_pins += 1
pin_name = str(groundNet.getName()) + "." + str(nb_vss_pins)
pin = Pin.create ( groundNet, pin_name, 2 , 2, metal3, pin_x2, pin_y2, DbU_lambda(pin_width), DbU_lambda(pin_height) )
nb_vss_pins += 1
UpdateSession.close()
########################
## AlimHorizontalRail ##
########################
def pyAlimHorizontalRail ( cell, ycoord ) :
'''This function places the horizontal alimentation call back in Alu 4
1. the two pins in Alu 4 which name is VDD or VSS are placed
2. the horizontal in Alu 4 is placed, and is locked on the two pins
y is in slice'''
global PITCH, SLICE, RING_WIDTH
global standard_instances_list, nb_alims_verticales, nb_lignes, standard_instances_masque
global nb_vdd_pins, nb_vss_pins
UpdateSession.open()
box = cell.getAbutmentBox()
# Error message if wrong abutment box
if ( box.getXMin() == box.getXMax() ) or ( box.getYMin() == box.getYMax() ) :
err = "\nAlimHorizontalRail : Can't place the rail horizontal in the abutment box of model " + str(cell.getName()) \
+ "\n The abutment box doesn't exist !" \
+ "\n Maybe you should use DefAb function or ResizeAb function to define un box before the placement of Rail Horizontal.\n"
raise ErrorMessage(2,err)
# Check the value of y
if ( ycoord >= nb_lignes ) or ( ycoord < 0 ) :
err = "\nAlimHorizontalRail : Illegal argument y, y must be between %d and %d\n" % ( 0, nb_lignes )
raise ErrorMessage(2,err)
# To get the informations about the placement
reference = getStandardInstancesMasque ( cell )
if not reference :
err = "AlimHorizontalRail : No instance is placed in the model " + str(cell.getName()) + ".\n"
raise ErrorMessage(2,err)
# get layers
metal4 = DataBase.getDB().getTechnology().getLayer ( "METAL4" )
via1 = DataBase.getDB().getTechnology().getLayer ( "VIA12" )
via2 = DataBase.getDB().getTechnology().getLayer ( "VIA23" )
via3 = DataBase.getDB().getTechnology().getLayer ( "VIA34" )
# Know if it is vdd or vss
string = getVddVss ( cell, ycoord )
pin_width = DbU_lambda(RING_WIDTH)
pin_height = DbU_lambda(RING_WIDTH)
pin_x1 = 0 + ( pin_height / 4 )
pin_x2 = cell.getAbutmentBox().getWidth() - ( pin_height / 4 )
pin_y = ycoord * DbU_lambda(SLICE)
# Create two pins
if string == "vdd" :
net = cell.getNet ( "vdd" )
pin_name = str(net.getName()) + "." + str(nb_vdd_pins)
pin1 = Pin.create ( net, pin_name, 4, 2, metal4, pin_x1, pin_y, pin_width, pin_height )
nb_vdd_pins += 1
pin_name = str(net.getName()) + "." + str(nb_vdd_pins)
pin2 = Pin.create ( net, pin_name, 3, 2, metal4, pin_x2, pin_y, pin_width, pin_height )
nb_vdd_pins += 1
else :
net = cell.getNet ( "vss" )
pin_name = str(net.getName()) + "." + str(nb_vss_pins)
pin1 = Pin.create ( net, pin_name, 4, 2, metal4, pin_x1, pin_y, pin_width, pin_height )
nb_vss_pins += 1
pin_name = str(net.getName()) + "." + str(nb_vss_pins)
pin2 = Pin.create ( net, pin_name, 3, 2, metal4, pin_x2, pin_y, pin_width, pin_height )
nb_vss_pins += 1
# Create horizontal rail
rail_horizontal = Horizontal.create ( pin1 , pin2 , metal4 , pin_y, pin_height, 0 , 0 )
power_hur_cell = CRL.AllianceFramework.get().getCell ( "powmid_x0", CRL.Catalog.State.Views )
Width_power = power_hur_cell.getAbutmentBox().getWidth()
nb_pitchs = Width_power / DbU_lambda(PITCH) # avoir l'interval du cellule power
# create contacts in via1 , via2 , et via3
i = 0
while i < nb_colonnes :
# if it is a power cell, make the via3, and pass the power cell
if standard_instances_masque[ycoord][i] == POWER :
contact_side = DbU_lambda(RING_WIDTH) - DbU_lambda(1.0)
if string == "vdd" : contact3 = Contact.create ( rail_horizontal, via3, i*DbU_lambda(PITCH) + DbU_lambda(10), 0, contact_side, DbU_lambda(2) )
else : contact3 = Contact.create ( rail_horizontal, via3, i*DbU_lambda(PITCH) + DbU_lambda(25), 0, contact_side, DbU_lambda(2) )
i += nb_pitchs
i+=1
UpdateSession.close()
####################
## AlimConnectors ##
####################
def pyAlimConnectors ( cell ) :
'''Creates the METAL1 connectors on the east & west sides of the core'''
global nb_lignes, nb_vdd_pins, nb_vss_pins
UpdateSession.open()
box = cell.getAbutmentBox()
# Error message if wrong abutment box
if ( box.getXMin() == box.getXMax() ) or ( box.getYMin() == box.getYMax() ) :
err = "\nAlimConnectors : can't place connectors. The abutment box don't exist.\n" \
+ "The abutment box don't exist !\n" \
+ "Maybe you should use DefAb function or ResizeAb function to define un box before the placement of alim connectors.\n"
raise ErrorMessage(2,err)
# avoir les infos actuelles de placement
getStandardInstancesMasque ( cell )
if not reference :
err = "\nAlimConnectors : no instance placed in the model " + str(cell.getName()) + "." \
+ "Please place some instances before the placement of alim connectors.\n"
raise ErrorMessage(2,err)
metal1 = DataBase.getDB().getTechnology().getLayer("METAL1")
string = getVddVss ( cell, 0 )
if re.search ( "vdd", string ) :
inv_string = "vss"
nb_string_pins = nb_vdd_pins
nb_inv_pins = nb_vss_pins
else :
inv_string = "vdd"
nb_string_pins = nb_vss_pins
nb_inv_pins = nb_vdd_pins
netPair = cell.getNet ( string )
if not netPair:
raise ErrorMessage(2,"AlimConnectors : can't get net %s."%string)
netImpair = cell.getNet ( inv_string )
if not netImpair:
raise ErrorMessage(2,"AlimConnectors : can't get net %s.\n"%inv_string)
for i in range ( nb_lignes + 1 ) :
pin_width = DbU_lambda(12)
pin_height = DbU_lambda(12)
pin_y = i * DbU_lambda(SLICE)
if i == 0 :
pin_height = pin_height / 2
pin_width = pin_width / 2
pin_y = pin_y + ( pin_height / 2 )
elif i == nb_lignes :
pin_height = pin_height / 2
pin_width = pin_width / 2
pin_y = pin_y - ( pin_height / 2 )
pin_x1 = 0 + ( pin_width / 2 )
pin_x2 = cell.getAbutmentBox().getWidth() - ( pin_width / 2 )
# Ligne impaire
if i % 2 :
pin_name = str(netImpair.getName()) + "." + str(nb_inv_pins)
pin1 = Pin.create ( netImpair, pin_name, 4, 2, metal1, pin_x1, pin_y, pin_width, pin_height )
nb_inv_pins += 1
pin_name = str(netImpair.getName()) + "." + str(nb_inv_pins)
pin2 = Pin.create ( netImpair, pin_name, 3, 2, metal1, pin_x2, pin_y, pin_width, pin_height )
nb_inv_pins += 1
Horizontal.create ( pin1, pin2, metal1, pin1.getY(), pin_height )
# Ligne paire
else :
pin_name = str(netPair.getName()) + "." + str(nb_string_pins)
pin1 = Pin.create ( netPair, pin_name, 4, 2, metal1, pin_x1, pin_y, pin_width, pin_height )
nb_string_pins += 1
pin_name = str(netPair.getName()) + "." + str(nb_string_pins)
pin2 = Pin.create ( netPair, pin_name, 3, 2, metal1, pin_x2, pin_y, pin_width, pin_height )
nb_string_pins += 1
Horizontal.create ( pin1, pin2, metal1, pin1.getY(), pin_height )
if re.search ( "vdd", string ) :
nb_vdd_pins = nb_string_pins
nb_vss_pins = nb_inv_pins
else :
nb_vss_pins = nb_string_pins
nb_vdd_pins = nb_inv_pins
UpdateSession.close()
#######################
## GlobalRoute ##
#######################
#def pyGlobalRoute ( cell ):
# """Perform global routing"""
#
# # Initialize Nimbus Grid (50x50 lambdas).
# Kite.setupNimbusGrid ( cell ) # ca a pas l'air de faire ce qu'il faut
#
# # la il faudrait rajouter un petit appel a cell->FlattenNets() pour que ce soit correct !
#
# # Global routing.
# globalRouter = Knik.getKnik ( cell
# , 1 # congestion.
# , 2 # preCongestion.
# , False # benchMode.
# , True # useSegments.
# )
# globalRouter.Route ()
# globalRouter.Delete ()
#######################
## DetailRoute ##
#######################
#def pyDetailRoute ( cell ):
# """Perform detailed routing"""
#
# viewer = getCEditor ( cell )
#
# TOOL_TOP = os.getenv ( "CORIOLIS_TOP" )
# if not TOOL_TOP:
# raise missingCORIOLIS_TOP
# config = TOOL_TOP + "/share/etc/kite.conf.xml"
#
# Kite.setDemoMode ( True )
# Kite.ConfigurationCreate ( config )
# detailedRouter = Kite.Create ( cell, viewer )
# detailedRouter.setGlobalThreshold ( 9*DbU_lambda(50.0) )
# detailedRouter.setRipupLimit ( 10 )
# detailedRouter.LoadGlobalRouting ( Kite.LOAD_GR_BY_NET )
# if viewer: viewer.Refresh ()
#
# detailedRouter.LayerAssign ( Kite.LAYER_ASSIGN_BY_TRUNK )
# if viewer: viewer.Refresh ()
#
# detailedRouter.ComputeNetConstraints ()
# if viewer: viewer.Refresh ()
#
# detailedRouter.ComputeNetOptimals ()
# if viewer: viewer.Refresh ()
#
# detailedRouter.RunNegociate ()
# if viewer: viewer.Refresh ()
#
# # Save detailed routing.
# detailedRouter.Delete ()
# if viewer: viewer.Refresh ()
#
# return
#def pyTimingStaticAnalysis ( cell ):
# """Perfom timing static analysis"""
#
# TOOL_TOP = os.getenv ( "CORIOLIS_TOP")
# if not TOOL_TOP:
# raise missingCORIOLIS_TOP
# config = TOOL_TOP + "/share/cells/sxlib/sxlib_timing.lib"
#
# LibertyParse ( config )
#
# lightning = Lightning.getLightning ( cell )
# timingStaticAnalysis = Zephyr.getZephyr ( cell )
# #zephiros = Zephiros.getZephiros ( cell )
#
# timingStaticAnalysis.Update()
# #zephiros.PrintMaxDelay()
#
# return
##############
## PadNorth ##
##############
def pyPadNorth ( cell, core, args ) :
'''This function places pads up north of the cell. It leaves an empty squarre of CARRE * CARRE, CARRE is defined in macro'''
global pad_north
# Sauvegarder la liste des plots
pad_north = args
UpdateSession.open()
# avoir le largeur de l espace au nord pour placer les pads
north_espace_width = cell.getAbutmentBox().getYMax() - core.getAbutmentBox().getYMax()
north_espace_longueur = cell.getAbutmentBox().getWidth() - (2 * getPadHeight ( cell ) ) # FIXME D2
# avoir le nombre de pads
nb_pads = len ( args )
# avoir le largeur total des pads
largeur = 0
for ins in args :
if ins.getPlacementStatus() :
raise ErrorMessage(2,"PadNorth : the instance %s is already placed."%str(ins.getName()))
if ins.getAbutmentBox().getHeight() >= north_espace_width :
raise ErrorMessage(2,"PadNorth : not enough space for all pads.")
largeur += ins.getAbutmentBox().getWidth()
if largeur > north_espace_longueur :
raise ErrorMessage(2,"PadNorth : not enough space for all pads.")
# calculer l interval entre les pads
interval = ( north_espace_longueur - largeur ) / ( nb_pads + 1 )
# placer les pads
Xmin_cell = cell.getAbutmentBox().getXMin()
Ymin_cell = cell.getAbutmentBox().getYMin()
Height_cell = cell.getAbutmentBox().getHeight()
x_init = Xmin_cell + getPadHeight ( cell ) + interval
##### Parcours des pads #####
for ins in args :
pad_height = ins.getAbutmentBox().getHeight()
pad_width = ins.getAbutmentBox().getWidth()
_y = Ymin_cell + Height_cell - pad_height # la position finale dans la cell
_x = x_init
# ATTENTION LES PLOTS DOIVENT ETRE PLACES SUR UNE GRILLE DE 5 LAMBDAS !!!!!!!!!!!!!!
_x = _x - ( _x % DbU_lambda(PITCH) )
# ATTENTION ON NE PLACE PAS DES PLOTS D ALIM EN DEHORS DE LA COURONNE INTERNE
if isInternalGroundPad ( ins ) or isInternalPowerPad ( ins ) \
or isExternalGroundPad ( ins ) or isExternalPowerPad ( ins ) :
cellAB = cell.getAbutmentBox()
coreAB = core.getAbutmentBox()
pad_height = getPadHeight ( cell )
if _x <= ( ( cellAB.getXMin() + pad_height ) + coreAB.getXMin() ) / 2 \
or _x >= ( ( cellAB.getXMax() - pad_height ) + coreAB.getXMax() ) / 2 :
raise ErrorMessage(2,"PadNorth : pad %s must be closer to the center.\n"%str(ins.getName()))
# x calcule pour le pad suivant
x_init = _x + interval + pad_width
# avoir x y
box = ins.getMasterCell().getAbutmentBox()
_difx = box.getXMin()
_dify = box.getYMin()
ins.setTransformation ( Transformation ( _x - _difx
, _y - _dify
, Transformation.Orientation.ID
)
)
ins.setPlacementStatus ( Instance.PlacementStatus.FIXED )
UpdateSession.close()
##############
## PadSouth ##
##############
def pyPadSouth ( cell, core, args ) :
'''This function places pads down south of the cell. It leaves an empty squarre of CARRE * CARRE, CARRE is defined in macro'''
global pad_south
# Sauvegarder la liste des plots
pad_south = args
UpdateSession.open()
# avoir le largeur du espace disponible du nord pour placer les pads
south_espace_width = core.getAbutmentBox().getYMin() - cell.getAbutmentBox().getYMin()
south_espace_longueur = cell.getAbutmentBox().getWidth() - ( 2 * getPadHeight ( cell ) )
# avoir le nombre de pads
nb_pads = len ( args )
# avoir le largeur total des pads
largeur = 0
for ins in args :
if ins.getPlacementStatus() :
raise ErrorMessage(2,"PadSouth : the instance %s is already placed."%str(ins.getName()))
if ins.getAbutmentBox().getHeight() >= south_espace_width :
raise ErrorMessage(2,"PadSouth : not enough space for all pads.")
largeur += ins.getAbutmentBox().getWidth()
if largeur > south_espace_longueur :
raise ErrorMessage(2,"PadSouth : not enough space for all pads.")
# calculer l'interval entre les pads
interval = ( south_espace_longueur - largeur ) / ( nb_pads + 1 )
# placer les pads
Xmin_cell = cell.getAbutmentBox().getXMin()
Ymin_cell = cell.getAbutmentBox().getYMin()
x_init = Xmin_cell + getPadHeight ( cell ) + interval
##### Parcours des pads #####
for ins in args :
pad_height = ins.getAbutmentBox().getHeight()
pad_width = ins.getAbutmentBox().getWidth()
_y = Ymin_cell # la position finale dans la cell
_x = x_init
# ATTENTION LES PLOTS DOIVENT ETRE PLACES SUR UNE GRILLE DE 5 LAMBDAS !!!!!!!!!!!!!!
_x = _x - ( _x % DbU_lambda(PITCH) )
# ATTENTION ON NE PLACE PAS DES PLOTS D ALIM EN DEHORS DE LA COURONNE INTERNE
if isInternalGroundPad ( ins ) or isInternalPowerPad ( ins ) \
or isExternalGroundPad ( ins ) or isExternalPowerPad ( ins ) :
cellAB = cell.getAbutmentBox()
coreAB = core.getAbutmentBox()
pad_height = getPadHeight ( cell )
if _x <= ( ( cellAB.getXMin() + pad_height ) + coreAB.getXMin() ) / 2 \
or _x >= ( ( cellAB.getXMax() - pad_height ) + coreAB.getXMax() ) / 2 :
raise ErrorMessage(2,"PadSouth : pad %s must be closer to the center."%str(ins.getName()))
# x calcule pour le pad suivant
x_init = _x + interval + pad_width
# avoir x y apres orientation
box = ins.getMasterCell().getAbutmentBox()
_difx = Transformation ( 0, 0, Transformation.Orientation.MY ).getBox ( box ).getXMin()
_dify = Transformation ( 0, 0, Transformation.Orientation.MY ).getBox ( box ).getYMin()
ins.setTransformation ( Transformation ( _x - _difx
, _y - _dify
, Transformation.Orientation.MY
)
)
ins.setPlacementStatus ( Instance.PlacementStatus.FIXED )
UpdateSession.close()
#############
## PadEast ##
#############
def pyPadEast ( cell, core, args ) :
'''This function places pads at the east of the cell. It leaves an empty squarre of CARRE * CARRE, CARRE is defined in macro'''
global pad_east
# Sauvegarder la liste des plots
pad_east = args
UpdateSession.open()
# avoir le largeur du espace disponible du nord pour placer les pads
east_espace_width = cell.getAbutmentBox().getXMax() - core.getAbutmentBox().getXMax()
east_espace_longueur = cell.getAbutmentBox().getHeight() - ( 2 * getPadHeight ( cell ) )
# avoir le nombre de pads
nb_pads = len ( args )
# avoir le largeur total des pads
largeur = 0
for ins in args :
if ins.getPlacementStatus() :
raise ErrorMessage(2,"PadEast : the instance %s is already placed."%str(insGetName()))
if ins.getAbutmentBox().getHeight() >= east_espace_width :
raise ErrorMessage(2,"PadEast : not enough space for pads.")
largeur += ins.getAbutmentBox().getWidth()
if largeur > east_espace_longueur :
raise ErrorMessage(2,"PadEast : not enough space for all pads.")
# calculer l'interval entre les pads
interval = ( east_espace_longueur - largeur ) / ( nb_pads + 1 )
# placer les pads
Xmin_cell = cell.getAbutmentBox().getXMin()
Ymin_cell = cell.getAbutmentBox().getYMin()
Xmax_cell = cell.getAbutmentBox().getXMax()
y_init = Ymin_cell + getPadHeight ( cell ) + interval
##### Parcours des pads #####
for ins in args :
pad_height = ins.getAbutmentBox().getHeight()
pad_width = ins.getAbutmentBox().getWidth()
Xmin_pad = ins.getMasterCell().getAbutmentBox().getXMin()
Ymin_pad = ins.getMasterCell().getAbutmentBox().getYMin()
_x = Xmax_cell - pad_height # la position finale dans la cell
_y = y_init
# ATTENTION LES PLOTS DOIVENT ETRE PLACES SUR UNE GRILLE DE 5 LAMBDAS !!!!!!!!!!!!!!
_y = _y - ( _y % DbU_lambda(PITCH) )
# ATTENTION ON NE PLACE PAS DES PLOTS D ALIM EN DEHORS DE LA COURONNE INTERNE
if isInternalGroundPad ( ins ) or isInternalPowerPad ( ins ) \
or isExternalGroundPad ( ins ) or isExternalPowerPad ( ins ) :
cellAB = cell.getAbutmentBox()
coreAB = core.getAbutmentBox()
pad_height = getPadHeight ( cell )
if _y <= ( ( cellAB.getYMin() + pad_height ) + coreAB.getYMin() ) / 2 \
or _y >= ( ( cellAB.getYMax() - pad_height ) + coreAB.getYMax() ) / 2 :
raise ErrorMessage(2,"PadEast : pad %s must be closer to the center.\n"%str(ins.getName()))
# y calcule pour le pad suivant
y_init = _y + interval + pad_width
# avoir le x y apres orientation
box = ins.getMasterCell().getAbutmentBox()
_difx = Transformation ( 0, 0, 7 ).getBox ( box ).getXMin()
_dify = Transformation ( 0, 0, 7 ).getBox ( box ).getYMin()
ins.setTransformation ( Transformation ( _x - _difx
, _y - _dify
, Transformation.Orientation.YR
)
)
ins.setPlacementStatus ( Instance.PlacementStatus.FIXED )
UpdateSession.close()
#############
## PadWest ##
#############
def pyPadWest ( cell, core, args ) :
'''This function places pads at the west of the cell. It leaves an empty squarre of CARRE * CARRE, CARRE is defined in macro'''
global pad_west
# Sauvegarder la liste des plots
pad_west = args
UpdateSession.open()
# avoir le largeur du espace disponible du nord pour placer les pads
west_espace_width = core.getAbutmentBox().getXMin() - cell.getAbutmentBox().getXMin()
west_espace_longueur = cell.getAbutmentBox().getHeight() - ( 2 * getPadHeight ( cell ) )
# avoir le nombre de pads
nb_pads = len ( args )
# avoir le largeur total des pads
largeur = 0
for ins in args :
if ins.getPlacementStatus() :
raise ErrorMessage(2,"PadWest : the instance %s is already placed."%str(ins.getName()))
if ins.getAbutmentBox().getHeight() >= west_espace_width :
raise ErrorMessage(2,"PadWest : not enough space for pads.")
largeur += ins.getAbutmentBox().getWidth()
if largeur > west_espace_longueur :
raise ErrorMessage(2,"PadWest : not enough space for pads.")
# calculer l'interval entre les pads
interval = int ( ( west_espace_longueur - largeur ) / ( nb_pads + 1 ) )
# placer les pads
Xmin_cell = cell.getAbutmentBox().getXMin()
Ymin_cell = cell.getAbutmentBox().getYMin()
y_init = Ymin_cell + getPadHeight ( cell ) + interval
##### Parcours des pads #####
for ins in args :
pad_height = ins.getAbutmentBox().getHeight()
pad_width = ins.getAbutmentBox().getWidth()
_x = Xmin_cell # la position finale dans la cell
_y = y_init
# ATTENTION LES PLOTS DOIVENT ETRE PLACES SUR UNE GRILLE DE 5 LAMBDAS !!!!!!!!!!!!!!
_y = _y - ( _y % DbU_lambda(PITCH) )
# ATTENTION ON NE PLACE PAS DES PLOTS D ALIM EN DEHORS DE LA COURONNE INTERNE
if isInternalGroundPad ( ins ) or isInternalPowerPad ( ins ) \
or isExternalGroundPad ( ins ) or isExternalPowerPad ( ins ) :
cellAB = cell.getAbutmentBox()
coreAB = core.getAbutmentBox()
pad_height = getPadHeight ( cell )
if _y <= ( ( cellAB.getYMin() + pad_height ) + coreAB.getYMin() ) / 2 \
or _y >= ( ( cellAB.getYMax() - pad_height ) + coreAB.getYMax() ) / 2 :
raise ErrorMessage(2,"PadWest : pad %s must be closer to the center.\n"%str(ins.getName()))
# y calcule pour le pad suivant
y_init = _y + interval + pad_width
# avoir x y apres orientation
box = ins.getMasterCell().getAbutmentBox()
_difx = Transformation ( 0, 0, 1 ).getBox ( box ).getXMin()
_dify = Transformation ( 0, 0, 1 ).getBox ( box ).getYMin()
ins.setTransformation ( Transformation ( _x - _difx
, _y - _dify
, Transformation.Orientation.R1
)
)
ins.setPlacementStatus ( Instance.PlacementStatus.FIXED )
UpdateSession.close()
###############
## PowerRing ##
###############
def pyPowerRing ( cell, core, n ) :
'''This function places power rings around the core and around the plots
n is the number of rings (n vdd, n+1 vss)
, Distance between rings is defined by macro DbU_lambda ( RING_INTERVAL )
Width of rings is defined by macro DbU_lambda ( RING_WIDTH )'''
global pad_north, pad_south, pad_east, pad_west
global RING_INTERVAL, RING_WIDTH
db = DataBase.getDB()
topRoutingLayerName = Cfg.getParamString('katabatic.topRoutingLayer', 'METAL4').asString()
topRoutingLayer = db.getTechnology().getLayer( topRoutingLayerName )
allowedDepth = CRL.AllianceFramework.get().getRoutingGauge().getLayerDepth( topRoutingLayer )
print 'topRoutingLayer: <%s> depth:%d' % (topRoutingLayer.getName(), allowedDepth)
UpdateSession.open()
if pad_north == [] : raise ErrorMessage(2,"PowerRing : Pads in the north haven't been placed")
if pad_south == [] : raise ErrorMessage(2,"PowerRing : Pads in the south haven't been placed")
if pad_east == [] : raise ErrorMessage(2,"PowerRing : Pads in the east haven't been placed")
if pad_west == [] : raise ErrorMessage(2,"PowerRing : Pads in the west haven't been placed")
#############################
# PARAMETRE DU PLACEMENT ##
#############################
# le largeur du fil de routage
routage_segment_width = DbU_lambda(12)
# la distance entre les deux centres des couronnes
decalage = DbU_lambda(RING_WIDTH) + DbU_lambda(RING_INTERVAL)
# Recuperer les informations sur le core
core_width = core.getAbutmentBox().getWidth()
core_height = core.getAbutmentBox().getHeight()
core_Xmin = core.getAbutmentBox().getXMin()
core_Ymin = core.getAbutmentBox().getYMin()
core_Xmax = core.getAbutmentBox().getXMax()
core_Ymax = core.getAbutmentBox().getYMax()
mips_core = core.getMasterCell()
# Recuperer la hauteur des plots
pad_height = getPadHeight ( cell )
# Recuperer les layers ( Vias , Alus )
metal4 = db.getTechnology().getLayer ( "METAL4" )
metal3 = db.getTechnology().getLayer ( "METAL3" )
metal2 = db.getTechnology().getLayer ( "METAL2" )
metal1 = db.getTechnology().getLayer ( "METAL1" )
via1 = db.getTechnology().getLayer ( "VIA12" )
via2 = db.getTechnology().getLayer ( "VIA23" )
via3 = db.getTechnology().getLayer ( "VIA34" )
if (allowedDepth < 3):
hCoronaLayer = metal2
vCoronaLayer = metal3
cCoronaLayer = via2
else:
hCoronaLayer = metal4
vCoronaLayer = metal3
cCoronaLayer = via3
# Recuperer les nets ( qui connectent les connectors du plot : vdde , vsse , vddi , vssi , ck )
instance = cell.getInstance( pad_north[0].getName() )
model = instance.getMasterCell()
vddp = instance.getPlug ( model.getNet("vdde") ).getNet()
vssp = instance.getPlug ( model.getNet("vsse") ).getNet()
vdd = instance.getPlug ( model.getNet("vddi") ).getNet()
vss = instance.getPlug ( model.getNet("vssi") ).getNet()
ck = instance.getPlug ( model.getNet("ck" ) ).getNet()
# If nets are globals, get them from the netlist.
if not vddp: vddp = cell.getNet('vdde')
if not vssp: vssp = cell.getNet('vsse')
if not vdd: vdd = cell.getNet('vddi')
if not vss: vss = cell.getNet('vssi')
if not ck: ck = cell.getNet('cki')
# Prendre la hauteur, la longueur, Xmin et Ymin de ce modele
cell_height = cell.getAbutmentBox().getHeight()
cell_width = cell.getAbutmentBox().getWidth()
cell_Xmin = cell.getAbutmentBox().getXMin()
cell_Ymin = cell.getAbutmentBox().getYMin()
cell_Xmax = cell.getAbutmentBox().getXMax()
cell_Ymax = cell.getAbutmentBox().getYMax()
# Verifier s'il y a assez de places pour les couronnes
if ( cell_height - core_height ) < ( cell_width - core_width ) : smaller = cell_height - core_height
else : smaller = cell_width - core_width
limit = DbU_lambda ( int ( DbU_getLambda ( smaller ) / 2 ) ) - pad_height
if ( (2*n + 1) * DbU_lambda(RING_INTERVAL) + (2*n) * DbU_lambda(RING_WIDTH) ) >= limit : # 2*n + 1 spaces + 2*n width
raise ErrorMessage(2,"PowerRing : too many rings, not enough space")
# la distance entre les couronnes et le core
marge = DbU_lambda ( int ( DbU_getLambda ( limit - (2*n + 1 ) * DbU_lambda(RING_INTERVAL) - (2*n) * DbU_lambda(RING_WIDTH) ) ) / 2 )
east_power = []
west_power = []
north_power = []
south_power = []
searchVddVss ( cell, east_power, west_power, north_power, south_power )
#affichePad ( cell )
# Creation des listes pad_north_pin_y_vss et pad_north_pin_vdd
pad_north_pin_x_vss = []
pad_north_pin_x_vdd = []
for pad_inst in pad_north :
if isInternalGroundPad ( pad_inst ) or isInternalPowerPad ( pad_inst ) \
or isExternalGroundPad ( pad_inst ) or isExternalPowerPad ( pad_inst ):
transformation = pad_inst.getTransformation()
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vssi") ):
if re.search ( "METAL2", str ( element.getLayer() ) ) \
and ( ( element.getY() - element.getBoundingBox().getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
pad_north_pin_x_vss.append ( [transformation.getX ( element.getX(), element.getY() ), element.getBoundingBox().getHalfWidth()] )
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vddi") ):
if re.search ( "METAL2", str ( element.getLayer() ) ) \
and ( ( element.getY() - element.getBoundingBox().getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
pad_north_pin_x_vdd.append ( [transformation.getX ( element.getX(), element.getY() ), element.getBoundingBox().getHalfWidth()] )
# Creation des listes pad_south_pin_y_vss et pad_south_pin_vdd
pad_south_pin_x_vss = []
pad_south_pin_x_vdd = []
for pad_inst in pad_south :
if isInternalGroundPad ( pad_inst ) or isInternalPowerPad ( pad_inst ) \
or isExternalGroundPad ( pad_inst ) or isExternalPowerPad ( pad_inst ):
transformation = pad_inst.getTransformation()
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vssi") ):
if re.search ( "METAL2", str ( element.getLayer() ) ) \
and ( ( element.getY() - element.getBoundingBox().getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
pad_south_pin_x_vss.append ( [transformation.getX ( element.getX(), element.getY() ), element.getBoundingBox().getHalfWidth()] )
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vddi") ):
if re.search ( "METAL2", str ( element.getLayer() ) ) \
and ( ( element.getY() - element.getBoundingBox().getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
pad_south_pin_x_vdd.append ( [transformation.getX ( element.getX(), element.getY() ), element.getBoundingBox().getHalfWidth()] )
# Creation des listes pad_east_pin_y_vss et pad_east_pin_vdd
pad_east_pin_y_vss = []
pad_east_pin_y_vdd = []
for pad_inst in pad_east :
if isInternalGroundPad ( pad_inst ) or isInternalPowerPad ( pad_inst ) \
or isExternalGroundPad ( pad_inst ) or isExternalPowerPad ( pad_inst ):
transformation = pad_inst.getTransformation()
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vssi") ):
if re.search ( "METAL2", str ( element.getLayer() ) ) \
and ( ( element.getY() - element.getBoundingBox().getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
pad_east_pin_y_vss.append ( [transformation.getY ( element.getX(), element.getY() ), element.getBoundingBox().getHalfHeight()] )
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vddi") ):
if re.search ( "METAL2", str ( element.getLayer() ) ) \
and ( ( element.getY() - element.getBoundingBox().getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
pad_east_pin_y_vdd.append ( [transformation.getY ( element.getX(), element.getY() ), element.getBoundingBox().getHalfHeight()] )
# Creation des listes pad_west_pin_y_vss et pad_west_pin_vdd
pad_west_pin_y_vss = []
pad_west_pin_y_vdd = []
for pad_inst in pad_west :
if isInternalGroundPad ( pad_inst ) or isInternalPowerPad ( pad_inst ) \
or isExternalGroundPad ( pad_inst ) or isExternalPowerPad ( pad_inst ):
transformation = pad_inst.getTransformation()
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vssi") ):
if re.search ( "METAL2", str ( element.getLayer() ) ) \
and ( ( element.getY() - element.getBoundingBox().getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
pad_west_pin_y_vss.append ( [transformation.getY ( element.getX(), element.getY() ), element.getBoundingBox().getHalfHeight()] )
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vddi") ):
if re.search ( "METAL2", str ( element.getLayer() ) ) \
and ( ( element.getY() - element.getBoundingBox().getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
pad_west_pin_y_vdd.append ( [transformation.getY ( element.getX(), element.getY() ), element.getBoundingBox().getHalfHeight()] )
#####################################
## PLACER LES COURONNES INTERNES ##
#####################################
# les listes pour sauvegarder les segments des couronnes des quatres coins
vertical_west_vss = []
vertical_east_vss = []
horizontal_south_vss = []
horizontal_north_vss = []
vertical_west_vdd = []
vertical_east_vdd = []
horizontal_south_vdd = []
horizontal_north_vdd = []
init_Xmin = core_Xmin - marge - DbU_lambda(RING_WIDTH) / 2
init_Xmin = init_Xmin - ( init_Xmin % DbU_lambda(PITCH) )
init_Ymin = core_Ymin - marge - DbU_lambda(RING_WIDTH) / 2
init_Ymin = init_Ymin - ( init_Ymin % DbU_lambda(PITCH) )
init_Xmax = core_Xmax + marge + DbU_lambda(RING_WIDTH) / 2
init_Xmax = init_Xmax - ( init_Xmax % DbU_lambda(PITCH) )
init_Ymax = core_Ymax + marge + DbU_lambda(RING_WIDTH) / 2
init_Ymax = init_Ymax - ( init_Ymax % DbU_lambda(PITCH) )
contact_side = DbU_lambda(RING_WIDTH-1)
for i in range ( 0, 2*n+1, 2 ) :
contact1 = Contact.create ( vss, cCoronaLayer, init_Xmin - decalage*i, init_Ymin - decalage*i, contact_side, contact_side )
contact2 = Contact.create ( vss, cCoronaLayer, init_Xmin - decalage*i, init_Ymax + decalage*i, contact_side, contact_side )
contact3 = Contact.create ( vss, cCoronaLayer, init_Xmax + decalage*i, init_Ymax + decalage*i, contact_side, contact_side )
contact4 = Contact.create ( vss, cCoronaLayer, init_Xmax + decalage*i, init_Ymin - decalage*i, contact_side, contact_side )
vertical_west_vss.append ( Vertical.create ( contact1, contact2, vCoronaLayer, init_Xmin - decalage*i, DbU_lambda(RING_WIDTH) ) )
vertical_east_vss.append ( Vertical.create ( contact3, contact4, vCoronaLayer, init_Xmax + decalage*i, DbU_lambda(RING_WIDTH) ) )
horizontal_south_vss.append ( Horizontal.create ( contact1, contact4, hCoronaLayer, init_Ymin - decalage*i, DbU_lambda(RING_WIDTH) ) )
horizontal_north_vss.append ( Horizontal.create ( contact2, contact3, hCoronaLayer, init_Ymax + decalage*i, DbU_lambda(RING_WIDTH) ) )
if i != 2*n :
contact1 = Contact.create ( vdd, cCoronaLayer, init_Xmin - decalage* ( i + 1 ), init_Ymin - decalage*( i + 1 ) , contact_side, contact_side )
contact2 = Contact.create ( vdd, cCoronaLayer, init_Xmin - decalage* ( i + 1 ), init_Ymax + decalage*( i + 1 ) , contact_side, contact_side )
contact3 = Contact.create ( vdd, cCoronaLayer, init_Xmax + decalage* ( i + 1 ), init_Ymax + decalage*( i + 1 ) , contact_side, contact_side )
contact4 = Contact.create ( vdd, cCoronaLayer, init_Xmax + decalage* ( i + 1 ), init_Ymin - decalage*( i + 1 ) , contact_side, contact_side )
vertical_west_vdd.append ( Vertical.create ( contact1, contact2, vCoronaLayer, init_Xmin - decalage* ( i + 1 ), DbU_lambda(RING_WIDTH) ) )
vertical_east_vdd.append ( Vertical.create ( contact3, contact4, vCoronaLayer, init_Xmax + decalage* ( i + 1 ), DbU_lambda(RING_WIDTH) ) )
horizontal_south_vdd.append ( Horizontal.create ( contact1, contact4, hCoronaLayer, init_Ymin - decalage* ( i + 1 ), DbU_lambda(RING_WIDTH) ) )
horizontal_north_vdd.append ( Horizontal.create ( contact2, contact3, hCoronaLayer, init_Ymax + decalage* ( i + 1 ), DbU_lambda(RING_WIDTH) ) )
# MACRO pour les directions d'access des pins
UNDEFINED = 0
NORTH = 1
SOUTH = 2
EAST = 3
WEST = 4
##############################################################
## Connecter les pins de vss aux couronnes de vss ##
##############################################################
core_transformation = core.getTransformation()
# parcourir les pins de vss
for element in mips_core.getNet("vss").getPins():
element_layer_name = str ( element.getLayer().getName() ) # string, nom du layer
# avoir le x, y transforme
_x = core_transformation.getX ( element.getX(), element.getY() )
_y = core_transformation.getY ( element.getX(), element.getY() )
# Creer un contact a la place du pin
if (allowedDepth > 2) and \
re.search ( "METAL4", element_layer_name ) : old_contact = Contact.create ( vss, metal4, _x, _y , element.getHeight(), element.getHeight() )
elif re.search ( "METAL1", element_layer_name ) : old_contact = Contact.create ( vss, metal1, _x, _y , element.getHeight(), element.getHeight() )
elif re.search ( "METAL3", element_layer_name ) : old_contact = Contact.create ( vss, metal3, _x, _y , element.getHeight(), element.getHeight() )
else :
raise ErrorMessage(2,"wrong layer of pin in the west of core : %s.\n" % element_layer_name)
# Connection du cote de l'ouest
if element.getAccessDirection() == WEST :
# Parcourir tous les couronnes vss
halfHeight = element.getHeight() / 2
lastVerti = n
for [yPin,pinHalfHeight] in pad_west_pin_y_vss + pad_west_pin_y_vdd :
if ( _y + halfHeight + DbU_lambda(3) >= yPin - pinHalfHeight and _y + halfHeight + DbU_lambda(3) <= yPin + pinHalfHeight ) \
or ( _y - halfHeight - DbU_lambda(3) <= yPin + pinHalfHeight and _y - halfHeight - DbU_lambda(3) >= yPin - pinHalfHeight ):
lastVerti = n/2 + (n+1)%2
for i in range ( lastVerti + 1 ) :
contact_x = init_Xmin - ( decalage*2 )*i # x du contact a creer
contact_side = element.getHeight() - DbU_lambda(1.0)
if (allowedDepth > 2) and re.search( "METAL4", element_layer_name ) :
contact = Contact.create ( vss, via3 , contact_x , _y , contact_side , contact_side )
horizontal = Horizontal.create ( contact, old_contact , metal4 , _y , element.getHeight() )
old_contact = contact
else :
contact_via1 = Contact.create ( vss, via1 , contact_x , _y , contact_side , contact_side )
contact_via2 = Contact.create ( vss, via2 , contact_x , _y , contact_side , contact_side )
horizontal = Horizontal.create ( contact_via1 , old_contact , metal1 , _y , element.getHeight() )
old_contact = contact_via1
# Connection du cote de l'est
if element.getAccessDirection() == EAST :
# Parcourir tous les couronnes vss
halfHeight = element.getHeight() / 2
lastVerti = n
for [yPin,pinHalfHeight] in pad_east_pin_y_vss + pad_east_pin_y_vdd :
if ( _y + halfHeight + DbU_lambda(3) >= yPin - pinHalfHeight and _y + halfHeight + DbU_lambda(3) <= yPin + pinHalfHeight ) \
or ( _y - halfHeight - DbU_lambda(3) <= yPin + pinHalfHeight and _y - halfHeight - DbU_lambda(3) >= yPin - pinHalfHeight ):
lastVerti = n/2 + (n+1)%2
for i in range ( lastVerti + 1 ) :
contact_x = init_Xmax + ( decalage*2 )*i # x du contact a creer
contact_side = element.getHeight() - DbU_lambda(1.0)
if (allowedDepth > 2) and re.search( "METAL4", element_layer_name ) :
contact = Contact.create ( vss, via3 , contact_x , _y , contact_side, contact_side )
horizontal = Horizontal.create ( contact, old_contact , metal4 , _y , element.getHeight() )
old_contact = contact
else :
contact_via1 = Contact.create ( vss, via1 , contact_x , _y , contact_side , contact_side )
contact_via2 = Contact.create ( vss, via2 , contact_x , _y , contact_side , contact_side )
horizontal = Horizontal.create ( contact_via1 , old_contact , metal1 , _y , element.getHeight() )
old_contact = contact_via1
# Connection du cote du nord
if element.getAccessDirection() == NORTH :
# Parcourir tous les couronnes vss
halfWidth = element.getHeight() / 2
lastVerti = n
for [xPin,pinHalfWidth] in pad_north_pin_x_vss + pad_north_pin_x_vdd :
if ( _x + halfWidth + DbU_lambda(3) >= xPin - pinHalfWidth and _x + halfWidth + DbU_lambda(3) <= xPin + pinHalfWidth ) \
or ( _x - halfWidth - DbU_lambda(3) <= xPin + pinHalfWidth and _x - halfWidth - DbU_lambda(3) >= xPin - pinHalfWidth ):
lastVerti = n/2 + (n+1)%2
for i in range ( lastVerti + 1 ) :
contact_y = init_Ymax + ( decalage*2 )*i # y du contact a creer
if re.search ( "METAL3", element_layer_name ) :
contact = Contact.create ( vss, via3, _x, contact_y, element.getHeight(), element.getHeight() )
vertical = Vertical.create ( contact, old_contact, metal3, _x, DbU_lambda(RING_WIDTH) )
old_contact = contact
else :
raise ErrorMessage(2,"wrong layer of pin in the west of core : %s.\n"% element_layer_name)
# Connection du cote du sud
if element.getAccessDirection() == SOUTH :
# Parcourir tous les couronnes vss
halfWidth = element.getHeight() / 2
lastVerti = n
for [xPin,pinHalfWidth] in pad_south_pin_x_vss + pad_south_pin_x_vdd :
if ( _x + halfWidth + DbU_lambda(3) >= xPin - pinHalfWidth and _x + halfWidth + DbU_lambda(3) <= xPin + pinHalfWidth ) \
or ( _x - halfWidth - DbU_lambda(3) <= xPin + pinHalfWidth and _x - halfWidth - DbU_lambda(3) >= xPin - pinHalfWidth ):
lastVerti = n/2 + (n+1)%2
for i in range ( lastVerti+1 ) :
contact_y = init_Ymin - ( decalage*2 )*i # x du contact a creer
if re.search ( "METAL3", element_layer_name ) :
contact = Contact.create ( vss, via3, _x, contact_y, element.getHeight(), element.getHeight() )
vertical = Vertical.create ( contact, old_contact, metal3, _x, DbU_lambda(RING_WIDTH) )
old_contact = contact
else :
raise ErrorMessage(2,"wrong layer of pin in the west of core : %s."%element_layer_name)
# End of while
#######################################################
### Connecter les pins de vdd aux couronnes de vdd ###
#######################################################
core_transformation = core.getTransformation()
# parcourir les pins de vdd
for element in mips_core.getNet("vdd").getPins():
element_layer_name = str(element.getLayer().getName()) # string , nom du layer
# avoir x, y transforme
_x = core_transformation.getX ( element.getX(), element.getY() )
_y = core_transformation.getY ( element.getX(), element.getY() )
# Creer un contact a la place du pin
if (allowedDepth > 2) and \
re.search ( "METAL4", element_layer_name ) : old_contact = Contact.create ( vdd, metal4, _x, _y , element.getHeight(), element.getHeight() )
elif re.search ( "METAL1", element_layer_name ) : old_contact = Contact.create ( vdd, metal1, _x, _y , element.getHeight(), element.getHeight() )
elif re.search ( "METAL3", element_layer_name ) : old_contact = Contact.create ( vdd, metal3, _x, _y , element.getHeight(), element.getHeight() )
else :
raise ErrorMessage(2,"wrong layer of pin in the west of core : %s."%element_layer_name)
# Connection du cote de l'ouest
if element.getAccessDirection() == WEST :
# Parcourir tous les couronnes vdd
halfHeight = element.getHeight() / 2
lastVerti = n
for [yPin,pinHalfHeight] in pad_west_pin_y_vss + pad_west_pin_y_vdd :
if ( _y + halfHeight + DbU_lambda(3) >= yPin - pinHalfHeight and _y + halfHeight + DbU_lambda(3) <= yPin + pinHalfHeight ) \
or ( _y - halfHeight - DbU_lambda(3) <= yPin + pinHalfHeight and _y - halfHeight - DbU_lambda(3) >= yPin - pinHalfHeight ):
lastVerti = n/2 + (n+1)%2
for i in range ( lastVerti ) :
contact_x = init_Xmin - decalage - ( decalage*2 )*i # x du contact a creer
contact_side = element.getHeight() - DbU_lambda(1.0)
if (allowedDepth > 2) and re.search( "METAL4", element_layer_name ) :
contact = Contact.create ( vdd, via3, contact_x, _y, contact_side, contact_side )
horizontal = Horizontal.create ( contact, old_contact, metal4, _y, element.getHeight() )
old_contact = contact
else :
contact_via1 = Contact.create ( vdd, via1, contact_x, _y, contact_side, contact_side )
contact_via2 = Contact.create ( vdd, via2, contact_x, _y, contact_side, contact_side )
horizontal = Horizontal.create ( contact_via1, old_contact, metal1, _y, element.getHeight() )
old_contact = contact_via1
# Connection du cote de l'est
if element.getAccessDirection() == EAST :
# Parcourir tous les couronnes vdd
halfHeight = element.getHeight() / 2
lastVerti = n
for [yPin,pinHalfHeight] in pad_east_pin_y_vss + pad_east_pin_y_vdd :
if ( _y + halfHeight + DbU_lambda(3) >= yPin - pinHalfHeight and _y + halfHeight + DbU_lambda(3) <= yPin + pinHalfHeight ) \
or ( _y - halfHeight - DbU_lambda(3) <= yPin + pinHalfHeight and _y - halfHeight - DbU_lambda(3) >= yPin - pinHalfHeight ):
lastVerti = n/2 + (n+1)%2
for i in range ( lastVerti ) :
contact_x = init_Xmax + ( decalage*2 )*i + decalage # x du contact a creer
contact_side = element.getHeight() - DbU_lambda(1.0)
if (allowedDepth > 2) and re.search( "METAL4", element_layer_name ) :
contact = Contact.create ( vdd, via3 , contact_x , _y , contact_side , contact_side )
horizontal = Horizontal.create ( contact, old_contact , metal4 , _y , element.getHeight() )
old_contact = contact
else :
contact_via1 = Contact.create ( vdd, via1, contact_x, _y, contact_side, contact_side )
contact_via2 = Contact.create ( vdd, via2, contact_x, _y, contact_side, contact_side )
horizontal = Horizontal.create ( contact_via1, old_contact, metal1, _y, element.getHeight() )
old_contact = contact_via1
# Connection du cote du nord
if element.getAccessDirection() == NORTH :
# Parcourir tous les couronnes vdd
halfWidth = element.getHeight() / 2
lastVerti = n
for [xPin,pinHalfWidth] in pad_north_pin_x_vss + pad_north_pin_x_vdd :
if ( _x + halfWidth + DbU_lambda(3) >= xPin - pinHalfWidth and _x + halfWidth + DbU_lambda(3) <= xPin + pinHalfWidth ) \
or ( _x - halfWidth - DbU_lambda(3) <= xPin + pinHalfWidth and _x - halfWidth - DbU_lambda(3) >= xPin - pinHalfWidth ):
lastVerti = n/2 + (n+1)%2
for i in range ( lastVerti ) :
contact_y = init_Ymax + decalage + ( decalage*2 )*i # x du contact a creer
if re.search ( "METAL3", element_layer_name ) :
contact = Contact.create ( vdd, via3, _x, contact_y, element.getHeight(), element.getHeight() )
vertical = Vertical.create ( contact, old_contact, metal3, _x, DbU_lambda(RING_WIDTH) )
old_contact = contact
else :
raise ErrorMessage(2,"wrong layer of pin in the west of core : %s."%element_layer_name)
# Connection du cote du sud
if element.getAccessDirection() == SOUTH :
# Parcourir tous les couronnes vdd
halfWidth = element.getHeight() / 2
lastVerti = n
for [xPin,pinHalfWidth] in pad_south_pin_x_vss + pad_south_pin_x_vdd :
if ( _x + halfWidth + DbU_lambda(3) >= xPin - pinHalfWidth and _x + halfWidth + DbU_lambda(3) <= xPin + pinHalfWidth ) \
or ( _x - halfWidth - DbU_lambda(3) <= xPin + pinHalfWidth and _x - halfWidth - DbU_lambda(3) >= xPin - pinHalfWidth ):
lastVerti = n/2 + (n+1)%2
for i in range ( lastVerti ) :
contact_y = init_Ymin - decalage - ( decalage*2 )*i # x du contact a creer
if re.search ( "METAL3", element_layer_name ) :
contact = Contact.create ( vdd, via3, _x, contact_y, element.getHeight(), element.getHeight() )
vertical = Vertical.create ( contact, old_contact, metal3, _x, DbU_lambda(RING_WIDTH) )
old_contact = contact
else :
raise ErrorMessage(2,"wrong layer of pin in the west of core : %s."%element_layer_name)
# End of while
# Attention au decalage de 1/2 de CMETAL
#LAMBDA = DbU_lambda ( 1 ) / 2
LAMBDA = DbU_lambda ( 1 )
###############################################################
# Connection entre couronnes internes et couronnes externes #
###############################################################
for pad_inst in pad_east :
if isInternalPowerPad ( pad_inst ) or isExternalPowerPad ( pad_inst ) \
or isInternalGroundPad ( pad_inst ) or isExternalGroundPad ( pad_inst ) :
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vssi") ):
layer = element.getLayer()
height = element.getBoundingBox().getHeight() - DbU_lambda(1.0)
if re.search ( "METAL3", str ( layer ) ) \
and ( ( element.getY() - ( height / 2 ) ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
X = pad_inst.getTransformation().getX ( element.getX(), element.getY() )
Y = pad_inst.getTransformation().getY ( element.getX(), element.getY() )
Contact.create ( vss, via2, X, Y, height, height )
contactPad = Contact.create ( vss, via1, X, Y, height, height )
Horizontal.create ( contactPad, vertical_east_vss[-1], metal1, Y, DbU_lambda ( RING_WIDTH ) )
Contact.create ( vss, via1, vertical_east_vss[-1].getX(), Y, height, height )
Contact.create ( vss, via2, vertical_east_vss[-1].getX(), Y, height, height )
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vddi") ):
layer = element.getLayer()
height = element.getBoundingBox().getHeight() - DbU_lambda(1.0)
if re.search ( "METAL3", str ( layer ) ) \
and ( ( element.getY() - ( height / 2 ) ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
X = pad_inst.getTransformation().getX ( element.getX(), element.getY() )
Y = pad_inst.getTransformation().getY ( element.getX(), element.getY() )
#Contact ( vdd, via2, X, Y, height, height )
contactPad = Contact.create ( vdd, via1, X, Y, height, height )
Horizontal.create ( contactPad, vertical_east_vdd[-1], metal1, Y, DbU_lambda ( RING_WIDTH ) )
Contact.create ( vdd, via1, vertical_east_vdd[-1].getX(), Y, height, height )
Contact.create ( vdd, via2, vertical_east_vdd[-1].getX(), Y, height, height )
for pad_inst in pad_west :
if isInternalPowerPad ( pad_inst ) or isExternalPowerPad ( pad_inst ) \
or isInternalGroundPad ( pad_inst ) or isExternalGroundPad ( pad_inst ) :
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vssi") ):
layer = element.getLayer()
height = element.getBoundingBox().getHeight() - DbU_lambda(1.0)
if re.search ( "METAL3", str ( layer ) ) \
and ( ( element.getY() - ( height / 2 ) ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
X = pad_inst.getTransformation().getX ( element.getX(), element.getY() )
Y = pad_inst.getTransformation().getY ( element.getX(), element.getY() )
#Contact ( vss, via2, X, Y, height, height )
contactPad = Contact.create ( vss, via1, X, Y, height, height )
Horizontal.create ( contactPad, vertical_west_vss[-1], metal1, Y, DbU_lambda ( RING_WIDTH ) )
Contact.create ( vss, via1, vertical_west_vss[-1].getX(), Y, height, height )
Contact.create ( vss, via2, vertical_west_vss[-1].getX(), Y, height, height )
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vddi") ):
layer = element.getLayer()
height = element.getBoundingBox().getHeight() - DbU_lambda(1.0)
if re.search ( "METAL3", str ( layer ) ) \
and ( ( element.getY() - ( height / 2 ) ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
X = pad_inst.getTransformation().getX ( element.getX(), element.getY() )
Y = pad_inst.getTransformation().getY ( element.getX(), element.getY() )
#Contact ( vdd, via2, X, Y, height, height )
contactPad = Contact.create ( vdd, via1, X, Y, height, height )
Horizontal.create ( contactPad, vertical_west_vdd[-1], metal1, Y, DbU_lambda ( RING_WIDTH ) )
Contact.create ( vdd, via1, vertical_west_vdd[-1].getX(), Y, height, height )
Contact.create ( vdd, via2, vertical_west_vdd[-1].getX(), Y, height, height )
for pad_inst in pad_north :
if isInternalPowerPad ( pad_inst ) or isExternalPowerPad ( pad_inst ) \
or isInternalGroundPad ( pad_inst ) or isExternalGroundPad ( pad_inst ) :
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vssi") ):
layer = element.getLayer()
height = element.getBoundingBox().getHeight() - DbU_lambda(1.0)
if re.search ( "METAL3", str ( layer ) ) \
and ( ( element.getY() - ( height / 2 ) ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
X = pad_inst.getTransformation().getX ( element.getX(), element.getY() )
Y = pad_inst.getTransformation().getY ( element.getX(), element.getY() )
Contact.create ( vss, via1, X, Y, height, height )
#Contact.create ( vss, via2, X, Y, height, height )
contactPad = Contact.create ( vss, metal1, X, Y, height, height )
Vertical.create ( contactPad, horizontal_north_vss[-1], metal1, X , DbU_lambda ( RING_WIDTH ) )
Contact.create ( vss, via1, X, horizontal_north_vss[-1].getY(), height, height )
if allowedDepth > 2:
Contact.create ( vss, via2, X, horizontal_north_vss[-1].getY(), height, height )
Contact.create ( vss, via3, X, horizontal_north_vss[-1].getY(), height, height )
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vddi") ):
layer = element.getLayer()
height = element.getBoundingBox().getHeight() - DbU_lambda(1.0)
if re.search ( "METAL3", str ( layer ) ) \
and ( ( element.getY() - ( height / 2 ) ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
X = pad_inst.getTransformation().getX ( element.getX(), element.getY() )
Y = pad_inst.getTransformation().getY ( element.getX(), element.getY() )
Contact.create ( vdd, via1, X, Y, height, height )
#Contact.create ( vdd, via2, X, Y, height, height )
contactPad = Contact.create ( vdd, metal1, X, Y, height, height )
Vertical.create ( contactPad, horizontal_north_vdd[-1], metal1, X, DbU_lambda ( RING_WIDTH ) )
Contact.create ( vdd, via1, X, horizontal_north_vdd[-1].getY(), height, height )
if allowedDepth > 2:
Contact.create ( vdd, via2, X, horizontal_north_vdd[-1].getY(), height, height )
Contact.create ( vdd, via3, X, horizontal_north_vdd[-1].getY(), height, height )
for pad_inst in pad_south :
if isInternalPowerPad ( pad_inst ) or isExternalPowerPad ( pad_inst ) \
or isInternalGroundPad ( pad_inst ) or isExternalGroundPad ( pad_inst ) :
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vssi") ):
layer = element.getLayer()
height = element.getBoundingBox().getHeight() - DbU_lambda(1.0)
if re.search ( "METAL3", str ( layer ) ) \
and ( ( element.getY() - ( height / 2 ) ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
X = pad_inst.getTransformation().getX ( element.getX(), element.getY() )
Y = pad_inst.getTransformation().getY ( element.getX(), element.getY() )
Contact.create ( vss, via1, X, Y, height, height )
#Contact.create ( vss, via2, X, Y, height, height )
contactPad = Contact.create ( vss, metal1, X, Y, height, height )
Vertical.create ( contactPad, horizontal_south_vss[-1], metal1, X , DbU_lambda ( RING_WIDTH ) )
Contact.create ( vss, via1, X, horizontal_south_vss[-1].getY(), height, height )
if allowedDepth > 2:
Contact.create ( vss, via2, X, horizontal_south_vss[-1].getY(), height, height )
Contact.create ( vss, via3, X, horizontal_south_vss[-1].getY(), height, height )
for element in NetExternalComponents.get ( pad_inst.getMasterCell().getNet("vddi") ):
layer = element.getLayer()
height = element.getBoundingBox().getHeight() - DbU_lambda(1.0)
if re.search ( "METAL3", str ( layer ) ) \
and ( ( element.getY() - ( height / 2 ) ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
X = pad_inst.getTransformation().getX ( element.getX(), element.getY() )
Y = pad_inst.getTransformation().getY ( element.getX(), element.getY() )
Contact.create ( vdd, via1, X, Y, height, height )
#Contact.create ( vdd, via2, X, Y, height, height )
contactPad = Contact.create ( vdd, metal1, X, Y, height, height )
Vertical.create ( contactPad, horizontal_south_vdd[-1], metal1, X , DbU_lambda ( RING_WIDTH ) )
Contact.create ( vdd, via1, X, horizontal_south_vdd[-1].getY(), height, height )
if allowedDepth > 2:
Contact.create ( vdd, via2, X, horizontal_south_vdd[-1].getY(), height, height )
Contact.create ( vdd, via3, X, horizontal_south_vdd[-1].getY(), height, height )
##################################### ###########################
## PLACER LES COURONNES EXTERNES ## # 1 2 #
##################################### # #
# #
# #
points_0 = [] # CHIP #
points_1 = [] # #
points_2 = [] # #
points_3 = [] # #
# #
# 0 3 #
###########################
instance = cell.getInstance ( pad_north[0].getName() )
trans = instance.getTransformation()
for net in instance.getMasterCell().getNets():
if net.isSupply() or net.isClock() :
for component in NetExternalComponents.get(net):
plug = instance.getPlug ( net )
NET = getNetFromPlug( plug )
if ( not NET ) : raise ErrorMessage(2,"Error plug : %s must be connected" % str(plug.getName()))
layer = getNonCLayer ( component.getLayer() )
# On applique la transformation au component, et on recupere les nouvelles coordonnees
Y = cell_Ymax + cell_Ymin - trans.getY ( component.getX(), component.getY() )
# On recupere la hauteur du component pour router sur la meme hauteur
RING_HEIGHT = component.getBoundingBox().getHeight()
# On calcule les differents points aux angles pour chaque net
X_point = cell_Xmin + Y
Y_point = cell_Ymin + Y
contact = Contact.create ( NET, layer, X_point, Y_point, RING_HEIGHT, RING_HEIGHT )
points_0.append ( dict ( [ ['X',X_point], ['Y',Y_point], ['N',NET], ['L',layer], ['R',RING_HEIGHT], ['C',contact] ] ) )
X_point = cell_Xmin + Y
Y_point = cell_Ymin + ( cell_Ymax - Y )
contact = Contact.create ( NET, layer, X_point, Y_point, RING_HEIGHT, RING_HEIGHT )
points_1.append ( dict ( [ ['X',X_point], ['Y',Y_point], ['N',NET], ['L',layer], ['R',RING_HEIGHT], ['C',contact] ] ) )
X_point = cell_Xmin + ( cell_Xmax - Y )
Y_point = cell_Ymin + ( cell_Ymax - Y )
contact = Contact.create ( NET, layer, X_point, Y_point, RING_HEIGHT, RING_HEIGHT )
points_2.append ( dict ( [ ['X',X_point], ['Y',Y_point], ['N',NET], ['L',layer], ['R',RING_HEIGHT], ['C',contact] ] ) )
X_point = cell_Xmin + ( cell_Xmax - Y )
Y_point = cell_Ymin + Y
contact = Contact.create ( NET, layer, X_point, Y_point, RING_HEIGHT, RING_HEIGHT )
points_3.append ( dict ( [ ['X',X_point], ['Y',Y_point], ['N',NET], ['L',layer], ['R',RING_HEIGHT], ['C',contact] ] ) )
# end of while
# end of while
#print "\n\n\n\npoints_0 : ", points_0 , "\n\npoints_1 : " ,points_1 , "\n\npoints_2 : " ,points_2 , "\n\npoints_3 : " , points_3 , "\n\n\n\n"
# Placer au cote du nord
for ins_pad in pad_north :
Y_pad = DbU_lambda ( int ( DbU_getLambda ( ins_pad.getAbutmentBox().getYCenter() ) ) )
X_pad = DbU_lambda ( int ( DbU_getLambda ( ins_pad.getAbutmentBox().getXCenter() ) ) )
if ins_pad == pad_north[0] :
for point in points_1 :
contact = Contact.create ( point['N'], point['L'], X_pad, point['Y'], point['R'], point['R'] )
Horizontal.create ( point['C'], contact, point['L'], point['Y'], point['R'] )
else :
for point in points_1 :
Horizontal.create ( point['N'], point['L'], point['Y'], point['R'], old_X_pad, X_pad )
if ins_pad == pad_north[-1] :
for point in points_2 :
contact = Contact.create ( point['N'], point['L'], X_pad, point['Y'], point['R'], point['R'] )
Horizontal.create ( contact, point['C'], point['L'], point['Y'], point['R'] )
old_X_pad = X_pad
# Placer au cote de l'est
for ins_pad in pad_east :
Y_pad = ins_pad.getAbutmentBox().getYCenter()
X_pad = ins_pad.getAbutmentBox().getXCenter()
if ins_pad == pad_east[0] :
for point in points_3 :
contact = Contact.create ( point['N'], point['L'], point['X'], Y_pad, point['R'], point['R'] )
Vertical.create ( point['C'], contact, point['L'], point['X'], point['R'] )
else :
for point in points_3 :
Vertical.create ( point['N'], point['L'], point['X'], point['R'], old_Y_pad, Y_pad )
if ins_pad == pad_east[-1] :
for point in points_2 :
contact = Contact.create ( point['N'], point['L'], point['X'], Y_pad, point['R'], point['R'] )
Vertical.create ( contact, point['C'], point['L'], point['X'], point['R'] )
old_Y_pad = Y_pad
# Placer au cote du south
for ins_pad in pad_south :
Y_pad = ins_pad.getAbutmentBox().getYCenter()
X_pad = ins_pad.getAbutmentBox().getXCenter()
if ins_pad == pad_south[0] :
for point in points_0 :
contact = Contact.create ( point['N'], point['L'], X_pad, point['Y'], point['R'], point['R'] )
Horizontal.create ( point['C'], contact, point['L'], point['Y'], point['R'] )
else :
for point in points_0 :
Horizontal.create ( point['N'], point['L'], point['Y'], point['R'], old_X_pad, X_pad )
if ins_pad == pad_south[-1] :
for point in points_3 :
contact = Contact.create ( point['N'], point['L'], X_pad, point['Y'], point['R'], point['R'] )
Horizontal.create ( contact, point['C'], point['L'], point['Y'], point['R'] )
old_X_pad = X_pad
# Placer au cote de l'ouest
for ins_pad in pad_west :
Y_pad = ins_pad.getAbutmentBox().getYCenter()
X_pad = ins_pad.getAbutmentBox().getXCenter()
if ins_pad == pad_west[0] :
for point in points_0 :
contact = Contact.create ( point['N'], point['L'], point['X'], Y_pad, point['R'], point['R'] )
Vertical.create ( point['C'], contact, point['L'], point['X'], point['R'] )
else :
for point in points_0 :
Vertical.create ( point['N'], point['L'], point['X'], point['R'], old_Y_pad, Y_pad )
if ins_pad == pad_west[-1] :
for point in points_1 :
contact = Contact.create ( point['N'], point['L'], point['X'], Y_pad, point['R'], point['R'] )
Vertical.create ( contact, point['C'], point['L'], point['X'], point['R'] )
old_Y_pad = Y_pad
UpdateSession.close()
#######################################
def create_inst ( model, name, cell ) :
# Error : if the cell the instance has to be instanciated in does not exist
if not cell :
raise ErrorMessage(2,"Cannot create instance %s : the cell does not exist."%name)
# Load model in the database
modelmastercell = CRL.AllianceFramework.get().getCell ( model, CRL.Catalog.State.Views )
# Error : if the model is not found in the libraries
if not modelmastercell :
raise ErrorMessage(2,"Cannot create instance %s : model %s does not exist in the database."%(name,model))
inst = Instance.create ( cell, name, modelmastercell )
# Connection
plugGround = inst.getPlug ( iter(modelmastercell.getGroundNets()).next() )
plugGround.setNet ( iter(cell.getGroundNets()).next() )
plugPower = inst.getPlug ( iter(modelmastercell.getPowerNets()).next() )
plugPower.setNet ( iter(cell.getPowerNets()).next() )
return inst
##########################
def place ( inst, x, y, orientation ) :
# Error : if the hurricane instance does not exist
if not inst :
raise ErrorMessage(2,"Layout : The instance of %s has not been created."%str(inst.getName()))
# Error : if the instance is already placed
if inst.getPlacementStatus() == Instance.PlacementStatus.FIXED :
raise ErrorMessage(2,"Placement : the instance %s is already placed."%str(inst.getName()))
UpdateSession.open()
## A COMPLETER POUR FAIRE DES PLACE AVEC TOUTES LES SYMETRIES ##
if orientation == Transformation.Orientation.MY :
y += inst.getAbutmentBox().getHeight()
inst.setTransformation ( Transformation ( x, y, orientation ) )
inst.setPlacementStatus ( Instance.PlacementStatus.FIXED )
UpdateSession.close()
#########################################
def getStandardInstancesMasque ( cell ) :
'''This function creates the mask of the standard cells'''
global FREE, standard_instances_masque, nb_lignes, nb_colonnes, reference
# The two dimensions of the mask
nb_lignes = cell.getAbutmentBox().getHeight() / DbU_lambda(SLICE)
nb_colonnes = cell.getAbutmentBox().getWidth() / DbU_lambda(PITCH)
# Creation of a mask named standard_instances_masque
standard_instances_masque = []
standard_instances_masque = [[FREE for j in range(nb_colonnes)] for i in range(nb_lignes)]
# Cover of all the instances of this model and fill in of the mask
reference = getAllStandardInstances ( cell )
return reference
######################################
def getAllStandardInstances ( cell ) :
'''This function is used to get all the standard instances of a cell and to flatten all the standard cells'''
global reference
reference = []
for element in cell.getInstances():
# FOR EACH PLACED or FIXED instance of the cell, we call getStandardInstances method
if element.getPlacementStatus() != Instance.PlacementStatus.UNPLACED :
reference = getStandardInstances ( cell, element, element.getTransformation(), cell.getName() )
return reference
##########################################################
def getStandardInstances ( cell, inst, transformation, name_masterinst ) :
'''This function covers all the instances of the model ,
it is also used to get all the transformations of the placed instances
it fills the standard_instances masque and the standard_instances_list '''
global POWER, OCCUPIED
global standard_instances_masque, reference
# Si l'instance est PLACED ou FIXED
if inst.getPlacementStatus() != Instance.PlacementStatus.UNPLACED :
name = str ( inst.getMasterCell().getLibrary().getName() )
if inst.isLeaf() :
# new abutmentbox
newbox = transformation.getBox ( inst.getMasterCell().getAbutmentBox() )
Height = newbox.getHeight()
Width = newbox.getWidth()
Xmin = newbox.getXMin()
Ymin = newbox.getYMin()
orientation = transformation.getOrientation()
if reference == [] : reference[ 0:3 ] = [ Xmin, Ymin, orientation ]
# on ajoute l'inst a la liste standard_instances_list
standard_instances_list.append ( ( Ymin, orientation, inst, str(name_masterinst) ) ) # add a tuple
nb_slices = Height / DbU_lambda(SLICE)
nb_pitchs = Width / DbU_lambda(PITCH)
# on remplit le masque
for i in range ( nb_slices ) :
for j in range ( nb_pitchs ) :
# on marque les cellules en POWER ou OCCUPIED FIXME : pourquoi ?
if re.search ( "powmid_x0", str ( inst.getMasterCell().getName() ) ) :
standard_instances_masque [ Ymin / DbU_lambda(SLICE) + i ][ Xmin / DbU_lambda(PITCH) + j ] = POWER
else :
standard_instances_masque [ Ymin / DbU_lambda(SLICE) + i ][ Xmin / DbU_lambda(PITCH) + j ] = OCCUPIED
# Si la masterCell n'est pas terminale, on appelle la fonction recursivement sur ses instances
else :
for element in inst.getMasterCell().getInstances():
getStandardInstances ( cell, element, transformation.getTransformation(element.getTransformation()), inst.getName() )
return reference
##########
def verifyPlacement ( cell ) :
'''This function is used to check the placement of the standard cells'''
global standard_instances_list
# YMin of reference
YMin = standard_instances_list[0][0]
# orientation code of reference
orientation = standard_instances_list[0][1]
# cover all the other
for i in range ( 1, len ( standard_instances_list ) ) :
element = standard_instances_list[i]
element_YMin = element[0]
element_orientation = element[1]
distance = element_YMin - YMin
# Error : if the orientation is different from 0, 2, 4 ,6
#if not element_orientation in [0,2,4,6] :
if element_orientation in [1,3,5,7] :
err = "Placement of cells : please check your file of layout with DRUC."
# err += "Error Detail :" + "\n"
# err += " instance " + str(element[2].getName()) + " of model " + str(element[2].getMasterCell().getName()) + "\n"
# err += " in cell " + str(element[2].getCell().getName()) + "\n"
# err += " incoherent with :" + "\n"
# err += " instance " + str(standard_instances_list[0][2].getName()) + "\n"
# err += " of model " + str(standard_instances_list[0][2].getMasterCell().getName()) + "\n"
# err += " in cell " + str(standard_instances_list[0][2].getCell().getName()) + "\n"
# err += " reference ymin is " + str(YMin) + " orientation " + str(orientation) + "\n"
# err += " element ymin is", element[0], "orientation", element_orientation + "\n"
raise ErrorMessage(2,err)
if distance < 0 : distance = -distance
nb_case = distance / DbU_lambda ( 50 )
# odd number
if nb_case % 2 :
if ( element_orientation - orientation ) in [4,-4] :
err = "Placement of cells : please check your file of layout with DRUC\n"
# err += "Error Detail :" + "\n"
# err += " instance " + str(element[2].getName()) + " of model " + str(element[2].getMasterCell().getName()) + "\n"
# err += " in cell " + str(element[2].getCell().getName()) + "\n"
# err += " incoherent with :" + "\n"
# err += " instance " + str(standard_instances_list[0][2].getName()) + "\n"
# err += " of model " + str(standard_instances_list[0][2].getMasterCell().getName()) + "\n"
# err += " in cell " + str(standard_instances_list[0][2].getCell().getName()) + "\n"
# err += " reference ymin is " + str(YMin) + " orientation " + orientation + "\n"
# err += " element ymin is " + element[0] + " orientation " + element_orientation + "\n"
raise ErrorMessage(2,err)
# even number
else :
if ( element_orientation - orientation ) in [2,-2,6,-6] :
err = "Placement of cells : please check your file of layout with DRUC\n"
# err += "Error Detail :"
# err += " instance " + str(element[2].getName()) + " of model " + str(element[2].getMasterCell().getName()) + "\n"
# err += " in cell " + str(element[2].getCell().getName()) + "\n"
# err += " incoherent with :" + "\n"
# err += " instance " + str(standard_instances_list[0][2].getName()) + "\n"
# err += " of model " + str(standard_instances_list[0][2].getMasterCell().getName()) + "\n"
# err += " in cell " + str(standard_instances_list[0][2].getCell().getName()) + "\n"
# err += " reference ymin is " + str(YMin) + " orientation " + orientation + "\n"
# err += " element ymin is " + element[0] + " orientation " + element_orientation + "\n"
raise ErrorMessage(2,err)
###################################
def temporarySave ( cell = None ) :
UpdateSession.open()
framework = CRL.AllianceFramework.get()
if cell == None :
for cell in framework.getLibrary(0).getCells():
if str ( cell.getName() ) != "__Scratch__" :
framework.saveCell ( cell, CRL.Catalog.State.Physical )
else :
framework.saveCell ( cell, CRL.Catalog.State.Physical )
UpdateSession.close()
###########################
def getVddVss ( cell, y ) :
'''This function returns a string 'vdd' or 'vss' according to the variance between y and the reference cell. y is in slices'''
global reference
if reference == [] : raise ErrorMessage(2,"getVddVss : Reference is not token.")
# in order to know if it is vdd or vss
distance = y - int ( DbU_getLambda ( reference[1] ) ) / 50
if distance < 0 : distance = -distance
orientation = reference[2]
if orientation in [0,4] :
if distance % 2 : return "vdd"
else : return "vss"
elif orientation in [2,6] :
if distance % 2 : return "vss"
else : return "vdd"
else :
raise ErrorMessage(2,"get_vdd_vss : Illegal orientation of reference %s.\n"%orientation)
###########################
def getPadHeight ( cell ) :
'''This function returns the pad height if there is at least one pad'''
padFound = 0
for instance in cell.getInstances():
if isPad ( instance ):
pad_height = instance.getMasterCell().getAbutmentBox().getHeight()
padFound = 1
break
if padFound : return pad_height
else : raise ErrorMessage(2,"getPadHeight : No pad found.")
###################
def isPad ( ins ) :
'''This function returns 1 if the instance is a pad'''
if re.search ( "p.*_px", str ( ins.getMasterCell().getName() ) ) \
or re.search ( "p.*_sp", str ( ins.getMasterCell().getName() ) ):
return True
else:
return False
################################
def isInternalPowerPad ( ins ) :
'''This function returns 1 if pad is an internal power pad'''
if re.search ( "pvddi", str ( ins.getMasterCell().getName() ) ) :
return 1
else:
return 0
################################
def isExternalPowerPad ( ins ) :
'''This function returns 1 if pad is an external power pad'''
if re.search ( "pvdde", str ( ins.getMasterCell().getName() ) ) :
return 1
else:
return 0
#################################
def isInternalGroundPad ( ins ) :
'''This function returns 1 if pad is an internal ground pad'''
if re.search ( "pvssi", str ( ins.getMasterCell().getName() ) ) :
return 1
else:
return 0
#################################
def isExternalGroundPad ( ins ) :
'''This function returns 1 if pad is an external ground pad'''
if re.search ( "pvsse", str ( ins.getMasterCell().getName() ) ) :
return 1
else:
return 0
################################
def isInternalClockPad ( ins ) :
'''This function returns 1 if pad is an internal clock pad'''
if re.search ( "pvssick_", str ( ins.getMasterCell().getName() ) ) \
or re.search ( "pvddick_", str ( ins.getMasterCell().getName() ) ) :
return 1
else:
return 0
################################
def isExternalClockPad ( ins ) :
'''This function returns 1 if pad is an external clock pad'''
if re.search ( "pvsseck_", str ( ins.getMasterCell().getName() ) ) \
or re.search ( "pvddeck_", str ( ins.getMasterCell().getName() ) ) :
return 1
else:
return 0
#########################
def affichePad ( cell ) :
global pad_north, pad_south, pad_east, pad_west
print "Pads in the north are :"
for pad in pad_north : print cell.getInstance ( pad.getName() ).getMasterCell().getName()
print "Pads in the south are :"
for pad in pad_south : print cell.getInstance ( pad.getName() ).getMasterCell().getName()
print "Pads in the east are :"
for pad in pad_east : print cell.getInstance ( pad.getName() ).getMasterCell().getName()
print "Pads in the west are :"
for pad in pad_west : print cell.getInstance ( pad.getName() ).getMasterCell().getName()
############
def searchVddVss ( cell, *args ) :
'''This function searches plots providing vdd and vss, and returns four lists'''
global pad_north, pad_south, pad_east, pad_west
# MACRO pour les directions d'access des pins
UNDEFINED = 0
NORTH = 1
SOUTH = 2
EAST = 3
WEST = 4
pad_list = [pad_east, pad_west, pad_north, pad_south]
for i in range ( len ( args ) ) :
for ins in pad_list[i] :
model = ins.getMasterCell()
transformation = ins.getTransformation()
if isInternalPowerPad ( ins ) or isExternalPowerPad ( ins ) \
or isInternalGroundPad ( ins ) or isExternalGroundPad ( ins ) :
# on connecte les pins vddi
for element in model.getNet("vddi").getPins():
layer = element.getLayer()
X = transformation.getX ( element.getX(), element.getY() )
Y = transformation.getY ( element.getX(), element.getY() )
args[i].append ( dict ( [['N', "vdd"], ['L',layer], ['X',X], ['Y',Y], ['C',0]] ) )
# on connecte les pins vssi
for element in model.getNet("vssi").getPins():
layer = element.getLayer()
X = transformation.getX ( element.getX(), element.getY() )
Y = transformation.getY ( element.getX(), element.getY() )
args[i].append ( dict ( [['N', "vss"], ['L',layer], ['X',X], ['Y', Y],['C',0]] ) )
########################
def createGrid ( my_tuple ) :
global ck_contact_list
global _Xmin, _Ymin, _Xmax, _Ymax
net, cell = my_tuple
def FindNearestPosition ( pos, poslist ) :
bestDistance = pos - poslist[0]
bestPos = poslist[0]
for x in poslist[1:] :
distance = pos - x
if distance <= 0 :
distance *= -1
if bestDistance > distance : return x
else :
if bestDistance > distance :
bestPos = x
bestDistance = pos - bestPos
return bestPos
def CreateZ ( contact1, contact2 ) :
centerX = (contact1.getX() + contact2.getX() ) / 2
centerX = centerX - (centerX % DbU_lambda(5))
zContact1 = Contact.create ( net, via5, centerX, contact1.getY(), DbU_lambda(11), DbU_lambda(11) )
zContact2 = Contact.create ( net, via5, centerX, contact2.getY(), DbU_lambda(11), DbU_lambda(11) )
Horizontal.create ( contact1, zContact1, metal6, contact1.getY(), DbU_lambda(12) )
Vertical.create ( zContact1, zContact2, metal5, zContact1.getX(), DbU_lambda(12) )
Horizontal.create ( zContact2, contact2, metal6, zContact2.getY(), DbU_lambda(12) )
def CreateN ( contact1, contact2 ) :
centerY = ( contact1.getY() + contact2.getY() ) / 2
centerY = centerY - ( centerY % DbU_lambda(5) )
nContact1 = Contact.create ( net, via5, contact1.getX(), centerY, DbU_lambda(11), DbU_lambda(11) )
nContact2 = Contact.create ( net, via5, contact2.getX(), centerY, DbU_lambda(11), DbU_lambda(11) )
Vertical.create ( contact1, nContact1, metal5, contact1.getX(), DbU_lambda(12) )
Horizontal.create ( nContact1, nContact2, metal6, nContact1.getY(), DbU_lambda(12) )
Vertical.create ( nContact2, contact2, metal5, nContact2.getX(), DbU_lambda(12) )
def FindPositionForContact ( position, contactlist1, contactlist2 ) :
def PositionIsInTargetRange ( position, target ) :
return position >= ( target - DbU_lambda(10) ) and position <= ( target + DbU_lambda(10) )
if contactlist1 == [] and contactlist2 == [] : return position
if contactlist1 != [] and contactlist2 != [] :
nearest1 = FindNearestPosition ( position, contactlist1 )
nearest2 = FindNearestPosition ( position, contactlist2 )
if ( not PositionIsInTargetRange(position, nearest1) ) and ( not PositionIsInTargetRange(position, nearest2) ) : return position
if PositionIsInTargetRange ( position, nearest1 ) :
if nearest2 > nearest1 : return position + DbU_lambda(12)
else : return position - DbU_lambda(12)
if PositionIsInTargetRange ( position, nearest2 ) :
if nearest1 > nearest2 : return position + DbU_lambda(12)
else : return position - DbU_lambda(12)
if contactlist1 != [] : contactlist = contactlist1
else : contactlist = contactlist2
nearest = FindNearestPosition ( position, contactlist )
if PositionIsInTargetRange ( position, nearest ) :
if position > nearest : return position + DbU_lambda(12)
else : return position - DbU_lambda(12)
else :
return position
#_Xmin = None
#_Ymin = None
#_Xmax = None
#_Ymax = None
coreBox = cell.getInstance('core').getAbutmentBox()
#print coreBox
_Xmin = coreBox.getXMin()
_Ymin = coreBox.getYMin()
_Xmax = coreBox.getXMax()
_Ymax = coreBox.getYMax()
ck_contact_list = []
getNetInstances ( cell, net, Transformation ( 0, 0, Transformation.Orientation.ID ) )
db = DataBase.getDB()
via1 = db.getTechnology().getLayer ( "VIA12" )
via2 = db.getTechnology().getLayer ( "VIA23" )
via3 = db.getTechnology().getLayer ( "VIA34" )
via4 = db.getTechnology().getLayer ( "VIA45" )
via5 = db.getTechnology().getLayer ( "VIA56" )
metal5 = db.getTechnology().getLayer ( "METAL5" )
metal6 = db.getTechnology().getLayer ( "METAL6" )
gridBoundingBox = Box()
for contact in ck_contact_list : gridBoundingBox.merge ( contact[0], contact[1] )
#the Bounding Box is inflated in function of the VIA_5 rule
gridBoundingBox.inflate ( DbU_lambda(15) )
#Create the Bounding Box grid
NEContact = Contact.create ( net, via5, gridBoundingBox.getXMin(), gridBoundingBox.getYMax() , DbU_lambda(11), DbU_lambda(11) )
NWContact = Contact.create ( net, via5, gridBoundingBox.getXMax(), gridBoundingBox.getYMax() , DbU_lambda(11), DbU_lambda(11) )
SEContact = Contact.create ( net, via5, gridBoundingBox.getXMin(), gridBoundingBox.getYMin() , DbU_lambda(11), DbU_lambda(11) )
SWContact = Contact.create ( net, via5, gridBoundingBox.getXMax(), gridBoundingBox.getYMin() , DbU_lambda(11), DbU_lambda(11) )
northSegment = Segment ( NEContact, NWContact, metal6, DbU_lambda(12) )
southSegment = Segment ( SEContact, SWContact, metal6, DbU_lambda(12) )
eastSegment = Segment ( NEContact, SEContact, metal5, DbU_lambda(12) )
westSegment = Segment ( NWContact, SWContact, metal5, DbU_lambda(12) )
northContacts = []
southContacts = []
eastContacts = []
westContacts = []
#connect the pins to the grid
plugList = []
#Fill a list with the plugs ... we are going to modify the underlying collection ;)
for plug in net.getPlugs():
plugList.append ( plug )
for plug in plugList:
instance = plug.getInstance()
if isPad ( instance ) :
# Connect this plug to the grid ...
masterNet = plug.getMasterNet()
transformation = instance.getTransformation()
for comp in NetExternalComponents.get(masterNet):
x = transformation.getX ( comp.getX(), comp.getY() )
y = transformation.getY ( comp.getX(), comp.getY() )
#layer = element.getLayer ()
#if re.search ( "METAL2", str ( layer ) ) \
# and ( ( element.getY() - element.getHalfHeight() ) < pad_inst.getMasterCell().getAbutmentBox().getYMin() ) :
if x >= gridBoundingBox.getXMin() and x <= gridBoundingBox.getXMax() :
layer = metal5
if y < gridBoundingBox.getYMin() :
if x == gridBoundingBox.getXMin() :
gridContact = NWContact
elif x == gridBoundingBox.getXMax() :
gridContact = NEContact
else :
gridContact = Contact.create(southSegment, via5, x, 0, DbU_lambda(11), DbU_lambda(11))
southContacts.append(x)
elif y > gridBoundingBox.getYMax() :
if x == gridBoundingBox.getXMin() :
gridContact = SWContact
elif x == gridBoundingBox.getXMax() :
gridBoundingBox = SEContact
else :
gridContact = Contact.create(northSegment, via5, x, 0, DbU_lambda(11), DbU_lambda(11))
northContacts.append(x)
else :
raise ErrorMessage(2,"RouteCK : bad pad placement.")
elif y >= gridBoundingBox.getYMin() and y <= gridBoundingBox.getYMax() :
layer = metal6
if x < gridBoundingBox.getXMin() :
if y == gridBoundingBox.getYMin() :
gridContact = SWContact
elif y == gridBoundingBox.getYMax() :
gridContact = NWContact
else :
gridContact = Contact.create(eastSegment, via5, 0, y, DbU_lambda(11), DbU_lambda(11))
eastContacts.append(y)
elif x > gridBoundingBox.getXMax() :
if y == gridBoundingBox.getYMin() :
gridContact = SEContact
elif y == gridBoundingBox.getYMax() :
gridContact = SWContact
else :
gridContact = Contact.create(westSegment, via5, 0, y, DbU_lambda(11), DbU_lambda(11))
westContacts.append(y)
else :
raise ErrorMessage(2,"RouteCK : bad pad placement.")
else :
message = [ "pyRouteCk: The pads <%s> must be in direct regard of the clock grid" % str(instance.getName())
, "Clock grid is %s" % str(gridBoundingBox)
]
raise ErrorMessage(2,message)
compContact = Contact.create ( net, via5, x, y, DbU_lambda(11), DbU_lambda(11) )
Segment ( compContact, gridContact, layer , DbU_lambda(12) )
break # just one component ...
# create the internal grid 200x200
nbVTracks = gridBoundingBox.getWidth() / DbU_lambda(200)
widthVTracks = gridBoundingBox.getWidth() / nbVTracks
nbHTracks = gridBoundingBox.getHeight() / DbU_lambda(200)
heightHTracks = gridBoundingBox.getHeight() / nbHTracks
via12Side = DbU.fromLambda(1.0)
via23Side = DbU.fromLambda(1.0)
via34Side = DbU.fromLambda(1.0)
via45Side = DbU.fromLambda(1.0)
via56Side = DbU.fromLambda(1.0)
xList = []
yList = []
for i in range ( 1, nbVTracks ) :
x = gridBoundingBox.getXMin() + i * widthVTracks
x = x - (x % DbU_lambda(5))
x = FindPositionForContact(x, northContacts, southContacts)
contact1 = Contact.create ( southSegment, via5, x, 0, DbU_lambda(11), DbU_lambda(11))
contact2 = Contact.create ( northSegment, via5, x, 0, DbU_lambda(11), DbU_lambda(11))
Segment ( contact1, contact2, metal5, DbU_lambda(12) )
xList.append ( x )
for i in range ( 1, nbHTracks ) :
y = gridBoundingBox.getYMin() + i * heightHTracks
y = y - ( y % DbU_lambda(5) )
y = FindPositionForContact ( y, eastContacts, westContacts )
contact1 = Contact.create ( westSegment, via5, 0, y, DbU_lambda(11), DbU_lambda(11) )
contact2 = Contact.create ( eastSegment, via5, 0, y, DbU_lambda(11), DbU_lambda(11) )
horizontal = Segment ( contact1, contact2, metal6, DbU_lambda(12) )
yList.append ( y )
for x in xList : Contact.create ( horizontal, via5, x, 0, DbU_lambda(11), DbU_lambda(11) )
# Connection to the grid
# Cette liste contient les contacts qui sont deja crees
ck_contact_list_created = []
# Now connect all the internal contacts to the grid
for contact in ck_contact_list :
xContact = contact[0]
yContact = contact[1]
plugContact = Contact.create ( net, via1 , xContact, yContact, via12Side, via12Side )
#find the closest x,y on grid
xList.insert ( 0, gridBoundingBox.getXMin() )
yList.insert ( 0, gridBoundingBox.getYMin() )
xList.append ( gridBoundingBox.getXMax() )
yList.append ( gridBoundingBox.getYMax() )
xTarget = FindNearestPosition ( xContact, xList )
yTarget = FindNearestPosition ( yContact, yList )
xDistance = abs ( xTarget - xContact )
yDistance = abs ( yTarget - yContact )
Contact.create(net, via2, xContact, yContact, via23Side, via23Side )
Contact.create(net, via3, xContact, yContact, via34Side, via34Side )
Contact.create(net, via4, xContact, yContact, via45Side, via45Side )
if xDistance != 0 or yDistance != 0 :
if ( xDistance <= yDistance + DbU_lambda(10) ): # test pour faire un horizontal
if xDistance != 0 :
if abs(xDistance) <= DbU_lambda(3) :
gridContact = Contact.create ( net, metal5, xTarget, yContact, via56Side, via56Side )
layer = metal5
else :
Contact.create ( net, via5, xContact, yContact, via56Side, via56Side )
gridContact = Contact.create ( net, via5, xTarget, yContact, via56Side, via56Side )
layer = metal6
Horizontal.create( gridContact, plugContact, layer, gridContact.getY(), DbU_lambda(2) )
else :
gridContact = Contact.create ( net, via5, xTarget, yContact, via56Side, via56Side )
else:
if yDistance != 0 :
if abs(yDistance) <= DbU_lambda(3) :
layer = metal6
gridContact = Contact.create ( net, metal6, xContact, yTarget, via56Side, via56Side )
Contact.create ( net, via5, xContact, yContact, via56Side, via56Side )
else :
gridContact = Contact.create ( net, via5, xContact, yTarget, via56Side, via56Side )
layer = metal5
Vertical.create ( gridContact, plugContact, layer, gridContact.getX(), DbU_lambda(2) )
else :
gridContact = Contact.create ( net, via5, xContact, yTarget, via56Side, via56Side )
del _Xmin
del _Ymin
del _Xmax
del _Ymax
del ck_contact_list
############################################
def getNetInstances ( cell, net, transformation) :
'''This function is used to cover instances with standard model, which are connected to "net"
transformation is the transformation of the instance which model contains this net'''
global ck_contact_list_to_create, ck_contact_list
global _Xmin, _Ymin, _Xmax, _Ymax
for plug in net.getPlugs(): # parcourir les plugs de ce net
ins = plug.getInstance()
# Si c est une instance de type leaf
if ins.isLeaf() :
if ins.getPlacementStatus() == Instance.PlacementStatus.UNPLACED :
raise ErrorMessage(2,"getNetInstances : instance %s is unplaced" % str(ins.getName()))
else :
if not isPad ( ins ) :
# get transformation final de cette instance
ins_transformation = transformation.getTransformation ( ins.getTransformation() )
nbSeg = 0
for segment in plug.getMasterNet().getSegments():
layer = segment.getLayer()
if NetExternalComponents.isExternal(segment) \
and ( re.search ( "METAL1", layer.getName() ) \
or re.search ( "METAL2", layer.getName() ) ):
# avoir x ,y de contact a placer
_x = ins_transformation.getX ( segment.getSourceX(), segment.getSourceY() )
_y = ins_transformation.getY ( segment.getSourceX(), segment.getSourceY() )
#print ins, ":", segment, ",", nbSeg, ",", _x, ",", _y
nbSeg += 1
ck_contact_list_to_create.append ( (_x, _y) )
ck_contact_list.append ( (_x, _y) )
newbox = ins_transformation.getBox ( ins.getMasterCell().getAbutmentBox() ) # get new box
Height = newbox.getHeight()
Width = newbox.getWidth()
Xmin = newbox.getXMin()
Ymin = newbox.getYMin()
Xmax = newbox.getXMax()
Ymax = newbox.getYMax()
#print " placer contact in ", _x, " ", _y , " in the net ", plug.getMasterNet().getName() ,
#print " of instance ", plug.getInstance().getName() , " in ", Xmin , " ", Ymin ,
#print " of model ", plug.getInstance().getMasterCell().getName(), "\n"
# Positionner la grille
if ( Xmin < _Xmin ) or ( _Xmin == None ) : _Xmin = Xmin
if ( Ymin < _Ymin ) or ( _Ymin == None ) : _Ymin = Ymin
if ( Xmax > _Xmax ) or ( _Xmax == None ) : _Xmax = Xmax
if ( Ymax > _Ymax ) or ( _Ymax == None ) : _Ymax = Ymax
break
if not nbSeg :
raise ErrorMessage(2,"getNetInstances : net %s in model %s does not have a segment\n" % ( str ( plug.getMasterNet().getName()), str(ins.getMasterCell().getName()) ) )
if ( not ck_contact_list ) : print "Error in function getNetInstances : no segment found"
else :
if ins.getPlacementStatus() == Instance.PlacementStatus.UNPLACED :
raise ErrorMessage(2,"getNetInstances : instance %s is unplaced" % str(ins.getName()))
else :
getNetInstances ( cell, plug.getMasterNet(), transformation.getTransformation ( ins.getTransformation () ))
############################
def getNonCLayer ( layer ) :
'''This function returns the nonC layer corresponding to the one given as argument'''
metal1 = DataBase.getDB ().getTechnology ().getLayer ( "METAL1" )
metal2 = DataBase.getDB ().getTechnology ().getLayer ( "METAL2" )
metal3 = DataBase.getDB ().getTechnology ().getLayer ( "METAL3" )
metal4 = DataBase.getDB ().getTechnology ().getLayer ( "METAL4" )
metal5 = DataBase.getDB ().getTechnology ().getLayer ( "METAL5" )
metal6 = DataBase.getDB ().getTechnology ().getLayer ( "METAL6" )
if re.search ( "CMETAL1", str ( layer.getName() ) ) : return metal1
if re.search ( "CMETAL2", str ( layer.getName() ) ) : return metal2
if re.search ( "CMETAL3", str ( layer.getName() ) ) : return metal3
if re.search ( "CMETAL4", str ( layer.getName() ) ) : return metal4
if re.search ( "CMETAL5", str ( layer.getName() ) ) : return metal5
if re.search ( "CMETAL6", str ( layer.getName() ) ) : return metal6
return layer
######################################################
def Segment ( component1, component2, layer, width ) :
'''This function creates a segment linking component1 and component2'''
if component1.getX() == component2.getX() : return Vertical.create ( component1, component2, layer, component1.getX(), width )
elif component1.getY() == component2.getY() : return Horizontal.create ( component1, component2, layer, component1.getY(), width )
else:
raise ErrorMessage(2,"Segment : the components must be horizontaly or verticaly aligned.")