blob: 85380fe94bba2926815e9520673226511e566f73 [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
41 alllibname = destlibdir + '/' + destlib + '.gds'
42 if os.path.isfile(alllibname):
43 os.remove(alllibname)
44
45 glist = glob.glob(destlibdir + '/*.gds')
46 glist.extend(glob.glob(destlibdir + '/*.gdsii'))
47 glist.extend(glob.glob(destlibdir + '/*.gds2'))
48 if alllibname in glist:
49 glist.remove(alllibname)
50
51 # Create exclude list with glob-style matching using fnmatch
52 if len(glist) > 0:
53 glistnames = list(os.path.split(item)[1] for item in glist)
54 notglist = []
55 for exclude in excludelist:
56 notglist.extend(fnmatch.filter(glistnames, exclude))
57
58 # Apply exclude list
59 if len(notglist) > 0:
60 for file in glist[:]:
61 if os.path.split(file)[1] in notglist:
62 glist.remove(file)
63
64 if len(glist) > 1:
65 print('New file is: ' + alllibname)
66
67 if os.path.isfile(startup_script):
68 # If the symbolic link exists, remove it.
69 if os.path.isfile(destlibdir + '/.magicrc'):
70 os.remove(destlibdir + '/.magicrc')
71 os.symlink(startup_script, destlibdir + '/.magicrc')
72
73 # A GDS library is binary and requires handling in Magic
74 print('Creating magic generation script to generate GDS library.')
75 with open(destlibdir + '/generate_magic.tcl', 'w') as ofile:
76 print('#!/usr/bin/env wish', file=ofile)
77 print('#--------------------------------------------', file=ofile)
78 print('# Script to generate .gds library from files ', file=ofile)
79 print('#--------------------------------------------', file=ofile)
80 print('drc off', file=ofile)
81 print('gds readonly true', file=ofile)
82 print('gds flatten true', file=ofile)
83 print('gds rescale false', file=ofile)
84 print('tech unlock *', file=ofile)
85
86 for gdsfile in glist:
87 print('gds read ' + gdsfile, file=ofile)
88
89 print('puts stdout "Creating cell ' + destlib + '"', file=ofile)
90 print('load ' + destlib, file=ofile)
91 print('puts stdout "Adding cells to library"', file=ofile)
92 print('box values 0 0 0 0', file=ofile)
93 for gdsfile in glist:
94 gdsroot = os.path.split(gdsfile)[1]
95 gdsname = os.path.splitext(gdsroot)[0]
96 print('getcell ' + gdsname, file=ofile)
97 # Could properly make space for the cell here. . .
98 print('box move e 200', file=ofile)
99
100 print('puts stdout "Writing GDS library ' + destlib + '"', file=ofile)
101 print('gds library true', file=ofile)
102 print('gds write ' + destlib, file=ofile)
103 print('puts stdout "Done."', file=ofile)
104 print('quit -noprompt', file=ofile)
105
106 # Run magic to read in the individual GDS files and
107 # write out the consolidated GDS library
108
109 print('Running magic to create GDS library.')
110 sys.stdout.flush()
111
112 mproc = subprocess.run(['magic', '-dnull', '-noconsole',
113 destlibdir + '/generate_magic.tcl'],
114 stdin = subprocess.DEVNULL,
115 stdout = subprocess.PIPE,
116 stderr = subprocess.PIPE, cwd = destlibdir,
117 universal_newlines = True)
118
119 if mproc.stdout:
120 for line in mproc.stdout.splitlines():
121 print(line)
122 if mproc.stderr:
123 print('Error message output from magic:')
124 for line in mproc.stderr.splitlines():
125 print(line)
126 if mproc.returncode != 0:
127 print('ERROR: Magic exited with status ' + str(mproc.returncode))
128 if do_compile_only == True:
129 print('Compile-only: Removing individual GDS files')
130 for gfile in glist:
131 if os.path.isfile(gfile):
132 os.remove(gfile)
Tim Edwards51f81422020-07-26 12:49:48 -0400133 if not keep:
134 os.remove(destlibdir + '/generate_magic.tcl')
135 else:
136 print('Only one file (' + str(glist) + '); ignoring "compile" option.')
137
138#----------------------------------------------------------------------------
139
140if __name__ == '__main__':
141
142 if len(sys.argv) == 1:
143 usage()
144 sys.exit(0)
145
146 argumentlist = []
147
148 # Defaults
149 do_compile_only = False
150 keep = False
151 excludelist = []
152
153 # Break arguments into groups where the first word begins with "-".
154 # All following words not beginning with "-" are appended to the
155 # same list (optionlist). Then each optionlist is processed.
156 # Note that the first entry in optionlist has the '-' removed.
157
158 for option in sys.argv[1:]:
159 if option.find('-', 0) == 0:
160 keyval = option[1:].split('=')
161 if keyval[0] == 'compile-only':
162 if len(keyval) > 0:
Tim Edwards9be4ac22020-07-26 12:59:30 -0400163 if keyval[1].tolower() == 'true' or keyval[1].tolower() == 'yes' or keyval[1] == '1':
Tim Edwards51f81422020-07-26 12:49:48 -0400164 do_compile_only = True
165 else:
166 do_compile_only = True
167 elif keyval[1] == 'exclude' or key == 'excludelist':
168 if len(keyval) > 0:
169 excludelist = keyval[1].trim('"').split(',')
170 else:
171 print("No items in exclude list (ignoring).")
172 elif keyval[1] == 'keep':
173 keep = True
174 else:
175 print("Unknown option '" + keyval[0] + "' (ignoring).")
176 else:
177 argumentlist.append(option)
178
179 if len(argumentlist) < 3:
180 print("Not enough arguments given to create_gds_library.py.")
181 usage()
182 sys.exit(1)
183
184 destlibdir = argumentlist[0]
185 destlib = argumentlist[1]
186 startup_script = argumentlist[2]
187
188 print('')
189 print('Create GDS library from files:')
190 print('')
191 print('Path to files: ' + destlibdir)
192 print('Name of compiled library: ' + destlib + '.gds')
193 print('Path to magic startup script: ' + startup_script)
194 print('Remove individual files: ' + 'Yes' if do_compile_only else 'No')
195 if len(excludelist) > 0:
196 print('List of files to exclude: ')
197 for file in excludelist:
198 print(file)
199 print('Keep generating script: ' + 'Yes' if keep else 'No')
200 print('')
201
202 create_gds_library(destlibdir, destlib, startup_script, do_compile_only, excludelist, keep)
203 print('Done.')
204 sys.exit(0)
205
206#----------------------------------------------------------------------------