2020-03-30 05:40:29 -05:00
#!/usr/bin/python
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2022-07-13 04:20:55 -05:00
import sys
Comprehensive reorganisation of the Python part of Coriolis.
* Move all Python stuff under a common Python namespace "coriolis".
* Instead of having a series subtrees for each tool, integrate
everything in one common tree. So now, all components can be
located either with an absolute path from "coriolis" or, inside
cross-reference themselves through relatives imports.
* As a consequence, we only need to add ".../site-packages/coriolis/"
to the PYTHONPATH, and not a whole bunch of subdirectories.
And nothing, if installed in-system.
* The tree of free technologies configuration files is also moved
below "coriolis/technos" instead of "/etc".
* Supressed "cumulus" level for the plugins.
* All python modules are rewritten using relative imports except
for the configuration files that uses absolute import as they
can be cloned outside of the tree to serve as templates.
* Change: In boostrap/FindPythonSitePackages, include "/coriolis" in
Python_CORIOLISARCH and Python_CORIOLISLIB.
Provide a Python_SITELIB *without* "/coriolis" appended.
* Change: In cumulus/plugins/__init__.loadPlugins(), must prefix modules
read in the plugins directory by "coriolis.plugins.". No longer need
to add their path to sys.path.
* Change: In crlcore/python/technos/nodeX/*/devices.py, the scripts of
the layouts generators must be prefixed by "coriolis.oroshi.".
* Change: In CRL::System CTOR, no longer add the pathes of the various
plugins to sys.path. Only "site-packages/coriolis/".
* New: In Utilities::Path::toPyModePath(), new method to convert a
filesystem path into a python module path.
Examples:
"coriolis/plugins/block" --> "coriolis.plugins.block".
"coriolis/plugins/rsave.py" --> "coriolis.plugins.rsave".
* Change: In katanaEngine::_runKatanaEngine(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In BoraEngine::_runBoraEngine(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In UnicornGui::_runUnicornInit(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In cumulus.plugins.chip.constants, put the constants
outside __init__.py to avoid a loop at initialization.
2023-02-27 15:14:32 -06:00
from math import sqrt , ceil
from . . Hurricane import *
from . . CRL import *
from . . import Constant
from . . helpers . io import ErrorMessage as Error
from . . helpers import trace , u
from . import getRules
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
def doBreak ( level , message ) :
UpdateSession . close ( )
Breakpoint . stop ( level , message )
UpdateSession . open ( )
2022-07-13 04:20:55 -05:00
def toDbU ( l ) : return DbU . fromPhysical ( l , DbU . UnitPowerMicro )
def toPhy ( l ) : return DbU . toPhysical ( int ( l ) , DbU . UnitPowerMicro )
2020-03-30 05:40:29 -05:00
def toFoundryGrid ( l ) :
twoGrid = DbU . fromGrid ( 2.0 )
return l + ( twoGrid - ( l % twoGrid ) )
def isNearNorth ( y , ab ) : return ab . getYMax ( ) - y < y - ab . getYMin ( )
class Resistor ( object ) :
Comprehensive reorganisation of the Python part of Coriolis.
* Move all Python stuff under a common Python namespace "coriolis".
* Instead of having a series subtrees for each tool, integrate
everything in one common tree. So now, all components can be
located either with an absolute path from "coriolis" or, inside
cross-reference themselves through relatives imports.
* As a consequence, we only need to add ".../site-packages/coriolis/"
to the PYTHONPATH, and not a whole bunch of subdirectories.
And nothing, if installed in-system.
* The tree of free technologies configuration files is also moved
below "coriolis/technos" instead of "/etc".
* Supressed "cumulus" level for the plugins.
* All python modules are rewritten using relative imports except
for the configuration files that uses absolute import as they
can be cloned outside of the tree to serve as templates.
* Change: In boostrap/FindPythonSitePackages, include "/coriolis" in
Python_CORIOLISARCH and Python_CORIOLISLIB.
Provide a Python_SITELIB *without* "/coriolis" appended.
* Change: In cumulus/plugins/__init__.loadPlugins(), must prefix modules
read in the plugins directory by "coriolis.plugins.". No longer need
to add their path to sys.path.
* Change: In crlcore/python/technos/nodeX/*/devices.py, the scripts of
the layouts generators must be prefixed by "coriolis.oroshi.".
* Change: In CRL::System CTOR, no longer add the pathes of the various
plugins to sys.path. Only "site-packages/coriolis/".
* New: In Utilities::Path::toPyModePath(), new method to convert a
filesystem path into a python module path.
Examples:
"coriolis/plugins/block" --> "coriolis.plugins.block".
"coriolis/plugins/rsave.py" --> "coriolis.plugins.rsave".
* Change: In katanaEngine::_runKatanaEngine(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In BoraEngine::_runBoraEngine(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In UnicornGui::_runUnicornInit(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In cumulus.plugins.chip.constants, put the constants
outside __init__.py to avoid a loop at initialization.
2023-02-27 15:14:32 -06:00
rules = getRules ( )
2020-03-30 05:40:29 -05:00
def __init__ ( self , device , nets , resistorType , resistance = 0 , resDim = { " width " : 10 , " length " : 0 } , direction = " horizontal " , bends = 0 , shape = 90 ) :
self . device = device
self . nets = nets
trace ( 100 , ' \t width: {0} , length: {1} , bends: {2} \n ' . format ( resDim [ ' width ' ] , resDim [ ' length ' ] , bends ) )
#resDim["width" ] = toDbU(resDim["width" ])
#resDim["length"] = toDbU(resDim["length"])
self . __initArgs__ ( resistorType , direction , bends , shape )
self . setRules ( )
self . __initResDim__ ( resistance , resDim )
if self . snakeMode :
self . snakeSegmentDict = { }
self . resPlateExtrimity1 = { }
self . resPlateExtrimity2 = { }
self . resPlateExtension1 = { }
self . resPlateExtension2 = { }
self . snakeCornerDict = { }
if self . shape == 135 :
self . rightCorPointsVector = [ ]
self . leftCorPointsVector = [ ]
self . resPlateExtensions = { }
self . resPlateExtrimities = { }
self . resistorPlateDict = { }
self . abutmentBoxDict = { " XMin " : 0 , " YMin " : 0 }
self . abutmentBox = Box ( )
self . terminal1Box = Box ( )
self . terminal2Box = Box ( )
self . t1cutsEnclosure = { }
self . t2cutsEnclosure = { }
self . t1CutCenterDict = { }
self . t2CutCenterDict = { }
if self . resistorType == " RPOLYH " :
self . pImplant_layerDict = { }
self . hresLayerDict = { }
if self . resistorType == " RPOLY2PH " :
self . restrmLayerDict = { }
self . resdefLayerDict = { }
self . enclosure_resistor_abutmentBox = { }
return
def __initArgs__ ( self , resistorType , direction , bends , shape ) :
if resistorType == " RPOLYH " or resistorType == " RPOLY2PH " : self . resistorType = resistorType
else : raise Error ( 1 , ' __initArgs__() : Unsupported resistor type : %s . ' % resistorType )
if direction in [ " horizontal " , " vertical " ] : self . direction = direction
else : raise Error ( 1 , ' __initDirection__() : Direction must be either " horizontal " or " vertical " . ' )
if bends > = 0 :
if bends == 0 : [ self . bends , self . snakeMode ] = [ bends , False ]
elif bends > 0 and shape in [ 90 , 135 ] : [ self . bends , self . snakeMode , self . shape ] = [ bends , True , shape ]
else : raise Error ( 1 , ' __initArgs__() : Resistor shape must be either 90 or 135 degrees : shape = %s . ' % shape )
else : raise Error ( 1 , ' __initArgs__() : Bends number must not be negative : bends = %s . ' % bends )
return
def __initContactsNumber__ ( self , resDim ) :
layer_minWidth = Resistor . rules . minWidth_cut0 + 2 * Resistor . rules . minEnclosure_poly2_cut0
layerWidth = self . resPlateExtensions_minWidth if resDim [ " width " ] < layer_minWidth else resDim [ " width " ]
self . contactsNumber = self . cutMaxNumber ( layerWidth , Resistor . rules . minWidth_cut0 , Resistor . rules . minSpacing_cut0 , Resistor . rules . minEnclosure_poly2_cut0 )
return
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
def __initResDim__ ( self , resistance , resDim ) :
if self . __isDimOk__ ( resDim , " width " ) :
self . __initContactsNumber__ ( resDim )
print ( " contacts " , self . contactsNumber )
if resistance > 0 and resDim [ " length " ] > 0 :
if resistance - resistance / 1000 < = self . __computeResistance__ ( resDim , self . resistorType ) < = resistance + resistance / 1000 and self . __isDimOk__ ( resDim , " length " ) :
self . resDim = resDim
else :
raise Error ( 1 , ' __initResDim__() : No compatibiliy between resistance value, %s , and resistor dimensions, " width " : %s , " length " : %s . ' % ( resistance , toPhy ( resDim [ " width " ] ) , toPhy ( resDim [ " length " ] ) ) )
elif resistance > 0 and resDim [ " length " ] == 0 :
print ( " resistance0 " , resistance )
self . resDim = self . __computeResDim__ ( resistance , self . resistorType , resDim )
elif resistance == 0 and resDim [ " width " ] > 0 and resDim [ " length " ] > 0 and self . __isDimOk__ ( resDim , " length " ) :
self . resDim = resDim
else : raise Error ( 1 , ' __initResDim__() : Invalid input parameters : resistance and/or resistor dimensions ( %s , %s ). Please provide at least one valid parameter. ' % ( resistance , resDim ) )
return
def setSidesDimRules ( self ) :
if self . resistorType == " RPOLYH " :
self . __setattr__ ( " minWidth_resistorPlate " , Resistor . rules . minWidth_rpolyh )
if self . resistorType == " RPOLY2PH " :
self . __setattr__ ( " minWidth_resistorPlate " , Resistor . rules . minWidthHighPrec_rpolyh )
self . __setattr__ ( " minLength_resistorPlate " , Resistor . rules . minRpolyhSquares )
return
def __isDimOk__ ( self , resdim , side ) :
self . setSidesDimRules ( )
2022-07-13 04:20:55 -05:00
print ( resdim )
if list ( resdim . keys ( ) ) == [ " width " , " length " ] and side in [ " width " , " length " ] :
2020-03-30 05:40:29 -05:00
if side == " width " :
rule = self . minWidth_resistorPlate
if side == " length " :
print ( " test0 " , resdim [ " width " ] )
rule = toDbU ( self . minLength_resistorPlate * toPhy ( resdim [ " width " ] ) )
state = True if resdim [ side ] > = rule else False
if state == False : raise Error ( 1 , ' __isDimOk__() : Resistor or bend side dimension, %s = %s , is below the minimal limit, %s . '
% ( side , toPhy ( resdim [ side ] ) , toPhy ( rule ) ) )
else : raise Error ( 1 , ' __isDimOk__() : The resistor or bend dimensions and the specified side, %s and %s , must be either " width " or " length " . '
% ( resdim , side ) )
return state
def __computeResistance__ ( self , resDim , resistorType ) :
resistancePart1 = self . __getSheetResistance__ ( resistorType , " resistorPlate " ) * toPhy ( resDim [ " length " ] ) / toPhy ( resDim [ " width " ] )
resistancePart2 = 2 * self . __getSheetResistance__ ( resistorType , " contact " ) / self . contactsNumber
print ( " computedRes " , resistancePart1 + resistancePart2 )
return resistancePart1 + resistancePart2
def __computeResDim__ ( self , resistance , resistorType , resDim ) :
contactsResistance = self . __getSheetResistance__ ( resistorType , " contact " ) / self . contactsNumber
print ( " contactsResistance " , contactsResistance )
wl_ratio = ( resistance - 2 * contactsResistance ) / self . __getSheetResistance__ ( resistorType , " resistorPlate " )
width = toPhy ( resDim [ " width " ] )
length = wl_ratio * width
resDim [ " length " ] = toFoundryGrid ( toDbU ( length ) )
print ( ' length0 ' , length )
if self . __isDimOk__ ( resDim , " width " ) and self . __isDimOk__ ( resDim , " length " ) :
return resDim
def __getSheetResistance__ ( self , resistorType , material ) :
if material == ' resistorPlate ' :
if resistorType == " RPOLYH " : resistance = Resistor . rules . RPOLYHSheetRes
elif resistorType == " RPOLY2PH " : resistance = Resistor . rules . RPOLY2PHSheetRes
else : raise Error ( 1 , ' __getSheetResistance__() : Unsupported resistor type : %s . ' % resistorType )
elif material == " contact " :
resistance = Resistor . rules . MET1RPOLYHContRes
return resistance
def __computeSnakeCornerDim__ ( self ) :
self . snakeCornerDict [ " width " ] = self . resDim [ " width " ]
self . snakeCornerDict [ " length " ] = 2 * self . resDim [ " width " ] + self . minSpacing_resistorPlate
return
def __getCornerResistanceCorrectionFactor__ ( self ) :
if self . shape not in [ 90 , 135 ] : raise Error ( 1 , ' __getCornerResistanceCorrectionFactor__() : Invalid shape : %s . ' % shape )
if self . shape == 135 : correctionFactor = Resistor . rules . corrFactor135
if self . shape == 90 : correctionFactor = Resistor . rules . corrFactor90
print ( correctionFactor )
return correctionFactor
def setRules ( self ) :
trace ( 101 , ' +, ' , ' \t Resistor.setRules() \n ' )
self . minSpacing_resistorPlate = Resistor . rules . minSpacing_rpolyh
self . minWidth_contact = Resistor . rules . minWidth_cut0
self . minHeight_contact = Resistor . rules . minWidth_cut0
self . minSpacing_contact = Resistor . rules . minSpacing_cut0
self . minEnclosure_resistorPlate_contact = Resistor . rules . minEnclosure_poly2_cut0
self . minEnclosure_routingLayer_contact = Resistor . rules . minEnclosure_metal1_cut0
self . minEnclosure_metal1_cut0 = Resistor . rules . minEnclosure_metal1_cut0
self . minEnclosure_metal1_cut1 = Resistor . rules . minEnclosure_metal1_cut1
self . minWidth_cut1 = Resistor . rules . minWidth_cut1
self . minSpacing_cut1 = Resistor . rules . minSpacing_cut1
if self . resistorType == " RPOLYH " :
self . minWidth_pImplantLayer = Resistor . rules . minWidth_pImplant
self . minSpacing_pImplantLayer = Resistor . rules . minSpacing_pImplant
self . minSpacing_resistorPlate_pImplantLayer = Resistor . rules . minSpacing_rpolyh_pImplant
self . minEnclosure_pImplantLayer_contact = Resistor . rules . minEnclosure_pImplant_poly2con
self . minEnclosure_hres_poly2 = Resistor . rules . minEnclosure_hres_poly2
self . minWidth_hres = Resistor . rules . minWidth_hres
self . minSpacing_hres = Resistor . rules . minSpacing_hres
self . minSpacing_hres_poly1 = Resistor . rules . minSpacing_hres_poly1
self . minSpacing_hres_poly2 = Resistor . rules . minSpacing_hres_poly2
self . minSpacing_hres_active = Resistor . rules . minSpacing_hres_active
self . resPlateExtensions_minWidth = self . minWidth_contact + 2 * self . minEnclosure_resistorPlate_contact
# Get the METAL 1/2/3 layers.
self . cut1 = DataBase . getDB ( ) . getTechnology ( ) . getLayer ( ' cut1 ' )
self . metal1 = DataBase . getDB ( ) . getTechnology ( ) . getLayer ( ' metal1 ' )
self . metal2 = DataBase . getDB ( ) . getTechnology ( ) . getLayer ( ' metal2 ' )
self . metal3 = DataBase . getDB ( ) . getTechnology ( ) . getLayer ( ' metal3 ' )
# Get the symbolic pitch.
rg = AllianceFramework . get ( ) . getRoutingGauge ( )
self . METAL2Pitch = rg . getHorizontalPitch ( )
self . METAL3Pitch = rg . getVerticalPitch ( )
self . isVH = rg . isVH ( )
foundHor = False
foundVer = False
for depth in range ( rg . getDepth ( ) ) :
rlg = rg . getLayerGauge ( depth )
if rlg . getLayer ( ) . getMask ( ) == self . metal2 . getMask ( ) : self . metal2Width = rlg . getWireWidth ( )
if rlg . getLayer ( ) . getMask ( ) == self . metal3 . getMask ( ) : self . metal3Width = rlg . getWireWidth ( )
if rlg . getType ( ) == Constant . PinOnly : continue
if rlg . getDirection ( ) == Constant . Horizontal and not foundHor :
trace ( 101 , ' \t self.hpitch set \n ' )
self . hpitch = rlg . getPitch ( )
foundHor = True
if rlg . getDirection ( ) == Constant . Vertical and not foundVer :
trace ( 101 , ' \t self.vpitch set \n ' )
self . vpitch = rlg . getPitch ( )
foundVer = True
trace ( 101 , ' -, ' )
return
def getLayers ( self ) :
technology = DataBase . getDB ( ) . getTechnology ( )
self . layers = { }
self . layers [ " resistorPlate " ] = technology . getLayer ( " poly2 " )
self . layers [ " contacts " ] = technology . getLayer ( " cut0 " )
self . layers [ " routingLayer " ] = technology . getLayer ( " metal1 " )
self . layers [ " metal2 " ] = technology . getLayer ( " metal2 " )
self . layers [ " pImplant " ] = technology . getLayer ( " pImplant " )
self . layers [ " resdef " ] = technology . getLayer ( " resdef " )
if self . resistorType == " RPOLYH " : self . layers [ " hres " ] = technology . getLayer ( " hres " )
if self . resistorType == " RPOLY2PH " : self . layers [ " restrm " ] = technology . getLayer ( " restrm " )
2022-07-13 04:20:55 -05:00
return self . layers
2020-03-30 05:40:29 -05:00
def create ( self , bbMode = False ) :
UpdateSession . open ( )
layerDict = self . getLayers ( )
2022-07-13 04:20:55 -05:00
self . computeDimensions ( bbMode )
2020-03-30 05:40:29 -05:00
self . drawAbutmentBox ( )
self . device . setAbutmentBox ( self . abutmentBox )
if bbMode == False :
if self . resistorType == " RPOLYH " : self . drawLayer ( " hres " , layerDict [ " hres " ] ) #self.drawHRESLayer( layerDict["hres"] )
self . drawLayer ( " resistorPlate " , layerDict [ " resistorPlate " ] )
self . drawResPlateExtrimities ( layerDict [ " resistorPlate " ] , layerDict [ " pImplant " ] )
if self . snakeMode : self . drawCorners ( layerDict [ " resistorPlate " ] )
self . drawContacts ( layerDict [ " contacts " ] )
self . drawRoutingLayer ( layerDict [ " routingLayer " ] )
if self . resistorType == " RPOLY2PH " : self . drawRestrmLayer ( layerDict [ " restrm " ] )
self . drawResdefLayer ( layerDict [ " resdef " ] )
self . drawTerminals ( )
UpdateSession . close ( )
return self . abutmentBoxDict
def computeDimensions ( self , bbMode ) :
if self . snakeMode :
self . __computeSnakeCornerDim__ ( )
self . computeSnakeSegmentDimensions ( )
if self . resistorType == " RPOLYH " : self . snakeSegments_spacing = max ( self . minSpacing_resistorPlate_pImplantLayer , self . minSpacing_resistorPlate )
if self . resistorType == " RPOLY2PH " : self . snakeSegments_spacing = self . minSpacing_resistorPlate
self . computeAbutmentBoxDimensions ( )
if bbMode == False :
if not self . snakeMode :
self . computeResistorPlateDimensions ( )
if self . snakeMode :
self . computeFirstSnakeSegmentPosition ( )
return
def computePImplantLayerDim ( self ) :
pImplantLayer_width = max ( self . minWidth_pImplantLayer , 2 * self . minEnclosure_pImplantLayer_contact + self . minWidth_contact )
self . pImplant_layerDict [ " width " ] = self . contactsNumber * self . minWidth_contact + ( self . contactsNumber - 1 ) * self . minSpacing_contact + 2 * self . minEnclosure_pImplantLayer_contact
self . pImplant_layerDict [ " length " ] = pImplantLayer_width
return
## extensions2 refers to a part of the corner
def computeResPlateExtensionsDim ( self ) :
self . resPlateExtensions_minWidth = self . minWidth_contact + 2 * self . minEnclosure_resistorPlate_contact
self . resPlateExtensions [ " width " ] = self . resPlateExtensions_minWidth if self . resDim [ " width " ] < self . resPlateExtensions_minWidth else self . resDim [ " width " ]
if self . resistorType == " RPOLYH " : self . resPlateExtensions [ " length " ] = self . minWidth_contact + self . minEnclosure_resistorPlate_contact + self . minEnclosure_pImplantLayer_contact
if self . resistorType == " RPOLY2PH " : self . resPlateExtensions [ " length " ] = self . minWidth_contact + self . minEnclosure_resistorPlate_contact
print ( " self.resPlateExtensions[ ' length ' ] " , self . resPlateExtensions [ " length " ] )
if self . snakeMode :
self . resPlateExtension1 = self . resPlateExtensions
self . resPlateExtension2 [ " width " ] = self . snakeSegmentDict [ " width " ]
self . resPlateExtension2 [ " length " ] = self . snakeSegmentDict [ " width " ]
return
def computeResPlateExtrimitiesDim ( self ) :
if self . resistorType == " RPOLYH " :
self . resPlateExtrimities [ " width " ] = self . pImplant_layerDict [ " width " ] + 2 * self . enclosure_resistor_hres
self . resPlateExtrimities [ " length " ] = self . pImplant_layerDict [ " length " ] + self . enclosure_resistor_hres #self.pImplant_layerDict
if self . resistorType == " RPOLY2PH " :
for key in self . resPlateExtensions . keys ( ) : self . resPlateExtrimities [ key ] = self . resPlateExtensions [ key ]
if self . snakeMode :
for key in self . resPlateExtrimities . keys ( ) : self . resPlateExtrimity1 [ key ] = self . resPlateExtrimities [ key ]
if self . resistorType == " RPOLYH " :
self . resPlateExtrimity2 [ " width " ] = self . resPlateExtension2 [ " width " ] + 2 * self . enclosure_resistor_hres
self . resPlateExtrimity2 [ " length " ] = self . resPlateExtension2 [ " length " ] + self . enclosure_resistor_hres
if self . resistorType == " RPOLY2PH " :
for key in self . resPlateExtension2 . keys ( ) : self . resPlateExtrimity2 [ key ] = self . resPlateExtension2 [ key ]
for key in self . resPlateExtrimity1 . keys ( ) : self . resPlateExtrimities [ key ] = max ( self . resPlateExtrimity1 [ key ] , self . resPlateExtrimity2 [ key ] )
return
def computeAbutmentBoxDimensions ( self ) :
if self . resistorType == " RPOLYH " : self . enclosure_resistor_abutmentBox = self . minSpacing_hres
if self . resistorType == " RPOLY2PH " : self . enclosure_resistor_abutmentBox = self . minSpacing_resistorPlate
self . computeResPlateExtensionsDim ( )
print ( " self.resPlateExtensionsabt0[ ' length ' ] " , toPhy ( self . resPlateExtensions [ " length " ] ) )
if not self . snakeMode : layerWidth = self . resPlateExtensions [ " width " ]
if self . snakeMode : layerWidth = self . resPlateExtension1 [ " width " ]
self . contactsNumber = self . cutMaxNumber ( layerWidth , self . minHeight_contact , self . minSpacing_contact , self . minEnclosure_resistorPlate_contact )
if self . resistorType == " RPOLYH " :
self . computePImplantLayerDim ( )
self . computeHRESLayerDimensions ( )
self . computeResPlateExtrimitiesDim ( )
if not self . snakeMode :
abutmentBoxSide1 = self . resPlateExtrimities [ " width " ] + 2 * self . enclosure_resistor_abutmentBox
abutmentBoxSide2 = self . resDim [ " length " ] + 2 * self . resPlateExtrimities [ " length " ] + 2 * self . enclosure_resistor_abutmentBox
if self . snakeMode :
2022-07-13 04:20:55 -05:00
if self . resistorType == " RPOLYH " : resistor_width = list ( self . hresLayerDict . values ( ) ) [ 0 ]
2020-03-30 05:40:29 -05:00
if self . resistorType == " RPOLY2PH " : resistor_width = ( self . bends + 1 ) * self . snakeSegmentDict [ " width " ] + self . bends * self . snakeSegments_spacing
abutmentBoxSide1 = resistor_width + 2 * self . enclosure_resistor_abutmentBox #width
if self . bends > 1 :
abutmentBoxSide2 = self . snakeSegmentDict [ " length " ] + 2 * self . resPlateExtrimities [ " length " ] + 2 * self . enclosure_resistor_abutmentBox
if self . bends == 1 :
abutmentBoxSide2 = self . snakeSegmentDict [ " length " ] + self . resPlateExtrimity1 [ " length " ] + self . resPlateExtrimity2 [ " length " ] + 2 * self . enclosure_resistor_abutmentBox
if self . direction == " vertical " :
self . abutmentBoxDict [ " width " ] = abutmentBoxSide1
self . abutmentBoxDict [ " height " ] = abutmentBoxSide2
if self . direction == " horizontal " :
self . abutmentBoxDict [ " width " ] = abutmentBoxSide2
self . abutmentBoxDict [ " height " ] = abutmentBoxSide1
return
def computeHRESLayerDimensions ( self ) :
self . enclosure_resistor_hres = self . minEnclosure_hres_poly2
if not self . snakeMode : hresLayerSide1 = max ( self . minWidth_hres , self . pImplant_layerDict [ " width " ] + 2 * self . enclosure_resistor_hres )
if self . snakeMode : hresLayerSide1 = max ( self . minWidth_hres , ( self . bends + 1 ) * self . snakeSegmentDict [ " width " ] + self . bends * self . snakeSegments_spacing + 2 * self . enclosure_resistor_hres )
if self . direction == " vertical " :
self . hresLayerDict [ " length " ] = hresLayerSide1
if self . direction == " horizontal " :
self . hresLayerDict [ " width " ] = hresLayerSide1
return
def computeResistorPlateDimensions ( self ) :
self . resistorPlateDict [ " width " ] = self . resDim [ " width " ]
self . resistorPlateDict [ " length " ] = self . resDim [ " length " ]
2022-07-13 04:20:55 -05:00
if self . direction == " vertical " : keysList = [ " XCenter " , " YMin " , " YMax " , " XMin " , " width " ]
if self . direction == " horizontal " : keysList = [ " YCenter " , " XMin " , " XMax " , " YMin " , " height " ]
2020-03-30 05:40:29 -05:00
self . resistorPlateDict [ keysList [ 0 ] ] = self . abutmentBoxDict [ keysList [ 3 ] ] + self . abutmentBoxDict [ keysList [ 4 ] ] / 2
self . resistorPlateDict [ keysList [ 1 ] ] = self . abutmentBoxDict [ keysList [ 1 ] ] + self . enclosure_resistor_abutmentBox + self . resPlateExtrimities [ " length " ]
self . resistorPlateDict [ keysList [ 2 ] ] = self . resistorPlateDict [ keysList [ 1 ] ] + self . resistorPlateDict [ " length " ]
return
## The first bend is the lowest one (horizontally)
def computeSnakeSegmentDimensions ( self ) :
snakeSegmentDict = { }
snakeSegmentDict [ " width " ] = toPhy ( self . resDim [ " width " ] )
totalResLength = toPhy ( self . resDim [ " length " ] )
correctionFactor = self . __getCornerResistanceCorrectionFactor__ ( )
snakeSegmentDict [ " length " ] = ( totalResLength - self . bends * ( snakeSegmentDict [ " width " ] * ( correctionFactor + 1 ) + toPhy ( self . minSpacing_resistorPlate ) ) ) / ( self . bends + 1 )
snakeSegmentDict [ " length " ] = toFoundryGrid ( toDbU ( snakeSegmentDict [ " length " ] ) )
snakeSegmentDict [ " width " ] = toFoundryGrid ( toDbU ( snakeSegmentDict [ " width " ] ) )
print ( " snakesegW " , snakeSegmentDict [ " width " ] )
if self . __isDimOk__ ( snakeSegmentDict , " length " ) :
self . snakeSegmentDict [ " width " ] = snakeSegmentDict [ " width " ]
self . snakeSegmentDict [ " length " ] = snakeSegmentDict [ " length " ]
return
## The first bend is the lowest one (horizontally)
def computeFirstSnakeSegmentPosition ( self ) :
2022-07-13 04:20:55 -05:00
if self . direction == " vertical " :
2020-03-30 05:40:29 -05:00
if self . bends > 1 : firstExtrimity_width = self . resPlateExtrimities [ " width " ]
if self . bends == 1 : firstExtrimity_width = self . resPlateExtrimity1 [ " width " ]
if self . resistorType == " RPOLYH " :
self . snakeSegmentDict [ " XCenter " ] = self . abutmentBoxDict [ " XMin " ] + self . enclosure_resistor_abutmentBox + self . snakeSegmentDict [ " width " ] / 2 + self . enclosure_resistor_hres
self . snakeSegmentDict [ " YMin " ] = self . abutmentBoxDict [ " YMin " ] + self . enclosure_resistor_abutmentBox + firstExtrimity_width #length
if self . resistorType == " RPOLY2PH " :
self . snakeSegmentDict [ " XCenter " ] = self . abutmentBoxDict [ " XMin " ] + self . enclosure_resistor_abutmentBox + self . snakeSegmentDict [ " width " ] / 2
self . snakeSegmentDict [ " YMin " ] = self . abutmentBoxDict [ " YMin " ] + self . enclosure_resistor_abutmentBox + firstExtrimity_width
self . snakeSegmentDict [ " YMax " ] = self . snakeSegmentDict [ " YMin " ] + self . snakeSegmentDict [ " length " ]
2022-07-13 04:20:55 -05:00
if self . direction == " horizontal " :
2020-03-30 05:40:29 -05:00
if self . bends > 1 : firstExtrimity_length = self . resPlateExtrimities [ " length " ]
if self . bends == 1 : firstExtrimity_length = self . resPlateExtrimity1 [ " length " ]
if self . resistorType == " RPOLYH " :
self . snakeSegmentDict [ " YCenter " ] = self . abutmentBoxDict [ " YMin " ] + self . enclosure_resistor_abutmentBox + self . snakeSegmentDict [ " width " ] / 2 + self . enclosure_resistor_hres
self . snakeSegmentDict [ " XMin " ] = self . abutmentBoxDict [ " XMin " ] + self . enclosure_resistor_abutmentBox + firstExtrimity_length
if self . resistorType == " RPOLY2PH " :
self . snakeSegmentDict [ " YCenter " ] = self . abutmentBoxDict [ " YMin " ] + self . enclosure_resistor_abutmentBox + self . snakeSegmentDict [ " width " ] / 2
self . snakeSegmentDict [ " XMin " ] = self . abutmentBoxDict [ " XMin " ] + self . enclosure_resistor_abutmentBox + firstExtrimity_length
self . snakeSegmentDict [ " XMax " ] = self . snakeSegmentDict [ " XMin " ] + self . snakeSegmentDict [ " length " ]
def computeHRESLayerPosition ( self ) :
2022-07-13 04:20:55 -05:00
if self . direction == " vertical " :
2020-03-30 05:40:29 -05:00
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
2022-07-13 04:20:55 -05:00
if self . direction == " horizontal " :
2020-03-30 05:40:29 -05:00
self . hresLayerDict [ " YCenter " ] = self . abutmentBox . getYCenter ( )
self . hresLayerDict [ " XMin " ] = self . abutmentBox . getXMin ( ) + self . enclosure_resistor_abutmentBox
self . hresLayerDict [ " XMax " ] = self . abutmentBox . getXMax ( ) - self . enclosure_resistor_abutmentBox
def drawLayer ( self , layerLabel , layer ) :
thiknessKey = " width "
maxIterations = 1
centerTranslation = 0
if layerLabel not in [ " hres " , " resistorPlate " ] : raise Error ( 1 , ' drawLayer() : Supported layer labels " hres " or " resistorPlate " . ' )
if layerLabel == " hres " :
self . computeHRESLayerPosition ( )
positionParams = self . hresLayerDict
if self . direction == " vertical " : thiknessKey = " length "
if layerLabel == " resistorPlate " :
if not self . snakeMode :
positionParams = self . resistorPlateDict
if self . snakeMode :
positionParams = self . snakeSegmentDict
maxIterations = self . bends + 1
centerTranslation = self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing
if self . direction == " vertical " :
for i in range ( 0 , maxIterations ) :
2022-07-13 04:20:55 -05:00
print ( self . nets [ 0 ] , layer \
2020-03-30 05:40:29 -05:00
, positionParams [ " XCenter " ] + i * centerTranslation \
, positionParams [ thiknessKey ] \
, positionParams [ " YMin " ] \
2022-07-13 04:20:55 -05:00
, positionParams [ " YMax " ] )
2020-03-30 05:40:29 -05:00
Vertical . create ( self . nets [ 0 ] , layer
2022-07-13 04:20:55 -05:00
, int ( positionParams [ " XCenter " ] + i * centerTranslation )
, int ( positionParams [ thiknessKey ] )
, int ( positionParams [ " YMin " ] )
, int ( positionParams [ " YMax " ] )
2020-03-30 05:40:29 -05:00
)
if self . direction == " horizontal " :
for i in range ( 0 , maxIterations ) :
Horizontal . create ( self . nets [ 0 ] , layer
2022-07-13 04:20:55 -05:00
, int ( positionParams [ " YCenter " ] + i * centerTranslation )
, int ( positionParams [ thiknessKey ] )
, int ( positionParams [ " XMin " ] )
, int ( tositionParams [ " XMax " ] )
2020-03-30 05:40:29 -05:00
)
return
def drawResdefLayer ( self , layer ) :
self . computeResDefDimensions ( )
if not self . snakeMode :
self . drawResdefForResistorPlate ( layer )
if self . snakeMode :
self . drawResdefForSnakeSegments ( layer )
self . drawResdefForCorners ( layer )
return
def drawResdefForResistorPlate ( self , layer ) :
if self . direction == " vertical " :
Vertical . create ( self . nets [ 0 ] , layer
2022-07-13 04:20:55 -05:00
, int ( self . resdefLayerDict [ " XCenter " ] )
, int ( self . resdefLayerDict [ " width " ] )
, int ( self . resdefLayerDict [ " YMin " ] )
, int ( self . resdefLayerDict [ " YMax " ] )
2020-03-30 05:40:29 -05:00
)
if self . direction == " horizontal " :
Horizontal . create ( self . nets [ 0 ] , layer
2022-07-13 04:20:55 -05:00
, int ( self . resdefLayerDict [ " YCenter " ] )
, int ( self . resdefLayerDict [ " width " ] )
, int ( self . resdefLayerDict [ " XMin " ] )
, int ( self . resdefLayerDict [ " XMax " ] )
2020-03-30 05:40:29 -05:00
)
print ( " self.resdefLayerDict[ ' width ' ] " , self . resdefLayerDict [ " width " ] )
print ( " self.resistorPlateDict[ ' width ' ] " , self . resistorPlateDict [ " width " ] )
return
def drawResdefForSnakeSegments ( self , layer ) :
if not self . snakeMode : centerTranslation = 0
if self . snakeMode : centerTranslation = self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing
if self . resistorType == " RPOLYH " : extrimityTranslation = 0
if self . resistorType == " RPOLY2PH " : extrimityTranslation = self . minWidth_contact / 4
if self . direction == " vertical " :
for i in range ( 0 , self . bends + 1 ) :
if self . resistorType == " RPOLYH " : factor0 , factor1 = 1 , 1
if self . resistorType == " RPOLY2PH " :
factor0 = 0 if ( i == self . bends and self . bends % 2 == 0 ) else 1
factor1 = 0 if ( i == self . bends and self . bends % 2 != 0 ) or i == 0 else 1
Vertical . create ( self . nets [ 0 ] , layer
2022-07-13 04:20:55 -05:00
, int ( self . resdefLayerDict [ " XCenter " ] + i * centerTranslation )
, int ( self . resdefLayerDict [ " width " ] )
, int ( self . resdefLayerDict [ " YMin " ] + factor0 * extrimityTranslation )
, int ( self . resdefLayerDict [ " YMax " ] - factor1 * extrimityTranslation )
2020-03-30 05:40:29 -05:00
)
if self . direction == " horizontal " :
for i in range ( 0 , self . bends + 1 ) :
if self . resistorType == " RPOLYH " : factor0 , factor1 = 1 , 1
if self . resistorType == " RPOLY2PH " :
factor0 = 0 if i == 0 or ( i == self . bends and self . bends % 2 != 0 ) else 1
factor1 = 0 if i == self . bends and self . bends % 2 == 0 else 1
Horizontal . create ( self . nets [ 0 ] , layer
2022-07-13 04:20:55 -05:00
, int ( self . resdefLayerDict [ " YCenter " ] + i * centerTranslation )
, int ( self . resdefLayerDict [ " width " ] )
, int ( self . resdefLayerDict [ " XMin " ] + factor0 * extrimityTranslation )
, int ( self . resdefLayerDict [ " XMax " ] - factor1 * extrimityTranslation )
2020-03-30 05:40:29 -05:00
)
return
def drawResdefForCorners ( self , layer ) :
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
k , factor = 0 , 0
if self . shape == 135 :
factor = 1
self . computeFirstSnakeCornerPosition90 ( )
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
translation = self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing
centersTranslationConst = self . snakeSegmentDict [ " width " ] + self . snakeSegmentDict [ " length " ]
if self . shape == 90 : widthExtension = self . minWidth_contact / 2
if self . shape == 135 : widthExtension = self . minWidth_contact / 4 + toDbU ( 0.2 )
if self . direction == " vertical " :
snakeCornersYCenters = [ self . snakeCornerDict [ " YCenter " ] - factor * ( toDbU ( 0.2 ) / 2 + self . minWidth_contact / 8 )
, self . snakeCornerDict [ " YCenter " ] + factor * ( toDbU ( 0.2 ) / 2 + self . minWidth_contact / 8 ) + centersTranslationConst ]
for i in range ( 0 , self . bends ) :
Horizontal . create ( self . nets [ 0 ] , layer
2022-07-13 04:20:55 -05:00
, int ( snakeCornersYCenters [ k ] )
, int ( self . snakeCornerDict [ " width " ] + widthExtension )
, int ( self . snakeCornerDict [ " XMin " ] - self . minWidth_contact / 4 + i * translation )
, int ( self . snakeCornerDict [ " XMax " ] + self . minWidth_contact / 4 + i * translation )
2020-03-30 05:40:29 -05:00
)
k = k + 1 if k < 1 else 0
if self . direction == " horizontal " :
snakeCornersXCenters = [ self . snakeCornerDict [ " XCenter " ] + factor * ( toDbU ( 0.2 ) / 2 + self . minWidth_contact / 8 )
, self . snakeCornerDict [ " XCenter " ] - factor * ( toDbU ( 0.2 ) / 2 + self . minWidth_contact / 8 ) - centersTranslationConst ]
for i in range ( 0 , self . bends ) :
Vertical . create ( self . nets [ 0 ] , layer
2022-07-13 04:20:55 -05:00
, int ( snakeCornersXCenters [ k ] )
, int ( self . snakeCornerDict [ " width " ] + widthExtension )
, int ( self . snakeCornerDict [ " YMin " ] - self . minWidth_contact / 4 + i * translation )
, int ( self . snakeCornerDict [ " YMax " ] + self . minWidth_contact / 4 + i * translation )
2020-03-30 05:40:29 -05:00
)
k = k + 1 if k < 1 else 0
return
def drawSnakeSegments ( self , layer ) :
translation = self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing
if self . direction == " vertical " :
for i in range ( 0 , self . bends + 1 ) :
Vertical . create ( self . nets [ 0 ] , layer
, self . snakeSegmentDict [ " XCenter " ] + i * translation
, self . snakeSegmentDict [ " width " ]
, self . snakeSegmentDict [ " YMin " ]
, self . snakeSegmentDict [ " YMax " ]
)
if self . direction == " horizontal " :
for i in range ( 0 , self . bends + 1 ) :
Horizontal . create ( self . nets [ 0 ] , layer
, self . snakeSegmentDict [ " YCenter " ] + i * translation
, self . snakeSegmentDict [ " width " ]
, self . snakeSegmentDict [ " XMin " ]
, self . snakeSegmentDict [ " XMax " ]
)
return
def drawAbutmentBox ( self ) :
ab = Box ( self . abutmentBoxDict [ " XMin " ]
, self . abutmentBoxDict [ " YMin " ]
, self . abutmentBoxDict [ " width " ]
, self . abutmentBoxDict [ " height " ]
)
height = ab . getHeight ( )
heightAdjust = height % ( 2 * self . hpitch )
if heightAdjust :
heightAdjust = 2 * self . hpitch - heightAdjust
2022-07-13 04:20:55 -05:00
ab . inflate ( 0 , heightAdjust / / 2 )
2020-03-30 05:40:29 -05:00
width = ab . getWidth ( )
widthAdjust = width % ( 2 * self . vpitch )
if widthAdjust :
widthAdjust = 2 * self . vpitch - widthAdjust
2022-07-13 04:20:55 -05:00
ab . inflate ( widthAdjust / / 2 , 0 )
2020-03-30 05:40:29 -05:00
self . abutmentBox = ab
return
def drawResPlateExtrimities ( self , resPlateLayer , pImplantLayer ) :
self . drawResPlateExtensions ( resPlateLayer )
if self . resistorType == " RPOLYH " :
self . drawPImplantLayer ( pImplantLayer )
return
## extension1 is on the right side of the resistor (if direction == horizontal) and the bottom side otherwhise
def computeResPlateExtensionsPosition ( self ) :
self . resPlateExtensions [ " ex1 " ] = { }
if self . direction == " vertical " :
if not self . snakeMode : self . resPlateExtensions [ " ex1 " ] [ " XMin " ] = self . abutmentBox . getXCenter ( ) - self . resPlateExtensions [ " width " ] / 2
if self . snakeMode : self . resPlateExtensions [ " ex1 " ] [ " XMin " ] = self . abutmentBox . getXCenter ( ) + ( self . bends * ( self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing ) ) / 2 - self . resPlateExtensions [ " width " ] / 2
if not self . snakeMode : translation = self . resPlateExtensions [ " length " ] + self . resDim [ " length " ] / 2
if self . snakeMode and self . bends % 2 == 0 : translation = self . resPlateExtensions [ " length " ] + self . snakeSegmentDict [ " length " ] / 2
if self . snakeMode and self . bends % 2 != 0 : translation = self . snakeSegmentDict [ " length " ] / 2
print ( " self.resPlateExtensions5[ ' length ' ] " , toPhy ( self . resPlateExtensions [ " length " ] ) )
# print("self.snakeSegmentDict['length']/2",toPhy(self.snakeSegmentDict["length"]/2))
# print("translation",toPhy(self.resPlateExtensions['length'] + self.snakeSegmentDict["length"]/2))
print ( " self.abutmentBox.getYCenter( " , toPhy ( self . abutmentBox . getYCenter ( ) ) )
if not self . snakeMode or self . snakeMode and self . bends % 2 == 0 : self . resPlateExtensions [ " ex1 " ] [ " YMin " ] = self . abutmentBox . getYCenter ( ) - translation
if self . snakeMode and self . bends % 2 != 0 : self . resPlateExtensions [ " ex1 " ] [ " YMin " ] = self . abutmentBox . getYCenter ( ) + translation
print ( " self.resPlateExtensions[ ' ex1 ' ][ ' YMin ' ] " , toPhy ( self . resPlateExtensions [ " ex1 " ] [ " YMin " ] ) )
self . resPlateExtensions [ " ex1 " ] [ " XMax " ] = self . resPlateExtensions [ " ex1 " ] [ " XMin " ] + self . resPlateExtensions [ " width " ]
self . resPlateExtensions [ " ex1 " ] [ " YMax " ] = self . resPlateExtensions [ " ex1 " ] [ " YMin " ] + self . resPlateExtensions [ " length " ]
if self . direction == " horizontal " :
if not self . snakeMode : resistorLength = self . resDim [ " length " ]
if self . snakeMode : resistorLength = self . snakeSegmentDict [ " length " ]
self . resPlateExtensions [ " ex1 " ] [ " XMin " ] = self . abutmentBox . getXCenter ( ) - self . resPlateExtensions [ " length " ] - resistorLength / 2
if not self . snakeMode : self . resPlateExtensions [ " ex1 " ] [ " YMin " ] = self . abutmentBox . getYCenter ( ) - self . resPlateExtensions [ " width " ] / 2
if self . snakeMode : self . resPlateExtensions [ " ex1 " ] [ " YMin " ] = self . snakeSegmentDict [ " YCenter " ] - self . resPlateExtensions [ " width " ] / 2
self . resPlateExtensions [ " ex1 " ] [ " XMax " ] = self . resPlateExtensions [ " ex1 " ] [ " XMin " ] + self . resPlateExtensions [ " length " ]
# print("self.resPlateExtensions['length']",toPhy(self.resPlateExtension2["length"]))
self . resPlateExtensions [ " ex1 " ] [ " YMax " ] = self . resPlateExtensions [ " ex1 " ] [ " YMin " ] + self . resPlateExtensions [ " width " ]
return
def drawResPlateExtensions ( self , layer ) :
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
self . computeResPlateExtensionsPosition ( )
if not self . snakeMode : resistorLength = self . resDim [ " length " ]
if self . snakeMode : resistorLength = self . snakeSegmentDict [ " length " ]
translation1 = resistorLength + self . resPlateExtensions [ " length " ]
if self . snakeMode : translation2 = self . bends * ( self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing ) #- self.resPlateExtensions["width"]
if self . direction == " vertical " :
if not self . snakeMode : [ hTranslation , vTranslation ] = [ 0 , translation1 ]
if self . snakeMode and self . bends % 2 == 0 : [ hTranslation , vTranslation ] = [ translation2 , translation1 ]
if self . snakeMode and self . bends % 2 != 0 : [ hTranslation , vTranslation ] = [ translation2 , 0 ]
2022-07-13 04:20:55 -05:00
self . terminal1Box = Box ( int ( self . resPlateExtensions [ " ex1 " ] [ " XMin " ] )
, int ( self . resPlateExtensions [ " ex1 " ] [ " YMin " ] )
, int ( self . resPlateExtensions [ " ex1 " ] [ " XMax " ] )
, int ( self . resPlateExtensions [ " ex1 " ] [ " YMax " ] )
2020-03-30 05:40:29 -05:00
)
2022-07-13 04:20:55 -05:00
self . terminal2Box = Box ( int ( self . resPlateExtensions [ " ex1 " ] [ " XMin " ] - hTranslation )
, int ( self . resPlateExtensions [ " ex1 " ] [ " YMin " ] + vTranslation )
, int ( self . resPlateExtensions [ " ex1 " ] [ " XMax " ] - hTranslation )
, int ( self . resPlateExtensions [ " ex1 " ] [ " YMax " ] + vTranslation )
2020-03-30 05:40:29 -05:00
)
if self . direction == " horizontal " :
if not self . snakeMode : [ hTranslation , vTranslation ] = [ translation1 , 0 ]
if self . snakeMode and self . bends % 2 == 0 : [ hTranslation , vTranslation ] = [ translation1 , translation2 ]
if self . snakeMode and self . bends % 2 != 0 : [ hTranslation , vTranslation ] = [ 0 , translation2 ]
print ( " vTranslation " , vTranslation )
print ( " hTranslation " , hTranslation )
self . terminal1Box = Box ( self . resPlateExtensions [ " ex1 " ] [ " XMin " ]
, self . resPlateExtensions [ " ex1 " ] [ " YMin " ]
, self . resPlateExtensions [ " ex1 " ] [ " XMax " ]
, self . resPlateExtensions [ " ex1 " ] [ " YMax " ]
)
self . terminal2Box = Box ( self . resPlateExtensions [ " ex1 " ] [ " XMin " ] + hTranslation
, self . resPlateExtensions [ " ex1 " ] [ " YMin " ] + vTranslation
, self . resPlateExtensions [ " ex1 " ] [ " XMax " ] + hTranslation
, self . resPlateExtensions [ " ex1 " ] [ " YMax " ] + vTranslation
)
terminal1Pad = Pad . create ( self . nets [ 0 ] , layer , self . terminal1Box )
terminal2Pad = Pad . create ( self . nets [ 1 ] , layer , self . terminal2Box )
return
def computePImplantLayerPosition ( self ) :
factor1 = factor2 = - 1
if not self . snakeMode : centerTranslation = 0
if self . snakeMode : centerTranslation = self . bends * ( self . snakeSegments_spacing + self . snakeSegmentDict [ " width " ] ) / 2
if self . direction == " vertical " :
keysList = [ " YCenter " , " XMin " , " XMax " , " YMin " ]
functionsList = [ self . abutmentBox . getYCenter ( ) , self . abutmentBox . getXCenter ( ) ]
if self . snakeMode and self . bends % 2 != 0 : factor1 = 1
if self . snakeMode : factor2 = 1
if self . direction == " horizontal " :
keysList = [ " XCenter " , " YMin " , " YMax " , " XMin " ]
functionsList = [ self . abutmentBox . getXCenter ( ) , self . abutmentBox . getYCenter ( ) ]
if not self . snakeMode : resistorLength = self . resDim [ " length " ]
if self . snakeMode : resistorLength = self . snakeSegmentDict [ " length " ]
self . pImplant_layerDict [ keysList [ 0 ] ] = functionsList [ 0 ] + factor1 * ( resistorLength / 2 + self . pImplant_layerDict [ " length " ] / 2 )
self . pImplant_layerDict [ keysList [ 1 ] ] = functionsList [ 1 ] + factor2 * centerTranslation - self . pImplant_layerDict [ " width " ] / 2 #- centerTranslation - self.pImplant_layerDict["width" ]/2
self . pImplant_layerDict [ keysList [ 2 ] ] = self . pImplant_layerDict [ keysList [ 1 ] ] + self . pImplant_layerDict [ " width " ]
return
def drawPImplantLayer ( self , layer ) :
self . computePImplantLayerPosition ( )
if not self . snakeMode : resistorLength = self . resDim [ " length " ]
if self . snakeMode : resistorLength = self . snakeSegmentDict [ " length " ]
if not self . snakeMode or self . snakeMode and self . bends % 2 == 0 : centerTranslation = resistorLength + self . pImplant_layerDict [ " length " ]
if self . snakeMode and self . bends % 2 != 0 : centerTranslation = 0
if not self . snakeMode : extrimitiesTranslation = 0
if self . snakeMode : extrimitiesTranslation = self . bends * ( self . snakeSegments_spacing + self . snakeSegmentDict [ " width " ] ) #+ self.pImplant_layerDict["width"]/2
if self . direction == " vertical " :
for i in [ 0 , 1 ] : Horizontal . create ( self . nets [ i ] , layer
2022-07-13 04:20:55 -05:00
, int ( self . pImplant_layerDict [ " YCenter " ] + i * centerTranslation )
, int ( self . pImplant_layerDict [ " length " ] )
, int ( self . pImplant_layerDict [ " XMin " ] - i * extrimitiesTranslation )
, int ( self . pImplant_layerDict [ " XMax " ] - i * extrimitiesTranslation )
2020-03-30 05:40:29 -05:00
)
if self . direction == " horizontal " :
for i in [ 0 , 1 ] : Vertical . create ( self . nets [ i ] , layer
2022-07-13 04:20:55 -05:00
, int ( self . pImplant_layerDict [ " XCenter " ] + i * centerTranslation )
, int ( self . pImplant_layerDict [ " length " ] )
, int ( self . pImplant_layerDict [ " YMin " ] + i * extrimitiesTranslation )
, int ( self . pImplant_layerDict [ " YMax " ] + i * extrimitiesTranslation )
2020-03-30 05:40:29 -05:00
)
return
## t1Cut connected to terminal1 (on the right side/bottom side of rectangular)
def computecenterTranslationDimensions ( self ) :
enclosure1 = ( self . resPlateExtensions [ " width " ] - ( self . contactsNumber * self . minHeight_contact + ( self . contactsNumber - 1 ) * self . minSpacing_contact ) ) / 2
enclosure2 = self . minEnclosure_resistorPlate_contact
if self . resistorType == " RPOLYH " : enclosure3 = self . minEnclosure_pImplantLayer_contact
if self . resistorType == " RPOLY2PH " : enclosure3 = 0
if self . direction == " vertical " :
self . t1cutsEnclosure [ " horizontal " ] = enclosure1
if not self . snakeMode or self . snakeMode and self . bends % 2 == 0 : self . t1cutsEnclosure [ " vertical " ] = enclosure2
if self . snakeMode and self . bends % 2 != 0 : self . t1cutsEnclosure [ " vertical " ] = enclosure3
self . t2cutsEnclosure [ " horizontal " ] = enclosure1
self . t2cutsEnclosure [ " vertical " ] = enclosure3
if self . direction == " horizontal " :
self . t1cutsEnclosure [ " horizontal " ] = enclosure2
self . t1cutsEnclosure [ " vertical " ] = enclosure1
if not self . snakeMode or self . snakeMode and self . bends % 2 == 0 : self . t2cutsEnclosure [ " horizontal " ] = enclosure3
if self . snakeMode and self . bends % 2 != 0 : self . t2cutsEnclosure [ " horizontal " ] = enclosure2
#self.t2cutsEnclosure["horizontal"] = enclosure3
self . t2cutsEnclosure [ " vertical " ] = enclosure1
self . t1CutCenterDict [ " XCenter " ] = self . terminal1Box . getXMin ( ) + self . t1cutsEnclosure [ " horizontal " ] + self . minWidth_contact / 2
self . t1CutCenterDict [ " YCenter " ] = self . terminal1Box . getYMin ( ) + self . t1cutsEnclosure [ " vertical " ] + self . minHeight_contact / 2
self . t2CutCenterDict [ " XCenter " ] = self . terminal2Box . getXMin ( ) + self . t2cutsEnclosure [ " horizontal " ] + self . minWidth_contact / 2
self . t2CutCenterDict [ " YCenter " ] = self . terminal2Box . getYMin ( ) + self . t2cutsEnclosure [ " vertical " ] + self . minHeight_contact / 2
return
def drawContacts ( self , layer ) :
self . computecenterTranslationDimensions ( )
if self . direction == " vertical " : cutLineDirection = " horizontal "
if self . direction == " horizontal " : cutLineDirection = " vertical "
self . cutLine ( self . nets [ 0 ] , layer
, self . t1CutCenterDict [ " XCenter " ]
, self . t1CutCenterDict [ " YCenter " ]
, self . minWidth_contact
, self . minHeight_contact
, self . minSpacing_contact
, self . contactsNumber
, cutLineDirection
)
self . cutLine ( self . nets [ 1 ] , layer
, self . t2CutCenterDict [ " XCenter " ]
, self . t2CutCenterDict [ " YCenter " ]
, self . minWidth_contact
, self . minHeight_contact
, self . minSpacing_contact
, self . contactsNumber
, cutLineDirection
)
return
def drawRoutingLayer ( self , layer ) :
layer_width = self . minWidth_contact + 2 * self . minEnclosure_routingLayer_contact
layer_height = self . contactsNumber * self . minWidth_contact + ( self . contactsNumber - 1 ) * self . minSpacing_contact + 2 * self . minEnclosure_routingLayer_contact
if self . direction == " vertical " : key = " XCenter "
if self . direction == " horizontal " : key = " YCenter "
source1 = self . t1CutCenterDict [ key ] - self . minWidth_contact / 2 - self . minEnclosure_routingLayer_contact
target1 = source1 + layer_height
source2 = self . t2CutCenterDict [ key ] - self . minWidth_contact / 2 - self . minEnclosure_routingLayer_contact
target2 = source2 + layer_height
if self . direction == " vertical " :
Horizontal . create ( self . nets [ 0 ]
2022-07-13 04:20:55 -05:00
, layer
, int ( self . t1CutCenterDict [ " YCenter " ] )
, int ( layer_width )
, int ( source1 )
, int ( target1 ) )
2020-03-30 05:40:29 -05:00
Horizontal . create ( self . nets [ 1 ]
, layer
2022-07-13 04:20:55 -05:00
, int ( self . t2CutCenterDict [ " YCenter " ] )
, int ( layer_width )
, int ( source2 )
, int ( target2 ) )
2020-03-30 05:40:29 -05:00
trace ( 101 , ' \t IN PAD self.t1CutCenterDict[ " XCenter " ] = {0} \n ' . format ( DbU . getValueString ( self . t1CutCenterDict [ " XCenter " ] ) ) )
trace ( 101 , ' \t IN PAD source1 = {0} \n ' . format ( DbU . getValueString ( source1 ) ) )
trace ( 101 , ' \t IN PAD target1 = {0} \n ' . format ( DbU . getValueString ( target1 ) ) )
#h = Horizontal.create( self.nets[0]
# , self.layers['metal2']
# , self.t1CutCenterDict["YCenter"]
# , layer_width
# , source1
# , target1 )
#NetExternalComponents.setExternal( h )
#
#h = Horizontal.create( self.nets[1]
# , self.layers['metal2']
# , self.t2CutCenterDict["YCenter"]
# , layer_width
# , source2
# , target2 )
#NetExternalComponents.setExternal( h )
if self . direction == " horizontal " :
Vertical . create ( self . nets [ 0 ] , layer , self . t1CutCenterDict [ " XCenter " ] , layer_width , source1 , target1 )
Vertical . create ( self . nets [ 1 ] , layer , self . t2CutCenterDict [ " XCenter " ] , layer_width , source2 , target2 )
return
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
def drawRestrmLayer ( self , layer ) :
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
self . computeRestrmLayerPosition ( )
if not self . snakeMode : resistorLength = self . resDim [ " length " ]
if self . snakeMode : resistorLength = self . snakeSegmentDict [ " length " ]
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
if not self . snakeMode or self . snakeMode and self . bends % 2 == 0 : centerTranslation = resistorLength + self . restrmLayerDict [ " width " ]
if self . snakeMode and self . bends % 2 != 0 : centerTranslation = 0
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
if not self . snakeMode : extrimitiesTranslation = 0
if self . snakeMode : extrimitiesTranslation = self . bends * ( self . snakeSegments_spacing + self . snakeSegmentDict [ " width " ] )
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
if self . direction == " vertical " :
for i in [ 0 , 1 ] : Horizontal . create ( self . nets [ i ] , layer
, self . restrmLayerDict [ " YCenter " ] + i * centerTranslation
, self . restrmLayerDict [ " width " ]
, self . restrmLayerDict [ " XMin " ] - i * extrimitiesTranslation
, self . restrmLayerDict [ " XMax " ] - i * extrimitiesTranslation
)
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
if self . direction == " horizontal " :
for i in [ 0 , 1 ] : Vertical . create ( self . nets [ i ] , layer
, self . restrmLayerDict [ " XCenter " ] + i * centerTranslation
, self . restrmLayerDict [ " width " ]
, self . restrmLayerDict [ " YMin " ] + i * extrimitiesTranslation
, self . restrmLayerDict [ " YMax " ] + i * extrimitiesTranslation
)
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
return
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
def computeRestrmLayerPosition ( self ) :
self . restrmLayerDict [ " width " ] = self . minWidth_contact / 2
factor = 1
if self . direction == " vertical " :
keysList = [ " YCenter " , " XMin " , " XMax " ]
# if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : factor = 1
if self . snakeMode and self . bends % 2 != 0 : factor = - 1
if self . direction == " horizontal " :
keysList = [ " XCenter " , " YMin " , " YMax " ]
self . restrmLayerDict [ keysList [ 0 ] ] = self . t1CutCenterDict [ keysList [ 0 ] ] + factor * self . restrmLayerDict [ " width " ] / 2
self . restrmLayerDict [ keysList [ 1 ] ] = self . resPlateExtensions [ " ex1 " ] [ keysList [ 1 ] ] - self . restrmLayerDict [ " width " ]
self . restrmLayerDict [ keysList [ 2 ] ] = self . resPlateExtensions [ " ex1 " ] [ keysList [ 2 ] ] + self . restrmLayerDict [ " width " ]
return
def computeResDefDimensions ( self ) :
if self . direction == " vertical " : keysList = [ " YMin " , " YMax " , " XCenter " , " width " ]
if self . direction == " horizontal " : keysList = [ " XMin " , " XMax " , " YCenter " , " width " ]
if not self . snakeMode : resistorElement = self . resistorPlateDict
if self . snakeMode : resistorElement = self . snakeSegmentDict
if self . resistorType == " RPOLYH " : factor = 0
if self . resistorType == " RPOLY2PH " : factor = 1
self . resdefLayerDict [ keysList [ 0 ] ] = resistorElement [ keysList [ 0 ] ] - factor * self . minWidth_contact / 4
self . resdefLayerDict [ keysList [ 1 ] ] = resistorElement [ keysList [ 1 ] ] + factor * self . minWidth_contact / 4
self . resdefLayerDict [ keysList [ 2 ] ] = resistorElement [ keysList [ 2 ] ]
self . resdefLayerDict [ keysList [ 3 ] ] = resistorElement [ keysList [ 3 ] ]
if self . resDim [ " width " ] > = self . resPlateExtensions_minWidth :
self . resdefLayerDict [ keysList [ 3 ] ] = self . resdefLayerDict [ keysList [ 3 ] ] + self . minWidth_contact / 2
return
def computeFirstSnakeCornerPosition90 ( self ) :
if self . direction == " vertical " :
self . snakeCornerDict [ " YCenter " ] = self . snakeSegmentDict [ " YMin " ] - self . snakeCornerDict [ " width " ] / 2
self . snakeCornerDict [ " XMin " ] = self . snakeSegmentDict [ " XCenter " ] - self . snakeSegmentDict [ " width " ] / 2
self . snakeCornerDict [ " XMax " ] = self . snakeCornerDict [ " XMin " ] + self . snakeCornerDict [ " length " ]
if self . direction == " horizontal " :
self . snakeCornerDict [ " XCenter " ] = self . snakeSegmentDict [ " XMax " ] + self . snakeCornerDict [ " width " ] / 2
self . snakeCornerDict [ " YMin " ] = self . snakeSegmentDict [ " YCenter " ] - self . snakeSegmentDict [ " width " ] / 2
self . snakeCornerDict [ " YMax " ] = self . snakeCornerDict [ " YMin " ] + self . snakeCornerDict [ " length " ]
return
def drawCorners90 ( self , layer ) :
self . computeFirstSnakeCornerPosition90 ( )
k = 0
translation = self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing
centersTranslationConst = self . snakeSegmentDict [ " width " ] + self . snakeSegmentDict [ " length " ]
if self . direction == " vertical " :
snakeCornersYCenters = [ self . snakeCornerDict [ " YCenter " ]
, self . snakeCornerDict [ " YCenter " ] + centersTranslationConst ]
for i in range ( 0 , self . bends ) :
Horizontal . create ( self . nets [ 0 ] , layer
, snakeCornersYCenters [ k ]
, self . snakeCornerDict [ " width " ]
, self . snakeCornerDict [ " XMin " ] + i * translation
, self . snakeCornerDict [ " XMax " ] + i * translation
)
k = k + 1 if k < 1 else 0
if self . direction == " horizontal " :
snakeCornersXCenters = [ self . snakeCornerDict [ " XCenter " ]
, self . snakeCornerDict [ " XCenter " ] - centersTranslationConst ]
for i in range ( 0 , self . bends ) :
Vertical . create ( self . nets [ 0 ] , layer
, snakeCornersXCenters [ k ]
, self . snakeCornerDict [ " width " ]
, self . snakeCornerDict [ " YMin " ] + i * translation
, self . snakeCornerDict [ " YMax " ] + i * translation
)
k = k + 1 if k < 1 else 0
return
def computeFirstSnakeCornerPosition135 ( self ) :
param1 = ( self . snakeSegmentDict [ " width " ] * 42 / 100 ) / 2
param2 = toDbU ( 0.2 )
param3 = self . snakeSegmentDict [ " width " ] + param2
param4 = param3 - param1
if self . direction == " vertical " :
rx0 = self . snakeSegmentDict [ " XCenter " ] - self . snakeSegmentDict [ " width " ] / 2
ry0 = self . snakeSegmentDict [ " YMin " ]
rx1 = rx0
ry1 = ry0 - param1
rx2 = rx0 + param4
ry2 = ry1 - param4
rx3 = rx0 + 2 * self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing - param4
ry3 = ry2
rx4 = rx3 + param4
ry4 = ry1
rx5 = rx4
ry5 = ry0
rx6 = rx5 - self . snakeSegmentDict [ " width " ]
ry6 = ry0
rx7 = rx0 + self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing - param2
ry7 = ry0 - param2
rx8 = rx0 + self . snakeSegmentDict [ " width " ] + param2
ry8 = ry7
rx9 = rx0 + self . snakeSegmentDict [ " width " ]
ry9 = ry0
if self . direction == " horizontal " :
rx0 = self . snakeSegmentDict [ " XMax " ]
ry0 = self . snakeSegmentDict [ " YCenter " ] - self . snakeSegmentDict [ " width " ] / 2
rx1 = rx0 + param1
ry1 = ry0
rx2 = rx1 + ( self . snakeSegmentDict [ " width " ] + param2 ) - param1
ry2 = ry1 + ( self . snakeSegmentDict [ " width " ] + param2 ) - param1
rx3 = rx2
ry3 = ry2 + ( 2 * self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing ) - 2 * ( self . snakeSegmentDict [ " width " ] + param2 - param1 )
rx4 = rx1
ry4 = ry1 + 2 * self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing
rx5 = rx0
ry5 = ry0 + 2 * self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing
rx6 = rx0
ry6 = ry0 + self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing
rx7 = rx0 + param2
ry7 = ry6 - param2
rx8 = rx7
ry8 = ry0 + self . snakeSegmentDict [ " width " ] + param2
rx9 = rx0
ry9 = ry0 + self . snakeSegmentDict [ " width " ]
rightCorCordinatesList = [ [ rx0 , ry0 ] , [ rx1 , ry1 ]
, [ rx2 , ry2 ] , [ rx3 , ry3 ]
, [ rx4 , ry4 ] , [ rx5 , ry5 ]
, [ rx6 , ry6 ] , [ rx7 , ry7 ]
, [ rx8 , ry8 ] , [ rx9 , ry9 ]
]
for p in rightCorCordinatesList :
2022-07-13 04:20:55 -05:00
self . rightCorPointsVector . append ( Point ( int ( p [ 0 ] ) , int ( p [ 1 ] ) ) )
self . leftCorPointsVector . append ( Point ( int ( p [ 0 ] ) , int ( p [ 1 ] ) ) )
2020-03-30 05:40:29 -05:00
translationList = [ self . snakeSegmentDict [ " length " ]
, self . snakeSegmentDict [ " length " ] + 2 * param1
, self . snakeSegmentDict [ " length " ] + 2 * param3
, self . snakeSegmentDict [ " length " ] + 2 * param3
, self . snakeSegmentDict [ " length " ] + 2 * param1
, self . snakeSegmentDict [ " length " ]
, self . snakeSegmentDict [ " length " ]
, self . snakeSegmentDict [ " length " ] + 2 * param2
, self . snakeSegmentDict [ " length " ] + 2 * param2
, self . snakeSegmentDict [ " length " ]
]
if self . direction == " vertical " :
2022-07-13 04:20:55 -05:00
for i in range ( 0 , len ( self . leftCorPointsVector ) ) : self . leftCorPointsVector [ i ] . translate ( 0 , int ( translationList [ i ] ) )
2020-03-30 05:40:29 -05:00
if self . direction == " horizontal " :
2022-07-13 04:20:55 -05:00
for i in range ( 0 , len ( self . leftCorPointsVector ) ) : self . leftCorPointsVector [ i ] . translate ( int ( - translationList [ i ] ) , 0 )
2020-03-30 05:40:29 -05:00
return
def drawCorners135 ( self , layer ) :
self . computeFirstSnakeCornerPosition135 ( )
2022-07-13 04:20:55 -05:00
if self . bends % 2 == 0 : [ rightCornersNum , leftCornersNum ] = [ self . bends / / 2 , self . bends / / 2 ]
if self . bends % 2 != 0 : [ rightCornersNum , leftCornersNum ] = [ ( self . bends + 1 ) / / 2 , ( self . bends - 1 ) / / 2 ]
2020-03-30 05:40:29 -05:00
translationFactor = 2 * ( self . snakeSegmentDict [ " width " ] + self . snakeSegments_spacing )
if self . direction == " vertical " : [ dxTranslation , dyTranslation ] = [ translationFactor , 0 ]
if self . direction == " horizontal " : [ dxTranslation , dyTranslation ] = [ 0 , translationFactor ]
for i in range ( 0 , rightCornersNum ) :
Rectilinear . create ( self . nets [ 0 ] , layer , self . rightCorPointsVector ) . translate ( i * dxTranslation , i * dyTranslation )
for i in range ( 0 , leftCornersNum ) :
if i == 0 :
2022-07-13 04:20:55 -05:00
if self . direction == " vertical " : Rectilinear . create ( self . nets [ 0 ] , layer , self . leftCorPointsVector ) . translate ( dxTranslation / / 2 , dyTranslation )
if self . direction == " horizontal " : Rectilinear . create ( self . nets [ 0 ] , layer , self . leftCorPointsVector ) . translate ( dxTranslation , dyTranslation / / 2 )
2020-03-30 05:40:29 -05:00
if i != 0 :
2022-07-13 04:20:55 -05:00
if self . direction == " vertical " : Rectilinear . create ( self . nets [ 0 ] , layer , self . leftCorPointsVector ) . translate ( i * 3 * dxTranslation / / 2 , dyTranslation )
if self . direction == " horizontal " : Rectilinear . create ( self . nets [ 0 ] , layer , self . leftCorPointsVector ) . translate ( dxTranslation , i * 3 * dyTranslation / / 2 )
2020-03-30 05:40:29 -05:00
return
def drawCorners ( self , layer ) :
if self . shape == 90 : self . drawCorners90 ( layer )
if self . shape == 135 : self . drawCorners135 ( layer )
return
# def drawResDefLayer( self, layer ):
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
2020-03-30 05:40:29 -05:00
# self.computeResDefDimensions()
# if self.direction == "vertical" : Vertical.create ( self.nets[0], layer, self.resdefLayerDict["XCenter"], self.resdefLayerDict["width"], self.resdefLayerDict["YMin"], self.resdefLayerDict["YMax"] )
# if self.direction == "horizontal" : Horizontal.create ( self.nets[0], layer, self.resdefLayerDict["YCenter"], self.resdefLayerDict["width"], self.resdefLayerDict["XMin"], self.resdefLayerDict["XMax"] )
# return
## Creates a horizontal or vertical line of contacts according to the specified direction.
def cutLine ( self , net , layer , firstCutXCenter , firstCutYCenter , width_cut , height_cut , spacing_cut , cutNumber , direction ) :
for i in range ( 0 , cutNumber ) :
2022-07-13 04:20:55 -05:00
if direction == ' horizontal ' :
segment = Contact . create ( net
, layer
, int ( firstCutXCenter + i * ( width_cut + spacing_cut ) )
, int ( firstCutYCenter )
, int ( width_cut )
, int ( height_cut ) )
else :
segment = Contact . create ( net
, layer
, int ( firstCutXCenter )
, int ( firstCutYCenter + i * ( height_cut + spacing_cut ) )
, int ( width_cut )
, int ( height_cut ) )
2020-03-30 05:40:29 -05:00
return segment
## Computes the maximal number of cuts to be placed on a layer of width \c width_layer considering specifications such as the spacing between the cuts, its width and its enclosure in the layer.
def cutMaxNumber ( self , width_layer , width_cut , spacing_cut , enclosure_cut ) :
cutNumber = int ( ( width_layer - 2 * enclosure_cut + spacing_cut ) / ( width_cut + spacing_cut ) )
if cutNumber > 0 : return cutNumber
else :
raise Error ( 1 , " cutMaxNumber() : Zero number of cuts found. Layer width is too tight. " )
def drawTerminals ( self ) :
VIA1overhang = self . minWidth_cut1 / 2 + self . minEnclosure_metal1_cut1
t1net = self . device . getNet ( ' t1 ' )
t2net = self . device . getNet ( ' t2 ' )
t1metal1 = None
t2metal1 = None
for component in t1net . getComponents ( ) :
if isinstance ( component , Horizontal ) and component . getLayer ( ) == self . metal1 :
t1metal1 = component
break
for component in t2net . getComponents ( ) :
if isinstance ( component , Horizontal ) and component . getLayer ( ) == self . metal1 :
t2metal1 = component
break
ab = self . device . getAbutmentBox ( )
t1OnNorth = isNearNorth ( t1metal1 . getY ( ) , ab )
t2OnNorth = isNearNorth ( t2metal1 . getY ( ) , ab )
if t1OnNorth and t2OnNorth :
t1YM2 = ab . getYMax ( ) - self . hpitch * 2
t2YM2 = ab . getYMax ( ) - self . hpitch
elif t1OnNorth :
t1YM2 = ab . getYMax ( ) - self . hpitch
t2YM2 = ab . getYMin ( ) + self . hpitch
elif t2OnNorth :
t1YM2 = ab . getYMin ( ) + self . hpitch
t2YM2 = ab . getYMax ( ) - self . hpitch
else :
t1YM2 = ab . getYMin ( ) + self . hpitch * 2
t2YM2 = ab . getYMin ( ) + self . hpitch
m1Width = self . contactsNumber * self . minWidth_contact \
+ ( self . contactsNumber - 1 ) * self . minSpacing_contact \
+ 2 * self . minEnclosure_routingLayer_contact
edgeDelta = self . minWidth_contact / 2 + self . minEnclosure_metal1_cut0
if t1OnNorth :
2022-07-13 04:20:55 -05:00
t1BoxM1 = Box ( int ( 0 )
, int ( self . t1CutCenterDict [ " YCenter " ] - edgeDelta )
, int ( m1Width )
, int ( t1YM2 + VIA1overhang )
2020-03-30 05:40:29 -05:00
)
else :
2022-07-13 04:20:55 -05:00
t1BoxM1 = Box ( int ( 0 )
, int ( t1YM2 - VIA1overhang )
, int ( m1Width )
, int ( self . t1CutCenterDict [ " YCenter " ] + edgeDelta )
2020-03-30 05:40:29 -05:00
)
2022-07-13 04:20:55 -05:00
t1BoxM1 . translate ( int ( self . t1CutCenterDict [ " XCenter " ] - edgeDelta ) , 0 )
2020-03-30 05:40:29 -05:00
if t2OnNorth :
2022-07-13 04:20:55 -05:00
t2BoxM1 = Box ( int ( 0 )
, int ( self . t2CutCenterDict [ " YCenter " ] - edgeDelta )
, int ( m1Width )
, int ( t2YM2 + VIA1overhang )
2020-03-30 05:40:29 -05:00
)
else :
2022-07-13 04:20:55 -05:00
t2BoxM1 = Box ( int ( 0 )
, int ( t2YM2 - VIA1overhang )
, int ( m1Width )
, int ( self . t2CutCenterDict [ " YCenter " ] + edgeDelta )
2020-03-30 05:40:29 -05:00
)
2022-07-13 04:20:55 -05:00
t2BoxM1 . translate ( int ( self . t2CutCenterDict [ " XCenter " ] - edgeDelta ) , 0 )
2020-03-30 05:40:29 -05:00
self . drawM2Terminal ( t1net , t1BoxM1 , t1YM2 )
self . drawM2Terminal ( t2net , t2BoxM1 , t2YM2 )
return
def drawM2Terminal ( self , net , boxM1 , axisM2 ) :
ab = self . device . getAbutmentBox ( )
minBoxM1 = Box ( boxM1 . getCenter ( ) . getX ( ) , axisM2 )
2022-07-13 04:20:55 -05:00
minBoxM1 . inflate ( int ( self . minWidth_cut1 / 2 + self . minEnclosure_metal1_cut1 ) )
2020-03-30 05:40:29 -05:00
boxM1 . merge ( minBoxM1 )
h = Horizontal . create ( net
, self . metal2
2022-07-13 04:20:55 -05:00
, int ( axisM2 )
, int ( self . metal2Width )
, int ( ab . getXMin ( ) )
, int ( ab . getXMax ( ) ) )
2020-03-30 05:40:29 -05:00
NetExternalComponents . setExternal ( h )
Vertical . create ( net
, self . metal1
2022-07-13 04:20:55 -05:00
, int ( boxM1 . getCenter ( ) . getX ( ) )
, int ( boxM1 . getWidth ( ) )
, int ( boxM1 . getYMin ( ) )
, int ( boxM1 . getYMax ( ) )
2020-03-30 05:40:29 -05:00
)
cutNumber = ( ( boxM1 . getWidth ( ) - 2 * self . minEnclosure_metal1_cut1 - self . minWidth_cut1 ) \
2022-07-13 04:20:55 -05:00
/ / ( self . minSpacing_cut1 + self . minWidth_cut1 ) )
2020-03-30 05:40:29 -05:00
if cutNumber < = 0 : cutNumber = 1
centering = ( boxM1 . getWidth ( ) - 2 * self . minEnclosure_metal1_cut1 \
- cutNumber * self . minWidth_cut1 \
2022-07-13 04:20:55 -05:00
- ( cutNumber - 1 ) * self . minSpacing_cut1 ) / / 2
2020-03-30 05:40:29 -05:00
xcut1 = boxM1 . getXMin ( ) + centering \
2022-07-13 04:20:55 -05:00
+ self . minEnclosure_metal1_cut1 + self . minWidth_cut1 / / 2
2020-03-30 05:40:29 -05:00
trace ( 101 , ' \t cutNumber = {0} \n ' . format ( cutNumber ) )
for i in range ( cutNumber ) :
trace ( 101 , ' \t [ {0} ] \n ' . format ( i ) )
Contact . create ( net
, self . cut1
2022-07-13 04:20:55 -05:00
, int ( xcut1 )
, int ( axisM2 )
, int ( self . minWidth_cut1 )
, int ( self . minWidth_cut1 )
2020-03-30 05:40:29 -05:00
)
xcut1 + = self . minWidth_cut1 + self . minSpacing_cut1
return
2020-04-08 04:24:42 -05:00
def scriptMain ( * * kw ) :
2020-03-30 05:40:29 -05:00
editor = None
2022-07-13 04:20:55 -05:00
if ' editor ' in kw and kw [ ' editor ' ] :
2020-03-30 05:40:29 -05:00
editor = kw [ ' editor ' ]
UpdateSession . open ( )
device = AllianceFramework . get ( ) . createCell ( ' resistor ' )
device . setTerminal ( True )
t_1 = Net . create ( device , ' t1 ' )
t_1 . setExternal ( True )
t1 = device . getNet ( " t1 " )
doBreak ( 1 , ' Done building terminal 1 net ' )
t_2 = Net . create ( device , ' t2 ' )
t_2 . setExternal ( True )
t2 = device . getNet ( " t2 " )
doBreak ( 1 , ' Done building terminal 1 net ' )
if editor :
UpdateSession . close ( )
editor . setCell ( device )
editor . fit ( )
UpdateSession . open ( )
nets = [ t1 , t2 ]
#(device, resistorType, resistance = 0, resDim = { "width" : 10, "length" : 0 }, direction = "vertical", bends = 0 ):
#resistor = Resistor( device, nets, "RPOLY2PH", 50, direction = "vertical" )
#resistor = Resistor( device, nets, "RPOLY2PH", 200, direction = "horizontal", resDim = { "width" : 0.8, "length" : 0 } ) #w >= 2 dogBone not possible in 0.35 um (used only in test)
#resistor = Resistor( device, nets, "RPOLY2PH", 800, direction = "vertical", resDim = { "width" : 0.8, "length" : 0 }, bends = 4 ) #w >= 2 dogBone not possible
#resistor = Resistor( device, nets, "RPOLYH", 4800, direction = "vertical", resDim = { "width" : 0.8, "length" : 0 } ) #w = 0.8 dogBone
#resistor = Resistor( device, nets, "RPOLYH", 48000, direction = "horizontal", resDim = { "width" : 0.8, "length" : 0 }, bends = 3 ) #w = 0.8 dogBone
#resistor = Resistor( device, nets, "RPOLY2PH", 200, direction = "horizontal") #RPOLY2PH normal
#resistor = Resistor( device, nets, "RPOLYH", 7000, direction = "horizontal", resDim = { "width" : 10, "length" : 0 }) #RPOLYH normal
#resistor = Resistor( device, nets, "RPOLYH", 20000, direction = "vertical", bends = 1, shape = 135 ) #RPOLYH snake
resistor = Resistor ( device , nets , " RPOLY2PH " , 2000 , resDim = { " width " : 2.5 , " length " : 0 } , direction = " vertical " , bends = 1 , shape = 90 ) #RPOLY2PH snake
abutmentBoxDim = resistor . create ( )
print ( " abutmentBoxDim " , abutmentBoxDim )
AllianceFramework . get ( ) . saveCell ( device , Catalog . State . Views )
return True