From 311318c57800dec4c5f3f8c79ae7cbdbfe81f224 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 17 Feb 2019 18:54:33 +0100 Subject: [PATCH] Ported edge/edge DRC functions to hierarchical mode. --- src/db/db/dbAsIfFlatEdges.cc | 45 ---------- src/db/db/dbAsIfFlatEdges.h | 40 +++++++++ src/db/db/dbDeepEdges.cc | 118 +++++++++++++++++++++++++- src/db/unit_tests/dbDeepEdgesTests.cc | 48 +++++++++++ testdata/algo/deep_edges_au9.gds | Bin 0 -> 8846 bytes 5 files changed, 204 insertions(+), 47 deletions(-) create mode 100644 testdata/algo/deep_edges_au9.gds diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index f405b3e24..dbd39d432 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -557,51 +557,6 @@ AsIfFlatEdges::filtered (const EdgeFilterBase &filter) const return new_region.release (); } -namespace -{ - -/** - * @brief A helper class for the DRC functionality which acts as an edge pair receiver - * - * If will perform a edge by edge check using the provided EdgeRelationFilter - */ -template -class edge2edge_check_for_edges - : public db::box_scanner_receiver -{ -public: - edge2edge_check_for_edges (const EdgeRelationFilter &check, Output &output, bool requires_different_layers) - : mp_check (&check), mp_output (&output) - { - m_requires_different_layers = requires_different_layers; - } - - void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2) - { - // Overlap or inside checks require input from different layers - if (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0) { - - // ensure that the first check argument is of layer 1 and the second of - // layer 2 (unless both are of the same layer) - int l1 = int (p1 & size_t (1)); - int l2 = int (p2 & size_t (1)); - - db::EdgePair ep; - if (mp_check->check (l1 <= l2 ? *o1 : *o2, l1 <= l2 ? *o2 : *o1, &ep)) { - mp_output->insert (ep); - } - - } - } - -private: - const EdgeRelationFilter *mp_check; - Output *mp_output; - bool m_requires_different_layers; -}; - -} - EdgePairs AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const { diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index 26dd22326..bac96e687 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -105,6 +105,46 @@ private: std::set m_seen; }; +/** + * @brief A helper class for the DRC functionality which acts as an edge pair receiver + * + * If will perform a edge by edge check using the provided EdgeRelationFilter + */ +template +class edge2edge_check_for_edges + : public db::box_scanner_receiver +{ +public: + edge2edge_check_for_edges (const EdgeRelationFilter &check, Output &output, bool requires_different_layers) + : mp_check (&check), mp_output (&output) + { + m_requires_different_layers = requires_different_layers; + } + + void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2) + { + // Overlap or inside checks require input from different layers + if (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0) { + + // ensure that the first check argument is of layer 1 and the second of + // layer 2 (unless both are of the same layer) + int l1 = int (p1 & size_t (1)); + int l2 = int (p2 & size_t (1)); + + db::EdgePair ep; + if (mp_check->check (l1 <= l2 ? *o1 : *o2, l1 <= l2 ? *o2 : *o1, &ep)) { + mp_output->insert (ep); + } + + } + } + +private: + const EdgeRelationFilter *mp_check; + Output *mp_output; + bool m_requires_different_layers; +}; + /** * @brief A helper class to turn joined edge sequences into polygons * diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 9083947ab..d23dd71fa 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -24,6 +24,7 @@ #include "dbRegion.h" #include "dbDeepEdges.h" #include "dbDeepRegion.h" +#include "dbDeepEdgePairs.h" #include "dbHierNetworkProcessor.h" #include "dbCellGraphUtils.h" #include "dbCellVariants.h" @@ -1174,10 +1175,123 @@ EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const return AsIfFlatEdges::in (other, invert); } +namespace +{ + +class CheckLocalOperation + : public local_operation +{ +public: + CheckLocalOperation (const EdgeRelationFilter &check, bool has_other) + : m_check (check), m_has_other (has_other) + { + // .. nothing yet .. + } + + virtual void compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const + { + edge2edge_check_for_edges > edge_check (m_check, result, m_has_other); + + db::box_scanner scanner; + std::set others; + + if (m_has_other) { + + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j)); + } + } + + size_t n = 0; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::Edge &subject = interactions.subject_shape (i->first); + scanner.insert (& subject, n); + n += 2; + } + + n = 1; + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + scanner.insert (o.operator-> (), n); + n += 2; + } + + } else { + + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + others.insert (interactions.subject_shape (i->first)); + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j)); + } + } + + size_t n = 0; + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + scanner.insert (o.operator-> (), n); + n += 2; + } + + } + + scanner.process (edge_check, m_check.distance (), db::box_convert ()); + } + + virtual db::Coord dist () const + { + // TODO: will the distance be sufficient? Or should we take somewhat more? + return m_check.distance (); + } + + virtual on_empty_intruder_mode on_empty_intruder_hint () const + { + return Drop; + } + + virtual std::string description () const + { + return tl::to_string (tr ("Generic DRC check")); + } + +private: + EdgeRelationFilter m_check; + bool m_has_other; +}; + +} + EdgePairs DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const { - // TODO: implement - return AsIfFlatEdges::run_check (rel, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection); + const db::DeepEdges *other_deep = 0; + if (other) { + other_deep = dynamic_cast (other->delegate ()); + if (! other_deep) { + return db::AsIfFlatEdges::run_check (rel, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection); + } + } + + ensure_merged_edges_valid (); + + EdgeRelationFilter check (rel, d, metrics); + check.set_whole_edges (whole_edges); + check.set_ignore_angle (ignore_angle); + check.set_min_projection (min_projection); + check.set_max_projection (max_projection); + + std::auto_ptr res (new db::DeepEdgePairs (m_merged_edges.derived ())); + + db::CheckLocalOperation op (check, other_deep != 0); + + db::local_processor proc (const_cast (&m_deep_layer.layout ()), + const_cast (&m_deep_layer.initial_cell ()), + other_deep ? &other_deep->deep_layer ().layout () : const_cast (&m_deep_layer.layout ()), + other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&m_deep_layer.initial_cell ())); + + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (m_deep_layer.store ()->threads ()); + + proc.run (&op, m_merged_edges.layer (), other_deep ? other_deep->deep_layer ().layer () : m_merged_edges.layer (), res->deep_layer ().layer ()); + + return db::EdgePairs (res.release ()); } } diff --git a/src/db/unit_tests/dbDeepEdgesTests.cc b/src/db/unit_tests/dbDeepEdgesTests.cc index c7747c4f8..6bd54f06b 100644 --- a/src/db/unit_tests/dbDeepEdgesTests.cc +++ b/src/db/unit_tests/dbDeepEdgesTests.cc @@ -386,3 +386,51 @@ TEST(8_SelectInteracting) db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au8.gds"); } +TEST(9_DRCChecks) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/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 l3 = ly.get_layer (db::LayerProperties (3, 0)); + unsigned int l6 = ly.get_layer (db::LayerProperties (6, 0)); + unsigned int l4 = ly.get_layer (db::LayerProperties (4, 0)); + + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); + db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss); + db::Region r4 (db::RecursiveShapeIterator (ly, top_cell, l4), dss); + + db::Edges e3 = r3.edges (); + db::Edges e4 = r4.edges (); + db::Edges e6 = r6.edges (); + + { + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (4, 0)), r4); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (6, 0)), r6); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e3.space_check (500, false, db::Projection, 90, 0)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e3.space_check (500, true, db::Projection, 90, 300)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e3.separation_check (e4, 200, false, db::Projection, 90, 0)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e6.enclosing_check (e4, 100, true, db::Projection, 90, 0)); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au9.gds"); + } +} + diff --git a/testdata/algo/deep_edges_au9.gds b/testdata/algo/deep_edges_au9.gds new file mode 100644 index 0000000000000000000000000000000000000000..2ca62fbee0dec25876b4137e405385864fbbab95 GIT binary patch literal 8846 zcmchc&ud&&6vt2AOkO6FAEt2-ky2`rLNTCdY!R#)DQMCdC59p){s*OqxKt?Eji4eD zy0Jo6b)y?`A(ExI$jU{QMFMUu1iDg^Jip(2<~VO2bMKrtK?~(u?t5oG_ndpqx%b^l zE?M@joF2<2{*X*g$-FGeh4R0pmF26;uZeUT<1a6Ldg%ve!aONr^n-V z?L6ODUs`)dq}dY5XEJF>KAVZi!d#;$icgB-aGxsDIE&GbO>LYi%~L)5X4(EYD~jV? z{Dl_xpuhLj#*cSX_F!((US#Yd?R#qDvKh0-yXRoDt6JQH9+R(X<8eOi$X6Y^NIU%P zs*P9pdD;J?9q?}z#nBGzJ_7qGQyZuD&A((1_Wkf2N;{G4im8qF>?b6-(ycsSUc2_3 zG}|KWd0X{quJZBwAYlc$ii4lF4+cEVpBTF-f?vR#zKr}rj z=F9_A8>jZgs+6mk!=vFjly->KjH!*M?HS|7BK&|h?`W(|Z5&$8^%B1*{@OwTZKzIg z-4Rt&8_zfT>}{>L7{gFs9aXM%<2zkzD(ob?-qXns@qACjbYe$j9JZ!{e|LYcJYVC5 z+CE&s9Jf%v3;Z3#ecRN=sRQS$_WNKghWZ~6FCDjdO=@pxcWWbm67?*tN8mO7bm)C0 z`eD|?tS~?1Nb`&G+nfC*8~F-FzjCoO zGR@UUtZY!|xc3{EU#bON6vTmz-S&SW7s$LfT2@wzK zT`&3*RyU}Bz1XQ34XS^JawEJgRDU!W!?1%wy}6;W<37t+*2|6Q^O_q|E523MoWR>5 zH(>3`4UHYG7(>4mW5*d%{WIha6HX1>Y1~yQH#DQD-i+cd$hTF!EWEu&ma3Pfu?wde z#L&OWj2*iT)t^z^-I-BTFN^;0ZPj`#b^x-x^`#7U8#3$F*YtU;8S2ZMQCe41E2`e? zRexwjziL>)AI^||Rc3f5wtwjIvg-I%tTKkMSoPOJC%!hLlrk7uKLn*M&uk7^@}|!^b6a^TrBNTwtsnh)JgoRe~v2O-gwtbzlCsq z8uU#RjiKg-^+PXh2`-eMw zk@LLWI@*R+_ZF;smy(El;`=LVr7>jRXzYa^?DUH_14R76TP{i`G-9+*IV^)3yvLt zf5Q5;alcu9)_yzwtaCU1?94&@*@ai*&z|qUk?)(!<^8zb8_&j{t>274+xo5dtb4oP zciUXO9sm0my&b1kZ^wt-`-+^y{XDanTKOtX+%ca$(i?KB-NX-P+5J1!&*B{{-VS%M ze%8#P`bG7#rr%Q*)z4b^Q(06$>*+U@MfJ0;p*r!lQ2nfp&y_{>v##D(7S+#MxvVUz zpSARvvZ#L6D-V=K^|KydRTkCHdhB~;QT?n-FDZ-aXT9)^vZxhS^#4_owVbeG4bRSr zP%CHBgjJ%x5>~7$vZ#JmqHiQv>>FfJ{j5ZNC0ML0vZ#JmA`cTR<{w#9KPypR2^Q;$ qEUKTC=!Xdw`yg3VKP%Cr5-j#6vZ#JmqLvdZ)-YLAW8q}fY|20V!JiiZ literal 0 HcmV?d00001