Created
September 16, 2025 02:51
-
-
Save bigjosh/8417adb3b3242bdb1412e2b56fb82b0c to your computer and use it in GitHub Desktop.
GDSII Template for 010 Editor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//--- 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