mirror of https://github.com/KLayout/klayout.git
WIP: LVS DB model
This commit is contained in:
parent
252622e3f8
commit
f1fc16d55f
|
|
@ -27,6 +27,10 @@ namespace db
|
|||
|
||||
namespace l2n_std_format
|
||||
{
|
||||
const char *l2n_magic_string_cstr = "#%l2n-klayout";
|
||||
template<> DB_PUBLIC const std::string keys<false>::l2n_magic_string (l2n_magic_string_cstr);
|
||||
template<> DB_PUBLIC const std::string keys<true>::l2n_magic_string (l2n_magic_string_cstr);
|
||||
|
||||
template<> DB_PUBLIC const std::string keys<false>::version_key ("version");
|
||||
template<> DB_PUBLIC const std::string keys<false>::description_key ("description");
|
||||
template<> DB_PUBLIC const std::string keys<false>::top_key ("top");
|
||||
|
|
|
|||
|
|
@ -134,6 +134,8 @@ namespace l2n_std_format
|
|||
template <bool Short>
|
||||
struct DB_PUBLIC keys
|
||||
{
|
||||
static const std::string l2n_magic_string;
|
||||
|
||||
static const std::string version_key;
|
||||
static const std::string description_key;
|
||||
static const std::string top_key;
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ void std_writer_impl<Keys>::write (const db::Netlist *nl, const db::LayoutToNetl
|
|||
const std::string indent (nested ? indent1 : "");
|
||||
|
||||
if (! nested) {
|
||||
*mp_stream << "#%l2n-klayout" << endl;
|
||||
*mp_stream << Keys::l2n_magic_string << endl;
|
||||
}
|
||||
|
||||
if (version > 0) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ namespace db
|
|||
|
||||
namespace lvs_std_format
|
||||
{
|
||||
const char *lvs_magic_string_cstr = "#%lvsdb-klayout";
|
||||
template<> DB_PUBLIC const std::string keys<false>::lvs_magic_string (lvs_magic_string_cstr);
|
||||
template<> DB_PUBLIC const std::string keys<true>::lvs_magic_string (lvs_magic_string_cstr);
|
||||
|
||||
template<> DB_PUBLIC const std::string keys<false>::reference_key ("reference");
|
||||
template<> DB_PUBLIC const std::string keys<false>::layout_key ("layout");
|
||||
template<> DB_PUBLIC const std::string keys<false>::xref_key ("xref");
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ namespace db
|
|||
*
|
||||
* Global statements:
|
||||
*
|
||||
* #%lvsdb-klayout - header line identifies format
|
||||
* version(<number>) - file format version [short key: V]
|
||||
* description(<text>) - an arbitrary description text [short key: B]
|
||||
* layout([layout]) - layout part [short key: J]
|
||||
|
|
@ -126,6 +127,8 @@ namespace lvs_std_format
|
|||
{
|
||||
typedef l2n_std_format::keys<Short> l2n_keys;
|
||||
|
||||
static const std::string lvs_magic_string;
|
||||
|
||||
static const std::string reference_key;
|
||||
static const std::string layout_key;
|
||||
static const std::string xref_key;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void std_writer_impl<Keys>::write (const db::LayoutVsSchematic *lvs)
|
|||
{
|
||||
const int version = 0;
|
||||
|
||||
stream () << "#%lvsdb-klayout" << endl;
|
||||
stream () << Keys::lvs_magic_string << endl;
|
||||
|
||||
if (version > 0) {
|
||||
stream () << Keys::version_key << "(" << version << ")" << endl;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "laybasicCommon.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace db
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "layConfigurationDialog.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbLayoutToNetlistFormatDefs.h"
|
||||
#include "dbLayoutVsSchematicFormatDefs.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
|
|
@ -442,22 +444,38 @@ NetlistBrowserDialog::open_clicked ()
|
|||
BEGIN_PROTECTED
|
||||
|
||||
std::string fmts = tl::to_string (QObject::tr ("All files (*)"));
|
||||
#if 0 // @@@ would be good to have this:
|
||||
#if 0 // TODO: would be good to have this:
|
||||
// collect the formats available ...
|
||||
for (tl::Registrar<rdb::FormatDeclaration>::iterator rdr = tl::Registrar<rdb::FormatDeclaration>::begin (); rdr != tl::Registrar<rdb::FormatDeclaration>::end (); ++rdr) {
|
||||
fmts += ";;" + rdr->file_format ();
|
||||
}
|
||||
#else
|
||||
fmts += ";;L2N DB files (*.l2n)";
|
||||
// @@@ TODO: add plain spice
|
||||
fmts += ";;L2N DB files (*.l2n);;LVS DB files (*.lvsdb)";
|
||||
// TODO: add plain spice
|
||||
#endif
|
||||
|
||||
// prepare and open the file dialog
|
||||
lay::FileDialog open_dialog (this, tl::to_string (QObject::tr ("Netlist Database File")), fmts);
|
||||
lay::FileDialog open_dialog (this, tl::to_string (QObject::tr ("Netlist/LVS Database File")), fmts);
|
||||
if (open_dialog.get_open (m_open_filename)) {
|
||||
|
||||
std::auto_ptr <db::LayoutToNetlist> db (new db::LayoutToNetlist ());
|
||||
db->load (m_open_filename);
|
||||
std::auto_ptr <db::LayoutToNetlist> db;
|
||||
|
||||
// TODO: generic concept to detect format
|
||||
std::string first_line;
|
||||
{
|
||||
tl::InputStream stream (m_open_filename);
|
||||
tl::TextInputStream text_stream (stream);
|
||||
first_line = text_stream.get_line ();
|
||||
}
|
||||
|
||||
if (first_line.find (db::lvs_std_format::keys<false>::lvs_magic_string) == 0) {
|
||||
db::LayoutVsSchematic *lvs_db = new db::LayoutVsSchematic ();
|
||||
db.reset (lvs_db);
|
||||
lvs_db->load (m_open_filename);
|
||||
} else {
|
||||
db.reset (new db::LayoutToNetlist ());
|
||||
db->load (m_open_filename);
|
||||
}
|
||||
|
||||
int l2n_index = view ()->add_l2ndb (db.release ());
|
||||
l2ndb_cb->setCurrentIndex (l2n_index);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "layNetlistBrowserModel.h"
|
||||
#include "layIndexedNetlistModel.h"
|
||||
#include "layNetlistCrossReferenceModel.h"
|
||||
#include "dbNetlistDeviceClasses.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
|
@ -205,12 +206,19 @@ static inline bool always (bool)
|
|||
}
|
||||
|
||||
NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer)
|
||||
: QAbstractItemModel (parent), mp_l2ndb (l2ndb), mp_colorizer (colorizer)
|
||||
: QAbstractItemModel (parent), mp_l2ndb (l2ndb), mp_lvsdb (0), mp_colorizer (colorizer)
|
||||
{
|
||||
mp_indexer.reset (new SingleIndexedNetlistModel (l2ndb->netlist ()));
|
||||
connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ()));
|
||||
}
|
||||
|
||||
NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutVsSchematic *lvsdb, NetColorizer *colorizer)
|
||||
: QAbstractItemModel (parent), mp_l2ndb (0), mp_lvsdb (lvsdb), mp_colorizer (colorizer)
|
||||
{
|
||||
mp_indexer.reset (new NetlistCrossReferenceModel (lvsdb->cross_ref ()));
|
||||
connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ()));
|
||||
}
|
||||
|
||||
NetlistBrowserModel::~NetlistBrowserModel ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
|
|
@ -307,6 +315,10 @@ NetlistBrowserModel::make_id_circuit_device_terminal (size_t circuit_index, size
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return id == 0;
|
||||
}
|
||||
|
|
@ -314,6 +326,10 @@ NetlistBrowserModel::is_id_circuit (void *id) const
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit_pin (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 1 && always (pop (id, mp_indexer->pin_count (circuits))) && id == 0);
|
||||
|
|
@ -322,6 +338,10 @@ NetlistBrowserModel::is_id_circuit_pin (void *id) const
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit_pin_net (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 1 && always (pop (id, mp_indexer->pin_count (circuits))) && id != 0);
|
||||
|
|
@ -330,6 +350,10 @@ NetlistBrowserModel::is_id_circuit_pin_net (void *id) const
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit_net (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && id == 0);
|
||||
|
|
@ -338,24 +362,50 @@ NetlistBrowserModel::is_id_circuit_net (void *id) const
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit_net_device_terminal (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *org_id = id;
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 1 && always (pop (id, mp_indexer->net_terminal_count (nets))) && id == 0);
|
||||
if (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 1) {
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (org_id);
|
||||
pop (id, mp_indexer->net_terminal_count (nets));
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NetlistBrowserModel::is_id_circuit_net_device_terminal_others (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *org_id = id;
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 1 && always (pop (id, mp_indexer->net_terminal_count (nets))) && id != 0);
|
||||
if (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 1) {
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (org_id);
|
||||
pop (id, mp_indexer->net_terminal_count (nets));
|
||||
return id != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NetlistBrowserModel::is_id_circuit_net_pin (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 2);
|
||||
|
|
@ -364,24 +414,50 @@ NetlistBrowserModel::is_id_circuit_net_pin (void *id) const
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit_net_subcircuit_pin (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *org_id = id;
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 3 && always (pop (id, mp_indexer->net_subcircuit_pin_count (nets))) && id == 0);
|
||||
if (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 3) {
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (org_id);
|
||||
pop (id, mp_indexer->net_subcircuit_pin_count (nets));
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NetlistBrowserModel::is_id_circuit_net_subcircuit_pin_others (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *org_id = id;
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 3 && always (pop (id, mp_indexer->net_subcircuit_pin_count (nets))) && id != 0);
|
||||
if (pop (id, 8) == 2 && always (pop (id, mp_indexer->net_count (circuits))) && pop (id, 4) == 3) {
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (org_id);
|
||||
pop (id, mp_indexer->net_subcircuit_pin_count (nets));
|
||||
return id != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NetlistBrowserModel::is_id_circuit_subcircuit (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 3 && always (pop (id, mp_indexer->subcircuit_count (circuits))) && id == 0);
|
||||
|
|
@ -390,6 +466,10 @@ NetlistBrowserModel::is_id_circuit_subcircuit (void *id) const
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit_subcircuit_pin (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 3 && always (pop (id, mp_indexer->subcircuit_count (circuits))) && id != 0);
|
||||
|
|
@ -398,6 +478,10 @@ NetlistBrowserModel::is_id_circuit_subcircuit_pin (void *id) const
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit_device (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 4 && always (pop (id, mp_indexer->device_count (circuits))) && id == 0);
|
||||
|
|
@ -406,6 +490,10 @@ NetlistBrowserModel::is_id_circuit_device (void *id) const
|
|||
bool
|
||||
NetlistBrowserModel::is_id_circuit_device_terminal (void *id) const
|
||||
{
|
||||
if (mp_indexer->circuit_count () == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
pop (id, mp_indexer->circuit_count ());
|
||||
return (pop (id, 8) == 4 && always (pop (id, mp_indexer->device_count (circuits))) && id != 0);
|
||||
|
|
@ -884,7 +972,7 @@ NetlistBrowserModel::text (const QModelIndex &index) const
|
|||
if (index.column () == 0) {
|
||||
return tl::to_qstring (str_from_names (circuits, mp_indexer->is_single ()));
|
||||
} else if (!mp_indexer->is_single ()) {
|
||||
return tl::to_qstring (str_from_name (index.column () == 2 ? circuits.first : circuits.second));
|
||||
return tl::to_qstring (str_from_name (index.column () == 1 ? circuits.first : circuits.second));
|
||||
}
|
||||
|
||||
} else if (is_id_circuit_pin (id)) {
|
||||
|
|
@ -896,7 +984,7 @@ NetlistBrowserModel::text (const QModelIndex &index) const
|
|||
if (index.column () == 0) {
|
||||
return tl::to_qstring (str_from_expanded_names (pins, mp_indexer->is_single ()));
|
||||
} else if (!mp_indexer->is_single ()) {
|
||||
return tl::to_qstring (str_from_expanded_name (index.column () == 2 ? pins.first : pins.second));
|
||||
return tl::to_qstring (str_from_expanded_name (index.column () == 1 ? pins.first : pins.second));
|
||||
}
|
||||
|
||||
} else if (is_id_circuit_pin_net (id)) {
|
||||
|
|
@ -1468,104 +1556,6 @@ NetlistBrowserModel::flags (const QModelIndex & /*index*/) const
|
|||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
static size_t device_rows_for (const db::Circuit *circuit)
|
||||
{
|
||||
if (! circuit) {
|
||||
return 0;
|
||||
} else {
|
||||
return circuit->device_count ();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t device_rows_for (const IndexedNetlistModel::circuit_pair &circuits)
|
||||
{
|
||||
return std::max (device_rows_for (circuits.first), device_rows_for (circuits.second));
|
||||
}
|
||||
|
||||
static size_t pin_rows_for (const db::Circuit *circuit)
|
||||
{
|
||||
if (! circuit) {
|
||||
return 0;
|
||||
} else {
|
||||
return circuit->pin_count ();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t pin_rows_for (const IndexedNetlistModel::circuit_pair &circuits)
|
||||
{
|
||||
return std::max (pin_rows_for (circuits.first), pin_rows_for (circuits.second));
|
||||
}
|
||||
|
||||
static size_t net_rows_for (const db::Circuit *circuit)
|
||||
{
|
||||
if (! circuit) {
|
||||
return 0;
|
||||
} else {
|
||||
return circuit->net_count ();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t net_rows_for (const IndexedNetlistModel::circuit_pair &circuits)
|
||||
{
|
||||
return std::max (net_rows_for (circuits.first), net_rows_for (circuits.second));
|
||||
}
|
||||
|
||||
static size_t subcircuit_rows_for (const db::Circuit *circuit)
|
||||
{
|
||||
if (! circuit) {
|
||||
return 0;
|
||||
} else {
|
||||
return circuit->subcircuit_count ();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t subcircuit_rows_for (const IndexedNetlistModel::circuit_pair &circuits)
|
||||
{
|
||||
return std::max (subcircuit_rows_for (circuits.first), subcircuit_rows_for (circuits.second));
|
||||
}
|
||||
|
||||
static size_t pin_rows_for (const db::Net *net)
|
||||
{
|
||||
if (! net) {
|
||||
return 0;
|
||||
} else {
|
||||
return net->pin_count ();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t pin_rows_for (const IndexedNetlistModel::net_pair &nets)
|
||||
{
|
||||
return std::max (pin_rows_for (nets.first), pin_rows_for (nets.second));
|
||||
}
|
||||
|
||||
static size_t subcircuit_rows_for (const db::Net *net)
|
||||
{
|
||||
if (! net) {
|
||||
return 0;
|
||||
} else {
|
||||
return net->subcircuit_pin_count ();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t subcircuit_rows_for (const IndexedNetlistModel::net_pair &nets)
|
||||
{
|
||||
return std::max (subcircuit_rows_for (nets.first), subcircuit_rows_for (nets.second));
|
||||
}
|
||||
|
||||
static size_t terminal_rows_for (const db::Net *net)
|
||||
{
|
||||
if (! net) {
|
||||
return 0;
|
||||
} else {
|
||||
return net->terminal_count ();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t terminal_rows_for (const IndexedNetlistModel::net_pair &nets)
|
||||
{
|
||||
return std::max (terminal_rows_for (nets.first), terminal_rows_for (nets.second));
|
||||
}
|
||||
|
||||
static size_t rows_for (const db::Device *device)
|
||||
{
|
||||
if (! device || ! device->device_class ()) {
|
||||
|
|
@ -1607,7 +1597,7 @@ NetlistBrowserModel::hasChildren (const QModelIndex &parent) const
|
|||
{
|
||||
if (! parent.isValid ()) {
|
||||
|
||||
return mp_l2ndb->netlist () && mp_l2ndb->netlist ()->circuit_count () > 0;
|
||||
return mp_indexer.get () && mp_indexer->circuit_count () > 0;
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -1616,10 +1606,10 @@ NetlistBrowserModel::hasChildren (const QModelIndex &parent) const
|
|||
if (is_id_circuit (id)) {
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
return device_rows_for (circuits.first) > 0 || device_rows_for (circuits.second) > 0 ||
|
||||
subcircuit_rows_for (circuits.first) > 0 || subcircuit_rows_for (circuits.second) > 0 ||
|
||||
pin_rows_for (circuits.first) > 0 || pin_rows_for (circuits.second) > 0 ||
|
||||
net_rows_for (circuits.first) > 0 || net_rows_for (circuits.second) > 0;
|
||||
return mp_indexer->device_count (circuits) > 0 ||
|
||||
mp_indexer->subcircuit_count (circuits) > 0 ||
|
||||
mp_indexer->pin_count (circuits) > 0 ||
|
||||
mp_indexer->net_count (circuits) > 0;
|
||||
|
||||
} else if (is_id_circuit_pin (id)) {
|
||||
|
||||
|
|
@ -1638,9 +1628,9 @@ NetlistBrowserModel::hasChildren (const QModelIndex &parent) const
|
|||
} else if (is_id_circuit_net (id)) {
|
||||
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
return pin_rows_for (nets.first) > 0 || pin_rows_for (nets.second) > 0 ||
|
||||
terminal_rows_for (nets.first) > 0 || terminal_rows_for (nets.second) > 0 ||
|
||||
subcircuit_rows_for (nets.first) > 0 || subcircuit_rows_for (nets.second) > 0;
|
||||
return mp_indexer->net_pin_count (nets) > 0 ||
|
||||
mp_indexer->net_terminal_count (nets) > 0 ||
|
||||
mp_indexer->net_subcircuit_pin_count (nets) > 0;
|
||||
|
||||
} else if (is_id_circuit_net_subcircuit_pin (id)) {
|
||||
|
||||
|
|
@ -1691,22 +1681,22 @@ NetlistBrowserModel::index (int row, int column, const QModelIndex &parent) cons
|
|||
|
||||
int r = row;
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
int rpins = int (pin_rows_for (circuits));
|
||||
int rpins = int (mp_indexer->pin_count (circuits));
|
||||
if (r < rpins) {
|
||||
new_id = make_id_circuit_pin (circuit_index_from_id (id), size_t (r));
|
||||
} else {
|
||||
r -= rpins;
|
||||
int rnets = int (net_rows_for (circuits));
|
||||
int rnets = int (mp_indexer->net_count (circuits));
|
||||
if (r < int (rnets)) {
|
||||
new_id = make_id_circuit_net (circuit_index_from_id (id), size_t (r));
|
||||
} else {
|
||||
r -= int (rnets);
|
||||
int rsubcircuits = int (subcircuit_rows_for (circuits));
|
||||
int rsubcircuits = int (mp_indexer->subcircuit_count (circuits));
|
||||
if (r < rsubcircuits) {
|
||||
new_id = make_id_circuit_subcircuit (circuit_index_from_id (id), size_t (r));
|
||||
} else {
|
||||
r -= rsubcircuits;
|
||||
if (r < int (device_rows_for (circuits))) {
|
||||
if (r < int (mp_indexer->device_count (circuits))) {
|
||||
new_id = make_id_circuit_device (circuit_index_from_id (id), size_t (r));
|
||||
}
|
||||
}
|
||||
|
|
@ -1729,17 +1719,17 @@ NetlistBrowserModel::index (int row, int column, const QModelIndex &parent) cons
|
|||
|
||||
int r = row;
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
int rterminals = int (terminal_rows_for (nets));
|
||||
int rterminals = int (mp_indexer->net_terminal_count (nets));
|
||||
if (r < rterminals){
|
||||
new_id = make_id_circuit_net_device_terminal (circuit_index_from_id (id), circuit_net_index_from_id (id), size_t (r));
|
||||
} else {
|
||||
r -= rterminals;
|
||||
int rpins = int (pin_rows_for (nets));
|
||||
int rpins = int (mp_indexer->net_pin_count (nets));
|
||||
if (r < rpins) {
|
||||
new_id = make_id_circuit_net_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), size_t (r));
|
||||
} else {
|
||||
r -= rpins;
|
||||
if (r < int (subcircuit_rows_for (nets))) {
|
||||
if (r < int (mp_indexer->net_subcircuit_pin_count (nets))) {
|
||||
new_id = make_id_circuit_net_subcircuit_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), size_t (r));
|
||||
}
|
||||
}
|
||||
|
|
@ -1893,7 +1883,7 @@ NetlistBrowserModel::index_from_id (void *id, int column) const
|
|||
} else if (is_id_circuit_net (id)) {
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
return createIndex (int (pin_rows_for (circuits) + circuit_net_index_from_id (id)), column, id);
|
||||
return createIndex (int (mp_indexer->pin_count (circuits) + circuit_net_index_from_id (id)), column, id);
|
||||
|
||||
} else if (is_id_circuit_net_device_terminal (id)) {
|
||||
|
||||
|
|
@ -1906,12 +1896,12 @@ NetlistBrowserModel::index_from_id (void *id, int column) const
|
|||
} else if (is_id_circuit_net_pin (id)) {
|
||||
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
return createIndex (int (terminal_rows_for (nets) + circuit_net_pin_index_from_id (id)), column, id);
|
||||
return createIndex (int (mp_indexer->net_terminal_count (nets) + circuit_net_pin_index_from_id (id)), column, id);
|
||||
|
||||
} else if (is_id_circuit_net_subcircuit_pin (id)) {
|
||||
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
return createIndex (int (terminal_rows_for (nets) + pin_rows_for (nets) + circuit_net_subcircuit_pin_index_from_id (id)), column, id);
|
||||
return createIndex (int (mp_indexer->net_terminal_count (nets) + mp_indexer->net_pin_count (nets) + circuit_net_subcircuit_pin_index_from_id (id)), column, id);
|
||||
|
||||
} else if (is_id_circuit_net_subcircuit_pin_others (id)) {
|
||||
|
||||
|
|
@ -1920,7 +1910,7 @@ NetlistBrowserModel::index_from_id (void *id, int column) const
|
|||
} else if (is_id_circuit_subcircuit (id)) {
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
return createIndex (int (pin_rows_for (circuits) + net_rows_for (circuits) + circuit_subcircuit_index_from_id (id)), column, id);
|
||||
return createIndex (int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + circuit_subcircuit_index_from_id (id)), column, id);
|
||||
|
||||
} else if (is_id_circuit_subcircuit_pin (id)) {
|
||||
|
||||
|
|
@ -1929,7 +1919,7 @@ NetlistBrowserModel::index_from_id (void *id, int column) const
|
|||
} else if (is_id_circuit_device (id)) {
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
return createIndex (int (pin_rows_for (circuits) + net_rows_for (circuits) + subcircuit_rows_for (circuits) + circuit_device_index_from_id (id)), column, id);
|
||||
return createIndex (int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + mp_indexer->subcircuit_count (circuits) + circuit_device_index_from_id (id)), column, id);
|
||||
|
||||
} else if (is_id_circuit_device_terminal (id)) {
|
||||
|
||||
|
|
@ -1967,17 +1957,17 @@ NetlistBrowserModel::parent (const QModelIndex &index) const
|
|||
} else if (is_id_circuit_net_device_terminal (id) || is_id_circuit_net_pin (id) || is_id_circuit_net_subcircuit_pin (id)) {
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
return createIndex (int (pin_rows_for (circuits) + circuit_net_index_from_id (id)), column, make_id_circuit_net (circuit_index_from_id (id), circuit_net_index_from_id (id)));
|
||||
return createIndex (int (mp_indexer->pin_count (circuits) + circuit_net_index_from_id (id)), column, make_id_circuit_net (circuit_index_from_id (id), circuit_net_index_from_id (id)));
|
||||
|
||||
} else if (is_id_circuit_subcircuit_pin (id)) {
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
return createIndex (int (pin_rows_for (circuits) + net_rows_for (circuits) + circuit_subcircuit_index_from_id (id)), column, make_id_circuit_subcircuit (circuit_index_from_id (id), circuit_subcircuit_index_from_id (id)));
|
||||
return createIndex (int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + circuit_subcircuit_index_from_id (id)), column, make_id_circuit_subcircuit (circuit_index_from_id (id), circuit_subcircuit_index_from_id (id)));
|
||||
|
||||
} else if (is_id_circuit_device_terminal (id)) {
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
return createIndex (int (pin_rows_for (circuits) + net_rows_for (circuits) + subcircuit_rows_for (circuits) + circuit_device_index_from_id (id)), column, make_id_circuit_device (circuit_index_from_id (id), circuit_device_index_from_id (id)));
|
||||
return createIndex (int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + mp_indexer->subcircuit_count (circuits) + circuit_device_index_from_id (id)), column, make_id_circuit_device (circuit_index_from_id (id), circuit_device_index_from_id (id)));
|
||||
|
||||
} else if (is_id_circuit_net_device_terminal_others (id)) {
|
||||
|
||||
|
|
@ -1986,7 +1976,7 @@ NetlistBrowserModel::parent (const QModelIndex &index) const
|
|||
} else if (is_id_circuit_net_subcircuit_pin_others (id)) {
|
||||
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
return createIndex (size_t (terminal_rows_for (nets) + pin_rows_for (nets) + circuit_net_subcircuit_pin_index_from_id (id)), column, make_id_circuit_net_subcircuit_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), circuit_net_subcircuit_pin_index_from_id (id)));
|
||||
return createIndex (size_t (mp_indexer->net_terminal_count (nets) + mp_indexer->net_pin_count (nets) + circuit_net_subcircuit_pin_index_from_id (id)), column, make_id_circuit_net_subcircuit_pin (circuit_index_from_id (id), circuit_net_index_from_id (id), circuit_net_subcircuit_pin_index_from_id (id)));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2000,7 +1990,7 @@ NetlistBrowserModel::rowCount (const QModelIndex &parent) const
|
|||
{
|
||||
if (! parent.isValid ()) {
|
||||
|
||||
return int (mp_l2ndb->netlist ()->circuit_count ());
|
||||
return int (mp_indexer.get () ? mp_indexer->circuit_count () : 0);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -2009,7 +1999,7 @@ NetlistBrowserModel::rowCount (const QModelIndex &parent) const
|
|||
if (is_id_circuit (id)) {
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = circuits_from_id (id);
|
||||
return int (pin_rows_for (circuits) + net_rows_for (circuits) + subcircuit_rows_for (circuits) + device_rows_for (circuits));
|
||||
return int (mp_indexer->pin_count (circuits) + mp_indexer->net_count (circuits) + mp_indexer->subcircuit_count (circuits) + mp_indexer->device_count (circuits));
|
||||
|
||||
} else if (is_id_circuit_pin (id)) {
|
||||
|
||||
|
|
@ -2038,7 +2028,7 @@ NetlistBrowserModel::rowCount (const QModelIndex &parent) const
|
|||
} else if (is_id_circuit_net (id)) {
|
||||
|
||||
IndexedNetlistModel::net_pair nets = nets_from_id (id);
|
||||
return int (terminal_rows_for (nets) + pin_rows_for (nets) + subcircuit_rows_for (nets));
|
||||
return int (mp_indexer->net_terminal_count (nets) + mp_indexer->net_pin_count (nets) + mp_indexer->net_subcircuit_pin_count (nets));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "laybasicCommon.h"
|
||||
|
||||
#include "dbLayoutToNetlist.h"
|
||||
#include "dbLayoutVsSchematic.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QColor>
|
||||
|
|
@ -110,6 +111,7 @@ Q_OBJECT
|
|||
|
||||
public:
|
||||
NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer);
|
||||
NetlistBrowserModel (QWidget *parent, db::LayoutVsSchematic *lvsdb, NetColorizer *colorizer);
|
||||
~NetlistBrowserModel ();
|
||||
|
||||
virtual int columnCount (const QModelIndex &parent) const;
|
||||
|
|
@ -202,6 +204,7 @@ private:
|
|||
QIcon icon_for_connection (const std::pair<const db::Net *, const db::Net *> &net) const;
|
||||
|
||||
db::LayoutToNetlist *mp_l2ndb;
|
||||
db::LayoutVsSchematic *mp_lvsdb;
|
||||
NetColorizer *mp_colorizer;
|
||||
std::auto_ptr<IndexedNetlistModel> mp_indexer;
|
||||
mutable std::map<lay::color_t, QIcon> m_net_icon_per_color;
|
||||
|
|
|
|||
|
|
@ -617,28 +617,34 @@ NetlistBrowserPage::show_all (bool f)
|
|||
}
|
||||
|
||||
void
|
||||
NetlistBrowserPage::set_l2ndb (db::LayoutToNetlist *database)
|
||||
NetlistBrowserPage::set_db (db::LayoutToNetlist *l2ndb)
|
||||
{
|
||||
if (mp_info_dialog) {
|
||||
delete mp_info_dialog;
|
||||
mp_info_dialog = 0;
|
||||
}
|
||||
|
||||
mp_database.reset (database);
|
||||
db::LayoutVsSchematic *lvsdb = dynamic_cast<db::LayoutVsSchematic *> (l2ndb);
|
||||
mp_database.reset (l2ndb);
|
||||
|
||||
clear_markers ();
|
||||
highlight (std::vector<const db::Net *> (), std::vector<const db::Device *> (), std::vector<const db::SubCircuit *> ());
|
||||
|
||||
if (! database) {
|
||||
if (! mp_database.get ()) {
|
||||
delete directory_tree->model ();
|
||||
directory_tree->setModel (0);
|
||||
return;
|
||||
}
|
||||
|
||||
m_cell_context_cache = db::ContextCache (database->internal_layout ());
|
||||
m_cell_context_cache = db::ContextCache (mp_database->internal_layout ());
|
||||
|
||||
// NOTE: with the tree as the parent, the tree will take over ownership of the model
|
||||
NetlistBrowserModel *new_model = new NetlistBrowserModel (directory_tree, database, &m_colorizer);
|
||||
NetlistBrowserModel *new_model = 0;
|
||||
if (lvsdb) {
|
||||
new_model = new NetlistBrowserModel (directory_tree, lvsdb, &m_colorizer);
|
||||
} else {
|
||||
new_model = new NetlistBrowserModel (directory_tree, l2ndb, &m_colorizer);
|
||||
}
|
||||
|
||||
delete directory_tree->model ();
|
||||
directory_tree->setModel (new_model);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "layNetlistBrowser.h"
|
||||
#include "laybasicCommon.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
#include "dbLayoutVsSchematic.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
|
||||
#include "tlObject.h"
|
||||
|
|
@ -82,11 +83,28 @@ public:
|
|||
void set_view (lay::LayoutView *view, unsigned int cv_index);
|
||||
|
||||
/**
|
||||
* @brief Attach the page to a L2N DB
|
||||
*
|
||||
* To detach the page from any L2N DB, pass 0 for the pointer.
|
||||
* @brief Attaches the page to a L2N DB
|
||||
*/
|
||||
void set_l2ndb (db::LayoutToNetlist *database);
|
||||
void set_l2ndb (db::LayoutToNetlist *database)
|
||||
{
|
||||
set_db (database);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attaches the page to a LVS DB
|
||||
*/
|
||||
void set_lvsdb (db::LayoutVsSchematic *database)
|
||||
{
|
||||
set_db (database);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detaches the page from any DB
|
||||
*/
|
||||
void reset_db ()
|
||||
{
|
||||
set_db (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects a net or clears the selection if net == 0
|
||||
|
|
@ -188,6 +206,7 @@ private:
|
|||
tl::DeferredMethod<NetlistBrowserPage> dm_update_highlights;
|
||||
db::ContextCache m_cell_context_cache;
|
||||
|
||||
void set_db (db::LayoutToNetlist *l2ndb);
|
||||
void add_to_history (void *id, bool fwd);
|
||||
void navigate_to (void *id, bool forward = true);
|
||||
void adjust_view ();
|
||||
|
|
|
|||
|
|
@ -39,37 +39,44 @@ size_t NetlistCrossReferenceModel::circuit_count () const
|
|||
|
||||
size_t NetlistCrossReferenceModel::net_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return std::max (circuits.first ? circuits.first->net_count () : 0, circuits.second ? circuits.second->net_count () : 0);
|
||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
return data ? data->nets.size () : 0;
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::net_terminal_count (const net_pair &nets) const
|
||||
{
|
||||
return std::max (nets.first ? nets.first->terminal_count () : 0, nets.second ? nets.second->terminal_count () : 0);
|
||||
const db::NetlistCrossReference::PerNetData *data = mp_cross_ref->per_net_data_for (nets);
|
||||
return data ? data->terminals.size () : 0;
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::net_subcircuit_pin_count (const net_pair &nets) const
|
||||
{
|
||||
return std::max (nets.first ? nets.first->subcircuit_pin_count () : 0, nets.second ? nets.second->subcircuit_pin_count () : 0);
|
||||
const db::NetlistCrossReference::PerNetData *data = mp_cross_ref->per_net_data_for (nets);
|
||||
return data ? data->subcircuit_pins.size () : 0;
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::net_pin_count (const net_pair &nets) const
|
||||
{
|
||||
return std::max (nets.first ? nets.first->pin_count () : 0, nets.second ? nets.second->pin_count () : 0);
|
||||
const db::NetlistCrossReference::PerNetData *data = mp_cross_ref->per_net_data_for (nets);
|
||||
return data ? data->pins.size () : 0;
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::device_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return std::max (circuits.first ? circuits.first->device_count () : 0, circuits.second ? circuits.second->device_count () : 0);
|
||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
return data ? data->devices.size () : 0;
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::pin_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return std::max (circuits.first ? circuits.first->pin_count () : 0, circuits.second ? circuits.second->pin_count () : 0);
|
||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
return data ? data->pins.size () : 0;
|
||||
}
|
||||
|
||||
size_t NetlistCrossReferenceModel::subcircuit_count (const circuit_pair &circuits) const
|
||||
{
|
||||
return std::max (circuits.first ? circuits.first->subcircuit_count () : 0, circuits.second ? circuits.second->subcircuit_count () : 0);
|
||||
const db::NetlistCrossReference::PerCircuitData *data = mp_cross_ref->per_circuit_data_for (circuits);
|
||||
return data ? data->subcircuits.size () : 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
|||
|
|
@ -217,3 +217,34 @@ TEST (1)
|
|||
EXPECT_EQ (model->rowCount (inv2Device1GateIndex), 0);
|
||||
}
|
||||
|
||||
TEST (2)
|
||||
{
|
||||
db::LayoutVsSchematic lvs;
|
||||
lvs.load (tl::testsrc () + "/testdata/lay/lvsdb_browser.lvsdb");
|
||||
|
||||
lay::NetColorizer colorizer;
|
||||
std::auto_ptr<lay::NetlistBrowserModel> model (new lay::NetlistBrowserModel (0, &lvs, &colorizer));
|
||||
|
||||
EXPECT_EQ (model->hasChildren (QModelIndex ()), true);
|
||||
// two circuits
|
||||
EXPECT_EQ (model->rowCount (QModelIndex ()), 4);
|
||||
EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, QModelIndex ()), Qt::UserRole).toString ()), "INV2PAIRX");
|
||||
EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, QModelIndex ()), Qt::DisplayRole).toString ()), "-/INV2PAIRX");
|
||||
EXPECT_EQ (tl::to_string (model->data (model->index (0, 1, QModelIndex ()), Qt::DisplayRole).toString ()), "");
|
||||
EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, QModelIndex ()), Qt::DisplayRole).toString ()), "INV2PAIRX");
|
||||
EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, QModelIndex ()), Qt::DisplayRole).toString ()), "INV2/INV2");
|
||||
EXPECT_EQ (tl::to_string (model->data (model->index (1, 1, QModelIndex ()), Qt::DisplayRole).toString ()), "INV2");
|
||||
EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, QModelIndex ()), Qt::DisplayRole).toString ()), "INV2");
|
||||
EXPECT_EQ (model->parent (model->index (0, 0, QModelIndex ())).isValid (), false);
|
||||
EXPECT_EQ (model->parent (model->index (1, 0, QModelIndex ())).isValid (), false);
|
||||
|
||||
EXPECT_EQ (model->hasChildren (model->index (0, 0, QModelIndex ())), false);
|
||||
EXPECT_EQ (model->rowCount (model->index (0, 0, QModelIndex ())), 0);
|
||||
|
||||
QModelIndex inv2Index = model->index (1, 0, QModelIndex ());
|
||||
|
||||
EXPECT_EQ (model->hasChildren (inv2Index), true);
|
||||
EXPECT_EQ (model->rowCount (inv2Index), 14);
|
||||
|
||||
// ...
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue