WIP: DRC integration

This commit is contained in:
Matthias Koefferlein 2024-06-23 19:30:01 +02:00
parent e63a7b5940
commit a54365a9a7
13 changed files with 140 additions and 147 deletions

View File

@ -1378,13 +1378,13 @@ AsIfFlatRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
} }
RegionDelegate * RegionDelegate *
AsIfFlatRegion::sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode, const Region *stop_at) const AsIfFlatRegion::sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode) const
{ {
return sized_inside (inside, d, d, steps, mode, stop_at); return sized_inside (inside, d, d, steps, mode);
} }
RegionDelegate * RegionDelegate *
AsIfFlatRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode, const Region *stop_at) const AsIfFlatRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const
{ {
if (steps <= 0 || empty ()) { if (steps <= 0 || empty ()) {
// Nothing to do - NOTE: don't return EmptyRegion because we want to // Nothing to do - NOTE: don't return EmptyRegion because we want to
@ -1409,9 +1409,6 @@ AsIfFlatRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy
std::vector<db::generic_shape_iterator<db::Polygon> > others; std::vector<db::generic_shape_iterator<db::Polygon> > others;
others.push_back (inside.begin_merged ()); others.push_back (inside.begin_merged ());
if (stop_at) {
others.push_back (stop_at->begin ());
}
proc.run_flat (begin_merged (), others, std::vector<bool> (), &op, results); proc.run_flat (begin_merged (), others, std::vector<bool> (), &op, results);

View File

@ -121,8 +121,8 @@ public:
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const; 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 (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 Region *stop_at) 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 Region *stop_at) const; virtual RegionDelegate *sized_inside (const Region &inside, 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 *and_with (const Region &other, PropertyConstraint property_constraint) const;
virtual RegionDelegate *not_with (const Region &other, PropertyConstraint property_constraint) const; virtual RegionDelegate *not_with (const Region &other, PropertyConstraint property_constraint) const;

View File

@ -1782,13 +1782,13 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
} }
RegionDelegate * RegionDelegate *
DeepRegion::sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode, const Region *stop_at) const DeepRegion::sized_inside (const Region &inside, coord_type d, int steps, unsigned int mode) const
{ {
return sized_inside (inside, d, d, steps, mode, stop_at); return sized_inside (inside, d, d, steps, mode);
} }
RegionDelegate * RegionDelegate *
DeepRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode, const Region *stop_at) const DeepRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const
{ {
if (steps <= 0 || empty ()) { if (steps <= 0 || empty ()) {
// Nothing to do - NOTE: don't return EmptyRegion because we want to // Nothing to do - NOTE: don't return EmptyRegion because we want to
@ -1802,23 +1802,7 @@ DeepRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, in
const db::DeepRegion *inside_deep = dynamic_cast<const db::DeepRegion *> (inside.delegate ()); const db::DeepRegion *inside_deep = dynamic_cast<const db::DeepRegion *> (inside.delegate ());
if (! inside_deep) { if (! inside_deep) {
return db::AsIfFlatRegion::sized_inside (inside, dx, dy, steps, mode, stop_at); return db::AsIfFlatRegion::sized_inside (inside, dx, dy, steps, mode);
}
const db::DeepRegion *stop_at_deep = 0;
if (stop_at) {
stop_at_deep = dynamic_cast<const db::DeepRegion *> (stop_at->delegate ());
if (! stop_at_deep) {
return db::AsIfFlatRegion::sized_inside (inside, dx, dy, steps, mode, stop_at);
}
if (&inside_deep->deep_layer ().layout () != &stop_at_deep->deep_layer ().layout ()
|| &inside_deep->deep_layer ().initial_cell () != &stop_at_deep->deep_layer ().initial_cell ()) {
throw tl::Exception (tl::to_string (tr ("'sized_inside' operation needs to use the same layout and top cell "
"for 'inside' and 'stop_at' arguments")));
}
} }
const db::DeepLayer &polygons = merged_deep_layer (); const db::DeepLayer &polygons = merged_deep_layer ();
@ -1834,13 +1818,7 @@ DeepRegion::sized_inside (const Region &inside, coord_type dx, coord_type dy, in
std::unique_ptr<db::DeepRegion> res (new db::DeepRegion (polygons.derived ())); std::unique_ptr<db::DeepRegion> res (new db::DeepRegion (polygons.derived ()));
std::vector<unsigned int> other_layers; proc.run (&op, polygons.layer (), inside_polygons.layer (), res->deep_layer ().layer ());
other_layers.push_back (inside_polygons.layer ());
if (stop_at_deep) {
other_layers.push_back (stop_at_deep->deep_layer ().layer ());
}
proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ());
return res.release (); return res.release ();
} }

View File

@ -136,8 +136,8 @@ public:
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const; 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 (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 Region *stop_at) 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 Region *stop_at) const; virtual RegionDelegate *sized_inside (const Region &inside, 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; virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;

View File

@ -97,8 +97,8 @@ public:
virtual RegionDelegate *sized (coord_type, unsigned int) const { return new EmptyRegion (); } 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 (coord_type, coord_type, unsigned int) const { return new EmptyRegion (); }
virtual RegionDelegate *sized_inside (const Region &, coord_type, int, unsigned int, const Region *) 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 Region *) const { return new EmptyRegion (); } virtual RegionDelegate *sized_inside (const Region &, 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 *and_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); }
virtual RegionDelegate *not_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); } virtual RegionDelegate *not_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); }

