mirror of https://github.com/KLayout/klayout.git
WIP: provide a less memory intensive way to deliver shapes from nets.
This commit is contained in:
parent
e439d50111
commit
ad6d9b5715
|
|
@ -219,35 +219,69 @@ static void deliver_shape (const db::PolygonRef &pr, db::Region ®ion, const T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Tr>
|
||||||
|
static void deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr)
|
||||||
|
{
|
||||||
|
if (pr.obj ().is_box ()) {
|
||||||
|
shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
|
||||||
|
} else {
|
||||||
|
db::Layout *layout = shapes.layout ();
|
||||||
|
if (layout) {
|
||||||
|
shapes.insert (db::PolygonRef (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ()));
|
||||||
|
} else {
|
||||||
|
shapes.insert (pr.obj ().transformed (pr.trans ()).transformed (tr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class To>
|
||||||
|
static void deliver_shapes_of_net_recursive (const db::NetlistExtractor &netex, const db::Net &net, unsigned int layer_id, To &to)
|
||||||
|
{
|
||||||
|
const db::Circuit *circuit = net.circuit ();
|
||||||
|
tl_assert (circuit != 0);
|
||||||
|
|
||||||
|
db::cell_index_type ci = circuit->cell_index ();
|
||||||
|
|
||||||
|
for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (netex.clusters (), layer_id, ci, net.cluster_id ()); !rci.at_end (); ++rci) {
|
||||||
|
deliver_shape (*rci, to, rci.trans ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class To>
|
||||||
|
static void deliver_shapes_of_net_nonrecursive (const db::NetlistExtractor &netex, const db::Net &net, unsigned int layer_id, To &to)
|
||||||
|
{
|
||||||
|
const db::Circuit *circuit = net.circuit ();
|
||||||
|
tl_assert (circuit != 0);
|
||||||
|
|
||||||
|
db::cell_index_type ci = circuit->cell_index ();
|
||||||
|
|
||||||
|
const db::local_cluster<db::PolygonRef> &lc = netex.clusters ().clusters_per_cell (ci).cluster_by_id (net.cluster_id ());
|
||||||
|
|
||||||
|
for (db::local_cluster<db::PolygonRef>::shape_iterator s = lc.begin (layer_id); !s.at_end (); ++s) {
|
||||||
|
deliver_shape (*s, to, db::UnitTrans ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const
|
||||||
|
{
|
||||||
|
unsigned int lid = layer_of (of_layer);
|
||||||
|
|
||||||
|
if (! recursive) {
|
||||||
|
deliver_shapes_of_net_nonrecursive (m_netex, net, lid, to);
|
||||||
|
} else {
|
||||||
|
deliver_shapes_of_net_recursive (m_netex, net, lid, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const
|
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const
|
||||||
{
|
{
|
||||||
unsigned int lid = layer_of (of_layer);
|
unsigned int lid = layer_of (of_layer);
|
||||||
std::auto_ptr<db::Region> res (new db::Region ());
|
std::auto_ptr<db::Region> res (new db::Region ());
|
||||||
|
|
||||||
if (! recursive) {
|
if (! recursive) {
|
||||||
|
deliver_shapes_of_net_nonrecursive (m_netex, net, lid, *res);
|
||||||
const db::Circuit *circuit = net.circuit ();
|
|
||||||
tl_assert (circuit != 0);
|
|
||||||
|
|
||||||
db::cell_index_type ci = circuit->cell_index ();
|
|
||||||
|
|
||||||
const db::local_cluster<db::PolygonRef> &lc = m_netex.clusters ().clusters_per_cell (ci).cluster_by_id (net.cluster_id ());
|
|
||||||
|
|
||||||
for (db::local_cluster<db::PolygonRef>::shape_iterator s = lc.begin (lid); !s.at_end (); ++s) {
|
|
||||||
deliver_shape (*s, *res, db::UnitTrans ());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
deliver_shapes_of_net_recursive (m_netex, net, lid, *res);
|
||||||
const db::Circuit *circuit = net.circuit ();
|
|
||||||
tl_assert (circuit != 0);
|
|
||||||
|
|
||||||
db::cell_index_type ci = circuit->cell_index ();
|
|
||||||
|
|
||||||
for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (m_netex.clusters (), lid, ci, net.cluster_id ()); !rci.at_end (); ++rci) {
|
|
||||||
deliver_shape (*rci, *res, rci.trans ());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.release ();
|
return res.release ();
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,17 @@ public:
|
||||||
*/
|
*/
|
||||||
db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const;
|
db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delivers all shapes of a specific net and layer to the given Shapes container.
|
||||||
|
*
|
||||||
|
* If "recursive" is true, the returned region will contain the shapes of
|
||||||
|
* all subcircuits too.
|
||||||
|
*
|
||||||
|
* This methods returns a new'd Region. It's the responsibility of the caller
|
||||||
|
* to delete this object.
|
||||||
|
*/
|
||||||
|
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Finds the net by probing a specific location on the given layer
|
* @brief Finds the net by probing a specific location on the given layer
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -141,11 +141,16 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
||||||
gsi::method ("netlist", &db::LayoutToNetlist::netlist,
|
gsi::method ("netlist", &db::LayoutToNetlist::netlist,
|
||||||
"@brief gets the netlist extracted (0 if no extraction happened yet)\n"
|
"@brief gets the netlist extracted (0 if no extraction happened yet)\n"
|
||||||
) +
|
) +
|
||||||
gsi::factory ("shapes_of_net", &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"),
|
gsi::factory ("shapes_of_net", (db::Region *(db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"),
|
||||||
"@brief Returns all shapes of a specific net and layer.\n"
|
"@brief Returns all shapes of a specific net and layer.\n"
|
||||||
"If 'recursive'' is true, the returned region will contain the shapes of\n"
|
"If 'recursive'' is true, the returned region will contain the shapes of\n"
|
||||||
"all subcircuits too.\n"
|
"all subcircuits too.\n"
|
||||||
) +
|
) +
|
||||||
|
gsi::method ("shapes_of_net", (void (db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, db::Shapes &) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), gsi::arg ("to"),
|
||||||
|
"@brief Sends all shapes of a specific net and layer to the given Shapes container.\n"
|
||||||
|
"If 'recursive'' is true, the returned region will contain the shapes of\n"
|
||||||
|
"all subcircuits too.\n"
|
||||||
|
) +
|
||||||
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"),
|
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"),
|
||||||
"@brief Finds the net by probing a specific location on the given layer\n"
|
"@brief Finds the net by probing a specific location on the given layer\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
|
||||||
|
|
@ -148,23 +148,25 @@ static void dump_recursive_nets_to_layout (const db::LayoutToNetlist &l2n, db::L
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool any = false;
|
||||||
|
for (std::map<const db::Region *, unsigned int>::const_iterator m = lmap.begin (); m != lmap.end () && !any; ++m) {
|
||||||
|
any = !db::recursive_cluster_shape_iterator<db::PolygonRef> (l2n.net_clusters (), l2n.layer_of (*m->first), c->cell_index (), n->cluster_id ()).at_end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!any) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
db::cell_index_type nci = std::numeric_limits<db::cell_index_type>::max ();
|
db::cell_index_type nci = std::numeric_limits<db::cell_index_type>::max ();
|
||||||
|
|
||||||
|
if (nci == std::numeric_limits<db::cell_index_type>::max ()) {
|
||||||
|
std::string nn = "RNET_" + c->name () + "_" + n->expanded_name ();
|
||||||
|
nci = ly.add_cell (nn.c_str ());
|
||||||
|
cell.insert (db::CellInstArray (db::CellInst (nci), db::Trans ()));
|
||||||
|
}
|
||||||
|
|
||||||
for (std::map<const db::Region *, unsigned int>::const_iterator m = lmap.begin (); m != lmap.end (); ++m) {
|
for (std::map<const db::Region *, unsigned int>::const_iterator m = lmap.begin (); m != lmap.end (); ++m) {
|
||||||
|
l2n.shapes_of_net (*n, *m->first, true, ly.cell (nci).shapes (m->second));
|
||||||
std::auto_ptr<db::Region> shapes (l2n.shapes_of_net (*n, *m->first, true));
|
|
||||||
if (shapes->empty ()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nci == std::numeric_limits<db::cell_index_type>::max ()) {
|
|
||||||
std::string nn = "RNET_" + c->name () + "_" + n->expanded_name ();
|
|
||||||
nci = ly.add_cell (nn.c_str ());
|
|
||||||
cell.insert (db::CellInstArray (db::CellInst (nci), db::Trans ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
shapes->insert_into (&ly, nci, m->second);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,12 @@ END
|
||||||
|
|
||||||
assert_equal(l2n.shapes_of_net(n, rmetal1, true).to_s, "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)")
|
assert_equal(l2n.shapes_of_net(n, rmetal1, true).to_s, "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)")
|
||||||
|
|
||||||
|
shapes = RBA::Shapes::new
|
||||||
|
l2n.shapes_of_net(n, rmetal1, true, shapes)
|
||||||
|
r = RBA::Region::new
|
||||||
|
shapes.each { |s| r.insert(s.polygon) }
|
||||||
|
assert_equal(r.to_s, "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)")
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_10_LayoutToNetlistExtractionWithoutDevices
|
def test_10_LayoutToNetlistExtractionWithoutDevices
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue