Skip to content

Commit

Permalink
Fixed issue #1643 (Feeding the same layer to two-layer operations in …
Browse files Browse the repository at this point in the history
…deep mode does not render the desired result) by implementating the identical layer case as an exception for booleans and interactions
  • Loading branch information
Matthias Koefferlein committed Mar 23, 2024
1 parent e1b0411 commit a6d2930
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 12 deletions.
72 changes: 69 additions & 3 deletions src/db/db/dbDeepEdges.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,10 @@ EdgesDelegate *DeepEdges::and_with (const Edges &other) const

return AsIfFlatEdges::and_with (other);

} else if (deep_layer () == other_deep->deep_layer ()) {

return clone ();

} else {

return new DeepEdges (and_or_not_with (other_deep, EdgeAnd).first);
Expand All @@ -1071,6 +1075,10 @@ EdgesDelegate *DeepEdges::not_with (const Edges &other) const

return AsIfFlatEdges::not_with (other);

} else if (deep_layer () == other_deep->deep_layer ()) {

return new DeepEdges (deep_layer ().derived ());

} else {

return new DeepEdges (and_or_not_with (other_deep, EdgeNot).first);
Expand Down Expand Up @@ -1164,6 +1172,10 @@ DeepEdges::andnot_with (const Edges &other) const

return AsIfFlatEdges::andnot_with (other);

} else if (deep_layer () == other_deep->deep_layer ()) {

return std::make_pair (clone (), new DeepEdges (deep_layer ().derived ()));

} else {

auto res = and_or_not_with (other_deep, EdgeAndNot);
Expand All @@ -1188,6 +1200,10 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const

return AsIfFlatEdges::xor_with (other);

} else if (deep_layer () == other_deep->deep_layer ()) {

return new DeepEdges (deep_layer ().derived ());

} else {

// Implement XOR as (A-B)+(B-A) - only this implementation
Expand All @@ -1203,6 +1219,11 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const

EdgesDelegate *DeepEdges::or_with (const Edges &other) const
{
const DeepEdges *other_deep = dynamic_cast <const DeepEdges *> (other.delegate ());
if (other_deep && other_deep->deep_layer () == deep_layer ()) {
return clone ();
}

// NOTE: in the hierarchical case we don't do a merge on "or": just map to add
return add (other);
}
Expand Down Expand Up @@ -1503,8 +1524,19 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode
other_deep = dr_holder.get ();
}

if (deep_layer () == other_deep->deep_layer () && !counting) {
if ((mode == EdgesOutside) == inverse) {
return clone ();
} else {
return new DeepEdges (deep_layer ().derived ());
}
}

const db::DeepLayer &edges = merged_deep_layer ();

// NOTE: with counting the other region needs to be merged
const db::DeepLayer &other_edges = (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ());

DeepLayer dl_out (edges.derived ());

db::Edge2EdgeInteractingLocalOperation op (mode, inverse ? db::Edge2EdgeInteractingLocalOperation::Inverse : db::Edge2EdgeInteractingLocalOperation::Normal, min_count, max_count);
Expand All @@ -1513,8 +1545,13 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());

// NOTE: with counting the other region needs to be merged
proc.run (&op, edges.layer (), (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), dl_out.layer ());
if (edges == other_edges) {
// with counting and two identical inputs, a copy needs to be made
db::DeepLayer copy (other_edges.copy ());
proc.run (&op, edges.layer (), copy.layer (), dl_out.layer ());
} else {
proc.run (&op, edges.layer (), other_edges.layer (), dl_out.layer ());
}

return new db::DeepEdges (dl_out);
}
Expand All @@ -1533,8 +1570,19 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio
other_deep = dr_holder.get ();
}

if (deep_layer () == other_deep->deep_layer () && !counting) {
if (mode != EdgesOutside) {
return std::make_pair (clone (), new DeepEdges (deep_layer ().derived ()));
} else {
return std::make_pair (new DeepEdges (deep_layer ().derived ()), clone ());
}
}

