mirror of https://github.com/KLayout/klayout.git
WIP: major enhancements with respect to device handling
The device handling in the netlist extractor was now entirely moved to device cells. New options are introduced for exporting these cells. Tests have been updated.
This commit is contained in:
parent
1af81b74d2
commit
5962d66940
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ CellMapping::create_from_names (const db::Layout &layout_a, db::cell_index_type
|
|||
}
|
||||
|
||||
std::vector<db::cell_index_type>
|
||||
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<db::cell_index_type> *exclude_cells)
|
||||
{
|
||||
std::vector<db::cell_index_type> new_cells;
|
||||
std::vector<db::cell_index_type> 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<db::cell_index_type>::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);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
#include "dbTypes.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
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<db::cell_index_type> 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<db::cell_index_type> 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<db::cell_index_type> *exclude_cells = 0);
|
||||
|
||||
private:
|
||||
void extract_unique (std::map <db::cell_index_type, std::vector<db::cell_index_type> >::const_iterator cand,
|
||||
|
|
|
|||
|
|
@ -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<db::cell_index_type> *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;
|
||||
|
|
|
|||
|
|
@ -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<db::cell_index_type> *excluded_cells = 0);
|
||||
|
||||
/**
|
||||
* @brief For testing
|
||||
|
|
|
|||
|
|
@ -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<db::cell_index_type> 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 <class To>
|
||||
static void deliver_shapes_of_net_recursive (const db::hier_clusters<db::PolygonRef> &clusters, const db::Net &net, unsigned int layer_id, To &to)
|
||||
static void deliver_shapes_of_net_recursive (const db::hier_clusters<db::PolygonRef> &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<db::PolygonRef> rci (clusters, layer_id, ci, net.cluster_id ()); !rci.at_end (); ++rci) {
|
||||
// deliver the net shapes
|
||||
for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
|
||||
deliver_shape (*rci, to, rci.trans ());
|
||||
}
|
||||
}
|
||||
|
||||
template <class To>
|
||||
static void deliver_shapes_of_net_nonrecursive (const db::hier_clusters<db::PolygonRef> &clusters, const db::Net &net, unsigned int layer_id, To &to)
|
||||
static void deliver_shapes_of_net_nonrecursive (const db::hier_clusters<db::PolygonRef> &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<db::PolygonRef> &lc = clusters.clusters_per_cell (ci).cluster_by_id (net.cluster_id ());
|
||||
const db::local_cluster<db::PolygonRef> &lc = clusters.clusters_per_cell (ci).cluster_by_id (cid);
|
||||
|
||||
for (db::local_cluster<db::PolygonRef>::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_clusters<db::Poly
|
|||
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const
|
||||
{
|
||||
unsigned int lid = layer_of (of_layer);
|
||||
const db::Circuit *circuit = net.circuit ();
|
||||
tl_assert (circuit != 0);
|
||||
|
||||
if (! recursive) {
|
||||
deliver_shapes_of_net_nonrecursive (m_net_clusters, net, lid, to);
|
||||
deliver_shapes_of_net_nonrecursive (m_net_clusters, circuit->cell_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<db::Region> 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<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const
|
||||
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const
|
||||
{
|
||||
for (std::map<unsigned int, const db::Region *>::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<db::PolygonRef> &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<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const
|
||||
{
|
||||
for (std::map<unsigned int, const db::Region *>::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<db::PolygonRef> &clusters = m_net_clusters.clusters_per_cell (ci);
|
||||
typedef db::connected_clusters<db::PolygonRef>::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<std::pair<db::cell_index_type, size_t>, db::cell_index_type>::const_iterator cm = cmap.find (std::make_pair (ci, c->id ()));
|
||||
std::map<std::pair<db::cell_index_type, size_t>, 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<db::cell_index_type>::max ())).first;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
target_cell.insert (db::CellInstArray (db::CellInst (cm->second), c->inst ().complex_trans ()));
|
||||
if (cm->second != std::numeric_limits<db::cell_index_type>::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<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix) const
|
||||
LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &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<std::pair<db::cell_index_type, size_t>, 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<unsigned int, const db::Region *> &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<unsigned int, const db::Region *> &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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix) const;
|
||||
void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &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<unsigned int, const db::Region *> &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<unsigned int, const db::Region *> &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<db::PolygonRef> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
|
||||
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const;
|
||||
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, 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<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<bool, db::property_names_id_type> 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<db::Device *, geometry_per_terminal_type>::const_iterator d = m_new_devices.begin (); d != m_new_devices.end (); ++d) {
|
||||
for (std::map<size_t, geometry_per_terminal_type>::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<db::DeviceParameterDefinition> &pd = mp_device_class->parameter_definitions ();
|
||||
for (std::vector<db::DeviceParameterDefinition>::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)
|
||||
|
|
|
|||
|
|
@ -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<unsigned int> m_layers;
|
||||
error_list m_errors;
|
||||
std::map<db::Device *, geometry_per_terminal_type> m_new_devices;
|
||||
std::map<size_t, geometry_per_terminal_type> m_new_devices;
|
||||
std::map<DeviceCellKey, db::cell_index_type> m_device_cells;
|
||||
|
||||
// no copying
|
||||
|
|
|
|||
|
|
@ -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<db::cell_index_type, std::map<size_t, size_t> > 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) {
|
||||
|
|
|
|||
|
|
@ -90,11 +90,9 @@ private:
|
|||
std::pair<bool, db::property_names_id_type> m_text_annot_name_id;
|
||||
std::pair<bool, db::property_names_id_type> m_device_annot_name_id;
|
||||
std::pair<bool, db::property_names_id_type> m_terminal_annot_name_id;
|
||||
std::pair<bool, db::property_names_id_type> 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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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 <typeinfo>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
void VariantUserClass<db::NetlistProperty>::destroy (void *p) const
|
||||
{
|
||||
delete (db::NetlistProperty *) p;
|
||||
}
|
||||
|
||||
bool VariantUserClass<db::NetlistProperty>::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<db::NetlistProperty>::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<db::NetlistProperty>::clone (const void *p) const
|
||||
{
|
||||
return ((const db::NetlistProperty *) p)->clone ();
|
||||
}
|
||||
|
||||
std::string VariantUserClass<db::NetlistProperty>::to_string (const void *p) const
|
||||
{
|
||||
return ((const db::NetlistProperty *) p)->to_string ();
|
||||
}
|
||||
|
||||
void VariantUserClass<db::NetlistProperty>::read (void * /*p*/, tl::Extractor & /*ex*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
return;
|
||||
}
|
||||
|
||||
void VariantUserClass<db::NetlistProperty>::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<db::NetlistProperty>::deref_proxy (tl::Object *proxy) const
|
||||
{
|
||||
return proxy;
|
||||
}
|
||||
|
||||
void VariantUserClass<db::NetlistProperty>::register_instance (const tl::VariantUserClassBase *inst, bool is_const)
|
||||
{
|
||||
VariantUserClassBase::register_instance (inst, typeid (db::NetlistProperty), is_const);
|
||||
}
|
||||
|
||||
void VariantUserClass<db::NetlistProperty>::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<db::NetlistProperty> *NetlistProperty::variant_class ()
|
||||
{
|
||||
static tl::VariantUserClass<db::NetlistProperty> 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<const DeviceTerminalProperty *> (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<const DeviceTerminalProperty *> (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<const DeviceTerminalProperty *> (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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 <string>
|
||||
|
||||
namespace db
|
||||
{
|
||||
class NetlistProperty;
|
||||
}
|
||||
|
||||
namespace tl
|
||||
{
|
||||
class Extractor;
|
||||
|
||||
// specialization of tl::VariantUserClass for the purpose of NetlistProperty representation
|
||||
template <> class DB_PUBLIC VariantUserClass<db::NetlistProperty>
|
||||
: 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<db::NetlistProperty *> (ptr); }
|
||||
const db::NetlistProperty *get (const void *ptr) const { return reinterpret_cast<const db::NetlistProperty *> (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<db::NetlistProperty> *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
|
||||
|
|
@ -43,17 +43,19 @@ static db::Cell *l2n_internal_top_cell (db::LayoutToNetlist *l2n)
|
|||
return const_cast<db::Cell *> (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<unsigned int, const db::Region *> &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<unsigned int, const db::Region *> &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<unsigned int, const db::Region *> &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<unsigned int, const db::Region *> &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<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
||||
|
|
@ -150,9 +152,11 @@ Class<db::LayoutToNetlist> 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<db::LayoutToNetlist> 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<db::LayoutToNetlist> 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<db::LayoutToNetlist> 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"
|
||||
|
|
|
|||
|
|
@ -37,103 +37,11 @@
|
|||
#include <memory>
|
||||
#include <limits>
|
||||
|
||||
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<bool, db::cell_index_type> 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<db::DeviceParameterDefinition> &pd = device->device_class ()->parameter_definitions ();
|
||||
for (std::vector<db::DeviceParameterDefinition>::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<const db::Region *, unsigned int> &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<unsigned int, const db::Region *> 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<unsigned int, const db::Region *> 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<unsigned int, const db::Region *> 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<unsigned int, const db::Region *> 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
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include "dbWriter.h"
|
||||
#include "dbCommonReader.h"
|
||||
#include "dbTestSupport.h"
|
||||
#include "dbNetlistProperty.h"
|
||||
#include "dbCellMapping.h"
|
||||
|
||||
#include "tlUnitTest.h"
|
||||
|
|
|
|||
|
|
@ -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 <memory>
|
||||
|
||||
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<db::DeviceTerminalProperty> 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<db::NetlistProperty> (), true);
|
||||
EXPECT_EQ (dynamic_cast<db::DeviceTerminalProperty &>(v.to_user<db::NetlistProperty> ()).to_string (), "42:17");
|
||||
EXPECT_EQ (v.to_string (), "42:17");
|
||||
|
||||
tl::Variant vv = v;
|
||||
v = tl::Variant ();
|
||||
EXPECT_EQ (v.is_user<db::NetlistProperty> (), false);
|
||||
EXPECT_EQ (vv.is_user<db::NetlistProperty> (), true);
|
||||
EXPECT_EQ (dynamic_cast<db::DeviceTerminalProperty &>(vv.to_user<db::NetlistProperty> ()).to_string (), "42:17");
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,6 @@ SOURCES = \
|
|||
dbDeepRegionTests.cc \
|
||||
dbDeepShapeStoreTests.cc \
|
||||
dbHierNetworkProcessorTests.cc \
|
||||
dbNetlistPropertyTests.cc \
|
||||
dbNetlistTests.cc \
|
||||
dbNetlistExtractorTests.cc \
|
||||
dbNetlistDeviceExtractorTests.cc \
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue