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 000000000..40dc8210f Binary files /dev/null and b/testdata/algo/device_extract_au5_flattened_circuits.gds differ 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))