diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index 20543592e..94fa44317 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -182,6 +182,33 @@ public: shape_reference_translator (db::Layout * /*target_layout*/) { } }; +template +class shape_reference_translator > + : public shape_reference_translator +{ +public: + typedef db::object_with_properties shape_type; + + shape_reference_translator (db::Layout *target_layout) + : shape_reference_translator (target_layout) + { + // .. nothing yet .. + } + + shape_type operator() (const shape_type &s) const + { + // CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging) + return shape_type (shape_reference_translator::operator () (s), s.properties_id ()); + } + + template + shape_type operator() (const shape_type &s, const Trans &tr) const + { + // CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging) + return shape_type (shape_reference_translator::operator () (s, tr), s.properties_id ()); + } +}; + template class shape_reference_translator_with_trans_from_shape_ref { @@ -273,6 +300,26 @@ private: Trans m_trans; }; +template +class shape_reference_translator_with_trans, Trans> + : public shape_reference_translator_with_trans +{ +public: + typedef db::object_with_properties shape_type; + + shape_reference_translator_with_trans (db::Layout *target_layout) + : shape_reference_translator_with_trans (target_layout) + { + // .. nothing yet .. + } + + shape_type operator() (const shape_type &s) const + { + // CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging) + return shape_type (shape_reference_translator_with_trans::operator () (s), s.properties_id ()); + } +}; + // --------------------------------------------------------------------------------------------- /** @@ -398,6 +445,7 @@ template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; @@ -711,6 +759,7 @@ template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; @@ -815,6 +864,7 @@ template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; @@ -1285,6 +1335,7 @@ template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; @@ -1347,6 +1398,7 @@ template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; @@ -2362,6 +2414,7 @@ template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 8fd048aa0..78dbc813d 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -742,28 +742,28 @@ static bool deliver_shape (const db::NetShape &s, db::Shapes &shapes, const Tr & db::PolygonRef pr = s.polygon_ref (); - if (pr.obj ().is_box ()) { + db::Layout *layout = shapes.layout (); + if (layout) { + // NOTE: by maintaining the PolygonRefs we can directly use the output of "build_nets" as input + // for a hierarchical processor. + db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ()); + if (propid) { + shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid)); + } else { + shapes.insert (polygon_ref); + } + } else if (pr.obj ().is_box ()) { if (propid) { shapes.insert (db::BoxWithProperties (pr.obj ().box ().transformed (pr.trans ()).transformed (tr), propid)); } else { shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr)); } } else { - db::Layout *layout = shapes.layout (); - if (layout) { - db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ()); - if (propid) { - shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid)); - } else { - shapes.insert (polygon_ref); - } + db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr)); + if (propid) { + shapes.insert (db::PolygonWithProperties (polygon, propid)); } else { - db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr)); - if (propid) { - shapes.insert (db::PolygonWithProperties (polygon, propid)); - } else { - shapes.insert (polygon); - } + shapes.insert (polygon); } } diff --git a/src/db/db/dbLocalOperation.cc b/src/db/db/dbLocalOperation.cc index e9bdb84f8..d5c2573f8 100644 --- a/src/db/db/dbLocalOperation.cc +++ b/src/db/db/dbLocalOperation.cc @@ -92,6 +92,7 @@ template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; diff --git a/src/db/db/dbShapeFlags.h b/src/db/db/dbShapeFlags.h index b812e5df4..5c2b46e03 100644 --- a/src/db/db/dbShapeFlags.h +++ b/src/db/db/dbShapeFlags.h @@ -33,30 +33,53 @@ namespace db template unsigned int shape_flags (); template unsigned int shape_flags_pure (); -template <> inline unsigned int shape_flags () { return 1 << db::ShapeIterator::PolygonRef; } -template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::PolygonRef; } +template <> inline unsigned int shape_flags () { return 1 << db::ShapeIterator::PolygonRef; } +template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::PolygonRef; } -template <> inline unsigned int shape_flags () { return 1 << db::ShapeIterator::TextRef; } -template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::TextRef; } +template <> inline unsigned int shape_flags () { return 1 << db::ShapeIterator::TextRef; } +template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::TextRef; } -template <> inline unsigned int shape_flags () { return db::ShapeIterator::Boxes; } -template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Box; } +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Boxes; } +template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Box; } -template <> inline unsigned int shape_flags () { return db::ShapeIterator::Paths; } -template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Path; } +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Paths; } +template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Path; } -template <> inline unsigned int shape_flags () { return db::ShapeIterator::Polygons; } -template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Polygon; } +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Polygons; } +template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Polygon; } -template <> inline unsigned int shape_flags () { return db::ShapeIterator::Edges; } -template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Edge; } +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Edges; } +template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Edge; } -template <> inline unsigned int shape_flags () { return db::ShapeIterator::EdgePairs; } -template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::EdgePair; } +template <> inline unsigned int shape_flags () { return db::ShapeIterator::EdgePairs; } +template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::EdgePair; } -template <> inline unsigned int shape_flags () { return db::ShapeIterator::Texts; } -template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Text; } +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Texts; } +template <> inline unsigned int shape_flags_pure () { return 1 << db::ShapeIterator::Text; } +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Properties | shape_flags_pure (); } +template <> inline unsigned int shape_flags_pure () { return db::ShapeIterator::Properties | shape_flags_pure (); } + +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Properties | shape_flags_pure (); } +template <> inline unsigned int shape_flags_pure () { return db::ShapeIterator::Properties | shape_flags_pure (); } + +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Properties | shape_flags_pure (); } +template <> inline unsigned int shape_flags_pure () { return db::ShapeIterator::Properties | shape_flags_pure (); } + +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Properties | shape_flags_pure (); } +template <> inline unsigned int shape_flags_pure () { return db::ShapeIterator::Properties | shape_flags_pure (); } + +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Properties | shape_flags_pure (); } +template <> inline unsigned int shape_flags_pure () { return db::ShapeIterator::Properties | shape_flags_pure (); } + +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Properties | shape_flags_pure (); } +template <> inline unsigned int shape_flags_pure () { return db::ShapeIterator::Properties | shape_flags_pure (); } + +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Properties | shape_flags_pure (); } +template <> inline unsigned int shape_flags_pure () { return db::ShapeIterator::Properties | shape_flags_pure (); } + +template <> inline unsigned int shape_flags () { return db::ShapeIterator::Properties | shape_flags_pure (); } +template <> inline unsigned int shape_flags_pure () { return db::ShapeIterator::Properties | shape_flags_pure (); } template struct DB_PUBLIC shape_to_object diff --git a/src/db/unit_tests/dbHierNetsProcessorTests.cc b/src/db/unit_tests/dbHierNetsProcessorTests.cc index 2ac47f8df..8cec23abb 100644 --- a/src/db/unit_tests/dbHierNetsProcessorTests.cc +++ b/src/db/unit_tests/dbHierNetsProcessorTests.cc @@ -28,7 +28,10 @@ #include "dbReader.h" #include "dbWriter.h" #include "dbCommonReader.h" +#include "dbHierProcessor.h" +// @@@ +#include "dbLocalOperationUtils.h" static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_layer, int gds_datatype = 0) { @@ -37,6 +40,91 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la return lid; } +class BoolBetweenNets + : public db::local_operation +{ +public: + BoolBetweenNets (bool is_and, bool connected) + : m_is_and (is_and), m_connected (connected) + { + // .. nothing yet .. + } + + db::OnEmptyIntruderHint + on_empty_intruder_hint () const + { + return m_is_and ? db::Drop : db::Copy; + } + + std::string + description () const + { + return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation")); + } + + void + do_compute_local (db::Layout *layout, const db::shape_interactions &interactions, std::vector > &results, size_t max_vertex_count, double area_ratio) const + { + tl_assert (results.size () == 1); + std::unordered_set &result = results.front (); + + db::EdgeProcessor ep; + + // NOTE: is guess we do not need to handle subject/subject interactions ... + for (auto i = interactions.begin (); i != interactions.end (); ++i) { + + const db::PolygonRefWithProperties &subject = interactions.subject_shape (i->first); + + bool any_intruder = false; + for (auto j = i->second.begin (); j != i->second.end () && ! any_intruder; ++j) { + const db::PolygonRefWithProperties &other = interactions.intruder_shape (*j).second; + any_intruder = ((other.properties_id () == subject.properties_id ()) == m_connected); + } + + if (! any_intruder) { + + // shortcut (not: keep, and: drop) + if (! m_is_and) { + result.insert (subject); + } + + } else { + + ep.clear (); + + for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) { + ep.insert (*e, 0); + } + + for (auto j = i->second.begin (); j != i->second.end (); ++j) { + + const db::PolygonRefWithProperties &other = interactions.intruder_shape (*j).second; + if ((other.properties_id () == subject.properties_id ()) == m_connected) { + for (db::PolygonRef::polygon_edge_iterator e = other.begin_edge (); ! e.at_end(); ++e) { + ep.insert (*e, 1); + } + } + + } + + db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB); + db::PolygonRefGenerator pr (layout, result); + db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count); + db::PolygonGenerator pg (splitter, true, true); + ep.set_base_verbosity (50); + ep.process (pg, op); + + } + + } + + } + +private: + bool m_is_and; + bool m_connected; +}; + TEST(0_Develop) { @@ -122,17 +210,22 @@ TEST(0_Develop) lmap_write [wvia1 = ly2.insert_layer (db::LayerProperties (16, 0))] = l2n.layer_by_name ("via1"); lmap_write [wmetal2 = ly2.insert_layer (db::LayerProperties (17, 0))] = l2n.layer_by_name ("metal2"); - l2n.build_all_nets (cm, ly2, lmap_write, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/); + l2n.build_all_nets (cm, ly2, lmap_write, "NET_", db::LayoutToNetlist::FakePropId, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/); + unsigned int out = ly2.insert_layer (db::LayerProperties (1000, 0)); + + db::local_processor proc (&ly2, &top2); + BoolBetweenNets n2n (true, true); + proc.run (&n2n, wmetal1, wmetal2, out); + + // @@@ may no work correctly as we have used fake prop ids { db::SaveLayoutOptions options; - std::string fn ("net.gds"); // @@@ + std::string fn ("net_out.gds"); // @@@ tl::OutputStream stream (fn); db::Writer writer (options); writer.write (ly2, stream); } - - } diff --git a/src/plugins/tools/net_tracer/unit_tests/dbTraceAllNets.cc b/src/plugins/tools/net_tracer/unit_tests/dbTraceAllNets.cc index b9566e183..3b1f98af0 100644 --- a/src/plugins/tools/net_tracer/unit_tests/dbTraceAllNets.cc +++ b/src/plugins/tools/net_tracer/unit_tests/dbTraceAllNets.cc @@ -78,7 +78,7 @@ void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracer db::Cell &top_cell = layout_nets.cell (layout_nets.add_cell ("NETS")); db::CellMapping cm = l2ndb.cell_mapping_into (layout_nets, top_cell); - l2ndb.build_all_nets (cm, layout_nets, l2ndb.create_layermap (layout_nets, 1000), "NET_", tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0); + l2ndb.build_all_nets (cm, layout_nets, l2ndb.create_layermap (layout_nets, 1000), "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0); std::string fn (tl::testdata ()); fn += "/net_tracer/";