From b2fee5da3d96a25b58f47947483bfe1c1f9c89e3 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 19 May 2019 00:34:14 +0200 Subject: [PATCH] WIP: LVS DB writer. --- src/db/db/dbLayoutToNetlistReader.cc | 6 +- src/db/db/dbLayoutToNetlistReader.h | 12 +- src/db/db/dbLayoutToNetlistWriter.cc | 219 +++++------ src/db/db/dbLayoutToNetlistWriter.h | 44 +++ src/db/db/dbLayoutVsSchematic.cc | 2 +- src/db/db/dbLayoutVsSchematicReader.cc | 13 +- src/db/db/dbLayoutVsSchematicReader.h | 17 +- src/db/db/dbLayoutVsSchematicWriter.cc | 509 +++++-------------------- src/db/db/dbLayoutVsSchematicWriter.h | 8 +- 9 files changed, 284 insertions(+), 546 deletions(-) diff --git a/src/db/db/dbLayoutToNetlistReader.cc b/src/db/db/dbLayoutToNetlistReader.cc index 52a2bfb6e..b78e0d010 100644 --- a/src/db/db/dbLayoutToNetlistReader.cc +++ b/src/db/db/dbLayoutToNetlistReader.cc @@ -127,10 +127,10 @@ LayoutToNetlistStandardReader::skip () } } -void LayoutToNetlistStandardReader::read (db::LayoutToNetlist *l2n) +void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n) { try { - do_read (0, l2n); + read_netlist (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)); } @@ -145,7 +145,7 @@ static db::Region &layer_by_name (db::LayoutToNetlist *l2n, const std::string &n return *l; } -void LayoutToNetlistStandardReader::do_read (db::Netlist *netlist, db::LayoutToNetlist *l2n, bool nested, std::map > *id2net_per_circuit) +void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::LayoutToNetlist *l2n, bool nested, std::map > *id2net_per_circuit) { int version = 0; std::string description; diff --git a/src/db/db/dbLayoutToNetlistReader.h b/src/db/db/dbLayoutToNetlistReader.h index 35bfd4b66..87f5e5413 100644 --- a/src/db/db/dbLayoutToNetlistReader.h +++ b/src/db/db/dbLayoutToNetlistReader.h @@ -68,7 +68,13 @@ public: LayoutToNetlistReaderBase () { } virtual ~LayoutToNetlistReaderBase () { } - virtual void read (db::LayoutToNetlist *l2n) = 0; + void read (db::LayoutToNetlist *l2n) + { + do_read (l2n); + } + +private: + virtual void do_read (db::LayoutToNetlist *l2n) = 0; }; /** @@ -80,13 +86,13 @@ class DB_PUBLIC LayoutToNetlistStandardReader public: LayoutToNetlistStandardReader (tl::InputStream &stream); - void read (db::LayoutToNetlist *l2n); + void do_read (db::LayoutToNetlist *l2n); protected: friend class l2n_std_reader::Brace; typedef l2n_std_reader::Brace Brace; - void do_read (Netlist *netlist, db::LayoutToNetlist *l2n, bool nested = false, std::map > *id2net_per_circuit = 0); + void read_netlist (Netlist *netlist, db::LayoutToNetlist *l2n, bool nested = false, std::map > *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 (); diff --git a/src/db/db/dbLayoutToNetlistWriter.cc b/src/db/db/dbLayoutToNetlistWriter.cc index 0febc845c..ac52f6ee2 100644 --- a/src/db/db/dbLayoutToNetlistWriter.cc +++ b/src/db/db/dbLayoutToNetlistWriter.cc @@ -50,29 +50,8 @@ void LayoutToNetlistWriterBase::write (const db::LayoutToNetlist *l2n) namespace l2n_std_format { -// ------------------------------------------------------------------------------------------- -// std_writer_impl implementation - -template -class std_writer_impl -{ -public: - std_writer_impl (tl::OutputStream &stream); - - void write (const db::LayoutToNetlist *l2n); - -private: - tl::OutputStream *mp_stream; - db::Point m_ref; - - void write (const db::LayoutToNetlist *l2n, const db::Circuit &circuit); - void write (const db::LayoutToNetlist *l2n, const db::Net &net, unsigned int id); - void write (const db::LayoutToNetlist *l2n, const db::SubCircuit &subcircuit, std::map &net2id); - void write (const db::LayoutToNetlist *l2n, const db::Device &device, std::map &net2id); - void write (const db::LayoutToNetlist *l2n, const db::DeviceAbstract &device_abstract); - void write (const db::PolygonRef *s, const db::ICplxTrans &tr, const std::string &lname, bool relative); - void reset_geometry_ref (); -}; +template class std_writer_impl >; +template class std_writer_impl >; static const std::string endl ("\n"); static const std::string indent1 (" "); @@ -96,100 +75,117 @@ static std::string name_for_layer (const db::LayoutToNetlist *l2n, unsigned int template void std_writer_impl::write (const db::LayoutToNetlist *l2n) +{ + write (l2n->netlist (), l2n, false, 0); + +} + +template +void std_writer_impl::write (const db::Netlist *nl, const db::LayoutToNetlist *l2n, bool nested, std::map > *net2id_per_circuit) { bool any = false; const int version = 0; - const db::Layout *ly = l2n->internal_layout (); - const db::Netlist *nl = l2n->netlist (); + const db::Layout *ly = l2n ? l2n->internal_layout () : 0; + const std::string indent (nested ? indent1 : ""); - *mp_stream << "#%l2n-klayout" << endl; + if (! nested) { + *mp_stream << "#%l2n-klayout" << endl; + } if (! Keys::is_short ()) { - *mp_stream << endl << "# General section" << endl << endl; + *mp_stream << endl << indent << "# General section" << endl << endl; } if (version > 0) { - *mp_stream << Keys::version_key << "(" << version << ")" << endl; + *mp_stream << indent << Keys::version_key << "(" << version << ")" << endl; } - *mp_stream << Keys::top_key << "(" << tl::to_word_or_quoted_string (ly->cell_name (l2n->internal_top_cell ()->cell_index ())) << ")" << endl; - *mp_stream << Keys::unit_key << "(" << ly->dbu () << ")" << endl; - - if (! Keys::is_short ()) { - *mp_stream << endl << "# Layer section" << endl; - *mp_stream << "# This section lists the mask layers (drawing or derived) and their connections." << endl; + if (ly) { + *mp_stream << indent << Keys::top_key << "(" << tl::to_word_or_quoted_string (ly->cell_name (l2n->internal_top_cell ()->cell_index ())) << ")" << endl; + *mp_stream << indent << Keys::unit_key << "(" << ly->dbu () << ")" << endl; } if (! Keys::is_short ()) { - *mp_stream << endl << "# Mask layers" << endl; + *mp_stream << endl << indent << "# Layer section" << endl; + *mp_stream << indent << "# This section lists the mask layers (drawing or derived) and their connections." << endl; } - for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { - *mp_stream << Keys::layer_key << "(" << name_for_layer (l2n, *l); - db::LayerProperties lp = ly->get_properties (*l); - if (! lp.is_null ()) { - *mp_stream << " " << tl::to_word_or_quoted_string (lp.to_string ()); + + if (ly) { + if (! Keys::is_short ()) { + *mp_stream << endl << indent << "# Mask layers" << endl; } - *mp_stream << ")" << endl; - } - - if (! Keys::is_short ()) { - *mp_stream << endl << "# Mask layer connectivity" << endl; - } - for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { - - db::Connectivity::layer_iterator ce = l2n->connectivity ().end_connected (*l); - db::Connectivity::layer_iterator cb = l2n->connectivity ().begin_connected (*l); - if (cb != ce) { - *mp_stream << Keys::connect_key << "(" << name_for_layer (l2n, *l); - for (db::Connectivity::layer_iterator c = l2n->connectivity ().begin_connected (*l); c != ce; ++c) { - *mp_stream << " " << name_for_layer (l2n, *c); + for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { + *mp_stream << indent << Keys::layer_key << "(" << name_for_layer (l2n, *l); + db::LayerProperties lp = ly->get_properties (*l); + if (! lp.is_null ()) { + *mp_stream << indent << " " << tl::to_word_or_quoted_string (lp.to_string ()); } - *mp_stream << ")" << endl; + *mp_stream << indent << ")" << endl; } - } - any = false; - for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { + if (l2n) { - db::Connectivity::global_nets_iterator ge = l2n->connectivity ().end_global_connections (*l); - db::Connectivity::global_nets_iterator gb = l2n->connectivity ().begin_global_connections (*l); - if (gb != ge) { - if (! any) { - if (! Keys::is_short ()) { - *mp_stream << endl << "# Global nets and connectivity" << endl; + if (! Keys::is_short ()) { + *mp_stream << endl << indent << "# Mask layer connectivity" << endl; + } + for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { + + db::Connectivity::layer_iterator ce = l2n->connectivity ().end_connected (*l); + db::Connectivity::layer_iterator cb = l2n->connectivity ().begin_connected (*l); + if (cb != ce) { + *mp_stream << indent << Keys::connect_key << "(" << name_for_layer (l2n, *l); + for (db::Connectivity::layer_iterator c = l2n->connectivity ().begin_connected (*l); c != ce; ++c) { + *mp_stream << indent << " " << name_for_layer (l2n, *c); } - any = true; + *mp_stream << indent << ")" << endl; } - *mp_stream << Keys::global_key << "(" << name_for_layer (l2n, *l); - for (db::Connectivity::global_nets_iterator g = gb; g != ge; ++g) { - *mp_stream << " " << tl::to_word_or_quoted_string (l2n->connectivity ().global_net_name (*g)); + + } + + any = false; + for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { + + db::Connectivity::global_nets_iterator ge = l2n->connectivity ().end_global_connections (*l); + db::Connectivity::global_nets_iterator gb = l2n->connectivity ().begin_global_connections (*l); + if (gb != ge) { + if (! any) { + if (! Keys::is_short ()) { + *mp_stream << endl << "# Global nets and connectivity" << endl; + } + any = true; + } + *mp_stream << indent << Keys::global_key << "(" << name_for_layer (l2n, *l); + for (db::Connectivity::global_nets_iterator g = gb; g != ge; ++g) { + *mp_stream << indent << " " << tl::to_word_or_quoted_string (l2n->connectivity ().global_net_name (*g)); + } + *mp_stream << indent << ")" << endl; } - *mp_stream << ")" << endl; + } } if (nl->begin_device_classes () != nl->end_device_classes () && ! Keys::is_short ()) { - *mp_stream << endl << "# Device class section" << endl; + *mp_stream << endl << indent << "# Device class section" << endl; for (db::Netlist::const_device_class_iterator c = nl->begin_device_classes (); c != nl->end_device_classes (); ++c) { db::DeviceClassTemplateBase *temp = db::DeviceClassTemplateBase::is_a (c.operator-> ()); if (temp) { - *mp_stream << Keys::class_key << "(" << tl::to_word_or_quoted_string (c->name ()) << " " << tl::to_word_or_quoted_string (temp->name ()) << ")" << endl; + *mp_stream << indent << Keys::class_key << "(" << tl::to_word_or_quoted_string (c->name ()) << " " << tl::to_word_or_quoted_string (temp->name ()) << ")" << endl; } } } if (nl->begin_device_abstracts () != nl->end_device_abstracts () && ! Keys::is_short ()) { - *mp_stream << endl << "# Device abstracts section" << endl; - *mp_stream << "# Device abstracts list the pin shapes of the devices." << endl; + *mp_stream << endl << indent << "# Device abstracts section" << endl; + *mp_stream << indent << "# Device abstracts list the pin shapes of the devices." << endl; } for (db::Netlist::const_abstract_model_iterator m = nl->begin_device_abstracts (); m != nl->end_device_abstracts (); ++m) { if (m->device_class ()) { - *mp_stream << Keys::device_key << "(" << tl::to_word_or_quoted_string (m->name ()) << " " << tl::to_word_or_quoted_string (m->device_class ()->name ()) << endl; - write (l2n, *m); - *mp_stream << ")" << endl; + *mp_stream << indent << Keys::device_key << "(" << tl::to_word_or_quoted_string (m->name ()) << " " << tl::to_word_or_quoted_string (m->device_class ()->name ()) << endl; + write (l2n, *m, indent); + *mp_stream << indent << ")" << endl; } } @@ -199,55 +195,60 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n) } for (db::Netlist::const_bottom_up_circuit_iterator i = nl->begin_bottom_up (); i != nl->end_bottom_up (); ++i) { const db::Circuit *x = *i; - *mp_stream << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (x->name ()) << endl; - write (l2n, *x); - *mp_stream << ")" << endl; + *mp_stream << indent << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (x->name ()) << endl; + write (l2n, *x, indent, net2id_per_circuit); + *mp_stream << indent << ")" << endl; } } template -void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Circuit &circuit) +void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Circuit &circuit, const std::string &indent, std::map > *net2id_per_circuit) { - std::map net2id; + std::map net2id_local; + std::map *net2id = &net2id_local; + if (net2id_per_circuit) { + net2id = &(*net2id_per_circuit) [&circuit]; + } + unsigned int id = 0; if (circuit.begin_nets () != circuit.end_nets ()) { if (! Keys::is_short ()) { - *mp_stream << endl << indent1 << "# Nets with their geometries" << endl; + *mp_stream << endl << indent << indent1 << "# Nets with their geometries" << endl; } for (db::Circuit::const_net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) { - net2id.insert (std::make_pair (n.operator-> (), ++id)); - write (l2n, *n, id); + net2id->insert (std::make_pair (n.operator-> (), ++id)); + write (l2n, *n, id, indent); } } if (circuit.begin_pins () != circuit.end_pins ()) { if (! Keys::is_short ()) { - *mp_stream << endl << indent1 << "# Outgoing pins and their connections to nets" << endl; + *mp_stream << endl << indent << indent1 << "# Outgoing pins and their connections to nets" << endl; } for (db::Circuit::const_pin_iterator p = circuit.begin_pins (); p != circuit.end_pins (); ++p) { const db::Net *net = circuit.net_for_pin (p->id ()); if (net) { - *mp_stream << indent1 << Keys::pin_key << "(" << tl::to_word_or_quoted_string (p->expanded_name ()) << " " << net2id [net] << ")" << endl; + *mp_stream << indent << indent1 << Keys::pin_key << "(" << tl::to_word_or_quoted_string (p->expanded_name ()) << " " << (*net2id) [net] << ")" << endl; } } } if (circuit.begin_devices () != circuit.end_devices ()) { if (! Keys::is_short ()) { - *mp_stream << endl << indent1 << "# Devices and their connections" << endl; + *mp_stream << endl << indent << indent1 << "# Devices and their connections" << endl; } for (db::Circuit::const_device_iterator d = circuit.begin_devices (); d != circuit.end_devices (); ++d) { - write (l2n, *d, net2id); + write (l2n, *d, *net2id, indent); } } if (circuit.begin_subcircuits () != circuit.end_subcircuits ()) { if (! Keys::is_short ()) { - *mp_stream << endl << indent1 << "# Subcircuits and their connections" << endl; + *mp_stream << endl << indent << indent1 << "# Subcircuits and their connections" << endl; } for (db::Circuit::const_subcircuit_iterator x = circuit.begin_subcircuits (); x != circuit.end_subcircuits (); ++x) { - write (l2n, *x, net2id); + write (l2n, *x, *net2id, indent); } } @@ -335,7 +336,7 @@ void std_writer_impl::write (const db::PolygonRef *s, const db::ICplxTrans } template -void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Net &net, unsigned int id) +void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Net &net, unsigned int id, const std::string &indent) { if (! l2n->netlist ()) { throw tl::Exception (tl::to_string (tr ("Can't write annotated netlist before extraction has been done"))); @@ -367,7 +368,7 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Net } else { if (! any) { - *mp_stream << indent1 << Keys::net_key << "(" << id; + *mp_stream << indent << indent1 << Keys::net_key << "(" << id; if (! net.name ().empty ()) { *mp_stream << " " << Keys::name_key << "(" << tl::to_word_or_quoted_string (net.name ()) << ")"; } @@ -390,7 +391,7 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Net } if (any) { - *mp_stream << indent1 << ")" << endl; + *mp_stream << indent << indent1 << ")" << endl; } else { *mp_stream << indent1 << Keys::net_key << "(" << id; @@ -403,12 +404,12 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Net } template -void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::SubCircuit &subcircuit, std::map &net2id) +void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::SubCircuit &subcircuit, std::map &net2id, const std::string &indent) { const db::Layout *ly = l2n->internal_layout (); double dbu = ly->dbu (); - *mp_stream << indent1 << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (subcircuit.expanded_name ()); + *mp_stream << indent << indent1 << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (subcircuit.expanded_name ()); *mp_stream << " " << tl::to_word_or_quoted_string (subcircuit.circuit_ref ()->name ()); const db::DCplxTrans &tr = subcircuit.trans (); @@ -434,7 +435,7 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Sub const db::Net *net = subcircuit.net_for_pin (p->id ()); if (net) { if (separate_lines) { - *mp_stream << indent2; + *mp_stream << indent << indent2; } else { *mp_stream << " "; } @@ -446,14 +447,14 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Sub } if (separate_lines) { - *mp_stream << indent1; + *mp_stream << indent << indent1; } *mp_stream << ")" << endl; } template -void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::DeviceAbstract &device_abstract) +void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::DeviceAbstract &device_abstract, const std::string &indent) { const std::vector &td = device_abstract.device_class ()->terminal_definitions (); @@ -462,7 +463,7 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Dev for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { - *mp_stream << indent1 << Keys::terminal_key << "(" << t->name () << endl; + *mp_stream << indent << indent1 << Keys::terminal_key << "(" << t->name () << endl; reset_geometry_ref (); @@ -471,7 +472,7 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Dev const db::local_cluster &lc = clusters.clusters_per_cell (device_abstract.cell_index ()).cluster_by_id (device_abstract.cluster_id_for_terminal (t->id ())); for (db::local_cluster::shape_iterator s = lc.begin (*l); ! s.at_end (); ++s) { - *mp_stream << indent2; + *mp_stream << indent << indent2; write (s.operator-> (), db::ICplxTrans (), name_for_layer (l2n, *l), true); *mp_stream << endl; @@ -479,13 +480,13 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Dev } - *mp_stream << indent1 << ")" << endl; + *mp_stream << indent << indent1 << ")" << endl; } } template -void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Device &device, std::map &net2id) +void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Device &device, std::map &net2id, const std::string &indent) { const db::Layout *ly = l2n->internal_layout (); double dbu = ly->dbu (); @@ -495,7 +496,7 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Dev const std::vector &td = device.device_class ()->terminal_definitions (); const std::vector &pd = device.device_class ()->parameter_definitions (); - *mp_stream << indent1 << Keys::device_key << "(" << tl::to_word_or_quoted_string (device.expanded_name ()); + *mp_stream << indent << indent1 << Keys::device_key << "(" << tl::to_word_or_quoted_string (device.expanded_name ()); tl_assert (device.device_abstract () != 0); *mp_stream << " " << tl::to_word_or_quoted_string (device.device_abstract ()->name ()) << endl; @@ -505,7 +506,7 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Dev db::Vector pos = dbu_inv * a->offset; - *mp_stream << " " << Keys::device_key << "(" << tl::to_word_or_quoted_string (a->device_abstract->name ()) << " " << pos.x () << " " << pos.y () << ")" << endl; + *mp_stream << indent << indent2 << Keys::device_key << "(" << tl::to_word_or_quoted_string (a->device_abstract->name ()) << " " << pos.x () << " " << pos.y () << ")" << endl; } @@ -513,27 +514,27 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Dev for (std::map >::const_iterator t = reconnected_terminals.begin (); t != reconnected_terminals.end (); ++t) { for (std::vector::const_iterator c = t->second.begin (); c != t->second.end (); ++c) { - *mp_stream << " " << Keys::connect_key << "(" << c->device_index << " " << tl::to_word_or_quoted_string (td [t->first].name ()) << " " << tl::to_word_or_quoted_string (td [c->other_terminal_id].name ()) << ")" << endl; + *mp_stream << indent << indent2 << Keys::connect_key << "(" << c->device_index << " " << tl::to_word_or_quoted_string (td [t->first].name ()) << " " << tl::to_word_or_quoted_string (td [c->other_terminal_id].name ()) << ")" << endl; } } db::Point pos = dbu_inv * device.position (); - *mp_stream << indent2 << Keys::location_key << "(" << pos.x () << " " << pos.y () << ")" << endl; + *mp_stream << indent << indent2 << Keys::location_key << "(" << pos.x () << " " << pos.y () << ")" << endl; for (std::vector::const_iterator i = pd.begin (); i != pd.end (); ++i) { - *mp_stream << indent2 << Keys::param_key << "(" << tl::to_word_or_quoted_string (i->name ()) << " " << device.parameter_value (i->id ()) << ")" << endl; + *mp_stream << indent << indent2 << Keys::param_key << "(" << tl::to_word_or_quoted_string (i->name ()) << " " << device.parameter_value (i->id ()) << ")" << endl; } for (std::vector::const_iterator i = td.begin (); i != td.end (); ++i) { const db::Net *net = device.net_for_terminal (i->id ()); if (net) { - *mp_stream << indent2 << Keys::terminal_key << "(" << tl::to_word_or_quoted_string (i->name ()) << " " << net2id [net] << ")" << endl; + *mp_stream << indent << indent2 << Keys::terminal_key << "(" << tl::to_word_or_quoted_string (i->name ()) << " " << net2id [net] << ")" << endl; } } - *mp_stream << indent1 << ")" << endl; + *mp_stream << indent << indent1 << ")" << endl; } } diff --git a/src/db/db/dbLayoutToNetlistWriter.h b/src/db/db/dbLayoutToNetlistWriter.h index b8f08a844..7bb1ed4ca 100644 --- a/src/db/db/dbLayoutToNetlistWriter.h +++ b/src/db/db/dbLayoutToNetlistWriter.h @@ -24,11 +24,55 @@ #define HDR_dbLayoutToNetlistWriter #include "dbCommon.h" +#include "dbPoint.h" +#include "dbTrans.h" +#include "dbPolygon.h" #include "tlStream.h" namespace db { +class Circuit; +class SubCircuit; +class Device; +class DeviceAbstract; +class Net; +class Netlist; +class LayoutToNetlist; + +namespace l2n_std_format +{ + +template +class std_writer_impl +{ +public: + std_writer_impl (tl::OutputStream &stream); + + void write (const db::LayoutToNetlist *l2n); + +protected: + void write (const db::Netlist *netlist, const db::LayoutToNetlist *l2n, bool nested, std::map > *net2id_per_circuit); + void write (const db::LayoutToNetlist *l2n, const db::Circuit &circuit, const std::string &indent, std::map > *net2id_per_circuit); + void write (const db::LayoutToNetlist *l2n, const db::Net &net, unsigned int id, const std::string &indent); + void write (const db::LayoutToNetlist *l2n, const db::SubCircuit &subcircuit, std::map &net2id, const std::string &indent); + void write (const db::LayoutToNetlist *l2n, const db::Device &device, std::map &net2id, const std::string &indent); + void write (const db::LayoutToNetlist *l2n, const db::DeviceAbstract &device_abstract, const std::string &indent); + void write (const db::PolygonRef *s, const db::ICplxTrans &tr, const std::string &lname, bool relative); + void reset_geometry_ref (); + + tl::OutputStream &stream () + { + return *mp_stream; + } + +private: + tl::OutputStream *mp_stream; + db::Point m_ref; +}; + +} + class LayoutToNetlist; /** diff --git a/src/db/db/dbLayoutVsSchematic.cc b/src/db/db/dbLayoutVsSchematic.cc index a2249b739..e6c092795 100644 --- a/src/db/db/dbLayoutVsSchematic.cc +++ b/src/db/db/dbLayoutVsSchematic.cc @@ -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_lvs (this); + reader.read (this); } } diff --git a/src/db/db/dbLayoutVsSchematicReader.cc b/src/db/db/dbLayoutVsSchematicReader.cc index f44f85160..9eadfbed1 100644 --- a/src/db/db/dbLayoutVsSchematicReader.cc +++ b/src/db/db/dbLayoutVsSchematicReader.cc @@ -29,22 +29,25 @@ namespace db typedef lvs_std_format::keys skeys; typedef lvs_std_format::keys lkeys; +// ------------------------------------------------------------------------------------------------- +// LayoutVsSchematicStandardReader implementation + LayoutVsSchematicStandardReader::LayoutVsSchematicStandardReader (tl::InputStream &stream) : LayoutToNetlistStandardReader (stream) { // .. nothing yet .. } -void LayoutVsSchematicStandardReader::read_lvs (db::LayoutVsSchematic *l2n) +void LayoutVsSchematicStandardReader::do_read_lvs (db::LayoutVsSchematic *l2n) { try { - do_read (l2n); + read_netlist (l2n); } catch (tl::Exception &ex) { throw tl::Exception (tl::sprintf (tl::to_string (tr ("%s in line: %d of %s")), ex.msg (), stream ().line_number (), path ())); } } -void LayoutVsSchematicStandardReader::do_read (db::LayoutVsSchematic *lvs) +void LayoutVsSchematicStandardReader::read_netlist (db::LayoutVsSchematic *lvs) { int version = 0; std::string description; @@ -78,14 +81,14 @@ void LayoutVsSchematicStandardReader::do_read (db::LayoutVsSchematic *lvs) } else if (test (skeys::layout_key) || test (lkeys::layout_key)) { Brace br (this); - LayoutToNetlistStandardReader::do_read (0, lvs, true /*nested*/, &m_id2net_per_circuit_a); + LayoutToNetlistStandardReader::read_netlist (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 netlist (new db::Netlist ()); - LayoutToNetlistStandardReader::do_read (netlist.get (), 0, true /*nested*/, &m_id2net_per_circuit_b); + LayoutToNetlistStandardReader::read_netlist (netlist.get (), 0, true /*nested*/, &m_id2net_per_circuit_b); lvs->set_reference_netlist (netlist.release ()); br.done (); diff --git a/src/db/db/dbLayoutVsSchematicReader.h b/src/db/db/dbLayoutVsSchematicReader.h index 0c41d4850..2f79783eb 100644 --- a/src/db/db/dbLayoutVsSchematicReader.h +++ b/src/db/db/dbLayoutVsSchematicReader.h @@ -49,7 +49,13 @@ public: LayoutVsSchematicReaderBase () { } virtual ~LayoutVsSchematicReaderBase () { } - virtual void read_lvs (db::LayoutVsSchematic *lvs) = 0; + void read (db::LayoutVsSchematic *lvs) + { + do_read_lvs (lvs); + } + +protected: + virtual void do_read_lvs (db::LayoutVsSchematic *lvs) = 0; }; /** @@ -61,10 +67,15 @@ class DB_PUBLIC LayoutVsSchematicStandardReader public: LayoutVsSchematicStandardReader (tl::InputStream &stream); - void read_lvs (db::LayoutVsSchematic *lvs); + void read (db::LayoutVsSchematic *lvs) + { + do_read_lvs (lvs); + } + + virtual void do_read_lvs (db::LayoutVsSchematic *lvs); private: - void do_read (db::LayoutVsSchematic *lvs); + void read_netlist (db::LayoutVsSchematic *lvs); bool read_status (db::NetlistCrossReference::Status &status); void read_xref (db::NetlistCrossReference *xref); diff --git a/src/db/db/dbLayoutVsSchematicWriter.cc b/src/db/db/dbLayoutVsSchematicWriter.cc index 0c90a3acb..43233bd7a 100644 --- a/src/db/db/dbLayoutVsSchematicWriter.cc +++ b/src/db/db/dbLayoutVsSchematicWriter.cc @@ -20,6 +20,7 @@ */ +#include "dbLayoutToNetlistWriter.h" #include "dbLayoutVsSchematicWriter.h" #include "dbLayoutVsSchematic.h" #include "dbLayoutVsSchematicFormatDefs.h" @@ -40,15 +41,14 @@ LayoutVsSchematicWriterBase::~LayoutVsSchematicWriterBase () // .. nothing yet .. } -void LayoutVsSchematicWriterBase::write (const db::LayoutVsSchematic *l2n) +void LayoutVsSchematicWriterBase::write (const db::LayoutVsSchematic *lvs) { - do_write (l2n); + do_write_lvs (lvs); } -#if 0 // ------------------------------------------------------------------------------------------- -namespace l2n_std_format +namespace lvs_std_format { // ------------------------------------------------------------------------------------------- @@ -56,6 +56,7 @@ namespace l2n_std_format template class std_writer_impl + : public l2n_std_format::std_writer_impl { public: std_writer_impl (tl::OutputStream &stream); @@ -63,16 +64,15 @@ public: void write (const db::LayoutVsSchematic *l2n); private: - tl::OutputStream *mp_stream; - db::Point m_ref; + tl::OutputStream &stream () + { + return l2n_std_format::std_writer_impl::stream (); + } - void write (const db::LayoutVsSchematic *l2n, const db::Circuit &circuit); - void write (const db::LayoutVsSchematic *l2n, const db::Net &net, unsigned int id); - void write (const db::LayoutVsSchematic *l2n, const db::SubCircuit &subcircuit, std::map &net2id); - void write (const db::LayoutVsSchematic *l2n, const db::Device &device, std::map &net2id); - void write (const db::LayoutVsSchematic *l2n, const db::DeviceAbstract &device_abstract); - void write (const db::PolygonRef *s, const db::ICplxTrans &tr, const std::string &lname, bool relative); - void reset_geometry_ref (); + std::string status_to_s (const db::NetlistCrossReference::Status status); + void write (const db::NetlistCrossReference *xref); + + std::map > m_net2id_per_circuit_a, m_net2id_per_circuit_b; }; static const std::string endl ("\n"); @@ -81,464 +81,135 @@ static const std::string indent2 (" "); template std_writer_impl::std_writer_impl (tl::OutputStream &stream) - : mp_stream (&stream) + : l2n_std_format::std_writer_impl (stream) { // .. nothing yet .. } -static std::string name_for_layer (const db::LayoutVsSchematic *l2n, unsigned int l) -{ - std::string n = l2n->name (l); - if (n.empty ()) { - n = "L" + tl::to_string (l); - } - return n; -} - template -void std_writer_impl::write (const db::LayoutVsSchematic *l2n) +void std_writer_impl::write (const db::LayoutVsSchematic *lvs) { - bool any = false; - const int version = 0; - const db::Layout *ly = l2n->internal_layout (); - const db::Netlist *nl = l2n->netlist (); - - *mp_stream << "#%l2n-klayout" << endl; + stream () << "#%lvs-klayout" << endl; if (! Keys::is_short ()) { - *mp_stream << endl << "# General section" << endl << endl; + stream () << endl << "# General section" << endl << endl; } if (version > 0) { - *mp_stream << Keys::version_key << "(" << version << ")" << endl; - } - *mp_stream << Keys::top_key << "(" << tl::to_word_or_quoted_string (ly->cell_name (l2n->internal_top_cell ()->cell_index ())) << ")" << endl; - *mp_stream << Keys::unit_key << "(" << ly->dbu () << ")" << endl; - - if (! Keys::is_short ()) { - *mp_stream << endl << "# Layer section" << endl; - *mp_stream << "# This section lists the mask layers (drawing or derived) and their connections." << endl; + stream () << Keys::version_key << "(" << version << ")" << endl; } if (! Keys::is_short ()) { - *mp_stream << endl << "# Mask layers" << endl; - } - for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { - *mp_stream << Keys::layer_key << "(" << name_for_layer (l2n, *l); - db::LayerProperties lp = ly->get_properties (*l); - if (! lp.is_null ()) { - *mp_stream << " " << tl::to_word_or_quoted_string (lp.to_string ()); - } - *mp_stream << ")" << endl; + stream () << endl << "# Layout" << endl; } + stream () << Keys::layout_key << "(" << endl; + l2n_std_format::std_writer_impl::write (0, lvs, true, &m_net2id_per_circuit_a); + stream () << ")" << endl; if (! Keys::is_short ()) { - *mp_stream << endl << "# Mask layer connectivity" << endl; - } - for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { - - db::Connectivity::layer_iterator ce = l2n->connectivity ().end_connected (*l); - db::Connectivity::layer_iterator cb = l2n->connectivity ().begin_connected (*l); - if (cb != ce) { - *mp_stream << Keys::connect_key << "(" << name_for_layer (l2n, *l); - for (db::Connectivity::layer_iterator c = l2n->connectivity ().begin_connected (*l); c != ce; ++c) { - *mp_stream << " " << name_for_layer (l2n, *c); - } - *mp_stream << ")" << endl; - } - - } - - any = false; - for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) { - - db::Connectivity::global_nets_iterator ge = l2n->connectivity ().end_global_connections (*l); - db::Connectivity::global_nets_iterator gb = l2n->connectivity ().begin_global_connections (*l); - if (gb != ge) { - if (! any) { - if (! Keys::is_short ()) { - *mp_stream << endl << "# Global nets and connectivity" << endl; - } - any = true; - } - *mp_stream << Keys::global_key << "(" << name_for_layer (l2n, *l); - for (db::Connectivity::global_nets_iterator g = gb; g != ge; ++g) { - *mp_stream << " " << tl::to_word_or_quoted_string (l2n->connectivity ().global_net_name (*g)); - } - *mp_stream << ")" << endl; - } - - } - - if (nl->begin_device_classes () != nl->end_device_classes () && ! Keys::is_short ()) { - *mp_stream << endl << "# Device class section" << endl; - for (db::Netlist::const_device_class_iterator c = nl->begin_device_classes (); c != nl->end_device_classes (); ++c) { - db::DeviceClassTemplateBase *temp = db::DeviceClassTemplateBase::is_a (c.operator-> ()); - if (temp) { - *mp_stream << Keys::class_key << "(" << tl::to_word_or_quoted_string (c->name ()) << " " << tl::to_word_or_quoted_string (temp->name ()) << ")" << endl; - } - } - } - - if (nl->begin_device_abstracts () != nl->end_device_abstracts () && ! Keys::is_short ()) { - *mp_stream << endl << "# Device abstracts section" << endl; - *mp_stream << "# Device abstracts list the pin shapes of the devices." << endl; - } - for (db::Netlist::const_abstract_model_iterator m = nl->begin_device_abstracts (); m != nl->end_device_abstracts (); ++m) { - if (m->device_class ()) { - *mp_stream << Keys::device_key << "(" << tl::to_word_or_quoted_string (m->name ()) << " " << tl::to_word_or_quoted_string (m->device_class ()->name ()) << endl; - write (l2n, *m); - *mp_stream << ")" << endl; - } + stream () << endl << "# Reference netlist" << endl; } + stream () << Keys::reference_key << "(" << endl; + l2n_std_format::std_writer_impl::write (lvs->reference_netlist (), 0, true, &m_net2id_per_circuit_b); + stream () << ")" << endl; if (! Keys::is_short ()) { - *mp_stream << endl << "# Circuit section" << endl; - *mp_stream << "# Circuits are the hierarchical building blocks of the netlist." << endl; + stream () << endl << "# Cross reference" << endl; } - for (db::Netlist::const_bottom_up_circuit_iterator i = nl->begin_bottom_up (); i != nl->end_bottom_up (); ++i) { - const db::Circuit *x = *i; - *mp_stream << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (x->name ()) << endl; - write (l2n, *x); - *mp_stream << ")" << endl; + stream () << Keys::xref_key << "(" << endl; + write (lvs->cross_ref ()); + stream () << ")" << endl; + + if (! Keys::is_short ()) { + stream () << endl; } } -template -void std_writer_impl::write (const db::LayoutVsSchematic *l2n, const db::Circuit &circuit) +template +std::string name_to_s (const Obj *obj) { - std::map net2id; - unsigned int id = 0; - - if (circuit.begin_nets () != circuit.end_nets ()) { - if (! Keys::is_short ()) { - *mp_stream << endl << indent1 << "# Nets with their geometries" << endl; - } - for (db::Circuit::const_net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) { - net2id.insert (std::make_pair (n.operator-> (), ++id)); - write (l2n, *n, id); - } - } - - if (circuit.begin_pins () != circuit.end_pins ()) { - if (! Keys::is_short ()) { - *mp_stream << endl << indent1 << "# Outgoing pins and their connections to nets" << endl; - } - for (db::Circuit::const_pin_iterator p = circuit.begin_pins (); p != circuit.end_pins (); ++p) { - const db::Net *net = circuit.net_for_pin (p->id ()); - if (net) { - *mp_stream << indent1 << Keys::pin_key << "(" << tl::to_word_or_quoted_string (p->expanded_name ()) << " " << net2id [net] << ")" << endl; - } - } - } - - if (circuit.begin_devices () != circuit.end_devices ()) { - if (! Keys::is_short ()) { - *mp_stream << endl << indent1 << "# Devices and their connections" << endl; - } - for (db::Circuit::const_device_iterator d = circuit.begin_devices (); d != circuit.end_devices (); ++d) { - write (l2n, *d, net2id); - } - } - - if (circuit.begin_subcircuits () != circuit.end_subcircuits ()) { - if (! Keys::is_short ()) { - *mp_stream << endl << indent1 << "# Subcircuits and their connections" << endl; - } - for (db::Circuit::const_subcircuit_iterator x = circuit.begin_subcircuits (); x != circuit.end_subcircuits (); ++x) { - write (l2n, *x, net2id); - } - } - - if (! Keys::is_short ()) { - *mp_stream << endl; - } -} - -void write_point (tl::OutputStream &stream, const db::Point &pt, db::Point &ref, bool relative) -{ - if (relative) { - - stream << "("; - stream << pt.x () - ref.x (); - stream << " "; - stream << pt.y () - ref.y (); - stream << ")"; - + if (obj) { + return tl::to_word_or_quoted_string (obj->name ()); } else { - - if (pt.x () == 0 || pt.x () != ref.x ()) { - stream << pt.x (); - } else { - stream << "*"; - } - - if (pt.y () == 0 || pt.y () != ref.y ()) { - stream << pt.y (); - } else { - stream << "*"; - } - - } - - ref = pt; -} - -template -void write_points (tl::OutputStream &stream, const T &poly, const Tr &tr, db::Point &ref, bool relative) -{ - for (typename T::polygon_contour_iterator c = poly.begin_hull (); c != poly.end_hull (); ++c) { - - typename T::point_type pt = tr * *c; - - stream << " "; - write_point (stream, pt, ref, relative); - + return "()"; } } -template -void std_writer_impl::reset_geometry_ref () +template +std::string expanded_name_to_s (const Obj *obj) { - m_ref = db::Point (); -} - -template -void std_writer_impl::write (const db::PolygonRef *s, const db::ICplxTrans &tr, const std::string &lname, bool relative) -{ - db::ICplxTrans t = tr * db::ICplxTrans (s->trans ()); - - const db::Polygon &poly = s->obj (); - if (poly.is_box ()) { - - db::Box box = t * poly.box (); - *mp_stream << Keys::rect_key << "(" << lname; - *mp_stream << " "; - write_point (*mp_stream, box.p1 (), m_ref, relative); - *mp_stream << " "; - write_point (*mp_stream, box.p2 (), m_ref, relative); - *mp_stream << ")"; - + if (obj) { + return tl::to_word_or_quoted_string (obj->expanded_name ()); } else { - - *mp_stream << Keys::polygon_key << "(" << lname; - if (poly.holes () > 0) { - db::SimplePolygon sp (poly); - write_points (*mp_stream, sp, t, m_ref, relative); - } else { - write_points (*mp_stream, poly, t, m_ref, relative); - } - *mp_stream << ")"; - + return "()"; } } -template -void std_writer_impl::write (const db::LayoutVsSchematic *l2n, const db::Net &net, unsigned int id) +std::string net_id_to_s (const db::Net *net, const std::map &net2id) { - if (! l2n->netlist ()) { - throw tl::Exception (tl::to_string (tr ("Can't write annotated netlist before extraction has been done"))); - } - - const db::hier_clusters &clusters = l2n->net_clusters (); - const db::Circuit *circuit = net.circuit (); - const db::Connectivity &conn = l2n->connectivity (); - - bool any = false; - - reset_geometry_ref (); - - for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) { - - db::cell_index_type cci = circuit->cell_index (); - db::cell_index_type prev_ci = cci; - - for (db::recursive_cluster_shape_iterator si (clusters, *l, cci, net.cluster_id ()); ! si.at_end (); ) { - - // NOTE: we don't recursive into circuits which will later be output. However, as circuits may - // vanish in "purge" but the clusters will still be there we need to recursive into clusters from - // unknown cells. - db::cell_index_type ci = si.cell_index (); - if (ci != prev_ci && ci != cci && (l2n->netlist ()->circuit_by_cell_index (ci) || l2n->netlist ()->device_abstract_by_cell_index (ci))) { - - si.skip_cell (); - - } else { - - if (! any) { - *mp_stream << indent1 << Keys::net_key << "(" << id; - if (! net.name ().empty ()) { - *mp_stream << " " << Keys::name_key << "(" << tl::to_word_or_quoted_string (net.name ()) << ")"; - } - *mp_stream << endl; - any = true; - } - - *mp_stream << indent2; - write (si.operator-> (), si.trans (), name_for_layer (l2n, *l), true); - *mp_stream << endl; - - prev_ci = ci; - - ++si; - - } - - } - - } - - if (any) { - *mp_stream << indent1 << ")" << endl; + if (net) { + std::map::const_iterator i = net2id.find (net); + tl_assert (i != net2id.end ()); + return tl::to_string (i->second); } else { - - *mp_stream << indent1 << Keys::net_key << "(" << id; - if (! net.name ().empty ()) { - *mp_stream << " " << Keys::name_key << "(" << tl::to_word_or_quoted_string (net.name ()) << ")"; - } - *mp_stream << ")" << endl; - + return "()"; } } template -void std_writer_impl::write (const db::LayoutVsSchematic *l2n, const db::SubCircuit &subcircuit, std::map &net2id) +std::string std_writer_impl::status_to_s (const db::NetlistCrossReference::Status status) { - const db::Layout *ly = l2n->internal_layout (); - double dbu = ly->dbu (); - - *mp_stream << indent1 << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (subcircuit.expanded_name ()); - *mp_stream << " " << tl::to_word_or_quoted_string (subcircuit.circuit_ref ()->name ()); - - const db::DCplxTrans &tr = subcircuit.trans (); - if (tr.is_mag ()) { - *mp_stream << " " << Keys::scale_key << "(" << tr.mag () << ")"; - } - if (tr.is_mirror ()) { - *mp_stream << " " << Keys::mirror_key; - } - if (fabs (tr.angle ()) > 1e-6) { - *mp_stream << " " << Keys::rotation_key << "(" << tr.angle () << ")"; - } - *mp_stream << " " << Keys::location_key << "(" << tr.disp ().x () / dbu << " " << tr.disp ().y () / dbu << ")"; - - // each pin in one line for more than a few pins - bool separate_lines = (subcircuit.circuit_ref ()->pin_count () > 1); - - if (separate_lines) { - *mp_stream << endl; - } - - for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) { - const db::Net *net = subcircuit.net_for_pin (p->id ()); - if (net) { - if (separate_lines) { - *mp_stream << indent2; - } else { - *mp_stream << " "; - } - *mp_stream << Keys::pin_key << "(" << tl::to_word_or_quoted_string (p->expanded_name ()) << " " << net2id [net] << ")"; - if (separate_lines) { - *mp_stream << endl; - } - } - } - - if (separate_lines) { - *mp_stream << indent1; - } - - *mp_stream << ")" << endl; -} - -template -void std_writer_impl::write (const db::LayoutVsSchematic *l2n, const db::DeviceAbstract &device_abstract) -{ - const std::vector &td = device_abstract.device_class ()->terminal_definitions (); - - const db::hier_clusters &clusters = l2n->net_clusters (); - const db::Connectivity &conn = l2n->connectivity (); - - for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { - - *mp_stream << indent1 << Keys::terminal_key << "(" << t->name () << endl; - - reset_geometry_ref (); - - for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) { - - const db::local_cluster &lc = clusters.clusters_per_cell (device_abstract.cell_index ()).cluster_by_id (device_abstract.cluster_id_for_terminal (t->id ())); - for (db::local_cluster::shape_iterator s = lc.begin (*l); ! s.at_end (); ++s) { - - *mp_stream << indent2; - write (s.operator-> (), db::ICplxTrans (), name_for_layer (l2n, *l), true); - *mp_stream << endl; - - } - - } - - *mp_stream << indent1 << ")" << endl; - + if (status == db::NetlistCrossReference::Match) { + return " " + Keys::match_key; + } else if (status == db::NetlistCrossReference::NoMatch) { + return " " + Keys::nomatch_key; + } else if (status == db::NetlistCrossReference::Mismatch) { + return " " + Keys::mismatch_key; + } else if (status == db::NetlistCrossReference::MatchWithWarning) { + return " " + Keys::warning_key; + } else if (status == db::NetlistCrossReference::Skipped) { + return " " + Keys::skipped_key; + } else { + return std::string (); } } template -void std_writer_impl::write (const db::LayoutVsSchematic *l2n, const db::Device &device, std::map &net2id) +void std_writer_impl::write (const db::NetlistCrossReference *xref) { - const db::Layout *ly = l2n->internal_layout (); - double dbu = ly->dbu (); - db::VCplxTrans dbu_inv (1.0 / dbu); + for (db::NetlistCrossReference::circuits_iterator c = xref->begin_circuits (); c != xref->end_circuits (); ++c) { - tl_assert (device.device_class () != 0); - const std::vector &td = device.device_class ()->terminal_definitions (); - const std::vector &pd = device.device_class ()->parameter_definitions (); + const db::NetlistCrossReference::PerCircuitData *pcd = xref->per_circuit_data_for (*c); + tl_assert (pcd != 0); - *mp_stream << indent1 << Keys::device_key << "(" << tl::to_word_or_quoted_string (device.expanded_name ()); + stream () << indent1 << Keys::circuit_key << "(" << name_to_s (c->first) << " " << name_to_s (c->second) << status_to_s (pcd->status) << endl; + stream () << indent2 << Keys::xref_key << endl; - tl_assert (device.device_abstract () != 0); - *mp_stream << " " << tl::to_word_or_quoted_string (device.device_abstract ()->name ()) << endl; - - const std::vector &other_abstracts = device.other_abstracts (); - for (std::vector::const_iterator a = other_abstracts.begin (); a != other_abstracts.end (); ++a) { - - db::Vector pos = dbu_inv * a->offset; - - *mp_stream << " " << Keys::device_key << "(" << tl::to_word_or_quoted_string (a->device_abstract->name ()) << " " << pos.x () << " " << pos.y () << ")" << endl; - - } - - const std::map > &reconnected_terminals = device.reconnected_terminals (); - for (std::map >::const_iterator t = reconnected_terminals.begin (); t != reconnected_terminals.end (); ++t) { - - for (std::vector::const_iterator c = t->second.begin (); c != t->second.end (); ++c) { - *mp_stream << " " << Keys::connect_key << "(" << c->device_index << " " << tl::to_word_or_quoted_string (td [t->first].name ()) << " " << tl::to_word_or_quoted_string (td [c->other_terminal_id].name ()) << ")" << endl; + for (db::NetlistCrossReference::PerCircuitData::net_pairs_const_iterator n = pcd->nets.begin (); n != pcd->nets.end (); ++n) { + stream () << indent1 << indent2 << Keys::net_key << "(" << net_id_to_s (n->pair.first, m_net2id_per_circuit_a [c->first]) << " " << net_id_to_s (n->pair.second, m_net2id_per_circuit_b [c->second]) << status_to_s (n->status) << ")" << endl; } - } - - db::Point pos = dbu_inv * device.position (); - - *mp_stream << indent2 << Keys::location_key << "(" << pos.x () << " " << pos.y () << ")" << endl; - - for (std::vector::const_iterator i = pd.begin (); i != pd.end (); ++i) { - *mp_stream << indent2 << Keys::param_key << "(" << tl::to_word_or_quoted_string (i->name ()) << " " << device.parameter_value (i->id ()) << ")" << endl; - } - - for (std::vector::const_iterator i = td.begin (); i != td.end (); ++i) { - const db::Net *net = device.net_for_terminal (i->id ()); - if (net) { - *mp_stream << indent2 << Keys::terminal_key << "(" << tl::to_word_or_quoted_string (i->name ()) << " " << net2id [net] << ")" << endl; + for (db::NetlistCrossReference::PerCircuitData::pin_pairs_const_iterator n = pcd->pins.begin (); n != pcd->pins.end (); ++n) { + stream () << indent1 << indent2 << Keys::pin_key << "(" << expanded_name_to_s (n->pair.first) << " " << expanded_name_to_s (n->pair.second) << status_to_s (n->status) << ")" << endl; } - } - *mp_stream << indent1 << ")" << endl; + for (db::NetlistCrossReference::PerCircuitData::device_pairs_const_iterator n = pcd->devices.begin (); n != pcd->devices.end (); ++n) { + stream () << indent1 << indent2 << Keys::device_key << "(" << expanded_name_to_s (n->pair.first) << " " << expanded_name_to_s (n->pair.second) << status_to_s (n->status) << ")" << endl; + } + + for (db::NetlistCrossReference::PerCircuitData::subcircuit_pairs_const_iterator n = pcd->subcircuits.begin (); n != pcd->subcircuits.end (); ++n) { + stream () << indent1 << indent2 << Keys::circuit_key << "(" << expanded_name_to_s (n->pair.first) << " " << expanded_name_to_s (n->pair.second) << status_to_s (n->status) << ")" << endl; + } + + stream () << indent2 << ")" << endl; + stream () << indent1 << ")" << endl; + + } } } -#endif // ------------------------------------------------------------------------------------------- // LayoutVsSchematicStandardWriter implementation @@ -549,17 +220,15 @@ LayoutVsSchematicStandardWriter::LayoutVsSchematicStandardWriter (tl::OutputStre // .. nothing yet .. } -void LayoutVsSchematicStandardWriter::do_write (const db::LayoutVsSchematic * /*lvs*/) +void LayoutVsSchematicStandardWriter::do_write_lvs (const db::LayoutVsSchematic *lvs) { -#if 0 if (m_short_version) { - l2n_std_format::std_writer_impl > writer (*mp_stream); - writer.write (l2n); + lvs_std_format::std_writer_impl > writer (*mp_stream); + writer.write (lvs); } else { - l2n_std_format::std_writer_impl > writer (*mp_stream); - writer.write (l2n); + lvs_std_format::std_writer_impl > writer (*mp_stream); + writer.write (lvs); } -#endif } } diff --git a/src/db/db/dbLayoutVsSchematicWriter.h b/src/db/db/dbLayoutVsSchematicWriter.h index 4f4d01485..e7b6e0810 100644 --- a/src/db/db/dbLayoutVsSchematicWriter.h +++ b/src/db/db/dbLayoutVsSchematicWriter.h @@ -24,12 +24,16 @@ #define HDR_dbLayoutVsSchematicWriter #include "dbCommon.h" +#include "dbLayoutToNetlistWriter.h" #include "tlStream.h" namespace db { +class Circuit; +class Net; class LayoutVsSchematic; +class NetlistCrossReference; /** * @brief The base class for a LayoutVsSchematic writer @@ -43,7 +47,7 @@ public: void write (const db::LayoutVsSchematic *lvs); protected: - virtual void do_write (const db::LayoutVsSchematic *lvs) = 0; + virtual void do_write_lvs (const db::LayoutVsSchematic *lvs) = 0; private: std::string m_filename; @@ -59,7 +63,7 @@ public: LayoutVsSchematicStandardWriter (tl::OutputStream &stream, bool short_version); protected: - void do_write (const db::LayoutVsSchematic *lvs); + void do_write_lvs (const db::LayoutVsSchematic *lvs); private: tl::OutputStream *mp_stream;