aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/parse_firrtl_transform_log.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/scripts/parse_firrtl_transform_log.py b/scripts/parse_firrtl_transform_log.py
new file mode 100755
index 00000000..16ea77cd
--- /dev/null
+++ b/scripts/parse_firrtl_transform_log.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+
+import sys
+import os
+import re
+from itertools import *
+from collections import namedtuple
+import argparse
+
+Transform = namedtuple('Transform', ['name', 'children', 'runtime'])
+
+start_xform_re = re.compile(r'\s*=+\s+Starting\s+Transform\s+(\S+)\s+=+\s*')
+finish_xform_re = re.compile(r'\s*=+\s+Finished\s+Transform\s+(\S+)\s+=+\s*')
+time_re = re.compile(r'\s*Time:\s*(\d+(\.\d+)?)\s*ms\s*')
+
+
+def get_start(line):
+ if line is not None:
+ m = start_xform_re.match(line)
+ if m:
+ return m.group(1)
+ return None
+
+
+def get_finish(line):
+ m = finish_xform_re.match(line)
+ if m:
+ return m.group(1)
+ return None
+
+
+def get_time(line):
+ m = time_re.match(line)
+ if m:
+ return m.group(1)
+ return None
+
+
+def safe_next(it):
+ try:
+ return next(it)
+ except StopIteration:
+ return None
+
+
+def non_empty(it):
+ return any(True for _ in it)
+
+
+def read_transform(name, lines):
+ # The log may be malformed so we just catch that whenever
+ try:
+ children = []
+ time = None
+ while True:
+ line = next(lines)
+ start_opt = get_start(line)
+ if start_opt is not None:
+ child = read_transform(start_opt, lines)
+ children.append(child)
+ else:
+ time_opt = get_time(line)
+ if time_opt is not None:
+ time = time_opt
+ else:
+ end_opt = get_finish(line)
+ if end_opt is not None:
+ assert end_opt == name
+ return Transform(name, children, time)
+ except StopIteration:
+ return None
+
+
+def read_top_transform(it):
+ # Find start
+ lines = dropwhile(lambda line: not start_xform_re.match(line), it)
+ name = get_start(safe_next(lines))
+ if name is not None:
+ return read_transform(name, lines)
+ else:
+ return None
+
+
+def pretty_transform(xform):
+ time_str = " ({} ms)".format(xform.runtime) if xform.runtime is not None else ""
+ lines = [xform.name + time_str]
+ nchildren = len(xform.children)
+ for i in range(0, nchildren):
+ child = xform.children[i]
+ child_lines = pretty_transform(child)
+ if i == nchildren - 1:
+ branch = "└── "
+ indent = " "
+ else:
+ branch = "├── "
+ indent = "│ "
+ first = True
+ for line in child_lines:
+ prefix = branch if first else indent
+ lines.append(prefix + line)
+ first = False
+ return lines
+
+
+def remove_time(xform):
+ children = [remove_time(child) for child in xform.children]
+ return Transform(xform.name, children, None)
+
+
+def is_existing_file(name):
+ if not os.path.isfile(name):
+ msg = "File {} does not exist!".format(name)
+ raise argparse.ArgumentTypeError(msg)
+ else:
+ return name
+
+
+def get_parser():
+ parser = argparse.ArgumentParser(description='Parse FIRRTL transform log')
+ parser.add_argument('file', help='log file',
+ type=is_existing_file)
+ parser.add_argument('-s', '--strip-time', action='store_true', default=False,
+ help='Strip time values')
+ return parser
+
+
+if __name__ == "__main__":
+ parser = get_parser()
+ args = parser.parse_args()
+
+ transforms = []
+ with open(args.file, "r") as f:
+ while True:
+ xform = read_top_transform(f)
+ if xform is None:
+ break
+ else:
+ transforms.append(xform)
+ if len(transforms) == 0:
+ print("{} does not contain a FIRRTL Transform log!".format(args.file))
+ sys.exit(-1)
+ top = Transform("firrtl.stage.transforms.Compiler", transforms, None)
+ if args.strip_time:
+ top = remove_time(top)
+ pretty = pretty_transform(top)
+ for line in pretty:
+ print(line)
+