First integration of Resistors (straight & snake).
This commit is contained in:
parent
5ee4487d95
commit
e1389f501a
|
@ -1,5 +1,7 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
print "SOURCE CapacitorMatrix"
|
||||
|
||||
import sys
|
||||
from Hurricane import *
|
||||
from CRL import *
|
||||
|
@ -40,10 +42,11 @@ class CapacitorStack( CapacitorUnit ):
|
|||
|
||||
self.device = device
|
||||
self.capacitorType = capacitorType
|
||||
print("self.capacitorType0",self.capacitorType)
|
||||
self.matrixDim = { "columns" : matrixDim[1], "rows" : matrixDim[0] }
|
||||
self.unitCapDim = self.__computeCapDim__( unitCap , capacitorType )
|
||||
self.unitCapDim = self.__computeCapDim__( unitCap , capacitorType )
|
||||
|
||||
self.doMatrix = False
|
||||
self.doMatrix = False
|
||||
self.abutmentBox = Box()
|
||||
self.abutmentBoxPosition = { "XMin" : abutmentBoxPosition[0], "YMin" : abutmentBoxPosition[1] }
|
||||
self.nets = nets
|
||||
|
@ -59,7 +62,7 @@ class CapacitorStack( CapacitorUnit ):
|
|||
self.vRoutingTrack_width = 0
|
||||
|
||||
if self.__areInputDataOK__(capacitance) == True :
|
||||
if self.matchingMode == False :
|
||||
if self.matchingMode == False :
|
||||
self.compactCapDim = self.__computeCapDim__( capacitance[0] , capacitorType )
|
||||
|
||||
if unitCap == 0 :
|
||||
|
@ -115,10 +118,9 @@ class CapacitorStack( CapacitorUnit ):
|
|||
def __initMatchingMode__( self ) :
|
||||
|
||||
self.vRoutingTrack_width = max( self.minWidth_vRoutingTrack, 2*self.minEnclosure_vRoutingTrackCut + self.minWidth_vRoutingTrackCut,self.minWidth_hRoutingLayer_topPlate_cut + 2*self.minEnclosure_hRoutingLayer_topPlate_cut )
|
||||
[factor1 , factor2 ] = [ self.capacitorsNumber , (self.capacitorsNumber +1) ] if ( self.capacitorsNumber % 2 == 0 ) else [ self.capacitorsNumber +1 , self.capacitorsNumber +2 ]
|
||||
|
||||
# if self.dummyElement == True : [factor1 , factor2 ] = [factor1 + 1 , factor2 + 1 ]
|
||||
self.abutmentBox_spacing = factor1*self.vRoutingTrack_width + factor2*self.minSpacing_vRoutingTrack
|
||||
if ( self.capacitorsNumber % 2 == 0 ) : [factor1 , factor2 ] = [ self.capacitorsNumber , (self.capacitorsNumber +1) ]
|
||||
if ( self.capacitorsNumber % 2 != 0 ) : [factor1 , factor2 ] = [ self.capacitorsNumber +1 , self.capacitorsNumber +2 ]
|
||||
self.abutmentBox_spacing = factor1*self.vRoutingTrack_width + factor2*self.minSpacing_vRoutingTrack
|
||||
|
||||
return
|
||||
|
||||
|
@ -137,7 +139,8 @@ class CapacitorStack( CapacitorUnit ):
|
|||
|
||||
[ self.capacitance , self.unitCapDim ] = [ capacitance , self.compactCapDim ]
|
||||
|
||||
elif ( self.matrixDim.values() == [1,1] and not(CapacitorUnit.__isCapacitorUnitOK__( self, self.compactCapDim)) ): raise Error(1, '__init__(): Impossible to draw the capacitor, dimensions are either too large or too small, "%s".' % self.compactCapDim ) #com2 : use to physical
|
||||
elif ( self.matrixDim.values() == [1,1] and not(CapacitorUnit.__isCapacitorUnitOK__( self, self.compactCapDim)) ):
|
||||
raise Error(1, '__init__(): Impossible to draw the capacitor, dimensions are either too large or too small, "%s".' % self.compactCapDim ) #com2 : use to physical
|
||||
|
||||
elif ( self.matrixDim["columns"]>1 or self.matrixDim["rows"]>1) :
|
||||
|
||||
|
@ -300,14 +303,15 @@ class CapacitorStack( CapacitorUnit ):
|
|||
|
||||
[ matchingSchemeCapIds , capacitanceIds ] = [ list( numpy.unique(self.matchingScheme) ) , range(0,self.capacitorsNumber) ]
|
||||
if (self.matchingScheme != [] and set(matchingSchemeCapIds) == set(capacitanceIds) ) or (self.matchingScheme == [] and len(capacitance) == 1) :
|
||||
|
||||
print("len(self.nets)",len(self.nets))
|
||||
print("self.capacitorsNumber + 1",self.capacitorsNumber + 1)
|
||||
if (len(self.nets) == self.capacitorsNumber + 1 and self.dummyElement == False and self.dummyRing == True ) or (len(self.nets) == self.capacitorsNumber and self.dummyElement == False and self.dummyRing == False) or (len(self.nets) == self.capacitorsNumber and self.dummyElement == True and self.dummyRing == True) or (len(self.nets) == self.capacitorsNumber and self.dummyElement == True and self.dummyRing == False ):
|
||||
|
||||
if ( self.matchingMode == True and self.__isMatchingSchemeOK__() ) or ( self.matchingMode == False and self.matchingScheme == [] ):
|
||||
state = True
|
||||
else: raise Error(1, '__areInputDataOK__(): Please check compatibility of the entered parameters (Matching mode, matching scheme, capacitance). It must be either equal to (False, [], one capacitance value) or ( True, matching scheme, capacitance values as much as there are capacitor ids in matching scheme ). The entered parameters are (%s, %s, %s).' %(self.matchingMode, self.matchingScheme, capacitance) ) #com2 : tester
|
||||
|
||||
else : raise Error(1,'__areInputDataOK__() : Nets number is incompatible with number of capacitors to be drawn.')
|
||||
else : raise Error(1,'__areInputDataOK__() : Nets number, %s, is incompatible with number of capacitors to be drawn, %s.' %(self.netsNumber, self.capacitorsNumber))
|
||||
|
||||
else : raise Error(1, '__areInputDataOK__() : Please check compatibility between matching scheme elements, %s, and capacitance indexes, %s. They must be identical. Otherwise, when matching scheme is "False", capacitance indexes must be [0].' %(matchingSchemeCapIds, capacitanceIds) )
|
||||
|
||||
|
@ -384,11 +388,12 @@ class CapacitorStack( CapacitorUnit ):
|
|||
|
||||
def capacitorLine( self, dy, abutmentBox_spacing , matchingSchemeRowIndex = 0 ):
|
||||
|
||||
line = [ CapacitorUnit( self.device, self.unitCapacitance, self.capacitorType, [self.abutmentBoxPosition["XMin"], dy] ) ]
|
||||
print("self.capacitorType",self.capacitorType)
|
||||
line = [ CapacitorUnit( self.device, self.capacitorType, [self.abutmentBoxPosition["XMin"], dy], capacitance = self.unitCapacitance ) ]
|
||||
self.createElementInCapacitorLine( line, matchingSchemeRowIndex,0 )
|
||||
limit = self.matrixDim["columns"] + 2 if self.dummyRing == True else self.matrixDim["columns"]
|
||||
for j in range(1, limit ) :
|
||||
line.append( CapacitorUnit( self.device, self.unitCapacitance, self.capacitorType, [line[j-1].abutmentBox.getXMax() + abutmentBox_spacing, dy] ) )
|
||||
line.append( CapacitorUnit( self.device, self.capacitorType, [line[j-1].abutmentBox.getXMax() + abutmentBox_spacing, dy], capacitance = self.unitCapacitance ) )
|
||||
self.createElementInCapacitorLine( line, matchingSchemeRowIndex,j )
|
||||
|
||||
return line
|
||||
|
@ -430,18 +435,18 @@ class CapacitorStack( CapacitorUnit ):
|
|||
|
||||
def dummyLine( self, direction, dx, dy ):
|
||||
|
||||
dummyList = [ CapacitorUnit( self.device, self.unitCapacitance, self.capacitorType, [dx, dy] ) ]
|
||||
dummyList = [ CapacitorUnit( self.device, self.capacitorType, [dx, dy], capacitance = self.unitCapacitance ) ]
|
||||
dummyList[0].create( self.nets[-1][0], self.nets[-1][1] )
|
||||
|
||||
if direction == 'vertical':
|
||||
for i in range(1, self.matrixDim["rows"] + 2):
|
||||
dummyList.append( CapacitorUnit( self.device, self.unitCapacitance, self.capacitorType, [dx, dummyList[i-1].abutmentBox.getYMax() + self.abutmentBox_spacing] ) )
|
||||
dummyList.append( CapacitorUnit( self.device, self.capacitorType, [dx, dummyList[i-1].abutmentBox.getYMax() + self.abutmentBox_spacing], capacitance = self.unitCapacitance ) )
|
||||
dummyList[i].create(self.nets[-1][0], self.nets[-1][1])
|
||||
|
||||
elif direction == 'horizontal':
|
||||
for j in range(1, self.matrixDim["columns"] + 2):
|
||||
print('j',j)
|
||||
dummyList.append( CapacitorUnit( self.device, self.unitCapacitance, self.capacitorType, [dummyList[j-1].abutmentBox.getXMax() + self.abutmentBox_spacing, dy]) )
|
||||
dummyList.append( CapacitorUnit( self.device, self.capacitorType, [dummyList[j-1].abutmentBox.getXMax() + self.abutmentBox_spacing, dy], capacitance = self.unitCapacitance ) )
|
||||
dummyList[j].create(self.nets[-1][0], self.nets[-1][1])
|
||||
|
||||
else : raise Error(1,'dummyLine() : Direction must be either "horizontal" or "vertical".' %direction)
|
||||
|
@ -588,7 +593,7 @@ def ScriptMain( **kw ):
|
|||
editor.setCell( device )
|
||||
editor.fit()
|
||||
UpdateSession.open()
|
||||
nets = [[t0, b0]]# , [t1, b1], [t2, b2] ] # [t3, b3] ]
|
||||
nets = [[t0, b0] , [t1, b1] , [t2, b2] ] # [t3, b3] ]
|
||||
capacitorInstance = CapacitorStack( device, [750,750], 'MIMCap', [0,0], nets,unitCap = 93, matrixDim = [4,4], matchingMode = True, matchingScheme = [ [1,0,1,0] , [0,1,0,1] , [1,0,1,0] , [0,1,0,1] ], dummyRing = True)
|
||||
#capacitorInstance = CapacitorStack( device, [1488], 'MIMCap', [0,0], nets,unitCap = 93, matrixDim = [4,4], dummyRing = True)
|
||||
#capacitorInstance = CapacitorStack( device, {"C1" : 558, "C2" : 558, "C3" : 372}, 'MIMCap', [0,0], nets, unitCap = 93, matrixDim = [4,4], matchingMode = True, matchingScheme = [ ['C2','C1','C2','C1'] , ['C1','C2','C1','C2'] , ['C2','C1','C2','C1'] , ['C3','C3','C3','C3'] ])
|
||||
|
|
|
@ -10,7 +10,6 @@ import oroshi
|
|||
from CapacitorUnit import CapacitorUnit
|
||||
from CapacitorMatrix import CapacitorStack
|
||||
from CapacitorVRTracks import VerticalRoutingTracks
|
||||
#from collections import OrderedDict
|
||||
|
||||
|
||||
## Routs two matched capacitors, C1 and C2, drawn in a capacitor matrix. Connections are put in place with reference to a given matching scheme. Elementary capacitor units are connected to horizontal and vertical routeing tracks that represent top plates and bottom plates nets of C1 and C2 . Supported types of capacitors are Poly-Poly and Metal-Metal. Technologycal rules are provided by 350 nm AMS CMOS technology with three-four metal layers. Metal layers that are used for routeing are placed similarly to horziontal-vertical (HV) symbolic Alliance CAD tool routeer, where horizontal metal channels are drawn in metal 2 and the vertical ones are in metal 3. Given a matrix of dimensions \f$ R*C \f$, the total number of vertical tracks is \f$ 2C+2 \f$ equivalent to \f$ C+1 \f$ couples, ensuring that every elementary capacitor is positioned between four vertical tracks, two from each side. In fact, every adjacent couple of these tracks represent top plates and bottom plates of C1 or C2 as shown in Figure 1.
|
||||
|
@ -58,15 +57,16 @@ class RoutMatchedCapacitor( CapacitorUnit, CapacitorStack, VerticalRoutingTracks
|
|||
VerticalRoutingTracks.__init__( self, vRTInstance.capacitorInstance, vRTInstance.capacitor )
|
||||
|
||||
if self.dummyRing == True :
|
||||
|
||||
self.capacitor = [vRTInstance.capacitor[1][1:len(vRTInstance.capacitor[1])-1]]
|
||||
|
||||
for i in range(2,self.matrixDim["rows"]+1):
|
||||
self.capacitor.append(vRTInstance.capacitor[i][1:len(vRTInstance.capacitor[1])-1])
|
||||
self.dummyRingCapacitor = [ vRTInstance.capacitor[0], vRTInstance.capacitor[-1] ]
|
||||
|
||||
self.dummyRingCapacitor = [ vRTInstance.capacitor[0], vRTInstance.capacitor[-1] ]
|
||||
self.dummyRingVRLayersDict = {}
|
||||
|
||||
self.hRoutingLayer_width = 0
|
||||
self.hRoutingTrack_width = vRTInstance.hRoutingTrack_width #gethRoutingTrack_width()
|
||||
self.hRoutingTrack_width = vRTInstance.hRoutingTrack_width
|
||||
self.minSpacing_hRoutingTrack = 0
|
||||
self.minimumPosition = 0
|
||||
self.maximumPosition = 0
|
||||
|
@ -276,7 +276,7 @@ class RoutMatchedCapacitor( CapacitorUnit, CapacitorStack, VerticalRoutingTracks
|
|||
abutmentBoxXMin = self.capacitorInstance.computeAbutmentBoxDimensions( self.abutmentBox_spacing )["XMin"]
|
||||
abutmentBoxXMax = abutmentBoxXMin + self.capacitorInstance.computeAbutmentBoxDimensions( self.abutmentBox_spacing )["width" ]
|
||||
|
||||
bondingBoxDimensions["XMin" ] = self.vRoutingTrackXCenter[0 ]["t1"] - self.vRoutingTrack_width/2
|
||||
bondingBoxDimensions["XMin" ] = self.vRoutingTrackXCenter[0]["t1"] - self.vRoutingTrack_width/2
|
||||
|
||||
if self.capacitorsNumber % 2 == 0 :
|
||||
factor = self.capacitorsNumber
|
||||
|
@ -758,7 +758,7 @@ def ScriptMain( **kw ):
|
|||
capWithVRT.create()
|
||||
|
||||
routedCap = RoutMatchedCapacitor( capWithVRT )
|
||||
surface = routedCap.route( )
|
||||
surface = routedCap.route(True)
|
||||
print('routeMatchedCap bbMode', surface)
|
||||
|
||||
AllianceFramework.get().saveCell( Device, Catalog.State.Views )
|
||||
|
|
|
@ -2,16 +2,23 @@
|
|||
|
||||
import sys
|
||||
import numpy
|
||||
from Hurricane import *
|
||||
from CRL import *
|
||||
from math import sqrt, ceil
|
||||
from Hurricane import *
|
||||
from CRL import *
|
||||
from math import sqrt, ceil
|
||||
import helpers
|
||||
from helpers.io import ErrorMessage as Error
|
||||
from helpers import trace
|
||||
from helpers.io import ErrorMessage as Error
|
||||
from helpers import trace
|
||||
import oroshi
|
||||
|
||||
def toDbU ( l ): return DbU.fromPhysical( l, DbU.UnitPowerMicro )
|
||||
def toDbU ( l ): return DbU.fromPhysical( l, DbU.UnitPowerMicro )
|
||||
def toPhY ( l ): return DbU.toPhysical ( l, DbU.UnitPowerMicro )
|
||||
|
||||
def doBreak( level, message ):
|
||||
UpdateSession.close()
|
||||
Breakpoint.stop( level, message )
|
||||
UpdateSession.open()
|
||||
|
||||
helpers.staticInitialization( True )
|
||||
|
||||
## Draws a capacitor of type Poly-Poly or Metal-Metal in 350 nm AMS CMOS technology.
|
||||
# PIP and MIM capacitors are the result of surface superposition between poly1 and poly2 or metal2 and metalcap layers, respectively.
|
||||
|
@ -23,6 +30,9 @@ class CapacitorUnit():
|
|||
|
||||
rules = oroshi.getRules()
|
||||
|
||||
|
||||
|
||||
|
||||
## This is the class constructor. Few of the class attributes final values are computed in this level. Most of attributes are only initialized to zero or empty values. Then, it is computed in dedicated class method. Input parameters are :
|
||||
# \param device Hurricane AMS device into which layout is drawn.
|
||||
# \param capacitance Capacitor value, expressed in \f$ femto Farad (fF) \f$.
|
||||
|
@ -50,13 +60,17 @@ class CapacitorUnit():
|
|||
# \param minheight_topPlatecut Minimum height of cuts for top plate connection to other metal layer.
|
||||
# \param topCutLineNumber Maximum possible number cuts to be drawn for top plate's connection.
|
||||
# \param bottomCutLineNumber Maximum possible number cuts to be drawn for top plate's connection.
|
||||
#
|
||||
# \remark Abutment box must be defined as an attribute because the position of dummy capacitor in \c NonUnitCapacitor class must be precisely defined.
|
||||
|
||||
|
||||
def __init__( self, device, capacitance, capacitorType, abutmentBoxPosition ):
|
||||
def __init__( self, device, capacitorType, abutmentBoxPosition, capacitance = 0, capDim = {} ):
|
||||
|
||||
self.device = device
|
||||
self.capacitorType = capacitorType
|
||||
self.capDim = self.__computeCapDim__( capacitance, capacitorType )
|
||||
# self.capDim = self.__computeCapDim__( capacitance, capacitorType )
|
||||
self.enclosure_botPlate_abtBox = 0
|
||||
|
||||
self.__initCapDim__( capacitance, capDim )
|
||||
|
||||
self.abutmentBoxDict = { "XMin" : abutmentBoxPosition[0], "YMin" : abutmentBoxPosition[1] }
|
||||
self.abutmentBox = Box ()
|
||||
|
@ -72,29 +86,54 @@ class CapacitorUnit():
|
|||
self.topCutLineDict = {}
|
||||
self.topPlateRLayerDict = {}
|
||||
self.bottomPlateRLayerDict = {}
|
||||
self.topCutLineNumber = {}
|
||||
|
||||
self.enclosure_botPlate_topPlate = 0
|
||||
self.minheight_topPlatecut = 0
|
||||
self.topCutLineNumber = 0
|
||||
self.bottomCutLineNumber = 0
|
||||
|
||||
# self.nets = { "bNet" : bNet, "tNet" : tNet }
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def __initCapDim__( self, capacitance, capDim ):
|
||||
|
||||
if capacitance != 0 and capDim.values() != [] :
|
||||
if self.__computeCapacitance__( capDim, self.capacitorType ) == capacitance :
|
||||
self.capDim = capDim
|
||||
else : raise Error(1,'__initCapDim__() : Please check compatibility between capacitance value, %s, and the given capacitor dimensions, %s.' %(capacitance, capDim))
|
||||
|
||||
elif capacitance == 0 and capDim.values() != [] :
|
||||
self.capDim = capDim
|
||||
capacitance = self.__computeCapacitance__( capDim, self.capacitorType )
|
||||
print("capacitance", capacitance)
|
||||
|
||||
elif capacitance != 0 and capDim.values() == [] :
|
||||
print("self.capacitorType ",self.capacitorType )
|
||||
self.capDim = self.__computeCapDim__( capacitance, self.capacitorType )
|
||||
print("self.capDim",self.capDim)
|
||||
|
||||
else : raise Error(1, '__initCapDim__() : Invalid capacitance and/or capacitance dimensions (%s, %s). Please provide at least one valid parameter.'
|
||||
%(capacitance, capDim))
|
||||
|
||||
return
|
||||
|
||||
|
||||
## Sets the area and perimeter capacitances as specified in 350 nm AMS technology and according to \c capacitorType (MIM or PIP).
|
||||
# \return a list containing the area and perimeter capacitances.
|
||||
# \remarks An exception is raised if the entered capacitor type is unknown.
|
||||
|
||||
def __setCapacitorPerUnit__( self, capacitorType ) :
|
||||
|
||||
print("self.capacitorType",self.capacitorType)
|
||||
if capacitorType == 'MIMCap':
|
||||
[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ] = [ CapacitorUnit.rules.MIMCap, CapacitorUnit.rules.MIMPerimeterCap ]
|
||||
[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ] = [ CapacitorUnit.rules.MIMCap
|
||||
, CapacitorUnit.rules.MIMPerimeterCap
|
||||
]
|
||||
|
||||
elif capacitorType == 'PIPCap':
|
||||
[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ] = [ CapacitorUnit.rules.PIPCap, CapacitorUnit.rules.PIPPerimeterCap ]
|
||||
[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ] = [ CapacitorUnit.rules.PIPCap
|
||||
, CapacitorUnit.rules.PIPPerimeterCap
|
||||
]
|
||||
|
||||
else:
|
||||
raise Error( 1, 'setCapacitorPerUnit() : Unsupported capacitor type : %s.' % capacitorType )
|
||||
|
@ -107,33 +146,51 @@ class CapacitorUnit():
|
|||
# \remark The capacitor is square. Thus, length and width are equal.
|
||||
|
||||
def __computeCapDim__( self, capacitance, capacitorType ) :
|
||||
print("capacitorType",capacitorType)
|
||||
[a, b, c ] = [ self.__setCapacitorPerUnit__( capacitorType )[0]
|
||||
, 4*self.__setCapacitorPerUnit__( capacitorType )[1]
|
||||
, - capacitance
|
||||
]
|
||||
|
||||
[a, b, c ] = [ self.__setCapacitorPerUnit__( capacitorType )[0], 4*self.__setCapacitorPerUnit__( capacitorType )[1], -capacitance ]
|
||||
delta = (b**2) - 4*a*c
|
||||
c1 = ( -b + sqrt(delta) ) / (2*a)
|
||||
|
||||
return { "width" : toDbU(c1), "height" : toDbU(c1) }
|
||||
|
||||
|
||||
def __computeCapacitance__( self, capDim, capacitorType ):
|
||||
|
||||
[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ] = self.__setCapacitorPerUnit__( capacitorType )
|
||||
areaCapacitance = toPhY(capDim["width"]) * toPhY(capDim["height"]) *areaCapacitorPerUnit
|
||||
perimeterCapacitance = ( toPhY(capDim["width"]) + toPhY(capDim["height"]) )*perimeterCapacitorPerUnit
|
||||
capacitance = areaCapacitance + perimeterCapacitance
|
||||
|
||||
return capacitance
|
||||
|
||||
|
||||
## Checks if the computed capacitor dimensions exceed or are less than maximum and minimum limits, respectively, as specified in technology rules.
|
||||
## \return \c True if all rules are respected.
|
||||
# \remark Maximum poly2 layer dimensions for PIP capacitor are not specified in technology rules. Thus, only minimum limit condition is checked.
|
||||
|
||||
def __isCapacitorUnitOK__( self, capDim ):
|
||||
def __isCapacitorUnitOK__( self, capDim ):
|
||||
|
||||
if ( self.capacitorType == 'MIMCap' and CapacitorUnit.getMinimumCapWidth( self ) < capDim["width"] < self.getMaximumCapWidth()) or self.capacitorType == 'PIPCap' and self.getMinimumCapWidth() < capDim["width"]:
|
||||
return True
|
||||
state = False
|
||||
if ( self.capacitorType == 'MIMCap' and CapacitorUnit.getMinimumCapWidth( self ) < capDim["width"] < self.getMaximumCapWidth() and CapacitorUnit.getMinimumCapWidth( self ) < capDim["height"] < self.getMaximumCapWidth() ) or ( self.capacitorType == 'PIPCap' and self.getMinimumCapWidth() < capDim["width"] and self.getMinimumCapWidth() < capDim["height"] ) :
|
||||
state = True
|
||||
|
||||
return state
|
||||
|
||||
|
||||
|
||||
|
||||
## Redefines technological rules as object attributes of the class. For example, class attributes \c CapacitorUnit.rules.minWidth_metcap becomes \c self.minWidth_topPlate and \c CapacitorUnit.rules.minSpacing_cut2_metcap becomes \c self.minSpacing_botPlateCut_topPlat. This obviously helps using shorter names for the attributes. \c __setattr__() is declared in all \c Capacitor \c Generator classes, also in Hurricane and oroshi databases.
|
||||
|
||||
def __setattr__( self, attribute, value ):
|
||||
|
||||
def __setattr__( self, attribute, value ) :
|
||||
|
||||
self.__dict__[attribute] = value
|
||||
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
|
||||
## Selects technological rules according to the capacitor type.
|
||||
|
@ -245,8 +302,8 @@ class CapacitorUnit():
|
|||
|
||||
def getLayers( self ):
|
||||
|
||||
technology = DataBase.getDB().getTechnology()
|
||||
layerDict = {}
|
||||
technology = DataBase.getDB().getTechnology()
|
||||
layerDict = {}
|
||||
|
||||
if self.capacitorType == 'MIMCap':
|
||||
|
||||
|
@ -272,27 +329,29 @@ class CapacitorUnit():
|
|||
|
||||
## When bonding box mode is activated, the function draws all layout physical layers of the capacitor after checking its dimensions. All functions are excecuted in a new Update Session. In the contrary, only an exact estimation of layout dimensions is given. An error is raised when dimensions reach technological limits for MIM and PIP capacitors or when \c bbMode parameters is other than \c True or \c False.
|
||||
#
|
||||
# \param ( tNet , bNet ) nets of top and bottom plates, respectively
|
||||
# \param ( t , b ) nets of top and bottom plates, respectively
|
||||
# \param bbMode activates bonding box dimensions computing when set to \c True
|
||||
def create( self, tNet, bNet, bbMode = False ):
|
||||
#
|
||||
|
||||
def create( self, t, b, bbMode = False, vEnclosure_botPlate_abtBox = None, hEnclosure_botPlate_abtBox = None ):
|
||||
|
||||
UpdateSession.open()
|
||||
|
||||
abutmentBoxDimensions = None
|
||||
self.setRules ()
|
||||
self.setRules ()
|
||||
|
||||
if self.__isCapacitorUnitOK__( self.capDim ) == True :
|
||||
|
||||
self.computeDimensions ( self.capDim )
|
||||
self.computeDimensions ( self.capDim, vEnclosure_botPlate_abtBox, hEnclosure_botPlate_abtBox )
|
||||
self.drawAbutmentBox ()
|
||||
self.device.setAbutmentBox( self.abutmentBox )
|
||||
#self.device.setAbutmentBox( self.abutmentBox )
|
||||
|
||||
if bbMode == True :
|
||||
abutmentBoxDimensions = self.abutmentBoxDict
|
||||
|
||||
elif bbMode == False :
|
||||
layerDict = self.getLayers()
|
||||
self.drawCapacitor( layerDict, tNet, bNet )
|
||||
self.drawCapacitor( layerDict, t, b )
|
||||
|
||||
else :raise Error(1, 'drawCapacitor(): The bonding box mode parameter, "bbMode" must be either True or False : %s.' %bbMode )
|
||||
|
||||
|
@ -306,16 +365,17 @@ class CapacitorUnit():
|
|||
|
||||
## Draws all layout physicial layers of the capacitor.
|
||||
#
|
||||
# \param layerDict a dictionary containing a description of the required physical layers according to capacitor type
|
||||
# \param ( tNet , bNet ) nets of top and bottom plates, respectively
|
||||
def drawCapacitor( self, layerDict, tNet, bNet ):
|
||||
# \param layerDict a dictionary containing a description of the required physical layers according to capacitor type
|
||||
# \param ( t , b ) nets of top and bottom plates, respectively
|
||||
#
|
||||
|
||||
def drawCapacitor( self, layerDict, t, b ):
|
||||
|
||||
self.bottomPlateBox = self.drawOnePlate( layerDict["bottomPlateLayer" ] , bNet , self.bottomPlateBoxDict )
|
||||
self.topPlateBox = self.drawOnePlate( layerDict["topPlateLayer" ] , tNet , self.topPlateBoxDict )
|
||||
self.drawBottomPlateCut ( layerDict["topBottomcutsLayer"] , bNet )
|
||||
self.drawTopPlateCut ( layerDict["topBottomcutsLayer"] , tNet )
|
||||
self.drawRoutingLayers ( layerDict["bottomPlateRLayer" ] , layerDict["topPlateRLayer"] , tNet , bNet )
|
||||
self.bottomPlateBox = self.drawOnePlate( layerDict["bottomPlateLayer" ] , b , self.bottomPlateBoxDict )
|
||||
self.topPlateBox = self.drawOnePlate( layerDict["topPlateLayer" ] , t , self.topPlateBoxDict )
|
||||
self.drawBottomPlateCut ( layerDict["topBottomcutsLayer"] , b )
|
||||
self.drawTopPlateCut ( layerDict["topBottomcutsLayer"] , t )
|
||||
self.drawRoutingLayers ( layerDict["bottomPlateRLayer" ] , layerDict["topPlateRLayer"] , t , b )
|
||||
|
||||
return
|
||||
|
||||
|
@ -329,16 +389,22 @@ class CapacitorUnit():
|
|||
# - ordinate of the same two cuts.
|
||||
#
|
||||
# Given parameters described above, it is possible to draw the entire lines of cuts on both sides of bottom plate using \c cutLine function.
|
||||
#
|
||||
|
||||
def computeBottomPlateCuts( self ):
|
||||
|
||||
self.bottomCutLineNumber = self.cutMaxNumber( self.bottomPlateBoxDict["height"], self.minheight_topPlatecut, self.minSpacingOnBotPlate_cut, self.minEnclo_botPlate_botPlateCut )
|
||||
self.bottomCutLineNumber = self.cutMaxNumber( self.bottomPlateBoxDict["height"]
|
||||
, self.minheight_topPlatecut
|
||||
, self.minSpacingOnBotPlate_cut
|
||||
, self.minEnclo_botPlate_botPlateCut
|
||||
)
|
||||
enclosure_botPlate_botPlateCut = ( self.bottomPlateBoxDict["height"] - (self.bottomCutLineNumber * self.minheight_topPlatecut + (self.bottomCutLineNumber -1) * self.minSpacingOnBotPlate_cut) )/2
|
||||
|
||||
self.cutLeftLineDict ["XMin"] = self.topPlateBoxDict["XMin"] - self.minSpacing_botPlateCut_topPlate - self.minWidth_topPlatecut/2
|
||||
self.cutRightLineDict["XMin"] = self.topPlateBoxDict["XMin"] + self.topPlateBoxDict["width"] + self.minSpacing_botPlateCut_topPlate + self.minWidth_topPlatecut/2
|
||||
self.cutLeftLineDict ["XMin"] = self.topPlateBoxDict ["XMin" ] - self.minSpacing_botPlateCut_topPlate - self.minWidth_topPlatecut/2
|
||||
self.cutRightLineDict["XMin"] = self.topPlateBoxDict ["XMin" ] + self.topPlateBoxDict["width"] + self.minSpacing_botPlateCut_topPlate + self.minWidth_topPlatecut/2
|
||||
|
||||
self.cutLeftLineDict ["YMin"] = self.bottomPlateBoxDict["YMin"] + self.minheight_topPlatecut/2 + enclosure_botPlate_botPlateCut
|
||||
self.cutRightLineDict["YMin"] = self.cutLeftLineDict["YMin"]
|
||||
self.cutLeftLineDict ["YMin"] = self.bottomPlateBoxDict["YMin" ] + self.minheight_topPlatecut/2 + enclosure_botPlate_botPlateCut
|
||||
self.cutRightLineDict["YMin"] = self.cutLeftLineDict ["YMin" ]
|
||||
|
||||
return
|
||||
|
||||
|
@ -351,25 +417,37 @@ class CapacitorUnit():
|
|||
# - ordinate of the same two cuts.
|
||||
#
|
||||
# Given parameters described above, it is possible to draw the entire lines of cuts on both sides of bottom plate using \c cutLine function.
|
||||
|
||||
def computeTopPlateCuts( self ):
|
||||
|
||||
self.topCutLineNumber = self.cutMaxNumber( self.topPlateBoxDict["height"], self.minheight_topPlatecut, self.minSpacingOnTopPlate_cut, self.minEnclo_topPlate_topPlateCut )
|
||||
enclosure_topPlate_topPlateCut = ( self.topPlateBoxDict["height"] - (self.topCutLineNumber *self.minheight_topPlatecut + (self.topCutLineNumber -1)*self.minSpacingOnTopPlate_cut) )/2
|
||||
|
||||
enclosure_topPlate_topPlateCut = {}
|
||||
self.topCutLineNumber["vertical"] = self.cutMaxNumber( self.topPlateBoxDict["height"]
|
||||
, self.minheight_topPlatecut
|
||||
, self.minSpacingOnTopPlate_cut
|
||||
, self.minEnclo_topPlate_topPlateCut
|
||||
)
|
||||
enclosure_topPlate_topPlateCut["vertical"] = ( self.topPlateBoxDict["height"] - (self.topCutLineNumber["vertical"] *self.minheight_topPlatecut + (self.topCutLineNumber["vertical"] -1)*self.minSpacingOnTopPlate_cut) )/2
|
||||
|
||||
if self.capacitorType == 'MIMCap':
|
||||
|
||||
self.cut2MatrixDict[ "Width" ] = (self.topCutLineNumber - 2)*self.minWidth_topPlatecut + (self.topCutLineNumber - 1) * self.minSpacingOnTopPlate_cut
|
||||
cut2MatrixAttribute = ["XMin", "YMin" ]
|
||||
topPlateBoxCordinates = [self.topPlateBoxDict["XMin"], self.topPlateBoxDict["YMin"]]
|
||||
self.topCutLineNumber["horizontal"] = self.cutMaxNumber( self.topPlateBoxDict["width"]
|
||||
, self.minWidth_topPlatecut
|
||||
, self.minSpacingOnTopPlate_cut
|
||||
, self.minEnclo_topPlate_topPlateCut
|
||||
)
|
||||
enclosure_topPlate_topPlateCut["horizontal"] = ( self.topPlateBoxDict["width"] - (self.topCutLineNumber["horizontal"] *self.minheight_topPlatecut + (self.topCutLineNumber["horizontal"] -1)*self.minSpacingOnTopPlate_cut) )/2
|
||||
|
||||
self.cut2MatrixDict [ "Width" ] = (self.topCutLineNumber["horizontal"]- 2)*self.minWidth_topPlatecut + (self.topCutLineNumber["horizontal"] - 1) * self.minSpacingOnTopPlate_cut
|
||||
[ cut2MatrixAttribute , enclosure_attribute ] = [ ["XMin", "YMin" ] , [ "horizontal" , "vertical" ] ]
|
||||
topPlateBoxCordinates = [self.topPlateBoxDict["XMin"], self.topPlateBoxDict["YMin"]]
|
||||
|
||||
for i in range(2):
|
||||
topPlateCutTab = [ self.minWidth_topPlatecut, self.minheight_topPlatecut ]
|
||||
self.cut2MatrixDict[ cut2MatrixAttribute[i] ] = topPlateBoxCordinates[i] + topPlateCutTab[i] /2 + enclosure_topPlate_topPlateCut
|
||||
topPlateCutTab = [ self.minWidth_topPlatecut , self.minheight_topPlatecut ]
|
||||
self.cut2MatrixDict[ cut2MatrixAttribute[i] ] = topPlateBoxCordinates[i] + topPlateCutTab[i] /2 + enclosure_topPlate_topPlateCut[enclosure_attribute[i]]
|
||||
|
||||
elif self.capacitorType == 'PIPCap':
|
||||
self.topCutLineDict["XMin"] = self.topPlateBoxDict["XMin"] + self.topPlateBoxDict["width"] - self.minEnclo_topPlate_topPlateCut - self.minWidth_topPlatecut/2
|
||||
self.topCutLineDict["YMin"] = self.topPlateBoxDict["YMin"] + self.minheight_topPlatecut/2 + enclosure_topPlate_topPlateCut
|
||||
self.topCutLineDict["YMin"] = self.topPlateBoxDict["YMin"] + self.minheight_topPlatecut/2 + enclosure_topPlate_topPlateCut["vertical"]
|
||||
|
||||
else :
|
||||
raise Error( 1, 'computeTopPlateCuts() : Unsupported capacitor type : %s. Cuts cannot be drawn. ' % self.capacitorType )
|
||||
|
@ -378,23 +456,31 @@ class CapacitorUnit():
|
|||
return
|
||||
|
||||
|
||||
|
||||
def computeRoutingLayersDimensions( self ):
|
||||
|
||||
if self.capacitorType == 'MIMCap' :
|
||||
|
||||
self.cut2MatrixDict ["XMax"] = self.cut2MatrixDict["XMin"] + self.cut2MatrixDict["Width"] + self.minWidth_topPlatecut
|
||||
[ topmetalXMin,topmetalXMax ] = [ self.cut2MatrixDict["XMin"] - self.minEnclo_topPlateRMetal_topPlateCut - self.minWidth_topPlatecut/2, self.cut2MatrixDict["XMax"] + self.minEnclo_topPlateRMetal_topPlateCut + self.minWidth_topPlatecut/2]
|
||||
[ width_topMetal, width_bottomMetal ] = [ topmetalXMax - topmetalXMin, max( self.minWidth_botRMetal, (self.minWidth_botPlatecut + 2*self.minEnclo_botPlateRMetal_botPlateCut) ) ]
|
||||
[ topmetalXMin,topmetalXMax ] = [ self.cut2MatrixDict["XMin"] - self.minEnclo_topPlateRMetal_topPlateCut - self.minWidth_topPlatecut/2
|
||||
, self.cut2MatrixDict["XMax"] + self.minEnclo_topPlateRMetal_topPlateCut + self.minWidth_topPlatecut/2
|
||||
]
|
||||
[ width_topMetal, width_bottomMetal ] = [ topmetalXMax - topmetalXMin
|
||||
, max( self.minWidth_botRMetal, (self.minWidth_botPlatecut + 2*self.minEnclo_botPlateRMetal_botPlateCut) )
|
||||
]
|
||||
topMetalXCenter = self.abutmentBoxDict["XMin"] + self.abutmentBoxDict["width"]/2
|
||||
|
||||
elif self.capacitorType == 'PIPCap' :
|
||||
|
||||
topMetalXCenter = self.topCutLineDict["XMin"]
|
||||
width_topMetal = max( self.minWidth_botRMetal, (self.minWidth_topPlatecut+ 2*self.minEnclo_topPlateRMetal_topPlateCut), ( self.minWidth_routingTrackcut +2*self.minEnclo_routingTrackMetal_cut) )
|
||||
width_topMetal = max( self.minWidth_botRMetal
|
||||
, (self.minWidth_topPlatecut + 2*self.minEnclo_topPlateRMetal_topPlateCut)
|
||||
, ( self.minWidth_routingTrackcut + 2*self.minEnclo_routingTrackMetal_cut)
|
||||
)
|
||||
width_bottomMetal = width_topMetal
|
||||
|
||||
else :
|
||||
raise Error( 1, 'drawRoutingLayers() : Unsupported capacitor type : %s. Routing layers parameters cannot be computed. ' % self.capacitorType ) #com verirfy the two next lines are after else or before
|
||||
raise Error( 1, 'computeRoutingLayersDimensions() : Unsupported capacitor type : %s. Routing layers parameters cannot be computed. ' % self.capacitorType )
|
||||
|
||||
[ dySourceTop , dyTargetTop ] = [ self.bottomPlateBoxDict["YMin"], self.topPlateBoxDict["YMin"] + self.topPlateBoxDict["height"] ]
|
||||
[ dySourceBottom, dyTargetBottom ] = [ self.bottomPlateBoxDict["YMin"], self.bottomPlateBoxDict["YMin"]+self.bottomPlateBoxDict["height"] ]
|
||||
|
@ -405,15 +491,31 @@ class CapacitorUnit():
|
|||
return
|
||||
|
||||
|
||||
def setBottomPlateAbtBoxEnclosure( self, vEnclosure_botPlate_abtBox, hEnclosure_botPlate_abtBox ):
|
||||
|
||||
def computeAbutmentBoxDimensions( self, capDim ) :
|
||||
if vEnclosure_botPlate_abtBox == None : self.vEnclosure_botPlate_abtBox = self.minSpacing_botPlate
|
||||
elif vEnclosure_botPlate_abtBox >= toPhY(self.minSpacing_botPlate) : self.vEnclosure_botPlate_abtBox = toDbU(vEnclosure_botPlate_abtBox)
|
||||
else :
|
||||
raise Error(1,'setBottomPlateAbtBoxEnclosure() : Bottom plate vertical enclosure in abutment box must be equal or higher than the minimal limit %s um.'
|
||||
%toPhY(self.minSpacing_botPlate))
|
||||
|
||||
if hEnclosure_botPlate_abtBox == None : self.hEnclosure_botPlate_abtBox = self.minSpacing_botPlate
|
||||
elif hEnclosure_botPlate_abtBox >= toPhY(self.minSpacing_botPlate) : self.hEnclosure_botPlate_abtBox = toDbU(hEnclosure_botPlate_abtBox)
|
||||
else :
|
||||
raise Error(1,'setBottomPlateAbtBoxEnclosure() : Bottom plate horizontal enclosure in abutment box must be equal or higher than the minimal limit %s um.' %toPhY(self.minSpacing_botPlate))
|
||||
|
||||
return
|
||||
|
||||
|
||||
self.enclosure_botPlate_topPlate = self.minEnclo_botPlate_botPlateCut + self.minWidth_topPlatecut + self.minSpacing_botPlateCut_topPlate
|
||||
abutmentBoxDimensions = {}
|
||||
for key in capDim.keys():
|
||||
abutmentBoxDimensions[key] = 2*self.enclosure_botPlate_topPlate + capDim[key] + 2*self.minSpacing_botPlate
|
||||
abutmentBoxDimensions["surface"] = numpy.prod(abutmentBoxDimensions.values())
|
||||
|
||||
def computeAbutmentBoxDimensions( self, capDim, vEnclosure_botPlate_abtBox = None, hEnclosure_botPlate_abtBox = None ) :
|
||||
|
||||
self.setBottomPlateAbtBoxEnclosure(vEnclosure_botPlate_abtBox, hEnclosure_botPlate_abtBox)
|
||||
self.enclosure_botPlate_topPlate = self.minEnclo_botPlate_botPlateCut + self.minWidth_topPlatecut + self.minSpacing_botPlateCut_topPlate
|
||||
abutmentBoxDimensions = {}
|
||||
abutmentBoxDimensions["width" ] = 2*self.enclosure_botPlate_topPlate + capDim["width" ] + 2*self.hEnclosure_botPlate_abtBox
|
||||
abutmentBoxDimensions["height" ] = 2*self.enclosure_botPlate_topPlate + capDim["height"] + 2*self.vEnclosure_botPlate_abtBox
|
||||
#abutmentBoxDimensions["surface"] = numpy.prod(abutmentBoxDimensions.values())
|
||||
|
||||
return abutmentBoxDimensions
|
||||
|
||||
|
@ -422,31 +524,34 @@ class CapacitorUnit():
|
|||
|
||||
def drawAbutmentBox( self ):
|
||||
|
||||
self.abutmentBox = Box(self.abutmentBoxDict["XMin"],self.abutmentBoxDict["YMin"],self.abutmentBoxDict["width"]+self.abutmentBoxDict["XMin"],self.abutmentBoxDict["height"]+self.abutmentBoxDict["YMin"])
|
||||
|
||||
self.abutmentBox = Box(self.abutmentBoxDict["XMin" ]
|
||||
,self.abutmentBoxDict["YMin" ]
|
||||
,self.abutmentBoxDict["width" ] + self.abutmentBoxDict["XMin"]
|
||||
,self.abutmentBoxDict["height"] + self.abutmentBoxDict["YMin"]
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
def computeOnePlateBoxDimensions( self, inputBoxDimensions, enclosure ):
|
||||
def computeOnePlateBoxDimensions( self, inputBoxDimensions, vEnclosure, hEnclosure ):
|
||||
|
||||
outputboxDimensions = {}
|
||||
outputboxDimensions["XMin" ] = inputBoxDimensions["XMin" ] + enclosure
|
||||
outputboxDimensions["YMin" ] = inputBoxDimensions["YMin" ] + enclosure
|
||||
outputboxDimensions["width" ] = inputBoxDimensions["width" ] - 2*enclosure
|
||||
outputboxDimensions["height"] = inputBoxDimensions["height"] - 2*enclosure
|
||||
outputboxDimensions["XMin" ] = inputBoxDimensions["XMin" ] + hEnclosure
|
||||
outputboxDimensions["YMin" ] = inputBoxDimensions["YMin" ] + vEnclosure
|
||||
outputboxDimensions["width" ] = inputBoxDimensions["width" ] - 2*hEnclosure
|
||||
outputboxDimensions["height"] = inputBoxDimensions["height"] - 2*vEnclosure
|
||||
|
||||
return outputboxDimensions
|
||||
|
||||
|
||||
|
||||
def computeDimensions( self, capDim ):
|
||||
def computeDimensions( self, capDim, vEnclosure, hEnclosure ):
|
||||
|
||||
abutmentBoxDimensions = self.computeAbutmentBoxDimensions(capDim)
|
||||
abutmentBoxDimensions = self.computeAbutmentBoxDimensions(capDim, vEnclosure, hEnclosure )
|
||||
for key in abutmentBoxDimensions.keys():
|
||||
self.abutmentBoxDict[key] = abutmentBoxDimensions[key]
|
||||
|
||||
self.bottomPlateBoxDict = self.computeOnePlateBoxDimensions( self.abutmentBoxDict , self.minSpacing_botPlate )
|
||||
self.topPlateBoxDict = self.computeOnePlateBoxDimensions( self.bottomPlateBoxDict, self.enclosure_botPlate_topPlate )
|
||||
self.bottomPlateBoxDict = self.computeOnePlateBoxDimensions( self.abutmentBoxDict , self.vEnclosure_botPlate_abtBox, self.hEnclosure_botPlate_abtBox )
|
||||
self.topPlateBoxDict = self.computeOnePlateBoxDimensions( self.bottomPlateBoxDict, self.enclosure_botPlate_topPlate, self.enclosure_botPlate_topPlate )
|
||||
self.computeBottomPlateCuts()
|
||||
self.computeTopPlateCuts()
|
||||
self.computeRoutingLayersDimensions()
|
||||
|
@ -456,19 +561,13 @@ class CapacitorUnit():
|
|||
## Draws the top or bottom plate through inflation of the Box under it. These boxes are the abutment box in the case of the bottom plate and the bottom plate's box in the case of the top plate. This function also creates a a net for the drawn plate and sets it as external.
|
||||
# \return The drawn box.
|
||||
|
||||
#def drawOnePlate( self, layer, net, inputPlateBox, depth ):
|
||||
|
||||
# outputPlateBox = Box( inputPlateBox.getXMin(), inputPlateBox.getYMin(), inputPlateBox.getXMax(), inputPlateBox.getYMax() ).inflate( -depth )
|
||||
# platePad = Pad.create( net, layer, outputPlateBox )
|
||||
# NetExternalComponents.setExternal( platePad )
|
||||
# return outputPlateBox
|
||||
|
||||
|
||||
def drawOnePlate( self, layer, net, boxDimensions) :
|
||||
|
||||
outputPlateBox = Box( boxDimensions["XMin"], boxDimensions["YMin"], boxDimensions["XMin"] + boxDimensions["width"], boxDimensions["YMin"] + boxDimensions["height"] )
|
||||
print("outputPlate",outputPlateBox)
|
||||
print("net",net)
|
||||
outputPlateBox = Box( boxDimensions["XMin"]
|
||||
, boxDimensions["YMin"]
|
||||
, boxDimensions["XMin"] + boxDimensions["width" ]
|
||||
, boxDimensions["YMin"] + boxDimensions["height"]
|
||||
)
|
||||
platePad = Pad.create( net, layer, outputPlateBox )
|
||||
NetExternalComponents.setExternal( platePad )
|
||||
|
||||
|
@ -478,37 +577,76 @@ class CapacitorUnit():
|
|||
## Draws the required cuts to connect the bottom plate. First, the maximal possible number of cuts that can be drawn is computed. Second, using the computed number, the enclosure of this cuts in the bottom plate's layer is adjusted while the minimal enclosure is respected. Third, the relative positions of the cuts on both sides of the plate are computed. Finally, two vertical lines of cuts are drawns.
|
||||
# \remark The relative positions describe the cordinates of the first bottom cut in every line of cuts. Then, knowing the spacing and width specifications of these cuts the rest of the line is easilly constructed.
|
||||
|
||||
def drawBottomPlateCut( self, layer, bNet ):
|
||||
def drawBottomPlateCut( self, layer, b ):
|
||||
|
||||
self.cutLine( bNet, layer, self.cutLeftLineDict ["XMin"], self.cutLeftLineDict ["YMin"], self.minWidth_botPlatecut, self.minheight_topPlatecut, self.minSpacingOnBotPlate_cut, self.bottomCutLineNumber , 'vertical' )
|
||||
self.cutLine( bNet, layer, self.cutRightLineDict["XMin"], self.cutRightLineDict["YMin"], self.minWidth_botPlatecut, self.minheight_topPlatecut, self.minSpacingOnBotPlate_cut, self.bottomCutLineNumber , 'vertical' )
|
||||
self.cutLine( b, layer
|
||||
, self.cutLeftLineDict ["XMin"]
|
||||
, self.cutLeftLineDict ["YMin"]
|
||||
, self.minWidth_botPlatecut
|
||||
, self.minheight_topPlatecut
|
||||
, self.minSpacingOnBotPlate_cut
|
||||
, self.bottomCutLineNumber
|
||||
, 'vertical'
|
||||
)
|
||||
self.cutLine( b, layer
|
||||
, self.cutRightLineDict["XMin"]
|
||||
, self.cutRightLineDict["YMin"]
|
||||
, self.minWidth_botPlatecut
|
||||
, self.minheight_topPlatecut
|
||||
, self.minSpacingOnBotPlate_cut
|
||||
, self.bottomCutLineNumber , 'vertical'
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
|
||||
## Draws the top plate's cuts after computing the maximal number of cuts that can be placed and its exact enclosure in the top plate.
|
||||
|
||||
def drawTopPlateCut( self, layer, tNet ):
|
||||
def drawTopPlateCut( self, layer, t ):
|
||||
|
||||
if self.capacitorType == 'MIMCap':
|
||||
self.cutMatrix(tNet,layer,self.cut2MatrixDict["XMin"],self.cut2MatrixDict["YMin"],self.minWidth_topPlatecut,self.minheight_topPlatecut,self.minSpacingOnTopPlate_cut,self.topCutLineNumber,self.topCutLineNumber)
|
||||
self.cutMatrix(t,layer
|
||||
,self.cut2MatrixDict["XMin"]
|
||||
,self.cut2MatrixDict["YMin"]
|
||||
,self.minWidth_topPlatecut
|
||||
,self.minheight_topPlatecut
|
||||
,self.minSpacingOnTopPlate_cut
|
||||
,self.topCutLineNumber["horizontal"]
|
||||
,self.topCutLineNumber["vertical" ]
|
||||
)
|
||||
|
||||
else : self.cutLine (tNet,layer,self.topCutLineDict["XMin"],self.topCutLineDict["YMin"],self.minWidth_topPlatecut,self.minheight_topPlatecut,self.minSpacingOnTopPlate_cut,self.topCutLineNumber,'vertical')
|
||||
else : self.cutLine(t,layer
|
||||
,self.topCutLineDict["XMin"]
|
||||
,self.topCutLineDict["YMin"]
|
||||
,self.minWidth_topPlatecut
|
||||
,self.minheight_topPlatecut
|
||||
,self.minSpacingOnTopPlate_cut
|
||||
,self.topCutLineNumber["vertical"]
|
||||
,'vertical'
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
|
||||
## Draws the routing layers of both bottom and top plates after computing widths and the exact position of these layers. Also computes positions if rlayers that are crucual for routing. this of putting it in a second function
|
||||
## Draws the routing layers of both bottom and top plates after computing widths and the exact position of these layers. Also computes positions if rlayers that are crucial for routing.
|
||||
|
||||
def drawRoutingLayers( self, bottomPlateLayer, topPlateLayer, tNet, bNet ):
|
||||
def drawRoutingLayers( self, bottomPlateLayer, topPlateLayer, t, b ):
|
||||
|
||||
Vertical.create ( tNet, topPlateLayer, self.topPlateRLayerDict["XCenter"], self.topPlateRLayerDict["width"], self.topPlateRLayerDict["YMin"], self.topPlateRLayerDict["YMax"] )
|
||||
Vertical.create ( t, topPlateLayer
|
||||
, self.topPlateRLayerDict["XCenter"]
|
||||
, self.topPlateRLayerDict["width" ]
|
||||
, self.topPlateRLayerDict["YMin" ]
|
||||
, self.topPlateRLayerDict["YMax" ]
|
||||
)
|
||||
|
||||
cutLinesXMins = [ self.cutLeftLineDict["XMin"], self.cutRightLineDict["XMin"] ]
|
||||
for i in range(2):
|
||||
Vertical.create ( bNet, bottomPlateLayer, cutLinesXMins[i] , self.bottomPlateRLayerDict["width"], self.bottomPlateRLayerDict["YMin"], self.bottomPlateRLayerDict["YMax"] )
|
||||
|
||||
|
||||
Vertical.create ( b, bottomPlateLayer
|
||||
, cutLinesXMins[i]
|
||||
, self.bottomPlateRLayerDict["width"]
|
||||
, self.bottomPlateRLayerDict["YMin" ]
|
||||
, self.bottomPlateRLayerDict["YMax" ]
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
|
@ -566,7 +704,7 @@ class CapacitorUnit():
|
|||
|
||||
|
||||
## \return the ordinate of the highest cut of the bottom plate's left line of cuts.
|
||||
def getBottomPlateLeftCutYMax ( self ) : return self.cutLeftLineDict ["YMin" ] + ( self.topCutLineNumber - 1 )*( self.minSpacingOnBotPlate_cut + self.minWidth_botPlatecut )
|
||||
def getBottomPlateLeftCutYMax ( self ) : return self.cutLeftLineDict ["YMin" ] + ( self.bottomCutLineNumber - 1 )*( self.minSpacingOnBotPlate_cut + self.minWidth_botPlatecut )
|
||||
|
||||
|
||||
## \return the absissa of the bottom plate's right line of cuts.
|
||||
|
@ -653,13 +791,15 @@ def ScriptMain( **kw ):
|
|||
device = AllianceFramework.get().createCell( 'capacitor' )
|
||||
device.setTerminal( True )
|
||||
|
||||
bottomPlate_net = Net.create( device, 'bNet' )
|
||||
bottomPlate_net = Net.create( device, 'b' )
|
||||
bottomPlate_net.setExternal( True )
|
||||
bNet = device.getNet("bNet")
|
||||
b = device.getNet("b")
|
||||
doBreak( 1, 'Done building bottomPlate')
|
||||
|
||||
topPlate_net = Net.create( device, 'tNet' )
|
||||
topPlate_net = Net.create( device, 't' )
|
||||
topPlate_net.setExternal( True )
|
||||
tNet = device.getNet("tNet")
|
||||
t = device.getNet("t")
|
||||
doBreak( 1, 'Done building t')
|
||||
|
||||
if editor:
|
||||
UpdateSession.close( )
|
||||
|
@ -667,9 +807,9 @@ def ScriptMain( **kw ):
|
|||
editor.fit ( )
|
||||
UpdateSession.open ( )
|
||||
|
||||
capacitor = CapacitorUnit ( device,500, 'MIMCap', [0,0] ) # 129.56
|
||||
surface = capacitor.create( bNet, tNet )
|
||||
print(surface)
|
||||
capacitor = CapacitorUnit ( device, 'MIMCap', [0,0], capacitance = 129.56) # square: capacitance : 129.56 , capDim = {"width" : 39650L , "height" : 39650L } # rectangular capDim = {"width" : 78919L , "height" : 118378L }
|
||||
abutmentBoxDim = capacitor.create( b, t, bbMode = True, vEnclosure_botPlate_abtBox = 1.5, hEnclosure_botPlate_abtBox = 0.9)
|
||||
print(abutmentBoxDim)
|
||||
|
||||
AllianceFramework.get().saveCell( device, Catalog.State.Views )
|
||||
|
||||
|
|
|
@ -0,0 +1,758 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
from Hurricane import *
|
||||
from CRL import *
|
||||
from math import sqrt, ceil
|
||||
import helpers
|
||||
from helpers.io import ErrorMessage as Error
|
||||
from helpers import trace, u
|
||||
import oroshi
|
||||
#from CapacitorUnit import CapacitorUnit
|
||||
|
||||
def toDbU ( l ): return DbU.fromPhysical( l, DbU.UnitPowerMicro )
|
||||
def toPhY ( l ): return DbU.toPhysical ( l, DbU.UnitPowerMicro )
|
||||
|
||||
def doBreak( level, message ):
|
||||
UpdateSession.close()
|
||||
Breakpoint.stop( level, message )
|
||||
UpdateSession.open()
|
||||
|
||||
helpers.staticInitialization( True )
|
||||
|
||||
|
||||
|
||||
|
||||
class Resistor():
|
||||
|
||||
|
||||
rules = oroshi.getRules()
|
||||
|
||||
def __init__( self, device, nets, resistorType, resistance = 0, resDim = { "width" : 0.8, "length" : 0 }, direction = "horizontal", snakeMode = False, bends = 0 ):
|
||||
|
||||
self.device = device
|
||||
self.nets = nets
|
||||
|
||||
self.__initArgs__ ( resistorType, direction, snakeMode, bends )
|
||||
|
||||
[ resDim["width" ], resDim["length"] ] = [ toDbU(resDim["width" ]), toDbU(resDim["length"]) ]
|
||||
self.__initResDim__( resistance, resDim )
|
||||
|
||||
if self.snakeMode :
|
||||
self.bendDim = self.__computeBendDim__( self )
|
||||
self.snakeSegmentDict = {}
|
||||
|
||||
self.resistorPlateDict = {}
|
||||
self.abutmentBoxDict = { "XMin" : 0, "YMin" : 0 }
|
||||
self.abutmentBox = Box ()
|
||||
self.terminal1Box = Box()
|
||||
self.terminal2Box = Box()
|
||||
|
||||
self.contactsNumber = 0
|
||||
self.resPlateExtensions_minWidth = 0
|
||||
self.cutsEnclosure = {}
|
||||
|
||||
|
||||
self.t1CutsDict = {}
|
||||
self.t2CutsDict = {}
|
||||
|
||||
if self.resistorType == "RPOLYH" :
|
||||
self.pImplant_layerDict = {}
|
||||
self.hresLayerDict = {}
|
||||
if self.resistorType == "RPOLY2PH" :
|
||||
self.restrmLayerDict = {}
|
||||
|
||||
self.enclosure_resistor_abutmentBox = {}
|
||||
self.resPlateExtensions = {}
|
||||
self.resPlateExtrimities = {}
|
||||
return
|
||||
|
||||
|
||||
|
||||
def __initArgs__( self, resistorType, direction, snakeMode, bends ):
|
||||
|
||||
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 snakeMode in [True, False] :
|
||||
if snakeMode == False and bends == 0 or snakeMode == False and bends > 0 : self.snakeMode = snakeMode
|
||||
else : raise Error(1,'__initDirection__() : Please check compatibility between snake mode, %s, and bends number, %s.' % (snakeMode, bends))
|
||||
else : raise Error(1,'__initDirection__() : Snake mode must be either "True" or "False".')
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def __initResDim__( self, resistance, resDim ):
|
||||
|
||||
if self.__isDimOk__( resDim, "width" ) :
|
||||
|
||||
if resistance > 0 and resDim["length"] > 0 :
|
||||
|
||||
if self.__computeResistance__( resDim, self.resistorType ) == resistance and self.__isDimOk__( resDim, "length" ):
|
||||
self.resDim = resDim
|
||||
else :
|
||||
raise Error(1,'__initResDim__() : Non compatibiliy between resistance value, %s, and the given resistor dimensions, %s, or invalid length, %s.' %(resistance, resDim))
|
||||
|
||||
elif resistance > 0 and resDim["length"] == 0 :
|
||||
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 __isDimOk__( self, resdim, side ) :
|
||||
|
||||
if resdim.keys() == ["width","length"] and side in ["width","length"]:
|
||||
if side == ["width"]: rule = Resistor.rules.minWidth_rpolyh
|
||||
else : rule = Resistor.rules.minWidth_rpolyh # Resistor.rules.minLength_rpolyh if self.resistorType == "RPOLYH" else Resistor.rules.minLength_rpolyh
|
||||
|
||||
state = True if resdim[side] >= rule else False
|
||||
if state == False : raise Error(1,'__isDimOk__() : Resistor or bend side dimension exceeds the minimal limit : (side dimension, minimal limit) = (%s ,%s).' % (resdim[side], 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 ): return self.__getResistorMaterial__( resistorType, "resistorPlate" )*toPhY(resDim["length"])*toPhY(resDim["width"])
|
||||
|
||||
|
||||
|
||||
def __computeResDim__( self, resistance, resistorType, resDim ):
|
||||
|
||||
wl_ratio = resistance/self.__getResistorMaterial__( resistorType, "resistorPlate" )
|
||||
width = toPhY(resDim["width"])
|
||||
length = wl_ratio*width
|
||||
resDim["length"] = toDbU(length)
|
||||
print('length',length)
|
||||
if self.__isDimOk__(resDim, "width") and self.__isDimOk__(resDim, "length") :
|
||||
return resDim
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def __getResistorMaterial__( self, resistorType, material ):
|
||||
|
||||
if material == 'resistorPlate':
|
||||
if resistorType == "RPOLYH" : resistance = Resistor.rules.RPOLYHSheetRes
|
||||
elif resistorType == "RPOLY2PH": resistance = Resistor.rules.RPOLY2PHSheetRes
|
||||
else : raise Error( 1, '__getResistorMaterial__() : Unsupported resistor type : %s.' % resistorType )
|
||||
|
||||
elif material == "contact" :
|
||||
resistance = Resistor.rules.MET1RPOLYHContRes
|
||||
|
||||
return resistance
|
||||
|
||||
|
||||
|
||||
def __computeBendDim__( self ):
|
||||
|
||||
length = 0
|
||||
if self.__isDimOk__(self.bendDim, "length") : bendDim = { "width" : self.resDim["width"], "length" : toDbU(length) }
|
||||
|
||||
return bendDim
|
||||
|
||||
|
||||
def setRules( self ):
|
||||
|
||||
self.__setattr__ ( "minSpacing_resistorPlate" , Resistor.rules.minSpacing_rpolyh )
|
||||
self.__setattr__ ( "minWidth_contact" , Resistor.rules.minWidth_cut0 )
|
||||
self.__setattr__ ( "minHeight_contact" , Resistor.rules.minWidth_cut0 )
|
||||
self.__setattr__ ( "minSpacing_contact" , Resistor.rules.minSpacing_cut0 )
|
||||
self.__setattr__ ( "minEnclosure_resistorPlate_contact" , Resistor.rules.minEnclosure_poly2_cut0 )
|
||||
|
||||
if self.resistorType == "RPOLYH":
|
||||
self.__setattr__( "minWidth_resistorPlate" , Resistor.rules.minWidth_rpolyh )
|
||||
self.__setattr__( "minWidth_pImplantLayer" , Resistor.rules.minWidth_pImplant )
|
||||
self.__setattr__( "minSpacing_pImplantLayer" , Resistor.rules.minSpacing_pImplant )
|
||||
self.__setattr__( "minSpacing_resistorPlate_pImplantLayer" , Resistor.rules.minSpacing_rpolyh_pImplant )
|
||||
self.__setattr__( "minEnclosure_pImplantLayer_contact" , Resistor.rules.minEnclosure_pImplant_poly2con )
|
||||
self.__setattr__( "minEnclosure_hres_poly2" , Resistor.rules.minEnclosure_hres_poly2 )
|
||||
self.__setattr__( "minWidth_hres" , Resistor.rules.minWidth_hres )
|
||||
self.__setattr__( "minSpacing_hres" , Resistor.rules.minSpacing_hres )
|
||||
self.__setattr__( "minSpacing_hres_poly1" , Resistor.rules.minSpacing_hres_poly1 )
|
||||
self.__setattr__( "minSpacing_hres_poly2" , Resistor.rules.minSpacing_hres_poly2 )
|
||||
self.__setattr__( "minSpacing_hres_active" , Resistor.rules.minSpacing_hres_active )
|
||||
# self.__setattr__( "minLength_resistorPlate" , Resistor.rules.minLength_rpolyh )
|
||||
|
||||
elif self.resistorType == "RPOLY2PH":
|
||||
self.__setattr__( "minWidth_resistorPlate" , Resistor.rules.minWidth_rpolyh )
|
||||
|
||||
# self.__setattr__( "minLength_resistorPlate" , Resistor.rules.minLength_rpoly2ph )
|
||||
|
||||
else : raise Error( 1, 'setRules() : Unsupported resistor type : %s.' % resistorType )
|
||||
|
||||
return
|
||||
|
||||
|
||||
def __setattr__( self, attribute, value ):
|
||||
|
||||
self.__dict__[attribute] = value
|
||||
|
||||
return
|
||||
|
||||
|
||||
def getLayers( self ):
|
||||
|
||||
technology = DataBase.getDB().getTechnology()
|
||||
layerDict = {}
|
||||
|
||||
layerDict["resistorPlate"] = technology.getLayer( "poly2" )
|
||||
layerDict["contacts" ] = technology.getLayer( "cut0" )
|
||||
layerDict["pImplant" ] = technology.getLayer( "pImplant" )
|
||||
layerDict["resdef" ] = technology.getLayer( "resdef" )
|
||||
|
||||
if self.resistorType == "RPOLYH" : layerDict["hres" ] = technology.getLayer( "hres" )
|
||||
if self.resistorType == "RPOLY2PH" : layerDict["restrm"] = technology.getLayer( "restrm" )
|
||||
|
||||
return layerDict
|
||||
|
||||
|
||||
|
||||
|
||||
def create( self ):
|
||||
|
||||
UpdateSession.open()
|
||||
|
||||
self.setRules()
|
||||
layerDict = self.getLayers()
|
||||
self.computeDimensions()
|
||||
self.drawAbutmentBox ()
|
||||
self.device.setAbutmentBox( self.abutmentBox )
|
||||
if self.resistorType == "RPOLYH" : self.drawHRESLayer( layerDict["hres"] )
|
||||
|
||||
if self.snakeMode == False :
|
||||
self.drawRectangularResistorPlate( layerDict["resistorPlate"] )
|
||||
self.drawResPlateExtrimities ( layerDict["resistorPlate"], layerDict["pImplant"] )
|
||||
# elif :
|
||||
# pass
|
||||
self.drawContacts( layerDict["contacts"])
|
||||
if self.resistorType == "RPOLY2PH" : self.drawRestrmLayer(layerDict["restrm"])
|
||||
|
||||
self.drawResDefLayer(layerDict["resdef"])
|
||||
|
||||
UpdateSession.close()
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def computeDimensions( self ):
|
||||
|
||||
self.computeAbutmentBoxDimensions2()
|
||||
|
||||
if self.snakeMode == False :
|
||||
self.computeResistorPlateDimensions()
|
||||
|
||||
# else : self.computeBendDimensions()
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def computePImplantLayerDim ( self ):
|
||||
|
||||
pImplantLayer_width = max(self.minWidth_pImplantLayer, 2*self.minEnclosure_pImplantLayer_contact + self.minWidth_contact)
|
||||
# self.pImplant_layerDict["width"] = pImplantLayer_width if self.resDim["width"] < pImplantLayer_width else self.contactsNumber*self.minWidth_contact + (self.contactsNumber-1)*self.minSpacing_contact + 2*self.minEnclosure_pImplantLayer_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
|
||||
|
||||
|
||||
|
||||
def computeResPlateExtensionsDim( self ):
|
||||
|
||||
self.resPlateExtensions_minWidth = self.minWidth_contact + 2*self.minEnclosure_resistorPlate_contact
|
||||
print("self.resDim['width']",self.resDim['width'])
|
||||
print("self.resPlateExtensions_minWidth",self.resPlateExtensions_minWidth)
|
||||
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
|
||||
|
||||
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.hresLayerDict #self.pImplant_layerDict
|
||||
|
||||
if self.resistorType == "RPOLY2PH" :
|
||||
self.resPlateExtrimities = self.resPlateExtensions
|
||||
print("self.resPlateExtrimities['length']ExtrimDim",toPhY(self.resPlateExtrimities["length"]))
|
||||
|
||||
return
|
||||
|
||||
|
||||
def computeAbutmentBoxDimensions( self ):
|
||||
|
||||
if self.resistorType == "RPOLYH" : self.enclosure_resistor_abutmentBox = max(self.minSpacing_hres, self.minSpacing_hres_poly1, self.minSpacing_hres_poly2, self.minSpacing_hres_active) #max(self.minSpacing_resistorPlate, self.minSpacing_pImplantLayer, self.minSpacing_resistorPlate_pImplantLayer)
|
||||
if self.resistorType == "RPOLY2PH" : self.enclosure_resistor_abutmentBox = self.minSpacing_resistorPlate
|
||||
|
||||
if self.snakeMode == False:
|
||||
|
||||
self.computeResPlateExtensionsDim()
|
||||
self.contactsNumber = self.cutMaxNumber( self.resPlateExtensions["width"], self.minHeight_contact, self.minSpacing_contact, self.minEnclosure_resistorPlate_contact )
|
||||
|
||||
if self.resistorType == "RPOLYH" :
|
||||
self.computePImplantLayerDim()
|
||||
|
||||
self.computeResPlateExtrimitiesDim()
|
||||
|
||||
abutmentBoxSide1 = self.resPlateExtrimities["width"] + 2*self.enclosure_resistor_abutmentBox
|
||||
abutmentBoxSide2 = self.resDim["length"] + 2*self.resPlateExtrimities["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
|
||||
|
||||
|
||||
if self.snakeMode == True : print("hi")
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
def computeAbutmentBoxDimensions2( self ):
|
||||
|
||||
if self.resistorType == "RPOLYH" : self.enclosure_resistor_abutmentBox = self.minSpacing_hres #max(self.minSpacing_resistorPlate, self.minSpacing_pImplantLayer, self.minSpacing_resistorPlate_pImplantLayer)
|
||||
if self.resistorType == "RPOLY2PH" : self.enclosure_resistor_abutmentBox = self.minSpacing_resistorPlate
|
||||
|
||||
if self.snakeMode == False:
|
||||
|
||||
self.computeResPlateExtensionsDim()
|
||||
self.contactsNumber = self.cutMaxNumber( self.resPlateExtensions["width"], self.minHeight_contact, self.minSpacing_contact, self.minEnclosure_resistorPlate_contact )
|
||||
|
||||
if self.resistorType == "RPOLYH" :
|
||||
self.computePImplantLayerDim()
|
||||
self.computeHRESLayerDimensions()
|
||||
|
||||
self.computeResPlateExtrimitiesDim()
|
||||
|
||||
print("self.resPlateEtrimities['length']abtBoxDim2",toPhY(self.resPlateExtrimities['length']))
|
||||
|
||||
abutmentBoxSide1 = self.resPlateExtrimities["width"] + 2*self.enclosure_resistor_abutmentBox
|
||||
print("self.resPlateExtrimities",self.resPlateExtrimities)
|
||||
abutmentBoxSide2 = self.resDim["length"] + 2*self.resPlateExtrimities["length"] + 2*self.enclosure_resistor_abutmentBox
|
||||
print("self.resDim['length']2",toPhY(self.resDim["length"]))
|
||||
print("self.enclosure_resistor_abutmentBox2",toPhY(self.enclosure_resistor_abutmentBox))
|
||||
print("self.resPlateEtrimities['length']2",toPhY(self.resPlateExtrimities['length']))
|
||||
# if self.resistorType == "RPOLYH" : abutmentBoxSide2 = self.resPlateExtrimities["length"]+ 2*self.enclosure_resistor_abutmentBox
|
||||
# if self.resistorType == "RPOLY2PH" : abutmentBoxSide2 = self.resDim["length"] + 2*self.resPlateExtrimities["length"] + 2*self.enclosure_resistor_abutmentBox
|
||||
print("abutmentBoxSide2",toPhY(abutmentBoxSide2))
|
||||
if self.direction == "vertical" :
|
||||
self.abutmentBoxDict["width" ] = abutmentBoxSide1
|
||||
self.abutmentBoxDict["height"] = abutmentBoxSide2
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
self.abutmentBoxDict["width" ] = abutmentBoxSide2
|
||||
self.abutmentBoxDict["height"] = abutmentBoxSide1
|
||||
|
||||
|
||||
|
||||
if self.snakeMode == True : print("hi")
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def computeHRESLayerDimensions( self ):
|
||||
|
||||
self.enclosure_resistor_hres = self.minEnclosure_hres_poly2
|
||||
hresLayerSide1 = max(self.minWidth_hres, self.pImplant_layerDict["width" ] + 2*self.enclosure_resistor_hres)
|
||||
#hresLayerSide2 = max(self.minWidth_hres, 2*self.pImplant_layerDict["length"] + 2*self.enclosure_resistor_hres + self.resDim["length"])
|
||||
|
||||
if self.direction == "vertical" :
|
||||
#self.hresLayerDict["width" ] = hresLayerSide2
|
||||
self.hresLayerDict["length"] = hresLayerSide1
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
self.hresLayerDict["width" ] = hresLayerSide1
|
||||
#self.hresLayerDict["length"] = hresLayerSide2
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def computeResistorPlateDimensions( self ):
|
||||
|
||||
self.resistorPlateDict["width" ] = self.resDim["width" ]
|
||||
self.resistorPlateDict["length" ] = self.resDim["length"]
|
||||
|
||||
if self.direction == "vertical" :
|
||||
self.resistorPlateDict["XCenter"] = self.abutmentBoxDict ["XMin"] + self.abutmentBoxDict ["width"]/2
|
||||
self.resistorPlateDict["YMin" ] = self.abutmentBoxDict ["YMin"] + self.enclosure_resistor_abutmentBox + self.resPlateExtrimities["length"]
|
||||
self.resistorPlateDict["YMax" ] = self.resistorPlateDict["YMin"] + self.resistorPlateDict["length"]
|
||||
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
print("self.abutmentBoxDict ['XMin']",toPhY(self.abutmentBoxDict ["XMin"]))
|
||||
print("self.enclosure_resistor_abutmentBox",toPhY(self.enclosure_resistor_abutmentBox))
|
||||
print("self.resPlateExtrimities['length']",toPhY(self.resPlateExtrimities["length"]
|
||||
))
|
||||
self.resistorPlateDict["YCenter"] = self.abutmentBoxDict ["YMin"] + self.abutmentBoxDict ["height"]/2
|
||||
self.resistorPlateDict["XMin" ] = self.abutmentBoxDict ["XMin"] + self.enclosure_resistor_abutmentBox + self.resPlateExtrimities["length"]
|
||||
print("self.resistorPlateDict['XMin' ]",toPhY(self.resistorPlateDict["XMin" ]))
|
||||
self.resistorPlateDict["XMax" ] = self.resistorPlateDict["XMin"] + self.resistorPlateDict["length"]
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
def drawLayer( self, layer, positionParams ):
|
||||
|
||||
if self.direction == "vertical" : positionParamsKeys = ["XCenter","width","YMin","YMax"]
|
||||
if self.direction == "horizontal" : positionParamsKeys = ["YCenter","width","XMin","XMax"]
|
||||
|
||||
if type(positionParams) is dict :
|
||||
for key in positionParams.keys() :
|
||||
if key not in positionParams : raise Error(1,'drawLayer() : %s must contain all following keys : %s.' %(positionParams, positionParams))
|
||||
else : raise Error(1,'drawLayer() : %s must be a dictionary of %s keys.' %(positionParams, positionParams) )
|
||||
|
||||
if layer == 1: self.computeHRESLayerPosition()
|
||||
if layer == 1: self.computeResDefDimensions()
|
||||
|
||||
if self.direction == "vertical" : Vertical.create ( self.nets[0], layer, positionParams["XCenter"], positionParams["width"], positionParams["YMin"], positionParams["YMax"] )
|
||||
if self.direction == "horizontal" : Horizontal.create( self.nets[0], layer, positionParams["YCenter"], positionParams["width"], positionParams["XMin"], positionParams["XMax"] )
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
def drawHRESLayer( self, layer ):
|
||||
print("layer",layer)
|
||||
self.computeHRESLayerPosition()
|
||||
|
||||
if self.direction == "vertical" : Vertical.create ( self.nets[0], layer, self.hresLayerDict["XCenter"], self.hresLayerDict["length"], self.hresLayerDict["YMin"], self.hresLayerDict["YMax"] )
|
||||
if self.direction == "horizontal" : Horizontal.create ( self.nets[0], layer, self.hresLayerDict["YCenter"], self.hresLayerDict["width" ], self.hresLayerDict["XMin"], self.hresLayerDict["XMax"] )
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def drawAbutmentBox( self ):
|
||||
|
||||
self.abutmentBox = Box(self.abutmentBoxDict["XMin"], self.abutmentBoxDict["YMin"], self.abutmentBoxDict["width"], self.abutmentBoxDict["height"])
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
def drawRectangularResistorPlate( self, layer ):
|
||||
|
||||
if self.direction == "vertical" : Vertical.create ( self.nets[0], layer, self.resistorPlateDict["XCenter"], self.resistorPlateDict["width"], self.resistorPlateDict["YMin"], self.resistorPlateDict["YMax"] )
|
||||
if self.direction == "horizontal" : Horizontal.create( self.nets[0], layer, self.resistorPlateDict["YCenter"], self.resistorPlateDict["width"], self.resistorPlateDict["XMin"], self.resistorPlateDict["XMax"] )
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
def drawResPlateExtrimities( self, resPlateLayer, pImplantLayer ):
|
||||
|
||||
self.drawResPlateExtensions(resPlateLayer)
|
||||
if self.resistorType == "RPOLYH" : self.drawPImplantLayer(pImplantLayer)
|
||||
|
||||
return
|
||||
|
||||
|
||||
def computeResPlateExtensionsPosition( self ):
|
||||
|
||||
self.resPlateExtensions["ex1"] = {}
|
||||
|
||||
if self.direction == "vertical" :
|
||||
|
||||
self.resPlateExtensions["ex1"]["XMin"] = self.abutmentBox.getXCenter() - self.resPlateExtensions["width" ]/2
|
||||
self.resPlateExtensions["ex1"]["YMin"] = self.abutmentBox.getYCenter() - self.resPlateExtensions["length"] - self.resDim["length"]/2
|
||||
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" :
|
||||
|
||||
self.resPlateExtensions["ex1"]["XMin"] = self.abutmentBox.getXCenter() - self.resPlateExtensions["length"] - self.resDim["length"]/2
|
||||
self.resPlateExtensions["ex1"]["YMin"] = self.abutmentBox.getYCenter() - self.resPlateExtensions["width" ]/2
|
||||
self.resPlateExtensions["ex1"]["XMax"] = self.resPlateExtensions["ex1"]["XMin"] + self.resPlateExtensions["length"]
|
||||
self.resPlateExtensions["ex1"]["YMax"] = self.resPlateExtensions["ex1"]["YMin"] + self.resPlateExtensions["width" ]
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def drawResPlateExtensions( self, layer ):
|
||||
|
||||
self.computeResPlateExtensionsPosition()
|
||||
translation = self.resDim["length"] + self.resPlateExtensions["length"]
|
||||
|
||||
if self.direction == "vertical" :
|
||||
|
||||
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"], self.resPlateExtensions["ex1"]["YMin"] + translation, self.resPlateExtensions["ex1"]["XMax"], self.resPlateExtensions["ex1"]["YMax"] + translation)
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
|
||||
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"] + translation, self.resPlateExtensions["ex1"]["YMin"], self.resPlateExtensions["ex1"]["XMax"] + translation, self.resPlateExtensions["ex1"]["YMax"])
|
||||
|
||||
terminal1Pad = Pad.create(self.nets[0], layer, self.terminal1Box)
|
||||
terminal2Pad = Pad.create(self.nets[1], layer, self.terminal2Box)
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def computePImplantLayerPosition( self ):
|
||||
|
||||
if self.direction == "vertical" :
|
||||
|
||||
self.pImplant_layerDict["YCenter"] = self.abutmentBoxDict ["YMin"] + self.enclosure_resistor_abutmentBox + self.enclosure_resistor_hres + self.pImplant_layerDict["length"]/2
|
||||
self.pImplant_layerDict["XMin" ] = self.abutmentBox.getXCenter() - self.pImplant_layerDict["width"]/2
|
||||
self.pImplant_layerDict["XMax" ] = self.pImplant_layerDict["XMin"] + self.pImplant_layerDict["width"]
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
|
||||
self.pImplant_layerDict["XCenter"] = self.abutmentBoxDict ["XMin"] + self.enclosure_resistor_abutmentBox + self.enclosure_resistor_hres + self.pImplant_layerDict["length"]/2 #self.minWidth_contact + self.minEnclosure_resistorPlate_contact)/2
|
||||
self.pImplant_layerDict["YMin" ] = self.abutmentBox.getYCenter() - self.pImplant_layerDict["width"]/2 #self.abutmentBoxDict ["YMin"] + self.enclosure_resistor_abutmentBox
|
||||
self.pImplant_layerDict["YMax" ] = self.pImplant_layerDict["YMin"] + self.pImplant_layerDict["width"]
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
def drawPImplantLayer( self, layer ):
|
||||
|
||||
self.computePImplantLayerPosition()
|
||||
translation = self.resDim["length"] + self.pImplant_layerDict["length"]
|
||||
|
||||
if self.direction == "vertical" :
|
||||
Horizontal.create( self.nets[0], layer, self.pImplant_layerDict["YCenter"] , self.pImplant_layerDict["length"], self.pImplant_layerDict["XMin"], self.pImplant_layerDict["XMax"] )
|
||||
Horizontal.create( self.nets[0], layer, self.pImplant_layerDict["YCenter"] + translation, self.pImplant_layerDict["length"], self.pImplant_layerDict["XMin"], self.pImplant_layerDict["XMax"] )
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
|
||||
Vertical.create ( self.nets[0], layer, self.pImplant_layerDict["XCenter"] , self.pImplant_layerDict["length"], self.pImplant_layerDict["YMin"], self.pImplant_layerDict["YMax"] )
|
||||
Vertical.create ( self.nets[1], layer, self.pImplant_layerDict["XCenter"] + translation, self.pImplant_layerDict["length"], self.pImplant_layerDict["YMin"], self.pImplant_layerDict["YMax"] )
|
||||
|
||||
return
|
||||
|
||||
|
||||
def computeCutsDimensions( self ):
|
||||
|
||||
if self.direction == "vertical":
|
||||
self.cutsEnclosure ["horizontal"] = ( self.resPlateExtensions["width"] - (self.contactsNumber*self.minHeight_contact + (self.contactsNumber -1)*self.minSpacing_contact) )/2
|
||||
self.cutsEnclosure ["vertical" ] = self.minEnclosure_resistorPlate_contact
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
self.cutsEnclosure["horizontal"] = self.minEnclosure_resistorPlate_contact
|
||||
self.cutsEnclosure["vertical" ] = ( self.resPlateExtensions["width"] - (self.contactsNumber*self.minHeight_contact + (self.contactsNumber -1)*self.minSpacing_contact) )/2
|
||||
|
||||
self.t1CutsDict["XCenter"] = self.terminal1Box.getXMin() + self.cutsEnclosure ["horizontal"] + self.minWidth_contact/2
|
||||
self.t1CutsDict["YCenter"] = self.terminal1Box.getYMin() + self.cutsEnclosure ["vertical" ] + self.minHeight_contact/2
|
||||
|
||||
if self.resistorType == "RPOLYH" : translation = self.resDim["length"] + self.minWidth_contact + 2*self.minEnclosure_pImplantLayer_contact
|
||||
if self.resistorType == "RPOLY2PH" : translation = self.resDim["length"] + self.minWidth_contact
|
||||
|
||||
if self.direction == "vertical":
|
||||
self.t2CutsDict["XCenter"] = self.t1CutsDict["XCenter"]
|
||||
self.t2CutsDict["YCenter"] = self.t1CutsDict["YCenter"] + translation
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
self.t2CutsDict["XCenter"] = self.t1CutsDict["XCenter"] + translation
|
||||
self.t2CutsDict["YCenter"] = self.t1CutsDict["YCenter"]
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def drawContacts( self, layer ):
|
||||
|
||||
self.computeCutsDimensions()
|
||||
|
||||
if self.direction == "vertical" : cutLineDirection = "horizontal"
|
||||
if self.direction == "horizontal" : cutLineDirection = "vertical"
|
||||
self.cutLine( self.nets[0], layer, self.t1CutsDict["XCenter"], self.t1CutsDict["YCenter"], self.minWidth_contact, self.minHeight_contact, self.minSpacing_contact, self.contactsNumber , cutLineDirection )
|
||||
self.cutLine( self.nets[1], layer, self.t2CutsDict["XCenter"], self.t2CutsDict["YCenter"], self.minWidth_contact, self.minHeight_contact, self.minSpacing_contact, self.contactsNumber , cutLineDirection )
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def drawRestrmLayer( self, layer ):
|
||||
|
||||
self.computeRestrmLayerPosition()
|
||||
translation = self.resDim["length"] + self.restrmLayerDict["width"]
|
||||
|
||||
if self.direction == "vertical" :
|
||||
Horizontal.create( self.nets[0], layer, self.restrmLayerDict["YCenter"] , self.restrmLayerDict["width"], self.restrmLayerDict["XMin"], self.restrmLayerDict["XMax"] )
|
||||
Horizontal.create( self.nets[1], layer, self.restrmLayerDict["YCenter"]+translation, self.restrmLayerDict["width"], self.restrmLayerDict["XMin"], self.restrmLayerDict["XMax"] )
|
||||
if self.direction == "horizontal" :
|
||||
Vertical.create ( self.nets[0], layer, self.restrmLayerDict["XCenter"] , self.restrmLayerDict["width"], self.restrmLayerDict["YMin"], self.restrmLayerDict["YMax"] )
|
||||
Vertical.create ( self.nets[1], layer, self.restrmLayerDict["XCenter"]+translation, self.restrmLayerDict["width"], self.restrmLayerDict["YMin"], self.restrmLayerDict["YMax"] )
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def computeRestrmLayerPosition( self ):
|
||||
|
||||
self.restrmLayerDict["width"] = self.minWidth_contact/2
|
||||
|
||||
if self.direction == "vertical" :
|
||||
self.restrmLayerDict["YCenter"] = self.t1CutsDict["YCenter"] + self.restrmLayerDict["width"]/2
|
||||
self.restrmLayerDict["XMin" ] = self.resPlateExtensions["ex1"]["XMin"] - self.restrmLayerDict["width"]
|
||||
self.restrmLayerDict["XMax" ] = self.resPlateExtensions["ex1"]["XMax"] + self.restrmLayerDict["width"]
|
||||
|
||||
if self.direction == "horizontal" :
|
||||
self.restrmLayerDict["XCenter"] = self.t1CutsDict["XCenter"] + self.restrmLayerDict["width"]/2
|
||||
self.restrmLayerDict["YMin" ] = self.resPlateExtensions["ex1"]["YMin"] - self.restrmLayerDict["width"]
|
||||
self.restrmLayerDict["YMax" ] = self.resPlateExtensions["ex1"]["YMax"] + self.restrmLayerDict["width"]
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def computeResDefDimensions( self ):
|
||||
|
||||
self.resdefDict = self.resistorPlateDict
|
||||
if self.resistorType == "RPOLY2PH" :
|
||||
|
||||
if self.direction == "vertical" : keysList = ["YMin","YMax","width"]
|
||||
if self.direction == "horizontal" : keysList = ["XMin","XMax","width"]
|
||||
|
||||
self.resdefDict[keysList[0]] = self.resdefDict[keysList[0]] - self.minWidth_contact/4
|
||||
self.resdefDict[keysList[1]] = self.resdefDict[keysList[1]] + self.minWidth_contact/4
|
||||
|
||||
if self.resDim["width"] > self.resPlateExtensions_minWidth :
|
||||
self.resdefDict[keysList[2]] = self.resdefDict[keysList[2]] + self.minWidth_contact/2
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def drawResDefLayer( self, layer ):
|
||||
|
||||
self.computeResDefDimensions()
|
||||
if self.direction == "vertical" : Vertical.create ( self.nets[0], layer, self.resdefDict["XCenter"], self.resdefDict["width"], self.resdefDict["YMin"], self.resdefDict["YMax"] )
|
||||
if self.direction == "horizontal" : Horizontal.create ( self.nets[0], layer, self.resdefDict["YCenter"], self.resdefDict["width"], self.resdefDict["XMin"], self.resdefDict["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) :
|
||||
segment = Contact.create( net, layer, firstCutXCenter + i*(width_cut + spacing_cut), firstCutYCenter, width_cut, height_cut ) if direction == 'horizontal' else Contact.create( net, layer, firstCutXCenter, firstCutYCenter + i*(height_cut + spacing_cut), width_cut, 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 ScriptMain( **kw ):
|
||||
|
||||
editor = None
|
||||
if kw.has_key('editor') 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", snakeMode = False, bends = 0 ):
|
||||
#resistor = Resistor( device, nets, "RPOLY2PH", 50, direction = "vertical" )
|
||||
resistor = Resistor( device, nets, "RPOLY2PH", 50, direction = "horizontal" ) #l = 0.8 dogBone
|
||||
# resistor = Resistor( device, nets, "RPOLYH", 2000, direction = "horizontal" ) #RPOLYH normal
|
||||
# resistor = Resistor( device, nets, "RPOLY2PH", 100, direction = "horizontal" ) #RPOLY2PH normal
|
||||
# resistor = Resistor( device, nets, "RPOLY2PH", 25, direction = "vertical" ) #L=w/2
|
||||
resistor.create()
|
||||
|
||||
AllianceFramework.get().saveCell( device, Catalog.State.Views )
|
||||
|
||||
return True
|
||||
|
|
@ -6,6 +6,10 @@ from helpers import trace
|
|||
class Rules ( object ):
|
||||
|
||||
ruleSet = [ 'minSpacing_nWell'
|
||||
, 'minWidth_pImplant'
|
||||
, 'minSpacing_pImplant'
|
||||
, 'minSpacing_rpolyh_pImplant'
|
||||
, 'minEnclosure_pImplant_poly2con'
|
||||
, 'minEnclosure_nImplant_active'
|
||||
, 'minEnclosure_pImplant_active'
|
||||
, 'minSpacing_nImplant_pImplant'
|
||||
|
@ -57,6 +61,7 @@ class Rules ( object ):
|
|||
, 'minWidth_cpoly'
|
||||
, 'minWidth_poly2'
|
||||
, 'minWidth_rpolyh'
|
||||
, 'minWidthHighPrec_rpolyh'
|
||||
, 'minSpacing_cpoly'
|
||||
, 'minSpacing_poly2'
|
||||
, 'minSpacing_rpolyh'
|
||||
|
@ -70,6 +75,18 @@ class Rules ( object ):
|
|||
, 'PIPCap'
|
||||
, 'MIMPerimeterCap'
|
||||
, 'PIPPerimeterCap'
|
||||
, 'RPOLYHSheetRes'
|
||||
, 'RPOLY2PHSheetRes'
|
||||
, 'MET1RPOLYHContRes'
|
||||
, 'minWidth_hres'
|
||||
, 'minSpacing_hres'
|
||||
, 'minEnclosure_hres_poly2'
|
||||
, 'minSpacing_hres_poly1'
|
||||
, 'minSpacing_hres_poly2'
|
||||
, 'minSpacing_hres_active'
|
||||
, 'corrFactor90'
|
||||
, 'corrFactor135'
|
||||
, 'minRpolyhSquares'
|
||||
]
|
||||
|
||||
def __init__ ( self, dtr ):
|
||||
|
@ -86,8 +103,15 @@ class Rules ( object ):
|
|||
value = None
|
||||
words = attribute.split( '_' )
|
||||
try:
|
||||
if len(words) == 1 and words[0].endswith('Cap'): value = self.dtr.getUnitRule( words[0] ).getValue()
|
||||
elif len(words) < 4: value = self.dtr.getPhysicalRule( *tuple(words) ).getValue()
|
||||
if len(words) == 1:
|
||||
if words[0].endswith('Cap' ): value = self.dtr.getUnitRule( words[0] ).getValue()
|
||||
if words[0].endswith('ContRes' ): value = self.dtr.getUnitRule( words[0] ).getValue()
|
||||
if words[0].endswith('Res' ): value = self.dtr.getUnitRule( words[0] ).getValue()
|
||||
if words[0].endswith('ctor90' ): value = self.dtr.getUnitRule( words[0] ).getValue()
|
||||
if words[0].endswith('ctor135' ): value = self.dtr.getUnitRule( words[0] ).getValue()
|
||||
if words[0].endswith('quares' ): value = self.dtr.getUnitRule( words[0] ).getValue()
|
||||
elif len(words) < 4:
|
||||
value = self.dtr.getPhysicalRule( *tuple(words) ).getValue()
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
V ALLIANCE : 6
|
||||
H capacitor,P,12/12/2019,100
|
||||
A 0,0,27184,27184
|
||||
EOF
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
-- =======================================================================
|
||||
-- Coriolis Structural VHDL Driver
|
||||
-- Generated on Dec 12, 2019, 11:42
|
||||
--
|
||||
-- To be interoperable with Alliance, it uses it's special VHDL subset.
|
||||
-- ("man vhdl" under Alliance for more informations)
|
||||
-- =======================================================================
|
||||
|
||||
entity capacitor is
|
||||
port ( b0 : linkage bit
|
||||
; b1 : linkage bit
|
||||
; b2 : linkage bit
|
||||
; b3 : linkage bit
|
||||
; t0 : linkage bit
|
||||
; t1 : linkage bit
|
||||
; t2 : linkage bit
|
||||
; t3 : linkage bit
|
||||
);
|
||||
end capacitor;
|
||||
|
||||
architecture structural of capacitor is
|
||||
|
||||
|
||||
|
||||
begin
|
||||
|
||||
end structural;
|
||||
|
Loading…
Reference in New Issue