Applies the `pyupgrade` hook to all files in the repo. Change-Id: I9879c634a65c5fcaa9567c63bc5977ff97d5d3bf
236 lines
7.9 KiB
Python
236 lines
7.9 KiB
Python
# 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:
|
|
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)
|