coriolis/oroshi/python/CapacitorRouted.py

768 lines
49 KiB
Python
Raw Normal View History

First stage in analog capacitor integration * Bug: In Technology::getPhysicalRule(), if the named layerdo not exists, throw an exception instead of silently putting a NULL pointer inside a rule. * New: In Hurricane/Analog, new parameters classes for capacitor devices: - Analog::Matrix, a matrix of null or positives integers to encode capacitor matrix matching. - Analog::Capacities, a list of float values for all component of a multi-capacitor. * New: In Hurricane::Script, add a "getFileName()" method to get the full path name of the Python module. * Change: In Analog::LayoutGenerator, completly remove the logger utility as it is no longer used. Simply print error messages instead. * Change: In Analog::MetaCapacitor, rename top & bottom plate 'T' & 'B'. Accessors renamed in "getTopPlate()" & "getBottomPlate()". * New: In Analog::MultiCapacitor, complete rewrite. Makes use of the new parameters "capacities" and "matrix". Dynamically generates it's terminals as we do not know beforehand how many capacitors could be put in it. * Bug: In isobar/PyHurricane.h, in Type object definition, do not prepend a "Py" to class name (so the keep the C++ name). * Change: In CRL/etc/scn6m_deep_09/devices.py, add entry for the new capacitor generator. * New: In oroshi/python/ParamsMatrix, add a "family" entry in the [0,0] element to distinguish between transistor, capacitor and resistor. (this is the matrix of values returned to the LayoutGenerator after device generation). Now have one "setGlobalParams()" function per family. * New: In oroshi/python/Rules.py, added DTR rules needed by capacitors. Catch exceptions if something wrong append when we extract the rules from the technology. * New: In Bora, the devices are no longer *only* transistors, so the possibles configurations are no longer defined only by a number of fingers. We must be able to support any kind of range of configuration. So the explicit range of number of fingers is replaced by a base class ParameterRange, and it's derived classes: - Bora::StepParameterRange, to encode the possible number of fingers of a transistor (the former only possibility). - Bora::MatrixParameterRange, to encode all the possible matching scheme for a capacitor. As there is no way to compress it, this is a vector of Matrix (from Analog). * Change: In Bora::DSlicingNode::_place(), the ParameterRange has to be set on the right configuration (through the index) before being called. The generation parameters are taken from the active item in the ParameterRange. * Change: In Bora::NodeSets::create(), iterate over the ParameterRange to build all the configuration. Adjustement to the routing gauge pitchs are moved into the DBoxSet CTOR to save a lot of code. Semantic change: the index in the NodeSets is now the index in the associated ParameterRange and no longer the number of fingers of a transistor. Check that the ParameterRange dynamic class is consitent with the device family. * Change: In Bora::DBoxSet, same semantic change as for NodeSets, the number of finger become an index in ParameterRange. In DBoxSet::create(), now also perform the abutment box adjustement to the RoutingGauge, if possible. * New: In Karakaze/python/AnalogDesign.py, add support for Capacitor devices.
2019-11-07 10:05:49 -06:00
#!/usr/bin/python
import sys
from Hurricane import *
from CRL import *
import helpers
from helpers.io import ErrorMessage as Error
from helpers import trace
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.
# \image html Layout.png "Layout" width=.1\linewidth
# An elementary capacitor unit can be a part of C1 or C2 according to the matching scheme. However, to respect common-centroid layout specifications, for C1 and C2 to be equal, the matrix number of colums and number of rows must be both even. Addionnally, the number of elementary capacitors dedicated to C1 must be equal to those dedicated to C2. These two conditions are tested in one of the class methods. An exception is raised if at least one of the two is not respected.
class RoutMatchedCapacitor( CapacitorUnit, CapacitorStack, VerticalRoutingTracks ):
rules = oroshi.getRules()
## A special method used to customize the class instance to an initial state in which :
# - the class attirbutes describing positions and dimensions of the layout are computed in dedicated class methods,
# - the attributes related to the capacitor matrix are copied from the \c CapacitorStack instance.
#
# Position and dimensions attributes, also refered by layout variables, in Figure 2, are defined below :
# \param device The Hurricane AMS device onto which the layout is drawn.
# \param capacitorInstance Instance of \c CapacitorStack class.
# \param capacitor A nested list containing the matrix elements, which are \c CapacitorUnit objects.
# \param matchingScheme A nested list, with equal dimensions as \c capacitor attribute, containing assignements of matrix elementary units to C1 and C2, identified by 1 and 2, respectively. Therefore, \c self.matchingScheme content is a succession of 1 and 2 values, defined as \ capacitor identifiers. For example, given a matrix of dimensions 2x2, the matching scheme can be \f$ [ [1,2], [1,2] ] or [ [2,1], [2,1] ] \f$. The first sub-list dictates that the first elementary capacitor, \f$ C_{00} \f$. The second element \f$ C_{01} \f$ is affected to C2 and so on. An immediate and obvious consequence to this, is that an error is raised if \c self.matchingSchem and \c self.capacitor dimensions are not identical or if \c self.matchingScheme content is different from supported capacitor identifiers, '1' and '2'.
#
# \param capacitorType Supported types of capacitors are MIM and PIP only. An exception is raised otherwise.
# \param abutmentBox The matrix's abutment box.
# \param matrxiDim The matrix dimensions, also equal to \c self.matchingScheme nested list dimensions.
# \param abutmentBox_spacing The spacing between elementary units in the matrix. It is computed in \c CapacitorStack and is reloaded in \c RoutMatchedCapacitor. \c self.abutmentBox_spacing includes, vertical routeing tracks width and minimum allowed spacing between two adjacent ones.
# \param hRoutingLayer_width The width of horizontal routeing layers in metal 2, which connect capacitors plates to vertical routeing tracks.
# \param vRoutingTrack_width The width of vertical routeing tracks in metal 3, which connects identical nets together ( ie : bottom plates of C1, top plates of C2, bottom plates of C2 and top plates of C2 ).
# \param hRoutingTrack_width The width of horizontal routeing tracks in metal 2, which connect identical vertical routeing tracks together.
# \param minSpacing_hRoutingTrack Minimum spacing between horizontal routeing tracks. Wide metal 2 specifications are considered since metal 2 dimensions may exceed 10 \f$ m\f$.
#
#\remark For more information about wide metal specifications, refer to ENG-183_rev8.pdf technology manual.
#
# \param minimumPosition The ordinate of the top plate's routeing layer's bottom extremity after stretching.
# \param maximumPosition The ordinate of the top plate's routeing layer's top extremity, also equivalent to the top plate's top extremity.
# \param vRoutingTrackXCenter A nested list of ordered dictionaries, with dimensions equal to \c self.matrixDim, containing abcissas of vertical routeing tracks. All sub-lists' lengths are identical and are equal to 2. The first and second elements describe position of top plate track and bottom plate track, respectively. For example, given a matrix of dimensions 2x2, \c self.vRoutingTrackXCenter can be [[0, 2], [4,6], [8,10]] \f$ \mu m\f$. Elements of this nested list have particular indexing as described in Figure 2.
#
# \param hRoutingtrackYCenter A nested dicitonary containing two keys, \c topTracks and \c bottomTracks. Each key contains as value a dictionary describing centers' ordinates of four parallel horizontal tracks. The reason why four tracks are needed on top and bottom positions of the matrix is that four nets are used, two for every capacitor \c Ci, were \c i is in [1,2].
# \param hRoutingLayerYCenter A nested dicitonary containing two keys, \c top and \c bottom. Each key contains as value a dictionary describing centers' ordinates of horizontal routeing layers.
# \param vRoutingTrackDict A dictionary of routeing tracks top and bottom extremities ordinates.
# \param topPlateStretching Since not only the same metal 2 layer is used to draw top/bottom plates connections to vertical tracks but also the two plates are superimposed, the top plate's routeing tracks is stretched. \c self.topPlateStretching is therefore the length added to top plate's routeing layer in order to avoid short circuits between top and bottom plates routeing to vertical tracks since the same metal is used for both.
def __init__( self, vRTInstance ) :
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.dummyRingVRLayersDict = {}
self.hRoutingLayer_width = 0
self.hRoutingTrack_width = vRTInstance.hRoutingTrack_width #gethRoutingTrack_width()
self.minSpacing_hRoutingTrack = 0
self.minimumPosition = 0
self.maximumPosition = 0
self.hRoutingtrackYCenter = { "topTracks" : {} , "bottomTracks" : {} }
self.hRoutingLayerYCenter = { "topPlate" : [] , "bottomPlate" : [] }
self.vRTInstance = vRTInstance
self.topPlateStretching = 0
return
## Draws the complete layout given the capacitor matrix. \c route method is succession of calls to user-defined methods inside a newly created \c Updatesession. The following tasks are excecuted :
# -# A nex \c UpdateSession is created,
# -# all required physical layers are loaded,
# -# technology rules are defined according to capacitor type,
# -# layout dimension parameters are computed,
# -# routeing tracks and layers are drawn,
# -# top plates are stretched,
# -# all required cuts are drawn,
# -# The \c UpdateSession is closed.
#
# Meanwhile, an exception is raised when the entered \c capacitor is not a capacitor matrix or if the capacitor type is unsupported.
def route( self, bbMode = False ):
UpdateSession.open ()
self.setRules ()
if not( self.capacitorInstance.__isUnitCap__() ):
if CapacitorStack.__isMatchingSchemeOK__(self):
layersDict = self.setLayers ()
bondingBox = self.computeDimensions( bbMode )
if not bbMode :
self.drawHRLayers ( layersDict["xPlateHRLayer" ] )
self.drawHRoutingTracks ( layersDict["hRoutingTracks" ] )
self.__stretchTopPlates__( self.capacitor , layersDict["xPlateRLayer" ] )
self.drawCuts ( layersDict["cut_hRoutingLayer_vRoutingTracks"] , layersDict["cut_hRoutingTracks_vRoutingTracks"], layersDict["cut_hRoutingLayer_topPlate"] )
if self.dummyRing == True:
self.routeDummyRing (layersDict ["xPlateVRLayer_dummyRing" ] , layersDict["cut_hRoutingTracks_vRoutingTracks"] )
else : raise Error( 1, 'drawHRLayers() : Invalid matching scheme : "%s".' % self.matchingScheme )
else : raise Error( 1,'An input matrix is required.' % self.matrixDim )
UpdateSession.close ()
return bondingBox
def routeDummyRing( self, routeingLayer, cutLayer ):
net = self.nets[-1][1]
bottomPlateRLayer_width = self.dummyRingCapacitor[0][0].getBotPlateRLayerWidth()
topPlateRLayer_width = self.dummyRingCapacitor[0][0].getTopPlateRLayerWidth()
self.computeDummyRingDimensions ()
self.routeLeftAndRightSides (net, routeingLayer, bottomPlateRLayer_width, topPlateRLayer_width )
self.routeTopOrBottomSide (net, "topSide" , routeingLayer , bottomPlateRLayer_width, topPlateRLayer_width)
self.routeTopOrBottomSide (net, "bottomSide" , routeingLayer , bottomPlateRLayer_width, topPlateRLayer_width)
self.drawDummyRing_hRTracks_Cuts (net, "topSide" , cutLayer )
self.drawDummyRing_hRTracks_Cuts (net, "bottomSide" , cutLayer )
return
def routeLeftAndRightSides( self, dummyNet, routeingLayer, bottomPlateRLayer_width, topPlateRLayer_width ) :
for i in range(0,2):
bottomPlateLeftRLayerXCenter = self.dummyRingCapacitor[0][0 + i*(-1)].getBotPlateLeftRLayerXCenter()
bottomPlateRightRLayerXCenter = self.dummyRingCapacitor[0][0 + i*(-1)].getBotPlateRightRLayerXCenter()
Vertical.create ( dummyNet, routeingLayer , bottomPlateLeftRLayerXCenter , bottomPlateRLayer_width , self.dummyRingVRLayersDict["YMin"] , self.dummyRingVRLayersDict["YMax"] )
Vertical.create ( dummyNet, routeingLayer , bottomPlateRightRLayerXCenter , bottomPlateRLayer_width , self.dummyRingVRLayersDict["YMin"] , self.dummyRingVRLayersDict["YMax"] )
for i in range(0,2):
topPlateRLayerXCenter = self.dummyRingCapacitor[0][0 + i*(-1)].topPlateRLayerDict["XCenter"]
Vertical.create ( dummyNet, routeingLayer , topPlateRLayerXCenter , topPlateRLayer_width , self.dummyRingVRLayersDict["YMin"] , self.dummyRingVRLayersDict["YMax"] )
return
def routeTopOrBottomSide( self, dummyNet, side, routeingLayer, bottomPlateRLayer_width, topPlateRLayer_width):
if side == "topSide" :
dummyRingElement = self.dummyRingCapacitor[-1]
dyTarget = self.vRoutingTrackDict ["YMax"]
elif side == "bottomSide" :
dummyRingElement = self.dummyRingCapacitor[0]
dyTarget = self.vRoutingTrackDict ["YMin"]
else : raise Error(1,'routeTopOrBottomSide() : side parameter must be either "topSide" or "bottomSide" : %s' %side)
for j in range(1,len(self.dummyRingCapacitor[0])-1):
bottomPlateLeftRLayerXCenter = dummyRingElement[j].getBotPlateLeftRLayerXCenter()
bottomPlateRightRLayerXCenter = dummyRingElement[j].getBotPlateRightRLayerXCenter()
Vertical.create ( dummyNet, routeingLayer , bottomPlateLeftRLayerXCenter , bottomPlateRLayer_width , dummyRingElement[j].getBotPlateRLayerYMin() , dyTarget )
Vertical.create ( dummyNet, routeingLayer , bottomPlateRightRLayerXCenter , bottomPlateRLayer_width , dummyRingElement[j].getBotPlateRLayerYMin() , dyTarget )
topPlateRLayerXCenter = dummyRingElement[j].topPlateRLayerDict["XCenter"]
Vertical.create ( dummyNet, routeingLayer , topPlateRLayerXCenter , topPlateRLayer_width , dummyRingElement[j].getTopPlateRLayerYMin() , dyTarget )
return
## Defines technology rules used to draw the layout. Some of the rules, namely those describing routeing layers and tracks are applicable for both MIM and PIP capacitors. However, cuts rules are different. \remark All \c CapacitorStack class rules are also reloaded in this class. An exception is raised if the entered capacitor type is unsupported.
# \return a dictionary with rules labels as keys and rules content as values.
def setRules ( self ):
VerticalRoutingTracks.setRules ( self )
CapacitorUnit.__setattr__ ( self, "minSpacing_hRoutingLayer" , RoutMatchedCapacitor.rules.minSpacing_metbot )
CapacitorUnit.__setattr__ ( self, "minSpacing_hRoutingTrackCut" , RoutMatchedCapacitor.rules.minSpacing_cut2 )
CapacitorUnit.__setattr__ ( self, "minSpacing_vRoutingTrackCut" , RoutMatchedCapacitor.rules.minSpacing_cut2 )
CapacitorUnit.__setattr__ ( self, "minSpacing_hRoutingLayer_vRoutingTrack_cut" , RoutMatchedCapacitor.rules.minSpacing_cut2 )
if self.capacitorType == 'MIMCap':
CapacitorUnit.__setattr__( self, "minWidth_hRoutingLayer_topPlate_cut" , RoutMatchedCapacitor.rules.minWidth_cut2 )
CapacitorUnit.__setattr__( self, "minSpacing_hRoutingLayer_topPlate_cut" , RoutMatchedCapacitor.rules.minSpacing_cut2 )
CapacitorUnit.__setattr__( self, "minEnclosure_hRoutingLayer_topPlate_cut" , RoutMatchedCapacitor.rules.minEnclosure_metal2_cut2 )
elif self.capacitorType == 'PIPCap' :
CapacitorUnit.__setattr__( self, "minWidth_hRoutingLayer_topPlate_cut" , RoutMatchedCapacitor.rules.minWidth_cut1 )
CapacitorUnit.__setattr__( self, "minSpacing_hRoutingLayer_topPlate_cut" , RoutMatchedCapacitor.rules.minSpacing_cut1 )
CapacitorUnit.__setattr__( self, "minEnclosure_hRoutingLayer_topPlate_cut" , RoutMatchedCapacitor.rules.minEnclosure_metal2_cut1 )
else: raise Error( 1, 'setRules() : Unsupported capacitor type : %s.' %self.capacitorType )
return
## Defines all physical layers used to draw the layout. Layers are loaded using \c DataBase API. The same routeing layers are used for both capacitor types except cuts layers that connect top plates to vertical routeing tracks. Basicaly, metal 2, meta 3, cut 1 and cut 2 are the ones defined.
# \return a dictionary composed of layers labels as keys and layers as values.
def setLayers( self ):
layersDict = {}
layersDict["hRoutingTracks" ] = DataBase.getDB().getTechnology().getLayer("metal2" )
layersDict["xPlateHRLayer" ] = DataBase.getDB().getTechnology().getLayer("metal2" )
layersDict["xPlateRLayer" ] = CapacitorUnit.getLayers( self )["bottomPlateRLayer"]
layersDict["cut_hRoutingTracks_vRoutingTracks"] = DataBase.getDB().getTechnology().getLayer("cut2" )
layersDict["cut_hRoutingLayer_vRoutingTracks" ] = DataBase.getDB().getTechnology().getLayer("cut2" )
layersDict["cut_hRoutingLayer_topPlate" ] = DataBase.getDB().getTechnology().getLayer("cut2" ) if self.capacitorType == 'MIMCap' else DataBase.getDB().getTechnology().getLayer("cut1")
if self.dummyRing == True:
layersDict["xPlateVRLayer_dummyRing" ] = DataBase.getDB().getTechnology().getLayer("metal3" ) if self.capacitorType == 'MIMCap' else DataBase.getDB().getTechnology().getLayer("metal1")
return layersDict
## Computes, through simple instructions and functions calls, layout variables detailed in Figure 2.
def computeDimensions ( self, bbMode ) :
print 'routMatchedCapacitor.computeDimensions()'
bondingBoxDimensions = {}
self.hRoutingLayer_width = max( self.minWidth_hRoutingLayer, self.minWidth_hRoutingLayer_vRoutingTrack_cut + 2*self.minEnclosure_hRoutingLayer_vRoutingTrack_cut, self.minWidth_hRoutingLayer_topPlate_cut + 2*self.minEnclosure_hRoutingLayer_topPlate_cut )
self.abutmentBox_spacing = self.capacitorInstance.abutmentBox_spacing
self.vRoutingTrack_spacing = self.capacitorInstance.getVRoutingTrack_spacing()
abutmentBoxXMin = self.capacitorInstance.computeAbutmentBoxDimensions( self.abutmentBox_spacing )["XMin"] #getAbutmentBox_spacing()
abutmentBoxYMin = self.capacitorInstance.computeAbutmentBoxDimensions( self.abutmentBox_spacing )["YMin"] #getAbutmentBox_spacing()
abutmentBoxYMax = abutmentBoxYMin + self.capacitorInstance.computeAbutmentBoxDimensions( self.abutmentBox_spacing )["height"] #getAbutmentBox_spacing()
self.minimumPosition = self.vRTInstance.minimumPosition #abutmentBoxYMin - self.__setStretching__()
self.maximumPosition = self.vRTInstance.maximumPosition #abutmentBoxYMax + self.__setStretching__()
self.vRoutingTrackDict = self.vRTInstance.vRoutingTrackDict #self.minimumPosition - 4*self.hRoutingTrack_width - 4*self.minSpacing_hRoutingTrack
translation1 = self.vRoutingTrack_width/2 + self.vRoutingTrack_spacing
translation2 = translation1 + self.vRoutingTrack_width/2
self.vRoutingTrackXCenter = self.vRTInstance.vRoutingTrackXCenter #getvRoutingTrackXCenter()
if bbMode == True :
bondingBoxDimensions = self.computeBondingBoxDimInbbMode()
elif bbMode == False :
self.computeHRoutingTrackYCenter()
self.computeHRLayerYCenter()
else :raise Error(1, 'computeDimensions(): The bonding box mode parameter, "bbMode" must be either True or False : %s.' %bbMode )
print 'BOUNDING BOX:', bondingBoxDimensions
return bondingBoxDimensions
def computeBondingBoxDimInbbMode( self ):
bondingBoxDimensions = {}
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
if self.capacitorsNumber % 2 == 0 :
factor = self.capacitorsNumber
else :
factor = self.capacitorsNumber + 1 if self.matrixDim["columns"] % 2 == 0 else self.capacitorsNumber - 1
bondingBoxXMax = abutmentBoxXMax + factor*(self.vRoutingTrack_width + self.vRoutingTrack_spacing)
bondingBoxDimensions["YMin" ] = self.vRoutingTrackDict["YMin"]
bondingBoxYMax = self.vRoutingTrackDict["YMax"]
bondingBoxDimensions["width" ] = bondingBoxXMax - bondingBoxDimensions["XMin"]
bondingBoxDimensions["height" ] = bondingBoxYMax - bondingBoxDimensions["YMin"]
bondingBoxDimensions["surface"] = bondingBoxDimensions["width"]*bondingBoxDimensions["height"]
bondingBox = Box( bondingBoxDimensions["XMin"], bondingBoxDimensions["YMin"], bondingBoxXMax, bondingBoxYMax )
self.device.setAbutmentBox( bondingBox )
return bondingBoxDimensions
## Computes centers' ordinates of the eight horizontal routeing tracks. The tracks include four on top and four on bottom of the matrix. To do the computations, fist, center of the first bottom or top track, given in Figure 2, is computed. Then, all adjacent three centers are deduced by simples translation of the first one. Translation quantity is equal to the sum of distance between adjacent routeing tracks, self.hRoutingTracks_spacing, and half width of the routeing track itself, \c self.hRoutingTrack_width.
def computeHRoutingTrackYCenter( self ):
self.hRoutingtrackYCenter = { "topTracks" : {} , "bottomTracks" : {} }
self.hRoutingtrackYCenter["topTracks" ]["t0"] = self.maximumPosition + self.hRoutingTrack_width/2 + self.minSpacing_hRoutingTrack
self.hRoutingtrackYCenter["bottomTracks" ]["t0"] = self.minimumPosition - self.hRoutingTrack_width/2 - self.minSpacing_hRoutingTrack
keys = self.__setPlatesIds__()
print("key",keys)
print(" self.capacitorsNumber", self.capacitorsNumber)
# limit = 2*self.capacitorsNumber if self.dummyRing == False else 2*self.capacitorsNumber + 1
for k in range(1, len(keys)):
print('keysk',keys[k])
self.hRoutingtrackYCenter["topTracks" ][keys[k]] = self.hRoutingtrackYCenter["topTracks" ][keys[k-1]] + (self.hRoutingTrack_width + self.minSpacing_hRoutingTrack)
self.hRoutingtrackYCenter["bottomTracks" ][keys[k]] = self.hRoutingtrackYCenter["bottomTracks"][keys[k-1]] - (self.hRoutingTrack_width + self.minSpacing_hRoutingTrack)
print("keyskk",keys[k-1])
print("self.hRoutingtrackYCenter",self.hRoutingtrackYCenter)
# if self.dummyRing == True :
# self.hRoutingtrackYCenter["topTracks" ]["gnd"] = self.hRoutingtrackYCenter["topTracks" ][keys[k]] + (self.hRoutingTrack_width + self.minSpacing_hRoutingTrack)
# self.hRoutingtrackYCenter["bottomTracks" ]["gnd"] = self.hRoutingtrackYCenter["bottomTracks"][keys[k]] - (self.hRoutingTrack_width + self.minSpacing_hRoutingTrack)
print('self.hRoutingtrackYCenter',self.hRoutingtrackYCenter)
return
## Sets the stretching value of top plates. Then iteratively computes the centers of horizontal routeing layer regarding top and bottom plates.
def computeHRLayerYCenter ( self ):
shortCircuitLists = self.__findPossibleShortCircuits__()
self.topPlateStretching = self.__setStretching__( )
print(' shortCircuitLists', shortCircuitLists)
for i in range( 0,self.matrixDim["rows"] ):
print("i",i)
print("rows", self.matrixDim["rows"])
print("rowsCap", len(self.capacitor))
if shortCircuitLists[i][0] == 0 :
self.hRoutingLayerYCenter["bottomPlate"].append( [self.capacitor[i][0].getBottomPlateRightCutYMax ()] )
else :
bottomPlateYCenter0 = [(self.capacitor[i][0].getBottomPlateRightCutYMax () + self.capacitor[i][0].getBottomPlateRightCutYMin() ) /2 ]
self.hRoutingLayerYCenter["bottomPlate"].append(bottomPlateYCenter0)
topPlateYCenter = self.__setStretchingDySourceDyTarget__( self.capacitor[i][0], self.topPlateStretching )[1] + self.hRoutingLayer_width/2
self.hRoutingLayerYCenter["topPlate" ].append( [topPlateYCenter ] )
for j in range( 1,self.matrixDim["columns"] ):
topPlateYCenter = self.__setStretchingDySourceDyTarget__( self.capacitor[i][j], self.topPlateStretching )[1] + self.hRoutingLayer_width/2
if shortCircuitLists[i][j] == 0 :
self.hRoutingLayerYCenter["bottomPlate"][i].append( self.capacitor[i][j].getBottomPlateRightCutYMax () )
self.hRoutingLayerYCenter["topPlate" ][i].append( topPlateYCenter )
else :
bottomPlateYCenter = (self.capacitor[i][j].getBottomPlateRightCutYMax() + self.capacitor[i][j].getBottomPlateRightCutYMin()) /2
topPlateYCenter2 = topPlateYCenter + self.minSpacing_hRoutingLayer + self.hRoutingLayer_width
self.hRoutingLayerYCenter["bottomPlate"][i].append(bottomPlateYCenter)
self.hRoutingLayerYCenter["topPlate" ][i].append(topPlateYCenter2)
print('self.hRoutingLayerYCenter',self.hRoutingLayerYCenter)
return
def computeLayoutDimensionsInbbMode( self ):
bondingBoxDict = {}
bondingBoxDict["YMin" ] = self.hRoutingtrackYCenter["bottomTracks"]["botB"] - self.hRoutingTrack_width/2
bondingBoxDict["XMin" ] = self.vRoutingTrackXCenter[0 ][0] - self.vRoutingTrack_width/2
bondingBoxDict["height" ] = self.hRoutingtrackYCenter["topTracks" ]["botB"] + self.hRoutingTrack_width/2 - bondingBoxDict["YMin"]
bondingBoxDict["width" ] = self.vRoutingTrackXCenter[-1][1] + self.vRoutingTrack_width/2 - bondingBoxDict["XMin"]
self.bondingBox = Box( bondingBoxDict["XMin"], bondingBoxDict["YMin"], bondingBoxDict["XMin"] + bondingBoxDict["width"], bondingBoxDict["YMin"] + bondingBoxDict["height"] )
return bondingBoxDict
def computeDummyRingDimensions( self ):
for key in self.vRoutingTrackDict.keys():
self.dummyRingVRLayersDict[key] = self.vRoutingTrackDict[key]
return
## Iteratively draws horizontal routeing tracks on top and bottom positions of the matrix using physical layer \c routeingTracksLayer.
def drawHRoutingTracks( self , routeingTracksLayer ):
lastVRTId = self.vRoutingTrackXCenter[-1].keys()[-1]
firstVRTId = "t0"
# doDummyRing = 1 if self.dummyRing == True else 0
dxSource = self.vRoutingTrackXCenter[0][firstVRTId] - self.vRoutingTrack_width/2 if self.dummyRing == False else self.abutmentBox.getXMin()
dxTarget = self.vRoutingTrackXCenter[-1][lastVRTId] + self.vRoutingTrack_width/2 if self.dummyRing == False else self.abutmentBox.getXMax()
for i in self.hRoutingtrackYCenter.keys():
for j in self.hRoutingtrackYCenter[i].keys():
if j[0] == 't' :
net = self.nets[ int(j[1]) ][0]
elif j[0] == 'b' :
net = self.nets[ int(j[1]) ][1]
else :
print("hi")
net = self.nets[-1][1]
# net = self.nets[ int(j[1]) ][0] if j[0] == 't' else self.nets[ int(j[1]) ][1]
print('net',net)
Horizontal.create ( net , routeingTracksLayer, self.hRoutingtrackYCenter[i][j] , self.hRoutingTrack_width , dxSource , dxTarget )
return
## Iteratively draws the horizontal routeing layers starting with bottom left elementary capacitor \f$ C_{00} \f$.
def drawHRLayers( self, xPlateRLayer ) :
for i in range( 0,self.matrixDim["rows"] ):
for j in range( 0,self.matrixDim["columns"] ):
[ t , b ] = [ self.nets[self.matchingScheme[i][j]][0], self.nets[self.matchingScheme[i][j]][1] ]
dxDict = self.__computeConnections__( i,j, self.matchingScheme[i][j] )
Horizontal.create ( t, xPlateRLayer , self.hRoutingLayerYCenter["topPlate" ][i][j] , self.hRoutingLayer_width , dxDict["topPlate" ][ "source" ] , dxDict["topPlate" ][ "target" ] )
Horizontal.create ( b, xPlateRLayer , self.hRoutingLayerYCenter["bottomPlate"][i][j] , self.hRoutingLayer_width , dxDict["bottomPlate" ][ "source" ] , dxDict["bottomPlate" ][ "target" ] )
return
## Draws all required cuts using physical layers :
# - \c layer_hRTrack_hRLayer to connect bottom plates to vertical routeing tracks,
# - \c layer_tracksCut to connect vertical routeing tracks to horizontal ones,
# - \c layer_topPlateCut to connect top plates to vertical routeing tracks.
# ALso in \c drawCuts, nUmber of maximum cuts number on every layer is computed and cuts enclosure is adjusted according to layer's width.
def drawCuts( self, layer_hRTrack_hRLayer, layer_tracksCut, layer_topPlateCut ):
cutNumber = CapacitorUnit.cutMaxNumber( self, self.vRoutingTrack_width, self.minWidth_vRoutingTrackCut, self.minSpacing_vRoutingTrackCut , self.minEnclosure_vRoutingTrackCut )
enclosure_hRoutingTrack_cut = (self.vRoutingTrack_width - cutNumber*self.minWidth_hRoutingTrackCut - (cutNumber - 1)*self.minSpacing_hRoutingTrackCut)/2
self.drawCuts_vRoutingTrack_HRLayer ( layer_hRTrack_hRLayer, cutNumber, enclosure_hRoutingTrack_cut )
self.drawCuts_vRoutingTrack_hRoutingTrack ( layer_tracksCut , cutNumber, enclosure_hRoutingTrack_cut )
self.drawCuts_stretchedTopPlate ( layer_topPlateCut )
return
def drawCuts_vRoutingTrack_HRLayer( self, cutLayer, cutNumber, enclosure_cut ):
[ vRoutingTrackXCenter, cutXMin ] = [{}, {}]
for i in range( 0, self.matrixDim["rows"] ):
for j in range( 0, self.matrixDim["columns"] ):
if ( j % 2 == 0 ):
leftVRTIds = self.capacitorIds[0:self.capacitorsNumber/2] if (self.capacitorsNumber % 2 == 0) else self.capacitorIds[0: int(self.capacitorsNumber/2+1)]
rightVRTIds = self.capacitorIds[self.capacitorsNumber/2 : self.capacitorsNumber] if (self.capacitorsNumber % 2 == 0) else self.capacitorIds[int(self.capacitorsNumber/2+1) : self.capacitorsNumber]
else:
leftVRTIds = self.capacitorIds[self.capacitorsNumber/2 : self.capacitorsNumber] if (self.capacitorsNumber % 2 == 0) else self.capacitorIds[int(self.capacitorsNumber/2+1) : self.capacitorsNumber]
rightVRTIds = self.capacitorIds[0:self.capacitorsNumber/2] if (self.capacitorsNumber % 2 == 0) else self.capacitorIds[0: int(self.capacitorsNumber/2+1)]
index1 = j if self.matchingScheme[i][j] in leftVRTIds else j+1
[topPlateLabel, bottomPlateLabel ] = [self.__setPlatesLabels__(i,j)["t"] , self.__setPlatesLabels__(i,j)["b"]]
vRoutingTrackXCenter["topPlate" ] = self.vRoutingTrackXCenter[index1][topPlateLabel + str( self.matchingScheme[i][j] )]
vRoutingTrackXCenter["bottomPlate"] = self.vRoutingTrackXCenter[index1][bottomPlateLabel + str( self.matchingScheme[i][j] )]
cutXMin["topPlate" ] = vRoutingTrackXCenter["topPlate" ] - self.vRoutingTrack_width/2 + enclosure_cut + self.minWidth_hRoutingTrackCut/2
cutXMin["bottomPlate"] = vRoutingTrackXCenter["bottomPlate"] - self.vRoutingTrack_width/2 + enclosure_cut + self.minWidth_hRoutingTrackCut/2
[ t , b ] = [ self.nets[self.matchingScheme[i][j]][0] , self.nets[self.matchingScheme[i][j]][1] ]
self.drawOneCut_vRoutingTrack_HRLayer( t, cutLayer, cutXMin["topPlate" ], self.hRoutingLayerYCenter["topPlate" ][i][j], cutNumber )
self.drawOneCut_vRoutingTrack_HRLayer( b, cutLayer, cutXMin["bottomPlate"], self.hRoutingLayerYCenter["bottomPlate"][i][j], cutNumber )
return
## Draws one cut, in layer \c cutLayer, in order to connect a vertical routeing track, at position \c cutXMin in metal 2, and a horizontal routeing track, at position \c cutYMin in metal 3.
def drawOneCut_vRoutingTrack_HRLayer( self, net, cutLayer, cutXMin, cutYMin, cutNumber ):
CapacitorUnit.cutLine(self,net,cutLayer,cutXMin,cutYMin,self.minWidth_hRoutingLayer_vRoutingTrack_cut,self.minWidth_hRoutingLayer_vRoutingTrack_cut,self.minSpacing_hRoutingLayer_vRoutingTrack_cut,cutNumber,'horizontal')
return
## Draws cuts to connect vertical routeing tracks in metal 2 and horizontal routeing tracks in metal 3.
def drawCuts_vRoutingTrack_hRoutingTrack( self,cutLayer, cutNumber, enclosure_cut ):
keysList = self.hRoutingtrackYCenter.keys()
for i in range(0, len(self.vRoutingTrackXCenter) ):
for k in self.vRoutingTrackXCenter[i]:
if self.vRoutingTrackXCenter[i][k] != None :
for l in range(0, 2) :
net = self.nets[ int(k[1]) ][0] if k[0] == 't' else self.nets[ int(k[1]) ][1]
cutXMin = self.vRoutingTrackXCenter[i][k] - self.vRoutingTrack_width/2 + enclosure_cut + self.minWidth_hRoutingTrackCut/2
CapacitorUnit.cutLine(self,net,cutLayer,cutXMin,self.hRoutingtrackYCenter[keysList[l]][k],self.minWidth_hRoutingTrackCut,self.minWidth_hRoutingTrackCut,self.minSpacing_hRoutingTrackCut,cutNumber,'horizontal')
return
# \param cutLayer
def drawCuts_stretchedTopPlate( self, cutLayer ):
layer_width = self.capacitor[0][0].getTopPlateRLayerWidth()
cutNumber = CapacitorUnit.cutMaxNumber( self, layer_width , self.minWidth_hRoutingLayer_topPlate_cut, self.minSpacing_hRoutingLayer_topPlate_cut , self.minEnclosure_hRoutingLayer_topPlate_cut )
enclosure_hRoutingTrack_cut = (layer_width - cutNumber*self.minWidth_hRoutingLayer_topPlate_cut - (cutNumber - 1)*self.minSpacing_hRoutingLayer_topPlate_cut)/2
for i in range(0, self.matrixDim["rows"] ):
for j in range(0, self.matrixDim["columns"] ):
tNet = self.nets[self.matchingScheme[i][j]][0]
cutXMin = self.capacitor[i][j].getTopPlateRLayerXMin() + enclosure_hRoutingTrack_cut + self.minWidth_hRoutingLayer_topPlate_cut/2
CapacitorUnit.cutLine( self, tNet, cutLayer, cutXMin , self.hRoutingLayerYCenter["topPlate"][i][j] , self.minWidth_hRoutingLayer_topPlate_cut, self.minWidth_hRoutingLayer_topPlate_cut, self.minSpacing_hRoutingLayer_topPlate_cut, cutNumber, 'horizontal' )
return
def drawDummyRing_hRTracks_Cuts( self, dummyNet, side, cutLayer ):
if side == "topSide" :
dummyRingElement = self.dummyRingCapacitor[-1]
key = "topTracks"
elif side == "bottomSide" :
dummyRingElement = self.dummyRingCapacitor[0]
key = "bottomTracks"
else : raise Error(1,'routeTopOrBottomSide() : side parameter must be either "topSide" or "bottomSide" : %s' %side)
topPlateLayer_width = dummyRingElement[0].getTopPlateRLayerWidth()
bottomPlateLayer_width = dummyRingElement[0].getBotPlateRLayerWidth()
topPlateCutNumber = CapacitorUnit.cutMaxNumber( self, topPlateLayer_width , self.minWidth_vRoutingTrackCut, self.minSpacing_vRoutingTrackCut , self.minEnclosure_vRoutingTrackCut )
bottomPlateCutNumber = CapacitorUnit.cutMaxNumber( self, bottomPlateLayer_width, self.minWidth_vRoutingTrackCut, self.minSpacing_vRoutingTrackCut , self.minEnclosure_vRoutingTrackCut )
topPlateCutEnclosure = (topPlateLayer_width - topPlateCutNumber *self.minWidth_vRoutingTrackCut - (topPlateCutNumber - 1)*self.minSpacing_vRoutingTrackCut)/2
# bottomPlateCutEnclosure = (bottomPlateLayer_width - bottomPlateCutNumber*self.minWidth_vRoutingTrackCut - (bottomPlateCutNumber - 1)*self.minSpacing_vRoutingTrackCut)/2
netsDistribution = self.__setPlatesIds__()
print("netsDistribution2",netsDistribution)
print("self.hRoutingtrackYCenter",self.hRoutingtrackYCenter)
for j in range(0,len(dummyRingElement)):
topPlateCutXCenter = dummyRingElement[j].getTopPlateRLayerXMin () + topPlateCutEnclosure + self.minWidth_vRoutingTrackCut/2
bottomPlateLeftCutXCenter = dummyRingElement[j].getBottomPlateLeftCutXMin() #dummyRingElement[j].getBotPlateLeftRLayerXMin () + bottomPlateCutEnclosure + self.minWidth_vRoutingTrackCut/2
bottomPlateRightCutXCenter = dummyRingElement[j].getBottomPlateRightCutXMin() #dummyRingElement[j].getBotPlateRightRLayerXMin() + bottomPlateCutEnclosure + self.minWidth_vRoutingTrackCut/2f
CapacitorUnit.cutLine( self, dummyNet, cutLayer, topPlateCutXCenter , self.hRoutingtrackYCenter[key][netsDistribution[-1]] , self.minWidth_vRoutingTrackCut,self.minWidth_vRoutingTrackCut,self.minSpacing_vRoutingTrackCut,topPlateCutNumber,'horizontal')
CapacitorUnit.cutLine( self, dummyNet, cutLayer, bottomPlateLeftCutXCenter , self.hRoutingtrackYCenter[key][netsDistribution[-1]] , self.minWidth_vRoutingTrackCut,self.minWidth_vRoutingTrackCut,self.minSpacing_vRoutingTrackCut,bottomPlateCutNumber,'horizontal')
CapacitorUnit.cutLine( self, dummyNet, cutLayer, bottomPlateRightCutXCenter, self.hRoutingtrackYCenter[key][netsDistribution[-1]] , self.minWidth_hRoutingTrackCut,self.minWidth_hRoutingTrackCut,self.minSpacing_hRoutingTrackCut,bottomPlateCutNumber,'horizontal')
return
## Iteratively performs top plates stretching for the capacitor matrix. Vertical segments are connected to top plate routeing layer.
# \param capacitor Capacitor matrix.
# \param rlayer Layer of the drawn vertical rectangle.
def __stretchTopPlates__( self, capacitor, rlayer ):
for i in range( 0, self.matrixDim["rows"] ):
for j in range( 0, self.matrixDim["columns"] ):
t = self.nets[self.matchingScheme[i][j]][0]
print('t',t)
self.__stretchTopPlateCompactCap__( t , capacitor[i][j], rlayer, j )
return
## Draws vertical stretched layers for a given elementary capacitor.
def __stretchTopPlateCompactCap__( self, net, capacitor, routeingLayer, j = 0 ):
topPlateRLayer_width = capacitor.getTopPlateRLayerWidth()
topPlateRLayerXCenter = capacitor.getTopPlateRLayerXCenter()
[ dySource , dyTarget ] = self.__setStretchingDySourceDyTarget__( capacitor, self.topPlateStretching )
Vertical.create ( net, routeingLayer , topPlateRLayerXCenter , topPlateRLayer_width , dySource , dyTarget )
return
## Sets the abcissas of the extremities of the vertical stretching to be applied to capacitor's top plates for a given elementary capacitor in the matrix.
# \param capacitor .values() Elementary unit capacitor.
# \param deltay Stretching value.
# \return A list that contains \c dySource and \dyTarget as top extremity and bottom extermity, respectively.
def __setStretchingDySourceDyTarget__( self, capacitor, deltay ):
dySource = capacitor.getTopPlateRLayerYMin()
dyTarget = dySource - deltay
return [ dySource , dyTarget ]
## Computes horizontal routeing layers source and target abcissas for top and bottom plates connections to its associated routeing track.
# \param (i,j) row and column indexes, respectively, in the matrix which describe the elementary capacitor position in the matrix.
# \param capacitorIdentifier equal to '1' if C1 and '2' if C2.
# \return A nested dicitionary. The overal dictionary is composed of keys equal to \c topPlate and \d bottomPlate and values equal to sub-dictionaries. The sub-dictionaries, are in their turn composed of two keys standing for the abcissa of the source and the abcissa of the target.
# \remark Naturally, an exception is raised if an unsupported capacitor identifier is given.
def __computeConnections__( self, i,j, capacitorIdentifier ):
if capacitorIdentifier in self.capacitorIds :
dxDict = { "bottomPlate": {}, "topPlate": {} }
if ( j % 2 == 0 ):
leftVRTIds = self.capacitorIds[0 :self.capacitorsNumber/2 ] if (self.capacitorsNumber % 2 == 0) else self.capacitorIds[0 : int(self.capacitorsNumber/2+1)]
rightVRTIds = self.capacitorIds[self.capacitorsNumber/2 : self.capacitorsNumber ] if (self.capacitorsNumber % 2 == 0) else self.capacitorIds[int(self.capacitorsNumber/2+1) : self.capacitorsNumber ]
else:
leftVRTIds = self.capacitorIds[self.capacitorsNumber/2 : self.capacitorsNumber ] if (self.capacitorsNumber % 2 == 0) else self.capacitorIds[int(self.capacitorsNumber/2+1) : self.capacitorsNumber ]
rightVRTIds = self.capacitorIds[0 : self.capacitorsNumber/2 ] if (self.capacitorsNumber % 2 == 0) else self.capacitorIds[0 : int(self.capacitorsNumber/2+1)]
[topPlateLabel, bottomPlateLabel ] = [self.__setPlatesLabels__(i,j)["t"] , self.__setPlatesLabels__(i,j)["b"]]
dxDict["topPlate" ][ "source" ] = self.capacitor[i][j].getTopPlateRLayerXMax () if self.matchingScheme[i][j] in leftVRTIds else self.capacitor[i][j].getTopPlateRLayerXMin()
dxDict["topPlate" ][ "target" ] = self.__findHRLDyTrarget__( i,j, topPlateLabel, leftVRTIds, rightVRTIds )
dxDict["bottomPlate" ][ "source" ] = self.capacitor[i][j].getBotPlateLeftRLayerXMax () if self.matchingScheme[i][j] in leftVRTIds else self.capacitor[i][j].getBotPlateRightRLayerXMin ()
# bottomPlateLabel = 'b' if self.dummyElement == False or not( self.__isCapacitorAdummy__(capacitorIdentifier) ) else 't'
print("bottomPlateLabel",bottomPlateLabel)
dxDict["bottomPlate" ][ "target" ] = self.__findHRLDyTrarget__( i, j, bottomPlateLabel, leftVRTIds, rightVRTIds )
else : raise Error(1, '__computeConnections__(): Unknown capacitor Id : %s.' %capacitorIdentifier )
print('dxDict',dxDict)
return dxDict
def __isCapacitorAdummy__( self, capacitorIdentifier ) :
state = False
if self.dummyElement == True :
if capacitorIdentifier == self.capacitorIds[-1] : state = True
else : raise Error(1,'The matrix contains no dummies because dummy element is "False".')
return state
def __setPlatesLabels__( self, i, j ):
platesLabels = {}
capacitorIdentifier = self.matchingScheme[i][j]
platesLabels["t"] = 't'
platesLabels["b"] = 'b' if self.dummyElement == False or not( self.__isCapacitorAdummy__(capacitorIdentifier) ) else 't'
return platesLabels
def __findHRLDyTrarget__( self, i,j, plateLabel, leftVRTIds, rightVRTIds ):
if plateLabel in ['t','b'] :
plateIndex = self.matchingScheme[i][j]
[ doLeft , doRight ] = [1,0] if self.matchingScheme[i][j] in leftVRTIds else [0,1]
xCenterList = leftVRTIds if [ doLeft , doRight ] == [1,0] else rightVRTIds
index1 = j if [ doLeft , doRight ] == [1,0] else j+1
for key in self.vRoutingTrackXCenter[index1].keys() :
if key == plateLabel + str(plateIndex) :
index2 = key
break
else : raise Error(1,'__findHRLDyTrarget__() : Plate label must be "t" for top plate and "b" for bottom plate. The given label is : %s.' %plateLabel)
return self.vRoutingTrackXCenter[index1][index2] - doLeft*self.vRoutingTrack_width/2 + doRight*self.vRoutingTrack_width/2
def __setPlatesIds__( self ):
keys = []
for k in range(0, len(self.nets)):
keys.append( 't' + str(k) )
keys.append( 'b' + str(k) )
if self.dummyRing == True or self.dummyElement == True : keys = keys[0:len(keys)-1]
return keys
def __findPossibleShortCircuits__( self ):
shortCircuitLists = []
self.vRTsDistribution = self.vRTInstance.vRTsDistribution
for i in range(0, self.matrixDim["rows"]):
shortCircuitLists.append([0])
for j in range(0, self.matrixDim["columns"]):
shortCircuitLists[i].append(0)
for i in range(0, self.matrixDim["rows"]):
for j in range(0, self.matrixDim["columns"]-1):
print('self.vRTsDistribution',self.vRTsDistribution)
if self.matchingScheme[i][j] in self.vRTsDistribution[j+1] and self.matchingScheme[i][j+1] in self.vRTsDistribution[j+1] and self.matchingScheme[i][j] > self.matchingScheme[i][j+1] : shortCircuitLists[i][j] = 1
return shortCircuitLists
def ScriptMain( **kw ):
editor = None
if kw.has_key('editor') and kw['editor']:
editor = kw['editor']
UpdateSession.open()
Device = AllianceFramework.get().createCell( 'capacitor' )
Device.setTerminal( True )
bottomPlate_net0 = Net.create( Device, 'b0' )
bottomPlate_net1 = Net.create( Device, 'b1' )
bottomPlate_net2 = Net.create( Device, 'b2' )
bottomPlate_net3 = Net.create( Device, 'b3' )
bottomPlate_net0.setExternal( True )
bottomPlate_net1.setExternal( True )
bottomPlate_net2.setExternal( True )
bottomPlate_net3.setExternal( True )
b0 = Device.getNet("b0")
b1 = Device.getNet("b1")
b2 = Device.getNet("b2")
b3 = Device.getNet("b3")
topPlate_net0 = Net.create( Device, 't0' )
topPlate_net1 = Net.create( Device, 't1' )
topPlate_net2 = Net.create( Device, 't2' )
topPlate_net3 = Net.create( Device, 't3' )
topPlate_net0.setExternal( True )
topPlate_net1.setExternal( True )
topPlate_net2.setExternal( True )
topPlate_net3.setExternal( True )
t0 = Device.getNet("t0")
t1 = Device.getNet("t1")
t2 = Device.getNet("t2")
t3 = Device.getNet("t3")
if editor:
UpdateSession.close()
editor.setCell( Device )
editor.fit()
UpdateSession.open()
nets = [[t0, b0] , [t1, b1], [t2, b2] ] # [t3, b3] ]
capacitorInstance = CapacitorStack( Device, [372,1116], 'MIMCap', [0,0], nets, unitCap = 93, matrixDim = [4,4], matchingMode = True, matchingScheme = [ [1,1,1,0] , [0,1,1,1] , [1,1,1,0] , [0,1,1,1] ] , dummyRing = True )#dummyRing = True)
# capacitorInstance = CapacitorStack( Device, [279,1023, 186], 'MIMCap', [0,0], nets, unitCap = 93, matrixDim = [4,4], matchingMode = True, matchingScheme = [ [1,1,1,0] , [0,1,2,1] , [1,1,1,0] , [2,1,1,1] ], dummyElement = True, dummyRing = True )#dummyRing = True)
# capacitorInstance = CapacitorStack( Device, capacitance, 'MIMCap', [0,0], nets, unitCap = 50, matchingMode = True, matchingScheme = [ ['C2','C1','C2','C1','C1'] , ['C1','C2','C1','C2','C2'] , ['C1','C2','C2','C2', 'C1'] , ['C1','C2','C2','C1', 'C1'], ['C2','C2','C2','C2','C2'] ] )
# capacitorInstance = CapacitorStack( Device, capacitance, 'MIMCap', [0,0], nets, unitCap = 93, matchingMode = True, matchingScheme = [ ['C2','C2','C2','C2'] , ['C1','C2','C2','C2'] , ['C1','C2','C2','C2'] , ['C1','C2','C2','C1'] ] )
# capacitorInstance = CapacitorStack( Device, capacitance, 'MIMCap', [0,0], nets, unitCap = 93, matchingMode = True, matchingScheme = [ ['C2','C2','C1','C2'] , ['C1','C2','C2','C1'] , ['C1','C1','C2','C3'] , ['C1','C1','C2','C3'] ] )
# capacitorInstance = CapacitorStack( Device, capacitance, 'MIMCap', [0,0], nets, matrixDim = [5,5] , matchingMode = True, matchingScheme = [ ['C2','C1','C2','C3','C1'] , ['C1','C2','C4','C3','C2'] , ['C4','C2','C2','C3', 'C1'] , ['C1','C2','C2','C1', 'C1'], ['C2','C2','C3','C2','C4'] ] )
capacitor = capacitorInstance.create()
print('capa',capacitor)
capWithVRT = VerticalRoutingTracks( capacitorInstance, capacitor, True )
capWithVRT.create()
routedCap = RoutMatchedCapacitor( capWithVRT )
surface = routedCap.route( )
print('routeMatchedCap bbMode', surface)
AllianceFramework.get().saveCell( Device, Catalog.State.Views )
return True