python,util: Pull enum hh|cc generation out of the MetaEnum class.

Change-Id: Ibfcc2d6916318ffef806f74e57e3f8360489efb6
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49452
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-08-19 23:11:40 -07:00
parent 4003ad7510
commit b0f9375377
3 changed files with 170 additions and 144 deletions

View File

@@ -1318,146 +1318,6 @@ class MetaEnum(MetaParamValue):
super().__init__(name, bases, init_dict)
# Generate C++ class declaration for this enum type.
# Note that we wrap the enum in a class/struct to act as a namespace,
# so that the enum strings can be brief w/o worrying about collisions.
def cxx_decl(cls, code):
wrapper_name = cls.wrapper_name
wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
name = cls.__name__ if cls.enum_name is None else cls.enum_name
idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
code('''\
#ifndef $idem_macro
#define $idem_macro
namespace gem5
{
''')
if cls.is_class:
code('''\
enum class $name
{
''')
else:
code('''\
$wrapper $wrapper_name {
enum $name
{
''')
code.indent(1)
code.indent(1)
for val in cls.vals:
code('$val = ${{cls.map[val]}},')
code('Num_$name = ${{len(cls.vals)}}')
code.dedent(1)
code('};')
if cls.is_class:
code('''\
extern const char *${name}Strings[static_cast<int>(${name}::Num_${name})];
''')
elif cls.wrapper_is_struct:
code('static const char *${name}Strings[Num_${name}];')
else:
code('extern const char *${name}Strings[Num_${name}];')
if not cls.is_class:
code.dedent(1)
code('}; // $wrapper_name')
code()
code('} // namespace gem5')
code()
code('#endif // $idem_macro')
def cxx_def(cls, code):
wrapper_name = cls.wrapper_name
file_name = cls.__name__
name = cls.__name__ if cls.enum_name is None else cls.enum_name
code('#include "base/compiler.hh"')
code('#include "enums/$file_name.hh"')
code()
code('namespace gem5')
code('{')
code()
if cls.wrapper_is_struct:
code('const char *${wrapper_name}::${name}Strings'
'[Num_${name}] =')
else:
if cls.is_class:
code('''\
const char *${name}Strings[static_cast<int>(${name}::Num_${name})] =
''')
else:
code('''GEM5_DEPRECATED_NAMESPACE(Enums, enums);
namespace enums
{''')
code.indent(1)
code('const char *${name}Strings[Num_${name}] =')
code('{')
code.indent(1)
for val in cls.vals:
code('"$val",')
code.dedent(1)
code('};')
if not cls.wrapper_is_struct and not cls.is_class:
code.dedent(1)
code('} // namespace enums')
code('} // namespace gem5')
def pybind_def(cls, code):
name = cls.__name__
enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name
wrapper_name = enum_name if cls.is_class else cls.wrapper_name
code('''#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
#include <sim/init.hh>
namespace py = pybind11;
namespace gem5
{
static void
module_init(py::module_ &m_internal)
{
py::module_ m = m_internal.def_submodule("enum_${name}");
''')
if cls.is_class:
code('py::enum_<${enum_name}>(m, "enum_${name}")')
else:
code('py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}")')
code.indent()
code.indent()
for val in cls.vals:
code('.value("${val}", ${wrapper_name}::${val})')
code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})')
if not cls.is_class:
code('.export_values()')
code(';')
code.dedent()
code('}')
code.dedent()
code()
code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);')
code()
code('} // namespace gem5')
# Base class for enum types.
class Enum(ParamValue, metaclass=MetaEnum):
vals = []