Design Rule Checks (DRC) Basics

KLayout supports design rule checks beginning with version 0.23. The capabilities of the DRC feature include:

  • Basic DRC checks such as checks for minimum width and space.
  • Layer-generation methods such as boolean operations and sizing.
  • Extended geometrical checks such as overlap, enclosure and inside and outside checks.
  • Support for edge objects derived from polygons or as output from other functions. Edge objects are useful to implement edge-related operations, for example selective sizing.
  • The capability the work with multiple input layouts.
  • Cell filtering, local (region-constrained) operation.
  • A tiling approach for large layouts which can be configured to make use of multiple CPU cores.

The DRC function is controlled by a script. A DRC script is basically a usualy script that is executed in the context of the DRC engine. The script language is based on KLayout's integrated Ruby interpreter and wraps the scripting methods into a lean and expressive language. Script execution is immediate. That means, that it is possible to embed conditional statements or loops based on the result of a previous operations. It is also possible to code low-level operations on shapes inside the script, although this will be considerably slower than using the functions provided.

Output of the DRC script can be sent to a layout layer or a report database. The report database is visualized in the marker database browser.

Basic scripts

Runset writing is described in detail in DRC Runsets. Here is a simple example for a DRC script:

report("A simple script")

active = input(1, 0)
poly = input(6, 0)
gate = active & poly
gate.width(0.3).output("gate_width", "Gate width violations")

metal1 = input(17, 0)
metal1.width(0.7).output("m1_width", "M1 width violations")
metal1.space(0.4).output("m1_space", "M1 spacing violations")

This script will compute the gate poly shapes from the active and poly layers using a boolean "AND". The active layer has GDS layer 1, while the poly layer has GDS layer 6. On this layer it will perform a width check for 0.3 micrometer. In addition an width and space check on the first metal layer, which is on GDS layer 17.

Let's take the script apart:

  • report("A simple script")
    This line will instruct the script to send output to a report database. The report database is shown in the marker database browser. The description text of the report database is given in brackets.
  • active = input(1, 0)
    This line will create an input layer. "Layers" are basically collections of shapes, edges or edge pairs (edge pairs are objects created as output of check methods). "input" is a function which delivers a layer object. Checks and other functions are performed on those layer objects in the spirit of object-oriented programming and the underlying Ruby interpreter. "active" will be a variable that holds such an object.
    The parameters of the "input" method specify where to take the input from, in that case GDS layer 1 and database 0. In that simple form, the first layout loaded into the current view is used for input.
  • poly = input(6, 0)
    This line will create another input layer for poly silicon (from GDS layer 6, datatype 0).
  • gate = active & poly
    This line will compute the boolean "AND" of active and poly layers. The "&" is the operator for the boolean "AND" operation which computes the intersection of active and poly. The result will be sent to a new layer and a new layer object is created and put into the "gate" variable. This layer object is a temporary one and will not appear in the output but can be used in subsequent operations.
  • gate.width(0.3).output("gate_width", "Gate width violations")
    This line combines two operations into one statement: first is performs a width check against a minimum width of 0.3 micrometer using the width method on the "gate" layer. A "method" is a function performed on a specific object and the notation used in the DRC script is the ".". "gate.width(0.3)" will perform a width check on the gate layer and create a new layer object with "edge pairs" for each violation. "Edge pairs" are marker objects consisting of two edges or partial edges which describe where two edges violate the check condition. In the simple geometrical checks, there are always two edges involved in such a violation - hence such a violation is best described by a pair of edges.
    The result of the check is sent to a report database category using the "output" method. Again this is a method called on an object, in that case the edge pair collection returned by the width check. The parameters of the output method describe a formal name and a readable description of the category.
  • metal1 = input(17, 0)
    As before, this statement will fetch input from GDS layer 17 and datatype 0 and create a layer object representing that input.
  • metal1.width(0.7).output("m1_width", "M1 width violations")
    As for the gate, this statement will perform a width check (this time for 0.7 micrometer) and output the violation markers to a report database category.
  • metal1.space(0.4).output("m1_space", "M1 spacing violations")
    And again a geometrical check: this time a space check for minimum space of 0.4 micrometer.

The script can be written in several alternative forms. Here for example is a very brief version of the gate width check:

(input(1, 0)*input(6, 0)).width(0.3).output("gate_width", "Gate width violations")

