Layer space and width

edited March 2013 in KLayout Development
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

Comments

  • 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
    threadNo = 4 #thread 4 core CPU

    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)
    threads(threadNo)

    ## 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
Sign In or Register to comment.