LEL

LayoutEditor Library

Component libraries are a central part of the SchematicEditor. Every placed device is a reference into a library: the library definition ties together

  • the symbol (graphics and pins shown on the schematic),
  • the schematic / hierarchy role (ports, parameters, optional sheet-as-component),
  • the netlist / model templates used for simulation, and
  • the layout recipe used for schematic-driven layout (SDL).

Without a matching library entry, a schematic can open only as graphics—pins, simulation, and layout generation have nothing to bind to.

Role of the .lel format

.lel (LayoutEditor Library) is the native library format that supports the full set of options the SchematicEditor understands: parameters with formulas, multi-symbol devices, all layout backends ([cell], [macro], [oa], [tcl], [gdsFactory], …), netlist/model per format, extraction hooks, links, and more.

Foreign library/symbol formats (LTspice .asy, xschem .sym, Qucs, Eagle, KiCad, OpenAccess components, …) are converted into this internal component model when opened or imported. After that conversion, the SchematicEditor works on the same in-memory representation that .lel stores. Saving a library as .lel persists the complete native definition; other formats are import sources, not a second equally complete store.

Schematics themselves are stored in LES and reference library components by name + library. Hierarchy may embed a full component copy inside LES as SubComponent (same tag family as below); shared reusable libraries should still live in .lel.

Using LEL in the LayoutEditor

  • Add Library opens a .lel file (or other supported library sources, which are mapped into the same model).
  • Edit Component reads and writes the native tag set; changes go back to the .lel on save.
  • Prefer one authoritative .lel (or OA library) per team for a PDK or company kit; keep component names stable when schematics already reference them.

LEL is a UTF-8 text format in XML style—not strict XML. Many tags are opening-only; field order matters. Prefer round-tripping through Edit Component when unsure.

Encoding

Same entity encoding as LES for single-token fields:

Character / value Stored form
space &sp;
< &lt;
> &gt;
" &quote;
' &rsquo;
newline &newline;
empty string &nbsp;

Raw multi-line bodies (not entity-encoded): Description, Layout, Label, Netlist, Model, extraction bodies. Graphic colors: wire or #rrggbb / named color.


File-level structure

A .lel file may contain any number of the following. Text outside these blocks is ignored.

<Info>
optional library-wide notes
</Info>

<Category group-name>
componentA
componentB
</Category>

<Component component-name>
  …
</Component>

<Info></Info>

Optional free-text information for the whole library (shown in library/info UI).

<Category name></Category>

Groups component names for the Components dock / filter UI.

  • Fields: encoded category name.
  • Body: one component name per line (names that exist in this library).

<Component name></Component>

One complete device definition. The name is the type name used in placements (<Component … name library> in LES).


Component tags

These tags appear inside <Component> (and the same payload is used inside LES <SubComponent> for embedded hierarchy).

<Description></Description>

Free-text description (may include a URL). Raw text.

<Prefix prefix>

Device-name prefix for generated instance names / netlists (opening-only). Empty linked prefixes may be written as _.

<Parameter></Parameter>

Parameter declarations for the component type.

Declaration lines (pseudo-tags):

Declaration Meaning
<string name [default]> String parameter
<int name [default]> Integer (integer accepted on read; writer uses int)
<double name [default]> Floating-point
<list name v1 v2 …> Choice list; with pcbPackage=true values come from the PCB catalog

Option lines until the next <…> declaration:

Option Meaning
callback=… Callback / UI hook
unit=… Unit label
info=… Help text
edit=… Edit policy
display=… Display hint
parse=true Value is an expression (true / True / TRUE / t)
parseAsNum=false Disable numeric parse force
multiplier=true Multiplier-style parameter
pcbPackage=true PCB package selector

<Label></Label>

Instance label template ($devicename, $value, other $parameters). Raw text.

<Symbol [index]></Symbol>

Symbol graphics for slot index (optional; default 0). Repeat for multi-symbol / multi-gate devices.

Primitives inside Symbol (one opening tag per line):

Tag Fields (summary)
<Line x1 y1 … color> Polyline
<Polygon … color> Filled polygon
<Circle x1 y1 x2 y2 color> Bounding-box circle
<Rect x1 y1 x2 y2 color> Rectangle
<Arc … color> Arc
<Text x y size [rotation] color text> Text
<Port x y name [global\|local] [type] [symbolName]> Pin
<Busport x y name [type] [symbolName]> Bus pin

