diff --git a/src/db/db/dbDeviceClass.cc b/src/db/db/dbDeviceClass.cc index 057c611d2..7d44e08f2 100644 --- a/src/db/db/dbDeviceClass.cc +++ b/src/db/db/dbDeviceClass.cc @@ -39,11 +39,13 @@ static int compare_parameters (double pa, double pb, double absolute, double rel pa_min -= mean * relative; pa_max += mean * relative; - // NOTE: parameter values may be small (e.g. pF for caps) -> no epsilon + // NOTE: parameter values may be small (e.g. pF for caps) -> no fixed epsilon - if (pa_max < pb) { + double eps = (fabs (pa_max) + fabs(pa_min)) * 0.5e-10; + + if (pa_max < pb - eps) { return -1; - } else if (pa_min > pb) { + } else if (pa_min > pb + eps) { return 1; } else { return 0; diff --git a/src/db/db/dbDeviceClass.h b/src/db/db/dbDeviceClass.h index b749528f8..e37b8f1f8 100644 --- a/src/db/db/dbDeviceClass.h +++ b/src/db/db/dbDeviceClass.h @@ -563,12 +563,22 @@ public: * * The device class takes ownership of the delegate. */ - virtual void set_parameter_compare_delegate (db::DeviceParameterCompareDelegate *delegate) + void set_parameter_compare_delegate (db::DeviceParameterCompareDelegate *delegate) { - delegate->keep (); // assume transfer of ownership for scripts + if (delegate) { + delegate->keep (); // assume transfer of ownership for scripts + } mp_pc_delegate.reset (delegate); } + /** + * @brief Gets the parameter compare delegate or null if no such delegate is registered + */ + db::DeviceParameterCompareDelegate *parameter_compare_delegate () + { + return mp_pc_delegate.get (); + } + private: friend class Netlist; diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 79a91fc2c..b8b7636c9 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -835,6 +835,11 @@ static void equal_parameters (db::DeviceClass *cls, db::EqualDeviceParameters *c cls->set_parameter_compare_delegate (comparer); } +static db::EqualDeviceParameters *get_equal_parameters (db::DeviceClass *cls) +{ + return dynamic_cast (cls->parameter_compare_delegate ()); +} + Class decl_dbDeviceClass ("db", "DeviceClass", gsi::method ("name", &db::DeviceClass::name, "@brief Gets the name of the device class." @@ -905,6 +910,12 @@ Class decl_dbDeviceClass ("db", "DeviceClass", "An exception is thrown if there is no terminal with the given name. Use \\has_terminal to check " "whether the name is a valid terminal name." ) + + gsi::method_ext ("equal_parameters", &get_equal_parameters, + "@brief Gets the device parameter comparer for netlist verification or nil if no comparer is registered.\n" + "See \\equal_parameters= for the setter.\n" + "\n" + "This getter has been introduced in version 0.26.4.\n" + ) + gsi::method_ext ("equal_parameters=", &equal_parameters, gsi::arg ("comparer"), "@brief Specifies a device parameter comparer for netlist verification.\n" "By default, all devices are compared with all parameters. If you want to select only certain parameters " @@ -912,6 +923,8 @@ Class decl_dbDeviceClass ("db", "DeviceClass", "to the device class of one netlist. You can also chain multiple \\EqualDeviceParameters objects with the '+' operator " "for specifying multiple parameters in the equality check.\n" "\n" + "You can assign nil for the parameter comparer to remove it.\n" + "\n" "In special cases, you can even implement a custom compare scheme by deriving your own comparer from the \\GenericDeviceParameterCompare class." ), "@brief A class describing a specific type of device.\n" diff --git a/src/lay/lay/doc/about/lvs_ref_global.xml b/src/lay/lay/doc/about/lvs_ref_global.xml index 970b72954..940f6af21 100644 --- a/src/lay/lay/doc/about/lvs_ref_global.xml +++ b/src/lay/lay/doc/about/lvs_ref_global.xml @@ -160,4 +160,14 @@ See Netter#same_nets for a des

See Netter#schematic for a description of that function.

+

"tolerance" - Specifies compare tolerances for certain device parameters

+ +

Usage:

+
    +
  • tolerance(device_class_name, parameter_name, absolute_tolerance [, relative_tolerance])
  • +
  • tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance])
  • +
+

+See Netter#tolerance for a description of that function. +

diff --git a/src/lay/lay/doc/about/lvs_ref_netter.xml b/src/lay/lay/doc/about/lvs_ref_netter.xml index 3e22ca91d..b4a1c1b94 100644 --- a/src/lay/lay/doc/about/lvs_ref_netter.xml +++ b/src/lay/lay/doc/about/lvs_ref_netter.xml @@ -257,4 +257,19 @@ If no reader is provided, Spice format will be assumed. The reader object is a Alternatively, a Netlist object can be given which is obtained from any other source.

+

"tolerance" - Specifies compare tolerances for certain device parameters

+ +

Usage:

+
    +
  • tolerance(device_class_name, parameter_name, absolute_tolerance [, relative_tolerance])
  • +
  • tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance])
  • +
+

+Specifies a compare tolerance for a specific parameter on a given device class. +The device class is the name of a device class in the extracted netlist. +Tolerances can be given in absolute units or relative or both. +The relative tolerance is given as a factor, so 0.1 is a 10% tolerance. +Absolute and relative tolerances add, so specifying both allows for a larger +deviation. +

