Length values in expressions using TilingProcessor

edited September 18 in Ruby Scripting

Hello, I have a question regarding the TilingProcessor and expressions.

I have the following (shortened) setup:

tp = RBA::TilingProcessor::new
tp.frame = chip
tp.dbu = ly.dbu
tp.threads = threads
tp.tile_size(tile_size, tile_size)

tp.input("COMP", ly, top_cell.cell_index, COMP)
tp.input("Poly2", ly, top_cell.cell_index, Poly2)
tp.input("PMNDMY", ly, top_cell.cell_index, PMNDMY)

tp.var("space_to_COMP", 3.5 / ly.dbu)
tp.var("space_to_Poly2", 1.5 / ly.dbu)

tp.output("to_fill", TilingOperator::new(ly, top_cell, fill_cell.cell_index, fc_box_in_dbu, row_step_in_dbu, column_step_in_dbu, fc_origin_in_dbu))

tp.queue("
var COMP_20um_spacing = COMP.sized(20um).sized(-20um)
var fill_region = _tile & _frame - COMP_20um_spacing.sized(space_to_COMP) - Poly2.sized(space_to_Poly2) - PMNDMY;
_output(to_fill, fill_region)")

I get the following error:

ERROR: Worker thread: Length or area value with unit requires a layout context at line 3, position 36 (..20um).sized(-20um)

Which makes a lot of sense, however since the tiling processor has information about the dbu, shouldn't it be possible to convert the length value?
Or is there another way to supply the layout context?

As a workaround I can supply the constant as a variable like I did for the spacing:

tp.var("um20", 20 / ly.dbu)

Let me know if you need a full reproducible.

Thanks!

Comments

  • Hi Leo,

    You're correct, the layout context is not there and it's not just the DBU, with a layout context for example you can obtain layer indexes using angle brackets (e.g. "<2/0>" turns into the layer index). Bottom line is: a "layout context" is really a layout and although the tiling process gets the DBU, the layout is a not readily accessible.

    My recommendation was to turn the "20 µm" value into a variable like you suggested. I feel it's a good practice to define every physical value somewhere globally, so I would write:

    min_dim = 40
    
    ...
    tp.var("min_dim", min_dim / ly.dbu)
    ...
    
    tp.queue("
    var COMP_cleaned = COMP.sized(min_dim / 2).sized(-min_dim / 2)
    ...
    )
    

    (this is how I understand the intention of the code).

    BTW: in case you're trying filling, have you seen this: https://www.klayout.de/forum/discussion/2620/fill-multiorigin-and-manufacturing-grid#latest ?

    (and please use static origin, I am not happy with the auto_origin or multi_origin feature. Needs work :( )

    Best regards,

    Matthias

  • Hi Matthias,

    Thank you for the explanation! I will go with the variables :)

    No, I haven't seen the latest update yet. Very cool!

    Yes, I'm actually working on fill, but not for ihp-sg13g2 ;)
    This is for gf180mcu, where the fill rules are much simpler. It's just a fixed shape with a fixed stagger.

    However, I'm really looking forward to all the fill improvements! Having a reliable fill method for ihp-sg13g2, even for dense digital designs, would be absolutely great 🙌

    One more question: Have you thought about variable-size fill shapes? Magic allows to specify a minimum and maximum length, and will then try to fit the largest fill shapes.
    It is quite useful to get the to the last missing percent of density. However, I'm not sure how valuable this feature really is: whether modern process nodes allow arbitrary fill shapes, and whether it' actually needed (maybe not all processes are as picky as ihp-sg13g2).

    Best,
    Leo

  • Hi Leo,

    The way I know variable fill is implemented is by placing some grating pattern over your layout, the subtract the non-fill regions with some sizing and then clean up the cut grating parts with a under/oversize to remove the pieces where the grating a partially clipped. Finally the lines could be cut into pieces with a maximum length using a polygon processor.

    That should not be too difficult to implement, but from perspective of process isotropy and parasitic coupling, I think that the square fill pattern is easier to handle. I have seen line fill in advances nodes with a pronounced isotropic lithographic setup (dipole illumination) and multi-patterning. I think however, in these cases it's more common to include fill pattern in form of dummy gates for example.

    Matthias

  • Thank you for all the information, Matthias!

    Anyways, for now a simple fill is sufficient on gf180mcu :)

    I have one more question about the filler generation:

    I'm using sized to ensure the minimum spacing between the dummy comp and the other layers.
    However, for euclidean measurements the spacing (3.5um) is violated, as you can see:

    (The filler cell is the red one.)

    I don't quite understand why this is happening.
    I could pass a different mode to sized, but this should only change how corners are handled.
    Does fill_region somehow need to use euclidian measurements?

    Leo

  • Hi Leo,

    Basically the sizing implements an edge shift, so provided, the filler (red shape I assume) is outside the sized region, it should observe the Euclidian distance. I suspect the latter is not the case. First thing I'd try is to confirm that the fill shapes are inside the allowed area by dumping the sized layer. If that is not the case, then there is a problem with the fill shape definition I assume. Maybe you can share the current script, so I can take a look.

    I also like to use this opportunity to advertise some new features of KLayout 0.30.4 - namely "margin" for the fill pattern (helps keeping a distance without need for "sized") and "fill_exclude" ("fill" method) which avoids having to do the boolean NOT for computing the area to fill.

    Best regards,

    Matthias

  • Hi Matthias,

    As this is a Ruby script that uses the TileOutputReceiver, I'm not sure how easy it is to dump the sized layers.

    Perhaps you can take a quick look: https://github.com/wafer-space/gf180mcu/tree/ed1a3104ffe3dc387276e1bc9f031f6f5071092b/gf180mcuD/libs.tech/klayout/tech/drc/filler_generation

    But maybe don't put too much time into this. I'll convert this to a DRC script soon, like you have done for Greyhound, as this seems to be the better way to do fill.

    fill_exclude sounds great! However, I don't think I can use margin on gf180mcu, since I need to keep different distances to different layers.
    See the Dummy COMP rules for example: https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_13_1.html

    Thanks a lot for your help!
    Leo

Sign In or Register to comment.