diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 0da3ca0ca..f45a74d1a 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -142,7 +142,6 @@ SOURCES = \ dbHierProcessor.cc \ dbDeepRegion.cc \ dbHierNetworkProcessor.cc \ - dbNetlistProperty.cc \ dbNetlist.cc \ gsiDeclDbNetlist.cc \ dbNetlistDeviceClasses.cc \ @@ -271,7 +270,6 @@ HEADERS = \ dbHierarchyBuilder.h \ dbLocalOperation.h \ dbHierProcessor.h \ - dbNetlistProperty.h \ dbNetlist.h \ dbNetlistDeviceClasses.h \ dbNetlistDeviceExtractor.h \ diff --git a/src/db/db/dbCellMapping.cc b/src/db/db/dbCellMapping.cc index f942981bd..9554e79ba 100644 --- a/src/db/db/dbCellMapping.cc +++ b/src/db/db/dbCellMapping.cc @@ -283,7 +283,7 @@ CellMapping::create_from_names (const db::Layout &layout_a, db::cell_index_type } std::vector -CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b) +CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set *exclude_cells) { std::vector new_cells; std::vector new_cells_b; @@ -293,7 +293,7 @@ CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type / called_b.insert (cell_index_b); for (std::set::const_iterator b = called_b.begin (); b != called_b.end (); ++b) { - if (m_b2a_mapping.find (*b) == m_b2a_mapping.end ()) { + if (m_b2a_mapping.find (*b) == m_b2a_mapping.end () && (! exclude_cells || exclude_cells->find (*b) == exclude_cells->end ())) { db::cell_index_type new_cell = layout_a.add_cell (layout_b.cell_name (*b)); new_cells.push_back (new_cell); new_cells_b.push_back (*b); diff --git a/src/db/db/dbCellMapping.h b/src/db/db/dbCellMapping.h index 854fd1ffa..63740b1ca 100644 --- a/src/db/db/dbCellMapping.h +++ b/src/db/db/dbCellMapping.h @@ -30,6 +30,8 @@ #include "dbTypes.h" #include +#include +#include namespace db { @@ -186,9 +188,11 @@ public: * left unmapped. This method allows creating mappings for these missing cells by adding * new cells and the corresponding instances into the target layout_a. * + * If given, "exclude_cells" can specify a list of cells not to map. + * * The returned vector lists the new cells. */ - std::vector create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b); + std::vector create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set *exclude_cells = 0); private: void extract_unique (std::map >::const_iterator cand, diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index b677bcfff..438456bc4 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -388,7 +388,7 @@ DeepShapeStore::invalidate_hier () } const db::CellMapping & -DeepShapeStore::cell_mapping_to_original (size_t layout_index, db::Layout *into_layout, db::cell_index_type into_cell) +DeepShapeStore::cell_mapping_to_original (size_t layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set *excluded_cells) { const db::Layout *source_layout = &m_layouts [layout_index]->layout; if (source_layout->begin_top_down () == source_layout->end_top_cells ()) { @@ -436,21 +436,21 @@ DeepShapeStore::cell_mapping_to_original (size_t layout_index, db::Layout *into_ } - // Add new cells for the variants and (possible) devices which are cells added during the device - // extraction process - cm->second.create_missing_mapping (*into_layout, into_cell, *source_layout, source_top); - } else if (into_layout->cells () == 1) { // Another simple case is mapping into an empty (or single-top-cell-only) layout, where we can use "create_from_single_full". - cm->second.create_single_mapping_full (*into_layout, into_cell, *source_layout, source_top); + cm->second.create_single_mapping (*into_layout, into_cell, *source_layout, source_top); } else { - cm->second.create_from_geometry_full (*into_layout, into_cell, *source_layout, source_top); + cm->second.create_from_geometry (*into_layout, into_cell, *source_layout, source_top); } + // Add new cells for the variants and (possible) devices which are cells added during the device + // extraction process + cm->second.create_missing_mapping (*into_layout, into_cell, *source_layout, source_top, excluded_cells); + } return cm->second; diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index 0c658eb17..306b8f429 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -239,8 +239,10 @@ public: * If necessary, this method will modify the original layout and add new cells. * "layout_index" is the layout to return to it's original. "into_layout" is the original layout, "into_cell" * the original cell. + * + * "excluded_cells" - if not 0 - will exclude the given cells (and flatten them). */ - const db::CellMapping &cell_mapping_to_original (size_t layout_index, db::Layout *into_layout, db::cell_index_type into_cell); + const db::CellMapping &cell_mapping_to_original (size_t layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set *excluded_cells = 0); /** * @brief For testing diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 57896e388..773a47c1e 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -211,9 +211,22 @@ unsigned int LayoutToNetlist::layer_of (const db::Region ®ion) const return dr->deep_layer ().layer (); } -db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell &cell) +db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells) { - return m_dss.cell_mapping_to_original (0, &layout, cell.cell_index ()); + unsigned int layout_index = 0; + + std::set device_cells; + + if (! with_device_cells) { + const db::Layout &src_layout = m_dss.layout (layout_index); + for (db::Layout::const_iterator c = src_layout.begin (); c != src_layout.end (); ++c) { + if (db::NetlistDeviceExtractor::is_device_cell (src_layout, c->cell_index ())) { + device_cells.insert (c->cell_index ()); + } + } + } + + return m_dss.cell_mapping_to_original (layout_index, &layout, cell.cell_index (), &device_cells); } db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell) @@ -258,26 +271,18 @@ static void deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const T } template -static void deliver_shapes_of_net_recursive (const db::hier_clusters &clusters, const db::Net &net, unsigned int layer_id, To &to) +static void deliver_shapes_of_net_recursive (const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, To &to) { - const db::Circuit *circuit = net.circuit (); - tl_assert (circuit != 0); - - db::cell_index_type ci = circuit->cell_index (); - - for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, net.cluster_id ()); !rci.at_end (); ++rci) { + // deliver the net shapes + for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) { deliver_shape (*rci, to, rci.trans ()); } } template -static void deliver_shapes_of_net_nonrecursive (const db::hier_clusters &clusters, const db::Net &net, unsigned int layer_id, To &to) +static void deliver_shapes_of_net_nonrecursive (const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, To &to) { - const db::Circuit *circuit = net.circuit (); - tl_assert (circuit != 0); - - db::cell_index_type ci = circuit->cell_index (); - const db::local_cluster &lc = clusters.clusters_per_cell (ci).cluster_by_id (net.cluster_id ()); + const db::local_cluster &lc = clusters.clusters_per_cell (ci).cluster_by_id (cid); for (db::local_cluster::shape_iterator s = lc.begin (layer_id); !s.at_end (); ++s) { deliver_shape (*s, to, db::UnitTrans ()); @@ -287,71 +292,95 @@ static void deliver_shapes_of_net_nonrecursive (const db::hier_clusterscell_index (), net.cluster_id (), lid, to); } else { - deliver_shapes_of_net_recursive (m_net_clusters, net, lid, to); + deliver_shapes_of_net_recursive (m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, to); } } db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const { unsigned int lid = layer_of (of_layer); + const db::Circuit *circuit = net.circuit (); + tl_assert (circuit != 0); + std::auto_ptr res (new db::Region ()); if (! recursive) { - deliver_shapes_of_net_nonrecursive (m_net_clusters, net, lid, *res); + deliver_shapes_of_net_nonrecursive (m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, *res); } else { - deliver_shapes_of_net_recursive (m_net_clusters, net, lid, *res); + deliver_shapes_of_net_recursive (m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, *res); } return res.release (); } void -LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, std::map, db::cell_index_type> &cmap) const +LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap) const { - for (std::map::const_iterator l = lmap.begin (); l != lmap.end (); ++l) { - shapes_of_net (net, *l->second, false, target_cell.shapes (l->first)); - } - - if (! cell_name_prefix) { - return; - } - const db::Circuit *circuit = net.circuit (); tl_assert (circuit != 0); - const db::connected_clusters &clusters = m_net_clusters.clusters_per_cell (circuit->cell_index ()); + build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, cell_name_prefix, device_cell_name_prefix, cmap); +} + +void +LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap) const +{ + for (std::map::const_iterator l = lmap.begin (); l != lmap.end (); ++l) { + deliver_shapes_of_net_nonrecursive (m_net_clusters, ci, cid, layer_of (*l->second), target_cell.shapes (l->first)); + } + + if (! cell_name_prefix && ! device_cell_name_prefix) { + return; + } + + const db::connected_clusters &clusters = m_net_clusters.clusters_per_cell (ci); typedef db::connected_clusters::connections_type connections_type; - const connections_type &connections = clusters.connections_for_cluster (net.cluster_id ()); + const connections_type &connections = clusters.connections_for_cluster (cid); for (connections_type::const_iterator c = connections.begin (); c != connections.end (); ++c) { - db::cell_index_type ci = c->inst ().inst_ptr.cell_index (); - const db::Circuit *subcircuit = mp_netlist->circuit_by_cell_index (ci); - tl_assert (subcircuit != 0); + db::cell_index_type subci = c->inst ().inst_ptr.cell_index (); + size_t subcid = c->id (); - const db::Net *subnet = subcircuit->net_by_cluster_id (c->id ()); - tl_assert (subnet != 0); - - std::map, db::cell_index_type>::const_iterator cm = cmap.find (std::make_pair (ci, c->id ())); + std::map, db::cell_index_type>::const_iterator cm = cmap.find (std::make_pair (subci, subcid)); if (cm == cmap.end ()) { - db::cell_index_type target_ci = target.add_cell ((std::string (cell_name_prefix) + subcircuit->name ()).c_str ()); - cm = cmap.insert (std::make_pair (std::make_pair (ci, c->id ()), target_ci)).first; + const char *name_prefix = 0; + if (db::NetlistDeviceExtractor::is_device_cell (*internal_layout (), subci)) { + name_prefix = device_cell_name_prefix; + } else { + name_prefix = cell_name_prefix; + } - build_net_rec (*subnet, target, target.cell (target_ci), lmap, cell_name_prefix, cmap); + if (name_prefix) { + + std::string cell_name = internal_layout ()->cell_name (subci); + + db::cell_index_type target_ci = target.add_cell ((std::string (name_prefix) + cell_name).c_str ()); + cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), target_ci)).first; + + build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, cell_name_prefix, device_cell_name_prefix, cmap); + + } else { + cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), std::numeric_limits::max ())).first; + } } - target_cell.insert (db::CellInstArray (db::CellInst (cm->second), c->inst ().complex_trans ())); + if (cm->second != std::numeric_limits::max ()) { + target_cell.insert (db::CellInstArray (db::CellInst (cm->second), c->inst ().complex_trans ())); + } } } void -LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix) const +LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix) const { if (! m_netlist_extracted) { throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); @@ -359,11 +388,11 @@ LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &ta std::map, db::cell_index_type> cell_map; - build_net_rec (net, target, target_cell, lmap, cell_name_prefix, cell_map); + build_net_rec (net, target, target_cell, lmap, cell_name_prefix, device_cell_name_prefix, cell_map); } void -LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix) const +LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const { if (! m_netlist_extracted) { throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); @@ -409,7 +438,7 @@ LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target } - build_net_rec (*n, target, target.cell (net_ci), lmap, circuit_cell_name_prefix, cell_map); + build_net_rec (*n, target, target.cell (net_ci), lmap, circuit_cell_name_prefix, device_cell_name_prefix, cell_map); } diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index af30a3436..d2f5649e8 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -214,9 +214,11 @@ public: /** * @brief Creates a cell mapping for copying shapes from the internal layout to the given target layout. - * CAUTION: may create new cells in "layout". + * If 'with_device_cells' is true, cells will be produced for devices. These are cells not corresponding to circuits, so they are disabled normally. + * Use this option, if you want to access device terminal shapes per device. + * CAUTION: This function may create new cells in "layout". */ - db::CellMapping cell_mapping_into (db::Layout &layout, db::Cell &cell); + db::CellMapping cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells = false); /** * @brief Creates a cell mapping for copying shapes from the internal layout to the given target layout. @@ -275,12 +277,16 @@ public: * Recursive mode is picked when a cell name prefix is given. The new cells will be * named like cell_name_prefix + circuit name. * + * If a device cell name prefix is given, cells will be produced for each device model + * using a name like device_cell_name_prefix + device name. + * * @param target The target layout * @param target_cell The target cell * @param lmap Target layer indexes (keys) and net regions (values) * @param cell_name_prefix Chooses recursive mode if non-null + * @param device_cell_name_prefix See above */ - void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix) const; + void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix) const; /** * @brief Builds a full hierarchical representation of the nets @@ -300,13 +306,17 @@ public: * * Subnet hierarchy (circuit_cell_name_prefix != 0): for each root net, a full hierarchy is built * to accomodate the subnets (see build_net in recursive mode). * + * If a device cell name prefix is given, cells will be produced for each device model + * using a name like device_cell_name_prefix + device name. + * * @param cmap The mapping of internal layout to target layout for the circuit mapping * @param target The target layout * @param lmap Target layer indexes (keys) and net regions (values) * @param circuit_cell_name_prefix See method description * @param net_cell_name_prefix See method description + * @param device_cell_name_prefix See above */ - void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix) const; + void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const; /** * @brief Finds the net by probing a specific location on the given layer @@ -344,7 +354,8 @@ private: bool m_netlist_extracted; 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, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, std::map, db::cell_index_type> &cmap) const; + void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap) const; + void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap) const; }; } diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index f8c44f331..74b38e3b9 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -21,7 +21,6 @@ */ #include "dbNetlistDeviceExtractor.h" -#include "dbNetlistProperty.h" #include "dbRegion.h" #include "dbHierNetworkProcessor.h" #include "dbDeepRegion.h" @@ -224,16 +223,21 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db: } } -bool NetlistDeviceExtractor::is_device_cell (db::cell_index_type ci) const +bool NetlistDeviceExtractor::is_device_cell (const db::Layout &layout, db::cell_index_type ci) { - db::properties_id_type pi = mp_layout->cell (ci).prop_id (); + db::properties_id_type pi = layout.cell (ci).prop_id (); if (pi == 0) { return false; } - const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (pi); + std::pair pn = layout.properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::device_class_property_name ()); + if (! pn.first) { + return false; + } + + const db::PropertiesRepository::properties_set &ps = layout.properties_repository ().properties (pi); for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) { - if (j->first == m_device_class_propname_id) { + if (j->first == pn.second) { return true; } } @@ -241,13 +245,20 @@ bool NetlistDeviceExtractor::is_device_cell (db::cell_index_type ci) const return false; } +bool NetlistDeviceExtractor::is_device_cell (db::cell_index_type ci) const +{ + return is_device_cell (*mp_layout, ci); +} + void NetlistDeviceExtractor::push_new_devices () { db::VCplxTrans dbu_inv = db::CplxTrans (mp_layout->dbu ()).inverted (); - for (std::map::const_iterator d = m_new_devices.begin (); d != m_new_devices.end (); ++d) { + for (std::map::const_iterator d = m_new_devices.begin (); d != m_new_devices.end (); ++d) { - db::Vector disp = dbu_inv * d->first->position () - db::Point (); + db::Device *device = mp_circuit->device_by_id (d->first); + + db::Vector disp = dbu_inv * device->position () - db::Point (); DeviceCellKey key; @@ -265,7 +276,7 @@ void NetlistDeviceExtractor::push_new_devices () const std::vector &pd = mp_device_class->parameter_definitions (); for (std::vector::const_iterator p = pd.begin (); p != pd.end (); ++p) { - key.parameters.insert (std::make_pair (p->id (), d->first->parameter_value (p->id ()))); + key.parameters.insert (std::make_pair (p->id (), device->parameter_value (p->id ()))); } db::PropertiesRepository::properties_set ps; @@ -311,11 +322,11 @@ void NetlistDeviceExtractor::push_new_devices () } // make the cell index known to the device - d->first->set_cell_index (c->second); + device->set_cell_index (c->second); // Build a property set for the device ID ps.clear (); - ps.insert (std::make_pair (m_device_id_propname_id, tl::Variant (d->first->id ()))); + ps.insert (std::make_pair (m_device_id_propname_id, tl::Variant (d->first))); db::properties_id_type pi = mp_layout->properties_repository ().properties_id (ps); db::CellInstArrayWithProperties inst (db::CellInstArray (db::CellInst (c->second), db::Trans (disp)), pi); @@ -383,7 +394,7 @@ void NetlistDeviceExtractor::define_terminal (Device *device, size_t terminal_id unsigned int layer_index = m_layers [geometry_index]; db::PolygonRef pr (polygon, mp_layout->shape_repository ()); - m_new_devices[device][terminal_id][layer_index].push_back (pr); + m_new_devices[device->id ()][terminal_id][layer_index].push_back (pr); } void NetlistDeviceExtractor::define_terminal (Device *device, size_t terminal_id, size_t layer_index, const db::Box &box) diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index bf6281919..3626e4876 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -234,6 +234,11 @@ public: */ static const tl::Variant &device_class_property_name (); + /** + * @brief Returns true, if the given cell is a device cell + */ + static bool is_device_cell (const db::Layout &layout, db::cell_index_type ci); + /** * @brief Performs the extraction * @@ -507,7 +512,7 @@ private: layer_definitions m_layer_definitions; std::vector m_layers; error_list m_errors; - std::map m_new_devices; + std::map m_new_devices; std::map m_device_cells; // no copying diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index de0e4c118..2d0b95248 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -23,7 +23,6 @@ #include "dbNetlistExtractor.h" #include "dbDeepShapeStore.h" #include "dbNetlistDeviceExtractor.h" -#include "dbNetlistProperty.h" namespace db { @@ -50,7 +49,6 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect m_terminal_annot_name_id = mp_layout->properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::terminal_id_property_name ()); m_device_annot_name_id = mp_layout->properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::device_id_property_name ()); - m_device_class_annot_name_id = mp_layout->properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::device_class_property_name ()); // the big part: actually extract the nets @@ -68,7 +66,7 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect std::map > pins_per_cluster_per_cell; for (db::Layout::bottom_up_const_iterator cid = mp_layout->begin_bottom_up (); cid != mp_layout->end_bottom_up (); ++cid) { - if (cell_is_device_cell (*cid)) { + if (db::NetlistDeviceExtractor::is_device_cell (*mp_layout, *cid)) { continue; } @@ -149,27 +147,6 @@ void NetlistExtractor::collect_labels (const connected_clusters_type &clusters, } } -bool NetlistExtractor::cell_is_device_cell (db::cell_index_type ci) const -{ - if (! m_device_class_annot_name_id.first) { - return false; - } - - const db::Cell &cell = mp_layout->cell (ci); - if (cell.prop_id () == 0) { - return false; - } - - const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (cell.prop_id ()); - for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) { - if (j->first == m_device_class_annot_name_id.second) { - return true; - } - } - - return false; -} - bool NetlistExtractor::instance_is_device (db::properties_id_type prop_id) const { if (! prop_id || ! m_device_annot_name_id.first) { diff --git a/src/db/db/dbNetlistExtractor.h b/src/db/db/dbNetlistExtractor.h index 70d6f4565..5447f63b5 100644 --- a/src/db/db/dbNetlistExtractor.h +++ b/src/db/db/dbNetlistExtractor.h @@ -90,11 +90,9 @@ private: std::pair m_text_annot_name_id; std::pair m_device_annot_name_id; std::pair m_terminal_annot_name_id; - std::pair m_device_class_annot_name_id; void assign_net_name (const std::string &n, db::Net *net); bool instance_is_device (db::properties_id_type prop_id) const; - bool cell_is_device_cell (db::cell_index_type ci) const; db::Device *device_from_instance (db::properties_id_type prop_id, db::Circuit *circuit) const; /** diff --git a/src/db/db/dbNetlistProperty.cc b/src/db/db/dbNetlistProperty.cc deleted file mode 100644 index 1680c86d7..000000000 --- a/src/db/db/dbNetlistProperty.cc +++ /dev/null @@ -1,197 +0,0 @@ - -/* - - KLayout Layout Viewer - Copyright (C) 2006-2019 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 - -*/ - -#include "dbNetlistProperty.h" -#include "tlString.h" - -#include - -namespace tl -{ - -void VariantUserClass::destroy (void *p) const -{ - delete (db::NetlistProperty *) p; -} - -bool VariantUserClass::equal (const void *a, const void *b) const -{ - const db::NetlistProperty *pa = (db::NetlistProperty *) a; - const db::NetlistProperty *pb = (db::NetlistProperty *) b; - if (typeid (*pa) == typeid (*pb)) { - return pa->equals (pb); - } else { - return false; - } -} - -bool VariantUserClass::less (const void *a, const void *b) const -{ - const db::NetlistProperty *pa = (db::NetlistProperty *) a; - const db::NetlistProperty *pb = (db::NetlistProperty *) b; - if (typeid (*pa) == typeid (*pb)) { - return pa->less (pb); - } else { - return typeid (*pa).before (typeid (*pb)); - } -} - -void *VariantUserClass::clone (const void *p) const -{ - return ((const db::NetlistProperty *) p)->clone (); -} - -std::string VariantUserClass::to_string (const void *p) const -{ - return ((const db::NetlistProperty *) p)->to_string (); -} - -void VariantUserClass::read (void * /*p*/, tl::Extractor & /*ex*/) const -{ - // .. nothing yet .. - return; -} - -void VariantUserClass::assign (void *self, const void *other) const -{ - db::NetlistProperty *pself = (db::NetlistProperty *) self; - const db::NetlistProperty *pother = (const db::NetlistProperty *) other; - tl_assert (typeid (*pself) == typeid (*pother)); - pself->assign (pother); -} - -void *VariantUserClass::deref_proxy (tl::Object *proxy) const -{ - return proxy; -} - -void VariantUserClass::register_instance (const tl::VariantUserClassBase *inst, bool is_const) -{ - VariantUserClassBase::register_instance (inst, typeid (db::NetlistProperty), is_const); -} - -void VariantUserClass::unregister_instance (const tl::VariantUserClassBase *inst, bool is_const) -{ - VariantUserClassBase::unregister_instance (inst, typeid (db::NetlistProperty), is_const); -} - -} - -namespace db -{ - -// -------------------------------------------------------------------------------------------- -// NetlistProperty Implementation - -NetlistProperty::NetlistProperty () -{ - // .. nothing yet .. -} - -NetlistProperty::NetlistProperty (const NetlistProperty &) -{ - // .. nothing yet .. -} - -NetlistProperty::~NetlistProperty () -{ - // .. nothing yet .. -} - -const tl::VariantUserClass *NetlistProperty::variant_class () -{ - static tl::VariantUserClass s_cls; - return &s_cls; -} - -// -------------------------------------------------------------------------------------------- -// DeviceTerminalProperty Implementation - -DeviceTerminalProperty::DeviceTerminalProperty () - : NetlistProperty (), m_terminal_id (0), m_device_id (0) -{ - // .. nothing yet .. -} - -DeviceTerminalProperty::DeviceTerminalProperty (const DeviceTerminalProperty &other) - : NetlistProperty (other), m_terminal_id (other.m_terminal_id), m_device_id (other.m_device_id) -{ - // .. nothing yet .. -} - -DeviceTerminalProperty::DeviceTerminalProperty (size_t device_id, size_t terminal_id) - : NetlistProperty (), m_terminal_id (terminal_id), m_device_id (device_id) -{ - // .. nothing yet .. -} - -void DeviceTerminalProperty::set_terminal_ref (size_t device_id, size_t terminal_id) -{ - m_device_id = device_id; - m_terminal_id = terminal_id; -} - -DeviceTerminalProperty &DeviceTerminalProperty::operator= (const DeviceTerminalProperty &other) -{ - NetlistProperty::operator= (other); - if (this != &other) { - m_terminal_id = other.m_terminal_id; - m_device_id = other.m_device_id; - } - return *this; -} - -bool DeviceTerminalProperty::equals (const NetlistProperty *p) const -{ - const DeviceTerminalProperty *pp = static_cast (p); - return NetlistProperty::equals (p) && m_terminal_id == pp->m_terminal_id && m_device_id == pp->m_device_id; -} - -bool DeviceTerminalProperty::less (const NetlistProperty *p) const -{ - if (! NetlistProperty::equals (p)) { - return NetlistProperty::less (p); - } else { - const DeviceTerminalProperty *pp = static_cast (p); - if (m_terminal_id != pp->m_terminal_id) { - return m_terminal_id < pp->m_terminal_id; - } else { - return m_device_id < pp->m_device_id; - } - } -} - -void DeviceTerminalProperty::assign (const NetlistProperty *p) -{ - NetlistProperty::assign (p); - const DeviceTerminalProperty *pp = static_cast (p); - m_terminal_id = pp->m_terminal_id; - m_device_id = pp->m_device_id; -} - - -std::string DeviceTerminalProperty::to_string () const -{ - return tl::to_string (m_device_id) + ":" + tl::to_string (m_terminal_id); -} - -} diff --git a/src/db/db/dbNetlistProperty.h b/src/db/db/dbNetlistProperty.h deleted file mode 100644 index 1eff42c23..000000000 --- a/src/db/db/dbNetlistProperty.h +++ /dev/null @@ -1,241 +0,0 @@ - -/* - - KLayout Layout Viewer - Copyright (C) 2006-2019 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_dbNetlistProperty -#define _HDR_dbNetlistProperty - -#include "dbCommon.h" -#include "dbNetlist.h" -#include "tlVariant.h" - -#include - -namespace db -{ - class NetlistProperty; -} - -namespace tl -{ - class Extractor; - - // specialization of tl::VariantUserClass for the purpose of NetlistProperty representation - template <> class DB_PUBLIC VariantUserClass - : public tl::VariantUserClassBase - { - public: - // creation not supported - virtual void *create () const { tl_assert (false); } - - virtual void destroy (void *p) const; - virtual bool equal (const void *a, const void *b) const; - virtual bool less (const void *a, const void *b) const; - virtual void *clone (const void *p) const; - virtual const char *name () const { return ""; } - virtual bool is_const () const { return false; } - virtual const gsi::ClassBase *gsi_cls () const { return 0; } - virtual const tl::EvalClass *eval_cls () const { return 0; } - virtual std::string to_string (const void *p) const; - virtual void read (void *p, tl::Extractor &ex) const; - virtual void assign (void *self, const void *other) const; - virtual void *deref_proxy (tl::Object *proxy) const; - - db::NetlistProperty *get (void *ptr) const { return reinterpret_cast (ptr); } - const db::NetlistProperty *get (const void *ptr) const { return reinterpret_cast (ptr); } - - protected: - void register_instance (const tl::VariantUserClassBase *inst, bool is_const); - void unregister_instance (const tl::VariantUserClassBase *inst, bool is_const); - }; - -} - -namespace db -{ - -/** - * @brief The base class for a netlist property attached to a shape - * - * This class provides a wrapper for binding a netlist property - * to a tl::Variant. Hence it can be kept as a shape property - * in the context of db::Layout's propery repo. - */ -class DB_PUBLIC NetlistProperty -{ -public: - /** - * @brief Gets the class descriptor for keeping the object inside a tl::Variant - * - * For a Variant that owns a NetlistProperty object, use - * - * @code - * db::NetlistProperty *prop = new db::NetlistProperty (); - * bool shared = true; // the variant will own the object - * tl::Variant prop_in_var (prop, prop->variant_class (), shared); - * @endcode - */ - static const tl::VariantUserClass *variant_class (); - - /** - * @brief Constructor - */ - NetlistProperty (); - - /** - * @brief Copy constructor - */ - NetlistProperty (const NetlistProperty &other); - - /** - * @brief (virtual) Destructor - */ - virtual ~NetlistProperty (); - - /** - * @brief Clones the object - */ - virtual NetlistProperty *clone () const - { - return new NetlistProperty (*this); - } - - /** - * @brief Compares two objects (equal). Both types are guaranteed to be the same. - */ - virtual bool equals (const NetlistProperty *) const - { - return true; - } - - /** - * @brief Compares two objects (less). Both types are guaranteed to be the same. - */ - virtual bool less (const NetlistProperty *) const - { - return false; - } - - /** - * @brief Assigned the other object to self. Both types are guaranteed to be identical. - */ - virtual void assign (const NetlistProperty *) - { - // .. nothing yet .. - } - - /** - * @brief Converts to a string - */ - virtual std::string to_string () const - { - return std::string (); - } -}; - -/** - * @brief A reference to a device terminal - * - * This property is used to mark a shape as a device terminal reference. - * Such a terminal reference points to a terminal of a specific device. - * Attaching such a property to a shape allows connecting the - * net to the device later. - */ -class DB_PUBLIC DeviceTerminalProperty - : public db::NetlistProperty -{ -public: - /** - * @brief Creates a netlist name property without a specific name - */ - DeviceTerminalProperty (); - - /** - * @brief copy constructor - */ - DeviceTerminalProperty (const db::DeviceTerminalProperty &other); - - /** - * @brief Creates a netlist name property with the given name - */ - DeviceTerminalProperty (size_t device_id, size_t terminal_id); - - /** - * @brief Assignment - */ - DeviceTerminalProperty &operator= (const DeviceTerminalProperty &other); - - /** - * @brief Sets the terminal reference - */ - void set_terminal_ref (size_t device_id, size_t terminal_id); - - /** - * @brief Gets the terminal ID - */ - size_t terminal_id () const - { - return m_terminal_id; - } - - /** - * @brief Gets the device ID - */ - size_t device_id () const - { - return m_device_id; - } - - /** - * @brief Clones the object - */ - virtual DeviceTerminalProperty *clone () const - { - return new DeviceTerminalProperty (*this); - } - - /** - * @brief Compares two objects (equal). Both types are guaranteed to be the same. - */ - virtual bool equals (const NetlistProperty *) const; - - /** - * @brief Compares two objects (less). Both types are guaranteed to be the same. - */ - virtual bool less (const NetlistProperty *) const; - - /** - * @brief Assigned the other object to self. Both types are guaranteed to be identical. - */ - virtual void assign (const NetlistProperty *); - - /** - * @brief Converts to a string - */ - virtual std::string to_string () const; - -private: - size_t m_terminal_id, m_device_id; -}; - -} - -#endif diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index ad0539767..884ad8f94 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -43,17 +43,19 @@ static db::Cell *l2n_internal_top_cell (db::LayoutToNetlist *l2n) return const_cast (l2n->internal_top_cell ()); } -static void build_net (const db::LayoutToNetlist *l2n, const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const tl::Variant &cell_name_prefix) +static void build_net (const db::LayoutToNetlist *l2n, const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix) { - std::string p = cell_name_prefix.to_string (); - l2n->build_net (net, target, target_cell, lmap, cell_name_prefix.is_nil () ? 0 : p.c_str ()); + std::string p = circuit_cell_name_prefix.to_string (); + std::string dp = device_cell_name_prefix.to_string (); + l2n->build_net (net, target, target_cell, lmap, circuit_cell_name_prefix.is_nil () ? 0 : p.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ()); } -static void build_all_nets (const db::LayoutToNetlist *l2n, const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const tl::Variant &net_cell_name_prefix, const tl::Variant &circuit_cell_name_prefix) +static void build_all_nets (const db::LayoutToNetlist *l2n, const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const tl::Variant &net_cell_name_prefix, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix) { std::string cp = circuit_cell_name_prefix.to_string (); std::string np = net_cell_name_prefix.to_string (); - l2n->build_all_nets (cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), circuit_cell_name_prefix.is_nil () ? 0 : cp.c_str ()); + std::string dp = device_cell_name_prefix.to_string (); + l2n->build_all_nets (cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), circuit_cell_name_prefix.is_nil () ? 0 : cp.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ()); } Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", @@ -150,9 +152,11 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "This method is required to derive the internal layer index - for example for\n" "investigating the cluster tree.\n" ) + - gsi::method ("cell_mapping_into", &db::LayoutToNetlist::cell_mapping_into, gsi::arg ("layout"), gsi::arg ("cell"), + gsi::method ("cell_mapping_into", &db::LayoutToNetlist::cell_mapping_into, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("with_device_cells", false), "@brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.\n" - "CAUTION: may create new cells in 'layout'.\n" + "If 'with_device_cells' is true, cells will be produced for devices. These are cells not corresponding to circuits, so they are disabled normally.\n" + "Use this option, if you want to access device terminal shapes per device.\n" + "CAUTION: this function may create new cells in 'layout'.\n" ) + gsi::method ("const_cell_mapping_into", &db::LayoutToNetlist::const_cell_mapping_into, gsi::arg ("layout"), gsi::arg ("cell"), "@brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.\n" @@ -172,7 +176,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "If 'recursive'' is true, the returned region will contain the shapes of\n" "all subcircuits too.\n" ) + - gsi::method_ext ("build_net", &build_net, gsi::arg ("net"), gsi::arg ("target"), gsi::arg ("target_cell"), gsi::arg ("lmap"), gsi::arg ("cell_name"), + gsi::method_ext ("build_net", &build_net, gsi::arg ("net"), gsi::arg ("target"), gsi::arg ("target_cell"), gsi::arg ("lmap"), 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" "\n" "This method has two modes: recursive and top-level mode. In recursive mode,\n" @@ -182,15 +186,19 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "In top-level mode, only the shapes from the net inside it's circuit are copied to\n" "the given target cell. No other cells are created.\n" "\n" - "Recursive mode is picked when a cell name prefix is given. The new cells will be\n" - "named like cell_name_prefix + circuit name.\n" + "Recursive mode is picked when a circuit cell name prefix is given. The new cells will be\n" + "named like circuit_cell_name_prefix + circuit name.\n" + "\n" + "If a device cell name prefix is given, device shapes will be output on device cells named\n" + "like device_cell_name_prefix + device name.\n" "\n" "@param target The target layout\n" "@param target_cell The target cell\n" "@param lmap Target layer indexes (keys) and net regions (values)\n" - "@param cell_name_prefix Chooses recursive mode if non-nil\n" + "@param circuit_cell_name_prefix Chooses recursive mode if non-nil\n" + "@param device_cell_name_prefix If given, devices will be output as separate cells\n" ) + - gsi::method_ext ("build_all_nets", &build_all_nets, gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix"), gsi::arg ("circuit_cell_name_prefix"), + gsi::method_ext ("build_all_nets", &build_all_nets, gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"), "@brief Builds a full hierarchical representation of the nets\n" "\n" "This method copies all nets into cells corresponding to the circuits. It uses the cmap\n" @@ -214,11 +222,15 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", " to accomodate the subnets (see build_net in recursive mode). @/li\n" "@/ul\n" "\n" + "If a device name prefix is given, device shapes will be output on device cells named\n" + "like device_name_prefix + device name.\n" + "\n" "@param cmap The mapping of internal layout to target layout for the circuit mapping\n" "@param target The target layout\n" "@param lmap Target layer indexes (keys) and net regions (values)\n" "@param circuit_cell_name_prefix See method description\n" "@param net_cell_name_prefix See method description\n" + "@param device_cell_name_prefix If given, devices will be output as separate cells\n" ) + gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), "@brief Finds the net by probing a specific location on the given layer\n" diff --git a/src/db/unit_tests/dbLayoutToNetlistTests.cc b/src/db/unit_tests/dbLayoutToNetlistTests.cc index 250b91ac0..cc358fee1 100644 --- a/src/db/unit_tests/dbLayoutToNetlistTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistTests.cc @@ -37,103 +37,11 @@ #include #include -namespace -{ - static std::string qnet_name (const db::Net *net) { return net ? net->qname () : "(null)"; } -static std::string device_name (const db::Device &device) -{ - if (device.name ().empty ()) { - return "$" + tl::to_string (device.id ()); - } else { - return device.name (); - } -} - -static void mos2layout (const db::Layout *layout, db::cell_index_type cell_index, db::Layout *debug_out, const db::Device *device, unsigned int ldiff, const db::Region &diff, unsigned int lgate, const db::Region &gate) -{ - std::string cn = layout->cell_name (cell_index); - std::pair target_cp = debug_out->cell_by_name (cn.c_str ()); - tl_assert (target_cp.first); - - db::cell_index_type dci = debug_out->add_cell ((device->device_class ()->name () + "_" + device->circuit ()->name () + "_" + device_name (*device)).c_str ()); - debug_out->cell (target_cp.second).insert (db::CellInstArray (db::CellInst (dci), db::Trans ())); - - db::Cell &device_cell = debug_out->cell (dci); - for (db::Region::const_iterator p = diff.begin (); ! p.at_end (); ++p) { - device_cell.shapes (ldiff).insert (*p); - } - for (db::Region::const_iterator p = gate.begin (); ! p.at_end (); ++p) { - device_cell.shapes (lgate).insert (*p); - } - - std::string ps; - const std::vector &pd = device->device_class ()->parameter_definitions (); - for (std::vector::const_iterator i = pd.begin (); i != pd.end (); ++i) { - if (! ps.empty ()) { - ps += ","; - } - ps += i->name () + "=" + tl::to_string (device->parameter_value (i->id ())); - } - device_cell.shapes (ldiff).insert (db::Text (ps, db::Trans (diff.bbox ().center () - db::Point ()))); -} - -class MOSFET3Extractor - : public db::NetlistDeviceExtractorMOS3Transistor -{ -public: - MOSFET3Extractor (const std::string &name, db::Layout *debug_out) - : db::NetlistDeviceExtractorMOS3Transistor (name), mp_debug_out (debug_out), m_ldiff (0), m_lgate (0) - { - if (mp_debug_out) { - m_ldiff = mp_debug_out->insert_layer (db::LayerProperties (100, 0)); - m_lgate = mp_debug_out->insert_layer (db::LayerProperties (101, 0)); - } - } - -private: - db::Layout *mp_debug_out; - unsigned int m_ldiff, m_lgate; - - void device_out (const db::Device *device, const db::Region &diff, const db::Region &gate) - { - if (mp_debug_out) { - mos2layout (layout (), cell_index (), mp_debug_out, device, m_ldiff, diff, m_lgate, gate); - } - } -}; - -class MOSFET4Extractor - : public db::NetlistDeviceExtractorMOS4Transistor -{ -public: - MOSFET4Extractor (const std::string &name, db::Layout *debug_out) - : db::NetlistDeviceExtractorMOS4Transistor (name), mp_debug_out (debug_out), m_ldiff (0), m_lgate (0) - { - if (mp_debug_out) { - m_ldiff = mp_debug_out->insert_layer (db::LayerProperties (100, 0)); - m_lgate = mp_debug_out->insert_layer (db::LayerProperties (101, 0)); - } - } - -private: - db::Layout *mp_debug_out; - unsigned int m_ldiff, m_lgate; - - void device_out (const db::Device *device, const db::Region &diff, const db::Region &gate) - { - if (mp_debug_out) { - mos2layout (layout (), cell_index (), mp_debug_out, device, m_ldiff, diff, m_lgate, gate); - } - } -}; - -} - static void dump_nets_to_layout (const db::LayoutToNetlist &l2n, db::Layout &ly, const std::map &lmap, const db::CellMapping &cmap) { const db::Netlist &nl = *l2n.netlist (); @@ -271,25 +179,8 @@ TEST(1_Basic) 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 (10, 0)); // 10/0 -> Gate - unsigned int lsd = ly.insert_layer (db::LayerProperties (11, 0)); // 11/0 -> Source/Drain - unsigned int lpdiff = ly.insert_layer (db::LayerProperties (12, 0)); // 12/0 -> P Diffusion - unsigned int lndiff = ly.insert_layer (db::LayerProperties (13, 0)); // 13/0 -> N Diffusion - - 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); - - // NOTE: the device extractor will add more debug layers for the transistors: - // 20/0 -> Diffusion - // 21/0 -> Gate - MOSFET3Extractor pmos_ex ("PMOS", &ly); - MOSFET3Extractor nmos_ex ("NMOS", &ly); + db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); + db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); // device extraction @@ -305,6 +196,23 @@ TEST(1_Basic) dl["P"] = rpoly.get (); // not needed for extraction but to return terminal shapes l2n.extract_devices (nmos_ex, dl); + // return the computed layers into the original layout and write it for debugging purposes + // NOTE: this will include the device layers too + + unsigned int lgate = ly.insert_layer (db::LayerProperties (10, 0)); // 10/0 -> Gate + unsigned int lsd = ly.insert_layer (db::LayerProperties (11, 0)); // 11/0 -> Source/Drain + unsigned int lpdiff = ly.insert_layer (db::LayerProperties (12, 0)); // 12/0 -> P Diffusion + unsigned int lndiff = ly.insert_layer (db::LayerProperties (13, 0)); // 13/0 -> N Diffusion + unsigned int lpoly = ly.insert_layer (db::LayerProperties (14, 0)); // 14/0 -> Poly with gate terminal + + 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); + rpoly->insert_into (&ly, tc.cell_index (), lpoly); + // net extraction // Intra-layer @@ -356,7 +264,7 @@ TEST(1_Basic) dump_map [rmetal2.get () ] = ly.insert_layer (db::LayerProperties (208, 0)); // write nets to layout - db::CellMapping cm = l2n.cell_mapping_into (ly, tc); + db::CellMapping cm = l2n.cell_mapping_into (ly, tc, true /*with device cells*/); dump_nets_to_layout (l2n, ly, dump_map, cm); dump_map.clear (); @@ -425,7 +333,7 @@ TEST(1_Basic) ly2.dbu (ly.dbu ()); db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP")); - db::CellMapping cm = l2n.cell_mapping_into (ly2, top2); + db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/); std::map lmap; lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = &rpsd; @@ -437,7 +345,7 @@ TEST(1_Basic) lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get (); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get (); - l2n.build_all_nets (cm, ly2, lmap, 0, 0); + l2n.build_all_nets (cm, ly2, lmap, 0, 0, 0); std::string au = tl::testsrc (); au = tl::combine_path (au, "testdata"); @@ -452,7 +360,7 @@ TEST(1_Basic) ly2.dbu (ly.dbu ()); db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP")); - db::CellMapping cm = l2n.cell_mapping_into (ly2, top2); + db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/); std::map lmap; lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = &rpsd; @@ -464,7 +372,7 @@ TEST(1_Basic) lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get (); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get (); - l2n.build_all_nets (cm, ly2, lmap, "NET_", 0); + l2n.build_all_nets (cm, ly2, lmap, "NET_", 0, 0); std::string au = tl::testsrc (); au = tl::combine_path (au, "testdata"); @@ -479,7 +387,7 @@ TEST(1_Basic) ly2.dbu (ly.dbu ()); db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP")); - db::CellMapping cm = l2n.cell_mapping_into (ly2, top2); + db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/); std::map lmap; lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = &rpsd; @@ -491,7 +399,7 @@ TEST(1_Basic) lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get (); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get (); - l2n.build_all_nets (cm, ly2, lmap, 0, "CIRCUIT_"); + l2n.build_all_nets (cm, ly2, lmap, 0, "CIRCUIT_", 0); std::string au = tl::testsrc (); au = tl::combine_path (au, "testdata"); @@ -506,7 +414,7 @@ TEST(1_Basic) ly2.dbu (ly.dbu ()); db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP")); - db::CellMapping cm = l2n.cell_mapping_into (ly2, top2); + db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/); std::map lmap; lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = &rpsd; @@ -518,7 +426,7 @@ TEST(1_Basic) lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get (); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get (); - l2n.build_all_nets (cm, ly2, lmap, "NET_", "CIRCUIT_"); + l2n.build_all_nets (cm, ly2, lmap, "NET_", "CIRCUIT_", "DEVICE_"); std::string au = tl::testsrc (); au = tl::combine_path (au, "testdata"); @@ -641,11 +549,8 @@ TEST(2_Probing) rpsd.insert_into (&ly, tc.cell_index (), lpdiff); rnsd.insert_into (&ly, tc.cell_index (), lndiff); - // NOTE: the device extractor will add more debug layers for the transistors: - // 20/0 -> Diffusion - // 21/0 -> Gate - MOSFET3Extractor pmos_ex ("PMOS", &ly); - MOSFET3Extractor nmos_ex ("NMOS", &ly); + db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); + db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); // device extraction @@ -895,11 +800,8 @@ TEST(3_GlobalNetConnections) rpsd.insert_into (&ly, tc.cell_index (), lptie); rnsd.insert_into (&ly, tc.cell_index (), lntie); - // NOTE: the device extractor will add more debug layers for the transistors: - // 20/0 -> Diffusion - // 21/0 -> Gate - MOSFET3Extractor pmos_ex ("PMOS", &ly); - MOSFET3Extractor nmos_ex ("NMOS", &ly); + db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); + db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); // device extraction @@ -1166,11 +1068,8 @@ TEST(4_GlobalNetDeviceExtraction) rpsd.insert_into (&ly, tc.cell_index (), lptie); rnsd.insert_into (&ly, tc.cell_index (), lntie); - // NOTE: the device extractor will add more debug layers for the transistors: - // 20/0 -> Diffusion - // 21/0 -> Gate - MOSFET4Extractor pmos_ex ("PMOS", &ly); - MOSFET4Extractor nmos_ex ("NMOS", &ly); + db::NetlistDeviceExtractorMOS4Transistor pmos_ex ("PMOS"); + db::NetlistDeviceExtractorMOS4Transistor nmos_ex ("NMOS"); // device extraction @@ -1442,11 +1341,8 @@ TEST(5_DeviceExtractionWithDeviceCombination) rpsd.insert_into (&ly, tc.cell_index (), lptie); rnsd.insert_into (&ly, tc.cell_index (), lntie); - // NOTE: the device extractor will add more debug layers for the transistors: - // 20/0 -> Diffusion - // 21/0 -> Gate - MOSFET4Extractor pmos_ex ("PMOS", &ly); - MOSFET4Extractor nmos_ex ("NMOS", &ly); + db::NetlistDeviceExtractorMOS4Transistor pmos_ex ("PMOS"); + db::NetlistDeviceExtractorMOS4Transistor nmos_ex ("NMOS"); // device extraction diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index 28219f41b..44d09a4a9 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -34,7 +34,6 @@ #include "dbWriter.h" #include "dbCommonReader.h" #include "dbTestSupport.h" -#include "dbNetlistProperty.h" #include "dbCellMapping.h" #include "tlUnitTest.h" diff --git a/src/db/unit_tests/dbNetlistPropertyTests.cc b/src/db/unit_tests/dbNetlistPropertyTests.cc deleted file mode 100644 index bbac12a0c..000000000 --- a/src/db/unit_tests/dbNetlistPropertyTests.cc +++ /dev/null @@ -1,63 +0,0 @@ - -/* - - KLayout Layout Viewer - Copyright (C) 2006-2019 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 - -*/ - - -#include "dbNetlistProperty.h" - -#include "tlUnitTest.h" -#include "tlVariant.h" - -#include - -TEST(1_TerminalRefBasic) -{ - db::DeviceTerminalProperty dp (42, 17); - EXPECT_EQ (dp.to_string (), "42:17"); - EXPECT_EQ (dp.device_id () == 42, true); - EXPECT_EQ (dp.terminal_id () == 17, true); - - dp.set_terminal_ref (2, 1); - EXPECT_EQ (dp.to_string (), "2:1"); - EXPECT_EQ (dp.device_id () == 2, true); - EXPECT_EQ (dp.terminal_id () == 1, true); - - db::DeviceTerminalProperty dp2 = dp; - EXPECT_EQ (dp2.to_string (), "2:1"); -} - -TEST(2_Variants) -{ - std::auto_ptr dp (new db::DeviceTerminalProperty ()); - dp->set_terminal_ref (42, 17); - - tl::Variant v (dp.release (), db::NetlistProperty::variant_class (), true); - EXPECT_EQ (v.is_user (), true); - EXPECT_EQ (dynamic_cast(v.to_user ()).to_string (), "42:17"); - EXPECT_EQ (v.to_string (), "42:17"); - - tl::Variant vv = v; - v = tl::Variant (); - EXPECT_EQ (v.is_user (), false); - EXPECT_EQ (vv.is_user (), true); - EXPECT_EQ (dynamic_cast(vv.to_user ()).to_string (), "42:17"); -} - diff --git a/src/db/unit_tests/unit_tests.pro b/src/db/unit_tests/unit_tests.pro index d1b455c68..c0701254d 100644 --- a/src/db/unit_tests/unit_tests.pro +++ b/src/db/unit_tests/unit_tests.pro @@ -59,7 +59,6 @@ SOURCES = \ dbDeepRegionTests.cc \ dbDeepShapeStoreTests.cc \ dbHierNetworkProcessorTests.cc \ - dbNetlistPropertyTests.cc \ dbNetlistTests.cc \ dbNetlistExtractorTests.cc \ dbNetlistDeviceExtractorTests.cc \ diff --git a/testdata/algo/deep_region_au4b.gds b/testdata/algo/deep_region_au4b.gds index 8947f5e02..af9145709 100644 Binary files a/testdata/algo/deep_region_au4b.gds and b/testdata/algo/deep_region_au4b.gds differ diff --git a/testdata/algo/device_extract_au1_rebuild_ff.gds b/testdata/algo/device_extract_au1_rebuild_ff.gds index afbbb5092..c6ec960bd 100644 Binary files a/testdata/algo/device_extract_au1_rebuild_ff.gds and b/testdata/algo/device_extract_au1_rebuild_ff.gds differ diff --git a/testdata/algo/device_extract_au1_rebuild_fr.gds b/testdata/algo/device_extract_au1_rebuild_fr.gds index 4673a339e..1f2f6ab76 100644 Binary files a/testdata/algo/device_extract_au1_rebuild_fr.gds and b/testdata/algo/device_extract_au1_rebuild_fr.gds differ diff --git a/testdata/algo/device_extract_au1_rebuild_nf.gds b/testdata/algo/device_extract_au1_rebuild_nf.gds index 56af23394..a684cd03a 100644 Binary files a/testdata/algo/device_extract_au1_rebuild_nf.gds and b/testdata/algo/device_extract_au1_rebuild_nf.gds differ diff --git a/testdata/algo/device_extract_au1_rebuild_nr.gds b/testdata/algo/device_extract_au1_rebuild_nr.gds index 19301649d..0050d5e7d 100644 Binary files a/testdata/algo/device_extract_au1_rebuild_nr.gds and b/testdata/algo/device_extract_au1_rebuild_nr.gds differ diff --git a/testdata/algo/device_extract_au1_with_rec_nets.gds b/testdata/algo/device_extract_au1_with_rec_nets.gds index c61fa0fb5..1bc3662a1 100644 Binary files a/testdata/algo/device_extract_au1_with_rec_nets.gds and b/testdata/algo/device_extract_au1_with_rec_nets.gds differ diff --git a/testdata/algo/device_extract_au2_with_rec_nets.gds b/testdata/algo/device_extract_au2_with_rec_nets.gds index ddd8db94c..228fa0ef1 100644 Binary files a/testdata/algo/device_extract_au2_with_rec_nets.gds and b/testdata/algo/device_extract_au2_with_rec_nets.gds differ diff --git a/testdata/algo/device_extract_au3_with_rec_nets.gds b/testdata/algo/device_extract_au3_with_rec_nets.gds index e9fbf4d08..bb6696cd4 100644 Binary files a/testdata/algo/device_extract_au3_with_rec_nets.gds and b/testdata/algo/device_extract_au3_with_rec_nets.gds differ diff --git a/testdata/algo/device_extract_au4_with_rec_nets.gds b/testdata/algo/device_extract_au4_with_rec_nets.gds index 7f0110515..bd142cbed 100644 Binary files a/testdata/algo/device_extract_au4_with_rec_nets.gds and b/testdata/algo/device_extract_au4_with_rec_nets.gds differ diff --git a/testdata/algo/device_extract_au5_with_rec_nets.gds b/testdata/algo/device_extract_au5_with_rec_nets.gds index 8cdea5c74..dbc1be608 100644 Binary files a/testdata/algo/device_extract_au5_with_rec_nets.gds and b/testdata/algo/device_extract_au5_with_rec_nets.gds differ