Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Using the fill tool

edited December 2014 in General
I have created a mask consisting of evenly spaced rectangles. These structures are to be fully exposed in e-beam lithography, so I need to fill them. I understand that using the layer toolbox to assign some "stipple" is only for visualization and does not actually do any filling?

Do I need to use the fill tool in Utilities? How do I use it? I keep getting an error message saying "no valid layer selected to get fill cell's bounding box from"


Please try to explain simply, as I've only recently started using Klayout :)

Comments

  • edited 8:00PM

    Hi,

    are you familiar with mask layout procedures in general?

    Basically, every polygon (box, path ...) is "filled" on a mask. The stipple is only provided for visualization - if multiple layers are overlapping the stipple pattern helps to distinguish them.

    The "fill tool" has an entirely different scope. It is used to create dummy shapes (filled ones) in order to equalize the pattern density. The background is that certain processes (etching, CMP etc.) give better results if the average density of the pattern is similar on the mask. Hence the fill tool can be used to put dummy shapes into the empty regions so the density is increased there leading to a more uniform density pattern.

    Matthias

  • Is there a way to use threading with the fill tool?
    We have a relatively large design, and a relatively powerful PC with lots of cores that is taking a lot (more than a day) to compute the filling of a single chip of our design.
    I saw something similar in a post for the DRC, you mentioned a "tiles" command, and that indeed helped to speed up our DRC.
    Is there something similar for the fill tool?

    Doug

  • edited February 21

    Hi Doug,

    yes, tiling should help. But that's not available yet as an option in the fill dialog. You can however add it through scripting and embed the algorithm inside a tiling processor.

    That's not entirely trivial, specifically if you want to enable multiple cores. The fill algorithm itself isn't thread-safe yet, but you'll benefit from the tiling approach in other ways:

    • memory footprint is reduced to a single tile
    • any boolean and sizing operations required can happen on multiple cores

    This approach requires that you script all the details. Here is a starting point. I hope the comments explain the various steps:

    # Take the loaded layout and it's top cell to create the fill on
    ly = RBA::CellView::active.layout
    micron2dbu = RBA::CplxTrans::new(ly.dbu).inverted
    
    top_cell = ly.top_cell
    
    # This example assumes we want to fill everything not covered by ndiff|pdiff|ntie|ptie
    # with fill cell "DIFF_FILL" with a min distance of 3 µm.
    # The fill cell is created if required using a repetition box of -2,-2/2,2 and a single
    # patch with 2x2 µm centered in this box at layer 2.
    ndiff = ly.layer(3, 0)
    pdiff = ly.layer(4, 0)
    ntie = ly.layer(5, 0)
    ptie = ly.layer(6, 0)
    
    # chip's bbox (boundary to fill)
    chip = RBA::DBox::new(0, 0, 4500.0, 4500.0)
    
    # distance
    distance = 3.0  # micron
    
    # number of cores for the boolean operations
    ncpus = 4
    
    # tile size in micron
    tile_size = 1000.0
    
    # origin of the fill pattern
    # For "enhanced fill use":
    #   fc_origin = nil
    fc_origin = RBA::DPoint::new(0.0, 0.0)
    
    # creates a fill cell with a shape on 
    fc_name = "DIFF_FILL"
    fc_box = RBA::DBox::new(-2.0, -2.0, 2.0, 2.0)
    
    # define the fill cell's content
    fill_layer = ly.layer(2, 0)
    fill_shape = RBA::DBox::new(-1.0, -1.0, 1.0, 1.0)
    
    # ----------------------------
    # implementation
    
    fill_cell = ly.cell(fc_name)
    if ! fill_cell
      fill_cell = ly.create_cell(fc_name)
      fill_shape_in_dbu = micron2dbu * fill_shape
      fill_cell.shapes(fill_layer).insert(fill_shape_in_dbu)
    end
    
    fc_box_in_dbu = micron2dbu * fc_box
    fc_origin_in_dbu = fc_origin && (micron2dbu * fc_origin)
    
    # This is an object which will receive the regions to tile
    # It is driven single-threaded which is good since the tiling function
    # isn't multi-threading safe
    class TilingOperator < RBA::TileOutputReceiver
      def initialize(ly, top_cell, *fill_args)
        @ly = ly
        @top_cell = top_cell
        @fill_args = fill_args
      end
      def put(ix, iy, tile, obj, dbu, clip)
        # This is the core function. It creates the fill.
        # For details see https://www.klayout.de/doc-qt4/code/class_Cell.html#k_63
        @top_cell.fill_region(obj, *@fill_args)
      end
    end
    
    # prepare a tiling processor to compute the parts to put into the tiling algorithm
    # this can be tiled
    tp = RBA::TilingProcessor::new
    tp.frame = chip
    tp.dbu = ly.dbu
    tp.threads = ncpus
    tp.tile_size(tile_size, tile_size)
    tp.input("ndiff", ly, top_cell.cell_index, ndiff)
    tp.input("pdiff", ly, top_cell.cell_index, pdiff)
    tp.input("ntie", ly, top_cell.cell_index, ntie)
    tp.input("ptie", ly, top_cell.cell_index, ptie)
    tp.var("dist", distance / ly.dbu)
    tp.output("to_fill", TilingOperator::new(ly, top_cell, fill_cell.cell_index, fc_box_in_dbu, fc_origin_in_dbu))
    
    # perform the computations inside the tiling processor through "expression" syntax
    # (see https://www.klayout.de/doc-qt4/about/expressions.html)
    tp.queue("var exclude = ndiff + pdiff + ntie + ptie; var fill_region = _tile & _frame - exclude.sized(dist); _output(to_fill, fill_region)")
    
    begin
      ly.start_changes   # makes the layout handle many changes more efficiently
      tp.execute("Tiled fill")
    ensure
      ly.end_changes
    end
    

    And this is the result on a sample of mine with enhanced mode (fc_origin = nil):

    The white shapes are the fill cell instances created.

    Regards,

    Matthias

  • You are incredible Matthias. And you have an incredible piece of software.
    It worked as a charm. Exactly what I needed.
    Thanks a bunch!

    Doug

Sign In or Register to comment.