Really easy question

edited December 2017 in Ruby Scripting
I have a script that when I have a technology library charged in Klayout, it finds in the active cell all same cells that they appear in technology library and replace all of them. The problem is that I want to generate a file specifying in what position and how much cells it replaces. I put some like that to see the names of and the position of each cell, but it reports a lot of cells with the same name and the same position and for some of cells no. I think that the problem is that I call only parent cells and not all children cells :| if anyone could help me, I am sure that it will be easy but i can't fix it.

cell_inst_object.cell_index = cv.layout.cell_by_name(names[instan.child_inst.cell_index])
n = cell_inst_object
x = n.trans.disp.x
y = n.trans.disp.y
name = n.cell.name
puts "#{name} at #{'%.3f'%(x*layout.dbu)}, #{'%.3f'%(y*layout.dbu)} #{instan.child_inst.cell_inst.na} #{instan.child_inst.b}"

Thank you

Comments

  • edited November -1

    Hi,

    Could you show the full code? This is just a small part and I can't read much from that.

    Matthias

  • edited November -1
    Sorry for the delay,

    The full code to replace cells from a library is as follow. And my problem is in line 190 :
    # This file read technology library of Ligentec and check if BB are in
    # A utility function which copies one layout into another
    def copy_cells(lsrc, ltarget, lmap, pmap, names)

    citarget = nil

    # a map for the cell indices
    cmap = {}

    lsrc.each_cell_bottom_up do |cisrc|
    #print tn
    names.each do |names_value|
    puts names_value[1].to_s
    puts lsrc.cell_name(cisrc).to_s
    puts names_value[1].to_s.eql?lsrc.cell_name(cisrc).to_s
    if names_value[1].to_s.eql?lsrc.cell_name(cisrc).to_s

    # create a new cell in the target layout and add to the cell index map
    csrc = lsrc.cell(cisrc)
    citarget = ltarget.add_cell(lsrc.cell_name(cisrc))
    ctarget = ltarget.cell(citarget)
    cmap[cisrc] = citarget

    # copy the shapes
    lsrc.layer_indices.each do |lisrc|
    shtarget = ctarget.shapes(lmap[lisrc])
    csrc.shapes(lisrc).each do |shape|

    # property mapping
    newpid = 0 # =no properties
    if shape.has_prop_id?
    newpid = pmap[shape.prop_id]
    if !newpid
    newpid = ltarget.properties_id(lsrc.properties(shape.prop_id))
    pmap[shape.prop_id] = newpid
    end
    end

    newshape = shtarget.insert(shape)
    shtarget.replace_prop_id(newshape, newpid)
    end
    end

    # translate and copy the instances
    csrc.each_inst do |inst|

    # property mapping
    newpid = 0 # =no properties
    if inst.has_prop_id?
    newpid = pmap[inst.prop_id]
    if !newpid
    newpid = ltarget.properties_id(lsrc.properties(inst.prop_id))
    pmap[inst.prop_id] = newpid
    end
    end

    # get the instance object and create a new one with the new cell index
    i = inst.cell_inst
    trans = i.is_complex? ? i.cplx_trans : i.trans
    cinew = cmap[i.cell_index]
    if i.is_regular_array?
    newinst = ctarget.insert(RBA::CellInstArray.new(cinew, trans, i.a, i.b, i.na, i.nb))
    else
    newinst = ctarget.insert(RBA::CellInstArray.new(cinew, trans))
    end

    # apply the new property id
    ctarget.replace_prop_id(newinst, newpid)

    end
    end
    end
    end

    return cmap

    end



    app = RBA::Application.instance

    mw = app.main_window
    # get the current layout view
    lv = mw.current_view
    if lv == nil
    raise "No view selected"
    end

    # get the current cell view (the one selected in the hierarchy browser)
    cv = lv.cellview(lv.active_cellview_index)
    if !cv.is_valid?
    raise "No layout selected"
    end

    layout = cv.layout

    # fetch the name of the layout with the replacement cells
    fn = ENV['HOME']+"\\klayout_library_MPW.gds"


    library =RBA::Library.library_by_name("Lib_klayout")
    library || raise("Please charge Library of Klayout Tools->klayout Library")
    lib=library.layout
    #lib = RBA::Layout::new
    #puts lib
    #lmap = lib.read(fn)

    if ((lib.dbu - cv.layout.dbu).abs > 1e-6)
    raise "Database units of the layouts must be identical"
    end
    org_layers = {}
    new_layers = {}
    =begin
    cv.layout.layer_indices.each do |l|
    info = cv.layout.get_info(l)
    if lmap.is_mapped?(info)
    puts info
    ll = lmap.logical(info)
    puts ll
    org_layers[l] = ll
    new_layers[ll] = l
    end
    end
    =end
    cv.layout.layer_indices.each do |l|
    info = cv.layout.get_info(l)

    lib.layer_indices.each do |l_auxi|
    info_auxi = lib.get_info(l_auxi)
    puts info.to_s.eql?info_auxi.to_s
    if info.to_s.eql?info_auxi.to_s
    puts info
    ll = l_auxi
    org_layers[l] = ll
    new_layers[ll] = l
    end
    end
    end
    has_new_layers = false

    lib.layer_indices.each do |l|
    if ! new_layers[l]
    # puts l
    ll = cv.layout.insert_layer(lib.get_info(l))
    new_layers[l] = ll
    org_layers[ll] = l
    has_new_layers = true
    end
    end
    puts has_new_layers
    tmap = {}
    names = {}
    dummy = 0
    lib.each_cell do |t|
    tn = lib.cell_name(t.cell_index)
    #print tn
    if cv.layout.has_cell?(tn)
    tt = cv.layout.cell_by_name(tn)
    tmap[tt] = t
    names[tt] = tn
    cv.layout.rename_cell(tt, "dummy")
    cv.layout.prune_subcells(tt, -1)
    end
    end

    pmap = {}
    cmap = copy_cells(lib, cv.layout, new_layers, pmap, names)
    namebf=""
    ss=0
    tr = RBA::CplxTrans::new
    #puts cmap[1]
    layout.each_cell do |cell_prob|
    i=0
    cell_prob.each_parent_inst do |instan|
    if tmap[instan.child_inst.cell_index]
    i=i+1
    end
    end
    x=0
    while x<i
    cell_prob.each_parent_inst do |instan|
    if tmap[instan.child_inst.cell_index]
    n = instan.child_inst
    cell_inst_object = n.dup
    #puts cv.layout.cell_name(tmap[instan.child_inst.cell_index].cell_index)
    cell_inst_object.cell_index = cv.layout.cell_by_name(names[instan.child_inst.cell_index])
    n = cell_inst_object
    =begin
    x = n.trans.disp.x
    y = n.trans.disp.y

    name = n.cell.name
    =end puts "#{name} at #{'%.3f'%(x*layout.dbu)}, #{'%.3f'%(y*layout.dbu)} #{instan.child_inst.cell_inst.na} #{instan.child_inst.b}"

    end
    end
    x = x+1
    end
    end
    tmap.each do |k,v|
    layout.prune_cell(k, -1)
    end
    if has_new_layers
    mw.cm_lv_add_missing
    end
    =begin
    topcell = "Edge_Coupler"
    ly = layout
    parent_cell_p = ly.cell(ly.cell_by_name(topcell))
    parent_cell_p.each_parent_cell{ |parent_cell_index|
    parent_cell = layout.cell(parent_cell_index)
    parent_cell.each_inst { |inst| # Iterate over all the child instances
    x = inst.bbox.center.x
    y = inst.bbox.center.y
    if inst.cell.name.to_s.eql?topcell
    puts "#{inst.cell.name} at #{'%.3f'%(x*ly.dbu)}, #{'%.3f'%(y*ly.dbu)}"
    end
    }
    }

    def search_cell(from_cell, name_re, dbu, tr = RBA::CplxTrans::new)
    from_cell.each_inst do |inst|
    child_cell = inst.cell
    path_tr = tr * inst.cplx_trans
    if child_cell.name =~ name_re
    name=child_cell.name
    coords=path_tr.disp
    x=coords.x*dbu
    y=coords.y*dbu
    puts "#{name} ( #{'%.3f'%x} , #{'%.3f'%y} )"
    else
    search_cell(child_cell, name_re, dbu, path_tr)
    end
    end
    end
    dbu = layout.dbu

    search_cell(layout.top_cell, Edge_Coupler, dbu)

    layout.top_cell.each_inst { |inst| # Iterate over all the child instances

    if inst.is_regular_array?

    a,b,na,nb = inst.a, inst.b, inst.na, inst.nb
    x0,y0 = inst.bbox.center.x, inst.bbox.center.y # The xy position of the primary (bottom-left in this case) element

    na.times { |i|
    nb.times { |j|

    x = x0 + a.x*j + a.y*j
    y = y0 + b.x*i + b.y*i
    puts "#{inst.cell.name} at #{'%.3f'%(x*layout.dbu)}, #{'%.3f'%(y*layout.dbu)}"

    }
    }

    else
    x = inst.bbox.center.x
    y = inst.bbox.center.y
    puts "#{inst.cell.name} at #{'%.3f'%(x*layout.dbu)}, #{'%.3f'%(y*layout.dbu)}"
    end

    }
    =end

    Could you recommend something for this code to try to extract the number of cells and the name to put in one file?

    Thank you
  • edited March 2018

    Hi,

    first think I see is that there is an apparent lack of support for copying multiple cells of one layout to another ... the copy_cells function looks fairly complex.

    Nevertheless, the real issue is probably that you're iterating over the parent instances. That does not allow to modify the respective child instance. In addition, if you would modify it while iterating, that would change the parent-child relationship while you traverse it. Bad idea.

    So the solution I'd suggest is this (not tested)

    ...
    
    new_layers = {}
    has_new_layers = false
    lib.layer_indexes do |l_lib|
      li_lib = lib.get_info(l_lib)
      l_ly = layout.find_layer(li_lib)
      if !l_ly
        has_new_layers = true
        l_ly = layout.layer(li_lib)
      end
      new_layers[l_lib] = l_ly
    end
    
    names = {}
    lib.each_cell do |t|
      tn = lib.cell_name(t.cell_index)
      tt = layout.cell(tn)
      if tt
        names[tt.cell_index] = tn
        tt.name = "__dummy__"
        tt.prune_subcells
      end
    end
    
    pmap = {}
    # there should be a built-in method for this:
    copy_cells(lib, layout, new_layers, pmap, names)
    
    layout.each_cell do |cell|
      cell.each_instance do |inst|
        if names[inst.cell_index]
          inst.cell = cv.layout.cell(names[inst.cell_index])
        end 
      end
    end
    
    names.each do |k,v|
      layout.prune_cell(k, -1)
    end
    

    Regards,

    Matthias

Sign In or Register to comment.