Some aliases are provided for the boolean operation, so if you prefer object-oriented notation, you can use the "and" method:

input(1, 0).and(input(6, 0)).width(0.3).output("gate_width", "Gate width violations")

or the functional notation:

and(input(1, 0), input(6, 0)).width(0.3).output("gate_width", "Gate width violations")

Dimensions can be given in different ways:

# floating-point (will default to micrometer)
gate.width(0.3).output("gate_width", "Gate width violations")

# floating-point with unit
gate.width(0.3.micron).output("gate_width", "Gate width violations")
gate.width(300.nm).output("gate_width", "Gate width violations")

# integer values will give dimensions in database units!
gate.width(300).output("gate_width", "Gate width violations")

# as variable
min_width = 300.nm
gate.width(min_width).output("gate_width", "Gate width violations")

Installing and running scripts

To create a DRC script, choose "Tools/DRC/New DRC Script". KLayout will open the Macro development IDE and create a new script. The first thing to do is to give the script a proper name. The cursor is already on the name - just enter a new name and press "Enter".

The next step is to give the DRC script some description. Press the "Properties" button in the macro editor's toolbar and enter a description text - this is the text that will appear in the menu entry.

The DRC script will now appear in "Tools/DRC" with the description and selecting that entry will run the script.

To edit the DRC scripts, choose "Edit DRC Scripts" from "Tools/DRC" or enter the macro editor IDE and select the DRC category (the tab above the macro list).

DRC scripts can be shared or installed globally like normal macros. They can be put into the "macros" folders, but the preferred way is to deploy them in a folder called "drc" beside the "macros" folder. KLayout will scan various places for DRC scripts or macros, including the installation path and the application folder (usually in the home directory). Both places can be used to store DRC scripts.

For the more experienced user, DRC scripts are basically just macros bound to a DRC interpreter instead of the plain Ruby interpreter. You can create and run DRC scripts like ordinary macros. Use "Macros/Macro Development" to enter the macro IDE and create a DRC scripts with the "add macro" function (the "+" button). Choose "DRC scripts" as the template to use (in the "General" section). DRC scripts are by default bound to the DRC menu, but that can be changed like for any ordinary macro.

See About Macro Development for more details about the macro development facility.

By default, DRC scripts are put into the DRC category of the macro IDE. Macro categories are a way to organize macros, but does not imply a certain runtime behavior. DRC scripts can be put into any other location beside the "drc" folders selected by the DRC category.

DRC scripts can be executed in the debugger like ordinary macros and breakpoints or single-stepping can be used to debug DRC scripts. Behind the scene, the DRC commands are mapped to Ruby functions, so stepping into such commands will reveal the code behind the DRC functions.

DRC scripts are stored in ".lydrc" files in KLayout's macro format. Those are XML files containing the script code in the text element. KLayout also recognizes plain text files with the extension ".drc", but those files are lacking the necessary meta-information that allow KLayout to bind them to a menu entry. Hence such files can only be run from the macro IDE.

Using KLayout as a standalone DRC engine

KLayout can be used as a non-interactive DRC engine using a specific kind of DRC scripts. Since there is no "current layout" in standalong engine mode, those DRC script have to specify input explicitly using the "source" function. The same way, output has to be specified explicitly using either "target" to create an output layout or "report" to create an output report database (see DRC Reference: Global Functions for details about these functions).

Here is an example. It reads layer 1, datatype 0 from "input.gds", sizes it by 200 nanometers and writes the output to "out.gds", layer 10, datatype 0:

source("input.gds")
target("out.gds")
input(1, 0).sized(200.nm).output(10, 0)

Here is another example which saves the results to category "sized" of the report database file "out.lyrdb":

source("input.gds")
report("out.lyrdb")
input(1, 0).sized(200.nm).output("sized")

To run these DRC scripts, save the scripts to a file with suffix ".drc" and run it like shown below (replace "my.drc" by your file). It is recommended to disable some of the features not used in that case and put KLayout into non-interactive batch mode with "-b":

klayout -b -r my.drc

"-b" will disable all of the user interface functionality and puts KLayout in engine mode in which no display connection is required on Unix. Implicit loading of macros from the various search locations is disabled (you can still load some with "-rm") and the configuration file is neither read nor written, which causes less I/O and avoids write conflicts between different instances of KLayout.