merge sevral GDS

edited November 2011 in KLayout Support
I want to draw a new layout based on 4 cells in 4 GDS2 file A.GDS, B.GDS, C.GDS and D.GDS.
My toplevel should be A+B+C+D.

I am very confused between new layout, new panel and new cell.

How to merge those 4 GDS to draw my new layout ?

Thanks,
OkGuy

Comments

  • edited 2:13PM
    Hi OkGuy,

    "New Panel" creates a new tab but without a layout loaded. That is not what you need.

    All edit commands like "new layout" or "new cell" create new objects but don't import anything.

    What you can do is to open the four GDS files in separate tabs. Then you create a new layout using "New layout" and copy the four cells of the four layouts into the new one. To do so, select the tab of layout "A", select the top cell in the cell tree and choose "Copy" from the cell tree's context menu (right mouse button). Then go to the new layout's tab and paste the cell into this by choosing "Paste" from the cell list's context menu.

    Proceed the same way with the other cells and finally you'll have all four cells in the new layout. You can then combine them into a single layout by creating instances of these cells in the new layout's top cell.

    Best regards,

    Matthias
  • alualu
    edited 2:13PM
    Hi Matthias,

    Is it possible to use a ruby script to merge several GDS and stream out into one GDS?

    Thanks and BR,

    Allen
  • edited February 2012

    Hi Allen,

    That depends somewhat of the merge functionality. The feature available in "File->Import->Other File Into Current" is somewhat elaborate and is not easy to use inside a Ruby script.

    A simple merge however can be achieved with that script:

    # merge_files.rb 
    #
    # Merges two files into one
    #
    # Run this script with 
    #   klayout -rd file1=first_file.gds -rd file2=second_file.gds -rd output=output_file.gds -z -r merge_files.rb
    #
    # (Note: -z puts KLayout into non-GUI mode)
    #
    # WARNING: this implementation merges the contents of all cells with identical names
    # unless the cells are renamed (see comments)
    
    # Read the first layout
    layout = RBA::Layout.new
    lmap = layout.read($file1)
    
    # read the second file which basically performs the merge
    load_layout_options = RBA::LoadLayoutOptions.new
    load_layout_options.set_layer_map(lmap, true)
    layout.read($file2, load_layout_options)
    
    layout.write($output)
    

    Please note the warning: this script will merge cells named identically in both files which may result in severe distortions of the layout. If you want to prevent this, you can use a modified form of the script which prefixes the cell names of the layouts:

    # merge_files.rb 
    #
    # Merges two files into one
    #
    # Run this script with 
    #   klayout -rd file1=first_file.gds -rd file2=second_file.gds -rd output=output_file.gds -z -r merge_files.rb
    #
    # All cells of file1 are prefixed with "A", all cells of file2 with "B".
    #
    # (Note: -z puts KLayout into non-GUI mode)
    
    # Read the first layout
    layout = RBA::Layout.new
    lmap = layout.read($file1)
    
    # store and take away the cell names of all cells read so far
    # (by setting the cell name to "" the cells basically become invisible for
    # the following read)
    cell_names = { }
    (0..(layout.cells-1)).each do |ci|
      cell_names[ci] = layout.cell_name(ci)
      layout.rename_cell(ci, "") # this prevents a name clash on the next read
    end
    
    # read the second file which basically performs the merge
    load_layout_options = RBA::LoadLayoutOptions.new
    load_layout_options.set_layer_map(lmap, true)
    layout.read($file2, load_layout_options)
    
    # rename the cells by using prefix "A" for layout 1 and "B" for layout 2
    (0..(layout.cells-1)).each do |ci|
      if cell_names[ci]  
        layout.rename_cell(ci, "A" + cell_names[ci])
      else
        layout.rename_cell(ci, "B" + layout.cell_name(ci))
      end
    end
    
    layout.write($output)
    

    Please note that both versions of the script do not deliver reasonable results if the database units of the files differ.

    Hopefully that helps.

    Best regards,

    Matthias

  • alualu
    edited 2:13PM
    Hi Matthias,

    Thanks a lot for your response and help!

    I used your first script to merge some dummy pattern gds files and it works like a charm.
    Compared with running a SKILL script in Virtuoso, this script saves me time.

    However, there is one problem. The script seems to work with small gds files. If each gds file is bigger than 20+MB, I got error message:

    ERROR: Ruby error: 'Operation cancelled' (RuntimeError)
    ./merge_files.rb: in 'write'

    I tried to set some options in SaveLayoutOptions in layout.write but not working.
    (e.g. gds2_allow_big_records=true and gds2_allow_multi_xy_records=true)
    Could you give me some advice? I can send you the gds files if it helps to clarify the issue.

    Thanks and Best Regards,

    Allen


    when merging two slightly bigger gds files. Big means the combined gds
  • edited February 2012

    Hi Allen,

    you're right. Apparently KLayout tries to bring up the progress bar and since that fails, it cancels the operation.

    I'll try to fix that in the next version. There is a simple workaround: just don't use the -z option. In that case, KLayout shows the user interface and the progress bar is displayed. Hence, the script does not abort.

    Thanks for the hint and best regards,

    Matthias

  • alualu
    edited 2:13PM
    Hi Matthias,

    Thanks for solving my question! It works well without -z option.

    One more question: can I extend the above script to merge three files or more?
    I added "layout.read($file3, load_layout_options)" in the script and run it. The error message is "internal error: /root/klayout-0.21.15/src/dblayout.cc:1365 m_layer_states[index]== Free was not true."
    Is there a limitation of the script? Just curious.

    Thanks and best regards,

    Allen
  • edited February 2012

    Hi Allen,

    there is no general limitation, but the code adaptations required are somewhat more elaborate. First you have to save the layer map after each load (failing to do so gives the error message you observed). Then you need to reset the cell names before each load to avoid the name clashes.

    Here is the generic form of the script:

    # merge_n_files.rb 
    #
    # Merges multiple files into one
    #
    # Run this script with 
    #   klayout -rd files=first_file.gds,second_file.gds,third_file.gds -rd prefixes=A,B,C rd output=output_file.gds -r merge_n_files.rb
    #
    
    files = $files.split(/,/)
    prefixes = $prefixes.split(/,/)
    
    lmap = nil
    layout = RBA::Layout.new
    cell_name_maps = []
    
    files.each do |file|
    
      # read the file which basically performs the merge
      load_layout_options = RBA::LoadLayoutOptions.new
      lmap && load_layout_options.set_layer_map(lmap, true)
      lmap = layout.read(file, load_layout_options)
    
      # store and take away the cell names of all cells read so far
      # (by setting the cell name to "" the cells basically become invisible for
      # the following read)
      cell_name_map = { }
      (0..(layout.cells-1)).each do |ci|
        if !layout.cell_name(ci).empty?
          cell_name_map[ci] = layout.cell_name(ci)
          layout.rename_cell(ci, "") # this prevents a name clash on the next read
        end
      end
    
      cell_name_maps.push(cell_name_map)
    
    end
    
    # rename the cells by using the given prefixes for the different layouts
    (0..(layout.cells-1)).each do |ci|
      cell_name_maps.each_with_index do |m,i|
        if m[ci]  
          layout.rename_cell(ci, prefixes[i] + m[ci])
        end
      end
    end
    
    layout.write($output)
    

    Best regards,

    Matthias

  • alualu
    edited 2:13PM
    Hi Matthias,

    The script works well. Thanks for providing the awesome tool and script!

    Best Regards,

    Allen
Sign In or Register to comment.