#!/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
r"""Stopgap script to generate some cores for the englishbreakfast toplevel.

All output files are written to $REPO_TOP/build/$TOPNAME-autogen/.
"""

import argparse
import sys
import yaml
import shutil
import subprocess
import os

try:
    from yaml import CSafeDumper as YamlDumper
except ImportError:
    from yaml import SafeDumper as YamlDumper


def write_core(core_filepath, generated_core):
    with open(core_filepath, 'w') as f:
        # FuseSoC requires this line to appear first in the YAML file.
        # Inserting this line through the YAML serializer requires ordered dicts
        # to be used everywhere, which is annoying syntax-wise on Python <3.7,
        # where native dicts are not sorted.
        f.write('CAPI=2:\n')
        yaml.dump(generated_core,
                  f,
                  encoding="utf-8",
                  Dumper=YamlDumper)
    print("Core file written to %s" % (core_filepath, ))


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--files-root', required=True)
    parser.add_argument('--topname', required=True)

    args = parser.parse_args()
    topname = args.topname
    files_root = args.files_root

    # Call topgen.
    files_data = files_root + "/hw/" + topname + "/data/"
    files_out = os.path.abspath(files_root + "/build/" + topname + "-autogen/")
    shutil.rmtree(files_out, ignore_errors=True)
    os.makedirs(files_out, exist_ok=False)
    cmd = [files_root + "/util/topgen.py",  # "--verbose",
           "-t", files_data + topname + ".hjson",
           "-o", files_out]
    try:
        print("Running topgen.")
        subprocess.run(cmd,
                       check=True,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.STDOUT,
                       universal_newlines=True)

    except subprocess.CalledProcessError as e:
        print("topgen failed: " + str(e))
        print(e.stdout)
        sys.exit(1)

    # Create core files.
    print("Creating core files.")

    # For some cores such IP package files, we need a separate dependency for the register file.
    # Combining this with the generated topgen core file below leads to cyclic dependencies. For
    # example, flash_ctrl depends on topgen but also on pwrmgr_pkg which depends on
    # pwrmgr_reg_pkg generated by topgen.
    reg_top_suffix = {
        'clkmgr': '',
        'flash_ctrl': '_core',
        'pinmux': '',
        'pwrmgr': '',
        'rstmgr': '',
    }

    # reg-only
    for ip in ['clkmgr', 'flash_ctrl', 'pinmux', 'pwrmgr', 'rstmgr']:
        core_filepath = os.path.abspath(os.path.join(files_out, 'generated-%s.core' % ip))
        name = 'lowrisc:ip:%s_reggen' % ip,
        files = ['ip/%s/rtl/autogen/%s_reg_pkg.sv' % (ip, ip),
                 'ip/%s/rtl/autogen/%s_reg_top.sv' % (ip, ip + reg_top_suffix[ip])]
        generated_core = {
            'name': '%s' % name,
            'filesets': {
                'files_rtl': {
                    'depend': [
                        'lowrisc:ip:tlul',
                    ],
                    'files': files,
                    'file_type': 'systemVerilogSource'
                },
            },
            'targets': {
                'default': {
                    'filesets': [
                        'files_rtl',
                    ],
                },
            },
        }
        write_core(core_filepath, generated_core)

    # topgen
    nameparts = topname.split('_')
    if nameparts[0] == 'top' and len(nameparts) > 1:
        chipname = 'chip_' + '_'.join(nameparts[1:])
    else:
        chipname = topname

    core_filepath = os.path.abspath(os.path.join(files_out, 'generated-topgen.core'))
    generated_core = {
        'name': "lowrisc:systems:generated-topgen",
        'filesets': {
            'files_rtl': {
                'depend': [
                    # Ibex and OTBN constants
                    'lowrisc:ibex:ibex_pkg',
                    'lowrisc:ip:otbn_pkg',
                    # flash_ctrl
                    'lowrisc:constants:top_pkg',
                    'lowrisc:prim:util',
                    'lowrisc:ip:lc_ctrl_pkg',
                    'lowrisc:ip:pwrmgr_pkg',
                    # rstmgr
                    'lowrisc:prim:clock_mux2',
                    # clkmgr
                    'lowrisc:prim:all',
                    'lowrisc:prim:clock_gating',
                    'lowrisc:prim:clock_buf',
                    'lowrisc:prim:clock_div',
                    'lowrisc:ip:clkmgr_components',
                    # Top
                    # ast and sensor_ctrl not auto-generated, re-used from top_earlgrey
                    'lowrisc:systems:sensor_ctrl',
                    'lowrisc:systems:ast_pkg',
                    # TODO: absorb this into AST longerm
                    'lowrisc:systems:clkgen_xil7series',
                ],
                'files': [
                    # IPs
                    'ip/clkmgr/rtl/autogen/clkmgr.sv',
                    'ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv',
                    'ip/flash_ctrl/rtl/autogen/flash_ctrl.sv',
                    'ip/flash_ctrl/rtl/autogen/flash_ctrl_region_cfg.sv',
                    'ip/rstmgr/rtl/autogen/rstmgr_pkg.sv',
                    'ip/rstmgr/rtl/autogen/rstmgr.sv',
                    # Top
                    'rtl/autogen/%s_rnd_cnst_pkg.sv' % topname,
                    'rtl/autogen/%s_pkg.sv' % topname,
                    'rtl/autogen/%s.sv' % topname,
                    # TODO: this is not ideal. we should extract
                    # this info from the target configuration and
                    # possibly generate separate core files for this.
                    'rtl/autogen/%s_cw305.sv' % chipname,
                ],
                'file_type': 'systemVerilogSource'
            },
        },
        'targets': {
            'default': {
                'filesets': [
                    'files_rtl',
                ],
            },
        },
    }
    write_core(core_filepath, generated_core)

    return 0


if __name__ == "__main__":
    main()
