coriolis/oroshi/python/nonunitcapacitor.py

255 lines
7.8 KiB
Python

#!/usr/bin/python
import sys
from math import sqrt, ceil
from ..Hurricane import *
from ..CRL import *
from ..helpers.io import ErrorMessage as Error
from ..helpers import staticInitialization, trace
from . import getRules
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()
staticInitialization( True )
class NonUnitCapacitor(CapacitorUnit):
rules = getRules()
def __init__( self, device, capacitorType, direction, capacitance, capacitorUnit, abutmentBoxPosition, capUnitTopPlates_spacing = -1 ):
self.device = device
self.capacitorType = capacitorType
self.direction = direction
self.capacitance = capacitance
self.capacitorUnit = capacitorUnit
self.abutmentBoxPosition = abutmentBoxPosition
self.capUnitTopPlates_spacing = capUnitTopPlates_spacing
self.unitCapDim = CapacitorUnit.__computeCapDim__( self, capacitorUnit, capacitorType )
if self.__isDirectionOk__(direction):
self.nonUnitCapDim = {"width" : self.unitCapDim["width"] , "height" : 0 } if direction == "vertical" else {"width" : 0 , "height" : self.unitCapDim["width"] }
self.nonUnitCapDim_sideLimit = 0
self.dummyCapDim = {}
return
def __isDirectionOk__( self, direction ):
state = True if direction in ["horizontal","vertical"] else False
if state == False : raise Error(1,'__isDirectionOk__() : The direction must be either "vertical" or "horizontal" : %s.' % direction)
return state
def setRules( self ):
CapacitorUnit.setRules(self)
if self.capacitorType == 'MIMCap':
self.__setattr__( "minWidth_dummyTopPlate" , CapacitorUnit.rules.minWidth_metcapdum )
elif self.capacitorType == 'PIPCap':
self.__setattr__( "minWidth_dummyTopPlate" , CapacitorUnit.rules.minWidth_cpoly )
return
def create( self, b, t ) :
UpdateSession.open()
self.setRules()
self.computeDimensions()
if self.__isCapacitorOk__() :
print('drawing capacitor')
activeCapacitor = CapacitorUnit ( self.device, self.capacitorType, self.abutmentBoxPosition, capDim = self.nonUnitCapDim )
activeCapacitor.create( b, t )
side = "height" if self.direction == "vertical" else "width"
if self.__isNonUnitCapSideOk__( side ) :
print("drawing dummy too")
# activeCapacitor = CapacitorUnit ( self.device, activeCapacitance, self.capacitorType, self.abutmentBoxPosition )
dummyAbutmentBoxPosition = [ self.abutmentBoxPosition[0], self.abutmentBoxPosition[1] - CapacitorUnit.computeAbutmentBoxDimensions( self, self.dummyCapDim )["height"] ] if self.direction == "vertical" else [ self.abutmentBoxPosition[0] + CapacitorUnit.computeAbutmentBoxDimensions( self, self.nonUnitCapDim )["width"] , self.abutmentBoxPosition[1] ]
dummyCapacitor = CapacitorUnit( self.device, self.capacitorType, dummyAbutmentBoxPosition, capDim = self.dummyCapDim )
# activeCapacitor.create( b, t )
dummyCapacitor.create ( b, t )
else : print("not drawing dummy")
# abutmentBoxDimensions = self.computeAbutmentBoxDimensions(capDim)
# CapacitorUnit.drawAbutmentBox( self )
else : raise Error(1,'create() : Impossible to draw capacitor in the defined geometric limits.')
UpdateSession.close()
return
def __isCapacitorOk__( self ):
capacitorMax = self.computeCapacitorMax()
print("CMax",capacitorMax)
print("self.capacitance",self.capacitance)
print("self.capUnitTopPlates_spacing",toPhy(self.capUnitTopPlates_spacing))
return True if self.capacitance < capacitorMax else False
def computeDimensions( self ):
if self.capUnitTopPlates_spacing == -1 :
CapacitorUnit.computeAbutmentBoxDimensions(self, self.unitCapDim )
self.capUnitTopPlates_spacing = 2*(self.minSpacing_botPlate + self.enclosure_botPlate_topPlate)
self.nonUnitCapDim_sideLimit = 2*self.unitCapDim["width"] - self.minWidth_dummyTopPlate
if self.direction == "vertical":
self.nonUnitCapDim["height"] = self.computeNonUnitCapheight()
else : self.nonUnitCapDim["width"] = self.computeNonUnitCapheight()
print("sideLimit",toPhy(self.nonUnitCapDim_sideLimit))
print("self.capUnitTopPlates_spacing",toPhy(self.capUnitTopPlates_spacing))
print('self.nonUnitCapDim["width"]',toPhy(self.nonUnitCapDim["width"]))
print('self.nonUnitCapDim["height"]',toPhy(self.nonUnitCapDim["height"]))
nonUnitCapDim_sideMax = 2*self.unitCapDim["width"] + self.capUnitTopPlates_spacing
self.dummyCapDim["width" ] = self.unitCapDim["width" ] if self.direction == "vertical" else nonUnitCapDim_sideMax - self.capUnitTopPlates_spacing - self.nonUnitCapDim["width"]
self.dummyCapDim["height"] = nonUnitCapDim_sideMax - self.capUnitTopPlates_spacing - self.nonUnitCapDim["height"] if self.direction == "vertical" else self.unitCapDim["width" ]
print("self.dummyCapDim",toPhy(self.dummyCapDim["width" ]))
print("self.dummyCapDim",toPhy(self.dummyCapDim["height" ]))
return
def computeCapacitorMax( self ):
[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ] = CapacitorUnit.__setCapacitorPerUnit__(self, self.capacitorType)
capUnit_width = toPhy( self.unitCapDim["width"] )
topPlates_spacing = toPhy( self.capUnitTopPlates_spacing )
print("[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ]",[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ])
print("width",capUnit_width)
CMax = ( 2*capUnit_width + topPlates_spacing )*capUnit_width*areaCapacitorPerUnit + ( 3*capUnit_width + topPlates_spacing )*perimeterCapacitorPerUnit
return CMax
def computeNonUnitCapheight( self ):
[ areaCapacitorPerUnit, perimeterCapacitorPerUnit ] = CapacitorUnit.__setCapacitorPerUnit__(self, self.capacitorType)
width = toPhy( self.unitCapDim["width"] )
height = self.capacitance/( (width*areaCapacitorPerUnit + perimeterCapacitorPerUnit) + width*perimeterCapacitorPerUnit )
print("height",height)
return toDbU(height)
def __isNonUnitCapSideOk__( self, side ):
if side in ["width","height"]:
state = True if self.nonUnitCapDim[side] < self.nonUnitCapDim_sideLimit else False
else : raise Error(1,'__isNonUnitCapSideOk__() : The side must be either "width" or "height" : %s.' % side)
return state
def scriptMain( **kw ):
editor = None
if 'editor' in kw and kw['editor']:
editor = kw['editor']
UpdateSession.open()
device = AllianceFramework.get().createCell( 'nonUnitCapacitor' )
device.setTerminal( True )
bottomPlate_net = Net.create( device, 'b' )
bottomPlate_net.setExternal( True )
b = device.getNet("b")
doBreak( 1, 'Done building bottomPlate')
topPlate_net = Net.create( device, 't' )
topPlate_net.setExternal( True )
t = device.getNet("t")
doBreak( 1, 'Done building tNet')
if editor:
UpdateSession.close( )
editor.setCell ( device )
editor.fit ( )
UpdateSession.open ( )
nonUnitCapacitor = NonUnitCapacitor ( device, 'PIPCap', 'horizontal', 65, 50, [0,0] )
nonUnitCapacitor.create(b,t)
AllianceFramework.get().saveCell( device, Catalog.State.Views )
return True