blob: 746a06f86385faced7d8fe9dfa9bbce84bbc07a5 [file] [log] [blame]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001#!/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
14import stat
15import sys
16import os
17import re
18
19def makeuserwritable(filepath):
20 if os.path.exists(filepath):
21 st = os.stat(filepath)
22 os.chmod(filepath, st.st_mode | stat.S_IWUSR)
23
24def 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
71if __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