Skip to content

Instantly share code, notes, and snippets.

@InternetUnexplorer
Created December 22, 2022 06:01
Show Gist options
  • Save InternetUnexplorer/97dfe205898b68a2deb52a9c18a8e32a to your computer and use it in GitHub Desktop.
Save InternetUnexplorer/97dfe205898b68a2deb52a9c18a8e32a to your computer and use it in GitHub Desktop.
Python script for pretty-printing timing/utilization reports produced by nextpnr
#! /usr/bin/env python3
#
# This script pretty-prints timing/utilization reports produced by nextpnr.
# You can use it in your build process like this:
#
# nextpnr-ecp5 ... --report report.json
# ./print-report.py < report.json
#
# License: CC0 <https://creativecommons.org/publicdomain/zero/1.0>
import json, sys
from typing import Any, Dict
RED, GREEN, CYAN = "\x1b[31m", "\x1b[32m", "\x1b[36m"
BOLD, RESET = "\x1b[1m", "\x1b[0m"
def print_header(title: str) -> None:
print(BOLD + GREEN + f"==== {title} ".ljust(60, "=") + RESET)
def print_frequency_report(frequencies: Dict[str, Any]) -> None:
if not frequencies:
return
frequencies = {
name: (value["achieved"], value["constraint"])
for name, value in frequencies.items()
}
name_width = max(len(name) for name in frequencies.keys())
print_header("Frequency Report")
for name, (achieved, constraint) in frequencies.items():
name_text = CYAN + (name + ":").ljust(name_width + 1) + RESET
pass_fail_text = (
f"{GREEN}PASS{RESET}" if achieved >= constraint else f"{RED}FAIL{RESET}"
)
print(
f" {name_text} {achieved:5.1f} MHz"
f" ({pass_fail_text} at {constraint:5.1f} MHz)"
)
print()
def print_device_utilization(utilization: Dict[str, Any]) -> None:
utilization = {
name: (value["used"], value["available"])
for name, value in utilization.items()
if value["used"] > 0
}
percentages = {
name: f"{value[0] / value[1] * 100:5.1f}" for name, value in utilization.items()
}
name_width = max(len(name) for name in utilization.keys())
percent_width = max(len(percent) for percent in percentages.values())
print_header("Device Utilization")
for name, (used, available) in utilization.items():
name_text = CYAN + (name + ":").ljust(name_width + 1) + RESET
percent_text = f"{percentages[name].rjust(percent_width)}%"
print(
f" {name_text} {str(used).rjust(5)} / {str(available).rjust(5)}",
f"({GREEN if used <= available else RED}{percent_text}{RESET})",
)
print()
def print_report(report: Dict[str, Any]) -> None:
print_frequency_report(report.get("fmax"))
print_device_utilization(report.get("utilization"))
if __name__ == "__main__":
print()
print_report(json.load(sys.stdin))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment