mirror of https://github.com/KLayout/klayout.git
GSI binding of RNetExtractor, introducing layers for nodes
This commit is contained in:
parent
fc25590dd7
commit
77aa729b06
|
|
@ -30,379 +30,6 @@
|
|||
namespace gsi
|
||||
{
|
||||
|
||||
class RNode
|
||||
{
|
||||
public:
|
||||
~RNode () { }
|
||||
|
||||
pex::RNode::node_type type () const { return checked_pointer ()->type; }
|
||||
db::DBox location () const { return checked_pointer ()->location; }
|
||||
unsigned int port_index () const { return checked_pointer ()->port_index; }
|
||||
std::string to_string (bool with_coords = false) const { return checked_pointer ()->to_string (with_coords); }
|
||||
|
||||
size_t obj_id () const
|
||||
{
|
||||
return size_t (mp_ptr);
|
||||
}
|
||||
|
||||
static RNode *make_node_object (const pex::RNode *node)
|
||||
{
|
||||
return new RNode (node);
|
||||
}
|
||||
|
||||
const pex::RNode *checked_pointer () const
|
||||
{
|
||||
if (! mp_graph.get ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Network graph has been destroyed - RNode object no longer is valid")));
|
||||
}
|
||||
return mp_ptr;
|
||||
}
|
||||
|
||||
pex::RNode *checked_pointer ()
|
||||
{
|
||||
if (! mp_graph.get ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Network graph has been destroyed - RNode object no longer is valid")));
|
||||
}
|
||||
return const_cast<pex::RNode *> (mp_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
tl::weak_ptr<pex::RNetwork> mp_graph;
|
||||
const pex::RNode *mp_ptr;
|
||||
|
||||
RNode (const pex::RNode *node)
|
||||
: mp_graph (node->graph ()),
|
||||
mp_ptr (node)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
};
|
||||
|
||||
class RElement
|
||||
{
|
||||
public:
|
||||
~RElement () { }
|
||||
|
||||
double conductance () const { return checked_pointer ()->conductance; }
|
||||
double resistance () const { return checked_pointer ()->resistance (); }
|
||||
|
||||
RNode *a () const { return RNode::make_node_object (checked_pointer ()->a ()); }
|
||||
RNode *b () const { return RNode::make_node_object (checked_pointer ()->b ()); }
|
||||
|
||||
std::string to_string (bool with_coords = false) const { return checked_pointer ()->to_string (with_coords); }
|
||||
|
||||
size_t obj_id () const
|
||||
{
|
||||
return size_t (mp_ptr);
|
||||
}
|
||||
|
||||
static RElement *make_element_object (const pex::RElement *element)
|
||||
{
|
||||
return new RElement (element);
|
||||
}
|
||||
|
||||
const pex::RElement *checked_pointer () const
|
||||
{
|
||||
if (! mp_graph.get ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Network graph has been destroyed - RElement object no longer is valid")));
|
||||
}
|
||||
return mp_ptr;
|
||||
}
|
||||
|
||||
pex::RElement *checked_pointer ()
|
||||
{
|
||||
if (! mp_graph.get ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Network graph has been destroyed - RElement object no longer is valid")));
|
||||
}
|
||||
return const_cast<pex::RElement *> (mp_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
tl::weak_ptr<pex::RNetwork> mp_graph;
|
||||
const pex::RElement *mp_ptr;
|
||||
|
||||
RElement (const pex::RElement *node)
|
||||
: mp_graph (node->graph ()),
|
||||
mp_ptr (node)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
};
|
||||
|
||||
class RElementIterator
|
||||
{
|
||||
public:
|
||||
typedef std::list<const pex::RElement *>::const_iterator basic_iter;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef RElement *value_type;
|
||||
typedef RElement *reference;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
RElementIterator (basic_iter it)
|
||||
: m_it (it)
|
||||
{ }
|
||||
|
||||
bool operator== (const RElementIterator &it) const { return m_it == it.m_it; }
|
||||
void operator++ () { ++m_it; }
|
||||
|
||||
RElement *operator* () const
|
||||
{
|
||||
return RElement::make_element_object (*m_it);
|
||||
}
|
||||
|
||||
private:
|
||||
basic_iter m_it;
|
||||
};
|
||||
|
||||
static RElementIterator begin_node_elements (RNode *node)
|
||||
{
|
||||
return RElementIterator (node->checked_pointer ()->elements ().begin ());
|
||||
}
|
||||
|
||||
static RElementIterator end_network_elements (RNode *node)
|
||||
{
|
||||
return RElementIterator (node->checked_pointer ()->elements ().end ());
|
||||
}
|
||||
|
||||
gsi::Enum<pex::RNode::node_type> decl_NodeType ("pex", "RNodeType",
|
||||
gsi::enum_const ("Internal", pex::RNode::Internal,
|
||||
"@brief Specifies an internal node in a R network\n"
|
||||
"Internal nodes are generated during the R extraction process. "
|
||||
"The port index of such a node is an arbitrary index."
|
||||
) +
|
||||
gsi::enum_const ("VertexPort", pex::RNode::VertexPort,
|
||||
"@brief Specifies a vertex port node in a R network\n"
|
||||
"Vertex port nodes are generated for vertex ports in \\RExtractor#extract, see 'vertex_ports' argument. "
|
||||
"The port index of such a node refers to the position in that list."
|
||||
) +
|
||||
gsi::enum_const ("PolygonPort", pex::RNode::PolygonPort,
|
||||
"@brief Specifies a polygon port node in a R network\n"
|
||||
"Polygon port nodes are generated for polygon ports in \\RExtractor#extract, see 'polygon_ports' argument. "
|
||||
"The port index of such a node refers to the position in that list."
|
||||
),
|
||||
"@brief This class represents the node type for RNode.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.1"
|
||||
);
|
||||
|
||||
Class<RNode> decl_RNode ("pex", "RNode",
|
||||
gsi::method ("object_id", &RNode::obj_id,
|
||||
"@brief Returns an ID representing the actual object\n"
|
||||
"For every call, a new instance of this object is created, while multiple "
|
||||
"ones may represent the same internal object. The 'object_id' is a ID that "
|
||||
"indicates the internal object. Same object_id means same node."
|
||||
) +
|
||||
gsi::method ("to_s", &RNode::to_string, gsi::arg ("with_coords", false),
|
||||
"@brief Returns a string representation of this object\n"
|
||||
"Nodes are printed with coordinates with 'with_coords' is true."
|
||||
) +
|
||||
gsi::iterator_ext ("each_element", gsi::return_new_object (), &begin_node_elements, &end_network_elements,
|
||||
"@brief Iterates the \\RElement objects attached to the node\n"
|
||||
) +
|
||||
gsi::method ("type", &RNode::type,
|
||||
"@brief Gets the type attribute of the node\n"
|
||||
) +
|
||||
gsi::method ("location", &RNode::location,
|
||||
"@brief Gets the location attribute of the node\n"
|
||||
"The location defined the original position of the node"
|
||||
) +
|
||||
gsi::method ("port_index", &RNode::port_index,
|
||||
"@brief Gets the port index of the node\n"
|
||||
"The port index associates a node with a original port definition."
|
||||
),
|
||||
"@brief Represents a node in a R network graph\n"
|
||||
"See \\RNetwork for a description of this object\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.1"
|
||||
);
|
||||
|
||||
// Inject the RNode::node_type declarations into RNode
|
||||
gsi::ClassExt<RNode> inject_NodeType_in_RNode (decl_NodeType.defs ());
|
||||
|
||||
Class<RElement> decl_RElement ("pex", "RElement",
|
||||
gsi::method ("object_id", &RElement::obj_id,
|
||||
"@brief Returns an ID representing the actual object\n"
|
||||
"For every call, a new instance of this object is created, while multiple "
|
||||
"ones may represent the same internal object. The 'object_id' is a ID that "
|
||||
"indicates the internal object. Same object_id means same element."
|
||||
) +
|
||||
gsi::method ("to_s", &RElement::to_string, gsi::arg ("with_coords", false),
|
||||
"@brief Returns a string representation of this object\n"
|
||||
"Nodes are printed with coordinates with 'with_coords' is true."
|
||||
) +
|
||||
gsi::method ("resistance", &RElement::resistance,
|
||||
"@brief Gets the resistance value of the object\n"
|
||||
) +
|
||||
gsi::factory ("a", &RElement::a,
|
||||
"@brief Gets the first node the element connects\n"
|
||||
) +
|
||||
gsi::factory ("b", &RElement::b,
|
||||
"@brief Gets the second node the element connects\n"
|
||||
),
|
||||
"@brief Represents an edge (also called element) in a R network graph\n"
|
||||
"See \\RNetwork for a description of this object"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.1"
|
||||
);
|
||||
|
||||
static RNode *create_node (pex::RNetwork *network, pex::RNode::node_type type, unsigned int port_index)
|
||||
{
|
||||
return RNode::make_node_object (network->create_node (type, port_index));
|
||||
}
|
||||
|
||||
static RElement *create_element (pex::RNetwork *network, double r, RNode *a, RNode *b)
|
||||
{
|
||||
double s = fabs (r) < 1e-10 ? pex::RElement::short_value () : 1.0 / r;
|
||||
return RElement::make_element_object (network->create_element (s, a->checked_pointer (), b->checked_pointer ()));
|
||||
}
|
||||
|
||||
static void remove_element (pex::RNetwork *network, RElement *element)
|
||||
{
|
||||
network->remove_element (element->checked_pointer ());
|
||||
}
|
||||
|
||||
static void remove_node (pex::RNetwork *network, RNode *node)
|
||||
{
|
||||
network->remove_node (node->checked_pointer ());
|
||||
}
|
||||
|
||||
class NetworkElementIterator
|
||||
{
|
||||
public:
|
||||
typedef pex::RNetwork::element_iterator basic_iter;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef RElement *value_type;
|
||||
typedef RElement *reference;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
NetworkElementIterator (basic_iter it)
|
||||
: m_it (it)
|
||||
{ }
|
||||
|
||||
bool operator== (const NetworkElementIterator &it) const { return m_it == it.m_it; }
|
||||
void operator++ () { ++m_it; }
|
||||
|
||||
RElement *operator* () const
|
||||
{
|
||||
return RElement::make_element_object (m_it.operator-> ());
|
||||
}
|
||||
|
||||
private:
|
||||
basic_iter m_it;
|
||||
};
|
||||
|
||||
static NetworkElementIterator begin_network_elements (pex::RNetwork *network)
|
||||
{
|
||||
return NetworkElementIterator (network->begin_elements ());
|
||||
}
|
||||
|
||||
static NetworkElementIterator end_network_elements (pex::RNetwork *network)
|
||||
{
|
||||
return NetworkElementIterator (network->end_elements ());
|
||||
}
|
||||
|
||||
class NetworkNodeIterator
|
||||
{
|
||||
public:
|
||||
typedef pex::RNetwork::node_iterator basic_iter;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef RNode *value_type;
|
||||
typedef RNode *reference;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
NetworkNodeIterator (basic_iter it)
|
||||
: m_it (it)
|
||||
{ }
|
||||
|
||||
bool operator== (const NetworkNodeIterator &it) const { return m_it == it.m_it; }
|
||||
void operator++ () { ++m_it; }
|
||||
|
||||
RNode *operator* () const
|
||||
{
|
||||
return RNode::make_node_object (m_it.operator-> ());
|
||||
}
|
||||
|
||||
private:
|
||||
basic_iter m_it;
|
||||
};
|
||||
|
||||
static NetworkNodeIterator begin_network_nodes (pex::RNetwork *network)
|
||||
{
|
||||
return NetworkNodeIterator (network->begin_nodes ());
|
||||
}
|
||||
|
||||
static NetworkNodeIterator end_network_nodes (pex::RNetwork *network)
|
||||
{
|
||||
return NetworkNodeIterator (network->end_nodes ());
|
||||
}
|
||||
|
||||
Class<pex::RNetwork> decl_RNetwork ("pex", "RNetwork",
|
||||
gsi::factory_ext ("create_node", &create_node, gsi::arg ("type"), gsi::arg ("port_index"),
|
||||
"@brief Creates a new node with the given type and index'.\n"
|
||||
"@return A reference to the new nbode object."
|
||||
) +
|
||||
gsi::factory_ext ("create_element", &create_element, gsi::arg ("resistance"), gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief Creates a new element between the nodes given by 'a' abd 'b'.\n"
|
||||
"If a resistor already exists between the two nodes, both resistors are combined into one.\n"
|
||||
"@return A reference to the new resistor object."
|
||||
) +
|
||||
gsi::method_ext ("remove_element", &remove_element, gsi::arg ("element"),
|
||||
"@brief Removes the given element\n"
|
||||
"If removing the element renders an internal node orphan (i.e. without elements), this "
|
||||
"node is removed too."
|
||||
) +
|
||||
gsi::method_ext ("remove_node", &remove_node, gsi::arg ("node"),
|
||||
"@brief Removes the given node\n"
|
||||
"Only internal nodes can be removed. Removing a node will also remove the "
|
||||
"elements attached to this node."
|
||||
) +
|
||||
gsi::method ("clear", &pex::RNetwork::clear,
|
||||
"@brief Clears the network\n"
|
||||
) +
|
||||
gsi::method ("simplify", &pex::RNetwork::simplify,
|
||||
"@brief Simplifies the network\n"
|
||||
"\n"
|
||||
"This will:\n"
|
||||
"@ul\n"
|
||||
"@li Join serial resistors if connected by an internal node @/li\n"
|
||||
"@li Remove shorts and join the nodes, if one of them is\n"
|
||||
" an internal node. The non-internal node will persist @/li\n"
|
||||
"@li Remove \"dangling\" resistors if the dangling node is\n"
|
||||
" an internal one @/li\n"
|
||||
"@/ul\n"
|
||||
) +
|
||||
gsi::iterator_ext ("each_element", gsi::return_new_object (), &begin_network_elements, &end_network_elements,
|
||||
"@brief Iterates the \\RElement objects inside the network\n"
|
||||
) +
|
||||
gsi::iterator_ext ("each_node", gsi::return_new_object (), &begin_network_nodes, &end_network_nodes,
|
||||
"@brief Iterates the \\RNode objects inside the network\n"
|
||||
) +
|
||||
gsi::method ("num_nodes", &pex::RNetwork::num_nodes,
|
||||
"@brief Gets the total number of nodes in the network\n"
|
||||
) +
|
||||
gsi::method ("num_internal_nodes", &pex::RNetwork::num_internal_nodes,
|
||||
"@brief Gets the number of internal nodes in the network\n"
|
||||
) +
|
||||
gsi::method ("num_elements", &pex::RNetwork::num_elements,
|
||||
"@brief Gets the number of elements in the network\n"
|
||||
) +
|
||||
gsi::method ("to_s", &pex::RNetwork::to_string, gsi::arg ("with_coords", false),
|
||||
"@brief Returns a string representation of the network\n"
|
||||
"Nodes are printed with coordinates with 'with_coords' is true."
|
||||
),
|
||||
"@brief Represents a network of resistors\n"
|
||||
"\n"
|
||||
"The network is basically a graph with nodes and edges (the resistors). "
|
||||
"The resistors are called 'elements' and are represented by \\RElement objects. "
|
||||
"The nodes are represented by \\RNode objects. "
|
||||
"The network is created by \\RExtractor#extract, which turns a polygon into a resistor network.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.1\n"
|
||||
);
|
||||
|
||||
static pex::RExtractor *new_sqc_rextractor (double dbu, bool skip_simplify)
|
||||
{
|
||||
auto res = new pex::SquareCountingRExtractor (dbu);
|
||||
|
|
@ -490,7 +117,7 @@ Class<pex::RExtractor> decl_RExtractor ("pex", "RExtractor",
|
|||
"Use \\tesselation_extractor and \\square_counting_extractor to create an actual extractor object.\n"
|
||||
"To use the extractor, call the \\extract method on a given polygon with ports that define the network attachment points.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.1\n"
|
||||
"This class has been introduced in version 0.30.2\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,393 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2025 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 "gsiDecl.h"
|
||||
#include "pexRExtractorTech.h"
|
||||
#include "pexRNetExtractor.h"
|
||||
#include "pexRNetwork.h"
|
||||
#include "gsiEnums.h"
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
static unsigned int via_get_bottom_conductor (const pex::RExtractorTechVia *via)
|
||||
{
|
||||
return via->bottom_conductor;
|
||||
}
|
||||
|
||||
static void via_set_bottom_conductor (pex::RExtractorTechVia *via, unsigned int l)
|
||||
{
|
||||
via->bottom_conductor = l;
|
||||
}
|
||||
|
||||
static unsigned int via_get_cut_layer (const pex::RExtractorTechVia *via)
|
||||
{
|
||||
return via->cut_layer;
|
||||
}
|
||||
|
||||
static void via_set_cut_layer (pex::RExtractorTechVia *via, unsigned int l)
|
||||
{
|
||||
via->cut_layer = l;
|
||||
}
|
||||
|
||||
static unsigned int via_get_top_conductor (const pex::RExtractorTechVia *via)
|
||||
{
|
||||
return via->top_conductor;
|
||||
}
|
||||
|
||||
static void via_set_top_conductor (pex::RExtractorTechVia *via, unsigned int l)
|
||||
{
|
||||
via->top_conductor = l;
|
||||
}
|
||||
|
||||
static double via_get_resistance (const pex::RExtractorTechVia *via)
|
||||
{
|
||||
return via->resistance;
|
||||
}
|
||||
|
||||
static void via_set_resistance (pex::RExtractorTechVia *via, double r)
|
||||
{
|
||||
via->resistance = r;
|
||||
}
|
||||
|
||||
static double via_get_merge_distance (const pex::RExtractorTechVia *via)
|
||||
{
|
||||
return via->merge_distance;
|
||||
}
|
||||
|
||||
static void via_set_merge_distance (pex::RExtractorTechVia *via, double dist)
|
||||
{
|
||||
via->merge_distance = dist;
|
||||
}
|
||||
|
||||
Class<pex::RExtractorTechVia> decl_RExtractorTechVia ("pex", "RExtractorTechVia",
|
||||
gsi::method_ext ("merge_distance", &via_get_merge_distance,
|
||||
"@brief Gets the merge distance\n"
|
||||
"If this value is not zero, it specifies the distance below (or equal) which "
|
||||
"vias are merged into bigger blocks. This is an optimization to reduce the "
|
||||
"complexity of the via extraction. The value is given in micrometers."
|
||||
) +
|
||||
gsi::method_ext ("merge_distance=", &via_set_merge_distance, gsi::arg ("d"),
|
||||
"@brief Sets the merge distance\n"
|
||||
"See \\merge_distance for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("resistance", &via_get_resistance,
|
||||
"@brief Gets the area resistance value of the vias\n"
|
||||
"This value specifies the via resistance in Ohm * square micrometers. "
|
||||
"The actual resistance is obtained by dividing this value by the via area."
|
||||
) +
|
||||
gsi::method_ext ("resistance=", &via_set_resistance, gsi::arg ("d"),
|
||||
"@brief Sets the via area resistance value\n"
|
||||
"See \\resistance for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("bottom_conductor", &via_get_bottom_conductor,
|
||||
"@brief Gets the bottom conductor layer index\n"
|
||||
"The layer index is a generic identifier for the layer. It is the value used as key in the "
|
||||
"geometry and port arguments of \\RNetExtractor#extract."
|
||||
) +
|
||||
gsi::method_ext ("bottom_conductor=", &via_set_bottom_conductor, gsi::arg ("l"),
|
||||
"@brief Sets the via bottom conductor layer index\n"
|
||||
"See \\bottom_conductor for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("cut_layer", &via_get_cut_layer,
|
||||
"@brief Gets the cut layer index\n"
|
||||
"The layer index is a generic identifier for the layer. It is the value used as key in the "
|
||||
"geometry and port arguments of \\RNetExtractor#extract. "
|
||||
"The cut layer is the layer where the via exists."
|
||||
) +
|
||||
gsi::method_ext ("cut_layer=", &via_set_cut_layer, gsi::arg ("l"),
|
||||
"@brief Sets the cut layer index\n"
|
||||
"See \\cut_layer for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("top_conductor", &via_get_top_conductor,
|
||||
"@brief Gets the top conductor layer index\n"
|
||||
"The layer index is a generic identifier for the layer. It is the value used as key in the "
|
||||
"geometry and port arguments of \\RNetExtractor#extract."
|
||||
) +
|
||||
gsi::method_ext ("top_conductor=", &via_set_top_conductor, gsi::arg ("l"),
|
||||
"@brief Sets the via top conductor layer index\n"
|
||||
"See \\top_conductor for a description of this attribute."
|
||||
),
|
||||
"@brief Describes a via for the network extraction.\n"
|
||||
"This class is used to describe a via type in the context of "
|
||||
"the \\RExtractorTech#extract method.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.2."
|
||||
);
|
||||
|
||||
static pex::RExtractorTechConductor::Algorithm cond_get_algorithm (const pex::RExtractorTechConductor *cond)
|
||||
{
|
||||
return cond->algorithm;
|
||||
}
|
||||
|
||||
static void cond_set_algorithm (pex::RExtractorTechConductor *cond, pex::RExtractorTechConductor::Algorithm a)
|
||||
{
|
||||
cond->algorithm = a;
|
||||
}
|
||||
|
||||
static unsigned int cond_get_layer (const pex::RExtractorTechConductor *cond)
|
||||
{
|
||||
return cond->layer;
|
||||
}
|
||||
|
||||
static void cond_set_layer (pex::RExtractorTechConductor *cond, unsigned int l)
|
||||
{
|
||||
cond->layer = l;
|
||||
}
|
||||
|
||||
static double cond_get_resistance (const pex::RExtractorTechConductor *cond)
|
||||
{
|
||||
return cond->resistance;
|
||||
}
|
||||
|
||||
static void cond_set_resistance (pex::RExtractorTechConductor *cond, double r)
|
||||
{
|
||||
cond->resistance = r;
|
||||
}
|
||||
|
||||
static double cond_get_triangulation_min_b (const pex::RExtractorTechConductor *cond)
|
||||
{
|
||||
return cond->triangulation_min_b;
|
||||
}
|
||||
|
||||
static void cond_set_triangulation_min_b (pex::RExtractorTechConductor *cond, double min_b)
|
||||
{
|
||||
cond->triangulation_min_b = min_b;
|
||||
}
|
||||
|
||||
static double cond_get_triangulation_max_area (const pex::RExtractorTechConductor *cond)
|
||||
{
|
||||
return cond->triangulation_max_area;
|
||||
}
|
||||
|
||||
static void cond_set_triangulation_max_area (pex::RExtractorTechConductor *cond, double max_area)
|
||||
{
|
||||
cond->triangulation_max_area = max_area;
|
||||
}
|
||||
|
||||
Class<pex::RExtractorTechConductor> decl_RExtractorTechConductor ("pex", "RExtractorTechConductor",
|
||||
gsi::method_ext ("algorithm", &cond_get_algorithm,
|
||||
"@brief Gets the algorithm to use\n"
|
||||
"Specifies the algorithm to use. The default algorithm is 'SquareCounting'."
|
||||
) +
|
||||
gsi::method_ext ("algorithm=", &cond_set_algorithm, gsi::arg ("d"),
|
||||
"@brief Sets the algorithm to use\n"
|
||||
"See \\algorithm for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("resistance", &cond_get_resistance,
|
||||
"@brief Gets the sheet resistance value of the conductor layer\n"
|
||||
"This value specifies the cond resistance in Ohm per square. "
|
||||
"The actual resistance is obtained by multiplying this value with the number of squares."
|
||||
) +
|
||||
gsi::method_ext ("resistance=", &cond_set_resistance, gsi::arg ("r"),
|
||||
"@brief Sets the sheet resistance value of the conductor layer\n"
|
||||
"See \\resistance for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("layer", &cond_get_layer,
|
||||
"@brief Gets the layer index\n"
|
||||
"The layer index is a generic identifier for the layer. It is the value used as key in the "
|
||||
"geometry and port arguments of \\RNetExtractor#extract. "
|
||||
"This attribute specifies the layer the conductor is on."
|
||||
) +
|
||||
gsi::method_ext ("layer=", &cond_set_layer, gsi::arg ("l"),
|
||||
"@brief Sets the layer index\n"
|
||||
"See \\layer for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("triangulation_min_b", &cond_get_triangulation_min_b,
|
||||
"@brief Gets the triangulation 'min_b' parameter\n"
|
||||
"This parameter is used for the 'Tesselation' algorithm and specifies the shortest edge to circle radius ratio of "
|
||||
"the Delaunay triangulation. "
|
||||
) +
|
||||
gsi::method_ext ("triangulation_min_b=", &cond_set_triangulation_min_b, gsi::arg ("min_b"),
|
||||
"@brief Sets the triangulation 'min_b' parameter\n"
|
||||
"See \\triangulation_min_b for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("triangulation_max_area", &cond_get_triangulation_max_area,
|
||||
"@brief Gets the triangulation 'max_area' parameter\n"
|
||||
"This parameter is used for the 'Tesselation' algorithm and specifies the maximum area of "
|
||||
"the triangles in square micrometers."
|
||||
) +
|
||||
gsi::method_ext ("triangulation_max_area=", &cond_set_triangulation_max_area, gsi::arg ("max_area"),
|
||||
"@brief Sets the triangulation 'max_area' parameter\n"
|
||||
"See \\triangulation_max_area for a description of this attribute."
|
||||
),
|
||||
"@brief Describes a conductor layer for the network extraction.\n"
|
||||
"This class is used to describe a conductor layer in the context of "
|
||||
"the \\RExtractorTech#extract method.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.2."
|
||||
);
|
||||
|
||||
gsi::Enum<pex::RExtractorTechConductor::Algorithm> decl_RExtractorTechConductor_Algorithm ("pex", "Algorithm",
|
||||
gsi::enum_const ("SquareCounting", pex::RExtractorTechConductor::SquareCounting,
|
||||
"@brief Specifies the square counting algorithm for \\RExtractorTechConductor#algorithm.\n"
|
||||
"See \\RExtractor#square_counting_extractor for more details."
|
||||
) +
|
||||
gsi::enum_const ("Tesselation", pex::RExtractorTechConductor::Tesselation,
|
||||
"@brief Specifies the square counting algorithm for \\RExtractorTechConductor#algorithm.\n"
|
||||
"See \\RExtractor#tesselation_extractor for more details."
|
||||
),
|
||||
"@brief This enum represents the extraction algorithm for \\RExtractorTechConductor.\n"
|
||||
"\n"
|
||||
"This enum has been introduced in version 0.30.2."
|
||||
);
|
||||
|
||||
gsi::ClassExt<pex::RExtractorTechConductor> inject_RExtractorTechConductor_in_parent (decl_RExtractorTechConductor_Algorithm.defs ());
|
||||
|
||||
static bool tech_get_skip_simplify (const pex::RExtractorTech *tech)
|
||||
{
|
||||
return tech->skip_simplify;
|
||||
}
|
||||
|
||||
static void tech_set_skip_simplify (pex::RExtractorTech *tech, bool f)
|
||||
{
|
||||
tech->skip_simplify = f;
|
||||
}
|
||||
|
||||
static auto tech_begin_vias (const pex::RExtractorTech *tech)
|
||||
{
|
||||
return tech->vias.begin ();
|
||||
}
|
||||
|
||||
static auto tech_end_vias (const pex::RExtractorTech *tech)
|
||||
{
|
||||
return tech->vias.end ();
|
||||
}
|
||||
|
||||
static void tech_clear_vias (pex::RExtractorTech *tech)
|
||||
{
|
||||
tech->vias.clear ();
|
||||
}
|
||||
|
||||
static void tech_add_via (pex::RExtractorTech *tech, const pex::RExtractorTechVia &via)
|
||||
{
|
||||
tech->vias.push_back (via);
|
||||
}
|
||||
|
||||
static auto tech_begin_conductors (const pex::RExtractorTech *tech)
|
||||
{
|
||||
return tech->conductors.begin ();
|
||||
}
|
||||
|
||||
static auto tech_end_conductors (const pex::RExtractorTech *tech)
|
||||
{
|
||||
return tech->conductors.end ();
|
||||
}
|
||||
|
||||
static void tech_clear_conductors (pex::RExtractorTech *tech)
|
||||
{
|
||||
tech->conductors.clear ();
|
||||
}
|
||||
|
||||
static void tech_add_conductor (pex::RExtractorTech *tech, const pex::RExtractorTechConductor &conductor)
|
||||
{
|
||||
tech->conductors.push_back (conductor);
|
||||
}
|
||||
|
||||
Class<pex::RExtractorTech> decl_RExtractorTech ("pex", "RExtractorTech",
|
||||
gsi::method_ext ("skip_simplify", &tech_get_skip_simplify,
|
||||
"@brief Gets a value indicating whether to skip the simplify step\n"
|
||||
"This values specifies to skip the simplify step of the network after the extraction has "
|
||||
"been done. By default, the network is simplified - i.e. serial resistors are joined etc. "
|
||||
"By setting this attribute to 'false', this step is skipped."
|
||||
) +
|
||||
gsi::method_ext ("skip_simplify=", &tech_set_skip_simplify, gsi::arg ("f"),
|
||||
"@brief Sets a value indicating whether to skip the simplify step\n"
|
||||
"See \\skip_simplify for a description of this attribute."
|
||||
) +
|
||||
gsi::method_ext ("each_via", &tech_begin_vias, &tech_end_vias,
|
||||
"@brief Iterates the list of via definitions\n"
|
||||
) +
|
||||
gsi::method_ext ("clear_vias", &tech_clear_vias,
|
||||
"@brief Clears the list of via definitions\n"
|
||||
) +
|
||||
gsi::method_ext ("add_via", &tech_add_via, gsi::arg ("via"),
|
||||
"@brief Adds the given via definition to the list of vias\n"
|
||||
) +
|
||||
gsi::method_ext ("each_conductor", &tech_begin_conductors, &tech_end_conductors,
|
||||
"@brief Iterates the list of conductor definitions\n"
|
||||
) +
|
||||
gsi::method_ext ("clear_conductors", &tech_clear_conductors,
|
||||
"@brief Clears the list of conductor definitions\n"
|
||||
) +
|
||||
gsi::method_ext ("add_conductor", &tech_add_conductor, gsi::arg ("conductor"),
|
||||
"@brief Adds the given conductor definition to the list of conductors\n"
|
||||
),
|
||||
"@brief Specifies the tech stack for the R extraction.\n"
|
||||
"The tech stack is a collection of via and conductor definitions and some other attributes. "
|
||||
"It is used for the \\RNetExtractor#extract method.\n"
|
||||
"\n"
|
||||
"This enum has been introduced in version 0.30.2."
|
||||
);
|
||||
|
||||
static pex::RNetExtractor *new_net_rextractor (double dbu)
|
||||
{
|
||||
return new pex::RNetExtractor (dbu);
|
||||
}
|
||||
|
||||
static pex::RNetwork *rex_extract (pex::RNetExtractor *rex,
|
||||
const pex::RExtractorTech *tech,
|
||||
const std::map<unsigned int, db::Region> *geo,
|
||||
const std::map<unsigned int, std::vector<db::Point> > *vertex_ports,
|
||||
const std::map<unsigned int, std::vector<db::Polygon> > *polygon_ports)
|
||||
{
|
||||
std::unique_ptr<pex::RNetwork> network (new pex::RNetwork ());
|
||||
std::map<unsigned int, db::Region> empty_geo;
|
||||
std::map<unsigned int, std::vector<db::Point> > empty_vertex_ports;
|
||||
std::map<unsigned int, std::vector<db::Polygon> > empty_polygon_ports;
|
||||
rex->extract (*tech, geo ? *geo : empty_geo, vertex_ports ? *vertex_ports : empty_vertex_ports, polygon_ports ? *polygon_ports : empty_polygon_ports, *network);
|
||||
return network.release ();
|
||||
}
|
||||
|
||||
Class<pex::RNetExtractor> decl_RNetExtractor ("pex", "RNetExtractor",
|
||||
gsi::constructor ("new", &new_net_rextractor, gsi::arg ("dbu"),
|
||||
"@brief Creates a network R extractor\n"
|
||||
"\n"
|
||||
"@param dbu The database unit of the polygons the extractor will work on\n"
|
||||
"@param skip_simplify If true, the final step to simplify the netlist will be skipped. This feature is for testing mainly.\n"
|
||||
"@return A new \\RNetExtractor object that implements the net extractor\n"
|
||||
) +
|
||||
gsi::factory_ext ("extract", &rex_extract, gsi::arg ("tech_stack"), gsi::arg ("geo"), gsi::arg ("vertex_ports"), gsi::arg ("polygon_ports"),
|
||||
"@brief Runs the extraction on the given multi-layer geometry\n"
|
||||
"See the description of the class for more details."
|
||||
),
|
||||
"@brief The network R extractor class\n"
|
||||
"\n"
|
||||
"This class provides the algorithms for extracting a R network from a multi-layer arrangement of conductors and vias.\n"
|
||||
"The main feature is the \\extract method. It takes a multi-layer geometry, a tech stack and a number of port definitions\n"
|
||||
"and returns a R network. The nodes in that network are annotated, so the corresponding port can be deduced from a node of\n"
|
||||
"VertexPort or PolygonPort type.\n"
|
||||
"\n"
|
||||
"Layers are given by layer indexes - those are generic IDs. Every layer has to be given a unique ID, which must be used throughout "
|
||||
"the different specifications (geometry, vias, conductors, ports).\n"
|
||||
"\n"
|
||||
"Two kind of ports are provided: point-like vertex ports and polygon ports. Polygons for polygon ports should be convex and sit inside "
|
||||
"the geometry they mark. Ports become nodes in the network. Beside ports, the network can have internal nodes. Nodes are annotated with "
|
||||
"a type (vertex, polygon, internal) and an index and layer. The layer is the layer ID, the index specifies the position of the "
|
||||
"corresponding port in the 'vertex_ports' or 'polygon_ports' list of the \\extract call.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.2\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,412 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2025 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 "gsiDecl.h"
|
||||
#include "pexRExtractor.h"
|
||||
#include "pexSquareCountingRExtractor.h"
|
||||
#include "pexTriangulationRExtractor.h"
|
||||
#include "gsiEnums.h"
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
class RNode
|
||||
{
|
||||
public:
|
||||
~RNode () { }
|
||||
|
||||
pex::RNode::node_type type () const { return checked_pointer ()->type; }
|
||||
db::DBox location () const { return checked_pointer ()->location; }
|
||||
unsigned int port_index () const { return checked_pointer ()->port_index; }
|
||||
unsigned int layer () const { return checked_pointer ()->layer; }
|
||||
std::string to_string (bool with_coords = false) const { return checked_pointer ()->to_string (with_coords); }
|
||||
|
||||
size_t obj_id () const
|
||||
{
|
||||
return size_t (mp_ptr);
|
||||
}
|
||||
|
||||
static RNode *make_node_object (const pex::RNode *node)
|
||||
{
|
||||
return new RNode (node);
|
||||
}
|
||||
|
||||
const pex::RNode *checked_pointer () const
|
||||
{
|
||||
if (! mp_graph.get ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Network graph has been destroyed - RNode object no longer is valid")));
|
||||
}
|
||||
return mp_ptr;
|
||||
}
|
||||
|
||||
pex::RNode *checked_pointer ()
|
||||
{
|
||||
if (! mp_graph.get ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Network graph has been destroyed - RNode object no longer is valid")));
|
||||
}
|
||||
return const_cast<pex::RNode *> (mp_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
tl::weak_ptr<pex::RNetwork> mp_graph;
|
||||
const pex::RNode *mp_ptr;
|
||||
|
||||
RNode (const pex::RNode *node)
|
||||
: mp_graph (node->graph ()),
|
||||
mp_ptr (node)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
};
|
||||
|
||||
class RElement
|
||||
{
|
||||
public:
|
||||
~RElement () { }
|
||||
|
||||
double conductance () const { return checked_pointer ()->conductance; }
|
||||
double resistance () const { return checked_pointer ()->resistance (); }
|
||||
|
||||
RNode *a () const { return RNode::make_node_object (checked_pointer ()->a ()); }
|
||||
RNode *b () const { return RNode::make_node_object (checked_pointer ()->b ()); }
|
||||
|
||||
std::string to_string (bool with_coords = false) const { return checked_pointer ()->to_string (with_coords); }
|
||||
|
||||
size_t obj_id () const
|
||||
{
|
||||
return size_t (mp_ptr);
|
||||
}
|
||||
|
||||
static RElement *make_element_object (const pex::RElement *element)
|
||||
{
|
||||
return new RElement (element);
|
||||
}
|
||||
|
||||
const pex::RElement *checked_pointer () const
|
||||
{
|
||||
if (! mp_graph.get ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Network graph has been destroyed - RElement object no longer is valid")));
|
||||
}
|
||||
return mp_ptr;
|
||||
}
|
||||
|
||||
pex::RElement *checked_pointer ()
|
||||
{
|
||||
if (! mp_graph.get ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Network graph has been destroyed - RElement object no longer is valid")));
|
||||
}
|
||||
return const_cast<pex::RElement *> (mp_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
tl::weak_ptr<pex::RNetwork> mp_graph;
|
||||
const pex::RElement *mp_ptr;
|
||||
|
||||
RElement (const pex::RElement *node)
|
||||
: mp_graph (node->graph ()),
|
||||
mp_ptr (node)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
};
|
||||
|
||||
class RElementIterator
|
||||
{
|
||||
public:
|
||||
typedef std::list<const pex::RElement *>::const_iterator basic_iter;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef RElement *value_type;
|
||||
typedef RElement *reference;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
RElementIterator (basic_iter it)
|
||||
: m_it (it)
|
||||
{ }
|
||||
|
||||
bool operator== (const RElementIterator &it) const { return m_it == it.m_it; }
|
||||
void operator++ () { ++m_it; }
|
||||
|
||||
RElement *operator* () const
|
||||
{
|
||||
return RElement::make_element_object (*m_it);
|
||||
}
|
||||
|
||||
private:
|
||||
basic_iter m_it;
|
||||
};
|
||||
|
||||
static RElementIterator begin_node_elements (RNode *node)
|
||||
{
|
||||
return RElementIterator (node->checked_pointer ()->elements ().begin ());
|
||||
}
|
||||
|
||||
static RElementIterator end_network_elements (RNode *node)
|
||||
{
|
||||
return RElementIterator (node->checked_pointer ()->elements ().end ());
|
||||
}
|
||||
|
||||
gsi::Enum<pex::RNode::node_type> decl_NodeType ("pex", "RNodeType",
|
||||
gsi::enum_const ("Internal", pex::RNode::Internal,
|
||||
"@brief Specifies an internal node in a R network\n"
|
||||
"Internal nodes are generated during the R extraction process. "
|
||||
"The port index of such a node is an arbitrary index."
|
||||
) +
|
||||
gsi::enum_const ("VertexPort", pex::RNode::VertexPort,
|
||||
"@brief Specifies a vertex port node in a R network\n"
|
||||
"Vertex port nodes are generated for vertex ports in \\RExtractor#extract, see 'vertex_ports' argument. "
|
||||
"The port index of such a node refers to the position in that list."
|
||||
) +
|
||||
gsi::enum_const ("PolygonPort", pex::RNode::PolygonPort,
|
||||
"@brief Specifies a polygon port node in a R network\n"
|
||||
"Polygon port nodes are generated for polygon ports in \\RExtractor#extract, see 'polygon_ports' argument. "
|
||||
"The port index of such a node refers to the position in that list."
|
||||
),
|
||||
"@brief This class represents the node type for RNode.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.2"
|
||||
);
|
||||
|
||||
Class<RNode> decl_RNode ("pex", "RNode",
|
||||
gsi::method ("object_id", &RNode::obj_id,
|
||||
"@brief Returns an ID representing the actual object\n"
|
||||
"For every call, a new instance of this object is created, while multiple "
|
||||
"ones may represent the same internal object. The 'object_id' is a ID that "
|
||||
"indicates the internal object. Same object_id means same node."
|
||||
) +
|
||||
gsi::method ("to_s", &RNode::to_string, gsi::arg ("with_coords", false),
|
||||
"@brief Returns a string representation of this object\n"
|
||||
"Nodes are printed with coordinates with 'with_coords' is true."
|
||||
) +
|
||||
gsi::iterator_ext ("each_element", gsi::return_new_object (), &begin_node_elements, &end_network_elements,
|
||||
"@brief Iterates the \\RElement objects attached to the node\n"
|
||||
) +
|
||||
gsi::method ("type", &RNode::type,
|
||||
"@brief Gets the type attribute of the node\n"
|
||||
) +
|
||||
gsi::method ("location", &RNode::location,
|
||||
"@brief Gets the location attribute of the node\n"
|
||||
"The location defined the original position of the node"
|
||||
) +
|
||||
gsi::method ("port_index", &RNode::port_index,
|
||||
"@brief Gets the port index of the node\n"
|
||||
"The port index associates a node with a original port definition."
|
||||
) +
|
||||
gsi::method ("layer", &RNode::layer,
|
||||
"@brief Gets the Layer ID of the node\n"
|
||||
"The port index associates a node with a original port definition layer-wise."
|
||||
),
|
||||
"@brief Represents a node in a R network graph\n"
|
||||
"See \\RNetwork for a description of this object\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.2"
|
||||
);
|
||||
|
||||
// Inject the RNode::node_type declarations into RNode
|
||||
gsi::ClassExt<RNode> inject_NodeType_in_RNode (decl_NodeType.defs ());
|
||||
|
||||
Class<RElement> decl_RElement ("pex", "RElement",
|
||||
gsi::method ("object_id", &RElement::obj_id,
|
||||
"@brief Returns an ID representing the actual object\n"
|
||||
"For every call, a new instance of this object is created, while multiple "
|
||||
"ones may represent the same internal object. The 'object_id' is a ID that "
|
||||
"indicates the internal object. Same object_id means same element."
|
||||
) +
|
||||
gsi::method ("to_s", &RElement::to_string, gsi::arg ("with_coords", false),
|
||||
"@brief Returns a string representation of this object\n"
|
||||
"Nodes are printed with coordinates with 'with_coords' is true."
|
||||
) +
|
||||
gsi::method ("resistance", &RElement::resistance,
|
||||
"@brief Gets the resistance value of the object\n"
|
||||
) +
|
||||
gsi::factory ("a", &RElement::a,
|
||||
"@brief Gets the first node the element connects\n"
|
||||
) +
|
||||
gsi::factory ("b", &RElement::b,
|
||||
"@brief Gets the second node the element connects\n"
|
||||
),
|
||||
"@brief Represents an edge (also called element) in a R network graph\n"
|
||||
"See \\RNetwork for a description of this object"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.2"
|
||||
);
|
||||
|
||||
static RNode *create_node (pex::RNetwork *network, pex::RNode::node_type type, unsigned int port_index, unsigned int layer)
|
||||
{
|
||||
return RNode::make_node_object (network->create_node (type, port_index, layer));
|
||||
}
|
||||
|
||||
static RElement *create_element (pex::RNetwork *network, double r, RNode *a, RNode *b)
|
||||
{
|
||||
double s = fabs (r) < 1e-10 ? pex::RElement::short_value () : 1.0 / r;
|
||||
return RElement::make_element_object (network->create_element (s, a->checked_pointer (), b->checked_pointer ()));
|
||||
}
|
||||
|
||||
static void remove_element (pex::RNetwork *network, RElement *element)
|
||||
{
|
||||
network->remove_element (element->checked_pointer ());
|
||||
}
|
||||
|
||||
static void remove_node (pex::RNetwork *network, RNode *node)
|
||||
{
|
||||
network->remove_node (node->checked_pointer ());
|
||||
}
|
||||
|
||||
class NetworkElementIterator
|
||||
{
|
||||
public:
|
||||
typedef pex::RNetwork::element_iterator basic_iter;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef RElement *value_type;
|
||||
typedef RElement *reference;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
NetworkElementIterator (basic_iter it)
|
||||
: m_it (it)
|
||||
{ }
|
||||
|
||||
bool operator== (const NetworkElementIterator &it) const { return m_it == it.m_it; }
|
||||
void operator++ () { ++m_it; }
|
||||
|
||||
RElement *operator* () const
|
||||
{
|
||||
return RElement::make_element_object (m_it.operator-> ());
|
||||
}
|
||||
|
||||
private:
|
||||
basic_iter m_it;
|
||||
};
|
||||
|
||||
static NetworkElementIterator begin_network_elements (pex::RNetwork *network)
|
||||
{
|
||||
return NetworkElementIterator (network->begin_elements ());
|
||||
}
|
||||
|
||||
static NetworkElementIterator end_network_elements (pex::RNetwork *network)
|
||||
{
|
||||
return NetworkElementIterator (network->end_elements ());
|
||||
}
|
||||
|
||||
class NetworkNodeIterator
|
||||
{
|
||||
public:
|
||||
typedef pex::RNetwork::node_iterator basic_iter;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef RNode *value_type;
|
||||
typedef RNode *reference;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
NetworkNodeIterator (basic_iter it)
|
||||
: m_it (it)
|
||||
{ }
|
||||
|
||||
bool operator== (const NetworkNodeIterator &it) const { return m_it == it.m_it; }
|
||||
void operator++ () { ++m_it; }
|
||||
|
||||
RNode *operator* () const
|
||||
{
|
||||
return RNode::make_node_object (m_it.operator-> ());
|
||||
}
|
||||
|
||||
private:
|
||||
basic_iter m_it;
|
||||
};
|
||||
|
||||
static NetworkNodeIterator begin_network_nodes (pex::RNetwork *network)
|
||||
{
|
||||
return NetworkNodeIterator (network->begin_nodes ());
|
||||
}
|
||||
|
||||
static NetworkNodeIterator end_network_nodes (pex::RNetwork *network)
|
||||
{
|
||||
return NetworkNodeIterator (network->end_nodes ());
|
||||
}
|
||||
|
||||
Class<pex::RNetwork> decl_RNetwork ("pex", "RNetwork",
|
||||
gsi::factory_ext ("create_node", &create_node, gsi::arg ("type"), gsi::arg ("port_index"), gsi::arg ("layer", (unsigned int) 0),
|
||||
"@brief Creates a new node with the given type and index'.\n"
|
||||
"@return A reference to the new nbode object."
|
||||
) +
|
||||
gsi::factory_ext ("create_element", &create_element, gsi::arg ("resistance"), gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief Creates a new element between the nodes given by 'a' abd 'b'.\n"
|
||||
"If a resistor already exists between the two nodes, both resistors are combined into one.\n"
|
||||
"@return A reference to the new resistor object."
|
||||
) +
|
||||
gsi::method_ext ("remove_element", &remove_element, gsi::arg ("element"),
|
||||
"@brief Removes the given element\n"
|
||||
"If removing the element renders an internal node orphan (i.e. without elements), this "
|
||||
"node is removed too."
|
||||
) +
|
||||
gsi::method_ext ("remove_node", &remove_node, gsi::arg ("node"),
|
||||
"@brief Removes the given node\n"
|
||||
"Only internal nodes can be removed. Removing a node will also remove the "
|
||||
"elements attached to this node."
|
||||
) +
|
||||
gsi::method ("clear", &pex::RNetwork::clear,
|
||||
"@brief Clears the network\n"
|
||||
) +
|
||||
gsi::method ("simplify", &pex::RNetwork::simplify,
|
||||
"@brief Simplifies the network\n"
|
||||
"\n"
|
||||
"This will:\n"
|
||||
"@ul\n"
|
||||
"@li Join serial resistors if connected by an internal node @/li\n"
|
||||
"@li Remove shorts and join the nodes, if one of them is\n"
|
||||
" an internal node. The non-internal node will persist @/li\n"
|
||||
"@li Remove \"dangling\" resistors if the dangling node is\n"
|
||||
" an internal one @/li\n"
|
||||
"@/ul\n"
|
||||
) +
|
||||
gsi::iterator_ext ("each_element", gsi::return_new_object (), &begin_network_elements, &end_network_elements,
|
||||
"@brief Iterates the \\RElement objects inside the network\n"
|
||||
) +
|
||||
gsi::iterator_ext ("each_node", gsi::return_new_object (), &begin_network_nodes, &end_network_nodes,
|
||||
"@brief Iterates the \\RNode objects inside the network\n"
|
||||
) +
|
||||
gsi::method ("num_nodes", &pex::RNetwork::num_nodes,
|
||||
"@brief Gets the total number of nodes in the network\n"
|
||||
) +
|
||||
gsi::method ("num_internal_nodes", &pex::RNetwork::num_internal_nodes,
|
||||
"@brief Gets the number of internal nodes in the network\n"
|
||||
) +
|
||||
gsi::method ("num_elements", &pex::RNetwork::num_elements,
|
||||
"@brief Gets the number of elements in the network\n"
|
||||
) +
|
||||
gsi::method ("to_s", &pex::RNetwork::to_string, gsi::arg ("with_coords", false),
|
||||
"@brief Returns a string representation of the network\n"
|
||||
"Nodes are printed with coordinates with 'with_coords' is true."
|
||||
),
|
||||
"@brief Represents a network of resistors\n"
|
||||
"\n"
|
||||
"The network is basically a graph with nodes and edges (the resistors). "
|
||||
"The resistors are called 'elements' and are represented by \\RElement objects. "
|
||||
"The nodes are represented by \\RNode objects. "
|
||||
"The network is created by \\RExtractor#extract, which turns a polygon into a resistor network.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.2\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -7,6 +7,8 @@ include($$PWD/../../lib.pri)
|
|||
DEFINES += MAKE_PEX_LIBRARY
|
||||
|
||||
SOURCES = \
|
||||
gsiDeclRNetExtractor.cc \
|
||||
gsiDeclRNetwork.cc \
|
||||
pexForceLink.cc \
|
||||
pexRExtractor.cc \
|
||||
gsiDeclRExtractor.cc \
|
||||
|
|
|
|||
|
|
@ -97,10 +97,10 @@ public:
|
|||
SquareCounting = 0,
|
||||
|
||||
/**
|
||||
* @brief The triangulation algorithm
|
||||
* @brief The tesselation algorithm
|
||||
* This algorithm is suitable to "large" sheets, specifically substrate.
|
||||
*/
|
||||
Triangulation = 1
|
||||
Tesselation = 1
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -69,19 +69,6 @@ RNetExtractor::extract (const RExtractorTech &tech,
|
|||
continue;
|
||||
}
|
||||
|
||||
// Compute the offsets for the port indexes
|
||||
// The port indexes are assigned incrementally, so the first index of a port
|
||||
// for layer n is:
|
||||
// size(ports for layer 0) + ... + size(ports for layer n-1)
|
||||
// (size is 0 for empty port list)
|
||||
unsigned int vp_offset = 0, pp_offset = 0;
|
||||
for (auto p = vertex_ports.begin (); p != vertex_ports.end () && p->first < g->first; ++p) {
|
||||
vp_offset += p->second.size ();
|
||||
}
|
||||
for (auto p = polygon_ports.begin (); p != polygon_ports.end () && p->first < g->first; ++p) {
|
||||
pp_offset += p->second.size ();
|
||||
}
|
||||
|
||||
// fetch the port list for vertex ports
|
||||
auto ivp = vertex_ports.find (g->first);
|
||||
static std::vector<db::Point> empty_vertex_ports;
|
||||
|
|
@ -98,7 +85,7 @@ RNetExtractor::extract (const RExtractorTech &tech,
|
|||
const std::vector<ViaPort> &viap = iviap == via_ports.end () ? empty_via_ports : iviap->second;
|
||||
|
||||
// extract the conductor polygon and integrate the results into the target network
|
||||
extract_conductor (*cond, g->second, vp, vp_offset, pp, pp_offset, viap, rnetwork);
|
||||
extract_conductor (*cond, g->second, vp, pp, viap, rnetwork);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -178,8 +165,8 @@ RNetExtractor::create_via_port (const pex::RExtractorTechVia &tech,
|
|||
std::map<unsigned int, std::vector<ViaPort> > &vias,
|
||||
RNetwork &rnetwork)
|
||||
{
|
||||
RNode *a = rnetwork.create_node (RNode::Internal, port_index++);
|
||||
RNode *b = rnetwork.create_node (RNode::Internal, port_index++);
|
||||
RNode *a = rnetwork.create_node (RNode::Internal, port_index++, tech.bottom_conductor);
|
||||
RNode *b = rnetwork.create_node (RNode::Internal, port_index++, tech.top_conductor);
|
||||
|
||||
db::CplxTrans to_um (m_dbu);
|
||||
db::Box box = poly.box ();
|
||||
|
|
@ -266,9 +253,7 @@ class ExtractingReceiver
|
|||
public:
|
||||
ExtractingReceiver (const RExtractorTechConductor *cond,
|
||||
const std::vector<db::Point> *vertex_ports,
|
||||
unsigned int vertex_port_index_offset,
|
||||
const std::vector<db::Polygon> *polygon_ports,
|
||||
unsigned int polygon_port_index_offset,
|
||||
const std::vector<RNetExtractor::ViaPort> *via_ports,
|
||||
double dbu,
|
||||
RNetwork *rnetwork)
|
||||
|
|
@ -277,8 +262,6 @@ public:
|
|||
mp_polygon_ports (polygon_ports),
|
||||
mp_via_ports (via_ports),
|
||||
m_next_internal_port_index (0),
|
||||
m_vertex_port_index_offset (vertex_port_index_offset),
|
||||
m_polygon_port_index_offset (polygon_port_index_offset),
|
||||
m_dbu (dbu),
|
||||
mp_rnetwork (rnetwork)
|
||||
{
|
||||
|
|
@ -316,8 +299,6 @@ private:
|
|||
const std::vector<RNetExtractor::ViaPort> *mp_via_ports;
|
||||
std::map<size_t, RNode *> m_id_to_node;
|
||||
unsigned int m_next_internal_port_index;
|
||||
unsigned int m_vertex_port_index_offset;
|
||||
unsigned int m_polygon_port_index_offset;
|
||||
double m_dbu;
|
||||
RNetwork *mp_rnetwork;
|
||||
|
||||
|
|
@ -355,7 +336,7 @@ private:
|
|||
rex.extract (poly, local_vertex_ports, local_polygon_ports, local_network);
|
||||
}
|
||||
break;
|
||||
case RExtractorTechConductor::Triangulation:
|
||||
case RExtractorTechConductor::Tesselation:
|
||||
{
|
||||
pex::TriangulationRExtractor rex (m_dbu);
|
||||
rex.extract (poly, local_vertex_ports, local_polygon_ports, local_network);
|
||||
|
|
@ -380,7 +361,7 @@ private:
|
|||
if (local->type == RNode::Internal) {
|
||||
|
||||
// for internal nodes always create a node in the target network
|
||||
global = mp_rnetwork->create_node (local->type, ++m_next_internal_port_index);
|
||||
global = mp_rnetwork->create_node (local->type, ++m_next_internal_port_index, mp_cond->layer);
|
||||
global->location = local->location;
|
||||
|
||||
} else if (local->type == RNode::VertexPort) {
|
||||
|
|
@ -395,7 +376,7 @@ private:
|
|||
global = i2n->second;
|
||||
} else {
|
||||
if (type_from_id (id) == 0) { // vertex port
|
||||
global = mp_rnetwork->create_node (RNode::VertexPort, index_from_id (id) + m_vertex_port_index_offset);
|
||||
global = mp_rnetwork->create_node (RNode::VertexPort, index_from_id (id), mp_cond->layer);
|
||||
global->location = local->location;
|
||||
} else if (type_from_id (id) == 1) { // via port
|
||||
global = (*mp_via_ports) [index_from_id (id)].node;
|
||||
|
|
@ -414,7 +395,7 @@ private:
|
|||
if (i2n != m_id_to_node.end ()) {
|
||||
global = i2n->second;
|
||||
} else {
|
||||
global = mp_rnetwork->create_node (RNode::PolygonPort, index_from_id (id) + m_polygon_port_index_offset);
|
||||
global = mp_rnetwork->create_node (RNode::PolygonPort, index_from_id (id), mp_cond->layer);
|
||||
global->location = local->location;
|
||||
m_id_to_node.insert (std::make_pair (id, global));
|
||||
}
|
||||
|
|
@ -455,9 +436,7 @@ void
|
|||
RNetExtractor::extract_conductor (const RExtractorTechConductor &cond,
|
||||
const db::Region ®ion,
|
||||
const std::vector<db::Point> &vertex_ports,
|
||||
unsigned int vertex_ports_index_offset,
|
||||
const std::vector<db::Polygon> &polygon_ports,
|
||||
unsigned int polygon_ports_index_offset,
|
||||
const std::vector<ViaPort> &via_ports,
|
||||
RNetwork &rnetwork)
|
||||
{
|
||||
|
|
@ -490,7 +469,7 @@ RNetExtractor::extract_conductor (const RExtractorTechConductor &cond,
|
|||
scanner.insert2 (&box_heap.back (), make_id (i - polygon_ports.begin (), 2));
|
||||
}
|
||||
|
||||
ExtractingReceiver rec (&cond, &vertex_ports, vertex_ports_index_offset, &polygon_ports, polygon_ports_index_offset, &via_ports, m_dbu, &rnetwork);
|
||||
ExtractingReceiver rec (&cond, &vertex_ports, &polygon_ports, &via_ports, m_dbu, &rnetwork);
|
||||
scanner.process (rec, 0, db::box_convert<db::Polygon> (), db::box_convert<db::Box> ());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,9 +84,7 @@ protected:
|
|||
void extract_conductor (const RExtractorTechConductor &cond,
|
||||
const db::Region ®ion,
|
||||
const std::vector<db::Point> &vertex_ports,
|
||||
unsigned int vertex_ports_index_offset,
|
||||
const std::vector<db::Polygon> &polygon_ports,
|
||||
unsigned int polygon_ports_index_offset,
|
||||
const std::vector<ViaPort> &via_ports,
|
||||
RNetwork &rnetwork);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,19 +33,24 @@ std::string
|
|||
RNode::to_string (bool with_coords) const
|
||||
{
|
||||
std::string res;
|
||||
|
||||
switch (type) {
|
||||
default:
|
||||
res += "$" + tl::to_string (port_index);
|
||||
res += "$";
|
||||
break;
|
||||
case VertexPort:
|
||||
res += "V" + tl::to_string (port_index);
|
||||
res += "V";
|
||||
break;
|
||||
case PolygonPort:
|
||||
res += "P" + tl::to_string (port_index);
|
||||
res += "P";
|
||||
break;
|
||||
}
|
||||
|
||||
res += tl::to_string (port_index);
|
||||
if (layer > 0) {
|
||||
res += ".";
|
||||
res += tl::to_string (layer);
|
||||
}
|
||||
|
||||
if (with_coords) {
|
||||
res += location.to_string ();
|
||||
}
|
||||
|
|
@ -116,27 +121,27 @@ RNetwork::clear ()
|
|||
}
|
||||
|
||||
RNode *
|
||||
RNetwork::create_node (RNode::node_type type, unsigned int port_index)
|
||||
RNetwork::create_node (RNode::node_type type, unsigned int port_index, unsigned int layer)
|
||||
{
|
||||
if (type != RNode::Internal) {
|
||||
|
||||
auto i = m_nodes_by_type.find (std::make_pair (type, port_index));
|
||||
auto i = m_nodes_by_type.find (std::make_pair (type, std::make_pair (port_index, layer)));
|
||||
if (i != m_nodes_by_type.end ()) {
|
||||
|
||||
return i->second;
|
||||
|
||||
} else {
|
||||
|
||||
RNode *new_node = new RNode (this, type, db::DBox (), port_index);
|
||||
RNode *new_node = new RNode (this, type, db::DBox (), port_index, layer);
|
||||
m_nodes.push_back (new_node);
|
||||
m_nodes_by_type.insert (std::make_pair (std::make_pair (type, port_index), new_node));
|
||||
m_nodes_by_type.insert (std::make_pair (std::make_pair (type, std::make_pair (port_index, layer)), new_node));
|
||||
|
||||
return new_node;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
RNode *new_node = new RNode (this, type, db::DBox (), port_index);
|
||||
RNode *new_node = new RNode (this, type, db::DBox (), port_index, layer);
|
||||
m_nodes.push_back (new_node);
|
||||
return new_node;
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,13 @@ public:
|
|||
*/
|
||||
unsigned int port_index;
|
||||
|
||||
/**
|
||||
* @brief An index locating the node in a layer
|
||||
*
|
||||
* For internal nodes, the layer is 0.
|
||||
*/
|
||||
unsigned int layer;
|
||||
|
||||
/**
|
||||
* @brief Gets the R elements connected to this node
|
||||
*/
|
||||
|
|
@ -106,8 +113,8 @@ protected:
|
|||
friend class RElement;
|
||||
friend class tl::list_impl<RNode, false>;
|
||||
|
||||
RNode (RNetwork *network, node_type _type, const db::DBox &_location, unsigned int _port_index)
|
||||
: type (_type), location (_location), port_index (_port_index), mp_network (network)
|
||||
RNode (RNetwork *network, node_type _type, const db::DBox &_location, unsigned int _port_index, unsigned int _layer)
|
||||
: type (_type), location (_location), port_index (_port_index), layer (_layer), mp_network (network)
|
||||
{ }
|
||||
|
||||
~RNode () { }
|
||||
|
|
@ -249,7 +256,7 @@ public:
|
|||
* or port index already. This avoids creating duplicates
|
||||
* for the same port.
|
||||
*/
|
||||
RNode *create_node (RNode::node_type type, unsigned int port_index);
|
||||
RNode *create_node (RNode::node_type type, unsigned int port_index, unsigned int layer);
|
||||
|
||||
/**
|
||||
* @brief Creates a new element between the given nodes
|
||||
|
|
@ -363,7 +370,7 @@ private:
|
|||
node_list m_nodes;
|
||||
element_list m_elements;
|
||||
std::map<std::pair<RNode *, RNode *>, RElement *> m_elements_by_nodes;
|
||||
std::map<std::pair<RNode::node_type, unsigned int>, RNode *> m_nodes_by_type;
|
||||
std::map<std::pair<RNode::node_type, std::pair<unsigned int, unsigned int> >, RNode *> m_nodes_by_type;
|
||||
|
||||
RNetwork (const RNetwork &);
|
||||
RNetwork &operator= (const RNetwork &);
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector
|
|||
for (auto p = ports.begin (); p != ports.end (); ++p) {
|
||||
auto n4p = nodes_for_ports.find (p->first);
|
||||
if (n4p == nodes_for_ports.end ()) {
|
||||
pex::RNode *node = rnetwork.create_node (p->first.type, p->first.port_index);
|
||||
pex::RNode *node = rnetwork.create_node (p->first.type, p->first.port_index, 0);
|
||||
node->location = to_um * p->first.location;
|
||||
n4p = nodes_for_ports.insert (std::make_pair (p->first, node)).first;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector<
|
|||
if (pn != pport_nodes.end ()) {
|
||||
n = pn->second;
|
||||
} else {
|
||||
n = rnetwork.create_node (pex::RNode::PolygonPort, port_index);
|
||||
n = rnetwork.create_node (pex::RNode::PolygonPort, port_index, 0);
|
||||
pport_nodes.insert (std::make_pair (port_index, n));
|
||||
n->location = trans * polygon_ports [port_index].box ();
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector<
|
|||
for (auto pi = vertex->ids ().begin (); pi != vertex->ids ().end (); ++pi) {
|
||||
size_t port_index = size_t (*pi);
|
||||
if (port_index < vertex_ports.size ()) {
|
||||
RNode *nn = rnetwork.create_node (pex::RNode::VertexPort, port_index);
|
||||
RNode *nn = rnetwork.create_node (pex::RNode::VertexPort, port_index, 0);
|
||||
nn->location = db::DBox (*vertex, *vertex);
|
||||
if (n) {
|
||||
// in case of multiple vertexes on the same spot, short them
|
||||
|
|
@ -172,7 +172,7 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector<
|
|||
|
||||
} else {
|
||||
|
||||
n = rnetwork.create_node (pex::RNode::Internal, internal_node_id++);
|
||||
n = rnetwork.create_node (pex::RNode::Internal, internal_node_id++, 0);
|
||||
n->location = db::DBox (*vertex, *vertex);
|
||||
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector<
|
|||
if (ip != pport_nodes.end ()) {
|
||||
|
||||
// create a new vertex port and short it to the polygon port
|
||||
auto n = rnetwork.create_node (pex::RNode::VertexPort, iv);
|
||||
auto n = rnetwork.create_node (pex::RNode::VertexPort, iv, 0);
|
||||
n->location = db::DBox (trans * vp, trans * vp);
|
||||
rnetwork.create_element (pex::RElement::short_value (), n, ip->second);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,15 +30,74 @@ TEST(network_basic)
|
|||
pex::RNetwork rn;
|
||||
EXPECT_EQ (rn.to_string (), "");
|
||||
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::Internal, 1);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2);
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::Internal, 1, 0);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 1, 1);
|
||||
EXPECT_EQ (n1 != n2, true);
|
||||
pex::RNode *n2_dup = rn.create_node (pex::RNode::Internal, 1, 1);
|
||||
EXPECT_EQ (n2 != n2_dup, true);
|
||||
|
||||
/* pex::RElement *e12 = */ rn.create_element (0.5, n1, n2);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R $1 $1.1 2"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(network_basic_vertex_nodes)
|
||||
{
|
||||
pex::RNetwork rn;
|
||||
EXPECT_EQ (rn.to_string (), "");
|
||||
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1, 0);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::VertexPort, 1, 1);
|
||||
EXPECT_EQ (n1 != n2, true);
|
||||
pex::RNode *n2_dup = rn.create_node (pex::RNode::VertexPort, 1, 1);
|
||||
EXPECT_EQ (n2 == n2_dup, true);
|
||||
pex::RNode *n2_wrong_type = rn.create_node (pex::RNode::PolygonPort, 1, 1);
|
||||
EXPECT_EQ (n2 != n2_wrong_type, true);
|
||||
|
||||
/* pex::RElement *e12 = */ rn.create_element (0.5, n1, n2);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R V1 V1.1 2"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(network_basic_polygon_nodes)
|
||||
{
|
||||
pex::RNetwork rn;
|
||||
EXPECT_EQ (rn.to_string (), "");
|
||||
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::PolygonPort, 1, 0);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::PolygonPort, 1, 1);
|
||||
EXPECT_EQ (n1 != n2, true);
|
||||
pex::RNode *n2_dup = rn.create_node (pex::RNode::PolygonPort, 1, 1);
|
||||
EXPECT_EQ (n2 == n2_dup, true);
|
||||
pex::RNode *n2_wrong_type = rn.create_node (pex::RNode::VertexPort, 1, 1);
|
||||
EXPECT_EQ (n2 != n2_wrong_type, true);
|
||||
|
||||
/* pex::RElement *e12 = */ rn.create_element (0.5, n1, n2);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R P1 P1.1 2"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(network_basic_elements)
|
||||
{
|
||||
pex::RNetwork rn;
|
||||
EXPECT_EQ (rn.to_string (), "");
|
||||
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::Internal, 1, 0);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2, 0);
|
||||
|
||||
/* pex::RElement *e12 = */ rn.create_element (0.5, n1, n2);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R $1 $2 2"
|
||||
);
|
||||
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3, 0);
|
||||
/* pex::RElement *e13 = */ rn.create_element (0.25, n1, n3);
|
||||
pex::RElement *e23 = rn.create_element (1.0, n2, n3);
|
||||
|
||||
|
|
@ -89,9 +148,9 @@ TEST(network_simplify1)
|
|||
pex::RNetwork rn;
|
||||
EXPECT_EQ (rn.to_string (), "");
|
||||
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::VertexPort, 3);
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1, 0);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2, 0);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::VertexPort, 3, 0);
|
||||
|
||||
rn.create_element (1, n1, n2);
|
||||
rn.create_element (pex::RElement::short_value (), n2, n3);
|
||||
|
|
@ -115,11 +174,11 @@ TEST(network_simplify2)
|
|||
pex::RNetwork rn;
|
||||
EXPECT_EQ (rn.to_string (), "");
|
||||
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3);
|
||||
pex::RNode *n4 = rn.create_node (pex::RNode::VertexPort, 4);
|
||||
pex::RNode *n5 = rn.create_node (pex::RNode::VertexPort, 5);
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1, 0);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2, 0);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3, 0);
|
||||
pex::RNode *n4 = rn.create_node (pex::RNode::VertexPort, 4, 0);
|
||||
pex::RNode *n5 = rn.create_node (pex::RNode::VertexPort, 5, 0);
|
||||
|
||||
rn.create_element (1, n1, n2);
|
||||
rn.create_element (pex::RElement::short_value (), n2, n3);
|
||||
|
|
@ -147,10 +206,10 @@ TEST(network_simplify3)
|
|||
pex::RNetwork rn;
|
||||
EXPECT_EQ (rn.to_string (), "");
|
||||
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3);
|
||||
pex::RNode *n4 = rn.create_node (pex::RNode::VertexPort, 4);
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1, 0);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2, 0);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3, 0);
|
||||
pex::RNode *n4 = rn.create_node (pex::RNode::VertexPort, 4, 0);
|
||||
|
||||
rn.create_element (1, n1, n2);
|
||||
rn.create_element (pex::RElement::short_value (), n2, n3);
|
||||
|
|
@ -174,10 +233,10 @@ TEST(network_simplify4)
|
|||
pex::RNetwork rn;
|
||||
EXPECT_EQ (rn.to_string (), "");
|
||||
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3);
|
||||
pex::RNode *n4 = rn.create_node (pex::RNode::VertexPort, 4);
|
||||
pex::RNode *n1 = rn.create_node (pex::RNode::VertexPort, 1, 0);
|
||||
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2, 0);
|
||||
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3, 0);
|
||||
pex::RNode *n4 = rn.create_node (pex::RNode::VertexPort, 4, 0);
|
||||
|
||||
rn.create_element (1, n1, n4);
|
||||
rn.create_element (1, n2, n1);
|
||||
|
|
|
|||
|
|
@ -79,10 +79,10 @@ TEST(netex_viagen1)
|
|||
EXPECT_EQ (via_ports [l3].size (), size_t (4));
|
||||
|
||||
EXPECT_EQ (network.to_string (true),
|
||||
"R $0(1.7,0.1;1.9,0.3) $1(1.7,0.1;1.9,0.3) 50\n"
|
||||
"R $2(0.4,0.5;0.6,0.7) $3(0.4,0.5;0.6,0.7) 50\n"
|
||||
"R $4(0.8,0.5;1,0.7) $5(0.8,0.5;1,0.7) 50\n"
|
||||
"R $6(2.9,0.5;3.1,0.7) $7(2.9,0.5;3.1,0.7) 50"
|
||||
"R $0.1(1.7,0.1;1.9,0.3) $1.2(1.7,0.1;1.9,0.3) 50\n"
|
||||
"R $2.1(0.4,0.5;0.6,0.7) $3.2(0.4,0.5;0.6,0.7) 50\n"
|
||||
"R $4.1(0.8,0.5;1,0.7) $5.2(0.8,0.5;1,0.7) 50\n"
|
||||
"R $6.1(2.9,0.5;3.1,0.7) $7.2(2.9,0.5;3.1,0.7) 50"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -129,12 +129,12 @@ TEST(netex_viagen2)
|
|||
EXPECT_EQ (via_ports [l3].size (), size_t (6));
|
||||
|
||||
EXPECT_EQ (network.to_string (true),
|
||||
"R $0(4.6,2.8;4.8,3) $1(4.6,2.8;4.8,3) 50\n"
|
||||
"R $2(2.5,3.7;2.7,3.9) $3(2.5,3.7;2.7,3.9) 50\n"
|
||||
"R $4(3,3.7;3.2,3.9) $5(3,3.7;3.2,3.9) 50\n"
|
||||
"R $6(2.2,1.2;3.4,3.4) $7(2.2,1.2;3.4,3.4) 2.77778\n"
|
||||
"R $8(0.4,0.4;2.2,4.2) $9(0.4,0.4;2.2,4.2) 1\n"
|
||||
"R $10(0.6,4.9;1.2,5.1) $11(0.6,4.9;1.2,5.1) 25"
|
||||
"R $0.1(4.6,2.8;4.8,3) $1.2(4.6,2.8;4.8,3) 50\n"
|
||||
"R $2.1(2.5,3.7;2.7,3.9) $3.2(2.5,3.7;2.7,3.9) 50\n"
|
||||
"R $4.1(3,3.7;3.2,3.9) $5.2(3,3.7;3.2,3.9) 50\n"
|
||||
"R $6.1(2.2,1.2;3.4,3.4) $7.2(2.2,1.2;3.4,3.4) 2.77778\n"
|
||||
"R $8.1(0.4,0.4;2.2,4.2) $9.2(0.4,0.4;2.2,4.2) 1\n"
|
||||
"R $10.1(0.6,4.9;1.2,5.1) $11.2(0.6,4.9;1.2,5.1) 25"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +162,11 @@ TEST(netex_2layer)
|
|||
unsigned int l3p = ly.get_layer (db::LayerProperties (3, 1));
|
||||
unsigned int l3v = ly.get_layer (db::LayerProperties (3, 2));
|
||||
|
||||
// That is coincidence, but it needs to be that way for the strings to match
|
||||
EXPECT_EQ (l1, 1u);
|
||||
EXPECT_EQ (l2, 0u);
|
||||
EXPECT_EQ (l3, 2u);
|
||||
|
||||
std::map<unsigned int, db::Region> geo;
|
||||
geo.insert (std::make_pair (l1, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l1))));
|
||||
geo.insert (std::make_pair (l2, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l2))));
|
||||
|
|
@ -216,19 +221,19 @@ TEST(netex_2layer)
|
|||
rex.extract (tech, geo, vertex_ports, polygon_ports, network);
|
||||
|
||||
EXPECT_EQ (network.to_string (true),
|
||||
"R $0(0.3,-5.7;0.5,-5.5) $1(0.3,-5.7;0.5,-5.5) 50\n"
|
||||
"R $2(9.3,-5.9;9.9,-5.3) $3(9.3,-5.9;9.9,-5.3) 12.5\n"
|
||||
"R $4(9.3,0.1;9.9,0.3) $5(9.3,0.1;9.9,0.3) 25\n"
|
||||
"R $6(0.1,0.1;0.7,0.7) $7(0.1,0.1;0.7,0.7) 12.5\n"
|
||||
"R $0(0.3,-5.7;0.5,-5.5) $2(9.3,-5.9;9.9,-5.3) 5.75\n"
|
||||
"R $2(9.3,-5.9;9.9,-5.3) P0(12.9,-5.9;13.5,-5.3) 2.25\n"
|
||||
"R $6(0.1,0.1;0.7,0.7) V0(5.2,0.4;5.2,0.4) 3\n"
|
||||
"R $4(9.3,0.1;9.9,0.3) V0(5.2,0.4;5.2,0.4) 2.75\n"
|
||||
"R $5(9.3,0.1;9.9,0.3) $8(10,-3.5;10,-2.7) 1.03125\n"
|
||||
"R $3(9.3,-5.9;9.9,-5.3) $8(10,-3.5;10,-2.7) 0.78125\n"
|
||||
"R $8(10,-3.5;10,-2.7) P1(12.9,-3.4;13.5,-2.8) 1\n"
|
||||
"R $7(0.1,0.1;0.7,0.7) V1(0.4,-5.6;0.4,-5.6) 1.875\n"
|
||||
"R $1(0.3,-5.7;0.5,-5.5) V1(0.4,-5.6;0.4,-5.6) 0"
|
||||
"R $0.1(0.3,-5.7;0.5,-5.5) $1.2(0.3,-5.7;0.5,-5.5) 50\n"
|
||||
"R $2.1(9.3,-5.9;9.9,-5.3) $3.2(9.3,-5.9;9.9,-5.3) 12.5\n"
|
||||
"R $4.1(9.3,0.1;9.9,0.3) $5.2(9.3,0.1;9.9,0.3) 25\n"
|
||||
"R $6.1(0.1,0.1;0.7,0.7) $7.2(0.1,0.1;0.7,0.7) 12.5\n"
|
||||
"R $0.1(0.3,-5.7;0.5,-5.5) $2.1(9.3,-5.9;9.9,-5.3) 5.75\n"
|
||||
"R $2.1(9.3,-5.9;9.9,-5.3) P0.1(12.9,-5.9;13.5,-5.3) 2.25\n"
|
||||
"R $6.1(0.1,0.1;0.7,0.7) V0.1(5.2,0.4;5.2,0.4) 3\n"
|
||||
"R $4.1(9.3,0.1;9.9,0.3) V0.1(5.2,0.4;5.2,0.4) 2.75\n"
|
||||
"R $5.2(9.3,0.1;9.9,0.3) $8.2(10,-3.5;10,-2.7) 1.03125\n"
|
||||
"R $3.2(9.3,-5.9;9.9,-5.3) $8.2(10,-3.5;10,-2.7) 0.78125\n"
|
||||
"R $8.2(10,-3.5;10,-2.7) P0.2(12.9,-3.4;13.5,-2.8) 1\n"
|
||||
"R $7.2(0.1,0.1;0.7,0.7) V0.2(0.4,-5.6;0.4,-5.6) 1.875\n"
|
||||
"R $1.2(0.3,-5.7;0.5,-5.5) V0.2(0.4,-5.6;0.4,-5.6) 0"
|
||||
);
|
||||
|
||||
tech.skip_simplify = false;
|
||||
|
|
@ -236,11 +241,11 @@ TEST(netex_2layer)
|
|||
rex.extract (tech, geo, vertex_ports, polygon_ports, network);
|
||||
|
||||
EXPECT_EQ (network.to_string (true),
|
||||
"R $2(9.3,-5.9;9.9,-5.3) P0(12.9,-5.9;13.5,-5.3) 2.25\n"
|
||||
"R $8(10,-3.5;10,-2.7) P1(12.9,-3.4;13.5,-2.8) 1\n"
|
||||
"R $2(9.3,-5.9;9.9,-5.3) V1(0.3,-5.7;0.5,-5.5) 55.75\n"
|
||||
"R $2(9.3,-5.9;9.9,-5.3) $8(10,-3.5;10,-2.7) 13.2813\n"
|
||||
"R $8(10,-3.5;10,-2.7) V0(5.2,0.4;5.2,0.4) 28.7812\n"
|
||||
"R V0(5.2,0.4;5.2,0.4) V1(0.3,-5.7;0.5,-5.5) 17.375"
|
||||
"R $2.1(9.3,-5.9;9.9,-5.3) P0.1(12.9,-5.9;13.5,-5.3) 2.25\n"
|
||||
"R $8.2(10,-3.5;10,-2.7) P0.2(12.9,-3.4;13.5,-2.8) 1\n"
|
||||
"R $2.1(9.3,-5.9;9.9,-5.3) V0.2(0.3,-5.7;0.5,-5.5) 55.75\n"
|
||||
"R $2.1(9.3,-5.9;9.9,-5.3) $8.2(10,-3.5;10,-2.7) 13.2813\n"
|
||||
"R $8.2(10,-3.5;10,-2.7) V0.1(5.2,0.4;5.2,0.4) 28.7812\n"
|
||||
"R V0.1(5.2,0.4;5.2,0.4) V0.2(0.3,-5.7;0.5,-5.5) 17.375"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ TEST(basic)
|
|||
|
||||
std::vector<std::pair<TestableSquareCountingRExtractor::PortDefinition, pex::RNode *> > ports;
|
||||
for (auto pd = pds.begin (); pd != pds.end (); ++pd) {
|
||||
ports.push_back (std::make_pair (*pd, rn.create_node (pd->type, pd->port_index)));
|
||||
ports.push_back (std::make_pair (*pd, rn.create_node (pd->type, pd->port_index, 0)));
|
||||
}
|
||||
|
||||
rex.do_extract (poly, ports, rn);
|
||||
|
|
@ -90,7 +90,7 @@ TEST(basic)
|
|||
|
||||
ports.clear ();
|
||||
for (auto pd = pds.begin (); pd != pds.end (); ++pd) {
|
||||
ports.push_back (std::make_pair (*pd, rn.create_node (pd->type, pd->port_index)));
|
||||
ports.push_back (std::make_pair (*pd, rn.create_node (pd->type, pd->port_index, 0)));
|
||||
ports.back ().first.location.transform (r90);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue