# LVS Input/Output

LVS (and also DRC as far as netlist extraction is concerned) provides interfaces to write and read netlists/schematics, annotated layout and LVS results. There are three major categories of I/O:

- Netlist: this is the plain circuit information. With subcircuit this forms a hierarchical netlist. Currently, the format available to import and export netlists is a certain SPICE netlist flavor. It's possible to customize the reading and writing process to achieve some flexibility.
- Layout-to-netlist database (L2N DB): also called extracted netlist or annotated layout. This is the netlist taken from the original layout together with the corresponding shapes. This database allows reconstructing a net geometrically as far as non-device shapes are involved. Devices are abstracted by their terminal geometries.
- LVS result database (LVS DB): this is the L2N database plus the reference netlist and a "cross reference": a list of paired circuits, nets, devices, pins and subcircuits and status information. The cross-reference is both a lookup table and a debugging aid.

## Writing netlists

You can write a netlist file to supply netlists for (functional) simulators for example. Within LVS scripts, the global "target_netlist" statement triggers writing of a netlist (see target_netlist for details).

    target_netlist("output.cir", write_spice, "Created by KLayout")

This statement can basically appear anywhere in the LVS script. The netlist will written after the script has executed successfully. The first argument is the file's path (by default relative to the original layout file). The second argument is the "writer". "write_spice" creates a netlist writer writing SPICE format with a limited degree of flexbility. See below for customizing the writer. The third argument finally is an (optional) comment which will be written into the netlist as a header.

The "write_spice" configuration function has two options:

    write_spice(use_net_names, with_comments)

Both options are boolean values. If true and present, the first option will make the writer use the real net's names instead of numerical IDs. If true and present, "with_comments" will embed debug comments into the netlist showing instance locations, pin names etc.

Further customization can be achieved by providing an explicit SPICE writer with a delegate (see ). For doing so, subclass NetlistSpiceWriterDelegate and reimplement one or several of the methods provided for reimplementation. Those are , and .

Here is an example that supplied subcircuit models rather than device elements:

    # Write extracted netlist to extracted.cir using a special
    # writer delegate

    # This delegate makes the writer emit subcicuit calls instead of
    # standard elements for the devices
    class SubcircuitModels < RBA::NetlistSpiceWriterDelegate

      def write_header
        emit_line(".INCLUDE 'models.cir'")
      end

      def write_device(device)
        str = "X" + device.expanded_name
        device_class = device.device_class
        device_class.terminal_definitions.each do |td|
          str += " " + net_to_string(device.net_for_terminal(td.id))
        end
        str += " " + device_class.name
        str += " PARAMS:"
        device_class.parameter_definitions.each do |pd|
          str += " " + pd.name + ("=%.12g" % device.parameter(pd.id))
        end
        emit_line(str)
      end

    end

    # Prepare a writer using the new delegate
    custom_spice_writer = RBA::NetlistSpiceWriter::new(SubcircuitModels::new)
    custom_spice_writer.use_net_names= true
    custom_spice_writer.with_comments = false

    # The declaration of netlist production using the new custom writer
    target_netlist("extracted.cir", custom_spice_writer, "Extracted by KLayout")

This script will produce the following netlist for the simple inverter from the LVS introduction. Instead of printing "M" elements - which is the default - subcircuit calls are produced. This allows putting more elaborate models into subcircuits. The device class name addresses these model subcircuits:

    * Extracted by KLayout
    .INCLUDE 'models.cir'

    .SUBCKT INVERTER
    X$1 VDD IN OUT NWELL PMOS PARAMS: L=0.25 W=1.5 AS=0.675 AD=0.675 PS=3.9 PD=3.9
    X$2 VSS IN OUT SUBSTRATE NMOS PARAMS: L=0.25 W=0.9 AS=0.405 AD=0.405 PS=2.7
    + PD=2.7
    .ENDS INVERTER

Netlists can be written directly from the netlist object. Within the script, the netlist object can be obtained with the netlist function. This function will first trigger a netlist extraction unless this was done already and return a object. Use to write this netlist object then. Unlike "target_netlist", this method is executed immediately and this way, a single netlist can be written to multiple files in different flavours.

## Reading netlists

The main use case for reading netlists is for comparison in LVS. Reference netlists are read with the "schematic" function (see schematic):

    schematic("inverter.cir")

Currently SPICE is understood with some limitations:

- Parametrized circuits are not permitted except for device subcircuits (with a delegate)
- Only a subset of elements is implemented by default. These are "M" (gives "MOS4" device classes), "Q" (gives BJT3 or BJT4 device classes), "R" (gives Resistor device classes), "C" (gives Capacitor device classes) and "D" (gives diode device classes).

As for the SPICE reader, a delegate can be provided to customize the reader. For doing so, subclass the class and reimplement the methods provided. These are: , , and

This example customizes a reader to pull MOS devices from subcircuit models rather than from "M" elements. Basically this customization does the opposite part of the writer customization before (only for MOS devices).

    # Provides a SPICE netlist reader delegate which turns
    # some subcircuit models (for subcircuits NMOS and PMOS)
    # into devices

    class SubcircuitModelsReader < RBA::NetlistSpiceReaderDelegate

      # implements the delegate interface:
      # says we want to catch these subcircuits as devices
      def wants_subcircuit(name)
        name == "NMOS" || name == "PMOS"
      end

      # implements the delegate interface:
      # take and translate the element
      def element(circuit, el, name, model, value, nets, params)

        if el != "X"
          # all other elements are left to the standard implementation
          return super
        end

        if nets.size != 4
          error("Subcircuit #{model} needs four nodes")
        end

        # provide a device class
        cls = circuit.netlist.device_class_by_name(model)
        if ! cls
          cls = RBA::DeviceClassMOS4Transistor::new
          cls.name = model
          circuit.netlist.add(cls)
        end

        # create a device
        device = circuit.create_device(cls, name)

        # and configure the device
        [ "S", "G", "D", "B" ].each_with_index do |t,index|
          device.connect_terminal(t, nets[index])
        end

        # parameters in the model are given in micrometer units, so
        # we need to translate the parameter values from SI to um values:
        device.set_parameter("W", (params["W"] || 0.0) * 1e6)
        device.set_parameter("L", (params["L"] || 0.0) * 1e6)

        return true

      end

    end

    # Instantiate a reader using the new delegate
    reader = RBA::NetlistSpiceReader::new(SubcircuitModelsReader::new)

    # Import the schematic with this reader
    schematic("inv_xmodels.cir", reader)

## Layout-to-Netlist database/report

The layout-to-netlist database (L2N DB) is written using the global report_netlist function. This function can be put anywhere in the script. Writing will happen after the script executed successfully:

    report_netlist("extracted.l2n")

Without the filename, only the netlist browser will be opened but no file will be written. The layout-to-netlist database is a KLayout-specific format. It contains the netlist information plus the shape and instance information from the layout. L2N databases can be read into the netlist browser for example. Hence exchange of extracted netlists is possible.

## Layout-vs-Schematic database/report

The Layout-vs-schematic database (LVS DB) is written using the global report_lvs function. This function can be put anywhere in the script. Writing will happen after the script executed successfully:

    report_lvs("extracted.lvsdb")

Without the filename, only the netlist browser will be opened but no file will be written. The LVS database is a KLayout-specific format. It contains the extracted netlist information, the reference netlist and the cross-reference table. LVS databases can be read into the netlist browser for example. Hence exchange of LVS reports is possible.