mirror of https://github.com/KLayout/klayout.git
WIP: refactoring - singularization of classes in separate files.
This commit is contained in:
parent
9fa5618034
commit
baf50bd0b1
|
|
@ -153,7 +153,13 @@ SOURCES = \
|
|||
gsiDeclDbHierNetworkProcessor.cc \
|
||||
dbNetlistDeviceExtractorClasses.cc \
|
||||
dbLayoutToNetlist.cc \
|
||||
gsiDeclDbLayoutToNetlist.cc
|
||||
gsiDeclDbLayoutToNetlist.cc \
|
||||
dbCircuit.cc \
|
||||
dbDevice.cc \
|
||||
dbDeviceClass.cc \
|
||||
dbNet.cc \
|
||||
dbSubCircuit.cc \
|
||||
dbPin.cc
|
||||
|
||||
HEADERS = \
|
||||
dbArray.h \
|
||||
|
|
@ -270,7 +276,14 @@ HEADERS = \
|
|||
dbNetlistExtractor.h \
|
||||
dbNetlistDeviceExtractorClasses.h \
|
||||
dbLayoutToNetlist.h \
|
||||
dbHierNetworkProcessor.h
|
||||
dbHierNetworkProcessor.h \
|
||||
dbNetlistUtils.h \
|
||||
dbNet.h \
|
||||
dbCircuit.h \
|
||||
dbDevice.h \
|
||||
dbDeviceClass.h \
|
||||
dbPin.h \
|
||||
dbSubCircuit.h
|
||||
|
||||
!equals(HAVE_QT, "0") {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,567 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbCircuit.h"
|
||||
#include "dbNetlist.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Circuit class implementation
|
||||
|
||||
Circuit::Circuit ()
|
||||
: mp_netlist (0),
|
||||
m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices),
|
||||
m_subcircuit_by_id (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
|
||||
m_net_by_cluster_id (this, &Circuit::begin_nets, &Circuit::end_nets),
|
||||
m_device_by_name (this, &Circuit::begin_devices, &Circuit::end_devices),
|
||||
m_subcircuit_by_name (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
|
||||
m_net_by_name (this, &Circuit::begin_nets, &Circuit::end_nets),
|
||||
m_index (0)
|
||||
{
|
||||
m_devices.changed ().add (this, &Circuit::devices_changed);
|
||||
m_nets.changed ().add (this, &Circuit::nets_changed);
|
||||
m_subcircuits.changed ().add (this, &Circuit::subcircuits_changed);
|
||||
}
|
||||
|
||||
Circuit::Circuit (const Circuit &other)
|
||||
: mp_netlist (0),
|
||||
m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices),
|
||||
m_subcircuit_by_id (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
|
||||
m_net_by_cluster_id (this, &Circuit::begin_nets, &Circuit::end_nets),
|
||||
m_device_by_name (this, &Circuit::begin_devices, &Circuit::end_devices),
|
||||
m_subcircuit_by_name (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
|
||||
m_net_by_name (this, &Circuit::begin_nets, &Circuit::end_nets),
|
||||
m_index (0)
|
||||
{
|
||||
operator= (other);
|
||||
m_devices.changed ().add (this, &Circuit::devices_changed);
|
||||
m_nets.changed ().add (this, &Circuit::nets_changed);
|
||||
m_subcircuits.changed ().add (this, &Circuit::subcircuits_changed);
|
||||
}
|
||||
|
||||
Circuit::~Circuit ()
|
||||
{
|
||||
m_devices.changed ().remove (this, &Circuit::devices_changed);
|
||||
m_nets.changed ().remove (this, &Circuit::nets_changed);
|
||||
m_subcircuits.changed ().remove (this, &Circuit::subcircuits_changed);
|
||||
|
||||
// the default destructor will make the nets access "this" to unregister the
|
||||
// objects - hence we have to do this explicitly.
|
||||
m_nets.clear ();
|
||||
m_subcircuits.clear ();
|
||||
m_devices.clear ();
|
||||
}
|
||||
|
||||
Circuit &Circuit::operator= (const Circuit &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
|
||||
clear ();
|
||||
|
||||
m_name = other.m_name;
|
||||
m_pins = other.m_pins;
|
||||
|
||||
std::map<const Device *, Device *> device_table;
|
||||
for (const_device_iterator i = other.begin_devices (); i != other.end_devices (); ++i) {
|
||||
Device *d = new Device (*i);
|
||||
device_table [i.operator-> ()] = d;
|
||||
add_device (d);
|
||||
}
|
||||
|
||||
std::map<const SubCircuit *, SubCircuit *> sc_table;
|
||||
for (const_subcircuit_iterator i = other.begin_subcircuits (); i != other.end_subcircuits (); ++i) {
|
||||
SubCircuit *sc = new SubCircuit (*i);
|
||||
sc_table [i.operator-> ()] = sc;
|
||||
add_subcircuit (sc);
|
||||
}
|
||||
|
||||
for (const_net_iterator i = other.begin_nets (); i != other.end_nets (); ++i) {
|
||||
|
||||
// translate the net
|
||||
Net *n = new Net ();
|
||||
n->set_cluster_id (i->cluster_id ());
|
||||
n->set_name (i->name ());
|
||||
add_net (n);
|
||||
|
||||
for (Net::const_terminal_iterator p = i->begin_terminals (); p != i->end_terminals (); ++p) {
|
||||
std::map<const Device *, Device *>::const_iterator m = device_table.find (p->device ());
|
||||
tl_assert (m != device_table.end ());
|
||||
n->add_terminal (NetTerminalRef (m->second, p->terminal_id ()));
|
||||
}
|
||||
|
||||
for (Net::const_pin_iterator p = i->begin_pins (); p != i->end_pins (); ++p) {
|
||||
n->add_pin (NetPinRef (p->pin_id ()));
|
||||
}
|
||||
|
||||
for (Net::const_subcircuit_pin_iterator p = i->begin_subcircuit_pins (); p != i->end_subcircuit_pins (); ++p) {
|
||||
std::map<const SubCircuit *, SubCircuit *>::const_iterator m = sc_table.find (p->subcircuit ());
|
||||
tl_assert (m != sc_table.end ());
|
||||
n->add_subcircuit_pin (NetSubcircuitPinRef (m->second, p->pin_id ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Circuit::set_netlist (Netlist *netlist)
|
||||
{
|
||||
mp_netlist = netlist;
|
||||
}
|
||||
|
||||
const Pin *Circuit::pin_by_id (size_t id) const
|
||||
{
|
||||
if (id >= m_pins.size ()) {
|
||||
return 0;
|
||||
} else {
|
||||
return &m_pins [id];
|
||||
}
|
||||
}
|
||||
|
||||
const Pin *Circuit::pin_by_name (const std::string &name) const
|
||||
{
|
||||
for (Circuit::const_pin_iterator p = begin_pins (); p != end_pins (); ++p) {
|
||||
if (p->name () == name) {
|
||||
return p.operator-> ();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Circuit::devices_changed ()
|
||||
{
|
||||
m_device_by_id.invalidate ();
|
||||
m_device_by_name.invalidate ();
|
||||
}
|
||||
|
||||
void Circuit::subcircuits_changed ()
|
||||
{
|
||||
m_subcircuit_by_id.invalidate ();
|
||||
m_subcircuit_by_name.invalidate ();
|
||||
|
||||
if (mp_netlist) {
|
||||
mp_netlist->invalidate_topology ();
|
||||
}
|
||||
}
|
||||
|
||||
void Circuit::nets_changed ()
|
||||
{
|
||||
m_net_by_cluster_id.invalidate ();
|
||||
m_net_by_name.invalidate ();
|
||||
}
|
||||
|
||||
void Circuit::clear ()
|
||||
{
|
||||
m_name.clear ();
|
||||
m_pins.clear ();
|
||||
m_devices.clear ();
|
||||
m_nets.clear ();
|
||||
m_subcircuits.clear ();
|
||||
}
|
||||
|
||||
void Circuit::set_name (const std::string &name)
|
||||
{
|
||||
m_name = name;
|
||||
if (mp_netlist) {
|
||||
mp_netlist->m_circuit_by_name.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
void Circuit::set_cell_index (const db::cell_index_type ci)
|
||||
{
|
||||
m_cell_index = ci;
|
||||
if (mp_netlist) {
|
||||
mp_netlist->m_circuit_by_cell_index.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
Circuit::child_circuit_iterator Circuit::begin_children ()
|
||||
{
|
||||
tl_assert (mp_netlist != 0);
|
||||
return mp_netlist->child_circuits (this).begin ();
|
||||
}
|
||||
|
||||
Circuit::child_circuit_iterator Circuit::end_children ()
|
||||
{
|
||||
tl_assert (mp_netlist != 0);
|
||||
return mp_netlist->child_circuits (this).end ();
|
||||
}
|
||||
|
||||
Circuit::const_child_circuit_iterator Circuit::begin_children () const
|
||||
{
|
||||
tl_assert (mp_netlist != 0);
|
||||
return reinterpret_cast<const tl::vector<const Circuit *> &> (mp_netlist->child_circuits (const_cast <Circuit *> (this))).begin ();
|
||||
}
|
||||
|
||||
Circuit::const_child_circuit_iterator Circuit::end_children () const
|
||||
{
|
||||
tl_assert (mp_netlist != 0);
|
||||
return reinterpret_cast<const tl::vector<const Circuit *> &> (mp_netlist->child_circuits (const_cast <Circuit *> (this))).end ();
|
||||
}
|
||||
|
||||
Circuit::child_circuit_iterator Circuit::begin_parents ()
|
||||
{
|
||||
tl_assert (mp_netlist != 0);
|
||||
return mp_netlist->parent_circuits (this).begin ();
|
||||
}
|
||||
|
||||
Circuit::child_circuit_iterator Circuit::end_parents ()
|
||||
{
|
||||
tl_assert (mp_netlist != 0);
|
||||
return mp_netlist->parent_circuits (this).end ();
|
||||
}
|
||||
|
||||
Circuit::const_child_circuit_iterator Circuit::begin_parents () const
|
||||
{
|
||||
tl_assert (mp_netlist != 0);
|
||||
return reinterpret_cast<const tl::vector<const Circuit *> &> (mp_netlist->parent_circuits (const_cast <Circuit *> (this))).begin ();
|
||||
}
|
||||
|
||||
Circuit::const_child_circuit_iterator Circuit::end_parents () const
|
||||
{
|
||||
tl_assert (mp_netlist != 0);
|
||||
return reinterpret_cast<const tl::vector<const Circuit *> &> (mp_netlist->parent_circuits (const_cast <Circuit *> (this))).end ();
|
||||
}
|
||||
|
||||
const Pin &Circuit::add_pin (const std::string &name)
|
||||
{
|
||||
m_pins.push_back (Pin (name));
|
||||
m_pins.back ().set_id (m_pins.size () - 1);
|
||||
return m_pins.back ();
|
||||
}
|
||||
|
||||
void Circuit::add_net (Net *net)
|
||||
{
|
||||
m_nets.push_back (net);
|
||||
net->set_circuit (this);
|
||||
}
|
||||
|
||||
void Circuit::remove_net (Net *net)
|
||||
{
|
||||
m_nets.erase (net);
|
||||
}
|
||||
|
||||
void Circuit::add_device (Device *device)
|
||||
{
|
||||
device->set_circuit (this);
|
||||
|
||||
size_t id = 0;
|
||||
if (! m_devices.empty ()) {
|
||||
tl_assert (m_devices.back () != 0);
|
||||
id = m_devices.back ()->id ();
|
||||
}
|
||||
device->set_id (id + 1);
|
||||
|
||||
m_devices.push_back (device);
|
||||
}
|
||||
|
||||
void Circuit::remove_device (Device *device)
|
||||
{
|
||||
m_devices.erase (device);
|
||||
}
|
||||
|
||||
void Circuit::add_subcircuit (SubCircuit *subcircuit)
|
||||
{
|
||||
subcircuit->set_circuit (this);
|
||||
|
||||
size_t id = 0;
|
||||
if (! m_subcircuits.empty ()) {
|
||||
tl_assert (m_subcircuits.back () != 0);
|
||||
id = m_subcircuits.back ()->id ();
|
||||
}
|
||||
subcircuit->set_id (id + 1);
|
||||
|
||||
m_subcircuits.push_back (subcircuit);
|
||||
}
|
||||
|
||||
void Circuit::remove_subcircuit (SubCircuit *subcircuit)
|
||||
{
|
||||
m_subcircuits.erase (subcircuit);
|
||||
}
|
||||
|
||||
void Circuit::register_ref (SubCircuit *r)
|
||||
{
|
||||
m_refs.push_back (r);
|
||||
}
|
||||
|
||||
void Circuit::unregister_ref (SubCircuit *r)
|
||||
{
|
||||
m_refs.erase (r);
|
||||
}
|
||||
|
||||
void Circuit::translate_circuits (const std::map<const Circuit *, Circuit *> &map)
|
||||
{
|
||||
for (subcircuit_iterator i = m_subcircuits.begin (); i != m_subcircuits.end (); ++i) {
|
||||
std::map<const Circuit *, Circuit *>::const_iterator m = map.find (i->circuit_ref ());
|
||||
tl_assert (m != map.end ());
|
||||
i->set_circuit_ref (m->second);
|
||||
}
|
||||
}
|
||||
|
||||
void Circuit::translate_device_classes (const std::map<const DeviceClass *, DeviceClass *> &map)
|
||||
{
|
||||
for (device_iterator i = m_devices.begin (); i != m_devices.end (); ++i) {
|
||||
std::map<const DeviceClass *, DeviceClass *>::const_iterator m = map.find (i->device_class ());
|
||||
tl_assert (m != map.end ());
|
||||
i->set_device_class (m->second);
|
||||
}
|
||||
}
|
||||
|
||||
void Circuit::set_pin_ref_for_pin (size_t pin_id, Net::pin_iterator iter)
|
||||
{
|
||||
if (m_pin_refs.size () < pin_id + 1) {
|
||||
m_pin_refs.resize (pin_id + 1, Net::pin_iterator ());
|
||||
}
|
||||
m_pin_refs [pin_id] = iter;
|
||||
}
|
||||
|
||||
const Net *Circuit::net_for_pin (size_t pin_id) const
|
||||
{
|
||||
if (pin_id < m_pin_refs.size ()) {
|
||||
Net::pin_iterator p = m_pin_refs [pin_id];
|
||||
if (p != Net::pin_iterator ()) {
|
||||
return p->net ();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Circuit::connect_pin (size_t pin_id, Net *net)
|
||||
{
|
||||
if (net_for_pin (pin_id) == net) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pin_id < m_pin_refs.size ()) {
|
||||
Net::pin_iterator p = m_pin_refs [pin_id];
|
||||
if (p != Net::pin_iterator () && p->net ()) {
|
||||
p->net ()->erase_pin (p);
|
||||
}
|
||||
m_pin_refs [pin_id] = Net::pin_iterator ();
|
||||
}
|
||||
|
||||
if (net) {
|
||||
net->add_pin (NetPinRef (pin_id));
|
||||
}
|
||||
}
|
||||
|
||||
void Circuit::purge_nets ()
|
||||
{
|
||||
std::vector<db::Net *> nets_to_be_purged;
|
||||
for (net_iterator n = begin_nets (); n != end_nets (); ++n) {
|
||||
if (n->is_floating ()) {
|
||||
nets_to_be_purged.push_back (n.operator-> ());
|
||||
}
|
||||
}
|
||||
for (std::vector<db::Net *>::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) {
|
||||
delete *n;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sanity check for device to be removed
|
||||
*/
|
||||
static void check_device_before_remove (db::Circuit *c, const db::Device *d)
|
||||
{
|
||||
if (d->device_class () == 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Internal error: No device class after removing device in device combination")) + ": name=" + d->name () + ", circuit=" + c->name ());
|
||||
}
|
||||
const std::vector<db::DeviceTerminalDefinition> &pd = d->device_class ()->terminal_definitions ();
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
|
||||
if (d->net_for_terminal (p->id ()) != 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Internal error: Terminal still connected after removing device in device combination")) + ": name=" + d->name () + ", circuit=" + c->name () + ", terminal=" + p->name ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Circuit::combine_parallel_devices (const db::DeviceClass &cls)
|
||||
{
|
||||
typedef std::vector<const db::Net *> key_type;
|
||||
std::map<key_type, std::vector<db::Device *> > combination_candidates;
|
||||
|
||||
bool any = false;
|
||||
|
||||
// identify the candidates for combination - all devices sharing the same nets
|
||||
// are candidates for combination in parallel mode
|
||||
for (device_iterator d = begin_devices (); d != end_devices (); ++d) {
|
||||
|
||||
if (tl::id_of (d->device_class ()) != tl::id_of (&cls)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key_type k;
|
||||
const std::vector<db::DeviceTerminalDefinition> &terminals = cls.terminal_definitions ();
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator p = terminals.begin (); p != terminals.end (); ++p) {
|
||||
const db::Net *n = d->net_for_terminal (p->id ());
|
||||
if (n) {
|
||||
k.push_back (n);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (k.begin (), k.end ());
|
||||
k.erase (std::unique (k.begin (), k.end ()), k.end ());
|
||||
combination_candidates[k].push_back (d.operator-> ());
|
||||
|
||||
}
|
||||
|
||||
// actually combine the devices
|
||||
for (std::map<key_type, std::vector<db::Device *> >::iterator cc = combination_candidates.begin (); cc != combination_candidates.end (); ++cc) {
|
||||
|
||||
std::vector<db::Device *> &cl = cc->second;
|
||||
for (size_t i = 0; i < cl.size () - 1; ++i) {
|
||||
for (size_t j = i + 1; j < cl.size (); ) {
|
||||
if (cls.combine_devices (cl [i], cl [j])) {
|
||||
check_device_before_remove (this, cl [j]); // sanity check
|
||||
delete cl [j];
|
||||
cl.erase (cl.begin () + j);
|
||||
any = true;
|
||||
} else {
|
||||
++j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
static std::pair<db::Device *, db::Device *> attached_two_devices (db::Net &net, const db::DeviceClass &cls)
|
||||
{
|
||||
if (net.begin_pins () != net.end_pins ()) {
|
||||
return std::make_pair ((db::Device *) 0, (db::Device *) 0);
|
||||
}
|
||||
|
||||
db::Device *d1 = 0, *d2 = 0;
|
||||
|
||||
Net::terminal_iterator p = net.begin_terminals ();
|
||||
if (p == net.end_terminals () || tl::id_of (p->device_class ()) != tl::id_of (&cls)) {
|
||||
return std::make_pair ((db::Device *) 0, (db::Device *) 0);
|
||||
} else {
|
||||
d1 = p->device ();
|
||||
}
|
||||
|
||||
++p;
|
||||
if (p == net.end_terminals () || tl::id_of (p->device_class ()) != tl::id_of (&cls)) {
|
||||
return std::make_pair ((db::Device *) 0, (db::Device *) 0);
|
||||
} else {
|
||||
d2 = p->device ();
|
||||
}
|
||||
|
||||
++p;
|
||||
if (p != net.end_terminals () || d1 == d2 || !d1 || !d2) {
|
||||
return std::make_pair ((db::Device *) 0, (db::Device *) 0);
|
||||
} else {
|
||||
return std::make_pair (d1, d2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static bool same_or_swapped (const std::pair<T, T> &p1, const std::pair<T, T> &p2)
|
||||
{
|
||||
return (p1.first == p2.first && p1.second == p2.second) || (p1.first == p2.second && p1.second == p2.first);
|
||||
}
|
||||
|
||||
bool Circuit::combine_serial_devices(const db::DeviceClass &cls)
|
||||
{
|
||||
bool any = false;
|
||||
|
||||
for (net_iterator n = begin_nets (); n != end_nets (); ++n) {
|
||||
|
||||
std::pair<db::Device *, db::Device *> dd = attached_two_devices (*n, cls);
|
||||
if (! dd.first) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The net is an internal node: the devices attached to this internal node are
|
||||
// combination candidates if the number of nets emerging from the attached device pair (not counting
|
||||
// the internal node we just found) does not exceed the number of pins available for the
|
||||
// new device.
|
||||
|
||||
std::vector<const db::Net *> other_nets;
|
||||
|
||||
const std::vector<db::DeviceTerminalDefinition> &terminals = cls.terminal_definitions ();
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator p = terminals.begin (); p != terminals.end (); ++p) {
|
||||
db::Net *on;
|
||||
on = dd.first->net_for_terminal (p->id ());
|
||||
if (on && ! same_or_swapped (dd, attached_two_devices (*on, cls))) {
|
||||
other_nets.push_back (on);
|
||||
}
|
||||
on = dd.second->net_for_terminal (p->id ());
|
||||
if (on && ! same_or_swapped (dd, attached_two_devices (*on, cls))) {
|
||||
other_nets.push_back (on);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (other_nets.begin (), other_nets.end ());
|
||||
other_nets.erase (std::unique (other_nets.begin (), other_nets.end ()), other_nets.end ());
|
||||
|
||||
if (other_nets.size () <= cls.terminal_definitions().size ()) {
|
||||
|
||||
// found a combination candidate
|
||||
if (cls.combine_devices (dd.first, dd.second)) {
|
||||
check_device_before_remove (this, dd.second); // sanity check
|
||||
delete dd.second;
|
||||
any = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
void Circuit::combine_devices ()
|
||||
{
|
||||
tl_assert (netlist () != 0);
|
||||
|
||||
for (Netlist::device_class_iterator dc = netlist ()->begin_device_classes (); dc != netlist ()->end_device_classes (); ++dc) {
|
||||
|
||||
// repeat the combination step unless no combination happens - this is required to take care of combinations that arise after
|
||||
// other combinations have been realized.
|
||||
bool any = true;
|
||||
while (any) {
|
||||
|
||||
any = false;
|
||||
|
||||
if (dc->supports_parallel_combination ()) {
|
||||
if (combine_parallel_devices (*dc)) {
|
||||
any = true;
|
||||
}
|
||||
}
|
||||
if (dc->supports_serial_combination ()) {
|
||||
if (combine_serial_devices (*dc)) {
|
||||
any = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,634 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HDR_dbCircuit
|
||||
#define _HDR_dbCircuit
|
||||
|
||||
#include "dbCommon.h"
|
||||
#include "dbTypes.h"
|
||||
#include "dbNet.h"
|
||||
#include "dbDevice.h"
|
||||
#include "dbPin.h"
|
||||
#include "dbSubCircuit.h"
|
||||
#include "dbNetlistUtils.h"
|
||||
|
||||
#include "tlObject.h"
|
||||
#include "tlObjectCollection.h"
|
||||
#include "tlVector.h"
|
||||
#include "gsiObject.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class Netlist;
|
||||
|
||||
/**
|
||||
* @brief A circuit
|
||||
*
|
||||
* A circuit is a list of nets, of subcircuit references and actual
|
||||
* devices.
|
||||
*/
|
||||
class DB_PUBLIC Circuit
|
||||
: public gsi::ObjectBase, public tl::Object
|
||||
{
|
||||
public:
|
||||
typedef tl::vector<Pin> pin_list;
|
||||
typedef pin_list::const_iterator const_pin_iterator;
|
||||
typedef pin_list::iterator pin_iterator;
|
||||
typedef tl::shared_collection<Device> device_list;
|
||||
typedef device_list::const_iterator const_device_iterator;
|
||||
typedef device_list::iterator device_iterator;
|
||||
typedef tl::shared_collection<Net> net_list;
|
||||
typedef net_list::const_iterator const_net_iterator;
|
||||
typedef net_list::iterator net_iterator;
|
||||
typedef tl::shared_collection<SubCircuit> subcircuit_list;
|
||||
typedef subcircuit_list::const_iterator const_subcircuit_iterator;
|
||||
typedef subcircuit_list::iterator subcircuit_iterator;
|
||||
typedef tl::weak_collection<SubCircuit>::const_iterator const_refs_iterator;
|
||||
typedef tl::weak_collection<SubCircuit>::iterator refs_iterator;
|
||||
typedef tl::vector<Circuit *>::const_iterator child_circuit_iterator;
|
||||
typedef tl::vector<const Circuit *>::const_iterator const_child_circuit_iterator;
|
||||
typedef tl::vector<Circuit *>::const_iterator parent_circuit_iterator;
|
||||
typedef tl::vector<const Circuit *>::const_iterator const_parent_circuit_iterator;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* Creates an empty circuit.
|
||||
*/
|
||||
Circuit ();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
Circuit (const Circuit &other);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Circuit ();
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
Circuit &operator= (const Circuit &other);
|
||||
|
||||
/**
|
||||
* @brief Gets the netlist the circuit lives in
|
||||
* This pointer is 0 if the circuit is not part of a netlist.
|
||||
*/
|
||||
Netlist *netlist ()
|
||||
{
|
||||
return mp_netlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the netlist the circuit lives in (const version)
|
||||
* This pointer is 0 if the circuit is not part of a netlist.
|
||||
*/
|
||||
const Netlist *netlist () const
|
||||
{
|
||||
return mp_netlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the circuit
|
||||
*/
|
||||
void clear ();
|
||||
|
||||
/**
|
||||
* @brief Sets the name of the circuit
|
||||
*/
|
||||
void set_name (const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the circuit
|
||||
*/
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The index of the circuit in the netlist
|
||||
* CAUTION: this attribute is used for internal purposes and may not be valid always.
|
||||
*/
|
||||
size_t index () const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the layout cell reference for this circuit
|
||||
*
|
||||
* The layout cell reference links a circuit to a layout cell.
|
||||
*/
|
||||
void set_cell_index (const db::cell_index_type ci);
|
||||
|
||||
/**
|
||||
* @brief Gets the layout cell index
|
||||
*/
|
||||
db::cell_index_type cell_index () const
|
||||
{
|
||||
return m_cell_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the references to this circuit (begin, non-const version)
|
||||
* This iterator will deliver all subcircuits referencing this circuit
|
||||
*/
|
||||
refs_iterator begin_refs ()
|
||||
{
|
||||
return m_refs.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the references to this circuit (end, non-const version)
|
||||
* This iterator will deliver all subcircuits referencing this circuit
|
||||
*/
|
||||
refs_iterator end_refs ()
|
||||
{
|
||||
return m_refs.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the references to this circuit (begin, const version)
|
||||
* This iterator will deliver all subcircuits referencing this circuit
|
||||
*/
|
||||
const_refs_iterator begin_refs () const
|
||||
{
|
||||
return m_refs.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the child circuits iterator (begin)
|
||||
* The child circuits are the circuits referenced by all subcircuits
|
||||
* in the circuit.
|
||||
*/
|
||||
child_circuit_iterator begin_children ();
|
||||
|
||||
/**
|
||||
* @brief Gets the child circuits iterator (end)
|
||||
*/
|
||||
child_circuit_iterator end_children ();
|
||||
|
||||
/**
|
||||
* @brief Gets the child circuits iterator (begin, const version)
|
||||
* The child circuits are the circuits referenced by all subcircuits
|
||||
* in the circuit.
|
||||
*/
|
||||
const_child_circuit_iterator begin_children () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the child circuits iterator (end, const version)
|
||||
*/
|
||||
const_child_circuit_iterator end_children () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the parent circuits iterator (begin)
|
||||
* The parents circuits are the circuits referencing this circuit via subcircuits.
|
||||
*/
|
||||
parent_circuit_iterator begin_parents ();
|
||||
|
||||
/**
|
||||
* @brief Gets the parent circuits iterator (end)
|
||||
*/
|
||||
parent_circuit_iterator end_parents ();
|
||||
|
||||
/**
|
||||
* @brief Gets the parent circuits iterator (begin, const version)
|
||||
* The parents circuits are the circuits referencing this circuit via subcircuits.
|
||||
*/
|
||||
const_parent_circuit_iterator begin_parents () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the parent circuits iterator (end, const version)
|
||||
*/
|
||||
const_parent_circuit_iterator end_parents () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the references to this circuit (end, const version)
|
||||
* This iterator will deliver all subcircuits referencing this circuit
|
||||
*/
|
||||
const_refs_iterator end_refs () const
|
||||
{
|
||||
return m_refs.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a pin to this circuit
|
||||
* The circuit takes over ownership of the object.
|
||||
*/
|
||||
const Pin &add_pin(const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the pins of the circuit (non-const version)
|
||||
*/
|
||||
pin_iterator begin_pins ()
|
||||
{
|
||||
return m_pins.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the pins of the circuit (non-const version)
|
||||
*/
|
||||
pin_iterator end_pins ()
|
||||
{
|
||||
return m_pins.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the pin count
|
||||
*/
|
||||
size_t pin_count () const
|
||||
{
|
||||
return m_pins.size ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the pin by ID (the ID is basically the index)
|
||||
*/
|
||||
const Pin *pin_by_id (size_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the pin by name
|
||||
*
|
||||
* If there is no pin with that name, null is returned.
|
||||
* NOTE: this is a linear search, so it's performance may not be good for many pins.
|
||||
*/
|
||||
const Pin *pin_by_name (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the pins of the circuit (const version)
|
||||
*/
|
||||
const_pin_iterator begin_pins () const
|
||||
{
|
||||
return m_pins.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the pins of the circuit (const version)
|
||||
*/
|
||||
const_pin_iterator end_pins () const
|
||||
{
|
||||
return m_pins.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a net to this circuit
|
||||
*
|
||||
* The circuit takes over ownership of the object.
|
||||
*/
|
||||
void add_net (Net *net);
|
||||
|
||||
/**
|
||||
* @brief Deletes a net from the circuit
|
||||
*/
|
||||
void remove_net (Net *net);
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the nets of the circuit (non-const version)
|
||||
*/
|
||||
net_iterator begin_nets ()
|
||||
{
|
||||
return m_nets.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the nets of the circuit (non-const version)
|
||||
*/
|
||||
net_iterator end_nets ()
|
||||
{
|
||||
return m_nets.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the nets of the circuit (const version)
|
||||
*/
|
||||
const_net_iterator begin_nets () const
|
||||
{
|
||||
return m_nets.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the nets of the circuit (const version)
|
||||
*/
|
||||
const_net_iterator end_nets () const
|
||||
{
|
||||
return m_nets.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net from a given cluster ID (const version)
|
||||
*
|
||||
* If the cluster ID is not valid, null is returned.
|
||||
*/
|
||||
const Net *net_by_cluster_id (size_t cluster_id) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->net_by_cluster_id (cluster_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net from a given cluster ID (non-const version)
|
||||
*
|
||||
* If the cluster ID is not valid, null is returned.
|
||||
*/
|
||||
Net *net_by_cluster_id (size_t cluster_id)
|
||||
{
|
||||
return m_net_by_cluster_id.object_by (cluster_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net from a given name (const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
const Net *net_by_name (const std::string &name) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->net_by_name (name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net from a given name (non-const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
Net *net_by_name (const std::string &name)
|
||||
{
|
||||
return m_net_by_name.object_by (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a device to this circuit
|
||||
*
|
||||
* The circuit takes over ownership of the object.
|
||||
*/
|
||||
void add_device (Device *device);
|
||||
|
||||
/**
|
||||
* @brief Deletes a device from the circuit
|
||||
*/
|
||||
void remove_device (Device *device);
|
||||
|
||||
/**
|
||||
* @brief Gets the device from a given ID (const version)
|
||||
*
|
||||
* If the ID is not valid, null is returned.
|
||||
*/
|
||||
const Device *device_by_id (size_t id) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->device_by_id (id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device from a given ID (non-const version)
|
||||
*
|
||||
* If the ID is not valid, null is returned.
|
||||
*/
|
||||
Device *device_by_id (size_t id)
|
||||
{
|
||||
return m_device_by_id.object_by (id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device from a given name (const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
const Device *device_by_name (const std::string &name) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->device_by_name (name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device from a given name (non-const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
Device *device_by_name (const std::string &name)
|
||||
{
|
||||
return m_device_by_name.object_by (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the devices of the circuit (non-const version)
|
||||
*/
|
||||
device_iterator begin_devices ()
|
||||
{
|
||||
return m_devices.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the devices of the circuit (non-const version)
|
||||
*/
|
||||
device_iterator end_devices ()
|
||||
{
|
||||
return m_devices.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the devices of the circuit (const version)
|
||||
*/
|
||||
const_device_iterator begin_devices () const
|
||||
{
|
||||
return m_devices.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the devices of the circuit (const version)
|
||||
*/
|
||||
const_device_iterator end_devices () const
|
||||
{
|
||||
return m_devices.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a subcircuit to this circuit
|
||||
*
|
||||
* The circuit takes over ownership of the object.
|
||||
*/
|
||||
void add_subcircuit (SubCircuit *subcircuit);
|
||||
|
||||
/**
|
||||
* @brief Deletes a subcircuit from the circuit
|
||||
*/
|
||||
void remove_subcircuit (SubCircuit *subcircuit);
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit from a given ID (const version)
|
||||
*
|
||||
* If the ID is not valid, null is returned.
|
||||
*/
|
||||
const SubCircuit *subcircuit_by_id (size_t id) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->subcircuit_by_id (id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit from a given ID (non-const version)
|
||||
*
|
||||
* If the ID is not valid, null is returned.
|
||||
*/
|
||||
SubCircuit *subcircuit_by_id (size_t id)
|
||||
{
|
||||
return m_subcircuit_by_id.object_by (id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit from a given name (const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
const SubCircuit *subcircuit_by_name (const std::string &name) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->subcircuit_by_name (name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit from a given name (non-const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
SubCircuit *subcircuit_by_name (const std::string &name)
|
||||
{
|
||||
return m_subcircuit_by_name.object_by (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the subcircuits of the circuit (non-const version)
|
||||
*/
|
||||
subcircuit_iterator begin_subcircuits ()
|
||||
{
|
||||
return m_subcircuits.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the subcircuits of the circuit (non-const version)
|
||||
*/
|
||||
subcircuit_iterator end_subcircuits ()
|
||||
{
|
||||
return m_subcircuits.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the subcircuits of the circuit (const version)
|
||||
*/
|
||||
const_subcircuit_iterator begin_subcircuits () const
|
||||
{
|
||||
return m_subcircuits.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the subcircuits of the circuit (const version)
|
||||
*/
|
||||
const_subcircuit_iterator end_subcircuits () const
|
||||
{
|
||||
return m_subcircuits.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the connected net for a pin with the given id
|
||||
*
|
||||
* Returns 0 if the pin is not connected to a net.
|
||||
*/
|
||||
const Net *net_for_pin (size_t pin_id) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the connected net for a pin with the given id (non-const version)
|
||||
*
|
||||
* Returns 0 if the pin is not connected to a net.
|
||||
*/
|
||||
Net *net_for_pin (size_t pin_id)
|
||||
{
|
||||
return const_cast<Net *> (((const Circuit *) this)->net_for_pin (pin_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connects the given pin to the given net
|
||||
* If the net is 0 the pin is disconnected.
|
||||
* If non-null, a NetPinRef object will be inserted into the
|
||||
* net and connected with the given pin.
|
||||
*/
|
||||
void connect_pin (size_t pin_id, Net *net);
|
||||
|
||||
/**
|
||||
* @brief Purge unused nets
|
||||
*
|
||||
* This method will purge all nets which return "floating".
|
||||
*/
|
||||
void purge_nets ();
|
||||
|
||||
/**
|
||||
* @brief Combine devices
|
||||
*
|
||||
* This method will combine devices that can be combined according
|
||||
* to their device classes "combine_devices" method.
|
||||
*/
|
||||
void combine_devices ();
|
||||
|
||||
private:
|
||||
friend class Netlist;
|
||||
friend class Net;
|
||||
friend class SubCircuit;
|
||||
friend class Device;
|
||||
|
||||
std::string m_name;
|
||||
db::cell_index_type m_cell_index;
|
||||
net_list m_nets;
|
||||
pin_list m_pins;
|
||||
device_list m_devices;
|
||||
subcircuit_list m_subcircuits;
|
||||
Netlist *mp_netlist;
|
||||
std::vector<Net::pin_iterator> m_pin_refs;
|
||||
object_by_attr<Circuit, Circuit::device_iterator, id_attribute<Device> > m_device_by_id;
|
||||
object_by_attr<Circuit, Circuit::subcircuit_iterator, id_attribute<SubCircuit> > m_subcircuit_by_id;
|
||||
object_by_attr<Circuit, Circuit::net_iterator, cluster_id_attribute<Net> > m_net_by_cluster_id;
|
||||
object_by_attr<Circuit, Circuit::device_iterator, name_attribute<Device> > m_device_by_name;
|
||||
object_by_attr<Circuit, Circuit::subcircuit_iterator, name_attribute<SubCircuit> > m_subcircuit_by_name;
|
||||
object_by_attr<Circuit, Circuit::net_iterator, name_attribute<Net> > m_net_by_name;
|
||||
tl::weak_collection<SubCircuit> m_refs;
|
||||
size_t m_index;
|
||||
|
||||
void set_index (size_t index)
|
||||
{
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
void set_pin_ref_for_pin (size_t ppin_id, Net::pin_iterator iter);
|
||||
|
||||
void register_ref (SubCircuit *sc);
|
||||
void unregister_ref (SubCircuit *sc);
|
||||
|
||||
void translate_circuits (const std::map<const Circuit *, Circuit *> &map);
|
||||
void translate_device_classes (const std::map<const DeviceClass *, DeviceClass *> &map);
|
||||
void set_netlist (Netlist *netlist);
|
||||
bool combine_parallel_devices (const db::DeviceClass &cls);
|
||||
bool combine_serial_devices (const db::DeviceClass &cls);
|
||||
|
||||
void devices_changed ();
|
||||
void subcircuits_changed ();
|
||||
void nets_changed ();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbDevice.h"
|
||||
#include "dbCircuit.h"
|
||||
#include "dbDeviceClass.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Device class implementation
|
||||
|
||||
Device::Device ()
|
||||
: mp_device_class (0), m_id (0), mp_circuit (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Device::~Device ()
|
||||
{
|
||||
for (std::vector<Net::terminal_iterator>::const_iterator t = m_terminal_refs.begin (); t != m_terminal_refs.end (); ++t) {
|
||||
if (*t != Net::terminal_iterator () && (*t)->net ()) {
|
||||
(*t)->net ()->erase_terminal (*t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Device::Device (DeviceClass *device_class, const std::string &name)
|
||||
: mp_device_class (device_class), m_name (name), m_id (0), mp_circuit (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Device::Device (const Device &other)
|
||||
: mp_device_class (0), m_id (0), mp_circuit (0)
|
||||
{
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
Device &Device::operator= (const Device &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_name = other.m_name;
|
||||
mp_device_class = other.mp_device_class;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Device::set_circuit (Circuit *circuit)
|
||||
{
|
||||
mp_circuit = circuit;
|
||||
}
|
||||
|
||||
void Device::set_name (const std::string &n)
|
||||
{
|
||||
m_name = n;
|
||||
if (mp_circuit) {
|
||||
mp_circuit->m_device_by_name.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
void Device::set_terminal_ref_for_terminal (size_t terminal_id, Net::terminal_iterator iter)
|
||||
{
|
||||
if (m_terminal_refs.size () < terminal_id + 1) {
|
||||
m_terminal_refs.resize (terminal_id + 1, Net::terminal_iterator ());
|
||||
}
|
||||
m_terminal_refs [terminal_id] = iter;
|
||||
}
|
||||
|
||||
const Net *Device::net_for_terminal (size_t terminal_id) const
|
||||
{
|
||||
if (terminal_id < m_terminal_refs.size ()) {
|
||||
Net::terminal_iterator p = m_terminal_refs [terminal_id];
|
||||
if (p != Net::terminal_iterator ()) {
|
||||
return p->net ();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Device::connect_terminal (size_t terminal_id, Net *net)
|
||||
{
|
||||
if (net_for_terminal (terminal_id) == net) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (terminal_id < m_terminal_refs.size ()) {
|
||||
Net::terminal_iterator p = m_terminal_refs [terminal_id];
|
||||
if (p != Net::terminal_iterator () && p->net ()) {
|
||||
p->net ()->erase_terminal (p);
|
||||
}
|
||||
m_terminal_refs [terminal_id] = Net::terminal_iterator ();
|
||||
}
|
||||
|
||||
if (net) {
|
||||
net->add_terminal (NetTerminalRef (this, terminal_id));
|
||||
}
|
||||
}
|
||||
|
||||
double Device::parameter_value (size_t param_id) const
|
||||
{
|
||||
if (m_parameters.size () > param_id) {
|
||||
return m_parameters [param_id];
|
||||
} else if (mp_device_class) {
|
||||
const db::DeviceParameterDefinition *pd = mp_device_class->parameter_definition (param_id);
|
||||
if (pd) {
|
||||
return pd->default_value ();
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void Device::set_parameter_value (size_t param_id, double v)
|
||||
{
|
||||
if (m_parameters.size () <= param_id) {
|
||||
|
||||
// resize the parameter vector with default values
|
||||
size_t from_size = m_parameters.size ();
|
||||
m_parameters.resize (param_id + 1, 0.0);
|
||||
|
||||
if (mp_device_class) {
|
||||
for (size_t n = from_size; n < param_id; ++n) {
|
||||
const db::DeviceParameterDefinition *pd = mp_device_class->parameter_definition (n);
|
||||
if (pd) {
|
||||
m_parameters [n] = pd->default_value ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_parameters [param_id] = v;
|
||||
}
|
||||
|
||||
double Device::parameter_value (const std::string &name) const
|
||||
{
|
||||
return device_class () ? parameter_value (device_class ()->parameter_id_for_name (name)) : 0.0;
|
||||
}
|
||||
|
||||
void Device::set_parameter_value (const std::string &name, double v)
|
||||
{
|
||||
if (device_class ()) {
|
||||
set_parameter_value (device_class ()->parameter_id_for_name (name), v);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HDR_dbDevice
|
||||
#define _HDR_dbDevice
|
||||
|
||||
#include "dbCommon.h"
|
||||
#include "dbNet.h"
|
||||
|
||||
#include "tlObject.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class Circuit;
|
||||
class DeviceClass;
|
||||
|
||||
/**
|
||||
* @brief An actual device
|
||||
*
|
||||
* This class represents the incarnation of a specific device.
|
||||
* The device has a class which specifies a type. This class
|
||||
* is intended for subclassing.
|
||||
* A specific device subclass is supposed to correspond to
|
||||
* a specific device class.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
Device ();
|
||||
|
||||
/**
|
||||
* @brief The constructor
|
||||
*/
|
||||
Device (DeviceClass *device_class, const std::string &name = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
Device (const Device &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
Device &operator= (const Device &other);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Device ();
|
||||
|
||||
/**
|
||||
* @brief Gets the device class
|
||||
*/
|
||||
const DeviceClass *device_class () const
|
||||
{
|
||||
return mp_device_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device ID
|
||||
* The ID is a unique integer which identifies the device.
|
||||
* It can be used to retrieve the device from the circuit using Circuit::device_by_id.
|
||||
* When assigned, the device ID is not 0.
|
||||
*/
|
||||
size_t id () const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit the device lives in (const version)
|
||||
* This pointer is 0 if the device isn't added to a circuit
|
||||
*/
|
||||
const Circuit *circuit () const
|
||||
{
|
||||
return mp_circuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit the device lives in (non-const version)
|
||||
* This pointer is 0 if the device isn't added to a circuit
|
||||
*/
|
||||
Circuit *circuit ()
|
||||
{
|
||||
return mp_circuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the name
|
||||
*/
|
||||
void set_name (const std::string &n);
|
||||
|
||||
/**
|
||||
* @brief Gets the name
|
||||
*/
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net attached to a specific terminal
|
||||
* Returns 0 if no net is attached.
|
||||
*/
|
||||
const Net *net_for_terminal (size_t terminal_id) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the net attached to a specific terminal (non-const version)
|
||||
* Returns 0 if no net is attached.
|
||||
*/
|
||||
Net *net_for_terminal (size_t terminal_id)
|
||||
{
|
||||
return const_cast<Net *> (((const Device *) this)->net_for_terminal (terminal_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connects the given terminal to the given net
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* @brief Gets the value for the parameter with the given ID
|
||||
*/
|
||||
double parameter_value (size_t param_id) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the value for the parameter with the given ID
|
||||
*/
|
||||
void set_parameter_value (size_t param_id, double v);
|
||||
|
||||
/**
|
||||
* @brief Gets the value for the parameter with the given name
|
||||
* If the name is not valid, an exception is thrown.
|
||||
*/
|
||||
double parameter_value (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the value for the parameter with the given name
|
||||
* If the name is not valid, an exception is thrown.
|
||||
*/
|
||||
void set_parameter_value (const std::string &name, double v);
|
||||
|
||||
private:
|
||||
friend class Circuit;
|
||||
friend class Net;
|
||||
|
||||
DeviceClass *mp_device_class;
|
||||
std::string m_name;
|
||||
std::vector<Net::terminal_iterator> m_terminal_refs;
|
||||
std::vector<double> m_parameters;
|
||||
size_t m_id;
|
||||
Circuit *mp_circuit;
|
||||
|
||||
/**
|
||||
* @brief Sets the terminal reference for a specific terminal
|
||||
*/
|
||||
void set_terminal_ref_for_terminal (size_t terminal_id, Net::terminal_iterator iter);
|
||||
|
||||
/**
|
||||
* @brief Sets the device class
|
||||
*/
|
||||
void set_device_class (DeviceClass *dc)
|
||||
{
|
||||
mp_device_class = dc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the device ID
|
||||
*/
|
||||
void set_id (size_t id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the circuit
|
||||
*/
|
||||
void set_circuit (Circuit *circuit);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbDeviceClass.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// DeviceClass class implementation
|
||||
|
||||
DeviceClass::DeviceClass ()
|
||||
: mp_netlist (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
DeviceClass::DeviceClass (const DeviceClass &other)
|
||||
: mp_netlist (0)
|
||||
{
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
DeviceClass &DeviceClass::operator= (const DeviceClass &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_terminal_definitions = other.m_terminal_definitions;
|
||||
m_name = other.m_name;
|
||||
m_description = other.m_description;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const DeviceTerminalDefinition &DeviceClass::add_terminal_definition (const DeviceTerminalDefinition &pd)
|
||||
{
|
||||
m_terminal_definitions.push_back (pd);
|
||||
m_terminal_definitions.back ().set_id (m_terminal_definitions.size () - 1);
|
||||
return m_terminal_definitions.back ();
|
||||
}
|
||||
|
||||
void DeviceClass::clear_terminal_definitions ()
|
||||
{
|
||||
m_terminal_definitions.clear ();
|
||||
}
|
||||
|
||||
const DeviceTerminalDefinition *DeviceClass::terminal_definition (size_t id) const
|
||||
{
|
||||
if (id < m_terminal_definitions.size ()) {
|
||||
return & m_terminal_definitions [id];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const DeviceParameterDefinition &DeviceClass::add_parameter_definition (const DeviceParameterDefinition &pd)
|
||||
{
|
||||
m_parameter_definitions.push_back (pd);
|
||||
m_parameter_definitions.back ().set_id (m_parameter_definitions.size () - 1);
|
||||
return m_parameter_definitions.back ();
|
||||
}
|
||||
|
||||
void DeviceClass::clear_parameter_definitions ()
|
||||
{
|
||||
m_parameter_definitions.clear ();
|
||||
}
|
||||
|
||||
const DeviceParameterDefinition *DeviceClass::parameter_definition (size_t id) const
|
||||
{
|
||||
if (id < m_parameter_definitions.size ()) {
|
||||
return & m_parameter_definitions [id];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceClass::has_parameter_with_name (const std::string &name) const
|
||||
{
|
||||
const std::vector<db::DeviceParameterDefinition> &pd = parameter_definitions ();
|
||||
for (std::vector<db::DeviceParameterDefinition>::const_iterator i = pd.begin (); i != pd.end (); ++i) {
|
||||
if (i->name () == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t DeviceClass::parameter_id_for_name (const std::string &name) const
|
||||
{
|
||||
const std::vector<db::DeviceParameterDefinition> &pd = parameter_definitions ();
|
||||
for (std::vector<db::DeviceParameterDefinition>::const_iterator i = pd.begin (); i != pd.end (); ++i) {
|
||||
if (i->name () == name) {
|
||||
return i->id ();
|
||||
}
|
||||
}
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid parameter name")) + ": '" + name + "'");
|
||||
}
|
||||
|
||||
bool DeviceClass::has_terminal_with_name (const std::string &name) const
|
||||
{
|
||||
const std::vector<db::DeviceTerminalDefinition> &td = terminal_definitions ();
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator i = td.begin (); i != td.end (); ++i) {
|
||||
if (i->name () == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t DeviceClass::terminal_id_for_name (const std::string &name) const
|
||||
{
|
||||
const std::vector<db::DeviceTerminalDefinition> &td = terminal_definitions ();
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator i = td.begin (); i != td.end (); ++i) {
|
||||
if (i->name () == name) {
|
||||
return i->id ();
|
||||
}
|
||||
}
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid terminal name")) + ": '" + name + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,422 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HDR_dbDeviceClass
|
||||
#define _HDR_dbDeviceClass
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "gsiObject.h"
|
||||
#include "tlObject.h"
|
||||
#include "tlUniqueId.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class Netlist;
|
||||
class Device;
|
||||
|
||||
/**
|
||||
* @brief A device terminal definition
|
||||
*/
|
||||
class DB_PUBLIC DeviceTerminalDefinition
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates an empty device terminal definition
|
||||
*/
|
||||
DeviceTerminalDefinition ()
|
||||
: m_name (), m_description (), m_id (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a device terminal definition with the given name and description
|
||||
*/
|
||||
DeviceTerminalDefinition (const std::string &name, const std::string &description)
|
||||
: m_name (name), m_description (description), m_id (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the terminal name
|
||||
*/
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the terminal name
|
||||
*/
|
||||
void set_name (const std::string &n)
|
||||
{
|
||||
m_name = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the terminal description
|
||||
*/
|
||||
const std::string &description () const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the terminal description
|
||||
*/
|
||||
void set_description (const std::string &d)
|
||||
{
|
||||
m_description = d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the terminal ID
|
||||
*/
|
||||
size_t id () const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class DeviceClass;
|
||||
|
||||
std::string m_name, m_description;
|
||||
size_t m_id;
|
||||
|
||||
void set_id (size_t id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A device parameter definition
|
||||
*/
|
||||
class DB_PUBLIC DeviceParameterDefinition
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates an empty device parameter definition
|
||||
*/
|
||||
DeviceParameterDefinition ()
|
||||
: m_name (), m_description (), m_default_value (0.0), m_id (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a device parameter definition with the given name and description
|
||||
*/
|
||||
DeviceParameterDefinition (const std::string &name, const std::string &description, double default_value = 0.0)
|
||||
: m_name (name), m_description (description), m_default_value (default_value), m_id (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter name
|
||||
*/
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the parameter name
|
||||
*/
|
||||
void set_name (const std::string &n)
|
||||
{
|
||||
m_name = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter description
|
||||
*/
|
||||
const std::string &description () const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the parameter description
|
||||
*/
|
||||
void set_description (const std::string &d)
|
||||
{
|
||||
m_description = d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter default value
|
||||
*/
|
||||
double default_value () const
|
||||
{
|
||||
return m_default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the parameter description
|
||||
*/
|
||||
void set_default_value (double d)
|
||||
{
|
||||
m_default_value = d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter ID
|
||||
*/
|
||||
size_t id () const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class DeviceClass;
|
||||
|
||||
std::string m_name, m_description;
|
||||
double m_default_value;
|
||||
size_t m_id;
|
||||
|
||||
void set_id (size_t id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A device class
|
||||
*
|
||||
* A device class describes a type of device.
|
||||
*/
|
||||
class DB_PUBLIC DeviceClass
|
||||
: public gsi::ObjectBase, public tl::Object, public tl::UniqueId
|
||||
{
|
||||
public:
|
||||
typedef size_t terminal_id_type;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* Creates an empty circuit.
|
||||
*/
|
||||
DeviceClass ();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* NOTE: do not use this copy constructor as the device class
|
||||
* is intended to subclassing.
|
||||
*/
|
||||
DeviceClass (const DeviceClass &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
* NOTE: do not use this copy constructor as the device class
|
||||
* is intended to subclassing.
|
||||
*/
|
||||
DeviceClass &operator= (const DeviceClass &other);
|
||||
|
||||
/**
|
||||
* @brief Gets the netlist the device class lives in
|
||||
*/
|
||||
db::Netlist *netlist ()
|
||||
{
|
||||
return mp_netlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the netlist the device class lives in (const version)
|
||||
*/
|
||||
const db::Netlist *netlist () const
|
||||
{
|
||||
return mp_netlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the device class
|
||||
*
|
||||
* The name is a formal name which identifies the class.
|
||||
*/
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the device name
|
||||
*/
|
||||
void set_name (const std::string &n)
|
||||
{
|
||||
m_name = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the description text for the device class
|
||||
*
|
||||
* The description text is a human-readable text that
|
||||
* identifies the device class.
|
||||
*/
|
||||
const std::string &description () const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the description text
|
||||
*/
|
||||
void set_description (const std::string &d)
|
||||
{
|
||||
m_description = d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the terminal definitions
|
||||
*
|
||||
* The terminal definitions indicate what terminals the device offers.
|
||||
* The number of terminals is constant per class. The index of the terminal
|
||||
* is used as an ID of the terminal, hence the order must be static.
|
||||
*/
|
||||
const std::vector<DeviceTerminalDefinition> &terminal_definitions () const
|
||||
{
|
||||
return m_terminal_definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a terminal definition
|
||||
*/
|
||||
const DeviceTerminalDefinition &add_terminal_definition (const DeviceTerminalDefinition &pd);
|
||||
|
||||
/**
|
||||
* @brief Clears the terminal definition
|
||||
*/
|
||||
void clear_terminal_definitions ();
|
||||
|
||||
/**
|
||||
* @brief Gets the terminal definition from the ID
|
||||
*/
|
||||
const DeviceTerminalDefinition *terminal_definition (size_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter definitions
|
||||
*/
|
||||
const std::vector<DeviceParameterDefinition> ¶meter_definitions () const
|
||||
{
|
||||
return m_parameter_definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a parameter definition
|
||||
*/
|
||||
const DeviceParameterDefinition &add_parameter_definition (const DeviceParameterDefinition &pd);
|
||||
|
||||
/**
|
||||
* @brief Clears the parameter definition
|
||||
*/
|
||||
void clear_parameter_definitions ();
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter definition from the ID
|
||||
*/
|
||||
const DeviceParameterDefinition *parameter_definition (size_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the device has a parameter with the given name
|
||||
*/
|
||||
bool has_parameter_with_name (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the parameter ID for the parameter with the given name
|
||||
* If the name is invalid, an exception is thrown.
|
||||
*/
|
||||
size_t parameter_id_for_name (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the device has a terminal with the given name
|
||||
*/
|
||||
bool has_terminal_with_name (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the parameter ID for the terminal with the given name
|
||||
* If the name is invalid, an exception is thrown.
|
||||
*/
|
||||
size_t terminal_id_for_name (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Clears the circuit
|
||||
*/
|
||||
virtual DeviceClass *clone () const
|
||||
{
|
||||
return new DeviceClass (*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Combines two devices
|
||||
*
|
||||
* This method shall test, whether the two devices can be combined. Both devices
|
||||
* are guaranteed to share the same device class (this).
|
||||
* If they cannot be combined, this method shall do nothing and return false.
|
||||
* If they can be combined, this method shall reconnect the nets of the first
|
||||
* device and entirely disconnect the nets of the second device.
|
||||
* The second device will be deleted afterwards.
|
||||
*/
|
||||
virtual bool combine_devices (db::Device * /*a*/, db::Device * /*b*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the device class supports device combination in parallel mode
|
||||
*/
|
||||
virtual bool supports_parallel_combination () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the device class supports device combination in serial mode
|
||||
*/
|
||||
virtual bool supports_serial_combination () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Netlist;
|
||||
|
||||
std::string m_name, m_description;
|
||||
std::vector<DeviceTerminalDefinition> m_terminal_definitions;
|
||||
std::vector<DeviceParameterDefinition> m_parameter_definitions;
|
||||
db::Netlist *mp_netlist;
|
||||
|
||||
void set_netlist (db::Netlist *nl)
|
||||
{
|
||||
mp_netlist = nl;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbNet.h"
|
||||
#include "dbDevice.h"
|
||||
#include "dbDeviceClass.h"
|
||||
#include "dbCircuit.h"
|
||||
#include "dbSubCircuit.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// NetTerminalRef class implementation
|
||||
|
||||
NetTerminalRef::NetTerminalRef ()
|
||||
: m_terminal_id (0), mp_device (0), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetTerminalRef::NetTerminalRef (Device *device, size_t terminal_id)
|
||||
: m_terminal_id (terminal_id), mp_device (device), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetTerminalRef::NetTerminalRef (const NetTerminalRef &other)
|
||||
: m_terminal_id (other.m_terminal_id), mp_device (other.mp_device), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetTerminalRef &NetTerminalRef::operator= (const NetTerminalRef &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_terminal_id = other.m_terminal_id;
|
||||
mp_device = other.mp_device;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const DeviceTerminalDefinition *
|
||||
NetTerminalRef::terminal_def () const
|
||||
{
|
||||
const DeviceClass *dc = device_class ();
|
||||
if (dc) {
|
||||
return dc->terminal_definition (m_terminal_id);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const DeviceClass *
|
||||
NetTerminalRef::device_class () const
|
||||
{
|
||||
return mp_device ? mp_device->device_class () : 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// NetPinRef class implementation
|
||||
|
||||
NetPinRef::NetPinRef ()
|
||||
: m_pin_id (0), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetPinRef::NetPinRef (size_t pin_id)
|
||||
: m_pin_id (pin_id), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetPinRef::NetPinRef (const NetPinRef &other)
|
||||
: m_pin_id (other.m_pin_id), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetPinRef &NetPinRef::operator= (const NetPinRef &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_pin_id = other.m_pin_id;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Pin *NetPinRef::pin () const
|
||||
{
|
||||
if (mp_net && mp_net->circuit ()) {
|
||||
return mp_net->circuit ()->pin_by_id (m_pin_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// NetSubcircuitPinRef class implementation
|
||||
|
||||
NetSubcircuitPinRef::NetSubcircuitPinRef ()
|
||||
: m_pin_id (0), mp_subcircuit (0), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetSubcircuitPinRef::NetSubcircuitPinRef (SubCircuit *circuit, size_t pin_id)
|
||||
: m_pin_id (pin_id), mp_subcircuit (circuit), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetSubcircuitPinRef::NetSubcircuitPinRef (const NetSubcircuitPinRef &other)
|
||||
: m_pin_id (other.m_pin_id), mp_subcircuit (other.mp_subcircuit), mp_net (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetSubcircuitPinRef &NetSubcircuitPinRef::operator= (const NetSubcircuitPinRef &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_pin_id = other.m_pin_id;
|
||||
mp_subcircuit = other.mp_subcircuit;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Pin *NetSubcircuitPinRef::pin () const
|
||||
{
|
||||
if (mp_subcircuit && mp_subcircuit->circuit_ref ()) {
|
||||
return mp_subcircuit->circuit_ref ()->pin_by_id (m_pin_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Net class implementation
|
||||
|
||||
Net::Net ()
|
||||
: m_cluster_id (0), mp_circuit (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Net::Net (const std::string &name)
|
||||
: m_cluster_id (0), mp_circuit (0)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
Net::Net (const Net &other)
|
||||
: m_cluster_id (0), mp_circuit (0)
|
||||
{
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
Net &Net::operator= (const Net &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
|
||||
clear ();
|
||||
|
||||
m_name = other.m_name;
|
||||
m_cluster_id = other.m_cluster_id;
|
||||
|
||||
for (const_subcircuit_pin_iterator i = other.begin_subcircuit_pins (); i != other.end_subcircuit_pins (); ++i) {
|
||||
add_subcircuit_pin (*i);
|
||||
}
|
||||
|
||||
for (const_pin_iterator i = other.begin_pins (); i != other.end_pins (); ++i) {
|
||||
add_pin (*i);
|
||||
}
|
||||
|
||||
for (const_terminal_iterator i = other.begin_terminals (); i != other.end_terminals (); ++i) {
|
||||
add_terminal (*i);
|
||||
}
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Net::~Net ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
void Net::clear ()
|
||||
{
|
||||
m_name.clear ();
|
||||
m_cluster_id = 0;
|
||||
|
||||
while (! m_terminals.empty ()) {
|
||||
erase_terminal (begin_terminals ());
|
||||
}
|
||||
|
||||
while (! m_pins.empty ()) {
|
||||
erase_pin (begin_pins ());
|
||||
}
|
||||
|
||||
while (! m_subcircuit_pins.empty ()) {
|
||||
erase_subcircuit_pin (begin_subcircuit_pins ());
|
||||
}
|
||||
}
|
||||
|
||||
void Net::set_name (const std::string &name)
|
||||
{
|
||||
m_name = name;
|
||||
if (mp_circuit) {
|
||||
mp_circuit->m_net_by_name.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Net::qname () const
|
||||
{
|
||||
if (circuit ()) {
|
||||
return circuit ()->name () + ":" + expanded_name ();
|
||||
} else {
|
||||
return expanded_name ();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Net::expanded_name () const
|
||||
{
|
||||
if (name ().empty ()) {
|
||||
if (cluster_id () > std::numeric_limits<size_t>::max () / 2) {
|
||||
// avoid printing huge ID numbers for internal cluster IDs
|
||||
return "$I" + tl::to_string ((std::numeric_limits<size_t>::max () - cluster_id ()) + 1);
|
||||
} else {
|
||||
return "$" + tl::to_string (cluster_id ());
|
||||
}
|
||||
} else {
|
||||
return name ();
|
||||
}
|
||||
}
|
||||
|
||||
void Net::set_cluster_id (size_t ci)
|
||||
{
|
||||
m_cluster_id = ci;
|
||||
if (mp_circuit) {
|
||||
mp_circuit->m_net_by_cluster_id.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
void Net::add_pin (const NetPinRef &pin)
|
||||
{
|
||||
m_pins.push_back (pin);
|
||||
NetPinRef &new_pin = m_pins.back ();
|
||||
new_pin.set_net (this);
|
||||
|
||||
if (mp_circuit) {
|
||||
mp_circuit->set_pin_ref_for_pin (new_pin.pin_id (), --m_pins.end ());
|
||||
}
|
||||
}
|
||||
|
||||
void Net::add_subcircuit_pin (const NetSubcircuitPinRef &pin)
|
||||
{
|
||||
m_subcircuit_pins.push_back (pin);
|
||||
NetSubcircuitPinRef &new_pin = m_subcircuit_pins.back ();
|
||||
new_pin.set_net (this);
|
||||
|
||||
tl_assert (pin.subcircuit () != 0);
|
||||
new_pin.subcircuit ()->set_pin_ref_for_pin (new_pin.pin_id (), --m_subcircuit_pins.end ());
|
||||
}
|
||||
|
||||
void Net::erase_pin (pin_iterator iter)
|
||||
{
|
||||
if (mp_circuit) {
|
||||
mp_circuit->set_pin_ref_for_pin (iter->pin_id (), pin_iterator ());
|
||||
}
|
||||
m_pins.erase (iter);
|
||||
}
|
||||
|
||||
void Net::erase_subcircuit_pin (subcircuit_pin_iterator iter)
|
||||
{
|
||||
if (iter->subcircuit ()) {
|
||||
iter->subcircuit ()->set_pin_ref_for_pin (iter->pin_id (), subcircuit_pin_iterator ());
|
||||
}
|
||||
m_subcircuit_pins.erase (iter);
|
||||
}
|
||||
|
||||
void Net::add_terminal (const NetTerminalRef &terminal)
|
||||
{
|
||||
if (! terminal.device ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_terminals.push_back (terminal);
|
||||
NetTerminalRef &new_terminal = m_terminals.back ();
|
||||
new_terminal.set_net (this);
|
||||
new_terminal.device ()->set_terminal_ref_for_terminal (new_terminal.terminal_id (), --m_terminals.end ());
|
||||
}
|
||||
|
||||
void Net::erase_terminal (terminal_iterator iter)
|
||||
{
|
||||
if (iter->device ()) {
|
||||
iter->device ()->set_terminal_ref_for_terminal (iter->terminal_id (), terminal_iterator ());
|
||||
}
|
||||
m_terminals.erase (iter);
|
||||
}
|
||||
|
||||
void Net::set_circuit (Circuit *circuit)
|
||||
{
|
||||
mp_circuit = circuit;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,651 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HDR_dbNet
|
||||
#define _HDR_dbNet
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "tlObject.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class Device;
|
||||
class Net;
|
||||
class SubCircuit;
|
||||
class Circuit;
|
||||
class DeviceTerminalDefinition;
|
||||
class DeviceClass;
|
||||
class Pin;
|
||||
|
||||
/**
|
||||
* @brief A reference to a terminal of a device
|
||||
*
|
||||
* A terminal must always refer to a device inside the current circuit.
|
||||
*/
|
||||
class DB_PUBLIC NetTerminalRef
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
NetTerminalRef ();
|
||||
|
||||
/**
|
||||
* @brief Creates a pin reference to the given pin of the current circuit
|
||||
*/
|
||||
NetTerminalRef (Device *device, size_t terminal_id);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
NetTerminalRef (const NetTerminalRef &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
NetTerminalRef &operator= (const NetTerminalRef &other);
|
||||
|
||||
/**
|
||||
* @brief Comparison
|
||||
*/
|
||||
bool operator< (const NetTerminalRef &other) const
|
||||
{
|
||||
if (mp_device != other.mp_device) {
|
||||
return mp_device < other.mp_device;
|
||||
}
|
||||
return m_terminal_id < other.m_terminal_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality
|
||||
*/
|
||||
bool operator== (const NetTerminalRef &other) const
|
||||
{
|
||||
return (mp_device == other.mp_device && m_terminal_id == other.m_terminal_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device reference
|
||||
*/
|
||||
Device *device ()
|
||||
{
|
||||
return mp_device;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device reference (const version)
|
||||
*/
|
||||
const Device *device () const
|
||||
{
|
||||
return mp_device;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the terminal index
|
||||
*/
|
||||
size_t terminal_id () const
|
||||
{
|
||||
return m_terminal_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the terminal definition
|
||||
*
|
||||
* Returns 0 if the terminal is not a valid terminal reference.
|
||||
*/
|
||||
const DeviceTerminalDefinition *terminal_def () const;
|
||||
|
||||
/**
|
||||
* @brief Returns the device class
|
||||
*/
|
||||
const DeviceClass *device_class () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the net the terminal lives in
|
||||
*/
|
||||
Net *net ()
|
||||
{
|
||||
return mp_net;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net the terminal lives in (const version)
|
||||
*/
|
||||
const Net *net () const
|
||||
{
|
||||
return mp_net;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Net;
|
||||
|
||||
size_t m_terminal_id;
|
||||
Device *mp_device;
|
||||
Net *mp_net;
|
||||
|
||||
/**
|
||||
* @brief Sets the net the terminal lives in
|
||||
*/
|
||||
void set_net (Net *net)
|
||||
{
|
||||
mp_net = net;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A reference to a pin inside a net
|
||||
*
|
||||
* This object describes a connection to an outgoing pin.
|
||||
*/
|
||||
class DB_PUBLIC NetPinRef
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
NetPinRef ();
|
||||
|
||||
/**
|
||||
* @brief Creates a pin reference to the given pin of the current circuit
|
||||
*/
|
||||
NetPinRef (size_t pin_id);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
NetPinRef (const NetPinRef &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
NetPinRef &operator= (const NetPinRef &other);
|
||||
|
||||
/**
|
||||
* @brief Comparison
|
||||
*/
|
||||
bool operator< (const NetPinRef &other) const
|
||||
{
|
||||
return m_pin_id < other.m_pin_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality
|
||||
*/
|
||||
bool operator== (const NetPinRef &other) const
|
||||
{
|
||||
return (m_pin_id == other.m_pin_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the pin reference (const version)
|
||||
*/
|
||||
size_t pin_id () const
|
||||
{
|
||||
return m_pin_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the pin reference from the pin id
|
||||
* If the pin cannot be resolved, null is returned.
|
||||
*/
|
||||
const Pin *pin () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the net the pin lives in
|
||||
*/
|
||||
Net *net ()
|
||||
{
|
||||
return mp_net;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net the pin lives in (const version)
|
||||
*/
|
||||
const Net *net () const
|
||||
{
|
||||
return mp_net;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Net;
|
||||
|
||||
size_t m_pin_id;
|
||||
Net *mp_net;
|
||||
|
||||
/**
|
||||
* @brief Sets the net the terminal lives in
|
||||
*/
|
||||
void set_net (Net *net)
|
||||
{
|
||||
mp_net = net;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A reference to a pin inside a net
|
||||
*
|
||||
* This object describes a connection to a pin of a subcircuit.
|
||||
*/
|
||||
class DB_PUBLIC NetSubcircuitPinRef
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
NetSubcircuitPinRef ();
|
||||
|
||||
/**
|
||||
* @brief Creates a pin reference to the given pin of the given subcircuit
|
||||
*/
|
||||
NetSubcircuitPinRef (SubCircuit *circuit, size_t pin_id);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
NetSubcircuitPinRef (const NetSubcircuitPinRef &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
NetSubcircuitPinRef &operator= (const NetSubcircuitPinRef &other);
|
||||
|
||||
/**
|
||||
* @brief Comparison
|
||||
*/
|
||||
bool operator< (const NetSubcircuitPinRef &other) const
|
||||
{
|
||||
if (mp_subcircuit != other.mp_subcircuit) {
|
||||
return mp_subcircuit < other.mp_subcircuit;
|
||||
}
|
||||
return m_pin_id < other.m_pin_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality
|
||||
*/
|
||||
bool operator== (const NetSubcircuitPinRef &other) const
|
||||
{
|
||||
return (mp_subcircuit == other.mp_subcircuit && m_pin_id == other.m_pin_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the pin reference (const version)
|
||||
*/
|
||||
size_t pin_id () const
|
||||
{
|
||||
return m_pin_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the pin reference from the pin id
|
||||
* If the pin cannot be resolved, null is returned.
|
||||
*/
|
||||
const Pin *pin () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit reference
|
||||
*/
|
||||
SubCircuit *subcircuit ()
|
||||
{
|
||||
return mp_subcircuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit reference (const version)
|
||||
*/
|
||||
const SubCircuit *subcircuit () const
|
||||
{
|
||||
return mp_subcircuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net the pin lives in
|
||||
*/
|
||||
Net *net ()
|
||||
{
|
||||
return mp_net;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net the pin lives in (const version)
|
||||
*/
|
||||
const Net *net () const
|
||||
{
|
||||
return mp_net;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Net;
|
||||
|
||||
size_t m_pin_id;
|
||||
SubCircuit *mp_subcircuit;
|
||||
Net *mp_net;
|
||||
|
||||
/**
|
||||
* @brief Sets the net the terminal lives in
|
||||
*/
|
||||
void set_net (Net *net)
|
||||
{
|
||||
mp_net = net;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A net
|
||||
*
|
||||
* A net connects terminals of devices and pins or circuits
|
||||
*/
|
||||
class DB_PUBLIC Net
|
||||
: public tl::Object
|
||||
{
|
||||
public:
|
||||
typedef std::list<NetTerminalRef> terminal_list;
|
||||
typedef terminal_list::const_iterator const_terminal_iterator;
|
||||
typedef terminal_list::iterator terminal_iterator;
|
||||
typedef std::list<NetPinRef> pin_list;
|
||||
typedef pin_list::const_iterator const_pin_iterator;
|
||||
typedef pin_list::iterator pin_iterator;
|
||||
typedef std::list<NetSubcircuitPinRef> subcircuit_pin_list;
|
||||
typedef subcircuit_pin_list::const_iterator const_subcircuit_pin_iterator;
|
||||
typedef subcircuit_pin_list::iterator subcircuit_pin_iterator;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* Creates an empty circuit.
|
||||
*/
|
||||
Net ();
|
||||
|
||||
/**
|
||||
* @brief Creates a empty net with the give name
|
||||
*/
|
||||
Net (const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
Net (const Net &other);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Net ();
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
Net &operator= (const Net &other);
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit the net lives in
|
||||
* This pointer is 0 if the net is not part of a circuit.
|
||||
*/
|
||||
Circuit *circuit ()
|
||||
{
|
||||
return mp_circuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit the net lives in (const version)
|
||||
* This pointer is 0 if the net is not part of a circuit.
|
||||
*/
|
||||
const Circuit *circuit () const
|
||||
{
|
||||
return mp_circuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the circuit
|
||||
*/
|
||||
void clear ();
|
||||
|
||||
/**
|
||||
* @brief Sets the name of the circuit
|
||||
*/
|
||||
void set_name (const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the circuit
|
||||
*/
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the expanded name
|
||||
*
|
||||
* The "expanded name" is a non-empty name for the net. It uses the
|
||||
* cluster ID if no name is set.
|
||||
*/
|
||||
std::string expanded_name () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the qualified name
|
||||
*
|
||||
* The qualified name is like the expanded name, but preceeded with the
|
||||
* Circuit name if known (e.g. "CIRCUIT:NET")
|
||||
*/
|
||||
std::string qname () const;
|
||||
|
||||
/**
|
||||
* @brief Sets the cluster ID of this net
|
||||
*
|
||||
* The cluster ID links the net to a cluster from the
|
||||
* hierarchical layout netlist extractor.
|
||||
*/
|
||||
void set_cluster_id (size_t ci);
|
||||
|
||||
/**
|
||||
* @brief Gets the cluster ID
|
||||
*/
|
||||
size_t cluster_id () const
|
||||
{
|
||||
return m_cluster_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a pin to this net
|
||||
*/
|
||||
void add_pin (const NetPinRef &pin);
|
||||
|
||||
/**
|
||||
* @brief Erases the given pin from this net
|
||||
*/
|
||||
void erase_pin (pin_iterator iter);
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the pins of the net (const version)
|
||||
*/
|
||||
const_pin_iterator begin_pins () const
|
||||
{
|
||||
return m_pins.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the pins of the net (const version)
|
||||
*/
|
||||
const_pin_iterator end_pins () const
|
||||
{
|
||||
return m_pins.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the pins of the net (non-const version)
|
||||
*/
|
||||
pin_iterator begin_pins ()
|
||||
{
|
||||
return m_pins.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the pins of the net (non-const version)
|
||||
*/
|
||||
pin_iterator end_pins ()
|
||||
{
|
||||
return m_pins.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a subcircuit pin to this net
|
||||
*/
|
||||
void add_subcircuit_pin (const NetSubcircuitPinRef &pin);
|
||||
|
||||
/**
|
||||
* @brief Erases the given subcircuit pin from this net
|
||||
*/
|
||||
void erase_subcircuit_pin (subcircuit_pin_iterator iter);
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the pins of the net (const version)
|
||||
*/
|
||||
const_subcircuit_pin_iterator begin_subcircuit_pins () const
|
||||
{
|
||||
return m_subcircuit_pins.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the pins of the net (const version)
|
||||
*/
|
||||
const_subcircuit_pin_iterator end_subcircuit_pins () const
|
||||
{
|
||||
return m_subcircuit_pins.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the pins of the net (non-const version)
|
||||
*/
|
||||
subcircuit_pin_iterator begin_subcircuit_pins ()
|
||||
{
|
||||
return m_subcircuit_pins.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the pins of the net (non-const version)
|
||||
*/
|
||||
subcircuit_pin_iterator end_subcircuit_pins ()
|
||||
{
|
||||
return m_subcircuit_pins.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a terminal to this net
|
||||
*/
|
||||
void add_terminal (const NetTerminalRef &terminal);
|
||||
|
||||
/**
|
||||
* @brief Erases the given terminal from this net
|
||||
*/
|
||||
void erase_terminal (terminal_iterator iter);
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the terminals of the net (const version)
|
||||
*/
|
||||
const_terminal_iterator begin_terminals () const
|
||||
{
|
||||
return m_terminals.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the terminals of the net (const version)
|
||||
*/
|
||||
const_terminal_iterator end_terminals () const
|
||||
{
|
||||
return m_terminals.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the terminals of the net (non-const version)
|
||||
*/
|
||||
terminal_iterator begin_terminals ()
|
||||
{
|
||||
return m_terminals.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End iterator for the terminals of the net (non-const version)
|
||||
*/
|
||||
terminal_iterator end_terminals ()
|
||||
{
|
||||
return m_terminals.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the net is floating (has no or only a single connection)
|
||||
*/
|
||||
bool is_floating () const
|
||||
{
|
||||
return (m_pins.size () + m_subcircuit_pins.size () + m_terminals.size ()) < 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the net is an internal node (connects two terminals only)
|
||||
*/
|
||||
bool is_internal () const
|
||||
{
|
||||
return m_pins.size () == 0 && m_subcircuit_pins.size () == 0 && m_terminals.size () == 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of outgoing pins connected
|
||||
*/
|
||||
size_t pin_count () const
|
||||
{
|
||||
return m_pins.size ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of subcircuit pins connected
|
||||
*/
|
||||
size_t subcircuit_pin_count () const
|
||||
{
|
||||
return m_subcircuit_pins.size ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of terminals connected
|
||||
*/
|
||||
size_t terminal_count () const
|
||||
{
|
||||
return m_terminals.size ();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Circuit;
|
||||
|
||||
terminal_list m_terminals;
|
||||
pin_list m_pins;
|
||||
subcircuit_pin_list m_subcircuit_pins;
|
||||
std::string m_name;
|
||||
size_t m_cluster_id;
|
||||
Circuit *mp_circuit;
|
||||
|
||||
void set_circuit (Circuit *circuit);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HDR_dbNetlistUtils
|
||||
#define _HDR_dbNetlistUtils
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A getter for the ID of an object
|
||||
*/
|
||||
template <class T>
|
||||
struct id_attribute
|
||||
{
|
||||
typedef size_t attr_type;
|
||||
size_t operator() (const T *t) const { return t->id (); }
|
||||
bool has (const T * /*t*/) const { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A getter for the cluster ID of an object
|
||||
*/
|
||||
template <class T>
|
||||
struct cluster_id_attribute
|
||||
{
|
||||
typedef size_t attr_type;
|
||||
attr_type operator() (const T *t) const { return t->cluster_id (); }
|
||||
bool has (const T * /*t*/) const { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A getter for the cluster ID of an object
|
||||
*/
|
||||
template <class T>
|
||||
struct cell_index_attribute
|
||||
{
|
||||
typedef db::cell_index_type attr_type;
|
||||
attr_type operator() (const T *t) const { return t->cell_index (); }
|
||||
bool has (const T * /*t*/) const { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A getter for the name of an object
|
||||
*/
|
||||
template <class T>
|
||||
struct name_attribute
|
||||
{
|
||||
typedef std::string attr_type;
|
||||
const attr_type &operator() (const T *t) const { return t->name (); }
|
||||
bool has (const T *t) const { return ! t->name ().empty (); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An id-to-object translation table
|
||||
*/
|
||||
template <class T, class I, class ATTR>
|
||||
class object_by_attr
|
||||
{
|
||||
public:
|
||||
typedef typename ATTR::attr_type attr_type;
|
||||
typedef typename I::value_type value_type;
|
||||
|
||||
object_by_attr (T *self, I (T::*bi) (), I (T::*ei) ()) : mp_self (self), m_bi (bi), m_ei (ei), m_valid (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void invalidate ()
|
||||
{
|
||||
m_valid = false;
|
||||
m_map.clear ();
|
||||
}
|
||||
|
||||
value_type *object_by (const attr_type &attr) const
|
||||
{
|
||||
if (! m_valid) {
|
||||
validate ();
|
||||
}
|
||||
typename std::map<attr_type, value_type *>::const_iterator m = m_map.find (attr);
|
||||
return m == m_map.end () ? 0 : m->second;
|
||||
}
|
||||
|
||||
private:
|
||||
T *mp_self;
|
||||
I (T::*m_bi) ();
|
||||
I (T::*m_ei) ();
|
||||
mutable bool m_valid;
|
||||
mutable std::map<attr_type, value_type *> m_map;
|
||||
|
||||
void validate () const
|
||||
{
|
||||
ATTR attr;
|
||||
m_map.clear ();
|
||||
for (I i = (mp_self->*m_bi) (); i != (mp_self->*m_ei) (); ++i) {
|
||||
if (attr.has (i.operator-> ())) {
|
||||
m_map.insert (std::make_pair (attr (i.operator-> ()), i.operator-> ()));
|
||||
}
|
||||
}
|
||||
m_valid = true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbPin.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Pin class implementation
|
||||
|
||||
Pin::Pin ()
|
||||
: m_id (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Pin::Pin (const std::string &name)
|
||||
: m_name (name), m_id (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HDR_dbPin
|
||||
#define _HDR_dbPin
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The definition of a pin of a circuit
|
||||
*
|
||||
* A pin is some place other nets can connect to a circuit.
|
||||
*/
|
||||
class DB_PUBLIC Pin
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
Pin ();
|
||||
|
||||
/**
|
||||
* @brief Creates a pin with the given name.
|
||||
*/
|
||||
Pin (const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the pin
|
||||
*/
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the ID of the pin (only pins inside circuits have valid ID's)
|
||||
*/
|
||||
size_t id () const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Circuit;
|
||||
|
||||
std::string m_name;
|
||||
size_t m_id;
|
||||
|
||||
void set_id (size_t id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbSubCircuit.h"
|
||||
#include "dbCircuit.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// SubCircuit class implementation
|
||||
|
||||
SubCircuit::SubCircuit ()
|
||||
: m_id (0), mp_circuit (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
SubCircuit::~SubCircuit()
|
||||
{
|
||||
for (std::vector<Net::subcircuit_pin_iterator>::const_iterator p = m_pin_refs.begin (); p != m_pin_refs.end (); ++p) {
|
||||
if (*p != Net::subcircuit_pin_iterator () && (*p)->net ()) {
|
||||
(*p)->net ()->erase_subcircuit_pin (*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SubCircuit::SubCircuit (Circuit *circuit, const std::string &name)
|
||||
: m_circuit_ref (0), m_name (name), m_id (0), mp_circuit (0)
|
||||
{
|
||||
set_circuit_ref (circuit);
|
||||
}
|
||||
|
||||
SubCircuit::SubCircuit (const SubCircuit &other)
|
||||
: m_id (0), mp_circuit (0)
|
||||
{
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
SubCircuit &SubCircuit::operator= (const SubCircuit &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_name = other.m_name;
|
||||
m_trans = other.m_trans;
|
||||
set_circuit_ref (const_cast<Circuit *> (other.circuit_ref ()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SubCircuit::set_name (const std::string &n)
|
||||
{
|
||||
m_name = n;
|
||||
if (mp_circuit) {
|
||||
mp_circuit->m_subcircuit_by_name.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
void SubCircuit::set_trans (const db::DCplxTrans &t)
|
||||
{
|
||||
m_trans = t;
|
||||
}
|
||||
|
||||
void SubCircuit::set_pin_ref_for_pin (size_t pin_id, Net::subcircuit_pin_iterator iter)
|
||||
{
|
||||
if (m_pin_refs.size () < pin_id + 1) {
|
||||
m_pin_refs.resize (pin_id + 1, Net::subcircuit_pin_iterator ());
|
||||
}
|
||||
m_pin_refs [pin_id] = iter;
|
||||
}
|
||||
|
||||
void SubCircuit::set_circuit_ref (Circuit *c)
|
||||
{
|
||||
if (m_circuit_ref.get ()) {
|
||||
m_circuit_ref->unregister_ref (this);
|
||||
}
|
||||
m_circuit_ref.reset (c);
|
||||
if (m_circuit_ref.get ()) {
|
||||
m_circuit_ref->register_ref (this);
|
||||
}
|
||||
}
|
||||
|
||||
const Net *SubCircuit::net_for_pin (size_t pin_id) const
|
||||
{
|
||||
if (pin_id < m_pin_refs.size ()) {
|
||||
Net::subcircuit_pin_iterator p = m_pin_refs [pin_id];
|
||||
if (p != Net::subcircuit_pin_iterator ()) {
|
||||
return p->net ();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SubCircuit::connect_pin (size_t pin_id, Net *net)
|
||||
{
|
||||
if (net_for_pin (pin_id) == net) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pin_id < m_pin_refs.size ()) {
|
||||
Net::subcircuit_pin_iterator p = m_pin_refs [pin_id];
|
||||
if (p != Net::subcircuit_pin_iterator () && p->net ()) {
|
||||
p->net ()->erase_subcircuit_pin (p);
|
||||
}
|
||||
m_pin_refs [pin_id] = Net::subcircuit_pin_iterator ();
|
||||
}
|
||||
|
||||
if (net) {
|
||||
net->add_subcircuit_pin (NetSubcircuitPinRef (this, pin_id));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HDR_dbSubCircuit
|
||||
#define _HDR_dbSubCircuit
|
||||
|
||||
#include "dbCommon.h"
|
||||
#include "dbTrans.h"
|
||||
#include "dbNet.h"
|
||||
|
||||
#include "tlObject.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class Circuit;
|
||||
|
||||
/**
|
||||
* @brief A subcircuit of a circuit
|
||||
*
|
||||
* This class essentially is a reference to another circuit
|
||||
*/
|
||||
class DB_PUBLIC SubCircuit
|
||||
: public tl::Object
|
||||
{
|
||||
public:
|
||||
typedef tl::vector<const Net *> connected_net_list;
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
SubCircuit ();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
SubCircuit (const SubCircuit &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
SubCircuit &operator= (const SubCircuit &other);
|
||||
|
||||
/**
|
||||
* @brief Creates a subcircuit reference to the given circuit
|
||||
*/
|
||||
SubCircuit (Circuit *circuit_ref, const std::string &name = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~SubCircuit ();
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit ID
|
||||
* The ID is a unique integer which identifies the subcircuit.
|
||||
* It can be used to retrieve the subcircuit from the circuit using Circuit::subcircuit_by_id.
|
||||
* When assigned, the subcircuit ID is not 0.
|
||||
*/
|
||||
size_t id () const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit the subcircuit lives in (const version)
|
||||
* This pointer is 0 if the subcircuit isn't added to a circuit
|
||||
*/
|
||||
const Circuit *circuit () const
|
||||
{
|
||||
return mp_circuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit the subcircuit lives in (non-const version)
|
||||
* This pointer is 0 if the subcircuit isn't added to a circuit
|
||||
*/
|
||||
Circuit *circuit ()
|
||||
{
|
||||
return mp_circuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit the reference points to (const version)
|
||||
*/
|
||||
const Circuit *circuit_ref () const
|
||||
{
|
||||
return m_circuit_ref.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit the reference points to (non-const version)
|
||||
*/
|
||||
Circuit *circuit_ref ()
|
||||
{
|
||||
return m_circuit_ref.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the name of the subcircuit
|
||||
*
|
||||
* The name is one way to identify the subcircuit. The transformation is
|
||||
* another one.
|
||||
*/
|
||||
void set_name (const std::string &n);
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the subcircuit
|
||||
*/
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the transformation describing the subcircuit
|
||||
*
|
||||
* The transformation is a natural description of a subcircuit
|
||||
* (in contrast to the name) when deriving it from a layout.
|
||||
*/
|
||||
void set_trans (const db::DCplxTrans &trans);
|
||||
|
||||
/**
|
||||
* @brief Gets the transformation describing the subcircuit
|
||||
*/
|
||||
const db::DCplxTrans &trans () const
|
||||
{
|
||||
return m_trans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net attached to a specific pin
|
||||
* Returns 0 if no net is attached.
|
||||
*/
|
||||
const Net *net_for_pin (size_t pin_id) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the net attached to a specific pin (non-const version)
|
||||
* Returns 0 if no net is attached.
|
||||
*/
|
||||
Net *net_for_pin (size_t pin_id)
|
||||
{
|
||||
return const_cast<Net *> (((const SubCircuit *) this)->net_for_pin (pin_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connects the given pin to the given net
|
||||
* If the net is 0 the pin is disconnected.
|
||||
* If non-null, a NetPinRef object will be inserted into the
|
||||
* net and connected with the given pin.
|
||||
*/
|
||||
void connect_pin (size_t pin_id, Net *net);
|
||||
|
||||
private:
|
||||
friend class Circuit;
|
||||
friend class Net;
|
||||
|
||||
tl::weak_ptr<Circuit> m_circuit_ref;
|
||||
std::string m_name;
|
||||
db::DCplxTrans m_trans;
|
||||
std::vector<Net::subcircuit_pin_iterator> m_pin_refs;
|
||||
size_t m_id;
|
||||
Circuit *mp_circuit;
|
||||
|
||||
/**
|
||||
* @brief Sets the pin reference for a specific pin
|
||||
*/
|
||||
void set_pin_ref_for_pin (size_t ppin_id, Net::subcircuit_pin_iterator iter);
|
||||
|
||||
/**
|
||||
* @brief Sets the circuit reference
|
||||
*/
|
||||
void set_circuit_ref (Circuit *c);
|
||||
|
||||
/**
|
||||
* @brief Sets the circuit the subcircuit belongs to
|
||||
*/
|
||||
void set_circuit (Circuit *c)
|
||||
{
|
||||
mp_circuit = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the device ID
|
||||
*/
|
||||
void set_id (size_t id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
static std::string pd2string (const db::DeviceTerminalDefinition &pd)
|
||||
{
|
||||
return pd.name () + "(" + pd.description () + ") #" + tl::to_string (pd.id ());
|
||||
|
|
@ -38,78 +40,6 @@ static std::string pd2string (const db::DeviceParameterDefinition &pd)
|
|||
return pd.name () + "(" + pd.description () + ")=" + tl::to_string (pd.default_value ()) + " #" + tl::to_string (pd.id ());
|
||||
}
|
||||
|
||||
TEST(1_DeviceTerminalDefinition)
|
||||
{
|
||||
db::DeviceTerminalDefinition pd;
|
||||
|
||||
EXPECT_EQ (pd2string (pd), "() #0");
|
||||
pd.set_name ("name");
|
||||
pd.set_description ("nothing yet");
|
||||
EXPECT_EQ (pd2string (pd), "name(nothing yet) #0");
|
||||
|
||||
db::DeviceTerminalDefinition pd2;
|
||||
pd2 = pd;
|
||||
EXPECT_EQ (pd2string (pd2), "name(nothing yet) #0");
|
||||
pd2.set_name ("name2");
|
||||
pd2.set_description ("now it has something");
|
||||
EXPECT_EQ (pd2string (pd2), "name2(now it has something) #0");
|
||||
|
||||
db::DeviceClass dc;
|
||||
dc.add_terminal_definition (pd);
|
||||
dc.add_terminal_definition (pd2);
|
||||
EXPECT_EQ (pd2string (dc.terminal_definitions ()[0]), "name(nothing yet) #0");
|
||||
EXPECT_EQ (pd2string (dc.terminal_definitions ()[1]), "name2(now it has something) #1");
|
||||
|
||||
dc.clear_terminal_definitions ();
|
||||
EXPECT_EQ (dc.terminal_definitions ().empty (), true);
|
||||
|
||||
db::DeviceParameterDefinition ppd ("P1", "Parameter 1", 1.0);
|
||||
dc.add_parameter_definition (ppd);
|
||||
|
||||
db::DeviceParameterDefinition ppd2 ("P2", "Parameter 2");
|
||||
dc.add_parameter_definition (ppd2);
|
||||
|
||||
EXPECT_EQ (pd2string (dc.parameter_definitions ()[0]), "P1(Parameter 1)=1 #0");
|
||||
EXPECT_EQ (pd2string (dc.parameter_definitions ()[1]), "P2(Parameter 2)=0 #1");
|
||||
|
||||
dc.clear_parameter_definitions ();
|
||||
EXPECT_EQ (dc.parameter_definitions ().empty (), true);
|
||||
}
|
||||
|
||||
TEST(2_DeviceClass)
|
||||
{
|
||||
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");
|
||||
EXPECT_EQ (dc.name (), "devname");
|
||||
EXPECT_EQ (dc.description (), "devdesc");
|
||||
dc.add_terminal_definition (pd);
|
||||
dc.add_terminal_definition (pd2);
|
||||
EXPECT_EQ (dc.terminal_definitions ().size (), size_t (2));
|
||||
EXPECT_EQ (pd2string (dc.terminal_definitions ()[0]), "name(nothing yet) #0");
|
||||
EXPECT_EQ (pd2string (dc.terminal_definitions ()[1]), "name2(now it has something) #1");
|
||||
|
||||
EXPECT_EQ (pd2string (*dc.terminal_definition (dc.terminal_definitions ()[0].id ())), "name(nothing yet) #0");
|
||||
EXPECT_EQ (pd2string (*dc.terminal_definition (dc.terminal_definitions ()[1].id ())), "name2(now it has something) #1");
|
||||
EXPECT_EQ (dc.terminal_definition (3), 0);
|
||||
|
||||
db::DeviceClass dc2 = dc;
|
||||
EXPECT_EQ (dc2.name (), "devname");
|
||||
EXPECT_EQ (dc2.description (), "devdesc");
|
||||
EXPECT_EQ (dc2.terminal_definitions ().size (), size_t (2));
|
||||
EXPECT_EQ (pd2string (*dc2.terminal_definition (dc2.terminal_definitions ()[0].id ())), "name(nothing yet) #0");
|
||||
EXPECT_EQ (pd2string (*dc2.terminal_definition (dc2.terminal_definitions ()[1].id ())), "name2(now it has something) #1");
|
||||
EXPECT_EQ (dc2.terminal_definition (3), 0);
|
||||
}
|
||||
|
||||
static std::string pins2string (const db::Circuit &c)
|
||||
{
|
||||
std::string res;
|
||||
|
|
@ -123,32 +53,6 @@ static std::string pins2string (const db::Circuit &c)
|
|||
return res;
|
||||
}
|
||||
|
||||
TEST(3_CircuitBasic)
|
||||
{
|
||||
db::Circuit c;
|
||||
c.set_name ("name");
|
||||
EXPECT_EQ (c.name (), "name");
|
||||
|
||||
db::Pin p1 = c.add_pin ("p1");
|
||||
db::Pin p2 = c.add_pin ("p2");
|
||||
EXPECT_EQ (pins2string (c), "p1#0,p2#1");
|
||||
|
||||
EXPECT_EQ (c.pin_by_id (0)->name (), "p1");
|
||||
EXPECT_EQ (c.pin_by_id (1)->name (), "p2");
|
||||
EXPECT_EQ (c.pin_by_id (2), 0);
|
||||
EXPECT_EQ (c.pin_by_name ("p1")->name (), "p1");
|
||||
EXPECT_EQ (c.pin_by_name ("doesnt_exist") == 0, true);
|
||||
EXPECT_EQ (c.pin_by_name ("p2")->name (), "p2");
|
||||
|
||||
db::Circuit c2 = c;
|
||||
EXPECT_EQ (c2.name (), "name");
|
||||
EXPECT_EQ (pins2string (c), "p1#0,p2#1");
|
||||
|
||||
EXPECT_EQ (c2.pin_by_id (0)->name (), "p1");
|
||||
EXPECT_EQ (c2.pin_by_id (1)->name (), "p2");
|
||||
EXPECT_EQ (c2.pin_by_id (2), 0);
|
||||
}
|
||||
|
||||
static std::string net2string (const db::Net &n)
|
||||
{
|
||||
std::string res;
|
||||
|
|
@ -243,6 +147,186 @@ static std::string netlist2 (const db::Circuit &c)
|
|||
return res;
|
||||
}
|
||||
|
||||
static std::string nl2string (const db::Netlist &nl)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Netlist::const_circuit_iterator c = nl.begin_circuits (); c != nl.end_circuits (); ++c) {
|
||||
res += "[" + c->name () + "]\n";
|
||||
res += nets2string (*c);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// dual form of netlist
|
||||
static std::string netlist2 (const db::Netlist &nl)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Netlist::const_circuit_iterator c = nl.begin_circuits (); c != nl.end_circuits (); ++c) {
|
||||
res += netlist2 (*c);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string refs2string (const db::Circuit *c)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Circuit::const_refs_iterator r = c->begin_refs (); r != c->end_refs (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += r->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string children2string (const db::Circuit *c)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Circuit::const_child_circuit_iterator r = c->begin_children (); r != c->end_children (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += (*r)->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string parents2string (const db::Circuit *c)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Circuit::const_parent_circuit_iterator r = c->begin_parents (); r != c->end_parents (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += (*r)->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string td2string (const db::Netlist *nl)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Netlist::const_top_down_circuit_iterator r = nl->begin_top_down (); r != nl->end_top_down (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += (*r)->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string bu2string (const db::Netlist *nl)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Netlist::const_bottom_up_circuit_iterator r = nl->begin_bottom_up (); r != nl->end_bottom_up (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += (*r)->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
TEST(1_DeviceTerminalDefinition)
|
||||
{
|
||||
db::DeviceTerminalDefinition pd;
|
||||
|
||||
EXPECT_EQ (pd2string (pd), "() #0");
|
||||
pd.set_name ("name");
|
||||
pd.set_description ("nothing yet");
|
||||
EXPECT_EQ (pd2string (pd), "name(nothing yet) #0");
|
||||
|
||||
db::DeviceTerminalDefinition pd2;
|
||||
pd2 = pd;
|
||||
EXPECT_EQ (pd2string (pd2), "name(nothing yet) #0");
|
||||
pd2.set_name ("name2");
|
||||
pd2.set_description ("now it has something");
|
||||
EXPECT_EQ (pd2string (pd2), "name2(now it has something) #0");
|
||||
|
||||
db::DeviceClass dc;
|
||||
dc.add_terminal_definition (pd);
|
||||
dc.add_terminal_definition (pd2);
|
||||
EXPECT_EQ (pd2string (dc.terminal_definitions ()[0]), "name(nothing yet) #0");
|
||||
EXPECT_EQ (pd2string (dc.terminal_definitions ()[1]), "name2(now it has something) #1");
|
||||
|
||||
dc.clear_terminal_definitions ();
|
||||
EXPECT_EQ (dc.terminal_definitions ().empty (), true);
|
||||
|
||||
db::DeviceParameterDefinition ppd ("P1", "Parameter 1", 1.0);
|
||||
dc.add_parameter_definition (ppd);
|
||||
|
||||
db::DeviceParameterDefinition ppd2 ("P2", "Parameter 2");
|
||||
dc.add_parameter_definition (ppd2);
|
||||
|
||||
EXPECT_EQ (pd2string (dc.parameter_definitions ()[0]), "P1(Parameter 1)=1 #0");
|
||||
EXPECT_EQ (pd2string (dc.parameter_definitions ()[1]), "P2(Parameter 2)=0 #1");
|
||||
|
||||
dc.clear_parameter_definitions ();
|
||||
EXPECT_EQ (dc.parameter_definitions ().empty (), true);
|
||||
}
|
||||
|
||||
TEST(2_DeviceClass)
|
||||
{
|
||||
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");
|
||||
EXPECT_EQ (dc.name (), "devname");
|
||||
EXPECT_EQ (dc.description (), "devdesc");
|
||||
dc.add_terminal_definition (pd);
|
||||
dc.add_terminal_definition (pd2);
|
||||
EXPECT_EQ (dc.terminal_definitions ().size (), size_t (2));
|
||||
EXPECT_EQ (pd2string (dc.terminal_definitions ()[0]), "name(nothing yet) #0");
|
||||
EXPECT_EQ (pd2string (dc.terminal_definitions ()[1]), "name2(now it has something) #1");
|
||||
|
||||
EXPECT_EQ (pd2string (*dc.terminal_definition (dc.terminal_definitions ()[0].id ())), "name(nothing yet) #0");
|
||||
EXPECT_EQ (pd2string (*dc.terminal_definition (dc.terminal_definitions ()[1].id ())), "name2(now it has something) #1");
|
||||
EXPECT_EQ (dc.terminal_definition (3), 0);
|
||||
|
||||
db::DeviceClass dc2 = dc;
|
||||
EXPECT_EQ (dc2.name (), "devname");
|
||||
EXPECT_EQ (dc2.description (), "devdesc");
|
||||
EXPECT_EQ (dc2.terminal_definitions ().size (), size_t (2));
|
||||
EXPECT_EQ (pd2string (*dc2.terminal_definition (dc2.terminal_definitions ()[0].id ())), "name(nothing yet) #0");
|
||||
EXPECT_EQ (pd2string (*dc2.terminal_definition (dc2.terminal_definitions ()[1].id ())), "name2(now it has something) #1");
|
||||
EXPECT_EQ (dc2.terminal_definition (3), 0);
|
||||
}
|
||||
|
||||
TEST(3_CircuitBasic)
|
||||
{
|
||||
db::Circuit c;
|
||||
c.set_name ("name");
|
||||
EXPECT_EQ (c.name (), "name");
|
||||
|
||||
db::Pin p1 = c.add_pin ("p1");
|
||||
db::Pin p2 = c.add_pin ("p2");
|
||||
EXPECT_EQ (pins2string (c), "p1#0,p2#1");
|
||||
|
||||
EXPECT_EQ (c.pin_by_id (0)->name (), "p1");
|
||||
EXPECT_EQ (c.pin_by_id (1)->name (), "p2");
|
||||
EXPECT_EQ (c.pin_by_id (2), 0);
|
||||
EXPECT_EQ (c.pin_by_name ("p1")->name (), "p1");
|
||||
EXPECT_EQ (c.pin_by_name ("doesnt_exist") == 0, true);
|
||||
EXPECT_EQ (c.pin_by_name ("p2")->name (), "p2");
|
||||
|
||||
db::Circuit c2 = c;
|
||||
EXPECT_EQ (c2.name (), "name");
|
||||
EXPECT_EQ (pins2string (c), "p1#0,p2#1");
|
||||
|
||||
EXPECT_EQ (c2.pin_by_id (0)->name (), "p1");
|
||||
EXPECT_EQ (c2.pin_by_id (1)->name (), "p2");
|
||||
EXPECT_EQ (c2.pin_by_id (2), 0);
|
||||
}
|
||||
|
||||
TEST(4_CircuitDevices)
|
||||
{
|
||||
db::DeviceClass dc1;
|
||||
|
|
@ -403,38 +487,6 @@ TEST(4_CircuitDevices)
|
|||
);
|
||||
}
|
||||
|
||||
static std::string nl2string (const db::Netlist &nl)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Netlist::const_circuit_iterator c = nl.begin_circuits (); c != nl.end_circuits (); ++c) {
|
||||
res += "[" + c->name () + "]\n";
|
||||
res += nets2string (*c);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// dual form of netlist
|
||||
static std::string netlist2 (const db::Netlist &nl)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Netlist::const_circuit_iterator c = nl.begin_circuits (); c != nl.end_circuits (); ++c) {
|
||||
res += netlist2 (*c);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string refs2string (const db::Circuit *c)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Circuit::const_refs_iterator r = c->begin_refs (); r != c->end_refs (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += r->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
TEST(4_NetlistSubcircuits)
|
||||
{
|
||||
std::auto_ptr<db::Netlist> nl (new db::Netlist ());
|
||||
|
|
@ -897,54 +949,6 @@ TEST(11_NetlistCircuitRefs)
|
|||
EXPECT_EQ (refs2string (c2), "sc1,sc2");
|
||||
}
|
||||
|
||||
static std::string children2string (const db::Circuit *c)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Circuit::const_child_circuit_iterator r = c->begin_children (); r != c->end_children (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += (*r)->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string parents2string (const db::Circuit *c)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Circuit::const_parent_circuit_iterator r = c->begin_parents (); r != c->end_parents (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += (*r)->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string td2string (const db::Netlist *nl)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Netlist::const_top_down_circuit_iterator r = nl->begin_top_down (); r != nl->end_top_down (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += (*r)->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string bu2string (const db::Netlist *nl)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Netlist::const_bottom_up_circuit_iterator r = nl->begin_bottom_up (); r != nl->end_bottom_up (); ++r) {
|
||||
if (!res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += (*r)->name ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
TEST(12_NetlistTopology)
|
||||
{
|
||||
std::auto_ptr<db::Netlist> nl (new db::Netlist ());
|
||||
|
|
|
|||
Loading…
Reference in New Issue