<Offsetlabel angle offsetX offsetY>

Default label offset for a given placement angle (opening-only; zero offsets omitted on write).

<Layout></Layout>

Schematic-driven layout recipe. See Layout section below—this is the link from the schematic device to a layout cell, macro, OA view, Tcl/gdsFactory generator, or package footprint.

<Netlist format></Netlist>

Netlist line template for a named format (spice, hspice, spectre, …). Placeholders such as $devicename, $node(port), $value. Repeat per format.

<Model format></Model>

Model / subcircuit text emitted once per component type (not once per instance), per format.

<netlistFromSchematic/>

Self-closing flag: hierarchical netlist/model content is generated from the defining schematic sheet.

<Extraction method></Extraction>

Device extraction setup.

  • <ExtractionParameter></ExtractionParameter> — raw text
  • <ExtractionDeviceParameter></ExtractionDeviceParameter> — raw text

<Proc formInitProc doneProc>

Optional form-init and done procedure names (opening-only; written only if set).

<OaStoreLayoutOnly true|false>

OpenAccess storage policy (opening-only).

<Link type [cell] [library]>

Component is a link (e.g. to another component, or special link types). Opening-only. Used for linked definitions; parameters/prefix may still be present.


Layout section (<Layout>)

The Layout body is plain text, not XML tags. It is evaluated during schematic-driven layout when the netlist tool resolves a device to a layout cell.

