From 0c6ead6f90de1fdac67c4931871a0dfba03966a5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 9 Jul 2019 01:18:23 +0200 Subject: [PATCH] WIP: introduced boundary into L2N format so we have something to display for abstracts. --- src/db/db/dbCircuit.cc | 25 ++++ src/db/db/dbCircuit.h | 23 ++++ src/db/db/dbHierNetworkProcessor.cc | 2 +- src/db/db/dbLayoutToNetlistFormatDefs.h | 9 ++ src/db/db/dbLayoutToNetlistReader.cc | 50 +++++++- src/db/db/dbLayoutToNetlistReader.h | 2 + src/db/db/dbLayoutToNetlistWriter.cc | 117 +++++++++++------- src/db/db/dbNetlistDeviceExtractor.cc | 4 +- src/db/db/dbNetlistExtractor.cc | 4 +- src/db/db/gsiDeclDbNetlist.cc | 6 + .../laybasic/layNetlistBrowserPage.cc | 21 ++-- 11 files changed, 199 insertions(+), 64 deletions(-) diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index 7a9fe43d0..b410478a5 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -22,6 +22,7 @@ #include "dbCircuit.h" #include "dbNetlist.h" +#include "dbLayout.h" #include @@ -46,6 +47,23 @@ Circuit::Circuit () m_subcircuits.changed ().add (this, &Circuit::subcircuits_changed); } +Circuit::Circuit (const db::Layout &layout, db::cell_index_type ci) + : m_name (layout.cell_name (ci)), m_dont_purge (false), m_cell_index (ci), mp_netlist (0), + m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices), + m_subcircuit_by_id (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits), + m_net_by_cluster_id (this, &Circuit::begin_nets, &Circuit::end_nets), + m_device_by_name (this, &Circuit::begin_devices, &Circuit::end_devices), + m_subcircuit_by_name (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits), + m_net_by_name (this, &Circuit::begin_nets, &Circuit::end_nets), + m_index (0) +{ + m_devices.changed ().add (this, &Circuit::devices_changed); + m_nets.changed ().add (this, &Circuit::nets_changed); + m_subcircuits.changed ().add (this, &Circuit::subcircuits_changed); + + set_boundary (db::DPolygon (db::CplxTrans (layout.dbu ()) * layout.cell (ci).bbox ())); +} + Circuit::Circuit (const Circuit &other) : gsi::ObjectBase (other), tl::Object (other), m_dont_purge (false), m_cell_index (0), mp_netlist (0), m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices), @@ -82,6 +100,7 @@ Circuit &Circuit::operator= (const Circuit &other) clear (); m_name = other.m_name; + m_boundary = other.m_boundary; m_dont_purge = other.m_dont_purge; m_cell_index = other.m_cell_index; m_pins = other.m_pins; @@ -184,6 +203,7 @@ void Circuit::clear () m_devices.clear (); m_nets.clear (); m_subcircuits.clear (); + m_boundary.clear (); } void Circuit::set_name (const std::string &name) @@ -194,6 +214,11 @@ void Circuit::set_name (const std::string &name) } } +void Circuit::set_boundary (const db::DPolygon &boundary) +{ + m_boundary = boundary; +} + void Circuit::set_dont_purge (bool dp) { m_dont_purge = dp; diff --git a/src/db/db/dbCircuit.h b/src/db/db/dbCircuit.h index 6e84784e2..c07d52fc6 100644 --- a/src/db/db/dbCircuit.h +++ b/src/db/db/dbCircuit.h @@ -30,6 +30,7 @@ #include "dbPin.h" #include "dbSubCircuit.h" #include "dbNetlistUtils.h" +#include "dbPolygon.h" #include "tlObject.h" #include "tlObjectCollection.h" @@ -40,6 +41,7 @@ namespace db { class Netlist; +class Layout; /** * @brief An iterator wrapper for the child and parent circuit iterator @@ -113,6 +115,13 @@ public: */ Circuit (); + /** + * @brief Constructor + * + * Creates a circuit corresponding to a layout cell + */ + Circuit (const db::Layout &layout, db::cell_index_type ci); + /** * @brief Copy constructor */ @@ -164,6 +173,19 @@ public: return m_name; } + /** + * @brief Sets the boundary + */ + void set_boundary (const db::DPolygon &boundary); + + /** + * @brief Gets the boundary + */ + const db::DPolygon &boundary () const + { + return m_boundary; + } + /** * @brief Sets or resets the "don't purge" flag * This flag will prevent "purge" from deleting this circuit. It is set by "blank". @@ -697,6 +719,7 @@ private: friend class Device; std::string m_name; + db::DPolygon m_boundary; bool m_dont_purge; db::cell_index_type m_cell_index; net_list m_nets; diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index c14bcaaf8..8ce6411ec 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -2052,7 +2052,7 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c } } - // add dummy clusters for global nets not having any shape on it + // add dummy cluster instance for global nets not having any shape on it for (size_t gn_id = 0; gn_id < conn.global_nets (); ++gn_id) { if (gn_seen.find (gn_id) == gn_seen.end ()) { diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.h b/src/db/db/dbLayoutToNetlistFormatDefs.h index aa54014f1..8d70abcbc 100644 --- a/src/db/db/dbLayoutToNetlistFormatDefs.h +++ b/src/db/db/dbLayoutToNetlistFormatDefs.h @@ -64,6 +64,8 @@ namespace db * * [circuit-def]: * + * [boundary-def] + * * net( [name]? [geometry-def]*) * - net geometry [short key: N] * A net declaration shall be there also if no geometry @@ -75,6 +77,13 @@ namespace db * circuit( [name]? [subcircuit-def]) * - subcircuit with connections [short key: X] * + * [boundary-def]: + * + * polygon([coord] ...) - defines a polygon [short key: Q] + * "*" for or means take previous + * rect([coord] [coord]) - defines a rectangle [short key: R] + * coordinates are bottom/left and top/right + * * [combined-device]: * * device( [trans-def]) diff --git a/src/db/db/dbLayoutToNetlistReader.cc b/src/db/db/dbLayoutToNetlistReader.cc index daf09830e..5cfa6ac49 100644 --- a/src/db/db/dbLayoutToNetlistReader.cc +++ b/src/db/db/dbLayoutToNetlistReader.cc @@ -285,6 +285,8 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo db::cell_index_type device_cell_index = 0; + db::CplxTrans dbu (m_dbu); + if (l2n) { db::Layout *ly = l2n->internal_layout (); @@ -303,7 +305,11 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo while (br) { - if (test (skeys::net_key) || test (lkeys::net_key)) { + if (test (skeys::rect_key) || test (lkeys::rect_key)) { + circuit->set_boundary (db::DPolygon (dbu * read_rect ())); + } else if (test (skeys::polygon_key) || test (lkeys::polygon_key)) { + circuit->set_boundary (read_polygon ().transformed (dbu)); + } else if (test (skeys::net_key) || test (lkeys::net_key)) { read_net (netlist, l2n, circuit, *map); } else if (test (skeys::pin_key) || test (lkeys::pin_key)) { read_pin (netlist, l2n, circuit, *map); @@ -312,9 +318,9 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo } else if (test (skeys::circuit_key) || test (lkeys::circuit_key)) { read_subcircuit (netlist, l2n, circuit, *map, connections); } else if (at_end ()) { - throw tl::Exception (tl::to_string (tr ("Unexpected end of file inside circuit definition (net, pin, device or circuit expected)"))); + throw tl::Exception (tl::to_string (tr ("Unexpected end of file inside circuit definition (rect, polygon, net, pin, device or circuit expected)"))); } else { - throw tl::Exception (tl::to_string (tr ("Invalid keyword inside circuit definition (net, pin, device or circuit expected)"))); + throw tl::Exception (tl::to_string (tr ("Invalid keyword inside circuit definition (rect, polygon, net, pin, device or circuit expected)"))); } } @@ -455,12 +461,46 @@ LayoutToNetlistStandardReader::read_geometry (db::LayoutToNetlist *l2n) return std::make_pair (lid, db::PolygonRef (poly, l2n->internal_layout ()->shape_repository ())); } else if (at_end ()) { - throw tl::Exception (tl::to_string (tr ("Unexpected end of file inside net or terminal definition (polygon or rect expected)"))); + throw tl::Exception (tl::to_string (tr ("Unexpected end of file (polygon or rect expected)"))); } else { - throw tl::Exception (tl::to_string (tr ("Invalid keyword inside net or terminal definition (polygon or rect expected)"))); + throw tl::Exception (tl::to_string (tr ("Invalid keyword (polygon or rect expected)"))); } } +db::Box +LayoutToNetlistStandardReader::read_rect () +{ + m_ref = db::Point (); + + Brace br (this); + + db::Point lb = read_point (); + db::Point rt = read_point (); + db::Box box (lb, rt); + + br.done (); + + return box; +} + +db::Polygon +LayoutToNetlistStandardReader::read_polygon () +{ + m_ref = db::Point (); + + Brace br (this); + + std::vector pt; + while (br) { + pt.push_back (read_point ()); + } + br.done (); + + db::Polygon poly; + poly.assign_hull (pt.begin (), pt.end ()); + return poly; +} + void LayoutToNetlistStandardReader::read_geometries (Brace &br, db::LayoutToNetlist *l2n, db::local_cluster &lc, db::Cell &cell) { diff --git a/src/db/db/dbLayoutToNetlistReader.h b/src/db/db/dbLayoutToNetlistReader.h index f8e3f1731..5d256c84e 100644 --- a/src/db/db/dbLayoutToNetlistReader.h +++ b/src/db/db/dbLayoutToNetlistReader.h @@ -140,6 +140,8 @@ protected: bool read_trans_part (db::DCplxTrans &tr); void read_abstract_terminal (db::LayoutToNetlist *l2n, db::DeviceAbstract *dm, db::DeviceClass *dc); std::pair read_geometry (db::LayoutToNetlist *l2n); + db::Polygon read_polygon (); + db::Box read_rect (); void read_geometries (Brace &br, db::LayoutToNetlist *l2n, db::local_cluster &lc, db::Cell &cell); db::Point read_point (); diff --git a/src/db/db/dbLayoutToNetlistWriter.cc b/src/db/db/dbLayoutToNetlistWriter.cc index 9357e0a34..b36eaf9ba 100644 --- a/src/db/db/dbLayoutToNetlistWriter.cc +++ b/src/db/db/dbLayoutToNetlistWriter.cc @@ -200,9 +200,84 @@ void std_writer_impl::write (const db::Netlist *nl, const db::LayoutToNetl } } +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 << ")"; + + } 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); + + } +} + template void std_writer_impl::write (const db::Netlist *netlist, const db::LayoutToNetlist *l2n, const db::Circuit &circuit, const std::string &indent, std::map > *net2id_per_circuit) { + if (circuit.boundary ().vertices () > 0) { + + if (! Keys::is_short ()) { + *mp_stream << endl << indent << indent1 << "# Circuit boundary" << endl; + } + + reset_geometry_ref (); + + db::Polygon poly = circuit.boundary ().transformed (db::VCplxTrans (1.0 / m_dbu)); + if (poly.is_box ()) { + + db::Box box = poly.box (); + *mp_stream << indent << indent1 << Keys::rect_key << "("; + write_point (*mp_stream, box.p1 (), m_ref, true); + *mp_stream << " "; + write_point (*mp_stream, box.p2 (), m_ref, true); + *mp_stream << ")" << endl; + + } else { + + *mp_stream << indent << indent1 << Keys::polygon_key << "("; + if (poly.holes () > 0) { + db::SimplePolygon sp = db::polygon_to_simple_polygon (poly); + write_points (*mp_stream, sp, db::UnitTrans (), m_ref, true); + } else { + write_points (*mp_stream, poly, db::UnitTrans (), m_ref, true); + } + *mp_stream << ")" << endl; + + } + + } + std::map net2id_local; std::map *net2id = &net2id_local; if (net2id_per_circuit) { @@ -274,48 +349,6 @@ void std_writer_impl::write (const db::Netlist *netlist, const db::LayoutT } } -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 << ")"; - - } 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); - - } -} - template void std_writer_impl::reset_geometry_ref () { diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index 9714fe5b2..77df10bd1 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -279,9 +279,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db: } else { // create a new circuit for this cell - mp_circuit = new db::Circuit (); - mp_circuit->set_cell_index (*ci); - mp_circuit->set_name (layout.cell_name (*ci)); + mp_circuit = new db::Circuit (layout, *ci); m_netlist->add_circuit (mp_circuit); } diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 115580c83..8231a1c0f 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -117,10 +117,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo std::map::const_iterator k = circuits.find (*cid); if (k == circuits.end ()) { - circuit = new db::Circuit (); + circuit = new db::Circuit (*mp_layout, *cid); nl.add_circuit (circuit); - circuit->set_name (mp_layout->cell_name (*cid)); - circuit->set_cell_index (*cid); circuits.insert (std::make_pair (*cid, circuit)); } else { circuit = k->second; diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 745573e42..911262002 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1191,6 +1191,12 @@ Class decl_dbCircuit ("db", "Circuit", gsi::method ("name", &db::Circuit::name, "@brief Gets the name of the circuit" ) + + gsi::method ("boundary=", &db::Circuit::set_boundary, gsi::arg ("boundary"), + "@brief Sets the boundary of the circuit" + ) + + gsi::method ("boundary", &db::Circuit::boundary, + "@brief Gets the boundary of the circuit" + ) + gsi::method ("dont_purge", &db::Circuit::dont_purge, "@brief Gets a value indicating whether the circuit can be purged on \\Netlist#purge.\n" ) + diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index 203245fb3..b55527db1 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -876,25 +876,26 @@ bbox_for_device_abstract (const db::Layout *layout, const db::DeviceAbstract *de return layout->cell (device_abstract->cell_index ()).bbox ().transformed (db::CplxTrans (layout->dbu ()).inverted () * trans * db::CplxTrans (layout->dbu ()));} static db::Box -bbox_for_subcircuit (const db::Layout *layout, const db::SubCircuit *subcircuit) +bbox_for_circuit (const db::Layout *layout, const db::Circuit *circuit) { - if (! subcircuit->circuit_ref () || ! layout->is_valid_cell_index (subcircuit->circuit_ref ()->cell_index ())) { + + if (! circuit || ! layout->is_valid_cell_index (circuit->cell_index ())) { return db::Box (); } - return layout->cell (subcircuit->circuit_ref ()->cell_index ()).bbox (); -} - -static db::Box -bbox_for_circuit (const db::Layout *layout, const db::Circuit *circuit) -{ - if (! layout->is_valid_cell_index (circuit->cell_index ())) { - return db::Box (); + if (circuit->boundary ().vertices () > 0) { + return db::CplxTrans (layout->dbu ()).inverted () * circuit->boundary ().box (); } return layout->cell (circuit->cell_index ()).bbox (); } +static db::Box +bbox_for_subcircuit (const db::Layout *layout, const db::SubCircuit *subcircuit) +{ + return bbox_for_circuit (layout, subcircuit->circuit_ref ()); +} + void NetlistBrowserPage::adjust_view () {