mirror of https://github.com/KLayout/klayout.git
WIP: hardening DeepRegion against min_coherence toggles (IHP PDK optimization)
This commit is contained in:
parent
5ae17c17a5
commit
a82f428d4c
|
|
@ -179,8 +179,10 @@ DeepRegion::~DeepRegion ()
|
|||
DeepRegion::DeepRegion (const DeepRegion &other)
|
||||
: MutableRegion (other), DeepShapeCollectionDelegateBase (other),
|
||||
m_merged_polygons_valid (other.m_merged_polygons_valid),
|
||||
m_merged_polygons_min_coherence (other.m_merged_polygons_min_coherence),
|
||||
m_merged_polygons_boc_hash (other.m_merged_polygons_boc_hash),
|
||||
m_is_merged (other.m_is_merged)
|
||||
m_is_merged (other.m_is_merged),
|
||||
m_is_merged_min_coherence (other.m_is_merged_min_coherence)
|
||||
{
|
||||
if (m_merged_polygons_valid) {
|
||||
m_merged_polygons = other.m_merged_polygons.copy ();
|
||||
|
|
@ -196,8 +198,10 @@ DeepRegion::operator= (const DeepRegion &other)
|
|||
DeepShapeCollectionDelegateBase::operator= (other);
|
||||
|
||||
m_merged_polygons_valid = other.m_merged_polygons_valid;
|
||||
m_merged_polygons_min_coherence = other.m_merged_polygons_min_coherence;
|
||||
m_merged_polygons_boc_hash = other.m_merged_polygons_boc_hash;
|
||||
m_is_merged = other.m_is_merged;
|
||||
m_is_merged_min_coherence = other.m_is_merged_min_coherence;
|
||||
if (m_merged_polygons_valid) {
|
||||
m_merged_polygons = other.m_merged_polygons.copy ();
|
||||
}
|
||||
|
|
@ -210,9 +214,11 @@ DeepRegion::operator= (const DeepRegion &other)
|
|||
void DeepRegion::init ()
|
||||
{
|
||||
m_merged_polygons_valid = false;
|
||||
m_merged_polygons_min_coherence = false;
|
||||
m_merged_polygons_boc_hash = 0;
|
||||
m_merged_polygons = db::DeepLayer ();
|
||||
m_is_merged = false;
|
||||
m_is_merged_min_coherence = false;
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
@ -228,7 +234,7 @@ void DeepRegion::merged_semantics_changed ()
|
|||
|
||||
void DeepRegion::min_coherence_changed ()
|
||||
{
|
||||
set_is_merged (false);
|
||||
// merged status is tracked in separate variables and is validated on inquiry
|
||||
}
|
||||
|
||||
void DeepRegion::join_properties_on_merge_changed ()
|
||||
|
|
@ -468,7 +474,7 @@ DeepRegion::empty () const
|
|||
bool
|
||||
DeepRegion::is_merged () const
|
||||
{
|
||||
return m_is_merged;
|
||||
return m_is_merged && (m_is_merged_min_coherence == min_coherence ());
|
||||
}
|
||||
|
||||
const db::Polygon *
|
||||
|
|
@ -739,18 +745,21 @@ DeepRegion::merged_deep_layer () const
|
|||
bool
|
||||
DeepRegion::merged_polygons_available () const
|
||||
{
|
||||
return m_is_merged || (m_merged_polygons_valid && m_merged_polygons_boc_hash == deep_layer ().breakout_cells_hash ());
|
||||
return (m_is_merged && m_is_merged_min_coherence == min_coherence ()) ||
|
||||
(m_merged_polygons_valid && m_merged_polygons_min_coherence == min_coherence () && m_merged_polygons_boc_hash == deep_layer ().breakout_cells_hash ());
|
||||
}
|
||||
|
||||
void
|
||||
DeepRegion::ensure_merged_polygons_valid () const
|
||||
{
|
||||
if (! m_merged_polygons_valid || (! m_is_merged && m_merged_polygons_boc_hash != deep_layer ().breakout_cells_hash ())) {
|
||||
if (! m_merged_polygons_valid || m_merged_polygons_min_coherence != min_coherence () ||
|
||||
((! m_is_merged || m_is_merged_min_coherence != min_coherence ()) && m_merged_polygons_boc_hash != deep_layer ().breakout_cells_hash ())) {
|
||||
|
||||
if (m_is_merged) {
|
||||
if (m_is_merged && m_is_merged_min_coherence == min_coherence ()) {
|
||||
|
||||
// NOTE: this will reuse the deep layer reference
|
||||
m_merged_polygons = deep_layer ();
|
||||
m_merged_polygons_min_coherence = min_coherence ();
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -796,6 +805,7 @@ DeepRegion::ensure_merged_polygons_valid () const
|
|||
}
|
||||
|
||||
m_merged_polygons_valid = true;
|
||||
m_merged_polygons_min_coherence = min_coherence ();
|
||||
m_merged_polygons_boc_hash = deep_layer ().breakout_cells_hash ();
|
||||
|
||||
}
|
||||
|
|
@ -813,7 +823,9 @@ DeepRegion::ensure_unmerged_polygons_valid () const
|
|||
db::DeepLayer &polygons = const_cast<db::DeepLayer &> (deep_layer ());
|
||||
|
||||
m_merged_polygons_valid = true;
|
||||
m_merged_polygons_min_coherence = m_is_merged_min_coherence;
|
||||
m_is_merged = false;
|
||||
m_is_merged_min_coherence = min_coherence ();
|
||||
m_merged_polygons_boc_hash = deep_layer ().breakout_cells_hash ();
|
||||
|
||||
db::Layout &layout = polygons.layout ();
|
||||
|
|
@ -845,6 +857,7 @@ void
|
|||
DeepRegion::set_is_merged (bool f)
|
||||
{
|
||||
m_is_merged = f;
|
||||
m_is_merged_min_coherence = min_coherence ();
|
||||
m_merged_polygons_valid = false;
|
||||
m_merged_polygons_boc_hash = 0;
|
||||
m_merged_polygons = db::DeepLayer ();
|
||||
|
|
@ -2026,6 +2039,7 @@ DeepRegion::merged () const
|
|||
|
||||
res->deep_layer ().layer ();
|
||||
|
||||
res->set_min_coherence (min_coherence ());
|
||||
res->set_is_merged (true);
|
||||
return res.release ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,8 +179,10 @@ private:
|
|||
|
||||
mutable DeepLayer m_merged_polygons;
|
||||
mutable bool m_merged_polygons_valid;
|
||||
mutable bool m_merged_polygons_min_coherence;
|
||||
mutable size_t m_merged_polygons_boc_hash;
|
||||
mutable bool m_is_merged;
|
||||
mutable bool m_is_merged_min_coherence;
|
||||
|
||||
void init ();
|
||||
void ensure_merged_polygons_valid () const;
|
||||
|
|
|
|||
|
|
@ -3341,3 +3341,132 @@ TEST(deep_region_peel)
|
|||
db::compare_layouts (_this, ly, tl::testdata () + "/algo/deep_region_peel_au.gds");
|
||||
}
|
||||
|
||||
TEST(min_coherence_and_merge)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
auto &top = ly.cell (ly.add_cell ("TOP"));
|
||||
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
|
||||
|
||||
top.shapes (l1).insert (db::Box (0, 0, 1000, 2000));
|
||||
top.shapes (l1).insert (db::Box (1000, 2000, 10000, 3000));
|
||||
top.shapes (l1).insert (db::Box (9000, 3000, 10000, 10000));
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
db::Region r1 (db::RecursiveShapeIterator (ly, top, l1), dss);
|
||||
|
||||
EXPECT_EQ (r1.min_coherence (), false);
|
||||
EXPECT_EQ (r1.is_merged (), false);
|
||||
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), false);
|
||||
EXPECT_EQ (r1.to_string (), "(0,0;0,2000;1000,2000;1000,0);(1000,2000;1000,3000;10000,3000;10000,2000);(9000,3000;9000,10000;10000,10000;10000,3000)");
|
||||
|
||||
// forces merged status
|
||||
r1.sized (1);
|
||||
|
||||
EXPECT_EQ (r1.min_coherence (), false);
|
||||
EXPECT_EQ (r1.is_merged (), false);
|
||||
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
|
||||
|
||||
db::Region r2 = r1.merged ();
|
||||
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
|
||||
|
||||
EXPECT_EQ (r2.min_coherence (), false);
|
||||
|
||||
EXPECT_EQ (r1.min_coherence (), false);
|
||||
EXPECT_EQ (r1.is_merged (), false);
|
||||
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
|
||||
|
||||
r1.set_min_coherence (true);
|
||||
|
||||
// valid_merged_polygons is invalidated
|
||||
EXPECT_EQ (r1.min_coherence (), true);
|
||||
EXPECT_EQ (r1.is_merged (), false);
|
||||
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), false);
|
||||
|
||||
r1.set_min_coherence (false);
|
||||
|
||||
// setting min_coherence to false will bring the validation back
|
||||
EXPECT_EQ (r1.min_coherence (), false);
|
||||
EXPECT_EQ (r1.is_merged (), false);
|
||||
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
|
||||
|
||||
r1.set_min_coherence (true);
|
||||
|
||||
// valid_merged_polygons is invalidated again by setting min_coherence to true
|
||||
EXPECT_EQ (r1.min_coherence (), true);
|
||||
EXPECT_EQ (r1.is_merged (), false);
|
||||
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), false);
|
||||
|
||||
// inserting a box into the region will reset the merged valid flag and not bring it back by resetting min_coherence
|
||||
db::Region r3 = r1;
|
||||
r3.insert (db::Box (0, 0, 100, 100));
|
||||
r3.set_min_coherence (false);
|
||||
EXPECT_EQ (r3.is_merged (), false);
|
||||
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r3.delegate ())->merged_polygons_available (), false);
|
||||
|
||||
// creates a intrinsically merged copy and tests if the min_coherence
|
||||
// flag is inherited
|
||||
r3 = r1.merged ();
|
||||
EXPECT_EQ (r3.to_string (), "(0,0;0,2000;1000,2000;1000,0);(1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000)");
|
||||
EXPECT_EQ (r3.is_merged (), true);
|
||||
EXPECT_EQ (r3.min_coherence (), true);
|
||||
|
||||
// merged polygons are validated against min_coherence = true during r1.merged() before, so
|
||||
// resetting min_coherence to false will invalidat them
|
||||
r1.set_min_coherence (false);
|
||||
EXPECT_EQ (r1.min_coherence (), false);
|
||||
EXPECT_EQ (r1.is_merged (), false);
|
||||
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), false);
|
||||
|
||||
// creates a intrinsically merged copy and tests if the min_coherence
|
||||
// flag is inherited
|
||||
r3 = r1.merged ();
|
||||
EXPECT_EQ (r3.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
|
||||
EXPECT_EQ (r3.is_merged (), true);
|
||||
EXPECT_EQ (r3.min_coherence (), false);
|
||||
|
||||
// r2 is an intrinsically merged region (with min coherence false)
|
||||
EXPECT_EQ (r2.min_coherence (), false);
|
||||
EXPECT_EQ (r2.is_merged (), true);
|
||||
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
|
||||
|
||||
// after changing min_coherence, the merged status is no longer true
|
||||
r2.set_min_coherence (true);
|
||||
EXPECT_EQ (r2.min_coherence (), true);
|
||||
EXPECT_EQ (r2.is_merged (), false);
|
||||
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
|
||||
|
||||
// read-only experiments with r2
|
||||
|
||||
// inserting a box into the region will reset the merged state
|
||||
// and not bring it back by resetting min_coherence
|
||||
r3 = r2;
|
||||
r3.insert (db::Box (0, 0, 100, 100));
|
||||
r3.set_min_coherence (false);
|
||||
EXPECT_EQ (r3.is_merged (), false);
|
||||
EXPECT_EQ (r3.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0);(0,0;0,100;100,100;100,0)");
|
||||
|
||||
// unmerge after resetting min coherence
|
||||
r3 = r2;
|
||||
r3.set_min_coherence (false);
|
||||
EXPECT_EQ (r3.is_merged (), true);
|
||||
r3.begin_unmerged ();
|
||||
EXPECT_EQ (r3.is_merged (), false);
|
||||
EXPECT_EQ (r3.to_string (), "(1000,2000;1000,3000;10000,3000;10000,2000);(9000,3000;9000,10000;10000,10000;10000,3000);(0,0;0,2000;1000,2000;1000,0)");
|
||||
|
||||
// r2 still remembers it is merged, even though it does not say so and
|
||||
// will unmerge
|
||||
r3 = r2;
|
||||
EXPECT_EQ (r3.is_merged (), false);
|
||||
// unmerge
|
||||
r3.begin_unmerged ();
|
||||
EXPECT_EQ (r3.is_merged (), false);
|
||||
EXPECT_EQ (r3.to_string (), "(1000,2000;1000,3000;10000,3000;10000,2000);(9000,3000;9000,10000;10000,10000;10000,3000);(0,0;0,2000;1000,2000;1000,0)");
|
||||
|
||||
// r2 merged state it can be restored by resetting min_coherence to false
|
||||
r2.set_min_coherence (false);
|
||||
EXPECT_EQ (r2.min_coherence (), false);
|
||||
EXPECT_EQ (r2.is_merged (), true);
|
||||
EXPECT_EQ (r2.to_string (), "(0,0;0,2000;1000,2000;1000,3000;9000,3000;9000,10000;10000,10000;10000,2000;1000,2000;1000,0)");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue