Added a new script in common/ "cleanup_unref.py" which removes all parameterized cell layouts from a directory that are unreferenced by any other layout file. These "orphan" cells are commonly left behind when changing parameter values of parameterized cells.
diff --git a/VERSION b/VERSION index 1edd062..eea6f62 100644 --- a/VERSION +++ b/VERSION
@@ -1 +1 @@ -1.0.71 +1.0.72
diff --git a/common/cleanup_unref.py b/common/cleanup_unref.py new file mode 100755 index 0000000..23f1805 --- /dev/null +++ b/common/cleanup_unref.py
@@ -0,0 +1,120 @@ +#!/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!')