Antenna check: tests added, 'catchall' diode protection

This commit is contained in:
Matthias Koefferlein 2019-03-01 23:07:28 +01:00
parent 9f4f2d58d7
commit 8d3b94201e
5 changed files with 98 additions and 13 deletions

View File

@ -896,25 +896,36 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg
double ametal = rmetal.area () * dbu * dbu;
double r = ratio;
bool skip = false;
for (std::vector<std::pair<db::Region *, double> >::const_iterator d = diodes.begin (); d != diodes.end (); ++d) {
for (std::vector<std::pair<db::Region *, double> >::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);
r += rdiode.area () * dbu * dbu / d->second;
}
if (tl::verbosity () >= 0 /*50*/) {
tl::info << "cell [" << ly.cell_name (*cid) << "]: agate=" << tl::to_string (agate) << ", ametal=" << tl::to_string (ametal) << ", r=" << tl::sprintf ("%.12g", r);
}
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);
if (fabs (d->second) < db::epsilon) {
if (rdiode.area () > 0) {
skip = true;
}
} else {
r += rdiode.area () * dbu * dbu * d->second;
}
}
if (! skip) {
if (tl::verbosity () >= 50) {
tl::info << "cell [" << ly.cell_name (*cid) << "]: agate=" << tl::to_string (agate) << ", ametal=" << tl::to_string (ametal) << ", r=" << tl::sprintf ("%.12g", r);
}
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);
}
}
}
}

View File

@ -517,6 +517,11 @@ public:
* A(diode) / Ared[um^2] to the ratio. A(diode) is the area of the
* diode layer per cluster. Both the diode layer and the Ared value
* are specified as pairs in "diodes".
*
* A special case is Ared = 0: in this case, the presence of any shapes
* on the diode layer will entirely disable the check on a cluster,
* regardless of the diode's area.
* In other words: any diode will make the net safe against antenna discharge.
*/
db::Region antenna_check (const db::Region &gate, const db::Region &metal, double ratio, const std::vector<std::pair<db::Region *, double> > &diodes = std::vector<std::pair<db::Region *, double> > ());

View File

@ -2263,6 +2263,7 @@ TEST(10_Antenna)
unsigned int metal1 = define_layer (ly, lmap, 9);
unsigned int via1 = define_layer (ly, lmap, 11);
unsigned int metal2 = define_layer (ly, lmap, 12);
unsigned int diode = define_layer (ly, lmap, 1);
{
db::LoadLayoutOptions options;
@ -2283,6 +2284,7 @@ TEST(10_Antenna)
db::DeepShapeStore dss;
std::auto_ptr<db::Region> rdiode (new db::Region (db::RecursiveShapeIterator (ly, tc, diode), dss));
std::auto_ptr<db::Region> rpoly (new db::Region (db::RecursiveShapeIterator (ly, tc, poly), dss));
std::auto_ptr<db::Region> rcont (new db::Region (db::RecursiveShapeIterator (ly, tc, cont), dss));
std::auto_ptr<db::Region> rmetal1 (new db::Region (db::RecursiveShapeIterator (ly, tc, metal1), dss));
@ -2293,6 +2295,7 @@ TEST(10_Antenna)
ly2.dbu (ly.dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOPTOP"));
rdiode->insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (1, 0)));
rpoly->insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (6, 0)));
rcont->insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (8, 0)));
rmetal1->insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (9, 0)));
@ -2367,6 +2370,72 @@ TEST(10_Antenna)
a2_17.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (202, 0)));
}
{
db::LayoutToNetlist l2n (&dss);
l2n.register_layer (*rdiode, "diode");
l2n.register_layer (*rpoly, "poly");
l2n.register_layer (*rcont, "cont");
l2n.register_layer (*rmetal1, "metal1");
// Intra-layer
l2n.connect (*rdiode);
l2n.connect (*rpoly);
l2n.connect (*rcont);
l2n.connect (*rmetal1);
// Inter-layer
l2n.connect (*rdiode, *rcont);
l2n.connect (*rpoly, *rcont);
l2n.connect (*rcont, *rmetal1);
l2n.extract_netlist ();
std::vector<std::pair<db::Region *, double> > diodes;
// 8.0 means: increase r by 8.0 for each um^2 of diode attached to a net
diodes.push_back (std::make_pair (rdiode.get (), 8.0));
db::Region a3_3 = l2n.antenna_check (*rpoly, *rmetal1, 3, diodes);
db::Region a3_10 = l2n.antenna_check (*rpoly, *rmetal1, 10, diodes);
db::Region a3_30 = l2n.antenna_check (*rpoly, *rmetal1, 30, diodes);
a3_3.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (300, 0)));
a3_10.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (301, 0)));
a3_30.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (302, 0)));
}
{
db::LayoutToNetlist l2n (&dss);
l2n.register_layer (*rdiode, "diode");
l2n.register_layer (*rpoly, "poly");
l2n.register_layer (*rcont, "cont");
l2n.register_layer (*rmetal1, "metal1");
// Intra-layer
l2n.connect (*rdiode);
l2n.connect (*rpoly);
l2n.connect (*rcont);
l2n.connect (*rmetal1);
// Inter-layer
l2n.connect (*rdiode, *rcont);
l2n.connect (*rpoly, *rcont);
l2n.connect (*rcont, *rmetal1);
l2n.extract_netlist ();
std::vector<std::pair<db::Region *, double> > diodes;
// 0.0 means: skip all nets where there is a rdiode attached
diodes.push_back (std::make_pair (rdiode.get (), 0.0));
db::Region a4_3 = l2n.antenna_check (*rpoly, *rmetal1, 3, diodes);
db::Region a4_10 = l2n.antenna_check (*rpoly, *rmetal1, 10, diodes);
db::Region a4_30 = l2n.antenna_check (*rpoly, *rmetal1, 30, diodes);
a4_3.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (400, 0)));
a4_10.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (401, 0)));
a4_30.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (402, 0)));
}
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");

Binary file not shown.

Binary file not shown.