#!/usr/bin/python

import sys		
from   Hurricane        import *
from   CRL              import *
import Constant
from   math             import sqrt, ceil
import helpers
from   helpers.io       import ErrorMessage as Error
from   helpers          import trace, u
import oroshi


def doBreak( level, message ):
    UpdateSession.close()
    Breakpoint.stop( level, message )
    UpdateSession.open()

def toDbU    ( l ): return DbU.fromPhysical( l, DbU.UnitPowerMicro )
def toPhy    ( l ): return DbU.toPhysical  ( l, DbU.UnitPowerMicro )

def toFoundryGrid ( l ):
    twoGrid = DbU.fromGrid( 2.0 )
    return l + (twoGrid - (l % twoGrid))

def isNearNorth ( y, ab ): return ab.getYMax() - y < y - ab.getYMin()


class Resistor ( object ):

    rules = oroshi.getRules()

    def __init__( self, device, nets, resistorType, resistance = 0, resDim = { "width" : 10, "length" : 0 }, direction = "horizontal", bends = 0, shape = 90 ):

        self.device = device
        self.nets   = nets

        trace( 100, '\twidth:{0}, length:{1}, bends:{2}\n'.format(resDim['width'],resDim['length'],bends) )
        
       #resDim["width" ] = toDbU(resDim["width" ])
       #resDim["length"] = toDbU(resDim["length"]) 

        self.__initArgs__  ( resistorType, direction, bends, shape )
        self.setRules()
        self.__initResDim__( resistance  , resDim) 

        if self.snakeMode: 
            self.snakeSegmentDict           = {}
            self.resPlateExtrimity1         = {}
            self.resPlateExtrimity2         = {}
            self.resPlateExtension1         = {}
            self.resPlateExtension2         = {}
            self.snakeCornerDict            = {}
            if self.shape == 135 : 
                self.rightCorPointsVector   = []
                self.leftCorPointsVector    = []

        self.resPlateExtensions             = {}
        self.resPlateExtrimities            = {}

        self.resistorPlateDict              = {}
        self.abutmentBoxDict                = { "XMin" : 0, "YMin" : 0 }
        self.abutmentBox                    =    Box ()
        self.terminal1Box                   =    Box()
        self.terminal2Box                   =    Box()

        self.t1cutsEnclosure                = {}
        self.t2cutsEnclosure                = {}
 
        self.t1CutCenterDict                = {}
        self.t2CutCenterDict                = {}
            
        if self.resistorType == "RPOLYH" : 
            self.pImplant_layerDict         = {}
            self.hresLayerDict              = {}
        if self.resistorType == "RPOLY2PH" :
            self.restrmLayerDict            = {}

        self.resdefLayerDict                = {}
        self.enclosure_resistor_abutmentBox = {}

        return



    def __initArgs__( self, resistorType, direction, bends, shape ):

        if resistorType == "RPOLYH" or resistorType == "RPOLY2PH" :   self.resistorType = resistorType
        else                                                      :   raise Error(1,'__initArgs__() : Unsupported resistor type : %s.' % resistorType)

        if direction in ["horizontal", "vertical"]                :   self.direction = direction
        else                                                      :   raise Error(1,'__initDirection__() : Direction must be either "horizontal" or "vertical".')

        if bends >= 0                                             :
            if bends == 0                                         : [ self.bends, self.snakeMode             ] = [ bends , False        ]
            elif bends  > 0 and shape in [90, 135]                : [ self.bends, self.snakeMode, self.shape ] = [ bends , True, shape  ]
            else                                                  :   raise Error(1,'__initArgs__() : Resistor shape must be either 90 or 135 degrees : shape = %s.' %shape)
        else                                                      :   raise Error(1,'__initArgs__() : Bends number must not be negative : bends = %s.' %bends)
        
        return


    def __initContactsNumber__( self, resDim ):

        layer_minWidth      = Resistor.rules.minWidth_cut0 + 2*Resistor.rules.minEnclosure_poly2_cut0
        layerWidth          = self.resPlateExtensions_minWidth if resDim["width"] < layer_minWidth else resDim["width"]

        self.contactsNumber = self.cutMaxNumber(layerWidth, Resistor.rules.minWidth_cut0, Resistor.rules.minSpacing_cut0, Resistor.rules.minEnclosure_poly2_cut0)

        return


    
    def __initResDim__( self, resistance, resDim ):

        if self.__isDimOk__( resDim, "width" ) :
        
            self.__initContactsNumber__(resDim)
            print("contacts",self.contactsNumber)

            if   resistance > 0 and resDim["length"] > 0 :
            
                if  resistance - resistance/1000 <= self.__computeResistance__( resDim, self.resistorType ) <= resistance + resistance/1000 and self.__isDimOk__( resDim, "length" ):
                    self.resDim = resDim
                else : 
                    raise Error(1,'__initResDim__() : No compatibiliy between resistance value, %s, and resistor dimensions, "width" : %s, "length" : %s.' %(resistance, toPhy(resDim["width"]), toPhy(resDim["length"])))

            elif resistance > 0 and resDim["length"] == 0 :
                print("resistance0",resistance)
                self.resDim = self.__computeResDim__( resistance, self.resistorType, resDim )

            elif resistance == 0 and resDim["width"] > 0 and resDim["length"] > 0 and self.__isDimOk__( resDim, "length" ): 
                self.resDim = resDim

            else : raise Error(1, '__initResDim__() : Invalid input parameters : resistance and/or resistor dimensions (%s, %s). Please provide at least one valid parameter.' %(resistance, resDim))

        return


    def setSidesDimRules( self ):

        if  self.resistorType == "RPOLYH"  :
            self.__setattr__( "minWidth_resistorPlate"                   ,  Resistor.rules.minWidth_rpolyh         )
        if self.resistorType == "RPOLY2PH" : 
            self.__setattr__( "minWidth_resistorPlate"                   ,  Resistor.rules.minWidthHighPrec_rpolyh )
        self.__setattr__    ( "minLength_resistorPlate"                  ,  Resistor.rules.minRpolyhSquares        )

        return


    def __isDimOk__( self, resdim, side ) :

        self.setSidesDimRules()

        if resdim.keys() == ["width","length"] and side in ["width","length"]:
        
            if side == "width"  :
                rule = self.minWidth_resistorPlate
            if side == "length" :
                print("test0",resdim["width"])
                rule = toDbU( self.minLength_resistorPlate*toPhy(resdim["width"]) )

            state = True if resdim[side] >= rule else False   
            if state == False : raise Error(1,'__isDimOk__() : Resistor or bend side dimension, %s = %s, is below the minimal limit, %s.'
                                           % (side, toPhy(resdim[side]), toPhy(rule)))

        else : raise Error(1,'__isDimOk__() : The resistor or bend dimensions and the specified side, %s and %s, must be either "width" or "length".'
                          %(resdim,side))

        return state



    def __computeResistance__( self, resDim, resistorType ): 
        
        resistancePart1 =   self.__getSheetResistance__( resistorType, "resistorPlate" )*toPhy(resDim["length"])/toPhy(resDim["width"])
        resistancePart2 = 2*self.__getSheetResistance__( resistorType, "contact"       )/self.contactsNumber
        print("computedRes",resistancePart1 + resistancePart2)  
        return resistancePart1 + resistancePart2

         

    def __computeResDim__( self, resistance, resistorType, resDim ):

        contactsResistance = self.__getSheetResistance__( resistorType, "contact" )/self.contactsNumber
        print("contactsResistance",contactsResistance)
        wl_ratio           = (resistance - 2*contactsResistance)/self.__getSheetResistance__( resistorType, "resistorPlate" )
        width              = toPhy(resDim["width"])
        length             = wl_ratio*width

        resDim["length"]   = toFoundryGrid( toDbU(length) )
        print('length0',length)
        if self.__isDimOk__(resDim, "width") and  self.__isDimOk__(resDim, "length") : 
            return resDim 


    def __getSheetResistance__( self, resistorType, material ):

        if material == 'resistorPlate':
            if     resistorType == "RPOLYH"  : resistance = Resistor.rules.RPOLYHSheetRes
            elif   resistorType == "RPOLY2PH": resistance = Resistor.rules.RPOLY2PHSheetRes
            else : raise Error( 1, '__getSheetResistance__() : Unsupported resistor type : %s.' % resistorType ) 

        elif material == "contact" :
            resistance = Resistor.rules.MET1RPOLYHContRes

        return resistance



    def __computeSnakeCornerDim__( self ):
        
        self.snakeCornerDict["width" ] =   self.resDim["width"]
        self.snakeCornerDict["length"] = 2*self.resDim["width"] + self.minSpacing_resistorPlate 

        return 



    def __getCornerResistanceCorrectionFactor__( self ):

        if self.shape not in [90, 135] : raise Error(1,'__getCornerResistanceCorrectionFactor__() : Invalid shape : %s.' %shape)
        if self.shape == 135           : correctionFactor = Resistor.rules.corrFactor135
        if self.shape == 90            : correctionFactor = Resistor.rules.corrFactor90

        print(correctionFactor)
        return correctionFactor




    def setRules( self ):
        trace( 101, '+,', '\tResistor.setRules()\n' )

        self.minSpacing_resistorPlate           = Resistor.rules.minSpacing_rpolyh
        self.minWidth_contact                   = Resistor.rules.minWidth_cut0
        self.minHeight_contact                  = Resistor.rules.minWidth_cut0
        self.minSpacing_contact                 = Resistor.rules.minSpacing_cut0
        self.minEnclosure_resistorPlate_contact = Resistor.rules.minEnclosure_poly2_cut0
        self.minEnclosure_routingLayer_contact  = Resistor.rules.minEnclosure_metal1_cut0
        self.minEnclosure_metal1_cut0           = Resistor.rules.minEnclosure_metal1_cut0
        self.minEnclosure_metal1_cut1           = Resistor.rules.minEnclosure_metal1_cut1
        self.minWidth_cut1                      = Resistor.rules.minWidth_cut1
        self.minSpacing_cut1                    = Resistor.rules.minSpacing_cut1

        if self.resistorType == "RPOLYH":
            self.minWidth_pImplantLayer                 =  Resistor.rules.minWidth_pImplant
            self.minSpacing_pImplantLayer               =  Resistor.rules.minSpacing_pImplant
            self.minSpacing_resistorPlate_pImplantLayer =  Resistor.rules.minSpacing_rpolyh_pImplant
            self.minEnclosure_pImplantLayer_contact     =  Resistor.rules.minEnclosure_pImplant_poly2con
            self.minEnclosure_hres_poly2                =  Resistor.rules.minEnclosure_hres_poly2
            self.minWidth_hres                          =  Resistor.rules.minWidth_hres
            self.minSpacing_hres                        =  Resistor.rules.minSpacing_hres
            self.minSpacing_hres_poly1                  =  Resistor.rules.minSpacing_hres_poly1
            self.minSpacing_hres_poly2                  =  Resistor.rules.minSpacing_hres_poly2
            self.minSpacing_hres_active                 =  Resistor.rules.minSpacing_hres_active
            
        self.resPlateExtensions_minWidth   = self.minWidth_contact + 2*self.minEnclosure_resistorPlate_contact

       # Get the METAL 1/2/3 layers.
        self.cut1   = DataBase.getDB().getTechnology().getLayer( 'cut1' )
        self.metal1 = DataBase.getDB().getTechnology().getLayer( 'metal1' )
        self.metal2 = DataBase.getDB().getTechnology().getLayer( 'metal2' )
        self.metal3 = DataBase.getDB().getTechnology().getLayer( 'metal3' )
       # Get the symbolic pitch.
        rg = AllianceFramework.get().getRoutingGauge()
        self.METAL2Pitch = rg.getHorizontalPitch()
        self.METAL3Pitch = rg.getVerticalPitch()
        self.isVH        = rg.isVH()
        
        foundHor = False
        foundVer = False
        for depth in range(rg.getDepth()):
            rlg = rg.getLayerGauge(depth)
            if rlg.getLayer().getMask() == self.metal2.getMask(): self.metal2Width = rlg.getWireWidth()
            if rlg.getLayer().getMask() == self.metal3.getMask(): self.metal3Width = rlg.getWireWidth()

            if rlg.getType() == Constant.PinOnly: continue
            if rlg.getDirection() == Constant.Horizontal and not foundHor:
                trace( 101, '\tself.hpitch set\n' )
                self.hpitch = rlg.getPitch()
                foundHor = True
            if rlg.getDirection() == Constant.Vertical and not foundVer:
                trace( 101, '\tself.vpitch set\n' )
                self.vpitch = rlg.getPitch()
                foundVer = True

        trace( 101, '-,' )
        return


    def getLayers( self ):

        technology                 = DataBase.getDB().getTechnology()
        self.layers                = {}

        self.layers["resistorPlate"] = technology.getLayer( "poly2"     )
        self.layers["contacts"     ] = technology.getLayer( "cut0"      )
        self.layers["routingLayer" ] = technology.getLayer( "metal1"    )
        self.layers["metal2"       ] = technology.getLayer( "metal2"    )
        self.layers["pImplant"     ] = technology.getLayer( "pImplant"  )
        self.layers["resdef"       ] = technology.getLayer( "resdef"    )

        if self.resistorType == "RPOLYH"   : self.layers["hres"  ] =  technology.getLayer( "hres"   )
        if self.resistorType == "RPOLY2PH" : self.layers["restrm"] =  technology.getLayer( "restrm" )
 
	return self.layers


    def create( self, bbMode = False ):

        UpdateSession.open()           

        layerDict = self.getLayers()
	self.computeDimensions(bbMode)
        self.drawAbutmentBox  ()
        self.device.setAbutmentBox( self.abutmentBox )
        
        if bbMode == False :

            if self.resistorType == "RPOLYH" : self.drawLayer("hres",  layerDict["hres"]) #self.drawHRESLayer( layerDict["hres"] )
        
            self.drawLayer        ("resistorPlate", layerDict["resistorPlate"]) 

            self.drawResPlateExtrimities( layerDict["resistorPlate"], layerDict["pImplant"] )
            if self.snakeMode : self.drawCorners(layerDict["resistorPlate"])
         
            self.drawContacts( layerDict["contacts"])
            self.drawRoutingLayer(layerDict["routingLayer"])
            if self.resistorType == "RPOLY2PH" : self.drawRestrmLayer(layerDict["restrm"])

            self.drawResdefLayer(layerDict["resdef"])
            self.drawTerminals()

        UpdateSession.close()

        return self.abutmentBoxDict



    def computeDimensions( self, bbMode ):

        if  self.snakeMode    :
            self.__computeSnakeCornerDim__    ()
            self.computeSnakeSegmentDimensions()
            if self.resistorType == "RPOLYH"   : self.snakeSegments_spacing = max(self.minSpacing_resistorPlate_pImplantLayer, self.minSpacing_resistorPlate)
            if self.resistorType == "RPOLY2PH" : self.snakeSegments_spacing =     self.minSpacing_resistorPlate

        self.computeAbutmentBoxDimensions()
        
        if bbMode == False :
            if not self.snakeMode :
                self.computeResistorPlateDimensions()
            if     self.snakeMode :
                self.computeFirstSnakeSegmentPosition()

        return



    def computePImplantLayerDim ( self ):

        pImplantLayer_width               = max(self.minWidth_pImplantLayer, 2*self.minEnclosure_pImplantLayer_contact + self.minWidth_contact)
        self.pImplant_layerDict["width" ] = self.contactsNumber*self.minWidth_contact + (self.contactsNumber-1)*self.minSpacing_contact + 2*self.minEnclosure_pImplantLayer_contact
        self.pImplant_layerDict["length"] = pImplantLayer_width
 
        return


    ## extensions2 refers to a part of the corner
    def computeResPlateExtensionsDim( self ):

        self.resPlateExtensions_minWidth   = self.minWidth_contact + 2*self.minEnclosure_resistorPlate_contact
        self.resPlateExtensions["width"]   = self.resPlateExtensions_minWidth if self.resDim["width"] < self.resPlateExtensions_minWidth else self.resDim["width"]
        
        if self.resistorType == "RPOLYH"   : self.resPlateExtensions["length"] = self.minWidth_contact + self.minEnclosure_resistorPlate_contact + self.minEnclosure_pImplantLayer_contact 
        if self.resistorType == "RPOLY2PH" : self.resPlateExtensions["length"] = self.minWidth_contact + self.minEnclosure_resistorPlate_contact 
        print("self.resPlateExtensions['length']",self.resPlateExtensions["length"])
        if self.snakeMode :
            self.resPlateExtension1           = self.resPlateExtensions
            self.resPlateExtension2["width" ] = self.snakeSegmentDict["width"]
            self.resPlateExtension2["length"] = self.snakeSegmentDict["width"]
 
        return
 



    def computeResPlateExtrimitiesDim( self ):

        if self.resistorType == "RPOLYH"       :
            self.resPlateExtrimities   ["width" ] = self.pImplant_layerDict ["width" ] + 2*self.enclosure_resistor_hres
            self.resPlateExtrimities   ["length"] = self.pImplant_layerDict ["length"] +   self.enclosure_resistor_hres     #self.pImplant_layerDict

        if self.resistorType == "RPOLY2PH"     :  
            for key in self.resPlateExtensions.keys(): self.resPlateExtrimities   [key] = self.resPlateExtensions [key] 
 
        if self.snakeMode                      :
            for key in self.resPlateExtrimities.keys(): self.resPlateExtrimity1   [key] = self.resPlateExtrimities [key] 

            if self.resistorType == "RPOLYH"   :
                self.resPlateExtrimity2["width" ] = self.resPlateExtension2 ["width" ] + 2*self.enclosure_resistor_hres
                self.resPlateExtrimity2["length"] = self.resPlateExtension2 ["length"] +   self.enclosure_resistor_hres

            if self.resistorType == "RPOLY2PH" :
                for key in self.resPlateExtension2.keys() : self.resPlateExtrimity2 [key] = self.resPlateExtension2[key] 

            for key in self.resPlateExtrimity1.keys()     : self.resPlateExtrimities[key] = max(self.resPlateExtrimity1[key] , self.resPlateExtrimity2[key]) 

        return




    def computeAbutmentBoxDimensions( self ):

        if self.resistorType == "RPOLYH"   :  self.enclosure_resistor_abutmentBox = self.minSpacing_hres  
        if self.resistorType == "RPOLY2PH" :  self.enclosure_resistor_abutmentBox = self.minSpacing_resistorPlate

        self.computeResPlateExtensionsDim()

        print("self.resPlateExtensionsabt0['length']",toPhy(self.resPlateExtensions["length"]))
        if not self.snakeMode : layerWidth = self.resPlateExtensions["width"]
        if     self.snakeMode : layerWidth = self.resPlateExtension1["width"]

        self.contactsNumber =   self.cutMaxNumber( layerWidth, self.minHeight_contact, self.minSpacing_contact, self.minEnclosure_resistorPlate_contact )

        if self.resistorType == "RPOLYH" : 
            self.computePImplantLayerDim()
            self.computeHRESLayerDimensions()

        self.computeResPlateExtrimitiesDim()

        if not self.snakeMode :
            abutmentBoxSide1 = self.resPlateExtrimities["width" ] + 2*self.enclosure_resistor_abutmentBox
            abutmentBoxSide2 = self.resDim             ["length"] + 2*self.resPlateExtrimities["length"]  + 2*self.enclosure_resistor_abutmentBox

        if self.snakeMode     :
            if self.resistorType == "RPOLYH"   : resistor_width = self.hresLayerDict.values()[0]
            if self.resistorType == "RPOLY2PH" : resistor_width = (self.bends+1)*self.snakeSegmentDict["width"] + self.bends*self.snakeSegments_spacing  

            abutmentBoxSide1 = resistor_width + 2*self.enclosure_resistor_abutmentBox  #width
            if self.bends > 1 :
                abutmentBoxSide2 = self.snakeSegmentDict["length"] + 2*self.resPlateExtrimities["length"]  + 2*self.enclosure_resistor_abutmentBox
            if self.bends == 1 :
                abutmentBoxSide2 = self.snakeSegmentDict["length"] + self.resPlateExtrimity1["length"] + self.resPlateExtrimity2["length"]  + 2*self.enclosure_resistor_abutmentBox

        if self.direction == "vertical"   :
            self.abutmentBoxDict["width" ] = abutmentBoxSide1
            self.abutmentBoxDict["height"] = abutmentBoxSide2 
                
        if self.direction == "horizontal" :
            self.abutmentBoxDict["width" ] = abutmentBoxSide2
            self.abutmentBoxDict["height"] = abutmentBoxSide1

        return



    def computeHRESLayerDimensions( self ):

        self.enclosure_resistor_hres = self.minEnclosure_hres_poly2
        if not self.snakeMode : hresLayerSide1 = max(self.minWidth_hres,   self.pImplant_layerDict["width" ] + 2*self.enclosure_resistor_hres)   
        if     self.snakeMode : hresLayerSide1 = max(self.minWidth_hres,  (self.bends+1)*self.snakeSegmentDict["width"] + self.bends*self.snakeSegments_spacing + 2*self.enclosure_resistor_hres)

        if self.direction == "vertical"   :
            self.hresLayerDict["length"] = hresLayerSide1 
                
        if self.direction == "horizontal" :
            self.hresLayerDict["width" ] = hresLayerSide1


        return



    def computeResistorPlateDimensions( self ):

        self.resistorPlateDict["width"  ]     = self.resDim["width" ]
        self.resistorPlateDict["length" ]     = self.resDim["length"]

 	if self.direction == "vertical"      : keysList = ["XCenter","YMin","YMax","XMin","width" ]
 	if self.direction == "horizontal"    : keysList = ["YCenter","XMin","XMax","YMin","height"]

        self.resistorPlateDict[ keysList[0] ] = self.abutmentBoxDict  [keysList[3]] + self.abutmentBoxDict  [keysList[4]]/2
        self.resistorPlateDict[ keysList[1] ] = self.abutmentBoxDict  [keysList[1]] + self.enclosure_resistor_abutmentBox + self.resPlateExtrimities["length"]
        self.resistorPlateDict[ keysList[2] ] = self.resistorPlateDict[keysList[1]] + self.resistorPlateDict["length"]


        return


    ## The first bend is the lowest one (horizontally)
    def computeSnakeSegmentDimensions( self ):

        snakeSegmentDict           = {}
        snakeSegmentDict["width" ] =  toPhy(self.resDim["width" ]) 
        totalResLength             =  toPhy(self.resDim["length"]) 
        correctionFactor           =  self.__getCornerResistanceCorrectionFactor__()

        snakeSegmentDict["length"] = (totalResLength- self.bends*( snakeSegmentDict["width"]*(correctionFactor+1) + toPhy(self.minSpacing_resistorPlate) )) / (self.bends + 1)
        snakeSegmentDict     ["length"] = toFoundryGrid( toDbU(snakeSegmentDict["length"]) )
        snakeSegmentDict     ["width" ] = toFoundryGrid( toDbU(snakeSegmentDict["width" ]) )
        print("snakesegW",snakeSegmentDict["width"  ] )
        if self.__isDimOk__(snakeSegmentDict, "length") : 
            self.snakeSegmentDict["width"  ] = snakeSegmentDict["width" ]
            self.snakeSegmentDict["length" ] = snakeSegmentDict["length"]
            
        return


    ## The first bend is the lowest one (horizontally)
    def computeFirstSnakeSegmentPosition( self ) :

 	if self.direction == "vertical"        :

            if self.bends >  1 : firstExtrimity_width = self.resPlateExtrimities["width"]
            if self.bends == 1 : firstExtrimity_width = self.resPlateExtrimity1 ["width"]

            if self.resistorType == "RPOLYH"   : 
                self.snakeSegmentDict["XCenter"] = self.abutmentBoxDict["XMin"] + self.enclosure_resistor_abutmentBox + self.snakeSegmentDict["width"]/2 + self.enclosure_resistor_hres 
                self.snakeSegmentDict["YMin"   ] = self.abutmentBoxDict["YMin"] + self.enclosure_resistor_abutmentBox + firstExtrimity_width #length

            if self.resistorType == "RPOLY2PH" : 
                self.snakeSegmentDict["XCenter"] = self.abutmentBoxDict["XMin"] + self.enclosure_resistor_abutmentBox + self.snakeSegmentDict["width"]/2 
                self.snakeSegmentDict["YMin"   ] = self.abutmentBoxDict["YMin"] + self.enclosure_resistor_abutmentBox + firstExtrimity_width 

            self.snakeSegmentDict    ["YMax"   ] = self.snakeSegmentDict["YMin"] + self.snakeSegmentDict["length"]


 	if self.direction == "horizontal"      :

            if self.bends >  1 : firstExtrimity_length = self.resPlateExtrimities["length"]
            if self.bends == 1 : firstExtrimity_length = self.resPlateExtrimity1 ["length"]

            if self.resistorType == "RPOLYH"   : 
                self.snakeSegmentDict["YCenter"] = self.abutmentBoxDict["YMin"] + self.enclosure_resistor_abutmentBox + self.snakeSegmentDict["width"]/2 + self.enclosure_resistor_hres 
                self.snakeSegmentDict["XMin"   ] = self.abutmentBoxDict["XMin"] + self.enclosure_resistor_abutmentBox + firstExtrimity_length

            if self.resistorType == "RPOLY2PH" :
                self.snakeSegmentDict["YCenter"] = self.abutmentBoxDict["YMin"] + self.enclosure_resistor_abutmentBox + self.snakeSegmentDict["width"]/2 
                self.snakeSegmentDict["XMin"   ] = self.abutmentBoxDict["XMin"] + self.enclosure_resistor_abutmentBox + firstExtrimity_length 

            self.snakeSegmentDict    ["XMax"   ] = self.snakeSegmentDict["XMin"] + self.snakeSegmentDict["length"]

        return



    def computeHRESLayerPosition( self ):

 	if self.direction == "vertical"      :
            self.hresLayerDict["XCenter"] = self.abutmentBox.getXCenter()
            self.hresLayerDict["YMin"   ] = self.abutmentBox.getYMin() + self.enclosure_resistor_abutmentBox
            self.hresLayerDict["YMax"   ] = self.abutmentBox.getYMax() - self.enclosure_resistor_abutmentBox

 	if self.direction == "horizontal"    :
            self.hresLayerDict["YCenter"] = self.abutmentBox.getYCenter()
            self.hresLayerDict["XMin"   ] = self.abutmentBox.getXMin() + self.enclosure_resistor_abutmentBox
            self.hresLayerDict["XMax"   ] = self.abutmentBox.getXMax() - self.enclosure_resistor_abutmentBox


        return


    def drawLayer( self, layerLabel, layer):

        thiknessKey          = "width"
        maxIterations        =  1
        centerTranslation    =  0

        if layerLabel not in ["hres","resistorPlate"] : raise Error(1,'drawLayer() : Supported layer labels "hres" or "resistorPlate".')

        if layerLabel == "hres"   : 
            self.computeHRESLayerPosition()
            positionParams = self.hresLayerDict
            if self.direction == "vertical"   : thiknessKey = "length"

        if layerLabel == "resistorPlate" :
        
            if not self.snakeMode : 
                positionParams = self.resistorPlateDict

            if     self.snakeMode :
                positionParams = self.snakeSegmentDict
                maxIterations  = self.bends + 1
                centerTranslation    = self.snakeSegmentDict["width"] + self.snakeSegments_spacing

        if self.direction == "vertical"        : 
            for i in range(0, maxIterations)   :
                print self.nets[0], layer \
                    , positionParams["XCenter"  ] + i*centerTranslation \
                    , positionParams[thiknessKey] \
                    , positionParams["YMin"     ] \
                    , positionParams["YMax"     ] 
                Vertical.create  ( self.nets[0], layer
                                 , positionParams["XCenter"  ] + i*centerTranslation
                                 , positionParams[thiknessKey]
                                 , positionParams["YMin"     ] 
                                 , positionParams["YMax"     ] 
                                 )

        if self.direction == "horizontal"      : 
            for i in range(0, maxIterations)   :
                Horizontal.create( self.nets[0], layer
                                 , positionParams["YCenter"  ] + i*centerTranslation
                                 , positionParams[thiknessKey]
                                 , positionParams["XMin"     ]
                                 , positionParams["XMax"     ] 
                                 ) 
        return



    def drawResdefLayer( self, layer ):

        self.computeResDefDimensions ()
        if not self.snakeMode :
            self.drawResdefForResistorPlate( layer )
        if     self.snakeMode : 
            self.drawResdefForSnakeSegments( layer )
            self.drawResdefForCorners      ( layer )        


        return


    def drawResdefForResistorPlate( self, layer ):

        if self.direction == "vertical"        :
            Vertical.create  ( self.nets[0], layer
                             , 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"   ] 
                             ) 
        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
                                 , self.resdefLayerDict["XCenter"] + i*centerTranslation
                                 , self.resdefLayerDict["width"  ]
                                 , self.resdefLayerDict["YMin"   ] + factor0*extrimityTranslation
                                 , self.resdefLayerDict["YMax"   ] - factor1*extrimityTranslation
                                 )

        if self.direction == "horizontal"      : 

            for i in range(0, self.bends + 1)  :
                if self.resistorType == "RPOLYH"   : factor0, factor1 = 1, 1
                if self.resistorType == "RPOLY2PH" : 
                    factor0 = 0 if i == 0 or (i == self.bends and self.bends % 2 != 0) else 1
                    factor1 = 0 if            i == self.bends and self.bends % 2 == 0  else 1
                Horizontal.create( self.nets[0], layer
                                 , self.resdefLayerDict["YCenter"] + i*centerTranslation
                                 , self.resdefLayerDict["width"  ]
                                 , self.resdefLayerDict["XMin"   ] + factor0*extrimityTranslation
                                 , self.resdefLayerDict["XMax"   ] - factor1*extrimityTranslation
                                 ) 
        return



    def drawResdefForCorners( self, layer ):

        k,factor = 0,0
        if self.shape == 135    :
            factor = 1
            self.computeFirstSnakeCornerPosition90()

        translation             = self.snakeSegmentDict ["width"  ] + self.snakeSegments_spacing
        centersTranslationConst = self.snakeSegmentDict ["width"  ] + self.snakeSegmentDict["length"]

        if self.shape == 90     : widthExtension = self.minWidth_contact/2
        if self.shape == 135    : widthExtension = self.minWidth_contact/4 + toDbU(0.2)

        if self.direction == "vertical"        : 
            snakeCornersYCenters    = [ self.snakeCornerDict["YCenter"] - factor*( toDbU(0.2)/2 + self.minWidth_contact/8 ) 
                                      , self.snakeCornerDict["YCenter"] + factor*( toDbU(0.2)/2 + self.minWidth_contact/8 ) + centersTranslationConst ]

            for i in range(0,self.bends)       : 
                Horizontal.create( self.nets[0], layer
                                 , snakeCornersYCenters[k]      
                                 , self.snakeCornerDict["width"] + widthExtension 
                                 , self.snakeCornerDict["XMin" ] - self.minWidth_contact/4 + i*translation
                                 , self.snakeCornerDict["XMax" ] + self.minWidth_contact/4 + i*translation
                                 ) 
                k = k+1 if k<1 else 0

        if self.direction == "horizontal"      : 
            snakeCornersXCenters = [ self.snakeCornerDict["XCenter"] + factor*( toDbU(0.2)/2 + self.minWidth_contact/8 )
                                   , self.snakeCornerDict["XCenter"] - factor*( toDbU(0.2)/2 + self.minWidth_contact/8 ) - centersTranslationConst ] 

            for i in range(0,self.bends)       : 
                Vertical.create  ( self.nets[0], layer
                                 , snakeCornersXCenters[k]
                                 , self.snakeCornerDict["width"] + widthExtension  
                                 , self.snakeCornerDict["YMin" ] - self.minWidth_contact/4 + i*translation
                                 , self.snakeCornerDict["YMax" ] + self.minWidth_contact/4 + i*translation 
                                 ) 
                k = k+1 if k<1 else 0

        return



    def drawSnakeSegments( self, layer ):

        translation       =  self.snakeSegmentDict["width"] + self.snakeSegments_spacing 

        if self.direction == "vertical"       : 

            for i in range(0, self.bends + 1) : 
                Vertical.create  ( self.nets[0], layer
                                 , self.snakeSegmentDict["XCenter"] + i*translation
                                 , self.snakeSegmentDict["width" ]
                                 , self.snakeSegmentDict["YMin"  ]
                                 , self.snakeSegmentDict["YMax"  ] 
                                 ) 

        if self.direction == "horizontal"     :
        
            for i in range(0, self.bends + 1) :
                Horizontal.create( self.nets[0], layer
                                 , self.snakeSegmentDict["YCenter"] + i*translation
                                 , self.snakeSegmentDict["width"  ]
                                 , self.snakeSegmentDict["XMin"   ]
                                 , self.snakeSegmentDict["XMax"   ]
                                 )          
        return



    def drawAbutmentBox( self ):

        ab = Box( self.abutmentBoxDict["XMin"  ]
                , self.abutmentBoxDict["YMin"  ]
                , self.abutmentBoxDict["width" ]
                , self.abutmentBoxDict["height"]
                )
        
        height        = ab.getHeight()
        heightAdjust  = height % (2*self.hpitch)
        if heightAdjust:
          heightAdjust = 2*self.hpitch - heightAdjust
          ab.inflate( 0, heightAdjust/2 )

        width = ab.getWidth()
        widthAdjust = width % (2*self.vpitch)
        if widthAdjust:
          widthAdjust = 2*self.vpitch - widthAdjust
          ab.inflate( widthAdjust/2, 0 )

        self.abutmentBox = ab
        return




    def drawResPlateExtrimities( self, resPlateLayer, pImplantLayer ):

        self.drawResPlateExtensions(resPlateLayer)
        if self.resistorType == "RPOLYH" :
            self.drawPImplantLayer(pImplantLayer)

        return

    ## extension1 is on the right side of the resistor (if direction == horizontal) and the bottom side otherwhise
    def computeResPlateExtensionsPosition( self ):

        self.resPlateExtensions["ex1"] = {}

        if self.direction == "vertical"      :

            if not self.snakeMode : self.resPlateExtensions["ex1"]["XMin"] = self.abutmentBox.getXCenter() - self.resPlateExtensions["width" ]/2
            if     self.snakeMode : self.resPlateExtensions["ex1"]["XMin"] = self.abutmentBox.getXCenter() + (self.bends*(self.snakeSegmentDict["width"] + self.snakeSegments_spacing))/2 - self.resPlateExtensions["width"]/2

            if not self.snakeMode                         : translation =  self.resPlateExtensions["length"]   + self.resDim["length"]/2
            if     self.snakeMode and self.bends % 2 == 0 : translation =  self.resPlateExtensions["length"]   + self.snakeSegmentDict["length"]/2
            if     self.snakeMode and self.bends % 2 != 0 : translation =  self.snakeSegmentDict  ["length"]/2
            print("self.resPlateExtensions5['length']",toPhy(self.resPlateExtensions["length"]))
