Skill语言学习_1 🦽

使用Skill语言将不同层的两条PathSeg连通并打孔

image-20260205101202920

Skill版本:

getSkillVersion
"SKILL35.00"
> 

学习参考:

https://mp.weixin.qq.com/s/85i0Y4TsJZYy4Ixz-e4Yug

[ Skill ] Cadence Skill 语言入门 - YEUNGCHIE - 博客园

脚本思路:

1、查询所选Path的层属性和首尾坐标;

2、计算不同层Path的相交点(x y);

3、延长各Path至相交点;

4、在相交点打孔。

设计操作:

1、查询所选Path的层属性和首尾坐标;

image-20260205102126940

geGetSelSet()~>??

((db:0x169fa1a8 cellView db:0x169fc09a objType "pathSeg"
	prop nil bBox 
	((62.965 7.89) 
	    (65.62 8.27)
	) children
	nil groupMembers nil isAnyInst nil
	isShape t matchPoints nil net
	nil parent nil pin nil
	purpose "drawing" textDisplays nil assocTextDisplays
	nil markers nil figGroup nil
	isUnshielded nil shieldedNet1 nil shieldedNet2
	nil layerName "M1" layerNum 61
	lpp 
	("M1" "drawing") connRoutes nil routeStatus
	"normal" width 0.38 beginExt 0.0
	endExt 0.0 beginPt 
	(62.965 8.08) endPt
	(65.62 8.08) boundary 
	((62.965 7.89) 
	    (62.965 8.27) 
	    (65.62 8.27) 
	    (65.62 7.89)
	) beginStyle "truncate"
	endStyle "truncate" topology "none" isOrthogonal
	t route db:0x169fbd29
    ) 
    (db:0x169fa1a9 cellView db:0x169fc09a objType "pathSeg"
	prop nil bBox 
	((67.085 9.185) 
	    (67.465 10.855)
	) children
	nil groupMembers nil isAnyInst nil
	isShape t matchPoints nil net
	nil parent nil pin nil
	purpose "drawing" textDisplays nil assocTextDisplays
	nil markers nil figGroup nil
	isUnshielded nil shieldedNet1 nil shieldedNet2
	nil layerName "M2" layerNum 62
	lpp 
	("M2" "drawing") connRoutes nil routeStatus
	"normal" width 0.38 beginExt 0.0
	endExt 0.0 beginPt 
	(67.275 9.185) endPt
	(67.275 10.855) boundary 
	((67.085 9.185) 
	    (67.085 10.855) 
	    (67.465 10.855) 
	    (67.465 9.185)
	) beginStyle "truncate"
	endStyle "truncate" topology "none" isOrthogonal
	t route db:0x169fbd28
    )
)
> 
通过仔细观察可以找到我们所需要的关键信息:

(1)Path的ID:(db:0x169fa1a8)和(db:0x169fa1a9);(type:list)

(2)Path的layerName :("M1")和("M2");(type:list)

(3)Path的beginPt和endPt:((62.965 8.08) ),((65.62 8.08))和 ((67.275 9.185) ),((67.275 10.855));(type:list)

通过代码将上述观察到的关键信息提取出来:
selSet = geGetSelSet()
path1 = car(selSet) 
path2 = cadr(selSet) 
layer1 = path1~>layerName
layer2 = path2~>layerName
pts1 = list(path1~>beginPt path1~>endPt)
pts2 = list(path2~>beginPt path2~>endPt)

(db:0x169fa1a8 db:0x169fa1a9)
Debug 5> 
db:0x169fa1a8
Debug 5> 
db:0x169fa1a9
Debug 5> 
"M1"
Debug 5> 
"M2"
Debug 5> 
((62.965 8.08) 
    (65.62 8.08)
)
Debug 5> 
((67.275 9.185) 
    (67.275 10.855)
)
Debug 5> 

2、计算不同层Path的相交点(x y);

将Path的首位坐标分别提取数值:
x1 = caar(pts1) 			
y1 = cadar(pts1)
x2 = caar(cdr(pts1)) 		
y2 = cadar(cdr(pts1))
x3 = caar(pts2)
y3 = cadar(pts2)
x4 = caar(cdr(pts2))
y4 = cadar(cdr(pts2))
基于向量叉积和参数方程的原理,通过判断两条线段是否相交,并计算出交点坐标:
denom = (y4 - y3)*(x2 - x1) - (x4 - x3)*(y2 - y1)
if( denom == 0.0 
then
	println("Error:2 Path no X.") 
else
	ua = ((x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3)) / denom
	ub = ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3)) / denom
	x = x1 + ua * (x2 - x1)
	y = y1 + ua * (y2 - y1)
	list1 = list(x y) 
)

3、延长各Path至相交点;

计算延长后的各Path首位坐标:
a1 = min(x1 x2 x)
b1 = min(y1 y2 y)
a2 = max(x1 x2 x)
b2 = max(y1 y2 y)
a3 = min(x3 x4 x)
b3 = min(y3 y4 y)
a4 = max(x3 x4 x)
b4 = max(y3 y4 y)
point11 = list(a1 b1)
point12 = list(a2 b2)
point22 = list(a3 b3)
point21 = list(a4 b4)
延长各Path至相交点:
path1~>beginPt = point11
path1~>endPt = point12

path2~>beginPt = point21
path2~>endPt = point22
使用不同方向的Path验证算法:

image-20260205112325309

出现问题:

image-20260205112405865

分析问题:以第二种情况为例
path1的原始:

beginPt为(72.915 23.64);

