├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── src ├── Makefile ├── gdsCalmaRecords.h ├── gdsFileParser.cpp ├── gdsFileParser.h └── main.cpp └── testData ├── Lumerical ├── GDS_GC_Ring.gds ├── GDS_GC_Ring.lsf ├── GDS_auto_export.lsf ├── GDS_auto_export_add_cell_to_top.lsf ├── GDS_auto_export_check_type_and_create_cell.lsf ├── GDS_auto_export_find_layer.lsf ├── GDS_auto_export_waveguide.lsf ├── GDS_export.gds ├── GDS_export_import.lsf ├── README ├── layer_builder.lsf ├── layer_builder_y_branch.gds └── output.gds └── juspertor ├── README ├── circles.gds ├── largeArray.gds ├── test-gds.gds └── test.gds /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "testData/caplet"] 2 | path = testData/caplet 3 | url = https://github.com/yuchsiao/caplet.git 4 | [submodule "testData/cpw-resonator"] 5 | path = testData/cpw-resonator 6 | url = https://github.com/axm108/cpw-resonator.git 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 EDDR Software, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | The gdsFileParser verifies GDSII files. The parser mechanism exposes GDSII data with callback functionality. 3 | 4 | # Limitations 5 | This library only parses, at the lowest level, the information contained in the GDSII files. It does not provide an API to store this data in any persistent manner. This is where the programmer must add their implementation on top of this library to make the data useful. 6 | 7 | # Get Involved 8 | If you or your company would like to participate in this project, please email us at support@eddrs.com. If you want to do simple code or documentation fixes but do not want to be a participating party, please take a look at these instructions on how to create a new pull request https://help.github.com/articles/creating-a-pull-request/. 9 | 10 | If you would like to ensure that this library covers a particular file or coverage of data in a file, please email us a test case file at support@eddrs.com or check it into the testData directory by following these instructions: https://help.github.com/articles/creating-a-pull-request/. Please do not check-in any data that you don't want shared with the world. We do not take any responsibility for design data that is part of this repository. 11 | 12 | # The Test Data 13 | Make sure you pull down this repository using the recursive flag. This will supply more test data. 14 | ```sh 15 | git clone --recursive https://github.com/EDDRSoftware/gdsFileParser 16 | ``` 17 | 18 | # Additional Notes 19 | Calma-GDSII to Layout 20 | 21 | Array => Instances 22 | 23 | Boundary element => Polygon, Rectangle, Circle, Hole 24 | 25 | Box element => Rectangle 26 | 27 | Element => Text 28 | 29 | Node => None 30 | 31 | None => Pin 32 | 33 | Path element => Path, Wire, Trace 34 | 35 | Plex => None 36 | 37 | Sref element => Instance 38 | 39 | Structure element => Design 40 | 41 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2017 EDDR Software, LLC. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | # 25 | # Changes: 26 | # 2017-05-05: First & Last Name: What you did. 27 | # 2017-06-10: Kevin Nesmith: Initial reading of the index of the GDSII file. 28 | # 29 | 30 | 31 | default: build 32 | 33 | CXX := /usr/bin/g++ 34 | TARGET := ../lib/libgdsFileParser.a 35 | TARGET_TEMP := gdsFileParser.o 36 | TARGET_TEST := testParser 37 | CXX_FILES := gdsFileParser.cpp 38 | CXX_HEADERS := gdsFileParser.h 39 | 40 | clean: 41 | rm $(TARGET) 42 | rm $(TARGET_TEMP) 43 | rm $(TARGET_TEST) 44 | 45 | build: 46 | mkdir -p ../lib 47 | mkdir -p ../include 48 | $(CXX) -c -o $(TARGET_TEMP) $(CXX_FILES) $(CXX_LIBS) 49 | ar crf $(TARGET) $(TARGET_TEMP) 50 | cp $(CXX_HEADERS) ../include/ 51 | $(CXX) -o $(TARGET_TEST) main.cpp -I. ../lib/libgdsFileParser.a 52 | -------------------------------------------------------------------------------- /src/gdsCalmaRecords.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 EDDR Software, LLC. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Attribution: Thanks for Jim Buchanan for his description of the Calma format. 27 | * http://www.buchanan1.net/stream_description.html 28 | */ 29 | 30 | /* 31 | * Changes: 32 | * 2017-01-01: First & Last Name: What you did. 33 | * 2017-06-10: Kevin Nesmith: Initial contribution. 34 | * 35 | */ 36 | 37 | #ifndef GDSCALMARECORDS_H_ 38 | #define GDSCALMARECORDS_H_ 39 | 40 | namespace gdsfp 41 | { 42 | /* 43 | * Record data type 44 | */ 45 | enum RecordDataType { 46 | NO_DATA = 0x00, 47 | BIT_ARRAY = 0x01, 48 | INTEGER_2 = 0x02, 49 | INTEGER_4 = 0x03, 50 | REAL_4 = 0x04, 51 | REAL_8 = 0x05, 52 | ASCII_STRING = 0x06 53 | }; 54 | 55 | /* 56 | * Record type Data type 57 | */ 58 | enum RecordType { 59 | HEADER = 0x00, /* 0x02 INTEGER_2 Start of stream, contains version number of 60 | stream file. 61 | < v3.0 0x0000 0 62 | v3.0 0x0003 3 63 | v4.0 0x0004 4 64 | v5.0 0x0005 5 65 | v6.0 0x0258 600 */ 66 | BGNLIB = 0x01, /* 0x02 INTEGER_2 Beginning of library, plus mod and access 67 | dates. 68 | Modification: 69 | year, month, day, hour, minute, second 70 | Last access: 71 | year, month, day, hour, minute, second */ 72 | LIBNAME = 0x02, /* 0x06 STRING The name of the library, supposedly following 73 | Calma DOS conventions. Using later tools, 74 | such as ISS LTL-100, it seems more flexible 75 | than that, but it won't allow any old thing 76 | you want. If memory serves, Calma DOS allowed 77 | 6 characters in a file name, with a 2 78 | character extension. */ 79 | UNITS = 0x03, /* 0x05 REAL_8 Size of db unit in user units, size of db 80 | unit in meters. To calculate the size of 81 | a user unit in meters, divide the second 82 | number by the first.*/ 83 | ENDLIB = 0x04, /* 0x00 NO_DATA End of the library. */ 84 | BGNSTR = 0x05, /* 0x02 INTEGER_2 Begin structure, plus create and mod dates in 85 | the same format as the BGNLIB record. */ 86 | STRNAME = 0x06, /* 0x06 STRING Name of a structure. Up to 32 characters in 87 | GDSII, A-Z, a-z, 0-9, _, ?, and $ are all legal characters. */ 88 | ENDSTR = 0x07, /* 0x00 NO_DATA End of a structure. */ 89 | BOUNDARY = 0x08, /* 0x00 NO_DATA The beginning of a BOUNDARY element. */ 90 | PATH = 0x09, /* 0x00 NO_DATA The beginning of a PATH element. */ 91 | SREF = 0x0a, /* 0x00 NO_DATA The beginning of an SREF element. */ 92 | AREF = 0x0b, /* 0x00 NO_DATA The beginning of an AREF element. */ 93 | TEXT = 0x0c, /* 0x00 NO_DATA The beginning of a TEXT element. */ 94 | LAYER = 0x0d, /* 0x02 INTEGER_2 Layer specification. On GDSII this could be 95 | 0 to 63, LTL allows 0 to 255. Of course a 96 | 3 byte integer allows up to 65535... */ 97 | DATATYPE = 0x0e, /* 0x02 INTEGER_2 Datatype specification. On GDSII this could 98 | be 0 to 63, LTL allows 0 to 255. Of course a 99 | 3 byte integer allows up to 65535... */ 100 | WIDTH = 0x0f, /* 0x03 INTEGER_4 Width specification, negative means absolute 101 | In data base units. */ 102 | XY = 0x10, /* 0x03 INTEGER_4 An array of XY coordinates. An array of 103 | coordinates in data base units. 104 | Path: 2 to 200 pairs in GDSII 105 | Boundary: 4 to 200 pairs in GDSII 106 | Text: Exactly 1 pair 107 | SREF: Exactly 1 pair 108 | AREF: Exactly 3 pairs 109 | 1: Array reference point 110 | 2: column_space*columns+reference_x 111 | 3: row_space*rows+reference_y 112 | Node: 1 to 50 pairs in GDSII 113 | Box: Exactly 5 pairs */ 114 | ENDEL = 0x11, /* 0x00 NO_DATA The end of an element. */ 115 | SNAME = 0x12, /* 0x06 STRING The name of a referenced structure. */ 116 | COLROW = 0x13, /* 0x02 INTEGER_2 Columns and rows for an AREF. Two 2 byte 117 | integers. The first is the number of columns. 118 | The second is the number of rows. In an AREF 119 | of course. Neither may exceed 32767 */ 120 | TEXTNODE = 0x14, /* 0x00 NO_DATA "Not currently used" per GDSII Stream Format 121 | Manual, v6.0. Would be the beginning of a 122 | TEXTNODE element if it were. */ 123 | NODE = 0x15, /* 0x00 NO_DATA The beginning of a NODE element. */ 124 | TEXTTYPE = 0x16, /* 0x02 INTEGER_2 Texttype specification. On GDSII this could 125 | be 0 to 63, LTL allows 0 to 255. Of course a 126 | 3 byte integer allows up to 65535... */ 127 | PRESENTATION = 0x17, /* 0x01 BIT_ARRAY Text origin and font specification. 128 | bits 15 to 0, l to r 129 | bits 0 and 1: 00 left, 01 center, 10 right 130 | bits 2 and 3: 00 top 01, middle, 10 bottom 131 | bits 4 and 5: 00 font 0, 01 font 1, 132 | 10 font 2, 11 font 3, */ 133 | SPACING = 0x18, /* UNKNOWN "Discontinued" per GDSII Stream Format 134 | Manual, v6.0. */ 135 | STRING = 0x19, /* 0x06 STRING Character string. Up to 512 char in GDSII */ 136 | STRANS = 0x1a, /* 0x01 BIT_ARRAY Bits 15 to 0, l to r 137 | 15=refl, 2=absmag, 1=absangle, others 138 | reserved for future use. */ 139 | MAG = 0x1b, /* 0x05 REAL_8 Magnification, 1 is the default if omitted. */ 140 | ANGLE = 0x1c, /* 0x05 REAL_8 Angular rotation factor in ccw direction. 141 | If omitted, the default is 0. */ 142 | UINTEGER = 0x1d, /* UNKNOWN User integer, used only in V2.0, when 143 | instreamed, should be converted to property 144 | attribute 126. */ 145 | USTRING = 0x1e, /* UNKNOWN User string, used only in V2.0, when 146 | instreamed, should be converted to property 147 | attribute 127. */ 148 | REFLIBS = 0x1f, /* 0x06 STRING Names of the reference libraries. Starts with 149 | name of the first library and is followed by 150 | the second. There are 44 bytes in each, NULLS 151 | are used for padding, including filling in an 152 | entire unused field. */ 153 | FONTS = 0x20, /* 0x06 STRING Names of the textfont definition files. 4 44 154 | byte fields, padded with NULLS if a field is 155 | unused or less than 44 bytes. */ 156 | PATHTYPE = 0x21, /* 0x02 INTEGER_2 Type of path ends. 157 | 0: Square ended paths 158 | 1: Round ended 159 | 2: Square ended, extended 1/2 width 160 | 4: Variable length extensions, CustomPlus 161 | The default is 0 */ 162 | GENERATIONS = 0x22, /* 0x02 INTEGER_2 Number of deleted or backed up structures to 163 | retain. Seems a bit odd in an archive... 164 | From 2-99, default is 3. */ 165 | ATTRTABLE = 0x23, /* 0x06 STRING Name of the attribute definition file. Max 166 | size 44 bytes. */ 167 | STYPTABLE = 0x24, /* 0x06 STRING "Unreleased feature" per GDSII Stream Format 168 | Manual, v6.0. */ 169 | STRTYPE = 0x25, /* 0x02 INTEGER_2 "Unreleased feature" per GDSII Stream Format 170 | Manual, v6.0 */ 171 | ELFLAGS = 0x26, /* 0x01 BIT_ARRAY Flags for template and exterior data. 172 | bits 15 to 0, l to r 173 | 0=template, 1=external data, others unused */ 174 | ELKEY = 0x27, /* 0x03 INTEGER_4 "Unreleased feature" per GDSII Stream Format 175 | Manual, v6.0. */ 176 | LINKTYPE = 0x28, /* UNKNOWN "Unreleased feature" per GDSII Stream Format 177 | Manual, v6.0. */ 178 | LINKKEYS = 0x29, /* UNKNOWN "Unreleased feature" per GDSII Stream Format 179 | Manual, v6.0. */ 180 | NODETYPE = 0x2a, /* 0x02 INTEGER_2 Nodetype specification. On GDSII this could 181 | be 0 to 63, LTL allows 0 to 255. Of course a 182 | 3 byte integer allows up to 65535... */ 183 | PROPATTR = 0x2b, /* 0x02 INTEGER_2 Property number. */ 184 | PROPVALUE = 0x2c, /* 0x06 STRING Property value. On GDSII, 128 characters max, 185 | unless an SREF, AREF, or NODE, which may 186 | have 512 characters. */ 187 | BOX = 0x2d, /* 0x00 NO_DATA The beginning of a BOX element. */ 188 | BOXTYPE = 0x2e, /* 0x02 INTEGER_2 Boxtype specification. On GDSII this could be 189 | 0 to 63, LTL allows 0 to 255. Of course a 190 | 3 byte integer allows up to 65535... */ 191 | PLEX = 0x2f, /* 0x03 INTEGER_4 Plex number and plexhead flag. The least 192 | significant bit of the most significant byte 193 | is the plexhead flag. Because of this, you 194 | can "only" have 2^24 plex groups. Or is that 195 | 2^24-1? I'm not sure if 0 is a valid plex 196 | group in a stream file. */ 197 | BGNEXTN = 0x30, /* 0x03 INTEGER_4 Path extension beginning for pathtype 4 in 198 | CustomPlus. In database units, may be 199 | negative. */ 200 | ENDEXTN = 0x31, /* 0x03 INTEGER_4 Path extension end for pathtype 4 in 201 | CustomPlus. In database units, may be 202 | negative. */ 203 | TAPENUM = 0x32, /* 0x02 INTEGER_2 Tape number for multi-reel stream file. */ 204 | TAPECODE = 0x33, /* 0x02 INTEGER_2 Tape code to verify that the reel is from the 205 | proper set. 12 bytes that are supposed to 206 | form a unique tape code. */ 207 | STRCLASS = 0x34, /* 0x01 BIT_ARRAY Calma use only. In stream files created by 208 | non-Calma programs, this should be missing or 209 | all field should be 0. */ 210 | RESERVED = 0x35, /* 0x03 INTEGER_4 Used to be NUMTYPES per GDSII Stream Format 211 | Manual, v6.0. */ 212 | FORMAT = 0x36, /* 0x02 INTEGER_2 Archive or Filtered flag. 213 | 0: Archive 214 | 1: filtered */ 215 | MASK = 0x37, /* 0x06 STRING Only in filtered streams. Layers and 216 | datatypes used for mask in a filtered stream 217 | file. A string giving ranges of layers and 218 | datatypes separated by a semicolon. There may 219 | be more than one mask in a stream file. */ 220 | ENDMASKS = 0x38, /* 0x00 NO_DATA The end of mask descriptions. */ 221 | LIBDIRSIZE = 0x39, /* 0x02 INTEGER_2 Number of pages in library director, a GDSII 222 | thing, it seems to have only been used when 223 | Calma INFORM was creating a new library. */ 224 | SRFNAME = 0x3a, /* 0x06 STRING Sticks rule file name. */ 225 | LIBSECUR = 0x3b /* 0x02 INTEGER_2 Access control list stuff for CalmaDOS, 226 | ancient. INFORM used this when creating a new 227 | library. Had 1 to 32 entries with group 228 | numbers, user numbers and access rights. */ 229 | }; 230 | } // End namespace gdsfp 231 | 232 | #endif // GDSCALMARECORDS_H_ 233 | 234 | -------------------------------------------------------------------------------- /src/gdsFileParser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 EDDR Software, LLC. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Changes: 27 | * 2017-01-01: First & Last Name: What you did. 28 | * 2017-06-10: Kevin Nesmith: Initial contribution. 29 | * 30 | */ 31 | 32 | #include "gdsFileParser.h" 33 | #include "gdsCalmaRecords.h" 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | using namespace std; 42 | 43 | namespace gdsfp 44 | { 45 | unsigned long p_256[8] = { 0x1, 46 | 0x100, 47 | 0x10000, 48 | 0x1000000, 49 | 0x100000000, 50 | 0x10000000000, 51 | 0x1000000000000, 52 | 0x100000000000000 53 | }; 54 | 55 | short gdsFileParser::readShort(std::ifstream *input) 56 | { 57 | unsigned char p[2]; 58 | input->read((char *)&p, sizeof(p)); 59 | return ((p[0]<<8) | p[1]); 60 | } 61 | 62 | short gdsFileParser::readShort(stringstream *input) 63 | { 64 | unsigned char p[2]; 65 | input->read((char *)&p, sizeof(p)); 66 | return ((p[0]<<8) | p[1]); 67 | } 68 | 69 | double gdsFileParser::readDouble(stringstream *input) 70 | { 71 | short neg = 1; 72 | unsigned char p[8]; 73 | int exp = 0; 74 | double man = 0.0; 75 | input->read((char *)&p, sizeof(p)); 76 | 77 | if(p[0]>127) { 78 | neg = -1; 79 | exp = p[0] - 192; 80 | } else { 81 | exp = p[0] - 64; 82 | } 83 | 84 | for(int i=1; i<8; ++i) { 85 | man+=(double)p[i]/(double)p_256[i]; 86 | } 87 | 88 | return man * pow(16, exp) * neg; 89 | } 90 | 91 | void gdsFileParser::readString(stringstream *input, string *str) 92 | { 93 | string temp = input->str(); 94 | 95 | for(string::iterator it = temp.begin(); it!=temp.end(); ++it) { 96 | if((*it)<32||(*it)>127) { // We only want viewable characters. 97 | continue; 98 | } 99 | 100 | (*str)+=(*it); 101 | } 102 | } 103 | 104 | int gdsFileParser::readInt(stringstream *input) 105 | { 106 | unsigned char p[4]; 107 | input->read((char *)&p[0], sizeof(p)); 108 | return ((p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]); 109 | } 110 | 111 | unsigned int gdsFileParser::readUInt(stringstream *input) 112 | { 113 | char p[4]; 114 | input->read((char *)&p[0], sizeof(p)); 115 | return ((p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]); 116 | } 117 | 118 | void gdsFileParser::readTimeStamp(stringstream *input, short *year, 119 | short *month, short *day, short *hour, 120 | short *minute, short *sec) 121 | { 122 | (*year) = readShort(input); 123 | (*month) = readShort(input); 124 | (*day) = readShort(input); 125 | (*hour) = readShort(input); 126 | (*minute) = readShort(input); 127 | (*sec) = readShort(input); 128 | 129 | if((*year)<1000) { 130 | (*year)+=1900; 131 | } 132 | } 133 | 134 | void gdsFileParser::readHeader(stringstream *input) 135 | { 136 | onParsedGDSVersion(readShort(input)); 137 | } 138 | 139 | void gdsFileParser::readModTimeStamp(stringstream *input) 140 | { 141 | short year, month, day, hour, minute, sec; 142 | readTimeStamp(input, &year, &month, &day, &hour, &minute, &sec); 143 | onParsedModTime(year, month, day, hour, minute, sec); 144 | } 145 | 146 | void gdsFileParser::readAccessTimeStamp(stringstream *input) 147 | { 148 | short year, month, day, hour, minute, sec; 149 | readTimeStamp(input, &year, &month, &day, &hour, &minute, &sec); 150 | onParsedAccessTime(year, month, day, hour, minute, sec); 151 | } 152 | 153 | void gdsFileParser::readLibName(stringstream *input) 154 | { 155 | std::string libName; 156 | readString(input, &libName); 157 | onParsedLibName(libName.c_str()); 158 | } 159 | 160 | void gdsFileParser::readUnits(stringstream *input) 161 | { 162 | double uu = readDouble(input); 163 | double db = readDouble(input); 164 | onParsedUnits(uu, db); 165 | } 166 | 167 | void gdsFileParser::readStrName(stringstream *input) 168 | { 169 | string strName; 170 | readString(input, &strName); 171 | onParsedStrName(strName.c_str()); 172 | } 173 | 174 | void gdsFileParser::readBoundary(stringstream *input) 175 | { 176 | onParsedBoundaryStart(); 177 | } 178 | 179 | void gdsFileParser::readPath(stringstream *input) 180 | { 181 | onParsedPathStart(); 182 | } 183 | 184 | void gdsFileParser::readBox(stringstream *input) 185 | { 186 | onParsedBoxStart(); 187 | } 188 | 189 | void gdsFileParser::readEndElement(stringstream *input) 190 | { 191 | onParsedEndElement(); 192 | } 193 | 194 | void gdsFileParser::readEndStructure(stringstream *input) 195 | { 196 | onParsedEndStructure(); 197 | } 198 | 199 | void gdsFileParser::readEndLib(stringstream *input) 200 | { 201 | onParsedEndLib(); 202 | } 203 | 204 | void gdsFileParser::readColumnRow(stringstream *input) 205 | { 206 | unsigned short column, row; 207 | column = readShort(input); 208 | row = readShort(input); 209 | onParsedColumnsRows(column, row); 210 | } 211 | 212 | void gdsFileParser::readPathType(stringstream *input) 213 | { 214 | unsigned short path; 215 | path = readShort(input); 216 | onParsedPathType(path); 217 | } 218 | 219 | void gdsFileParser::readStrans(stringstream *input) 220 | { 221 | short strans; 222 | strans = readShort(input); 223 | onParsedStrans(strans); 224 | } 225 | 226 | void gdsFileParser::readPresentation(stringstream *input) 227 | { 228 | short present; 229 | present = readShort(input); 230 | short font, valign, halign; 231 | font = (present & (0x10 | 0x20 | 0x30)); 232 | valign = (present & (0x04 | 0x08)); 233 | halign = (present & (0x01 | 0x02)); 234 | onParsedPresentation(font, valign, halign); 235 | } 236 | 237 | void gdsFileParser::readNode(stringstream *input) 238 | { 239 | onParsedNodeStart(); 240 | } 241 | 242 | void gdsFileParser::readText(stringstream *input) 243 | { 244 | onParsedTextStart(); 245 | } 246 | 247 | void gdsFileParser::readSref(stringstream *input) 248 | { 249 | onParsedSrefStart(); 250 | } 251 | 252 | void gdsFileParser::readAref(stringstream *input) 253 | { 254 | onParsedArefStart(); 255 | } 256 | 257 | void gdsFileParser::readSname(stringstream *input) 258 | { 259 | string sname; 260 | readString(input, &sname); 261 | onParsedSname(sname.c_str()); 262 | } 263 | 264 | void gdsFileParser::readString(stringstream *input) 265 | { 266 | string str; 267 | readString(input, &str); 268 | onParsedString(str.c_str()); 269 | } 270 | 271 | void gdsFileParser::readPropValue(stringstream *input) 272 | { 273 | string prop; 274 | readString(input, &prop); 275 | onParsedPropValue(prop.c_str()); 276 | } 277 | 278 | void gdsFileParser::readXY(stringstream *input) 279 | { 280 | input->seekp(0, ios::end); 281 | unsigned int length = input->tellp(); 282 | int count = length/8; 283 | int x[count]; 284 | int y[count]; 285 | 286 | for(int i=0; iread(&recType, sizeof(recType)); 375 | input->read(&dataType, sizeof(dataType)); 376 | 377 | switch(recType) { 378 | case HEADER: readHeader(input); break; 379 | 380 | case BGNLIB: readModTimeStamp(input); 381 | readAccessTimeStamp(input); break; 382 | 383 | case LIBNAME: readLibName(input); break; 384 | 385 | case BGNSTR: readModTimeStamp(input); 386 | readAccessTimeStamp(input); break; 387 | 388 | case UNITS: readUnits(input); break; 389 | 390 | case STRNAME: readStrName(input); break; 391 | 392 | case BOUNDARY: readBoundary(input); break; 393 | 394 | case PATH: readPath(input); break; 395 | 396 | case ENDEL: readEndElement(input); break; 397 | 398 | case ENDSTR: readEndStructure(input); break; 399 | 400 | case ENDLIB: readEndLib(input); break; 401 | 402 | case COLROW: readColumnRow(input); break; 403 | 404 | case PATHTYPE: readPathType(input); break; 405 | 406 | case STRANS: readStrans(input); break; 407 | 408 | case PRESENTATION: readPresentation(input); break; 409 | 410 | case TEXT: readText(input); break; 411 | 412 | case SREF: readSref(input); break; 413 | 414 | case AREF: readAref(input); break; 415 | 416 | case SNAME: readSname(input); break; 417 | 418 | case STRING: readString(input); break; 419 | 420 | case PROPVALUE: readPropValue(input); break; 421 | 422 | case XY: readXY(input); break; 423 | 424 | case LAYER: readLayer(input); break; 425 | 426 | case WIDTH: readWidth(input); break; 427 | 428 | case DATATYPE: readDataType(input); break; 429 | 430 | case TEXTTYPE: readTextType(input); break; 431 | 432 | case ANGLE: readAngle(input); break; 433 | 434 | case MAG: readMag(input); break; 435 | 436 | case BGNEXTN: readBeginExtension(input); break; 437 | 438 | case ENDEXTN: readEndExtension(input); break; 439 | 440 | case PROPATTR: readPropertyNumber(input); break; 441 | 442 | case NODE: readNode(input); break; 443 | 444 | case NODETYPE: readNodeType(input); break; 445 | 446 | case BOX: readBox(input); break; 447 | 448 | case BOXTYPE: readBoxType(input); break; 449 | 450 | default: 451 | break; 452 | } 453 | } 454 | 455 | int gdsFileParser::parse(const char *filePath) 456 | { 457 | std::ifstream gdsFile(filePath, ios::in | ios::binary); 458 | 459 | if(gdsFile.is_open()) { 460 | stringstream stream(ios::in | ios::out | ios::binary); 461 | unsigned int total = 0; 462 | 463 | do { 464 | stream.str(""); 465 | unsigned short length = readShort(&gdsFile); 466 | 467 | if(length==0) { 468 | break; // We have reached the end of the file. 469 | } 470 | 471 | short sub = sizeof(length); 472 | char buffer[length - sub]; 473 | gdsFile.read((char *)&buffer, sizeof(buffer)); 474 | total += length; 475 | stream.write(buffer, length - sub); 476 | parseBuffer(&stream); 477 | } while(gdsFile.good()); 478 | } else { 479 | cerr << "Error: something is wrong with the file." << endl; 480 | return 1; 481 | } 482 | 483 | return 0; 484 | } 485 | } // End namespace gdsfp 486 | -------------------------------------------------------------------------------- /src/gdsFileParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 EDDR Software, LLC. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Changes: 27 | * 2017-01-01: First & Last Name: What you did. 28 | * 2017-06-10: Kevin Nesmith: Initial contribution. 29 | * 30 | */ 31 | 32 | #ifndef GDSFILEPARSER_H_ 33 | #define GDSFILEPARSER_H_ 34 | 35 | #include 36 | #include 37 | 38 | namespace gdsfp 39 | { 40 | class ifstream; 41 | class gdsFileParser 42 | { 43 | public: 44 | int parse(const char *filePath); 45 | 46 | protected: 47 | virtual void onParsedGDSVersion(unsigned short version) = 0; 48 | virtual void onParsedModTime(short year, short month, short day, 49 | short hour, short minute, short sec) = 0; 50 | virtual void onParsedAccessTime(short year, short month, short day, 51 | short hour, short minute, short sec) = 0; 52 | virtual void onParsedLibName(const char *libName) = 0; 53 | virtual void onParsedUnits(double userUnits, double databaseUnits) = 0; 54 | virtual void onParsedStrName(const char *strName) = 0; 55 | virtual void onParsedBoundaryStart() = 0; 56 | virtual void onParsedPathStart() = 0; 57 | virtual void onParsedBoxStart() = 0; 58 | virtual void onParsedEndElement() = 0; 59 | virtual void onParsedEndStructure() = 0; 60 | virtual void onParsedEndLib() = 0; 61 | virtual void onParsedColumnsRows(unsigned short columns, 62 | unsigned short rows) = 0; 63 | virtual void onParsedPathType(unsigned short pathType) = 0; 64 | virtual void onParsedStrans(short strans) = 0; 65 | virtual void onParsedPresentation(short font, short valign, 66 | short halign) = 0; 67 | virtual void onParsedNodeStart() = 0; 68 | virtual void onParsedTextStart() = 0; 69 | virtual void onParsedSrefStart() = 0; 70 | virtual void onParsedArefStart() = 0; 71 | virtual void onParsedSname(const char *sname) = 0; 72 | virtual void onParsedString(const char *str) = 0; 73 | virtual void onParsedPropValue(const char *propValue) = 0; 74 | virtual void onParsedXY(int count, int x[], int y[]) = 0; 75 | virtual void onParsedLayer(unsigned short layer) = 0; 76 | virtual void onParsedWidth(int width) = 0; 77 | virtual void onParsedDataType(unsigned short dataType) = 0; 78 | virtual void onParsedTextType(unsigned short textType) = 0; 79 | virtual void onParsedAngle(double angle) = 0; 80 | virtual void onParsedMag(double mag) = 0; 81 | virtual void onParsedBeginExtension(unsigned short bext) = 0; 82 | virtual void onParsedEndExtension(unsigned short eext) = 0; 83 | virtual void onParsedPropertyNumber(unsigned short propNum) = 0; 84 | virtual void onParsedNodeType(unsigned short nodeType) = 0; 85 | virtual void onParsedBoxType(unsigned short boxType) = 0; 86 | 87 | private: 88 | void readString(std::stringstream *input, std::string *str); 89 | void readTimeStamp(std::stringstream *input, short *year, short *month, 90 | short *day, short *hour, short *minute, short *sec); 91 | short readShort(std::ifstream *input); 92 | short readShort(std::stringstream *input); 93 | unsigned int readUInt(std::stringstream *input); 94 | int readInt(std::stringstream *input); 95 | double readDouble(std::stringstream *input); 96 | void readHeader(std::stringstream *input); 97 | void readModTimeStamp(std::stringstream *input); 98 | void readAccessTimeStamp(std::stringstream *input); 99 | void parseBuffer(std::stringstream *input); 100 | void readLibName(std::stringstream *input); 101 | void readUnits(std::stringstream *input); 102 | void readStrName(std::stringstream *input); 103 | void readBoundary(std::stringstream *input); 104 | void readPath(std::stringstream *input); 105 | void readNode(std::stringstream *input); 106 | void readBox(std::stringstream *input); 107 | void readEndElement(std::stringstream *input); 108 | void readEndStructure(std::stringstream *input); 109 | void readEndLib(std::stringstream *input); 110 | void readColumnRow(std::stringstream *input); 111 | void readPathType(std::stringstream *input); 112 | void readStrans(std::stringstream *input); 113 | void readPresentation(std::stringstream *input); 114 | void readText(std::stringstream *input); 115 | void readSref(std::stringstream *input); 116 | void readAref(std::stringstream *input); 117 | void readSname(std::stringstream *input); 118 | void readString(std::stringstream *input); 119 | void readPropValue(std::stringstream *input); 120 | void readXY(std::stringstream *input); 121 | void readLayer(std::stringstream *input); 122 | void readWidth(std::stringstream *input); 123 | void readDataType(std::stringstream *input); 124 | void readTextType(std::stringstream *input); 125 | void readAngle(std::stringstream *input); 126 | void readMag(std::stringstream *input); 127 | void readBeginExtension(std::stringstream *input); 128 | void readEndExtension(std::stringstream *input); 129 | void readPropertyNumber(std::stringstream *input); 130 | void readNodeType(std::stringstream *input); 131 | void readBoxType(std::stringstream *input); 132 | }; 133 | 134 | } // End namespace gdsfp 135 | 136 | #endif //GDSFILEPARSER_H_ 137 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 EDDR Software, LLC. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Changes: 27 | * 2017-01-01: First & Last Name: What you did. 28 | * 2017-06-10: Kevin Nesmith: Initial contribution. 29 | * 30 | */ 31 | 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "gdsFileParser.h" 41 | 42 | using namespace std; 43 | 44 | #define SET_2W setfill('0') << setw(2) 45 | 46 | class MyTestParser : public gdsfp::gdsFileParser 47 | { 48 | protected: 49 | virtual void onParsedGDSVersion(unsigned short version) { 50 | cout << "GDSII Version: " << version << endl; 51 | }; 52 | virtual void onParsedModTime(short year, short month, short day, 53 | short hour, short minute, short sec) { 54 | cout << "Modified Time: " << endl; 55 | 56 | if(year==0 && month==0) { 57 | cout << "\tNot recorded." << endl; 58 | } else { 59 | cout << "\t" << year << "-" << SET_2W << month << "-" << SET_2W << 60 | day << " " << SET_2W << hour << ":" << SET_2W << minute << 61 | ":" << SET_2W << sec << endl; 62 | } 63 | }; 64 | virtual void onParsedAccessTime(short year, short month, short day, 65 | short hour, short minute, short sec) { 66 | cout << "Accessed Time: " << endl; 67 | 68 | if(year==0 && month==0) { 69 | cout << "\tNot recorded." << endl; 70 | } else { 71 | cout << "\t" << year << "-" << SET_2W << month << "-" << SET_2W << 72 | day << " " << SET_2W << hour << ":" << SET_2W << minute << 73 | ":" << SET_2W << sec << endl; 74 | } 75 | }; 76 | virtual void onParsedLibName(const char *libName) { 77 | cout << "LibName: " << libName << endl; 78 | }; 79 | virtual void onParsedUnits(double userUnits, double dbUnits) { 80 | cout << "UserUnits: " << setprecision(9) << fixed << userUnits << endl; 81 | cout << "DBUnits: " << setprecision(9) << fixed << dbUnits << endl; 82 | }; 83 | virtual void onParsedStrName(const char *strName) { 84 | cout << "StrName: " << strName << endl; 85 | }; 86 | virtual void onParsedBoundaryStart() { 87 | cout << "Boundry start" << endl; 88 | }; 89 | virtual void onParsedPathStart() { 90 | cout << "Path start" << endl; 91 | }; 92 | virtual void onParsedBoxStart() { 93 | cout << "Box start" << endl; 94 | }; 95 | virtual void onParsedEndElement() { 96 | cout << "Element end" << endl; 97 | }; 98 | virtual void onParsedEndStructure() { 99 | cout << "Structure end" << endl; 100 | }; 101 | virtual void onParsedEndLib() { 102 | cout << "Lib end" << endl; 103 | }; 104 | virtual void onParsedColumnsRows(unsigned short columns, 105 | unsigned short rows) { 106 | cout << "Columns: " << columns << " Rows: " << rows << endl; 107 | }; 108 | virtual void onParsedPathType(unsigned short pathType) { 109 | cout << "PathType: " << pathType << endl; 110 | }; 111 | virtual void onParsedStrans(short strans) { 112 | cout << "Strans: " << strans << endl; 113 | }; 114 | virtual void onParsedPresentation(short font, short valign, 115 | short halign) { 116 | cout << "Font: " << font << endl; 117 | cout << "Valign: " << valign << endl; 118 | cout << "Halign: " << halign << endl; 119 | }; 120 | virtual void onParsedNodeStart() { 121 | cout << "Node start" << endl; 122 | }; 123 | virtual void onParsedTextStart() { 124 | cout << "Text start" << endl; 125 | }; 126 | virtual void onParsedSrefStart() { 127 | cout << "Sref start" << endl; 128 | }; 129 | virtual void onParsedArefStart() { 130 | cout << "Aref start" << endl; 131 | }; 132 | virtual void onParsedSname(const char *sname) { 133 | cout << "Sname: " << sname << endl; 134 | }; 135 | virtual void onParsedString(const char *str) { 136 | cout << "String: " << str << endl; 137 | }; 138 | virtual void onParsedPropValue(const char *propValue) { 139 | cout << "Prop Value: " << propValue << endl; 140 | }; 141 | virtual void onParsedXY(int count, int x[], int y[]) { 142 | cout << "XY: " << count << endl; 143 | 144 | for(int i=0; iyspan/2) {y=yspan/2;} 90 | x=x/1e6; 91 | V(cc,1)=x+x0; 92 | V(cc,2)=y+y0; 93 | V(2*(n_custom+1)-cc+1,1)=x+x0; 94 | V(2*(n_custom+1)-cc+1,2)=-y+y0; 95 | } 96 | } 97 | if (get('make nonsymmetric')==1) { 98 | for (cc=1:n_custom+1) { 99 | x=xmin+(cc-1)*(xmax-xmin)/n_custom-x0; 100 | x=x*1e6; 101 | str1='y1='+eq1+';'; 102 | eval(str1); 103 | eq2=getnamed(obj_name, "equation 2"); 104 | str2='y2='+eq2+';'; 105 | eval(str2); 106 | y1=y1/1e6; 107 | y2=y2/1e6; 108 | if (y1>yspan/2) {y1=yspan/2;} 109 | if (y2>yspan/2) {y2=yspan/2;} 110 | x=x/1e6; 111 | V(cc,1)=x+x0; 112 | V(cc,2)=y1+y0; 113 | V(2*(n_custom+1)-cc+1,1)=x+x0; 114 | V(2*(n_custom+1)-cc+1,2)=-y2+y0; 115 | } 116 | } 117 | ?"custom detected: converted to polygon"; 118 | GDS_auto_export_find_layer; 119 | gdsbegincell(f,obj_name); 120 | gdsaddpoly(f,layer,V); 121 | gdsendcell(f); 122 | } 123 | else { 124 | if (haveproperty('surface units')==1) { 125 | # this is a surface object, ignore 126 | ?"surface detected: ignored"; 127 | } 128 | else { 129 | if (haveproperty('poles')==1) { 130 | # this is a waveguide object, convert to a polygon 131 | ?"waveguide detected: converted to polygon"; 132 | GDS_auto_export_find_layer; 133 | GDS_auto_export_waveguide; 134 | gdsbegincell(f,obj_name); 135 | gdsaddpoly(f,layer,V_final); 136 | gdsendcell(f); 137 | } 138 | else { 139 | if (haveproperty('x span top')==1) { 140 | # this is a pyramid, ignore 141 | ?"pyramid detected: ignored"; 142 | } 143 | else { 144 | # this is a rectangle 145 | ?"rectangle detected"; 146 | GDS_auto_export_find_layer; 147 | gdsbegincell(f,obj_name); 148 | gdsaddrect(f,layer,getnamed (obj_name,"x"), 149 | getnamed (obj_name,"y"), 150 | getnamed (obj_name,"x span"), 151 | getnamed (obj_name,"y span")); 152 | gdsendcell(f); 153 | } 154 | } 155 | } 156 | } 157 | } 158 | } 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /testData/Lumerical/GDS_auto_export_find_layer.lsf: -------------------------------------------------------------------------------- 1 | ##################################################### 2 | # Script file: GDS_auto_export_find_layer.lsf 3 | # Objective: for each object, check its z and z span to find the layer number 4 | # Associated files: 5 | # - GDS_auto_export.lsf 6 | 7 | # Copyright 2014 Lumerical Solutions 8 | ##################################################### 9 | 10 | z = getnamed(obj_name,"z"); 11 | if (haveproperty("z span")==1) { 12 | z_span = getnamed(obj_name,"z span"); 13 | } 14 | if (haveproperty("z span")==0) { 15 | z_span = getnamed(obj_name,"Base Height"); # for waveguide 16 | } 17 | if (round_to_nm==1) { 18 | layer_def=round(layer_def*1e9)*1e-9; 19 | z=round(z*1e9)*1e-9; 20 | z_span=round(z_span*1e9)*1e-9; 21 | } 22 | out=find(layer_def(1:layer_no,2)==z); 23 | format long; 24 | if (out==0) { 25 | ?'"Error:" Layer number not found. The z of the current object "' + obj_name + '" is ' + num2str(z); 26 | ?'The user-defined layer table is: [layer_no, z, z span]'; 27 | ?num2str(layer_def); 28 | ?'Please double-check this object. If it is due to precision errors, you can enable the "round_to_nm" option in the "GDS_auto_export.lsf".'; 29 | break; 30 | } 31 | else { 32 | temp=find(layer_def(1:layer_no,3)==z_span); 33 | if (temp==0) { 34 | ?'"Error:" Layer number not found. The z_span of the current object "' + obj_name + '" is ' + num2str(z_span); 35 | ?'The user-defined layer table is: [layer_no, z, z span]'; 36 | ?num2str(layer_def); 37 | ?'Please double-check this object. If it is due to precision errors, you can enable the "round_to_nm" option in the "GDS_auto_export.lsf".'; 38 | break; 39 | } 40 | else { 41 | if (length(out)==1) { layer=layer_def(out,1); } 42 | else { 43 | for (jj=1:length(out)) { 44 | if (layer_def(out(jj),3)==z_span) { layer=out(jj);} 45 | } 46 | } 47 | format short; 48 | ?"name = \"" + obj_name + "\", layer = " + num2str(layer); 49 | } 50 | } -------------------------------------------------------------------------------- /testData/Lumerical/GDS_auto_export_waveguide.lsf: -------------------------------------------------------------------------------- 1 | ##################################################### 2 | # Script file: GDS_auto_export_waveguide.lsf 3 | # Objective: calculate the vertices based on the poles 4 | # Associated files: 5 | # - GDS_auto_export_check_type_and_create_cell.lsf 6 | 7 | # Copyright 2014 Lumerical Solutions 8 | ##################################################### 9 | 10 | P=get('poles'); 11 | N=size(P); 12 | N=N(1)-1; 13 | x0=get('x'); 14 | y0=get('y'); 15 | z0=get('z'); 16 | zspan=get('Base Height'); 17 | W=get('Base Width'); 18 | 19 | T=matrix(n_wg+1,1); 20 | theta=matrix(n_wg+1,1); 21 | V=matrix(n_wg+1,2); 22 | V_final=matrix(2*(n_wg+1),2); 23 | 24 | # calculate the bezier curve 25 | for (ii=0:n_wg) { 26 | t=(ii/(n_wg)); 27 | T(ii+1)=t; 28 | B1=[0,0]; 29 | for (jj=0:N) { 30 | n=N; k=jj; 31 | # calulate binomial coefficients 32 | nk=1; 33 | if (k>0) { 34 | for (zz=1:k) { nk=nk*(n-(k-zz))/zz; } 35 | } 36 | B1=B1+nk*((1-t)^(N-jj))*(t^jj)*P(jj+1,1:2); } 37 | V(ii+1,1)=x0+B1(1,1); 38 | V(ii+1,2)=y0+B1(1,2); 39 | } 40 | 41 | # plot(V(1:n_wg+1,1), V(1:n_wg+1,2)); 42 | 43 | # calculate the normal plane angle (approximation!) 44 | for (ii=0:n_wg-2) { 45 | dx=V(ii+2,1)-V(ii+1,1); 46 | dy=V(ii+2,2)-V(ii+1,2); 47 | theta1=atan(dy/dx); 48 | dx=V(ii+3,1)-V(ii+2,1); 49 | dy=V(ii+3,2)-V(ii+2,2); 50 | theta2=atan(dy/dx); 51 | theta(ii+2)=(theta1+theta2)/2; 52 | } 53 | theta(1)=atan((V(2,2)-V(1,2))/(V(2,1)-V(1,1))); 54 | theta(n_wg+1)=atan((V(n_wg+1,2)-V(n_wg,2))/(V(n_wg+1,1)-V(n_wg,1))); 55 | 56 | # calculate the final polygon 57 | for (ii=0:n_wg) { 58 | V_final(ii+1,1)=V(ii+1,1)-W/2*sin(theta(ii+1)); 59 | V_final(ii+1,2)=V(ii+1,2)+W/2*cos(theta(ii+1)); 60 | V_final(2*(n_wg+1)-ii,1)=V(ii+1,1)+W/2*sin(theta(ii+1)); 61 | V_final(2*(n_wg+1)-ii,2)=V(ii+1,2)-W/2*cos(theta(ii+1)); 62 | } -------------------------------------------------------------------------------- /testData/Lumerical/GDS_export.gds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EDDRSoftware/gdsFileParser/4ab9c88a227497cad56bc141d624b35b68628435/testData/Lumerical/GDS_export.gds -------------------------------------------------------------------------------- /testData/Lumerical/GDS_export_import.lsf: -------------------------------------------------------------------------------- 1 | # stage 1: setting up some simple structures in FDTD 2 | 3 | deleteall; 4 | 5 | addrect; 6 | set("name","substrate"); 7 | set("x",0); 8 | set("y",0); 9 | set("z",0); 10 | set("x span", 10e-6); 11 | set("y span", 10e-6); 12 | set("z span", 1e-6); 13 | set("material","SiO2 (Glass) - Palik"); 14 | 15 | addpoly; 16 | set("name","Silicon_polygon"); 17 | set("x",-3e-6); 18 | set("y",-2e-6); 19 | set("z", 1e-6); 20 | set("z span", 1e-6); 21 | set("vertices",[0,-1;1,0;-1,0]*1e-6); 22 | set("material","Si (Silicon) - Palik"); 23 | 24 | addstructuregroup; 25 | set("name","Gold_PC_array"); 26 | set("x",0); 27 | set("y",0); 28 | set("z",0); 29 | 30 | addcircle; 31 | set("name","circle_1"); 32 | set("x",0); 33 | set("y",0e-6); 34 | set("z",1e-6); 35 | set("z span", 1e-6); 36 | set("radius", 1e-6); 37 | set("material","Au (Gold) - CRC"); 38 | addtogroup("Gold_PC_array"); 39 | 40 | copy; 41 | set("name","circle_2"); 42 | set("x",3e-6); 43 | set("y",0); 44 | copy; 45 | set("name","circle_3"); 46 | set("x",0); 47 | set("y",3e-6); 48 | copy; 49 | set("name","circle_4"); 50 | set("x",3e-6); 51 | set("y",3e-6); 52 | 53 | setnamed("Gold_PC_array","y",0.5e-6); 54 | # the y-coordinate of "group_1" is shifted by 0.5um, in other words (0,0.5,0)*e-6 55 | 56 | ################################################# 57 | 58 | # stage 2: exporting structure data to a GDS file 59 | 60 | f=gdsopen('GDS_export.gds'); 61 | 62 | # export substrate to cell named 'substrate', in layer 1. 63 | gdsbegincell(f,'Substrate'); 64 | gdsaddrect(f,1,getnamed ("substrate","x"), 65 | getnamed ("substrate","y"), 66 | getnamed ("substrate","x span"), 67 | getnamed ("substrate","y span")); 68 | gdsendcell(f); 69 | 70 | # export polygon to cell named 'Si_polygon', in layer 2. 71 | x = getnamed("Silicon_polygon","x"); 72 | y = getnamed("Silicon_polygon","y"); 73 | V = getnamed ("Silicon_polygon", "vertices"); 74 | num_vertices = size(V); 75 | V = V + [linspace(x,x,num_vertices(1)), linspace(y,y,num_vertices(1))]; 76 | gdsbegincell(f,'Si_polygon'); 77 | gdsaddpoly(f,2,V); 78 | gdsendcell(f); 79 | 80 | # export one gold circle to Au_particle cell, in layer 3. Circle is centered at zero. 81 | # This cell will not actually be imported. We only create it to show how the Au_particle_array cell 82 | # can be created by referencing a different cell. 83 | gdsbegincell(f,'Au_particle'); 84 | gdsaddcircle(f, 3, 0, 0, getnamed("Gold_PC_array::circle_1", "radius")); 85 | gdsendcell(f); 86 | 87 | # export array of 4 circles by reference to the Au_particle cell. Also use layer 3. 88 | # this command can replicate a cell to a new position by dx and dy 89 | gdsbegincell(f,'Au_particle_array'); 90 | gdsaddref(f,'Au_particle', 91 | getnamed("Gold_PC_array::circle_1", "x")+getnamed("Gold_PC_array","x"), 92 | getnamed("Gold_PC_array::circle_1", "y")+getnamed("Gold_PC_array","y")); 93 | gdsaddref(f,'Au_particle', 94 | getnamed("Gold_PC_array::circle_2", "x")+getnamed("Gold_PC_array","x"), 95 | getnamed("Gold_PC_array::circle_2", "y")+getnamed("Gold_PC_array","y")); 96 | gdsaddref(f,'Au_particle', 97 | getnamed("Gold_PC_array::circle_3", "x")+getnamed("Gold_PC_array","x"), 98 | getnamed("Gold_PC_array::circle_3", "y")+getnamed("Gold_PC_array","y")); 99 | gdsaddref(f,'Au_particle', 100 | getnamed("Gold_PC_array::circle_4", "x")+getnamed("Gold_PC_array","x"), 101 | getnamed("Gold_PC_array::circle_4", "y")+getnamed("Gold_PC_array","y")); 102 | gdsendcell(f); 103 | 104 | gdsclose(f); 105 | 106 | ################################################# 107 | 108 | # stage 3: importing a .gds file to FDTD 109 | # Note: If everything is imported properly, there will be two copies of all the objects: 110 | # the original objects created in stage 1, and a copy from the GDSII file. 111 | 112 | gdsimport('GDS_export.gds','Substrate', 1); 113 | set("material","SiO2 (Glass) - Palik"); 114 | set("z",0); 115 | set("z span", 1e-6); 116 | 117 | gdsimport('GDS_export.gds','Si_polygon', 2); 118 | set("material","Si (Silicon) - Palik"); 119 | set("z",1e-6); 120 | set("z span", 1e-6); 121 | 122 | gdsimport('GDS_export.gds','Au_particle_array', 3); 123 | set("material","Au (Gold) - CRC"); 124 | set("z",1e-6); 125 | set("z span", 1e-6); 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /testData/Lumerical/README: -------------------------------------------------------------------------------- 1 | Test data downloaded from: 2 | https://kb.lumerical.com/en/ref_sim_obj_gdsii_import_export.html 3 | https://kb.lumerical.com/en/ref_sim_obj_gdsii_auto_export.html 4 | https://kb.lumerical.com/en/ref_sim_obj_gdsii_real_example.html 5 | https://kb.lumerical.com/en/ref_sim_obj_layer_builder.html 6 | -------------------------------------------------------------------------------- /testData/Lumerical/layer_builder.lsf: -------------------------------------------------------------------------------- 1 | # add layer builder 2 | addlayerbuilder; 3 | 4 | # set background geometry 5 | set("x",0); 6 | set("y",0); 7 | set("z",0); 8 | set("x span", 20e-6); 9 | set("y span", 20e-6); 10 | 11 | # add two layers with specified names 12 | addlayer("substrate"); 13 | addlayer("y-branch"); 14 | 15 | # load GDS file 16 | loadgdsfile("layer_builder_y_branch.gds"); 17 | 18 | # set substrate layer thickness and material 19 | setlayer("substrate","thickness",2e-6); 20 | setlayer("substrate","material","SiO2 (Glass) - Palik"); 21 | 22 | # get list of layers from GDS file 23 | pattern_name = getlayerlist; 24 | 25 | # set patterned layer to use data from the first layer in the GDS file 26 | setlayer("y-branch","layer number",pattern_name{1}); 27 | setlayer("y-branch","pattern material","Si (Silicon) - Palik"); 28 | 29 | # set thickness of y-branch layer 30 | setlayer("y-branch","thickness",0.5e-6); 31 | 32 | #gds position reference 33 | #1 = centered at origin 34 | #2 = centered at upper-left corner 35 | #3 = centered at upper-right corner 36 | #4 = centered at lower-left corner 37 | #5 = centered at lower-right corner 38 | #6 = centered at custom coordinates 39 | set("gds position reference", 6); 40 | set("gds center x", -5e-6); 41 | set("gds center y", -10e-6); -------------------------------------------------------------------------------- /testData/Lumerical/layer_builder_y_branch.gds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EDDRSoftware/gdsFileParser/4ab9c88a227497cad56bc141d624b35b68628435/testData/Lumerical/layer_builder_y_branch.gds -------------------------------------------------------------------------------- /testData/Lumerical/output.gds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EDDRSoftware/gdsFileParser/4ab9c88a227497cad56bc141d624b35b68628435/testData/Lumerical/output.gds -------------------------------------------------------------------------------- /testData/juspertor/README: -------------------------------------------------------------------------------- 1 | Test data downloaded from http://www.layouteditor.net/wiki/GdsIITests. 2 | -------------------------------------------------------------------------------- /testData/juspertor/circles.gds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EDDRSoftware/gdsFileParser/4ab9c88a227497cad56bc141d624b35b68628435/testData/juspertor/circles.gds -------------------------------------------------------------------------------- /testData/juspertor/largeArray.gds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EDDRSoftware/gdsFileParser/4ab9c88a227497cad56bc141d624b35b68628435/testData/juspertor/largeArray.gds -------------------------------------------------------------------------------- /testData/juspertor/test-gds.gds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EDDRSoftware/gdsFileParser/4ab9c88a227497cad56bc141d624b35b68628435/testData/juspertor/test-gds.gds -------------------------------------------------------------------------------- /testData/juspertor/test.gds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EDDRSoftware/gdsFileParser/4ab9c88a227497cad56bc141d624b35b68628435/testData/juspertor/test.gds --------------------------------------------------------------------------------