def genLayout( self): """Main body of geometric construction code. Avoid modifying or overriding this method. PyCell-specific behaviors and calculations should be kept out of this method. """ # Decide whether small or big via spacing applies if ( ((self.xCnt > self.limitBig) and (self.yCnt >= self.limitBig)) or ((self.xCnt == self.limitBig) and (self.yCnt > self.limitBig)) ): # Over big spacing limit, use big spacing rules viaSpacing = self.viaSpacingBig else: # Under big spacing limit, use small spacing rules viaSpacing = self.viaSpacingSmall xViaPitch = self.viaWidth + viaSpacing yViaPitch = self.viaWidth + viaSpacing # Decide whether via farm rules apply if ( ((self.xCnt > self.limitFarm) and (self.yCnt >= self.limitFarm)) or ((self.xCnt == self.limitFarm) and (self.yCnt > self.limitFarm)) ): # Over farm limit, use farm spacing rules viaSpacingFarm = self.viaSpacingFarm else: # Under farm limit, use same spacing rules viaSpacingFarm = viaSpacing xViaPitchFarm = (self.limitFarm - 1) * xViaPitch + self.viaWidth + viaSpacingFarm yViaPitchFarm = (self.limitFarm - 1) * yViaPitch + self.viaWidth + viaSpacingFarm # # Place the via geometries. # xCoordMax = 0 yCoordMax = 0 # Loop iterates over farms to build up complete columns. # # Each o represents a via geometry. # # ooo ooo ooo ooo # ooo ooo ooo ooo # ooo ooo ooo ooo # # ooo ooo ooo ooo # ooo ooo ooo ooo # ooo ooo ooo ooo # # ooo ooo ooo ooo # ooo ooo ooo ooo # ooo ooo ooo ooo # yTotal = 0 yCoord = 0 yFarmCoord = 0 while yTotal < self.yCnt: # Loop interates over rows to build up columns, # but only for part of each column within a farm. # # Each o represents a via geometry. # # ooo ooo ooo ooo # ooo ooo ooo ooo # ooo ooo ooo ooo # y = 0 while (y < self.limitFarm) and (yTotal < self.yCnt): # Loop iterates over farms to build a complete row # # Each o represents a via geometry. # # ooo ooo ooo ooo # xTotal = 0 xCoord = 0 xFarmCoord = 0 while xTotal < self.xCnt: # Innermost loop builds part of each row within # a farm. # # Each o represents a via geometry. # # ooo # x = 0 while (x < self.limitFarm) and (xTotal < self.xCnt): Rect( self.via, Box( xCoord, yCoord, (xCoord + self.viaWidth), (yCoord + self.viaWidth) ) ) x += 1 xTotal += 1 xCoord += xViaPitch xCoordMax = xCoord - xViaPitch + self.viaWidth xFarmCoord += xViaPitchFarm xCoord = xFarmCoord yCoordMax = yCoord + self.viaWidth y += 1 yTotal += 1 yCoord += yViaPitch yFarmCoord += yViaPitchFarm yCoord = yFarmCoord # Construct upper metal plate. Rect( self.metalUpper, Box( -self.xEnc[ (self.metalUpper, self.via)], -self.yEnc[ (self.metalUpper, self.via)], xCoordMax + self.xEnc[ (self.metalUpper, self.via)], yCoordMax + self.yEnc[ (self.metalUpper, self.via)], ) ) # Construct lower metal plate. Rect( self.metalLower, Box( -self.xEnc[ (self.metalLower, self.via)], -self.yEnc[ (self.metalLower, self.via)], xCoordMax + self.xEnc[ (self.metalLower, self.via)], yCoordMax + self.yEnc[ (self.metalLower, self.via)], ) ) # Construct any outlining geometries, such as implant # layers needed for substrate/well contacts. for layer in self.outline: box = self.getBBox() for innerLayer in ( self.via, self.metalLower, self.metalUpper): innerBox = self.getBBox( innerLayer) innerBox.left -= self.xEnc[ (layer, innerLayer)] innerBox.right += self.xEnc[ (layer, innerLayer)] innerBox.bottom -= self.yEnc[ (layer, innerLayer)] innerBox.top += self.yEnc[ (layer, innerLayer)] box.merge( innerBox) Rect( layer, box) # Move origin if requested all = Grouping( "all", self.getComps()) if self.origin == "centerCenter": xCoord = round( (-xCoordMax / 2) / self.grid) * self.grid yCoord = round( (-yCoordMax / 2) / self.grid) * self.grid elif self.origin == "lowerCenter": xCoord = round( (-xCoordMax / 2) / self.grid) * self.grid yCoord = max( self.yEnc[ (self.metalUpper, self.via)], self.yEnc[ (self.metalLower, self.via)]) elif self.origin == "lowerLeft": xCoord = max( self.xEnc[ (self.metalUpper, self.via)], self.xEnc[ (self.metalLower, self.via)]) yCoord = max( self.yEnc[ (self.metalUpper, self.via)], self.yEnc[ (self.metalLower, self.via)]) elif self.origin == "centerLeft": xCoord = max( self.xEnc[ (self.metalUpper, self.via)], self.xEnc[ (self.metalLower, self.via)]) yCoord = round( (-yCoordMax / 2) / self.grid) * self.grid all.moveBy( xCoord, yCoord)
def genLayout( self): """Main body of geometric construction code. Create the leftmost contact and transistor gate. Loop to create center contacts and gates. Create the rightmost gate and contact. Avoid modifying or overriding this method. PyCell-specific behaviors and calculations should be kept out of this method. """ # obj is used to track the rightmost object, to calculate # the diffusion coordinates. # dbox is the bounding box of the underlying diffusion. dbox = Dictionary() dbox.bottom = 0 dbox.top = self.w origin = Dictionary() xCoord = 0 origin.y = 0 objectPitch = { True:self.ContGatePitch, False:self.GatePitchDiv2, } # Mark PyCell as containing stretch handles self.props["cniStretch"] = "CiraNova" # For integration with layout editors, save parameter # settings in the submaster. They are not saved on the # instance in the default case. # For auto-abutment self.props["diffContactLeft"] = self.diffContactLeft self.props["diffContactRight"] = self.diffContactRight # For stretch handles self.props["w"] = self.w self.props["l"] = self.l # Create electrical terminals needed for pins Term("G", TermType.INPUT) Term("S", TermType.INPUT_OUTPUT) Term("D", TermType.INPUT_OUTPUT) # Create leftmost diffusion contact obj = self.createSourceDrain( diffusionType = "left", withContact = self.diffContactLeft, coverage = self.diffContactLeftCov, stretch = "diffContactLeftCov", terminal = "S", x = xCoord, ) dbox.left = obj.getBBox( self.diffusion).getLeft() # Create leftmost gate w/optional gate contact xCoord += objectPitch[self.diffContactLeft]# + 0.0025 obj = self.createGate( x=xCoord, terminal="G") origin.x = obj.getBBox().left if self.gateContactLeft: self.createGateCont( gateRect = obj, coverage = self.gateContactLeftCov, stretch = "gateContactLeftCov", terminal = "G", ) # Loop to create center gates and contacts for i in range( self.fingers - 2): # Create diffusion contact on left of gate xCoord += objectPitch[self.diffContactCenter] + 0.0025 self.createSourceDrain( diffusionType = "full", withContact = self.diffContactCenter, coverage = self.diffContactCenterCov, stretch = "diffContactCenterCov", x = xCoord, ) # Create gate w/optional gate contact if self.diffContactCenter: xCoord += objectPitch[self.diffContactCenter] + 0.0025 else: xCoord += objectPitch[self.diffContactCenter] - 0.0025 obj = self.createGate( x=xCoord, terminal="G") if self.gateContactCenter: self.createGateCont( gateRect = obj, coverage = self.gateContactCenterCov, stretch = "gateContactCenterCov", terminal = "G", ) # Create rightmost gate w/optional gate contact if self.fingers > 1: if self.diffContactCenter: xCoord += objectPitch[self.diffContactCenter] + 0.0025 else: xCoord += objectPitch[self.diffContactCenter] - 0.0025 self.createSourceDrain( diffusionType = "full", withContact = self.diffContactCenter, coverage = self.diffContactCenterCov, stretch = "diffContactCenterCov", x = xCoord, ) xCoord += objectPitch[self.diffContactCenter] + 0.0025 obj = self.createGate( x=xCoord, terminal="G") if self.gateContactRight: self.createGateCont( gateRect = obj, coverage = self.gateContactRightCov, stretch = "gateContactRightCov", terminal = "G", ) # Create rightmost diffusion contact xCoord += objectPitch[self.diffContactRight]# + 0.0025 obj = self.createSourceDrain( diffusionType = "right", withContact = self.diffContactRight, coverage = self.diffContactRightCov, stretch = "diffContactRightCov", x = xCoord, terminal = "D", ) dbox.right = obj.getBBox(self.diffusion).getRight() # Create overall diffusion box Rect( self.diffusion, Box( dbox.left, dbox.bottom, dbox.right, dbox.top) ) # Create implant box, to overlap diffusion rather than whole cell Rect( self.implant, Box( dbox.left, dbox.bottom, dbox.right, dbox.top) ) Rect( self.well, Box( dbox.left - 0.055, dbox.bottom - 0.055, dbox.right + 0.055, dbox.top + 0.055 ) ) Rect( self.alt, Box( dbox.left - 0.055, dbox.bottom - 0.055, dbox.right + 0.055, dbox.top + 0.055 ) ) # Create other outline layers all = Grouping( "all", self.getComps()) # all.add( self.fgAddEnclosingRects( all, self.encLayers)) This wasn't working, replaced with above rectangles # Setting the origin is important. # Avoid shifting of instance locations during auto-abutment. # Correctly track mouse motion during stretching. all.moveBy( -origin.x, -origin.y)