How to extract real coordinate of cell instance ?

edited September 2016 in Ruby Scripting

Hi Matthias,

I'm trying to extract the coordinate of cell instace via RBA code but stucked, could you please help to figure out the problem ?

For example:

A db hierarchy is Top_Cell=>CellA=>CellB and CellC ,

I hope to extract the coordinates of CellB and CellC.

The code:

cell = layout.cell(layout.cell_by_name("CellA"))
cell.each_inst do |inst|
  p = inst.trans.disp
  x = p.x
  y = p.y
  name = inst.cell.name
  puts "#{name} at #{'%.3f'%(x*dbu)}, #{'%.3f'%(y*dbu)}"
end

It would only output the coordinate related to CellA, however I hope it could output the coordinate related to Top_Cell

Best Regards,

chhung

Comments

  • edited September 2016

    Hi chhung,

    First of all, I'd like so suggest a new solution - not based on Ruby but on the "Layout Queries" of "Search & Replace": open "Search & Replace" from the "Edit" menu. Chose the "Custom" tab and enter this expression:

    select path_trans.disp.x,path_trans.disp.y from instances of ...* where cell.name == "CellB" || cell.name == "CellC"
    

    hit Execute and the left table ("Results") will fill with a list of x, y coordinates. Using the "Export" button above you can write that table to a CSV file for example.

    If you want the see the results in Mikrometer units, you can modify the query:

    select path_trans.disp.x*layout.dbu, path_trans.disp.y*layout.dbu 
    from instances of ...* 
    where cell.name == "TRANS" || cell.name == "INV"
    

    A pure Ruby scripted solution involves recursively traversing the cell tree like this:

    def search_cell(from_cell, name_re, tr = RBA::CplxTrans::new)
      from_cell.each_inst do |i|
        child_cell = i.cell
        path_tr = tr * i.cplx_trans
        if child_cell.name =~ name_re
          puts path_tr.disp.to_s
        else
          search_cell(child_cell, name_re, path_tr)
        end
      end
    end
    
    search_cell(RBA::CellView::active.cell, /CellB|CellC/)
    

    Matthias

  • edited November -1

    Hi Matthias,

    Really thanks for your sample code, I modified it to fit our requirement.

    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
    
    layout = RBA::Layout.new
    layout.read("database.oas.gz")
    
    dbu = layout.dbu
    
    search_cell(layout.top_cell, /^P/, dbu)
    

    It would output all the instance coordinates start with P character, just like "P_cell ( 4107.618 , 2048.636 )
    "

    Tried to run the code with 1850 cells database, and it needs about 134s to complete the job.

    Best Regards,

    chhung

  • edited September 2016

    Hi,

    134s may be good or bad depending on the hierarchical complexity of your layout. If the cell tree expands to a lot of effective instances, the cells traversed may become pretty big. In general, Ruby is quite efficient, but far from an optimized C++ solution. Caching may be one way to optimize it.

    BTW: I noticed that the code above does not account for cell arrays. So if you are interested in the expanded instances of cell arrays, you'll need to iterate over the array locations additionally:

    if inst.is_regular_array?
      inst.na.times do |ia|
        inst.nb.times do |ib|
          # In addition to the basic transformation an array displacement needs to be added
          path_tr = tr * RBA::CplxTrans::new(RBA::Trans::new(inst.a * ia + inst.b * ib)) * inst.cplx_trans
          ...
        end
      end
    else
      path_tr = tr * inst.cplx_trans
      ...
    end 
    

    I wonder about the performance of the first solution based on Search & Replace. Did you try that one too?

    Matthias

  • edited September 2016

    Hi Matthias,

    Sorry to reply so late because Taiwan is in Mid-Autumn Festival.

    I tried the following command in search/replace function

    select path_trans.disp.x*layout.dbu, path_trans.disp.y*layout.dbu 
    from instances of *
    where cell.name == "Cell1" || cell.name == "Cell2"
    

    The run time is around 15s, must faster than search with RBA code,
    however it outputs a strange result as following data(incorrect coordinates):

    8.43750487998e-319,589.5
    8.43750487998e-319,589.5
    

    Correct coordinates:

    ( 2969.870 , 7349.461 )
    ( 3181.894 , 7349.461 )
    

    And I notice that the Export => To CSV file function would try to do the query again then save to CSV file, not save the quired results to CSV file directly, is that correct ?

    Best Regards,

    chhung

  • edited November -1

    Hi chhung,

    is it mid-autumn already? I thought it's kind of late-summer to early-autumn transition ...

    Sorry, just kidding :-)

    Thanks for the data. The strange value like "x.ye-319" is a typical close-to-zero rounding issue. But I don't understand the differences in the coordinates. I tried in a test case of mine and found that the coordinates of the search function and the script are the same. But they come out in a different order. Maybe you are just looking at the first entries of your list? Or maybe you use an older version?

    And yes: the query is run again on CSV export ... that's not necessary always, but the query will stop after having rendered more than a configurable maximum number of results (default 1000) while the CSV is rendered completely. Hence a new pass. But I agree it could be done more efficiently by reusing the existing list if it's not shortened.

    Kind regards,

    Matthias

  • edited September 2016

    Hi Matthias,

    Mid-autumn Festival is one of the feasts in Taiwan, and temperature is in summer. XD

    I tested two cells' name, one(cell1) is a subcell of topcell, another(cell2) is second level hierarchy of topcell.

    cell1(3142.411 , 4646.508)
    query1: 4.15701893754e-319,4646.508
    query2: 4.15504287498e-319,4646.508
    
    cell2(144.374 , 5256.662)
    query1: 4.10728852701e-319,211.558
    query2: 4.17885901283e-319,211.558
    

    For cell1, the y data is correct, however x is a random number. @_@a?

    For cell2, the y data is incorrect, but I found it's related to cell2's parent cell, x is still a random number.

    I'm trying this function with klayout v0.24.7

    If I switch the klayout version to v0.23.7:

    No matter cell1 or cell2 output incorrect data, x is still a random number,
    and y is always 0.

    Did I miss something or have a wrong command?

    Best Regards,

    chhung

  • edited November -1

    Very weired ... you're on Windows, are you? Maybe a problem with that build. It works perfectly for me on Linux.

    I'll take a look into that.

    Thanks for testing,

    Matthias

  • edited September 2016

    Hi Matthias,

    I'm running klayout v0.24.7 on CentOS6(RHEL6), then I switch to klayout v0.24.5 on MDK9.2, the same problem.

    CentOS6: gcc 4.4.6-3 + ruby 1.8.7-p352

    MDK9.2: gcc 4.2.2-0 + ruby 1.8.7-p371

    FYI.

    Best Regards,

    chhung

Sign In or Register to comment.