#            print("self.snakeSegmentDict['length']/2",toPhy(self.snakeSegmentDict["length"]/2))
#            print("translation",toPhy(self.resPlateExtensions['length']   + self.snakeSegmentDict["length"]/2))
            print("self.abutmentBox.getYCenter(",toPhy(self.abutmentBox.getYCenter()))
            if not self.snakeMode or  self.snakeMode and self.bends % 2 == 0 : self.resPlateExtensions["ex1"]["YMin"] = self.abutmentBox.getYCenter() - translation  
            if     self.snakeMode and self.bends % 2 != 0                    : self.resPlateExtensions["ex1"]["YMin"] = self.abutmentBox.getYCenter() + translation 
            
            print("self.resPlateExtensions['ex1']['YMin']",toPhy(self.resPlateExtensions["ex1"]["YMin"]))
            self.resPlateExtensions["ex1"]["XMax"] = self.resPlateExtensions["ex1"]["XMin"] + self.resPlateExtensions["width" ]
            self.resPlateExtensions["ex1"]["YMax"] = self.resPlateExtensions["ex1"]["YMin"] + self.resPlateExtensions["length"]

        if self.direction == "horizontal"    :

            if not self.snakeMode : resistorLength = self.resDim          ["length"]
            if     self.snakeMode : resistorLength = self.snakeSegmentDict["length"]

            self.resPlateExtensions["ex1"]["XMin"] = self.abutmentBox.getXCenter() - self.resPlateExtensions["length"]   - resistorLength/2 

            if not self.snakeMode : self.resPlateExtensions["ex1"]["YMin"] = self.abutmentBox.getYCenter() - self.resPlateExtensions["width" ]/2 
            if     self.snakeMode : self.resPlateExtensions["ex1"]["YMin"] = self.snakeSegmentDict["YCenter"]  - self.resPlateExtensions["width" ]/2

            self.resPlateExtensions["ex1"]["XMax"] = self.resPlateExtensions["ex1"]["XMin"] + self.resPlateExtensions["length"]
