diff --git a/src/lvs/unit_tests/lvsBasicTests.cc b/src/lvs/unit_tests/lvsBasicTests.cc index 7f710ecf8..1d221ac56 100644 --- a/src/lvs/unit_tests/lvsBasicTests.cc +++ b/src/lvs/unit_tests/lvsBasicTests.cc @@ -124,39 +124,106 @@ TEST(1) compare_text_files (output_lvsdb, au_lvsdb); } -#if 0 TEST(2) { + std::string input = tl::testsrc (); + input += "/testdata/lvs/inv2.oas"; + std::string schematic = "inv2.cir"; // relative to inv2.oas + std::string au_cir = tl::testsrc (); + au_cir += "/testdata/lvs/inv2_layout.cir"; + std::string au_lvsdb = tl::testsrc (); + au_lvsdb += "/testdata/lvs/inv2.lvsdb"; + + std::string output_cir = this->tmp_file ("tmp.cir"); + std::string output_lvsdb = this->tmp_file ("tmp.lvsdb"); + lym::Macro lvs; - lvs.set_text ( - "dbu 0.001\n" - "def compare(a, b, ex)\n" - " a = a.to_s\n" - " b = b.to_s\n" - " if a != b\n" - " raise(ex + \" (actual=#{a}, ref=#{b})\")\n" - " end\n" - "end\n" - "compare(0.1.um, 0.1, \"unexpected value when converting um\")\n" - "compare(0.1.micron, 0.1, \"unexpected value when converting micron\")\n" - "compare(0.1.um2, 0.1, \"unexpected value when converting um2\")\n" - "compare(0.1.mm2, 100000.0, \"unexpected value when converting mm2\")\n" - "compare(120.dbu, 0.12, \"unexpected value when converting dbu\")\n" - "compare((0.1.um + 120.dbu), 0.22, \"unexpected value when adding values\")\n" - "compare(0.1.mm, 100.0, \"unexpected value when converting mm\")\n" - "compare(1e-6.m, 1.0, \"unexpected value when converting m\")\n" - "compare(1.um, 1.0, \"unexpected value when converting integer um\")\n" - "compare(1.micron, 1.0, \"unexpected value when convering integer micron\")\n" - "compare(1.um2, 1.0, \"unexpected value when converting integer um2\")\n" - "compare(1.mm2, 1000000.0, \"unexpected value when converting integer mm2\")\n" - "compare((1.um + 120.dbu), 1.12, \"unexpected value when adding integer values\")\n" - "compare(1.mm, 1000.0, \"unexpected value when converting integer mm\")\n" - "compare(1.m, 1000000.0, \"unexpected value when converting integer m\")\n" + lvs.set_text (tl::sprintf ( + "source('%s', 'INVERTER_WITH_DIODES')\n" + "\n" + "deep\n" + "\n" + "# Reports generated\n" + "\n" + "# LVS report to inv.lvsdb\n" + "report_lvs('%s')\n" + "\n" + "# Write extracted netlist to inv_extracted.cir\n" + "target_netlist('%s', write_spice, 'Extracted by KLayout')\n" + "\n" + "# Drawing layers\n" + "\n" + "nwell = input(1, 0)\n" + "active = input(2, 0)\n" + "pplus = input(3, 0)\n" + "nplus = input(4, 0)\n" + "poly = input(5, 0)\n" + "contact = input(6, 0)\n" + "metal1 = input(7, 0)\n" + "metal1_lbl = labels(7, 1)\n" + "via1 = input(8, 0)\n" + "metal2 = input(9, 0)\n" + "metal2_lbl = labels(9, 1)\n" + "\n" + "# Bulk layer for terminal provisioning\n" + "\n" + "bulk = polygon_layer\n" + "\n" + "# Computed layers\n" + "\n" + "active_in_nwell = active & nwell\n" + "pactive = active_in_nwell & pplus\n" + "pgate = pactive & poly\n" + "psd = pactive - pgate\n" + "ntie = active_in_nwell & nplus\n" + "\n" + "active_outside_nwell = active - nwell\n" + "nactive = active_outside_nwell & nplus\n" + "ngate = nactive & poly\n" + "nsd = nactive - ngate\n" + "ptie = active_outside_nwell & pplus\n" + "\n" + "# Device extraction\n" + "\n" + "# PMOS transistor device extraction\n" + "extract_devices(mos4('PMOS'), { 'SD' => psd, 'G' => pgate, 'W' => nwell, \n" + " 'tS' => psd, 'tD' => psd, 'tG' => poly, 'tW' => nwell })\n" + "\n" + "# NMOS transistor device extraction\n" + "extract_devices(mos4('NMOS'), { 'SD' => nsd, 'G' => ngate, 'W' => bulk, \n" + " 'tS' => nsd, 'tD' => nsd, 'tG' => poly, 'tW' => bulk })\n" + "\n" + "# Define connectivity for netlist extraction\n" + "\n" + "# Inter-layer\n" + "connect(psd, contact)\n" + "connect(nsd, contact)\n" + "connect(poly, contact)\n" + "connect(ntie, contact)\n" + "connect(nwell, ntie)\n" + "connect(ptie, contact)\n" + "connect(contact, metal1)\n" + "connect(metal1, metal1_lbl) # attaches labels\n" + "connect(metal1, via1)\n" + "connect(via1, metal2)\n" + "connect(metal2, metal2_lbl) # attaches labels\n" + "\n" + "# Global\n" + "connect_global(bulk, 'SUBSTRATE')\n" + "connect_global(ptie, 'SUBSTRATE')\n" + "\n" + "# Compare section\n" + "\n" + "schematic('%s')\n" + "\n" + "compare\n" + , input, output_lvsdb, output_cir, schematic) ); lvs.set_interpreter (lym::Macro::DSLInterpreter); lvs.set_dsl_interpreter ("lvs-dsl"); EXPECT_EQ (lvs.run (), 0); -} -#endif + compare_text_files (output_cir, au_cir); + compare_text_files (output_lvsdb, au_lvsdb); +} diff --git a/testdata/lvs/inv2.lvsdb b/testdata/lvs/inv2.lvsdb new file mode 100644 index 000000000..2fb4b7e4e --- /dev/null +++ b/testdata/lvs/inv2.lvsdb @@ -0,0 +1,244 @@ +#%lvsdb-klayout + +# Layout +layout( + top(INVERTER_WITH_DIODES) + unit(0.001) + + # Layer section + # This section lists the mask layers (drawing or derived) and their connections. + + # Mask layers + layer(l103 'NWELL (1/0)') + layer(l108 'POLY (5/0)') + layer(l109 'CONTACT (6/0)') + layer(l110 'METAL1 (7/0)') + layer(l111 'METAL1_LABEL (7/1)') + layer(l112 'VIA1 (8/0)') + layer(l113 'METAL2 (9/0)') + layer(l114 'METAL2_LABEL (9/1)') + layer(l115) + layer(l123) + layer(l125) + layer(l133) + layer(l135) + + # Mask layer connectivity + connect(l103 l103 l125) + connect(l108 l108 l109) + connect(l109 l108 l109 l110 l123 l125 l133 l135) + connect(l110 l109 l110 l111 l112) + connect(l111 l110 l111) + connect(l112 l110 l112 l113) + connect(l113 l112 l113 l114) + connect(l114 l113 l114) + connect(l115 l115) + connect(l123 l109 l123) + connect(l125 l103 l109 l125) + connect(l133 l109 l133) + connect(l135 l109 l135) + + # Global nets and connectivity + global(l115 SUBSTRATE) + global(l135 SUBSTRATE) + + # Device class section + class(PMOS MOS4) + class(NMOS MOS4) + + # Device abstracts section + # Device abstracts list the pin shapes of the devices. + device(D$PMOS PMOS + terminal(S + rect(l123 (-575 -750) (450 1500)) + ) + terminal(G + rect(l108 (-125 -750) (250 1500)) + ) + terminal(D + rect(l123 (125 -750) (450 1500)) + ) + terminal(B + rect(l103 (-125 -750) (250 1500)) + ) + ) + device(D$NMOS NMOS + terminal(S + rect(l133 (-575 -450) (450 900)) + ) + terminal(G + rect(l108 (-125 -450) (250 900)) + ) + terminal(D + rect(l133 (125 -450) (450 900)) + ) + terminal(B + rect(l115 (-125 -450) (250 900)) + ) + ) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(INVERTER_WITH_DIODES + + # Nets with their geometries + net(1 name(IN) + rect(l108 (900 50) (250 1050)) + rect(l108 (-250 0) (250 3100)) + rect(l108 (-250 0) (250 1650)) + rect(l108 (-800 -3100) (550 400)) + rect(l109 (-450 -300) (200 200)) + rect(l110 (-300 -300) (400 400)) + rect(l111 (-201 -201) (2 2)) + ) + net(2 name(VDD) + rect(l103 (0 2950) (3000 3200)) + rect(l109 (-2450 -1800) (200 200)) + rect(l109 (-200 300) (200 200)) + rect(l109 (-200 300) (200 200)) + rect(l109 (1400 -800) (200 200)) + rect(l109 (-200 300) (200 200)) + rect(l110 (-1850 -1200) (300 1600)) + rect(l110 (1300 -1200) (300 1200)) + rect(l112 (-1850 -800) (200 200)) + rect(l112 (-200 300) (200 200)) + rect(l112 (1400 -700) (200 200)) + rect(l112 (-200 300) (200 200)) + rect(l113 (-2350 -850) (3000 1000)) + rect(l114 (-151 -851) (2 2)) + rect(l123 (-2401 -851) (450 1500)) + rect(l125 (1050 -1200) (600 1200)) + ) + net(3 name(OUT) + rect(l109 (1300 4350) (200 200)) + rect(l109 (-200 300) (200 200)) + rect(l109 (-200 300) (200 200)) + rect(l109 (-200 -5250) (200 200)) + rect(l109 (-200 300) (200 200)) + rect(l110 (-250 3250) (300 1400)) + rect(l110 (-300 -4600) (300 3200)) + rect(l110 (-300 -2900) (450 400)) + rect(l110 (-450 -1550) (300 850)) + rect(l111 (-51 499) (2 2)) + rect(l123 (-351 2649) (450 1500)) + rect(l133 (-450 -5500) (450 900)) + ) + net(4 name(VSS) + rect(l109 (550 300) (200 200)) + rect(l109 (-200 300) (200 200)) + rect(l109 (1400 -550) (200 200)) + rect(l109 (-200 300) (200 200)) + rect(l110 (-1850 -1100) (300 1050)) + rect(l110 (1300 -1050) (300 1200)) + rect(l112 (-1850 -1100) (200 200)) + rect(l112 (-200 300) (200 200)) + rect(l112 (1400 -700) (200 200)) + rect(l112 (-200 300) (200 200)) + rect(l113 (-2350 -850) (3000 1000)) + rect(l114 (-151 -851) (2 2)) + rect(l133 (-2401 49) (450 900)) + rect(l135 (1050 -900) (600 1200)) + ) + + # Devices and their connections + device(1 D$PMOS + location(1025 4950) + param(L 0.25) + param(W 1.5) + param(AS 0.675) + param(AD 0.675) + param(PS 3.9) + param(PD 3.9) + terminal(S 2) + terminal(G 1) + terminal(D 3) + terminal(B 2) + ) + device(2 D$NMOS + location(1025 650) + param(L 0.25) + param(W 0.9) + param(AS 0.405) + param(AD 0.405) + param(PS 2.7) + param(PD 2.7) + terminal(S 4) + terminal(G 1) + terminal(D 3) + terminal(B 4) + ) + + ) +) + +# Reference netlist +reference( + + # Device class section + class(PMOS MOS4) + class(NMOS MOS4) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(INVERTER_WITH_DIODES + + # Nets + net(1 name(VSS)) + net(2 name(IN)) + net(3 name(OUT)) + net(4 name(VDD)) + + # Outgoing pins and their connections to nets + pin(1) + pin(2) + pin(3) + pin(4) + + # Devices and their connections + device(1 PMOS + name(P) + param(L 0.25) + param(W 1.5) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 4) + terminal(G 2) + terminal(D 3) + terminal(B 4) + ) + device(2 NMOS + name(N) + param(L 0.25) + param(W 0.9) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 3) + terminal(G 2) + terminal(D 1) + terminal(B 1) + ) + + ) +) + +# Cross reference +xref( + circuit(INVERTER_WITH_DIODES INVERTER_WITH_DIODES match + xref( + net(1 2 match) + net(3 3 match) + net(2 4 match) + net(4 1 match) + pin(() 0 match) + pin(() 1 match) + pin(() 2 match) + pin(() 3 match) + device(2 2 match) + device(1 1 match) + ) + ) +) diff --git a/testdata/lvs/inv2_layout.cir b/testdata/lvs/inv2_layout.cir new file mode 100644 index 000000000..f55adc82a --- /dev/null +++ b/testdata/lvs/inv2_layout.cir @@ -0,0 +1,13 @@ +* Extracted by KLayout + +* cell INVERTER_WITH_DIODES +.SUBCKT INVERTER_WITH_DIODES +* net 1 IN +* net 2 VDD +* net 3 OUT +* net 4 VSS +* device instance $1 r0 *1 1.025,4.95 PMOS +M$1 2 1 3 2 PMOS L=0.25U W=1.5U AS=0.675P AD=0.675P PS=3.9U PD=3.9U +* device instance $2 r0 *1 1.025,0.65 NMOS +M$2 4 1 3 4 NMOS L=0.25U W=0.9U AS=0.405P AD=0.405P PS=2.7U PD=2.7U +.ENDS INVERTER_WITH_DIODES