diff --git a/src/lay/lay/doc/manual/lvs_compare.xml b/src/lay/lay/doc/manual/lvs_compare.xml index 01dd882fc..211e5aa8a 100644 --- a/src/lay/lay/doc/manual/lvs_compare.xml +++ b/src/lay/lay/doc/manual/lvs_compare.xml @@ -81,6 +81,77 @@
same_device_classes("PMOS_IN_LAYOUT", "PMOS_IN_SCHEMATIC")
 same_device_classes("NMOS_IN_LAYOUT", "NMOS_IN_SCHEMATIC")
+

Tolerances

+ +

+ When comparing device parameters, by default strict equivalence is required. + However, when drawing a device like a resistor, it's usually difficult to match + the exact value unless the resistor calibration is consistent with drawing grids and + the resistor geometry is not confined by design rule constraints. + So sometimes the target value or a device parameter can only be approximated in + the layout. This will by default lead to a mismatch. +

+ +

+ The solution is to specify parameter tolerances. Tolerances can be specified + in an absolute or relative fashion. If an absolute tolerance is given, the layout + parameter may deviate from the target value by this tolerance either to + lower or higher values. So the unit of the tolerance is the same than the + unit of the parameter. +

+ +

+ If a relative tolerance is given, the deviation is + computed from the target value times the tolerance. So the relative tolerance + is a factor and a value of 0.05 for example specifies an allowed deviation of + plus or minus 5%. Relative tolerances are unit-less. +

+ +

+ It's also possible to specify both an absolute and a relative tolerance. In this + case, both tolerances add and the allowed deviation becomes larger. +

+ +

+ To specify an absolute tolerance, use the tolerance function: +

+ +
tolerance("NMOS", "L", 0.05)
+ +

+ The two arguments are the name of the device class and the name of the parameter + for which the tolerance will be applied. In the case above, a tolerance of 50nm (the + unit of L is micrometer) is applied to the length parameter of "NMOS" devices. +

+ +

+ A relative tolerance is specified as an additonal forth parameter. You can set + the absolute tolerance to zero to specify only relative tolerances. This will + specify 1% tolerance for the "L" parameter of "NMOS" devices: +

+ +
tolerance("NMOS", "L", 0.0, 0.01)
+ +

+ There is also a more explicit notation for the tolerance: +

+ +
tolerance("NMOS", "L", :absolute => 0.05)
+tolerance("NMOS", "L", :relative => 0.01)
+ +

+ This notation is equivalent to the two forms above. +

+ +

+ An absolute plus relative tolerance can be specified by giving both. + The following calls will give you 50nm absolute and 1% relative tolerance for the "L" + parameter of "NMOS" devices: +

+ +
tolerance("NMOS", "L", 0.05, 0.01)
+tolerance("NMOS", "L", :absolute => 0.05, :relative => 0.01)
+

Pin swapping