#            print("self.resPlateExtensions['length']",toPhy(self.resPlateExtension2["length"]))
            self.resPlateExtensions["ex1"]["YMax"] = self.resPlateExtensions["ex1"]["YMin"] + self.resPlateExtensions["width" ]

        return



    def drawResPlateExtensions( self, layer ):
    
        self.computeResPlateExtensionsPosition()
        if not self.snakeMode : resistorLength = self.resDim          ["length"]
        if     self.snakeMode : resistorLength = self.snakeSegmentDict["length"]

        translation1                     = resistorLength + self.resPlateExtensions["length"]
        if self.snakeMode : translation2 = self.bends*(self.snakeSegmentDict["width"] + self.snakeSegments_spacing) #- self.resPlateExtensions["width"] 

        if self.direction == "vertical"   :

            if not self.snakeMode                         : [ hTranslation , vTranslation ] = [ 0            , translation1 ]
            if     self.snakeMode and self.bends % 2 == 0 : [ hTranslation , vTranslation ] = [ translation2 , translation1 ]
            if     self.snakeMode and self.bends % 2 != 0 : [ hTranslation , vTranslation ] = [ translation2 , 0            ]

            self.terminal1Box = Box( 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
                                   )

        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
                                              , self.pImplant_layerDict["YCenter"] + i*centerTranslation
                                              , self.pImplant_layerDict["length" ]
                                              , self.pImplant_layerDict["XMin"   ] - i*extrimitiesTranslation
                                              , self.pImplant_layerDict["XMax"   ] - i*extrimitiesTranslation
                                              )

        if self.direction == "horizontal" :
            for i in [0,1] : Vertical.create  ( self.nets[i], layer
                                              , self.pImplant_layerDict["XCenter"] + i*centerTranslation
                                              , self.pImplant_layerDict["length" ]
                                              , self.pImplant_layerDict["YMin"   ] + i*extrimitiesTranslation
                                              , self.pImplant_layerDict["YMax"   ] + i*extrimitiesTranslation

                                              )

        return

    ## t1Cut connected to terminal1 (on the right side/bottom side of rectangular)
    def computecenterTranslationDimensions( self ):

        enclosure1 = ( self.resPlateExtensions["width"] - (self.contactsNumber*self.minHeight_contact + (self.contactsNumber -1)*self.minSpacing_contact) )/2
        enclosure2 =   self.minEnclosure_resistorPlate_contact

        if self.resistorType == "RPOLYH"   : enclosure3 =   self.minEnclosure_pImplantLayer_contact
        if self.resistorType == "RPOLY2PH" : enclosure3 =   0 

        if self.direction == "vertical":

            self.t1cutsEnclosure["horizontal"] = enclosure1
            if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : self.t1cutsEnclosure["vertical"] = enclosure2 
            if     self.snakeMode                   and self.bends % 2 != 0 : self.t1cutsEnclosure["vertical"] = enclosure3 

            self.t2cutsEnclosure["horizontal"] = enclosure1
            self.t2cutsEnclosure["vertical"  ] = enclosure3 
 
        if self.direction == "horizontal" :

            self.t1cutsEnclosure["horizontal"] = enclosure2 
            self.t1cutsEnclosure["vertical"  ] = enclosure1

            if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : self.t2cutsEnclosure["horizontal"] = enclosure3 
            if     self.snakeMode                   and self.bends % 2 != 0 : self.t2cutsEnclosure["horizontal"] = enclosure2 
            #self.t2cutsEnclosure["horizontal"] = enclosure3

            self.t2cutsEnclosure["vertical"  ] = enclosure1

        self.t1CutCenterDict         ["XCenter"   ] = self.terminal1Box.getXMin() + self.t1cutsEnclosure ["horizontal"] + self.minWidth_contact/2 
        self.t1CutCenterDict         ["YCenter"   ] = self.terminal1Box.getYMin() + self.t1cutsEnclosure ["vertical"  ] + self.minHeight_contact/2

        self.t2CutCenterDict         ["XCenter"   ] = self.terminal2Box.getXMin() + self.t2cutsEnclosure ["horizontal"] + self.minWidth_contact/2 
        self.t2CutCenterDict         ["YCenter"   ] = self.terminal2Box.getYMin() + self.t2cutsEnclosure ["vertical"  ] + self.minHeight_contact/2

        return



    def drawContacts( self, layer ):

        self.computecenterTranslationDimensions()

        if self.direction == "vertical"   : cutLineDirection = "horizontal"                  
        if self.direction == "horizontal" : cutLineDirection = "vertical"

        self.cutLine              ( self.nets[0], layer
                                  , self.t1CutCenterDict["XCenter"]
                                  , self.t1CutCenterDict["YCenter"]
                                  , self.minWidth_contact
                                  , self.minHeight_contact
                                  , self.minSpacing_contact
                                  , self.contactsNumber 
                                  , cutLineDirection
                                  )

        self.cutLine              ( self.nets[1], layer
                                  , self.t2CutCenterDict["XCenter"]
                                  , self.t2CutCenterDict["YCenter"]
                                  , self.minWidth_contact
                                  , self.minHeight_contact
                                  , self.minSpacing_contact
                                  , self.contactsNumber
                                  , cutLineDirection 
                                  )

        return


    def drawRoutingLayer( self, layer ):

        layer_width  = self.minWidth_contact + 2*self.minEnclosure_routingLayer_contact
        layer_height = self.contactsNumber*self.minWidth_contact + (self.contactsNumber-1)*self.minSpacing_contact + 2*self.minEnclosure_routingLayer_contact

        if self.direction == "vertical"   : key = "XCenter"
        if self.direction == "horizontal" : key = "YCenter"

        source1 = self.t1CutCenterDict[key] - self.minWidth_contact/2 - self.minEnclosure_routingLayer_contact
        target1 = source1 + layer_height

        source2 = self.t2CutCenterDict[key] - self.minWidth_contact/2 - self.minEnclosure_routingLayer_contact
        target2 = source2 + layer_height


        if self.direction == "vertical"   :
            Horizontal.create( self.nets[0]
                             , layer, self.t1CutCenterDict["YCenter"]
                             , layer_width
                             , source1
                             , target1 )
            Horizontal.create( self.nets[1]
                             , layer
                             , self.t2CutCenterDict["YCenter"]
                             , layer_width
                             , source2
                             , target2) 

            trace( 101, '\tIN PAD self.t1CutCenterDict["XCenter"] = {0}\n'.format(DbU.getValueString(self.t1CutCenterDict["XCenter"])) )
            trace( 101, '\tIN PAD source1 = {0}\n'.format(DbU.getValueString(source1)) )
            trace( 101, '\tIN PAD target1 = {0}\n'.format(DbU.getValueString(target1)) )

           #h = Horizontal.create( self.nets[0]
           #                     , self.layers['metal2']
           #                     , self.t1CutCenterDict["YCenter"]
           #                     , layer_width
           #                     , source1
           #                     , target1 )
           #NetExternalComponents.setExternal( h )
           #
           #h = Horizontal.create( self.nets[1]
           #                     , self.layers['metal2']
           #                     , self.t2CutCenterDict["YCenter"]
           #                     , layer_width
           #                     , source2
           #                     , target2 ) 
           #NetExternalComponents.setExternal( h )

        if self.direction == "horizontal" :
            Vertical.create (self.nets[0], layer, self.t1CutCenterDict["XCenter"], layer_width, source1, target1)
            Vertical.create (self.nets[1], layer, self.t2CutCenterDict["XCenter"], layer_width, source2, target2)                           

        return



    def drawRestrmLayer( self, layer ):

        self.computeRestrmLayerPosition() 
        if not self.snakeMode : resistorLength = self.resDim          ["length"]
        if     self.snakeMode : resistorLength = self.snakeSegmentDict["length"]

        if not self.snakeMode or     self.snakeMode and self.bends % 2 == 0 : centerTranslation = resistorLength + self.restrmLayerDict["width"]
        if     self.snakeMode                       and self.bends % 2 != 0 : centerTranslation = 0 

        if not self.snakeMode : extrimitiesTranslation  = 0
        if     self.snakeMode : extrimitiesTranslation  = self.bends*(self.snakeSegments_spacing + self.snakeSegmentDict["width"]) 

        if self.direction == "vertical"   :
            for i in [0,1]: Horizontal.create( self.nets[i], layer
                                             , self.restrmLayerDict["YCenter"] + i*centerTranslation
                                             , self.restrmLayerDict["width"  ]
                                             , self.restrmLayerDict["XMin"   ] - i*extrimitiesTranslation
                                             , self.restrmLayerDict["XMax"   ] - i*extrimitiesTranslation
                                             ) 

        if self.direction == "horizontal" :
            for i in [0,1]: Vertical.create  ( self.nets[i], layer
                                             , self.restrmLayerDict["XCenter"] + i*centerTranslation
                                             , self.restrmLayerDict["width"  ]
                                             , self.restrmLayerDict["YMin"   ] + i*extrimitiesTranslation
                                             , self.restrmLayerDict["YMax"   ] + i*extrimitiesTranslation
                                             ) 

        return



    def computeRestrmLayerPosition( self ):

        self.restrmLayerDict["width"]  = self.minWidth_contact/2
        factor                         = 1

        if self.direction == "vertical"   :
            keysList = ["YCenter","XMin","XMax"]
