diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 8c881c847..7777a4a56 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -40,6 +40,7 @@ #include "dbRegionLocalOperations.h" #include "dbHierProcessor.h" #include "dbCompoundOperation.h" +#include "dbLayoutToNetlist.h" #include @@ -1730,6 +1731,60 @@ AsIfFlatRegion::add (const Region &other) const } } +static void +deliver_shapes_of_nets_recursive (db::Shapes &out, db::PropertiesRepository *pr, const db::Circuit *circuit, const LayoutToNetlist *l2n, const db::Region *of_layer, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const db::ICplxTrans &tr, const std::set *net_filter) +{ + db::CplxTrans dbu_trans (l2n->internal_layout ()->dbu ()); + auto dbu_trans_inv = dbu_trans.inverted (); + + for (auto n = circuit->begin_nets (); n != circuit->end_nets (); ++n) { + + if (! net_filter || net_filter->find (n.operator-> ()) != net_filter->end ()) { + db::properties_id_type prop_id = db::NetBuilder::make_netname_propid (*pr, prop_mode, net_prop_name, *n); + l2n->shapes_of_net (*n, *of_layer, true, out, prop_id, tr); + } + + // dive into subcircuits + for (auto sc = circuit->begin_subcircuits (); sc != circuit->end_subcircuits (); ++sc) { + const db::Circuit *circuit_ref = sc->circuit_ref (); + db::ICplxTrans tr_ref = tr * (dbu_trans_inv * sc->trans () * dbu_trans); + deliver_shapes_of_nets_recursive (out, pr, circuit_ref, l2n, of_layer, prop_mode, net_prop_name, tr_ref, net_filter); + } + + } +} + +RegionDelegate * +AsIfFlatRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *net_filter) const +{ + if (! l2n->is_netlist_extracted ()) { + throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); + } + + std::unique_ptr result (new db::FlatRegion ()); + std::unique_ptr region_for_layer (l2n->layer_by_original (this)); + + if (! region_for_layer) { + throw tl::Exception (tl::to_string (tr ("The given layer is not an original layer used in netlist extraction"))); + } + + if (l2n->netlist ()->top_circuit_count () == 0) { + throw tl::Exception (tl::to_string (tr ("No top circuit found in netlist"))); + } else if (l2n->netlist ()->top_circuit_count () > 1) { + throw tl::Exception (tl::to_string (tr ("More than one top circuit found in netlist"))); + } + const db::Circuit *top_circuit = l2n->netlist ()->begin_top_down ().operator-> (); + + std::set net_filter_set; + if (net_filter) { + net_filter_set.insert (net_filter->begin (), net_filter->end ()); + } + + deliver_shapes_of_nets_recursive (result->raw_polygons (), result->properties_repository (), top_circuit, l2n, region_for_layer.get (), prop_mode, net_prop_name, db::ICplxTrans (), net_filter ? &net_filter_set : 0); + + return result.release (); +} + void AsIfFlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const { diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index be8cb8184..8f2fa642f 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -278,6 +278,8 @@ public: virtual bool equals (const Region &other) const; virtual bool less (const Region &other) const; + virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *net_filter) const; + virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; protected: diff --git a/src/db/db/dbFlatRegion.cc b/src/db/db/dbFlatRegion.cc index f41949d39..e6b6b7022 100644 --- a/src/db/db/dbFlatRegion.cc +++ b/src/db/db/dbFlatRegion.cc @@ -436,12 +436,6 @@ const db::PropertiesRepository *FlatRegion::properties_repository () const return mp_properties_repository.get_const (); } -RegionDelegate *FlatRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *net_filter) const -{ - // @@@ TODO: implement (how?) - return 0; -} - void FlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const { db::PropertyMapper pm (&layout->properties_repository (), mp_properties_repository.get_const ()); diff --git a/src/db/db/dbFlatRegion.h b/src/db/db/dbFlatRegion.h index a5be95b79..f11f20a53 100644 --- a/src/db/db/dbFlatRegion.h +++ b/src/db/db/dbFlatRegion.h @@ -103,8 +103,6 @@ public: virtual db::PropertiesRepository *properties_repository (); virtual const db::PropertiesRepository *properties_repository () const; - virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *net_filter) const; - void do_insert (const db::Polygon &polygon, db::properties_id_type prop_id); void do_transform (const db::Trans &t) diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 3969e31c8..3aa885b51 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -267,7 +267,7 @@ void LayoutToNetlist::connect (const db::Region &l) reset_extracted (); if (! is_persisted (l)) { - register_layer (l, make_new_name ()); + register_layer (l); } // we need to keep a reference, so we can safely delete the region @@ -282,10 +282,10 @@ void LayoutToNetlist::connect_impl (const db::ShapeCollection &a, const db::Shap reset_extracted (); if (! is_persisted (a)) { - register_layer (a, make_new_name ()); + register_layer (a); } if (! is_persisted (b)) { - register_layer (b, make_new_name ()); + register_layer (b); } // we need to keep a reference, so we can safely delete the region @@ -302,7 +302,7 @@ size_t LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const reset_extracted (); if (! is_persisted (l)) { - register_layer (l, make_new_name ()); + register_layer (l); } // we need to keep a reference, so we can safely delete the region @@ -548,9 +548,17 @@ db::Region *LayoutToNetlist::layer_by_index (unsigned int index) db::Region *LayoutToNetlist::layer_by_original (const ShapeCollectionDelegateBase *original_delegate) { - auto n = m_region_by_original.find (original_delegate); + auto n = m_region_by_original.find (tl::id_of (original_delegate)); if (n == m_region_by_original.end ()) { - return 0; + + DeepShapeCollectionDelegateBase *dl = const_cast (original_delegate)->deep (); + if (dl && dl->deep_layer ().store () == mp_dss.get ()) { + // implicitly original because the collection is inside our DSS + return new db::Region (new db::DeepRegion (dl->deep_layer ())); + } else { + return 0; + } + } else { return new db::Region (new db::DeepRegion (n->second)); } @@ -581,7 +589,11 @@ std::string LayoutToNetlist::name (const ShapeCollection &coll) const void LayoutToNetlist::register_layer (const ShapeCollection &collection, const std::string &n) { - if (m_named_regions.find (n) != m_named_regions.end ()) { + if (m_region_by_original.find (tl::id_of (collection.get_delegate ())) != m_region_by_original.end ()) { + throw tl::Exception (tl::to_string (tr ("The layer is already registered"))); + } + + if (! n.empty () && m_named_regions.find (n) != m_named_regions.end ()) { throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n); } @@ -611,9 +623,12 @@ void LayoutToNetlist::register_layer (const ShapeCollection &collection, const s } - m_named_regions [n] = dl; - m_region_by_original [collection.get_delegate ()] = dl; - m_name_of_layer [dl.layer ()] = n; + m_region_by_original [tl::id_of (collection.get_delegate ())] = dl; + + if (! n.empty ()) { + m_named_regions [n] = dl; + m_name_of_layer [dl.layer ()] = n; + } } db::DeepLayer LayoutToNetlist::deep_layer_of (const db::ShapeCollection &coll) const @@ -633,6 +648,17 @@ db::DeepLayer LayoutToNetlist::deep_layer_of (const db::ShapeCollection &coll) c } } +bool LayoutToNetlist::is_persisted_impl (const db::ShapeCollection &coll) const +{ + if (coll.get_delegate ()->deep () && coll.get_delegate ()->deep ()->deep_layer ().store () == mp_dss.get ()) { + // implicitly persisted because the collection is inside our DSS + return true; + } else { + // explicitly persisted through "register" + return m_region_by_original.find (tl::id_of (coll.get_delegate ())) != m_region_by_original.end (); + } +} + db::CellMapping LayoutToNetlist::make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector *nets, bool with_device_cells) { std::set device_cells; @@ -865,7 +891,7 @@ static bool deliver_shapes_of_net (bool recursive, const db::Netlist *nl, const return true; } -void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid) const +void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid, const ICplxTrans &trans) const { unsigned int lid = layer_of (of_layer); const db::Circuit *circuit = net.circuit (); @@ -874,10 +900,10 @@ void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_la std::map lmap; lmap [lid] = &to; - deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), propid); + deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, trans, propid); } -db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const +db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, const db::ICplxTrans &trans) const { unsigned int lid = layer_of (of_layer); const db::Circuit *circuit = net.circuit (); @@ -887,7 +913,7 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region std::map lmap; lmap [lid] = res.get (); - deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), 0); + deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, trans, 0); return res.release (); } diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index 1c7359cba..78d988c58 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -237,14 +237,22 @@ public: double device_scaling () const; /** - * @brief Register a layer under the given name - * This is a formal name for the layer. Using a name or layer properties - * (see below) enhances readability of backannotated information + * @brief Register a layer, optionally under the given name + * Using a name or layer properties (see below) enhances readability of backannotated information * if layers are involved. Use this method to attach a name to a region * derived by boolean operations for example. - * Named regions are persisted inside the LayoutToNetlist object. + * + * Registered regions are persisted inside the LayoutToNetlist object + * if they are flat or original layer regions. + * This allows passing flat or original layer collections. + * + * If no name is given, the region will not be registered under a name. + * Still the collection will be persisted if required. + * + * In addition to regions, text collections can be registered too. + * Including texts in "connect" makes net names begin assigned from the text strings. */ - void register_layer (const ShapeCollection &collection, const std::string &name); + void register_layer (const ShapeCollection &collection, const std::string &name = std::string ()); /** * @brief Gets the name of the given collection @@ -279,7 +287,7 @@ public: template bool is_persisted (const Collection &coll) const { - return m_name_of_layer.find (layer_of (coll)) != m_name_of_layer.end (); + return is_persisted_impl (coll); } /** @@ -705,7 +713,7 @@ public: * This methods returns a new'd Region. It's the responsibility of the caller * to delete this object. */ - db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const; + db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, const db::ICplxTrans &trans = db::ICplxTrans ()) const; /** * @brief Delivers all shapes of a specific net and layer to the given Shapes container. @@ -718,7 +726,7 @@ public: * * propid is an optional properties ID which is attached to the shapes if not 0. */ - void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0) const; + void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0, const db::ICplxTrans &trans = db::ICplxTrans ()) const; /** * @brief Builds a net representation in the given layout and cell @@ -932,7 +940,7 @@ private: std::set m_dlrefs; std::map m_named_regions; std::map m_name_of_layer; - std::map m_region_by_original; + std::map m_region_by_original; bool m_netlist_extracted; bool m_is_flat; double m_device_scaling; @@ -953,6 +961,7 @@ private: db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector *nets, bool with_device_cells); void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b); size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn); + bool is_persisted_impl (const db::ShapeCollection &coll) const; // implementation of NetlistManipulationCallbacks virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans); diff --git a/src/db/db/dbOriginalLayerRegion.cc b/src/db/db/dbOriginalLayerRegion.cc index 4f14e95da..3acfc2012 100644 --- a/src/db/db/dbOriginalLayerRegion.cc +++ b/src/db/db/dbOriginalLayerRegion.cc @@ -440,12 +440,6 @@ OriginalLayerRegion::insert_into (Layout *layout, db::cell_index_type into_cell, } } -RegionDelegate *OriginalLayerRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *net_filter) const -{ - // @@@ TODO: implement (how?) - return 0; -} - void OriginalLayerRegion::ensure_merged_polygons_valid () const { diff --git a/src/db/db/dbOriginalLayerRegion.h b/src/db/db/dbOriginalLayerRegion.h index 7ce905653..8019cc7c8 100644 --- a/src/db/db/dbOriginalLayerRegion.h +++ b/src/db/db/dbOriginalLayerRegion.h @@ -76,8 +76,6 @@ public: virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; - virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *net_filter) const; - protected: virtual void merged_semantics_changed (); virtual void min_coherence_changed (); diff --git a/src/db/db/dbShapeFlags.h b/src/db/db/dbShapeFlags.h index 1032845da..700a104e5 100644 --- a/src/db/db/dbShapeFlags.h +++ b/src/db/db/dbShapeFlags.h @@ -75,7 +75,7 @@ template <> struct shape_flags_traits : public shape_flags_traits { - static unsigned int generic () { return db::ShapeIterator::Polygons; } + static unsigned int generic () { return db::ShapeIterator::Regions; } static unsigned int pure () { return 1 << db::ShapeIterator::Polygon; } }; @@ -83,7 +83,7 @@ template <> struct shape_flags_traits : public shape_flags_traits { - static unsigned int generic () { return db::ShapeIterator::Polygons; } + static unsigned int generic () { return db::ShapeIterator::Regions; } static unsigned int pure () { return 1 << db::ShapeIterator::SimplePolygon; } }; diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index 4fe246750..bf80bc24e 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -315,10 +315,12 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", gsi::method ("layer_name", (std::string (db::LayoutToNetlist::*) (unsigned int) const) &db::LayoutToNetlist::name, gsi::arg ("l"), "@brief Gets the name of the given layer (by index)\n" ) + - gsi::method ("register", (void (db::LayoutToNetlist::*) (const db::ShapeCollection &collection, const std::string &)) &db::LayoutToNetlist::register_layer, gsi::arg ("l"), gsi::arg ("n"), + gsi::method ("register", (void (db::LayoutToNetlist::*) (const db::ShapeCollection &collection, const std::string &)) &db::LayoutToNetlist::register_layer, gsi::arg ("l"), gsi::arg ("n", std::string ()), "@brief Names the given layer\n" - "'l' must be a hierarchical \\Region or \\Texts object derived with \\make_layer, \\make_text_layer or \\make_polygon_layer or " - "a region derived from those by boolean operations or other hierarchical operations.\n" + "'l' must be a \\Region or \\Texts object.\n" + "Flat regions or text collections must be registered with this function, before they can be used in \\connect. " + "Registering will copy the shapes into the LayoutToNetlist object in this step to enable " + "netlist extraction.\n" "\n" "Naming a layer allows the system to indicate the layer in various contexts, i.e. " "when writing the data to a file. Named layers are also persisted inside the LayoutToNetlist object. " @@ -574,16 +576,20 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", gsi::method ("netlist", &db::LayoutToNetlist::netlist, "@brief gets the netlist extracted (0 if no extraction happened yet)\n" ) + - gsi::factory ("shapes_of_net", (db::Region *(db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), + gsi::factory ("shapes_of_net", (db::Region *(db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, const db::ICplxTrans &) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive", true), gsi::arg ("trans", db::ICplxTrans (), "unity"), "@brief Returns all shapes of a specific net and layer.\n" "If 'recursive'' is true, the returned region will contain the shapes of\n" "all subcircuits too.\n" + "\n" + "The optional 'trans' parameter allows applying a transformation to all shapes. It has been introduced in version 0.28.4." ) + - gsi::method ("shapes_of_net", (void (db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, db::Shapes &, db::properties_id_type) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), gsi::arg ("to"), gsi::arg ("propid", db::properties_id_type (0), "0"), + gsi::method ("shapes_of_net", (void (db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, db::Shapes &, db::properties_id_type, const db::ICplxTrans &) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), gsi::arg ("to"), gsi::arg ("propid", db::properties_id_type (0), "0"), gsi::arg ("trans", db::ICplxTrans (), "unity"), "@brief Sends all shapes of a specific net and layer to the given Shapes container.\n" "If 'recursive'' is true, the returned region will contain the shapes of\n" "all subcircuits too.\n" "\"prop_id\" is an optional properties ID. If given, this property set will be attached to the shapes." + "\n" + "The optional 'trans' parameter allows applying a transformation to all shapes. It has been introduced in version 0.28.4." ) + gsi::method_ext ("build_net", &build_net, gsi::arg ("net"), gsi::arg ("target"), gsi::arg ("target_cell"), gsi::arg ("lmap"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"), "@brief Builds a net representation in the given layout and cell\n" diff --git a/src/db/unit_tests/dbHierNetsProcessorTests.cc b/src/db/unit_tests/dbHierNetsProcessorTests.cc index 4c10e348f..381bdf0c1 100644 --- a/src/db/unit_tests/dbHierNetsProcessorTests.cc +++ b/src/db/unit_tests/dbHierNetsProcessorTests.cc @@ -23,15 +23,12 @@ #include "tlUnitTest.h" #include "tlStream.h" +#include "tlFileUtils.h" #include "dbLayoutToNetlist.h" #include "dbTestSupport.h" #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) { @@ -40,33 +37,37 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la return lid; } -TEST(0_Develop) +db::Region make_region (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, bool flat) +{ + return flat ? db::Region (si) : db::Region (si, dss); +} + +void run_test (tl::TestBase *_this, bool flat, bool flat_nets, const std::string &au_fn) { db::Layout ly; db::DeepShapeStore dss; - // @@@ dss.set_subcircuit_hierarchy_for_nets (true); + if (! flat_nets) { + dss.set_subcircuit_hierarchy_for_nets (true); + } + db::LayerMap lmap; - unsigned int poly = define_layer (ly, lmap, 7); - unsigned int cont = define_layer (ly, lmap, 14); - unsigned int metal1 = define_layer (ly, lmap, 15); - unsigned int via1 = define_layer (ly, lmap, 16); - unsigned int metal2 = define_layer (ly, lmap, 17); - unsigned int via2 = define_layer (ly, lmap, 18); - unsigned int metal3 = define_layer (ly, lmap, 19); - unsigned int via3 = define_layer (ly, lmap, 20); - unsigned int metal4 = define_layer (ly, lmap, 21); + unsigned int poly = define_layer (ly, lmap, 1); + unsigned int cont = define_layer (ly, lmap, 2); + unsigned int metal1 = define_layer (ly, lmap, 3); + unsigned int via1 = define_layer (ly, lmap, 4); + unsigned int metal2 = define_layer (ly, lmap, 5); + unsigned int via2 = define_layer (ly, lmap, 6); + unsigned int metal3 = define_layer (ly, lmap, 7); + unsigned int via3 = define_layer (ly, lmap, 8); + unsigned int metal4 = define_layer (ly, lmap, 9); { db::LoadLayoutOptions options; options.get_options ().layer_map = lmap; options.get_options ().create_other_layers = false; - // @@@ std::string fn (tl::testdata ()); - // @@@ fn = tl::combine_path (fn, "algo"); - // @@@ fn = tl::combine_path (fn, "device_extract_l1.gds"); - - std::string fn ("/home/matthias/klayout/testdata/laurent_ANA_DRIVE7/ANA_DRIVE7.gds"); // @@@ + std::string fn = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "nets_proc_1.gds"); tl::InputStream stream (fn); db::Reader reader (stream); @@ -75,21 +76,39 @@ TEST(0_Develop) db::Cell &tc = ly.cell (*ly.begin_top_down ()); - db::Region rpoly (db::RecursiveShapeIterator (ly, tc, poly), dss); - db::Region rcont (db::RecursiveShapeIterator (ly, tc, cont), dss); - db::Region rmetal1 (db::RecursiveShapeIterator (ly, tc, metal1), dss); - db::Region rvia1 (db::RecursiveShapeIterator (ly, tc, via1), dss); - db::Region rmetal2 (db::RecursiveShapeIterator (ly, tc, metal2), dss); - db::Region rvia2 (db::RecursiveShapeIterator (ly, tc, via2), dss); - db::Region rmetal3 (db::RecursiveShapeIterator (ly, tc, metal3), dss); - db::Region rvia3 (db::RecursiveShapeIterator (ly, tc, via3), dss); - db::Region rmetal4 (db::RecursiveShapeIterator (ly, tc, metal4), dss); + db::Region rpoly = make_region (db::RecursiveShapeIterator (ly, tc, poly), dss, flat); + db::Region rcont = make_region (db::RecursiveShapeIterator (ly, tc, cont), dss, flat); + db::Region rmetal1 = make_region (db::RecursiveShapeIterator (ly, tc, metal1), dss, flat); + db::Region rvia1 = make_region (db::RecursiveShapeIterator (ly, tc, via1), dss, flat); + db::Region rmetal2 = make_region (db::RecursiveShapeIterator (ly, tc, metal2), dss, flat); + db::Region rvia2 = make_region (db::RecursiveShapeIterator (ly, tc, via2), dss, flat); + db::Region rmetal3 = make_region (db::RecursiveShapeIterator (ly, tc, metal3), dss, flat); + db::Region rvia3 = make_region (db::RecursiveShapeIterator (ly, tc, via3), dss, flat); + db::Region rmetal4 = make_region (db::RecursiveShapeIterator (ly, tc, metal4), dss, flat); - std::unique_ptr l2n (new db::LayoutToNetlist (&dss)); - EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false); + std::unique_ptr l2n; + if (! flat) { + l2n.reset (new db::LayoutToNetlist (&dss)); + EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false); + } else { + l2n.reset (new db::LayoutToNetlist (ly.cell_name (tc.cell_index ()), ly.dbu ())); + } // net extraction + if (flat) { + // flat or original layers need to be registered + l2n->register_layer (rpoly); + l2n->register_layer (rcont); + l2n->register_layer (rmetal1); + l2n->register_layer (rvia1); + l2n->register_layer (rmetal2); + l2n->register_layer (rvia2); + l2n->register_layer (rmetal3); + l2n->register_layer (rvia3); + l2n->register_layer (rmetal4); + } + // Intra-layer l2n->connect (rpoly); l2n->connect (rcont); @@ -110,41 +129,17 @@ TEST(0_Develop) l2n->connect (rmetal3, rvia3); l2n->connect (rvia3, rmetal4); -printf("@@@ extraction\n"); fflush(stdout); l2n->extract_netlist (); -printf("@@@ cells1=%d\n", int(dss.layout ().cells())); fflush(stdout); db::Region rmetal1_nets = rmetal1.nets (*l2n, db::NPM_NetNameAndIDOnly, tl::Variant (1)); - EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), true); -printf("@@@ cells2=%d\n", int(dss.layout ().cells())); fflush(stdout); + if (! flat) { + EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), true); + } db::Region rmetal2_nets = rmetal2.nets (*l2n, db::NPM_NetNameAndIDOnly, tl::Variant (1)); -printf("@@@ cells3=%d\n", int(dss.layout ().cells())); fflush(stdout); - db::Region rmetal1_nets_more = rmetal1.nets (*l2n, db::NPM_NetNameAndIDOnly, tl::Variant (1)); -printf("@@@ cells4=%d\n", int(dss.layout ().cells())); fflush(stdout); - -// @@@ -dss.layout().set_properties(rpoly.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(7, 0)); -dss.layout().set_properties(rcont.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(14, 0)); -dss.layout().set_properties(rmetal1.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(15, 0)); -dss.layout().set_properties(rvia1.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(16, 0)); -dss.layout().set_properties(rmetal2.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(17, 0)); -dss.layout().set_properties(rmetal1_nets.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(115, 0)); -dss.layout().set_properties(rmetal2_nets.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(117, 0)); -{ - db::SaveLayoutOptions options; - std::string fn ("net_outx.gds"); // @@@ - tl::OutputStream stream (fn); - db::Writer writer (options); - writer.write (dss.layout(), stream); -} -// @@@ db::Region res1 = rmetal1_nets.bool_and (rmetal2_nets, db::SamePropertiesConstraint); -printf("@@@2\n"); fflush(stdout); db::Region res2 = rmetal1_nets.bool_and (rmetal2_nets, db::DifferentPropertiesConstraint); -printf("@@@3\n"); fflush(stdout); db::Region res3 = rmetal1_nets.bool_and (rmetal2_nets, db::NoPropertyConstraint); -printf("@@@4\n"); fflush(stdout); rmetal1_nets.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (100, 0))); rmetal2_nets.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (101, 0))); @@ -152,19 +147,28 @@ printf("@@@4\n"); fflush(stdout); res1.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1000, 0))); res2.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1001, 0))); res3.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1002, 0))); -printf("@@@5\n"); fflush(stdout); // Test auto-unregistration l2n.reset (0); - EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false); - - { - db::SaveLayoutOptions options; - - std::string fn (dss.subcircuit_hierarchy_for_nets () ? "net_outh.gds" : "net_out.gds"); // @@@ - - tl::OutputStream stream (fn); - db::Writer writer (options); - writer.write (ly, stream); + if (! flat) { + EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false); } + + std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), au_fn); + db::compare_layouts (_this, ly, au_path); +} + +TEST(1_NetSpecificBoolFlat) +{ + run_test (_this, false, true, "net_proc_au1.gds"); +} + +TEST(2_NetSpecificBoolFlatNets) +{ + run_test (_this, false, true, "net_proc_au2.gds"); +} + +TEST(3_NetSpecificBoolFullyHier) +{ + run_test (_this, false, false, "net_proc_au3.gds"); } diff --git a/testdata/algo/net_proc_au1.gds b/testdata/algo/net_proc_au1.gds new file mode 100644 index 000000000..0f2963078 Binary files /dev/null and b/testdata/algo/net_proc_au1.gds differ diff --git a/testdata/algo/net_proc_au2.gds b/testdata/algo/net_proc_au2.gds new file mode 100644 index 000000000..aa1308051 Binary files /dev/null and b/testdata/algo/net_proc_au2.gds differ diff --git a/testdata/algo/net_proc_au3.gds b/testdata/algo/net_proc_au3.gds new file mode 100644 index 000000000..f52c02180 Binary files /dev/null and b/testdata/algo/net_proc_au3.gds differ diff --git a/testdata/algo/nets_proc_1.gds b/testdata/algo/nets_proc_1.gds new file mode 100644 index 000000000..e1b911ddb Binary files /dev/null and b/testdata/algo/nets_proc_1.gds differ