WIP: DRC properties constraints now need explicit generation of output properties.

This commit is contained in:
Matthias Koefferlein 2023-01-21 14:04:06 +01:00
parent 9b64224cb4
commit 38808fccf7
12 changed files with 161 additions and 49 deletions

View File

@ -1017,7 +1017,7 @@ EdgePairsDelegate *
AsIfFlatRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) AsIfFlatRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{ {
std::unique_ptr<FlatEdgePairs> output (new FlatEdgePairs ()); std::unique_ptr<FlatEdgePairs> output (new FlatEdgePairs ());
if (prop_constraint == db::IgnoreProperties) { if (pc_skip (prop_constraint)) {
region_cop_impl<db::EdgePair> (this, &output->raw_edge_pairs (), node); region_cop_impl<db::EdgePair> (this, &output->raw_edge_pairs (), node);
} else { } else {
region_cop_with_properties_impl<db::EdgePair> (this, &output->raw_edge_pairs (), output->properties_repository (), node, prop_constraint); region_cop_with_properties_impl<db::EdgePair> (this, &output->raw_edge_pairs (), output->properties_repository (), node, prop_constraint);
@ -1029,7 +1029,7 @@ RegionDelegate *
AsIfFlatRegion::cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) AsIfFlatRegion::cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{ {
std::unique_ptr<FlatRegion> output (new FlatRegion ()); std::unique_ptr<FlatRegion> output (new FlatRegion ());
if (prop_constraint == db::IgnoreProperties) { if (pc_skip (prop_constraint)) {
region_cop_impl<db::Polygon> (this, &output->raw_polygons (), node); region_cop_impl<db::Polygon> (this, &output->raw_polygons (), node);
} else { } else {
region_cop_with_properties_impl<db::Polygon> (this, &output->raw_polygons (), output->properties_repository (), node, prop_constraint); region_cop_with_properties_impl<db::Polygon> (this, &output->raw_polygons (), output->properties_repository (), node, prop_constraint);
@ -1041,7 +1041,7 @@ EdgesDelegate *
AsIfFlatRegion::cop_to_edges (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint) AsIfFlatRegion::cop_to_edges (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint)
{ {
std::unique_ptr<FlatEdges> output (new FlatEdges ()); std::unique_ptr<FlatEdges> output (new FlatEdges ());
if (prop_constraint == db::IgnoreProperties) { if (pc_skip (prop_constraint)) {
region_cop_impl<db::Edge> (this, &output->raw_edges (), node); region_cop_impl<db::Edge> (this, &output->raw_edges (), node);
} else { } else {
region_cop_with_properties_impl<db::Edge> (this, &output->raw_edges (), output->properties_repository (), node, prop_constraint); region_cop_with_properties_impl<db::Edge> (this, &output->raw_edges (), output->properties_repository (), node, prop_constraint);
@ -1113,7 +1113,7 @@ EdgePairsDelegate *
AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const
{ {
// force different polygons in the different properties case to skip intra-polygon checks // force different polygons in the different properties case to skip intra-polygon checks
if (options.prop_constraint == DifferentPropertiesConstraint) { if (pc_always_different (options.prop_constraint)) {
different_polygons = true; different_polygons = true;
} }
@ -1159,7 +1159,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons,
std::vector<db::Shapes *> results; std::vector<db::Shapes *> results;
results.push_back (&output->raw_edge_pairs ()); results.push_back (&output->raw_edge_pairs ());
if (options.prop_constraint == db::IgnoreProperties) { if (pc_skip (options.prop_constraint)) {
db::check_local_operation<db::Polygon, db::Polygon> op (check, different_polygons, primary_is_merged, has_other, other_is_merged, options); db::check_local_operation<db::Polygon, db::Polygon> op (check, different_polygons, primary_is_merged, has_other, other_is_merged, options);
@ -1209,7 +1209,7 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) { for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result->raw_edge_pairs (), options.negative, false /*=same polygons*/, false /*=same layers*/, options.shielded, true /*symmetric edge pairs*/, options.prop_constraint == db::IgnoreProperties ? 0 : pm (p.prop_id ())); edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result->raw_edge_pairs (), options.negative, false /*=same polygons*/, false /*=same layers*/, options.shielded, true /*symmetric edge pairs*/, pc_remove (options.prop_constraint) ? 0 : pm (p.prop_id ()));
poly2poly_check<db::Polygon> poly_check (edge_check); poly2poly_check<db::Polygon> poly_check (edge_check);
do { do {
@ -1364,7 +1364,7 @@ AsIfFlatRegion::and_with (const Region &other, PropertyConstraint property_const
// Nothing to do // Nothing to do
return new EmptyRegion (); return new EmptyRegion ();
} else if (property_constraint == db::IgnoreProperties && is_box () && other.is_box ()) { } else if (pc_skip (property_constraint) && is_box () && other.is_box ()) {
// @@@ TODO: implement this with property constraints as that is important for the clip implementation! // @@@ TODO: implement this with property constraints as that is important for the clip implementation!
@ -1373,7 +1373,7 @@ AsIfFlatRegion::and_with (const Region &other, PropertyConstraint property_const
b &= other.bbox (); b &= other.bbox ();
return region_from_box (b); return region_from_box (b);
} else if (property_constraint == db::IgnoreProperties && is_box () && ! other.strict_handling ()) { } else if (pc_skip (property_constraint) && is_box () && ! other.strict_handling ()) {
// @@@ TODO: implement this with property constraints as that is important for the clip implementation! // @@@ TODO: implement this with property constraints as that is important for the clip implementation!
@ -1390,7 +1390,7 @@ AsIfFlatRegion::and_with (const Region &other, PropertyConstraint property_const
return new_region.release (); return new_region.release ();
} else if (property_constraint == db::IgnoreProperties && other.is_box () && ! strict_handling ()) { } else if (pc_skip (property_constraint) && other.is_box () && ! strict_handling ()) {
// @@@ TODO: implement this with property constraints as that is important for the clip implementation! // @@@ TODO: implement this with property constraints as that is important for the clip implementation!
@ -1443,7 +1443,7 @@ AsIfFlatRegion::not_with (const Region &other, PropertyConstraint property_const
RegionDelegate * RegionDelegate *
AsIfFlatRegion::and_or_not_with (bool is_and, const Region &other, PropertyConstraint property_constraint) const AsIfFlatRegion::and_or_not_with (bool is_and, const Region &other, PropertyConstraint property_constraint) const
{ {
if (property_constraint == db::IgnoreProperties) { if (pc_skip (property_constraint)) {
// Generic case // Generic case
db::EdgeProcessor ep (report_progress (), progress_desc ()); db::EdgeProcessor ep (report_progress (), progress_desc ());
@ -1520,7 +1520,7 @@ AsIfFlatRegion::andnot_with (const Region &other, PropertyConstraint property_co
// Nothing to do // Nothing to do
return std::make_pair (new EmptyRegion (), clone ()); return std::make_pair (new EmptyRegion (), clone ());
} else if (property_constraint == db::IgnoreProperties) { } else if (pc_skip (property_constraint)) {
// Generic case // Generic case
db::EdgeProcessor ep (report_progress (), progress_desc ()); db::EdgeProcessor ep (report_progress (), progress_desc ());

View File

@ -1549,7 +1549,7 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi
set_description ("check"); set_description ("check");
// force different polygons in the different properties case to skip intra-polygon checks // force different polygons in the different properties case to skip intra-polygon checks
if (m_options.prop_constraint == DifferentPropertiesConstraint) { if (pc_always_different (m_options.prop_constraint)) {
m_different_polygons = true; m_different_polygons = true;
} }

View File

@ -1658,7 +1658,7 @@ protected:
for (size_t n = 0; n < results.size (); ++n) { for (size_t n = 0; n < results.size (); ++n) {
for (auto i = results_wo_props [n].begin (); i != results_wo_props [n].end (); ++i) { for (auto i = results_wo_props [n].begin (); i != results_wo_props [n].end (); ++i) {
results [n].insert (db::object_with_properties<TR> (*i, s2p->first)); results [n].insert (db::object_with_properties<TR> (*i, pc_norm (m_prop_constraint, s2p->first)));
} }
} }

View File

@ -858,7 +858,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op, db::PropertyC
{ {
DeepLayer dl_out (deep_layer ().derived ()); DeepLayer dl_out (deep_layer ().derived ());
if (property_constraint == db::IgnoreProperties) { if (pc_skip (property_constraint)) {
db::BoolAndOrNotLocalOperation op (and_op); db::BoolAndOrNotLocalOperation op (and_op);
@ -893,7 +893,7 @@ DeepRegion::and_and_not_with (const DeepRegion *other, PropertyConstraint proper
DeepLayer dl_out1 (deep_layer ().derived ()); DeepLayer dl_out1 (deep_layer ().derived ());
DeepLayer dl_out2 (deep_layer ().derived ()); DeepLayer dl_out2 (deep_layer ().derived ());
if (property_constraint == db::IgnoreProperties) { if (pc_skip (property_constraint)) {
db::TwoBoolAndNotLocalOperation op; db::TwoBoolAndNotLocalOperation op;
@ -1840,7 +1840,7 @@ EdgePairsDelegate *
DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{ {
DeepEdgePairs *output = 0; DeepEdgePairs *output = 0;
if (prop_constraint == db::IgnoreProperties) { if (pc_skip (prop_constraint)) {
output = region_cop_impl<db::EdgePair, DeepEdgePairs> (this, node); output = region_cop_impl<db::EdgePair, DeepEdgePairs> (this, node);
} else { } else {
output = region_cop_with_properties_impl<db::EdgePair, DeepEdgePairs> (this, node, prop_constraint); output = region_cop_with_properties_impl<db::EdgePair, DeepEdgePairs> (this, node, prop_constraint);
@ -1856,7 +1856,7 @@ RegionDelegate *
DeepRegion::cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) DeepRegion::cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{ {
DeepRegion *output = 0; DeepRegion *output = 0;
if (prop_constraint == db::IgnoreProperties) { if (pc_skip (prop_constraint)) {
output = region_cop_impl<db::PolygonRef, db::DeepRegion> (this, node); output = region_cop_impl<db::PolygonRef, db::DeepRegion> (this, node);
} else { } else {
output = region_cop_with_properties_impl<db::PolygonRef, DeepRegion> (this, node, prop_constraint); output = region_cop_with_properties_impl<db::PolygonRef, DeepRegion> (this, node, prop_constraint);
@ -1872,7 +1872,7 @@ EdgesDelegate *
DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{ {
DeepEdges *output = 0; DeepEdges *output = 0;
if (prop_constraint == db::IgnoreProperties) { if (pc_skip (prop_constraint)) {
output = region_cop_impl<db::Edge, DeepEdges> (this, node); output = region_cop_impl<db::Edge, DeepEdges> (this, node);
} else { } else {
output = region_cop_with_properties_impl<db::Edge, DeepEdges> (this, node, prop_constraint); output = region_cop_with_properties_impl<db::Edge, DeepEdges> (this, node, prop_constraint);
@ -1894,7 +1894,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
} }
// force different polygons in the different properties case to skip intra-polygon checks // force different polygons in the different properties case to skip intra-polygon checks
if (options.prop_constraint == DifferentPropertiesConstraint) { if (pc_always_different (options.prop_constraint)) {
different_polygons = true; different_polygons = true;
} }
@ -2004,7 +2004,7 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) { for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) {
edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result, options.negative, false /*does not require different polygons*/, false /*does not require different layers*/, options.shielded, true /*symmetric edge pairs*/, options.prop_constraint == db::IgnoreProperties ? 0 : s->prop_id ()); edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result, options.negative, false /*does not require different polygons*/, false /*does not require different layers*/, options.shielded, true /*symmetric edge pairs*/, pc_remove (options.prop_constraint) ? 0 : s->prop_id ());
poly2poly_check<db::Polygon> poly_check (edge_check); poly2poly_check<db::Polygon> poly_check (edge_check);
db::Polygon poly; db::Polygon poly;

View File

@ -341,9 +341,8 @@ separate_interactions_by_properties (const shape_interactions<db::object_with_pr
for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) { for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) {
const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii); const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii);
db::properties_id_type intruder_prop_id = (property_constraint == db::NoPropertyConstraint ? prop_id : pmi (intruder.second.properties_id ()));
if ((property_constraint == db::DifferentPropertiesConstraint) == (prop_id != intruder_prop_id)) { if (pc_match (property_constraint, prop_id, pmi (intruder.second.properties_id ()))) {
s2p.second.insert (&intruder.second); s2p.second.insert (&intruder.second);
} }
@ -382,9 +381,8 @@ separate_interactions_to_interactions_by_properties (const shape_interactions<db
const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii); const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii);
tl_assert (intruder.first < (unsigned int) pmis.size ()); tl_assert (intruder.first < (unsigned int) pmis.size ());
db::properties_id_type intruder_prop_id = (property_constraint == db::NoPropertyConstraint ? prop_id : pmis[intruder.first] (intruder.second.properties_id ()));
if ((property_constraint == db::DifferentPropertiesConstraint) == (prop_id != intruder_prop_id)) { if (pc_match (property_constraint, prop_id, pmis[intruder.first] (intruder.second.properties_id ()))) {
s2p.add_interaction (i->first, *ii); s2p.add_interaction (i->first, *ii);
intruder_ids.insert (*ii); intruder_ids.insert (*ii);
} }

View File

@ -26,6 +26,7 @@
#define HDR_dbPropertyConstraint #define HDR_dbPropertyConstraint
#include "dbCommon.h" #include "dbCommon.h"
#include "dbTypes.h"
namespace db namespace db
{ {
@ -56,14 +57,74 @@ enum PropertyConstraint
*/ */
SamePropertiesConstraint = 2, SamePropertiesConstraint = 2,
/**
* @brief Shapes are processed if their properties are the same
*
* No properties are attached to the output.
*/
SamePropertiesConstraintDrop = 3,
/** /**
* @brief Shapes are processed if their properties are different * @brief Shapes are processed if their properties are different
* *
* Properties are attached to the outputs where applicable. * Properties are attached to the outputs where applicable.
*/ */
DifferentPropertiesConstraint = 3 DifferentPropertiesConstraint = 4,
/**
* @brief Shapes are processed if their properties are different
*
* No properties are attached to the output.
*/
DifferentPropertiesConstraintDrop = 5
}; };
/**
* @brief Returns a predicate indicating whether properties need to be considered
*/
bool inline pc_skip (PropertyConstraint pc)
{
return pc == IgnoreProperties;
}
/**
* @brief Returns a predicate indicating whether properties are always different
*/
bool inline pc_always_different (PropertyConstraint pc)
{
return pc == DifferentPropertiesConstraint || pc == DifferentPropertiesConstraintDrop;
}
/**
* @brief Returns a value indicating whether two properties satisfy the condition
*/
bool inline pc_match (PropertyConstraint pc, db::properties_id_type a, db::properties_id_type b)
{
if (pc == SamePropertiesConstraint || pc == SamePropertiesConstraintDrop) {
return a == b;
} else if (pc == DifferentPropertiesConstraint || pc == DifferentPropertiesConstraintDrop) {
return a != b;
} else {
return true;
}
}
/**
* @brief Returns a value indicating whether the property can be removed on output
*/
bool inline pc_remove (PropertyConstraint pc)
{
return pc == IgnoreProperties || pc == SamePropertiesConstraintDrop || pc == DifferentPropertiesConstraintDrop;
}
/**
* @brief Returns a normalized property for output
*/
db::properties_id_type inline pc_norm (PropertyConstraint pc, db::properties_id_type prop_id)
{
return pc_remove (pc) ? 0 : prop_id;
}
} }
#endif #endif

View File

@ -782,7 +782,7 @@ check_local_operation_with_properties<TS, TI>::do_compute_local (db::Layout *lay
} }
for (auto r = result.begin (); r != result.end (); ++r) { for (auto r = result.begin (); r != result.end (); ++r) {
results.front ().insert (db::EdgePairWithProperties (*r, s2p->first)); results.front ().insert (db::EdgePairWithProperties (*r, pc_norm (check_local_operation_base<TS, TI>::m_options.prop_constraint, s2p->first)));
} }
} }
@ -1668,8 +1668,7 @@ bool_and_or_not_local_operation_with_properties<TS, TI, TR>::do_compute_local (d
for (auto j = i->second.begin (); j != i->second.end (); ++j) { for (auto j = i->second.begin (); j != i->second.end (); ++j) {
const db::object_with_properties<TI> &intruder = interactions.intruder_shape (*j).second; const db::object_with_properties<TI> &intruder = interactions.intruder_shape (*j).second;
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? m_pmi (intruder.properties_id ()) : prop_id_s); if (pc_match (m_property_constraint, prop_id_s, m_pmi (intruder.properties_id ()))) {
if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) {
shapes_by_prop.second.insert (intruder); shapes_by_prop.second.insert (intruder);
} }
} }
@ -1684,7 +1683,7 @@ bool_and_or_not_local_operation_with_properties<TS, TI, TR>::do_compute_local (d
size_t p1 = 0, p2 = 1; size_t p1 = 0, p2 = 1;
const std::set<TI> &others = p2s->second.second; const std::set<TI> &others = p2s->second.second;
db::properties_id_type prop_id = p2s->first; db::properties_id_type prop_id = pc_norm (m_property_constraint, p2s->first);
for (auto s = p2s->second.first.begin (); s != p2s->second.first.end (); ++s) { for (auto s = p2s->second.first.begin (); s != p2s->second.first.end (); ++s) {
@ -1857,8 +1856,7 @@ two_bool_and_not_local_operation_with_properties<TS, TI, TR>::do_compute_local (
for (auto j = i->second.begin (); j != i->second.end (); ++j) { for (auto j = i->second.begin (); j != i->second.end (); ++j) {
const db::object_with_properties<TI> &intruder = interactions.intruder_shape (*j).second; const db::object_with_properties<TI> &intruder = interactions.intruder_shape (*j).second;
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? m_pmi (intruder.properties_id ()) : prop_id_s); if (pc_match (m_property_constraint, prop_id_s, m_pmi (intruder.properties_id ()))) {
if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) {
shapes_by_prop.second.insert (intruder); shapes_by_prop.second.insert (intruder);
} }
} }
@ -1873,7 +1871,7 @@ two_bool_and_not_local_operation_with_properties<TS, TI, TR>::do_compute_local (
size_t p1 = 0, p2 = 1; size_t p1 = 0, p2 = 1;
const std::set<TR> &others = p2s->second.second; const std::set<TR> &others = p2s->second.second;
db::properties_id_type prop_id = p2s->first; db::properties_id_type prop_id = pc_norm (m_property_constraint, p2s->first);
for (auto s = p2s->second.first.begin (); s != p2s->second.first.end (); ++s) { for (auto s = p2s->second.first.begin (); s != p2s->second.first.end (); ++s) {

View File

@ -3172,10 +3172,20 @@ gsi::EnumIn<db::Region, db::PropertyConstraint> decl_Region_PropertyConstraint (
"When using this constraint - for example on a boolean operation - shapes are considered " "When using this constraint - for example on a boolean operation - shapes are considered "
"only if their user properties are the same. Properties are generated on the output shapes where applicable." "only if their user properties are the same. Properties are generated on the output shapes where applicable."
) + ) +
gsi::enum_const ("SamePropertiesConstraintDrop", db::SamePropertiesConstraintDrop,
"@brief Specifies to consider shapes only if their user properties are the same\n"
"When using this constraint - for example on a boolean operation - shapes are considered "
"only if their user properties are the same. No properties are generated on the output shapes."
) +
gsi::enum_const ("DifferentPropertiesConstraint", db::DifferentPropertiesConstraint, gsi::enum_const ("DifferentPropertiesConstraint", db::DifferentPropertiesConstraint,
"@brief Specifies to consider shapes only if their user properties are different\n" "@brief Specifies to consider shapes only if their user properties are different\n"
"When using this constraint - for example on a boolean operation - shapes are considered " "When using this constraint - for example on a boolean operation - shapes are considered "
"only if their user properties are different. Properties are generated on the output shapes where applicable." "only if their user properties are different. Properties are generated on the output shapes where applicable."
) +
gsi::enum_const ("DifferentPropertiesConstraintDrop", db::DifferentPropertiesConstraintDrop,
"@brief Specifies to consider shapes only if their user properties are different\n"
"When using this constraint - for example on a boolean operation - shapes are considered "
"only if their user properties are the same. No properties are generated on the output shapes."
), ),
"@brief This class represents the property constraint for boolean and check functions.\n" "@brief This class represents the property constraint for boolean and check functions.\n"
"\n" "\n"

View File

@ -267,6 +267,13 @@ module DRC
# #
# m1m2_overlap_connected = metal1.nets.and(metal2, props_eq) # m1m2_overlap_connected = metal1.nets.and(metal2, props_eq)
# @/code # @/code
#
# "props_eq" can be combined with \props_copy. In this case, properties
# are transferred to the output shapes and can be used in further processing:
#
# @code
# m1m2_overlap_connected = metal1.nets.and(metal2, props_eq + props_copy)
# @/code
# #
# See also \props_ne. # See also \props_ne.
@ -291,6 +298,13 @@ module DRC
# m1m2_overlap_not_connected = metal1.nets.and(metal2, props_ne) # m1m2_overlap_not_connected = metal1.nets.and(metal2, props_ne)
# @/code # @/code
# #
# "props_ne" can be combined with \props_copy. In this case, properties
# are transferred to the output shapes and can be used in further processing:
#
# @code
# m1m2_overlap_connected = metal1.nets.and(metal2, props_ne + props_copy)
# @/code
#
# See also \props_eq. # See also \props_eq.
# %DRC% # %DRC%

View File

@ -3781,10 +3781,17 @@ CODE
# @code # @code
# #
# \props_copy is a special properties constraint that does not alter the behaviour of # \props_copy is a special properties constraint that does not alter the behaviour of
# the checks, but copies the primary shape's properties to the output markers # the checks, but copies the primary shape's properties to the output markers.
# (a behaviour that is implied by \props_eq and \props_ne, but not there by default).
# This constraint is applicable to \width and \notch checks too. The effect is that # This constraint is applicable to \width and \notch checks too. The effect is that
# the original polygon's properties are copied to the error markers. # the original polygon's properties are copied to the error markers.
# \props_copy can be combined with \props_eq and \props_ne to copy the original
# shape's properties to the output too:
#
# @code
# space_not_connected = metal1_nets.space(0.4.um, props_ne + props_copy)
# space_connected = metal1_nets.space(0.4.um, props_eq + props_copy)
# @code
#
# %DRC% # %DRC%
# @name space # @name space

View File

@ -151,6 +151,30 @@ module DRC
def initialize(v) def initialize(v)
self.value = v self.value = v
end end
def is_eq?
self.value == RBA::Region::SamePropertiesConstraint || self.value == RBA::Region::SamePropertiesConstraintDrop
end
def is_ne?
self.value == RBA::Region::DifferentPropertiesConstraint || self.value == RBA::Region::DifferentPropertiesConstraintDrop
end
def is_copy?
self.value == RBA::Region::NoPropertyConstraint || self.value == RBA::Region::SamePropertiesConstraint || self.value == RBA::Region::DifferentPropertiesConstraint
end
def +(other)
other.is_a?(DRCPropertiesConstraint) || raise("'+' needs to be applied to two properties constraints (got #{other.inspect} for the second one)")
is_eq = self.is_eq? || other.is_eq?
is_ne = self.is_ne? || other.is_ne?
is_copy = self.is_copy? || other.is_copy?
if is_eq == is_ne
DRCPropertiesConstraint::new(is_copy ? RBA::Region::NoPropertyConstraint : RBA::Region::IgnoreProperties)
elsif is_eq
DRCPropertiesConstraint::new(is_copy ? RBA::Region::SamePropertiesConstraint : RBA::Region::SamePropertiesConstraintDrop)
elsif is_ne
DRCPropertiesConstraint::new(is_copy ? RBA::Region::DifferentPropertiesConstraint : RBA::Region::DifferentPropertiesConstraintDrop)
else
nil
end
end
end end
# Negative output on checks # Negative output on checks

View File

@ -40,15 +40,15 @@ l4_wp.output(16, 0)
# booleans with properties constraints # booleans with properties constraints
l3_wp.and(l4_wp, props_eq).output(20, 0) l3_wp.and(l4_wp, props_eq + props_copy).output(20, 0)
l3_wp1.and(l4_wp, props_eq).output(21, 0) l3_wp1.and(l4_wp, props_eq + props_copy).output(21, 0)
l3_wp2as1.and(l4_wp, props_eq).output(22, 0) l3_wp2as1.and(l4_wp, props_eq + props_copy).output(22, 0)
l3_nowp.and(l4_wp, props_eq).output(23, 0) l3_nowp.and(l4_wp, props_eq + props_copy).output(23, 0)
l3_wp.and(l4_wp, props_ne).output(30, 0) l3_wp.and(l4_wp, props_ne + props_copy).output(30, 0)
l3_wp1.and(l4_wp, props_ne).output(31, 0) l3_wp1.and(l4_wp, props_ne + props_copy).output(31, 0)
l3_wp2as1.and(l4_wp, props_ne).output(32, 0) l3_wp2as1.and(l4_wp, props_ne + props_copy).output(32, 0)
l3_nowp.and(l4_wp, props_ne).output(33, 0) l3_nowp.and(l4_wp, props_ne + props_copy).output(33, 0)
l3_wp.and(l4_wp, props_copy).output(40, 0) l3_wp.and(l4_wp, props_copy).output(40, 0)
l3_wp1.and(l4_wp, props_copy).output(41, 0) l3_wp1.and(l4_wp, props_copy).output(41, 0)
@ -79,15 +79,15 @@ l1.nets("NOTEXIST", "NOTEXIST").output(113, 0)
l1_nets = l1.nets l1_nets = l1.nets
l1_nets.space(1.0.um, projection).polygons.output(200, 0) l1_nets.space(1.0.um, projection).polygons.output(200, 0)
l1_nets.space(1.0.um, projection, props_eq).polygons.output(201, 0) l1_nets.space(1.0.um, projection, props_eq + props_copy).polygons.output(201, 0)
l1_nets.space(1.0.um, projection, props_ne).polygons.output(202, 0) l1_nets.space(1.0.um, projection, props_ne + props_copy).polygons.output(202, 0)
l1_nets.space(1.0.um, projection, props_copy).polygons.output(203, 0) l1_nets.space(1.0.um, projection, props_copy).polygons.output(203, 0)
l1_nets.width(1.0.um, projection).polygons.output(204, 0) l1_nets.width(1.0.um, projection).polygons.output(204, 0)
l1_nets.width(1.0.um, projection, props_copy).polygons.output(205, 0) l1_nets.width(1.0.um, projection, props_copy).polygons.output(205, 0)
l1_nets.drc(space(projection) < 1.0.um).polygons.output(210, 0) l1_nets.drc(space(projection) < 1.0.um).polygons.output(210, 0)
l1_nets.drc(space(projection) < 1.0.um, props_eq).polygons.output(211, 0) l1_nets.drc(space(projection) < 1.0.um, props_eq + props_copy).polygons.output(211, 0)
l1_nets.drc(space(projection) < 1.0.um, props_ne).polygons.output(212, 0) l1_nets.drc(space(projection) < 1.0.um, props_ne + props_copy).polygons.output(212, 0)
l1_nets.drc(space(projection) < 1.0.um, props_copy).polygons.output(213, 0) l1_nets.drc(space(projection) < 1.0.um, props_copy).polygons.output(213, 0)
l1_nets.drc(width(projection) < 1.0.um).polygons.output(214, 0) l1_nets.drc(width(projection) < 1.0.um).polygons.output(214, 0)
l1_nets.drc(width(projection) < 1.0.um, props_copy).polygons.output(215, 0) l1_nets.drc(width(projection) < 1.0.um, props_copy).polygons.output(215, 0)
@ -103,10 +103,10 @@ l1_nets.space(1.0.um, projection, props_copy).edges.extended_in(10.nm).output(22
# sizing with properties # sizing with properties
l1_nets_sized = l1_nets.sized(0.2.um) l1_nets_sized = l1_nets.sized(0.2.um)
l1_nets_sized.and(l1_nets_sized, props_ne).output(300, 0) # overlap of different nets, same layer l1_nets_sized.and(l1_nets_sized, props_ne + props_copy).output(300, 0) # overlap of different nets, same layer
l1_nets.drc(primary.sized(0.2.um) & foreign.sized(0.2.um)).output(310, 0) l1_nets.drc(primary.sized(0.2.um) & foreign.sized(0.2.um)).output(310, 0)
l1_nets.drc(primary.sized(0.2.um) & foreign.sized(0.2.um), props_ne).output(311, 0) l1_nets.drc(primary.sized(0.2.um) & foreign.sized(0.2.um), props_ne + props_copy).output(311, 0)
l1_nets.drc(primary.sized(0.2.um) & foreign.sized(0.2.um), props_eq).output(312, 0) l1_nets.drc(primary.sized(0.2.um) & foreign.sized(0.2.um), props_eq + props_copy).output(312, 0)
l1_nets.drc(primary.sized(0.2.um) & foreign.sized(0.2.um), props_copy).output(313, 0) l1_nets.drc(primary.sized(0.2.um) & foreign.sized(0.2.um), props_copy).output(313, 0)