mirror of https://github.com/KLayout/klayout.git
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:
parent
ba35ac9bfe
commit
e34fc8967a
|
|
@ -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) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 < 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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
.SUBCKT Rre
|
||||
RR0 vdd! gnd! 10 RR1 W=600n L=6u M=1
|
||||
.ENDS
|
||||
|
||||
Binary file not shown.
|
|
@ -0,0 +1,4 @@
|
|||
.SUBCKT Rre
|
||||
RR0 vdd! gnd! 10 RR1 W=600n L=7u M=1
|
||||
.ENDS
|
||||
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in New Issue