| #!/usr/bin/env python3 |
| # |
| # cleanup_unref.py: Look up all .mag files in the indicated path, and |
| # parse all files for "use" lines and make a list of all the cells being |
| # used. Next, check all files to determine which ones are parameterized |
| # PDK cells (those that have "string gencell" in the properties section). |
| # Finally, remove all the files which represent parametersized PDK cells |
| # that are not used anywhere by any other layout file. |
| # |
| # The purpose of this script is to reduce the number of cells scattered |
| # about the filesystem that come from parameterized cells being modified |
| # in place. Eventually, magic will be upgraded to have a way to indicate |
| # just the cell name and parameters in the .mag file so that all parameterized |
| # cells can be generated on-the-fly and do not need to be saved in .mag files. |
| # |
| # Note that this routine assumes that all files are local to a single project |
| # directory and are not being used by layout in some other directory. So use |
| # with caution. |
| # |
| # Usage, e.g.: |
| # |
| # cleanup_unref.py <path_to_layout> |
| |
| import os |
| import re |
| import sys |
| import glob |
| |
| def usage(): |
| print("cleanup_unref.py [-remove] <path_to_layout>") |
| return 0 |
| |
| if __name__ == '__main__': |
| |
| if len(sys.argv) == 1: |
| usage() |
| sys.exit(0) |
| |
| optionlist = [] |
| arguments = [] |
| |
| testmode = True |
| debugmode = 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 cleanup_unref.py.") |
| usage() |
| sys.exit(0) |
| |
| if '-remove' in optionlist or '-delete' in optionlist: |
| testmode = False |
| if '-debug' in optionlist: |
| debugmode = True |
| |
| filepath = arguments[0] |
| |
| magpath = filepath + '/*.mag' |
| sourcefiles = glob.glob(magpath) |
| |
| if len(sourcefiles) == 0: |
| print("Warning: No files were found in the path " + filepath + ".") |
| |
| usedfiles = [] |
| pdkfiles = [] |
| |
| for file in sourcefiles: |
| if debugmode: |
| print("Checking file " + file) |
| fileroot = os.path.split(file)[1] |
| cellname = os.path.splitext(fileroot)[0] |
| |
| proprex = re.compile('^string[ \t]+gencell[ \t]+([^ \t]+)') |
| userex = re.compile('^use[ \t]+([^ \t]+)') |
| |
| with open(file, 'r') as ifile: |
| magtext = ifile.read().splitlines() |
| for line in magtext: |
| pmatch = proprex.match(line) |
| if pmatch: |
| pdkfiles.append(cellname) |
| umatch = userex.match(line) |
| if umatch: |
| cellname = umatch.group(1) |
| if cellname not in usedfiles: |
| usedfiles.append(cellname) |
| |
| unusedfiles = list(item for item in pdkfiles if item not in usedfiles) |
| |
| if debugmode: |
| print('') |
| print('Parameterized cells found:') |
| for cellname in sorted(pdkfiles): |
| print(cellname) |
| |
| print('') |
| print('Used cells found:') |
| for cellname in sorted(usedfiles): |
| print(cellname) |
| |
| if testmode: |
| # Just report on files that are unused |
| print('') |
| print('Parameterized cells not used by any layout:') |
| for cellname in sorted(unusedfiles): |
| print(cellname) |
| else: |
| # Remove files that are unused |
| for cellname in sorted(unusedfiles): |
| file = filepath + '/' + cellname + '.mag' |
| os.remove(file) |
| print('Removed unused parameterized cell ' + cellname) |
| |
| print('') |
| print('Done!') |