View File

@ -310,29 +310,29 @@ Region::sized (coord_type dx, coord_type dy, unsigned int mode) const
} }
Region & Region &
Region::size_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode, const db::Region *stop_at) Region::size_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode)
{ {
set_delegate (mp_delegate->sized_inside (inside, d, steps, mode, stop_at)); set_delegate (mp_delegate->sized_inside (inside, d, steps, mode));
return *this; return *this;
} }
Region & Region &
Region::size_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode, const db::Region *stop_at) Region::size_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode)
{ {
set_delegate (mp_delegate->sized_inside (inside, dx, dy, steps, mode, stop_at)); set_delegate (mp_delegate->sized_inside (inside, dx, dy, steps, mode));
return *this; return *this;
} }
Region Region
Region::sized_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode, const db::Region *stop_at) const Region::sized_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode) const
{ {
return Region (mp_delegate->sized_inside (inside, d, steps, mode, stop_at)); return Region (mp_delegate->sized_inside (inside, d, steps, mode));
} }
Region Region
Region::sized_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode, const db::Region *stop_at) const Region::sized_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode) const
{ {
return Region (mp_delegate->sized_inside (inside, dx, dy, steps, mode, stop_at)); return Region (mp_delegate->sized_inside (inside, dx, dy, steps, mode));
} }
void void

View File

