From 1b9a532f48f153b45dec13d66f6f7bb3788eac3a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 19 Jan 2023 14:44:17 +0100 Subject: [PATCH] WIP: net generation from region layers --- src/db/db/db.pro | 1 + src/db/db/dbDeepRegion.cc | 25 +++++ src/db/db/dbDeepRegion.h | 2 + src/db/db/dbDeepShapeStore.cc | 63 ++++++++++- src/db/db/dbDeepShapeStore.h | 43 ++++++++ src/db/db/dbEmptyRegion.h | 2 + src/db/db/dbFlatRegion.cc | 6 ++ src/db/db/dbFlatRegion.h | 2 + src/db/db/dbLayoutToNetlist.cc | 14 ++- src/db/db/dbLayoutToNetlist.h | 70 +++--------- src/db/db/dbLayoutToNetlistEnums.h | 85 +++++++++++++++ src/db/db/dbOriginalLayerRegion.cc | 6 ++ src/db/db/dbOriginalLayerRegion.h | 2 + src/db/db/dbRegion.h | 14 +++ src/db/db/dbRegionDelegate.h | 6 ++ src/db/unit_tests/dbHierNetsProcessorTests.cc | 101 +++++++----------- 16 files changed, 325 insertions(+), 117 deletions(-) create mode 100644 src/db/db/dbLayoutToNetlistEnums.h diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 74c06e0d8..a65043b30 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -262,6 +262,7 @@ HEADERS = \ dbLayoutLayers.h \ dbLayoutQuery.h \ dbLayoutStateModel.h \ + dbLayoutToNetlistEnums.h \ dbLayoutUtils.h \ dbLibrary.h \ dbLibraryManager.h \ diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index b6fe07871..884250907 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -41,6 +41,7 @@ #include "dbRegionLocalOperations.h" #include "dbLocalOperationUtils.h" #include "dbCompoundOperation.h" +#include "dbLayoutToNetlist.h" #include "tlTimer.h" namespace db @@ -742,6 +743,30 @@ DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsi deep_layer ().insert_into (layout, into_cell, into_layer); } +RegionDelegate * +DeepRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *nets) const +{ + db::NetBuilder &net_builder = deep_layer ().store_non_const ()->net_builder_for (l2n); + + if (&l2n->dss () != deep_layer ().store ()) { + throw tl::Exception (tl::to_string (tr ("Extracted netlist is from different scope as this layer - cannot pull net shapes"))); + } + + DeepLayer result = deep_layer ().derived (); + + 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"))); + } + + std::map lmap; + lmap.insert (std::make_pair (result.layer (), region_for_layer.get ())); + + net_builder.build_nets (nets, lmap, prop_mode, net_prop_name); + + return new db::DeepRegion (result); +} + RegionDelegate * DeepRegion::and_with (const Region &other, PropertyConstraint property_constraint) const { diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 6f24ff3f4..df40fec49 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -139,6 +139,8 @@ 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 *nets) const; + virtual DeepShapeCollectionDelegateBase *deep () { return this; diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index e0d22e9a4..c398e6a55 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -33,6 +33,7 @@ #include "dbDeepEdgePairs.h" #include "dbDeepTexts.h" #include "dbShapeCollection.h" +#include "dbLayoutToNetlist.h" #include "tlTimer.h" @@ -261,10 +262,31 @@ DeepLayer::check_dss () const } } -// ---------------------------------------------------------------------------------- - struct DeepShapeStore::LayoutHolder { + class L2NStatusChangedListener + : public tl::Object + { + public: + L2NStatusChangedListener (DeepShapeStore::LayoutHolder *lh, db::LayoutToNetlist *l2n) + : mp_lh (lh), mp_l2n (l2n) + { + mp_l2n->status_changed_event ().add (this, &L2NStatusChangedListener::l2n_destroyed); + } + + private: + void l2n_destroyed (gsi::ObjectBase::StatusEventType ev) + { + if (ev == gsi::ObjectBase::ObjectDestroyed) { + // CAUTION: this will eventually delete *this! + mp_lh->remove_l2n (mp_l2n); + } + } + + DeepShapeStore::LayoutHolder *mp_lh; + db::LayoutToNetlist *mp_l2n; + }; + LayoutHolder (const db::ICplxTrans &trans) : refs (0), layout (false), builder (&layout, trans) { @@ -287,9 +309,34 @@ struct DeepShapeStore::LayoutHolder } } + bool has_net_builder_for (db::LayoutToNetlist *l2n) const + { + auto l = net_builders.find (l2n); + return (l != net_builders.end ()); + } + + db::NetBuilder &net_builder_for (db::Cell &top, db::LayoutToNetlist *l2n) + { + auto l = net_builders.find (l2n); + if (l == net_builders.end ()) { + // @@@ what happens if layout is the same than used inside l2n (l2n has weak reference to same DSS)?? + l = net_builders.insert (std::make_pair (l2n, std::make_pair (L2NStatusChangedListener (this, l2n), db::NetBuilder (&layout, l2n->cell_mapping_into (layout, top, false), l2n)))).first; + } + return l->second.second; + } + + void remove_l2n (db::LayoutToNetlist *l2n) + { + auto l = net_builders.find (l2n); + if (l != net_builders.end ()) { + net_builders.erase (l); + } + } + int refs; db::Layout layout; db::HierarchyBuilder builder; + std::map > net_builders; std::map layer_refs; }; @@ -653,6 +700,18 @@ DeepShapeStore::add_breakout_cells (unsigned int layout_index, const std::sethas_net_builder_for (l2n); +} + +db::NetBuilder & +DeepShapeStore::net_builder_for (unsigned int layout_index, db::LayoutToNetlist *l2n) +{ + return m_layouts [layout_index]->net_builder_for (initial_cell (layout_index), l2n); +} + void DeepShapeStore::set_threads (int n) { m_state.set_threads (n); diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index 40da1fa65..d4a6ff297 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -47,6 +47,8 @@ class Edges; class EdgePairs; class Texts; class ShapeCollection; +class NetBuilder; +class LayoutToNetlist; /** * @brief Represents a shape collection from the deep shape store @@ -220,6 +222,16 @@ public: return mp_store.get (); } + /** + * @brief Gets the non-const shape store object + * This feature is intended for internal purposes. + */ + DeepShapeStore *store_non_const () const + { + check_dss (); + return const_cast (mp_store.get ()); + } + private: friend class DeepShapeStore; @@ -668,6 +680,37 @@ public: */ bool is_valid_layout_index (unsigned int n) const; + /** + * @brief Gets the net builder object for a given layout index and LayoutToNetlist database + * + * If no net builder is available, one will be created. Use \\has_net_builder to check whether one is + * already created. + */ + db::NetBuilder &net_builder_for (unsigned int layout_index, db::LayoutToNetlist *l2n); + + /** + * @brief Gets the net builder object for a given LayoutToNetlist database (requires the DSS to be singular) + */ + db::NetBuilder &net_builder_for (db::LayoutToNetlist *l2n) + { + require_singular (); + return net_builder_for (0, l2n); + } + + /** + * @brief Gets a value indicating whether a net building is available + */ + bool has_net_builder_for(unsigned int layout_index, db::LayoutToNetlist *l2n); + + /** + * @brief Gets the net builder object for a given LayoutToNetlist database (requires the DSS to be singular) + */ + bool has_net_builder_for (db::LayoutToNetlist *l2n) + { + require_singular (); + return has_net_builder_for (0, l2n); + } + /** * @brief The deep shape store also keeps the number of threads to allocate for the hierarchical processor * diff --git a/src/db/db/dbEmptyRegion.h b/src/db/db/dbEmptyRegion.h index 44ef8470c..c1f04e0f2 100644 --- a/src/db/db/dbEmptyRegion.h +++ b/src/db/db/dbEmptyRegion.h @@ -150,6 +150,8 @@ public: virtual void insert_into (Layout *, db::cell_index_type, unsigned int) const { } + virtual RegionDelegate *nets (LayoutToNetlist *, NetPropertyMode, const tl::Variant &, const std::vector *) const { return new EmptyRegion (); } + private: EmptyRegion &operator= (const EmptyRegion &other); }; diff --git a/src/db/db/dbFlatRegion.cc b/src/db/db/dbFlatRegion.cc index e6b6b7022..f41949d39 100644 --- a/src/db/db/dbFlatRegion.cc +++ b/src/db/db/dbFlatRegion.cc @@ -436,6 +436,12 @@ 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 f11f20a53..a5be95b79 100644 --- a/src/db/db/dbFlatRegion.h +++ b/src/db/db/dbFlatRegion.h @@ -103,6 +103,8 @@ 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 35a352f65..1bae80931 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -433,6 +433,7 @@ void LayoutToNetlist::mem_stat (MemStatistics *stat, MemStatistics::purpose_t pu db::mem_stat (stat, purpose, cat, m_dlrefs, true, (void *) this); db::mem_stat (stat, purpose, cat, m_named_regions, true, (void *) this); db::mem_stat (stat, purpose, cat, m_name_of_layer, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_region_by_original, true, (void *) this); db::mem_stat (stat, purpose, cat, m_joined_net_names, true, (void *) this); db::mem_stat (stat, purpose, cat, m_joined_net_names_per_cell, true, (void *) this); db::mem_stat (stat, purpose, cat, m_joined_nets, true, (void *) this); @@ -537,7 +538,7 @@ db::Region *LayoutToNetlist::layer_by_name (const std::string &name) db::Region *LayoutToNetlist::layer_by_index (unsigned int index) { - std::map::const_iterator n = m_name_of_layer.find (index); + auto n = m_name_of_layer.find (index); if (n == m_name_of_layer.end ()) { return 0; } else { @@ -545,6 +546,16 @@ 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); + if (n == m_region_by_original.end ()) { + return 0; + } else { + return new db::Region (new db::DeepRegion (n->second)); + } +} + static db::DeepLayer dss_create_from_flat (db::DeepShapeStore &dss, const db::ShapeCollection &coll) { const db::Region *region = dynamic_cast (&coll); @@ -601,6 +612,7 @@ 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; } diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index efe656107..66632b9e4 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -27,6 +27,7 @@ #include "dbCellMapping.h" #include "dbNetlistExtractor.h" #include "dbNetlistDeviceExtractor.h" +#include "dbLayoutToNetlistEnums.h" #include "tlGlobPattern.h" namespace db @@ -34,60 +35,6 @@ namespace db class NetlistBuilder; -/** - * @brief An enum describing the way how net information is attached to shapes as properties in "build_nets" - */ -enum NetPropertyMode -{ - /** - * @brief Do no generate properties - */ - NPM_NoProperties, - - /** - * @brief Attach all net properties plus the net name (if a "netname_prop" is specified to "build_nets") - */ - NPM_AllProperties, - - /** - * @brief Attach net name only (if a "netname_prop" is specified to "build_nets") - */ - NPM_NetNameOnly, - - /** - * @brief Like NetNameOnly, but use a unique net ID (db::Net address actually) instead of name - */ - NPM_NetIDOnly, - - /** - * @brief Like NetNameOnly, but use a tuple of name and ID - */ - NPM_NetNameAndIDOnly, -}; - -/** - * @brief An enum describing the way the net hierarchy is mapped - */ -enum BuildNetHierarchyMode -{ - /** - * @brief Flatten the net - * Collects all shapes of a net and puts that into the net cell or circuit cell - */ - BNH_Flatten = 0, - /** - * @brief Build a net hierarchy adding cells for each subcircuit on the net - * Uses the circuit_cell_prefix to build the subcircuit cell names - */ - BNH_SubcircuitCells = 1, - /** - * @brief No hierarchy - * Just output the shapes of the net belonging to the circuit cell. - * Connections are not indicated! - */ - BNH_Disconnected = 2 -}; - /** * @brief A generic framework for extracting netlists from layouts * @@ -353,6 +300,20 @@ public: */ db::Region *layer_by_index (unsigned int index); + /** + * @brief Gets the internal layer from the original layer + */ + db::Region *layer_by_original (const ShapeCollection &original_layer) + { + return layer_by_original (original_layer.get_delegate ()); + } + + /** + * @brief Gets the layer from the original layer's delegate + * Returns 0 if the original layer was not registered as an input_layer. + */ + db::Region *layer_by_original (const ShapeCollectionDelegateBase *original_delegate); + /** * @brief Iterates over the layer indexes and names managed by this object (begin) */ @@ -971,6 +932,7 @@ private: std::set m_dlrefs; std::map m_named_regions; std::map m_name_of_layer; + std::map m_region_by_original; bool m_netlist_extracted; bool m_is_flat; double m_device_scaling; diff --git a/src/db/db/dbLayoutToNetlistEnums.h b/src/db/db/dbLayoutToNetlistEnums.h new file mode 100644 index 000000000..2662c92c2 --- /dev/null +++ b/src/db/db/dbLayoutToNetlistEnums.h @@ -0,0 +1,85 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2023 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _HDR_dbLayoutToNetlistEnums +#define _HDR_dbLayoutToNetlistEnums + +namespace db +{ + +/** + * @brief An enum describing the way how net information is attached to shapes as properties in "build_nets" + */ +enum NetPropertyMode +{ + /** + * @brief Do no generate properties + */ + NPM_NoProperties, + + /** + * @brief Attach all net properties plus the net name (if a "netname_prop" is specified to "build_nets") + */ + NPM_AllProperties, + + /** + * @brief Attach net name only (if a "netname_prop" is specified to "build_nets") + */ + NPM_NetNameOnly, + + /** + * @brief Like NetNameOnly, but use a unique net ID (db::Net address actually) instead of name + */ + NPM_NetIDOnly, + + /** + * @brief Like NetNameOnly, but use a tuple of name and ID + */ + NPM_NetNameAndIDOnly, +}; + +/** + * @brief An enum describing the way the net hierarchy is mapped + */ +enum BuildNetHierarchyMode +{ + /** + * @brief Flatten the net + * Collects all shapes of a net and puts that into the net cell or circuit cell + */ + BNH_Flatten = 0, + /** + * @brief Build a net hierarchy adding cells for each subcircuit on the net + * Uses the circuit_cell_prefix to build the subcircuit cell names + */ + BNH_SubcircuitCells = 1, + /** + * @brief No hierarchy + * Just output the shapes of the net belonging to the circuit cell. + * Connections are not indicated! + */ + BNH_Disconnected = 2 +}; + +} + +#endif diff --git a/src/db/db/dbOriginalLayerRegion.cc b/src/db/db/dbOriginalLayerRegion.cc index 3acfc2012..4f14e95da 100644 --- a/src/db/db/dbOriginalLayerRegion.cc +++ b/src/db/db/dbOriginalLayerRegion.cc @@ -440,6 +440,12 @@ 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 8019cc7c8..7ce905653 100644 --- a/src/db/db/dbOriginalLayerRegion.h +++ b/src/db/db/dbOriginalLayerRegion.h @@ -76,6 +76,8 @@ 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/dbRegion.h b/src/db/db/dbRegion.h index eb23d180c..2ab52d087 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -1830,6 +1830,20 @@ public: return mp_delegate->insert_into (layout, into_cell, into_layer); } + /** + * @brief Pulls the net shapes from a LayoutToNetlist database + * + * This will pull the net shapes from the LayoutToNetlist database, provided that this + * layer was an input to the netlist extraction. + * + * Netlist names will be attached as properties according to prop_mode and net_prop_name. + * A net filter can be provided so that only certain nets are produced. + */ + Region nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *nets = 0) const + { + return Region (mp_delegate->nets (l2n, prop_mode, net_prop_name, nets)); + } + /** * @brief Delivers texts as dots (degenerated edges) * diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index facf84b89..d4ccac4a2 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -35,8 +35,10 @@ #include "dbGenericShapeIterator.h" #include "dbRegionLocalOperations.h" #include "dbHash.h" +#include "dbLayoutToNetlistEnums.h" #include +#include #include namespace db { @@ -46,6 +48,8 @@ class EdgeFilterBase; class EdgesDelegate; class EdgePairsDelegate; class CompoundRegionOperationNode; +class LayoutToNetlist; +class Net; /** * @brief A base class for polygon filters @@ -326,6 +330,8 @@ public: virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const = 0; + virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector *net_filter) const = 0; + const std::string &progress_desc () const { return m_progress_desc; diff --git a/src/db/unit_tests/dbHierNetsProcessorTests.cc b/src/db/unit_tests/dbHierNetsProcessorTests.cc index 0e581e9ea..a3c03507c 100644 --- a/src/db/unit_tests/dbHierNetsProcessorTests.cc +++ b/src/db/unit_tests/dbHierNetsProcessorTests.cc @@ -43,6 +43,7 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la TEST(0_Develop) { db::Layout ly; + db::DeepShapeStore dss; db::LayerMap lmap; unsigned int poly = define_layer (ly, lmap, 7); @@ -72,77 +73,57 @@ TEST(0_Develop) } db::Cell &tc = ly.cell (*ly.begin_top_down ()); - db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set ())); - std::unique_ptr rpoly (l2n.make_polygon_layer (poly, "poly")); - std::unique_ptr rcont (l2n.make_polygon_layer (cont, "cont")); - std::unique_ptr rmetal1 (l2n.make_polygon_layer (metal1, "metal1")); - std::unique_ptr rvia1 (l2n.make_polygon_layer (via1, "via1")); - std::unique_ptr rmetal2 (l2n.make_polygon_layer (metal2, "metal2")); - std::unique_ptr rvia2 (l2n.make_polygon_layer (via1, "via2")); - std::unique_ptr rmetal3 (l2n.make_polygon_layer (metal2, "metal3")); - std::unique_ptr rvia3 (l2n.make_polygon_layer (via1, "via3")); - std::unique_ptr rmetal4 (l2n.make_polygon_layer (metal2, "metal4")); + 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::LayoutToNetlist l2n (&dss); // net extraction // Intra-layer - l2n.connect (*rpoly); - l2n.connect (*rcont); - l2n.connect (*rmetal1); - l2n.connect (*rvia1); - l2n.connect (*rmetal2); - l2n.connect (*rvia2); - l2n.connect (*rmetal3); - l2n.connect (*rvia3); - l2n.connect (*rmetal4); + l2n.connect (rpoly); + l2n.connect (rcont); + l2n.connect (rmetal1); + l2n.connect (rvia1); + l2n.connect (rmetal2); + l2n.connect (rvia2); + l2n.connect (rmetal3); + l2n.connect (rvia3); + l2n.connect (rmetal4); // Inter-layer - l2n.connect (*rpoly, *rcont); - l2n.connect (*rcont, *rmetal1); - l2n.connect (*rmetal1, *rvia1); - l2n.connect (*rvia1, *rmetal2); - l2n.connect (*rmetal2, *rvia2); - l2n.connect (*rvia2, *rmetal3); - l2n.connect (*rmetal3, *rvia3); - l2n.connect (*rvia3, *rmetal4); + l2n.connect (rpoly, rcont); + l2n.connect (rcont, rmetal1); + l2n.connect (rmetal1, rvia1); + l2n.connect (rvia1, rmetal2); + l2n.connect (rmetal2, rvia2); + l2n.connect (rvia2, rmetal3); + l2n.connect (rmetal3, rvia3); + l2n.connect (rvia3, rmetal4); l2n.extract_netlist (); - // .... + // @@@ TODO: beautify + db::Region rmetal1_nets = rmetal1.nets (&l2n, db::NPM_NetNameAndIDOnly, tl::Variant (1)); + db::Region rmetal2_nets = rmetal2.nets (&l2n, db::NPM_NetNameAndIDOnly, tl::Variant (1)); - db::Layout ly2; - ly2.dbu (l2n.internal_layout ()->dbu ()); - db::Cell &top2 = ly2.cell (ly2.add_cell (ly.cell_name (tc.cell_index ()))); + db::Region res1 = rmetal1_nets.bool_and (rmetal2_nets, db::SamePropertiesConstraint); + db::Region res2 = rmetal1_nets.bool_and (rmetal2_nets, db::DifferentPropertiesConstraint); + db::Region res3 = rmetal1_nets.bool_and (rmetal2_nets, db::NoPropertyConstraint); - db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, false /*without device cells*/); + 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))); - std::map lmap_write; - unsigned int wpoly, wcont, wmetal1, wvia1, wmetal2; - lmap_write [wpoly = ly2.insert_layer (db::LayerProperties (7, 0))] = l2n.layer_by_name ("poly"); - lmap_write [wcont = ly2.insert_layer (db::LayerProperties (14, 0))] = l2n.layer_by_name ("cont"); - lmap_write [wmetal1 = ly2.insert_layer (db::LayerProperties (15, 0))] = l2n.layer_by_name ("metal1"); - 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::NPM_NetNameAndIDOnly, tl::Variant (1), db::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/); - - unsigned int out1 = ly2.insert_layer (db::LayerProperties (1000, 0)); - unsigned int out2 = ly2.insert_layer (db::LayerProperties (1001, 0)); - unsigned int out3 = ly2.insert_layer (db::LayerProperties (1002, 0)); - - db::local_processor proc (&ly2, &top2); - { - db::BoolAndOrNotLocalOperationWithProperties n2n (true, &ly2.properties_repository (), &ly2.properties_repository (), &ly2.properties_repository (), db::SamePropertiesConstraint); - proc.run (&n2n, wmetal1, wmetal2, out1); - } - { - db::BoolAndOrNotLocalOperationWithProperties n2n (true, &ly2.properties_repository (), &ly2.properties_repository (), &ly2.properties_repository (), db::DifferentPropertiesConstraint); - proc.run (&n2n, wmetal1, wmetal2, out2); - } - { - db::BoolAndOrNotLocalOperationWithProperties n2n (true, &ly2.properties_repository (), &ly2.properties_repository (), &ly2.properties_repository (), db::NoPropertyConstraint); - proc.run (&n2n, wmetal1, wmetal2, out3); - } + 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))); { db::SaveLayoutOptions options; @@ -151,6 +132,6 @@ TEST(0_Develop) tl::OutputStream stream (fn); db::Writer writer (options); - writer.write (ly2, stream); + writer.write (ly, stream); } }