Tests, debugging

This commit is contained in:
Matthias Koefferlein 2026-06-30 23:29:20 +02:00
parent 9e1bd7c9e9
commit 1c560caaa7
5 changed files with 219 additions and 27 deletions

View File

@ -204,6 +204,12 @@ static void test_initialize (db::NetlistDeviceExtractor *ex, db::Netlist *nl)
ex->initialize (nl);
}
// for test only
static db::DeviceClass *default_device_class (db::NetlistDeviceExtractor *ex)
{
return ex->default_device_class ();
}
Class<db::NetlistDeviceExtractor> decl_dbNetlistDeviceExtractor ("db", "DeviceExtractorBase",
gsi::method ("name", &db::NetlistDeviceExtractor::name,
"@brief Gets the name of the device extractor and the device class."
@ -219,6 +225,7 @@ Class<db::NetlistDeviceExtractor> decl_dbNetlistDeviceExtractor ("db", "DeviceEx
"This method has been added in version 0.27.3.\n"
) +
gsi::method_ext ("test_initialize", &test_initialize, gsi::arg ("netlist"), "@hide") + // for test only
gsi::factory_ext ("default_device_class", &default_device_class, "@hide") + // for test only
gsi::iterator ("each_layer_definition", &db::NetlistDeviceExtractor::begin_layer_definitions, &db::NetlistDeviceExtractor::end_layer_definitions,
"@brief Iterates over all layer definitions."
) +
@ -592,7 +599,15 @@ static db::NetlistDeviceExtractorMOS4Transistor *make_mos4_extractor (const std:
Class<db::NetlistDeviceExtractorMOS4Transistor> decl_NetlistDeviceExtractorMOS4Transistor (decl_dbNetlistDeviceExtractor, "db", "DeviceExtractorMOS4Transistor",
gsi::constructor ("new", &make_mos4_extractor, gsi::arg ("name"), gsi::arg ("strict", false), gsi::arg ("factory", (DeviceClassFactoryImpl *)0, "none"),
"@brief Creates a new device extractor with the given name\n"
"If \\strict is true, the MOS device extraction will happen in strict mode. That is, source and drain "
"are not interchangeable.\n"
"\n"
"For the 'factory' parameter see \\DeviceClassFactory. It has been added in version 0.27.3.\n"
) +
gsi::method ("strict?", &db::NetlistDeviceExtractorMOS4Transistor::is_strict,
"@brief Returns a value indicating whether extraction happens in strict mode.\n"
"\n"
"This attribute has been added in version 0.31.0."
),
"@brief A device extractor for a four-terminal MOS transistor\n"
"\n"

View File

@ -476,6 +476,9 @@ module DRC
DRCTransformationVariantHint::new(expression, nil)
end
def spice_profile(name)
DRCSpiceProfile::new(name)
end
# %DRC%
# @brief Specifies "same properties" for operations supporting user properties constraints
@ -801,7 +804,8 @@ module DRC
# about this device class.
def mos3_class(name)
cls = RBA::DeviceClassMOS3Transistor::new(false)
cls = RBA::DeviceClassMOS3Transistor::new
cls.strict = false
cls.name = name
cls
end
@ -841,7 +845,8 @@ module DRC
# about this device class.
def mos4_class(name)
cls = RBA::DeviceClassMOS4Transistor::new(false)
cls = RBA::DeviceClassMOS4Transistor::new
cls.strict = false
cls.name = name
cls
end
@ -883,7 +888,8 @@ module DRC
# about this device class.
def dmos3_class(name)
cls = RBA::DeviceClassMOS3Transistor::new(true)
cls = RBA::DeviceClassMOS3Transistor::new
cls.strict = true
cls.name = name
cls
end
@ -925,7 +931,8 @@ module DRC
# about this device class.
def dmos4_class(name)
cls = RBA::DeviceClassMOS4Transistor::new(true)
cls = RBA::DeviceClassMOS4Transistor::new
cls.strict = true
cls.name = name
cls
end
@ -1053,10 +1060,10 @@ module DRC
# %DRC%
# @brief Supplies the resistor extractor class.
# @name resistor
# @synopsis resistor(name, area_cap)
# @synopsis resistor(device_class, area_cap)
# @synopsis resistor(name, rho)
# @synopsis resistor(device_class, rho)
# Use this class with \extract_devices to specify extraction of a resistor.
# The sheet_rho value is the sheet resistance in ohms/square.
# "rho" is the sheet resistance in ohms/square.
# If used with a name, the extractor will produce devices with device
# class RBA::DeviceClassResistor. If used with a specific device
# class object, the extractor will produce devices with this class.
@ -1066,12 +1073,12 @@ module DRC
# See RBA::DeviceExtractorResistor for more details
# about this extractor.
def resistor(name_or_class, area_cap, cls = nil)
def resistor(name_or_class, rho, cls = nil)
self._context("resistor") do
if name_or_class.is_a?(RBA::DeviceClass)
RBA::DeviceExtractorResistor::new(name_or_class.name, area_cap, _make_dup_factory(name_or_class))
RBA::DeviceExtractorResistor::new(name_or_class.name, rho, _make_dup_factory(name_or_class))
else
RBA::DeviceExtractorResistor::new(name_or_class.to_s, area_cap, _make_factory(cls))
RBA::DeviceExtractorResistor::new(name_or_class.to_s, rho, _make_factory(cls))
end
end
end
@ -1133,11 +1140,11 @@ module DRC
# %DRC%
# @brief Supplies the resistor extractor class that includes a bulk terminal
# @name resistor_with_bulk
# @synopsis resistor_with_bulk(name, area_cap)
# @synopsis resistor_with_bulk(device_class, area_cap)
# @synopsis resistor_with_bulk(name, rho)
# @synopsis resistor_with_bulk(device_class, rho)
# 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.
# "rho" is the sheet resistance in ohms/square.
# If used with a name, the extractor will produce devices with device
# class RBA::DeviceClassResistorWithBulk. If used with a specific device
# class object, the extractor will produce devices with this class.
@ -1147,12 +1154,12 @@ module DRC
# See RBA::DeviceExtractorResistorWithBulk for more details
# about this extractor.
def resistor_with_bulk(name_or_class, area_cap, cls = nil)
def resistor_with_bulk(name_or_class, rho, cls = nil)
self._context("resistor_with_bulk") do
if name_or_class.is_a?(RBA::DeviceClass)
RBA::DeviceExtractorResistorWithBulk::new(name_or_class.name, area_cap, _make_dup_factory(name_or_class))
RBA::DeviceExtractorResistorWithBulk::new(name_or_class.name, rho, _make_dup_factory(name_or_class))
else
RBA::DeviceExtractorResistorWithBulk::new(name_or_class.to_s, area_cap, _make_factory(cls))
RBA::DeviceExtractorResistorWithBulk::new(name_or_class.to_s, rho, _make_factory(cls))
end
end
end

View File

@ -1072,8 +1072,10 @@ module DRC
@l2n.name = "DRC"
@l2n.generator = @engine._generator
@devcls.each do |cls|
@l2n.register_device_class(cls)
if @devcls
@devcls.each do |cls|
@l2n.register_device_class(cls)
end
end
end

View File

@ -28,7 +28,7 @@
#include "lymMacro.h"
#include "tlFileUtils.h"
void run_test (tl::TestBase *_this, const std::string &suffix, const std::string &layout, bool with_l2n = false, bool with_lvs = true, const std::string &top = std::string (), bool change_case = false)
void run_test (tl::TestBase *_this, const std::string &suffix, const std::string &layout, bool with_l2n = false, bool with_lvs = true, bool with_cir = true, const std::string &top = std::string (), bool change_case = false)
{
std::string rs = tl::testdata ();
rs += "/lvs/" + suffix + ".lvs";
@ -73,12 +73,19 @@ void run_test (tl::TestBase *_this, const std::string &suffix, const std::string
if (with_lvs) {
_this->compare_text_files (output_lvsdb, au_lvsdb);
}
_this->compare_text_files (output_cir, au_cir);
if (with_cir) {
_this->compare_text_files (output_cir, au_cir);
}
if (with_l2n) {
_this->compare_text_files (output_l2n, au_l2n);
}
}
TEST(0_basic)
{
run_test (_this, "basic", "ringo.gds", false, false, false);
}
TEST(1_simple)
{
run_test (_this, "ringo_simple", "ringo.gds");
@ -123,14 +130,14 @@ TEST(6_simple_pin_swapping)
{
run_test (_this, "ringo_simple_pin_swapping", "ringo.gds");
// change case
run_test (_this, "ringo_simple_pin_swapping", "ringo.gds", false, true, std::string (), true);
run_test (_this, "ringo_simple_pin_swapping", "ringo.gds", false, true, true, std::string (), true);
}
TEST(7_net_and_circuit_equivalence)
{
run_test (_this, "ringo_simple_net_and_circuit_equivalence", "ringo_renamed.gds");
// change case
run_test (_this, "ringo_simple_net_and_circuit_equivalence", "ringo_renamed.gds", false, true, std::string (), true);
run_test (_this, "ringo_simple_net_and_circuit_equivalence", "ringo_renamed.gds", false, true, true, std::string (), true);
}
TEST(8_simplification)
@ -168,14 +175,14 @@ TEST(13_simple_ringo_device_subcircuits)
{
run_test (_this, "ringo_device_subcircuits", "ringo.gds");
// change case
run_test (_this, "ringo_device_subcircuits", "ringo.gds", false, true, std::string (), true);
run_test (_this, "ringo_device_subcircuits", "ringo.gds", false, true, true, std::string (), true);
}
TEST(13b_simple_ringo_device_subcircuits_devcls)
{
run_test (_this, "ringo_device_subcircuits_devcls", "ringo.gds");
// change case
run_test (_this, "ringo_device_subcircuits_devcls", "ringo.gds", false, true, std::string (), true);
run_test (_this, "ringo_device_subcircuits_devcls", "ringo.gds", false, true, true, std::string (), true);
}
TEST(14_simple_ringo_mixed_hierarchy)
@ -190,7 +197,7 @@ TEST(15_simple_dummy_device)
TEST(16_floating)
{
run_test (_this, "floating", "floating.gds", false, true, "TOP");
run_test (_this, "floating", "floating.gds", false, true, true, "TOP");
}
TEST(17_layout_variants)
@ -362,12 +369,12 @@ TEST(61_StrayTextsDoNotMakeNets)
// Issue #1719, part 3 (layer naming)
TEST(62_LayerNames)
{
run_test (_this, "layer_names", "layer_names.gds", false, true, "TOP");
run_test (_this, "layer_names", "layer_names.gds", false, true, true, "TOP");
}
TEST(63_FlagMissingPorts)
{
run_test (_this, "flag_missing_ports", "flag_missing_ports.gds", false, true, "TOP");
run_test (_this, "flag_missing_ports", "flag_missing_ports.gds", false, true, true, "TOP");
}
// Split substrate - marker and global connection (issue #2345)

161
testdata/lvs/basic.lvs vendored Normal file
View File

@ -0,0 +1,161 @@
def assert_equal(a, b)
if a != b
raise RuntimeError::new("#{a.to_s} does not equal #{b.to_s}")
end
end
p = spice_profile("my_profile")
assert_equal(p.name, "my_profile")
# device extractors and classes
ex = mos3("name")
assert_equal(ex.is_a?(RBA::DeviceExtractorMOS3Transistor), true)
assert_equal(ex.name, "name")
assert_equal(ex.strict?, false)
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassMOS3Transistor), true)
assert_equal(dc.strict?, false)
ex = mos3(mos3_class("name"))
assert_equal(ex.is_a?(RBA::DeviceExtractorMOS3Transistor), true)
assert_equal(ex.name, "name")
assert_equal(ex.strict?, false)
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassMOS3Transistor), true)
assert_equal(dc.strict?, false)
ex = dmos3("name")
assert_equal(ex.is_a?(RBA::DeviceExtractorMOS3Transistor), true)
assert_equal(ex.name, "name")
assert_equal(ex.strict?, true)
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassMOS3Transistor), true)
assert_equal(dc.strict?, true)
ex = dmos3(dmos3_class("name"))
assert_equal(ex.is_a?(RBA::DeviceExtractorMOS3Transistor), true)
assert_equal(ex.name, "name")
assert_equal(ex.strict?, true)
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassMOS3Transistor), true)
assert_equal(dc.strict?, true)
ex = mos4("name")
assert_equal(ex.is_a?(RBA::DeviceExtractorMOS4Transistor), true)
assert_equal(ex.name, "name")
assert_equal(ex.strict?, false)
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassMOS4Transistor), true)
assert_equal(dc.strict?, false)
ex = mos4(mos4_class("name"))
assert_equal(ex.is_a?(RBA::DeviceExtractorMOS4Transistor), true)
assert_equal(ex.name, "name")
assert_equal(ex.strict?, false)
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassMOS4Transistor), true)
assert_equal(dc.strict?, false)
ex = dmos4("name")
assert_equal(ex.is_a?(RBA::DeviceExtractorMOS4Transistor), true)
assert_equal(ex.name, "name")
assert_equal(ex.strict?, true)
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassMOS4Transistor), true)
assert_equal(dc.strict?, true)
ex = dmos4(dmos4_class("name"))
assert_equal(ex.is_a?(RBA::DeviceExtractorMOS4Transistor), true)
assert_equal(ex.name, "name")
assert_equal(ex.strict?, true)
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassMOS4Transistor), true)
assert_equal(dc.strict?, true)
ex = diode("name")
assert_equal(ex.is_a?(RBA::DeviceExtractorDiode), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassDiode), true)
ex = diode(diode_class("name"))
assert_equal(ex.is_a?(RBA::DeviceExtractorDiode), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassDiode), true)
ex = bjt3("name")
assert_equal(ex.is_a?(RBA::DeviceExtractorBJT3Transistor), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassBJT3Transistor), true)
ex = bjt3(bjt3_class("name"))
assert_equal(ex.is_a?(RBA::DeviceExtractorBJT3Transistor), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassBJT3Transistor), true)
ex = bjt4("name")
assert_equal(ex.is_a?(RBA::DeviceExtractorBJT4Transistor), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassBJT4Transistor), true)
ex = bjt4(bjt4_class("name"))
assert_equal(ex.is_a?(RBA::DeviceExtractorBJT4Transistor), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassBJT4Transistor), true)
ex = resistor("name", 1.0)
assert_equal(ex.is_a?(RBA::DeviceExtractorResistor), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassResistor), true)
ex = resistor(resistor_class("name"), 1.0)
assert_equal(ex.is_a?(RBA::DeviceExtractorResistor), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassResistor), true)
ex = resistor_with_bulk("name", 1.0)
assert_equal(ex.is_a?(RBA::DeviceExtractorResistorWithBulk), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassResistorWithBulk), true)
ex = resistor_with_bulk(resistor_with_bulk_class("name"), 1.0)
assert_equal(ex.is_a?(RBA::DeviceExtractorResistorWithBulk), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassResistorWithBulk), true)
ex = capacitor("name", 1.0)
assert_equal(ex.is_a?(RBA::DeviceExtractorCapacitor), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassCapacitor), true)
ex = capacitor(capacitor_class("name"), 1.0)
assert_equal(ex.is_a?(RBA::DeviceExtractorCapacitor), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassCapacitor), true)
ex = capacitor_with_bulk("name", 1.0)
assert_equal(ex.is_a?(RBA::DeviceExtractorCapacitorWithBulk), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassCapacitorWithBulk), true)
ex = capacitor_with_bulk(capacitor_with_bulk_class("name"), 1.0)
assert_equal(ex.is_a?(RBA::DeviceExtractorCapacitorWithBulk), true)
assert_equal(ex.name, "name")
dc = ex.default_device_class
assert_equal(dc.is_a?(RBA::DeviceClassCapacitorWithBulk), true)