# Layer space and width

edited March 2013
Hi,

Is there any way to check the sapce and width between all polygon and paths within the same layer ?
Even with a maximum of checks (i.e. set in the settings such as 1000), it would be very useful for small layouts after a small change of 1 layer.
It cannot replace a full DRC, but help to avoid silly mistake.

Thanks, Rgds,
OkGuy

• edited March 2013

Hi,

well, having a width and spacing check would already be the very core of real DRC functionality. There is no such function (yet). You can mimic the effect with under/oversizing and XOR, i.e.

``````# minimum spacing check (distance d)
l = ... # input
min_space = l.xor(l.size(d/2).size(-d/2))

# minimum width check (width d)
min_width = l.xor(l.size(-d/2).size(d/2))
``````

I am using the notation of the layer processing framework here. Please note that these operations are not quite efficient and will only work on small layouts.

Regards,

Matthias

• edited March 2014
Hi, OkGuy:
Based my experience, klayout 0.23+ version is good for DRC. I use the Boolean operation to figure out the width/space Perato. Here is my example code:

########################################333
tileNo = 10 #define the tiles in 10um
borderNo = 0 #no border

startTime=Time.new

## define width/space for boolean operation
widthset = [150,180,200,250,500] # <500nm
spaceset =[180,200,226,250,300,500,2500] # <2500nm

## define output layer
WidthOutPut ="1000"
SpaceOutPut= "2000"
WidthSpaceOut="3000"

## define layer alias matrix
wopt = Array.new ## store the widthset layer alias
sopt = Array.new ## store the spaceset layer alias
wsopt = Array.new ## store the width/space alias

## resort width/space from small to large distributions
widthset.sort
spaceset.sort

## define the widthset and spaceset temperates for ruby bug
wtemp=Array.new(widthset)
stemp=Array.new(spaceset)

## use tiles, borders and threads in Klyout v0.23+ DRC part
tiles(tileNo)
tile_borders(borderNo)

## call RBA for active layout
ly=RBA::CellView::active.layout
## define topcell name
top_cell=ly.top_cell.name

##DRC file add time stamp to avoid DRC log file overwrite
timetemp=Time.new.to_a
timeStamp = timetemp[4]*timetemp[3]+timetemp[2]*timetemp[1]+timetemp[0] ##hours digit1 x hour digit2 + minute digit1 x minute digit2 + second digit

drcfile = "Agogo_"+top_cell+"_"+timeStamp.to_s+".log"
log_file(drcfile) ##define DRC file end

verbose(true)

layer1=input("1/0") #layer for DRC check

ww_old=layer1 ## for layer1 temp to minus
i=0
j=0

## widthset distribution
widthset.each do |widthset|
j=i+1
wopt[i] = WidthOutPut.to_s+"/"+j.to_s
woptalias = """W"+widthset.to_s+"nm ("+wopt[i].to_s+")"""
halfsize = widthset/2000.0 ##change nm to um
halfsize = halfsize.to_f
## Follow Matthias recommendation by using +/- sizing to figure the specific value.
ww = ww_old.sized(-halfsize).sized(halfsize)
w = ww_old - ww
w.output(woptalias)
layerArea=w.area
layerLength=layerArea/halfsize*2
## display on console
puts "W = #{widthset.to_s} nm; area = #{layerArea.to_s} ; mean length = #{layerLength}"
##store in log file
info "**W <= #{widthset.to_s} nm; area = #{layerArea.to_s} ; mean length = #{layerLength}"
i=i+1
ww_old=ww
end

widthCount=i ##widthset matrix number
##free memory
ww_old=nil
ww=nil
GC.start ## garbage collecting start

## spaceset distribution
i=0
j=0
ss_old=layer1
spaceset.each do |spaceset|
j=j+1
sopt[i] = SpaceOutPut.to_s+"/"+j.to_s
soptalias = """S"+spaceset.to_s+"nm ("+sopt[i].to_s+")"""
halfsize = spaceset/2000.0 ##change nm to um
halfsize = halfsize.to_f

ss = layer1.sized(halfsize).sized(-halfsize)
s = ss - ss_old
s.output(soptalias)

layerArea=s.area
layerLength=layerArea/halfsize*2
puts "S = #{spaceset.to_s} nm; area = #{layerArea.to_s} ; mean length = #{layerLength}"
##store in log file
info "**S <= #{spaceset.to_s} nm; area = #{layerArea.to_s} ; mean length = #{layerLength}"

i=i+1
ss_old=ss
end

spaceCount = i
ss=nil
ss_old=nil

i=0
j=0
k=0
######## the following codes are optional #################
## width / space ditribution for cross analysis
while i<widthCount do
w=input(wopt[i])
if w!=nil
w=w.sized(0.001) #minimun unit to interact with other space
k=0
while k<spaceCount do
s=input(sopt[k])
j=j+1
wsopt[j]=WidthSpaceOut.to_s + "/" + j.to_s
wsalias = """W"+wtemp[i].to_s + "S" + stemp[k].to_s+" ("+wsopt[j]+")"""
if s!=nil
ws=w.and(s)
if ws!=nil
ws.output(wsalias)
layerArea=ws.area
layerLength = layerArea/0.001/2
puts "W#{wtemp[i].to_s}S#{stemp[k].to_s} ; area = #{layerArea.to_s} ; length = #{layerLength.to_s}"
info "**W#{wtemp[i].to_s}S#{stemp[k].to_s} ; area = #{layerArea.to_s} ; length = #{layerLength.to_s}"
end
end
k=k+1
end
end
i=i+1
end
##free huge layout memory
w=nil
s=nil
ws=nil
layer1=nil
###### optional code end here ###############

flat
no_borders

saveFile=top_cell+"_drc.oas.gz"
opt = RBA::SaveLayoutOptions::new
opt.format="OASIS"
opt.oasis_compression_level=9
ly.write(saveFile, true, opt)
puts "filename: #{saveFile} saved."
info "drc layout saved in #{saveFile}"
endTime=Time.new
processTime=endTime.to_i - startTime.to_i

puts "Start #{startTime}, end #{endTime} Process time #{processTime}"
info "Start #{startTime}, end #{endTime} ,process time #{processTime} ,threads: #{threadNo}, tiles: #{tileNo}, borders: #{borderNo}"

##########end here########################################

arided