Counting number of cell instantiations using "begin_instances_rec"

Hello Matthias and all,

I'm trying to make a script to count the number of instantiations of each sub cell inside the currently viewed cell using the method "begin_instances_rec". I get some weird results and I can't figure out what's going wrong. I'm (still) using version 0.27.13.

module MyMacro

  include RBA

  layout_view = Application.instance.main_window.current_view
  cell_view = layout_view.active_cellview
  layout = cell_view.layout
  viewed_cell = cell_view.cell

  sub_cell_names = []

  counter = 0

  viewed_cell.called_cells.each do |cell_index|

      sub_cell_names << layout.cell(cell_index).name

      counter += 1

  end # each

  sub_cell_names.sort!

  line_length = sub_cell_names.map{|string| string.size}.max + 10

  puts "Number of cell instantiations in viewed cell \"#{viewed_cell.name}\" (#{counter} different sub cells detected):\n\n\n"

  iterator1 = viewed_cell.begin_instances_rec

  sub_cell_names.each do |sub_cell_name|

      counter = 0

      iterator1.targets = sub_cell_name

      while !iterator1.at_end?

        counter += 1

        iterator1.next

      end # while

      number_of_spaces = line_length - sub_cell_name.size - counter.to_s.size

      puts sub_cell_name + " " * number_of_spaces + counter.to_s

  end # each

end # MyMacro

Attached a gds test file with 4 top cells:

1) Number Of Cell Instantiations In viewed cell "TOP_CELL_1" (1 different sub cells detected):

CHILD_CELL_1 12

ok

2) Number Of Cell Instantiations In viewed cell "TOP_CELL_2" (2 different sub cells detected):

CHILD_CELL_2 12
CHILD_CELL_2_1 12

ok

3) Number Of Cell Instantiations In viewed cell "TOP_CELL_3" (3 different sub cells detected):

CHILD_CELL_3 12
CHILD_CELL_3_1 12
CHILD_CELL_3_1_1 0

ko ---> 0 should be 12???

4) Number Of Cell Instantiations In viewed cell "TOP_CELL_3_B" (4 different sub cells detected):

CHILD_CELL_3 12
CHILD_CELL_3_1 15
CHILD_CELL_3_1_1 2
CHILD_CELL_3_B 1

ko --> 2 should be 15???

Cheers,

Tomas

Comments

  • edited April 2023

    Hi,
    maybe a 'iterator1.reset' is missing before 'iterator1.targets = sub_cell_name'
    but I have not tested.
    Best regards,
    Frank

  • Hi Frank,

    Thanks for the reply. I added the reset but it doesn't change a thing.
    I also ran the sample code listed in the documentation (https://www.klayout.de/doc-qt5/code/class_RecursiveInstanceIterator.html) on the attached gds file with top cell "TOP_CELL_3_B" selected and it gives only 2 references as well, instead of 15:

    Instance of CHILD_CELL_3_1_1 in TOP_CELL_3_B: r0 *1 120,40
    Instance of CHILD_CELL_3_1_1 in TOP_CELL_3_B: r0 *1 120,0

    The code is:

    module MyMacro
    
      include RBA
    
          layout_view = Application.instance.main_window.current_view
          cell_view = layout_view.active_cellview
          layout = cell_view.layout
          viewed_cell = cell_view.cell
    
    #--------------------Input-------------------------
    
    instance_cell_name = "CHILD_CELL_3_1_1"
    
    #---------------------------------------------------
    
          iterator = viewed_cell.begin_instances_rec
    
          iterator.targets = instance_cell_name
    
          while !iterator.at_end?
    
            puts "Instance of #{iterator.inst_cell.name} in #{viewed_cell.name}: " + (iterator.dtrans * iterator.inst_dtrans).to_s
    
            iterator.next
    
          end # while
    
    end # MyMacro
    

    Cheers,

    Tomas

  • @tomas2004 That looks like a bug, probably the arrays are not traversed properly in the recursion. I'll open a ticket. Thanks for reporting that and the testcase.

    Regarding your problem: the recursive instance iterator is not the right approach as it will traverse the hierarchy far too often in the general case. You only need to sum up weighted counts, like here:

    def collect_counts(cell, weight, counts)
      counts[cell.name] ||= 0
      counts[cell.name] += weight
      cell.each_inst do |inst|
        w = weight * inst.size
        cc = cell.layout.cell(inst.cell_index)
        collect_counts(cc, w, counts)
      end
    end
    
    layout_view = RBA::Application.instance.main_window.current_view
    cell_view = layout_view.active_cellview
    layout = cell_view.layout
    viewed_cell = cell_view.cell
    
    counts = {}
    collect_counts(viewed_cell, 1, counts)
    
    counts.keys.sort.each do |cn|
      puts cn + ": " + counts[cn].to_s
    end
    

    This gives for "TOP_CELL_3B":

    CHILD_CELL_3: 12
    CHILD_CELL_3_1: 15
    CHILD_CELL_3_1_1: 15
    CHILD_CELL_3_B: 1
    TOP_CELL_3_B: 1
    

    Matthias

  • Ticket is here in case someone is interested: https://github.com/KLayout/klayout/issues/1353

    Matthias

  • Hi Matthias,

    Thank you for the improved code. It's indeed very fast :-)

    Cheers,

    Tomas

Sign In or Register to comment.