# 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, p, p.ptype_str)
    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)
