Added a new script that can print the creation and modification dates of the library header of any GDS file. Modified the "fakediode_2" cell to put back the diffusion layer---this version only removes the contacts from the original diode cell. This prevents issues with FOM fill generation when using the fakediode cell.
diff --git a/common/get_gds_date.py b/common/get_gds_date.py new file mode 100755 index 0000000..5e0f143 --- /dev/null +++ b/common/get_gds_date.py
@@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# Script to read a GDS file and print out the timestamp(s). + +import os +import sys +import datetime + +def usage(): + print('get_gds_date.py <path_to_gds_in> [-created | -modified]') + +if __name__ == '__main__': + debug = False + + if len(sys.argv) == 1: + print("No options given to change_gds_date.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) != 1: + print("Wrong number of arguments given to get_gds_date.py.") + usage() + sys.exit(0) + + created = True + modified = True + + if '-debug' in optionlist: + debug = True + if '-created' in optionlist: + modified = False + if '-modified' in optionlist: + created = False + + source = arguments[0] + + sourcedir = os.path.split(source)[0] + gdsinfile = os.path.split(source)[1] + + with open(source, 'rb') as ifile: + gdsdata = ifile.read() + + datalen = len(gdsdata) + dataptr = 0 + while dataptr < datalen: + # Read stream records up to any string, then search for search text. + bheader = gdsdata[dataptr:dataptr + 2] + reclen = int.from_bytes(bheader, 'big') + if reclen == 0: + print('Error: found zero-length record at position ' + str(dataptr)) + break + + rectype = gdsdata[dataptr + 2] + datatype = gdsdata[dataptr + 3] + + brectype = rectype.to_bytes(1, byteorder='big') + bdatatype = datatype.to_bytes(1, byteorder='big') + + if rectype == 1: # 1 = beginlib + # Datatype should be 2 + if datatype != 2: + print('Error: Header data type is not 2-byte integer!') + if reclen != 28: + print('Error: Header record length is not 28!') + if debug: + print('Record type = ' + str(rectype) + ' data type = ' + str(datatype) + ' length = ' + str(reclen)) + + if created: + crec1 = gdsdata[dataptr + 4:dataptr + 6] + crec2 = gdsdata[dataptr + 6:dataptr + 8] + crec3 = gdsdata[dataptr + 8:dataptr + 10] + crec4 = gdsdata[dataptr + 10:dataptr + 12] + crec5 = gdsdata[dataptr + 12:dataptr + 14] + crec6 = gdsdata[dataptr + 14:dataptr + 16] + + modyear = int.from_bytes(crec1, 'big') + year = modyear + 1900 + month = int.from_bytes(crec2, 'big') + day = int.from_bytes(crec3, 'big') + hour = int.from_bytes(crec4, 'big') + minute = int.from_bytes(crec5, 'big') + second = int.from_bytes(crec6, 'big') + + print('Created date: {}-{}-{}-{}-{}-{}'.format(year, month, day, hour, minute, second)) + + if modified: + mrec1 = gdsdata[dataptr + 16:dataptr + 18] + mrec2 = gdsdata[dataptr + 18:dataptr + 20] + mrec3 = gdsdata[dataptr + 20:dataptr + 22] + mrec4 = gdsdata[dataptr + 22:dataptr + 24] + mrec5 = gdsdata[dataptr + 24:dataptr + 26] + mrec6 = gdsdata[dataptr + 26:dataptr + 28] + + modyear = int.from_bytes(mrec1, 'big') + year = modyear + 1900 + month = int.from_bytes(mrec2, 'big') + day = int.from_bytes(mrec3, 'big') + hour = int.from_bytes(mrec4, 'big') + minute = int.from_bytes(mrec5, 'big') + second = int.from_bytes(mrec6, 'big') + + print('Modified date: {}-{}-{}-{}-{}-{}'.format(year, month, day, hour, minute, second)) + break + + # Advance the pointer past the data + dataptr += reclen + + exit(0)
diff --git a/sky130/custom/sky130_fd_sc_hd/gds/sky130_ef_sc_hd__fakediode_2.gds b/sky130/custom/sky130_fd_sc_hd/gds/sky130_ef_sc_hd__fakediode_2.gds index f3d1e24..9fe03d9 100644 --- a/sky130/custom/sky130_fd_sc_hd/gds/sky130_ef_sc_hd__fakediode_2.gds +++ b/sky130/custom/sky130_fd_sc_hd/gds/sky130_ef_sc_hd__fakediode_2.gds Binary files differ