diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 97ff3a824..29f927cf7 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -39,6 +39,10 @@ Class decl_dbPin ("db", "Pin", ) + gsi::method ("name", &db::Pin::name, "@brief Gets the name of the pin.\n" + ) + + gsi::method ("expanded_name", &db::Pin::expanded_name, + "@brief Gets the expanded name of the pin.\n" + "The expanded name is the name or a generic identifier made from the ID if the name is empty." ), "@brief A pin of a circuit.\n" "Pin objects are used to describe the outgoing pins of " @@ -1010,6 +1014,11 @@ Class decl_dbNetlist ("db", "Netlist", "@brief Converts the netlist to a string representation.\n" "This method is intended for test purposes mainly." ) + + gsi::method ("from_s", &db::Netlist::from_string, gsi::arg ("str"), + "@brief Reads the netlist from a string representation.\n" + "This method is intended for test purposes mainly. It turns a string returned by \\to_s back into " + "a netlist. Note that the device classes must be created before as they are not persisted inside the string." + ) + gsi::method ("combine_devices", &db::Netlist::combine_devices, "@brief Combines devices where possible\n" "This method will combine devices that can be combined according " diff --git a/src/db/db/gsiDeclDbNetlistCompare.cc b/src/db/db/gsiDeclDbNetlistCompare.cc index 04d7c8f0c..50b91ae69 100644 --- a/src/db/db/gsiDeclDbNetlistCompare.cc +++ b/src/db/db/gsiDeclDbNetlistCompare.cc @@ -296,11 +296,10 @@ public: }; } - namespace gsi { -Class decl_GenericNetlistCompareLogger (decl_GenericNetlistCompareLogger, "db", "GenericNetlistCompareLogger", +Class decl_GenericNetlistCompareLogger ("db", "GenericNetlistCompareLogger", gsi::callback ("begin_netlist", &GenericNetlistCompareLogger::begin_netlist, &GenericNetlistCompareLogger::cb_begin_netlist, gsi::arg ("a"), gsi::arg ("b"), "@brief This function is called at the beginning of the compare process.\n" "This method is called once when the compare run begins.\n" @@ -401,13 +400,13 @@ Class decl_GenericNetlistCompareLogger (decl_Generi "This class has been introduced in version 0.26.\n" ); -db::NetlistComparer *make_comparer (db::NetlistCompareLogger *logger) +static db::NetlistComparer *make_comparer (GenericNetlistCompareLogger *logger) { return new db::NetlistComparer (logger); } Class decl_dbNetlistComparer ("db", "NetlistComparer", - gsi::constructor ("new", &make_comparer, gsi::arg ("logger", (db::NetlistCompareLogger *) 0), + gsi::constructor ("new", &make_comparer, gsi::arg ("logger", (GenericNetlistCompareLogger *) 0), "@brief Creates a new comparer object." "The logger is a delegate or event receiver which the comparer will send compare events to. " "See the class description for more details." diff --git a/src/rba/unit_tests/rba.cc b/src/rba/unit_tests/rba.cc index 5c6d4175e..cdc31958b 100644 --- a/src/rba/unit_tests/rba.cc +++ b/src/rba/unit_tests/rba.cc @@ -113,6 +113,7 @@ RUBYTEST (dbMatrix, "dbMatrix.rb") RUBYTEST (dbNetlist, "dbNetlist.rb") RUBYTEST (dbNetlistDeviceClasses, "dbNetlistDeviceClasses.rb") RUBYTEST (dbNetlistWriterTests, "dbNetlistWriterTests.rb") +RUBYTEST (dbNetlistCompare, "dbNetlistCompare.rb") RUBYTEST (dbPathTest, "dbPathTest.rb") RUBYTEST (dbPCells, "dbPCells.rb") RUBYTEST (dbPointTest, "dbPointTest.rb") diff --git a/testdata/ruby/dbNetlistCompare.rb b/testdata/ruby/dbNetlistCompare.rb new file mode 100644 index 000000000..69d9f44ce --- /dev/null +++ b/testdata/ruby/dbNetlistCompare.rb @@ -0,0 +1,747 @@ +# encoding: UTF-8 + +# KLayout Layout Viewer +# Copyright(C) 2006-2019 Matthias Koefferlein +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +#(at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +if !$:.member?(File::dirname($0)) + $:.push(File::dirname($0)) +end + +load("test_prologue.rb") + +class NetlistCompareTestLogger < RBA::GenericNetlistCompareLogger + + def initialize + @texts = [] + end + + def out(text) + @texts << text + end + + def begin_circuit(a, b) + out("begin_circuit " + circuit2str(a) + " " + circuit2str(b)) + end + + def end_circuit(a, b, matching) + out("end_circuit " + circuit2str(a) + " " + circuit2str(b) + " " + (matching ? "MATCH" : "NOMATCH")) + end + + def circuit_skipped(a, b) + out("circuit_skipped " + circuit2str(a) + " " + circuit2str(b)) + end + + def circuit_mismatch(a, b) + out("circuit_mismatch " + circuit2str(a) + " " + circuit2str(b)) + end + + def match_nets(a, b) + out("match_nets " + net2str(a) + " " + net2str(b)) + end + + def match_ambiguous_nets(a, b) + out("match_ambiguous_nets " + net2str(a) + " " + net2str(b)) + end + + def net_mismatch(a, b) + out("net_mismatch " + net2str(a) + " " + net2str(b)) + end + + def match_devices(a, b) + out("match_devices " + device2str(a) + " " + device2str(b)) + end + + def device_mismatch(a, b) + out("device_mismatch " + device2str(a) + " " + device2str(b)) + end + + def match_devices_with_different_parameters(a, b) + out("match_devices_with_different_parameters " + device2str(a) + " " + device2str(b)) + end + + def match_devices_with_different_device_classes(a, b) + out("match_devices_with_different_device_classes " + device2str(a) + " " + device2str(b)) + end + + def match_pins(a, b) + out("match_pins " + pin2str(a) + " " + pin2str(b)) + end + + def pin_mismatch(a, b) + out("pin_mismatch " + pin2str(a) + " " + pin2str(b)) + end + + def match_subcircuits(a, b) + out("match_subcircuits " + subcircuit2str(a) + " " + subcircuit2str(b)) + end + + def subcircuit_mismatch(a, b) + out("subcircuit_mismatch " + subcircuit2str(a) + " " + subcircuit2str(b)) + end + + def text + return @texts.join("\n") + "\n" + end + + def clear + @texts = [] + end + + def circuit2str(x) + return x ? x.name : "(null)" + end + + def device2str(x) + return x ? x.expanded_name : "(null)" + end + + def net2str(x) + return x ? x.expanded_name : "(null)" + end + + def pin2str(x) + return x ? x.expanded_name : "(null)" + end + + def subcircuit2str(x) + return x ? x.expanded_name : "(null)" + end + +end + +def prep_nl(nl, str) + + dc = RBA::DeviceClassMOS3Transistor::new + dc.name = "PMOS" + nl.add(dc) + + dc = RBA::DeviceClassMOS3Transistor::new + dc.name = "NMOS" + nl.add(dc) + + dc = RBA::DeviceClassMOS3Transistor::new + dc.name = "PMOSB" + nl.add(dc) + + dc = RBA::DeviceClassMOS3Transistor::new + dc.name = "NMOSB" + nl.add(dc) + + dc = RBA::DeviceClassMOS4Transistor::new + dc.name = "PMOS4" + nl.add(dc) + + dc = RBA::DeviceClassMOS4Transistor::new + dc.name = "NMOS4" + nl.add(dc) + + dc = RBA::DeviceClassResistor::new + dc.name = "RES" + nl.add(dc) + + dc = RBA::DeviceClassCapacitor::new + dc.name = "CAP" + nl.add(dc) + + dc = RBA::DeviceClassInductor::new + dc.name = "IND" + nl.add(dc) + + dc = RBA::DeviceClassDiode::new + dc.name = "DIODE" + nl.add(dc) + + nl.from_s(str) + +end + +class NetlistCompare_TestClass < TestBase + + def test_1 + + nls1 = <<"END" +circuit INV($1=IN,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1(S=VDD,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $2(S=VSS,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nls2 = <<"END" +circuit INV($1=VDD,$2=IN,$3=VSS,$4=OUT); + device NMOS $1(S=OUT,G=IN,D=VSS)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2(S=VDD,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + good = comp.compare(nl1, nl2) + + assert_equal(logger.text, <<"END") +begin_circuit INV INV +match_nets VDD VDD +match_nets VSS VSS +match_nets OUT OUT +match_nets IN IN +match_pins $0 $1 +match_pins $1 $3 +match_pins $2 $0 +match_pins $3 $2 +match_devices $2 $1 +match_devices $1 $2 +end_circuit INV INV MATCH +END + + assert_equal(good, true) + + end + + def test_2 + + nls1 = <<"END" +circuit INV($1=IN,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1(S=VDD,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $2(S=VSS,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nls2 = <<"END" +circuit INV($1=VDD,$2=IN,$3=VSS,$4=OUT); + device NMOSB $1(S=OUT,G=IN,D=VSS)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOSB $2(S=VDD,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + comp.same_device_classes(nl1.device_class_by_name("PMOS"), nl2.device_class_by_name("PMOSB")) + + good = comp.compare(nl1, nl2) + assert_equal(good, false) + + logger.clear + comp.same_device_classes(nl1.device_class_by_name("NMOS"), nl2.device_class_by_name("NMOSB")) + good = comp.compare(nl1, nl2) + + assert_equal(logger.text(), <<"END") +begin_circuit INV INV +match_nets VDD VDD +match_nets VSS VSS +match_nets OUT OUT +match_nets IN IN +match_pins $0 $1 +match_pins $1 $3 +match_pins $2 $0 +match_pins $3 $2 +match_devices $2 $1 +match_devices $1 $2 +end_circuit INV INV MATCH +END + + assert_equal(good, true) + + end + + def test_3 + + nls1 = <<"END" +circuit INV($1=IN,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1(S=VDD,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $2(S=VSS,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nls2 = <<"END" +circuit INV($1=VDD,$2=IN,$3=VSS,$4=OUT); + device NMOS $1(S=OUT,G=IN,D=VSS)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2(S=VDD,G=IN,D=OUT)(L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + ca = nl1.circuit_by_name("INV") + cb = nl2.circuit_by_name("INV") + comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD")) + comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS")) + + good = comp.compare(nl1, nl2) + + assert_equal(logger.text(), <<"END") +begin_circuit INV INV +match_nets OUT OUT +match_nets IN IN +match_pins $0 $1 +match_pins $1 $3 +match_pins $2 $0 +match_pins $3 $2 +match_devices $2 $1 +match_devices $1 $2 +end_circuit INV INV MATCH +END + + assert_equal(good, true) + + end + + def test_4 + + nls1 = <<"END" +circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $3 (S=VDD,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $4 (S=VSS,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nls2 = <<"END" +circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT); + device PMOS $1 (S=VDD,G=IN,D=$10) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2 (S=VDD,G=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $5 (S=$10,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $7 (S=$11,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + good = comp.compare(nl1, nl2) + + assert_equal(logger.text, <<"END") +begin_circuit BUF BUF +match_nets OUT OUT +match_nets VDD VDD +match_nets IN IN +match_nets VSS VSS +match_ambiguous_nets INT $10 +match_ambiguous_nets INT2 $11 +match_pins $0 $1 +match_pins $1 $3 +match_pins $2 $0 +match_pins $3 $2 +match_devices $1 $1 +match_devices $3 $2 +match_devices $5 $3 +match_devices $7 $4 +match_devices $2 $5 +match_devices $4 $6 +match_devices $6 $7 +match_devices $8 $8 +end_circuit BUF BUF MATCH +END + + assert_equal(good, true) + + end + + def test_5 + + nls1 = <<"END" +circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $3 (S=VDD,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $4 (S=VSS,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nls2 = <<"END" +circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT); + device PMOS $1 (S=VDD,G=IN,D=$10) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2 (S=VDD,G=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $5 (S=$10,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $7 (S=$11,G=IN,D=VSS) (L=0.35,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + # NOTE: adding this power hint makes the device class error harder to detect + ca = nl1.circuit_by_name("BUF") + cb = nl2.circuit_by_name("BUF") + comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD")) + comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS")) + + good = comp.compare(nl1, nl2) + + assert_equal(logger.text, <<"END") +begin_circuit BUF BUF +match_nets OUT OUT +match_nets IN IN +match_ambiguous_nets INT $10 +match_nets INT2 $11 +match_pins $0 $1 +match_pins $1 $3 +match_pins $2 $0 +match_pins $3 $2 +match_devices $1 $1 +match_devices $3 $2 +match_devices $5 $3 +match_devices $7 $4 +match_devices $2 $5 +match_devices $4 $6 +match_devices_with_different_parameters $6 $7 +match_devices $8 $8 +end_circuit BUF BUF NOMATCH +END + + assert_equal(good, false) + + end + + def test_6 + + nls1 = <<"END" +circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $3 (S=VDD,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $4 (S=VSS,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOSB $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOSB $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nls2 = <<"END" +circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT); + device PMOS $1 (S=VDD,G=IN,D=$10) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2 (S=VDD,G=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $5 (S=$10,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $7 (S=$11,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOSB $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + # NOTE: adding this power hint makes the device class error harder to detect + ca = nl1.circuit_by_name("BUF") + cb = nl2.circuit_by_name("BUF") + comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD")) + comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS")) + + good = comp.compare(nl1, nl2) + + assert_equal(logger.text, <<"END") +begin_circuit BUF BUF +match_nets IN IN +match_nets INT $10 +match_nets OUT OUT +match_nets INT2 $11 +match_pins $0 $1 +match_pins $1 $3 +match_pins $2 $0 +match_pins $3 $2 +match_devices $1 $1 +match_devices $3 $2 +match_devices $5 $3 +match_devices_with_different_device_classes $7 $4 +match_devices $2 $5 +match_devices $4 $6 +match_devices $6 $7 +match_devices $8 $8 +end_circuit BUF BUF NOMATCH +END + + assert_equal(good, false) + + end + + def test_7 + + nls1 = <<"END" +circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $3 (S=VDD,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $4 (S=VSS,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOSB $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOSB $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +END + + nls2 = <<"END" +circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT); + device PMOS $1 (S=VDD,G=IN,D=$10) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2 (S=VDD,G=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOSB $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $5 (S=$10,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $7 (S=$11,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOSB $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device RES $9 (A=$10,B=$11) (R=42); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + # Forcing the power nets into equality makes the resistor error harder to detect + ca = nl1.circuit_by_name("BUF") + cb = nl2.circuit_by_name("BUF") + comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD")) + comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS")) + + good = comp.compare(nl1, nl2) + + assert_equal(logger.text, <<"END") +begin_circuit BUF BUF +match_nets INT $10 +match_nets OUT OUT +match_nets INT2 $11 +match_nets IN IN +match_pins $0 $1 +match_pins $1 $3 +match_pins $2 $0 +match_pins $3 $2 +match_devices $1 $1 +match_devices $3 $2 +match_devices $5 $3 +match_devices $7 $4 +match_devices $2 $5 +match_devices $4 $6 +match_devices $6 $7 +match_devices $8 $8 +device_mismatch (null) $9 +end_circuit BUF BUF NOMATCH +END + + assert_equal(good, false) + + end + + def test_8 + + nls1 = <<"END" +circuit INV ($1=IN,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $2 (S=VSS,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +circuit TOP ($1=IN,$2=OUT,$3=VDD,$4=VSS); + subcircuit INV $1 ($1=IN,$2=INT,$3=VDD,$4=VSS); + subcircuit INV $2 ($1=INT,$2=OUT,$3=VDD,$4=VSS); +end; +END + + nls2 = <<"END" +circuit INVB ($1=VDD,$2=IN,$3=VSS,$4=OUT); + device NMOS $1 (S=OUT,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +circuit TOP ($1=OUT,$2=VDD,$3=IN,$4=VSS); + subcircuit INVB $1 ($1=VDD,$2=INT,$3=VSS,$4=OUT); + subcircuit INVB $2 ($1=VDD,$2=IN,$3=VSS,$4=INT); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + good = comp.compare(nl1, nl2) + assert_equal(good, false) + + logger.clear + comp.same_circuits(nl1.circuit_by_name("INV"), nl2.circuit_by_name("INVB")) + + good = comp.compare(nl1, nl2) + + assert_equal(logger.text, <<"END") +begin_circuit INV INVB +match_nets VDD VDD +match_nets VSS VSS +match_nets OUT OUT +match_nets IN IN +match_pins $0 $1 +match_pins $1 $3 +match_pins $2 $0 +match_pins $3 $2 +match_devices $2 $1 +match_devices $1 $2 +end_circuit INV INVB MATCH +begin_circuit TOP TOP +match_nets OUT OUT +match_nets IN IN +match_nets VSS VSS +match_nets VDD VDD +match_nets INT INT +match_pins $0 $2 +match_pins $1 $0 +match_pins $2 $1 +match_pins $3 $3 +match_subcircuits $2 $1 +match_subcircuits $1 $2 +end_circuit TOP TOP MATCH +END + + assert_equal(good, true) + + end + + def test_9 + + nls1 = <<"END" +circuit NAND ($0=A,$1=B,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1 (S=VDD,G=A,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $3 (S=VSS,G=A,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $4 (S=INT,G=B,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +circuit TOP ($0=IN1,$1=IN2,$2=OUT,$3=VDD,$4=VSS); + subcircuit NAND $1 ($0=IN1,$1=IN2,$2=INT,$3=VDD,$4=VSS); + subcircuit NAND $2 ($0=IN1,$1=INT,$2=OUT,$3=VDD,$4=VSS); +end; +END + + nls2 = <<"END" +circuit NAND ($0=A,$1=B,$2=OUT,$3=VDD,$4=VSS); + device PMOS $1 (S=VDD,G=A,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $3 (S=VSS,G=A,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); + device NMOS $4 (S=INT,G=B,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5); +end; +circuit TOP ($0=IN1,$1=IN2,$2=OUT,$3=VDD,$4=VSS); + subcircuit NAND $2 ($0=IN1,$1=INT,$2=OUT,$3=VDD,$4=VSS); + subcircuit NAND $1 ($0=IN1,$1=IN2,$2=INT,$3=VDD,$4=VSS); +end; +END + + nl1 = RBA::Netlist::new + nl2 = RBA::Netlist::new + prep_nl(nl1, nls1) + prep_nl(nl2, nls2) + + logger = NetlistCompareTestLogger::new + comp = RBA::NetlistComparer::new(logger) + + comp.equivalent_pins(nl2.circuit_by_name("NAND"), 0, 1) + + good = comp.compare(nl1, nl2) + + assert_equal(logger.text, <<"END") +begin_circuit NAND NAND +match_nets VSS VSS +match_nets VDD VDD +match_nets B B +match_nets OUT OUT +match_nets A A +match_nets INT INT +match_pins $0 $0 +match_pins $1 $1 +match_pins $2 $2 +match_pins $3 $3 +match_pins $4 $4 +match_devices $1 $1 +match_devices $2 $2 +match_devices $3 $3 +match_devices $4 $4 +end_circuit NAND NAND MATCH +begin_circuit TOP TOP +match_nets OUT OUT +match_nets VSS VSS +match_nets VDD VDD +match_nets IN1 IN1 +match_nets INT INT +match_nets IN2 IN2 +match_pins $0 $0 +match_pins $1 $1 +match_pins $2 $2 +match_pins $3 $3 +match_pins $4 $4 +match_subcircuits $2 $1 +match_subcircuits $1 $2 +end_circuit TOP TOP MATCH +END + + assert_equal(good, true) + + end + +end + +load("test_epilogue.rb") +