From 1b2a611d83ecd9d7848d236c6738649f5437085c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 15 Jun 2019 09:34:04 +0200 Subject: [PATCH] WIP: diode extraction test. --- src/db/db/dbNetlistDeviceExtractorClasses.cc | 4 +- src/db/db/dbNetlistDeviceExtractorClasses.h | 4 +- src/db/db/dbNetlistExtractor.cc | 9 ++ src/db/unit_tests/dbNetlistExtractorTests.cc | 131 +++++++++++++++++++ testdata/algo/diode_devices_nets.gds | Bin 0 -> 5206 bytes testdata/algo/diode_devices_test.oas | Bin 0 -> 885 bytes 6 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 testdata/algo/diode_devices_nets.gds create mode 100644 testdata/algo/diode_devices_test.oas diff --git a/src/db/db/dbNetlistDeviceExtractorClasses.cc b/src/db/db/dbNetlistDeviceExtractorClasses.cc index 3714ea201..ef114cbb6 100644 --- a/src/db/db/dbNetlistDeviceExtractorClasses.cc +++ b/src/db/db/dbNetlistDeviceExtractorClasses.cc @@ -377,7 +377,7 @@ void NetlistDeviceExtractorCapacitor::extract_devices (const std::vector modify_device (*p, layer_geometry, device); // output the device for debugging - device_out (device, db::Region (*p)); + device_out (device, *p); } } diff --git a/src/db/db/dbNetlistDeviceExtractorClasses.h b/src/db/db/dbNetlistDeviceExtractorClasses.h index 05821fb31..50ab9eef0 100644 --- a/src/db/db/dbNetlistDeviceExtractorClasses.h +++ b/src/db/db/dbNetlistDeviceExtractorClasses.h @@ -193,7 +193,7 @@ protected: * @brief A callback when the device is produced * This callback is provided as a debugging port */ - virtual void device_out (const db::Device * /*device*/, const db::Region & /*cap_area*/) + virtual void device_out (const db::Device * /*device*/, const db::Polygon & /*cap_area*/) { // .. no specific implementation .. } @@ -308,7 +308,7 @@ protected: * @brief A callback when the device is produced * This callback is provided as a debugging port */ - virtual void device_out (const db::Device * /*device*/, const db::Region & /*diode_area*/) + virtual void device_out (const db::Device * /*device*/, const db::Polygon & /*diode_area*/) { // .. no specific implementation .. } diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 81e6ac0db..115580c83 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -105,6 +105,7 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo db::DeviceAbstract *dm = nl.device_abstract_by_cell_index (*cid); if (dm) { + // This is a device abstract cell: // make the terminal to cluster ID connections for the device abstract from the device cells make_device_abstract_connections (dm, clusters); continue; @@ -212,6 +213,14 @@ NetlistExtractor::make_device_abstract_connections (db::DeviceAbstract *dm, cons } } + + // check whether all connections have been made + const std::vector &td = dm->device_class ()->terminal_definitions (); + for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { + if (! dm->cluster_id_for_terminal (t->id ())) { + throw tl::Exception (tl::sprintf (tl::to_string (tr ("Terminal '%s' of a device of class '%s' isn't connected - maybe the terminal annotation layer of this device type isn't part of the connectivity?")), t->name (), dm->device_class ()->name ())); + } + } } void NetlistExtractor::collect_labels (const connected_clusters_type &clusters, diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index 3faf281bc..9d219670b 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -1597,3 +1597,134 @@ TEST(6_BipolarTransistorExtraction) db::compare_layouts (_this, ly, au); } +TEST(7_DiodeExtraction) +{ + db::Layout ly; + db::LayerMap lmap; + + unsigned int nwell = define_layer (ly, lmap, 1); + unsigned int active = define_layer (ly, lmap, 2); + unsigned int diff_cont = define_layer (ly, lmap, 4); + unsigned int metal1 = define_layer (ly, lmap, 6); + unsigned int metal1_lbl = define_layer (ly, lmap, 6, 1); + unsigned int pplus = define_layer (ly, lmap, 9); + unsigned int nplus = define_layer (ly, lmap, 10); + + { + db::LoadLayoutOptions options; + options.get_options ().layer_map = lmap; + options.get_options ().create_other_layers = false; + + std::string fn (tl::testsrc ()); + fn = tl::combine_path (fn, "testdata"); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "diode_devices_test.oas"); + + 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 rnwell (db::RecursiveShapeIterator (ly, tc, nwell), dss); + db::Region ractive (db::RecursiveShapeIterator (ly, tc, active), dss); + db::Region rdiff_cont (db::RecursiveShapeIterator (ly, tc, diff_cont), dss); + db::Region rmetal1 (db::RecursiveShapeIterator (ly, tc, metal1), dss); + db::Region rmetal1_lbl (db::RecursiveShapeIterator (ly, tc, metal1_lbl), dss); + db::Region rpplus (db::RecursiveShapeIterator (ly, tc, pplus), dss); + db::Region rnplus (db::RecursiveShapeIterator (ly, tc, nplus), dss); + + // derived regions + + db::Region rn = ractive & rnwell; + db::Region rntie = rnwell & rnplus; + + // return the computed layers into the original layout and write it for debugging purposes + + unsigned int ln = ly.insert_layer (db::LayerProperties (10, 0)); // 10/0 -> N layer + unsigned int lntie = ly.insert_layer (db::LayerProperties (11, 0)); // 11/0 -> N contact + rn.insert_into (&ly, tc.cell_index (), ln); + rntie.insert_into (&ly, tc.cell_index (), lntie); + + // perform the extraction + + db::Netlist nl; + db::hier_clusters cl; + + db::NetlistDeviceExtractorDiode diode_ex ("DIODE"); + + db::NetlistDeviceExtractor::input_layers dl; + + dl["N"] = &rn; + dl["P"] = &rpplus; + dl["tC"] = &rnwell; + diode_ex.extract (dss, 0, dl, nl, cl); + + + // perform the net extraction + + db::NetlistExtractor net_ex; + + db::Connectivity conn; + // Intra-layer + conn.connect (rnwell); + conn.connect (rntie); + conn.connect (rpplus); + conn.connect (rdiff_cont); + conn.connect (rmetal1); + // Inter-layer + conn.connect (rntie, rnwell); + conn.connect (rntie, rdiff_cont); + conn.connect (rpplus, rdiff_cont); + conn.connect (rdiff_cont, rmetal1); + conn.connect (rmetal1, rmetal1_lbl); // attaches labels + + // extract the nets + + net_ex.extract_nets (dss, 0, conn, nl, cl, "*"); + + // cleanup + completion + nl.combine_devices (); + nl.make_top_level_pins (); + nl.purge (); + + EXPECT_EQ (all_net_names_unique (nl), true); + + // debug layers produced for nets + // 201/0 -> n well + // 204/0 -> Diffusion contacts + // 206/0 -> Metal1 + // 210/0 -> N tiedown + std::map dump_map; + dump_map [layer_of (rntie) ] = ly.insert_layer (db::LayerProperties (210, 0)); + dump_map [layer_of (rnwell) ] = ly.insert_layer (db::LayerProperties (201, 0)); + dump_map [layer_of (rdiff_cont)] = ly.insert_layer (db::LayerProperties (204, 0)); + dump_map [layer_of (rmetal1) ] = ly.insert_layer (db::LayerProperties (206, 0)); + + // write nets to layout + db::CellMapping cm = dss.cell_mapping_to_original (0, &ly, tc.cell_index ()); + dump_nets_to_layout (nl, cl, ly, dump_map, cm, true /*with device cells*/); + + // compare netlist as string + CHECKPOINT (); + db::compare_netlist (_this, nl, + "circuit TOP (A=A,C=C);\n" + " device DIODE $1 (A=A,C=C) (A=9.18,P=21);\n" + "end;\n" + ); + + // compare the collected test data + + std::string au = tl::testsrc (); + au = tl::combine_path (au, "testdata"); + au = tl::combine_path (au, "algo"); + au = tl::combine_path (au, "diode_devices_nets.gds"); + + db::compare_layouts (_this, ly, au); +} diff --git a/testdata/algo/diode_devices_nets.gds b/testdata/algo/diode_devices_nets.gds new file mode 100644 index 0000000000000000000000000000000000000000..cd88cb5e8f59edf08ce66d907620972bd3764bf3 GIT binary patch literal 5206 zcmd6rKWG#|6vp3eZYOu~a>fwEKUXNE44BT?h|vg&K}D_*5wx%nD+>z?3k!<~78VwQ z7IrpbWs$Mo(A?sICyy?irA`{>TE@&x&Ye6n zcbur+ATpx~y(803h-hkT$lBFg{C^H58al`SJE|IoQhf*W!?fvGZDUR!?_TPjIeY0C z_Z}f?jpw7AJvAP)wKts|W5uu4NsqV#9OGJk)vdMHWUR6@pX18E(9PF5oz2rnf1bWC zVs5O38oul{--W8idG6diZOmKSn+9)fe;ItP8t+X9e2}N_U7nw-%y)@~d4To}RgFUf z{=I+wKW_8*J!_%;No#*T%T?pOUYtj6&<_e8*Q~1X&G`O;@KA8SU*rm2+T-J|wSRJ#vev_DCdyaX?*@%Z%kug3sFh{Co3H)OaX76g<|OD)_8D z%C|bgL&1%n$Q69n9^sL9ekA8b)0@aYUvs7!ug}Nk4|x|J3Xa$6Uj;AialXGGJQV!z z7rBC$_Bg-R5*`ZP&g2SS+G9NO4qi09iM)ds)p-2=x$lJVP;iE8fGYT`Ju?5uukcWC z&DXht&)TDWt0O!V{OE~X!DsD0|G|I$QFnR|q<*EJv-~^NI5e2Q2rs#E^^0=}mGf@J zbNyV>@uhyIpG7r3v=kqIiJ#xK>((xD9#QGBenmA76~6dBHOrG)cBhdV_#f?4L7iz{ z=6U$U>+3Sl5C2B)scPJ*zfJ<4NcsuI&&!k?)uuGQ8P98A8tqVU)~;Ms)%ZF-SZ6D* zxSjL7@`|}DY&iC*Y8)C{CsIdI3-CPATcT}URpwmWsek{$_}Evlm!Q6Yul-cj_~tzJ zXz;ujGcPq-RO30n#X4;m!(K{OXnXvxx8gO+Zi&w>KX)g*hP@u_zBcONyRohOmhk+X zMb^1%-@r4~f|}FCJe2Y*Nx-9K@p@YCxis$9nV-vg&f^*2xi0rCc)WNec#9IADc~!3 zrhu>DnF3xsk*vFdp2_2}SMvP!MBzCKc&31_;F$uxf@cc&3ZBX1D|x1Xui%*izJg~8 zc=1H8-mqsVXnF79oXA1ZVo+;ofcqWgR8dGvF^LUhJsXtkzF0z-J zyney!Fwc8o5zo_LOUm!|0bgM+4fqP4G2qMWg&SReg}vAtzmga5caHHZyW_ml9^>VGna}Uun@~sa{vzteb??&yL!0Y&1-#`1xdY%3NH99Od literal 0 HcmV?d00001 diff --git a/testdata/algo/diode_devices_test.oas b/testdata/algo/diode_devices_test.oas new file mode 100644 index 0000000000000000000000000000000000000000..22a46c8b66c72774fe261970093f79736b728cc4 GIT binary patch literal 885 zcmd^)y-or_6oqH@?vF5_Llv1-@9PEc*vPsEbD|nnNA{uhS3r#h9na0%UPd>~5HJ$?B}h0UVU37( z-aG{W6!MA4TE;bwbP$+2#Uzk5_V&C?-f}@?)@(^6>zHi-%$y050G~hVk$BHcN#vaF zYGx8-zG=b)jtmVHCjP)UnSwb#Ib;$VcBMR1+tp3x;?OT;oJo!|vY(k!h-BO5p#uRn zeuC^zLp8`%ABi+thPdiuSfG~zYNxAeZMzw#UGZM1q-rXb(T(!9OzX{fM-a@wTM~cSuv@tP&j+Dz Df^i6N literal 0 HcmV?d00001