From 76982a3206e22469e67ae3e5923518146f16de1d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 29 Mar 2021 13:28:43 +0200 Subject: [PATCH] DRC support for fill, experimental --- src/db/db/gsiDeclDbBox.cc | 11 ++++ src/db/db/gsiDeclDbCell.cc | 25 ++++---- src/db/db/gsiDeclDbRegion.cc | 69 ++++++++++++++++++++++ src/drc/drc/built-in-macros/_drc_engine.rb | 28 +++++++-- src/drc/drc/built-in-macros/_drc_layer.rb | 66 ++++++++++++++++++++- src/drc/drc/built-in-macros/_drc_tags.rb | 38 ++++++++++-- 6 files changed, 211 insertions(+), 26 deletions(-) diff --git a/src/db/db/gsiDeclDbBox.cc b/src/db/db/gsiDeclDbBox.cc index e6c8c8a0a..28b1079ea 100644 --- a/src/db/db/gsiDeclDbBox.cc +++ b/src/db/db/gsiDeclDbBox.cc @@ -101,6 +101,11 @@ struct box_defs return std::hfunc (*box); } + static const C &bbox (const C *box) + { + return *box; + } + static gsi::Methods methods () { return @@ -172,6 +177,12 @@ struct box_defs method ("p2=", &C::set_p2, gsi::arg ("p"), "@brief Sets the upper right point of the box\n" ) + + method_ext ("bbox", &bbox, + "@brief Returns the bounding box\n" + "This method is provided for consistency of the shape API is returns the box itself.\n" + "\n" + "This method has been introduced in version 0.27." + ) + method_ext ("contains?", &box_defs::contains, gsi::arg ("x"), gsi::arg ("y"), "@brief Returns true if the box contains the given point\n" "\n" diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index b33c7005b..5fc4c6dc9 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -1298,21 +1298,21 @@ static void move_tree_shapes3 (db::Cell *cell, db::Cell &source_cell, const db:: static void fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin, - db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) + db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) { - db::fill_region (cell, fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0 || !glue_box.empty (), remaining_parts, fill_margin, remaining_polygons, glue_box); + db::fill_region (cell, fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box); } static void fill_region_skew (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point *origin, - db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) + db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) { - db::fill_region (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0 || !glue_box.empty (), remaining_parts, fill_margin, remaining_polygons, glue_box); + db::fill_region (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box); } static void fill_region_multi (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, 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::Point &origin, const db::Box &glue_box) { db::fill_region_repeat (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box); } @@ -1846,7 +1846,7 @@ Class decl_Cell ("db", "Cell", ) + gsi::method_ext ("fill_region", &fill_region_skew, gsi::arg ("region"), gsi::arg ("fill_cell_index"), - gsi::arg ("kernel_origin"), + gsi::arg ("fc_origin"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("origin", &default_origin, "(0, 0)"), @@ -1857,23 +1857,22 @@ Class decl_Cell ("db", "Cell", "@brief Fills the given region with cells of the given type (skew step version)\n" "@param region The region to fill\n" "@param fill_cell_index The fill cell to place\n" - "@param kernel_origin The fill cell's footprint\n" - "@param row_step The fill cell's footprint\n" - "@param column_step The fill cell's footprint\n" + "@param fc_origin The location of the reference point of the fill cell\n" + "@param row_step The 'rows' step vector\n" + "@param column_step The 'columns' step vector\n" "@param origin The global origin of the fill pattern or nil to allow local (per-polygon) optimization\n" "@param remaining_parts See explanation in other version\n" "@param fill_margin See explanation in other version\n" "@param remaining_polygons See explanation in other version\n" "\n" - "This version is similar to the version providing a rectangular fill kernel, but it offers a more generic, diamond-shaped kernel.\n" - "The kerne is defined by an origin and two vectors (row_step and column_step) which span the diamond.\n" - "This version will try to fit as many of these diamond-shaped kernels into the region to fill.\n" + "This version is similar to the version providing a rectangular fill kernel, but it offers more generic stepping of the fill cell.\n" + "The step pattern is defined by an origin and two vectors (row_step and column_step) which span the axes of the fill cell pattern.\n" "\n" "This variant has been introduced in version 0.27.\n" ) + gsi::method_ext ("fill_region_multi", &fill_region_multi, gsi::arg ("region"), gsi::arg ("fill_cell_index"), - gsi::arg ("kernel_origin"), + gsi::arg ("fc_origin"), gsi::arg ("row_step"), gsi::arg ("column_step"), gsi::arg ("fill_margin", db::Vector ()), diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 9ebd1d2c0..37265b2e1 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -32,6 +32,7 @@ #include "dbShapes.h" #include "dbDeepShapeStore.h" #include "dbRegion.h" +#include "dbFillTool.h" #include "dbRegionProcessors.h" #include "dbCompoundOperation.h" #include "tlGlobPattern.h" @@ -675,6 +676,29 @@ tl::Variant complex_op (db::Region *region, db::CompoundRegionOperationNode *nod } } +static void +fill_region (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin, + db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) +{ + db::fill_region (cell, *fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box); +} + +static void +fill_region_skew (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point *origin, + db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box) +{ + db::fill_region (cell, *fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box); +} + +static void +fill_region_multi (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, 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) +{ + db::fill_region_repeat (cell, *fr, fill_cell_index, kernel_origin, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box); +} + +static db::Point default_origin; + // provided by gsiDeclDbPolygon.cc: int td_simple (); int po_any (); @@ -2748,6 +2772,51 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "See \\base_verbosity= for details.\n" "\n" "This method has been introduced in version 0.26.\n" + ) + + gsi::method_ext ("fill", &fill_region, gsi::arg ("in_cell"), + gsi::arg ("fill_cell_index"), + gsi::arg ("fc_box"), + gsi::arg ("origin", &default_origin, "(0, 0)"), + gsi::arg ("remaining_parts", (db::Region *)0, "nil"), + gsi::arg ("fill_margin", db::Vector ()), + gsi::arg ("remaining_polygons", (db::Region *)0, "nil"), + gsi::arg ("glue_box", db::Box ()), + "@brief A mapping of \\Cell#fill_region to the Region class\n" + "\n" + "This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n" + "\n" + "This method has been introduced in version 0.27.\n" + ) + + gsi::method_ext ("fill", &fill_region_skew, gsi::arg ("in_cell"), + gsi::arg ("fill_cell_index"), + gsi::arg ("fc_origin"), + gsi::arg ("row_step"), + gsi::arg ("column_step"), + gsi::arg ("origin", &default_origin, "(0, 0)"), + gsi::arg ("remaining_parts", (db::Region *)0, "nil"), + gsi::arg ("fill_margin", db::Vector ()), + gsi::arg ("remaining_polygons", (db::Region *)0, "nil"), + gsi::arg ("glue_box", db::Box ()), + "@brief A mapping of \\Cell#fill_region to the Region class\n" + "\n" + "This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n" + "\n" + "This method has been introduced in version 0.27.\n" + ) + + gsi::method_ext ("fill_multi", &fill_region_multi, gsi::arg ("in_cell"), + gsi::arg ("fill_cell_index"), + gsi::arg ("fc_origin"), + gsi::arg ("row_step"), + 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" + "This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n" + "\n" + "This method has been introduced in version 0.27.\n" ), "@brief A region (a potentially complex area consisting of multiple polygons)\n" "\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 d84f3f9e3..d3270ad30 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -211,16 +211,16 @@ module DRC end end - def fill_cell(name) + def fill_pattern(name) DRCFillCell::new(name) end def hstep(x, y = nil) - DRCFillStep(true, x, y) + DRCFillStep::new(true, x, y) end def vstep(x, y = nil) - DRCFillStep(false, x, y) + DRCFillStep::new(false, x, y) end def auto_origin @@ -1967,7 +1967,7 @@ CODE end # disable progress again - if obj.is_a?(RBA::Region) + if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts) obj.disable_progress end @@ -2022,7 +2022,7 @@ CODE end # disable progress again - if obj.is_a?(RBA::Region) + if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts) obj.disable_progress end @@ -2065,7 +2065,7 @@ CODE end # disable progress again - if obj.is_a?(RBA::Region) + if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts) obj.disable_progress end @@ -2084,6 +2084,22 @@ CODE obj.send(method, *args) end end + + def _bx + @bx + end + + def _by + @by + end + + def _tx + @tx + end + + def _ty + @ty + end def _start diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 9f50b664e..752013a8c 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -3898,6 +3898,9 @@ CODE def fill(*args) + # generation of new cells not tested in deep mode + @deep && raise("fill command not supported in deep mode currently") + m = "fill" source = @engine.source @@ -3922,12 +3925,12 @@ CODE if row_step raise("Duplicate hstep specification for '#{m}' at argument ##{ai+1}") end - row_step = a + row_step = a.step else if column_step raise("Duplicate vstep specification for '#{m}' at argument ##{ai+1}") end - column_step = a + column_step = a.step end elsif a.is_a?(DRCFillOrigin) origin = a.origin @@ -3937,7 +3940,7 @@ CODE end if !pattern - raise("No fill pattern given for '#{m}'") + raise("No fill pattern given for '#{m}' (use 'fill_pattern')") end if !row_step @@ -3947,7 +3950,64 @@ CODE column_step = RBA::DVector::new(0, pattern.bbox.height) end + dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu) + fill_cell = pattern.create_cell(source.layout) + top_cell = source.cell_obj + ko = dbu_trans * pattern.cell_origin + rs = dbu_trans * row_step + cs = dbu_trans * column_step + origin = origin ? dbu_trans * origin : nil + fc_index = fill_cell.cell_index + + if @engine._tx && @engine._ty + + tp = RBA::TilingProcessor::new + tp.dbu = @engine.dbu + tp.scale_to_dbu = false + tp.tile_size(@engine._tx, @engine._ty) + bx = [ @engine._bx || 0.0, row_step.x ].max + by = [ @engine._by || 0.0, column_step.y ].max + tp.tile_border(bx, by) + tp.threads = (@engine.threads || 1) + + tp.input("region", self.data) + tp.var("top_cell", top_cell) + tp.var("ko", ko) + tp.var("rs", rs) + tp.var("cs", cs) + tp.var("origin", origin) + tp.var("fc_index", fc_index) + + tp.queue(<<"END") +var tc_box = top_cell.bbox; +var tile_box = _tile ? (tc_box & _tile.bbox) : top_cell.bbox; +!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, ko, rs, cs, origin, nil, Vector.new, nil, _tile.bbox) +) +END + + begin + source.layout.start_changes + @engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do + tp.execute("Tiled \"#{m}\" in: #{@engine.src_line}") + end + ensure + source.layout.end_changes + end + + else + + @engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do + self.data.fill(top_cell, fc_index, ko, rs, cs, origin) + end + + end + + self.data.disable_progress end diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb index b49d1ce7d..4280db894 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -190,6 +190,27 @@ module DRC @origin = RBA::DVector::new end + def create_cell(layout) + cell = layout.create_cell(@cell_name) + @shapes.each do |s| + li = layout.layer(s[0]) + s[1].each { |t| cell.shapes(li).insert(t) } + end + cell + end + + def cell_origin + @origin + end + + def bbox + box = RBA::DBox::new + @shapes.each do |s| + s[1].each { |t| box += t.bbox } + end + box + end + def shape(*args) layer = nil @@ -201,7 +222,6 @@ module DRC if a.is_a?(1.class) if !layer layer = a - datatype = 0 elsif !datatype datatype = a else @@ -223,17 +243,24 @@ module DRC if !shapes.empty? li = RBA::LayerInfo::new - layer && li.layer = layer - datatype && li.datatype = datatype - name && li.name = name + if layer + li.layer = layer + li.datatype = datatype || 0 + end + if name + li.name = name + end @shapes << [ li, shapes ] end + + self end def origin(x, y) + if !x.is_a?(1.class) && !x.is_a?(1.0.class) raise("x argument not numeric FillCell#origin") end @@ -241,6 +268,9 @@ module DRC raise("y argument not numeric FillCell#origin") end @origin = RBA::DVector::new(x, y) + + self + end end