@ -1031,40 +1031,32 @@ public:
* @brief Size the region incrementally * @brief Size the region incrementally
* *
* This method applies an incremental sizing to the region. Before the sizing is done, the * This method applies an incremental sizing to the region. Before the sizing is done, the
* region is merged if this is not the case already. * region is merged if this is not the case already. Incremental sizing is confined to be inside a certain region.
* * Only positive or zero sizing values are supported.
* Incremental sizing can be confined to be inside a certain region and a stop condition
* can be supplied. With a stop condition, sizing will stop when the sized region touches
* a shape on the "stop_at" region.
* *
* @param inside The confinement region * @param inside The confinement region
* @param d The (isotropic) sizing value * @param d The (isotropic) sizing value
* @param steps The number of steps to take * @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. * @param mode The sizing mode (see EdgeProcessor) for a description of the sizing mode which controls the miter distance.
* @param stop_at The stop condition or 0 for "not stopping"
* @return A reference to self * @return A reference to self
*/ */
Region &size_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode = 2, const db::Region *stop_at = 0); Region &size_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode = 2);
/** /**
* @brief Size the region incrementally and anisotropically * @brief Size the region incrementally and anisotropically
* *
* This method applies an incremental sizing to the region. Before the sizing is done, the * This method applies an incremental sizing to the region. Before the sizing is done, the
* region is merged if this is not the case already. * region is merged if this is not the case already. Incremental sizing is confined to be inside a certain region.
* * Only positive or zero sizing values are supported.
* Incremental sizing can be confined to be inside a certain region and a stop condition
* can be supplied. With a stop condition, sizing will stop when the sized region touches
* a shape on the "stop_at" region.
* *
* @param inside The confinement region * @param inside The confinement region
* @param dx The x sizing value * @param dx The x sizing value
* @param dy The y sizing value * @param dy The y sizing value
* @param steps The number of steps to take * @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. * @param mode The sizing mode (see EdgeProcessor) for a description of the sizing mode which controls the miter distance.
* @param stop_at The stop condition or 0 for "not stopping"
* @return A reference to self * @return A reference to self
*/ */
Region &size_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode = 2, const db::Region *stop_at = 0); Region &size_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode = 2);
/** /**
* @brief Returns the sized region * @brief Returns the sized region
@ -1074,7 +1066,7 @@ public:
* *
* Merged semantics applies. * Merged semantics applies.
*/ */
Region sized_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode = 2, const db::Region *stop_at = 0) const; Region sized_inside (const db::Region &inside, coord_type d, int steps, unsigned int mode = 2) const;
/** /**
* @brief Returns the sized region * @brief Returns the sized region
@ -1084,7 +1076,7 @@ public:
* *
* Merged semantics applies. * Merged semantics applies.
*/ */
Region sized_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode = 2, const db::Region *stop_at = 0) const; Region sized_inside (const db::Region &inside, coord_type dx, coord_type dy, int steps, unsigned int mode = 2) const;
/** /**
* @brief Boolean AND operator * @brief Boolean AND operator

View File

@ -226,8 +226,8 @@ public:
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const = 0; 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 (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 Region *stop_at) 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 Region *stop_at) const = 0; virtual RegionDelegate *sized_inside (const Region &inside, 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 *and_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *not_with (const Region &other, PropertyConstraint prop_constraint) const = 0; virtual RegionDelegate *not_with (const Region &other, PropertyConstraint prop_constraint) const = 0;

View File

@ -2004,16 +2004,10 @@ sized_inside_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout,
std::vector<db::Polygon> subjects; std::vector<db::Polygon> subjects;
std::set<const TI *> inside; std::set<const TI *> inside;
std::set<const TI *> stop_at;
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) { for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (typename shape_interactions<TS, TI>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { for (typename shape_interactions<TS, TI>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
const std::pair<unsigned int, TI> &is = interactions.intruder_shape (*j); inside.insert (&interactions.intruder_shape (*j).second);
if (is.first == 0) {
inside.insert (&is.second);
} else if (is.first == 1) {
stop_at.insert (&is.second);
}
} }
} }
@ -2062,50 +2056,6 @@ sized_inside_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout,
db::BooleanOp op (db::BooleanOp::And); db::BooleanOp op (db::BooleanOp::And);
ep_and.process (pg, op); ep_and.process (pg, op);
if (! subjects.empty () && ! stop_at.empty ()) {
// compute interations with "stop_at"
ep_interact.clear ();
db::EdgeProcessor::property_type p = 0;
for (auto i = subjects.begin (); i != subjects.end (); ++i, ++p) {
ep_interact.insert (*i, p);
}
db::EdgeProcessor::property_type nstart = p;
for (auto i = stop_at.begin (); i != stop_at.end (); ++i, ++p) {
ep_interact.insert (**i, p);
}
db::InteractionDetector id (0 /*interacting*/, nstart - 1);
id.set_include_touching (true);
db::EdgeSink es;
ep_interact.process (es, id);
id.finish ();
std::set<size_t> interacting;
for (db::InteractionDetector::iterator i = id.begin (); i != id.end (); ++i) {
interacting.insert (i->first);
}
// drop interacting subjects
if (! interacting.empty ()) {
std::vector<db::Polygon>::iterator iw = subjects.begin ();
for (auto i = subjects.begin (); i != subjects.end (); ++i) {
if (interacting.find (i - subjects.begin ()) == interacting.end ()) {
if (iw != i) {
iw->swap (*i);
}
++iw;
}
}
subjects.erase (iw, subjects.end ());
}
}
} }
db::polygon_ref_generator<TR> gen (layout, result); db::polygon_ref_generator<TR> gen (layout, result);

