#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# Note: this script relies on numpy and matplotlib, which both currently are
# not standard python requirements of OpenTitan. If you wish to use this script,
# make sure you install them with "pip3 install --user numpy matplotlib"

import argparse
import re
import sys
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np

USAGE = """
This script parses reports generated with the sweep.tcl DC synthesis
script and creates an AT-plot with that data.

usage: ./at-plot.py ./REPORTS/<dut1_basename> ./REPORTS/<dut2_basename> ...

In order to get convert area into gate equivalents (GE) the size of a GE
can be supplied using the -g switch.

The script currently supports plotting up to 10 different result series in
one plot.
"""


def main():
    parser = argparse.ArgumentParser(prog="")
    parser.add_argument('result_series',
                        type=str,
                        nargs='+',
                        help="Path and basename of result series.")

    parser.add_argument(
        '-g',
        '--gate_equivalent',
        type=float,
        default=1.0,
        help="Gate equivalent in square micrometre. Defaults to 1.0.")
    parser.add_argument('-o',
                        '--output',
                        type=str,
                        default="at-plot.png",
                        help='Filename of at plot. Defaults to "at-plot.png"')
    parser.add_argument('-t',
                        '--title',
                        type=str,
                        default="AT Plot",
                        help='Title of AT plot.')
    parser.add_argument('--semilogy',
                        action='store_true',
                        help='semilogy plot.')

    l = 0
    labels = []

    # line style and color setup
    linestyles = ['--', '--', '--', '--', '--', '--', '--', '--', '--', '--']
    markers = ['^', 'd', '.', '*', '>', '<', 'v', 's', 'h', 'o']
    cmap = plt.get_cmap("Set1")

    args = parser.parse_args()

    if len(args.result_series) > 10:
        print("Only up to ten result series can be plottet at once")
        sys.exit(1)

    print("Gate Equivalent is %.2f square micrometre" % args.gate_equivalent)

    for basename in args.result_series:
        report_filebase = Path(basename)

        print("%s" % (report_filebase.name))

        results = np.array([[]])

        for rpt_area in report_filebase.parent.rglob(report_filebase.name +
                                                     '_*_area.rpt'):
            tmp_period = Path(rpt_area).name.split('_area')
            tmp_period = tmp_period[0].split(report_filebase.name + '_')
            row = np.array([[float(tmp_period[1]), 0.0, 0.0]])
            if np.any(results):
                results = np.append(results, row, axis=0)
            else:
                results = row
            try:
                with open(rpt_area, 'r') as f:
                    full_file = f.read()
                    tmp_area = re.findall(r"^Total cell area:.*",
                                          full_file,
                                          flags=re.MULTILINE)
                    if tmp_area:
                        tmp_area = tmp_area[0].split("Total cell area:")
                        results[-1, 1] = float(
                            tmp_area[1]) / args.gate_equivalent
                    else:
                        print("Error, could not find total cell area in %s" %
                              (report_area))
                        sys.exit(1)

            except IOError as e:
                print(str(e))
                sys.exit(1)

            try:
                rpt_timing = rpt_area.parent.joinpath(
                    rpt_area.name.replace('_area', '_timing'))
                with open(rpt_timing, 'r') as f:
                    full_file = f.read()
                    tmp_slack = re.findall(r"^  slack \(.*",
                                           full_file,
                                           flags=re.MULTILINE)
                    if tmp_slack:
                        tmp_slack = tmp_slack[0].split(")")
                        # adjust period with slack
                        results[-1, 2] = results[-1][0] - float(tmp_slack[1])
                    else:
                        print("Error, could not find slack in %s" %
                              (rpt_timing))
                        sys.exit(1)

            except IOError as e:
                print(str(e))
                sys.exit(1)

        if np.any(results):

            results = results[np.argsort(results[:, 0])]

            if args.gate_equivalent == 1.0:
                print("constraint [ns], achieved [ns], complexity [GE]")
            else:
                print("constraint [ns], achieved [ns], complexity [um^2]")

            for k in range(len(results)):
                print("%.2f, %.2f, %.2f" %
                      (results[k][0], results[k][2], results[k][1]))
            if args.semilogy:
                plt.semilogy(results[:, 2],
                             results[:, 1],
                             color=cmap(l),
                             linestyle=linestyles[l],
                             marker=markers[l],
                             linewidth=1.5,
                             markersize=6,
                             markeredgecolor='k')
            else:
                plt.plot(results[:, 2],
                         results[:, 1],
                         color=cmap(l),
                         linestyle=linestyles[l],
                         marker=markers[l],
                         linewidth=1.5,
                         markersize=6,
                         markeredgecolor='k')

            l += 1
            labels += [report_filebase.name]

    print("Parsed %d result series" % l)

    plt.xlabel('Period [ns]')
    if args.gate_equivalent == 1.0:
        plt.ylabel('Complexity [um^2]')
    else:
        plt.ylabel('Complexity [GE]')
    plt.grid(which='both')
    plt.legend(labels)
    plt.title(args.title)
    plt.savefig(args.output)
    plt.show()


if __name__ == '__main__':
    main()
