From b4fa4b1bae62b8f16982d4873d28c584ca973506 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 26 Jul 2019 19:07:19 +0200 Subject: [PATCH] Flattening of layout with circuit flattening. Technically, the layout isn't flattened, but connections are made which allow regenerating the layout even after the circuit has been flattened. --- src/db/db/dbCircuit.cc | 12 +- src/db/db/dbHierNetworkProcessor.cc | 37 +-- src/db/db/dbHierNetworkProcessor.h | 24 +- src/db/db/dbLayoutToNetlist.cc | 41 ++- src/db/db/dbLayoutToNetlist.h | 11 +- src/db/db/dbNetlist.cc | 5 +- src/db/db/dbNetlist.h | 22 +- src/db/unit_tests/dbLayoutToNetlistTests.cc | 255 ++++++++++++++++++ .../device_extract_au5_flattened_circuits.gds | Bin 0 -> 114198 bytes testdata/lvs/ringo_simple_blackboxing.lvsdb | 20 +- .../lvs/ringo_simple_simplification.lvsdb.1 | 28 +- ...o_simple_simplification_with_align.lvsdb.1 | 28 +- 12 files changed, 433 insertions(+), 50 deletions(-) create mode 100644 testdata/algo/device_extract_au5_flattened_circuits.gds diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index dd3c6dc03..f608a9f77 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -88,9 +88,7 @@ Circuit::~Circuit () // the default destructor will make the nets access "this" to unregister the // objects - hence we have to do this explicitly. - m_nets.clear (); - m_subcircuits.clear (); - m_devices.clear (); + clear (); } Circuit &Circuit::operator= (const Circuit &other) @@ -376,14 +374,22 @@ void Circuit::flatten_subcircuit (SubCircuit *subcircuit) db::Net *outside_net = 0; if (n->pin_count () > 0) { + size_t pin_id = n->begin_pins ()->pin_id (); outside_net = subcircuit->net_for_pin (pin_id); + } else { + outside_net = new db::Net (); if (! n->name ().empty ()) { outside_net->set_name (subcircuit->expanded_name () + "." + n->name ()); } add_net (outside_net); + + if (netlist ()->callbacks ()) { + outside_net->set_cluster_id (netlist ()->callbacks ()->link_net_to_parent_circuit (n.operator-> (), this, subcircuit->trans ())); + } + } net2net.insert (std::make_pair (n.operator-> (), outside_net)); diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 2005b010c..f2e88a520 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -41,6 +41,25 @@ namespace db { +// ------------------------------------------------------------------------------ + +template void insert_transformed (db::Layout &layout, Container &shapes, const Shape &s, const Trans &t); + +template void insert_transformed (db::Layout &layout, Container &shapes, const db::PolygonRef &s, const Trans &t) +{ + db::Polygon poly = s.obj (); + poly.transform (s.trans ()); + if (! t.is_unity ()) { + poly.transform (t); + } + shapes.insert (db::PolygonRef (poly, layout.shape_repository ())); +} + +template void insert_transformed (db::Layout & /*layout*/, Container &shapes, const db::Edge &s, const Trans &t) +{ + shapes.insert (s.transformed (t)); +} + // ------------------------------------------------------------------------------ // Connectivity implementation @@ -993,7 +1012,6 @@ connected_clusters::join_cluster_with (typename local_cluster::id_type id, return; } - // join the shape clusters local_clusters::join_cluster_with (id, with_id); // handle the connections by translating @@ -2115,23 +2133,6 @@ hier_clusters::clusters_per_cell (db::cell_index_type cell_index) return c->second; } -template void insert_transformed (db::Layout &layout, db::Shapes &shapes, const Shape &s, const Trans &t); - -template void insert_transformed (db::Layout &layout, db::Shapes &shapes, const db::PolygonRef &s, const Trans &t) -{ - db::Polygon poly = s.obj (); - poly.transform (s.trans ()); - if (! t.is_unity ()) { - poly.transform (t); - } - shapes.insert (db::PolygonRef (poly, layout.shape_repository ())); -} - -template void insert_transformed (db::Layout & /*layout*/, db::Shapes &shapes, const db::Edge &s, const Trans &t) -{ - shapes.insert (s.transformed (t)); -} - template void hier_clusters::return_to_hierarchy (db::Layout &layout, const std::map &lm) const diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index 112648e9c..03d2df07c 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -522,6 +522,14 @@ public: return --m_next_dummy_id; } + /** + * @brief Gets a value indicating whether the given ID is a dummy ID + */ + bool is_dummy (typename local_cluster::id_type id) const + { + return id > m_clusters.size (); + } + private: void ensure_sorted (); @@ -600,12 +608,20 @@ public: return m_inst_prop_id; } + /** + * @brief Transform with the given transformation + */ + void transform (const db::ICplxTrans &tr) + { + m_inst_trans = tr * m_inst_trans; + } + /** * @brief Equality */ bool operator== (const ClusterInstElement &other) const { - return m_inst_cell_index == other.m_inst_cell_index && m_inst_trans == other.m_inst_trans && m_inst_prop_id == other.m_inst_prop_id; + return m_inst_cell_index == other.m_inst_cell_index && m_inst_trans.equal (other.m_inst_trans) && m_inst_prop_id == other.m_inst_prop_id; } /** @@ -624,8 +640,8 @@ public: if (m_inst_cell_index != other.m_inst_cell_index) { return m_inst_cell_index < other.m_inst_cell_index; } - if (m_inst_trans != other.m_inst_trans) { - return m_inst_trans < other.m_inst_trans; + if (! m_inst_trans.equal (other.m_inst_trans)) { + return m_inst_trans.less (other.m_inst_trans); } return m_inst_prop_id < other.m_inst_prop_id; } @@ -803,7 +819,7 @@ public: * The "with_id" cluster is removed. All connections of "with_id" are transferred to the * first one. All shapes of "with_id" are transferred to "id". */ - void join_cluster_with (typename local_cluster::id_type id, typename local_cluster::id_type with_id); + void join_cluster_with(typename local_cluster::id_type id, typename local_cluster::id_type with_id); /** * @brief An iterator delivering all clusters (even the connectors) diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index b7184c828..9138a3e4f 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -197,14 +197,36 @@ db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index, const return region.release (); } +size_t LayoutToNetlist::link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &dtrans) +{ + if (! subcircuit_net->circuit () || ! has_internal_layout () || ! internal_layout ()->is_valid_cell_index (parent_circuit->cell_index ())) { + return 0; + } + + db::CplxTrans dbu_trans (internal_layout ()->dbu ()); + db::ICplxTrans trans = dbu_trans.inverted () * dtrans * dbu_trans; + + connected_clusters &parent_net_clusters = m_net_clusters.clusters_per_cell (parent_circuit->cell_index ()); + + size_t id = parent_net_clusters.insert_dummy (); // @@@ + + parent_net_clusters.add_connection (id, db::ClusterInstance (subcircuit_net->cluster_id (), subcircuit_net->circuit ()->cell_index (), trans, 0)); + return id; +} + +void LayoutToNetlist::ensure_netlist () +{ + if (! mp_netlist.get ()) { + mp_netlist.reset (new db::Netlist (this)); + } +} + void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, const std::map &layers) { if (m_netlist_extracted) { throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted"))); } - if (! mp_netlist.get ()) { - mp_netlist.reset (new db::Netlist ()); - } + ensure_netlist (); extractor.extract (dss (), m_layout_index, layers, *mp_netlist, m_net_clusters, m_device_scaling); } @@ -277,9 +299,7 @@ void LayoutToNetlist::extract_netlist (const std::string &joined_net_names) if (m_netlist_extracted) { throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted"))); } - if (! mp_netlist.get ()) { - mp_netlist.reset (new db::Netlist ()); - } + ensure_netlist (); db::NetlistExtractor netex; netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters, joined_net_names); @@ -292,6 +312,11 @@ void LayoutToNetlist::set_netlist_extracted () m_netlist_extracted = true; } +bool LayoutToNetlist::has_internal_layout () const +{ + return mp_dss.get () && mp_dss->is_valid_layout_index (m_layout_index); +} + const db::Layout *LayoutToNetlist::internal_layout () const { ensure_layout (); @@ -540,9 +565,7 @@ db::Netlist *LayoutToNetlist::netlist () const db::Netlist *LayoutToNetlist::make_netlist () { - if (! mp_netlist.get ()) { - mp_netlist.reset (new db::Netlist ()); - } + ensure_netlist (); return mp_netlist.get (); } diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index 79d97e71f..e2287a301 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -70,7 +70,7 @@ namespace db * @li */ class DB_PUBLIC LayoutToNetlist - : public gsi::ObjectBase, public tl::Object + : public gsi::ObjectBase, public db::NetlistManipulationCallbacks { public: typedef std::map::const_iterator layer_iterator; @@ -409,6 +409,11 @@ public: return *mp_dss; } + /** + * @brief Returns true, if there a layout is set + */ + bool has_internal_layout () const; + /** * @brief Gets the internal layout */ @@ -756,6 +761,7 @@ private: typedef std::map cell_reuse_table_type; void init (); + void ensure_netlist (); size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path); void build_net_rec (const db::Net &net, db::Layout &target, cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const; void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const; @@ -765,6 +771,9 @@ private: std::string make_new_name (const std::string &stem = std::string ()); db::properties_id_type make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const; db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector *nets, bool with_device_cells); + + // 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/dbNetlist.cc b/src/db/db/dbNetlist.cc index 9b245fbf1..6b536c817 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -30,8 +30,9 @@ namespace db // -------------------------------------------------------------------------------- // Netlist class implementation -Netlist::Netlist () - : m_valid_topology (false), m_lock_count (0), +Netlist::Netlist (NetlistManipulationCallbacks *callbacks) + : mp_callbacks (callbacks), + m_valid_topology (false), m_lock_count (0), m_circuit_by_name (this, &Netlist::begin_circuits, &Netlist::end_circuits), m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits), m_device_abstract_by_name (this, &Netlist::begin_device_abstracts, &Netlist::end_device_abstracts), diff --git a/src/db/db/dbNetlist.h b/src/db/db/dbNetlist.h index df443c2c0..da26bd399 100644 --- a/src/db/db/dbNetlist.h +++ b/src/db/db/dbNetlist.h @@ -35,6 +35,20 @@ namespace db { +/** + * @brief An interface which connects the netlist with a layout representation + * Specifically this interface allows manipulating the layout in sync with the netlist. + */ +class DB_PUBLIC NetlistManipulationCallbacks + : public tl::Object +{ +public: + NetlistManipulationCallbacks () { } + virtual ~NetlistManipulationCallbacks () { } + + virtual size_t link_net_to_parent_circuit (const db::Net *subcircuit_net, db::Circuit *parent_circuit, const db::DCplxTrans &trans) = 0; +}; + /** * @brief The netlist class * @@ -65,7 +79,7 @@ public: * * This constructor creates an empty hierarchical netlist */ - Netlist (); + Netlist (NetlistManipulationCallbacks *callbacks = 0); /** * @brief Copy constructor @@ -480,6 +494,7 @@ private: friend class Circuit; friend class DeviceAbstract; + tl::weak_ptr mp_callbacks; circuit_list m_circuits; device_class_list m_device_classes; device_abstract_list m_device_abstracts; @@ -494,6 +509,11 @@ private: object_by_attr > m_device_abstract_by_name; object_by_attr > m_device_abstract_by_cell_index; + db::NetlistManipulationCallbacks *callbacks () + { + return mp_callbacks.get (); + } + void invalidate_topology (); void validate_topology (); void circuits_changed (); diff --git a/src/db/unit_tests/dbLayoutToNetlistTests.cc b/src/db/unit_tests/dbLayoutToNetlistTests.cc index 3fed04252..640552385 100644 --- a/src/db/unit_tests/dbLayoutToNetlistTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistTests.cc @@ -2755,3 +2755,258 @@ TEST(11_DuplicateInstances) "end;\n" ); } + +TEST(12_FlattenCircuitDoesFlattenLayout) +{ + db::Layout ly; + db::LayerMap lmap; + + unsigned int nwell = define_layer (ly, lmap, 1); + unsigned int active = define_layer (ly, lmap, 2); + unsigned int pplus = define_layer (ly, lmap, 10); + unsigned int nplus = define_layer (ly, lmap, 11); + unsigned int poly = define_layer (ly, lmap, 3); + unsigned int poly_lbl = define_layer (ly, lmap, 3, 1); + unsigned int diff_cont = define_layer (ly, lmap, 4); + unsigned int poly_cont = define_layer (ly, lmap, 5); + unsigned int metal1 = define_layer (ly, lmap, 6); + unsigned int metal1_lbl = define_layer (ly, lmap, 6, 1); + unsigned int via1 = define_layer (ly, lmap, 7); + unsigned int metal2 = define_layer (ly, lmap, 8); + unsigned int metal2_lbl = define_layer (ly, lmap, 8, 1); + + { + db::LoadLayoutOptions options; + options.get_options ().layer_map = lmap; + options.get_options ().create_other_layers = false; + + std::string fn (tl::testsrc ()); + fn = tl::combine_path (fn, "testdata"); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "device_extract_l5.gds"); + + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly, options); + } + + db::Cell &tc = ly.cell (*ly.begin_top_down ()); + db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set ())); + + std::auto_ptr rbulk (l2n.make_layer ("bulk")); + std::auto_ptr rnwell (l2n.make_layer (nwell, "nwell")); + std::auto_ptr ractive (l2n.make_layer (active, "active")); + std::auto_ptr rpplus (l2n.make_layer (pplus, "pplus")); + std::auto_ptr rnplus (l2n.make_layer (nplus, "nplus")); + std::auto_ptr rpoly (l2n.make_polygon_layer (poly, "poly")); + std::auto_ptr rpoly_lbl (l2n.make_text_layer (poly_lbl, "poly_lbl")); + std::auto_ptr rdiff_cont (l2n.make_polygon_layer (diff_cont, "diff_cont")); + std::auto_ptr rpoly_cont (l2n.make_polygon_layer (poly_cont, "poly_cont")); + std::auto_ptr rmetal1 (l2n.make_polygon_layer (metal1, "metal1")); + std::auto_ptr rmetal1_lbl (l2n.make_text_layer (metal1_lbl, "metal1_lbl")); + std::auto_ptr rvia1 (l2n.make_polygon_layer (via1, "via1")); + std::auto_ptr rmetal2 (l2n.make_polygon_layer (metal2, "metal2")); + std::auto_ptr rmetal2_lbl (l2n.make_text_layer (metal2_lbl, "metal2_lbl")); + + // derived regions + + db::Region ractive_in_nwell = *ractive & *rnwell; + db::Region rpactive = ractive_in_nwell & *rpplus; + db::Region rntie = ractive_in_nwell & *rnplus; + db::Region rpgate = rpactive & *rpoly; + db::Region rpsd = rpactive - rpgate; + + db::Region ractive_outside_nwell = *ractive - *rnwell; + db::Region rnactive = ractive_outside_nwell & *rnplus; + db::Region rptie = ractive_outside_nwell & *rpplus; + db::Region rngate = rnactive & *rpoly; + db::Region rnsd = rnactive - rngate; + + // return the computed layers into the original layout and write it for debugging purposes + + unsigned int lgate = ly.insert_layer (db::LayerProperties (20, 0)); // 20/0 -> Gate + unsigned int lsd = ly.insert_layer (db::LayerProperties (21, 0)); // 21/0 -> Source/Drain + unsigned int lpdiff = ly.insert_layer (db::LayerProperties (22, 0)); // 22/0 -> P Diffusion + unsigned int lndiff = ly.insert_layer (db::LayerProperties (23, 0)); // 23/0 -> N Diffusion + unsigned int lptie = ly.insert_layer (db::LayerProperties (24, 0)); // 24/0 -> P Tie + unsigned int lntie = ly.insert_layer (db::LayerProperties (25, 0)); // 25/0 -> N Tie + + rpgate.insert_into (&ly, tc.cell_index (), lgate); + rngate.insert_into (&ly, tc.cell_index (), lgate); + rpsd.insert_into (&ly, tc.cell_index (), lsd); + rnsd.insert_into (&ly, tc.cell_index (), lsd); + rpsd.insert_into (&ly, tc.cell_index (), lpdiff); + rnsd.insert_into (&ly, tc.cell_index (), lndiff); + rpsd.insert_into (&ly, tc.cell_index (), lptie); + rnsd.insert_into (&ly, tc.cell_index (), lntie); + + db::NetlistDeviceExtractorMOS4Transistor pmos_ex ("PMOS"); + db::NetlistDeviceExtractorMOS4Transistor nmos_ex ("NMOS"); + + // device extraction + + db::NetlistDeviceExtractor::input_layers dl; + + dl["SD"] = &rpsd; + dl["G"] = &rpgate; + dl["P"] = rpoly.get (); // not needed for extraction but to return terminal shapes + dl["W"] = rnwell.get (); + l2n.extract_devices (pmos_ex, dl); + + dl["SD"] = &rnsd; + dl["G"] = &rngate; + dl["P"] = rpoly.get (); // not needed for extraction but to return terminal shapes + dl["W"] = rbulk.get (); + l2n.extract_devices (nmos_ex, dl); + + // net extraction + + l2n.register_layer (rpsd, "psd"); + l2n.register_layer (rnsd, "nsd"); + l2n.register_layer (rptie, "ptie"); + l2n.register_layer (rntie, "ntie"); + + // Intra-layer + l2n.connect (rpsd); + l2n.connect (rnsd); + l2n.connect (*rnwell); + l2n.connect (*rpoly); + l2n.connect (*rdiff_cont); + l2n.connect (*rpoly_cont); + l2n.connect (*rmetal1); + l2n.connect (*rvia1); + l2n.connect (*rmetal2); + l2n.connect (rptie); + l2n.connect (rntie); + // Inter-layer + l2n.connect (rpsd, *rdiff_cont); + l2n.connect (rnsd, *rdiff_cont); + l2n.connect (*rpoly, *rpoly_cont); + l2n.connect (*rpoly_cont, *rmetal1); + l2n.connect (*rdiff_cont, *rmetal1); + l2n.connect (*rdiff_cont, rptie); + l2n.connect (*rdiff_cont, rntie); + l2n.connect (*rnwell, rntie); + l2n.connect (*rmetal1, *rvia1); + l2n.connect (*rvia1, *rmetal2); + l2n.connect (*rpoly, *rpoly_lbl); // attaches labels + l2n.connect (*rmetal1, *rmetal1_lbl); // attaches labels + l2n.connect (*rmetal2, *rmetal2_lbl); // attaches labels + // Global + l2n.connect_global (rptie, "BULK"); + l2n.connect_global (*rbulk, "BULK"); + + // create some mess - we have to keep references to the layers to make them not disappear + rmetal1_lbl.reset (0); + rmetal2_lbl.reset (0); + rpoly_lbl.reset (0); + + l2n.extract_netlist (); + + l2n.netlist ()->flatten_circuit (l2n.netlist ()->circuit_by_name ("INV2")); + l2n.netlist ()->flatten_circuit (l2n.netlist ()->circuit_by_name ("INV2PAIR")); + l2n.netlist ()->flatten_circuit (l2n.netlist ()->circuit_by_name ("TRANS")); + + // debug layers produced for nets + // 201/0 -> Well + // 203/0 -> Poly + // 204/0 -> Diffusion contacts + // 205/0 -> Poly contacts + // 206/0 -> Metal1 + // 207/0 -> Via1 + // 208/0 -> Metal2 + // 210/0 -> N source/drain + // 211/0 -> P source/drain + // 212/0 -> N tie + // 213/0 -> P tie + std::map dump_map; + dump_map [&rpsd ] = ly.insert_layer (db::LayerProperties (210, 0)); + dump_map [&rnsd ] = ly.insert_layer (db::LayerProperties (211, 0)); + dump_map [&rptie ] = ly.insert_layer (db::LayerProperties (212, 0)); + dump_map [&rntie ] = ly.insert_layer (db::LayerProperties (213, 0)); + dump_map [rbulk.get () ] = ly.insert_layer (db::LayerProperties (214, 0)); + dump_map [rnwell.get () ] = ly.insert_layer (db::LayerProperties (201, 0)); + dump_map [rpoly.get () ] = ly.insert_layer (db::LayerProperties (203, 0)); + dump_map [rdiff_cont.get ()] = ly.insert_layer (db::LayerProperties (204, 0)); + dump_map [rpoly_cont.get ()] = ly.insert_layer (db::LayerProperties (205, 0)); + dump_map [rmetal1.get () ] = ly.insert_layer (db::LayerProperties (206, 0)); + dump_map [rvia1.get () ] = ly.insert_layer (db::LayerProperties (207, 0)); + dump_map [rmetal2.get () ] = ly.insert_layer (db::LayerProperties (208, 0)); + + // write nets to layout + db::CellMapping cm = l2n.cell_mapping_into (ly, tc); + dump_nets_to_layout (l2n, ly, dump_map, cm); + + dump_map.clear (); + dump_map [&rpsd ] = ly.insert_layer (db::LayerProperties (310, 0)); + dump_map [&rnsd ] = ly.insert_layer (db::LayerProperties (311, 0)); + dump_map [&rptie ] = ly.insert_layer (db::LayerProperties (312, 0)); + dump_map [&rntie ] = ly.insert_layer (db::LayerProperties (313, 0)); + dump_map [rbulk.get () ] = ly.insert_layer (db::LayerProperties (314, 0)); + dump_map [rnwell.get () ] = ly.insert_layer (db::LayerProperties (301, 0)); + dump_map [rpoly.get () ] = ly.insert_layer (db::LayerProperties (303, 0)); + dump_map [rdiff_cont.get ()] = ly.insert_layer (db::LayerProperties (304, 0)); + dump_map [rpoly_cont.get ()] = ly.insert_layer (db::LayerProperties (305, 0)); + dump_map [rmetal1.get () ] = ly.insert_layer (db::LayerProperties (306, 0)); + dump_map [rvia1.get () ] = ly.insert_layer (db::LayerProperties (307, 0)); + dump_map [rmetal2.get () ] = ly.insert_layer (db::LayerProperties (308, 0)); + + dump_recursive_nets_to_layout (l2n, ly, dump_map, cm); + + // compare netlist as string + CHECKPOINT (); + db::compare_netlist (_this, *l2n.netlist (), + "circuit RINGO ();\n" + " device PMOS $1 (S=FB,G=$I7,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $2 (S=VDD,G=$I7,D=FB,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $3 (S=FB,G=$I7,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $4 (S=VSS,G=$I7,D=FB,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $5 (S=OSC,G=FB,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $6 (S=VDD,G=FB,D=OSC,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $7 (S=OSC,G=FB,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $8 (S=VSS,G=FB,D=OSC,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $9 (S=$I22,G=FB,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $10 (S=VDD,G=FB,D=$I22,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $11 (S=$I22,G=FB,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $12 (S=VSS,G=FB,D=$I22,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $13 (S=$I13,G=$I22,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $14 (S=VDD,G=$I22,D=$I13,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $15 (S=$I13,G=$I22,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $16 (S=VSS,G=$I22,D=$I13,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $17 (S=$I23,G=$I13,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $18 (S=VDD,G=$I13,D=$I23,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $19 (S=$I23,G=$I13,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $20 (S=VSS,G=$I13,D=$I23,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $21 (S=$I5,G=$I23,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $22 (S=VDD,G=$I23,D=$I5,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $23 (S=$I5,G=$I23,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $24 (S=VSS,G=$I23,D=$I5,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $25 (S=$I24,G=$I5,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $26 (S=VDD,G=$I5,D=$I24,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $27 (S=$I24,G=$I5,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $28 (S=VSS,G=$I5,D=$I24,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $29 (S=$I6,G=$I24,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $30 (S=VDD,G=$I24,D=$I6,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $31 (S=$I6,G=$I24,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $32 (S=VSS,G=$I24,D=$I6,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $33 (S=$I25,G=$I6,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $34 (S=VDD,G=$I6,D=$I25,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $35 (S=$I25,G=$I6,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $36 (S=VSS,G=$I6,D=$I25,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device PMOS $37 (S=$I7,G=$I25,D=VDD,B=VDD) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device PMOS $38 (S=VDD,G=$I25,D=$I7,B=VDD) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + " device NMOS $39 (S=$I7,G=$I25,D=VSS,B=VSS) (L=0.25,W=1.75,AS=0.91875,AD=0.48125,PS=4.55,PD=2.3);\n" + " device NMOS $40 (S=VSS,G=$I25,D=$I7,B=VSS) (L=0.25,W=1.75,AS=0.48125,AD=0.91875,PS=2.3,PD=4.55);\n" + "end;\n" + ); + + // compare the collected test data + + std::string au = tl::testsrc (); + au = tl::combine_path (au, "testdata"); + au = tl::combine_path (au, "algo"); + au = tl::combine_path (au, "device_extract_au5_flattened_circuits.gds"); + + db::compare_layouts (_this, ly, au); +} + diff --git a/testdata/algo/device_extract_au5_flattened_circuits.gds b/testdata/algo/device_extract_au5_flattened_circuits.gds new file mode 100644 index 0000000000000000000000000000000000000000..40dc8210fcb946042ff26222e3c0e1ed253c94ad GIT binary patch literal 114198 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 CFHmg& literal 0 HcmV?d00001 diff --git a/testdata/lvs/ringo_simple_blackboxing.lvsdb b/testdata/lvs/ringo_simple_blackboxing.lvsdb index c3d5d3d44..15e2a8cc5 100644 --- a/testdata/lvs/ringo_simple_blackboxing.lvsdb +++ b/testdata/lvs/ringo_simple_blackboxing.lvsdb @@ -185,10 +185,22 @@ layout( rect(l8 (17310 3010) (180 180)) rect(l11 (-1140 -240) (900 300)) ) - net(12) - net(13) - net(14) - net(15) + net(12 + rect(l8 (10110 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + ) + net(13 + rect(l8 (11910 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + ) + net(14 + rect(l8 (13710 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + ) + net(15 + rect(l8 (15510 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + ) # Outgoing pins and their connections to nets pin(5 name(FB)) diff --git a/testdata/lvs/ringo_simple_simplification.lvsdb.1 b/testdata/lvs/ringo_simple_simplification.lvsdb.1 index dd00ad8d8..f73156a89 100644 --- a/testdata/lvs/ringo_simple_simplification.lvsdb.1 +++ b/testdata/lvs/ringo_simple_simplification.lvsdb.1 @@ -621,10 +621,30 @@ layout( rect(l2 (-1275 1800) (425 1500)) rect(l6 (-425 -4890) (425 950)) ) - net(12) - net(13) - net(14) - net(15) + net(12 + rect(l8 (10110 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(13 + rect(l8 (11910 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(14 + rect(l8 (13710 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(15 + rect(l8 (15510 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) # Outgoing pins and their connections to nets pin(5 name(FB)) diff --git a/testdata/lvs/ringo_simple_simplification_with_align.lvsdb.1 b/testdata/lvs/ringo_simple_simplification_with_align.lvsdb.1 index dd00ad8d8..f73156a89 100644 --- a/testdata/lvs/ringo_simple_simplification_with_align.lvsdb.1 +++ b/testdata/lvs/ringo_simple_simplification_with_align.lvsdb.1 @@ -621,10 +621,30 @@ layout( rect(l2 (-1275 1800) (425 1500)) rect(l6 (-425 -4890) (425 950)) ) - net(12) - net(13) - net(14) - net(15) + net(12 + rect(l8 (10110 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(13 + rect(l8 (11910 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(14 + rect(l8 (13710 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(15 + rect(l8 (15510 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) # Outgoing pins and their connections to nets pin(5 name(FB))