const db::DeepLayer &edges = merged_deep_layer ();

// NOTE: with counting the other region needs to be merged
const db::DeepLayer &other_edges = (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ());

DeepLayer dl_out (edges.derived ());
DeepLayer dl_out2 (edges.derived ());

Expand All @@ -1550,7 +1598,13 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio
proc.set_threads (edges.store ()->threads ());

// NOTE: with counting the other region needs to be merged
proc.run (&op, edges.layer (), (counting || mode != EdgesInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), output_layers);
if (edges == other_edges) {
// with counting and two identical inputs, a copy needs to be made
db::DeepLayer copy (other_edges.copy ());
proc.run (&op, edges.layer (), copy.layer (), output_layers);
} else {
proc.run (&op, edges.layer (), other_edges.layer (), output_layers);
}

return std::make_pair (new db::DeepEdges (dl_out), new db::DeepEdges (dl_out2));
}
Expand Down Expand Up @@ -1591,6 +1645,10 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const
other_deep = dr_holder.get ();
}

if (deep_layer () == other_deep->deep_layer ()) {
return clone ();
}

const db::DeepLayer &edges = deep_layer ();
const db::DeepLayer &other_edges = other_deep->merged_deep_layer ();

Expand All @@ -1617,6 +1675,10 @@ EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
other_deep = dr_holder.get ();
}

if (deep_layer () == other_deep->deep_layer ()) {
return invert ? new db::DeepEdges (deep_layer ().derived ()) : clone ();
}

const db::DeepLayer &edges = merged_deep_layer ();

DeepLayer dl_out (edges.derived ());
Expand Down Expand Up @@ -1646,6 +1708,10 @@ std::pair<EdgesDelegate *, EdgesDelegate *> DeepEdges::in_and_out (const Edges &
other_deep = dr_holder.get ();
}

if (deep_layer () == other_deep->deep_layer ()) {
return std::make_pair (clone (), new db::DeepEdges (deep_layer ().derived ()));
}

const db::DeepLayer &edges = merged_deep_layer ();

DeepLayer dl_out (edges.derived ());
Expand Down
63 changes: 62 additions & 1 deletion src/db/db/dbDeepRegion.cc
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,10 @@ DeepRegion::and_with (const Region &other, PropertyConstraint property_constrain

return AsIfFlatRegion::and_with (other, property_constraint);

} else if (other_deep->deep_layer () == deep_layer ()) {

return clone ()->remove_properties (pc_remove (property_constraint));

} else {

return new DeepRegion (and_or_not_with (other_deep, true, property_constraint));
Expand All @@ -817,6 +821,10 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain

return AsIfFlatRegion::not_with (other, property_constraint);

} else if (other_deep->deep_layer () == deep_layer ()) {

return new DeepRegion (deep_layer ().derived ());

} else {

return new DeepRegion (and_or_not_with (other_deep, false, property_constraint));
Expand All @@ -827,6 +835,11 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain
RegionDelegate *
DeepRegion::or_with (const Region &other, db::PropertyConstraint /*property_constraint*/) const
{
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (other_deep && other_deep->deep_layer () == deep_layer ()) {
return clone ();
}

// TODO: implement property_constraint
RegionDelegate *res = add (other);
return res->merged_in_place ();
Expand All @@ -849,6 +862,10 @@ DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constr

return AsIfFlatRegion::andnot_with (other, property_constraint);

} else if (other_deep->deep_layer () == deep_layer ()) {

return std::make_pair (clone ()->remove_properties (pc_remove (property_constraint)), new DeepRegion (deep_layer ().derived ()));

} else {

std::pair<DeepLayer, DeepLayer> res = and_and_not_with (other_deep, property_constraint);
Expand Down Expand Up @@ -962,6 +979,10 @@ DeepRegion::xor_with (const Region &other, db::PropertyConstraint property_const

return AsIfFlatRegion::xor_with (other, property_constraint);

} else if (other_deep->deep_layer () == deep_layer ()) {

return new DeepRegion (deep_layer ().derived ());

} else {

// Implement XOR as (A-B)+(B-A) - only this implementation
Expand Down Expand Up @@ -2127,6 +2148,16 @@ DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode outpu
other_deep = dr_holder.get ();
}

if (deep_layer () == other_deep->deep_layer ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
} else if (output_mode == Negative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
}

const db::DeepLayer &polygons = merged_deep_layer ();
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();

Expand Down Expand Up @@ -2188,6 +2219,26 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
other_deep = dr_holder.get ();
}

if (deep_layer () == other_deep->deep_layer () && !counting) {
if (mode <= 0 /*inside or interacting*/) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
} else if (output_mode == Negative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
} else {
if (output_mode == PositiveAndNegative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ());
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
}
}
}

