blob: b02535f97f709606ce36e56750c6ffa9f8e74af0 [file] [log] [blame]
Tim Edwards51f81422020-07-26 12:49:48 -04001#!/usr/bin/env python3
2#
3# create_gds_library.py
4#
5#----------------------------------------------------------------------------
6# Given a destination directory holding individual GDS files of a number
7# of cells, create a single GDL library file named <alllibname> and place
8# it in the same directory. This is done for the option "compile" if specified
9# for the "-gds" install.
10#----------------------------------------------------------------------------
11
12import os
13import sys
14import glob
15import fnmatch
16import subprocess
17
18#----------------------------------------------------------------------------
19
20def usage():
21 print('')
22 print('Usage:')
23 print(' create_gds_library <destlibdir> <destlib> <startup_script> ')
24 print(' [-compile-only] [-excludelist="file1,file2,..."] [-keep]')
25 print('')
26 print('Create a single GDS library from a set of individual GDS files.')
27 print('')
28 print('where:')
29 print(' <destlibdir> is the directory containing the individual GDS files')
30 print(' <destlib> is the root name of the library file')
31 print(' <startup_script> is the full path to a magic startup script')
32 print(' -compile-only removes the indidual files if specified')
33 print(' -excludelist= is a comma-separated list of files to ignore')
34 print(' -keep keep the Tcl script used to generate the library')
35 print('')
36
37#----------------------------------------------------------------------------
38
Tim Edwards9be4ac22020-07-26 12:59:30 -040039def create_gds_library(destlibdir, destlib, startup_script, do_compile_only=False, excludelist=[], keep=False):
Tim Edwards51f81422020-07-26 12:49:48 -040040
Tim Edwards05e66eb2020-09-24 13:11:59 -040041 # destlib should not have a file extension
42 destlibroot = os.path.splitext(destlib)[0]
43
44 alllibname = destlibdir + '/' + destlibroot + '.gds'
Tim Edwards51f81422020-07-26 12:49:48 -040045 if os.path.isfile(alllibname):
46 os.remove(alllibname)
47
Tim Edwards995c1332020-09-25 15:33:58 -040048 # If file "filelist.txt" exists in the directory, get the list of files from it
49 if os.path.exists(destlibdir + '/filelist.txt'):
50 with open(destlibdir + '/filelist.txt', 'r') as ifile:
51 rlist = ifile.read().splitlines()
52 glist = []
53 for rfile in rlist:
54 glist.append(destlibdir + '/' + rfile)
55 else:
56 glist = glob.glob(destlibdir + '/*.gds')
57 glist.extend(glob.glob(destlibdir + '/*.gdsii'))
58 glist.extend(glob.glob(destlibdir + '/*.gds2'))
59
Tim Edwards51f81422020-07-26 12:49:48 -040060 if alllibname in glist:
61 glist.remove(alllibname)
62
63 # Create exclude list with glob-style matching using fnmatch
64 if len(glist) > 0:
65 glistnames = list(os.path.split(item)[1] for item in glist)
66 notglist = []
67 for exclude in excludelist:
68 notglist.extend(fnmatch.filter(glistnames, exclude))
69
70 # Apply exclude list
71 if len(notglist) > 0:
72 for file in glist[:]:
73 if os.path.split(file)[1] in notglist:
74 glist.remove(file)
75
76 if len(glist) > 1:
77 print('New file is: ' + alllibname)
78
79 if os.path.isfile(startup_script):
80 # If the symbolic link exists, remove it.
81 if os.path.isfile(destlibdir + '/.magicrc'):
82 os.remove(destlibdir + '/.magicrc')
83 os.symlink(startup_script, destlibdir + '/.magicrc')
84
85 # A GDS library is binary and requires handling in Magic
86 print('Creating magic generation script to generate GDS library.')
87 with open(destlibdir + '/generate_magic.tcl', 'w') as ofile:
88 print('#!/usr/bin/env wish', file=ofile)
89 print('#--------------------------------------------', file=ofile)
90 print('# Script to generate .gds library from files ', file=ofile)
91 print('#--------------------------------------------', file=ofile)
92 print('drc off', file=ofile)
93 print('gds readonly true', file=ofile)
94 print('gds flatten true', file=ofile)
95 print('gds rescale false', file=ofile)
96 print('tech unlock *', file=ofile)
97
98 for gdsfile in glist:
99 print('gds read ' + gdsfile, file=ofile)
100
Tim Edwards05e66eb2020-09-24 13:11:59 -0400101 print('puts stdout "Creating cell ' + destlibroot + '"', file=ofile)
102 print('load ' + destlibroot, file=ofile)
Tim Edwards51f81422020-07-26 12:49:48 -0400103 print('puts stdout "Adding cells to library"', file=ofile)
104 print('box values 0 0 0 0', file=ofile)
105 for gdsfile in glist:
106 gdsroot = os.path.split(gdsfile)[1]
107 gdsname = os.path.splitext(gdsroot)[0]
108 print('getcell ' + gdsname, file=ofile)
109 # Could properly make space for the cell here. . .
110 print('box move e 200', file=ofile)
111
Tim Edwards05e66eb2020-09-24 13:11:59 -0400112 print('puts stdout "Writing GDS library ' + destlibroot + '"', file=ofile)
Tim Edwards51f81422020-07-26 12:49:48 -0400113 print('gds library true', file=ofile)
Tim Edwards05e66eb2020-09-24 13:11:59 -0400114 print('gds write ' + destlibroot, file=ofile)
Tim Edwards51f81422020-07-26 12:49:48 -0400115 print('puts stdout "Done."', file=ofile)
116 print('quit -noprompt', file=ofile)
117
118 # Run magic to read in the individual GDS files and
119 # write out the consolidated GDS library
120
121 print('Running magic to create GDS library.')
122 sys.stdout.flush()
123
124 mproc = subprocess.run(['magic', '-dnull', '-noconsole',
125 destlibdir + '/generate_magic.tcl'],
126 stdin = subprocess.DEVNULL,
127 stdout = subprocess.PIPE,
128 stderr = subprocess.PIPE, cwd = destlibdir,
129 universal_newlines = True)
130
131 if mproc.stdout:
132 for line in mproc.stdout.splitlines():
133 print(line)
134 if mproc.stderr:
135 print('Error message output from magic:')
136 for line in mproc.stderr.splitlines():
137 print(line)
138 if mproc.returncode != 0:
139 print('ERROR: Magic exited with status ' + str(mproc.returncode))
140 if do_compile_only == True:
141 print('Compile-only: Removing individual GDS files')
142 for gfile in glist:
143 if os.path.isfile(gfile):
144 os.remove(gfile)
Tim Edwards51f81422020-07-26 12:49:48 -0400145 if not keep:
146 os.remove(destlibdir + '/generate_magic.tcl')
147 else:
148 print('Only one file (' + str(glist) + '); ignoring "compile" option.')
149
150#----------------------------------------------------------------------------
151
152if __name__ == '__main__':
153
154 if len(sys.argv) == 1:
155 usage()
156 sys.exit(0)
157
158 argumentlist = []
159
160 # Defaults
161 do_compile_only = False
162 keep = False
163 excludelist = []
164
165 # Break arguments into groups where the first word begins with "-".
166 # All following words not beginning with "-" are appended to the
167 # same list (optionlist). Then each optionlist is processed.
168 # Note that the first entry in optionlist has the '-' removed.
169
170 for option in sys.argv[1:]:
171 if option.find('-', 0) == 0:
172 keyval = option[1:].split('=')
173 if keyval[0] == 'compile-only':
174 if len(keyval) > 0:
Tim Edwards9be4ac22020-07-26 12:59:30 -0400175 if keyval[1].tolower() == 'true' or keyval[1].tolower() == 'yes' or keyval[1] == '1':
Tim Edwards51f81422020-07-26 12:49:48 -0400176 do_compile_only = True
177 else:
178 do_compile_only = True
179 elif keyval[1] == 'exclude' or key == 'excludelist':
180 if len(keyval) > 0:
181 excludelist = keyval[1].trim('"').split(',')
182 else:
183 print("No items in exclude list (ignoring).")
184 elif keyval[1] == 'keep':
185 keep = True
186 else:
187 print("Unknown option '" + keyval[0] + "' (ignoring).")
188 else:
189 argumentlist.append(option)
190
191 if len(argumentlist) < 3:
192 print("Not enough arguments given to create_gds_library.py.")
193 usage()
194 sys.exit(1)
195
196 destlibdir = argumentlist[0]
197 destlib = argumentlist[1]
198 startup_script = argumentlist[2]
199
200 print('')
201 print('Create GDS library from files:')
202 print('')
203 print('Path to files: ' + destlibdir)
204 print('Name of compiled library: ' + destlib + '.gds')
205 print('Path to magic startup script: ' + startup_script)
206 print('Remove individual files: ' + 'Yes' if do_compile_only else 'No')
207 if len(excludelist) > 0:
208 print('List of files to exclude: ')
209 for file in excludelist:
210 print(file)
211 print('Keep generating script: ' + 'Yes' if keep else 'No')
212 print('')
213
214 create_gds_library(destlibdir, destlib, startup_script, do_compile_only, excludelist, keep)
215 print('Done.')
216 sys.exit(0)
217
218#----------------------------------------------------------------------------