Corrected an error in change_gds_cell that fails to handle the GDSism of a null byte after an odd-length string. Added another helper script called find_gds_prefix.py which can find cells with a prefix as added by magic's "gds write" command when dumping a full GDS library into the output.
diff --git a/VERSION b/VERSION index 0a3b55e..f6e5575 100644 --- a/VERSION +++ b/VERSION
@@ -1 +1 @@ -1.0.172 +1.0.173
diff --git a/common/change_gds_cell.py b/common/change_gds_cell.py index 7e2c22a..ddb4e4d 100755 --- a/common/change_gds_cell.py +++ b/common/change_gds_cell.py
@@ -106,6 +106,9 @@ sys.exit(1) bstring = celldata[dataptr + 4: dataptr + reclen] + # Odd length strings end in null byte which needs to be removed + if bstring[-1] == 0: + bstring = bstring[:-1] strname = bstring.decode('ascii') if strname == cellname: print('Cell ' + cellname + ' found at position ' + str(saveptr)) @@ -163,6 +166,9 @@ sys.exit(1) bstring = gdsdata[dataptr + 4: dataptr + reclen] + # Odd length strings end in null byte which needs to be removed + if bstring[-1] == 0: + bstring = bstring[:-1] strname = bstring.decode('ascii') if strname == cellname: print('Cell ' + cellname + ' found at position ' + str(saveptr))
diff --git a/common/find_gds_prefix.py b/common/find_gds_prefix.py new file mode 100755 index 0000000..aeab8cc --- /dev/null +++ b/common/find_gds_prefix.py
@@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# +# Script to read a GDS file, and find the given cellname if it has the +# standard random two-character prefix generated by magic when writing +# out a vendor GDS, and report the prefix. No changes are made to any +# file. + +import os +import sys + +def usage(): + print('find_gds_prefix.py <cell_name> <path_to_cell_gds>') + +if __name__ == '__main__': + debug = False + + if len(sys.argv) == 1: + print("No options given to find_gds_prefix.py.") + usage() + sys.exit(0) + + optionlist = [] + arguments = [] + + for option in sys.argv[1:]: + if option.find('-', 0) == 0: + optionlist.append(option) + else: + arguments.append(option) + + if len(arguments) != 2: + print("Wrong number of arguments given to find_gds_prefix.py.") + usage() + sys.exit(0) + + for option in optionlist: + if option == '-debug': + debug = True + + cellname = arguments[0] + cellsource = arguments[1] + + cellsrcdir = os.path.split(cellsource)[0] + cellinfile = os.path.split(cellsource)[1] + + print('Reading GDS file looking for prefixed cell ' + cellname) + with open(cellsource, 'rb') as ifile: + celldata = ifile.read() + + #---------------------------------------------------------------------- + # Assume that celldata contains the cell in question. + # Find the extend of the data from 'beginstr' to 'endstr' + #---------------------------------------------------------------------- + + datalen = len(celldata) + dataptr = 0 + found = False + while dataptr < datalen: + # Read stream records up to 'beginstr' + bheader = celldata[dataptr:dataptr + 2] + reclen = int.from_bytes(bheader, 'big') + if reclen == 0: + print('Error: found zero-length record at position ' + str(dataptr)) + break + + rectype = celldata[dataptr + 2] + datatype = celldata[dataptr + 3] + + brectype = rectype.to_bytes(1, byteorder='big') + bdatatype = datatype.to_bytes(1, byteorder='big') + + if rectype == 5: # beginstr + saveptr = dataptr + + elif rectype == 6: # strname + if datatype != 6: + print('Error: Structure name record is not a string!') + sys.exit(1) + + bstring = celldata[dataptr + 4: dataptr + reclen] + # Odd length strings end in null byte which needs to be removed + if bstring[-1] == 0: + bstring = bstring[:-1] + strname = bstring.decode('ascii') + if strname[3:] == cellname: + print('Cell ' + strname + ' found at position ' + str(saveptr)) + print('Prefix: ' + strname[0:2]) + found = True + break + elif strname == cellname: + print('Unprefixed cell ' + strname + ' found at position ' + str(saveptr)) + elif debug: + print('Cell ' + strname + ' position ' + str(dataptr) + ' (ignored)') + + # Advance the pointer past the data + dataptr += reclen + + if not found: + print('Failed to find a prefixed cell ' + cellname) + sys.exit(1) + + exit(0)