mirror of https://github.com/KLayout/klayout.git
Generic DRC: new tests, bug fixes.
This commit is contained in:
parent
0d9ee8a70d
commit
9c95bed67e
|
|
@ -1486,6 +1486,18 @@ CompoundRegionEdgePairToEdgeProcessingOperationNode::do_compute_local (db::Layou
|
|||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||
: CompoundRegionMultiInputOperationNode (), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options)
|
||||
{
|
||||
set_description ("check");
|
||||
|
||||
m_check.set_include_zero (false);
|
||||
m_check.set_whole_edges (options.whole_edges);
|
||||
m_check.set_ignore_angle (options.ignore_angle);
|
||||
m_check.set_min_projection (options.min_projection);
|
||||
m_check.set_max_projection (options.max_projection);
|
||||
}
|
||||
|
||||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode *input, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||
: CompoundRegionMultiInputOperationNode (input), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options)
|
||||
{
|
||||
|
|
@ -1498,8 +1510,8 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi
|
|||
m_check.set_max_projection (options.max_projection);
|
||||
}
|
||||
|
||||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||
: CompoundRegionMultiInputOperationNode (), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options)
|
||||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode * /*input*/, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||
: CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options)
|
||||
{
|
||||
set_description ("check");
|
||||
|
||||
|
|
|
|||
|
|
@ -1387,7 +1387,12 @@ public:
|
|||
CompoundRegionCheckOperationNode (db::CompoundRegionOperationNode *input, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options);
|
||||
|
||||
/**
|
||||
* @brief Constructor for the single-layer check
|
||||
* @brief Constructor for the two-layer check
|
||||
*/
|
||||
CompoundRegionCheckOperationNode (db::CompoundRegionOperationNode *input, db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options);
|
||||
|
||||
/**
|
||||
* @brief Constructor for a single-polygon check (width, notch)
|
||||
*/
|
||||
CompoundRegionCheckOperationNode (db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,11 @@ static db::CompoundRegionOperationNode *new_primary ()
|
|||
return new db::CompoundRegionOperationPrimaryNode ();
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_foreign ()
|
||||
{
|
||||
return new db::CompoundRegionOperationForeignNode ();
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_secondary (db::Region *region)
|
||||
{
|
||||
check_non_null (region, "region");
|
||||
|
|
@ -372,7 +377,7 @@ static db::CompoundRegionOperationNode *new_edge_pair_to_second_edges (db::Compo
|
|||
|
||||
static db::CompoundRegionOperationNode *new_check_node (db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
{
|
||||
return new db::CompoundRegionCheckOperationNode (rel, different_polygons, d,
|
||||
return new db::CompoundRegionCheckOperationNode (new_primary (), rel, different_polygons, d,
|
||||
db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
|
|
@ -385,10 +390,10 @@ static db::CompoundRegionOperationNode *new_check_node (db::edge_relation_type r
|
|||
);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *input, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
{
|
||||
check_non_null (input, "input");
|
||||
return new db::CompoundRegionCheckOperationNode (input, rel, different_polygons, d,
|
||||
check_non_null (other, "other");
|
||||
return new db::CompoundRegionCheckOperationNode (new_primary (), other, rel, different_polygons, d,
|
||||
db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
|
|
@ -435,19 +440,19 @@ static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole
|
|||
return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::SpaceRelation, d, options), new_primary (), true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_separation_check (db::CompoundRegionOperationNode *input, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_separation_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
{
|
||||
return new_check_node (input, db::SpaceRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
return new_check_node (other, db::SpaceRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_overlap_check (db::CompoundRegionOperationNode *input, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_overlap_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
{
|
||||
return new_check_node (input, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
return new_check_node (other, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_inside_check (db::CompoundRegionOperationNode *input, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_inside_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
{
|
||||
return new_check_node (input, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
return new_check_node (other, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_perimeter_filter (db::CompoundRegionOperationNode *input, bool inverse, db::coord_traits<db::Coord>::perimeter_type pmin, db::coord_traits<db::Coord>::perimeter_type pmax)
|
||||
|
|
@ -502,6 +507,9 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
|||
gsi::constructor ("new_primary", &new_primary,
|
||||
"@brief Creates a node object representing the primary input"
|
||||
) +
|
||||
gsi::constructor ("new_foreign", &new_foreign,
|
||||
"@brief Creates a node object representing the primary input without the current polygon"
|
||||
) +
|
||||
gsi::constructor ("new_secondary", &new_secondary, gsi::arg ("region"),
|
||||
"@brief Creates a node object representing the secondary input from the given region"
|
||||
) +
|
||||
|
|
@ -620,13 +628,13 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
|||
gsi::constructor ("new_notch_check", &new_notch_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing a intra-polygon space check.\n"
|
||||
) +
|
||||
gsi::constructor ("new_separation_check", &new_separation_check, gsi::arg ("input"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoSideAllowed, "NoSideAllowed"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_separation_check", &new_separation_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoSideAllowed, "NoSideAllowed"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing a separation check.\n"
|
||||
) +
|
||||
gsi::constructor ("new_overlap_check", &new_overlap_check, gsi::arg ("input"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoSideAllowed, "NoSideAllowed"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_overlap_check", &new_overlap_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoSideAllowed, "NoSideAllowed"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing an overlap check.\n"
|
||||
) +
|
||||
gsi::constructor ("new_inside_check", &new_inside_check, gsi::arg ("input"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoSideAllowed, "NoSideAllowed"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_inside_check", &new_inside_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoSideAllowed, "NoSideAllowed"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing an inside (enclosure) check.\n"
|
||||
) +
|
||||
gsi::constructor ("new_perimeter_filter", &new_perimeter_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("pmin", 0), gsi::arg ("pmax", std::numeric_limits<db::coord_traits<db::Coord>::perimeter_type>::max (), "max"),
|
||||
|
|
|
|||
|
|
@ -84,9 +84,9 @@ void run_test1 (tl::TestBase *_this, bool deep)
|
|||
res.insert_into (&ly, *ly.begin_top_down (), l1000);
|
||||
|
||||
db::CompoundRegionOperationPrimaryNode *primary = new db::CompoundRegionOperationPrimaryNode ();
|
||||
db::CompoundRegionCheckOperationNode space_check (primary, db::SpaceRelation, true /*==different polygons*/, 1050, check_options);
|
||||
db::CompoundRegionCheckOperationNode isolation_check (primary, db::SpaceRelation, true /*==different polygons*/, 1050, check_options);
|
||||
|
||||
res = r.cop_to_edge_pairs (space_check);
|
||||
res = r.cop_to_edge_pairs (isolation_check);
|
||||
|
||||
unsigned int l1001 = ly.get_layer (db::LayerProperties (1001, 0));
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l1001);
|
||||
|
|
@ -99,6 +99,13 @@ void run_test1 (tl::TestBase *_this, bool deep)
|
|||
unsigned int l1002 = ly.get_layer (db::LayerProperties (1002, 0));
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l1002);
|
||||
|
||||
db::CompoundRegionCheckOperationNode space_check (primary, db::SpaceRelation, false /*==all polygons*/, 1050, check_options);
|
||||
|
||||
res = r.cop_to_edge_pairs (space_check);
|
||||
|
||||
unsigned int l1003 = ly.get_layer (db::LayerProperties (1003, 0));
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l1003);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, ly, make_au ("1", deep));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1495,16 +1495,21 @@ class DRCOpNodeCheck < DRCOpNodeWithCompare
|
|||
:isolated => :new_isolated_check, :overlap => :new_overlap_check,
|
||||
:enclosing => :new_inside_check }[self.check]
|
||||
|
||||
oargs = []
|
||||
if self.other
|
||||
oargs << self.other.create_node(cache)
|
||||
end
|
||||
|
||||
if self.lt || self.le
|
||||
dmin = self.le ? @engine._make_value(self.le) + 1 : @engine._make_value(self.lt)
|
||||
res = RBA::CompoundRegionOperationNode::send(factory, dmin, *self.args)
|
||||
res = RBA::CompoundRegionOperationNode::send(factory, *(oargs + [ dmin ] + self.args))
|
||||
else
|
||||
res = nil
|
||||
end
|
||||
|
||||
if self.gt || self.ge
|
||||
dmax = self.ge ? @engine._make_value(self.ge) : @engine._make_value(self.gt) + 1
|
||||
max_check = RBA::CompoundRegionOperationNode::send(factory, dmax, *self.args + [ true ])
|
||||
max_check = RBA::CompoundRegionOperationNode::send(factory, *(oargs + [ dmax ] + self.args + [ true ]))
|
||||
if res
|
||||
if self.check == :width || self.check == :notch
|
||||
# Same polygon check - we need to take both edges of the result
|
||||
|
|
|
|||
|
|
@ -206,9 +206,9 @@ module DRC
|
|||
# out = in.drc(primary & foreign.sized(0.5.um))
|
||||
# @/code
|
||||
|
||||
def primary
|
||||
res = DRCOpNode::new(self, RBA::CompoundRegionOperationNode::new_primary)
|
||||
res.description = "primary"
|
||||
def foreign
|
||||
res = DRCOpNode::new(self, RBA::CompoundRegionOperationNode::new_foreign)
|
||||
res.description = "foreign"
|
||||
return res
|
||||
end
|
||||
|
||||
|
|
@ -773,13 +773,9 @@ CODE
|
|||
end
|
||||
|
||||
if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated
|
||||
if other
|
||||
raise("No other layer must be specified for a single-layer check")
|
||||
end
|
||||
other && raise("No other layer must be specified for a single-layer check")
|
||||
else
|
||||
if !other
|
||||
raise("The other layer must be specified for a two-layer check")
|
||||
end
|
||||
other || raise("The other layer must be specified for a two-layer check")
|
||||
end
|
||||
|
||||
DRCOpNodeCheck::new(self, :#{f}, other, *args)
|
||||
|
|
|
|||
|
|
@ -1523,7 +1523,7 @@ CODE
|
|||
%w(
|
||||
enc
|
||||
enclosing
|
||||
overlapping
|
||||
overlap
|
||||
sep
|
||||
separation
|
||||
).each do |f|
|
||||
|
|
@ -1595,7 +1595,7 @@ CODE
|
|||
output
|
||||
outside
|
||||
outside_part
|
||||
overlap
|
||||
overlapping
|
||||
perimeter
|
||||
pull_inside
|
||||
pull_interacting
|
||||
|
|
|
|||
|
|
@ -78,3 +78,13 @@ TEST(1d)
|
|||
{
|
||||
runTest (_this, "1", true);
|
||||
}
|
||||
|
||||
TEST(2)
|
||||
{
|
||||
runTest (_this, "2", false);
|
||||
}
|
||||
|
||||
TEST(2d)
|
||||
{
|
||||
runTest (_this, "2", true);
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
source $drc_test_source
|
||||
target $drc_test_target
|
||||
|
||||
if $drc_test_deep
|
||||
deep
|
||||
end
|
||||
|
||||
l1 = input(1, 0)
|
||||
l2 = input(2, 0)
|
||||
l3 = input(3, 0)
|
||||
|
||||
l1.output(1, 0)
|
||||
l2.output(2, 0)
|
||||
l3.output(3, 0)
|
||||
|
||||
# space
|
||||
l1.drc(space(projection) < 1.0).polygons.output(100, 0)
|
||||
|
||||
# further options for DRC functions
|
||||
l1.drc(space(euclidian) < 1.0).polygons.output(110, 0)
|
||||
l1.drc(space(projection, projection_limits(0..2.0)) < 1.0).polygons.output(111, 0)
|
||||
l1.drc(space(projection, whole_edges) < 1.0).polygons.output(112, 0)
|
||||
l1.drc(separation(foreign, projection, only_opposite) < 1.0).polygons.output(113, 0)
|
||||
|
||||
# notch
|
||||
l1.drc(notch(projection) <= 1.0).polygons.output(120, 0)
|
||||
|
||||
# separation + flavours
|
||||
l1.drc(separation(l2, projection) < 1.0).polygons.output(130, 0)
|
||||
l1.drc(separation(secondary(l2), projection) < 1.0).polygons.output(131, 0)
|
||||
l1.drc(separation(projection, l2) < 1.0).polygons.output(132, 0)
|
||||
l1.drc(sep(projection, l2) < 1.0).polygons.output(133, 0)
|
||||
|
||||
# isolation
|
||||
l1.drc(isolated(projection) < 1.0).polygons.output(140, 0)
|
||||
|
||||
# enclosing, overlap
|
||||
l2.drc(enclosing(l1, projection) < 1.0).polygons.output(150, 0)
|
||||
l1.drc(overlap(l2, projection) < 1.0).polygons.output(151, 0)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue