length2

本文介绍了Oracle数据库中用于计算字符串长度的不同函数,包括LENGTH、LENGTHB、LENGTHC、LENGTH2和LENGTH4,并通过实例展示了它们如何处理不同类型的字符。

LENGTHC(c1).LENGTH2(c1).LENGTH4(c1)
【功能】返回字符串的长度;
【说明】多字节符(汉字、全角符等),按1个字符计算
【参数】C1 字符串
【返回】数值型
【示例】
SQL> select length('高乾竞'),length('北京市海锭区'),length('北京TO_CHAR') from dual;
返回:3,6,9
Oracle中的字符函数中,有一类函数是求字符长度的函数,length、lengthB、lengthC、length2、length4几个函数中比较常用的是length、lengthB。


他们的含义分别是:
Length函数返回字符的个数,使用定义是给定的字符集来计算字符的个数
LENGTHB给出该字符串的byte
LENGTHC使用纯Unicode
LENGTH2使用UCS2
LENGTH4使用UCS4
下面使一些例子:
Select length('你好') from dual;  
返回:2
Select lengthB('你好'),lengthC('你好'),length2('你好'), length4('你好')  from dual; 
返回:4,2,2,2

解释如下函数代码: def metalLink(tkcell,device,linkW=2,linkS=1,location=3,offset=['center',0],tkW=None,padW=None,padL=None,pitch=None,pad1offset=None,**pinset): '''把device放到tkcell中,并根据设置连线''' '''PADcell必须用pad画的, 否则需设置padW等参数''' '''location指device放到哪个PAD的右边, offset有3个值,center, up,down, 指放到pad哪个位置,默认为center,放到pad中间,up指放pad上面,大小写不敏感''' '''offset为列表, 当设置为center时, value一定是0, 当设置为非center时, eg offset=['up',10]指放到pad上面,离pad 10um''' '''如果把pin定义成字典, 必须提前定义, 参数前面加**来引用, 或者直接写成,G=11,D=12,S=11...''' '''写成字典形式: pinset={'G':12,'D':12,'S':11},引用 metalLink2(....,**pinset)''' pass metalCD=3 #转向PAD时的metal CD, device在pad上或下的时候会用到 metalCD2=4 #接触pad的metal CD metalS=3 #当metal会穿过PAD时,自动隔离的距离 pad_cell=gdspy.current_library.cell_dict.get(tkcell,tkcell) tkW=pad_cell.tkW if tkW==None else tkW padW=pad_cell.padW if padW==None else padW padL=pad_cell.padL if padL==None else padL pitch=pad_cell.pitch if pitch==None else pitch pad1offset=pad_cell.pad1offset if pad1offset==None else pad1offset metal2edge=(tkW-padW)/2-linkS-linkW #metal到edge的距离 d_cell=gdspy.current_library.cell_dict.get(device,device) ''' put in device ''' offset0=offset[0] if offset0.lower()=='center': d_cell.align(None,cc,pad_cell,cl,(location-1)*pitch+pad1offset+padL+(pitch-padL)/2,0) elif offset0.lower()=='up': bbox1=pad_cell.get_bounding_box() x1=bbox1[0][0] y1=bbox1[0][1] x_cc=(location-1)*pitch+pad1offset+padL+(pitch-padL)/2-d_cell.xCoord(None,cc)+x1 y_cc=tkW+offset[1]+d_cell.Width/2-d_cell.yCoord(None,cc)+y1 d_cell.insert(pad_cell,origin=(x_cc,y_cc)) # d_cell.align(None,cc,pad_cell,cl,(location-1)*pitch+pad1offset+padL+(pitch-padL)/2,tkW/2+d_cell.Width/2+offset[offset0]) elif offset0.lower()=='down': bbox1=pad_cell.get_bounding_box() x1=bbox1[0][0] y1=bbox1[0][1] x_cc=(location-1)*pitch+pad1offset+padL+(pitch-padL)/2-d_cell.xCoord(None,cc)+x1 y_cc=-(d_cell.Width/2+d_cell.yCoord(None,cc))-offset[1]+y1 d_cell.insert(pad_cell,origin=(x_cc,y_cc)) # d_cell.align(None,cc,pad_cell,cl,(location-1)*pitch+pad1offset+padL+(pitch-padL)/2,-(tkW/2+d_cell.Width/2+offset[offset0])) '''center 连线,(CD,layer,dir,loaction)''' pin_dict=d_cell.pin x1=d_cell.originX(pad_cell,'ll') y1=d_cell.originY(pad_cell,'ll') if offset0.lower()=='center': for pin1 in pin_dict: p_start=(pin_dict[pin1][3][0]+x1,pin_dict[pin1][3][1]+y1) Layer1=pin_dict[pin1][1] if pin_dict[pin1][2]=='+x': #右引线 path1=gdspy.Path(pin_dict[pin1][0],p_start) length1=location*pitch+pad1offset-p_start[0]+2 if length1>0: Layer1=pin_dict[pin1][1] path1.segment(length1,'+x',layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='-x': #左引线 path1=gdspy.Path(pin_dict[pin1][0],p_start) length1=p_start[0]-((location-1)*pitch+pad1offset+padL)+2 if length1>0: Layer1=pin_dict[pin1][1] path1.segment(length1,'-x',layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='+y': #上引线 Length1=tkW+pad_cell.yCoord(None,lc)-metal2edge-linkW/2-p_start[1] length3=(tkW-padW)/2-metal2edge-linkW/2+2 if pin1 in pinset: if pinset[pin1]>location: #device在PAD左边 Length2=(pinset[pin1]-1)*pitch+pad1offset+padL/2-p_start[0] turn1=-linkW/pin_dict[pin1][0] turn2=-metalCD2/pin_dict[pin1][0] else: #device在PAD右边 Length2=p_start[0]-((pinset[pin1]-1)*pitch+pad1offset+padL/2) turn1=linkW/pin_dict[pin1][0] turn2=metalCD2/pin_dict[pin1][0] length=[Length1,Length2,length3] turn=[turn1,turn2] path1=gdspy.L1Path(p_start,'+y',pin_dict[pin1][0],length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='-y': #下引线 Length1=p_start[1]-(metal2edge+linkW/2)-pad_cell.yCoord(None,lc) length3=(tkW-padW)/2-metal2edge-linkW/2+2 if pin1 in pinset: if pinset[pin1]>location: #device在PAD左边 Length2=(pinset[pin1]-1)*pitch+pad1offset+padL/2-p_start[0] turn1=linkW/pin_dict[pin1][0] turn2=metalCD2/pin_dict[pin1][0] else: #device在PAD右边 Length2=p_start[0]-((pinset[pin1]-1)*pitch+pad1offset+padL/2) turn1=-linkW/pin_dict[pin1][0] turn2=-metalCD2/pin_dict[pin1][0] length=[Length1,Length2,length3] turn=[turn1,turn2] path1=gdspy.L1Path(p_start,'-y',pin_dict[pin1][0],length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) return pad_cell '''device放到pad上面''' if offset0.lower()=='up': for pin1 in pin_dict: p_start=(pin_dict[pin1][3][0]+x1,pin_dict[pin1][3][1]+y1) Layer1=pin_dict[pin1][1] if pin_dict[pin1][2]=='+x': #右引线 if pin1 in pinset: pad_num=pinset[pin1] #读取pin对应的PADnumber length1=(pad_num-1)*pitch+pad1offset-p_start[0]+2 #右边pin脚到PAD edge的距离 length2=p_start[1]-tkW+(tkW-padW)/2+2 #上面到PAD edge的距离 if length1>0: #pin脚在pad左边 length=[length1+metalCD/2,length2] turn=[-metalCD/pin_dict[pin1][0]] path1=gdspy.L1Path(p_start,'+x',pin_dict[pin1][0],length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif abs(length1)<=padL-metalCD: #pin脚正好落在PAD上方 p_start=(p_start[0]+metalCD/2,p_start[1]+pin_dict[pin1][0]/2) path1=gdspy.Path(metalCD,p_start) path1.segment(length2+pin_dict[pin1][0]/2,'-y',layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif abs(length1)>padL-metalCD and abs(length1)<=pitch-metalCD-metalS: p_start=(p_start[0]+metalCD/2,p_start[1]+pin_dict[pin1][0]/2) length3=p_start[0]-((pad_num-1)*pitch+pad1offset+padL) length=[length2+pin_dict[pin1][0]/2+metalCD2/2,length3] turn=[-metalCD2/metalCD] path1=gdspy.L1Path(p_start,'-y',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) else: p_start=(p_start[0]+metalCD/2,p_start[1]+pin_dict[pin1][0]/2) length3=p_start[0]-((pad_num-1)*pitch+pad1offset+padL)+metalCD/2 length4=metalS+metalCD/2 length=[length2+pin_dict[pin1][0]/2-metalS-metalCD/2,length3,length4] turn=[-1,1] path1=gdspy.L1Path(p_start,'-y',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='-x': #左引线 if pin1 in pinset: pad_num=pinset[pin1] length1=p_start[0]-((pad_num-1)*pitch+pad1offset+padL)+2 #左边pin脚到PAD edge的距离 length2=p_start[1]-tkW+(tkW-padW)/2+2 #上面到PAD edge的距离 if length1>0: #pin脚在pad左边 length=[length1+metalCD/2,length2] turn=[metalCD/pin_dict[pin1][0]] path1=gdspy.L1Path(p_start,'-x',pin_dict[pin1][0],length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif abs(length1)<=padL-metalCD: #pin脚正好落在PAD上方 p_start=(p_start[0]-metalCD/2,p_start[1]+pin_dict[pin1][0]/2) path1=gdspy.Path(metalCD,p_start) path1.segment(length2+pin_dict[pin1][0]/2,'-y',layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif abs(length1)>padL-metalCD and abs(length1)<=pitch-metalCD-metalS: p_start=(p_start[0]-metalCD/2,p_start[1]+pin_dict[pin1][0]/2) length3=((pad_num-1)*pitch+pad1offset)-p_start[0] length=[length2+pin_dict[pin1][0]/2+metalCD2/2,length3] turn=[metalCD2/metalCD] path1=gdspy.L1Path(p_start,'-y',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) else: p_start=(p_start[0]-metalCD/2,p_start[1]+pin_dict[pin1][0]/2) length3=((pad_num-1)*pitch+pad1offset)-p_start[0]+metalCD/2 length4=metalS+metalCD/2 length=[length2+pin_dict[pin1][0]/2-metalS-metalCD/2,length3,length4] turn=[1,-1] path1=gdspy.L1Path(p_start,'-y',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='-y': #下引线 Length1=p_start[1]-(metal2edge+linkW/2) length3=(tkW-padW)/2-metal2edge-linkW/2+2 if pin1 in pinset: if pinset[pin1]>location: #device在PAD左边 Length2=(pinset[pin1]-1)*pitch+pad1offset+padL/2-p_start[0] turn1=linkW/pin_dict[pin1][0] turn2=metalCD2/pin_dict[pin1][0] else: #device在PAD右边 Length2=p_start[0]-((pinset[pin1]-1)*pitch+pad1offset+padL/2) turn1=-linkW/pin_dict[pin1][0] turn2=-metalCD2/pin_dict[pin1][0] length=[Length1,Length2,length3] turn=[turn1,turn2] path1=gdspy.L1Path(p_start,'-y',pin_dict[pin1][0],length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='+y': #上引线 if pin1 in pinset: pad_num=pinset[pin1] if pad_num>location: p_start=(p_start[0]-pin_dict[pin1][0]/2,p_start[1]+metalCD/2) if (pad_num-1)*pitch+pad1offset>=d_cell.xCoord(pad_cell,cr): #如果PAD在device右边 length1=(pad_num-1)*pitch+pad1offset-p_start[0]+metalCD/2 #pin脚到PAD edge的距离 length2=p_start[1]-tkW+(tkW-padW)/2 #上面到PAD edge的距离 length=[length1,length2] turn=[-1] path1=gdspy.L1Path(p_start,'+x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif (pad_num-1)*pitch+pad1offset<d_cell.xCoord(pad_cell,cr) and (pad_num-1)*pitch+pad1offset+padL>=d_cell.xCoord(pad_cell,cr): #PAD在device下面,但没跨过PAD length1=d_cell.xCoord(pad_cell,cr)-p_start[0]+metalCD+metalS+metalCD/2 #metal延伸到device右边, 并keep metalS length2=p_start[1]-tkW+(tkW-padW)/2 #上面到PAD的距离 length=[length1,length2] turn=[-1] path1=gdspy.L1Path(p_start,'+x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif (pad_num-1)*pitch+pad1offset<d_cell.xCoord(pad_cell,cr) and (pad_num-1)*pitch+pad1offset+pitch-metalS>d_cell.xCoord(pad_cell,cr): #PAD在device下面,但没跨过PAD length1=d_cell.xCoord(pad_cell,cr)-p_start[0]+metalCD+metalS+metalCD/2 #metal延伸到device右边, 并keep metalS length2=p_start[1]-tkW+(tkW-padW)/2+metalCD/2 #上面到PAD的距离 length3=d_cell.xCoord(pad_cell,cr)+metalCD+metalS+metalCD/2-((pad_num-1)*pitch+pad1offset+padL) #转弯与pad相连 length=[length1,length2,length3] turn=[-1,-1] path1=gdspy.L1Path(p_start,'+x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) else: length1=d_cell.xCoord(pad_cell,cr)-p_start[0]+metalCD+metalS+metalCD/2 #metal延伸到device右边, 并keep metalS length2=p_start[1]-tkW+(tkW-padW)/2-metalS-metalCD/2 #上面到PAD的距离 length3=d_cell.xCoord(pad_cell,cr)+metalCD+metalS+metalCD/2-((pad_num-1)*pitch+pad1offset+padL)+metalCD/2 #转弯与pad相连 length4=metalS+metalCD/2 length=[length1,length2,length3,length4] turn=[-1,-1,1] path1=gdspy.L1Path(p_start,'+x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) if pad_num<location: p_start=(p_start[0]+pin_dict[pin1][0]/2,p_start[1]+metalCD/2) if (pad_num-1)*pitch+pad1offset+padL<=d_cell.xCoord(pad_cell,cl): #如果PAD在device左边 length1=p_start[0]-((pad_num-1)*pitch+pad1offset+padL)+metalCD/2 #左边pin脚到PAD edge的距离 length2=p_start[1]-tkW+(tkW-padW)/2 #上面到PAD edge的距离 length=[length1,length2] turn=[1] path1=gdspy.L1Path(p_start,'-x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif (pad_num-1)*pitch+pad1offset+padL>d_cell.xCoord(pad_cell,cl) and (pad_num-1)*pitch+pad1offset<=d_cell.xCoord(pad_cell,cl): #PAD在device下面,但没跨过PAD length1=p_start[0]-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2 #左边pin脚到PAD edge的距离 length2=p_start[1]-tkW+(tkW-padW)/2 #上面到PAD的距离 length=[length1,length2] turn=[1] path1=gdspy.L1Path(p_start,'-x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif (pad_num-1)*pitch+pad1offset>d_cell.xCoord(pad_cell,cl) and (pad_num-1)*pitch+pad1offset-(pitch-padL)+metalS<=d_cell.xCoord(pad_cell,cl): #PAD在device下面,但没跨过PAD length1=p_start[0]-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2 #左边pin脚到PAD edge的距离 length2=p_start[1]-tkW+(tkW-padW)/2+metalCD/2 #上面到PAD的距离 length3=(pad_num-1)*pitch+pad1offset-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2 #转弯与pad相连 length=[length1,length2,length3] turn=[1,1] path1=gdspy.L1Path(p_start,'-x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) else: length1=p_start[0]-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2 #左边pin脚到PAD edge的距离 length2=p_start[1]-tkW+(tkW-padW)/2-metalS-metalCD/2 #上面到PAD的距离 length3=(pad_num-1)*pitch+pad1offset-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2+metalCD/2 #转弯与pad相连 length4=metalS+metalCD/2 length=[length1,length2,length3,length4] turn=[1,1,-1] path1=gdspy.L1Path(p_start,'-x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) return pad_cell '''device放到pad下面''' if offset0.lower()=='down': for pin1 in pin_dict: p_start=(pin_dict[pin1][3][0]+x1,pin_dict[pin1][3][1]+y1) Layer1=pin_dict[pin1][1] if pin_dict[pin1][2]=='+x': #右引线 if pin1 in pinset: pad_num=pinset[pin1] length1=(pad_num-1)*pitch+pad1offset-p_start[0] #右边pin脚到PAD edge的距离 length2=abs(p_start[1])+(tkW-padW)/2 #上面到PAD edge的距离 if length1>0: #pin脚在pad左边 length=[length1+metalCD/2,length2] turn=[metalCD/pin_dict[pin1][0]] path1=gdspy.L1Path(p_start,'+x',pin_dict[pin1][0],length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif abs(length1)<=padL-metalCD: p_start=(p_start[0]+metalCD/2,p_start[1]-pin_dict[pin1][0]/2) path1=gdspy.Path(metalCD,p_start) path1.segment(length2+pin_dict[pin1][0]/2,'+y',layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif abs(length1)>padL-metalCD and abs(length1)<=pitch-metalCD-metalS: p_start=(p_start[0]+metalCD/2,p_start[1]-pin_dict[pin1][0]/2) length3=p_start[0]-((pad_num-1)*pitch+pad1offset+padL) length=[length2+pin_dict[pin1][0]/2+metalCD2/2,length3] turn=[metalCD2/metalCD] path1=gdspy.L1Path(p_start,'+y',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) else: p_start=(p_start[0]+metalCD/2,p_start[1]-pin_dict[pin1][0]/2) length3=p_start[0]-((pad_num-1)*pitch+pad1offset+padL)+metalCD/2 length4=metalS+metalCD/2 length=[length2+pin_dict[pin1][0]/2-metalS-metalCD/2,length3,length4] turn=[1,-1] path1=gdspy.L1Path(p_start,'+y',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='-x': #左引线 if pin1 in pinset: pad_num=pinset[pin1] length1=p_start[0]-((pad_num-1)*pitch+pad1offset+padL) #左边pin脚到PAD edge的距离 length2=abs(p_start[1])+(tkW-padW)/2 #上面到PAD edge的距离 if length1>0: #pin脚在pad左边 length=[length1+metalCD/2,length2] turn=[-metalCD/pin_dict[pin1][0]] path1=gdspy.L1Path(p_start,'-x',pin_dict[pin1][0],length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif abs(length1)<=padL-metalCD: p_start=(p_start[0]-metalCD/2,p_start[1]-pin_dict[pin1][0]/2) path1=gdspy.Path(metalCD,p_start) path1.segment(length2+pin_dict[pin1][0]/2,'+y',layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif abs(length1)>padL-metalCD and abs(length1)<=pitch-metalCD-metalS: p_start=(p_start[0]-metalCD/2,p_start[1]-pin_dict[pin1][0]/2) length3=((pad_num-1)*pitch+pad1offset)-p_start[0] length=[length2+pin_dict[pin1][0]/2+metalCD2/2,length3] turn=[-metalCD2/metalCD] path1=gdspy.L1Path(p_start,'+y',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) else: p_start=(p_start[0]-metalCD/2,p_start[1]-pin_dict[pin1][0]/2) length3=((pad_num-1)*pitch+pad1offset)-p_start[0]+metalCD/2 length4=metalS+metalCD/2 length=[length2+pin_dict[pin1][0]/2-metalS-metalCD/2,length3,length4] turn=[-1,1] path1=gdspy.L1Path(p_start,'+y',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='-y': #下引线 if pin1 in pinset: pad_num=pinset[pin1] if pad_num>location: p_start=(p_start[0]-pin_dict[pin1][0]/2,p_start[1]-metalCD/2) if (pad_num-1)*pitch+pad1offset>=d_cell.xCoord(pad_cell,cr): #如果PAD在device右边 length1=(pad_num-1)*pitch+pad1offset-p_start[0]+metalCD/2 #pin脚到PAD edge的距离 length2=d_cell.Width+metalCD/2+offset[1]+(tkW-padW)/2 #上面到PAD edge的距离 length=[length1,length2] turn=[1] path1=gdspy.L1Path(p_start,'+x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif (pad_num-1)*pitch+pad1offset<d_cell.xCoord(pad_cell,cr) and (pad_num-1)*pitch+pad1offset+padL>=d_cell.xCoord(pad_cell,cr): #PAD在device下面,但没跨过PAD length1=d_cell.xCoord(pad_cell,cr)-p_start[0]+metalCD+metalS+metalCD/2 #metal延伸到device右边, 并keep metalS length2=d_cell.Width+metalCD/2+offset[1]+(tkW-padW)/2 #上面到PAD edge的距离 length=[length1,length2] turn=[1] path1=gdspy.L1Path(p_start,'+x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif (pad_num-1)*pitch+pad1offset<d_cell.xCoord(pad_cell,cr) and (pad_num-1)*pitch+pad1offset+pitch-metalS>d_cell.xCoord(pad_cell,cr): #PAD在device下面,但没跨过PAD length1=d_cell.xCoord(pad_cell,cr)-p_start[0]+metalCD+metalS+metalCD/2 #metal延伸到device右边, 并keep metalS length2=d_cell.Width+metalCD/2+offset[1]+(tkW-padW)/2 +metalCD/2 length3=d_cell.xCoord(pad_cell,cr)+metalCD+metalS+metalCD/2-((pad_num-1)*pitch+pad1offset+padL) #转弯与pad相连 length=[length1,length2,length3] turn=[1,1] path1=gdspy.L1Path(p_start,'+x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) else: length1=d_cell.xCoord(pad_cell,cr)-p_start[0]+metalCD+metalS+metalCD/2 #metal延伸到device右边, 并keep metalS length2=d_cell.Width+metalCD/2+offset[1]+(tkW-padW)/2-metalS-metalCD/2 length3=d_cell.xCoord(pad_cell,cr)+metalCD+metalS+metalCD/2-((pad_num-1)*pitch+pad1offset+padL)+metalCD/2 #转弯与pad相连 length4=metalS+metalCD/2 length=[length1,length2,length3,length4] turn=[1,1,-1] path1=gdspy.L1Path(p_start,'+x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) if pad_num<location: p_start=(p_start[0]+pin_dict[pin1][0]/2,p_start[1]-metalCD/2) if (pad_num-1)*pitch+pad1offset+padL<=d_cell.xCoord(pad_cell,cl): #如果PAD在device左边 length1=p_start[0]-((pad_num-1)*pitch+pad1offset+padL)+metalCD/2 #左边pin脚到PAD edge的距离 length2=d_cell.Width+metalCD/2+offset[1]+(tkW-padW)/2 length=[length1,length2] turn=[-1] path1=gdspy.L1Path(p_start,'-x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif (pad_num-1)*pitch+pad1offset+padL>d_cell.xCoord(pad_cell,cl) and (pad_num-1)*pitch+pad1offset<=d_cell.xCoord(pad_cell,cl): #PAD在device下面,但没跨过PAD length1=p_start[0]-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2 #左边pin脚到PAD edge的距离 length2=d_cell.Width+metalCD/2+offset[1]+(tkW-padW)/2 #上面到PAD edge的距离 length=[length1,length2] turn=[-1] path1=gdspy.L1Path(p_start,'-x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) elif (pad_num-1)*pitch+pad1offset>d_cell.xCoord(pad_cell,cl) and (pad_num-1)*pitch+pad1offset-(pitch-padL)+metalS<=d_cell.xCoord(pad_cell,cl): #PAD在device下面,但没跨过PAD length1=p_start[0]-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2 #左边pin脚到PAD edge的距离 length2=d_cell.Width+metalCD/2+offset[1]+(tkW-padW)/2 +metalCD/2 length3=(pad_num-1)*pitch+pad1offset-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2 #转弯与pad相连 length=[length1,length2,length3] turn=[-1,-1] path1=gdspy.L1Path(p_start,'-x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) else: length1=p_start[0]-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2 #左边pin脚到PAD edge的距离 length2=d_cell.Width+metalCD/2+offset[1]+(tkW-padW)/2-metalS-metalCD/2 length3=(pad_num-1)*pitch+pad1offset-d_cell.xCoord(pad_cell,cl)+metalCD+metalS+metalCD/2+metalCD/2 #转弯与pad相连 length4=metalS+metalCD/2 length=[length1,length2,length3,length4] turn=[-1,-1,1] path1=gdspy.L1Path(p_start,'-x',metalCD,length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) if pin_dict[pin1][2]=='+y': #上引线 Length1=tkW-metal2edge-linkW/2-p_start[1] length3=(tkW-padW)/2-metal2edge-linkW/2 if pin1 in pinset: if pinset[pin1]>location: #device在PAD左边 Length2=(pinset[pin1]-1)*pitch+pad1offset+padL/2-p_start[0] turn1=-linkW/pin_dict[pin1][0] turn2=-metalCD2/pin_dict[pin1][0] else: #device在PAD右边 Length2=p_start[0]-((pinset[pin1]-1)*pitch+pad1offset+padL/2) turn1=linkW/pin_dict[pin1][0] turn2=metalCD2/pin_dict[pin1][0] length=[Length1,Length2,length3] turn=[turn1,turn2] path1=gdspy.L1Path(p_start,'+y',pin_dict[pin1][0],length,turn,layer=gdsNo(Layer1),datatype=dtype(Layer1)) pad_cell.add(path1) return pad_cell
最新发布
10-21
<think>我们有一个函数 `metalLink`,它用于在GDSII布局中放置一个器件(device)并连接其引脚到指定的焊盘(PAD)。函数使用了gdspy库(用于创建GDSII文件的Python库)。我们将逐步解释这个函数。 函数参数: tkcell: 目标单元格(通常是一个PAD单元格),可以是一个cell对象或cell名字。 device: 要放置的器件,可以是一个cell对象或cell名字。 linkW: 连线宽度,默认为2。 linkS: 连线与边缘的间距,默认为1。 location: 指定器件放在哪个PAD的右边(焊盘编号),默认为3。 offset: 一个列表,指定器件相对于PAD的位置。默认为['center',0]。 offset[0]可以是'center', 'up', 'down'(不区分大小写),offset[1]是距离(当不是center时)。 tkW, padW, padL, pitch, pad1offset: 可选参数,用于覆盖从tkcell中获取的默认值。 pinset: 一个字典,指定器件的哪个引脚连接到哪个焊盘(焊盘编号)。例如,pinset={'G':12, 'D':12, 'S':11}。 函数内部: 1. 设置了一些常量(metalCD, metalCD2, metalS)用于连线。 2. 获取目标单元格(pad_cell)和器件单元格(d_cell)。 3. 如果调用者没有提供tkW, padW, padL, pitch, pad1offset,则从pad_cell中获取(假设pad_cell有这些属性)。 4. 计算metal2edge(金属线到边缘的距离)。 5. 根据offset[0]的值('center','up','down')来放置器件: - 'center': 将器件的中心(cc)对齐到指定PAD的中心位置。 - 'up': 将器件放在PAD的上方,位置计算涉及边界框(bounding box)和给定的偏移。 - 'down': 将器件放在PAD的下方,类似计算。 6. 放置器件后,根据器件引脚的方向('+x','-x','+y','-y')和pinset中指定的连接关系,绘制金属连线。 - 对于每个引脚,计算起点(p_start)和所在层(Layer1)。 - 根据引脚方向(以及相对于PAD的位置)计算路径,使用gdspy.Path或gdspy.L1Path(带拐弯的路径)来绘制。 - 路径的绘制考虑了多种情况(如引脚在PAD的左边、右边、正上方/下方,或者需要绕过其他PAD等)。 注意: - 代码中大量使用了条件判断来处理不同的引脚方向和位置情况。 - 函数最后返回了pad_cell(即添加了器件和连线的目标单元格)。 由于代码很长,我们按offset的三种情况分别处理了连线: - 当器件在PAD中心(center)时,主要处理水平和垂直方向的引脚。 - 当器件在PAD上方(up)时,除了处理水平和垂直引脚,还特别处理了向上引脚('+y')的情况。 - 当器件在PAD下方(down)时,类似地处理。 代码中使用了gdspy.L1Path来绘制带有拐弯的路径,它需要起点、初始方向、线宽、各段长度和拐弯的曲率(turn)。 另外,代码中使用了`gdsNo`和`dtype`函数(未在代码中定义,可能在外部定义)来获取GDSII的层号和数据类型。 由于代码较长且复杂,我们只解释了整体结构和主要步骤。实际应用中,该函数用于自动布局和连线。 注意:代码中有一些注释掉的代码(如align调用),可能是之前的版本。 最后,函数在每种情况(center, up, down)的连线处理结束后都返回pad_cell。 由于代码中使用了大量未定义的变量(如cc, cl, lc, cr等)和函数(如gdsNo, dtype, d_cell.xCoord等),这些可能是外部定义的辅助函数或属性。因此,要完整理解需要查看这些辅助部分的定义。 总结:这个函数是一个针对特定布局需求的自动化布线工具,用于将器件的引脚连接到焊盘上,考虑了器件相对于焊盘的不同位置(中心、上方、下方)以及引脚方向。 §§相关问题§§: 1. 在gdspy中,如何创建一个单元格(Cell)? 2. 在gdspy中,如何获取一个单元格的边界框(bounding box)? 3. 解释gdspy.Path和gdspy.L1Path的用法和区别。 4. 在GDSII布局中,层(layer)和数据类型(datatype)的作用是什么? </think>### 函数 `metalLink` 详细解释 该函数用于在 GDSII 布局中将器件(`device`)放置到目标单元(`tkcell`)中,并根据连接规则自动生成金属连线。主要用于集成电路版图设计中的自动化布线。 #### 核心功能解析: 1. **器件放置**: - 根据 `location` 确定器件相对于哪个焊盘(PAD)放置(默认为第3个焊盘) - 通过 `offset` 控制垂直位置: - `center`: 器件中心与焊盘中心对齐 - `up/down`: 器件位于焊盘上方/下方,偏移量由 `offset[1]` 指定 2. **参数处理逻辑**: ```python # 获取目标单元属性(若未显式提供参数) tkW = pad_cell.tkW if tkW is None else tkW padW = pad_cell.padW if padW is None else padW # ...类似处理 padL, pitch, pad1offset... ``` 3. **连线规则**: - 金属线宽由 `linkW` 控制(默认2μm) - 金属到边缘距离计算:`metal2edge = (tkW - padW)/2 - linkS - linkW` - 特殊金属参数: - `metalCD=3`:转向PAD时的金属临界尺寸 - `metalCD2=4`:接触PAD的金属临界尺寸 - `metalS=3`:金属穿过PAD时的隔离距离 4. **布线算法**: ```python # 示例:中心放置时的向右引线(+x) if pin_dict[pin1][2] == '+x': path1 = gdspy.Path(pin_dict[pin1][0], p_start) path1.segment(length1, '+x', layer=...) ``` - 使用 `gdspy.Path` 绘制直线路径 - 使用 `gdspy.L1Path` 绘制带拐弯的路径(含长度和弯曲半径参数) 5. **引脚连接处理**: - `pinset` 字典定义引脚到焊盘的映射(如 `{'G':12, 'D':12}`) - 自适应处理引脚方向(`+x/-x/+y/-y`) - 复杂场景处理(器件在PAD左侧/右侧/正上方等) #### 关键代码段说明: ```python # 器件放置(中心对齐) d_cell.align(None, cc, pad_cell, cl, (location-1)*pitch + pad1offset + padL + (pitch-padL)/2, 0) # 布线示例:向上引脚(+y)连接 if pin_dict[pin1][2] == '+y': Length1 = tkW + pad_cell.yCoord(None, lc) - metal2edge - linkW/2 - p_start[1] if pinset[pin1] > location: # 器件在PAD左侧 Length2 = (pinset[pin1]-1)*pitch + pad1offset + padL/2 - p_start[0] turn1 = -linkW/pin_dict[pin1][0] # ...生成L1Path路径... ``` #### 注意事项: 1. **依赖项**: - 需预定义 `gdsNo()` 和 `dtype()` 函数(GDS层号/数据类型转换) - 器件对象需包含 `pin` 字典(引脚信息)、`xCoord()`/`yCoord()` 方法 2. **特殊约定**: ```python # 引脚数据结构示例: pin_dict = { 'G': [width, layer, direction, (rel_x, rel_y)], 'D': [...] } ``` - 方向标识:`'+x'`(右), `'-x'`(左), `'+y'`(上), `'-y'`(下) 3. **边界处理**: - 自动计算金属路径长度(`length1 > 0` 才生成路径) - 复杂拐弯场景使用分段长度列表和弯曲半径列表 该函数实现了器件自动布局和智能布线,通过几何计算处理不同相对位置关系,适用于集成电路版图设计中的标准单元连接场景。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值