mirror of https://github.com/KLayout/klayout.git
WIP: first steps towards global nets.
This commit is contained in:
parent
eb435d5d85
commit
64c2548ab8
|
|
@ -269,7 +269,8 @@ HEADERS = \
|
|||
dbNetlistDeviceExtractor.h \
|
||||
dbNetlistExtractor.h \
|
||||
dbNetlistDeviceExtractorClasses.h \
|
||||
dbLayoutToNetlist.h
|
||||
dbLayoutToNetlist.h \
|
||||
dbHierNetworkProcessor.h
|
||||
|
||||
!equals(HAVE_QT, "0") {
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,60 @@ Connectivity::connect (const db::DeepLayer &la, const db::DeepLayer &lb)
|
|||
connect (la.layer (), lb.layer ());
|
||||
}
|
||||
|
||||
Connectivity::global_nets_type s_empty_global_nets;
|
||||
|
||||
Connectivity::global_nets_iterator
|
||||
Connectivity::begin_global_connections (unsigned int l) const
|
||||
{
|
||||
std::map<unsigned int, global_nets_type>::const_iterator g = m_global_connections.find (l);
|
||||
if (g != m_global_connections.end ()) {
|
||||
return g->second.begin ();
|
||||
} else {
|
||||
return s_empty_global_nets.begin ();
|
||||
}
|
||||
}
|
||||
|
||||
Connectivity::global_nets_iterator
|
||||
Connectivity::end_global_connections (unsigned int l) const
|
||||
{
|
||||
std::map<unsigned int, global_nets_type>::const_iterator g = m_global_connections.find (l);
|
||||
if (g != m_global_connections.end ()) {
|
||||
return g->second.end ();
|
||||
} else {
|
||||
return s_empty_global_nets.end ();
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
Connectivity::connect_global (unsigned int l, const std::string &gn)
|
||||
{
|
||||
for (std::vector<std::string>::const_iterator i = m_global_net_names.begin (); i != m_global_net_names.end (); ++i) {
|
||||
if (*i == gn) {
|
||||
size_t id = i - m_global_net_names.begin ();
|
||||
m_global_connections [l].insert (id);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
size_t id = m_global_net_names.size ();
|
||||
m_global_connections [l].insert (id);
|
||||
m_global_net_names.push_back (gn);
|
||||
return id;
|
||||
}
|
||||
|
||||
size_t
|
||||
Connectivity::connect_global (const db::DeepLayer &l, const std::string &gn)
|
||||
{
|
||||
return connect_global (l.layer (), gn);
|
||||
}
|
||||
|
||||
const std::string &
|
||||
Connectivity::global_net_name (size_t id) const
|
||||
{
|
||||
tl_assert (id < m_global_net_names.size ());
|
||||
return m_global_net_names [id];
|
||||
}
|
||||
|
||||
Connectivity::layer_iterator
|
||||
Connectivity::begin_layers () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ class DB_PUBLIC Connectivity
|
|||
public:
|
||||
typedef std::set<unsigned int> layers_type;
|
||||
typedef layers_type::const_iterator layer_iterator;
|
||||
typedef std::set<size_t> global_nets_type;
|
||||
typedef global_nets_type::const_iterator global_nets_iterator;
|
||||
|
||||
/**
|
||||
* @brief Creates a connectivity object without any connections
|
||||
|
|
@ -68,6 +70,11 @@ public:
|
|||
*/
|
||||
void connect (unsigned int la, unsigned int lb);
|
||||
|
||||
/**
|
||||
* @brief Adds a connection to a global net
|
||||
*/
|
||||
size_t connect_global (unsigned int l, const std::string &gn);
|
||||
|
||||
/**
|
||||
* @brief Adds intra-layer connectivity for layer l
|
||||
* This is a convenience method that takes a db::DeepLayer object.
|
||||
|
|
@ -82,6 +89,16 @@ public:
|
|||
*/
|
||||
void connect (const db::DeepLayer &la, const db::DeepLayer &lb);
|
||||
|
||||
/**
|
||||
* @brief Adds a connection to a global net
|
||||
*/
|
||||
size_t connect_global (const db::DeepLayer &la, const std::string &gn);
|
||||
|
||||
/**
|
||||
* @brief Gets the global net name per ID
|
||||
*/
|
||||
const std::string &global_net_name (size_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the layers involved
|
||||
*/
|
||||
|
|
@ -102,6 +119,16 @@ public:
|
|||
*/
|
||||
layer_iterator end_connected (unsigned int layer) const;
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the global connections for a specific layer
|
||||
*/
|
||||
global_nets_iterator begin_global_connections (unsigned int layer) const;
|
||||
|
||||
/**
|
||||
* @brief End iterator for the layers connected to a specific layer
|
||||
*/
|
||||
global_nets_iterator end_global_connections (unsigned int layer) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the given shapes on the given layers interact
|
||||
*
|
||||
|
|
@ -123,6 +150,8 @@ public:
|
|||
private:
|
||||
layers_type m_all_layers;
|
||||
std::map<unsigned int, layers_type> m_connected;
|
||||
std::vector<std::string> m_global_net_names;
|
||||
std::map<unsigned int, global_nets_type> m_global_connections;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -149,6 +149,27 @@ void LayoutToNetlist::connect (const db::Region &a, const db::Region &b)
|
|||
m_conn.connect (dla.layer (), dlb.layer ());
|
||||
}
|
||||
|
||||
size_t LayoutToNetlist::connect_global (const db::Region &l, const std::string &gn)
|
||||
{
|
||||
if (m_netlist_extracted) {
|
||||
throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted")));
|
||||
}
|
||||
if (! is_deep (l)) {
|
||||
throw (tl::Exception (tl::to_string (tr ("Non-hierarchical layers cannot be used in intra-layer connectivity for netlist extraction"))));
|
||||
}
|
||||
|
||||
// we need to keep a reference, so we can safely delete the region
|
||||
db::DeepLayer dl (l);
|
||||
m_dlrefs.insert (dl);
|
||||
|
||||
return m_conn.connect_global (dl.layer (), gn);
|
||||
}
|
||||
|
||||
const std::string &LayoutToNetlist::global_net_name (size_t id) const
|
||||
{
|
||||
return m_conn.global_net_name (id);
|
||||
}
|
||||
|
||||
void LayoutToNetlist::extract_netlist ()
|
||||
{
|
||||
if (m_netlist_extracted) {
|
||||
|
|
|
|||
|
|
@ -165,6 +165,17 @@ public:
|
|||
*/
|
||||
void connect (const db::Region &a, const db::Region &b);
|
||||
|
||||
/**
|
||||
* @brief Connects the given layer with a global net with the given name
|
||||
* Returns the global net ID
|
||||
*/
|
||||
size_t connect_global (const db::Region &l, const std::string &gn);
|
||||
|
||||
/**
|
||||
* @brief Gets the global net name for a given global net ID
|
||||
*/
|
||||
const std::string &global_net_name (size_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Runs the netlist extraction
|
||||
* See the class description for more details.
|
||||
|
|
|
|||
|
|
@ -113,8 +113,22 @@ const Net *Device::net_for_terminal (size_t terminal_id) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Device::connect_terminal_global (size_t terminal_id, size_t global_net_id)
|
||||
{
|
||||
connect_terminal (terminal_id, 0);
|
||||
m_global_connections.push_back (std::make_pair (terminal_id, global_net_id));
|
||||
}
|
||||
|
||||
void Device::connect_terminal (size_t terminal_id, Net *net)
|
||||
{
|
||||
for (size_t i = 0; i < m_global_connections.size (); ) {
|
||||
if (m_global_connections [i].first == terminal_id) {
|
||||
m_global_connections.erase (m_global_connections.begin () + i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if (net_for_terminal (terminal_id) == net) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -806,6 +806,9 @@ class DB_PUBLIC Device
|
|||
: public tl::Object
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::pair<size_t, size_t> > global_connections;
|
||||
typedef global_connections::const_iterator global_connections_iterator;
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
|
|
@ -881,6 +884,31 @@ public:
|
|||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the global connections iterator (begin)
|
||||
* Global connections are terminals attached to a global net.
|
||||
* This iterator delivers a pair of terminal ID (first)
|
||||
* and global net ID (second).
|
||||
* See Connectivity for the definition of the global net ID.
|
||||
*/
|
||||
global_connections_iterator begin_global_connections () const
|
||||
{
|
||||
return m_global_connections.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the global connections iterator (end)
|
||||
*/
|
||||
global_connections_iterator end_global_connections () const
|
||||
{
|
||||
return m_global_connections.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connects the given terminal to the given global net
|
||||
*/
|
||||
void connect_terminal_global (size_t terminal_id, size_t global_net_id);
|
||||
|
||||
/**
|
||||
* @brief Gets the net attached to a specific terminal
|
||||
* Returns 0 if no net is attached.
|
||||
|
|
@ -901,6 +929,8 @@ public:
|
|||
* If the net is 0 the terminal is disconnected.
|
||||
* If non-null, a NetTerminalRef object will be inserted into the
|
||||
* net and connected with the given terminal.
|
||||
* If the terminal is connected to a global net, it will be
|
||||
* disconnected from there.
|
||||
*/
|
||||
void connect_terminal (size_t terminal_id, Net *net);
|
||||
|
||||
|
|
@ -936,6 +966,7 @@ private:
|
|||
std::vector<double> m_parameters;
|
||||
size_t m_id;
|
||||
Circuit *mp_circuit;
|
||||
global_connections m_global_connections;
|
||||
|
||||
/**
|
||||
* @brief Sets the terminal reference for a specific terminal
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect
|
|||
circuits.insert (std::make_pair (c->cell_index (), c.operator-> ()));
|
||||
}
|
||||
|
||||
std::map<db::cell_index_type, std::map<size_t, size_t> > pins_per_cluster;
|
||||
std::map<db::cell_index_type, std::map<size_t, size_t> > pins_per_cluster_per_cell;
|
||||
std::map<db::cell_index_type, std::map<size_t, db::Net *> > global_nets_per_cell;
|
||||
|
||||
for (db::Layout::bottom_up_const_iterator cid = layout.begin_bottom_up (); cid != layout.end_bottom_up (); ++cid) {
|
||||
|
||||
|
|
@ -88,7 +89,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect
|
|||
circuit = k->second;
|
||||
}
|
||||
|
||||
std::map<size_t, size_t> &c2p = pins_per_cluster [*cid];
|
||||
std::map<size_t, db::Net *> &global_nets = global_nets_per_cell [*cid];
|
||||
std::map<size_t, size_t> &c2p = pins_per_cluster_per_cell [*cid];
|
||||
|
||||
std::map<db::InstElement, db::SubCircuit *> subcircuits;
|
||||
|
||||
|
|
@ -98,8 +100,19 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect
|
|||
net->set_cluster_id (*c);
|
||||
circuit->add_net (net);
|
||||
|
||||
// make global net connections for clusters which connect to such
|
||||
std::set<size_t> global_net_ids;
|
||||
std::vector<unsigned int> layers = clusters.cluster_by_id (*c).layers ();
|
||||
for (std::vector<unsigned int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||
global_net_ids.insert (conn.begin_global_connections (*l), conn.end_global_connections (*l));
|
||||
}
|
||||
for (std::set<size_t>::const_iterator g = global_net_ids.begin (); g != global_net_ids.end (); ++g) {
|
||||
global_nets.insert (std::make_pair (*g, net));
|
||||
assign_net_name (conn.global_net_name (*g), net);
|
||||
}
|
||||
|
||||
// make subcircuit connections (also make the subcircuits if required) from the connections of the clusters
|
||||
make_and_connect_subcircuits (circuit, clusters, *c, net, subcircuits, circuits, pins_per_cluster, layout.dbu ());
|
||||
make_and_connect_subcircuits (circuit, clusters, *c, net, subcircuits, circuits, pins_per_cluster_per_cell, layout.dbu ());
|
||||
|
||||
// collect the properties - we know that the cluster attributes are property ID's because the
|
||||
// cluster processor converts shape property IDs to attributes
|
||||
|
|
@ -110,7 +123,7 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect
|
|||
if (terminal_annot_name_id.first && j->first == terminal_annot_name_id.second) {
|
||||
make_device_terminal_from_property (j->second, circuit, net);
|
||||
} else if (text_annot_name_id.first && j->first == text_annot_name_id.second) {
|
||||
make_net_name_from_property (j->second, net);
|
||||
assign_net_name (j->second.to_string (), net);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -123,6 +136,49 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect
|
|||
|
||||
}
|
||||
|
||||
// make global net connections for devices
|
||||
for (db::Circuit::device_iterator d = circuit->begin_devices (); d != circuit->end_devices (); ++d) {
|
||||
|
||||
for (db::Device::global_connections_iterator g = d->begin_global_connections (); g != d->end_global_connections (); ++g) {
|
||||
|
||||
db::Net *&net = global_nets [g->second];
|
||||
if (! net) {
|
||||
net = new db::Net (conn.global_net_name (g->second));
|
||||
circuit->add_net (net);
|
||||
}
|
||||
|
||||
net->add_terminal (db::NetTerminalRef (d.operator-> (), g->first));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// make the global net connections into subcircuits - if necessary by creating pins into the subcircuit
|
||||
for (db::Circuit::subcircuit_iterator sc = circuit->begin_subcircuits (); sc != circuit->end_subcircuits (); ++sc) {
|
||||
|
||||
db::Circuit *subcircuit = sc->circuit_ref ();
|
||||
|
||||
const std::map<size_t, db::Net *> &sc_gn = global_nets_per_cell [subcircuit->cell_index ()];
|
||||
for (std::map<size_t, db::Net *>::const_iterator g = global_nets.begin (); g != global_nets.end (); ++g) {
|
||||
|
||||
std::map<size_t, db::Net *>::const_iterator gg = sc_gn.find (g->first);
|
||||
if (gg != sc_gn.end ()) {
|
||||
|
||||
size_t pin_id = 0;
|
||||
if (gg->second->pin_count () > 0) {
|
||||
pin_id = gg->second->begin_pins ()->pin_id ();
|
||||
} else {
|
||||
pin_id = subcircuit->add_pin (conn.global_net_name (gg->first)).id ();
|
||||
subcircuit->connect_pin (pin_id, gg->second);
|
||||
}
|
||||
g->second->add_subcircuit_pin (db::NetSubcircuitPinRef (sc.operator-> (), pin_id));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,14 +248,14 @@ void NetlistExtractor::make_device_terminal_from_property (const tl::Variant &v,
|
|||
}
|
||||
}
|
||||
|
||||
void NetlistExtractor::make_net_name_from_property (const tl::Variant &v, db::Net *net)
|
||||
void NetlistExtractor::assign_net_name (const std::string &n, db::Net *net)
|
||||
{
|
||||
std::string n = v.to_string ();
|
||||
if (! n.empty ()) {
|
||||
std::string nn = n;
|
||||
if (! nn.empty ()) {
|
||||
if (! net->name ().empty ()) {
|
||||
n = net->name () + "," + n;
|
||||
nn = net->name () + "," + nn;
|
||||
}
|
||||
net->set_name (n);
|
||||
net->set_name (nn);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ private:
|
|||
hier_clusters_type m_net_clusters;
|
||||
|
||||
void make_device_terminal_from_property (const tl::Variant &v, db::Circuit *circuit, db::Net *net);
|
||||
void make_net_name_from_property (const tl::Variant &v, db::Net *net);
|
||||
void assign_net_name (const std::string &n, db::Net *net);
|
||||
|
||||
/**
|
||||
* @brief Make a pin connection from clusters
|
||||
|
|
|
|||
|
|
@ -32,6 +32,13 @@ Class<db::Connectivity> decl_dbConnectivity ("db", "Connectivity",
|
|||
) +
|
||||
gsi::method ("connect", (void (db::Connectivity::*) (unsigned int, unsigned int)) &db::Connectivity::connect, gsi::arg ("layer_a"), gsi::arg ("layer_b"),
|
||||
"@brief Specifies inter-layer connectivity.\n"
|
||||
) +
|
||||
gsi::method ("connect_global", (size_t (db::Connectivity::*) (unsigned int, const std::string &)) &db::Connectivity::connect_global, gsi::arg ("layer"), gsi::arg ("global_net_name"),
|
||||
"@brief Connects the given layer to the global net given by name.\n"
|
||||
"Returns the ID of the global net."
|
||||
) +
|
||||
gsi::method ("global", &db::Connectivity::global_net_name, gsi::arg ("global_net_id"),
|
||||
"@brief Gets the name for a given global net ID.\n"
|
||||
),
|
||||
"@brief This class specifies connections between different layers."
|
||||
"Connections are build using \\connect. There are basically two flavours of connections: intra-layer and inter-layer.\n"
|
||||
|
|
@ -45,6 +52,11 @@ Class<db::Connectivity> decl_dbConnectivity ("db", "Connectivity",
|
|||
"\n"
|
||||
"All layers are specified in terms of layer indexes. Layer indexes are layout layer indexes (see \\Layout class).\n"
|
||||
"\n"
|
||||
"The connectivity object also manages the global nets. Global nets are substrate for example "
|
||||
"and they are propagated automatically from subcircuits to circuits. "
|
||||
"Global nets are defined by name and are managed through IDs. To get the name for a given ID, use "
|
||||
"\\global_net_name."
|
||||
"\n"
|
||||
"This class has been introduced in version 0.26.\n"
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -123,6 +123,14 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
|||
"@brief Defines an inter-layer connection for the given layers.\n"
|
||||
"The conditions mentioned with intra-layer \\connect apply for this method too.\n"
|
||||
) +
|
||||
gsi::method ("connect_global", (void (db::LayoutToNetlist::*) (const db::Region &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"),
|
||||
"@brief Defines a connection of the given layer with a global net.\n"
|
||||
"This method returns the ID of the global net. Use \\global_net_name to get "
|
||||
"the name back from the ID."
|
||||
) +
|
||||
gsi::method ("global_net_name", &db::LayoutToNetlist::global_net_name, gsi::arg ("global_net_id"),
|
||||
"@brief Gets the global net name for the given global net ID."
|
||||
) +
|
||||
gsi::method ("extract_netlist", &db::LayoutToNetlist::extract_netlist,
|
||||
"@brief Runs the netlist extraction\n"
|
||||
"See the class description for more details.\n"
|
||||
|
|
|
|||
|
|
@ -61,6 +61,44 @@ static void device_disconnect_terminal_by_name (db::Device *device, const std::s
|
|||
device_connect_terminal_by_name (device, terminal_name, 0);
|
||||
}
|
||||
|
||||
static tl::Variant device_terminal_for_global_net (const db::Device *device, size_t global_net)
|
||||
{
|
||||
for (db::Device::global_connections_iterator g = device->begin_global_connections (); g != device->end_global_connections (); ++g) {
|
||||
if (g->second == global_net) {
|
||||
return tl::Variant (g->first);
|
||||
}
|
||||
}
|
||||
return tl::Variant ();
|
||||
}
|
||||
|
||||
static tl::Variant device_global_net_for_terminal (const db::Device *device, size_t terminal_id)
|
||||
{
|
||||
for (db::Device::global_connections_iterator g = device->begin_global_connections (); g != device->end_global_connections (); ++g) {
|
||||
if (g->first == terminal_id) {
|
||||
return tl::Variant (g->second);
|
||||
}
|
||||
}
|
||||
return tl::Variant ();
|
||||
}
|
||||
|
||||
static tl::Variant device_global_net_for_terminal_name (const db::Device *device, const std::string &terminal_name)
|
||||
{
|
||||
if (! device->device_class ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Device does not have a device class")));
|
||||
}
|
||||
size_t terminal_id = device->device_class ()->terminal_id_for_name (terminal_name);
|
||||
return device_global_net_for_terminal (device, terminal_id);
|
||||
}
|
||||
|
||||
static void device_connect_terminal_global_by_name (db::Device *device, const std::string &terminal_name, size_t global_net)
|
||||
{
|
||||
if (! device->device_class ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Device does not have a device class")));
|
||||
}
|
||||
size_t terminal_id = device->device_class ()->terminal_id_for_name (terminal_name);
|
||||
device->connect_terminal_global (terminal_id, global_net);
|
||||
}
|
||||
|
||||
Class<db::Device> decl_dbDevice ("db", "Device",
|
||||
gsi::method ("device_class", &db::Device::device_class,
|
||||
"@brief Gets the device class the device belongs to.\n"
|
||||
|
|
@ -91,15 +129,37 @@ Class<db::Device> decl_dbDevice ("db", "Device",
|
|||
) +
|
||||
gsi::method_ext ("disconnect_terminal", &device_disconnect_terminal, gsi::arg ("terminal_id"),
|
||||
"@brief Disconnects the given terminal from any net.\n"
|
||||
"If the terminal has been connected to a global, this connection will be disconnected too."
|
||||
) +
|
||||
gsi::method_ext ("connect_terminal", &device_connect_terminal_by_name, gsi::arg ("terminal_name"), gsi::arg ("net"),
|
||||
"@brief Connects the given terminal to the specified net.\n"
|
||||
"This version accepts a terminal name. If the name is not a valid terminal name, an exception is raised."
|
||||
"This version accepts a terminal name. If the name is not a valid terminal name, an exception is raised.\n"
|
||||
"If the terminal has been connected to a global net, it will be disconnected from there."
|
||||
) +
|
||||
gsi::method_ext ("disconnect_terminal", &device_disconnect_terminal_by_name, gsi::arg ("terminal_name"),
|
||||
"@brief Disconnects the given terminal from any net.\n"
|
||||
"This version accepts a terminal name. If the name is not a valid terminal name, an exception is raised."
|
||||
) +
|
||||
gsi::method ("connect_terminal_global", &db::Device::connect_terminal_global, gsi::arg ("terminal_id"), gsi::arg ("global_net_id"),
|
||||
"@brief Connects the given terminal to the given global net.\n"
|
||||
"The global net ID is taken from \\Connectivity (connect_global, etc.).\n"
|
||||
"If the terminal was already connected to another net, it will be disconnected from there."
|
||||
) +
|
||||
gsi::method_ext ("connect_terminal_global", &device_connect_terminal_global_by_name, gsi::arg ("terminal_name"), gsi::arg ("global_net_id"),
|
||||
"@brief Connects the given terminal to the given global net.\n"
|
||||
"This version accepts a terminal name. If the name is not a valid terminal name, an exception is raised."
|
||||
) +
|
||||
gsi::method_ext ("terminal_on_global_net", &device_terminal_for_global_net, gsi::arg ("global_net_id"),
|
||||
"@brief Gets the terminal ID for the given global net or nil if no terminal is not that global net.\n"
|
||||
"The global net ID is managed by the \\Connectivity object."
|
||||
) +
|
||||
gsi::method_ext ("global_net_on_terminal", &device_global_net_for_terminal, gsi::arg ("terminal_id"),
|
||||
"@brief Gets the global net ID for the given terminal ID or nil if the terminal is not connected to a global net.\n"
|
||||
) +
|
||||
gsi::method_ext ("global_net_on_terminal", &device_global_net_for_terminal_name, gsi::arg ("terminal_name"),
|
||||
"@brief Gets the global net ID for the given terminal name or nil if the terminal is not connected to a global net.\n"
|
||||
"If the name is not a valid terminal name, an exception is raised."
|
||||
) +
|
||||
gsi::method ("parameter", (double (db::Device::*) (size_t) const) &db::Device::parameter_value, gsi::arg ("param_id"),
|
||||
"@brief Gets the parameter value for the given parameter ID."
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -44,6 +44,18 @@ static std::string l2s (db::Connectivity::layer_iterator b, db::Connectivity::la
|
|||
return s;
|
||||
}
|
||||
|
||||
static std::string gn2s (db::Connectivity::global_nets_iterator b, db::Connectivity::global_nets_iterator e)
|
||||
{
|
||||
std::string s;
|
||||
for (db::Connectivity::global_nets_iterator i = b; i != e; ++i) {
|
||||
if (! s.empty ()) {
|
||||
s += ",";
|
||||
}
|
||||
s += tl::to_string (*i);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
TEST(1_Connectivity)
|
||||
{
|
||||
db::Connectivity conn;
|
||||
|
|
@ -69,6 +81,27 @@ TEST(1_Connectivity)
|
|||
EXPECT_EQ (l2s (conn.begin_connected (0), conn.end_connected (0)), "0,1,2");
|
||||
EXPECT_EQ (l2s (conn.begin_connected (1), conn.end_connected (1)), "0,1");
|
||||
EXPECT_EQ (l2s (conn.begin_connected (2), conn.end_connected (2)), "0,2");
|
||||
|
||||
EXPECT_EQ (conn.connect_global (0, "GLOBAL"), size_t (0));
|
||||
EXPECT_EQ (gn2s (conn.begin_global_connections (2), conn.end_global_connections (2)), "");
|
||||
EXPECT_EQ (gn2s (conn.begin_global_connections (0), conn.end_global_connections (0)), "0");
|
||||
EXPECT_EQ (conn.connect_global (2, "GLOBAL2"), size_t (1));
|
||||
EXPECT_EQ (gn2s (conn.begin_global_connections (2), conn.end_global_connections (2)), "1");
|
||||
EXPECT_EQ (conn.connect_global (0, "GLOBAL2"), size_t (1));
|
||||
EXPECT_EQ (gn2s (conn.begin_global_connections (0), conn.end_global_connections (0)), "0,1");
|
||||
|
||||
EXPECT_EQ (conn.global_net_name (0), "GLOBAL");
|
||||
EXPECT_EQ (conn.global_net_name (1), "GLOBAL2");
|
||||
|
||||
db::Connectivity conn2 = conn;
|
||||
|
||||
EXPECT_EQ (l2s (conn2.begin_connected (0), conn2.end_connected (0)), "0,1,2");
|
||||
EXPECT_EQ (l2s (conn2.begin_connected (1), conn2.end_connected (1)), "0,1");
|
||||
EXPECT_EQ (l2s (conn2.begin_connected (2), conn2.end_connected (2)), "0,2");
|
||||
|
||||
EXPECT_EQ (gn2s (conn2.begin_global_connections (0), conn2.end_global_connections (0)), "0,1");
|
||||
EXPECT_EQ (conn2.global_net_name (0), "GLOBAL");
|
||||
EXPECT_EQ (conn2.global_net_name (1), "GLOBAL2");
|
||||
}
|
||||
|
||||
TEST(2_ShapeInteractions)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ TEST(1_DeviceTerminalDefinition)
|
|||
|
||||
dc.clear_parameter_definitions ();
|
||||
EXPECT_EQ (dc.parameter_definitions ().empty (), true);
|
||||
|
||||
}
|
||||
|
||||
TEST(2_DeviceClass)
|
||||
|
|
@ -1025,3 +1024,53 @@ TEST(12_NetlistTopology)
|
|||
EXPECT_EQ (td2string (nl.get ()), "c1,c3,c2");
|
||||
EXPECT_EQ (bu2string (nl.get ()), "c2,c3,c1");
|
||||
}
|
||||
|
||||
TEST(13_DeviceGlobalNets)
|
||||
{
|
||||
db::DeviceTerminalDefinition pd;
|
||||
pd.set_name ("name");
|
||||
pd.set_description ("nothing yet");
|
||||
|
||||
db::DeviceTerminalDefinition pd2;
|
||||
pd2.set_name ("name2");
|
||||
pd2.set_description ("now it has something");
|
||||
|
||||
db::DeviceClass dc;
|
||||
dc.set_name ("devname");
|
||||
dc.set_description ("devdesc");
|
||||
dc.add_terminal_definition (pd);
|
||||
dc.add_terminal_definition (pd2);
|
||||
|
||||
db::Device d (&dc);
|
||||
db::Net n;
|
||||
|
||||
d.connect_terminal_global (0, 17);
|
||||
|
||||
db::Device::global_connections_iterator g;
|
||||
|
||||
g = d.begin_global_connections ();
|
||||
EXPECT_EQ (g != d.end_global_connections (), true);
|
||||
EXPECT_EQ (g->first, size_t (0));
|
||||
EXPECT_EQ (g->second, size_t (17));
|
||||
|
||||
++g;
|
||||
EXPECT_EQ (g == d.end_global_connections (), true);
|
||||
|
||||
d.connect_terminal (0, &n);
|
||||
g = d.begin_global_connections ();
|
||||
EXPECT_EQ (g == d.end_global_connections (), true);
|
||||
EXPECT_EQ (d.net_for_terminal (0) == &n, true);
|
||||
|
||||
d.connect_terminal_global (0, 17);
|
||||
EXPECT_EQ (d.net_for_terminal (0) == 0, true);
|
||||
|
||||
g = d.begin_global_connections ();
|
||||
EXPECT_EQ (g != d.end_global_connections (), true);
|
||||
EXPECT_EQ (g->first, size_t (0));
|
||||
EXPECT_EQ (g->second, size_t (17));
|
||||
|
||||
d.connect_terminal (0, 0);
|
||||
g = d.begin_global_connections ();
|
||||
EXPECT_EQ (g == d.end_global_connections (), true);
|
||||
EXPECT_EQ (d.net_for_terminal (0) == 0, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ class DBLayoutToNetlist_TestClass < TestBase
|
|||
assert_equal(l2n.internal_layout.cell(ci).name, ly2.cell(cm.cell_mapping(ci)).name)
|
||||
end
|
||||
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0) )
|
||||
bulk_id = l2n.connect_global(rmetal1, "BULK")
|
||||
assert_equal(l2n.global_net_name(bulk_id), "BULK")
|
||||
|
||||
end
|
||||
|
||||
def test_2_ShapesFromNet
|
||||
|
|
|
|||
|
|
@ -257,6 +257,16 @@ class DBNetlist_TestClass < TestBase
|
|||
assert_equal(d1.net_for_terminal(1).inspect, "nil")
|
||||
assert_equal(d1.net_for_terminal(0).inspect, "nil")
|
||||
|
||||
d2.connect_terminal(0, net)
|
||||
assert_equal(net.terminal_count, 1)
|
||||
d2.connect_terminal_global(0, 1)
|
||||
assert_equal(net.terminal_count, 0)
|
||||
|
||||
assert_equal(d2.terminal_on_global_net(1), 0)
|
||||
assert_equal(d2.terminal_on_global_net(17).inspect, "nil")
|
||||
assert_equal(d2.global_net_on_terminal(0), 1)
|
||||
assert_equal(d2.global_net_on_terminal(1).inspect, "nil")
|
||||
|
||||
end
|
||||
|
||||
def test_5_SubCircuit
|
||||
|
|
|
|||
Loading…
Reference in New Issue