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 *
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 *
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 ()) {
// 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;
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);

View File

@ -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 Region *stop_at) 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 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 *and_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 *
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 *
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 ()) {
// 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 ());
if (! inside_deep) {
return db::AsIfFlatRegion::sized_inside (inside, dx, dy, steps, mode, stop_at);
}
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")));
}
return db::AsIfFlatRegion::sized_inside (inside, dx, dy, steps, mode);
}
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::vector<unsigned int> other_layers;
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 ());
proc.run (&op, polygons.layer (), inside_polygons.layer (), res->deep_layer ().layer ());
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 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 dx, coord_type dy, 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;
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, 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, 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 { 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 (); }

View File

@ -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, 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;
}
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;
}
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::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

View File

@ -1031,40 +1031,32 @@ public:
* @brief Size the region incrementally
*
* 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.
*
* 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.
* 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.
*
* @param inside The confinement 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.
* @param stop_at The stop condition or 0 for "not stopping"
* @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
*
* 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.
*
* 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.
* 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.
*
* @param inside The confinement 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.
* @param stop_at The stop condition or 0 for "not stopping"
* @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
@ -1074,7 +1066,7 @@ public:
*
* 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
@ -1084,7 +1076,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 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

View File

@ -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 Region *stop_at) 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 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 *and_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::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>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
const std::pair<unsigned int, TI> &is = interactions.intruder_shape (*j);
if (is.first == 0) {
inside.insert (&is.second);
} else if (is.first == 1) {
stop_at.insert (&is.second);
}
inside.insert (&interactions.intruder_shape (*j).second);
}
}
@ -2062,50 +2056,6 @@ sized_inside_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout,
db::BooleanOp op (db::BooleanOp::And);
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);

View File

@ -1009,15 +1009,15 @@ size_dvm (db::Region *region, const db::Vector &dv, unsigned int mode)
}
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 &
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;
}
@ -1942,7 +1942,7 @@ Class<db::Region> 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, 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"
"\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 steps The number of steps to take\n"
"@param mode The sizing mode (see \\size)\n"
"@param stop_at The optional stop layer\n"
"\n"
"@return The region after the sizing has been applied (self)\n"
"\n"
"Sizes the region, keeping inside another region and performing the size in discrete steps.\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"
"\n"
"This operaton 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 "
"somewhat less than the minimum well space, so sizing the active region results in a growing footprint that "
"follows the well contours.\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"
"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 tap footprint is incrementally sized, with the well as the 'inside' region. The steps is chosen so "
"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 and a small enough per-step sizing value ensures the sized contour does not cross well gaps.\n"
"\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\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), 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"
"\n"
"@return The region after the sizing has applied (self)\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"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\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, 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"
"\n"
"@return The region after the sizing has applied (self)\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"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\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 *) 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"
"\n"
"@return The sized region\n"
@ -2003,7 +1998,7 @@ Class<db::Region> 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_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"
"\n"
"@return The sized region\n"
@ -2014,7 +2009,7 @@ Class<db::Region> 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 *) 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"
"\n"
"@return The sized region\n"

View File

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

View File

@ -4678,8 +4678,8 @@ TP_SCRIPT
# %DRC%
# @name sized
# @brief Polygon sizing (per-edge biasing)
# @synopsis layer.sized(d [, mode])
# @synopsis layer.sized(dx, dy [, mode]))
# @synopsis layer.sized(d [, mode] [, inside(l) [, steps(n)]])
# @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
# 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
# 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.
#
# The following images show the effect of various forms of the "sized" method:
@ -4733,10 +4753,11 @@ TP_SCRIPT
# %DRC%
# @name size
# @brief Polygon sizing (per-edge biasing, modifies the layer)
# @synopsis layer.size(d [, mode])
# @synopsis layer.size(dx, dy [, mode]))
# @synopsis layer.size(d [, mode] [, inside(l) [, steps(n)]])
# @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.
%w(size sized).each do |f|
@ -4749,6 +4770,8 @@ TP_SCRIPT
dist = 0
steps = nil
inside = nil
mode = 2
values = []
args.each do |a|
@ -4758,10 +4781,40 @@ TP_SCRIPT
values.push(v)
elsif a.is_a?(DRCSizingMode)
mode = a.value
elsif a.is_a?(DRCSizingSteps)
steps = a.value
elsif a.is_a?(DRCSizingInside)
inside = a.value
end
end
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
raise "Method requires one or two sizing values"
elsif values.size > 2
@ -4771,17 +4824,21 @@ TP_SCRIPT
aa.push(values[-1])
end
if inside
aa.push(steps)
end
aa.push(mode)
if :#{f} == :size && @engine.is_tiled?
# 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
elsif :#{f} == :size
@engine._tcmd(self.data, dist, RBA::Region, :#{f}, *aa)
@engine._tcmd(self.data, dist, RBA::Region, f_size, *aa)
self
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

View File

@ -57,6 +57,22 @@ module DRC
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
class DRCEdgeMode
attr_accessor :value