WIP: introduced boundary into L2N format so we have something to display for abstracts.

This commit is contained in:
Matthias Koefferlein 2019-07-09 01:18:23 +02:00
parent c9e08c4500
commit 0c6ead6f90
11 changed files with 199 additions and 64 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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 ()) {

View File

@ -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])

View File

@ -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)
{

View File

@ -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 ();

View File

@ -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 ()
{

View File

@ -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);
}

View File

@ -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;

View File

@ -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"
) +

View File

@ -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 ()
{