Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/db/db/dbCircuit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -407,14 +407,16 @@ void Circuit::join_nets (Net *net, Net *with)
subcircuit->connect_pin (with->begin_subcircuit_pins ()->pin_id (), net);
}

while (with->begin_pins () != with->end_pins ()) {
join_pin_with_net (with->begin_pins ()->pin_id (), net);
}

if (netlist ()->callbacks ()) {
netlist ()->callbacks ()->link_nets (net, with);
}

// NOTE: this needs to happen after the callback was called because further up in the
// hierarchy we want the clusters to be joined already
while (with->begin_pins () != with->end_pins ()) {
join_pin_with_net (with->begin_pins ()->pin_id (), net);
}

// create a new name for the joined net
net->set_name (join_names (net->name (), with->name ()));

Expand Down
82 changes: 81 additions & 1 deletion src/db/db/dbHierNetworkProcessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1577,6 +1577,66 @@ connected_clusters<T>::add_connection (typename local_cluster<T>::id_type id, co
m_rev_connections [inst] = id;
}

template <class T>
void
connected_clusters<T>::rename_connection (const ClusterInstance &inst, typename local_cluster<T>::id_type to_id)
{
if (inst.id () == to_id) {
return; // nothing to do
}

ClusterInstance new_inst (to_id, inst);

auto rc = m_rev_connections.find (inst);
if (rc == m_rev_connections.end ()) {
return; // TODO: assert?
}

auto id = rc->second;
m_rev_connections.erase (rc);

auto &connections = m_connections [id];

auto rc_exists = m_rev_connections.find (new_inst);
if (rc_exists != m_rev_connections.end ()) {

// NOTE: possibly a different connection to the new cluster already exists (i.e.
// rc_exists->second != id).
// This may mean we are connecting two clusters here on parent level. In the netlist, this
// is reflected by having multiple upward pins. Right now, we cannot reflect this case
// in the reverse connection structures and keep the existing one only in the reverse
// lookup.

// Remove to original connections downwards
// TODO: this linear search may be slow
for (auto i = connections.begin (), ii = connections.begin (); i != connections.end (); ii = i, ++i) {
if (*i == inst) {
if (ii == i) {
connections.pop_front ();
} else {
connections.erase_after (ii);
}
break;
}
}

} else {

m_rev_connections.insert (std::make_pair (new_inst, id));

// Replace connections downwards
// TODO: this linear search may be slow
for (auto i = connections.begin (); i != connections.end (); ++i) {
if (*i == inst) {
*i = new_inst;
break;
}
}

}

}

template <class T>
void
connected_clusters<T>::join_cluster_with (typename local_cluster<T>::id_type id, typename local_cluster<T>::id_type with_id)
Expand All @@ -1599,11 +1659,31 @@ connected_clusters<T>::join_cluster_with (typename local_cluster<T>::id_type id,
}

connections_type &target = m_connections [id];
target.splice (to_join);

if (target.empty ()) {

target.swap (to_join);

} else if (! to_join.empty ()) {

// Join while removing duplicates
std::set<connections_type::value_type> in_target (target.begin (), target.end ());
for (auto j = to_join.begin (); j != to_join.end (); ++j) {
if (in_target.find (*j) == in_target.end ()) {
target.push_back (*j);
}
}

}

m_connections.erase (tc);

}

if (m_connected_clusters.find (with_id) != m_connected_clusters.end ()) {
m_connected_clusters.insert (id);
m_connected_clusters.erase (with_id);
}
}

template <class T>
Expand Down
11 changes: 11 additions & 0 deletions src/db/db/dbHierNetworkProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,12 @@ class DB_PUBLIC ClusterInstance
// .. nothing yet ..
}

ClusterInstance (size_t id, const db::ClusterInstElement &inst_element)
: ClusterInstElement (inst_element), m_id (id)
{
// .. nothing yet ..
}