endPt为(70.26 23.64) ;

计算后:

交叉点为(74.11 23.64);

point11为(70.26 23.64) ;

point12为(74.11 23.64);

使用延长算法:
path1~>beginPt = point11

由于此时path1的endPt的坐标为(70.26 23.64) ;

算法的BegingPt设置会失去作用;

此时beginPt依旧为(72.915 23.64);

path1~>endPt = point12

将endPt更新为(74.11 23.64);

延长算法后Path1坐标:

beginPt为(72.915 23.64);

endPt为(74.11 23.64);

造成延长效果的失败。

修改算法:
path1~>beginPt = point11
path1~>endPt = point12
path1~>beginPt = point11

path2~>beginPt = point21
path2~>endPt = point22
path2~>beginPt = point21
再次使用不同方向的Path验证算法:

image-20260205112325309

结果符合预想:

image-20260205141950055

更多不同位置的Path验证算法:

image-20260205142152826

4、在相交点打孔。

确定打孔层次;
sort1 = sort( list(layer2 layer1) 'alphalessp)		;基于alphalessp对layerName进行标准化排序
if(sort1 == list("M1" "M2")
	viaType = "M2_M1"
)
if(sort1 == list("M2" "M3")
	viaType = "M3_M2"
) 
调用交叉点坐标,使用dbCreateVia函数实现打孔功能;
cvID = geGetEditCellView()		; 获取当前编辑的版图视图
tech = techGetTechFile(cvID)		;获取工艺技术文件
viaDefId = techFindViaDefByName(tech viaType)		;查找指定的过孔定义
viaParams = list(list("cutRows" 2) list("cutColumns" 1))		;设置过孔参数:2行1列
dbCreateVia(cvID viaDefId list1 "R0" viaParams)		;创建过孔
使用不同层进行测试;

image-20260205143804010

整合上述功能:

;主程序
procedure(createViaAtPathIntersection()
    let((selSet path1 path2 layer1 layer2)
        selSet = geGetSelSet()
        when(length(selSet) != 2
            println("Error:Please chose 2 Path.")
        )
        path1 = car(selSet) 
        path2 = cadr(selSet) 
        
        layer1 = path1~>layerName
        layer2 = path2~>layerName
        
     	pts1 = list(path1~>beginPt path1~>endPt)
       	pts2 = list(path2~>beginPt path2~>endPt)
		

        intersectPt = calculateIntersection(pts1 pts2)
        when( intersectPt == nil
            println("Error:2 Path no X.")
            return()
		)

		CreateVia(list1)	;调用打孔模块打孔
		
		path1~>beginPt = point11
		path1~>endPt = point12
		path1~>beginPt = point11
	
		path2~>beginPt = point21
		path2~>endPt = point22
		path2~>beginPt = point21
    )
)
;辅助计算交叉点和Path拉伸坐标点
procedure(calculateIntersection(pts1 pts2)
    let((x1 y1 x2 y2 x3 y3 x4 y4 denom ua ub x y)
		x1 = caar(pts1) 			
		y1 = cadar(pts1)
		x2 = caar(cdr(pts1)) 		
		y2 = cadar(cdr(pts1))
		x3 = caar(pts2)
		y3 = cadar(pts2)
        x4 = caar(cdr(pts2))
		y4 = cadar(cdr(pts2))
        
        denom = (y4 - y3)*(x2 - x1) - (x4 - x3)*(y2 - y1)
        if( denom == 0.0 
		then
			println("Error:2 Path no X.") 
		else
			ua = ((x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3)) / denom
	        ub = ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3)) / denom
	        x = x1 + ua * (x2 - x1)
	        y = y1 + ua * (y2 - y1)
        	list1 = list(x y) 
		
			a1 = min(x1 x2 x)
			b1 = min(y1 y2 y)
			a2 = max(x1 x2 x)
			b2 = max(y1 y2 y)
			a3 = min(x3 x4 x)
			b3 = min(y3 y4 y)
			a4 = max(x3 x4 x)
			b4 = max(y3 y4 y)
			point11 = list(a1 b1)
			point12 = list(a2 b2)
			point22 = list(a3 b3)
			point21 = list(a4 b4)
		) 
	)
)
;辅助打孔模块
procedure(CreateVia(list1)
	let((cvID tech visDefId viaParams newVia)
	cvID = geGetEditCellView()
	tech = techGetTechFile(cvID)
	sort1 = sort( list(layer2 layer1) 'alphalessp)
	if(sort1 == list("M1" "M2")
		viaType = "M2_M1"
	)
	if(sort1 == list("M2" "M3")
		viaType = "M3_M2"
	) 
	viaDefId = techFindViaDefByName(tech viaType)
	viaParams = list(list("cutRows" 2) list("cutColumns" 1))
	dbCreateVia(cvID viaDefId list1 "R0" viaParams)
	)
)
;将该函数写为快捷键
hiSetBindKey("Layout" "Ctrl<Key>1" "createViaAtPathIntersection()")

将该脚本写入.cdsinit文件自动load

在桌面打开Terminal,输入:
cd
gedit .cdsinin
在.cdsinit文件内,load脚本的全路径:
load("/home/work/project/xian/createViaAtPathIntersection.il")
如下:

image-20260205144805588

PS:上述中的Path均为Virtuoso Layout中使用Wire功能绘制的连接线🎉🎉🎉

综上完成了不同Path连通并打孔的功能🎉🎉🎉

posted @ 2026-02-05 15:55  StupidMonkey19  阅读(12)  评论(0)    收藏  举报