Added a script to do the final composition from the top level design, the seal ring, and the fill generation.
diff --git a/scripts/compositor.py b/scripts/compositor.py index 3d96ca4..00b96b8 100644 --- a/scripts/compositor.py +++ b/scripts/compositor.py
@@ -1,5 +1,118 @@ #!/bin/env python3 # -# compository.py --- +# compositor.py --- # -# Final composition. Combine the caravel top level, seal ring, and fill. +# Compose the final GDS for caravel from the caravel GDS, seal ring +# GDS, and fill GDS. +# + +import sys +import os +import re +import subprocess + +def usage(): + print("compositor.py [layout_name] [-keep]") + return 0 + +if __name__ == '__main__': + + if len(sys.argv) == 1: + usage() + sys.exit(0) + + optionlist = [] + arguments = [] + + debugmode = False + keepmode = False + + 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 compositor.py.") + usage() + sys.exit(0) + + if len(arguments) == 1: + project = arguments[0] + else: + project = 'caravel' + + if '-debug' in optionlist: + debugmode = True + if '-keep' in optionlist: + keepmode = True + + magdir = '../mag' + rcfile = magdir + '/.magicrc' + + with open(magdir + '/compose_final.tcl', 'w') as ofile: + print('#!/bin/env wish', file=ofile) + print('drc off', file=ofile) + + print('load ' + project + ' -dereference', file=ofile) + print('select top cell', file=ofile) + + # Ceate a cell to represent the generated fill. There are + # no magic layers corresponding to the fill shape data, and + # it's gigabytes anyway, so we don't want to deal with any + # actual data. So it's just a placeholder. + + print('set bbox [box values]', file=ofile) + print('load ' + project + '_fill_pattern', file=ofile) + print('snap internal', file=ofile) + print('box values {*}$bbox', file=ofile) + print('paint comment', file=ofile) + print('property GDS_FILE ../gds/' + project + '_fill_pattern.gds', file=ofile) + print('property GDS_START 0', file=ofile) + print('property FIXED_BBOX "$bbox"', file=ofile) + + # Now go back to the project top level and place the fill cell. + print('load ' + project, file=ofile) + print('select top cell', file=ofile) + print('getcell ' + project + '_fill_pattern child 0 0', file=ofile) + + # Move existing origin to (6um, 6um) for seal ring placement + print('move origin -6um -6um', file=ofile) + + # Read in abstract view of seal ring + print('box position 0 0', file=ofile) + print('getcell advSeal_6um_gen', file=ofile) + + # Generate final GDS + print('puts stdout "Writing final GDS. . . "', file=ofile) + print('flush stdout', file=ofile) + print('gds write ../gds/' + project + '_final.gds', file=ofile) + print('quit -noprompt', file=ofile) + + myenv = os.environ.copy() + # Abstract views are appropriate for final composition + myenv['MAGTYPE'] = 'maglef' + + mproc = subprocess.run(['magic', '-dnull', '-noconsole', + '-rcfile', rcfile, magdir + '/compose_final.tcl'], + stdin = subprocess.DEVNULL, + stdout = subprocess.PIPE, + stderr = subprocess.PIPE, + cwd = magdir, + env = myenv, + universal_newlines = True) + if mproc.stdout: + for line in mproc.stdout.splitlines(): + print(line) + if mproc.stderr: + print('Error message output from magic:') + for line in mproc.stderr.splitlines(): + print(line) + if mproc.returncode != 0: + print('ERROR: Magic exited with status ' + str(mproc.returncode)) + + if not keepmode: + os.remove(magdir + '/compose_final.tcl') + + exit(0)