How matching works

  1. The file is scanned top to bottom.
  2. A line starting with [ starts a section (e.g. [cell]). Section names are case-sensitive.
  3. A line starting with # is a comment (ignored).
  4. Other non-empty lines are data rows for the current section.
  5. Fields are whitespace-separated; use quotes if a field contains spaces.
  6. The first field of every data row is the condition.
  7. The first matching row of any supported section wins; evaluation stops.

Condition

The condition is matched against a device token string built roughly as:

<componentTypeName> <param1=value1> <param2=value2> …

(instance parameters as produced for SDL). Matching rules (canUse):

Condition Meaning
* Always matches (unconditional default)
exact string equal to the full device token string Matches
one or more tokens (space-separated) Matches if every given token appears in the device token list (case-insensitive subset match)

Examples:

*                 → always
output=X1         → devices whose parameter set includes output=X1
PMOS w=0.15       → both tokens must be present

* is not a filename or cell-name wildcard—only a condition wildcard.

For [package], a row can also match when the instance’s package parameter equals the condition (usePackage), in addition to normal canUse matching.

Relative file paths in layout rows are resolved relative to the directory of the .lel file (unless absolute / drive-letter paths).

Unknown names are ignored (their data rows do nothing).


Supported types

[ignore]

Skip this device for SDL (no layout cell).

[ignore]
# ignored for parameter
*
Column Meaning
condition Which devices to ignore

Typical use: simulation-only components, supplies, or variants that must not create layout.

[cell]

Import or reuse a layout cell from a file (or from the currently open layout).

[cell]
#for parameter   layout file   cell   [pins…]
*                lib/AND.gds   AND2   A B Y
output=X1        .             AND3_X1
Column Meaning
condition Match rule (see above)
layout file Path to a layout file to import, or . = use/create the cell in the currently open layout database
cell Cell name inside that file. . as cell name is replaced by the condition/device string used for the match
pins… Optional pin names in connection order; fill empty connection names on the device

If the cell is missing and the file is ., an empty cell with that name may be created. Otherwise the file is imported and the named cell must exist.

[package]

PCB / footprint style: import a cell, clone it under a unique name, rewrite texts.

[package]
#for parameter   layout-file   cellname   [portname pinnumber]…   (nc = not connected)
*                pcb/SO8N.gds  SO8N       in+ 3 in- 2 out 1
Package=SO8N     pcb/SO8N.gds  SO8N       …
*                .             $package   …
Column Meaning
condition Match rule, or equals the instance package parameter
layout-file Footprint file (relative to .lel, or absolute). With PCB catalog packages, the shipped pcb/ catalog may supply the file
cellname Cell to import. . → take from instance parameter package. $paramName → take cell name from that instance parameter (PCB package parameters can redirect into the catalog / KiCad .kicad_mod paths)
port / pin pairs Repeated: schematic port name, then footprint pin number text to replace. Use port nc to remove that pin text from the footprint

On use, texts devicename and type in the footprint are replaced; a unique cell name is generated (component + device / package / condition).

[macro]

Run a LayoutEditor .layout macro as a parametric cell generator.

[macro]
#for parameter   macro-file              pins
*                pcb/capacitor.layout    pin1 pin2
Column Meaning
condition Match rule
macro-file Path to the .layout macro (relative to the .lel directory unless absolute)
pins… Optional pin names in order

The macro is executed with defines such as:

Define Content
NETLIST_PIN<n>_NAME Pin name for pin n (1-based)
NETLIST_DEVICENAME Instance device name
NETLIST_PARAMETER Device parameter/token string
NETLIST_PATH / NETLIST_LIBRARYPATH Library directory
NETLIST_MACROPATH Directory of the macro file

The layout cell that is current after a successful macro run becomes the device cell. Macros may also declare their own #parameter / #parameterDouble / #parameterInt headers for interactive PCell use.

[oa]

Load a cell from an OpenAccess library.

[oa]
#condition   lib   cell   view
*            pdk   nmos   layout
Column Meaning
condition Match rule
lib OA library name
cell OA cell name
view OA view (default layout if omitted)
pins… Optional pin names

Requires a working OpenAccess setup / plugin.

[external]

Generate geometry via an external tool (ASCII geometry protocol).

[external]
#condition   lib   cell   view   tool
*            mylib mycell layout mygenerator
Column Meaning
condition Match rule
lib Library name passed to the tool
cell Cell name
view View name (default layout)
tool External tool / generator name
pins… Optional pin names

The tool receives library/cell/view and device parameters and returns ASCII geometry (databaseunits, box, polygon, text, …).

[tcl]

Run a Tcl PCell command in the LayoutEditor Tcl environment (including Magic gencell-style openPDK flows when configured).

[tcl]
#condition   TCL command
*            sky130::sky130_fd_pr__nfet_01v8
Column Meaning
condition Match rule
TCL command Remainder of the line (may contain spaces)—executed as the PCell command

Generated cells are typically named from the component type plus a parameter hash and reused if already present. Requires Tcl support in the build (useTCL).

[gdsFactory]

Generate layout from a gdsfactory Python callable (live worker; not a GDS round-trip).

[gdsFactory]
#condition   callable
*            ihp.cells.nmos
Column Meaning
condition Match rule
callable Remainder of the line—Python callable path (e.g. ihp.cells.nmos)

Place PDK setup (gdsfactory.pdk, etc.) next to the library as required by the gdsFactory bridge. Geometry and ports are imported from the generated component; cells are cached by parameter hash.


Combining sections (extended recipes)

You may stack several sections and conditional rows. Because the first match wins, put specific conditions above a final * fallback:

<Layout>
[cell]
#condition     file              cell
output=X1      std/AND2_X1.gds   AND2_X1
output=X2      std/AND2_X2.gds   AND2_X2
[ignore]
#simulation-only variant
sim=true
[macro]
#fallback generator
*              devices/and2.layout   A B Y
</Layout>

In Edit Component, the simple radio modes write a single section; extended mode edits the full <Layout> text.


Netlist placeholders (brief)

Common tokens in <Netlist> / labels:

Token Meaning
$devicename Instance name
$node(port) Net attached to symbol port port
$value / $param Parameter values
$pinlist-style patterns Depend on how the template was authored (also used when converting foreign formats)

Minimal complete example

<Component rpoly>
<Description>
Poly resistor
</Description>
<Parameter>
<string value 1k>
</Parameter>
<Prefix R>
<Label>
$devicename
$value
</Label>
<Symbol>
<Line 0 0 0 -40 wire>
<Port 0 0 A>
<Port 0 -40 B>
</Symbol>
<Layout>
[macro]
#for parameter   macro-file              pins
*                resistors/rpoly.layout  A B
</Layout>
<Netlist spice>
R$devicename $node(A) $node(B) $value
</Netlist>
</Component>

Relation to other formats

Format Role
LEL Full native library definition (symbol + parameters + layout recipe + netlist/model + …)
LES Schematics: placements reference LEL (or embed SubComponent)
LTspice / xschem / Qucs / Eagle / KiCad / OA Imported into the internal component model; save as LEL to keep all LayoutEditor options

Hand-editing tips: keep attribute/field order from a Save/Edit Component result; validate by reopening the library; put shared PDK cells in version-controlled .lel files rather than duplicating them into every schematic.