const db::DeepLayer &polygons = merged_deep_layer ();
// NOTE: with counting, the other polygons must be merged
const db::DeepLayer &other_polygons = counting ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
Expand All @@ -2205,7 +2256,13 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
bool result_is_merged = (! split_after && (merged_semantics () || is_merged ()));
InteractingResultHolder orh (output_mode, result_is_merged, polygons);

proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
if (polygons == other_polygons) {
// with counting and two identical inputs we need to create a layer copy
db::DeepLayer other_copy (other_polygons.copy ());
proc.run (&op, polygons.layer (), other_copy.layer (), orh.layers ());
} else {
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
}

return orh.result_pair ();
}
Expand Down Expand Up @@ -2285,6 +2342,10 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
other_deep = dr_holder.get ();
}

if (deep_layer () == other_deep->deep_layer ()) {
return clone ();
}

// in "inside" mode, the first argument needs to be merged too
const db::DeepLayer &polygons = mode < 0 ? merged_deep_layer () : deep_layer ();
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
Expand Down
49 changes: 49 additions & 0 deletions src/db/unit_tests/dbDeepEdgesTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,55 @@ TEST(22_InteractingWithCount)
EXPECT_EQ (db::compare (e.selected_interacting_differential (r2, size_t (2), size_t(3)).second, "(0,0;200,0)"), true);
}

TEST(23_SameInputs)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_l1.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}

db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);

db::DeepShapeStore dss;

unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::Edges e2 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l2), dss)).edges ());

EXPECT_EQ ((e2 & e2).to_string (), e2.to_string ());
EXPECT_EQ ((e2 - e2).to_string (), "");
EXPECT_EQ (e2.andnot (e2).first.to_string (), e2.to_string ());
EXPECT_EQ (e2.andnot (e2).second.to_string (), "");
EXPECT_EQ ((e2 | e2).to_string (), e2.to_string ());
EXPECT_EQ ((e2 ^ e2).to_string (), "");
EXPECT_EQ (e2.in (e2).to_string (), e2.to_string ());
EXPECT_EQ (e2.in (e2, true).to_string (), "");
EXPECT_EQ (e2.in_and_out (e2).first.to_string (), e2.to_string ());
EXPECT_EQ (e2.in_and_out (e2).second.to_string (), "");
EXPECT_EQ (e2.selected_interacting (e2).to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_not_interacting (e2).to_string (), "");
EXPECT_EQ (e2.selected_interacting_differential (e2).first.to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_interacting_differential (e2).second.to_string (), "");
EXPECT_EQ ((e2.selected_interacting (e2, (size_t) 1, (size_t) 3) ^ e2).to_string (), "");
EXPECT_EQ ((e2.selected_interacting_differential (e2, (size_t) 1, (size_t) 3).first ^ e2).to_string (), "");
EXPECT_EQ (e2.selected_interacting_differential (e2, (size_t) 1, (size_t) 3).second.to_string (), "");
EXPECT_EQ (e2.selected_interacting (e2, (size_t) 4).to_string (), "");
EXPECT_EQ (e2.selected_interacting_differential (e2, (size_t) 4).first.to_string (), "");
EXPECT_EQ ((e2.selected_interacting_differential (e2, (size_t) 4).second ^ e2).to_string (), "");
EXPECT_EQ (e2.selected_inside (e2).to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_not_inside (e2).to_string (), "");
EXPECT_EQ (e2.selected_inside_differential (e2).first.to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_inside_differential (e2).second.to_string (), "");
EXPECT_EQ (e2.selected_outside (e2).to_string (), "");
EXPECT_EQ (e2.selected_not_outside (e2).to_string (), e2.to_string ());
EXPECT_EQ (e2.selected_outside_differential (e2).first.to_string (), "");
EXPECT_EQ (e2.selected_outside_differential (e2).second.to_string (), e2.to_string ());
EXPECT_EQ (e2.pull_interacting (e2).to_string (), e2.to_string ());
}