diff --git a/src/lvs/lvs/built-in-macros/_lvs_engine.rb b/src/lvs/lvs/built-in-macros/_lvs_engine.rb index ebb18df60..e1179f3a7 100644 --- a/src/lvs/lvs/built-in-macros/_lvs_engine.rb +++ b/src/lvs/lvs/built-in-macros/_lvs_engine.rb @@ -155,7 +155,14 @@ module LVS # @synopsis max_depth(n) # See \Netter#max_depth for a description of that function. - %w(schematic compare join_symmetric_nets align same_nets same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity).each do |f| + # %LVS% + # @name tolerance + # @brief Specifies compare tolerances for certain device parameters + # @synopsis tolerance(device_class_name, parameter_name, absolute_tolerance [, relative_tolerance]) + # @synopsis tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance]) + # See \Netter#tolerance for a description of that function. + + %w(schematic compare join_symmetric_nets tolerance align same_nets same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity).each do |f| eval <<"CODE" def #{f}(*args) _netter.#{f}(*args) diff --git a/src/lvs/lvs/built-in-macros/_lvs_netter.rb b/src/lvs/lvs/built-in-macros/_lvs_netter.rb index 1d0bd03be..ae27f99ea 100644 --- a/src/lvs/lvs/built-in-macros/_lvs_netter.rb +++ b/src/lvs/lvs/built-in-macros/_lvs_netter.rb @@ -98,6 +98,60 @@ module LVS _l2n_data && @lvs end + # %LVS% + # @name tolerance + # @brief Specifies compare tolerances for certain device parameters + # @synopsis tolerance(device_class_name, parameter_name, absolute_tolerance [, relative_tolerance]) + # @synopsis tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance]) + # Specifies a compare tolerance for a specific parameter on a given device class. + # The device class is the name of a device class in the extracted netlist. + # Tolerances can be given in absolute units or relative or both. + # The relative tolerance is given as a factor, so 0.1 is a 10% tolerance. + # Absolute and relative tolerances add, so specifying both allows for a larger + # deviation. + + def tolerance(device_class_name, parameter_name, *args) + + device_class_name.is_a?(String) || raise("Device class argument of 'tolerance' must be a string") + parameter_name.is_a?(String) || raise("Parameter name argument of 'tolerance' must be a string") + + abs_tol = nil + rel_tol = nil + args.each do |a| + if a.is_a?(Hash) + a.keys.each do |k| + if k == :absolute + abs_tol = a[k].to_f + elsif k == :relative + rel_tol = a[k].to_f + else + raise("Unknown option #{k.to_s} in 'tolerance' (allowed options are: absolute, relative)") + end + end + elsif abs_tol == nil + abs_tol = a.to_f + elsif rel_tol == nil + rel_tol = a.to_f + else + raise("Too many arguments in 'tolerance' (max. 4)") + end + end + + abs_tol ||= 0.0 + rel_tol ||= 0.0 + + dc = netlist.device_class_by_name(device_class_name) + if dc && dc.has_parameter?(parameter_name) + ep = RBA::EqualDeviceParameters::new(dc.parameter_id(parameter_name), abs_tol, rel_tol) + if dc.equal_parameters == nil + dc.equal_parameters = ep + else + dc.equal_parameters += ep + end + end + + end + # %LVS% # @name align # @brief Aligns the extracted netlist vs. the schematic diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc index df9709da6..44ee2133e 100644 --- a/src/lvs/unit_tests/lvsSimpleTests.cc +++ b/src/lvs/unit_tests/lvsSimpleTests.cc @@ -80,6 +80,11 @@ TEST(1_simple) run_test (_this, "ringo_simple", "ringo.gds"); } +TEST(1b_simple_with_tolerance) +{ + run_test (_this, "ringo_simple_with_tol", "ringo.gds"); +} + TEST(2_simple_io) { run_test (_this, "ringo_simple_io", "ringo.gds"); diff --git a/testdata/lvs/ringo_off_target.cir b/testdata/lvs/ringo_off_target.cir new file mode 100644 index 000000000..a8a198cef --- /dev/null +++ b/testdata/lvs/ringo_off_target.cir @@ -0,0 +1,27 @@ + +.SUBCKT RINGO VSS VDD FB ENABLE OUT +X$1 VDD 1 VSS VDD FB ENABLE VSS ND2X1 +X$2 VDD 2 VSS VDD 1 VSS INVX1 +X$3 VDD 3 VSS VDD 2 VSS INVX1 +X$4 VDD 4 VSS VDD 3 VSS INVX1 +X$5 VDD 5 VSS VDD 4 VSS INVX1 +X$6 VDD 6 VSS VDD 5 VSS INVX1 +X$7 VDD 7 VSS VDD 6 VSS INVX1 +X$8 VDD 8 VSS VDD 7 VSS INVX1 +X$9 VDD 9 VSS VDD 8 VSS INVX1 +X$10 VDD 10 VSS VDD 9 VSS INVX1 +X$11 VDD FB VSS VDD 10 VSS INVX1 +X$12 VDD OUT VSS VDD FB VSS INVX1 +.ENDS RINGO + +.SUBCKT ND2X1 VDD OUT VSS NWELL B A BULK +M$1 OUT A VDD NWELL PMOS L=0.251U W=1.6U +M$2 VDD B OUT NWELL PMOS L=0.25U W=1.5U +M$3 VSS A 1 BULK NMOS L=0.26U W=1.00U +M$4 1 B OUT BULK NMOS L=0.25U W=0.95U +.ENDS ND2X1 + +.SUBCKT INVX1 VDD OUT VSS NWELL IN BULK +M$1 VDD IN OUT NWELL PMOS L=0.25U W=1.5U +M$2 VSS IN OUT BULK NMOS L=0.25U W=0.95U +.ENDS INVX1 diff --git a/testdata/lvs/ringo_simple_with_tol.cir b/testdata/lvs/ringo_simple_with_tol.cir new file mode 100644 index 000000000..761afb771 --- /dev/null +++ b/testdata/lvs/ringo_simple_with_tol.cir @@ -0,0 +1,83 @@ +* Extracted by KLayout + +* cell RINGO +* pin FB +* pin VDD +* pin OUT +* pin ENABLE +* pin VSS +.SUBCKT RINGO 11 12 13 14 15 +* net 11 FB +* net 12 VDD +* net 13 OUT +* net 14 ENABLE +* net 15 VSS +* cell instance $1 r0 *1 1.8,0 +X$1 12 1 15 12 11 14 15 ND2X1 +* cell instance $2 r0 *1 4.2,0 +X$2 12 2 15 12 1 15 INVX1 +* cell instance $3 r0 *1 6,0 +X$3 12 3 15 12 2 15 INVX1 +* cell instance $4 r0 *1 7.8,0 +X$4 12 4 15 12 3 15 INVX1 +* cell instance $5 r0 *1 9.6,0 +X$5 12 5 15 12 4 15 INVX1 +* cell instance $6 r0 *1 11.4,0 +X$6 12 6 15 12 5 15 INVX1 +* cell instance $7 r0 *1 13.2,0 +X$7 12 7 15 12 6 15 INVX1 +* cell instance $8 r0 *1 15,0 +X$8 12 8 15 12 7 15 INVX1 +* cell instance $9 r0 *1 16.8,0 +X$9 12 9 15 12 8 15 INVX1 +* cell instance $10 r0 *1 18.6,0 +X$10 12 10 15 12 9 15 INVX1 +* cell instance $11 r0 *1 20.4,0 +X$11 12 11 15 12 10 15 INVX1 +* cell instance $12 r0 *1 22.2,0 +X$12 12 13 15 12 11 15 INVX1 +.ENDS RINGO + +* cell INVX1 +* pin VDD +* pin OUT +* pin VSS +* pin +* pin IN +* pin SUBSTRATE +.SUBCKT INVX1 1 2 3 4 5 6 +* net 1 VDD +* net 2 OUT +* net 3 VSS +* net 5 IN +* net 6 SUBSTRATE +* device instance $1 r0 *1 0.85,5.8 PMOS +M$1 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U +* device instance $2 r0 *1 0.85,2.135 NMOS +M$2 3 5 2 6 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U +.ENDS INVX1 + +* cell ND2X1 +* pin VDD +* pin OUT +* pin VSS +* pin +* pin B +* pin A +* pin SUBSTRATE +.SUBCKT ND2X1 1 2 3 4 5 6 7 +* net 1 VDD +* net 2 OUT +* net 3 VSS +* net 5 B +* net 6 A +* net 7 SUBSTRATE +* device instance $1 r0 *1 0.85,5.8 PMOS +M$1 2 6 1 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.3375P PS=3.85U PD=1.95U +* device instance $2 r0 *1 1.55,5.8 PMOS +M$2 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.3375P AD=0.6375P PS=1.95U PD=3.85U +* device instance $3 r0 *1 0.85,2.135 NMOS +M$3 3 6 8 7 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.21375P PS=2.75U PD=1.4U +* device instance $4 r0 *1 1.55,2.135 NMOS +M$4 8 5 2 7 NMOS L=0.25U W=0.95U AS=0.21375P AD=0.40375P PS=1.4U PD=2.75U +.ENDS ND2X1 diff --git a/testdata/lvs/ringo_simple_with_tol.lvs b/testdata/lvs/ringo_simple_with_tol.lvs new file mode 100644 index 000000000..5b2f6dcbd --- /dev/null +++ b/testdata/lvs/ringo_simple_with_tol.lvs @@ -0,0 +1,79 @@ + +source($lvs_test_source, "RINGO") + +report_lvs($lvs_test_target_lvsdb, true) + +target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") + +schematic("ringo_off_target.cir") + +deep + +# Drawing layers + +nwell = input(1, 0) +active = input(2, 0) +pplus = input(3, 0) +nplus = input(4, 0) +poly = input(5, 0) +contact = input(8, 0) +metal1 = input(9, 0) +via1 = input(10, 0) +metal2 = input(11, 0) + +# Bulk layer for terminal provisioning + +bulk = polygon_layer + +# Computed layers + +active_in_nwell = active & nwell +pactive = active_in_nwell & pplus +pgate = pactive & poly +psd = pactive - pgate +ntie = active_in_nwell & nplus + +active_outside_nwell = active - nwell +nactive = active_outside_nwell & nplus +ngate = nactive & poly +nsd = nactive - ngate +ptie = active_outside_nwell & pplus + +# Device extraction + +# PMOS transistor device extraction +extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell, + "tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell }) + +# NMOS transistor device extraction +extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk, + "tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk }) + +# Define connectivity for netlist extraction + +# Inter-layer +connect(psd, contact) +connect(nsd, contact) +connect(poly, contact) +connect(ntie, contact) +connect(nwell, ntie) +connect(ptie, contact) +connect(contact, metal1) +connect(metal1, via1) +connect(via1, metal2) + +# Global +connect_global(bulk, "SUBSTRATE") +connect_global(ptie, "SUBSTRATE") + +# Compare section + +tolerance("PMOS", "L", 0.001) # absolute +tolerance("PMOS", "W", 0.01, 0.1) # relative + absolute +tolerance("NMOS", "L", :absolute => 0.01) +tolerance("NMOS", "W", :relative => 0.07) + +netlist.simplify + +compare + diff --git a/testdata/lvs/ringo_simple_with_tol.lvsdb b/testdata/lvs/ringo_simple_with_tol.lvsdb new file mode 100644 index 000000000..9521ed1cb --- /dev/null +++ b/testdata/lvs/ringo_simple_with_tol.lvsdb @@ -0,0 +1,908 @@ +#%lvsdb-klayout + +# Layout +layout( + top(RINGO) + unit(0.001) + + # Layer section + # This section lists the mask layers (drawing or derived) and their connections. + + # Mask layers + layer(l3 '1/0') + layer(l4 '5/0') + layer(l8 '8/0') + layer(l11 '9/0') + layer(l12 '10/0') + layer(l13 '11/0') + layer(l7) + layer(l2) + layer(l9) + layer(l6) + layer(l10) + + # Mask layer connectivity + connect(l3 l3 l9) + connect(l4 l4 l8) + connect(l8 l4 l8 l11 l2 l9 l6 l10) + connect(l11 l8 l11 l12) + connect(l12 l11 l12 l13) + connect(l13 l12 l13) + connect(l7 l7) + connect(l2 l8 l2) + connect(l9 l3 l8 l9) + connect(l6 l8 l6) + connect(l10 l8 l10) + + # Global nets and connectivity + global(l7 SUBSTRATE) + global(l10 SUBSTRATE) + + # Device class section + class(PMOS MOS4) + class(NMOS MOS4) + + # Device abstracts section + # Device abstracts list the pin shapes of the devices. + device(D$PMOS PMOS + terminal(S + rect(l2 (-550 -750) (425 1500)) + ) + terminal(G + rect(l4 (-125 -750) (250 1500)) + ) + terminal(D + rect(l2 (125 -750) (450 1500)) + ) + terminal(B + rect(l3 (-125 -750) (250 1500)) + ) + ) + device(D$PMOS$1 PMOS + terminal(S + rect(l2 (-575 -750) (450 1500)) + ) + terminal(G + rect(l4 (-125 -750) (250 1500)) + ) + terminal(D + rect(l2 (125 -750) (425 1500)) + ) + terminal(B + rect(l3 (-125 -750) (250 1500)) + ) + ) + device(D$PMOS$2 PMOS + terminal(S + rect(l2 (-550 -750) (425 1500)) + ) + terminal(G + rect(l4 (-125 -750) (250 1500)) + ) + terminal(D + rect(l2 (125 -750) (425 1500)) + ) + terminal(B + rect(l3 (-125 -750) (250 1500)) + ) + ) + device(D$NMOS NMOS + terminal(S + rect(l6 (-550 -475) (425 950)) + ) + terminal(G + rect(l4 (-125 -475) (250 950)) + ) + terminal(D + rect(l6 (125 -475) (450 950)) + ) + terminal(B + rect(l7 (-125 -475) (250 950)) + ) + ) + device(D$NMOS$1 NMOS + terminal(S + rect(l6 (-575 -475) (450 950)) + ) + terminal(G + rect(l4 (-125 -475) (250 950)) + ) + terminal(D + rect(l6 (125 -475) (425 950)) + ) + terminal(B + rect(l7 (-125 -475) (250 950)) + ) + ) + device(D$NMOS$2 NMOS + terminal(S + rect(l6 (-550 -475) (425 950)) + ) + terminal(G + rect(l4 (-125 -475) (250 950)) + ) + terminal(D + rect(l6 (125 -475) (425 950)) + ) + terminal(B + rect(l7 (-125 -475) (250 950)) + ) + ) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(ND2X1 + + # Circuit boundary + rect((-100 400) (2600 7600)) + + # Nets with their geometries + net(1 name(VDD) + rect(l8 (1110 5160) (180 180)) + rect(l8 (-180 920) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l11 (-240 -790) (300 1700)) + rect(l11 (-1350 0) (2400 800)) + rect(l11 (-1151 -401) (2 2)) + rect(l2 (-276 -2151) (425 1500)) + rect(l2 (-400 -1500) (425 1500)) + ) + net(2 name(OUT) + rect(l8 (1810 1770) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l8 (-1580 3760) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (1220 920) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l8 (-180 370) (180 180)) + polygon(l11 (-240 -4180) (0 1390) (490 0) (0 -300) (-190 0) (0 -1090)) + rect(l11 (-110 1390) (300 1400)) + polygon(l11 (-1890 0) (0 600) (300 0) (0 -300) (1590 0) (0 -300)) + rect(l11 (-141 -501) (2 2)) + rect(l11 (-1751 1099) (300 1400)) + rect(l11 (1100 -1700) (300 300)) + rect(l11 (-300 0) (300 1400)) + rect(l2 (-1750 -1450) (425 1500)) + rect(l2 (950 -1500) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(3 name(VSS) + rect(l8 (410 1770) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-240 -1300) (300 1360)) + rect(l11 (-650 -2160) (2400 800)) + rect(l11 (-1151 -401) (2 2)) + rect(l6 (-951 859) (425 950)) + ) + net(4 + rect(l3 (-100 4500) (2600 3500)) + ) + net(5 name(B) + rect(l4 (1425 2860) (250 1940)) + rect(l4 (-345 -950) (300 300)) + rect(l4 (-205 650) (250 2000)) + rect(l4 (-250 -2000) (250 2000)) + rect(l4 (-250 -5390) (250 1450)) + rect(l8 (-285 1050) (180 180)) + rect(l11 (-71 -91) (2 2)) + rect(l11 (-171 -151) (300 300)) + ) + net(6 name(A) + rect(l4 (725 2860) (250 1940)) + rect(l4 (-325 -1850) (300 300)) + rect(l4 (-225 1550) (250 2000)) + rect(l4 (-250 -2000) (250 2000)) + rect(l4 (-250 -5390) (250 1450)) + rect(l8 (-265 150) (180 180)) + rect(l11 (-91 -91) (2 2)) + rect(l11 (-151 -151) (300 300)) + ) + net(7 name(SUBSTRATE)) + net(8 + rect(l6 (975 1660) (425 950)) + rect(l6 (-400 -950) (425 950)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4) + pin(5 name(B)) + pin(6 name(A)) + pin(7 name(SUBSTRATE)) + + # Devices and their connections + device(1 D$PMOS + location(850 5800) + param(L 0.25) + param(W 1.5) + param(AS 0.6375) + param(AD 0.3375) + param(PS 3.85) + param(PD 1.95) + terminal(S 2) + terminal(G 6) + terminal(D 1) + terminal(B 4) + ) + device(2 D$PMOS$1 + location(1550 5800) + param(L 0.25) + param(W 1.5) + param(AS 0.3375) + param(AD 0.6375) + param(PS 1.95) + param(PD 3.85) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(3 D$NMOS + location(850 2135) + param(L 0.25) + param(W 0.95) + param(AS 0.40375) + param(AD 0.21375) + param(PS 2.75) + param(PD 1.4) + terminal(S 3) + terminal(G 6) + terminal(D 8) + terminal(B 7) + ) + device(4 D$NMOS$1 + location(1550 2135) + param(L 0.25) + param(W 0.95) + param(AS 0.21375) + param(AD 0.40375) + param(PS 1.4) + param(PD 2.75) + terminal(S 8) + terminal(G 5) + terminal(D 2) + terminal(B 7) + ) + + ) + circuit(INVX1 + + # Circuit boundary + rect((-100 400) (2000 7600)) + + # Nets with their geometries + net(1 name(VDD) + rect(l8 (410 6260) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l11 (-240 -240) (300 1400)) + rect(l11 (-650 300) (1800 800)) + rect(l11 (-1450 -1100) (300 300)) + rect(l11 (299 399) (2 2)) + rect(l2 (-651 -2151) (425 1500)) + ) + net(2 name(OUT) + rect(l8 (1110 5160) (180 180)) + rect(l8 (-180 920) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (-180 -4120) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-240 -790) (300 4790)) + rect(l11 (-151 -2501) (2 2)) + rect(l2 (-226 1049) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(3 name(VSS) + rect(l8 (410 1770) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-240 -1300) (300 1360)) + rect(l11 (-650 -2160) (1800 800)) + rect(l11 (-851 -401) (2 2)) + rect(l6 (-651 859) (425 950)) + ) + net(4 + rect(l3 (-100 4500) (2000 3500)) + ) + net(5 name(IN) + rect(l4 (725 2860) (250 1940)) + rect(l4 (-525 -1850) (300 300)) + rect(l4 (-25 1550) (250 2000)) + rect(l4 (-250 -2000) (250 2000)) + rect(l4 (-250 -5390) (250 1450)) + rect(l8 (-465 150) (180 180)) + rect(l11 (-91 -91) (2 2)) + rect(l11 (-151 -151) (300 300)) + ) + net(6 name(SUBSTRATE)) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4) + pin(5 name(IN)) + pin(6 name(SUBSTRATE)) + + # Devices and their connections + device(1 D$PMOS$2 + location(850 5800) + param(L 0.25) + param(W 1.5) + param(AS 0.6375) + param(AD 0.6375) + param(PS 3.85) + param(PD 3.85) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(2 D$NMOS$2 + location(850 2135) + param(L 0.25) + param(W 0.95) + param(AS 0.40375) + param(AD 0.40375) + param(PS 2.75) + param(PD 2.75) + terminal(S 3) + terminal(G 5) + terminal(D 2) + terminal(B 6) + ) + + ) + circuit(RINGO + + # Circuit boundary + rect((0 350) (25800 7650)) + + # Nets with their geometries + net(1 + rect(l11 (4040 2950) (610 300)) + ) + net(2 + rect(l11 (5550 2950) (900 300)) + ) + net(3 + rect(l11 (7350 2950) (900 300)) + ) + net(4 + rect(l11 (9150 2950) (900 300)) + ) + net(5 + rect(l11 (10950 2950) (900 300)) + ) + net(6 + rect(l11 (12750 2950) (900 300)) + ) + net(7 + rect(l11 (14550 2950) (900 300)) + ) + net(8 + rect(l11 (16350 2950) (900 300)) + ) + net(9 + rect(l11 (18150 2950) (900 300)) + ) + net(10 + rect(l11 (19950 2950) (900 300)) + ) + net(11 name(FB) + rect(l11 (21750 2950) (900 300)) + rect(l11 (-19530 590) (320 320)) + rect(l11 (17820 -320) (320 320)) + rect(l12 (-18400 -260) (200 200)) + rect(l12 (17940 -200) (200 200)) + rect(l13 (-18040 -300) (17740 400)) + rect(l13 (-17921 -201) (2 2)) + rect(l13 (-221 -201) (400 400)) + rect(l13 (17740 -400) (400 400)) + ) + net(12 name(VDD) + rect(l3 (500 4500) (1400 3500)) + rect(l3 (-1900 -3500) (600 3500)) + rect(l3 (23300 -3500) (1400 3500)) + rect(l3 (-100 -3500) (600 3500)) + rect(l8 (-24690 -1240) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l8 (23220 370) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l11 (-21741 859) (2 2)) + rect(l11 (-2351 -451) (1200 800)) + rect(l11 (-750 -1450) (300 1400)) + rect(l11 (-101 -351) (2 2)) + rect(l11 (-1251 -401) (600 800)) + rect(l11 (23400 -800) (1200 800)) + rect(l11 (-750 -1450) (300 1400)) + rect(l11 (-101 -351) (2 2)) + rect(l11 (549 -401) (600 800)) + rect(l9 (-24850 -1500) (500 1500)) + rect(l9 (22900 -1500) (500 1500)) + ) + net(13 name(OUT) + rect(l11 (23440 3840) (320 320)) + rect(l12 (-260 -260) (200 200)) + rect(l13 (-101 -101) (2 2)) + rect(l13 (-201 -201) (400 400)) + ) + net(14 name(ENABLE) + rect(l11 (2440 2940) (320 320)) + rect(l12 (-260 -260) (200 200)) + rect(l13 (-101 -101) (2 2)) + rect(l13 (-201 -201) (400 400)) + ) + net(15 name(VSS) + rect(l8 (1110 1610) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l8 (23220 370) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-21741 -391) (2 2)) + rect(l11 (-1901 -401) (300 1400)) + rect(l11 (-750 -1450) (1200 800)) + rect(l11 (-551 -401) (2 2)) + rect(l11 (-1251 -401) (600 800)) + rect(l11 (23850 -750) (300 1400)) + rect(l11 (-750 -1450) (1200 800)) + rect(l11 (-551 -401) (2 2)) + rect(l11 (549 -401) (600 800)) + rect(l10 (-24850 -800) (500 1500)) + rect(l10 (22900 -1500) (500 1500)) + ) + + # Outgoing pins and their connections to nets + pin(11 name(FB)) + pin(12 name(VDD)) + pin(13 name(OUT)) + pin(14 name(ENABLE)) + pin(15 name(VSS)) + + # Subcircuits and their connections + circuit(1 ND2X1 location(1800 0) + pin(0 12) + pin(1 1) + pin(2 15) + pin(3 12) + pin(4 11) + pin(5 14) + pin(6 15) + ) + circuit(2 INVX1 location(4200 0) + pin(0 12) + pin(1 2) + pin(2 15) + pin(3 12) + pin(4 1) + pin(5 15) + ) + circuit(3 INVX1 location(6000 0) + pin(0 12) + pin(1 3) + pin(2 15) + pin(3 12) + pin(4 2) + pin(5 15) + ) + circuit(4 INVX1 location(7800 0) + pin(0 12) + pin(1 4) + pin(2 15) + pin(3 12) + pin(4 3) + pin(5 15) + ) + circuit(5 INVX1 location(9600 0) + pin(0 12) + pin(1 5) + pin(2 15) + pin(3 12) + pin(4 4) + pin(5 15) + ) + circuit(6 INVX1 location(11400 0) + pin(0 12) + pin(1 6) + pin(2 15) + pin(3 12) + pin(4 5) + pin(5 15) + ) + circuit(7 INVX1 location(13200 0) + pin(0 12) + pin(1 7) + pin(2 15) + pin(3 12) + pin(4 6) + pin(5 15) + ) + circuit(8 INVX1 location(15000 0) + pin(0 12) + pin(1 8) + pin(2 15) + pin(3 12) + pin(4 7) + pin(5 15) + ) + circuit(9 INVX1 location(16800 0) + pin(0 12) + pin(1 9) + pin(2 15) + pin(3 12) + pin(4 8) + pin(5 15) + ) + circuit(10 INVX1 location(18600 0) + pin(0 12) + pin(1 10) + pin(2 15) + pin(3 12) + pin(4 9) + pin(5 15) + ) + circuit(11 INVX1 location(20400 0) + pin(0 12) + pin(1 11) + pin(2 15) + pin(3 12) + pin(4 10) + pin(5 15) + ) + circuit(12 INVX1 location(22200 0) + pin(0 12) + pin(1 13) + pin(2 15) + pin(3 12) + pin(4 11) + pin(5 15) + ) + + ) +) + +# Reference netlist +reference( + + # Device class section + class(PMOS MOS4) + class(NMOS MOS4) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(ND2X1 + + # Nets + net(1 name(VDD)) + net(2 name(OUT)) + net(3 name(VSS)) + net(4 name(NWELL)) + net(5 name(B)) + net(6 name(A)) + net(7 name(BULK)) + net(8 name('1')) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4 name(NWELL)) + pin(5 name(B)) + pin(6 name(A)) + pin(7 name(BULK)) + + # Devices and their connections + device(1 PMOS + name($1) + param(L 0.251) + param(W 1.6) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 2) + terminal(G 6) + terminal(D 1) + terminal(B 4) + ) + device(2 PMOS + name($2) + param(L 0.25) + param(W 1.5) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(3 NMOS + name($3) + param(L 0.26) + param(W 1) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 3) + terminal(G 6) + terminal(D 8) + terminal(B 7) + ) + device(4 NMOS + name($4) + param(L 0.25) + param(W 0.95) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 8) + terminal(G 5) + terminal(D 2) + terminal(B 7) + ) + + ) + circuit(INVX1 + + # Nets + net(1 name(VDD)) + net(2 name(OUT)) + net(3 name(VSS)) + net(4 name(NWELL)) + net(5 name(IN)) + net(6 name(BULK)) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4 name(NWELL)) + pin(5 name(IN)) + pin(6 name(BULK)) + + # Devices and their connections + device(1 PMOS + name($1) + param(L 0.25) + param(W 1.5) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(2 NMOS + name($2) + param(L 0.25) + param(W 0.95) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 3) + terminal(G 5) + terminal(D 2) + terminal(B 6) + ) + + ) + circuit(RINGO + + # Nets + net(1 name(VSS)) + net(2 name(VDD)) + net(3 name(FB)) + net(4 name(ENABLE)) + net(5 name(OUT)) + net(6 name('1')) + net(7 name('2')) + net(8 name('3')) + net(9 name('4')) + net(10 name('5')) + net(11 name('6')) + net(12 name('7')) + net(13 name('8')) + net(14 name('9')) + net(15 name('10')) + + # Outgoing pins and their connections to nets + pin(1 name(VSS)) + pin(2 name(VDD)) + pin(3 name(FB)) + pin(4 name(ENABLE)) + pin(5 name(OUT)) + + # Subcircuits and their connections + circuit(1 ND2X1 name($1) + pin(0 2) + pin(1 6) + pin(2 1) + pin(3 2) + pin(4 3) + pin(5 4) + pin(6 1) + ) + circuit(2 INVX1 name($2) + pin(0 2) + pin(1 7) + pin(2 1) + pin(3 2) + pin(4 6) + pin(5 1) + ) + circuit(3 INVX1 name($3) + pin(0 2) + pin(1 8) + pin(2 1) + pin(3 2) + pin(4 7) + pin(5 1) + ) + circuit(4 INVX1 name($4) + pin(0 2) + pin(1 9) + pin(2 1) + pin(3 2) + pin(4 8) + pin(5 1) + ) + circuit(5 INVX1 name($5) + pin(0 2) + pin(1 10) + pin(2 1) + pin(3 2) + pin(4 9) + pin(5 1) + ) + circuit(6 INVX1 name($6) + pin(0 2) + pin(1 11) + pin(2 1) + pin(3 2) + pin(4 10) + pin(5 1) + ) + circuit(7 INVX1 name($7) + pin(0 2) + pin(1 12) + pin(2 1) + pin(3 2) + pin(4 11) + pin(5 1) + ) + circuit(8 INVX1 name($8) + pin(0 2) + pin(1 13) + pin(2 1) + pin(3 2) + pin(4 12) + pin(5 1) + ) + circuit(9 INVX1 name($9) + pin(0 2) + pin(1 14) + pin(2 1) + pin(3 2) + pin(4 13) + pin(5 1) + ) + circuit(10 INVX1 name($10) + pin(0 2) + pin(1 15) + pin(2 1) + pin(3 2) + pin(4 14) + pin(5 1) + ) + circuit(11 INVX1 name($11) + pin(0 2) + pin(1 3) + pin(2 1) + pin(3 2) + pin(4 15) + pin(5 1) + ) + circuit(12 INVX1 name($12) + pin(0 2) + pin(1 5) + pin(2 1) + pin(3 2) + pin(4 3) + pin(5 1) + ) + + ) +) + +# Cross reference +xref( + circuit(INVX1 INVX1 match + xref( + net(4 4 match) + net(5 5 match) + net(2 2 match) + net(6 6 match) + net(1 1 match) + net(3 3 match) + pin(3 3 match) + pin(4 4 match) + pin(1 1 match) + pin(5 5 match) + pin(0 0 match) + pin(2 2 match) + device(2 2 match) + device(1 1 match) + ) + ) + circuit(ND2X1 ND2X1 match + xref( + net(8 8 mismatch) + net(4 4 match) + net(6 6 match) + net(5 5 match) + net(2 2 mismatch) + net(7 7 mismatch) + net(1 1 mismatch) + net(3 3 match) + pin(3 3 match) + pin(5 5 match) + pin(4 4 match) + pin(1 1 match) + pin(6 6 match) + pin(0 0 match) + pin(2 2 match) + device(3 3 match) + device(4 4 match) + device(1 1 match) + device(2 2 match) + ) + ) + circuit(RINGO RINGO match + xref( + net(1 6 match) + net(10 15 match) + net(2 7 match) + net(3 8 match) + net(4 9 match) + net(5 10 match) + net(6 11 match) + net(7 12 match) + net(8 13 match) + net(9 14 match) + net(14 4 match) + net(11 3 match) + net(13 5 match) + net(12 2 match) + net(15 1 match) + pin(3 3 match) + pin(0 2 match) + pin(2 4 match) + pin(1 1 match) + pin(4 0 match) + circuit(2 2 match) + circuit(3 3 match) + circuit(4 4 match) + circuit(5 5 match) + circuit(6 6 match) + circuit(7 7 match) + circuit(8 8 match) + circuit(9 9 match) + circuit(10 10 match) + circuit(11 11 match) + circuit(12 12 match) + circuit(1 1 match) + ) + ) +) diff --git a/testdata/ruby/dbNetlistCompare.rb b/testdata/ruby/dbNetlistCompare.rb index d256aa849..7eb87c8e3 100644 --- a/testdata/ruby/dbNetlistCompare.rb +++ b/testdata/ruby/dbNetlistCompare.rb @@ -508,10 +508,39 @@ END assert_equal(good, true) + logger.clear + nl2.device_class_by_name("NMOS").equal_parameters = nil + assert_equal(nl2.device_class_by_name("NMOS").equal_parameters == nil, true) + good = comp.compare(nl1, nl2) + + assert_equal(logger.text, <<"END") +begin_circuit BUF BUF +match_nets OUT OUT +match_nets INT $10 +net_mismatch IN IN +net_mismatch 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) + logger.clear eqp = RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_W, 0.01, 0.0) eqp = eqp + RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_L, 0.2, 0.0) nl2.device_class_by_name("NMOS").equal_parameters = eqp + assert_equal(nl2.device_class_by_name("NMOS").equal_parameters == nil, false) good = comp.compare(nl1, nl2) assert_equal(logger.text, <<"END") @@ -538,9 +567,9 @@ END assert_equal(good, true) logger.clear - eqp = RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_W, 0.01, 0.0) - eqp += RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_L, 0.2, 0.0) - nl2.device_class_by_name("NMOS").equal_parameters = eqp + dc = nl2.device_class_by_name("NMOS") + dc.equal_parameters = RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_W, 0.01, 0.0) + dc.equal_parameters += RBA::EqualDeviceParameters::new(RBA::DeviceClassMOS3Transistor::PARAM_L, 0.2, 0.0) good = comp.compare(nl1, nl2) assert_equal(logger.text, <<"END")