예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
    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)