mirror of https://github.com/KLayout/klayout.git
WIP: introduced boundary into L2N format so we have something to display for abstracts.
This commit is contained in:
parent
c9e08c4500
commit
0c6ead6f90
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "dbCircuit.h"
|
||||
#include "dbNetlist.h"
|
||||
#include "dbLayout.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -2052,7 +2052,7 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &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 ()) {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ namespace db
|
|||
*
|
||||
* [circuit-def]:
|
||||
*
|
||||
* [boundary-def]
|
||||
*
|
||||
* net(<id> [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(<id> [name]? [subcircuit-def])
|
||||
* - subcircuit with connections [short key: X]
|
||||
*
|
||||
* [boundary-def]:
|
||||
*
|
||||
* polygon([coord] ...) - defines a polygon [short key: Q]
|
||||
* "*" for <x> or <y> means take previous
|
||||
* rect([coord] [coord]) - defines a rectangle [short key: R]
|
||||
* coordinates are bottom/left and top/right
|
||||
*
|
||||
* [combined-device]:
|
||||
*
|
||||
* device(<abstract> [trans-def])
|
||||
|
|
|
|||
|
|
@ -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<db::Point> 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<db::PolygonRef> &lc, db::Cell &cell)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<unsigned int, db::PolygonRef> read_geometry (db::LayoutToNetlist *l2n);
|
||||
db::Polygon read_polygon ();
|
||||
db::Box read_rect ();
|
||||
void read_geometries (Brace &br, db::LayoutToNetlist *l2n, db::local_cluster<db::PolygonRef> &lc, db::Cell &cell);
|
||||
db::Point read_point ();
|
||||
|
||||
|
|
|
|||
|
|
@ -200,9 +200,84 @@ void std_writer_impl<Keys>::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 <class T, class Tr>
|
||||
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 <class Keys>
|
||||
void std_writer_impl<Keys>::write (const db::Netlist *netlist, const db::LayoutToNetlist *l2n, const db::Circuit &circuit, const std::string &indent, std::map<const db::Circuit *, std::map<const db::Net *, unsigned int> > *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<const db::Net *, unsigned int> net2id_local;
|
||||
std::map<const db::Net *, unsigned int> *net2id = &net2id_local;
|
||||
if (net2id_per_circuit) {
|
||||
|
|
@ -274,48 +349,6 @@ void std_writer_impl<Keys>::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 <class T, class Tr>
|
||||
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 <class Keys>
|
||||
void std_writer_impl<Keys>::reset_geometry_ref ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,10 +117,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
|||
|
||||
std::map<db::cell_index_type, db::Circuit *>::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;
|
||||
|
|
|
|||
|
|
@ -1191,6 +1191,12 @@ Class<db::Circuit> 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"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue