.ledrc is the LayoutEditor rule-file language. The Rule File DRC button and Execute on a .ledrc tab in the Text Editor both run this language.
The engine is beta and ships from LayoutEditor 20260823. Every operator in the chapters below runs. There is no remaining Partial item in this reference.
This page is the language overview. Each operator — with a figure — is listed in the chapters below.
Each operator page shows input on the left and result on the right. Blue is layer A, orange is layer B, green is kept geometry, a dashed outline is discarded, and red marks violations (usually an edge pair). Coordinates in the sketches are schematic, not to scale. Y points up, as in the layout.
A check is an expression. width(m1) < 0.14 um already produces markers. check "id" "text" : only attaches a name and a report line.
A filter keeps shapes; it does not create markers. The complement is the layer minus the matching with_ filter, or without_ where that short form exists.
The engine has four value kinds. Nets are polygons that carry an identity after connect; they are not a fifth type.
| Type | What it is | Typical origin |
|---|---|---|
| polygons | Closed rings, optionally with holes | input, boolean, sized, selection, filters |
| edges | Open contour segments | edges(a), inside_part, with_length |
| edge_pairs | Two edges plus a measured distance | Spacing checks, ongrid as a layer, with_angle on polygons |
| texts | Anchor + string | texts |
units 1e-6
grid 0.005 um
mode flat
source TOP
layer m1 = input(68, 20)
layer via = input(70, 20)
layer gate = input(66, 20)
connect m1, via
connect gate, via
check "M1.W" "min width" : width(m1) < 0.14 um
check "M1.S" "min space" : space(m1) < 0.14 um
check "VIA.E" "enclosure" : enc(m1, via) < 0.05 um
check "M1.A" "min area" : area(m1) < 0.09 um2
check "M1.G" "off grid" : ongrid(m1) != 0.005 um
check "ANT.1" "antenna" : antenna(gate, m1) > 200
check "DEN.1" "density" : density(m1, window=50 um, step=25 um) < 0.20
layer dummy = fill(bounds(), exclude=m1 | via, shape=rect(0.5 um, 0.5 um), step=1.0 um)
output dummy 99, 0
inside(a, b) and a.inside(b) are the same.
A deck is UTF-8, one statement per line. # starts a comment outside "…".
units 1e-6
grid 0.005 um
mode flat
source TOP
include "common.ledrc"
units is metres per user unit (default 1e-6). grid is the manufacturing grid and the default for ongrid(layer) when no number is given. source names the start cell. include inserts another .ledrc file. cells keeps shapes from matching cell names. clip is a clip window (AND with the rectangle). gds name = "file" binds a second layout for input(…, from=name). select_checks and unselect_checks choose which check IDs run. max_results is a marker cap, or all. chip yes applies antenna and related rules on the chip top cell only.
mode flat flattens into the source cell (the default). mode deep is hierarchical: intra-cell, then a flatten pass for neighbourhood. mode tiles … tiles the layout; border and threads belong on that line. mode deep and mode tiles exclude each other. If border is omitted for tiles, the engine uses the largest check limit in the file. mode tiles … threads N parallelises the statement DAG inside each tile (tiles themselves stay sequential). The setup line threads N drives the flat pass (1 is serial; 0 or omitted is idealThreadCount); mode deep stays serial.
The GDS database unit comes from the layout, not from the deck.
0.18
0.18 um
180 nm
180 dbu
0.2 um + 1 dbu
inf
Bare numbers are user units. Area uses um2. Comparisons are < <= > >= == !=.
layer name = expr
input(n) and input(n, d) read a GDS layer and datatype. Unmerged input is input(n, d).raw. A second layout is bound with gds other = "file.gds", then input(n, d, from=other).
Boolean operators, weak to strong, are | (OR), ^ (XOR), & (AND), and - (difference). + is the same as |. a & b connected or not_connected keeps only result pieces whose A- and B-shapes sit on the same (connected) or a different (not_connected) geometric net of a|b.
sized(a, d) grows or shrinks. merged(a) unions overlapping shapes; merged(a, n) keeps n-fold overlap. extents(a) is the bbox of each shape; bounds() and bounds(a) are one bbox for the cell or the union of a. hulls and holes split outer contour and holes. snap(a, g) snaps to a grid. flatten(a) copies the layer as polygons. moved, rotated and scaled transform. rounded_corners and smoothed change vertices.
edges(a) is the contour. first_edges and second_edges take the sides of an edge pair. extended turns an edge into a band. start_segments, end_segments and centers cut a piece of length d. corners, bbox_center and intersections yield small boxes. with_edge(a, b) keeps A-shapes that share a collinear edge piece with B. polygons(x) turns pairs back into area.
Keep whole shapes of A when the relation holds to at least one shape of B, using inside, outside, not_inside, interacting, overlapping, covering, touching, cutting, abutting, and the corresponding not_ forms.
Clipping (cut edges, do not keep whole polygons) is inside_part / outside_part. edges(a) & b is inside_part.
One number is an exact value (tolerance 0.5 dbu² for area). Two numbers are [min, max]. inf is an open end.
The filters are with_area, with_perimeter, with_holes, with_angle, with_length, with_width, rectangles, squares, rectilinear, with_bbox, with_area_ratio, with_vertex_count, path_length, and with_distance. A without_ form is the layer minus the matching with_ filter, except the existing short form without_length.
ongrid(a) as a layer yields off-grid vertices as degenerate edge pairs, not the whole polygons. The check ongrid(a) != g marks the same vertices.
inside(a, b) keeps A when all vertices of A lie in some polygon of B — not a full edge-inside test on concave B.
check "M1.S.1" "min space" : space(m1) < 0.18 um
check "M1.S.1" "min space" severity warn : space(m1) < 0.18 um -> 200, 0
layer nar = width(m1) < 0.14 um
severity is error (default), warn or info. The level is stored on every violation, appears as a column in .drc.rpt, and is counted as warnings / infos. The error count and exit code stay the total number of markers.
| Check | Meaning |
|---|---|
| width(a) | Inside |
| space(a) | Outside, all pairs |
| notch(a) | Outside, same shape |
| isolated(a) | Outside, different shapes |
| sep(a, b) | Outside, two layers |
| enc(a, b) | a encloses b |
| enclosed(a, b) | The reverse |
| overlap(a, b) | Overlap width |
| width(a, b) | Inside width of the overlap (AND, then RelWidth) |
Maximum width is width(m1) > 20 um. Hole area is area(holes(m1)) < 0.2 um2. A width table is layer wide = polygons(width(m1) >= 0.5 um) then space(wide).
Shape and hygiene checks are area, ongrid, angle, length, count / empty / not_empty, density, self_intersecting, zero_width, and spikes.
Bare words after the limit are already available:
check "S.1" : space(m1) < 0.18 um projection whole_edges angle_limit(90)
The metric words are euclidean (default), projection, square, and manhattan. Shielding is shielded (default) or unshielded. Further bare words are without_touching_corners, without_touching_edges, whole_edges, and angle_limit(α) (default 90).
New options use name=value: nets=same / nets=different, projecting=min.. max, relation=parallel|acute|perpendicular|obtuse, opposite=only|waive, rect_sides=…, eol=yes, coincident=yes. Example: enc(m1, via) < 0.05 um eol=yes.
connect m1, via
connect gate, via
label m1, txt
check "S.U" : space(m1) < 0.18 um nets=different
check "ANT.M1" : antenna(gate, m1) > 200
connect is transitive. connect reset starts a new block. soft_connect counts for connected() / floating(), but is not conducting for nets= / antenna. Without connect, nets= on a spacing check uses geometric components of a|b; connected(), floating() and antenna have no graph.
layer dummy = fill(bounds(), exclude=m1 | via, shape=rect(0.5 um, 0.5 um), step=1.0 um)
check "D.1" : density(m1, window=50 um, step=25 um) < 0.20
The first argument of fill is always the fill region, not the keep-out. exclude= is the keep-out.
texts(n, d) reads text anchors; expand_text(t, d) makes a mini-box around each anchor. label m1, txt copies a text string onto the net.
The dock button, or JSON from the Text Editor, writes the violation list and markers. output name gds, dt adds an extra layer into the result. check … -> gds, dt writes that check onto a GDS layer. report "file.rdb" and target "out.gds" write a report or result file: .rdb is KLayout RDB XML, any other extension is marker GDS.
Fill and DFM layers are geometry, not violations, unless a check runs on them.
The file may use these; new decks should write the canonical name.
| Canonical | Alias |
|---|---|
| isolated | iso |
| sep | separation |
| enc | enclosing |
| euclidean | euclidian |
| | | + |
| unshielded | transparent |
| nets=same / nets=different | connected / not_connected |
| extended(e, out=d, in=0) | extended_out(e, d) |
| empty(a) | count(a) == 0 |
| self_intersecting | odd_polygons |
On each operator page Available means the operator is executed and produces markers or geometry. Partial would mean it runs with known limits, and Not yet available would mean it is accepted in the file but not executed. None of the operators in these chapters currently use those last two labels.