Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

File formats

reticle-io reads and writes the layout interchange formats and the technology description.

GDSII

GDSII is the long-standing binary interchange format for IC layout. Reticle reads and writes it through gds21, the de facto Rust GDSII library (part of the Layout21 project), mapping its structures, boundaries, paths, and references onto Reticle cells, shapes, instances, and arrays. Round-trip fidelity is tested: a document exported to GDSII and re-imported preserves its geometry, layers, and hierarchy.

The Reticle container format (OASIS-inspired, ADR 0004)

OASIS is the newer, compressed successor to GDSII, but it has no mature Rust library. Reticle’s Oasis type is therefore not a conformant OASIS reader or writer: it is an in-house binary container, OASIS-inspired (it borrows the spirit - a magic string, a START/END frame, and CELL/RECTANGLE/POLYGON/ PATH/TEXT/PLACEMENT/ARRAY records with explicit layer and datatype) but not its wire format. No third-party tool (KLayout, gdstk) can read it. It exists to round-trip Reticle’s own geometry and hierarchy compactly and losslessly for the supported record set; anything unsupported is a clear error rather than silent data loss. See ADR 0004 for the container layout and honest gaps.

Conformant OASIS reader and writer (oasis_std)

Separately, OasisStd is a genuine SEMI P39 OASIS reader and writer for a practical subset - its writer output is read by KLayout as OASIS, and its reader parses that same subset back into a Document, so a document survives a write-then-read round trip. The writer is uncompressed (no CBLOCK), emitting RECTANGLE, POLYGON, PATH, PLACEMENT, and TEXT with fully explicit modal state, CELLNAME+CELL tables, and PLACEMENT records carrying magnification and angle. The reader additionally decodes third-party OASIS constructs real PDKs and KLayout emit that the writer itself never produces: CBLOCK-compressed blocks, repetition records, and the short point-list forms. Documented writer-subset gaps: arrays are expanded to individual placements, a label’s anchor is dropped (OASIS TEXT is a point), and a path’s round end cap is written flush. KLayout reading oasis_std output is verified in-container by the interop harness; see the interop chapter and ADR 0086. The reader is wired into the app’s own open path (crates/reticle-app/src/open.rs), so opening a .oas/.oasis file whose bytes carry the conformant magic uses this reader, not the in-house container above. Check: cargo nextest run -p reticle-io --test oasis_std_read.

CIF

CIF (Caltech Intermediate Format) import reads the classic CIF 2.0 primitive subset used by MOSIS-era mask layouts: symbol definitions (DS/DF), layers (L), boxes (B), polygons (P), wires (W), and symbol calls with transforms (C). Import only; there is no CIF exporter. An unrecognized top-level command is skipped with a warning rather than rejected, so one private extension statement does not sink an otherwise good file. See crates/reticle-io/src/cif.rs for the full grammar and its honest gaps (CIF text/label extensions and rounded-flash geometry are not implemented).

DXF

DXF (Drawing Exchange Format) import reads the layout-relevant 2D subset of the ENTITIES section: LINE, LWPOLYLINE, the classic POLYLINE/VERTEX/SEQEND chain, CIRCLE, ARC, and the common polyline-boundary case of HATCH. Import only; there is no DXF exporter. Every other entity type (TEXT, INSERT, SPLINE, …) is recognized structurally, so it cannot desync the parser, and is skipped with a deduped warning. See crates/reticle-io/src/dxf.rs for the full entity list and its honest gaps (a bulged polyline imports as its straight-edged chord, not its rounded outline).

Magic

Magic (.mag) import reads the classic ASCII per-cell subset: a header, `<< layer

sections carryingrectgeometry, anduseplacements of other (by-name) cells. Import only; there is no Magic exporter. A.magfile describes exactly one cell, so ausebecomes an instance naming the target cell by string, without that cell's own geometry present in the document - real Magic resolves auseat read time from a directory of sibling files, which is out of scope for a reader that sees only one file's bytes. Seecrates/reticle-io/src/mag.rsfor the full grammar and its honest gaps (onlyrectgeometry; notri, polygon`, or label elements).

Technology files

A technology file describes the process: the database resolution, the layer table (numbers, datatypes, names, and display colors), and the design rules. Reticle parses a simple, readable text format into the model’s Technology, which then drives layer display and the design-rule checker.

Streaming a die: the record reader and the .rtla builder

The GDSII importer above reads a whole library into memory under a 256 MiB cap. A full shuttle die is several gigabytes and the in-browser converter runs in a worker, so both need to pull one record at a time without ever holding the whole file. Two pieces make that possible (Wave 2, ADR 0062 and ADR 0063).

GdsRecordReader<R: Read> is a forward-only GDSII reader over any byte source. It hand-rolls the record framing (2-byte length, record type, data type, payload) with no gds21 dependency, so it is wasm-clean, and it yields a small flat vocabulary of GdsEvents (library and struct boundaries, boundaries, paths, references, arrays, text) in document order. It carries the same hardening as the DOM importer: a zero-length string record is rejected before anyone can index data[-1], dates are skipped rather than parsed (so the out-of-range-date panic class cannot fire), and a record length is a 16-bit field, so no count ever drives an allocation past the remaining input. A differential test asserts the streaming reader accepts everything the DOM importer accepts and reports the same cells and per-layer shape counts across the real corpora; a fuzz target (gds_stream) drives it over arbitrary bytes.

build_rtla writes a .rtla streamed archive from a lazy record source using bounded memory. It is external and two-pass: pass 1 streams the records and spills them to sorted run files on disk; pass 2 merges the runs and emits the tiles in directory order, holding at most one sort chunk and one tile in memory. The finest pyramid level is exact (every record reaches it and round-trips); coarser levels are subsampled paint-only approximations. On the 30M-entry generated layout the build peaks at 127 MiB of RSS (far under a 2 GiB budget), and a 120M-record build produces a 2.42 GB archive to completion under the same bound. The on-disk framing (a 32-byte preamble locating the rkyv header and directory blocks, then byte-contiguous tiles) is specified in ADR 0063 so the native and wasm tile sources read to the same layout.

Converting a GDS to a streamable archive

reticle convert <in.gds> <out.rtla> joins those two pieces into one command: it turns a GDSII file into a .rtla archive you can browse over an HTTP range or a memory map without ever loading the whole die. It streams the input twice, holding no whole-file model. Pass one scans every record to find the world bounding box, recover the database scale, and count the drawn elements; pass two reopens the file as a lazy record source and feeds it to build_rtla. Peak memory is the builder’s spill budget, not the file size, so the command scales to the same gigabyte dies the builder targets. The conversion is byte-deterministic: records are emitted in document order, the world box is an order-independent union, the pyramid depth is a pure function of the world span, and the builder writes no timestamps, so the same input always produces identical bytes.

Its v1 flatten scope is deliberately narrow: only directly drawn geometry becomes a record. Each boundary and path bounding box is one tile record, in database units as authored (a path is inflated by half its width). Instance and array references are not composed into world space, because expanding a placement needs random access to the referenced cell’s geometry (a whole-file model), the very thing the streaming path avoids. A referenced cell’s own shapes are still captured where they are drawn, in that cell’s own frame, so a flat or already-flattened GDS (what the tile generator and the export path emit) converts faithfully, while a deeply hierarchical one does not yet reproduce its placements. True hierarchical flattening is a documented follow-up. See ADR 0072 for the flatten and leveling choices.

Robustness

The parsers are fuzzed. A parser must never panic or hang on malformed input; it either produces a document or returns an error. The streaming GdsRecordReader holds the same guarantee: its gds_stream fuzz target seeds from the committed GDS crash fixtures so it cannot reintroduce a fixed panic class, and a native regression test drives it over those fixtures on every platform (libFuzzer cannot link on MSVC).