ClusterInstance (size_t id)
: ClusterInstElement (), m_id (id)
{
Expand Down Expand Up @@ -1255,6 +1261,11 @@ class DB_PUBLIC_TEMPLATE connected_clusters
*/
void add_connection (typename local_cluster<T>::id_type, const ClusterInstance &inst);

/**
* @brief Changes the cluster ID of the connection
*/
void rename_connection (const ClusterInstance &inst, typename local_cluster<T>::id_type to_id);

/**
* @brief Joins the cluster id with the cluster with_id
*
Expand Down
130 changes: 100 additions & 30 deletions src/db/db/dbLayoutToNetlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,28 @@ void LayoutToNetlist::link_nets (const db::Net *net, const db::Net *with)
{
if (! net->circuit () || net->circuit () != with->circuit () || ! internal_layout ()
|| ! internal_layout ()->is_valid_cell_index (net->circuit ()->cell_index ())
|| net->cluster_id () == 0 || with->cluster_id () == 0) {
|| net->cluster_id () == 0 || with->cluster_id () == 0 || net == with) {
return;
}

connected_clusters<db::NetShape> &clusters = m_net_clusters.clusters_per_cell (net->circuit ()->cell_index ());
clusters.join_cluster_with (net->cluster_id (), with->cluster_id ());

// fix the connections from the parents

const db::Cell &cc = internal_layout ()->cell (net->circuit ()->cell_index ());

for (db::Cell::parent_inst_iterator p = cc.begin_parent_insts (); ! p.at_end (); ++p) {

connected_clusters<db::NetShape> &pclusters = m_net_clusters.clusters_per_cell (p->parent_cell_index ());

db::CellInstArray ci = p->child_inst ().cell_inst ();
for (db::CellInstArray::iterator ia = ci.begin (); ! ia.at_end(); ++ia) {
db::ClusterInstance cli (with->cluster_id (), ci.object ().cell_index (), ci.complex_trans (*ia), p->child_inst ().prop_id ());
pclusters.rename_connection (cli, net->cluster_id ());
}

}
}

size_t LayoutToNetlist::link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &dtrans)
Expand Down Expand Up @@ -1800,40 +1816,91 @@ LayoutToNetlist::compute_area_and_perimeter_of_net_shapes (db::cell_index_type c
}

db::Point
LayoutToNetlist::get_merged_shapes_of_net (db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Shapes &shapes, db::properties_id_type prop_id) const
LayoutToNetlist::get_shapes_of_net (db::cell_index_type ci, size_t cid, const std::vector<unsigned int> &layer_ids, bool merge, size_t max_polygons, db::Shapes &shapes, db::properties_id_type prop_id) const
{
const db::Layout *layout = &dss ().const_layout (m_layout_index);

db::Point ref;
// count vertices and polygons and determine label reference point

size_t n = 0, npoly = 0;
bool any_ref = false;
db::EdgeProcessor ep;
db::Point ref;

// count vertices and reserve space
size_t n = 0;
for (db::recursive_cluster_shape_iterator<db::NetShape> rci (m_net_clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
n += rci->polygon_ref ().vertices ();
}
ep.reserve (n);
for (auto l = layer_ids.begin (); l != layer_ids.end (); ++l) {
for (db::recursive_cluster_shape_iterator<db::NetShape> rci (m_net_clusters, *l, ci, cid); !rci.at_end (); ++rci) {

size_t p = 0;
for (db::recursive_cluster_shape_iterator<db::NetShape> rci (m_net_clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
db::PolygonRef pr = rci->polygon_ref ();
db::PolygonRef::polygon_edge_iterator e = pr.begin_edge ();
if (! e.at_end ()) {
// pick one reference point for the label
auto p1 = (rci.trans () * *e).p1 ();
if (! any_ref || p1 < ref) {
ref = p1;
any_ref = true;
db::PolygonRef pr = rci->polygon_ref ();

n += pr.vertices ();
++npoly;

db::PolygonRef::polygon_edge_iterator e = pr.begin_edge ();
if (! e.at_end ()) {
// pick one reference point for the label
auto p1 = (rci.trans () * *e).p1 ();
if (! any_ref || p1 < ref) {
ref = p1;
any_ref = true;
}
}
ep.insert_with_trans (pr, rci.trans (), ++p);

}
}

db::PolygonRefToShapesGenerator sg (const_cast<db::Layout *> (layout), &shapes, prop_id);
db::PolygonGenerator pg (sg, false);
db::SimpleMerge op;
ep.process (pg, op);
if (n == 0) {

// nothing to do ...

} else if (npoly >= max_polygons) {

db::Box bbox;

for (auto l = layer_ids.begin (); l != layer_ids.end (); ++l) {
for (db::recursive_cluster_shape_iterator<db::NetShape> rci (m_net_clusters, *l, ci, cid); !rci.at_end (); ++rci) {
db::PolygonRef pr = rci->polygon_ref ();
bbox += rci.trans () * pr.box ();
}
}

if (prop_id != 0) {
shapes.insert (db::BoxWithProperties (bbox, prop_id));
} else {
shapes.insert (bbox);
}

} else if (merge) {

db::EdgeProcessor ep;
ep.reserve (n);

size_t p = 0;
for (auto l = layer_ids.begin (); l != layer_ids.end (); ++l) {
for (db::recursive_cluster_shape_iterator<db::NetShape> rci (m_net_clusters, *l, ci, cid); !rci.at_end (); ++rci) {
db::PolygonRef pr = rci->polygon_ref ();
db::PolygonRef::polygon_edge_iterator e = pr.begin_edge ();
if (! e.at_end ()) {
ep.insert_with_trans (pr, rci.trans (), ++p);
}
}
}

db::PolygonRefToShapesGenerator sg (const_cast<db::Layout *> (layout), &shapes, prop_id);
db::PolygonGenerator pg (sg, false);
db::SimpleMerge op;
ep.process (pg, op);

} else {

db::PolygonRefToShapesGenerator sg (const_cast<db::Layout *> (layout), &shapes, prop_id);

for (auto l = layer_ids.begin (); l != layer_ids.end (); ++l) {
for (db::recursive_cluster_shape_iterator<db::NetShape> rci (m_net_clusters, *l, ci, cid); !rci.at_end (); ++rci) {
db::PolygonRef pr = rci->polygon_ref ();
sg.put (pr.instantiate ().transformed (rci.trans ()));
}
}

}

return ref;
}
Expand Down Expand Up @@ -2017,7 +2084,9 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a
prop_id = db::properties_id (ps);
}

db::Point ref = get_merged_shapes_of_net (*cid, *c, layer_of (metal), shapes, prop_id);
std::vector<unsigned int> layers;
layers.push_back (layer_of (metal));
db::Point ref = get_shapes_of_net (*cid, *c, layers, true, std::numeric_limits<size_t>::max (), shapes, prop_id);

if (values) {

Expand Down Expand Up @@ -2074,7 +2143,9 @@ LayoutToNetlist::measure_net (const db::Region &primary, const std::map<std::str
eval.set_var (v->first, v->second);
}

eval.set_primary_layer (layer_of (primary));
unsigned int primary_layer = layer_of (primary);
eval.set_primary_layer (primary_layer);

for (auto s = secondary.begin (); s != secondary.end (); ++s) {
if (s->second) {
eval.set_secondary_layer (s->first, layer_of (*s->second));
Expand All @@ -2088,7 +2159,6 @@ LayoutToNetlist::measure_net (const db::Region &primary, const std::map<std::str
eval.parse (compiled_expr, ex);

db::DeepLayer dl (&dss (), m_layout_index, ly.insert_layer ());
unsigned int primary_layer = layer_of (primary);

for (db::Layout::bottom_up_const_iterator cid = ly.begin_bottom_up (); cid != ly.end_bottom_up (); ++cid) {

Expand All @@ -2113,9 +2183,9 @@ LayoutToNetlist::measure_net (const db::Region &primary, const std::map<std::str
eval.reset (*cid, *c);
compiled_expr.execute ();

if (! eval.skip ()) {
if (! eval.copy_layers ().empty ()) {
db::Shapes &shapes = ly.cell (*cid).shapes (dl.layer ());
get_merged_shapes_of_net (*cid, *c, primary_layer, shapes, db::properties_id (eval.prop_set_out ()));
get_shapes_of_net (*cid, *c, eval.copy_layers (), eval.copy_merge (), eval.copy_max_polygons (), shapes, db::properties_id (eval.prop_set_out ()));
}

} catch (tl::Exception &ex) {
Expand Down
9 changes: 7 additions & 2 deletions src/db/db/dbLayoutToNetlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -1200,9 +1200,14 @@ class DB_PUBLIC LayoutToNetlist
void compute_area_and_perimeter_of_net_shapes (db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Polygon::area_type &area, db::Polygon::perimeter_type &perimeter) const;

/**
* @brief Utility: computes the merged shapes of a net
* @brief Utility: computes the shapes of a net
*
* If 'merged' is true, all polygons will be merged.
*
* If 'max_polygons' is set to a value less that std::numeric_limits<size_t>::max,
* the polygons will be replaced by a bounding box if the number of polygons exceeds the number given by the limit
*/
db::Point get_merged_shapes_of_net (db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Shapes &shapes, db::properties_id_type prop_id) const;
db::Point get_shapes_of_net (db::cell_index_type ci, size_t cid, const std::vector<unsigned int> &layer_ids, bool merged, size_t max_polygons, db::Shapes &shapes, db::properties_id_type prop_id) const;

private:
// no copying
Expand Down
5 changes: 4 additions & 1 deletion src/db/db/dbLayoutToNetlistFormatDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ namespace db
* scale(<mag>) - magnification (default is 1) [short key: S]
*
* [message-entry]:
* message([severity] [message|message-geometry|message-cell|message-category|any]*) - message entry [short key: H]
* message([severity] [message|message-geometry|message-cell|message-category|message-net|any]*) - message entry [short key: H]
*
* [message]:
* description(<name>) - message text [short key: B]
Expand All @@ -199,6 +199,9 @@ namespace db
* [message-cell]:
* cell(<name>) - message cell [short key: C]
*
* [message-net]:
* net(<name>) - message net name [short key: N]
*
* [message-category]:
* cat(<name> <name>?) - message category with optional description [short key: X]
*
Expand Down
Loading
Loading