Some enhancements

* Device#net_for_terminal with terminal name
* Spice writer now dumps all parameters for resistors and caps (also secondary)
* Enabled Spice writer delegate in LVS (spice_format(...))
* Device class factories for built-in device extractors
This commit is contained in:
Matthias Koefferlein 2021-07-05 22:22:13 +02:00
parent ba35ac9bfe
commit e34fc8967a
18 changed files with 665 additions and 25 deletions

View File

@ -117,6 +117,7 @@ void NetlistSpiceWriterDelegate::write_device (const db::Device &dev) const
os << " ";
os << format_name (dev.device_class ()->name ());
}
os << format_params (dev, db::DeviceClassCapacitor::param_id_C);
} else if (ind) {
@ -129,6 +130,7 @@ void NetlistSpiceWriterDelegate::write_device (const db::Device &dev) const
os << " ";
os << format_name (dev.device_class ()->name ());
}
os << format_params (dev, db::DeviceClassInductor::param_id_L);
} else if (res || res3) {
@ -141,6 +143,7 @@ void NetlistSpiceWriterDelegate::write_device (const db::Device &dev) const
os << " ";
os << format_name (dev.device_class ()->name ());
}
os << format_params (dev, db::DeviceClassResistor::param_id_R);
} else if (diode) {

View File

@ -251,6 +251,24 @@ static void add_other_abstracts (db::Device *device, const db::DeviceAbstractRef
device->other_abstracts ().push_back (ref);
}
static const db::Net *net_for_terminal_by_name_const (const db::Device *device, const std::string &name)
{
if (! device->device_class () || ! device->device_class ()->has_terminal_with_name (name)) {
return 0;
} else {
return device->net_for_terminal (device->device_class ()->terminal_id_for_name (name));
}
}
static const db::Net *net_for_terminal_by_name (db::Device *device, const std::string &name)
{
if (! device->device_class () || ! device->device_class ()->has_terminal_with_name (name)) {
return 0;
} else {
return device->net_for_terminal (device->device_class ()->terminal_id_for_name (name));
}
}
Class<db::Device> decl_dbDevice (decl_dbNetlistObject, "db", "Device",
gsi::method ("device_class", &db::Device::device_class,
"@brief Gets the device class the device belongs to.\n"
@ -337,6 +355,18 @@ Class<db::Device> decl_dbDevice (decl_dbNetlistObject, "db", "Device",
"\n\n"
"This constness variant has been introduced in version 0.26.8"
) +
gsi::method_ext ("net_for_terminal", net_for_terminal_by_name_const, gsi::arg ("terminal_name"),
"@brief Gets the net connected to the specified terminal.\n"
"If the terminal is not connected, nil is returned for the net."
"\n\n"
"This convenience method has been introduced in version 0.27.3.\n"
) +
gsi::method_ext ("net_for_terminal", net_for_terminal_by_name, gsi::arg ("terminal_name"),
"@brief Gets the net connected to the specified terminal (non-const version).\n"
"If the terminal is not connected, nil is returned for the net."
"\n\n"
"This convenience method has been introduced in version 0.27.3.\n"
) +
gsi::method ("connect_terminal", &db::Device::connect_terminal, gsi::arg ("terminal_id"), gsi::arg ("net"),
"@brief Connects the given terminal to the specified net.\n"
) +

View File

@ -4,6 +4,15 @@ require 'pathname'
module DRC
class CustomDeviceClassFactory < RBA::DeviceClassFactory
def initialize(cls)
@cls = cls
end
def create_class
@cls.new
end
end
# The DRC engine
# %DRC%
@ -308,22 +317,57 @@ module DRC
# @brief Defines SPICE output format (with options)
# @name write_spice
# @synopsis write_spice([ use_net_names [, with_comments ] ])
# @synopsis write_spice(writer_delegate [, use_net_names [, with_comments ] ])
# Use this option in \target_netlist for the format parameter to
# specify SPICE format.
# "use_net_names" and "with_comments" are boolean parameters indicating
# whether to use named nets (numbers if false) and whether to add
# information comments such as instance coordinates or pin names.
#
# "writer_delegate" allows using a \NetlistSpiceWriterDelegate object to
# control the actual writing.
def write_spice(*args)
def write_spice(use_net_names = nil, with_comments = nil)
self._context("write_spice") do
writer = RBA::NetlistSpiceWriter::new
delegate = nil
use_net_names = nil
with_comments = nil
args.each do |a|
if (a == false || a == true) && (use_net_names == nil || with_comments == nil)
if use_net_names == nil
use_net_names = a
else
with_comments = a
end
elsif a.is_a?(RBA::NetlistSpiceWriterDelegate)
delegate = a
else
raise("Too many arguments specified or argument is of wrong type: " + a.inspect)
end
end
writer = RBA::NetlistSpiceWriter::new(delegate)
if use_net_names != nil
writer.use_net_names = use_net_names
end
if with_comments != nil
writer.with_comments = with_comments
end
writer
end
end
def _make_factory(cls)
if !cls
return nil
elsif !cls.is_a?(Class)
raise("Expected a class object for the 'class' argument of device extractors")
else
CustomDeviceClassFactory::new(cls)
end
end
@ -331,15 +375,16 @@ module DRC
# @brief Supplies the MOS3 transistor extractor class
# @name mos3
# @synopsis mos3(name)
# @synopsis mos3(name, class)
# Use this class with \extract_devices to specify extraction of a
# three-terminal MOS transistor.
#
# See RBA::DeviceExtractorMOS3Transistor for more details
# about this extractor (non-strict mode applies for 'mos3').
def mos3(name)
def mos3(name, cls = nil)
self._context("mos3") do
RBA::DeviceExtractorMOS3Transistor::new(name)
RBA::DeviceExtractorMOS3Transistor::new(name, false, _make_factory(cls))
end
end
@ -347,15 +392,16 @@ module DRC
# @brief Supplies the MOS4 transistor extractor class
# @name mos4
# @synopsis mos4(name)
# @synopsis mos4(name, class)
# Use this class with \extract_devices to specify extraction of a
# four-terminal MOS transistor.
#
# See RBA::DeviceExtractorMOS4Transistor for more details
# about this extractor (non-strict mode applies for 'mos4').
def mos4(name)
def mos4(name, cls = nil)
self._context("mos4") do
RBA::DeviceExtractorMOS4Transistor::new(name)
RBA::DeviceExtractorMOS4Transistor::new(name, false, _make_factory(cls))
end
end
@ -363,6 +409,7 @@ module DRC
# @brief Supplies the DMOS3 transistor extractor class
# @name dmos3
# @synopsis dmos3(name)
# @synopsis dmos3(name, class)
# Use this class with \extract_devices to specify extraction of a
# three-terminal DMOS transistor. A DMOS transistor is essentially
# the same than a MOS transistor, but source and drain are
@ -371,9 +418,9 @@ module DRC
# See RBA::DeviceExtractorMOS3Transistor for more details
# about this extractor (strict mode applies for 'dmos3').
def dmos3(name)
def dmos3(name, cls = nil)
self._context("dmos3") do
RBA::DeviceExtractorMOS3Transistor::new(name, true)
RBA::DeviceExtractorMOS3Transistor::new(name, true, _make_factory(cls))
end
end
@ -381,6 +428,7 @@ module DRC
# @brief Supplies the MOS4 transistor extractor class
# @name dmos4
# @synopsis dmos4(name)
# @synopsis dmos4(name, class)
# Use this class with \extract_devices to specify extraction of a
# four-terminal DMOS transistor. A DMOS transistor is essentially
# the same than a MOS transistor, but source and drain are
@ -389,9 +437,9 @@ module DRC
# See RBA::DeviceExtractorMOS4Transistor for more details
# about this extractor (strict mode applies for 'dmos4').
def dmos4(name)
def dmos4(name, cls = nil)
self._context("dmos4") do
RBA::DeviceExtractorMOS4Transistor::new(name, true)
RBA::DeviceExtractorMOS4Transistor::new(name, true, _make_factory(cls))
end
end
@ -399,15 +447,16 @@ module DRC
# @brief Supplies the BJT3 transistor extractor class
# @name bjt3
# @synopsis bjt3(name)
# @synopsis bjt3(name, class)
# Use this class with \extract_devices to specify extraction of a
# bipolar junction transistor
#
# See RBA::DeviceExtractorBJT3Transistor for more details
# about this extractor.
def bjt3(name)
def bjt3(name, cls = nil)
self._context("bjt3") do
RBA::DeviceExtractorBJT3Transistor::new(name)
RBA::DeviceExtractorBJT3Transistor::new(name, _make_factory(cls))
end
end
@ -415,15 +464,16 @@ module DRC
# @brief Supplies the BJT4 transistor extractor class
# @name bjt4
# @synopsis bjt4(name)
# @synopsis bjt4(name, class)
# Use this class with \extract_devices to specify extraction of a
# bipolar junction transistor with a substrate terminal
#
# See RBA::DeviceExtractorBJT4Transistor for more details
# about this extractor.
def bjt4(name)
def bjt4(name, cls = nil)
self._context("bjt4") do
RBA::DeviceExtractorBJT4Transistor::new(name)
RBA::DeviceExtractorBJT4Transistor::new(name, _make_factory(cls))
end
end
@ -431,15 +481,16 @@ module DRC
# @brief Supplies the diode extractor class
# @name diode
# @synopsis diode(name)
# @synopsis diode(name, class)
# Use this class with \extract_devices to specify extraction of a
# planar diode
#
# See RBA::DeviceExtractorDiode for more details
# about this extractor.
def diode(name)
def diode(name, cls = nil)
self._context("diode") do
RBA::DeviceExtractorDiode::new(name)
RBA::DeviceExtractorDiode::new(name, _make_factory(cls))
end
end
@ -447,6 +498,7 @@ module DRC
# @brief Supplies the resistor extractor class
# @name resistor
# @synopsis resistor(name, sheet_rho)
# @synopsis resistor(name, sheet_rho, class)
# Use this class with \extract_devices to specify extraction of a resistor.
#
# The sheet_rho value is the sheet resistance in ohms/square. It is used
@ -455,9 +507,9 @@ module DRC
# See RBA::DeviceExtractorResistor for more details
# about this extractor.
def resistor(name, sheet_rho)
def resistor(name, sheet_rho, cls = nil)
self._context("resistor") do
RBA::DeviceExtractorResistor::new(name, sheet_rho)
RBA::DeviceExtractorResistor::new(name, sheet_rho, _make_factory(cls))
end
end
@ -465,6 +517,7 @@ module DRC
# @brief Supplies the resistor extractor class that includes a bulk terminal
# @name resistor_with_bulk
# @synopsis resistor_with_bulk(name, sheet_rho)
# @synopsis resistor_with_bulk(name, sheet_rho, class)
# Use this class with \extract_devices to specify extraction of a resistor
# with a bulk terminal.
# The sheet_rho value is the sheet resistance in ohms/square.
@ -472,9 +525,9 @@ module DRC
# See RBA::DeviceExtractorResistorWithBulk for more details
# about this extractor.
def resistor_with_bulk(name, sheet_rho)
def resistor_with_bulk(name, sheet_rho, cls = nil)
self._context("resistor_with_bulk") do
RBA::DeviceExtractorResistorWithBulk::new(name, sheet_rho)
RBA::DeviceExtractorResistorWithBulk::new(name, sheet_rho, _make_factory(cls))
end
end
@ -482,15 +535,16 @@ module DRC
# @brief Supplies the capacitor extractor class
# @name capacitor
# @synopsis capacitor(name, area_cap)
# @synopsis capacitor(name, area_cap, class)
# Use this class with \extract_devices to specify extraction of a capacitor.
# The area_cap argument is the capacitance in Farad per square micrometer.
#
# See RBA::DeviceExtractorCapacitor for more details
# about this extractor.
def capacitor(name, area_cap)
def capacitor(name, area_cap, cls = nil)
self._context("capacitor") do
RBA::DeviceExtractorCapacitor::new(name, area_cap)
RBA::DeviceExtractorCapacitor::new(name, area_cap, _make_factory(cls))
end
end
@ -498,6 +552,7 @@ module DRC
# @brief Supplies the capacitor extractor class that includes a bulk terminal
# @name capacitor_with_bulk
# @synopsis capacitor_with_bulk(name, area_cap)
# @synopsis capacitor_with_bulk(name, area_cap, class)
# Use this class with \extract_devices to specify extraction of a capacitor
# with a bulk terminal.
# The area_cap argument is the capacitance in Farad per square micrometer.
@ -505,9 +560,9 @@ module DRC
# See RBA::DeviceExtractorCapacitorWithBulk for more details
# about this extractor.
def capacitor_with_bulk(name, area_cap)
def capacitor_with_bulk(name, area_cap, cls = nil)
self._context("capacitor_with_bulk") do
RBA::DeviceExtractorCapacitorWithBulk::new(name, area_cap)
RBA::DeviceExtractorCapacitorWithBulk::new(name, area_cap, _make_factory(cls))
end
end

View File

@ -376,5 +376,33 @@ dc.enable_parameter("L", true)
fully enabled parameters.
</p>
<p>
Another way of customizing the built-in device extractors is to
supply a custom device class. The following code creates a new
resistor class which changes the preconfigured device parameter definitions
to enable "W" and "L".
</p>
<pre>class MyResistor &lt; RBA::DeviceClassResistor
def initialize
super
enable_parameter("W", true)
enable_parameter("L", true)
end
end
...
extract_devices(resistor("RES", 1, MyResistor), ...)
</pre>
<p>
The effect of this code is the same than the first one, but using a custom
device class opens the option to supply additional parameters for example
or to implement some entirely new device while using the extraction
mechanics of the resistor extractor. The only requirement is compatibility of
the parameter and terminal definitions.
</p>
</doc>

View File

@ -206,8 +206,14 @@ TEST(23_issue709)
run_test (_this, "empty_subcells", "empty_subcells.gds");
}
// empty gds
TEST(24_issue806)
{
run_test (_this, "custom_compare", "custom_compare.gds");
}
TEST(25_enableWandL)
{
run_test (_this, "enable_wl1", "resistor.gds");
run_test (_this, "enable_wl2", "resistor.gds");
run_test (_this, "enable_wl3", "resistor.gds");
}

11
testdata/lvs/enable_wl1.cir vendored Normal file
View File

@ -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 RR1 10 W=0.6 L=6
.ENDS Rre

52
testdata/lvs/enable_wl1.lvs vendored Normal file
View File

@ -0,0 +1,52 @@
# test spice writer delegate on this occasion
class MyWriterDelegate < RBA::NetlistSpiceWriterDelegate
def write_device(device)
if device.device_class.name == "RR1"
line = "R"
line += format_name(device.expanded_name)
line += " "
line += net_to_string(device.net_for_terminal("A"))
line += " "
line += net_to_string(device.net_for_terminal("B"))
line += " "
line += format_name(device.device_class.name)
line += " "
line += "%.12g" % device.parameter("R")
line += " W="
line += "%.12g" % device.parameter("W")
line += " L="
line += "%.12g" % device.parameter("L")
emit_line(line)
else
super
end
end
end
source($lvs_test_source)
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice(MyWriterDelegate::new), "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)
connect(contact, metal1_not_res)
connect(metal1_not_res, metal1_lbl)
align
netlist.simplify
compare

118
testdata/lvs/enable_wl1.lvsdb vendored Normal file
View File

@ -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)
)
)
)

