diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index 8b039bc75..dbffb95e9 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -402,11 +402,14 @@ static size_t s_instance_count = 0; static unsigned int init_layer (db::Layout &layout, const db::RecursiveShapeIterator &si) { unsigned int layer_index = layout.insert_layer (); - unsigned int iter_layer = si.multiple_layers () ? si.layers ().front () : si.layer (); - if (si.layout () && iter_layer < si.layout ()->layers ()) { + if (si.layout ()) { // try to preserve the layer properties - layout.set_properties (layer_index, si.layout ()->get_properties (iter_layer)); + if (! si.multiple_layers ()) { + layout.set_properties (layer_index, si.layout ()->get_properties (si.layer ())); + } else if (! si.layers ().empty ()) { + layout.set_properties (layer_index, si.layout ()->get_properties (si.layers ().front ())); + } } return layer_index; diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 461dfc01c..6d2daab9a 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -32,6 +32,7 @@ #include "dbLayoutVsSchematic.h" #include "dbLayoutToNetlistFormatDefs.h" #include "dbLayoutVsSchematicFormatDefs.h" +#include "dbShapeProcessor.h" #include "tlGlobPattern.h" namespace db @@ -1301,6 +1302,93 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Poin } } +namespace +{ + +class PolygonAreaAndPerimeterCollector + : public db::PolygonSink +{ +public: + typedef db::Polygon polygon_type; + typedef polygon_type::perimeter_type perimeter_type; + typedef polygon_type::area_type area_type; + + PolygonAreaAndPerimeterCollector () + : m_area (0), m_perimeter (0) + { } + + area_type area () const + { + return m_area; + } + + perimeter_type perimeter () const + { + return m_perimeter; + } + + virtual void put (const db::Polygon &poly) + { + m_area += poly.area (); + m_perimeter += poly.perimeter (); + } + +public: + area_type m_area; + perimeter_type m_perimeter; +}; + +} + +static void +compute_area_and_perimeter_of_net_shapes (const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Polygon::area_type &area, db::Polygon::perimeter_type &perimeter) +{ + db::EdgeProcessor ep; + + // count vertices and reserve space + size_t n = 0; + for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) { + n += rci->polygon_ref ().vertices (); + } + ep.reserve (n); + + size_t p = 0; + for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) { + ep.insert (rci.trans () * rci->polygon_ref (), ++p); + } + + PolygonAreaAndPerimeterCollector ap_collector; + db::PolygonGenerator pg (ap_collector, false); + db::SimpleMerge op; + ep.process (pg, op); + + area = ap_collector.area (); + perimeter = ap_collector.perimeter (); +} + +static void +get_merged_shapes_of_net (const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Shapes &shapes) +{ + db::EdgeProcessor ep; + + // count vertices and reserve space + size_t n = 0; + for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) { + n += rci->polygon_ref ().vertices (); + } + ep.reserve (n); + + size_t p = 0; + for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) { + ep.insert (rci.trans () * rci->polygon_ref (), ++p); + } + + db::ShapeGenerator sg (shapes); + db::PolygonGenerator pg (sg, false); + db::SimpleMerge op; + ep.process (pg, op); +} + db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector > &diodes) { // TODO: that's basically too much .. we only need the clusters @@ -1326,25 +1414,30 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a continue; } - db::Region rgate, rmetal; + db::Polygon::area_type agate_int = 0; + db::Polygon::perimeter_type pgate_int = 0; - deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (gate), db::ICplxTrans (), rgate, 0); - deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (metal), db::ICplxTrans (), rmetal, 0); + compute_area_and_perimeter_of_net_shapes (m_net_clusters, *cid, *c, layer_of (gate), agate_int, pgate_int); + + db::Polygon::area_type ametal_int = 0; + db::Polygon::perimeter_type pmetal_int = 0; + + compute_area_and_perimeter_of_net_shapes (m_net_clusters, *cid, *c, layer_of (metal), ametal_int, pmetal_int); double agate = 0.0; if (fabs (gate_area_factor) > 1e-6) { - agate += rgate.area () * dbu * dbu * gate_area_factor; + agate += agate_int * dbu * dbu * gate_area_factor; } if (fabs (gate_perimeter_factor) > 1e-6) { - agate += rgate.perimeter () * dbu * gate_perimeter_factor; + agate += pgate_int * dbu * gate_perimeter_factor; } double ametal = 0.0; if (fabs (metal_area_factor) > 1e-6) { - ametal += rmetal.area () * dbu * dbu * metal_area_factor; + ametal += ametal_int * dbu * dbu * metal_area_factor; } if (fabs (metal_perimeter_factor) > 1e-6) { - ametal += rmetal.perimeter () * dbu * metal_perimeter_factor; + ametal += pmetal_int * dbu * metal_perimeter_factor; } double r = ratio; @@ -1352,15 +1445,17 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a for (std::vector >::const_iterator d = diodes.begin (); d != diodes.end () && ! skip; ++d) { - db::Region rdiode; - deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (*d->first), db::ICplxTrans (), rdiode, 0); + db::Polygon::area_type adiode_int = 0; + db::Polygon::perimeter_type pdiode_int = 0; + + compute_area_and_perimeter_of_net_shapes (m_net_clusters, *cid, *c, layer_of (*d->first), adiode_int, pdiode_int); if (fabs (d->second) < db::epsilon) { - if (rdiode.area () > 0) { + if (adiode_int > 0) { skip = true; } } else { - r += rdiode.area () * dbu * dbu * d->second; + r += adiode_int * dbu * dbu * d->second; } } @@ -1373,9 +1468,7 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a if (agate > dbu * dbu && ametal / agate > r + db::epsilon) { db::Shapes &shapes = ly.cell (*cid).shapes (dl.layer ()); - for (db::Region::const_iterator r = rmetal.begin_merged (); ! r.at_end (); ++r) { - shapes.insert (*r); - } + get_merged_shapes_of_net (m_net_clusters, *cid, *c, layer_of (metal), shapes); } }