【一】标准数字(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 脚本思路
- 先获取使用到M1的cell
- 对这些使用的STD进行筛选,是否满足top定义的track
- 对筛选出来不满足的进行换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