mirror of https://github.com/KLayout/klayout.git
commit
d9ab2ed1a6
|
|
@ -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 <db::Polygon> 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;
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<db::Cell> 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. "
|
||||
|
|
|
|||
|
|
@ -1349,12 +1349,14 @@ Class<db::Layout> 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<db::cell_index_type> (), "[]"),
|
||||
"@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"),
|
||||
|
|
|
|||
|
|
@ -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<db::Region> 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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1044,7 +1044,9 @@ a positive value. A horizontal displacement component can be specified too, whic
|
|||
<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>
|
||||
</p><p>
|
||||
|
|
|
|||
|
|
@ -835,9 +835,9 @@ Class<lay::LayerProperties> 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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
Binary file not shown.
|
|
@ -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)
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue