Skip to content

Instantly share code, notes, and snippets.

@bigjosh
Created September 16, 2025 02:51
Show Gist options
  • Save bigjosh/8417adb3b3242bdb1412e2b56fb82b0c to your computer and use it in GitHub Desktop.
Save bigjosh/8417adb3b3242bdb1412e2b56fb82b0c to your computer and use it in GitHub Desktop.
GDSII Template for 010 Editor
//--- 010 Editor v12.0 Binary Template
//
// File: GDSII.bt
// Author: Gemini
// Version: 2.2
// Purpose: To parse GDSII (Graphic Data System) stream files hierarchically.
// File Mask: *.gds, *.gdsii
// ID Bytes: 00 06 00 02
// History:
// 2.2 2025-09-12 - Fixed 'ReadBytes' error in GDSReal8 struct.
// 2.1 2025-09-12 - Fixed syntax error with fgcolor attribute placement.
// 2.0 2025-09-12 - Reworked to parse hierarchically (Elements in Structures).
// 1.0 2025-09-12 - Initial flat-parsing version.
//------------------------------------------------
BigEndian(); // GDSII stream format is big-endian.
//------------------------------------------------
// Enums and Typedefs
//------------------------------------------------
typedef enum <ubyte> {
NODATA = 0x00,
BITARRAY = 0x01,
INT2 = 0x02,
INT4 = 0x03,
REAL4 = 0x04,
REAL8 = 0x05,
STRING = 0x06
} DataType;
typedef enum <ubyte> {
HEADER = 0x00, BGNLIB = 0x01, LIBNAME = 0x02, UNITS = 0x03, ENDLIB = 0x04,
BGNSTR = 0x05, STRNAME = 0x06, ENDSTR = 0x07, BOUNDARY = 0x08, PATH = 0x09,
SREF = 0x0A, AREF = 0x0B, TEXT = 0x0C, LAYER = 0x0D, DATATYPE_REC = 0x0E,
WIDTH = 0x0F, XY = 0x10, ENDEL = 0x11, SNAME = 0x12, COLROW = 0x13,
TEXTNODE = 0x14, NODE = 0x15, TEXTTYPE = 0x16, PRESENTATION = 0x17,
SPACING = 0x18, STRING_REC = 0x19, STRANS = 0x1A, MAG = 0x1B, ANGLE = 0x1C,
UINTEGER = 0x1D, USTRING = 0x1E, REFLIBS = 0x1F, FONTS = 0x20,
PATHTYPE = 0x21, GENERATIONS = 0x22, ATTRTABLE = 0x23, STYPTABLE = 0x24,
STRTYPE = 0x25, ELFLAGS = 0x26, ELKEY = 0x27, LINKTYPE = 0x28, LINKKEYS = 0x29,
NODETYPE = 0x2A, PROPATTR = 0x2B, PROPVALUE = 0x2C, BOX = 0x2D, BOXTYPE = 0x2E,
PLEX = 0x2F, BGNEXTN = 0x30, ENDEXTN = 0x31, TAPENUM = 0x32, TAPECODE = 0x33,
STRCLASS = 0x34, RESERVED_35 = 0x35, FORMAT = 0x36, MASK = 0x37,
ENDMASKS = 0x38, LIBDIRSIZE = 0x39, SRFNAME = 0x3A, LIBSECUR = 0x3B
} RecordType;
//------------------------------------------------
// Helper Structs & Functions
//------------------------------------------------
typedef struct {
short year; short month; short day;
short hour; short minute; short second;
} GDSDate;
typedef struct {
ubyte exponent_data;
ubyte mantissa_bytes[7];
local ulong mantissa = 0;
local int i;
for(i = 0; i < 7; i++) {
mantissa = (mantissa << 8) | mantissa_bytes[i];
}
local int sign = (exponent_data & 0x80) ? -1 : 1;
local int exponent = (exponent_data & 0x7F) - 64;
local double value = sign * (mantissa / 72057594037927936.0) * Pow(16, exponent);
} GDSReal8;
string ReadRecordName(RecordType rt) {
switch(rt) {
case HEADER: return "HEADER"; case BGNLIB: return "BGNLIB"; case LIBNAME: return "LIBNAME";
case UNITS: return "UNITS"; case ENDLIB: return "ENDLIB"; case BGNSTR: return "BGNSTR";
case STRNAME: return "STRNAME"; case ENDSTR: return "ENDSTR"; case BOUNDARY: return "BOUNDARY";
case PATH: return "PATH"; case SREF: return "SREF"; case AREF: return "AREF";
case TEXT: return "TEXT"; case LAYER: return "LAYER"; case DATATYPE_REC: return "DATATYPE";
case WIDTH: return "WIDTH"; case XY: return "XY"; case ENDEL: return "ENDEL";
case SNAME: return "SNAME"; case COLROW: return "COLROW"; case TEXTTYPE: return "TEXTTYPE";
case PRESENTATION: return "PRESENTATION"; case STRING_REC: return "STRING";
case STRANS: return "STRANS"; case MAG: return "MAG"; case ANGLE: return "ANGLE";
case REFLIBS: return "REFLIBS"; case FONTS: return "FONTS"; case PATHTYPE: return "PATHTYPE";
case GENERATIONS: return "GENERATIONS"; case ATTRTABLE: return "ATTRTABLE";
case ELFLAGS: return "ELFLAGS"; case NODETYPE: return "NODETYPE"; case PROPATTR: return "PROPATTR";
case PROPVALUE: return "PROPVALUE"; case BOX: return "BOX"; case BOXTYPE: return "BOXTYPE";
case PLEX: return "PLEX"; case BGNEXTN: return "BGNEXTN"; case ENDEXTN: return "ENDEXTN";
case FORMAT: return "FORMAT"; case MASK: return "MASK"; case ENDMASKS: return "ENDMASKS";
default: SPrintf(Str("%02Xh"), rt); return Str("%02Xh");
}
}
RecordType PeekRecordType() {
if (FEof()) return -1;
local ushort len = ReadUShort(FTell());
if (len < 4 || FTell() + 2 >= FileSize()) return -1;
return ReadUByte(FTell() + 2);
}
//------------------------------------------------
// Generic Record Parsing Struct
//------------------------------------------------
typedef struct {
ushort length <comment="Total length">;
if (length < 4) { Warning("Invalid record length (< 4)"); return -1; }
RecordType record_type <format=hex, read=ReadRecordName>;
DataType data_type <format=hex>;
local int data_len = length - 4;
switch(record_type) {
case HEADER: short version; break;
case BGNLIB: case BGNSTR: GDSDate mod_time; GDSDate acc_time; break;
case LIBNAME: case STRNAME: case SNAME: case STRING_REC: case PROPVALUE: case ATTRTABLE: case MASK:
char string_data[data_len]; break;
case UNITS: GDSReal8 user_unit; GDSReal8 db_unit_in_meters; break;
case LAYER: short layer_number; break;
case DATATYPE_REC: case TEXTTYPE: case NODETYPE: case BOXTYPE: short type_number; break;
case WIDTH: int width_value; break;
case XY: struct { int x; int y; } coords[data_len/8]; break;
case COLROW: short columns; short rows; break;
case PRESENTATION: ushort p_flags; break;
case STRANS: ushort s_flags; break;
case MAG: GDSReal8 magnification; break;
case ANGLE: GDSReal8 angle_in_deg; break;
case REFLIBS: char lib1[45]; char lib2[45]; break;
case FONTS: char font1[44]; char font2[44]; char font3[44]; char font4[44]; break;
case PATHTYPE: short path_type; break;
case GENERATIONS: short gen_count; break;
case ELFLAGS: ushort e_flags; break;
case PLEX: int plex_number; break;
case PROPATTR: short attribute_number; break;
case FORMAT: short format_type; break;
default: if(data_len > 0) ubyte data[data_len]; break;
}
} GdsRecord;
//------------------------------------------------
// Hierarchical Structs
//------------------------------------------------
// An Element is a geometric shape or reference (e.g. BOUNDARY, PATH, SREF).
typedef struct {
GdsRecord start_element_record <fgcolor=cLtBlue>;
while(PeekRecordType() != ENDEL && PeekRecordType() != -1) {
GdsRecord element_data;
}
if (PeekRecordType() == ENDEL) {
GdsRecord end_element_record;
} else {
Warning("Element did not end with ENDEL.");
}
} Element <read=ReadElementName>;
string ReadElementName(Element &e) {
return ReadRecordName(e.start_element_record.record_type);
}
// A Structure is a collection of Elements, like a cell definition.
typedef struct {
GdsRecord bgnstr <fgcolor=cLtGreen>;
GdsRecord strname;
while(PeekRecordType() != ENDSTR && PeekRecordType() != -1) {
Element element;
}
if (PeekRecordType() == ENDSTR) {
GdsRecord endstr;
} else {
Warning("Structure did not end with ENDSTR.");
}
} Structure <read=ReadStructureName>;
string ReadStructureName(Structure &s) {
return s.strname.string_data;
}
// The top-level file structure, representing the entire library.
typedef struct {
GdsRecord header <fgcolor=cLtYellow>;
GdsRecord bgnlib;
while(PeekRecordType() != ENDLIB && PeekRecordType() != -1) {
if (PeekRecordType() == BGNSTR) {
Structure structure;
} else {
// Parse other library-level records like LIBNAME, UNITS, etc.
GdsRecord lib_data;
}
}
if (PeekRecordType() == ENDLIB) {
GdsRecord endlib;
} else {
Warning("File did not end with ENDLIB.");
}
} GdsFile;
//------------------------------------------------
// Start Parsing
//------------------------------------------------
GdsFile file;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment