coriolis/oroshi/python/resistorsnake.py

1526 lines
72 KiB
Python

#!/usr/bin/python
import sys
from math import sqrt, ceil
from ..Hurricane import *
from ..CRL import *
from .. import Constant
from ..helpers.io import ErrorMessage as Error
from ..helpers import trace, u
from . import getRules
def doBreak( level, message ):
UpdateSession.close()
Breakpoint.stop( level, message )
UpdateSession.open()
def toDbU ( l ): return DbU.fromPhysical( l , DbU.UnitPowerMicro )
def toPhy ( l ): return DbU.toPhysical ( int(l), DbU.UnitPowerMicro )
def toFoundryGrid ( l ):
twoGrid = DbU.fromGrid( 2.0 )
return l + (twoGrid - (l % twoGrid))
def isNearNorth ( y, ab ): return ab.getYMax() - y < y - ab.getYMin()
class Resistor ( object ):
rules = getRules()
def __init__( self, device, nets, resistorType, resistance = 0, resDim = { "width" : 10, "length" : 0 }, direction = "horizontal", bends = 0, shape = 90 ):
self.device = device
self.nets = nets
trace( 100, '\twidth:{0}, length:{1}, bends:{2}\n'.format(resDim['width'],resDim['length'],bends) )
#resDim["width" ] = toDbU(resDim["width" ])
#resDim["length"] = toDbU(resDim["length"])
self.__initArgs__ ( resistorType, direction, bends, shape )
self.setRules()
self.__initResDim__( resistance , resDim)
if self.snakeMode:
self.snakeSegmentDict = {}
self.resPlateExtrimity1 = {}
self.resPlateExtrimity2 = {}
self.resPlateExtension1 = {}
self.resPlateExtension2 = {}
self.snakeCornerDict = {}
if self.shape == 135 :
self.rightCorPointsVector = []
self.leftCorPointsVector = []
self.resPlateExtensions = {}
self.resPlateExtrimities = {}
self.resistorPlateDict = {}
self.abutmentBoxDict = { "XMin" : 0, "YMin" : 0 }
self.abutmentBox = Box ()
self.terminal1Box = Box()
self.terminal2Box = Box()
self.t1cutsEnclosure = {}
self.t2cutsEnclosure = {}
self.t1CutCenterDict = {}
self.t2CutCenterDict = {}
if self.resistorType == "RPOLYH" :
self.pImplant_layerDict = {}
self.hresLayerDict = {}
if self.resistorType == "RPOLY2PH" :
self.restrmLayerDict = {}
self.resdefLayerDict = {}
self.enclosure_resistor_abutmentBox = {}
return
def __initArgs__( self, resistorType, direction, bends, shape ):
if resistorType == "RPOLYH" or resistorType == "RPOLY2PH" : self.resistorType = resistorType
else : raise Error(1,'__initArgs__() : Unsupported resistor type : %s.' % resistorType)
if direction in ["horizontal", "vertical"] : self.direction = direction
else : raise Error(1,'__initDirection__() : Direction must be either "horizontal" or "vertical".')
if bends >= 0 :
if bends == 0 : [ self.bends, self.snakeMode ] = [ bends , False ]
elif bends > 0 and shape in [90, 135] : [ self.bends, self.snakeMode, self.shape ] = [ bends , True, shape ]
else : raise Error(1,'__initArgs__() : Resistor shape must be either 90 or 135 degrees : shape = %s.' %shape)
else : raise Error(1,'__initArgs__() : Bends number must not be negative : bends = %s.' %bends)
return
def __initContactsNumber__( self, resDim ):
layer_minWidth = Resistor.rules.minWidth_cut0 + 2*Resistor.rules.minEnclosure_poly2_cut0
layerWidth = self.resPlateExtensions_minWidth if resDim["width"] < layer_minWidth else resDim["width"]
self.contactsNumber = self.cutMaxNumber(layerWidth, Resistor.rules.minWidth_cut0, Resistor.rules.minSpacing_cut0, Resistor.rules.minEnclosure_poly2_cut0)
return
def __initResDim__( self, resistance, resDim ):
if self.__isDimOk__( resDim, "width" ) :
self.__initContactsNumber__(resDim)
print("contacts",self.contactsNumber)
if resistance > 0 and resDim["length"] > 0 :
if resistance - resistance/1000 <= self.__computeResistance__( resDim, self.resistorType ) <= resistance + resistance/1000 and self.__isDimOk__( resDim, "length" ):
self.resDim = resDim
else :
raise Error(1,'__initResDim__() : No compatibiliy between resistance value, %s, and resistor dimensions, "width" : %s, "length" : %s.' %(resistance, toPhy(resDim["width"]), toPhy(resDim["length"])))
elif resistance > 0 and resDim["length"] == 0 :
print("resistance0",resistance)
self.resDim = self.__computeResDim__( resistance, self.resistorType, resDim )
elif resistance == 0 and resDim["width"] > 0 and resDim["length"] > 0 and self.__isDimOk__( resDim, "length" ):
self.resDim = resDim
else : raise Error(1, '__initResDim__() : Invalid input parameters : resistance and/or resistor dimensions (%s, %s). Please provide at least one valid parameter.' %(resistance, resDim))
return
def setSidesDimRules( self ):
if self.resistorType == "RPOLYH" :
self.__setattr__( "minWidth_resistorPlate" , Resistor.rules.minWidth_rpolyh )
if self.resistorType == "RPOLY2PH" :
self.__setattr__( "minWidth_resistorPlate" , Resistor.rules.minWidthHighPrec_rpolyh )
self.__setattr__ ( "minLength_resistorPlate" , Resistor.rules.minRpolyhSquares )
return
def __isDimOk__( self, resdim, side ) :
self.setSidesDimRules()
print( resdim )
if list(resdim.keys()) == ["width","length"] and side in ["width","length"]:
if side == "width" :
rule = self.minWidth_resistorPlate
if side == "length" :
print("test0",resdim["width"])
rule = toDbU( self.minLength_resistorPlate*toPhy(resdim["width"]) )
state = True if resdim[side] >= rule else False
if state == False : raise Error(1,'__isDimOk__() : Resistor or bend side dimension, %s = %s, is below the minimal limit, %s.'
% (side, toPhy(resdim[side]), toPhy(rule)))
else : raise Error(1,'__isDimOk__() : The resistor or bend dimensions and the specified side, %s and %s, must be either "width" or "length".'
%(resdim,side))
return state
def __computeResistance__( self, resDim, resistorType ):
resistancePart1 = self.__getSheetResistance__( resistorType, "resistorPlate" )*toPhy(resDim["length"])/toPhy(resDim["width"])
resistancePart2 = 2*self.__getSheetResistance__( resistorType, "contact" )/self.contactsNumber
print("computedRes",resistancePart1 + resistancePart2)
return resistancePart1 + resistancePart2
def __computeResDim__( self, resistance, resistorType, resDim ):
contactsResistance = self.__getSheetResistance__( resistorType, "contact" )/self.contactsNumber
print("contactsResistance",contactsResistance)
wl_ratio = (resistance - 2*contactsResistance)/self.__getSheetResistance__( resistorType, "resistorPlate" )
width = toPhy(resDim["width"])
length = wl_ratio*width
resDim["length"] = toFoundryGrid( toDbU(length) )
print('length0',length)
if self.__isDimOk__(resDim, "width") and self.__isDimOk__(resDim, "length") :
return resDim
def __getSheetResistance__( self, resistorType, material ):
if material == 'resistorPlate':
if resistorType == "RPOLYH" : resistance = Resistor.rules.RPOLYHSheetRes
elif resistorType == "RPOLY2PH": resistance = Resistor.rules.RPOLY2PHSheetRes
else : raise Error( 1, '__getSheetResistance__() : Unsupported resistor type : %s.' % resistorType )
elif material == "contact" :
resistance = Resistor.rules.MET1RPOLYHContRes
return resistance
def __computeSnakeCornerDim__( self ):
self.snakeCornerDict["width" ] = self.resDim["width"]
self.snakeCornerDict["length"] = 2*self.resDim["width"] + self.minSpacing_resistorPlate
return
def __getCornerResistanceCorrectionFactor__( self ):
if self.shape not in [90, 135] : raise Error(1,'__getCornerResistanceCorrectionFactor__() : Invalid shape : %s.' %shape)
if self.shape == 135 : correctionFactor = Resistor.rules.corrFactor135
if self.shape == 90 : correctionFactor = Resistor.rules.corrFactor90
print(correctionFactor)
return correctionFactor
def setRules( self ):
trace( 101, '+,', '\tResistor.setRules()\n' )
self.minSpacing_resistorPlate = Resistor.rules.minSpacing_rpolyh
self.minWidth_contact = Resistor.rules.minWidth_cut0
self.minHeight_contact = Resistor.rules.minWidth_cut0
self.minSpacing_contact = Resistor.rules.minSpacing_cut0
self.minEnclosure_resistorPlate_contact = Resistor.rules.minEnclosure_poly2_cut0
self.minEnclosure_routingLayer_contact = Resistor.rules.minEnclosure_metal1_cut0
self.minEnclosure_metal1_cut0 = Resistor.rules.minEnclosure_metal1_cut0
self.minEnclosure_metal1_cut1 = Resistor.rules.minEnclosure_metal1_cut1
self.minWidth_cut1 = Resistor.rules.minWidth_cut1
self.minSpacing_cut1 = Resistor.rules.minSpacing_cut1
if self.resistorType == "RPOLYH":
self.minWidth_pImplantLayer = Resistor.rules.minWidth_pImplant
self.minSpacing_pImplantLayer = Resistor.rules.minSpacing_pImplant
self.minSpacing_resistorPlate_pImplantLayer = Resistor.rules.minSpacing_rpolyh_pImplant
self.minEnclosure_pImplantLayer_contact = Resistor.rules.minEnclosure_pImplant_poly2con
self.minEnclosure_hres_poly2 = Resistor.rules.minEnclosure_hres_poly2
self.minWidth_hres = Resistor.rules.minWidth_hres
self.minSpacing_hres = Resistor.rules.minSpacing_hres
self.minSpacing_hres_poly1 = Resistor.rules.minSpacing_hres_poly1
self.minSpacing_hres_poly2 = Resistor.rules.minSpacing_hres_poly2
self.minSpacing_hres_active = Resistor.rules.minSpacing_hres_active
self.resPlateExtensions_minWidth = self.minWidth_contact + 2*self.minEnclosure_resistorPlate_contact
# Get the METAL 1/2/3 layers.
self.cut1 = DataBase.getDB().getTechnology().getLayer( 'cut1' )
self.metal1 = DataBase.getDB().getTechnology().getLayer( 'metal1' )
self.metal2 = DataBase.getDB().getTechnology().getLayer( 'metal2' )
self.metal3 = DataBase.getDB().getTechnology().getLayer( 'metal3' )
# Get the symbolic pitch.
rg = AllianceFramework.get().getRoutingGauge()
self.METAL2Pitch = rg.getHorizontalPitch()
self.METAL3Pitch = rg.getVerticalPitch()
self.isVH = rg.isVH()
foundHor = False
foundVer = False
for depth in range(rg.getDepth()):
rlg = rg.getLayerGauge(depth)
if rlg.getLayer().getMask() == self.metal2.getMask(): self.metal2Width = rlg.getWireWidth()
if rlg.getLayer().getMask() == self.metal3.getMask(): self.metal3Width = rlg.getWireWidth()
if rlg.getType() == Constant.PinOnly: continue
if rlg.getDirection() == Constant.Horizontal and not foundHor:
trace( 101, '\tself.hpitch set\n' )
self.hpitch = rlg.getPitch()
foundHor = True
if rlg.getDirection() == Constant.Vertical and not foundVer:
trace( 101, '\tself.vpitch set\n' )
self.vpitch = rlg.getPitch()
foundVer = True
trace( 101, '-,' )
return
def getLayers( self ):
technology = DataBase.getDB().getTechnology()
self.layers = {}
self.layers["resistorPlate"] = technology.getLayer( "poly2" )
self.layers["contacts" ] = technology.getLayer( "cut0" )
self.layers["routingLayer" ] = technology.getLayer( "metal1" )
self.layers["metal2" ] = technology.getLayer( "metal2" )
self.layers["pImplant" ] = technology.getLayer( "pImplant" )
self.layers["resdef" ] = technology.getLayer( "resdef" )
if self.resistorType == "RPOLYH" : self.layers["hres" ] = technology.getLayer( "hres" )
if self.resistorType == "RPOLY2PH" : self.layers["restrm"] = technology.getLayer( "restrm" )
return self.layers
def create( self, bbMode = False ):
UpdateSession.open()
layerDict = self.getLayers()
self.computeDimensions(bbMode)
self.drawAbutmentBox ()
self.device.setAbutmentBox( self.abutmentBox )
if bbMode == False :
if self.resistorType == "RPOLYH" : self.drawLayer("hres", layerDict["hres"]) #self.drawHRESLayer( layerDict["hres"] )
self.drawLayer ("resistorPlate", layerDict["resistorPlate"])
self.drawResPlateExtrimities( layerDict["resistorPlate"], layerDict["pImplant"] )
if self.snakeMode : self.drawCorners(layerDict["resistorPlate"])
self.drawContacts( layerDict["contacts"])
self.drawRoutingLayer(layerDict["routingLayer"])
if self.resistorType == "RPOLY2PH" : self.drawRestrmLayer(layerDict["restrm"])
self.drawResdefLayer(layerDict["resdef"])
self.drawTerminals()
UpdateSession.close()
return self.abutmentBoxDict
def computeDimensions( self, bbMode ):
if self.snakeMode :
self.__computeSnakeCornerDim__ ()
self.computeSnakeSegmentDimensions()
if self.resistorType == "RPOLYH" : self.snakeSegments_spacing = max(self.minSpacing_resistorPlate_pImplantLayer, self.minSpacing_resistorPlate)
if self.resistorType == "RPOLY2PH" : self.snakeSegments_spacing = self.minSpacing_resistorPlate
self.computeAbutmentBoxDimensions()
if bbMode == False :
if not self.snakeMode :
self.computeResistorPlateDimensions()
if self.snakeMode :
self.computeFirstSnakeSegmentPosition()
return
def computePImplantLayerDim ( self ):
pImplantLayer_width = max(self.minWidth_pImplantLayer, 2*self.minEnclosure_pImplantLayer_contact + self.minWidth_contact)
self.pImplant_layerDict["width" ] = self.contactsNumber*self.minWidth_contact + (self.contactsNumber-1)*self.minSpacing_contact + 2*self.minEnclosure_pImplantLayer_contact
self.pImplant_layerDict["length"] = pImplantLayer_width
return
## extensions2 refers to a part of the corner
def computeResPlateExtensionsDim( self ):
self.resPlateExtensions_minWidth = self.minWidth_contact + 2*self.minEnclosure_resistorPlate_contact
self.resPlateExtensions["width"] = self.resPlateExtensions_minWidth if self.resDim["width"] < self.resPlateExtensions_minWidth else self.resDim["width"]
if self.resistorType == "RPOLYH" : self.resPlateExtensions["length"] = self.minWidth_contact + self.minEnclosure_resistorPlate_contact + self.minEnclosure_pImplantLayer_contact
if self.resistorType == "RPOLY2PH" : self.resPlateExtensions["length"] = self.minWidth_contact + self.minEnclosure_resistorPlate_contact
print("self.resPlateExtensions['length']",self.resPlateExtensions["length"])
if self.snakeMode :
self.resPlateExtension1 = self.resPlateExtensions
self.resPlateExtension2["width" ] = self.snakeSegmentDict["width"]
self.resPlateExtension2["length"] = self.snakeSegmentDict["width"]
return
def computeResPlateExtrimitiesDim( self ):
if self.resistorType == "RPOLYH" :
self.resPlateExtrimities ["width" ] = self.pImplant_layerDict ["width" ] + 2*self.enclosure_resistor_hres
self.resPlateExtrimities ["length"] = self.pImplant_layerDict ["length"] + self.enclosure_resistor_hres #self.pImplant_layerDict
if self.resistorType == "RPOLY2PH" :
for key in self.resPlateExtensions.keys(): self.resPlateExtrimities [key] = self.resPlateExtensions [key]
if self.snakeMode :
for key in self.resPlateExtrimities.keys(): self.resPlateExtrimity1 [key] = self.resPlateExtrimities [key]
if self.resistorType == "RPOLYH" :
self.resPlateExtrimity2["width" ] = self.resPlateExtension2 ["width" ] + 2*self.enclosure_resistor_hres
self.resPlateExtrimity2["length"] = self.resPlateExtension2 ["length"] + self.enclosure_resistor_hres
if self.resistorType == "RPOLY2PH" :
for key in self.resPlateExtension2.keys() : self.resPlateExtrimity2 [key] = self.resPlateExtension2[key]
for key in self.resPlateExtrimity1.keys() : self.resPlateExtrimities[key] = max(self.resPlateExtrimity1[key] , self.resPlateExtrimity2[key])
return
def computeAbutmentBoxDimensions( self ):
if self.resistorType == "RPOLYH" : self.enclosure_resistor_abutmentBox = self.minSpacing_hres
if self.resistorType == "RPOLY2PH" : self.enclosure_resistor_abutmentBox = self.minSpacing_resistorPlate
self.computeResPlateExtensionsDim()
print("self.resPlateExtensionsabt0['length']",toPhy(self.resPlateExtensions["length"]))
if not self.snakeMode : layerWidth = self.resPlateExtensions["width"]
if self.snakeMode : layerWidth = self.resPlateExtension1["width"]
self.contactsNumber = self.cutMaxNumber( layerWidth, self.minHeight_contact, self.minSpacing_contact, self.minEnclosure_resistorPlate_contact )
if self.resistorType == "RPOLYH" :
self.computePImplantLayerDim()
self.computeHRESLayerDimensions()
self.computeResPlateExtrimitiesDim()
if not self.snakeMode :
abutmentBoxSide1 = self.resPlateExtrimities["width" ] + 2*self.enclosure_resistor_abutmentBox
abutmentBoxSide2 = self.resDim ["length"] + 2*self.resPlateExtrimities["length"] + 2*self.enclosure_resistor_abutmentBox
if self.snakeMode :
if self.resistorType == "RPOLYH" : resistor_width = list(self.hresLayerDict.values())[0]
if self.resistorType == "RPOLY2PH" : resistor_width = (self.bends+1)*self.snakeSegmentDict["width"] + self.bends*self.snakeSegments_spacing
abutmentBoxSide1 = resistor_width + 2*self.enclosure_resistor_abutmentBox #width
if self.bends > 1 :
abutmentBoxSide2 = self.snakeSegmentDict["length"] + 2*self.resPlateExtrimities["length"] + 2*self.enclosure_resistor_abutmentBox
if self.bends == 1 :
abutmentBoxSide2 = self.snakeSegmentDict["length"] + self.resPlateExtrimity1["length"] + self.resPlateExtrimity2["length"] + 2*self.enclosure_resistor_abutmentBox
if self.direction == "vertical" :
self.abutmentBoxDict["width" ] = abutmentBoxSide1
self.abutmentBoxDict["height"] = abutmentBoxSide2
if self.direction == "horizontal" :
self.abutmentBoxDict["width" ] = abutmentBoxSide2
self.abutmentBoxDict["height"] = abutmentBoxSide1
return
def computeHRESLayerDimensions( self ):
self.enclosure_resistor_hres = self.minEnclosure_hres_poly2
if not self.snakeMode : hresLayerSide1 = max(self.minWidth_hres, self.pImplant_layerDict["width" ] + 2*self.enclosure_resistor_hres)
if self.snakeMode : hresLayerSide1 = max(self.minWidth_hres, (self.bends+1)*self.snakeSegmentDict["width"] + self.bends*self.snakeSegments_spacing + 2*self.enclosure_resistor_hres)
if self.direction == "vertical" :
self.hresLayerDict["length"] = hresLayerSide1
if self.direction == "horizontal" :
self.hresLayerDict["width" ] = hresLayerSide1
return
def computeResistorPlateDimensions( self ):
self.resistorPlateDict["width" ] = self.resDim["width" ]
self.resistorPlateDict["length" ] = self.resDim["length"]
if self.direction == "vertical" : keysList = ["XCenter","YMin","YMax","XMin","width" ]
if self.direction == "horizontal" : keysList = ["YCenter","XMin","XMax","YMin","height"]
self.resistorPlateDict[ keysList[0] ] = self.abutmentBoxDict [keysList[3]] + self.abutmentBoxDict [keysList[4]]/2
self.resistorPlateDict[ keysList[1] ] = self.abutmentBoxDict [keysList[1]] + self.enclosure_resistor_abutmentBox + self.resPlateExtrimities["length"]
self.resistorPlateDict[ keysList[2] ] = self.resistorPlateDict[keysList[1]] + self.resistorPlateDict["length"]
return
## The first bend is the lowest one (horizontally)
def computeSnakeSegmentDimensions( self ):
snakeSegmentDict = {}
snakeSegmentDict["width" ] = toPhy(self.resDim["width" ])
totalResLength = toPhy(self.resDim["length"])
correctionFactor = self.__getCornerResistanceCorrectionFactor__()
snakeSegmentDict["length"] = (totalResLength- self.bends*( snakeSegmentDict["width"]*(correctionFactor+1) + toPhy(self.minSpacing_resistorPlate) )) / (self.bends + 1)
snakeSegmentDict ["length"] = toFoundryGrid( toDbU(snakeSegmentDict["length"]) )
snakeSegmentDict ["width" ] = toFoundryGrid( toDbU(snakeSegmentDict["width" ]) )
print("snakesegW",snakeSegmentDict["width" ] )
if self.__isDimOk__(snakeSegmentDict, "length") :
self.snakeSegmentDict["width" ] = snakeSegmentDict["width" ]
self.snakeSegmentDict["length" ] = snakeSegmentDict["length"]
return
## The first bend is the lowest one (horizontally)
def computeFirstSnakeSegmentPosition( self ) :
if self.direction == "vertical" :
if self.bends > 1 : firstExtrimity_width = self.resPlateExtrimities["width"]
if self.bends == 1 : firstExtrimity_width = self.resPlateExtrimity1 ["width"]
if self.resistorType == "RPOLYH" :
self.snakeSegmentDict["XCenter"] = self.abutmentBoxDict["XMin"] + self.enclosure_resistor_abutmentBox + self.snakeSegmentDict["width"]/2 + self.enclosure_resistor_hres
self.snakeSegmentDict["YMin" ] = self.abutmentBoxDict["YMin"] + self.enclosure_resistor_abutmentBox + firstExtrimity_width #length
if self.resistorType == "RPOLY2PH" :
self.snakeSegmentDict["XCenter"] = self.abutmentBoxDict["XMin"] + self.enclosure_resistor_abutmentBox + self.snakeSegmentDict["width"]/2
self.snakeSegmentDict["YMin" ] = self.abutmentBoxDict["YMin"] + self.enclosure_resistor_abutmentBox + firstExtrimity_width
self.snakeSegmentDict ["YMax" ] = self.snakeSegmentDict["YMin"] + self.snakeSegmentDict["length"]
if self.direction == "horizontal" :
if self.bends > 1 : firstExtrimity_length = self.resPlateExtrimities["length"]
if self.bends == 1 : firstExtrimity_length = self.resPlateExtrimity1 ["length"]
if self.resistorType == "RPOLYH" :
self.snakeSegmentDict["YCenter"] = self.abutmentBoxDict["YMin"] + self.enclosure_resistor_abutmentBox + self.snakeSegmentDict["width"]/2 + self.enclosure_resistor_hres
self.snakeSegmentDict["XMin" ] = self.abutmentBoxDict["XMin"] + self.enclosure_resistor_abutmentBox + firstExtrimity_length
if self.resistorType == "RPOLY2PH" :
self.snakeSegmentDict["YCenter"] = self.abutmentBoxDict["YMin"] + self.enclosure_resistor_abutmentBox + self.snakeSegmentDict["width"]/2
self.snakeSegmentDict["XMin" ] = self.abutmentBoxDict["XMin"] + self.enclosure_resistor_abutmentBox + firstExtrimity_length
self.snakeSegmentDict ["XMax" ] = self.snakeSegmentDict["XMin"] + self.snakeSegmentDict["length"]
def computeHRESLayerPosition( self ):
if self.direction == "vertical" :
self.hresLayerDict["XCenter"] = self.abutmentBox.getXCenter()
self.hresLayerDict["YMin" ] = self.abutmentBox.getYMin() + self.enclosure_resistor_abutmentBox
self.hresLayerDict["YMax" ] = self.abutmentBox.getYMax() - self.enclosure_resistor_abutmentBox
if self.direction == "horizontal" :
self.hresLayerDict["YCenter"] = self.abutmentBox.getYCenter()
self.hresLayerDict["XMin" ] = self.abutmentBox.getXMin() + self.enclosure_resistor_abutmentBox
self.hresLayerDict["XMax" ] = self.abutmentBox.getXMax() - self.enclosure_resistor_abutmentBox
def drawLayer( self, layerLabel, layer):
thiknessKey = "width"
maxIterations = 1
centerTranslation = 0
if layerLabel not in ["hres","resistorPlate"] : raise Error(1,'drawLayer() : Supported layer labels "hres" or "resistorPlate".')
if layerLabel == "hres" :
self.computeHRESLayerPosition()
positionParams = self.hresLayerDict
if self.direction == "vertical" : thiknessKey = "length"
if layerLabel == "resistorPlate" :
if not self.snakeMode :
positionParams = self.resistorPlateDict
if self.snakeMode :
positionParams = self.snakeSegmentDict
maxIterations = self.bends + 1
centerTranslation = self.snakeSegmentDict["width"] + self.snakeSegments_spacing
if self.direction == "vertical" :
for i in range(0, maxIterations) :
print( self.nets[0], layer \
, positionParams["XCenter" ] + i*centerTranslation \
, positionParams[thiknessKey] \
, positionParams["YMin" ] \
, positionParams["YMax" ] )
Vertical.create ( self.nets[0], layer
, int(positionParams["XCenter" ] + i*centerTranslation)
, int(positionParams[thiknessKey])
, int(positionParams["YMin" ])
, int(positionParams["YMax" ])
)
if self.direction == "horizontal" :
for i in range(0, maxIterations) :
Horizontal.create( self.nets[0], layer
, int(positionParams["YCenter" ] + i*centerTranslation)
, int(positionParams[thiknessKey])
, int(positionParams["XMin" ])
, int(tositionParams["XMax" ] )
)
return
def drawResdefLayer( self, layer ):
self.computeResDefDimensions ()
if not self.snakeMode :
self.drawResdefForResistorPlate( layer )
if self.snakeMode :
self.drawResdefForSnakeSegments( layer )
self.drawResdefForCorners ( layer )
return
def drawResdefForResistorPlate( self, layer ):
if self.direction == "vertical" :
Vertical.create ( self.nets[0], layer
, int(self.resdefLayerDict["XCenter"])
, int(self.resdefLayerDict["width" ])
, int(self.resdefLayerDict["YMin" ])
, int(self.resdefLayerDict["YMax" ])
)
if self.direction == "horizontal" :
Horizontal.create( self.nets[0], layer
, int(self.resdefLayerDict["YCenter"])
, int(self.resdefLayerDict["width" ])
, int(self.resdefLayerDict["XMin" ])
, int(self.resdefLayerDict["XMax" ])
)
print("self.resdefLayerDict['width' ]",self.resdefLayerDict["width" ])
print("self.resistorPlateDict['width' ]",self.resistorPlateDict["width" ])
return
def drawResdefForSnakeSegments( self, layer ):
if not self.snakeMode : centerTranslation = 0
if self.snakeMode : centerTranslation = self.snakeSegmentDict["width"] + self.snakeSegments_spacing
if self.resistorType == "RPOLYH" : extrimityTranslation = 0
if self.resistorType == "RPOLY2PH" : extrimityTranslation = self.minWidth_contact/4
if self.direction == "vertical" :
for i in range(0, self.bends + 1) :
if self.resistorType == "RPOLYH" : factor0, factor1 = 1,1
if self.resistorType == "RPOLY2PH" :
factor0 = 0 if ( i == self.bends and self.bends % 2 == 0 ) else 1
factor1 = 0 if ( i == self.bends and self.bends % 2 != 0 ) or i == 0 else 1
Vertical.create ( self.nets[0], layer
, int(self.resdefLayerDict["XCenter"] + i*centerTranslation)
, int(self.resdefLayerDict["width" ])
, int(self.resdefLayerDict["YMin" ] + factor0*extrimityTranslation)
, int(self.resdefLayerDict["YMax" ] - factor1*extrimityTranslation)
)
if self.direction == "horizontal" :
for i in range(0, self.bends + 1) :
if self.resistorType == "RPOLYH" : factor0, factor1 = 1, 1
if self.resistorType == "RPOLY2PH" :
factor0 = 0 if i == 0 or (i == self.bends and self.bends % 2 != 0) else 1
factor1 = 0 if i == self.bends and self.bends % 2 == 0 else 1
Horizontal.create( self.nets[0], layer
, int(self.resdefLayerDict["YCenter"] + i*centerTranslation)
, int(self.resdefLayerDict["width" ])
, int(self.resdefLayerDict["XMin" ] + factor0*extrimityTranslation)
, int(self.resdefLayerDict["XMax" ] - factor1*extrimityTranslation)
)
return
def drawResdefForCorners( self, layer ):
k,factor = 0,0
if self.shape == 135 :
factor = 1
self.computeFirstSnakeCornerPosition90()
translation = self.snakeSegmentDict ["width" ] + self.snakeSegments_spacing
centersTranslationConst = self.snakeSegmentDict ["width" ] + self.snakeSegmentDict["length"]
if self.shape == 90 : widthExtension = self.minWidth_contact/2
if self.shape == 135 : widthExtension = self.minWidth_contact/4 + toDbU(0.2)
if self.direction == "vertical" :
snakeCornersYCenters = [ self.snakeCornerDict["YCenter"] - factor*( toDbU(0.2)/2 + self.minWidth_contact/8 )
, self.snakeCornerDict["YCenter"] + factor*( toDbU(0.2)/2 + self.minWidth_contact/8 ) + centersTranslationConst ]
for i in range(0,self.bends) :
Horizontal.create( self.nets[0], layer
, int(snakeCornersYCenters[k] )
, int(self.snakeCornerDict["width"] + widthExtension )
, int(self.snakeCornerDict["XMin" ] - self.minWidth_contact/4 + i*translation)
, int(self.snakeCornerDict["XMax" ] + self.minWidth_contact/4 + i*translation)
)
k = k+1 if k<1 else 0
if self.direction == "horizontal" :
snakeCornersXCenters = [ self.snakeCornerDict["XCenter"] + factor*( toDbU(0.2)/2 + self.minWidth_contact/8 )
, self.snakeCornerDict["XCenter"] - factor*( toDbU(0.2)/2 + self.minWidth_contact/8 ) - centersTranslationConst ]
for i in range(0,self.bends) :
Vertical.create ( self.nets[0], layer
, int(snakeCornersXCenters[k])
, int(self.snakeCornerDict["width"] + widthExtension )
, int(self.snakeCornerDict["YMin" ] - self.minWidth_contact/4 + i*translation)
, int(self.snakeCornerDict["YMax" ] + self.minWidth_contact/4 + i*translation)
)
k = k+1 if k<1 else 0
return
def drawSnakeSegments( self, layer ):
translation = self.snakeSegmentDict["width"] + self.snakeSegments_spacing
if self.direction == "vertical" :
for i in range(0, self.bends + 1) :
Vertical.create ( self.nets[0], layer
, self.snakeSegmentDict["XCenter"] + i*translation
, self.snakeSegmentDict["width" ]
, self.snakeSegmentDict["YMin" ]
, self.snakeSegmentDict["YMax" ]
)
if self.direction == "horizontal" :
for i in range(0, self.bends + 1) :
Horizontal.create( self.nets[0], layer
, self.snakeSegmentDict["YCenter"] + i*translation
, self.snakeSegmentDict["width" ]
, self.snakeSegmentDict["XMin" ]
, self.snakeSegmentDict["XMax" ]
)
return
def drawAbutmentBox( self ):
ab = Box( self.abutmentBoxDict["XMin" ]
, self.abutmentBoxDict["YMin" ]
, self.abutmentBoxDict["width" ]
, self.abutmentBoxDict["height"]
)
height = ab.getHeight()
heightAdjust = height % (2*self.hpitch)
if heightAdjust:
heightAdjust = 2*self.hpitch - heightAdjust
ab.inflate( 0, heightAdjust//2 )
width = ab.getWidth()
widthAdjust = width % (2*self.vpitch)
if widthAdjust:
widthAdjust = 2*self.vpitch - widthAdjust
ab.inflate( widthAdjust//2, 0 )
self.abutmentBox = ab
return
def drawResPlateExtrimities( self, resPlateLayer, pImplantLayer ):
self.drawResPlateExtensions(resPlateLayer)
if self.resistorType == "RPOLYH" :
self.drawPImplantLayer(pImplantLayer)
return
## extension1 is on the right side of the resistor (if direction == horizontal) and the bottom side otherwhise
def computeResPlateExtensionsPosition( self ):
self.resPlateExtensions["ex1"] = {}
if self.direction == "vertical" :
if not self.snakeMode : self.resPlateExtensions["ex1"]["XMin"] = self.abutmentBox.getXCenter() - self.resPlateExtensions["width" ]/2
if self.snakeMode : self.resPlateExtensions["ex1"]["XMin"] = self.abutmentBox.getXCenter() + (self.bends*(self.snakeSegmentDict["width"] + self.snakeSegments_spacing))/2 - self.resPlateExtensions["width"]/2
if not self.snakeMode : translation = self.resPlateExtensions["length"] + self.resDim["length"]/2
if self.snakeMode and self.bends % 2 == 0 : translation = self.resPlateExtensions["length"] + self.snakeSegmentDict["length"]/2
if self.snakeMode and self.bends % 2 != 0 : translation = self.snakeSegmentDict ["length"]/2
print("self.resPlateExtensions5['length']",toPhy(self.resPlateExtensions["length"]))
# print("self.snakeSegmentDict['length']/2",toPhy(self.snakeSegmentDict["length"]/2))
# print("translation",toPhy(self.resPlateExtensions['length'] + self.snakeSegmentDict["length"]/2))
print("self.abutmentBox.getYCenter(",toPhy(self.abutmentBox.getYCenter()))
if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : self.resPlateExtensions["ex1"]["YMin"] = self.abutmentBox.getYCenter() - translation
if self.snakeMode and self.bends % 2 != 0 : self.resPlateExtensions["ex1"]["YMin"] = self.abutmentBox.getYCenter() + translation
print("self.resPlateExtensions['ex1']['YMin']",toPhy(self.resPlateExtensions["ex1"]["YMin"]))
self.resPlateExtensions["ex1"]["XMax"] = self.resPlateExtensions["ex1"]["XMin"] + self.resPlateExtensions["width" ]
self.resPlateExtensions["ex1"]["YMax"] = self.resPlateExtensions["ex1"]["YMin"] + self.resPlateExtensions["length"]
if self.direction == "horizontal" :
if not self.snakeMode : resistorLength = self.resDim ["length"]
if self.snakeMode : resistorLength = self.snakeSegmentDict["length"]
self.resPlateExtensions["ex1"]["XMin"] = self.abutmentBox.getXCenter() - self.resPlateExtensions["length"] - resistorLength/2
if not self.snakeMode : self.resPlateExtensions["ex1"]["YMin"] = self.abutmentBox.getYCenter() - self.resPlateExtensions["width" ]/2
if self.snakeMode : self.resPlateExtensions["ex1"]["YMin"] = self.snakeSegmentDict["YCenter"] - self.resPlateExtensions["width" ]/2
self.resPlateExtensions["ex1"]["XMax"] = self.resPlateExtensions["ex1"]["XMin"] + self.resPlateExtensions["length"]
# print("self.resPlateExtensions['length']",toPhy(self.resPlateExtension2["length"]))
self.resPlateExtensions["ex1"]["YMax"] = self.resPlateExtensions["ex1"]["YMin"] + self.resPlateExtensions["width" ]
return
def drawResPlateExtensions( self, layer ):
self.computeResPlateExtensionsPosition()
if not self.snakeMode : resistorLength = self.resDim ["length"]
if self.snakeMode : resistorLength = self.snakeSegmentDict["length"]
translation1 = resistorLength + self.resPlateExtensions["length"]
if self.snakeMode : translation2 = self.bends*(self.snakeSegmentDict["width"] + self.snakeSegments_spacing) #- self.resPlateExtensions["width"]
if self.direction == "vertical" :
if not self.snakeMode : [ hTranslation , vTranslation ] = [ 0 , translation1 ]
if self.snakeMode and self.bends % 2 == 0 : [ hTranslation , vTranslation ] = [ translation2 , translation1 ]
if self.snakeMode and self.bends % 2 != 0 : [ hTranslation , vTranslation ] = [ translation2 , 0 ]
self.terminal1Box = Box( int(self.resPlateExtensions["ex1"]["XMin"])
, int(self.resPlateExtensions["ex1"]["YMin"])
, int(self.resPlateExtensions["ex1"]["XMax"])
, int(self.resPlateExtensions["ex1"]["YMax"])
)
self.terminal2Box = Box( int(self.resPlateExtensions["ex1"]["XMin"] - hTranslation)
, int(self.resPlateExtensions["ex1"]["YMin"] + vTranslation)
, int(self.resPlateExtensions["ex1"]["XMax"] - hTranslation)
, int(self.resPlateExtensions["ex1"]["YMax"] + vTranslation)
)
if self.direction == "horizontal" :
if not self.snakeMode : [ hTranslation , vTranslation ] = [ translation1 , 0 ]
if self.snakeMode and self.bends % 2 == 0 : [ hTranslation , vTranslation ] = [ translation1 , translation2 ]
if self.snakeMode and self.bends % 2 != 0 : [ hTranslation , vTranslation ] = [ 0 , translation2 ]
print("vTranslation",vTranslation)
print("hTranslation",hTranslation)
self.terminal1Box = Box( self.resPlateExtensions["ex1"]["XMin"]
, self.resPlateExtensions["ex1"]["YMin"]
, self.resPlateExtensions["ex1"]["XMax"]
, self.resPlateExtensions["ex1"]["YMax"]
)
self.terminal2Box = Box( self.resPlateExtensions["ex1"]["XMin"] + hTranslation
, self.resPlateExtensions["ex1"]["YMin"] + vTranslation
, self.resPlateExtensions["ex1"]["XMax"] + hTranslation
, self.resPlateExtensions["ex1"]["YMax"] + vTranslation
)
terminal1Pad = Pad.create(self.nets[0], layer, self.terminal1Box)
terminal2Pad = Pad.create(self.nets[1], layer, self.terminal2Box)
return
def computePImplantLayerPosition( self ):
factor1 = factor2 = -1
if not self.snakeMode : centerTranslation = 0
if self.snakeMode : centerTranslation = self.bends*(self.snakeSegments_spacing + self.snakeSegmentDict["width"])/2
if self.direction == "vertical" :
keysList = ["YCenter","XMin","XMax","YMin"]
functionsList = [self.abutmentBox.getYCenter(), self.abutmentBox.getXCenter()]
if self.snakeMode and self.bends % 2 != 0 : factor1 = 1
if self.snakeMode : factor2 = 1
if self.direction == "horizontal" :
keysList = ["XCenter","YMin","YMax","XMin"]
functionsList = [self.abutmentBox.getXCenter(), self.abutmentBox.getYCenter()]
if not self.snakeMode : resistorLength = self.resDim ["length"]
if self.snakeMode : resistorLength = self.snakeSegmentDict["length"]
self.pImplant_layerDict[ keysList[0] ] = functionsList[0] + factor1*( resistorLength/2 + self.pImplant_layerDict["length"]/2 )
self.pImplant_layerDict[ keysList[1] ] = functionsList[1] + factor2*centerTranslation - self.pImplant_layerDict["width" ]/2 #- centerTranslation - self.pImplant_layerDict["width" ]/2
self.pImplant_layerDict[ keysList[2] ] = self.pImplant_layerDict[keysList[1]] + self.pImplant_layerDict["width" ]
return
def drawPImplantLayer( self, layer ):
self.computePImplantLayerPosition()
if not self.snakeMode : resistorLength = self.resDim ["length"]
if self.snakeMode : resistorLength = self.snakeSegmentDict["length"]
if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : centerTranslation = resistorLength + self.pImplant_layerDict["length"]
if self.snakeMode and self.bends % 2 != 0 : centerTranslation = 0
if not self.snakeMode : extrimitiesTranslation = 0
if self.snakeMode : extrimitiesTranslation = self.bends*(self.snakeSegments_spacing + self.snakeSegmentDict["width"]) #+ self.pImplant_layerDict["width"]/2
if self.direction == "vertical" :
for i in [0,1] : Horizontal.create( self.nets[i], layer
, int(self.pImplant_layerDict["YCenter"] + i*centerTranslation)
, int(self.pImplant_layerDict["length" ])
, int(self.pImplant_layerDict["XMin" ] - i*extrimitiesTranslation)
, int(self.pImplant_layerDict["XMax" ] - i*extrimitiesTranslation)
)
if self.direction == "horizontal" :
for i in [0,1] : Vertical.create ( self.nets[i], layer
, int(self.pImplant_layerDict["XCenter"] + i*centerTranslation)
, int(self.pImplant_layerDict["length" ])
, int(self.pImplant_layerDict["YMin" ] + i*extrimitiesTranslation)
, int(self.pImplant_layerDict["YMax" ] + i*extrimitiesTranslation)
)
return
## t1Cut connected to terminal1 (on the right side/bottom side of rectangular)
def computecenterTranslationDimensions( self ):
enclosure1 = ( self.resPlateExtensions["width"] - (self.contactsNumber*self.minHeight_contact + (self.contactsNumber -1)*self.minSpacing_contact) )/2
enclosure2 = self.minEnclosure_resistorPlate_contact
if self.resistorType == "RPOLYH" : enclosure3 = self.minEnclosure_pImplantLayer_contact
if self.resistorType == "RPOLY2PH" : enclosure3 = 0
if self.direction == "vertical":
self.t1cutsEnclosure["horizontal"] = enclosure1
if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : self.t1cutsEnclosure["vertical"] = enclosure2
if self.snakeMode and self.bends % 2 != 0 : self.t1cutsEnclosure["vertical"] = enclosure3
self.t2cutsEnclosure["horizontal"] = enclosure1
self.t2cutsEnclosure["vertical" ] = enclosure3
if self.direction == "horizontal" :
self.t1cutsEnclosure["horizontal"] = enclosure2
self.t1cutsEnclosure["vertical" ] = enclosure1
if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : self.t2cutsEnclosure["horizontal"] = enclosure3
if self.snakeMode and self.bends % 2 != 0 : self.t2cutsEnclosure["horizontal"] = enclosure2
#self.t2cutsEnclosure["horizontal"] = enclosure3
self.t2cutsEnclosure["vertical" ] = enclosure1
self.t1CutCenterDict ["XCenter" ] = self.terminal1Box.getXMin() + self.t1cutsEnclosure ["horizontal"] + self.minWidth_contact/2
self.t1CutCenterDict ["YCenter" ] = self.terminal1Box.getYMin() + self.t1cutsEnclosure ["vertical" ] + self.minHeight_contact/2
self.t2CutCenterDict ["XCenter" ] = self.terminal2Box.getXMin() + self.t2cutsEnclosure ["horizontal"] + self.minWidth_contact/2
self.t2CutCenterDict ["YCenter" ] = self.terminal2Box.getYMin() + self.t2cutsEnclosure ["vertical" ] + self.minHeight_contact/2
return
def drawContacts( self, layer ):
self.computecenterTranslationDimensions()
if self.direction == "vertical" : cutLineDirection = "horizontal"
if self.direction == "horizontal" : cutLineDirection = "vertical"
self.cutLine ( self.nets[0], layer
, self.t1CutCenterDict["XCenter"]
, self.t1CutCenterDict["YCenter"]
, self.minWidth_contact
, self.minHeight_contact
, self.minSpacing_contact
, self.contactsNumber
, cutLineDirection
)
self.cutLine ( self.nets[1], layer
, self.t2CutCenterDict["XCenter"]
, self.t2CutCenterDict["YCenter"]
, self.minWidth_contact
, self.minHeight_contact
, self.minSpacing_contact
, self.contactsNumber
, cutLineDirection
)
return
def drawRoutingLayer( self, layer ):
layer_width = self.minWidth_contact + 2*self.minEnclosure_routingLayer_contact
layer_height = self.contactsNumber*self.minWidth_contact + (self.contactsNumber-1)*self.minSpacing_contact + 2*self.minEnclosure_routingLayer_contact
if self.direction == "vertical" : key = "XCenter"
if self.direction == "horizontal" : key = "YCenter"
source1 = self.t1CutCenterDict[key] - self.minWidth_contact/2 - self.minEnclosure_routingLayer_contact
target1 = source1 + layer_height
source2 = self.t2CutCenterDict[key] - self.minWidth_contact/2 - self.minEnclosure_routingLayer_contact
target2 = source2 + layer_height
if self.direction == "vertical" :
Horizontal.create( self.nets[0]
, layer
, int(self.t1CutCenterDict["YCenter"])
, int(layer_width)
, int(source1)
, int(target1) )
Horizontal.create( self.nets[1]
, layer
, int(self.t2CutCenterDict["YCenter"])
, int(layer_width)
, int(source2)
, int(target2))
trace( 101, '\tIN PAD self.t1CutCenterDict["XCenter"] = {0}\n'.format(DbU.getValueString(self.t1CutCenterDict["XCenter"])) )
trace( 101, '\tIN PAD source1 = {0}\n'.format(DbU.getValueString(source1)) )
trace( 101, '\tIN PAD target1 = {0}\n'.format(DbU.getValueString(target1)) )
#h = Horizontal.create( self.nets[0]
# , self.layers['metal2']
# , self.t1CutCenterDict["YCenter"]
# , layer_width
# , source1
# , target1 )
#NetExternalComponents.setExternal( h )
#
#h = Horizontal.create( self.nets[1]
# , self.layers['metal2']
# , self.t2CutCenterDict["YCenter"]
# , layer_width
# , source2
# , target2 )
#NetExternalComponents.setExternal( h )
if self.direction == "horizontal" :
Vertical.create (self.nets[0], layer, self.t1CutCenterDict["XCenter"], layer_width, source1, target1)
Vertical.create (self.nets[1], layer, self.t2CutCenterDict["XCenter"], layer_width, source2, target2)
return
def drawRestrmLayer( self, layer ):
self.computeRestrmLayerPosition()
if not self.snakeMode : resistorLength = self.resDim ["length"]
if self.snakeMode : resistorLength = self.snakeSegmentDict["length"]
if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : centerTranslation = resistorLength + self.restrmLayerDict["width"]
if self.snakeMode and self.bends % 2 != 0 : centerTranslation = 0
if not self.snakeMode : extrimitiesTranslation = 0
if self.snakeMode : extrimitiesTranslation = self.bends*(self.snakeSegments_spacing + self.snakeSegmentDict["width"])
if self.direction == "vertical" :
for i in [0,1]: Horizontal.create( self.nets[i], layer
, self.restrmLayerDict["YCenter"] + i*centerTranslation
, self.restrmLayerDict["width" ]
, self.restrmLayerDict["XMin" ] - i*extrimitiesTranslation
, self.restrmLayerDict["XMax" ] - i*extrimitiesTranslation
)
if self.direction == "horizontal" :
for i in [0,1]: Vertical.create ( self.nets[i], layer
, self.restrmLayerDict["XCenter"] + i*centerTranslation
, self.restrmLayerDict["width" ]
, self.restrmLayerDict["YMin" ] + i*extrimitiesTranslation
, self.restrmLayerDict["YMax" ] + i*extrimitiesTranslation
)
return
def computeRestrmLayerPosition( self ):
self.restrmLayerDict["width"] = self.minWidth_contact/2
factor = 1
if self.direction == "vertical" :
keysList = ["YCenter","XMin","XMax"]
# if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : factor = 1
if self.snakeMode and self.bends % 2 != 0 : factor = -1
if self.direction == "horizontal" :
keysList = ["XCenter","YMin","YMax"]
self.restrmLayerDict[ keysList[0] ] = self.t1CutCenterDict [ keysList[0] ] + factor*self.restrmLayerDict["width"]/2
self.restrmLayerDict[ keysList[1] ] = self.resPlateExtensions["ex1"][ keysList[1] ] - self.restrmLayerDict["width"]
self.restrmLayerDict[ keysList[2] ] = self.resPlateExtensions["ex1"][ keysList[2] ] + self.restrmLayerDict["width"]
return
def computeResDefDimensions( self ):
if self.direction == "vertical" : keysList = ["YMin","YMax","XCenter","width"]
if self.direction == "horizontal" : keysList = ["XMin","XMax","YCenter","width"]
if not self.snakeMode : resistorElement = self.resistorPlateDict
if self.snakeMode : resistorElement = self.snakeSegmentDict
if self.resistorType == "RPOLYH" : factor = 0
if self.resistorType == "RPOLY2PH" : factor = 1
self.resdefLayerDict[keysList[0]] = resistorElement[keysList[0]] - factor*self.minWidth_contact/4
self.resdefLayerDict[keysList[1]] = resistorElement[keysList[1]] + factor*self.minWidth_contact/4
self.resdefLayerDict[keysList[2]] = resistorElement[keysList[2]]
self.resdefLayerDict[keysList[3]] = resistorElement[keysList[3]]
if self.resDim["width"] >= self.resPlateExtensions_minWidth :
self.resdefLayerDict[keysList[3]] = self.resdefLayerDict[keysList[3]] + self.minWidth_contact/2
return
def computeFirstSnakeCornerPosition90( self ):
if self.direction == "vertical" :
self.snakeCornerDict["YCenter"] = self.snakeSegmentDict["YMin" ] - self.snakeCornerDict ["width" ]/2
self.snakeCornerDict["XMin" ] = self.snakeSegmentDict["XCenter"] - self.snakeSegmentDict["width" ]/2
self.snakeCornerDict["XMax" ] = self.snakeCornerDict ["XMin" ] + self.snakeCornerDict ["length"]
if self.direction == "horizontal" :
self.snakeCornerDict["XCenter"] = self.snakeSegmentDict["XMax" ] + self.snakeCornerDict ["width" ]/2
self.snakeCornerDict["YMin" ] = self.snakeSegmentDict["YCenter"] - self.snakeSegmentDict["width" ]/2
self.snakeCornerDict["YMax" ] = self.snakeCornerDict ["YMin" ] + self.snakeCornerDict ["length"]
return
def drawCorners90( self, layer ):
self.computeFirstSnakeCornerPosition90()
k = 0
translation = self.snakeSegmentDict["width"] + self.snakeSegments_spacing
centersTranslationConst = self.snakeSegmentDict["width"] + self.snakeSegmentDict["length"]
if self.direction == "vertical" :
snakeCornersYCenters = [ self.snakeCornerDict["YCenter"]
, self.snakeCornerDict["YCenter"] + centersTranslationConst]
for i in range(0,self.bends) :
Horizontal.create( self.nets[0], layer
, snakeCornersYCenters[k]
, self.snakeCornerDict["width"]
, self.snakeCornerDict["XMin" ] + i*translation
, self.snakeCornerDict["XMax" ] + i*translation
)
k = k+1 if k<1 else 0
if self.direction == "horizontal" :
snakeCornersXCenters = [ self.snakeCornerDict["XCenter"]
, self.snakeCornerDict["XCenter"] - centersTranslationConst ]
for i in range(0,self.bends) :
Vertical.create ( self.nets[0], layer
, snakeCornersXCenters[k]
, self.snakeCornerDict["width"]
, self.snakeCornerDict["YMin" ] + i*translation
, self.snakeCornerDict["YMax" ] + i*translation
)
k = k+1 if k<1 else 0
return
def computeFirstSnakeCornerPosition135( self ):
param1 = (self.snakeSegmentDict["width"]*42/100)/2
param2 = toDbU(0.2)
param3 = self.snakeSegmentDict["width"] + param2
param4 = param3 - param1
if self.direction == "vertical" :
rx0 = self.snakeSegmentDict["XCenter"] - self.snakeSegmentDict["width"]/2
ry0 = self.snakeSegmentDict["YMin" ]
rx1 = rx0
ry1 = ry0 - param1
rx2 = rx0 + param4
ry2 = ry1 - param4
rx3 = rx0 + 2*self.snakeSegmentDict["width"] + self.snakeSegments_spacing - param4
ry3 = ry2
rx4 = rx3 + param4
ry4 = ry1
rx5 = rx4
ry5 = ry0
rx6 = rx5 - self.snakeSegmentDict["width"]
ry6 = ry0
rx7 = rx0 + self.snakeSegmentDict["width"] + self.snakeSegments_spacing - param2
ry7 = ry0 - param2
rx8 = rx0 + self.snakeSegmentDict["width"] + param2
ry8 = ry7
rx9 = rx0 + self.snakeSegmentDict["width"]
ry9 = ry0
if self.direction == "horizontal" :
rx0 = self.snakeSegmentDict["XMax" ]
ry0 = self.snakeSegmentDict["YCenter"] - self.snakeSegmentDict["width"]/2
rx1 = rx0 + param1
ry1 = ry0
rx2 = rx1 + (self.snakeSegmentDict["width"] + param2) - param1
ry2 = ry1 + (self.snakeSegmentDict["width"] + param2) - param1
rx3 = rx2
ry3 = ry2 + (2*self.snakeSegmentDict["width"] + self.snakeSegments_spacing) - 2*(self.snakeSegmentDict["width"] + param2 - param1)
rx4 = rx1
ry4 = ry1 + 2*self.snakeSegmentDict["width"] + self.snakeSegments_spacing
rx5 = rx0
ry5 = ry0 + 2*self.snakeSegmentDict["width"] + self.snakeSegments_spacing
rx6 = rx0
ry6 = ry0 + self.snakeSegmentDict["width"] + self.snakeSegments_spacing
rx7 = rx0 + param2
ry7 = ry6 - param2
rx8 = rx7
ry8 = ry0 + self.snakeSegmentDict["width"] + param2
rx9 = rx0
ry9 = ry0 + self.snakeSegmentDict["width"]
rightCorCordinatesList = [ [rx0 , ry0 ] , [rx1, ry1 ]
, [rx2 , ry2 ] , [rx3, ry3 ]
, [rx4 , ry4 ] , [rx5, ry5 ]
, [rx6 , ry6 ] , [rx7, ry7 ]
, [rx8 , ry8 ] , [rx9, ry9 ]
]
for p in rightCorCordinatesList :
self.rightCorPointsVector.append(Point(int(p[0]),int(p[1])))
self.leftCorPointsVector.append (Point(int(p[0]),int(p[1])))
translationList = [ self.snakeSegmentDict["length"]
, self.snakeSegmentDict["length"] + 2*param1
, self.snakeSegmentDict["length"] + 2*param3
, self.snakeSegmentDict["length"] + 2*param3
, self.snakeSegmentDict["length"] + 2*param1
, self.snakeSegmentDict["length"]
, self.snakeSegmentDict["length"]
, self.snakeSegmentDict["length"] + 2*param2
, self.snakeSegmentDict["length"] + 2*param2
, self.snakeSegmentDict["length"]
]
if self.direction == "vertical" :
for i in range(0, len(self.leftCorPointsVector)) : self.leftCorPointsVector[i].translate( 0 , int(translationList[i]) )
if self.direction == "horizontal" :
for i in range(0, len(self.leftCorPointsVector)) : self.leftCorPointsVector[i].translate( int(- translationList[i]) , 0)
return
def drawCorners135( self, layer ):
self.computeFirstSnakeCornerPosition135()
if self.bends % 2 == 0 : [ rightCornersNum, leftCornersNum ] = [ self.bends//2 , self.bends//2 ]
if self.bends % 2 != 0 : [ rightCornersNum, leftCornersNum ] = [ (self.bends+1)//2 , (self.bends-1)//2 ]
translationFactor = 2*(self.snakeSegmentDict["width"] + self.snakeSegments_spacing)
if self.direction == "vertical" : [dxTranslation, dyTranslation] = [ translationFactor, 0 ]
if self.direction == "horizontal" : [dxTranslation, dyTranslation] = [ 0 , translationFactor ]
for i in range(0, rightCornersNum) :
Rectilinear.create( self.nets[0], layer, self.rightCorPointsVector ).translate(i*dxTranslation, i*dyTranslation)
for i in range(0, leftCornersNum ) :
if i == 0 :
if self.direction == "vertical" : Rectilinear.create(self.nets[0], layer, self.leftCorPointsVector).translate(dxTranslation//2,dyTranslation)
if self.direction == "horizontal": Rectilinear.create(self.nets[0], layer, self.leftCorPointsVector).translate(dxTranslation,dyTranslation//2)
if i != 0 :
if self.direction == "vertical" : Rectilinear.create(self.nets[0], layer, self.leftCorPointsVector).translate(i*3*dxTranslation//2,dyTranslation)
if self.direction == "horizontal": Rectilinear.create(self.nets[0], layer, self.leftCorPointsVector).translate(dxTranslation,i*3*dyTranslation//2)
return
def drawCorners( self, layer):
if self.shape == 90 : self.drawCorners90 (layer)
if self.shape == 135 : self.drawCorners135(layer)
return
# def drawResDefLayer( self, layer ):
# self.computeResDefDimensions()
# if self.direction == "vertical" : Vertical.create ( self.nets[0], layer, self.resdefLayerDict["XCenter"], self.resdefLayerDict["width"], self.resdefLayerDict["YMin"], self.resdefLayerDict["YMax"] )
# if self.direction == "horizontal" : Horizontal.create ( self.nets[0], layer, self.resdefLayerDict["YCenter"], self.resdefLayerDict["width"], self.resdefLayerDict["XMin"], self.resdefLayerDict["XMax"] )
# return
## Creates a horizontal or vertical line of contacts according to the specified direction.
def cutLine( self, net, layer, firstCutXCenter, firstCutYCenter, width_cut, height_cut, spacing_cut, cutNumber, direction ):
for i in range(0, cutNumber) :
if direction == 'horizontal':
segment = Contact.create( net
, layer
, int(firstCutXCenter + i*(width_cut + spacing_cut))
, int(firstCutYCenter)
, int(width_cut)
, int(height_cut) )
else:
segment = Contact.create( net
, layer
, int(firstCutXCenter)
, int(firstCutYCenter + i*(height_cut + spacing_cut))
, int(width_cut)
, int(height_cut) )
return segment
## Computes the maximal number of cuts to be placed on a layer of width \c width_layer considering specifications such as the spacing between the cuts, its width and its enclosure in the layer.
def cutMaxNumber( self, width_layer, width_cut, spacing_cut, enclosure_cut ):
cutNumber = int( (width_layer - 2*enclosure_cut + spacing_cut) / (width_cut + spacing_cut) )
if cutNumber > 0: return cutNumber
else:
raise Error (1,"cutMaxNumber() : Zero number of cuts found. Layer width is too tight." )
def drawTerminals ( self ):
VIA1overhang = self.minWidth_cut1/2 + self.minEnclosure_metal1_cut1
t1net = self.device.getNet('t1')
t2net = self.device.getNet('t2')
t1metal1 = None
t2metal1 = None
for component in t1net.getComponents():
if isinstance(component,Horizontal) and component.getLayer() == self.metal1:
t1metal1 = component
break
for component in t2net.getComponents():
if isinstance(component,Horizontal) and component.getLayer() == self.metal1:
t2metal1 = component
break
ab = self.device.getAbutmentBox()
t1OnNorth = isNearNorth( t1metal1.getY(), ab )
t2OnNorth = isNearNorth( t2metal1.getY(), ab )
if t1OnNorth and t2OnNorth:
t1YM2 = ab.getYMax() - self.hpitch*2
t2YM2 = ab.getYMax() - self.hpitch
elif t1OnNorth:
t1YM2 = ab.getYMax() - self.hpitch
t2YM2 = ab.getYMin() + self.hpitch
elif t2OnNorth:
t1YM2 = ab.getYMin() + self.hpitch
t2YM2 = ab.getYMax() - self.hpitch
else:
t1YM2 = ab.getYMin() + self.hpitch*2
t2YM2 = ab.getYMin() + self.hpitch
m1Width = self.contactsNumber *self.minWidth_contact \
+ (self.contactsNumber-1)*self.minSpacing_contact \
+ 2*self.minEnclosure_routingLayer_contact
edgeDelta = self.minWidth_contact/2 + self.minEnclosure_metal1_cut0
if t1OnNorth:
t1BoxM1 = Box( int(0)
, int(self.t1CutCenterDict["YCenter"] - edgeDelta)
, int(m1Width)
, int(t1YM2 + VIA1overhang)
)
else:
t1BoxM1 = Box( int(0)
, int(t1YM2 - VIA1overhang)
, int(m1Width)
, int(self.t1CutCenterDict["YCenter"] + edgeDelta)
)
t1BoxM1.translate( int(self.t1CutCenterDict["XCenter"] - edgeDelta), 0 )
if t2OnNorth:
t2BoxM1 = Box( int(0)
, int(self.t2CutCenterDict["YCenter"] - edgeDelta)
, int(m1Width)
, int(t2YM2 + VIA1overhang)
)
else:
t2BoxM1 = Box( int(0)
, int(t2YM2 - VIA1overhang)
, int(m1Width)
, int(self.t2CutCenterDict["YCenter"] + edgeDelta)
)
t2BoxM1.translate( int(self.t2CutCenterDict["XCenter"] - edgeDelta), 0 )
self.drawM2Terminal( t1net, t1BoxM1, t1YM2 )
self.drawM2Terminal( t2net, t2BoxM1, t2YM2 )
return
def drawM2Terminal ( self, net, boxM1, axisM2 ):
ab = self.device.getAbutmentBox()
minBoxM1 = Box( boxM1.getCenter().getX(), axisM2 )
minBoxM1.inflate( int(self.minWidth_cut1/2 + self.minEnclosure_metal1_cut1) )
boxM1.merge( minBoxM1 )
h = Horizontal.create( net
, self.metal2
, int(axisM2)
, int(self.metal2Width)
, int(ab.getXMin())
, int(ab.getXMax()) )
NetExternalComponents.setExternal( h )
Vertical.create( net
, self.metal1
, int(boxM1.getCenter().getX())
, int(boxM1.getWidth())
, int(boxM1.getYMin())
, int(boxM1.getYMax())
)
cutNumber = ((boxM1.getWidth() - 2*self.minEnclosure_metal1_cut1 - self.minWidth_cut1) \
// (self.minSpacing_cut1 + self.minWidth_cut1))
if cutNumber <= 0: cutNumber = 1
centering = (boxM1.getWidth() - 2*self.minEnclosure_metal1_cut1 \
- cutNumber * self.minWidth_cut1 \
- (cutNumber-1) * self.minSpacing_cut1) // 2
xcut1 = boxM1.getXMin() + centering \
+ self.minEnclosure_metal1_cut1 + self.minWidth_cut1//2
trace( 101, '\tcutNumber = {0}\n'.format(cutNumber) )
for i in range(cutNumber):
trace( 101, '\t[{0}]\n'.format(i) )
Contact.create( net
, self.cut1
, int(xcut1)
, int(axisM2)
, int(self.minWidth_cut1)
, int(self.minWidth_cut1)
)
xcut1 += self.minWidth_cut1 + self.minSpacing_cut1
return
def scriptMain( **kw ):
editor = None
if 'editor' in kw and kw['editor']:
editor = kw['editor']
UpdateSession.open()
device = AllianceFramework.get().createCell( 'resistor' )
device.setTerminal( True )
t_1 = Net.create( device, 't1' )
t_1.setExternal( True )
t1 = device.getNet("t1")
doBreak( 1, 'Done building terminal 1 net')
t_2 = Net.create( device, 't2' )
t_2.setExternal( True )
t2 = device.getNet("t2")
doBreak( 1, 'Done building terminal 1 net')
if editor:
UpdateSession.close( )
editor.setCell ( device )
editor.fit ( )
UpdateSession.open ( )
nets = [t1,t2]
#(device, resistorType, resistance = 0, resDim = { "width" : 10, "length" : 0 }, direction = "vertical", bends = 0 ):
#resistor = Resistor( device, nets, "RPOLY2PH", 50, direction = "vertical" )
#resistor = Resistor( device, nets, "RPOLY2PH", 200, direction = "horizontal", resDim = { "width" : 0.8, "length" : 0 } ) #w >= 2 dogBone not possible in 0.35 um (used only in test)
#resistor = Resistor( device, nets, "RPOLY2PH", 800, direction = "vertical", resDim = { "width" : 0.8, "length" : 0 }, bends = 4 ) #w >= 2 dogBone not possible
#resistor = Resistor( device, nets, "RPOLYH", 4800, direction = "vertical", resDim = { "width" : 0.8, "length" : 0 } ) #w = 0.8 dogBone
#resistor = Resistor( device, nets, "RPOLYH", 48000, direction = "horizontal", resDim = { "width" : 0.8, "length" : 0 }, bends = 3 ) #w = 0.8 dogBone
#resistor = Resistor( device, nets, "RPOLY2PH", 200, direction = "horizontal") #RPOLY2PH normal
#resistor = Resistor( device, nets, "RPOLYH", 7000, direction = "horizontal", resDim = { "width" : 10, "length" : 0 }) #RPOLYH normal
#resistor = Resistor( device, nets, "RPOLYH", 20000, direction = "vertical", bends = 1, shape = 135 ) #RPOLYH snake
resistor = Resistor( device, nets, "RPOLY2PH", 2000, resDim = { "width" : 2.5, "length" : 0 }, direction = "vertical", bends = 1, shape = 90 ) #RPOLY2PH snake
abutmentBoxDim = resistor.create()
print("abutmentBoxDim",abutmentBoxDim)
AllianceFramework.get().saveCell( device, Catalog.State.Views )
return True