Merge pull request #821 from KLayout/test-stability

Test stability
This commit is contained in:
Matthias Köfferlein 2021-06-06 18:12:37 +02:00 committed by GitHub
commit f956dd478b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 18 deletions

View File

@ -144,13 +144,18 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
continue;
}
std::vector<db::Edges::length_type> widths;
// normalize the diffusion polygons so that the S/D assignment is more predicable
std::vector<db::Polygon> diffpoly;
diffpoly.reserve (2);
for (db::Region::const_iterator d2g = rdiff2gate.begin (); ! d2g.at_end (); ++d2g) {
diffpoly.push_back (*d2g);
}
std::sort (diffpoly.begin (), diffpoly.end ());
db::Region rd2g;
rd2g.insert (*d2g);
std::vector<db::Edges::length_type> widths;
for (std::vector<db::Polygon>::const_iterator d2g = diffpoly.begin (); d2g != diffpoly.end (); ++d2g) {
db::Edges edges (rgate.edges () & rd2g.edges ());
db::Edges edges (rgate.edges () & db::Edges (*d2g));
db::Edges::length_type l = edges.length ();
if (l == 0) {
error (tl::to_string (tr ("Vanishing edges for interaction gate/diff (corner interaction) - gate shape ignored")));
@ -179,18 +184,18 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, param_l);
int diff_index = 0;
for (db::Region::const_iterator d = rdiff2gate.begin (); !d.at_end () && diff_index < 2; ++d, ++diff_index) {
for (std::vector<db::Polygon>::const_iterator d2g = diffpoly.begin (); d2g != diffpoly.end () && diff_index < 2; ++d2g, ++diff_index) {
// count the number of gate shapes attached to this shape and distribute the area of the
// diffusion region to the number of gates
size_t n = rgates.selected_interacting (db::Region (*d)).count ();
size_t n = rgates.selected_interacting (db::Region (*d2g)).count ();
tl_assert (n > 0);
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_AS : db::DeviceClassMOS3Transistor::param_id_AD, sdbu () * sdbu () * d->area () / double (n));
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_PS : db::DeviceClassMOS3Transistor::param_id_PD, sdbu () * d->perimeter () / double (n));
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_AS : db::DeviceClassMOS3Transistor::param_id_AD, sdbu () * sdbu () * d2g->area () / double (n));
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_PS : db::DeviceClassMOS3Transistor::param_id_PD, sdbu () * d2g->perimeter () / double (n));
unsigned int sd_index = diff_index == 0 ? source_terminal_geometry_index : drain_terminal_geometry_index;
define_terminal (device, diff_index == 0 ? db::DeviceClassMOS3Transistor::terminal_id_S : db::DeviceClassMOS3Transistor::terminal_id_D, sd_index, *d);
define_terminal (device, diff_index == 0 ? db::DeviceClassMOS3Transistor::terminal_id_S : db::DeviceClassMOS3Transistor::terminal_id_D, sd_index, *d2g);
}
@ -463,8 +468,16 @@ void NetlistDeviceExtractorResistor::extract_devices (const std::vector<db::Regi
device->set_parameter_value (db::DeviceClassResistor::param_id_A, sdbu () * sdbu () * p->area ());
device->set_parameter_value (db::DeviceClassResistor::param_id_P, sdbu () * p->perimeter ());
// collect and normalize the contact polygons (gives better reproducibility)
std::vector<db::Polygon> contact_poly;
contact_poly.reserve (2);
for (db::Region::const_iterator d = contacts_per_res.begin (); !d.at_end (); ++d) {
contact_poly.push_back (*d);
}
std::sort (contact_poly.begin (), contact_poly.end ());
int cont_index = 0;
for (db::Region::const_iterator d = contacts_per_res.begin (); !d.at_end () && cont_index < 2; ++d, ++cont_index) {
for (std::vector<db::Polygon>::const_iterator d = contact_poly.begin (); d != contact_poly.end () && cont_index < 2; ++d, ++cont_index) {
size_t terminal_geometry_index = cont_index == 0 ? a_terminal_geometry_index : b_terminal_geometry_index;
define_terminal (device, cont_index == 0 ? db::DeviceClassResistor::terminal_id_A : db::DeviceClassResistor::terminal_id_B, terminal_geometry_index, *d);
}

View File

@ -2487,7 +2487,7 @@ Class<NetlistSpiceReaderDelegateImpl> db_NetlistSpiceReaderDelegate ("db", "Netl
"This method receives a string with the element specification and the element code. It is supposed to "
"parse the element line and return a model name, a value, a list of net names and a parameter value dictionary.\n"
"\n"
"'parse_element' is called one every element card. The results of this call go into the \\element method "
"'parse_element' is called on every element card. The results of this call go into the \\element method "
"to actually create the device. This method can be reimplemented to support other flavors of SPICE.\n"
"\n"
"This method has been introduced in version 0.27.1\n"
@ -2522,8 +2522,8 @@ Class<NetlistSpiceReaderDelegateImpl> db_NetlistSpiceReaderDelegate ("db", "Netl
) +
gsi::method_ext ("parse_element_components", &parse_element_components, gsi::arg ("s"),
"@brief Parses a string into string and parameter components.\n"
"This method is provided for simplifying the implementation of 'parse_element'. It takes a string and splits it into "
"string arguments and parameter values. For example, 'a b c=6' renders two string arguments in 'nn' and one parameter in pv ('C'->6.0). "
"This method is provided to simplify the implementation of 'parse_element'. It takes a string and splits it into "
"string arguments and parameter values. For example, 'a b c=6' renders two string arguments in 'nn' and one parameter ('C'->6.0). "
"It returns data \\ParseElementComponentsData object with the strings and parameters.\n"
"The parameter names are already translated to upper case.\n"
"\n"

View File

@ -3859,7 +3859,7 @@ CODE
#
# @code
# # reports areas where layer 1/0 density is below 10% on 20x20 um tiles
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um))
# low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(20.um))
# @/code
#
# Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)".
@ -3873,7 +3873,7 @@ CODE
# @code
# # reports areas where layer 1/0 density is below 10% on 30x30 um tiles
# # with a tile step of 20x20 um:
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
# low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
# @/code
#
# For "tile_step", anisotropic values can be given as well by using two values: the first for the
@ -3891,7 +3891,7 @@ CODE
# # reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from
# # layer 0/0:
# cell_frame = input(0, 0)
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
# low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
# @/code
#
# Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box.
@ -3903,7 +3903,7 @@ CODE
# @code
# # reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000
# # (100 and 150 tiles of 20 um each are used in horizontal and vertical direction):
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
# low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
# @/code
#
# The "padding mode" indicates how the area outside the layout's bounding box is considered.
@ -3917,7 +3917,7 @@ CODE
# Example:
#
# @code
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), padding_ignore)
# low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(20.um), padding_ignore)
# @/code
#
# The complementary version of "with_density" is \without_density.