Skip to content

Commit 0fdce69

Browse files
Merge pull request #2304 from KLayout/bugfix/issue-2299
Bugfix/issue 2299
2 parents 9d6fa50 + adb8126 commit 0fdce69

121 files changed

Lines changed: 2526 additions & 1490 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/db/db/dbAsIfFlatRegion.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ class DB_PUBLIC AsIfFlatRegion
138138

139139
virtual RegionDelegate *add (const Region &other) const;
140140

141+
virtual RegionDelegate *peel (double /*complexity_factor*/) const
142+
{
143+
return const_cast<AsIfFlatRegion *> (this);
144+
}
145+
141146
virtual RegionDelegate *selected_outside (const Region &other) const
142147
{
143148
return selected_interacting_generic (other, 1, false, Positive, size_t (1), std::numeric_limits<size_t>::max ()).first;

src/db/db/dbBoxScanner.h

Lines changed: 177 additions & 59 deletions
Large diffs are not rendered by default.

src/db/db/dbDeepRegion.cc

Lines changed: 218 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,13 @@ DeepRegion::begin_merged () const
401401
}
402402
}
403403

404+
RegionIteratorDelegate *
405+
DeepRegion::begin_unmerged () const
406+
{
407+
ensure_unmerged_polygons_valid ();
408+
return begin ();
409+
}
410+
404411
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
405412
DeepRegion::begin_iter () const
406413
{
@@ -445,6 +452,13 @@ DeepRegion::begin_merged_iter () const
445452
}
446453
}
447454

455+
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
456+
DeepRegion::begin_unmerged_iter () const
457+
{
458+
ensure_unmerged_polygons_valid ();
459+
return begin_iter ();
460+
}
461+
448462
bool
449463
DeepRegion::empty () const
450464
{
@@ -787,6 +801,46 @@ DeepRegion::ensure_merged_polygons_valid () const
787801
}
788802
}
789803

804+
void
805+
DeepRegion::ensure_unmerged_polygons_valid () const
806+
{
807+
if (! m_is_merged ||
808+
(deep_layer ().store ()->max_area_ratio () == 0.0 && deep_layer ().store ()->max_vertex_count () == 0)) {
809+
return;
810+
}
811+
812+
m_merged_polygons = deep_layer ().derived ();
813+
db::DeepLayer &polygons = const_cast<db::DeepLayer &> (deep_layer ());
814+
815+
m_merged_polygons_valid = true;
816+
m_is_merged = false;
817+
m_merged_polygons_boc_hash = deep_layer ().breakout_cells_hash ();
818+
819+
db::Layout &layout = polygons.layout ();
820+
polygons.swap (m_merged_polygons);
821+
822+
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
823+
824+
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
825+
db::Shapes &st = c->shapes (deep_layer ().layer ());
826+
827+
db::PolygonRefToShapesGenerator pr (&layout, &st);
828+
db::PolygonSplitter splitter (pr, polygons.store ()->max_area_ratio (), polygons.store ()->max_vertex_count ());
829+
830+
splitter.start ();
831+
for (auto p = s.begin (db::ShapeIterator::All); ! p.at_end (); ++p) {
832+
if (p->is_polygon ()) {
833+
pr.set_prop_id (p->prop_id ());
834+
db::Polygon poly;
835+
p->polygon (poly);
836+
splitter.put (poly);
837+
}
838+
}
839+
splitter.flush ();
840+
841+
}
842+
}
843+
790844
void
791845
DeepRegion::set_is_merged (bool f)
792846
{
@@ -826,6 +880,140 @@ DeepRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Var
826880
return new db::DeepRegion (result);
827881
}
828882

883+
namespace {
884+
885+
/**
886+
* @brief Implements a boolean AND or NOT operation with property handling
887+
*/
888+
class DB_PUBLIC PushHierLocalOperationWithProperties
889+
: public local_operation<db::object_with_properties<db::PolygonRef>, db::object_with_properties<db::PolygonRef>, db::object_with_properties<db::PolygonRef> >
890+
{
891+
public:
892+
PushHierLocalOperationWithProperties (double complexity_factor)
893+
: local_operation<db::object_with_properties<db::PolygonRef>, db::object_with_properties<db::PolygonRef>, db::object_with_properties<db::PolygonRef> > (),
894+
m_complexity_factor (complexity_factor)
895+
{
896+
// .. nothing yet ..
897+
}
898+
899+
OnEmptyIntruderHint on_empty_intruder_hint () const { return Copy; }
900+
901+
std::string description () const
902+
{
903+
return tl::to_string (tr ("'peel' operation"));
904+
}
905+
906+
907+
virtual void do_compute_local (db::Layout *layout, db::Cell * /*subject_cell*/, const shape_interactions<db::object_with_properties<db::PolygonRef>, db::object_with_properties<db::PolygonRef> > &interactions, std::vector<std::unordered_set<db::object_with_properties<db::PolygonRef> > > &results, const db::LocalProcessorBase *proc) const
908+
{
909+
tl_assert (results.size () == 1);
910+
auto &result = results.front ();
911+
912+
db::EdgeProcessor ep;
913+
914+
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
915+
916+
const auto &subject = interactions.subject_shape (i->first);
917+
db::properties_id_type prop_id = subject.properties_id ();
918+
919+
if (i->second.empty ()) {
920+
921+
result.insert (subject);
922+
923+
} else {
924+
925+
ep.clear ();
926+
927+
const auto &subject = interactions.subject_shape (i->first);
928+
for (auto e = subject.begin_edge (); ! e.at_end(); ++e) {
929+
ep.insert (*e, 0);
930+
}
931+
932+
size_t p2 = 1;
933+
for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) {
934+
const auto &intruder = interactions.intruder_shape (*ii);
935+
for (auto e = intruder.second.begin_edge (); ! e.at_end(); ++e) {
936+
ep.insert (*e, p2);
937+
}
938+
p2 += 2;
939+
}
940+
941+
std::unordered_set<db::object_with_properties<db::PolygonRef> > result1;
942+
943+
db::BooleanOp op (db::BooleanOp::ANotB);
944+
db::polygon_ref_generator_with_properties<db::object_with_properties<db::PolygonRef> > pr (layout, result1, prop_id);
945+
db::PolygonSplitter splitter (pr, proc->area_ratio (), proc->max_vertex_count ());
946+
db::PolygonGenerator pg (splitter, true, true);
947+
ep.set_base_verbosity (50);
948+
ep.process (pg, op);
949+
950+
if (result1.empty ()) {
951+
952+
// shortcut: nothing to do
953+
954+
} else if (m_complexity_factor < 0.0) {
955+
956+
// no complexity limit
957+
result.insert (result1.begin (), result1.end ());
958+
959+
} else if (m_complexity_factor == 0.0) {
960+
961+
// only remove shape if it is really entirely covered in this case
962+
result.insert (subject);
963+
964+
} else {
965+
966+
size_t vertices_before = subject.vertices ();
967+
size_t vertices_after = 0;
968+
for (auto r = result1.begin (); r != result1.end (); ++r) {
969+
vertices_after += r->vertices ();
970+
}
971+
972+
if (floor (0.5 + m_complexity_factor * vertices_before) >= vertices_after) {
973+
result.insert (result1.begin (), result1.end ());
974+
} else {
975+
result.insert (subject);
976+
}
977+
978+
}
979+
980+
}
981+
982+
}
983+
}
984+
985+
private:
986+
double m_complexity_factor;
987+
};
988+
989+
}
990+
991+
RegionDelegate *
992+
DeepRegion::peel (double complexity_factor) const
993+
{
994+
if (empty ()) {
995+
// we can return "this", as this method is only intended for in-place execution inside Region
996+
return const_cast<DeepRegion *> (this);
997+
}
998+
999+
DeepLayer dl_out (deep_layer ().derived ());
1000+
1001+
PushHierLocalOperationWithProperties op (complexity_factor);
1002+
1003+
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), deep_layer ().breakout_cells ());
1004+
configure_proc (proc);
1005+
proc.set_threads (deep_layer ().store ()->threads ());
1006+
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
1007+
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
1008+
1009+
// with this setting, only top-down interactions are considered
1010+
proc.set_top_down (true);
1011+
1012+
proc.run (&op, deep_layer ().layer (), deep_layer ().layer (), dl_out.layer ());
1013+
1014+
return new DeepRegion (dl_out);
1015+
}
1016+
8291017
RegionDelegate *
8301018
DeepRegion::and_with (const Region &other, PropertyConstraint property_constraint) const
8311019
{
@@ -922,6 +1110,10 @@ DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constr
9221110
DeepLayer
9231111
DeepRegion::and_with_impl (const DeepRegion *other, db::PropertyConstraint property_constraint) const
9241112
{
1113+
// booleans run better on simple polygons
1114+
ensure_unmerged_polygons_valid ();
1115+
other->ensure_unmerged_polygons_valid ();
1116+
9251117
DeepLayer dl_out (deep_layer ().derived ());
9261118

9271119
if (pc_skip (property_constraint)) {
@@ -956,6 +1148,10 @@ DeepRegion::and_with_impl (const DeepRegion *other, db::PropertyConstraint prope
9561148
DeepLayer
9571149
DeepRegion::not_with_impl (const DeepRegion *other, db::PropertyConstraint property_constraint) const
9581150
{
1151+
// booleans run better on simple polygons
1152+
ensure_unmerged_polygons_valid ();
1153+
other->ensure_unmerged_polygons_valid ();
1154+
9591155
DeepLayer dl_out (deep_layer ().derived ());
9601156
DeepLayer dl_prep;
9611157

@@ -1059,6 +1255,10 @@ DeepRegion::not_with_impl (const DeepRegion *other, db::PropertyConstraint prope
10591255
std::pair<DeepLayer, DeepLayer>
10601256
DeepRegion::and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const
10611257
{
1258+
// booleans run better on simple polygons
1259+
ensure_unmerged_polygons_valid ();
1260+
other->ensure_unmerged_polygons_valid ();
1261+
10621262
DeepLayer dl_out1 (deep_layer ().derived ());
10631263
DeepLayer dl_out2 (deep_layer ().derived ());
10641264

@@ -1179,6 +1379,10 @@ DeepRegion::add_in_place (const Region &other)
11791379
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
11801380
if (other_deep) {
11811381

1382+
// NOTE: as we don't benefit from merged shapes here, we prefer unmerged ones
1383+
// for potentially better performance.
1384+
other_deep->ensure_unmerged_polygons_valid ();
1385+
11821386
deep_layer ().add_from (other_deep->deep_layer ());
11831387

11841388
} else {
@@ -1885,6 +2089,10 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
18852089
return clone ();
18862090
}
18872091

2092+
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
2093+
// overlap after size and are not necessarily merged)
2094+
bool will_be_merged = (d < 0 && (merged_semantics () || is_merged ()));
2095+
18882096
const db::DeepLayer &polygons = merged_deep_layer ();
18892097

18902098
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
@@ -1904,7 +2112,8 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
19042112
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
19052113

19062114
db::PolygonRefToShapesGenerator pr (&layout, &st);
1907-
db::PolygonGenerator pg2 (pr, false /*don't resolve holes*/, true /*min. coherence*/);
2115+
db::PolygonSplitter splitter (pr, will_be_merged ? 0.0 : polygons.store ()->max_area_ratio (), will_be_merged ? 0 : polygons.store ()->max_vertex_count ());
2116+
db::PolygonGenerator pg2 (splitter, false /*don't resolve holes*/, true /*min. coherence*/);
19082117
db::SizingPolygonFilter siz (pg2, d_with_mag, d_with_mag, mode);
19092118

19102119
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
@@ -1916,11 +2125,7 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
19162125

19172126
}
19182127

1919-
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
1920-
// overlap after size and are not necessarily merged)
1921-
if (d < 0 && (merged_semantics () || is_merged ())) {
1922-
res->set_is_merged (true);
1923-
}
2128+
res->set_is_merged (will_be_merged);
19242129

19252130
return res.release ();
19262131
}
@@ -1938,6 +2143,10 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
19382143
return sized (dx, mode);
19392144
}
19402145

2146+
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
2147+
// overlap after size and are not necessarily merged)
2148+
bool will_be_merged = (dx < 0 && dy < 0 && (merged_semantics () || is_merged ()));
2149+
19412150
const db::DeepLayer &polygons = merged_deep_layer ();
19422151

19432152
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
@@ -1964,7 +2173,8 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
19642173
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
19652174

19662175
db::PolygonRefToShapesGenerator pr (&layout, &st);
1967-
db::PolygonGenerator pg2 (pr, false /*don't resolve holes*/, true /*min. coherence*/);
2176+
db::PolygonSplitter splitter (pr, will_be_merged ? 0.0 : polygons.store ()->max_area_ratio (), will_be_merged ? 0 : polygons.store ()->max_vertex_count ());
2177+
db::PolygonGenerator pg2 (splitter, false /*don't resolve holes*/, true /*min. coherence*/);
19682178
db::SizingPolygonFilter siz (pg2, dx_with_mag, dy_with_mag, mode);
19692179

19702180
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
@@ -1976,11 +2186,7 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
19762186

19772187
}
19782188

1979-
// in case of negative sizing the output polygons will still be merged (on positive sizing they might
1980-
// overlap after size and are not necessarily merged)
1981-
if (dx < 0 && dy < 0 && (merged_semantics () || is_merged ())) {
1982-
res->set_is_merged (true);
1983-
}
2189+
res->set_is_merged (will_be_merged);
19842190

19852191
return res.release ();
19862192
}

src/db/db/dbDeepRegion.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ class DB_PUBLIC DeepRegion
6666

6767
virtual RegionIteratorDelegate *begin () const;
6868
virtual RegionIteratorDelegate *begin_merged () const;
69+
virtual RegionIteratorDelegate *begin_unmerged () const;
6970

7071
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_iter () const;
7172
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_merged_iter () const;
73+
virtual std::pair<db::RecursiveShapeIterator, db::ICplxTrans> begin_unmerged_iter () const;
7274

7375
virtual bool empty () const;
7476
virtual bool is_merged () const;
@@ -138,6 +140,8 @@ class DB_PUBLIC DeepRegion
138140
virtual RegionDelegate *sized_inside (const Region &inside, bool outside, coord_type d, int steps, unsigned int mode) const;
139141
virtual RegionDelegate *sized_inside (const Region &inside, bool outside, coord_type dx, coord_type dy, int steps, unsigned int mode) const;
140142

143+
virtual RegionDelegate *peel (double complexity_factor) const;
144+
141145
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
142146

143147
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const Net *> *nets) const;
@@ -176,10 +180,11 @@ class DB_PUBLIC DeepRegion
176180
mutable DeepLayer m_merged_polygons;
177181
mutable bool m_merged_polygons_valid;
178182
mutable size_t m_merged_polygons_boc_hash;
179-
bool m_is_merged;
183+
mutable bool m_is_merged;
180184

181185
void init ();
182186
void ensure_merged_polygons_valid () const;
187+
void ensure_unmerged_polygons_valid () const;
183188
DeepLayer not_with_impl (const DeepRegion *other, PropertyConstraint property_constraint) const;
184189
DeepLayer and_with_impl (const DeepRegion *other, PropertyConstraint property_constraint) const;
185190
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const;

0 commit comments

Comments
 (0)