定制逻辑单元,手动布局STD之后,用SKILL实现批量换cell,实现metal Track的统一

【一】标准数字(STD)layout相关介绍

1.1 染色及track的概念

1.1.1 染色(double pattern)

在大工艺的中,如180nm的工艺,一层metal,只需要一张mask就可以实现,因为金属的宽度和间距不需要做的很小,光刻机可以实现。来到小工艺之后,在逻辑区,为了能有更多的走线通道,就需要把金属做的很细,间距很小,用一张mask,不用先进的光刻机,已经无法实现一张mask区完成了,因此会进行分版,同一层金属用两张mask去做,如M1,有两种染色,绿色和红色,这两种不同颜色的M1,在制造上有着先后顺序,区别应该是很小的,有些文档里记录着,绿色有更低的阻抗(随便听听,不确定),但是从TSMC的某节点工艺来说,标准数字的M1,优先使用绿色,红色作为电源使用(可能只是一种布局策略)。

1.1.2 走线通道(track)

简单来说就是固定间距走线,在数字中,为了提高金属的利用率,会固定间距走线,当然也有其他原因,不清楚,仅以个人经历过的项目为例,如三星和SMIC的某工艺,会根据M2的track,每一个STD做四个layout,如INV........_1,INV........_2,INV........_3,INV........_4,这四个STD的电路相同,四种不同的走线track,为了在top层,可以换cell去满足顶层的track,当然TSMC也会有这种,如INV..NOMSA,INV..NOMSB,INV..NOMSC,INV..NOMSD,这样也是代表四种不同metal track的STD,电路是相同的。

1.2 关于手动布局(正常数字后端布局)

一些阵列的数字core,或者很多path比较重要的小逻辑区,还是更倾向手动布局的,作为模拟版图来说,其实经常会手动布局一些小的逻辑,没啥可说的,手摆才是硬道理.......(好像没啥技术含量)

举个例子:如下图所示,随便调出来一些STD,我们可以看到红色和绿色的就是M1,如果要所有的M1都满足一个track,除了移动这些cell,就是换cell,上面说了,一个cell会做成四个不同track的STD,总有一个可以满足。


【二】批量换cell,实现top满足任意一种track

2.1 脚本思路

  1. 先获取使用到M1的cell
  2. 对这些使用的STD进行筛选,是否满足top定义的track
  3. 对筛选出来不满足的进行换cell,当满足track时结束替换

2.2实现的具体细节(TSMC工艺)

1.获取使用M1的STD,可以获取STD是否有这个层次去筛选,由于用的定制库,因此用cellname去判断筛选的,(NOMSA NOMSB NOMSC NOMSD)代码如下:

   cv = geGetEditCellView()
   insts=cv~>instances
   NOMS_insts=setof(x insts nindex((x~>cellName) "NOMS")!=nil)

2.再次筛选不满足track的STD,由于都是等间距排列的metal,判断cell内其中一根metal的坐标是否为track的整数倍就可以了,具体的数值以工艺为准,获取这个倍数的N的代码如下:

procedure(getTrackN(track inst_id)
prog(()
    case(track
	("NOMSA"  if(cadr(getInstMetalLeftEdge(inst_id))=="mask2Color" then
		     N=(car(getInstMetalLeftEdge(inst_id))-0.0155)/0.068
		  else
		     N=(car(getInstMetalLeftEdge(inst_id))-0.0495)/0.068 )
        )
	("NOMSB"  if(cadr(getInstMetalLeftEdge(inst_id))=="mask2Color" then
		     N=(car(getInstMetalLeftEdge(inst_id))-0.0325)/0.068
		  else
		     N=(car(getInstMetalLeftEdge(inst_id))-0.0665)/0.068 )
        )		
	("NOMSC"  if(cadr(getInstMetalLeftEdge(inst_id))=="mask2Color" then
		     N=(car(getInstMetalLeftEdge(inst_id))-0.0495)/0.068
		  else
		     N=(car(getInstMetalLeftEdge(inst_id))-0.0155)/0.068 )
        )

	("NOMSD"  if(cadr(getInstMetalLeftEdge(inst_id))=="mask2Color" then
		     N=(car(getInstMetalLeftEdge(inst_id))-0.0665)/0.068
		  else
		     N=(car(getInstMetalLeftEdge(inst_id))-0.0325)/0.068 )
        )
        )

return(N)
);prog
);procedure


procedure(getInstMetalLeftEdge(inst_id)
prog(()
     m_id = setof(x inst_id~>master~>shapes x~>lpp == '("M1" "drawing"))
     sort_m_id = sort(m_id 'lambda((a b) leftEdge(a)<leftEdge(b)))
     left_M1_clore = dbGetShapeColor(car(m_id))
     m_box = dbTransformBBox(car(sort_m_id)~>bBox  dbGetInstTransform(inst_id))
     left_edge = caar(m_box)
     return(list(left_edge left_M1_clore))
);prog
);procedure

3.开始替换cell,把不满足的整数倍的替换掉,替换之后继续循环判断替换之后满足track是否,然后继续循环执行,其中cellshift()子函数,直接调用别人写的,不便公开,循环执行代码如下:

procedure(cellShiftTrack(track)
let(()
   cv = geGetEditCellView()
   insts=cv~>instances
   NOMS_insts=setof(x insts nindex((x~>cellName) "NOMS")!=nil)
   shift_insts=setof(x NOMS_insts abs(round(getTrackN(track x))-getTrackN(track x))>1e-6)
   while((shift_insts != nil)
         shift_list=list()
         foreach(shift_inst shift_insts
             id=CellShift_all(shift_inst)
	         shift_list=append1(shift_list id)
	         geDeselectAllFig()	
);foreach
shift_insts=setof(x shift_list abs(round(getTrackN(track x))-getTrackN(track x))>1e-6)	
);while           
);let	
);procedure

  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值