diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index d731f059d..14c4c0f71 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -1378,14 +1378,16 @@ AsIfFlatRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const } RegionDelegate * -AsIfFlatRegion::sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode) const +AsIfFlatRegion::sized_inside (const Region &inside, bool outside, coord_type d, int steps, unsigned int mode) const { - return sized_inside (inside, d, d, steps, mode); + return sized_inside (inside, outside, d, d, steps, mode); } RegionDelegate * -AsIfFlatRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const +AsIfFlatRegion::sized_inside (const Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode) const { + // @@@ TODO: restrict max. number of steps in "outside" mode like for DeepRegion + if (steps <= 0 || empty ()) { // Nothing to do - NOTE: don't return EmptyRegion because we want to // maintain "deepness" @@ -1400,7 +1402,10 @@ AsIfFlatRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy std::vector results; results.push_back (&output->raw_polygons ()); - db::sized_inside_local_operation op (dx, dy, steps, mode, true /*inside layer is merged*/); + // NOTE: as we merge the inside region in the inside case, we can use distance 0 + db::Coord dist = outside ? std::max (dx, dy) : 0; + bool inside_is_merged = outside ? inside.is_merged () : true; + db::sized_inside_local_operation op (dx, dy, steps, mode, dist, outside, inside_is_merged, true /*split after*/); db::local_processor proc; proc.set_base_verbosity (base_verbosity ()); @@ -1408,7 +1413,8 @@ AsIfFlatRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy proc.set_report_progress (report_progress ()); std::vector > others; - others.push_back (inside.begin_merged ()); + // NOTE: it does not provide benefits to merge the outside region, so just don't + others.push_back (outside ? inside.begin () : inside.begin_merged ()); proc.run_flat (begin_merged (), others, std::vector (), &op, results); diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index b517ddc90..f06c4c362 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -121,8 +121,8 @@ public: virtual RegionDelegate *sized (coord_type d, unsigned int mode) const; virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const; - virtual RegionDelegate *sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode) const; - virtual RegionDelegate *sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const; + virtual RegionDelegate *sized_inside (const Region &inside, bool outside, coord_type d, int steps, unsigned int mode) const; + virtual RegionDelegate *sized_inside (const Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode) const; virtual RegionDelegate *and_with (const Region &other, PropertyConstraint property_constraint) const; virtual RegionDelegate *not_with (const Region &other, PropertyConstraint property_constraint) const; diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 52578aba8..3435f6c2d 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1782,14 +1782,17 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const } RegionDelegate * -DeepRegion::sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode) const +DeepRegion::sized_inside (const Region &inside, bool outside, coord_type d, int steps, unsigned int mode) const { - return sized_inside (inside, d, d, steps, mode); + return sized_inside (inside, outside, d, d, steps, mode); } RegionDelegate * -DeepRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const +DeepRegion::sized_inside (const Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode) const { + // empirical value + const int max_steps = 25; + if (steps <= 0 || empty ()) { // Nothing to do - NOTE: don't return EmptyRegion because we want to // maintain "deepness" @@ -1805,20 +1808,58 @@ DeepRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, in return db::AsIfFlatRegion::sized_inside (inside, dx, dy, steps, mode); } + // NOTE: it does not provide benefits to merge the outside region, so just don't + const db::DeepLayer &inside_polygons = outside ? inside_deep->deep_layer () : inside_deep->merged_deep_layer (); + bool inside_polygons_is_merged = outside ? inside_deep->is_merged () : true; + const db::DeepLayer &polygons = merged_deep_layer (); - const db::DeepLayer &inside_polygons = inside_deep->merged_deep_layer (); - - db::sized_inside_local_operation op (dx, dy, steps, mode, true /*inside layer is merged*/); - - db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &inside_polygons.layout (), &inside_polygons.initial_cell (), polygons.breakout_cells (), inside_polygons.breakout_cells ()); - configure_proc (proc); - proc.set_threads (polygons.store ()->threads ()); - proc.set_area_ratio (polygons.store ()->max_area_ratio ()); - proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); std::unique_ptr res (new db::DeepRegion (polygons.derived ())); + std::unique_ptr prev; - proc.run (&op, polygons.layer (), inside_polygons.layer (), res->deep_layer ().layer ()); + int steps_from = 0; + + while (steps > 0) { + + db::Coord dx_chunk = dx, dy_chunk = dy; + int steps_chunk = steps; + + // In outside mode, we perform at most max_steps in one chunk. + // This is supposed to limit the search range. + if (outside && steps > max_steps) { + steps_chunk = max_steps; + dx_chunk = db::coord_traits::rounded (dx * max_steps / double (steps)); + dy_chunk = db::coord_traits::rounded (dy * max_steps / double (steps)); + } + + steps -= steps_chunk; + dx -= dx_chunk; + dy -= dy_chunk; + + // NOTE: as we merge the inside region in the inside case, we can use distance 0 + db::Coord dist = outside ? std::max (dx_chunk, dy_chunk) : 0; + bool split_after = (steps == 0); + db::sized_inside_local_operation op (dx_chunk, dy_chunk, steps_chunk, mode, dist, outside, inside_polygons_is_merged, split_after); + + db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &inside_polygons.layout (), &inside_polygons.initial_cell (), polygons.breakout_cells (), inside_polygons.breakout_cells ()); + configure_proc (proc); + proc.set_threads (polygons.store ()->threads ()); + proc.set_area_ratio (polygons.store ()->max_area_ratio ()); + proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); + + // indicate chunk in the progress description + proc.set_description (proc.description (&op) + tl::sprintf (tl::to_string (tr (" (steps %d..%d)")), steps_from + 1, steps_from + steps_chunk + 1)); + + proc.run (&op, prev.get () ? prev->deep_layer ().layer () : polygons.layer (), inside_polygons.layer (), res->deep_layer ().layer ()); + + // @@@ TODO: should we also merge in the last step and consider splitting? + if (steps > 0) { + prev.reset (dynamic_cast (res->merged ())); + tl_assert (prev.get () != 0); + res.reset (new db::DeepRegion (polygons.derived ())); + } + + } return res.release (); } diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 1102c194a..2c56edb12 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -136,8 +136,8 @@ public: virtual RegionDelegate *sized (coord_type d, unsigned int mode) const; virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const; - virtual RegionDelegate *sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode) const; - virtual RegionDelegate *sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const; + virtual RegionDelegate *sized_inside (const Region &inside, bool outside, coord_type d, int steps, unsigned int mode) const; + virtual RegionDelegate *sized_inside (const Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode) const; virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; diff --git a/src/db/db/dbEmptyRegion.h b/src/db/db/dbEmptyRegion.h index 2170b5546..4529c159c 100644 --- a/src/db/db/dbEmptyRegion.h +++ b/src/db/db/dbEmptyRegion.h @@ -97,8 +97,8 @@ public: virtual RegionDelegate *sized (coord_type, unsigned int) const { return new EmptyRegion (); } virtual RegionDelegate *sized (coord_type, coord_type, unsigned int) const { return new EmptyRegion (); } - virtual RegionDelegate *sized_inside (const Region &, coord_type, int, unsigned int) const { return new EmptyRegion (); } - virtual RegionDelegate *sized_inside (const Region &, coord_type, coord_type, int, unsigned int) const { return new EmptyRegion (); } + virtual RegionDelegate *sized_inside (const Region &, bool, coord_type, int, unsigned int) const { return new EmptyRegion (); } + virtual RegionDelegate *sized_inside (const Region &, bool, coord_type, coord_type, int, unsigned int) const { return new EmptyRegion (); } virtual RegionDelegate *and_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); } virtual RegionDelegate *not_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); } diff --git a/src/db/db/dbRegion.cc b/src/db/db/dbRegion.cc index f68f5ca89..a8294dffa 100644 --- a/src/db/db/dbRegion.cc +++ b/src/db/db/dbRegion.cc @@ -310,29 +310,29 @@ Region::sized (coord_type dx, coord_type dy, unsigned int mode) const } Region & -Region::size_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode) +Region::size_inside (const db::Region &inside, bool outside, coord_type d, int steps, unsigned int mode) { - set_delegate (mp_delegate->sized_inside (inside, d, steps, mode)); + set_delegate (mp_delegate->sized_inside (inside, outside, d, steps, mode)); return *this; } Region & -Region::size_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) +Region::size_inside (const db::Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode) { - set_delegate (mp_delegate->sized_inside (inside, dx, dy, steps, mode)); + set_delegate (mp_delegate->sized_inside (inside, outside, dx, dy, steps, mode)); return *this; } Region -Region::sized_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode) const +Region::sized_inside (const db::Region &inside, bool outside, coord_type d, int steps, unsigned int mode) const { - return Region (mp_delegate->sized_inside (inside, d, steps, mode)); + return Region (mp_delegate->sized_inside (inside, outside, d, steps, mode)); } Region -Region::sized_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const +Region::sized_inside (const db::Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode) const { - return Region (mp_delegate->sized_inside (inside, dx, dy, steps, mode)); + return Region (mp_delegate->sized_inside (inside, outside, dx, dy, steps, mode)); } void diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index 8e7ad5678..3ed7d96ae 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -1035,12 +1035,13 @@ public: * Only positive or zero sizing values are supported. * * @param inside The confinement region + * @param outside If true, "inside" is negative - i.e. sizing is performed outside the "inside" region * @param d The (isotropic) sizing value * @param steps The number of steps to take * @param mode The sizing mode (see EdgeProcessor) for a description of the sizing mode which controls the miter distance. * @return A reference to self */ - Region &size_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode = 2); + Region &size_inside (const db::Region &inside, bool outside, coord_type d, int steps, unsigned int mode = 2); /** * @brief Size the region incrementally and anisotropically @@ -1050,13 +1051,14 @@ public: * Only positive or zero sizing values are supported. * * @param inside The confinement region + * @param outside If true, "inside" is negative - i.e. sizing is performed outside the "inside" region * @param dx The x sizing value * @param dy The y sizing value * @param steps The number of steps to take * @param mode The sizing mode (see EdgeProcessor) for a description of the sizing mode which controls the miter distance. * @return A reference to self */ - Region &size_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode = 2); + Region &size_inside (const db::Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode = 2); /** * @brief Returns the sized region @@ -1066,7 +1068,7 @@ public: * * Merged semantics applies. */ - Region sized_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode = 2) const; + Region sized_inside (const db::Region &inside, bool outside, coord_type d, int steps, unsigned int mode = 2) const; /** * @brief Returns the sized region @@ -1076,7 +1078,7 @@ public: * * Merged semantics applies. */ - Region sized_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode = 2) const; + Region sized_inside (const db::Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode = 2) const; /** * @brief Boolean AND operator diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index 137aa7ac4..7bbc64c9d 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -226,8 +226,8 @@ public: virtual RegionDelegate *sized (coord_type d, unsigned int mode) const = 0; virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const = 0; - virtual RegionDelegate *sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode) const = 0; - virtual RegionDelegate *sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const = 0; + virtual RegionDelegate *sized_inside (const Region &inside, bool outside, coord_type d, int steps, unsigned int mode) const = 0; + virtual RegionDelegate *sized_inside (const Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode) const = 0; virtual RegionDelegate *and_with (const Region &other, PropertyConstraint prop_constraint) const = 0; virtual RegionDelegate *not_with (const Region &other, PropertyConstraint prop_constraint) const = 0; diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index a7142ad9c..c475089ea 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -1948,13 +1948,10 @@ template class DB_PUBLIC two_bool_and_not_local_operation_with_properties -sized_inside_local_operation::sized_inside_local_operation (db::Coord dx, db::Coord dy, int steps, unsigned int mode, bool inside_is_merged) - : m_dx (dx), m_dy (dy), m_steps (steps), m_mode (mode), m_dist (0) +sized_inside_local_operation::sized_inside_local_operation (db::Coord dx, db::Coord dy, int steps, unsigned int mode, db::Coord dist, bool outside, bool inside_is_merged, bool split_after) + : m_dx (dx), m_dy (dy), m_dist (dist), m_steps (steps), m_mode (mode), m_outside (outside), m_inside_is_merged (inside_is_merged), m_split_after (split_after) { - m_dist = 0; - if (! inside_is_merged) { - m_dist = std::max (0, std::max (m_dx, m_dy)); - } + // .. nothing yet .. } template @@ -2011,6 +2008,24 @@ sized_inside_local_operation::do_compute_local (db::Layout *layout, } } + // Merge the inside region shapes as we are going to use them multiple times + std::vector inside_merged; + if (inside.size () > 1 && ! m_inside_is_merged && m_steps > 1) { + + db::EdgeProcessor ep; + db::SimpleMerge op; + db::EdgeContainer ec (inside_merged); + + db::EdgeProcessor::property_type p = 0; + for (auto i = inside.begin (); i != inside.end (); ++i, ++p) { + ep.insert (**i, p); + } + ep.process (ec, op); + + inside.clear (); + + } + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { subjects.push_back (db::Polygon ()); interactions.subject_shape (i->first).instantiate (subjects.back ()); @@ -2021,9 +2036,6 @@ sized_inside_local_operation::do_compute_local (db::Layout *layout, db::EdgeProcessor ep_and; ep_and.set_base_verbosity (50); - db::EdgeProcessor ep_interact; - ep_interact.set_base_verbosity (50); - // the main sizing loop db::Coord sx_last = 0, sy_last = 0; @@ -2050,10 +2062,15 @@ sized_inside_local_operation::do_compute_local (db::Layout *layout, ep_and.insert (**i, p); p += 2; } + for (auto i = inside_merged.begin (); i != inside_merged.end (); ++i) { + ep_and.insert (*i, p); + } db::PolygonContainer pc (subjects, true /*clear*/); - db::PolygonGenerator pg (pc, false /*don't resolve holes*/, false /*min. coherence*/); - db::BooleanOp op (db::BooleanOp::And); + db::PolygonSplitter splitter (pc, proc->area_ratio (), proc->max_vertex_count ()); + // NOTE: we split in the last step if requested + db::PolygonGenerator pg ((! m_split_after || step + 1 < m_steps) ? (PolygonSink &) pc : (PolygonSink &) splitter, false /*don't resolve holes*/, false /*min. coherence*/); + db::BooleanOp op (m_outside ? db::BooleanOp::ANotB : db::BooleanOp::And); ep_and.process (pg, op); } diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index 46ff57814..c89bd8474 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -471,7 +471,7 @@ class DB_PUBLIC sized_inside_local_operation : public local_operation { public: - sized_inside_local_operation (db::Coord dx, db::Coord dy, int steps, unsigned int mode, bool inside_is_merged); + sized_inside_local_operation (db::Coord dx, db::Coord dy, int steps, unsigned int mode, db::Coord dist, bool outside, bool inside_is_merged, bool split_after); virtual db::Coord dist () const; virtual OnEmptyIntruderHint on_empty_intruder_hint () const; @@ -489,6 +489,9 @@ private: db::Coord m_dist; int m_steps; unsigned int m_mode; + bool m_outside; + bool m_inside_is_merged; + bool m_split_after; db::MagnificationAndOrientationReducer m_vars_anisotropic; db::MagnificationReducer m_vars_isotropic; }; diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index dab1e9ed8..8e98a9656 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -1008,16 +1008,81 @@ size_dvm (db::Region *region, const db::Vector &dv, unsigned int mode) return *region; } +static db::Region +sized_inside_ddm (const db::Region *region, const db::Region &inside, db::Coord dx, db::Coord dy, int steps, unsigned int mode) +{ + return region->sized_inside (inside, false, dx, dy, steps, mode); +} + static db::Region sized_inside_dvm (const db::Region *region, const db::Region &inside, const db::Vector &dv, int steps, unsigned int mode) { - return region->sized_inside (inside, dv.x (), dv.y (), steps, mode); + return region->sized_inside (inside, false, dv.x (), dv.y (), steps, mode); +} + +static db::Region +sized_inside_dm (const db::Region *region, const db::Region &inside, db::Coord d, int steps, unsigned int mode) +{ + return region->sized_inside (inside, false, d, steps, mode); +} + +static db::Region & +size_inside_ddm (db::Region *region, const db::Region &inside, db::Coord dx, db::Coord dy, int steps, unsigned int mode) +{ + region->size_inside (inside, false, dx, dy, steps, mode); + return *region; } static db::Region & size_inside_dvm (db::Region *region, const db::Region &inside, const db::Vector &dv, int steps, unsigned int mode) { - region->sized_inside (inside, dv.x (), dv.y (), steps, mode); + region->size_inside (inside, false, dv.x (), dv.y (), steps, mode); + return *region; +} + +static db::Region & +size_inside_dm (db::Region *region, const db::Region &inside, db::Coord d, int steps, unsigned int mode) +{ + region->size_inside (inside, false, d, steps, mode); + return *region; +} + +static db::Region +sized_outside_ddm (const db::Region *region, const db::Region &inside, db::Coord dx, db::Coord dy, int steps, unsigned int mode) +{ + return region->sized_inside (inside, true, dx, dy, steps, mode); +} + +static db::Region +sized_outside_dvm (const db::Region *region, const db::Region &inside, const db::Vector &dv, int steps, unsigned int mode) +{ + return region->sized_inside (inside, true, dv.x (), dv.y (), steps, mode); +} + +static db::Region +sized_outside_dm (const db::Region *region, const db::Region &inside, db::Coord d, int steps, unsigned int mode) +{ + return region->sized_inside (inside, true, d, steps, mode); +} + +static db::Region & +size_outside_ddm (db::Region *region, const db::Region &inside, db::Coord dx, db::Coord dy, int steps, unsigned int mode) +{ + region->size_inside (inside, true, dx, dy, steps, mode); + return *region; +} + +static db::Region & +size_outside_dvm (db::Region *region, const db::Region &inside, const db::Vector &dv, int steps, unsigned int mode) +{ + region->size_inside (inside, true, dv.x (), dv.y (), steps, mode); + return *region; +} + +static db::Region & +size_outside_dm (db::Region *region, const db::Region &inside, db::Coord d, int steps, unsigned int mode) +{ + region->size_inside (inside, true, d, steps, mode); return *region; } @@ -1942,7 +2007,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + - method ("size_inside", (db::Region & (db::Region::*) (const db::Region &, db::Coord, db::Coord, int, unsigned int)) &db::Region::size_inside, gsi::arg ("inside"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("steps"), gsi::arg ("mode"), + method_ext ("size_inside", &size_inside_ddm, gsi::arg ("inside"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("steps"), gsi::arg ("mode"), "@brief Incremental, anisotropic sizing inside of another region\n" "\n" "@param inside The region the incremental sizing will stay inside.\n" @@ -1967,6 +2032,14 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.29.3." ) + + method_ext ("size_outside", &size_outside_ddm, gsi::arg ("outside"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("steps"), gsi::arg ("mode"), + "@brief Incremental, anisotropic sizing outside of another region\n" + "\n" + "This method is equivalent to \\size_inside, except that sizing is performed outside the given 'outside' region. " + "Technically this corresponds to a boolean 'NOT' operation instead of a boolean 'AND'.\n" + "\n" + "This method has been introduced in version 0.29.3." + ) + method_ext ("size_inside", &size_inside_dvm, gsi::arg ("inside"), gsi::arg ("dv"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), "@brief Incremental, anisotropic sizing inside of another region\n" "\n" @@ -1978,7 +2051,15 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.29.3." ) + - method ("size_inside", (db::Region & (db::Region::*) (const db::Region &, db::Coord, int, unsigned int)) &db::Region::size_inside, gsi::arg ("inside"), gsi::arg ("d"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), + method_ext ("size_outside", &size_outside_dvm, gsi::arg ("outside"), gsi::arg ("dv"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), + "@brief Incremental, anisotropic sizing outside of another region\n" + "\n" + "This method is equivalent to \\size_inside, except that sizing is performed outside the given 'outside' region. " + "Technically this corresponds to a boolean 'NOT' operation instead of a boolean 'AND'.\n" + "\n" + "This method has been introduced in version 0.29.3." + ) + + method_ext ("size_inside", &size_inside_dm, gsi::arg ("inside"), gsi::arg ("d"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), "@brief Incremental, isotropic sizing inside of another region\n" "\n" "@return The region after the sizing has applied (self)\n" @@ -1989,7 +2070,15 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.29.3." ) + - method ("sized_inside", (db::Region (db::Region::*) (const db::Region &, db::Coord, db::Coord, int, unsigned int) const) &db::Region::sized_inside, gsi::arg ("inside"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("steps"), gsi::arg ("mode"), + method_ext ("size_outside", &size_outside_dm, gsi::arg ("outside"), gsi::arg ("d"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), + "@brief Incremental, anisotropic sizing outside of another region\n" + "\n" + "This method is equivalent to \\size_inside, except that sizing is performed outside the given 'outside' region. " + "Technically this corresponds to a boolean 'NOT' operation instead of a boolean 'AND'.\n" + "\n" + "This method has been introduced in version 0.29.3." + ) + + method_ext ("sized_inside", &sized_inside_ddm, gsi::arg ("inside"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("steps"), gsi::arg ("mode"), "@brief Returns the incrementally and anisotropically sized region\n" "\n" "@return The sized region\n" @@ -1998,6 +2087,14 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("sized_outside", &sized_outside_ddm, gsi::arg ("outside"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("steps"), gsi::arg ("mode"), + "@brief Incremental, anisotropic sizing outside of another region\n" + "\n" + "This method is equivalent to \\size_inside, except that sizing is performed outside the given 'outside' region. " + "Technically this corresponds to a boolean 'NOT' operation instead of a boolean 'AND'.\n" + "\n" + "This method has been introduced in version 0.29.3." + ) + method_ext ("sized_inside", &sized_inside_dvm, gsi::arg ("inside"), gsi::arg ("dv"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), "@brief Returns the incrementally and anisotropically sized region\n" "\n" @@ -2009,7 +2106,15 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This variant has been introduced in version 0.28." ) + - method ("sized_inside", (db::Region (db::Region::*) (const db::Region &, db::Coord, int, unsigned int) const) &db::Region::sized_inside, gsi::arg ("inside"), gsi::arg ("d"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), + method_ext ("sized_outside", &sized_outside_dvm, gsi::arg ("outside"), gsi::arg ("dv"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), + "@brief Incremental, anisotropic sizing outside of another region\n" + "\n" + "This method is equivalent to \\size_inside, except that sizing is performed outside the given 'outside' region. " + "Technically this corresponds to a boolean 'NOT' operation instead of a boolean 'AND'.\n" + "\n" + "This method has been introduced in version 0.29.3." + ) + + method_ext ("sized_inside", &sized_inside_dm, gsi::arg ("inside"), gsi::arg ("d"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), "@brief Returns the incrementally sized region\n" "\n" "@return The sized region\n" @@ -2018,6 +2123,14 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("sized_outside", &sized_outside_dm, gsi::arg ("outside"), gsi::arg ("d"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), + "@brief Incremental, anisotropic sizing outside of another region\n" + "\n" + "This method is equivalent to \\size_inside, except that sizing is performed outside the given 'outside' region. " + "Technically this corresponds to a boolean 'NOT' operation instead of a boolean 'AND'.\n" + "\n" + "This method has been introduced in version 0.29.3." + ) + method_ext ("andnot", &andnot, gsi::arg ("other"), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), "@brief Returns the boolean AND and NOT between self and the other region\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 0ec05992a..90a63eb43 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -321,6 +321,10 @@ module DRC DRCSizingInside::new(arg) end + def outside(arg) + DRCSizingOutside::new(arg) + end + def padding_zero DRCDensityPadding::new(:zero) end diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index faa10e974..71cb01ccb 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -4333,7 +4333,7 @@ CODE value && raise("Value already specified") value = @engine._make_value(a) else - raise("Parameter #" + n.to_s + " does not have an expected type") + raise("Parameter #" + n.to_s + " if of unexpected type") end n += 1 end @@ -4518,7 +4518,7 @@ CODE limits = [ @engine._make_numeric_value_with_nil(a.begin), @engine._make_numeric_value_with_nil(a.end) ] nlimits = 2 else - raise("Parameter #" + n.to_s + " does not have an expected type") + raise("Parameter #" + n.to_s + " is of unexpected type") end n += 1 end @@ -4679,7 +4679,11 @@ TP_SCRIPT # @name sized # @brief Polygon sizing (per-edge biasing) # @synopsis layer.sized(d [, mode] [, inside(l) [, steps(n)]]) - # @synopsis layer.sized(dx, dy [, mode] [, inside(l) [, steps(n)]])) + # @synopsis layer.sized(d, inside(l) [, steps(n)] [, mode]) + # @synopsis layer.sized(d, outside(l) [, steps(n)] [, mode]) + # @synopsis layer.sized(dx, dy [, mode]) + # @synopsis layer.sized(dx, dy, inside(l) [, steps(n)] [, mode]) + # @synopsis layer.sized(dx, dy, outside(l) [, steps(n)] [, mode]) # # This method requires a polygon layer. It will apply a bias per edge of the polygons # and return the biased layer. The layer that this method is called on is not modified. @@ -4725,6 +4729,10 @@ TP_SCRIPT # # "inside" and "steps" can be used with positive sizing values only. # + # "outside" acts like "inside", but instead of confining the sized region to the + # inside of the given layer, it is confined to be outside of that layer. Technically, + # a boolean "NOT" is performed instead of a boolean "AND". + # # An example for the "inside" option is this: # # @code @@ -4753,8 +4761,12 @@ TP_SCRIPT # %DRC% # @name size # @brief Polygon sizing (per-edge biasing, modifies the layer) - # @synopsis layer.size(d [, mode] [, inside(l) [, steps(n)]]) - # @synopsis layer.size(dx, dy [, mode] [, inside(l) [, steps(n)]])) + # @synopsis layer.size(d [, mode]) + # @synopsis layer.size(d, inside(l) [, steps(n)] [, mode]) + # @synopsis layer.size(d, outside(l) [, steps(n)] [, mode]) + # @synopsis layer.size(dx, dy [, mode]) + # @synopsis layer.size(dx, dy, inside(l) [, steps(n)] [, mode]) + # @synopsis layer.size(dx, dy, outside(l) [, steps(n)] [, mode]) # # See \sized for a description of the options. # The size method basically does the same but modifies the layer @@ -4772,8 +4784,11 @@ TP_SCRIPT steps = nil inside = nil + outside = nil mode = 2 values = [] + + n = 1 args.each do |a| if a.is_a?(1.class) || a.is_a?(Float) v = @engine._make_value(a) @@ -4785,7 +4800,12 @@ TP_SCRIPT steps = a.value elsif a.is_a?(DRCSizingInside) inside = a.value + elsif a.is_a?(DRCSizingOutside) + outside = a.value + else + raise("Parameter #" + n.to_s + " is of unexpected type") end + n += 1 end aa = [] @@ -4793,8 +4813,12 @@ TP_SCRIPT f_size = :size f_sized = :sized + if inside && outside + raise "Cannot use 'inside' and 'outside' together" + end + if steps - if !inside + if !inside && !outside raise "'steps' is only allowed with 'inside'" end if !steps.is_a?(1.class) @@ -4802,17 +4826,30 @@ TP_SCRIPT end end - if inside + if inside || outside - inside.is_a?(DRCLayer) || raise("'inside' argument needs to be a DRC layer") - inside.data.is_a?(RBA::Region) || raise("'inside' requires a polygon layer") - aa.push(inside.data) + if inside + + inside.is_a?(DRCLayer) || raise("'inside' argument needs to be a DRC layer") + inside.data.is_a?(RBA::Region) || raise("'inside' requires a polygon layer") + aa.push(inside.data) + + f_size = :size_inside + f_sized = :sized_inside + + else + + outside.is_a?(DRCLayer) || raise("'outside' argument needs to be a DRC layer") + outside.data.is_a?(RBA::Region) || raise("'outside' requires a polygon layer") + aa.push(outside.data) + + f_size = :size_outside + f_sized = :sized_outside + + end steps ||= 1 - f_size = :size_inside - f_sized = :sized_inside - end if values.size < 1 @@ -4824,7 +4861,7 @@ TP_SCRIPT aa.push(values[-1]) end - if inside + if inside || outside aa.push(steps) end diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb index e2a32f3f1..56cf18023 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -73,6 +73,14 @@ module DRC end end + # A wrapper for the sizing "outside" value + class DRCSizingOutside + attr_accessor :value + def initialize(v) + self.value = v + end + end + # A wrapper for the edge mode value for Region#edges class DRCEdgeMode attr_accessor :value