11
testdata/lvs/enable_wl2.cir vendored Normal file
View File

@ -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 A=3.6P P=13.2U
.ENDS Rre

33
testdata/lvs/enable_wl2.lvs vendored Normal file
View File

@ -0,0 +1,33 @@
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
class MyResistorClass < RBA::DeviceClassResistor
def initialize
super
enable_parameter("W", true)
enable_parameter("L", true)
end
end
extract_devices(resistor("RR1", 1, MyResistorClass), { "R" => res , "C" => metal1_not_res})
connect(contact, metal1_not_res)
connect(metal1_not_res, metal1_lbl)
align
netlist.simplify
compare

118
testdata/lvs/enable_wl2.lvsdb vendored Normal file
View File

@ -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)
)
)
)

11
testdata/lvs/enable_wl3.cir vendored Normal file
View File

@ -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 A=3.6P P=13.2U
.ENDS Rre

33
testdata/lvs/enable_wl3.lvs vendored Normal file
View File

@ -0,0 +1,33 @@
source($lvs_test_source)
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("resistor2.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
class MyResistorClass < RBA::DeviceClassResistor
def initialize
super
enable_parameter("W", true)
enable_parameter("L", true)
end
end
extract_devices(resistor("RR1", 1, MyResistorClass), { "R" => res , "C" => metal1_not_res})
connect(contact, metal1_not_res)
connect(metal1_not_res, metal1_lbl)
align
netlist.simplify
compare

121
testdata/lvs/enable_wl3.lvsdb vendored Normal file
View File

@ -0,0 +1,121 @@
#%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 7)
param(W 0.6)
param(A 0)
param(P 0)
terminal(A 1)
terminal(B 2)
)
)
)
# Cross reference
xref(
circuit(Rre RRE nomatch
xref(
net(() 2 mismatch)
net(() 1 mismatch)
net(1 () mismatch)
net(2 () mismatch)
pin(0 () match)
pin(1 () match)
device(() 1 mismatch)
device(1 () mismatch)
)
)
)

4
testdata/lvs/resistor.cir vendored Normal file
View File

@ -0,0 +1,4 @@
.SUBCKT Rre
RR0 vdd! gnd! 10 RR1 W=600n L=6u M=1
.ENDS

BIN
testdata/lvs/resistor.gds vendored Normal file

Binary file not shown.

4
testdata/lvs/resistor2.cir vendored Normal file
View File

@ -0,0 +1,4 @@
.SUBCKT Rre
RR0 vdd! gnd! 10 RR1 W=600n L=7u M=1
.ENDS

View File

@ -331,6 +331,8 @@ class DBNetlist_TestClass < TestBase
assert_equal(net.terminal_count, 1)
assert_equal(d1.net_for_terminal(1).name, "NET")
assert_equal(d1.net_for_terminal("B").name, "NET")
assert_equal(d1.net_for_terminal("X").inspect, "nil")
assert_equal(d1.net_for_terminal(0).inspect, "nil")
d1.disconnect_terminal("B")