View File

@ -1009,15 +1009,15 @@ size_dvm (db::Region *region, const db::Vector &dv, unsigned int mode)
} }
static db::Region static db::Region
sized_inside_dvm (const db::Region *region, const db::Region &inside, const db::Vector &dv, int steps, unsigned int mode, const db::Region *stop_at) 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, stop_at); return region->sized_inside (inside, dv.x (), dv.y (), steps, mode);
} }
static db::Region & static db::Region &
size_inside_dvm (db::Region *region, const db::Region &inside, const db::Vector &dv, int steps, unsigned int mode, const db::Region *stop_at) 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, stop_at); region->sized_inside (inside, dv.x (), dv.y (), steps, mode);
return *region; return *region;
} }
@ -1942,7 +1942,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\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, const db::Region *)) &db::Region::size_inside, gsi::arg ("inside"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("steps"), gsi::arg ("mode"), gsi::arg ("stop_at", (db::Region *) 0, "nil"), 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"),
"@brief Incremental, anisotropic sizing inside of another region\n" "@brief Incremental, anisotropic sizing inside of another region\n"
"\n" "\n"
"@param inside The region the incremental sizing will stay inside.\n" "@param inside The region the incremental sizing will stay inside.\n"
@ -1950,51 +1950,46 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"@param dy The y sizing value\n" "@param dy The y sizing value\n"
"@param steps The number of steps to take\n" "@param steps The number of steps to take\n"
"@param mode The sizing mode (see \\size)\n" "@param mode The sizing mode (see \\size)\n"
"@param stop_at The optional stop layer\n"
"\n" "\n"
"@return The region after the sizing has been applied (self)\n" "@return The region after the sizing has been applied (self)\n"
"\n" "\n"
"Sizes the region, keeping inside another region and performing the size in discrete steps.\n" "Sizes the region, keeping inside another region and performing the size in discrete steps.\n"
"\n" "\n"
"Using this method is equivalent to applying a single-step size and consecutively doing a boolean AND with the 'inside' regiuon. " "Using this method is equivalent to applying a single-step size and consecutively doing a boolean AND with the 'inside' region. "
"This is repeated until the full sizing value is applied.\n" "This is repeated until the full sizing value is applied.\n"
"\n" "\n"
"This operaton is employed to implement latch-up rules where a device needs to be close to a well tap within the " "This operation is employed to implement latch-up rules, where a device needs to be close to a well tap within the "
"same well. For this, the incremental size of the device active region with the well as the 'inside' region is applied. The step is chosen as " "same well. For this, the tap footprint is incrementally sized, with the well as the 'inside' region. The steps is chosen so "
"somewhat less than the minimum well space, so sizing the active region results in a growing footprint that " "the per-step sizing is somewhat less than the minimum well space. Sizing the tap shape results in a growing footprint that "
"follows the well contours.\n" "follows the well contours and a small enough per-step sizing value ensures the sized contour does not cross well gaps.\n"
"\n"
"A stop region can be specified, meaning that the sizing propagation will stop if the sized shape "
"touches a shape from the stop region. If that happens, the sized shape is discarded. "
"In case of the latch-up rule application, the stop region will be the well tap layer.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.29.3." "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), gsi::arg ("stop_at", (db::Region *) 0, "nil"), 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" "@brief Incremental, anisotropic sizing inside of another region\n"
"\n" "\n"
"@return The region after the sizing has applied (self)\n" "@return The region after the sizing has applied (self)\n"
"\n" "\n"
"This method is equivalent to \"size_inside(dv.x, dv.y, steps, mode, stop_at)\".\n" "This method is equivalent to \"size_inside(dv.x, dv.y, steps, mode)\".\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.29.3." "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, const db::Region *)) &db::Region::size_inside, gsi::arg ("inside"), gsi::arg ("d"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), gsi::arg ("stop_at", (db::Region *) 0, "nil"), 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),
"@brief Incremental, isotropic sizing inside of another region\n" "@brief Incremental, isotropic sizing inside of another region\n"
"\n" "\n"
"@return The region after the sizing has applied (self)\n" "@return The region after the sizing has applied (self)\n"
"\n" "\n"
"This method is equivalent to \"size_inside(d, d, steps, mode, stop_at)\".\n" "This method is equivalent to \"size_inside(d, d, steps, mode)\".\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.29.3." "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 *) const) &db::Region::sized_inside, gsi::arg ("inside"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("steps"), gsi::arg ("mode"), gsi::arg ("stop_at", (db::Region *) 0, "nil"), 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"),
"@brief Returns the incrementally and anisotropically sized region\n" "@brief Returns the incrementally and anisotropically sized region\n"
"\n" "\n"
"@return The sized region\n" "@return The sized region\n"
@ -2003,7 +1998,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("sized_inside", &sized_inside_dvm, gsi::arg ("inside"), gsi::arg ("dv"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), gsi::arg ("stop_at", (db::Region *) 0, "nil"), 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" "@brief Returns the incrementally and anisotropically sized region\n"
"\n" "\n"
"@return The sized region\n" "@return The sized region\n"
@ -2014,7 +2009,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"This variant has been introduced in version 0.28." "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 *) const) &db::Region::sized_inside, gsi::arg ("inside"), gsi::arg ("d"), gsi::arg ("steps"), gsi::arg ("mode", (unsigned int) 2), gsi::arg ("stop_at", (db::Region *) 0, "nil"), 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),
"@brief Returns the incrementally sized region\n" "@brief Returns the incrementally sized region\n"
"\n" "\n"
"@return The sized region\n" "@return The sized region\n"

View File

@ -313,6 +313,14 @@ module DRC
DRCEdgeMode::new(RBA::EdgeMode::NotStep) DRCEdgeMode::new(RBA::EdgeMode::NotStep)
end end
def steps(arg)
DRCSizingSteps::new(arg)
end
def inside(arg)
DRCSizingInside::new(arg)
end
def padding_zero def padding_zero
DRCDensityPadding::new(:zero) DRCDensityPadding::new(:zero)
end end

View File

@ -4678,8 +4678,8 @@ TP_SCRIPT
# %DRC% # %DRC%
# @name sized # @name sized
# @brief Polygon sizing (per-edge biasing) # @brief Polygon sizing (per-edge biasing)
# @synopsis layer.sized(d [, mode]) # @synopsis layer.sized(d [, mode] [, inside(l) [, steps(n)]])
# @synopsis layer.sized(dx, dy [, mode])) # @synopsis layer.sized(dx, dy [, mode] [, inside(l) [, steps(n)]]))
# #
# This method requires a polygon layer. It will apply a bias per edge of the polygons # 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. # and return the biased layer. The layer that this method is called on is not modified.
@ -4711,6 +4711,26 @@ TP_SCRIPT
# Bias values can be given as floating-point values (in micron) or integer values (in # Bias values can be given as floating-point values (in micron) or integer values (in
# database units). To explicitly specify the unit, use the unit denominators. # database units). To explicitly specify the unit, use the unit denominators.
# #
# The "inside" option and the "steps" option implement incremental size. Incremental
# size means that the sizing value is applied in n steps. Between the steps, the sized
# shape is confined to the "inside" layer by means of a boolean "AND" operation.
#
# This scheme is used to implement latch-up rules where a device active region has to
# be close to a well tap. By using the well layer as the "inside" layer, the size function
# follows the well contours. The steps have to selected such that the per-step size value
# is smaller than the minimum space of the well shapes. With that, the sized shapes will
# not cross over to neighbor well regions. Specifically, the per-step size has to be less
# than about 70% of the minimum space to account for the minimum corner-to-corner case
# with Euclidian space measurements.
#
# "inside" and "steps" can be used with positive sizing values only.
#
# An example for the "inside" option is this:
#
# @code
# ntap.sized(30.um, inside(nwell), steps(100))
# @/code
#
# \size is working like \sized but modifies the layer it is called on. # \size is working like \sized but modifies the layer it is called on.
# #
# The following images show the effect of various forms of the "sized" method: # The following images show the effect of various forms of the "sized" method:
@ -4733,10 +4753,11 @@ TP_SCRIPT
# %DRC% # %DRC%
# @name size # @name size
# @brief Polygon sizing (per-edge biasing, modifies the layer) # @brief Polygon sizing (per-edge biasing, modifies the layer)
# @synopsis layer.size(d [, mode]) # @synopsis layer.size(d [, mode] [, inside(l) [, steps(n)]])
# @synopsis layer.size(dx, dy [, mode])) # @synopsis layer.size(dx, dy [, mode] [, inside(l) [, steps(n)]]))
# #
# See \sized. The size method basically does the same but modifies the layer # See \sized for a description of the options.
# The size method basically does the same but modifies the layer
# it is called on. The input layer is returned and available for further processing. # it is called on. The input layer is returned and available for further processing.
%w(size sized).each do |f| %w(size sized).each do |f|
@ -4749,6 +4770,8 @@ TP_SCRIPT
dist = 0 dist = 0
steps = nil
inside = nil
mode = 2 mode = 2
values = [] values = []
args.each do |a| args.each do |a|
@ -4758,10 +4781,40 @@ TP_SCRIPT
values.push(v) values.push(v)
elsif a.is_a?(DRCSizingMode) elsif a.is_a?(DRCSizingMode)
mode = a.value mode = a.value
elsif a.is_a?(DRCSizingSteps)
steps = a.value
elsif a.is_a?(DRCSizingInside)
inside = a.value
end end
end end
aa = [] aa = []
f_size = :size
f_sized = :sized
if steps
if !inside
raise "'steps' is only allowed with 'inside'"
end
if !steps.is_a?(1.class)
raise "'steps' must be an integer value"
end
end
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)
steps ||= 1
f_size = :size_inside
f_sized = :sized_inside
end
if values.size < 1 if values.size < 1
raise "Method requires one or two sizing values" raise "Method requires one or two sizing values"
elsif values.size > 2 elsif values.size > 2
@ -4771,17 +4824,21 @@ TP_SCRIPT
aa.push(values[-1]) aa.push(values[-1])
end end
if inside
aa.push(steps)
end
aa.push(mode) aa.push(mode)
if :#{f} == :size && @engine.is_tiled? if :#{f} == :size && @engine.is_tiled?
# in tiled mode, no modifying versions are available # in tiled mode, no modifying versions are available
self.data = @engine._tcmd(self.data, dist, RBA::Region, :sized, *aa) self.data = @engine._tcmd(self.data, dist, RBA::Region, f_sized, *aa)
self self
elsif :#{f} == :size elsif :#{f} == :size
@engine._tcmd(self.data, dist, RBA::Region, :#{f}, *aa) @engine._tcmd(self.data, dist, RBA::Region, f_size, *aa)
self self
else else
DRCLayer::new(@engine, @engine._tcmd(self.data, dist, RBA::Region, :#{f}, *aa)) DRCLayer::new(@engine, @engine._tcmd(self.data, dist, RBA::Region, f_sized, *aa))
end end
end end

View File

@ -57,6 +57,22 @@ module DRC
end end
end end
# A wrapper for the sizing steps value
class DRCSizingSteps
attr_accessor :value
def initialize(v)
self.value = v
end
end
# A wrapper for the sizing "inside" value
class DRCSizingInside
attr_accessor :value
def initialize(v)
self.value = v
end
end
# A wrapper for the edge mode value for Region#edges # A wrapper for the edge mode value for Region#edges
class DRCEdgeMode class DRCEdgeMode
attr_accessor :value attr_accessor :value