TEST(deep_edges_and_cheats)
{
Expand Down
47 changes: 39 additions & 8 deletions src/db/unit_tests/dbDeepRegionTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2666,16 +2666,47 @@ TEST(102_SameInputs)
db::DeepShapeStore dss;

unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));

db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);

EXPECT_EQ ((r2 & r2).to_string (), "...");
EXPECT_EQ ((r2 - r2).to_string (), "...");
EXPECT_EQ ((r2 | r2).to_string (), "...");
EXPECT_EQ ((r2 ^ r2).to_string (), "...");
EXPECT_EQ ((r2 + r2).to_string (), "...");
EXPECT_EQ ((r2 & r2).to_string (), r2.to_string ());
EXPECT_EQ ((r2 - r2).to_string (), "");
EXPECT_EQ (r2.andnot (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.andnot (r2).second.to_string (), "");
EXPECT_EQ ((r2 | r2).to_string (), r2.to_string ());
EXPECT_EQ ((r2 ^ r2).to_string (), "");
EXPECT_EQ (r2.in (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.in (r2, true).to_string (), "");
EXPECT_EQ (r2.in_and_out (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.in_and_out (r2).second.to_string (), "");
EXPECT_EQ (r2.selected_enclosing (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_not_enclosing (r2).to_string (), "");
EXPECT_EQ (r2.selected_enclosing_differential (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_enclosing_differential (r2).second.to_string (), "");
EXPECT_EQ (r2.selected_interacting (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_not_interacting (r2).to_string (), "");
EXPECT_EQ (r2.selected_interacting_differential (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_interacting_differential (r2).second.to_string (), "");
EXPECT_EQ (r2.selected_interacting (r2, (size_t) 1, (size_t) 2).to_string (), r2.merged ().to_string ());
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 1, (size_t) 2).first.to_string (), r2.merged ().to_string ());
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 1, (size_t) 2).second.to_string (), "");
EXPECT_EQ (r2.selected_interacting (r2, (size_t) 2).to_string (), "");
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 2).first.to_string (), "");
EXPECT_EQ (r2.selected_interacting_differential (r2, (size_t) 2).second.to_string (), r2.merged ().to_string ());
EXPECT_EQ (r2.selected_inside (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_not_inside (r2).to_string (), "");
EXPECT_EQ (r2.selected_inside_differential (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_inside_differential (r2).second.to_string (), "");
EXPECT_EQ (r2.selected_outside (r2).to_string (), "");
EXPECT_EQ (r2.selected_not_outside (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_outside_differential (r2).first.to_string (), "");
EXPECT_EQ (r2.selected_outside_differential (r2).second.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_overlapping (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_not_overlapping (r2).to_string (), "");
EXPECT_EQ (r2.selected_overlapping_differential (r2).first.to_string (), r2.to_string ());
EXPECT_EQ (r2.selected_overlapping_differential (r2).second.to_string (), "");
EXPECT_EQ (r2.pull_inside (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.pull_overlapping (r2).to_string (), r2.to_string ());
EXPECT_EQ (r2.pull_interacting (r2).to_string (), r2.to_string ());
}

TEST(issue_277)
Expand Down

0 comments on commit a6d2930

Please sign in to comment.