489315174的个人空间 https://blog.eetop.cn/carlliu [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

原来用Python做pcell 如此简单--MOS device

热度 1已有 1225 次阅读| 2024-6-25 20:24 |个人分类:日记|系统分类:芯片设计| Python, pcell, custom, compiler, pycell

前几天写了一个简单的金属电阻的pcell,经过这几天的摸索,在此编写了一个简单的 mos pcell 示例,用以演示一些常用命令的使用方法,并作为演示的 demo 供大家参考。

原来用Python做pcell 如此简单

Pycell studio 集成了丰富多样的 API,使得诸如 place、align、enclose、fill、devicecontact 等功能的实现变得极为简便。例如,smart placement 命令 fgPlace 能够依据 tech 中定义的规则,自动帮助放置并保持 minSpace 。在这个示例中,我们还尝试使用了 stretchHandle ,它能够支持 pcell 关键组件 size 的拉伸。

下面我们来详细介绍一下这个示例的关键步骤:

defineParamSpecs :用于定义参数规格。

setupParams :对参数进行初始化操作。

genlayout :负责创建 pcell 的形状。

整个示例的代码总计不到 150 行,并且每个部分都有清晰的功能说明,方便大家理解和学习。下面是主要的pcell结构。

class MyTransistor(DloGen):
def defineParamSpec(cls, specs):
# code to define parameters
def setupParams(self, params):
# code to process parameter values
def genToplogy(self):
# code to generate layout topology
def sizeDevices(self):
# code to size different devices
def genLayout(self):
# code to generate transistor layout

同样先制作对于的symbol,调用symbol设置好对于的参数,然后创建SDL layout 关系。   

图片

如下所以,可以在custom compiler中使用SDL调用创建的pcell。保证连接关系与电路的match。

图片

mos的pcell新增加支持handstretch功能,关键size可以通过拖拽改变。

图片

