python: Improve how templated SimObject classes are handled.

When setting up a SimObject's Param structure, gem5 will autogenerate
a header file which attempts to declare the SimObject's C++ type. It
has had at least some level of sophistication there where it would
pull off the namespaces ahead of the class name and handle them
properly, but it didn't know how to handle templates.

This change improves that handling in two ways. First, it adds a new
magical SimObject attribute called 'cxx_template_params' which is used
to specify what the template parameters are as a list. For instance, if
your SimObject was a template which took an integer constant as its
first parameter and a type as its second, this attribute could look
like the following:

cxx_template_params = [ 'int FOO', 'class Bar' ]

Importantly, if there are any default values for these template
parameters, they should *not* be included here, they should be
specified where the class is later defined.

The second new mechanism is to add an internal CxxClass in the
SimObject.cxx_param_decl method. This class accepts the class signature
in the cxx_class attribute and the cxx_template_params and does two
things. First, it strips off namespaces like in the old implementation.
Second, it extracts and processes any template arguments attached to
the class. If these are constants (as determined by the contents of
cxx_template_params), then they are stored verbatim. If they're types,
then they're recursively expanded into a CxxClass and stored that way.
Note that these are the *values* of the template arguments, where as
cxx_template_params lists the *types* and *names* of those arguments.
In our earlier example, if cxx_class was:

cxx_class = 'CoolClasses::ClassName<12, Fruit::Apple>'

Then CxxClass would extract the namespace 'CoolClasses', the class
name 'ClassName', the argument '12', and the argument 'Fruit::Apple'.
That second argument would be expanded into a CxxClass with the
namespace 'Fruit' and the class name 'Apple'.

Importantly here, because there were no default arguments given in
cxx_template_params, all "hidden" arguments which would fall through
to their defaults need to be fully specified in cxx_class.

The CxxClass has a method called declare() which uses the information
extracted earlier to output all of the "stuff" necessary for declaring
the given class, including opening any containing namespaces and
putting template<...> ahead of the actual class declaration with the
template parameters specified.

If any of the template arguments are themselves CxxClass instances,
then they'll be recursively declared immediately before the current
class is.

An alternative solution to this problem might be to include the header
file which actually defines the cxx_class type to avoid having to
come up with a declaration. Unfortunately this doesn't work since it
can set up include loops where the SimObject C++ header file includes
the param header to get access to the Param type, but that includes
the C++ header to get access to the SimObject type.

This also makes it harder for SimObjects to refer to each other, since
they rely on the declaration in the params header files when declaring
a member pointer to that type in their own Param structures.

Change-Id: I68cfc36ddff6d789eb4cdef5178c4619ac2cc8b1
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/17228
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Gabe Black <gabeblack@google.com>
1 file changed