Tim Edwards | 55f4d0e | 2020-07-05 15:41:02 -0400 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # |
| 3 | # Remove timing information from a verilog file, which is everything between |
| 4 | # the keywords "specify" and "endspecify". |
| 5 | # |
| 6 | # Filter a verilog file to remove any backslash continuation lines, which |
| 7 | # iverilog does not parse. If targetroot is a directory, then find and |
| 8 | # process all files in the path of targetroot. If any file to be processed |
| 9 | # is unmodified (has no backslash continuation lines), then ignore it. If |
| 10 | # any file is a symbolic link and gets modified, then remove the symbolic |
| 11 | # link before overwriting with the modified file. |
| 12 | # |
| 13 | |
| 14 | import stat |
| 15 | import sys |
| 16 | import os |
| 17 | import re |
| 18 | |
| 19 | def makeuserwritable(filepath): |
| 20 | if os.path.exists(filepath): |
| 21 | st = os.stat(filepath) |
| 22 | os.chmod(filepath, st.st_mode | stat.S_IWUSR) |
| 23 | |
| 24 | def remove_specify(vfile, outfile): |
| 25 | modified = False |
| 26 | with open(vfile, 'r') as ifile: |
| 27 | vtext = ifile.read() |
| 28 | |
| 29 | if outfile == None: |
| 30 | outfile = vfile |
| 31 | |
| 32 | # Remove backslash-followed-by-newline and absorb initial whitespace. It |
| 33 | # is unclear what initial whitespace means in this context, as the use- |
| 34 | # case that has been seen seems to work under the assumption that leading |
| 35 | # whitespace is ignored up to the amount used by the last indentation. |
| 36 | |
| 37 | vlines = re.sub('\\\\\n[ \t]*', '', vtext) |
| 38 | |
| 39 | specrex = re.compile('\n[ \t]*specify[ \t\n]+') |
| 40 | endspecrex = re.compile('\n[ \t]*endspecify') |
| 41 | smatch = specrex.search(vlines) |
| 42 | while smatch: |
| 43 | specstart = smatch.start() |
| 44 | specpos = smatch.end() |
| 45 | ematch = endspecrex.search(vlines[specpos:]) |
| 46 | specend = ematch.end() |
| 47 | vtemp = vlines[0:specstart + 1] + vlines[specpos + specend + 1:] |
| 48 | vlines = vtemp |
| 49 | smatch = specrex.search(vlines) |
| 50 | |
| 51 | if vlines != vtext: |
| 52 | # File contents have been modified, so if this file was a symbolic |
| 53 | # link, then remove it. Otherwise, overwrite the file with the |
| 54 | # modified contents. |
| 55 | if outfile == vfile: |
| 56 | if os.path.islink(vfile): |
| 57 | os.unlink(vfile) |
| 58 | if os.path.exists(outfile): |
| 59 | makeuserwritable(outfile) |
| 60 | with open(outfile, 'w') as ofile: |
| 61 | ofile.write(vlines) |
| 62 | |
| 63 | elif outfile != vfile: |
| 64 | if os.path.exists(outfile): |
| 65 | makeuserwritable(outfile) |
| 66 | with open(outfile, 'w') as ofile: |
| 67 | ofile.write(vlines) |
| 68 | |
| 69 | # If called as main, run remove_specify |
| 70 | |
| 71 | if __name__ == '__main__': |
| 72 | |
| 73 | # Divide up command line into options and arguments |
| 74 | options = [] |
| 75 | arguments = [] |
| 76 | for item in sys.argv[1:]: |
| 77 | if item.find('-', 0) == 0: |
| 78 | options.append(item) |
| 79 | else: |
| 80 | arguments.append(item) |
| 81 | |
| 82 | # Need one argument: path to verilog netlist |
| 83 | # If two arguments, then 2nd argument is the output file. |
| 84 | |
| 85 | if len(arguments) == 2: |
| 86 | netlist_path = arguments[0] |
| 87 | output_path = arguments[1] |
| 88 | remove_specify(netlist_path, output_path) |
| 89 | elif len(arguments) != 1: |
| 90 | print("Usage: remove_spcify.py <file_path> [<output_path>]") |
| 91 | elif len(arguments) == 1: |
| 92 | netlist_path = arguments[0] |
| 93 | remove_specify(netlist_path, None) |
| 94 | |