diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc index 855be54b5..a684bc149 100644 --- a/src/db/db/dbFillTool.cc +++ b/src/db/db/dbFillTool.cc @@ -212,11 +212,6 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f throw tl::Exception (tl::to_string (tr ("Invalid row or column step vectors in fill_region: row_step x column_step vector vector product must be > 0"))); } - // disable enhanced mode an obey the origin if the polygon is not entirely inside and not at the boundary of the glue box - if (enhanced_fill && ! glue_box.empty () && ! fp0.box ().enlarged (db::Vector (1, 1)).inside (glue_box)) { - enhanced_fill = false; - } - db::Vector kernel_origin (fc_bbox.left (), fc_bbox.bottom ()); std::vector filled_regions; @@ -256,13 +251,21 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f continue; } - size_t ninsts = 0; + // disable enhanced mode an obey the origin if the polygon is not entirely inside and not at the boundary of the glue box + bool ef = enhanced_fill; + if (ef && ! glue_box.empty () && ! fp->box ().enlarged (db::Vector (1, 1)).inside (glue_box)) { + ef = false; + } + // pick a heuristic "good" starting point in enhanced mode + // TODO: this is a pretty weak optimization. db::Point o = origin; - if (enhanced_fill) { + if (ef) { o = fp->hull () [0]; } + size_t ninsts = 0; + GenericRasterizer am (*fp, row_step, column_step, o, fc_bbox.p2 () - fc_bbox.p1 ()); for (unsigned int i = 0; i < am.area_maps (); ++i) { @@ -454,7 +457,7 @@ fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell DB_PUBLIC void fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, - const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box) + const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) { const db::Region *fill_region = &fr; @@ -468,7 +471,7 @@ fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fi ++iteration; remaining.clear (); - fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, origin, true, &remaining, fill_margin, remaining_polygons, iteration, glue_box); + fill_region_impl (cell, *fill_region, fill_cell_index, fc_box, row_step, column_step, db::Point (), true, &remaining, fill_margin, remaining_polygons, iteration, glue_box); new_fill_region.swap (remaining); fill_region = &new_fill_region; diff --git a/src/db/db/dbFillTool.h b/src/db/db/dbFillTool.h index a6b5c905c..e3e060514 100644 --- a/src/db/db/dbFillTool.h +++ b/src/db/db/dbFillTool.h @@ -118,6 +118,6 @@ fill_region (db::Cell *cell, const db::Region &fp, db::cell_index_type fill_cell DB_PUBLIC void fill_region_repeat (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, - const db::Vector &fill_margin, db::Region *remaining_polygons = 0, const db::Point &origin = db::Point (), const db::Box &glue_box = db::Box ()); + const db::Vector &fill_margin, db::Region *remaining_polygons = 0, const db::Box &glue_box = db::Box ()); } diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index 6681da3f8..8fb411341 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -1312,9 +1312,9 @@ fill_region_skew (db::Cell *cell, const db::Region &fr, db::cell_index_type fill static void fill_region_multi (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, - const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box) + const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) { - db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box); + db::fill_region_repeat (cell, fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box); } static db::Instance cell_inst_dtransform_simple (db::Cell *cell, const db::Instance &inst, const db::DTrans &t) @@ -1881,7 +1881,6 @@ Class decl_Cell ("db", "Cell", gsi::arg ("column_step"), gsi::arg ("fill_margin", db::Vector ()), gsi::arg ("remaining_polygons", (db::Region *)0, "nil"), - gsi::arg ("origin", db::Point ()), gsi::arg ("glue_box", db::Box ()), "@brief Fills the given region with cells of the given type in enhanced mode with iterations\n" "This version operates like \\fill_region, but repeats the fill generation until no further fill cells can be placed. " diff --git a/src/db/db/gsiDeclDbLayout.cc b/src/db/db/gsiDeclDbLayout.cc index b950970b5..6ceeed6f6 100644 --- a/src/db/db/gsiDeclDbLayout.cc +++ b/src/db/db/gsiDeclDbLayout.cc @@ -1349,12 +1349,14 @@ Class decl_Layout ("db", "Layout", "This method is provided to ensure this explicitly. This can be useful while using \\start_changes and \\end_changes to wrap a performance-critical operation. " "See \\start_changes for more details." ) + - gsi::method ("cleanup", &db::Layout::cleanup, + gsi::method ("cleanup", &db::Layout::cleanup, gsi::arg ("cell_indexes_to_keep", std::set (), "[]"), "@brief Cleans up the layout\n" "This method will remove proxy objects that are no longer in use. After changing PCell parameters such " - "proxy objects may still be present in the layout and are cached for later reuse. Usually they are cleaned up automatically occasionally, " + "proxy objects may still be present in the layout and are cached for later reuse. Usually they are cleaned up automatically, " "but in a scripting context it may be useful to clean up these cells explicitly.\n" "\n" + "Use 'cell_indexes_to_keep' for specifying a list of cell indexes of PCell variants or library proxies you don't want to be cleaned up.\n" + "\n" "This method has been introduced in version 0.25.\n" ) + gsi::method ("dbu=", (void (db::Layout::*) (double)) &db::Layout::dbu, gsi::arg ("dbu"), diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 898e01120..c8ee01b40 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -730,9 +730,9 @@ fill_region_skew (const db::Region *fr, db::Cell *cell, db::cell_index_type fill static void fill_region_multi (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Vector &row_step, const db::Vector &column_step, - const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box) + const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) { - db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box); + db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box); } static db::Point default_origin; @@ -2921,7 +2921,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", gsi::arg ("column_step"), gsi::arg ("fill_margin", db::Vector ()), gsi::arg ("remaining_polygons", (db::Region *)0, "nil"), - gsi::arg ("origin", db::Point ()), gsi::arg ("glue_box", db::Box ()), "@brief A mapping of \\Cell#fill_region to the Region class\n" "\n" diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index d7cd228ed..9a3d2eefb 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -259,6 +259,10 @@ module DRC DRCFillOrigin::new end + def multi_origin + DRCFillOrigin::new(nil, nil, true) + end + def origin(x, y) DRCFillOrigin::new(x, y) end diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 489f2da3a..4d22374b8 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -4251,7 +4251,9 @@ CODE # @li @b origin(x, y) @/b: specifies a fixed point to align the pattern with. This point specifies the location # of the reference point for one pattern cell. @/li # @li @b auto_origin @/b: lets the algorithm choose the origin. This may result is a slightly better fill coverage - # as the algorithm is able to determine a pattern origin per fill island. @/li + # as the algorithm is able to determine a pattern origin per island to fill. @/li + # @li @b multi_origin @/b: lets the algorithm choose the origin and repeats the fill with different origins + # until no further fill cell can be fitted. @/li # @li @b fill_pattern(..) @/b: specifies the fill pattern. @/li # @/ul # @@ -4355,6 +4357,7 @@ CODE column_step = nil pattern = nil origin = RBA::DPoint::new + repeat = false args.each_with_index do |a,ai| if a.is_a?(DRCSource) @@ -4381,6 +4384,7 @@ CODE end elsif a.is_a?(DRCFillOrigin) origin = a.origin + repeat = a.repeat else raise("Argument ##{ai+1} not understood for '#{m}'") end @@ -4435,31 +4439,22 @@ CODE tp.var("cs", cs) tp.var("origin", origin) tp.var("fc_index", fc_index) + tp.var("repeat", repeat) + tp.var("with_left", with_left) - if with_left - tp.queue(<<"END") - var tc_box = _frame.bbox; - var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box; - !tile_box.empty && ( - tile_box = tile_box.enlarged(Vector.new(max(rs.x, fc_box.width), max(cs.y, fc_box.height))); - tile_box = tile_box & tc_box; - var left = Region.new; + tp.queue(<<"END") + var tc_box = _frame.bbox; + var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box; + !tile_box.empty && ( + tile_box = tile_box.enlarged(Vector.new(max(rs.x, fc_box.width), max(cs.y, fc_box.height))); + tile_box = tile_box & tc_box; + var left = with_left ? Region.new : nil; + repeat ? + (region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, Vector.new, left, _tile.bbox) : (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, Vector.new, left, _tile.bbox); - _output(#{result_arg}, left) - ) + with_left && _output(#{result_arg}, left) + ) END - else - tp.queue(<<"END") - var tc_box = _frame.bbox; - var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box; - !tile_box.empty && ( - tile_box.right = tile_box.right + rs.x - 1; - tile_box.top = tile_box.top + cs.y - 1; - tile_box = tile_box & tc_box; - (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, nil, Vector.new, nil, _tile.bbox) - ) -END - end begin @engine._output_layout.start_changes @@ -4477,10 +4472,19 @@ END end @engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do - self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, result) + if repeat + self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, RBA::Vector::new, result) + else + self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, result) + end end end + + if fill_cell.parent_cells == 0 + # fill cell not required (not placed) -> remove + fill_cell.delete + end self.data.disable_progress diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb index 283a7813d..0da810678 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -334,7 +334,8 @@ module DRC # A wrapper for the fill origin definition class DRCFillOrigin - def initialize(x = nil, y = nil) + def initialize(x = nil, y = nil, repeat = false) + @repeat = repeat if !x && !y @origin = nil else @@ -350,6 +351,9 @@ module DRC def origin @origin end + def repeat + @repeat + end end # A wrapper for the tile_size option diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 36b46732a..5d3abc750 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1222,3 +1222,13 @@ TEST(45_fillWithOverlappingBoxesTiled) { run_test (_this, "45", false); } + +TEST(46_fillWithOverlappingBoxes) +{ + run_test (_this, "46", false); +} + +TEST(47_fillWithOverlappingBoxesTiled) +{ + run_test (_this, "47", false); +} diff --git a/src/lay/lay/doc/about/drc_ref_layer.xml b/src/lay/lay/doc/about/drc_ref_layer.xml index 0d2b34c84..4b9b0554c 100644 --- a/src/lay/lay/doc/about/drc_ref_layer.xml +++ b/src/lay/lay/doc/about/drc_ref_layer.xml @@ -1044,7 +1044,9 @@ a positive value. A horizontal displacement component can be specified too, whic
  • origin(x, y) : specifies a fixed point to align the pattern with. This point specifies the location of the reference point for one pattern cell.
  • auto_origin : lets the algorithm choose the origin. This may result is a slightly better fill coverage -as the algorithm is able to determine a pattern origin per fill island.
  • +as the algorithm is able to determine a pattern origin per island to fill. +
  • multi_origin : lets the algorithm choose the origin and repeats the fill with different origins +until no further fill cell can be fitted.
  • fill_pattern(..) : specifies the fill pattern.
  • diff --git a/src/laybasic/laybasic/gsiDeclLayLayers.cc b/src/laybasic/laybasic/gsiDeclLayLayers.cc index e04356784..75fd91eac 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayers.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayers.cc @@ -835,9 +835,9 @@ Class decl_LayerProperties ("lay", "LayerProperties", "If the layer index is positive, the shapes drawn are taken from this layer rather than " "searched for by layer and datatype. This property is stronger than the layer/datatype or " "name specification.\n\n" - "The similar method \\layer_index " - "returns the actual layer index used, not the given one. The latter may be negative indicating " - "that layer/datatype or name specifications are used.\n\n" + "A different method is \\layer_index which indicates the ID of the layer actually used. " + "While \"source_layer_index\" is one of several ways to address the layer drawn, \"layer_index\" is the ID (index) " + "of the layer matching the source specification and is >= 0 if such a layer is found.\n\n" "If \"real\" is true, the effective value is returned." ) + method_ext ("source_layer_index", &get_layer_index_1, diff --git a/testdata/drc/drcSimpleTests_46.drc b/testdata/drc/drcSimpleTests_46.drc new file mode 100644 index 000000000..1278a4681 --- /dev/null +++ b/testdata/drc/drcSimpleTests_46.drc @@ -0,0 +1,25 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0) +l1.output(1, 0) + +to_fill = extent - l1 + +fp1 = fill_pattern("FP1").shape(10, 0, box(0, 0, 800.nm, 800.nm)).origin(-100.nm, -100.nm) +to_fill = to_fill.fill_with_left(fp1, hstep(1.um), vstep(200.nm, 1.um), multi_origin) + +fp2 = fill_pattern("FP2").shape(10, 0, box(0, 0, 400.nm, 400.nm)).origin(-50.nm, -50.nm) +to_fill = to_fill.fill_with_left(fp2, hstep(0.5.um), vstep(100.nm, 0.5.um), multi_origin) + +fp3 = fill_pattern("FP3").shape(10, 0, box(0, 0, 200.nm, 200.nm)).origin(-25.nm, -25.nm) +to_fill = to_fill.fill_with_left(fp3, hstep(0.25.um), vstep(50.nm, 0.25.um), multi_origin) + +to_fill.output(100, 0) + + diff --git a/testdata/drc/drcSimpleTests_46.gds b/testdata/drc/drcSimpleTests_46.gds new file mode 100644 index 000000000..e9e05712b Binary files /dev/null and b/testdata/drc/drcSimpleTests_46.gds differ diff --git a/testdata/drc/drcSimpleTests_47.drc b/testdata/drc/drcSimpleTests_47.drc new file mode 100644 index 000000000..0d4fb3a06 --- /dev/null +++ b/testdata/drc/drcSimpleTests_47.drc @@ -0,0 +1,27 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +tiles(20, 20) + +l1 = input(1, 0) +l1.output(1, 0) + +to_fill = extent - l1 + +fp1 = fill_pattern("FP1").shape(10, 0, box(0, 0, 800.nm, 800.nm)).origin(-100.nm, -100.nm) +to_fill = to_fill.fill_with_left(fp1, hstep(1.um), vstep(200.nm, 1.um), multi_origin) + +fp2 = fill_pattern("FP2").shape(10, 0, box(0, 0, 400.nm, 400.nm)).origin(-50.nm, -50.nm) +to_fill = to_fill.fill_with_left(fp2, hstep(0.5.um), vstep(100.nm, 0.5.um), multi_origin) + +fp3 = fill_pattern("FP3").shape(10, 0, box(0, 0, 200.nm, 200.nm)).origin(-25.nm, -25.nm) +to_fill = to_fill.fill_with_left(fp3, hstep(0.25.um), vstep(50.nm, 0.25.um), multi_origin) + +to_fill.output(100, 0) + + diff --git a/testdata/drc/drcSimpleTests_47.gds b/testdata/drc/drcSimpleTests_47.gds new file mode 100644 index 000000000..e9e05712b Binary files /dev/null and b/testdata/drc/drcSimpleTests_47.gds differ diff --git a/testdata/drc/drcSimpleTests_au41.gds b/testdata/drc/drcSimpleTests_au41.gds index f509aa097..edfe1a1fe 100644 Binary files a/testdata/drc/drcSimpleTests_au41.gds and b/testdata/drc/drcSimpleTests_au41.gds differ diff --git a/testdata/drc/drcSimpleTests_au46.gds b/testdata/drc/drcSimpleTests_au46.gds new file mode 100644 index 000000000..4f3ebe68b Binary files /dev/null and b/testdata/drc/drcSimpleTests_au46.gds differ diff --git a/testdata/drc/drcSimpleTests_au47.gds b/testdata/drc/drcSimpleTests_au47.gds new file mode 100644 index 000000000..18de4fcf8 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au47.gds differ