#            if not self.snakeMode or self.snakeMode and self.bends % 2 == 0 : factor = 1
            if     self.snakeMode                   and self.bends % 2 != 0 : factor = -1
        if self.direction == "horizontal" : 
            keysList = ["XCenter","YMin","YMax"]

        self.restrmLayerDict[ keysList[0] ] = self.t1CutCenterDict          [ keysList[0] ] + factor*self.restrmLayerDict["width"]/2
        self.restrmLayerDict[ keysList[1] ] = self.resPlateExtensions["ex1"][ keysList[1] ] - self.restrmLayerDict["width"]
        self.restrmLayerDict[ keysList[2] ] = self.resPlateExtensions["ex1"][ keysList[2] ] + self.restrmLayerDict["width"]

        return



    def computeResDefDimensions( self ):

        if self.direction == "vertical"   : keysList = ["YMin","YMax","XCenter","width"]
        if self.direction == "horizontal" : keysList = ["XMin","XMax","YCenter","width"]

        if not self.snakeMode : resistorElement = self.resistorPlateDict
        if     self.snakeMode : resistorElement = self.snakeSegmentDict

        if self.resistorType == "RPOLYH"   : factor = 0
        if self.resistorType == "RPOLY2PH" : factor = 1 

        self.resdefLayerDict[keysList[0]] = resistorElement[keysList[0]] - factor*self.minWidth_contact/4
        self.resdefLayerDict[keysList[1]] = resistorElement[keysList[1]] + factor*self.minWidth_contact/4
        self.resdefLayerDict[keysList[2]] = resistorElement[keysList[2]]
        self.resdefLayerDict[keysList[3]] = resistorElement[keysList[3]]
        
        if self.resDim["width"] >= self.resPlateExtensions_minWidth :
            self.resdefLayerDict[keysList[3]] = self.resdefLayerDict[keysList[3]] + self.minWidth_contact/2

        return


    def computeFirstSnakeCornerPosition90( self ):

        if self.direction == "vertical"   :

            self.snakeCornerDict["YCenter"] = self.snakeSegmentDict["YMin"   ] - self.snakeCornerDict ["width" ]/2
            self.snakeCornerDict["XMin"   ] = self.snakeSegmentDict["XCenter"] - self.snakeSegmentDict["width" ]/2
            self.snakeCornerDict["XMax"   ] = self.snakeCornerDict ["XMin"   ] + self.snakeCornerDict ["length"]

        if self.direction == "horizontal" :

            self.snakeCornerDict["XCenter"] = self.snakeSegmentDict["XMax"   ] + self.snakeCornerDict ["width" ]/2
            self.snakeCornerDict["YMin"   ] = self.snakeSegmentDict["YCenter"] - self.snakeSegmentDict["width" ]/2
            self.snakeCornerDict["YMax"   ] = self.snakeCornerDict ["YMin"   ] + self.snakeCornerDict ["length"]

        return



    def drawCorners90( self, layer ):

        self.computeFirstSnakeCornerPosition90()
        k                       = 0
        translation             = self.snakeSegmentDict["width"] + self.snakeSegments_spacing
        centersTranslationConst = self.snakeSegmentDict["width"] + self.snakeSegmentDict["length"]

        if self.direction == "vertical"   :

            snakeCornersYCenters = [ self.snakeCornerDict["YCenter"]
                                   , self.snakeCornerDict["YCenter"] + centersTranslationConst]

            for i in range(0,self.bends)  : 
                Horizontal.create( self.nets[0], layer
                                 , snakeCornersYCenters[k]
                                 , self.snakeCornerDict["width"]
                                 , self.snakeCornerDict["XMin" ] + i*translation
                                 , self.snakeCornerDict["XMax" ] + i*translation
                                 ) 
                k = k+1 if k<1 else 0

        if self.direction == "horizontal" :

            snakeCornersXCenters = [ self.snakeCornerDict["XCenter"]
                                   , self.snakeCornerDict["XCenter"] - centersTranslationConst ]

            for i in range(0,self.bends)  : 
                Vertical.create  ( self.nets[0], layer
                                 , snakeCornersXCenters[k]
                                 , self.snakeCornerDict["width"]
                                 , self.snakeCornerDict["YMin" ] + i*translation
                                 , self.snakeCornerDict["YMax" ] + i*translation 
                                 ) 
                k = k+1 if k<1 else 0

        return



    def computeFirstSnakeCornerPosition135( self ):

        param1 = (self.snakeSegmentDict["width"]*42/100)/2
        param2 = toDbU(0.2)
        param3 = self.snakeSegmentDict["width"] + param2
        param4 = param3 - param1

        if self.direction == "vertical"   : 

            rx0 = self.snakeSegmentDict["XCenter"] - self.snakeSegmentDict["width"]/2
            ry0 = self.snakeSegmentDict["YMin"   ]
            rx1 = rx0  
            ry1 = ry0 - param1
            rx2 = rx0 + param4
            ry2 = ry1 - param4 
            rx3 = rx0 + 2*self.snakeSegmentDict["width"] + self.snakeSegments_spacing - param4
            ry3 = ry2 
            rx4 = rx3 + param4 
            ry4 = ry1 
            rx5 = rx4
            ry5 = ry0 
            rx6 = rx5 - self.snakeSegmentDict["width"]
            ry6 = ry0 
            rx7 = rx0 + self.snakeSegmentDict["width"] + self.snakeSegments_spacing - param2
            ry7 = ry0 - param2 
            rx8 = rx0 + self.snakeSegmentDict["width"] + param2 
            ry8 = ry7 
            rx9 = rx0 + self.snakeSegmentDict["width"] 
            ry9 = ry0 

        if self.direction == "horizontal" : 

            rx0 = self.snakeSegmentDict["XMax"   ]
            ry0 = self.snakeSegmentDict["YCenter"] - self.snakeSegmentDict["width"]/2
            rx1 = rx0 + param1  
            ry1 = ry0
            rx2 = rx1 + (self.snakeSegmentDict["width"] + param2) - param1
            ry2 = ry1 + (self.snakeSegmentDict["width"] + param2) - param1 
            rx3 = rx2
            ry3 = ry2 + (2*self.snakeSegmentDict["width"] + self.snakeSegments_spacing) - 2*(self.snakeSegmentDict["width"] + param2 - param1)
            rx4 = rx1 
            ry4 = ry1 + 2*self.snakeSegmentDict["width"] + self.snakeSegments_spacing
            rx5 = rx0
            ry5 = ry0 + 2*self.snakeSegmentDict["width"] + self.snakeSegments_spacing
            rx6 = rx0
            ry6 = ry0 + self.snakeSegmentDict["width"] + self.snakeSegments_spacing
            rx7 = rx0 + param2 
            ry7 = ry6 - param2 
            rx8 = rx7 
            ry8 = ry0 + self.snakeSegmentDict["width"] + param2 
            rx9 = rx0
            ry9 = ry0 + self.snakeSegmentDict["width"]

        rightCorCordinatesList = [ [rx0 , ry0 ] , [rx1, ry1 ]
                                 , [rx2 , ry2 ] , [rx3, ry3 ] 
                                 , [rx4 , ry4 ] , [rx5, ry5 ] 
                                 , [rx6 , ry6 ] , [rx7, ry7 ]
                                 , [rx8 , ry8 ] , [rx9, ry9 ]
                                 ]
        for p in rightCorCordinatesList : 
            self.rightCorPointsVector.append(Point(p[0],p[1]))
            self.leftCorPointsVector.append (Point(p[0],p[1]))

        translationList = [ self.snakeSegmentDict["length"]
                             , self.snakeSegmentDict["length"] + 2*param1
                             , self.snakeSegmentDict["length"] + 2*param3
                             , self.snakeSegmentDict["length"] + 2*param3
                             , self.snakeSegmentDict["length"] + 2*param1
                             , self.snakeSegmentDict["length"] 
                             , self.snakeSegmentDict["length"]
                             , self.snakeSegmentDict["length"] + 2*param2 
                             , self.snakeSegmentDict["length"] + 2*param2
                             , self.snakeSegmentDict["length"]
                             ]

        if self.direction == "vertical"   : 
            for i in range(0, len(self.leftCorPointsVector)) : self.leftCorPointsVector[i].translate( 0 ,  translationList[i] ) 
        if self.direction == "horizontal" :
            for i in range(0, len(self.leftCorPointsVector)) : self.leftCorPointsVector[i].translate( - translationList[i] , 0) 
          
        return


    def drawCorners135( self, layer ):

        self.computeFirstSnakeCornerPosition135()
        if self.bends % 2 == 0 : [ rightCornersNum, leftCornersNum ] = [  self.bends/2    ,  self.bends/2    ]
        if self.bends % 2 != 0 : [ rightCornersNum, leftCornersNum ] = [ (self.bends+1)/2 , (self.bends-1)/2 ]

        translationFactor = 2*(self.snakeSegmentDict["width"] + self.snakeSegments_spacing)

        if self.direction == "vertical"    : [dxTranslation, dyTranslation] = [ translationFactor, 0                 ]  
        if self.direction == "horizontal"  : [dxTranslation, dyTranslation] = [ 0                , translationFactor ]  

        for i in range(0, rightCornersNum) : 
            Rectilinear.create( self.nets[0], layer, self.rightCorPointsVector ).translate(i*dxTranslation, i*dyTranslation)

        for i in range(0, leftCornersNum ) :
            if i == 0 : 
                 if self.direction == "vertical"  : Rectilinear.create(self.nets[0], layer, self.leftCorPointsVector).translate(dxTranslation/2,dyTranslation)
                 if self.direction == "horizontal": Rectilinear.create(self.nets[0], layer, self.leftCorPointsVector).translate(dxTranslation,dyTranslation/2)
                
            if i != 0 : 
                if self.direction == "vertical"  : Rectilinear.create(self.nets[0], layer, self.leftCorPointsVector).translate(i*3*dxTranslation/2,dyTranslation)
                if self.direction == "horizontal": Rectilinear.create(self.nets[0], layer, self.leftCorPointsVector).translate(dxTranslation,i*3*dyTranslation/2)

        return


    def drawCorners( self, layer):

        if self.shape == 90  : self.drawCorners90 (layer)
        if self.shape == 135 : self.drawCorners135(layer)

        return 


