diff --git a/src/db/db/dbNetlistSpiceWriter.cc b/src/db/db/dbNetlistSpiceWriter.cc index 171945acd..3cc5cd92d 100644 --- a/src/db/db/dbNetlistSpiceWriter.cc +++ b/src/db/db/dbNetlistSpiceWriter.cc @@ -249,6 +249,7 @@ void NetlistSpiceWriterDelegate::write_device_profile (const db::Device &dev, co } if (! direct_value.is_nil ()) { + os << " "; write_parameter_value (os, direct_value, 1.0); } diff --git a/src/db/db/gsiDeclDbNetlistDeviceClass.cc b/src/db/db/gsiDeclDbNetlistDeviceClass.cc index a05d40236..e3229f001 100644 --- a/src/db/db/gsiDeclDbNetlistDeviceClass.cc +++ b/src/db/db/gsiDeclDbNetlistDeviceClass.cc @@ -350,6 +350,19 @@ Class decl_dbDeviceClassSpiceProfile ("db", "Devi "The terminal order is a list of terminal names that specifies which device terminal to tie to the " "nets given in the SPICE statement. The list items must be strings corresponding to valid terminal " "names of the device." + "\n" + "Note, that the terminal order attribute is a copy. In order to manipulate it, you need " + "to change the copy and put it back again:\n" + "\n" + "@code\n" + "# adds a new terminal 'B' to the terminal order of the default SPICE profile of a device class:\n" + "cls = ... # some device class\n" + "sp = cls.spice_profile('')\n" + "term = sp.terminal_order\n" + "term.append('B')\n" + "sp.terminal_order = term\n" + "cls.set_spice_profile('', sp)\n" + "@/code\n" ) + gsi::method_ext ("terminal_order=", &set_terminal_order, "@brief Sets the terminal order to use for this device.\n" @@ -391,6 +404,19 @@ Class decl_dbDeviceClassSpiceProfile ("db", "Devi "device or the default value is used if the parameter is a declared one.\n" "An empty expression string is equal to \"nil\", so you can drop a parameter\n" "by mapping the name to an empty string, e.g. '\"M\": \"\"' (drops \"M\").\n" + "\n" + "Note, that the incoming parameter hash is a copy. In order to manipulate it, you " + "need get and set it:\n" + "\n" + "@code\n" + "# adds a new incoming parameter called 'P' to a device classes default SPICE profile:\n" + "cls = ... # some device class\n" + "sp = cls.spice_profile('')\n" + "par = sp.incoming_parameters\n" + "par['P'] = 'P*2.0'\n" + "sp.incoming_parameters = par\n" + "cls.set_spice_profile('', sp)\n" + "@/code\n" ) + gsi::method_ext ("incoming_parameters=", &set_incoming_parameters, "@brief Sets the mapping of incoming parameters from SPICE files\n" @@ -419,6 +445,16 @@ Class decl_dbDeviceClassSpiceProfile ("db", "Devi "how the value of the parameter is computed from device parameters.\n" "\"_\" is the value of the same SPICE parameter. This is useful for generating\n" "catch-all rules, such as '\"*\": \"_\"' (copy all parameters).\n" + "\n" + "@code\n" + "# adds a new outgoing parameter called 'P' to a device classes default SPICE profile:\n" + "cls = ... # some device class\n" + "sp = cls.spice_profile('')\n" + "par = sp.outgoing_parameters\n" + "par['P'] = 'P*2.0'\n" + "sp.outgoing_parameters = par\n" + "cls.set_spice_profile('', sp)\n" + "@/code\n" ) + gsi::method_ext ("outgoing_parameters=", &set_outgoing_parameters, "@brief Sets the mapping tables for outgoing parameters\n" diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc index e248cee48..ae092428e 100644 --- a/src/lvs/unit_tests/lvsSimpleTests.cc +++ b/src/lvs/unit_tests/lvsSimpleTests.cc @@ -247,6 +247,7 @@ TEST(25_blackbox) TEST(26_enableWandL) { run_test (_this, "enable_wl1", "resistor.gds"); + run_test (_this, "enable_wl1b", "resistor.gds"); run_test (_this, "enable_wl2", "resistor.gds"); run_test (_this, "enable_wl3", "resistor.gds"); } diff --git a/testdata/lvs/enable_wl1b.cir b/testdata/lvs/enable_wl1b.cir new file mode 100644 index 000000000..d668c488e --- /dev/null +++ b/testdata/lvs/enable_wl1b.cir @@ -0,0 +1,11 @@ +* Extracted by KLayout + +* cell Rre +* pin gnd! +* pin vdd! +.SUBCKT Rre 1 2 +* net 1 gnd! +* net 2 vdd! +* device instance $1 r0 *1 8.43,1.51 RR1 +R$1 1 2 10 RR1 L=6U W=0.6U +.ENDS Rre diff --git a/testdata/lvs/enable_wl1b.lvs b/testdata/lvs/enable_wl1b.lvs new file mode 100644 index 000000000..c46f98fb6 --- /dev/null +++ b/testdata/lvs/enable_wl1b.lvs @@ -0,0 +1,36 @@ + +source($lvs_test_source) +report_lvs($lvs_test_target_lvsdb, true) +target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") + +schematic("resistor.cir") + +deep + +contact = input(15, 0) +metal1 = input(16, 0) +metal1_ver = input(16, 5) +metal1_lbl = labels(16, 3) +res = metal1 & metal1_ver +metal1_not_res = metal1 - metal1_ver + +dc = extract_devices(resistor("RR1", 1), { "R" => res , "C" => metal1_not_res}) +dc.enable_parameter("W", true) +dc.enable_parameter("L", true) +sp = dc.spice_profile("") +sp.outgoing_parameters = { + "R" => "", # drop + "W" => "W", + "L" => "L", + "$" => "R" # direct value +} +dc.set_spice_profile("", sp) + +connect(contact, metal1_not_res) +connect(metal1_not_res, metal1_lbl) + +align +netlist.make_top_level_pins(false) +netlist.simplify +compare + diff --git a/testdata/lvs/enable_wl1b.lvsdb b/testdata/lvs/enable_wl1b.lvsdb new file mode 100644 index 000000000..67695b612 --- /dev/null +++ b/testdata/lvs/enable_wl1b.lvsdb @@ -0,0 +1,118 @@ +#%lvsdb-klayout + +# Layout +layout( + top(Rre) + unit(0.001) + + # Layer section + # This section lists the mask layers (drawing or derived) and their connections. + + # Mask layers + layer(l3 '15/0') + layer(l4 '16/3') + layer(l1) + + # Mask layer connectivity + connect(l3 l3 l1) + connect(l4 l1) + connect(l1 l3 l4 l1) + + # Device class section + class(RR1 RES + param(L 1 0) + param(W 1 0) + ) + + # Device abstracts section + # Device abstracts list the pin shapes of the devices. + device(D$RR1 RR1 + terminal(A + rect(l1 (-3160 -300) (160 600)) + ) + terminal(B + rect(l1 (3000 -300) (160 600)) + ) + ) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(Rre + + # Circuit boundary + rect((5270 1210) (6320 600)) + + # Nets with their geometries + net(1 name('gnd!') + rect(l3 (5295 1230) (120 560)) + text(l4 'gnd!' (-60 -60)) + rect(l1 (-70 -505) (125 570)) + rect(l1 (-140 -585) (160 600)) + ) + net(2 name('vdd!') + rect(l3 (11455 1240) (120 540)) + text(l4 'vdd!' (-65 -60)) + rect(l1 (-65 -495) (125 560)) + rect(l1 (-140 -575) (160 600)) + ) + + # Outgoing pins and their connections to nets + pin(1 name('gnd!')) + pin(2 name('vdd!')) + + # Devices and their connections + device(1 D$RR1 + location(8430 1510) + param(R 10) + param(L 6) + param(W 0.6) + param(A 3.6) + param(P 13.2) + terminal(A 1) + terminal(B 2) + ) + + ) +) + +# Reference netlist +reference( + + # Device class section + class(RR1 RES) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(RRE + + # Nets + net(1 name('VDD!')) + net(2 name('GND!')) + + # Devices and their connections + device(1 RR1 + name(R0) + param(R 10) + param(L 6) + param(W 0.6) + param(A 0) + param(P 0) + terminal(A 1) + terminal(B 2) + ) + + ) +) + +# Cross reference +xref( + circuit(Rre RRE match + xref( + net(1 2 match) + net(2 1 match) + pin(0 () match) + pin(1 () match) + device(1 1 match) + ) + ) +)