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