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)
Exemple #2
0
    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)
Exemple #3
0
    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)
Exemple #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)
Exemple #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)