from cni.dlo import *
from cni.geo import *
from cni.constants import *
from cni.integ.common import *
class MyTransistor(DloGen):

    @classmethod
    def defineParamSpecs(cls, specs):
        # first use variables to set default values for all parameters
        tranType = 'pmos'
        oxide = 'thin'
        width = 0.4
        length = 0.2
        # now use these default parameter values in the parameter definitions
        specs('tranType', tranType, 'MOSFET type (pmos or nmos)', ChoiceConstraint(['pmos', 'nmos']))
        specs('oxide', oxide, 'Oxide (thin or thick)', ChoiceConstraint(['thin', 'thick']))
        specs('width', width, 'device width', RangeConstraint(width, 10*width, USE_DEFAULT))
        specs('length', length, 'device length', RangeConstraint(length, 10*length, USE_DEFAULT))
        specs('sourceDiffOverlap', 0.0)
        specs('drainDiffOverlap', 0.0)
        specs('dumFill', True)

    def setupParams(self, params):

        # save parameter values using class variables
        self.width = params['width']
        self.length = params['length']
        self.oxide = params['oxide']
        self.tranType = params['tranType']
        self.sourceDiffOverlap = params['sourceDiffOverlap']
        self.drainDiffOverlap = params['drainDiffOverlap']
        self.dumFill = params['dumFill']
        self.dumFillLayer = Layer('poly','dummy')
    
        # readjust width and length parameter values, since minimum values may be different
        self.width = max(self.width, 0.4)
        self.length = max(self.length, 0.2)
        
        # also snap width and length values to nearest grid points
        grid = Grid(self.tech.getGridResolution())
        self.width = grid.snap(self.width, SnapType.ROUND)
        self.length = grid.snap(self.length, SnapType.ROUND)

        # save layer values using class variables
        self.diffLayer = Layer('diff','drawing')
        self.gateLayer = Layer('poly','drawing')
        self.metalLayer = Layer('m1','drawing')
        self.m1Width =0.12
        #test layer
        self.testlayer =Layer('m3','drawing')
        # define the layers which should be used for enclosure rectangles
        if self.tranType == 'nmos':
            self.encLayers = [Layer('nplus','drawing')]
        else:
            self.encLayers = [Layer('pplus','drawing'), Layer('nwell','drawing')]
        if self.oxide == 'thick':
            self.encLayers.append(Layer('diff25','drawing'))
        # determine minimum extension for gate poly layer
        self.endcap = 0.1
    
    def genLayout(self):

        # first construct the rectangle for the gate
        gateBox = Box(0,-self.endcap, self.length ,(self.width + self.endcap))
        sdBox = Box(0,0,self.m1Width,self.width)
        gateRect = Rect(self.gateLayer, gateBox)
        
        # now construct device contacts for source and drain
        self.sourceContact = DeviceContact(self.diffLayer, self.metalLayer, sdBox, name='S')
        self.drainContact = DeviceContact(self.diffLayer, self.metalLayer, sdBox, name='D')

        # stretch the source and drain contacts to full transistor extent
        sourceBox = self.sourceContact.getRect1().getBBox()
        self.sourceContact.stretch(self.metalLayer, sourceBox)
        
        #Rect(self.testlayer, sourceBox)
        drainBox = self.drainContact.getRect1().getBBox()
        self.drainContact.stretch(self.metalLayer, drainBox)

        # use "smart place" to place gate between source and drain the drc space base on tf
        fgPlace(self.sourceContact, WEST, gateRect)
        fgPlace(self.drainContact, EAST, gateRect)
        
        # add any extra diffusion outside source and drain contacts
        sBox = self.sourceContact.getBBox(self.diffLayer)
        sBox.setLeft(sBox.left - self.sourceDiffOverlap)
        sourceRect=Rect(self.diffLayer, sBox)

        dBox = self.drainContact.getBBox(self.diffLayer)
        dBox.setRight(dBox.right + self.drainDiffOverlap)
        drainRect=Rect(self.diffLayer, dBox)

        left = sourceRect.getBBox().left
        right = drainRect.getBBox().right
        bottom = sourceRect.getBBox().top
        top = drainRect.getBBox().bottom
        diffBox = Box(left, bottom,right, top)
        diffRect = Rect(self.diffLayer, diffBox)
       
        # create gate dummy rectangle, from top of source to bottom of drain
        if self.dumFill == True :
            dumgateLRect = Rect(self.dumFillLayer, Box(0,-self.endcap, self.m1Width ,(self.width + self.endcap)))
            dumgateRRect = Rect(self.dumFillLayer, Box(0,-self.endcap, self.m1Width ,(self.width + self.endcap)))
            dumgateRRect.place(EAST,diffRect,0.1)
            dumgateLRect.place(WEST,diffRect,0.1)
            # fgPlace(dumgateRRect, EAST, diffRect)
            # fgPlace(dumgateLRect, WEST, diffRect)
        # define the enclosure rectangles on the enclosure layers for transistor
        fgAddEnclosingRects(self.makeGrouping(), self.encLayers)

        #stretch handle define
        stretchHandle(
        name = 'gateRect',
        shape = gateRect,
        parameter = "width",
        location = Location.UPPER_CENTER,
        direction = Direction.NORTH_SOUTH,
        stretchType = "relative",
        minVal = 0.4,
        userSnap = "%f" % (2.0 * self.tech.getGridResolution())
        )
        stretchHandle(
        name = 'gateRect',
        shape = gateRect,
        parameter = "length",
        location = Location.CENTER_RIGHT,
        direction = Direction.EAST_WEST,
        stretchType = "relative",
        minVal = 0.2,
        userSnap = "%f" % (2.0 * self.tech.getGridResolution())
        )
        
        # add the terminals for this transistor unit
        self.addTerm('S', TermType.INPUT_OUTPUT)    # source terminal
        self.addTerm('D', TermType.INPUT_OUTPUT)    # drain terminal
        self.addTerm('G', TermType.INPUT)           # gate terminal
        self.addTerm('B', TermType.INPUT_OUTPUT)    # bulk (substrate) terminal
        self.setTermOrder(['D', 'G', 'S', 'B'])
        # also define the pins for this transistor unit
        self.addPin('G', 'G', gateBox, self.gateLayer)
        self.addPin('S', 'S', self.sourceContact.getBBox(self.metalLayer), self.metalLayer)
        self.addPin('D', 'D', self.drainContact.getBBox(self.metalLayer), self.metalLayer)


1

点赞

刚表态过的朋友 (1 人)

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 4

    关注
  • 139

    粉丝
  • 65

    好友
  • 135

    获赞
  • 52

    评论
  • 1323

    访问数
关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-22 14:29 , Processed in 0.016072 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部