From 1c560caaa7f3a6b7a7816fb6d993a7e1a5c850cc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 30 Jun 2026 23:29:20 +0200 Subject: [PATCH] Tests, debugging --- src/db/db/gsiDeclDbNetlistDeviceExtractor.cc | 15 ++ src/drc/drc/built-in-macros/_drc_engine.rb | 39 +++-- src/drc/drc/built-in-macros/_drc_netter.rb | 6 +- src/lvs/unit_tests/lvsSimpleTests.cc | 25 +-- testdata/lvs/basic.lvs | 161 +++++++++++++++++++ 5 files changed, 219 insertions(+), 27 deletions(-) create mode 100644 testdata/lvs/basic.lvs diff --git a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc index b5c64173b..1af532e32 100644 --- a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc +++ b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc @@ -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 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 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 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" diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index 6730fd2b5..3eebb4ac9 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -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 diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb index a5b5bae08..bffe1e867 100644 --- a/src/drc/drc/built-in-macros/_drc_netter.rb +++ b/src/drc/drc/built-in-macros/_drc_netter.rb @@ -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 diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc index 4255a0084..547a64eb0 100644 --- a/src/lvs/unit_tests/lvsSimpleTests.cc +++ b/src/lvs/unit_tests/lvsSimpleTests.cc @@ -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) diff --git a/testdata/lvs/basic.lvs b/testdata/lvs/basic.lvs new file mode 100644 index 000000000..4c307cf8b --- /dev/null +++ b/testdata/lvs/basic.lvs @@ -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) +