WIP: refactoring of LVS/L2N DB readers

This commit is contained in:
Matthias Koefferlein 2019-05-18 22:24:58 +02:00
parent c09db62cf6
commit bee662eea8
6 changed files with 176 additions and 330 deletions

View File

@ -111,6 +111,7 @@ LayoutToNetlistStandardReader::read_double ()
bool
LayoutToNetlistStandardReader::at_end ()
{
skip ();
return (m_ex.at_end () && m_stream.at_end ());
}
@ -129,7 +130,7 @@ LayoutToNetlistStandardReader::skip ()
void LayoutToNetlistStandardReader::read (db::LayoutToNetlist *l2n)
{
try {
do_read (l2n);
do_read (0, l2n);
} catch (tl::Exception &ex) {
throw tl::Exception (tl::sprintf (tl::to_string (tr ("%s in line: %d of %s")), ex.msg (), m_stream.line_number (), m_path));
}
@ -144,20 +145,28 @@ static db::Region &layer_by_name (db::LayoutToNetlist *l2n, const std::string &n
return *l;
}
void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nested)
void LayoutToNetlistStandardReader::do_read (db::Netlist *netlist, db::LayoutToNetlist *l2n, bool nested, std::map<const db::Circuit *, std::map<unsigned int, Net *> > *id2net_per_circuit)
{
int version = 0;
std::string description;
tl_assert (l2n->internal_layout ());
l2n->internal_layout ()->dbu (1.0); // mainly for testing
if (l2n) {
if (l2n->internal_layout ()->cells () == 0) {
l2n->internal_layout ()->add_cell ("TOP");
tl_assert (netlist == 0);
tl_assert (l2n->internal_layout ());
l2n->internal_layout ()->dbu (1.0); // mainly for testing
if (l2n->internal_layout ()->cells () == 0) {
l2n->internal_layout ()->add_cell ("TOP");
}
tl_assert (l2n->internal_top_cell () != 0);
netlist = l2n->make_netlist ();
} else {
tl_assert (netlist != 0);
}
tl_assert (l2n->internal_top_cell () != 0);
l2n->make_netlist ();
while (! at_end ()) {
@ -173,14 +182,14 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
read_word_or_quoted (description);
br.done ();
} else if (test (skeys::unit_key) || test (lkeys::unit_key)) {
} else if (l2n && (test (skeys::unit_key) || test (lkeys::unit_key))) {
Brace br (this);
double dbu = read_double ();
l2n->internal_layout ()->dbu (dbu);
br.done ();
} else if (test (skeys::top_key) || test (lkeys::top_key)) {
} else if (l2n && (test (skeys::top_key) || test (lkeys::top_key))) {
Brace br (this);
std::string top;
@ -188,7 +197,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
l2n->internal_layout ()->rename_cell (l2n->internal_top_cell ()->cell_index (), top.c_str ());
br.done ();
} else if (test (skeys::layer_key) || test (lkeys::layer_key)) {
} else if (l2n && (test (skeys::layer_key) || test (lkeys::layer_key))) {
Brace br (this);
std::string layer, lspec;
@ -216,7 +225,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
read_word_or_quoted (templ_name);
br.done ();
if (l2n->netlist ()->device_class_by_name (class_name) != 0) {
if (netlist->device_class_by_name (class_name) != 0) {
throw tl::Exception (tl::to_string (tr ("Device class must be defined before being used in device")));
}
@ -227,9 +236,9 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
db::DeviceClass *dc = dct->create ();
dc->set_name (class_name);
l2n->netlist ()->add_device_class (dc);
netlist->add_device_class (dc);
} else if (test (skeys::connect_key) || test (lkeys::connect_key)) {
} else if (l2n && (test (skeys::connect_key) || test (lkeys::connect_key))) {
Brace br (this);
std::string l1;
@ -241,7 +250,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
}
br.done ();
} else if (test (skeys::global_key) || test (lkeys::global_key)) {
} else if (l2n && (test (skeys::global_key) || test (lkeys::global_key))) {
Brace br (this);
std::string l1;
@ -261,26 +270,36 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
db::Circuit *circuit = new db::Circuit ();
circuit->set_name (name);
l2n->netlist ()->add_circuit (circuit);
netlist->add_circuit (circuit);
db::Layout *ly = l2n->internal_layout ();
std::pair<bool, db::cell_index_type> ci_old = ly->cell_by_name (name.c_str ());
db::cell_index_type ci = ci_old.first ? ci_old.second : ly->add_cell (name.c_str ());
circuit->set_cell_index (ci);
db::cell_index_type device_cell_index = 0;
if (l2n) {
db::Layout *ly = l2n->internal_layout ();
std::pair<bool, db::cell_index_type> ci_old = ly->cell_by_name (name.c_str ());
device_cell_index = ci_old.first ? ci_old.second : ly->add_cell (name.c_str ());
circuit->set_cell_index (device_cell_index);
}
std::map<db::CellInstArray, std::list<Connections> > connections;
std::map<unsigned int, Net *> id2net;
std::map<unsigned int, Net *> id2net_local;
std::map<unsigned int, Net *> *id2net = &id2net_local;
if (id2net_per_circuit) {
id2net = &(*id2net_per_circuit)[circuit];
}
while (br) {
if (test (skeys::net_key) || test (lkeys::net_key)) {
read_net (l2n, circuit, id2net);
read_net (netlist, l2n, circuit, *id2net);
} else if (test (skeys::pin_key) || test (lkeys::pin_key)) {
read_pin (l2n, circuit, id2net);
read_pin (netlist, l2n, circuit, *id2net);
} else if (test (skeys::device_key) || test (lkeys::device_key)) {
read_device (l2n, circuit, id2net, connections);
read_device (netlist, l2n, circuit, *id2net, connections);
} else if (test (skeys::circuit_key) || test (lkeys::circuit_key)) {
read_subcircuit (l2n, circuit, id2net, connections);
read_subcircuit (netlist, l2n, circuit, *id2net, connections);
} else {
throw tl::Exception (tl::to_string (tr ("Invalid keyword inside circuit definition (net, pin, device or circuit expected)")));
}
@ -288,17 +307,22 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
}
br.done ();
db::Cell &ccell = ly->cell (ci);
if (l2n) {
// connections needs to be made after the instances (because in a readonly Instances container
// the Instance pointers will invalidate when new instances are added)
for (db::Cell::const_iterator i = ccell.begin (); ! i.at_end (); ++i) {
std::map<db::CellInstArray, std::list<Connections> >::const_iterator c = connections.find (i->cell_inst ());
if (c != connections.end ()) {
for (std::list<Connections>::const_iterator j = c->second.begin (); j != c->second.end (); ++j) {
l2n->net_clusters ().clusters_per_cell (ci).add_connection (j->from_cluster, db::ClusterInstance (j->to_cluster, i->cell_index (), i->complex_trans (), i->prop_id ()));
db::Layout *ly = l2n->internal_layout ();
db::Cell &ccell = ly->cell (device_cell_index);
// connections needs to be made after the instances (because in a readonly Instances container
// the Instance pointers will invalidate when new instances are added)
for (db::Cell::const_iterator i = ccell.begin (); ! i.at_end (); ++i) {
std::map<db::CellInstArray, std::list<Connections> >::const_iterator c = connections.find (i->cell_inst ());
if (c != connections.end ()) {
for (std::list<Connections>::const_iterator j = c->second.begin (); j != c->second.end (); ++j) {
l2n->net_clusters ().clusters_per_cell (device_cell_index).add_connection (j->from_cluster, db::ClusterInstance (j->to_cluster, i->cell_index (), i->complex_trans (), i->prop_id ()));
}
}
}
}
} else if (test (skeys::device_key) || test (lkeys::device_key)) {
@ -309,22 +333,24 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
db::DeviceAbstract *dm = new db::DeviceAbstract ();
dm->set_name (name);
l2n->netlist ()->add_device_abstract (dm);
netlist->add_device_abstract (dm);
db::cell_index_type ci = l2n->internal_layout ()->add_cell (name.c_str ());
dm->set_cell_index (ci);
if (l2n) {
db::cell_index_type ci = l2n->internal_layout ()->add_cell (name.c_str ());
dm->set_cell_index (ci);
}
std::string cls;
read_word_or_quoted (cls);
db::DeviceClass *dc = l2n->netlist ()->device_class_by_name (cls);
db::DeviceClass *dc = netlist->device_class_by_name (cls);
// use a generic device class unless the right one is registered already.
bool gen_dc = (dc == 0);
if (gen_dc) {
dc = new db::DeviceClass ();
dc->set_name (cls);
l2n->netlist ()->add_device_class (dc);
netlist->add_device_class (dc);
}
dm->set_device_class (dc);
@ -349,7 +375,9 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n, bool nest
}
l2n->set_netlist_extracted ();
if (l2n) {
l2n->set_netlist_extracted ();
}
}
db::Point
@ -429,7 +457,7 @@ LayoutToNetlistStandardReader::read_geometries (Brace &br, db::LayoutToNetlist *
}
void
LayoutToNetlistStandardReader::read_net (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net)
LayoutToNetlistStandardReader::read_net (db::Netlist * /*netlist*/, db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net)
{
Brace br (this);
@ -448,18 +476,22 @@ LayoutToNetlistStandardReader::read_net (db::LayoutToNetlist *l2n, db::Circuit *
id2net.insert (std::make_pair (id, net));
db::connected_clusters<db::PolygonRef> &cc = l2n->net_clusters ().clusters_per_cell (circuit->cell_index ());
db::local_cluster<db::PolygonRef> &lc = *cc.insert ();
net->set_cluster_id (lc.id ());
if (l2n) {
db::Cell &cell = l2n->internal_layout ()->cell (circuit->cell_index ());
read_geometries (br, l2n, lc, cell);
db::connected_clusters<db::PolygonRef> &cc = l2n->net_clusters ().clusters_per_cell (circuit->cell_index ());
db::local_cluster<db::PolygonRef> &lc = *cc.insert ();
net->set_cluster_id (lc.id ());
db::Cell &cell = l2n->internal_layout ()->cell (circuit->cell_index ());
read_geometries (br, l2n, lc, cell);
}
br.done ();
}
void
LayoutToNetlistStandardReader::read_pin (db::LayoutToNetlist * /*l2n*/, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net)
LayoutToNetlistStandardReader::read_pin (db::Netlist * /*netlist*/, db::LayoutToNetlist * /*l2n*/, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net)
{
Brace br (this);
std::string name;
@ -503,7 +535,7 @@ LayoutToNetlistStandardReader::device_model_by_name (db::Netlist *netlist, const
}
void
LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net, std::map<db::CellInstArray, std::list<Connections> > &connections)
LayoutToNetlistStandardReader::read_device (db::Netlist *netlist, db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net, std::map<db::CellInstArray, std::list<Connections> > &connections)
{
Brace br (this);
@ -513,7 +545,7 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
std::string dmname;
read_word_or_quoted (dmname);
db::DeviceAbstract *dm = device_model_by_name (l2n->netlist (), dmname);
db::DeviceAbstract *dm = device_model_by_name (netlist, dmname);
db::Device *device = new db::Device ();
device->set_device_class (const_cast<db::DeviceClass *> (dm->device_class ()));
@ -549,7 +581,7 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
br2.done ();
db::DeviceAbstract *da = device_model_by_name (l2n->netlist (), n);
db::DeviceAbstract *da = device_model_by_name (netlist, n);
device->other_abstracts ().push_back (db::DeviceAbstractRef (da, db::DVector (dbu * dx, dbu * dy)));
@ -628,53 +660,57 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
br.done ();
db::Cell &ccell = l2n->internal_layout ()->cell (circuit->cell_index ());
if (l2n) {
// make device cell instances
std::vector<db::CellInstArray> insts;
db::Cell &ccell = l2n->internal_layout ()->cell (circuit->cell_index ());
db::CellInstArray inst (db::CellInst (dm->cell_index ()), db::Trans (db::Vector (x, y)));
ccell.insert (inst);
insts.push_back (inst);
// make device cell instances
std::vector<db::CellInstArray> insts;
const std::vector<db::DeviceAbstractRef> &other_devices = device->other_abstracts ();
for (std::vector<db::DeviceAbstractRef>::const_iterator i = other_devices.begin (); i != other_devices.end (); ++i) {
db::CellInstArray inst (db::CellInst (dm->cell_index ()), db::Trans (db::Vector (x, y)));
ccell.insert (inst);
insts.push_back (inst);
db::CellInstArray other_inst (db::CellInst (i->device_abstract->cell_index ()), db::Trans (db::Vector (x, y) + dbu_inv * i->offset));
ccell.insert (other_inst);
insts.push_back (other_inst);
const std::vector<db::DeviceAbstractRef> &other_devices = device->other_abstracts ();
for (std::vector<db::DeviceAbstractRef>::const_iterator i = other_devices.begin (); i != other_devices.end (); ++i) {
}
db::CellInstArray other_inst (db::CellInst (i->device_abstract->cell_index ()), db::Trans (db::Vector (x, y) + dbu_inv * i->offset));
ccell.insert (other_inst);
insts.push_back (other_inst);
// register cluster collections to be made later
for (size_t tid = 0; tid < max_tid; ++tid) {
const db::Net *net = device->net_for_terminal (tid);
if (! net) {
continue;
}
if (! device->reconnected_terminals ().empty ()) {
// register cluster collections to be made later
const std::vector<db::DeviceReconnectedTerminal> *tr = device->reconnected_terminals_for (tid);
if (tr) {
for (std::vector<db::DeviceReconnectedTerminal>::const_iterator i = tr->begin (); i != tr->end (); ++i) {
const db::DeviceAbstract *da = dm;
if (i->device_index > 0) {
da = device->other_abstracts () [i->device_index - 1].device_abstract;
}
Connections ref (net->cluster_id (), da->cluster_id_for_terminal (i->other_terminal_id));
connections [insts [i->device_index]].push_back (ref);
}
for (size_t tid = 0; tid < max_tid; ++tid) {
const db::Net *net = device->net_for_terminal (tid);
if (! net) {
continue;
}
} else {
if (! device->reconnected_terminals ().empty ()) {
Connections ref (net->cluster_id (), dm->cluster_id_for_terminal (tid));
connections [insts [0]].push_back (ref);
const std::vector<db::DeviceReconnectedTerminal> *tr = device->reconnected_terminals_for (tid);
if (tr) {
for (std::vector<db::DeviceReconnectedTerminal>::const_iterator i = tr->begin (); i != tr->end (); ++i) {
const db::DeviceAbstract *da = dm;
if (i->device_index > 0) {
da = device->other_abstracts () [i->device_index - 1].device_abstract;
}
Connections ref (net->cluster_id (), da->cluster_id_for_terminal (i->other_terminal_id));
connections [insts [i->device_index]].push_back (ref);
}
}
} else {
Connections ref (net->cluster_id (), dm->cluster_id_for_terminal (tid));
connections [insts [0]].push_back (ref);
}
}
@ -682,7 +718,7 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
}
void
LayoutToNetlistStandardReader::read_subcircuit (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net, std::map<db::CellInstArray, std::list<Connections> > &connections)
LayoutToNetlistStandardReader::read_subcircuit (db::Netlist *netlist, db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net, std::map<db::CellInstArray, std::list<Connections> > &connections)
{
Brace br (this);
@ -694,7 +730,7 @@ LayoutToNetlistStandardReader::read_subcircuit (db::LayoutToNetlist *l2n, db::Ci
std::string xname;
read_word_or_quoted (xname);
db::Circuit *circuit_ref = l2n->netlist ()->circuit_by_name (xname);
db::Circuit *circuit_ref = netlist->circuit_by_name (xname);
if (! circuit_ref) {
throw tl::Exception (tl::to_string (tr ("Not a valid device circuit name: ")) + xname);
}
@ -783,14 +819,18 @@ LayoutToNetlistStandardReader::read_subcircuit (db::LayoutToNetlist *l2n, db::Ci
br.done ();
double dbu = l2n->internal_layout ()->dbu ();
subcircuit->set_trans (db::DCplxTrans (mag, angle, mirror, db::DVector (dbu * x, dbu * y)));
if (l2n) {
db::CellInstArray inst (db::CellInst (circuit_ref->cell_index ()), db::ICplxTrans (mag, angle, mirror, db::Vector (x, y)));
db::Cell &ccell = l2n->internal_layout ()->cell (circuit->cell_index ());
ccell.insert (inst);
double dbu = l2n->internal_layout ()->dbu ();
subcircuit->set_trans (db::DCplxTrans (mag, angle, mirror, db::DVector (dbu * x, dbu * y)));
connections [inst] = refs;
db::CellInstArray inst (db::CellInst (circuit_ref->cell_index ()), db::ICplxTrans (mag, angle, mirror, db::Vector (x, y)));
db::Cell &ccell = l2n->internal_layout ()->cell (circuit->cell_index ());
ccell.insert (inst);
connections [inst] = refs;
}
}
void
@ -819,12 +859,16 @@ LayoutToNetlistStandardReader::read_abstract_terminal (db::LayoutToNetlist *l2n,
tid = dc->add_terminal_definition (new_td).id ();
}
db::connected_clusters<db::PolygonRef> &cc = l2n->net_clusters ().clusters_per_cell (dm->cell_index ());
db::local_cluster<db::PolygonRef> &lc = *cc.insert ();
dm->set_cluster_id_for_terminal (tid, lc.id ());
if (l2n) {
db::Cell &cell = l2n->internal_layout ()->cell (dm->cell_index ());
read_geometries (br, l2n, lc, cell);
db::connected_clusters<db::PolygonRef> &cc = l2n->net_clusters ().clusters_per_cell (dm->cell_index ());
db::local_cluster<db::PolygonRef> &lc = *cc.insert ();
dm->set_cluster_id_for_terminal (tid, lc.id ());
db::Cell &cell = l2n->internal_layout ()->cell (dm->cell_index ());
read_geometries (br, l2n, lc, cell);
}
br.done ();
}

View File

@ -86,7 +86,7 @@ protected:
friend class l2n_std_reader::Brace;
typedef l2n_std_reader::Brace Brace;
void do_read (db::LayoutToNetlist *l2n, bool nested = false);
void do_read (Netlist *netlist, db::LayoutToNetlist *l2n, bool nested = false, std::map<const db::Circuit *, std::map<unsigned int, Net *> > *id2net_per_circuit = 0);
static size_t terminal_id (const db::DeviceClass *device_class, const std::string &tname);
static db::DeviceAbstract *device_model_by_name (db::Netlist *netlist, const std::string &dmname);
tl::TextInputStream &stream ();
@ -110,10 +110,10 @@ protected:
bool at_end ();
void skip ();
void read_net (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, db::Net *> &id2net);
void read_pin (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, db::Net *> &id2net);
void read_device (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, db::Net *> &id2net, std::map<db::CellInstArray, std::list<Connections> > &connections);
void read_subcircuit (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, db::Net *> &id2net, std::map<db::CellInstArray, std::list<Connections> > &connections);
void read_net (Netlist *netlist, db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, db::Net *> &id2net);
void read_pin (Netlist *netlist, db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, db::Net *> &id2net);
void read_device (Netlist *netlist, db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, db::Net *> &id2net, std::map<db::CellInstArray, std::list<Connections> > &connections);
void read_subcircuit (Netlist *netlist, db::LayoutToNetlist *l2n, db::Circuit *circuit, std::map<unsigned int, db::Net *> &id2net, std::map<db::CellInstArray, std::list<Connections> > &connections);
void read_abstract_terminal (db::LayoutToNetlist *l2n, db::DeviceAbstract *dm, db::DeviceClass *dc);
std::pair<unsigned int, db::PolygonRef> read_geometry (db::LayoutToNetlist *l2n);
void read_geometries (Brace &br, db::LayoutToNetlist *l2n, db::local_cluster<db::PolygonRef> &lc, db::Cell &cell);

View File

@ -53,7 +53,7 @@ LayoutVsSchematic::LayoutVsSchematic ()
// .. nothing yet ..
}
~LayoutVsSchematic ()
LayoutVsSchematic::~LayoutVsSchematic ()
{
// .. nothing yet ..
}
@ -100,7 +100,7 @@ void db::LayoutVsSchematic::load (const std::string &path)
db::LayoutVsSchematicStandardReader reader (stream);
set_filename (path);
set_name (stream.filename ());
reader.read (this);
reader.read_lvs (this);
}
}

View File

@ -48,6 +48,8 @@ void LayoutVsSchematicStandardReader::do_read (db::LayoutVsSchematic *lvs)
{
int version = 0;
std::string description;
m_id2net_per_circuit_a.clear ();
m_id2net_per_circuit_b.clear ();
tl_assert (lvs->internal_layout ());
lvs->internal_layout ()->dbu (1.0); // mainly for testing
@ -76,14 +78,14 @@ void LayoutVsSchematicStandardReader::do_read (db::LayoutVsSchematic *lvs)
} else if (test (skeys::layout_key) || test (lkeys::layout_key)) {
Brace br (this);
LayoutToNetlistStandardReader::do_read (lvs, true /*nested*/);
LayoutToNetlistStandardReader::do_read (0, lvs, true /*nested*/, &m_id2net_per_circuit_a);
br.done ();
} else if (test (skeys::reference_key) || test (lkeys::reference_key)) {
Brace br (this);
std::auto_ptr<db::Netlist> netlist (new db::Netlist ());
read_netlist (netlist.get ());
LayoutToNetlistStandardReader::do_read (netlist.get (), 0, true /*nested*/, &m_id2net_per_circuit_b);
lvs->set_reference_netlist (netlist.release ());
br.done ();
@ -105,216 +107,6 @@ void LayoutVsSchematicStandardReader::do_read (db::LayoutVsSchematic *lvs)
}
}
void LayoutVsSchematicStandardReader::read_netlist (db::Netlist *netlist)
{
Brace br (this);
while (br) {
if (test (skeys::circuit_key) || test (lkeys::circuit_key)) {
Brace br (this);
std::string name;
read_word_or_quoted (name);
db::Circuit *circuit = new db::Circuit ();
circuit->set_name (name);
netlist->add_circuit (circuit);
std::map<unsigned int, Net *> id2net;
while (br) {
if (test (skeys::net_key) || test (lkeys::net_key)) {
read_net (netlist, circuit, id2net);
} else if (test (skeys::pin_key) || test (lkeys::pin_key)) {
read_pin (netlist, circuit, id2net);
} else if (test (skeys::device_key) || test (lkeys::device_key)) {
read_device (netlist, circuit, id2net);
} else if (test (skeys::circuit_key) || test (lkeys::circuit_key)) {
read_subcircuit (netlist, circuit, id2net);
} else {
throw tl::Exception (tl::to_string (tr ("Invalid keyword inside circuit definition (net, pin, device or circuit expected)")));
}
}
br.done ();
}
}
br.done ();
}
void
LayoutVsSchematicStandardReader::read_net (db::Netlist * /*netlist*/, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net)
{
Brace br (this);
unsigned int id = (unsigned int) read_int ();
std::string name;
if (test (skeys::name_key) || test (lkeys::name_key)) {
Brace br_name (this);
read_word_or_quoted (name);
br_name.done ();
}
db::Net *net = new db::Net ();
net->set_name (name);
circuit->add_net (net);
id2net.insert (std::make_pair (id, net));
br.done ();
}
void
LayoutVsSchematicStandardReader::read_pin (db::Netlist * /*netlist*/, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net)
{
Brace br (this);
std::string name;
read_word_or_quoted (name);
unsigned int netid = (unsigned int) read_int ();
br.done ();
const db::Pin &pin = circuit->add_pin (name);
db::Net *net = id2net [netid];
if (!net) {
throw tl::Exception (tl::to_string (tr ("Not a valid net ID: ")) + tl::to_string (netid));
}
circuit->connect_pin (pin.id (), net);
}
void
LayoutVsSchematicStandardReader::read_device (db::Netlist *netlist, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net)
{
Brace br (this);
std::string name;
read_word_or_quoted (name);
std::string dmname;
read_word_or_quoted (dmname);
db::DeviceAbstract *dm = device_model_by_name (netlist, dmname);
db::Device *device = new db::Device ();
device->set_device_class (const_cast<db::DeviceClass *> (dm->device_class ()));
device->set_device_abstract (dm);
device->set_name (name);
circuit->add_device (device);
size_t max_tid = 0;
while (br) {
if (test (skeys::terminal_key) || test (lkeys::terminal_key)) {
Brace br2 (this);
std::string tname;
read_word_or_quoted (tname);
unsigned int netid = (unsigned int) read_int ();
br2.done ();
size_t tid = terminal_id (dm->device_class (), tname);
max_tid = std::max (max_tid, tid + 1);
db::Net *net = id2net [netid];
if (!net) {
throw tl::Exception (tl::to_string (tr ("Not a valid net ID: ")) + tl::to_string (netid));
}
device->connect_terminal (tid, net);
} else if (test (skeys::param_key) || test (lkeys::param_key)) {
Brace br2 (this);
std::string pname;
read_word_or_quoted (pname);
double value = read_double ();
br2.done ();
size_t pid = std::numeric_limits<size_t>::max ();
const std::vector<db::DeviceParameterDefinition> &pd = dm->device_class ()->parameter_definitions ();
for (std::vector<db::DeviceParameterDefinition>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
if (p->name () == pname) {
pid = p->id ();
break;
}
}
// if no parameter with this name exists, create one
if (pid == std::numeric_limits<size_t>::max ()) {
// TODO: this should only happen for generic devices
db::DeviceClass *dc = const_cast<db::DeviceClass *> (dm->device_class ());
pid = dc->add_parameter_definition (db::DeviceParameterDefinition (pname, std::string ())).id ();
}
device->set_parameter_value (pid, value);
} else {
throw tl::Exception (tl::to_string (tr ("Invalid keyword inside device definition (location, param or terminal expected)")));
}
}
br.done ();
}
void
LayoutVsSchematicStandardReader::read_subcircuit (db::Netlist *netlist, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net)
{
Brace br (this);
std::string name;
read_word_or_quoted (name);
std::string xname;
read_word_or_quoted (xname);
db::Circuit *circuit_ref = netlist->circuit_by_name (xname);
if (! circuit_ref) {
throw tl::Exception (tl::to_string (tr ("Not a valid device circuit name: ")) + xname);
}
db::SubCircuit *subcircuit = new db::SubCircuit (circuit_ref);
subcircuit->set_name (name);
circuit->add_subcircuit (subcircuit);
while (br) {
if (test (skeys::pin_key) || test (lkeys::pin_key)) {
Brace br2 (this);
std::string pname;
read_word_or_quoted (pname);
unsigned int netid = (unsigned int) read_int ();
br2.done ();
const db::Pin *sc_pin = circuit_ref->pin_by_name (pname);
if (! sc_pin) {
throw tl::Exception (tl::to_string (tr ("Not a valid pin name: ")) + pname + tl::to_string (tr (" for circuit: ")) + circuit_ref->name ());
}
db::Net *net = id2net [netid];
if (!net) {
throw tl::Exception (tl::to_string (tr ("Not a valid net ID: ")) + tl::to_string (netid));
}
subcircuit->connect_pin (sc_pin->id (), net);
} else {
throw tl::Exception (tl::to_string (tr ("Invalid keyword inside subcircuit definition (location, rotation, mirror, scale or pin expected)")));
}
}
br.done ();
}
bool LayoutVsSchematicStandardReader::read_status (db::NetlistCrossReference::Status &status)
{
if (test (skeys::match_key) || test (lkeys::match_key)) {
@ -429,17 +221,26 @@ std::pair<unsigned int, bool> LayoutVsSchematicStandardReader::read_non_numerica
}
}
static const db::Net *net_by_numerical_id (const db::Circuit *circuit, const std::pair<unsigned int, bool> &non)
static const db::Net *net_by_numerical_id (const db::Circuit *circuit, const std::pair<unsigned int, bool> &non, std::map<const db::Circuit *, std::map<unsigned int, Net *> > &id2net_per_circuit)
{
if (non.second && circuit) {
const db::Net *net = 0; // @@@ circuit->net_by_numerical_id (non.first);
if (! net) {
throw tl::Exception (tl::to_string (tr ("Not a valid net id: ")) + tl::to_string (non.first));
std::map<const db::Circuit *, std::map<unsigned int, Net *> >::const_iterator i = id2net_per_circuit.find (circuit);
if (i != id2net_per_circuit.end ()) {
std::map<unsigned int, Net *>::const_iterator j = i->second.find (non.first);
if (j != i->second.end ()) {
return j->second;
}
}
return net;
} else {
return 0;
throw tl::Exception (tl::to_string (tr ("Not a valid net id: ")) + tl::to_string (non.first));
}
return 0;
}
void LayoutVsSchematicStandardReader::read_net_pair (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b)
@ -455,7 +256,7 @@ void LayoutVsSchematicStandardReader::read_net_pair (db::NetlistCrossReference *
br.done ();
xref->gen_nets (net_by_numerical_id (circuit_a, non_a), net_by_numerical_id (circuit_b, non_b), status);
xref->gen_nets (net_by_numerical_id (circuit_a, non_a, m_id2net_per_circuit_a), net_by_numerical_id (circuit_b, non_b, m_id2net_per_circuit_b), status);
}
static const db::Pin *pin_by_name (const db::Circuit *circuit, const std::pair<std::string, bool> &non)

View File

@ -66,12 +66,7 @@ public:
private:
void do_read (db::LayoutVsSchematic *lvs);
void read_netlist (db::Netlist *netlist);
bool read_status (db::NetlistCrossReference::Status &status);
void read_net (db::Netlist *netlist, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net);
void read_subcircuit (db::Netlist *netlist, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net);
void read_device (db::Netlist *netlist, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net);
void read_pin (db::Netlist *netlist, db::Circuit *circuit, std::map<unsigned int, Net *> &id2net);
void read_xref (db::NetlistCrossReference *xref);
void read_xrefs_for_circuits (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b);
void read_net_pair (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b);
@ -80,6 +75,8 @@ private:
void read_subcircuit_pair (db::NetlistCrossReference *xref, const db::Circuit *circuit_a, const db::Circuit *circuit_b);
std::pair<std::string, bool> read_non_string ();
std::pair<unsigned int, bool> read_non_numerical ();
std::map<const db::Circuit *, std::map<unsigned int, Net *> > m_id2net_per_circuit_a, m_id2net_per_circuit_b;
};
}

View File

@ -45,6 +45,7 @@ void LayoutVsSchematicWriterBase::write (const db::LayoutVsSchematic *l2n)
do_write (l2n);
}
#if 0
// -------------------------------------------------------------------------------------------
namespace l2n_std_format
@ -537,6 +538,7 @@ void std_writer_impl<Keys>::write (const db::LayoutVsSchematic *l2n, const db::D
}
}
#endif
// -------------------------------------------------------------------------------------------
// LayoutVsSchematicStandardWriter implementation
@ -547,8 +549,9 @@ LayoutVsSchematicStandardWriter::LayoutVsSchematicStandardWriter (tl::OutputStre
// .. nothing yet ..
}
void LayoutVsSchematicStandardWriter::do_write (const db::LayoutVsSchematic *l2n)
void LayoutVsSchematicStandardWriter::do_write (const db::LayoutVsSchematic * /*lvs*/)
{
#if 0
if (m_short_version) {
l2n_std_format::std_writer_impl<l2n_std_format::keys<true> > writer (*mp_stream);
writer.write (l2n);
@ -556,6 +559,7 @@ void LayoutVsSchematicStandardWriter::do_write (const db::LayoutVsSchematic *l2n
l2n_std_format::std_writer_impl<l2n_std_format::keys<false> > writer (*mp_stream);
writer.write (l2n);
}
#endif
}
}