# Copyright 2004-2006 The Regents of The University of Michigan
# Copyright 2010-20013 Advanced Micro Devices, Inc.
# Copyright 2013 Mark D. Hill and David A. Wood
# Copyright 2017-2020 ARM Limited
# Copyright 2021 Google, Inc.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import argparse
import importlib
import os.path
import sys

import importer

from code_formatter import code_formatter

parser = argparse.ArgumentParser()
parser.add_argument("modpath", help="module the simobject belongs to")
parser.add_argument("param_hh", help="parameter header file to generate")

args = parser.parse_args()

basename = os.path.basename(args.param_hh)
sim_object_name = os.path.splitext(basename)[0]

importer.install()
module = importlib.import_module(args.modpath)
sim_object = getattr(module, sim_object_name)

from m5.objects.SimObject import SimObject
from m5.params import Enum

code = code_formatter()

# The 'local' attribute restricts us to the params declared in
# the object itself, not including inherited params (which
# will also be inherited from the base class's param struct
# here). Sort the params based on their key
params = list(
    map(lambda k_v: k_v[1], sorted(sim_object._params.local.items()))
)
ports = sim_object._ports.local
try:
    ptypes = [p.ptype for p in params]
except:
    print(sim_object)
    print(params)
    raise

warned_about_nested_templates = False


class CxxClass(object):
    def __init__(self, sig, template_params=[]):
        # Split the signature into its constituent parts. This could
        # potentially be done with regular expressions, but
        # it's simple enough to pick appart a class signature
        # manually.
        parts = sig.split("<", 1)
        base = parts[0]
        t_args = []
        if len(parts) > 1:
            # The signature had template arguments.
            text = parts[1].rstrip(" \t\n>")
            arg = ""
            # Keep track of nesting to avoid splitting on ","s embedded
            # in the arguments themselves.
            depth = 0
            for c in text:
                if c == "<":
                    depth = depth + 1
                    if depth > 0 and not warned_about_nested_templates:
                        warned_about_nested_templates = True
                        print(
                            "Nested template argument in cxx_class."
                            " This feature is largely untested and "
                            " may not work."
                        )
                elif c == ">":
                    depth = depth - 1
                elif c == "," and depth == 0:
                    t_args.append(arg.strip())
                    arg = ""
                else:
                    arg = arg + c
            if arg:
                t_args.append(arg.strip())
        # Split the non-template part on :: boundaries.
        class_path = base.split("::")

        # The namespaces are everything except the last part of the class path.
        self.namespaces = class_path[:-1]
        # And the class name is the last part.
        self.name = class_path[-1]

        self.template_params = template_params
        self.template_arguments = []
        # Iterate through the template arguments and their values. This
        # will likely break if parameter packs are used.
        for arg, param in zip(t_args, template_params):
            type_keys = ("class", "typename")
            # If a parameter is a type, parse it recursively. Otherwise
            # assume it's a constant, and store it verbatim.
            if any(param.strip().startswith(kw) for kw in type_keys):
                self.template_arguments.append(CxxClass(arg))
            else:
                self.template_arguments.append(arg)

    def declare(self, code):
        # First declare any template argument types.
        for arg in self.template_arguments:
            if isinstance(arg, CxxClass):
                arg.declare(code)
        # Re-open the target namespace.
        for ns in self.namespaces:
            code("namespace $ns {")
        # If this is a class template...
        if self.template_params:
            code('template <${{", ".join(self.template_params)}}>')
        # The actual class declaration.
        code("class ${{self.name}};")
        # Close the target namespaces.
        for ns in reversed(self.namespaces):
            code("} // namespace $ns")


code(
    """\
#ifndef __PARAMS__${sim_object}__
#define __PARAMS__${sim_object}__

"""
)


# The base SimObject has a couple of params that get
# automatically set from Python without being declared through
# the normal Param mechanism; we slip them in here (needed
# predecls now, actual declarations below)
if sim_object == SimObject:
    code("""#include <string>""")

cxx_class = CxxClass(
    sim_object._value_dict["cxx_class"],
    sim_object._value_dict["cxx_template_params"],
)

# A forward class declaration is sufficient since we are just
# declaring a pointer.
cxx_class.declare(code)

for param in params:
    param.cxx_predecls(code)
for port in ports.values():
    port.cxx_predecls(code)
code()

if sim_object._base:
    code('#include "params/${{sim_object._base.type}}.hh"')
    code()

for ptype in ptypes:
    if issubclass(ptype, Enum):
        code('#include "enums/${{ptype.__name__}}.hh"')
        code()

code("namespace gem5")
code("{")
code("")

# now generate the actual param struct
code("struct ${sim_object}Params")
if sim_object._base:
    code("    : public ${{sim_object._base.type}}Params")
code("{")
if not hasattr(sim_object, "abstract") or not sim_object.abstract:
    if "type" in sim_object.__dict__:
        code("    ${{sim_object.cxx_type}} create() const;")

code.indent()
if sim_object == SimObject:
    code(
        """
SimObjectParams() {}
virtual ~SimObjectParams() {}

std::string name;
    """
    )

for param in params:
    param.cxx_decl(code)
for port in ports.values():
    port.cxx_decl(code)

code.dedent()
code("};")
code()
code("} // namespace gem5")

code()
code("#endif // __PARAMS__${sim_object}__")

code.write(args.param_hh)