#    def drawResDefLayer( self, layer ):
    
#        self.computeResDefDimensions()
#        if self.direction == "vertical"    : Vertical.create   ( self.nets[0], layer, self.resdefLayerDict["XCenter"], self.resdefLayerDict["width"], self.resdefLayerDict["YMin"], self.resdefLayerDict["YMax"] ) 
#        if self.direction == "horizontal"  : Horizontal.create ( self.nets[0], layer, self.resdefLayerDict["YCenter"], self.resdefLayerDict["width"], self.resdefLayerDict["XMin"], self.resdefLayerDict["XMax"] ) 

#        return



    ## Creates a horizontal or vertical line of contacts according to the specified direction.

    def cutLine( self, net, layer, firstCutXCenter, firstCutYCenter, width_cut, height_cut, spacing_cut, cutNumber, direction ):       
 
        for i in range(0, cutNumber) :
            segment = Contact.create( net, layer, firstCutXCenter + i*(width_cut + spacing_cut), firstCutYCenter, width_cut, height_cut ) if direction == 'horizontal' else Contact.create( net, layer, firstCutXCenter, firstCutYCenter + i*(height_cut + spacing_cut), width_cut, height_cut )

        return segment



    ## Computes the maximal number of cuts to be placed on a layer of width \c width_layer considering specifications such as the spacing between the cuts, its width and its enclosure in the layer.

    def cutMaxNumber( self, width_layer, width_cut, spacing_cut, enclosure_cut ): 

        cutNumber = int( (width_layer - 2*enclosure_cut + spacing_cut) / (width_cut + spacing_cut) )
        if cutNumber > 0: return cutNumber
        else:
            raise Error (1,"cutMaxNumber() : Zero number of cuts found. Layer width is too tight." )


    def drawTerminals ( self ):
        VIA1overhang = self.minWidth_cut1/2 + self.minEnclosure_metal1_cut1

        t1net    = self.device.getNet('t1')
        t2net    = self.device.getNet('t2')
        t1metal1 = None
        t2metal1 = None

        for component in t1net.getComponents():
            if isinstance(component,Horizontal) and component.getLayer() == self.metal1:
                t1metal1 = component
                break

        for component in t2net.getComponents():
            if isinstance(component,Horizontal) and component.getLayer() == self.metal1:
                t2metal1 = component
                break

        ab        = self.device.getAbutmentBox()
        t1OnNorth = isNearNorth( t1metal1.getY(), ab )
        t2OnNorth = isNearNorth( t2metal1.getY(), ab )

        if t1OnNorth and t2OnNorth:
            t1YM2 = ab.getYMax() - self.hpitch*2
            t2YM2 = ab.getYMax() - self.hpitch
        elif t1OnNorth:
            t1YM2 = ab.getYMax() - self.hpitch
            t2YM2 = ab.getYMin() + self.hpitch
        elif t2OnNorth:
            t1YM2 = ab.getYMin() + self.hpitch
            t2YM2 = ab.getYMax() - self.hpitch
        else:
            t1YM2 = ab.getYMin() + self.hpitch*2
            t2YM2 = ab.getYMin() + self.hpitch

        m1Width   =  self.contactsNumber   *self.minWidth_contact   \
                  + (self.contactsNumber-1)*self.minSpacing_contact \
                  + 2*self.minEnclosure_routingLayer_contact
        edgeDelta = self.minWidth_contact/2 + self.minEnclosure_metal1_cut0

        if t1OnNorth:
            t1BoxM1 = Box( 0
                         , self.t1CutCenterDict["YCenter"] - edgeDelta
                         , m1Width
                         , t1YM2 + VIA1overhang
                         )
        else:
            t1BoxM1 = Box( 0
                         , t1YM2 - VIA1overhang
                         , m1Width
                         , self.t1CutCenterDict["YCenter"] + edgeDelta
                         )
        t1BoxM1.translate( self.t1CutCenterDict["XCenter"] - edgeDelta, 0 )

        if t2OnNorth:
            t2BoxM1 = Box( 0
                         , self.t2CutCenterDict["YCenter"] - edgeDelta
                         , m1Width
                         , t2YM2 + VIA1overhang
                         )
        else:
            t2BoxM1 = Box( 0
                         , t2YM2 - VIA1overhang
                         , m1Width
                         , self.t2CutCenterDict["YCenter"] + edgeDelta
                         )
        t2BoxM1.translate( self.t2CutCenterDict["XCenter"] - edgeDelta, 0 )

        self.drawM2Terminal( t1net, t1BoxM1, t1YM2 )
        self.drawM2Terminal( t2net, t2BoxM1, t2YM2 )

        return


    def drawM2Terminal ( self, net, boxM1, axisM2 ):
        ab = self.device.getAbutmentBox()

        minBoxM1 = Box( boxM1.getCenter().getX(), axisM2 )
        minBoxM1.inflate( self.minWidth_cut1/2 + self.minEnclosure_metal1_cut1 )
        boxM1.merge( minBoxM1 )

        h = Horizontal.create( net
                             , self.metal2
                             , axisM2
                             , self.metal2Width
                             , ab.getXMin()
                             , ab.getXMax() )
        NetExternalComponents.setExternal( h )

        Vertical.create( net
                       , self.metal1
                       , boxM1.getCenter().getX()
                       , boxM1.getWidth()
                       , boxM1.getYMin()
                       , boxM1.getYMax()
                       )

        cutNumber = ((boxM1.getWidth() - 2*self.minEnclosure_metal1_cut1 - self.minWidth_cut1) \
                    / (self.minSpacing_cut1 + self.minWidth_cut1))
        if cutNumber <= 0: cutNumber = 1
        centering = (boxM1.getWidth() - 2*self.minEnclosure_metal1_cut1 \
                  -  cutNumber    * self.minWidth_cut1               \
                  - (cutNumber-1) * self.minSpacing_cut1) / 2
        xcut1     = boxM1.getXMin() + centering \
                  + self.minEnclosure_metal1_cut1 + self.minWidth_cut1/2

        trace( 101, '\tcutNumber = {0}\n'.format(cutNumber) )
        for i in range(cutNumber):
            trace( 101, '\t[{0}]\n'.format(i) )
            Contact.create( net
                          , self.cut1
                          , xcut1
                          , axisM2
                          , self.minWidth_cut1
                          , self.minWidth_cut1
                          )
            xcut1 += self.minWidth_cut1 + self.minSpacing_cut1
        
        return
        


def scriptMain( **kw ):

    editor = None
    if kw.has_key('editor') and kw['editor']:
        editor = kw['editor']

    UpdateSession.open()
    device = AllianceFramework.get().createCell( 'resistor' )
    device.setTerminal( True )

    t_1 = Net.create( device, 't1' )
    t_1.setExternal( True )  
    t1 = device.getNet("t1")
    doBreak( 1, 'Done building terminal 1 net')

    t_2 = Net.create( device, 't2' )
    t_2.setExternal( True )  
    t2 = device.getNet("t2")
    doBreak( 1, 'Done building terminal 1 net')

    if editor:
        UpdateSession.close(        )
        editor.setCell     ( device ) 
        editor.fit         (        )            
        UpdateSession.open (        )     
    nets = [t1,t2]                  
   #(device, resistorType, resistance = 0, resDim = { "width" : 10, "length" : 0 }, direction = "vertical", 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