| #!/usr/bin/env python3 |
| import os, sys, threading |
| from os import path |
| import subprocess |
| import re |
| |
| num_runs = 8 |
| |
| if not path.exists("picorv32.json"): |
| subprocess.run(["wget", "https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v"], check=True) |
| subprocess.run(["yosys", "-q", "-p", "synth_ice40 -json picorv32.json -top top", "picorv32.v", "picorv32_top.v"], check=True) |
| |
| fmax = {} |
| |
| if not path.exists("picorv32_work"): |
| os.mkdir("picorv32_work") |
| |
| threads = [] |
| |
| for i in range(num_runs): |
| def runner(run): |
| ascfile = "picorv32_work/picorv32_s{}.asc".format(run) |
| if path.exists(ascfile): |
| os.remove(ascfile) |
| result = subprocess.run(["../nextpnr-ice40", "--hx8k", "--seed", str(run), "--json", "picorv32.json", "--asc", ascfile, "--freq", "40", "--opt-timing"], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL) |
| if result.returncode != 0: |
| print("Run {} failed!".format(run)) |
| else: |
| icetime_res = subprocess.check_output(["icetime", "-d", "hx8k", ascfile]) |
| fmax_m = re.search(r'\(([0-9.]+) MHz\)', icetime_res.decode('utf-8')) |
| fmax[run] = float(fmax_m.group(1)) |
| threads.append(threading.Thread(target=runner, args=[i+1])) |
| |
| for t in threads: t.start() |
| for t in threads: t.join() |
| |
| fmax_min = min(fmax.values()) |
| fmax_max = max(fmax.values()) |
| fmax_avg = sum(fmax.values()) / len(fmax) |
| |
| print("{}/{} runs passed".format(len(fmax), num_runs)) |
| print("icetime: min = {} MHz, avg = {} MHz, max = {} MHz".format(fmax_min, fmax_avg, fmax_max)) |