def genLayout( self): """Create the layout. Main body of geometric construction code. """ Term( "D", TermType.INPUT_OUTPUT) Term( "G", TermType.INPUT) Term( "S", TermType.INPUT_OUTPUT) Term( "B", TermType.INPUT_OUTPUT) # Create poly bbox = Box( -self.endcap, 0, (self.width + self.endcap), self.length) polyRect = Rect( self.gateLayer, bbox) Pin( "G", "G", Rect( self.gateLayer, bbox)) # Create source contact contact = self.createContact( "S", Direction.SOUTH, polyRect, self.sourceDiffOverlap) bottom = contact.getBBox().top # Create drain contact contact = self.createContact( "D", Direction.NORTH, polyRect, self.drainDiffOverlap ) top = contact.getBBox().bottom # Create diffusion Rect( self.diffLayer, Box( 0, bottom, self.width, top)) Rect( self.implantLayer, Box( 0, bottom, self.width, top)) #create nonenclosing implant layer # Create other outline layers all = Grouping( "all", self.getComps()) self.fgAddEnclosingRects( all, self.encLayers)
def createGateCont(self, gateRect=False, coverage=1.0, stretch=False, terminal=False): """Create a gate contact by instantiating a poly contact PyCell. Arguments: gateRect - (PhysicalComponent) Gate rectangle for alignment. coverage - (float ) Percentage of poly width to be covered by contact stretch - (string ) Name of stretch handle property for gate contact """ gateCont = ViaInstance( "pcont", ParamArray(), None, "I%d" % self.instance, ) self.place(gateCont, Direction.SOUTH, gateRect, 0) width = self.l * coverage gateCont.resize( width=width, via=self.contact, metalLayer=self.poly, ) # Create overlapping poly rectangle for stretch handle polyRect = gateCont.promoteMetal(self.poly) bbox = polyRect.getBBox() width = max(width, bbox.getWidth()) / 2 center = bbox.getCenterX() bbox.setLeft(center - width) bbox.setRight(center + width) polyRect.setBBox(bbox) # Stretch handle for gate contact coverage stretchHandle( shape=polyRect, name=("stretch%d" % self.instance), parameter=stretch, location=Location.CENTER_RIGHT, direction=Direction.EAST_WEST, stretchType="relative", userScale="1.0", userSnap="0.0025", minVal=0.0, maxVal=1.0, ) # Create weakly-connected pins if terminal: Pin(("%sC%d" % (terminal, self.instance)), terminal, Rect(self.poly, bbox)) self.instance += 1 return (gateCont)
def createContact( self, terminal, location, polyRect, moreOverlap): """Create the contact for source or drain. Arguments: terminal - (string) Name of terminal for pin. location - (NORTH||SOUTH) Relative location to place contact. polyRect - (PhysicalComponent::Rect) Shape to align contact. moreOverlap - (float) Amount of additional diffusion overlap. """ contact = Contact( self.diffLayer, self.xtorFillLayer, terminal, routeDir1 = Direction.EAST_WEST, routeDir2 = Direction.EAST_WEST) # Placement uses poly-to-diffusion spacing for dogbone # Demonstrate how dogbone should be done. isDogBone = contact.getBBox( self.diffLayer).getWidth() > self.width if isDogBone: self.fgPlace( contact, location, polyRect) else: self.fgPlace( contact, location, polyRect, ShapeFilter([self.diffLayer], False)) cbox = contact.getBBox( self.diffLayer) contact.moveBy( (cbox.left % self.grid), 0) if not isDogBone: pbox = polyRect.getBBox() contact.stretchTowards( Direction.EAST, pbox.right - self.endcap) contact.stretchTowards( Direction.WEST, pbox.left + self.endcap) Pin( terminal, terminal, Rect( self.xtorFillLayer, contact.getBBox( self.xtorFillLayer))) # Add additional diffusion overlap cbox = contact.getBBox( self.diffLayer) if moreOverlap: if location == Direction.NORTH: cbox.setTop( cbox.top + moreOverlap) elif location == Direction.SOUTH: cbox.setBottom( cbox.bottom - moreOverlap) else: raise ValueError, "Unsupported Direction for more diffusion overlap." Rect( self.diffLayer, cbox) return( contact)
def createSourceDrain( self, diffusionType="full", withContact=True, x=0, y=0, coverage=1.0, stretch=False, terminal=False): """Create a source or drain diffusion. Option to create diffusion contact instance. Option to create matching diffusion terminal. Option to create a stretch handle property. Override this method to create custom contacts. Arguments: diffusionType - (string) "full", "left", "right" withContact - (boolean) Create contact x - (float ) x coordinate for center of contact y - (float ) y coordinate for lower diffusion edge coverage - (float ) Percentage of source/drain diffusion to be covered by contact stretch - (string ) Name of stretch handle property """ # Create source/drain contact if withContact: diffCont = ViaInstance( "dcont", ParamArray( origin="lowerCenter"), None, "I%d" % self.instance, ) diffCont.setOrigin( Point(x, y-0.02)) height = self.w * coverage diffCont.resize( height = height, via = self.contact, metalLayer = self.diffusion, ) # Create overlapping diffusion rectangle for stretch handle diffRect = diffCont.promoteMetal( self.diffusion) bbox = diffRect.getBBox() height = max( height, bbox.getHeight()) bbox.setTop( bbox.getBottom() + height) diffRect.setBBox( bbox) # Stretch handle for diffusion contact coverage stretchHandle( shape = diffRect, name = ("stretch%d" % self.instance), parameter = stretch, location = Location.UPPER_CENTER, direction = Direction.NORTH_SOUTH, stretchType = "relative", userScale = "1.0", userSnap = "0.0025", minVal = 0.0, maxVal = 1.0, ) self.instance += 1 # Create source/drain diffusion if withContact: bbox = Box( bbox.getLeft(), y, bbox.getRight(), (y + self.w), ) else: if (diffusionType == "left"): bbox = Box( x, y, (x + self.GateSpaceDiv2), (y + self.w), ) elif (diffusionType == "right"): bbox = Box( (x - self.GateSpaceDiv2), y, x, (y + self.w), ) elif (diffusionType == "full"): bbox = Box( (x - self.GateSpaceDiv2), y, (x + self.GateSpaceDiv2), (y + self.w), ) else: raise ValueError, "Unknown: diffusionType=%s" % diffusionType if terminal: p0 = Pin( terminal, terminal, Rect( self.diffusion, bbox) ) pinRect = p0.getShapes()[0] autoAbutment( pinRect, self.w, [ Direction.WEST], "cniMOS", abut2PinEqual = [ { "spacing":0.0}, { "diffLeftStyle":"DiffHalf" }, { "diffLeftStyle":"DiffHalf" } ], abut2PinBigger = [ { "spacing":0.0}, { "diffLeftStyle":"DiffEdgeAbut" }, { "diffLeftStyle":"DiffEdgeAbut" } ], abut3PinBigger = [ { "spacing":0.0}, { "diffLeftStyle":"ContactEdgeAbut2"}, { "diffLeftStyle":"ContactEdgeAbut2"} ], abut3PinEqual = [ { "spacing":0.0}, { "diffLeftStyle":"DiffAbut" }, { "diffLeftStyle":"ContactEdgeAbut2"} ], abut2PinSmaller = [ { "spacing":0.0}, { "diffLeftStyle":"DiffEdgeAbut" }, { "diffLeftStyle":"DiffEdgeAbut" } ], abut3PinSmaller = [ { "spacing":0.0}, { "diffLeftStyle":"DiffEdgeAbut" }, { "diffLeftStyle":"DiffEdgeAbut" } ], noAbut = [ { "spacing":0.4}], function = "cniAbut", #shape = pinRect, #abutDirection = diffusionType, #abutClass = "cniMOS", #abutFunction = "cniAbut", #spacingRule = self.DiffSpace, ) else: pinRect = Rect( self.diffusion, bbox) return( pinRect)
def createGate( self, x=0, y=0, terminal=False): """Create the poly rectangle which represents the MOS transistor gate. Override this method to create custom gates. Arguments: x - (integer) x coordinate of gate center y - (integer) y coordinate of lower diffusion edge """ left = x - self.lDiv2 right = x + self.lDiv2 # Create transistor gate gateRect = Rect( self.poly, Box( left, (y - self.Endcap), right, (y + self.w + self.Endcap), ) ) # Stretch handles for w & l stretchHandle( shape = gateRect, name = ("stretch%d" % self.instance), parameter = "w", location = Location.UPPER_CENTER, direction = Direction.NORTH_SOUTH, display = ("w = %.2f" % self.w), stretchType = "relative", userScale = "1.0", userSnap = "0.0025", ) stretchHandle( shape = gateRect, name = ("stretch%d" % self.instance), parameter = "l", location = Location.CENTER_RIGHT, direction = Direction.EAST_WEST, display = ("l = %.2f" % self.l), stretchType = "relative", userScale = "1.0", userSnap = "0.0025", ) # Create weakly-connected pins if terminal: # Bottom gate pin Pin( "%sS%d" % (terminal, self.instance), terminal, Rect( self.poly, Box( left, (y - self.Endcap), right, y, ) ) ) # Top gate pin Pin( "%sN%d" % (terminal, self.instance), terminal, Rect( self.poly, Box( left, (y + self.w), right, (y + self.w + self.Endcap), ) ) ) self.instance += 1 return( gateRect)