mirror of https://github.com/KLayout/klayout.git
Implemented #462 (Generalize MOS transistor extraction to other gate figures)
This commit is contained in:
parent
85c033db64
commit
833edf53b2
|
|
@ -144,22 +144,39 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
|
|||
continue;
|
||||
}
|
||||
|
||||
db::Edges edges (rgate.edges () & rdiff2gate.edges ());
|
||||
if (edges.size () != 2) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Expected two edges interacting gate/diff (found %d) - width and length may be incorrect")), int (edges.size ())), *p);
|
||||
std::vector<db::Edges::length_type> widths;
|
||||
for (db::Region::const_iterator d2g = rdiff2gate.begin (); ! d2g.at_end (); ++d2g) {
|
||||
|
||||
db::Region rd2g;
|
||||
rd2g.insert (*d2g);
|
||||
|
||||
db::Edges edges (rgate.edges () & rd2g.edges ());
|
||||
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")));
|
||||
} else {
|
||||
widths.push_back (l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (widths.size () != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! p->is_box ()) {
|
||||
error (tl::to_string (tr ("Gate shape is not a box - width and length may be incorrect")), *p);
|
||||
}
|
||||
// Computation of the gate length and width - this scheme is compatible with
|
||||
// non-rectangular gates and circular gates. The computation is based on the
|
||||
// relationship: A(gate) = L(gate) * W(gate). W(gate) is determined from the
|
||||
// accumulated edge lengths (average of left and right length).
|
||||
double param_w = sdbu () * (widths[0] + widths[1]) * 0.5;
|
||||
double param_l = sdbu () * sdbu () * double (rgate.area ()) / param_w;
|
||||
|
||||
db::Device *device = create_device ();
|
||||
|
||||
device->set_trans (db::DCplxTrans ((p->box ().center () - db::Point ()) * dbu ()));
|
||||
|
||||
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, sdbu () * edges.length () * 0.5);
|
||||
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, sdbu () * (p->perimeter () - edges.length ()) * 0.5);
|
||||
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, param_w);
|
||||
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) {
|
||||
|
|
@ -230,24 +247,39 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
|
|||
continue;
|
||||
}
|
||||
|
||||
db::Region diff2gate = sdiff2gate + ddiff2gate;
|
||||
db::Edges::length_type sdwidth = 0, ddwidth = 0;
|
||||
|
||||
db::Edges edges (rgate.edges () & diff2gate.edges ());
|
||||
if (edges.size () != 2) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Expected two edges interacting gate/diff (found %d) - width and length may be incorrect")), int (edges.size ())), *p);
|
||||
continue;
|
||||
{
|
||||
db::Edges edges (rgate.edges () & sdiff2gate.edges ());
|
||||
sdwidth = edges.length ();
|
||||
if (sdwidth == 0) {
|
||||
error (tl::to_string (tr ("Vanishing edges for interaction gate/source diff (corner interaction) - gate shape ignored")));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (! p->is_box ()) {
|
||||
error (tl::to_string (tr ("Gate shape is not a box - width and length may be incorrect")), *p);
|
||||
{
|
||||
db::Edges edges (rgate.edges () & ddiff2gate.edges ());
|
||||
ddwidth = edges.length ();
|
||||
if (ddwidth == 0) {
|
||||
error (tl::to_string (tr ("Vanishing edges for interaction gate/drain diff (corner interaction) - gate shape ignored")));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Computation of the gate length and width - this scheme is compatible with
|
||||
// non-rectangular gates and circular gates. The computation is based on the
|
||||
// relationship: A(gate) = L(gate) * W(gate). W(gate) is determined from the
|
||||
// accumulated edge lengths (average of left and right length).
|
||||
double param_w = sdbu () * (sdwidth + ddwidth) * 0.5;
|
||||
double param_l = sdbu () * sdbu () * double (rgate.area ()) / param_w;
|
||||
|
||||
db::Device *device = create_device ();
|
||||
|
||||
device->set_trans (db::DCplxTrans ((p->box ().center () - db::Point ()) * dbu ()));
|
||||
|
||||
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, sdbu () * edges.length () * 0.5);
|
||||
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, sdbu () * (p->perimeter () - edges.length ()) * 0.5);
|
||||
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, param_w);
|
||||
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, param_l);
|
||||
|
||||
for (int diff_index = 0; diff_index < 2; ++diff_index) {
|
||||
|
||||
|
|
@ -272,6 +304,7 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
|
|||
modify_device (*p, layer_geometry, device);
|
||||
|
||||
// output the device for debugging
|
||||
db::Region diff2gate = sdiff2gate + ddiff2gate;
|
||||
device_out (device, diff2gate, rgate);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,14 @@
|
|||
*/
|
||||
|
||||
#include "dbNetlistDeviceExtractor.h"
|
||||
#include "dbLoadLayoutOptions.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbNetlistDeviceExtractorClasses.h"
|
||||
|
||||
#include "tlUnitTest.h"
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
TEST(1_NetlistDeviceExtractorErrorBasic)
|
||||
{
|
||||
|
|
@ -83,3 +89,717 @@ TEST(2_NetlistDeviceExtractorErrors)
|
|||
EXPECT_EQ (error2string (errors [2]), ":cat1:desc1:():msg1");
|
||||
EXPECT_EQ (error2string (errors [3]), ":cat1:desc1:(10,11;10,13;12,13;12,11):msg3");
|
||||
}
|
||||
|
||||
TEST(10_MOS3DeviceExtractorTest)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "mos3_1.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS3Transistor ex ("MOS3");
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["SD"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device MOS3 $1 (S=(null),G=(null),D=(null)) (L=0.3,W=0.8,AS=0.4,AD=0.16,PS=2.6,PD=2);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(-600,-200;-600,600;-100,600;-100,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(200,-200;200,600;400,600;400,-200)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-200;-100,600;200,600;200,-200)");
|
||||
}
|
||||
|
||||
TEST(11_MOS3DeviceExtractorTestNotRectangularGate)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "mos3_2.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS3Transistor ex ("MOS3");
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["SD"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device MOS3 $1 (S=(null),G=(null),D=(null)) (L=0.3,W=1,AS=0.32,AD=0.18,PS=2.6,PD=2.4);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(-600,-200;-600,600;-300,600;-300,200;-100,200;-100,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(200,-200;200,500;0,500;0,600;400,600;400,-200)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-200;-100,200;-300,200;-300,600;0,600;0,500;200,500;200,-200)");
|
||||
}
|
||||
|
||||
TEST(12_MOS3DeviceExtractorTestCircular)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "mos3_3.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS3Transistor ex ("MOS3");
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["SD"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device MOS3 $1 (S=(null),G=(null),D=(null)) (L=0.3,W=3.8,AS=0.4,AD=4.18,PS=2.6,PD=14.6);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(200,-200;200,600;700,600;700,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(-600,-1200;-600,1400;1600,1400;1600,-1200/-100,-500;1000,-500;1000,900;-100,900)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-500;-100,900;1000,900;1000,-500/200,-200;700,-200;700,600;200,600)");
|
||||
}
|
||||
|
||||
TEST(20_MOS4DeviceExtractorTest)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "mos4_1.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region l3 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(3, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
db::Region o4 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS4Transistor ex ("MOS4");
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["SD"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["W"] = &l3;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
dl["tB"] = &o4;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device MOS4 $1 (S=(null),G=(null),D=(null),B=(null)) (L=0.3,W=0.8,AS=0.4,AD=0.16,PS=2.6,PD=2);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(-600,-200;-600,600;-100,600;-100,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(200,-200;200,600;400,600;400,-200)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-200;-100,600;200,600;200,-200)");
|
||||
EXPECT_EQ (o4.to_string (), "(-100,-200;-100,600;200,600;200,-200)");
|
||||
}
|
||||
|
||||
TEST(21_MOS4DeviceExtractorTestNotRectangularGate)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "mos4_2.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region l3 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(3, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
db::Region o4 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS4Transistor ex ("MOS4");
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["SD"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["W"] = &l3;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
dl["tB"] = &o4;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device MOS4 $1 (S=(null),G=(null),D=(null),B=(null)) (L=0.3,W=1,AS=0.32,AD=0.18,PS=2.6,PD=2.4);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(-600,-200;-600,600;-300,600;-300,200;-100,200;-100,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(200,-200;200,500;0,500;0,600;400,600;400,-200)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-200;-100,200;-300,200;-300,600;0,600;0,500;200,500;200,-200)");
|
||||
EXPECT_EQ (o4.to_string (), "(-100,-200;-100,200;-300,200;-300,600;0,600;0,500;200,500;200,-200)");
|
||||
}
|
||||
|
||||
TEST(22_MOS4DeviceExtractorTestCircular)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "mos4_3.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region l3 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(3, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
db::Region o4 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS4Transistor ex ("MOS4");
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["SD"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["W"] = &l3;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
dl["tB"] = &o4;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device MOS4 $1 (S=(null),G=(null),D=(null),B=(null)) (L=0.3,W=3.8,AS=0.4,AD=4.18,PS=2.6,PD=14.6);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(200,-200;200,600;700,600;700,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(-600,-1200;-600,1400;1600,1400;1600,-1200/-100,-500;1000,-500;1000,900;-100,900)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-500;-100,900;1000,900;1000,-500/200,-200;700,-200;700,600;200,600)");
|
||||
EXPECT_EQ (o4.to_string (), "(-100,-500;-100,900;1000,900;1000,-500/200,-200;700,-200;700,600;200,600)");
|
||||
}
|
||||
|
||||
TEST(30_DMOS3DeviceExtractorTest)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "dmos3_1.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l0 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(0, 0))), dss);
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS3Transistor ex ("DMOS3", true);
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["S"] = &l0;
|
||||
dl["D"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device DMOS3 $1 (S=(null),G=(null),D=(null)) (L=0.3,W=0.8,AS=0.4,AD=0.16,PS=2.6,PD=2);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(-600,-200;-600,600;-100,600;-100,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(200,-200;200,600;400,600;400,-200)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-200;-100,600;200,600;200,-200)");
|
||||
}
|
||||
|
||||
TEST(31_DMOS3DeviceExtractorTestNotRectangularGate)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "dmos3_2.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l0 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(0, 0))), dss);
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS3Transistor ex ("DMOS3", true);
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["S"] = &l0;
|
||||
dl["D"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device DMOS3 $1 (S=(null),G=(null),D=(null)) (L=0.3,W=1,AS=0.32,AD=0.18,PS=2.6,PD=2.4);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(-600,-200;-600,600;-300,600;-300,200;-100,200;-100,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(200,-200;200,500;0,500;0,600;400,600;400,-200)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-200;-100,200;-300,200;-300,600;0,600;0,500;200,500;200,-200)");
|
||||
}
|
||||
|
||||
TEST(32_DMOS3DeviceExtractorTestCircular)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "dmos3_3.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l0 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(0, 0))), dss);
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS3Transistor ex ("DMOS3", true);
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["S"] = &l0;
|
||||
dl["D"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device DMOS3 $1 (S=(null),G=(null),D=(null)) (L=0.3,W=3.8,AS=0.4,AD=4.18,PS=2.6,PD=14.6);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(200,-200;200,600;700,600;700,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(-600,-1200;-600,1400;1600,1400;1600,-1200/-100,-500;1000,-500;1000,900;-100,900)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-500;-100,900;1000,900;1000,-500/200,-200;700,-200;700,600;200,600)");
|
||||
}
|
||||
|
||||
TEST(40_DMOS4DeviceExtractorTest)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "dmos4_1.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l0 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(0, 0))), dss);
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region l3 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(3, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
db::Region o4 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS4Transistor ex ("DMOS4", true);
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["S"] = &l0;
|
||||
dl["D"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["W"] = &l3;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
dl["tB"] = &o4;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device DMOS4 $1 (S=(null),G=(null),D=(null),B=(null)) (L=0.3,W=0.8,AS=0.4,AD=0.16,PS=2.6,PD=2);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(-600,-200;-600,600;-100,600;-100,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(200,-200;200,600;400,600;400,-200)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-200;-100,600;200,600;200,-200)");
|
||||
EXPECT_EQ (o4.to_string (), "(-100,-200;-100,600;200,600;200,-200)");
|
||||
}
|
||||
|
||||
TEST(41_DMOS4DeviceExtractorTestNotRectangularGate)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "dmos4_2.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l0 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(0, 0))), dss);
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region l3 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(3, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
db::Region o4 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS4Transistor ex ("DMOS4", true);
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["S"] = &l0;
|
||||
dl["D"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["W"] = &l3;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
dl["tB"] = &o4;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device DMOS4 $1 (S=(null),G=(null),D=(null),B=(null)) (L=0.3,W=1,AS=0.32,AD=0.18,PS=2.6,PD=2.4);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(-600,-200;-600,600;-300,600;-300,200;-100,200;-100,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(200,-200;200,500;0,500;0,600;400,600;400,-200)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-200;-100,200;-300,200;-300,600;0,600;0,500;200,500;200,-200)");
|
||||
EXPECT_EQ (o4.to_string (), "(-100,-200;-100,200;-300,200;-300,600;0,600;0,500;200,500;200,-200)");
|
||||
}
|
||||
|
||||
TEST(42_DMOS4DeviceExtractorTestCircular)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
db::LoadLayoutOptions options;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn = tl::combine_path (fn, "testdata");
|
||||
fn = tl::combine_path (fn, "algo");
|
||||
fn = tl::combine_path (fn, "dmos4_3.gds");
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_text_enlargement (1);
|
||||
dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
|
||||
// original layers
|
||||
db::Region l0 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(0, 0))), dss);
|
||||
db::Region l1 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(1, 0))), dss);
|
||||
db::Region l2 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(2, 0))), dss);
|
||||
db::Region l3 (db::RecursiveShapeIterator (ly, tc, ly.get_layer (db::LayerProperties(3, 0))), dss);
|
||||
db::Region o1 (dss);
|
||||
db::Region o2 (dss);
|
||||
db::Region o3 (dss);
|
||||
db::Region o4 (dss);
|
||||
|
||||
// perform the extraction
|
||||
|
||||
db::Netlist nl;
|
||||
db::hier_clusters<db::PolygonRef> cl;
|
||||
|
||||
db::NetlistDeviceExtractorMOS4Transistor ex ("DMOS4", true);
|
||||
|
||||
db::NetlistDeviceExtractor::input_layers dl;
|
||||
|
||||
dl["S"] = &l0;
|
||||
dl["D"] = &l1;
|
||||
dl["G"] = &l2;
|
||||
dl["W"] = &l3;
|
||||
dl["tS"] = &o1;
|
||||
dl["tD"] = &o2;
|
||||
dl["tG"] = &o3;
|
||||
dl["tB"] = &o4;
|
||||
ex.extract (dss, 0, dl, nl, cl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit TOP ();\n"
|
||||
" device DMOS4 $1 (S=(null),G=(null),D=(null),B=(null)) (L=0.3,W=3.8,AS=0.4,AD=4.18,PS=2.6,PD=14.6);\n"
|
||||
"end;\n"
|
||||
);
|
||||
EXPECT_EQ (o1.to_string (), "(200,-200;200,600;700,600;700,-200)");
|
||||
EXPECT_EQ (o2.to_string (), "(-600,-1200;-600,1400;1600,1400;1600,-1200/-100,-500;1000,-500;1000,900;-100,900)");
|
||||
EXPECT_EQ (o3.to_string (), "(-100,-500;-100,900;1000,900;1000,-500/200,-200;700,-200;700,600;200,600)");
|
||||
EXPECT_EQ (o4.to_string (), "(-100,-500;-100,900;1000,900;1000,-500/200,-200;700,-200;700,600;200,600)");
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue