|  | """ Gathers statistics from VPR runs, like pack/place/route runtimes and Fmax. | 
|  | """ | 
|  | import argparse | 
|  | import csv | 
|  | import os | 
|  | import sys | 
|  | import subprocess | 
|  |  | 
|  |  | 
|  | def scan_runtime(step, fname): | 
|  | """ Find runtime of VPR log (if any), else returns empty str. """ | 
|  | try: | 
|  | with open(fname, 'r') as f: | 
|  | step_runtime = 0 | 
|  | total_runtime = 0 | 
|  | for line in f: | 
|  | if line.startswith("# {} took".format(step)): | 
|  | step_runtime = float(line.split()[3]) | 
|  |  | 
|  | if line.startswith('The entire flow of VPR took'): | 
|  | total_runtime = float(line.split()[6]) | 
|  |  | 
|  | step_overhead = total_runtime - step_runtime | 
|  |  | 
|  | return str(step_runtime), str(step_overhead) | 
|  | except FileNotFoundError: | 
|  | return "" | 
|  |  | 
|  |  | 
|  | def scan_critical(fname): | 
|  | """ Find critical path and Fmax from VPR log (if any). | 
|  |  | 
|  | Returns | 
|  | ------- | 
|  | critical_path : str | 
|  | Critical path delay in nsec | 
|  | fmax : str | 
|  | Fmax in MHz. | 
|  |  | 
|  | """ | 
|  | try: | 
|  | with open(fname, 'r') as f: | 
|  | final_cpd = 0.0 | 
|  | final_fmax = 0.0 | 
|  |  | 
|  | final_cpd_geomean = 0.0 | 
|  | final_fmax_geomean = 0.0 | 
|  |  | 
|  | for line in f: | 
|  | if line.startswith('Final critical path delay'): | 
|  | parts = line.split() | 
|  | if len(parts) >= 9: | 
|  | # Final critical path delay (least slack): 16.8182 ns, Fmax: 59.4592 MHz | 
|  | final_cpd = float(parts[6]) | 
|  | final_fmax = float(parts[9]) | 
|  | elif len(parts) == 8 and parts[7].strip() == 'ns': | 
|  | # Final critical path delay (least slack): 17.9735 ns | 
|  | final_cpd = float(parts[6]) | 
|  | final_fmax = 1000. / final_cpd | 
|  |  | 
|  | if line.startswith( | 
|  | 'Final geomean non-virtual intra-domain period'): | 
|  | parts = line.split() | 
|  |  | 
|  | final_cpd_geomean = parts[5] | 
|  |  | 
|  | if final_cpd_geomean == "nan": | 
|  | final_cpd_geomean = "N/A" | 
|  | final_fmax_geomean = "N/A" | 
|  | continue | 
|  |  | 
|  | final_cpd_geomean = float(parts[5]) | 
|  | final_fmax_geomean = 1000. / final_cpd_geomean | 
|  |  | 
|  | return str(final_cpd), str(final_fmax), str( | 
|  | final_cpd_geomean | 
|  | ), str(final_fmax_geomean) | 
|  | except FileNotFoundError: | 
|  | pass | 
|  |  | 
|  | return "", "" | 
|  |  | 
|  |  | 
|  | def get_last_n_dirs(path, n): | 
|  | dirs = path.split("/") | 
|  | return "/".join(dirs[-n:]) | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | parser = argparse.ArgumentParser(description=__doc__) | 
|  | parser.add_argument("build_dir") | 
|  |  | 
|  | args = parser.parse_args() | 
|  |  | 
|  | fields = [ | 
|  | "path", | 
|  | "pack time (sec)", | 
|  | "pack overhead (sec)", | 
|  | "place time (sec)", | 
|  | "place overhead (sec)", | 
|  | "route time (sec)", | 
|  | "route overhead (sec)", | 
|  | "t_crit (ns)", | 
|  | "Fmax (MHz)", | 
|  | "t_crit geomean (ns)", | 
|  | "Fmax geomean (MHz)", | 
|  | ] | 
|  |  | 
|  | print( | 
|  | ''.join( | 
|  | subprocess. | 
|  | getoutput('git show --oneline -s --decorate --color=never') | 
|  | ), | 
|  | file=sys.stdout | 
|  | ) | 
|  | w = csv.DictWriter(sys.stdout, fields) | 
|  | w.writeheader() | 
|  | rows = list() | 
|  | for root, dirs, files in os.walk(args.build_dir): | 
|  | if 'pack.log' in files: | 
|  | d = {} | 
|  |  | 
|  | # Get step runtimes with the respective overhead | 
|  | pack_time, pack_overhead = scan_runtime( | 
|  | "Packing", os.path.join(root, 'pack.log') | 
|  | ) | 
|  |  | 
|  | place_time, place_overhead = scan_runtime( | 
|  | "Placement", os.path.join(root, 'place.log') | 
|  | ) | 
|  |  | 
|  | route_time, route_overhead = scan_runtime( | 
|  | "Routing", os.path.join(root, 'route.log') | 
|  | ) | 
|  |  | 
|  | final_cpd, final_fmax, final_cpd_geomean, final_fmax_geomean = scan_critical( | 
|  | os.path.join(root, 'route.log') | 
|  | ) | 
|  |  | 
|  | d['path'] = get_last_n_dirs(root, 2) | 
|  | d['pack time (sec)'] = pack_time | 
|  | d['pack overhead (sec)'] = pack_overhead | 
|  | d['place time (sec)'] = place_time | 
|  | d['place overhead (sec)'] = place_overhead | 
|  | d['route time (sec)'] = route_time | 
|  | d['route overhead (sec)'] = route_overhead | 
|  | d['t_crit (ns)'] = final_cpd | 
|  | d['Fmax (MHz)'] = final_fmax | 
|  | d['t_crit geomean (ns)'] = final_cpd_geomean | 
|  | d['Fmax geomean (MHz)'] = final_fmax_geomean | 
|  |  | 
|  | rows.append(d) | 
|  |  | 
|  | rows = sorted(rows, key=lambda row: row['path']) | 
|  |  | 
|  | for row in rows: | 
|  | w.writerow(row) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main() |