Skill语言学习_6🦽
使用Skill语言,完成差分对的匹配和Dummy管的添加

Skill版本:
getSkillVersion
"SKILL35.00"
>
学习参考:
[ Skill ] Cadence Skill 语言入门 - YEUNGCHIE - 博客园
脚本思路:
1、将框选区域所有器件按照器件名字分为两个列表;
2、按照ABBA,BAAB的匹配形式将两个列表的器件重新排列为两个新列表;
3、设定间距x,y;
4、按照设定的间距排布器件,并使得上下列器件的栅极生成于中间;
5、在上下两列器件两端加入Dummy器件。
设计操作:
1、将框选区域所有器件按照器件名字分为两个列表;
获取当前处于编辑状态的 CellView 的数据库 id,赋值给 cv;
cv = geGetEditCellView()
获取当前在版图窗口中被鼠标选中的所有对象的id列表;
instList = geGetSelSet()
提取每个对象的 baseName 属性;
bNameList = instList~>baseName
得到bNameList,并观察结果:
bNameList = instList~>baseName
("NM123.1" "NM123.2" "NM123.3" "NM123.4" "NM1.1" "NM1.2" "NM1.3" "NM1.4")
>
可知可根据baseName"."号之前的字符串将所有器件分为两类。
获取器件名称中第一个点号(.)之前的部分保存在nameList列表中;
nameList = foreach(mapcar bName bNameList car(parseString(bName ".")))
得到nameList,并观察结果:
nameList = foreach(mapcar bName bNameList car(parseString(bName ".")))
("NM123" "NM123" "NM123" "NM123" "NM1" "NM1" "NM1" "NM1")
>
使用mapcar函数将器件ID和器件nameList匹配;
pairedList = mapcar('list instList nameList)
得到pairedList,并观察结果:
pairedList = mapcar('list instList nameList)
( (db:0x16387a1d "NM123")
(db:0x16387a1e "NM123")
(db:0x16387a1f "NM123")
(db:0x16387a20 "NM123")
(db:0x16387a21 "NM1")
(db:0x16387a22 "NM1")
(db:0x16387a23 "NM1")
(db:0x16387a24 "NM1") )
>
将nameList去重后,作为两个列表的区分依据:
uniqueList = ciUtilsMakeUnique(nameList)
("NM123" "NM1")
>
根据nameList将器id分为两个列表:
nm1List = setof(pair pairedList (cadr(pair) == car(uniqueList)))
nm1List = mapcar('car nm1List)
nm0List = setof(pair pairedList (cadr(pair) == cadr(uniqueList)))
nm0List = mapcar('car nm0List)
得到nm0List和nm1List的id列表:
nm0List
nm1List
(db:0x16387a21 db:0x16387a22 db:0x16387a23 db:0x16387a24)
(db:0x16387a1d db:0x16387a1e db:0x16387a1f db:0x16387a20)
>
符合预期结果。
2、按照ABBA,BAAB的匹配形式将两个列表的器件重新排列为两个新列表;
abbaPattern = list(
nth(0 nm0List)
nth(0 nm1List)
nth(1 nm1List)
nth(1 nm0List)
)
baabPattern = list(
nth(2 nm1List)
nth(2 nm0List)
nth(3 nm0List)
nth(3 nm1List)
)
得到abbaPattern 和baabPattern两个id列表:
abbaPattern
baabPattern
(db:0x16387a21 db:0x16387a1d db:0x16387a1e db:0x16387a22)
(db:0x16387a1f db:0x16387a23 db:0x16387a24 db:0x16387a20)
>
3、设定间距x,y;
x = 2
y = 2
4、按照设定的间距排布器件,并使得上下列器件的栅极生成于中间;
确定器件的宽度和高度以及原始坐标;
bBox = car(nm0List)~>bBox
instWidth = caadr(bBox) - caar(bBox)
instHeight = cadadr(bBox) - cadar(bBox)
originxy = car(nm0List)~>xy
排布器件,并按照设定生成栅极;
for(i 0 (length(abbaPattern)-1)
let((currentItem newxy)
currentItem = nth(i abbaPattern)
dbReplaceProp(currentItem "connectGates" "string" "Bottom")
newxy = list(car(originxy) + i*(x+instWidth) cadr(originxy))
currentItem~>xy = newxy
printf("num %d: value = %L\n" i currentItem~>xy)
);let
);for
for(i 0 (length(baabPattern)-1)
let((currentItem newxy)
currentItem = nth(i baabPattern)
dbReplaceProp(currentItem "connectGates" "string" "Top")
newxy = list(car(originxy) + i*(x+instWidth) cadr(originxy) - y - instHeight)
currentItem~>xy = newxy
printf("num %d: value = %L\n" i currentItem~>xy)
;println(i currentItem~>bBox)
);let
);for

5、在上下两列器件的左右两端加入Dummy器件。
let((targetInst bBox origin left right top bottom x1 y1 width x2 height dummyLib dummyCell masterCv spacing leftOrigin rightOrigin maxNum num newName leftInst rightInst)
targetInst = car(abbaPattern)
bBox = targetInst~>bBox
origin = targetInst~>xy
left = caadr(bBox)
right = caar(bBox)
top = cadadr(bBox)
bottom = cadar(bBox)
x1 = car(origin)
y1 = cadr(origin)
x2 = caar(last(abbaPattern)~>xy)
width = left - right
height = top - bottom
dummyLib = targetInst~>libName
dummyCell = targetInst~>cellName
masterCv = dbOpenCellViewByType(dummyLib dummyCell "layout")
spacing = x
leftOrigin = list(x1 - width - spacing, y1)
rightOrigin = list(x2 + width + spacing, y1)
maxNum = 0
foreach(instName cv~>instances~>name
if(rexMatchp("Dummy*" instName)
then
num = atoi(substring(instName strlen("Dummy")+1))
if(num > maxNum then
maxNum = num
);if
);if
);foreach
newName = sprintf(str "Dummy%d" (maxNum+1))
leftInst = dbCreateInst(cv masterCv newName leftOrigin "R0" 1)
dbCopyProp(targetInst leftInst)
newName = sprintf(str "Dummy%d" (maxNum+2))
rightInst = dbCreateInst(cv masterCv newName rightOrigin "R0" 1)
dbCopyProp(targetInst rightInst)
);let
let((selected targetInst bBox origin left right top bottom x1 y1 x2 width height dummyLib dummyCell masterCv spacing leftOrigin rightOrigin maxNum num newName leftInst rightInst)
targetInst = car(baabPattern)
bBox = targetInst~>bBox
origin = targetInst~>xy
left = caadr(bBox)
right = caar(bBox)
top = cadadr(bBox)
bottom = cadar(bBox)
x1 = car(origin)
y1 = cadr(origin)
x2 = caar(last(baabPattern)~>xy)
width = left - right
height = top - bottom
dummyLib = targetInst~>libName
dummyCell = targetInst~>cellName
masterCv = dbOpenCellViewByType(dummyLib dummyCell "layout")
spacing = x
leftOrigin = list(x1 - width - spacing, y1)
rightOrigin = list(x2 + width + spacing, y1)
maxNum = 0
foreach(instName cv~>instances~>name
if(rexMatchp("Dummy*" instName)
then
num = atoi(substring(instName strlen("Dummy")+1))
if(num > maxNum then
maxNum = num
);if
);if
);foreach
newName = sprintf(str "Dummy%d" (maxNum+1))
leftInst = dbCreateInst(cv masterCv newName leftOrigin "R0" 1)
dbCopyProp(targetInst leftInst)
newName = sprintf(str "Dummy%d" (maxNum+2))
rightInst = dbCreateInst(cv masterCv newName rightOrigin "R0" 1)
dbCopyProp(targetInst rightInst)
);let
整合上述代码,并绑定快捷键:
procedure(arrangeMultiplierDevicesAddDummy(x y)
let((cv instList bNameList nameList pairedList uniqueList nm1List nm0List bBox instWidth instHeight abbaPattern baabPattern originxy)
cv = geGetEditCellView()
instList = geGetSelSet()
bNameList = instList~>baseName
nameList = foreach(mapcar bName bNameList car(parseString(bName ".")))
pairedList = mapcar('list instList nameList)
uniqueList = ciUtilsMakeUnique(nameList)
nm1List = setof(pair pairedList
(cadr(pair) == car(uniqueList)))
nm1List = mapcar('car nm1List)
nm0List = setof(pair pairedList
(cadr(pair) == cadr(uniqueList)))
nm0List = mapcar('car nm0List)
abbaPattern = list(
nth(0 nm0List)
nth(0 nm1List)
nth(1 nm1List)
nth(1 nm0List)
)
baabPattern = list(
nth(2 nm1List)
nth(2 nm0List)
nth(3 nm0List)
nth(3 nm1List)
)
bBox = car(nm0List)~>bBox
instWidth = caadr(bBox) - caar(bBox)
instHeight = cadadr(bBox) - cadar(bBox)
originxy = car(nm0List)~>xy
for(i 0 (length(abbaPattern)-1)
let((currentItem newxy)
currentItem = nth(i abbaPattern)
dbReplaceProp(currentItem "connectGates" "string" "Bottom")
newxy = list(car(originxy) + i*(x+instWidth) cadr(originxy))
currentItem~>xy = newxy
printf("num %d: value = %L\n" i currentItem~>xy)
);let
);for
for(i 0 (length(baabPattern)-1)
let((currentItem newxy)
currentItem = nth(i baabPattern)
dbReplaceProp(currentItem "connectGates" "string" "Top")
newxy = list(car(originxy) + i*(x+instWidth) cadr(originxy) - y - instHeight)
currentItem~>xy = newxy
printf("num %d: value = %L\n" i currentItem~>xy)
;println(i currentItem~>bBox)
);let
);for
let((targetInst bBox origin left right top bottom x1 y1 width x2 height dummyLib dummyCell masterCv spacing leftOrigin rightOrigin maxNum num newName leftInst rightInst)
targetInst = car(abbaPattern)
bBox = targetInst~>bBox
origin = targetInst~>xy
left = caadr(bBox)
right = caar(bBox)
top = cadadr(bBox)
bottom = cadar(bBox)
x1 = car(origin)
y1 = cadr(origin)
x2 = caar(last(abbaPattern)~>xy)
width = left - right
height = top - bottom
dummyLib = targetInst~>libName
dummyCell = targetInst~>cellName
masterCv = dbOpenCellViewByType(dummyLib dummyCell "layout")
spacing = x
leftOrigin = list(x1 - width - spacing, y1)
rightOrigin = list(x2 + width + spacing, y1)
maxNum = 0
foreach(instName cv~>instances~>name
if(rexMatchp("Dummy*" instName)
then
num = atoi(substring(instName strlen("Dummy")+1))
if(num > maxNum then
maxNum = num
);if
);if
);foreach
newName = sprintf(str "Dummy%d" (maxNum+1))
leftInst = dbCreateInst(cv masterCv newName leftOrigin "R0" 1)
dbCopyProp(targetInst leftInst)
newName = sprintf(str "Dummy%d" (maxNum+2))
rightInst = dbCreateInst(cv masterCv newName rightOrigin "R0" 1)
dbCopyProp(targetInst rightInst)
);let
let((selected targetInst bBox origin left right top bottom x1 y1 x2 width height dummyLib dummyCell masterCv spacing leftOrigin rightOrigin maxNum num newName leftInst rightInst)
targetInst = car(baabPattern)
bBox = targetInst~>bBox
origin = targetInst~>xy
left = caadr(bBox)
right = caar(bBox)
top = cadadr(bBox)
bottom = cadar(bBox)
x1 = car(origin)
y1 = cadr(origin)
x2 = caar(last(baabPattern)~>xy)
width = left - right
height = top - bottom
dummyLib = targetInst~>libName
dummyCell = targetInst~>cellName
masterCv = dbOpenCellViewByType(dummyLib dummyCell "layout")
spacing = x
leftOrigin = list(x1 - width - spacing, y1)
rightOrigin = list(x2 + width + spacing, y1)
maxNum = 0
foreach(instName cv~>instances~>name
if(rexMatchp("Dummy*" instName)
then
num = atoi(substring(instName strlen("Dummy")+1))
if(num > maxNum then
maxNum = num
);if
);if
);foreach
newName = sprintf(str "Dummy%d" (maxNum+1))
leftInst = dbCreateInst(cv masterCv newName leftOrigin "R0" 1)
dbCopyProp(targetInst leftInst)
newName = sprintf(str "Dummy%d" (maxNum+2))
rightInst = dbCreateInst(cv masterCv newName rightOrigin "R0" 1)
dbCopyProp(targetInst rightInst)
);let
);let
);procedure
hiSetBindKey("Layout" "Ctrl<Key>2" "arrangeMultiplierDevicesAddDummy(2 2)")
PS:函数中的x代表器件的左右间距,y代表器件的上下间距,以(2 2)举例!!
测试该脚本:

将该脚本写入.cdsinit文件自动load
在桌面打开Terminal,输入:
cd
gedit .cdsinin
在.cdsinit文件内,load脚本的全路径:
load("/home/~~/~~/~~/arrangeMultiplierDevicesAddDummy.il")
如下:


浙公网安备 33010602011771号