# LVS Compare

The actual compare step is rather simple. Provided you have set up the extraction (extract_devices), the connectivity (connect, connect_global, connect_implicit) and provided a reference netlist (schematic), this function will perform the actual compare:

    compare

This method (compare will extract the netlist (if not already done) and compare it against the schematic. It returns true on success and false otherwise, in case you like to take specific actions on success or failure.

The compare step can configured by providing hints.

## Net equivalence hint

It can be useful to declare two nets as identical, at least for debugging. The compare algorithm will then be able to deduce the real causes for mismatches. It is helpful for example to provide equivalence for the power nets, because netlist compare fails will often cause the power nets no to be mapped. This in turn prevents matching of other, good parts of the circuit. To supply a power net equivalence for "VDD" within a circuit (e.g. "LOGIC"), use this statement:

    same_nets("LOGIC", "VDD", "VDD:P")

In this example it is assumed that the power net is labeled "VDD" in the layout and called "VDD:P" in the schematic. Don't leave this statement in the script for final verification as it may mask real errors.

For more information about "same_nets" see same_nets.

## Circuit equivalence hint

By default, circuits with the same name are considered equivalent. If this is not the case, equivalence can be established using the same_circuit function:

    same_circuits("CIRCUIT_IN_LAYOUT", "CIRCUIT_IN_SCHEMATIC")

Declaring circuits as 'same' means they will still be compared. The function is just a hint where to look for the compare target.

## Device class equivalence hint

By default, device classes with the same name are considered equivalent. If this is not the case, equivalence can be established using the same_device_classes function:

    same_device_classes("PMOS_IN_LAYOUT", "PMOS_IN_SCHEMATIC")
    same_device_classes("NMOS_IN_LAYOUT", "NMOS_IN_SCHEMATIC")

This method can be used also multiple times to establish a many-to-many equivalence:

    same_device_classes("POLYRES", "RES")
    same_device_classes("WELLRES", "RES")

If one target is "nil", the corresponding devices are basically ignored:

    # ignores "POLYRES" devices:
    same_device_classes("POLYRES", nil)

## 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 additional 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)

or

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

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

Pin swapping can be useful in cases, where a logic element has logically equivalent, but physically different inputs. This is the case for example for a CMOS NAND gate where the logic inputs are equivalent in function, but not in the circuit and physical implementation. For such circuits, the compare function needs to be given a degree of freedom and be allowed to swap the inputs. This is achieved with the equivalent_pins function:

    equivalent_pins("NAND_GATE", "A", "B")

The first argument is the name of the circuit in the layout netlist. You can only specify equivalence in layout, not in the reference schematic. Multiple pins can be listed after the circuit name. All of them will be considered equivalent.

## Capacitor and resistor elimination

This feature allows eliminating "open" resistors and capacitors. Serial resistors cannot be elimiated currently (shorted).

To eliminate all resistors with a resistance value above a certain threshold, use the max_res function. This will eliminate all resistors with a value >= 1kOhm:

    max_res(1000)

To eliminate all capacitors with a capacitance value below a certain threshold, use the min_caps function. This will eliminate all capacitances with a value <= 0.1fF:

    min_caps(1e-16)

## Compare and netlist hierarchy

Good layouts are built hierarchically and the netlist compare can make use of hierarchy. "Hierarchically" means that a circuit is built from cells which itself map to subcircuits of the schematic netlist. The netlist extractor tries hard to maintain the hierarchy and the netlist compare will utilize the hierarchy to provide more meaningful reports and enable a bottom-up design approach.

Given a hierarchical layout and schematic netlist, the compare algorithm will work bottom-up: it will first compare the leaf circuits (circuits without subcircuit calls) and if those match, it will continue with the calling circuits. This approach is more efficient and fosters a clean relationship between layout and schematic netlist.

To enable hierarchical extraction, you must use "deep" mode (deep). If the deep mode statement is missing, the layout netlist will be flat (i.e. without subcircuits).

The second useful feature is "align" (align). This statement will remove circuits from the layout or schematic netlist which are unknown in the other netlist. Often, layouts contain helper cells which are not corresponding to a circuit (e.g. via cells). These are removed in this step. Eventually, this step will also flatten the schematic netlist if the layout has been extracted in a flat way.

In general, it's a good idea to include "align" before "netlist.simplify" or similar netlist manipulation and the "compare" step.

A very useful side effect of "align" is this: it will remove circuits above the top level circuit of either side. So it will eventually render a sub-tree from the circuit tree and use that for compare. This enables subcell verification: by selecting a subcell in the layout hierarchy, an "align"-enabled LVS script will compare this cell against the corresponding subcircuit in the schematic netlist. It will ignore the parent hierarchy of this subcircuit. This way, you can work yourself upwards in the hierarchy and fix LVS errors cell by cell with the same schematic netlist.

## How the compare algorithm works

The coarse flow of the netlist compare algorithm is this:

    foreach circuit bottom up:
      if matching circuit found in reference netlist:
        if all subcircuits have been matched and pin matching has been established for them:
          compare net graph locally from this circuit
        else:
          skip circuit with warning
      else:
        issue a circuit mismatch error

A consequence of this flow is that the compare will stop treating parent circuits when one circuit's pins can't be matched to pins from the corresponding reference circuit or the corresponding circuit can't be found in the reference netlist. This behaviour fosters a bottom-up debugging approach: first fix the issues in subcircuits, then proceed to the parent circuits.

The local net graph compare algorithm is a backtracking algorithm with hinting through topological net classification. Topological net classification is based on nearest-net neighborhood. The following image illustrates this:

Here the IN net's neighborhood is VDD via a traversal of gate to source/drain over M1, to OUT via a twofold traversal of gate to source/drain over M1 and M2 and to VSS via another single traversal of gate to source/drain over M2. This uniquely identifies IN in this simple circuit. In effect, OUT, VDD and VSS can be identified uniquely because their transitions from the IN net are unambigously identifying them. The topological neighborhood is a simple metrics which allows identifying matching nets from two netlists and deducing further relations.

In big netlists, the algorithm will first try to match nets unambigously according to their neighborhood metrics and register them as paired nets. Such pairs often allow deducing further matching pairs. This deduction is continued until all non-ambiguous pairing options are exhausted. For resolving ambiguities, backtracking is employed: the algorithm proposes a match and tentatively proceeds with this assumption. If this execution path leads to a mismatch or logical contradiction, the algorith will go back to the beginning and restart with a new proposal. Backtracking is usually required mainly to match networks with a high symmetry such as clock trees.