From abe40ae99f83e72d79eb1ee3a84117b7c1a544ef Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 19 Oct 2021 20:48:13 +0200 Subject: [PATCH] Bugfix plus more tests --- src/db/db/dbNetlistDeviceExtractorClasses.cc | 5 +- .../dbNetlistDeviceExtractorTests.cc | 292 ++++++++++++++++++ testdata/algo/bjt3_1.gds | Bin 0 -> 234 bytes testdata/algo/bjt3_2.gds | Bin 0 -> 298 bytes testdata/algo/bjt3_3.gds | Bin 0 -> 298 bytes testdata/algo/bjt3_4.gds | Bin 0 -> 362 bytes testdata/algo/bjt4_1.gds | Bin 0 -> 362 bytes 7 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 testdata/algo/bjt3_1.gds create mode 100644 testdata/algo/bjt3_2.gds create mode 100644 testdata/algo/bjt3_3.gds create mode 100644 testdata/algo/bjt3_4.gds create mode 100644 testdata/algo/bjt4_1.gds diff --git a/src/db/db/dbNetlistDeviceExtractorClasses.cc b/src/db/db/dbNetlistDeviceExtractorClasses.cc index 957c9e8bb..c4cbd3844 100644 --- a/src/db/db/dbNetlistDeviceExtractorClasses.cc +++ b/src/db/db/dbNetlistDeviceExtractorClasses.cc @@ -694,13 +694,16 @@ void NetlistDeviceExtractorBJT3Transistor::extract_devices (const std::vector collector terminal is collector outside base - rcollector = rcollector2base - rbase; + rcollector = rcollectors.selected_interacting (rbase) - rbase; } else { // lateral transistor: base is reduced by collector area rcollector = rcollector2base; rbase -= rcollector2base; } + // TODO: rbase - rcollector2base above could basically split a base region into different + // subregions potentially forming one transistor each. + // this is what is the true base contact rbase -= remitter2base; diff --git a/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc b/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc index c6077ce61..6978a692c 100644 --- a/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc @@ -853,3 +853,295 @@ TEST(42_DMOS4DeviceExtractorTestCircular) 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(50_BJT3DeviceExtractorTest) +{ + db::Layout ly; + + { + db::LoadLayoutOptions options; + + std::string fn (tl::testdata ()); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "bjt3_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 cl; + + db::NetlistDeviceExtractorBJT3Transistor ex ("BJT3"); + + db::NetlistDeviceExtractor::input_layers dl; + + dl["E"] = &l0; + dl["B"] = &l1; + dl["C"] = &l2; + dl["tE"] = &o1; + dl["tB"] = &o2; + dl["tC"] = &o3; + ex.extract (dss, 0, dl, nl, cl); + + EXPECT_EQ (nl.to_string (), + "circuit TOP ();\n" + " device BJT3 $1 (C=(null),B=(null),E=(null)) (AE=0.81,PE=3.6,AB=5,PB=9,AC=5,PC=9,NE=1);\n" + "end;\n" + ); + EXPECT_EQ (o1.to_string (), "(700,400;700,1300;1600,1300;1600,400)"); + EXPECT_EQ (o2.to_string (), "(0,0;0,2000;2500,2000;2500,0/700,400;1600,400;1600,1300;700,1300)"); + EXPECT_EQ (o3.to_string (), "(0,0;0,2000;2500,2000;2500,0/700,400;1600,400;1600,1300;700,1300)"); +} + +TEST(51_BJT3DeviceExtractorTest) +{ + db::Layout ly; + + { + db::LoadLayoutOptions options; + + std::string fn (tl::testdata ()); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "bjt3_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 cl; + + db::NetlistDeviceExtractorBJT3Transistor ex ("BJT3"); + + db::NetlistDeviceExtractor::input_layers dl; + + dl["E"] = &l0; + dl["B"] = &l1; + dl["C"] = &l2; + dl["tE"] = &o1; + dl["tB"] = &o2; + dl["tC"] = &o3; + ex.extract (dss, 0, dl, nl, cl); + + EXPECT_EQ (nl.to_string (), + "circuit TOP ();\n" + " device BJT3 $1 (C=(null),B=(null),E=(null)) (AE=0.81,PE=3.6,AB=5,PB=9,AC=5,PC=9,NE=1);\n" + "end;\n" + ); + EXPECT_EQ (o1.to_string (), "(700,400;700,1300;1600,1300;1600,400)"); + EXPECT_EQ (o2.to_string (), "(0,0;0,2000;2500,2000;2500,0/700,400;1600,400;1600,1300;700,1300)"); + EXPECT_EQ (o3.to_string (), "(-1000,-500;-1000,2500;3000,2500;3000,-500/0,0;2500,0;2500,2000;0,2000)"); +} + +TEST(52_BJT3DeviceExtractorTestLateral) +{ + db::Layout ly; + + { + db::LoadLayoutOptions options; + + std::string fn (tl::testdata ()); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "bjt3_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 cl; + + db::NetlistDeviceExtractorBJT3Transistor ex ("BJT3"); + + db::NetlistDeviceExtractor::input_layers dl; + + dl["E"] = &l0; + dl["B"] = &l1; + dl["C"] = &l2; + dl["tE"] = &o1; + dl["tB"] = &o2; + dl["tC"] = &o3; + ex.extract (dss, 0, dl, nl, cl); + + EXPECT_EQ (nl.to_string (), + "circuit TOP ();\n" + " device BJT3 $1 (C=(null),B=(null),E=(null)) (AE=0.81,PE=3.6,AB=5,PB=9,AC=0.8,PC=4.8,NE=1);\n" + "end;\n" + ); + EXPECT_EQ (o1.to_string (), "(700,400;700,1300;1600,1300;1600,400)"); + EXPECT_EQ (o2.to_string (), "(0,0;0,2000;2100,2000;2100,0/700,400;1600,400;1600,1300;700,1300)"); + EXPECT_EQ (o3.to_string (), "(2100,0;2100,2000;2500,2000;2500,0)"); +} + +TEST(53_BJT3DeviceExtractorTestMultEmitter) +{ + db::Layout ly; + + { + db::LoadLayoutOptions options; + + std::string fn (tl::testdata ()); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "bjt3_4.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 cl; + + db::NetlistDeviceExtractorBJT3Transistor ex ("BJT3"); + + db::NetlistDeviceExtractor::input_layers dl; + + dl["E"] = &l0; + dl["B"] = &l1; + dl["C"] = &l2; + dl["tE"] = &o1; + dl["tB"] = &o2; + dl["tC"] = &o3; + ex.extract (dss, 0, dl, nl, cl); + + EXPECT_EQ (nl.to_string (), + "circuit TOP ();\n" + " device BJT3 $1 (C=(null),B=(null),E=(null)) (AE=0.5,PE=3,AB=10,PB=14,AC=10,PC=14,NE=1);\n" + " device BJT3 $2 (C=(null),B=(null),E=(null)) (AE=0.5,PE=3,AB=10,PB=14,AC=10,PC=14,NE=1);\n" + "end;\n" + ); + EXPECT_EQ (o1.to_string (), "(1000,500;1000,1500;1500,1500;1500,500);(3500,500;3500,1500;4000,1500;4000,500)"); + EXPECT_EQ (o2.to_string (), "(0,0;0,2000;5000,2000;5000,0/1000,500;1500,500;1500,1500;1000,1500/3500,500;4000,500;4000,1500;3500,1500);(0,0;0,2000;5000,2000;5000,0/1000,500;1500,500;1500,1500;1000,1500/3500,500;4000,500;4000,1500;3500,1500)"); + EXPECT_EQ (o3.to_string (), "(-500,-500;-500,2500;5500,2500;5500,-500/0,0;5000,0;5000,2000;0,2000);(-500,-500;-500,2500;5500,2500;5500,-500/0,0;5000,0;5000,2000;0,2000)"); +} + +TEST(54_BJT4DeviceExtractorTest) +{ + db::Layout ly; + + { + db::LoadLayoutOptions options; + + std::string fn (tl::testdata ()); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "bjt4_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 cl; + + db::NetlistDeviceExtractorBJT4Transistor ex ("BJT4"); + + db::NetlistDeviceExtractor::input_layers dl; + + dl["E"] = &l0; + dl["B"] = &l1; + dl["C"] = &l2; + dl["S"] = &l3; + dl["tE"] = &o1; + dl["tB"] = &o2; + dl["tC"] = &o3; + dl["tS"] = &o4; + ex.extract (dss, 0, dl, nl, cl); + + EXPECT_EQ (nl.to_string (), + "circuit TOP ();\n" + " device BJT4 $1 (C=(null),B=(null),E=(null),S=(null)) (AE=0.81,PE=3.6,AB=5,PB=9,AC=5,PC=9,NE=1);\n" + "end;\n" + ); + EXPECT_EQ (o1.to_string (), "(700,400;700,1300;1600,1300;1600,400)"); + EXPECT_EQ (o2.to_string (), "(0,0;0,2000;2500,2000;2500,0/700,400;1600,400;1600,1300;700,1300)"); + EXPECT_EQ (o3.to_string (), "(-1000,-500;-1000,2500;3000,2500;3000,-500/0,0;2500,0;2500,2000;0,2000)"); + EXPECT_EQ (o4.to_string (), "(0,0;0,2000;2500,2000;2500,0)"); +} + diff --git a/testdata/algo/bjt3_1.gds b/testdata/algo/bjt3_1.gds new file mode 100644 index 0000000000000000000000000000000000000000..11a0abdc5060455b33d4a9f0b37573e3257bb7d9 GIT binary patch literal 234 zcmZQzV_;&6V31*CVt>lO#UKoX{0ywfYz7V{HXlzX1_lvkRy)T|bMIrzKUli#&|fe+ zDuh9X6^}kPwh;dS1_l-m1_m}>CI&_ZHa;c>1_m7gW*~_K*e@_Ja2{b`fYC@&EP@FA jKvNLKq&_V4HE~_VEybsGgue^l;Rh_ literal 0 HcmV?d00001 diff --git a/testdata/algo/bjt3_2.gds b/testdata/algo/bjt3_2.gds new file mode 100644 index 0000000000000000000000000000000000000000..08c87c9ffc74cd8c2033b6314f05f01002ab1b14 GIT binary patch literal 298 zcmZQzV_;&6V31*CVt>lO#UKoX{0w5qYz7V{HXlzX1_lvkRy)T|bMIrzKUli#&|fe+ zDuh9X6^}kPwh;dS1_l-m1_m}>CI&_ZHa;c>1_m7gW*~_K*e@_Ja2{b`fYC@&EP@FA zObGq||NoKr|NkEkh=%Cp-T|Xw;vkvY4#FfcGqU|;~ztRg@u2Lufh2hw2u K>_9iLFaQ9|TrK|q literal 0 HcmV?d00001 diff --git a/testdata/algo/bjt3_3.gds b/testdata/algo/bjt3_3.gds new file mode 100644 index 0000000000000000000000000000000000000000..11d454da87196f1203365429663ae8a71378b4f8 GIT binary patch literal 298 zcmZQzV_;&6V31*CVt>lO#UKoX$_(1bYz7V{HXlzX1_lvkRy)T|bMIrzKUli#&|fe+ zDuh9X6^}kPwh;dS1_l-m1_m}>CI&_ZHa;c>1_m7gW*~_K*e@_Ja2{b`fYC@&EP@FA zOvw5$HTzDVFJ<1y#q$W#KAPOexNH5_A~8aU|^iUzyP9IMSxNc2pT31q`~^x Jfo@=7000KdCLsU- literal 0 HcmV?d00001 diff --git a/testdata/algo/bjt3_4.gds b/testdata/algo/bjt3_4.gds new file mode 100644 index 0000000000000000000000000000000000000000..d326300d8c75c64a2a44477aac7e50066e4bcb2e GIT binary patch literal 362 zcmZQzV_;&6V31*CVt>lO#UKoXrVQf9Yz7V{HXlzX1_lvkRy)T|bMIrzKUli#&|fe+ zDuh9X6^}kPwh;dS1_l-m1_m}>CI&_ZHa;c>1_m7gW*~_K*e@_J2zM|rz-S~X7D0r5 zCWQX~|Nrs8FarbU5e5d)8W;@|2hj}3`hl)M*w6fefr0T00|SU=y@QHj;y@awe%>_@ Y{U92opML>@2I+^&gY~lm{lLNi02_)r;{X5v literal 0 HcmV?d00001 diff --git a/testdata/algo/bjt4_1.gds b/testdata/algo/bjt4_1.gds new file mode 100644 index 0000000000000000000000000000000000000000..bffdecae4660d3aae2b7e5b063ba4ed57709f5ba GIT binary patch literal 362 zcmaKny$%6E6h_a^?#}vKA+}H`l|m^RK{P@_v4waeonE8UcmRb`)Lufb-iR?vCNq^O z=1jhullu)4A=b1!5j`l;AfZd>z9|T~m`xz@!{K<_pWlwp!Svia>^CW`@Q){Dx?Dj} z02vEBWK{s2ny+u?M0Y4&!O$56b?Xc3EA?tB^{(Xnx#hE=$#dfRx`o{@F5vATXPD^G g$kODRuJ2o4sjU6$khLM-9iI$M{_XblBmIYf4{eJ?O8@`> literal 0 HcmV?d00001