From defbf33d197daafbf38d27701e4b99ca22b3aede Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 25 Sep 2018 23:26:18 +0200 Subject: [PATCH] WIP: distance parameter for hierarchical processor. --- .../tools/netx/db_plugin/dbHierProcessor.cc | 67 ++--- .../tools/netx/db_plugin/dbHierProcessor.h | 7 +- src/plugins/tools/netx/testdata/hlp1.oas | Bin 583 -> 691 bytes src/plugins/tools/netx/testdata/hlp10.oas | Bin 489 -> 560 bytes src/plugins/tools/netx/testdata/hlp2.oas | Bin 827 -> 1039 bytes src/plugins/tools/netx/testdata/hlp3.oas | Bin 649 -> 755 bytes src/plugins/tools/netx/testdata/hlp4.oas | Bin 667 -> 768 bytes src/plugins/tools/netx/testdata/hlp5.oas | Bin 763 -> 868 bytes src/plugins/tools/netx/testdata/hlp6.oas | Bin 969 -> 1298 bytes src/plugins/tools/netx/testdata/hlp7.oas | Bin 693 -> 795 bytes src/plugins/tools/netx/testdata/hlp8.oas | Bin 815 -> 955 bytes src/plugins/tools/netx/testdata/hlp9.oas | Bin 724 -> 845 bytes .../netx/unit_tests/dbHierProcessorTests.cc | 236 +++++++++++++++++- 13 files changed, 272 insertions(+), 38 deletions(-) diff --git a/src/plugins/tools/netx/db_plugin/dbHierProcessor.cc b/src/plugins/tools/netx/db_plugin/dbHierProcessor.cc index b5e25f8b6..47ab20388 100644 --- a/src/plugins/tools/netx/db_plugin/dbHierProcessor.cc +++ b/src/plugins/tools/netx/db_plugin/dbHierProcessor.cc @@ -289,8 +289,8 @@ struct InteractionRegistrationShape2Inst : db::box_scanner_receiver2 { public: - InteractionRegistrationShape2Inst (db::Layout *layout, unsigned int intruder_layer, std::map > *result) - : mp_layout (layout), m_intruder_layer (intruder_layer), mp_result (result) + InteractionRegistrationShape2Inst (db::Layout *layout, unsigned int intruder_layer, db::Coord dist, std::map > *result) + : mp_layout (layout), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result) { // nothing yet .. } @@ -300,11 +300,11 @@ public: const db::Cell &intruder_cell = mp_layout->cell (inst->object ().cell_index ()); db::box_convert inst_bc (*mp_layout, m_intruder_layer); - for (db::CellInstArray::iterator n = inst->begin_touching (ref->box ().enlarged (db::Vector (-1, -1)), inst_bc); !n.at_end (); ++n) { + for (db::CellInstArray::iterator n = inst->begin_touching (ref->box ().enlarged (db::Vector (m_dist - 1, m_dist - 1)), inst_bc); !n.at_end (); ++n) { db::ICplxTrans tn = inst->complex_trans (*n); - db::Box region = ref->box ().transformed (tn.inverted ()) & intruder_cell.bbox (m_intruder_layer); + db::Box region = ref->box ().transformed (tn.inverted ()).enlarged (db::Vector (m_dist, m_dist)) & intruder_cell.bbox (m_intruder_layer).enlarged (db::Vector (m_dist, m_dist)); if (! region.empty ()) { // @@@ TODO: should be lighter, cache, handle arrays .. @@ -312,7 +312,7 @@ public: si.shape_flags (polygon_ref_flags ()); while (! si.at_end ()) { - // @@@ should be easier to transform references + // @@@ it should be easier to transform references const db::PolygonRef *ref2 = si.shape ().basic_ptr (db::PolygonRef::tag ()); db::Polygon poly = ref2->obj ().transformed (tn * si.trans () * db::ICplxTrans (ref2->trans ())); (*mp_result)[*ref].push_back (db::PolygonRef (poly, mp_layout->shape_repository())); @@ -329,11 +329,12 @@ public: private: db::Layout *mp_layout; unsigned int m_intruder_layer; + db::Coord m_dist; std::map > *mp_result; }; static bool -instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, unsigned int layer1, const db::Layout *layout2, const db::CellInstArray *inst2, unsigned int layer2) +instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, unsigned int layer1, const db::Layout *layout2, const db::CellInstArray *inst2, unsigned int layer2, db::Coord dist) { // TODO: this algorithm is not in particular effective for identical arrays @@ -347,7 +348,7 @@ instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, u db::ICplxTrans tn1 = inst1->complex_trans (*n); db::ICplxTrans tni1 = tn1.inverted (); - db::Box ibox1 = tn1 * cell1.bbox (layer1); + db::Box ibox1 = tn1 * cell1.bbox (layer1).enlarged (db::Vector (dist, dist)); if (! ibox1.empty ()) { @@ -361,7 +362,9 @@ instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, u } db::ICplxTrans tn2 = inst2->complex_trans (*k); - db::Box ibox2 = tn2 * cell2.bbox (layer2); + + // NOTE: we need to enlarge both subject *and* intruder boxes - either ubject comes close to intruder or the other way around + db::Box ibox2 = tn2 * cell2.bbox (layer2).enlarged (db::Vector (dist, dist)); db::ICplxTrans tn21 = tni1 * tn2; if (! relative_trans_seen.insert (tn21).second) { @@ -396,8 +399,8 @@ struct InteractionRegistrationInst2Inst : db::box_scanner_receiver2 { public: - InteractionRegistrationInst2Inst (const db::Layout *subject_layout, unsigned int subject_layer, const db::Layout *intruder_layout, unsigned int intruder_layer, std::map, std::set > > *result) - : mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_subject_layer (subject_layer), m_intruder_layer (intruder_layer), mp_result (result) + InteractionRegistrationInst2Inst (const db::Layout *subject_layout, unsigned int subject_layer, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, std::map, std::set > > *result) + : mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_subject_layer (subject_layer), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result) { // nothing yet .. } @@ -408,7 +411,7 @@ public: // NOTE: self-interactions are possible for arrays: different elements of the // array may interact which is a cell-external interaction. if ((*inst1 != *inst2 || inst1->size () > 1) - && instances_interact (mp_subject_layout, inst1, m_subject_layer, mp_intruder_layout, inst2, m_intruder_layer)) { + && instances_interact (mp_subject_layout, inst1, m_subject_layer, mp_intruder_layout, inst2, m_intruder_layer, m_dist)) { (*mp_result) [inst1].first.insert (inst2); } } @@ -416,20 +419,21 @@ public: private: const db::Layout *mp_subject_layout, *mp_intruder_layout; unsigned int m_subject_layer, m_intruder_layer; + db::Coord m_dist; std::map, std::set > > *mp_result; }; static bool -instance_shape_interacts (const db::Layout *layout, const db::CellInstArray *inst, unsigned int layer, const db::PolygonRef &ref) +instance_shape_interacts (const db::Layout *layout, const db::CellInstArray *inst, unsigned int layer, const db::PolygonRef &ref, db::Coord dist) { const db::Cell &cell = layout->cell (inst->object ().cell_index ()); db::box_convert inst_bc (*layout, layer); db::Box rbox = ref.box (); - for (db::CellInstArray::iterator n = inst->begin_touching (rbox.enlarged (db::Vector (-1, -1)), inst_bc); ! n.at_end (); ++n) { + for (db::CellInstArray::iterator n = inst->begin_touching (rbox.enlarged (db::Vector (dist - 1, dist - 1)), inst_bc); ! n.at_end (); ++n) { db::ICplxTrans tn = inst->complex_trans (*n); - db::Box cbox = (tn * cell.bbox (layer)) & rbox; + db::Box cbox = (tn * cell.bbox (layer)).enlarged (db::Vector (dist, dist)) & rbox.enlarged (db::Vector (dist, dist)); if (! cbox.empty ()) { @@ -452,15 +456,15 @@ struct InteractionRegistrationInst2Shape : db::box_scanner_receiver2 { public: - InteractionRegistrationInst2Shape (const db::Layout *subject_layout, unsigned int subject_layer, std::map, std::set > > *result) - : mp_subject_layout (subject_layout), m_subject_layer (subject_layer), mp_result (result) + InteractionRegistrationInst2Shape (const db::Layout *subject_layout, unsigned int subject_layer, db::Coord dist, std::map, std::set > > *result) + : mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result) { // nothing yet .. } void add (const db::CellInstArray *inst, int, const db::PolygonRef *ref, int) { - if (instance_shape_interacts (mp_subject_layout, inst, m_subject_layer, *ref)) { + if (instance_shape_interacts (mp_subject_layout, inst, m_subject_layer, *ref, m_dist)) { (*mp_result) [inst].second.insert (*ref); } } @@ -468,6 +472,7 @@ public: private: const db::Layout *mp_subject_layout; unsigned int m_subject_layer; + db::Coord m_dist; std::map, std::set > > *mp_result; }; @@ -482,10 +487,10 @@ LocalProcessor::LocalProcessor (db::Layout *layout, db::Cell *top) // .. nothing yet .. } -void LocalProcessor::run (LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer, db::Coord dist) +void LocalProcessor::run (LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer) { LocalProcessorContexts contexts; - compute_contexts (contexts, op, subject_layer, intruder_layer, dist); + compute_contexts (contexts, op, subject_layer, intruder_layer); compute_results (contexts, op, output_layer); } @@ -496,7 +501,7 @@ void LocalProcessor::push_results (db::Cell *cell, unsigned int output_layer, co } } -void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, db::Coord dist) +void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer) { tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Computing contexts for ")) + description ()); @@ -506,10 +511,10 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const L contexts.set_description (op->description ()); std::pair, std::set > intruders; - compute_contexts (contexts, 0, 0, mp_top, db::ICplxTrans (), dist, intruders); + compute_contexts (contexts, 0, 0, mp_top, db::ICplxTrans (), intruders, op->dist ()); } -void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *parent, db::Cell *cell, const db::ICplxTrans &cell_inst, db::Coord dist, const std::pair, std::set > &intruders) +void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *parent, db::Cell *cell, const db::ICplxTrans &cell_inst, const std::pair, std::set > &intruders, db::Coord dist) { if (tl::verbosity () >= 30) { if (! parent) { @@ -549,7 +554,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc { db::box_scanner2 scanner; - InteractionRegistrationInst2Inst rec (mp_layout, contexts.subject_layer (), mp_layout, contexts.intruder_layer (), &interactions); + InteractionRegistrationInst2Inst rec (mp_layout, contexts.subject_layer (), mp_layout, contexts.intruder_layer (), dist, &interactions); for (db::Cell::const_iterator i = cell->begin (); !i.at_end (); ++i) { if (! inst_bcs (i->cell_inst ()).empty ()) { @@ -566,12 +571,12 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc } } - scanner.process (rec, 0, inst_bcs, inst_bci); + scanner.process (rec, dist, inst_bcs, inst_bci); } { db::box_scanner2 scanner; - InteractionRegistrationInst2Shape rec (mp_layout, contexts.subject_layer (), &interactions); + InteractionRegistrationInst2Shape rec (mp_layout, contexts.subject_layer (), dist, &interactions); for (db::Cell::const_iterator i = cell->begin (); !i.at_end (); ++i) { if (! inst_bcs (i->cell_inst ()).empty ()) { @@ -586,7 +591,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc scanner.insert2 (i->basic_ptr (db::PolygonRef::tag ()), 0); } - scanner.process (rec, 0, inst_bcs, db::box_convert ()); + scanner.process (rec, dist, inst_bcs, db::box_convert ()); } for (std::map, std::set > >::const_iterator i = interactions.begin (); i != interactions.end (); ++i) { @@ -597,7 +602,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc db::ICplxTrans tn = i->first->complex_trans (*n); db::ICplxTrans tni = tn.inverted (); - db::Box nbox = tn * child_cell.bbox (contexts.subject_layer ()); + db::Box nbox = tn * child_cell.bbox (contexts.subject_layer ()).enlarged (db::Vector (dist, dist)); if (! nbox.empty ()) { @@ -619,7 +624,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc } } - compute_contexts (contexts, context, cell, &child_cell, tn, dist, intruders_below); + compute_contexts (contexts, context, cell, &child_cell, tn, intruders_below, dist); } @@ -684,14 +689,14 @@ LocalProcessor::compute_local_cell (LocalProcessorContexts &contexts, db::Cell * scanner.insert2 (i->basic_ptr (db::PolygonRef::tag ()), 0); } - scanner.process (rec, 0, db::box_convert (), db::box_convert ()); + scanner.process (rec, op->dist (), db::box_convert (), db::box_convert ()); } if (! shapes_subject.empty () && ! (cell->begin ().at_end () && intruders.first.empty ())) { db::box_scanner2 scanner; - InteractionRegistrationShape2Inst rec (mp_layout, contexts.intruder_layer (), &interactions); + InteractionRegistrationShape2Inst rec (mp_layout, contexts.intruder_layer (), op->dist (), &interactions); for (db::Shapes::shape_iterator i = shapes_subject.begin (polygon_ref_flags ()); !i.at_end (); ++i) { scanner.insert1 (i->basic_ptr (db::PolygonRef::tag ()), 0); @@ -708,7 +713,7 @@ LocalProcessor::compute_local_cell (LocalProcessorContexts &contexts, db::Cell * } } - scanner.process (rec, 0, db::box_convert (), inst_bci); + scanner.process (rec, op->dist (), db::box_convert (), inst_bci); } diff --git a/src/plugins/tools/netx/db_plugin/dbHierProcessor.h b/src/plugins/tools/netx/db_plugin/dbHierProcessor.h index 6113e50d7..56c7a0b20 100644 --- a/src/plugins/tools/netx/db_plugin/dbHierProcessor.h +++ b/src/plugins/tools/netx/db_plugin/dbHierProcessor.h @@ -52,6 +52,7 @@ public: virtual void compute_local (db::Layout *layout, const std::map > &interactions, std::set &result) const = 0; virtual on_empty_intruder_mode on_empty_intruder_hint () const = 0; virtual std::string description () const = 0; + virtual db::Coord dist () const { return 0; } }; class DB_PLUGIN_PUBLIC BoolAndOrNotLocalOperation @@ -212,8 +213,8 @@ class DB_PLUGIN_PUBLIC LocalProcessor { public: LocalProcessor (db::Layout *layout, db::Cell *top); - void run (LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer, db::Coord dist = 0); - void compute_contexts (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, db::Coord dist = 0); + void run (LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer); + void compute_contexts (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer); void compute_results (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int output_layer); void set_description (const std::string &d) @@ -233,7 +234,7 @@ private: db::Cell *mp_top; std::string m_description; - void compute_contexts (LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *parent, db::Cell *cell, const db::ICplxTrans &cell_inst, db::Coord dist, const std::pair, std::set > &intruders); + void compute_contexts (LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *parent, db::Cell *cell, const db::ICplxTrans &cell_inst, const std::pair, std::set > &intruders, db::Coord dist); void push_results (db::Cell *cell, unsigned int output_layer, const std::set &result) const; void compute_local_cell (LocalProcessorContexts &contexts, db::Cell *cell, const LocalOperation *op, const std::pair, std::set > &intruders, std::set &result); }; diff --git a/src/plugins/tools/netx/testdata/hlp1.oas b/src/plugins/tools/netx/testdata/hlp1.oas index 17754711a3ba196f11516e58c629422d70438e83..7dee89a076c77d0e72e4a3c29d851723d02402dc 100644 GIT binary patch delta 128 zcmX@kvYB;*J7cb>Wf~*f2BitiKe-mj|KQrd*>IHUgPy1bBhv%z4|*^DG3^isaV}`Q zV1H0{LsrxP#9pEMV<#h!$?`+FgYO2AoFF4=m=2OTpn9SXr2Ym=2j2vl3yvW651`2t VPB5)-W11Yu_+@eeBPSCB0|0ATZx*AC%pY tg}L>|P87FJkbyh)L>KPCq-u`)3*007s{YS{n) delta 89 zcmeC@*v&SfNQ#9y#6N(6h0WQ+)5pb-5y~)P=4GDT&S*8UV~Q9rgWw0o2{JpTFbaNP peshiSf`&*nBg15VCS7I`OQy*;7)>VIFr_mxO%`PS!`#5Y000P#7gYcN diff --git a/src/plugins/tools/netx/testdata/hlp3.oas b/src/plugins/tools/netx/testdata/hlp3.oas index 765d95764f3cf57d0d0dfe60aa849bf9cf510673..10ecef81b160e9b52e01652290c367dbf9e923f3 100644 GIT binary patch delta 185 zcmeBV{meR{n2*ib!_&vbkeNBeKY*8EVq;CcsAU=>+Xkfx%s;sn$p7Hl!1-YX(++V_ z3r3~~+8^|8JYr%1u`g)6V80NxfKAi@#9pEMVlE?)$?`+FgYO2AWDqq>2T2@I-H`-R zeuJfhk70%ui1`C(Y{MF+4|=?ef}4FD1N0gxQH7YhKuJ`xmn0szz& h&?vBj0+YA_I|CItWs`UTH30&X0Rr%o5CRPX0015G6YT&1 diff --git a/src/plugins/tools/netx/testdata/hlp4.oas b/src/plugins/tools/netx/testdata/hlp4.oas index 0e43780b40094afce9ccba2545d64f650b3e6f22..9da959541d776048b6bf490829585188091ca774 100644 GIT binary patch delta 186 zcmbQu+Q2rUNR*k)*~8Pv#Ry6pGBbzx2TWXFS1)Rq&d78@>EL6Sp#@_8 z;94Nxu!iY_o~UISBijb03Cur%B0sn`aDG_9v_l-ED{V>u6#;0J~Y PG7Dw`X~xa-8Dkg$?4~w< delta 48 zcmaFD_M3G=H7|3Be*iOkaHx~BtB=pbjyfh@rpbkj-8_tf9~dUcESSk8_8;y)NWEn(F7@00;tkC^%gb~DM`JvpwcLPMK zGl-g|gX9jV9_R$h0nNC<(!tlEe!&sU`2n<|<1*6O>t#s|CbW6J&NA26I5(eDRNIM>h*dYJ<`PZJ>o87J+#n t7f(3B1VkXuNP>L*pzOv(7H)D%N7Ozcby3;=a;c~1ZU delta 68 zcmV-K0K5N^3dskMdkq6rPf!B~Q&mDkMNCYQh%o^Ik-Fv;4FM7O0FWG@nF0#|^aGLt a;sFux0<$Xu6afJOlOY7}lQ0Ah0ssKRcoP!< diff --git a/src/plugins/tools/netx/testdata/hlp7.oas b/src/plugins/tools/netx/testdata/hlp7.oas index a167833a837033f9f79d6445be8fe47e52ef7042..a8c2a5649f187110296a98af298e5be80c4db14b 100644 GIT binary patch delta 214 zcmdnWI-6}mu_&vvf0%0!Gn=!Ar;m#vGjoW4059Xj1C#4TEz=m;HYiPC{>imK{s-3v z&JQb?c8H5wFfu*R{-Af`5fcN5eL>>|`-P|lY@!Ar_6pq>a~Xk5mLJL;d^dn3gQ#IT zNaBF%jwF!s8!R1s3^TMq%pX8w8`dy=(BowgDQ050B6dMzLo<^|L4#zED1%7B#5u}( vOoA^MJ}hG4W;kFcB>01Ig3JzaZl)LP8(8`o1vapVl*4s_Rcvl$G++b(0|P=L delta 93 zcmbQuwv}~4u_&9fho_H=Av1G`e*iP9vwxUt5HHi@Hb!$shKU`Mjd&Rae=tmt*&)u& x{DOT0OFyFk(*_p7A50$>u`qBm9Iz7-DQ9B1B6dMzLo*XMBaqLu`8A^fBLI{48MOca diff --git a/src/plugins/tools/netx/testdata/hlp8.oas b/src/plugins/tools/netx/testdata/hlp8.oas index 27ca4eb75fd2088524110bed946c4b7a336d0ba0..670bec10b96c52c1408917ee6d6a2eba04ee59a3 100644 GIT binary patch delta 300 zcmZ3_wwrxIu^g+jf0%0!Gn=!Ar;m#vGkb8Tle4Rj4>NO!e*iDz#FI6_qK4^=Ocyi` zsP0G-wP0lW!L>lXVGYvL%3$!i(SWkq%2HZq9nqFBkm NG}(~p4|4+p0{}F1TbKX< delta 164 zcmdnZzMgGDu^gMTho_H=Av1G`e*iP9vwxUt5HovlsFSm+j}I@?Qq(QPrbR#D>Q;OsQMy8)!ULqwQM0bcc9A)ALYo6@RB*(}!`5@De$rqSd GfjR*0r7U&; diff --git a/src/plugins/tools/netx/testdata/hlp9.oas b/src/plugins/tools/netx/testdata/hlp9.oas index 3baf603e09e750fea443d8d612e6402edb772029..c12644748b66b69ebad38ca37f68a1b1c604bb16 100644 GIT binary patch delta 220 zcmcb@dX{ZMH4jUWr=L4BbBKQcFXO~^Ic8DTw24dnCu=k6O#Eb7Z<)r(wn1qE^G~h? z@;|sXaDG_9v_o9ff|2Qg_6NNikC+%h>2uRx zq}qs);e|qjB}4O1AI8jKdmzxd58YMKgS&kzJkaWl-35D-;N0|{Jk+&qQR Gfe`?-fktou delta 99 zcmX@hc7=69H4k%$e*iN}kf)zJFVn(r?74wERMp4yNMy3X%8G_slb0h>r4O2k81@bR`GjHZ)a$p1i D7$P2o diff --git a/src/plugins/tools/netx/unit_tests/dbHierProcessorTests.cc b/src/plugins/tools/netx/unit_tests/dbHierProcessorTests.cc index afb862b97..7034f412f 100644 --- a/src/plugins/tools/netx/unit_tests/dbHierProcessorTests.cc +++ b/src/plugins/tools/netx/unit_tests/dbHierProcessorTests.cc @@ -39,6 +39,41 @@ enum TestMode TMNot = 1 }; +/** + * @brief A new processor class which and/nots with a sized version of the intruder + */ +class BoolAndOrNotWithSizedLocalOperation + : public db::BoolAndOrNotLocalOperation +{ +public: + BoolAndOrNotWithSizedLocalOperation (bool is_and, db::Coord dist) + : BoolAndOrNotLocalOperation (is_and), m_dist (dist) + { + // .. nothing yet .. + } + + virtual void compute_local (db::Layout *layout, const std::map > &interactions, std::set &result) const + { + std::map > sized_interactions = interactions; + for (std::map >::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) { + for (std::vector::iterator j = i->second.begin (); j != i->second.end (); ++j) { + db::Polygon poly = j->obj ().transformed (j->trans ()); + poly.size (m_dist, m_dist); + *j = db::PolygonRef (poly, layout->shape_repository ()); + } + } + BoolAndOrNotLocalOperation::compute_local (layout, sized_interactions, result); + } + + db::Coord dist () const + { + return m_dist; + } + +private: + db::Coord m_dist; +}; + /** * @brief Turns a layer into polygons and polygon references * The hierarchical processor needs polygon references and can't work on polygons directly. @@ -75,7 +110,7 @@ std::string contexts_to_s (db::Layout *layout, db::LocalProcessorContexts &conte return res; } -void run_test_bool (tl::TestBase *_this, const char *file, TestMode mode, int out_layer_num, db::Coord enl = 0, std::string *context_doc = 0) +void run_test_bool (tl::TestBase *_this, const char *file, TestMode mode, int out_layer_num, std::string *context_doc = 0) { db::Layout layout_org; @@ -120,7 +155,60 @@ void run_test_bool (tl::TestBase *_this, const char *file, TestMode mode, int ou proc.run (&op, l1, l2, lout); } else { db::LocalProcessorContexts contexts; - proc.compute_contexts (contexts, &op, l1, l2, enl); + proc.compute_contexts (contexts, &op, l1, l2); + *context_doc = contexts_to_s (&layout_org, contexts); + proc.compute_results (contexts, &op, lout); + } + + db::compare_layouts (_this, layout_org, testdata (file), lmap, false /*skip other layers*/, db::AsPolygons); +} + +void run_test_bool_with_size (tl::TestBase *_this, const char *file, TestMode mode, db::Coord dist, int out_layer_num, std::string *context_doc = 0) +{ + db::Layout layout_org; + + unsigned int l1 = 0, l2 = 0, lout = 0; + db::LayerMap lmap; + + { + tl::InputStream stream (testdata (file)); + db::Reader reader (stream); + + db::LayerProperties p; + + p.layer = 1; + p.datatype = 0; + lmap.map (db::LDPair (1, 0), l1 = layout_org.insert_layer ()); + layout_org.set_properties (l1, p); + + p.layer = 2; + p.datatype = 0; + lmap.map (db::LDPair (2, 0), l2 = layout_org.insert_layer ()); + layout_org.set_properties (l2, p); + + p.layer = out_layer_num; + p.datatype = 0; + lmap.map (db::LDPair (out_layer_num, 0), lout = layout_org.insert_layer ()); + layout_org.set_properties (lout, p); + + db::LoadLayoutOptions options; + options.get_options ().layer_map = lmap; + options.get_options ().create_other_layers = false; + reader.read (layout_org, options); + } + + layout_org.clear_layer (lout); + normalize_layer (layout_org, l1); + normalize_layer (layout_org, l2); + + BoolAndOrNotWithSizedLocalOperation op (mode == TMAnd, dist); + db::LocalProcessor proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ())); + + if (! context_doc) { + proc.run (&op, l1, l2, lout); + } else { + db::LocalProcessorContexts contexts; + proc.compute_contexts (contexts, &op, l1, l2); *context_doc = contexts_to_s (&layout_org, contexts); proc.compute_results (contexts, &op, lout); } @@ -228,7 +316,7 @@ TEST(BasicAnd9) { // Top-level ring structure, AND std::string doc; - run_test_bool (_this, "hlp9.oas", TMAnd, 100, 0, &doc); + run_test_bool (_this, "hlp9.oas", TMAnd, 100, &doc); EXPECT_EQ (doc, // This means: the interaction test is strong enough, so it does not see interactions between the // ring and the cells embedded inside the ring. So there is only one cell context. Some shapes @@ -244,7 +332,7 @@ TEST(BasicNot9) { // Top-level ring structure, NOT std::string doc; - run_test_bool (_this, "hlp9.oas", TMNot, 101, 0, &doc); + run_test_bool (_this, "hlp9.oas", TMNot, 101, &doc); EXPECT_EQ (doc, // This means: the interaction test is strong enough, so it does not see interactions between the // ring and the cells embedded inside the ring. So there is only one cell context. Some shapes @@ -268,3 +356,143 @@ TEST(BasicNot10) run_test_bool (_this, "hlp10.oas", TMNot, 101); } +TEST(BasicAndWithSize1) +{ + // Simple flat AND + run_test_bool_with_size (_this, "hlp1.oas", TMAnd, 1500, 102); +} + +TEST(BasicNotWithSize1) +{ + // Simple flat NOT + run_test_bool_with_size (_this, "hlp1.oas", TMNot, 1500, 103); +} + +TEST(BasicAndWithSize2) +{ + // Up/down and down/up interactions, AND + run_test_bool_with_size (_this, "hlp2.oas", TMAnd, 1500, 102); +} + +TEST(BasicNotWithSize2) +{ + // Up/down and down/up interactions, NOT + run_test_bool_with_size (_this, "hlp2.oas", TMNot, 1500, 103); +} + +TEST(BasicAndWithSize3) +{ + // Variant building, AND + run_test_bool_with_size (_this, "hlp3.oas", TMAnd, 1500, 102); +} + +TEST(BasicNotWithSize3) +{ + // Variant building, NOT + run_test_bool_with_size (_this, "hlp3.oas", TMNot, 1500, 103); +} + +TEST(BasicAndWithSize4) +{ + // Sibling interactions, variant building, AND + run_test_bool_with_size (_this, "hlp4.oas", TMAnd, 1500, 102); +} + +TEST(BasicNotWithSize4) +{ + // Sibling interactions, variant building, NOT + run_test_bool_with_size (_this, "hlp4.oas", TMNot, 1500, 103); +} + +TEST(BasicAndWithSize5) +{ + // Variant building with intermediate hierarchy, AND + run_test_bool_with_size (_this, "hlp5.oas", TMAnd, 1500, 102); +} + +TEST(BasicNotWithSize5) +{ + // Variant building with intermediate hierarchy, NOT + run_test_bool_with_size (_this, "hlp5.oas", TMNot, 1500, 103); +} + +TEST(BasicAndWithSize6) +{ + // Extreme variants (copy, vanishing), AND + run_test_bool_with_size (_this, "hlp6.oas", TMAnd, 1500, 102); +} + +TEST(BasicNotWithSize6) +{ + // Extreme variants (copy, vanishing), NOT + run_test_bool_with_size (_this, "hlp6.oas", TMNot, 1500, 103); +} + +TEST(BasicAndWithSize7) +{ + // Context replication - direct and indirect, AND + run_test_bool_with_size (_this, "hlp7.oas", TMAnd, 1500, 102); +} + +TEST(BasicNotWithSize7) +{ + // Context replication - direct and indirect, NOT + run_test_bool_with_size (_this, "hlp7.oas", TMNot, 1500, 103); +} + +TEST(BasicAndWithSize8) +{ + // Mixed sibling-parent contexts, AND + run_test_bool_with_size (_this, "hlp8.oas", TMAnd, 1500, 102); +} + +TEST(BasicNotWithSize8) +{ + // Mixed sibling-parent contexts, NOT + run_test_bool_with_size (_this, "hlp8.oas", TMNot, 1500, 103); +} + +TEST(BasicAndWithSize9) +{ + // Top-level ring structure, AND + std::string doc; + run_test_bool_with_size (_this, "hlp9.oas", TMAnd, 1500, 102, &doc); + EXPECT_EQ (doc, + // This means: the interaction test is strong enough, so it does not see interactions between the + // ring and the cells embedded inside the ring. So there is only one cell context. Some shapes + // from atop the CHILD cell don't interact with shapes inside CHILD, so there are 4 shapes rather than + // 6. And the shapes from top inside the ring are not seen by the RING's subject shapes. + "TOP[1] 0 insts, 0 shapes (1 times)\n" + "RING[1] 0 insts, 0 shapes (1 times)\n" + "CHILD1[1] 0 insts, 6 shapes (2 times)\n" + ); +} + +TEST(BasicNotWithSize9) +{ + // Top-level ring structure, NOT + std::string doc; + run_test_bool_with_size (_this, "hlp9.oas", TMNot, 1500, 103, &doc); + EXPECT_EQ (doc, + // This means: the interaction test is strong enough, so it does not see interactions between the + // ring and the cells embedded inside the ring. So there is only one cell context. Some shapes + // from atop the CHILD cell don't interact with shapes inside CHILD, so there are 4 shapes rather than + // 6. And the shapes from top inside the ring are not seen by the RING's subject shapes. + "TOP[1] 0 insts, 0 shapes (1 times)\n" + "RING[1] 0 insts, 0 shapes (1 times)\n" + "CHILD1[1] 0 insts, 6 shapes (2 times)\n" + ); +} + +TEST(BasicAndWithSize10) +{ + // Array instances, AND + run_test_bool_with_size (_this, "hlp10.oas", TMAnd, 150, 102); +} + +TEST(BasicNotWithSize10) +{ + // Array instances, NOT + run_test_bool_with_size (_this, "hlp10.oas", TMNot, 150, 103); +} +