diff --git a/build_tools/cxx_config_cc.py b/build_tools/cxx_config_cc.py index 7047857760..c4a2d8957f 100644 --- a/build_tools/cxx_config_cc.py +++ b/build_tools/cxx_config_cc.py @@ -1,5 +1,18 @@ +# 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 @@ -45,6 +58,242 @@ importer.install() module = importlib.import_module(args.modpath) sim_object = getattr(module, sim_object_name) +from m5.params import isSimObjectClass +import m5.params + code = code_formatter() -sim_object.cxx_config_param_file(code, False) + +entry_class = 'CxxConfigDirectoryEntry_%s' % sim_object_name +param_class = '%sCxxConfigParams' % sim_object_name + +def cxx_bool(b): + return 'true' if b else 'false' + +code('#include "params/%s.hh"' % sim_object_name) + +for param in sim_object._params.values(): + if isSimObjectClass(param.ptype): + code('#include "%s"' % param.ptype._value_dict['cxx_header']) + code('#include "params/%s.hh"' % param.ptype.__name__) + else: + param.ptype.cxx_ini_predecls(code) + +code('''#include "${{sim_object._value_dict['cxx_header']}}" +#include "base/str.hh" +#include "cxx_config/${sim_object_name}.hh" + +namespace gem5 +{ + +${param_class}::DirectoryEntry::DirectoryEntry() +{ +''') +code.indent() +for param in sim_object._params.values(): + is_vector = isinstance(param, m5.params.VectorParamDesc) + is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) + + code('parameters["%s"] = new ParamDesc("%s", %s, %s);' % + (param.name, param.name, cxx_bool(is_vector), + cxx_bool(is_simobj))); + +for port in sim_object._ports.values(): + is_vector = isinstance(port, m5.params.VectorPort) + is_requestor = port.role == 'GEM5 REQUESTOR' + + code('ports["%s"] = new PortDesc("%s", %s, %s);' % + (port.name, port.name, cxx_bool(is_vector), + cxx_bool(is_requestor))) + +code.dedent() + +code('''} + +bool +${param_class}::setSimObject(const std::string &name, SimObject *simObject) +{ + bool ret = true; + if (false) { +''') + +code.indent() +for param in sim_object._params.values(): + is_vector = isinstance(param, m5.params.VectorParamDesc) + is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) + + if is_simobj and not is_vector: + code('} else if (name == "${{param.name}}") {') + code.indent() + code('this->${{param.name}} = ' + 'dynamic_cast<${{param.ptype.cxx_type}}>(simObject);') + code('if (simObject && !this->${{param.name}})') + code(' ret = false;') + code.dedent() +code.dedent() + +code(''' + } else { + ret = false; + } + + return ret; +} + +bool +${param_class}::setSimObjectVector(const std::string &name, + const std::vector &simObjects) +{ + bool ret = true; + + if (false) { +''') + +code.indent() +for param in sim_object._params.values(): + is_vector = isinstance(param, m5.params.VectorParamDesc) + is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) + + if is_simobj and is_vector: + code('} else if (name == "${{param.name}}") {') + code.indent() + code('this->${{param.name}}.clear();') + code('for (auto i = simObjects.begin(); ' + 'ret && i != simObjects.end(); i ++)') + code('{') + code.indent() + code('${{param.ptype.cxx_type}} object = ' + 'dynamic_cast<${{param.ptype.cxx_type}}>(*i);') + code('if (*i && !object)') + code(' ret = false;') + code('else') + code(' this->${{param.name}}.push_back(object);') + code.dedent() + code('}') + code.dedent() +code.dedent() + +code(''' + } else { + ret = false; + } + + return ret; +} + +void +${param_class}::setName(const std::string &name_) +{ + this->name = name_; +} + +bool +${param_class}::setParam(const std::string &name, + const std::string &value, const Flags flags) +{ + bool ret = true; + + if (false) { +''') + +code.indent() +for param in sim_object._params.values(): + is_vector = isinstance(param, m5.params.VectorParamDesc) + is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) + + if not is_simobj and not is_vector: + code('} else if (name == "${{param.name}}") {') + code.indent() + param.ptype.cxx_ini_parse(code, + 'value', 'this->%s' % param.name, 'ret =') + code.dedent() +code.dedent() + +code(''' + } else { + ret = false; + } + + return ret; +} + +bool +${param_class}::setParamVector(const std::string &name, + const std::vector &values, const Flags flags) +{ + bool ret = true; + + if (false) { +''') + +code.indent() +for param in sim_object._params.values(): + is_vector = isinstance(param, m5.params.VectorParamDesc) + is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) + + if not is_simobj and is_vector: + code('} else if (name == "${{param.name}}") {') + code.indent() + code('${{param.name}}.clear();') + code('for (auto i = values.begin(); ' + 'ret && i != values.end(); i ++)') + code('{') + code.indent() + code('${{param.ptype.cxx_type}} elem;') + param.ptype.cxx_ini_parse(code, + '*i', 'elem', 'ret =') + code('if (ret)') + code(' this->${{param.name}}.push_back(elem);') + code.dedent() + code('}') + code.dedent() +code.dedent() + +code(''' + } else { + ret = false; + } + + return ret; +} + +bool +${param_class}::setPortConnectionCount(const std::string &name, + unsigned int count) +{ + bool ret = true; + + if (false) { +''') + +code.indent() +for port in sim_object._ports.values(): + code('} else if (name == "${{port.name}}") {') + code(' this->port_${{port.name}}_connection_count = count;') +code.dedent() + +code(''' + } else { + ret = false; + } + + return ret; +} + +SimObject * +${param_class}::simObjectCreate() +{ +''') + +code.indent() +if hasattr(sim_object, 'abstract') and sim_object.abstract: + code('return nullptr;') +else: + code('return this->create();') +code.dedent() + +code('''} + +} // namespace gem5 +''') + code.write(args.cxx_config_cc) diff --git a/build_tools/cxx_config_hh.py b/build_tools/cxx_config_hh.py index 3cae84b69e..4e47f87d21 100644 --- a/build_tools/cxx_config_hh.py +++ b/build_tools/cxx_config_hh.py @@ -1,5 +1,18 @@ +# 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 @@ -46,5 +59,61 @@ module = importlib.import_module(args.modpath) sim_object = getattr(module, sim_object_name) code = code_formatter() -sim_object.cxx_config_param_file(code, True) + +entry_class = 'CxxConfigDirectoryEntry_%s' % sim_object_name +param_class = '%sCxxConfigParams' % sim_object_name + +code('''#include "params/${sim_object_name}.hh" + +#include "sim/cxx_config.hh" + +namespace gem5 +{ + +class ${param_class} : public CxxConfigParams, public ${sim_object_name}Params +{ + private: + class DirectoryEntry : public CxxConfigDirectoryEntry + { + public: + DirectoryEntry(); + + CxxConfigParams * + makeParamsObject() const + { + return new ${param_class}; + } + }; + + public: + bool setSimObject(const std::string &name, SimObject *simObject); + + bool setSimObjectVector(const std::string &name, + const std::vector &simObjects); + + void setName(const std::string &name_); + + const std::string &getName() { return this->name; } + + bool setParam(const std::string &name, const std::string &value, + const Flags flags); + + bool setParamVector(const std::string &name, + const std::vector &values, const Flags flags); + + bool setPortConnectionCount(const std::string &name, unsigned int count); + + SimObject *simObjectCreate(); + + static CxxConfigDirectoryEntry * + makeDirectoryEntry() + { + return new DirectoryEntry; + } + +}; + +} // namespace gem5 +''') + code.write(args.cxx_config_hh) diff --git a/build_tools/cxx_config_init_cc.py b/build_tools/cxx_config_init_cc.py index d3af795f3e..aab8d29c3b 100644 --- a/build_tools/cxx_config_init_cc.py +++ b/build_tools/cxx_config_init_cc.py @@ -1,5 +1,18 @@ +# 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 @@ -39,20 +52,26 @@ code = code_formatter() for sim_object in args.sim_objects: code('#include "cxx_config/${sim_object}.hh"') -code('') -code('namespace gem5') -code('{') -code('') -code('void') -code('cxxConfigInit()') -code('{') + +code(''' +namespace gem5 +{ + +void +cxxConfigInit() +{ +''') + code.indent() for sim_object in args.sim_objects: code('cxx_config_directory["${sim_object}"] = ' '${sim_object}CxxConfigParams::makeDirectoryEntry();') code.dedent() -code('}') -code('') -code('} // namespace gem5') + +code(''' +} + +} // namespace gem5 +''') code.write(args.cxx_config_init_cc) diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index b2ed967d12..26a1227712 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -116,281 +116,6 @@ def public_value(key, value): isinstance(value, (FunctionType, MethodType, ModuleType, classmethod, type)) -def createCxxConfigDirectoryEntryFile(code, name, simobj, is_header): - entry_class = 'CxxConfigDirectoryEntry_%s' % name - param_class = '%sCxxConfigParams' % name - - code('#include "params/%s.hh"' % name) - - if not is_header: - for param in simobj._params.values(): - if isSimObjectClass(param.ptype): - code('#include "%s"' % param.ptype._value_dict['cxx_header']) - code('#include "params/%s.hh"' % param.ptype.__name__) - else: - param.ptype.cxx_ini_predecls(code) - - if is_header: - member_prefix = '' - end_of_decl = ';' - code('#include "sim/cxx_config.hh"') - code() - code('namespace gem5') - code('{') - code() - code('class ${param_class} : public CxxConfigParams,' - ' public ${name}Params') - code('{') - code(' private:') - code.indent() - code('class DirectoryEntry : public CxxConfigDirectoryEntry') - code('{') - code(' public:') - code.indent() - code('DirectoryEntry();'); - code() - code('CxxConfigParams *makeParamsObject() const') - code('{ return new ${param_class}; }') - code.dedent() - code('};') - code() - code.dedent() - code(' public:') - code.indent() - else: - member_prefix = '%s::' % param_class - end_of_decl = '' - code('#include "%s"' % simobj._value_dict['cxx_header']) - code('#include "base/str.hh"') - code('#include "cxx_config/${name}.hh"') - - code('namespace gem5') - code('{') - code() - code('${member_prefix}DirectoryEntry::DirectoryEntry()'); - code('{') - - def cxx_bool(b): - return 'true' if b else 'false' - - code.indent() - for param in simobj._params.values(): - is_vector = isinstance(param, m5.params.VectorParamDesc) - is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) - - code('parameters["%s"] = new ParamDesc("%s", %s, %s);' % - (param.name, param.name, cxx_bool(is_vector), - cxx_bool(is_simobj))); - - for port in simobj._ports.values(): - is_vector = isinstance(port, m5.params.VectorPort) - is_requestor = port.role == 'GEM5 REQUESTOR' - - code('ports["%s"] = new PortDesc("%s", %s, %s);' % - (port.name, port.name, cxx_bool(is_vector), - cxx_bool(is_requestor))) - - code.dedent() - code('}') - code() - - code('bool ${member_prefix}setSimObject(const std::string &name,') - code(' SimObject *simObject)${end_of_decl}') - - if not is_header: - code('{') - code.indent() - code('bool ret = true;') - code() - code('if (false) {') - for param in simobj._params.values(): - is_vector = isinstance(param, m5.params.VectorParamDesc) - is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) - - if is_simobj and not is_vector: - code('} else if (name == "${{param.name}}") {') - code.indent() - code('this->${{param.name}} = ' - 'dynamic_cast<${{param.ptype.cxx_type}}>(simObject);') - code('if (simObject && !this->${{param.name}})') - code(' ret = false;') - code.dedent() - code('} else {') - code(' ret = false;') - code('}') - code() - code('return ret;') - code.dedent() - code('}') - - code() - code('bool ${member_prefix}setSimObjectVector(' - 'const std::string &name,') - code(' const std::vector &simObjects)${end_of_decl}') - - if not is_header: - code('{') - code.indent() - code('bool ret = true;') - code() - code('if (false) {') - for param in simobj._params.values(): - is_vector = isinstance(param, m5.params.VectorParamDesc) - is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) - - if is_simobj and is_vector: - code('} else if (name == "${{param.name}}") {') - code.indent() - code('this->${{param.name}}.clear();') - code('for (auto i = simObjects.begin(); ' - 'ret && i != simObjects.end(); i ++)') - code('{') - code.indent() - code('${{param.ptype.cxx_type}} object = ' - 'dynamic_cast<${{param.ptype.cxx_type}}>(*i);') - code('if (*i && !object)') - code(' ret = false;') - code('else') - code(' this->${{param.name}}.push_back(object);') - code.dedent() - code('}') - code.dedent() - code('} else {') - code(' ret = false;') - code('}') - code() - code('return ret;') - code.dedent() - code('}') - - code() - code('void ${member_prefix}setName(const std::string &name_)' - '${end_of_decl}') - - if not is_header: - code('{') - code.indent() - code('this->name = name_;') - code.dedent() - code('}') - - if is_header: - code('const std::string &${member_prefix}getName()') - code('{ return this->name; }') - - code() - code('bool ${member_prefix}setParam(const std::string &name,') - code(' const std::string &value, const Flags flags)${end_of_decl}') - - if not is_header: - code('{') - code.indent() - code('bool ret = true;') - code() - code('if (false) {') - for param in simobj._params.values(): - is_vector = isinstance(param, m5.params.VectorParamDesc) - is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) - - if not is_simobj and not is_vector: - code('} else if (name == "${{param.name}}") {') - code.indent() - param.ptype.cxx_ini_parse(code, - 'value', 'this->%s' % param.name, 'ret =') - code.dedent() - code('} else {') - code(' ret = false;') - code('}') - code() - code('return ret;') - code.dedent() - code('}') - - code() - code('bool ${member_prefix}setParamVector(' - 'const std::string &name,') - code(' const std::vector &values,') - code(' const Flags flags)${end_of_decl}') - - if not is_header: - code('{') - code.indent() - code('bool ret = true;') - code() - code('if (false) {') - for param in simobj._params.values(): - is_vector = isinstance(param, m5.params.VectorParamDesc) - is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) - - if not is_simobj and is_vector: - code('} else if (name == "${{param.name}}") {') - code.indent() - code('${{param.name}}.clear();') - code('for (auto i = values.begin(); ' - 'ret && i != values.end(); i ++)') - code('{') - code.indent() - code('${{param.ptype.cxx_type}} elem;') - param.ptype.cxx_ini_parse(code, - '*i', 'elem', 'ret =') - code('if (ret)') - code(' this->${{param.name}}.push_back(elem);') - code.dedent() - code('}') - code.dedent() - code('} else {') - code(' ret = false;') - code('}') - code() - code('return ret;') - code.dedent() - code('}') - - code() - code('bool ${member_prefix}setPortConnectionCount(' - 'const std::string &name,') - code(' unsigned int count)${end_of_decl}') - - if not is_header: - code('{') - code.indent() - code('bool ret = true;') - code() - code('if (false)') - code(' ;') - for port in simobj._ports.values(): - code('else if (name == "${{port.name}}")') - code(' this->port_${{port.name}}_connection_count = count;') - code('else') - code(' ret = false;') - code() - code('return ret;') - code.dedent() - code('}') - - code() - code('SimObject *${member_prefix}simObjectCreate()${end_of_decl}') - - if not is_header: - code('{') - if hasattr(simobj, 'abstract') and simobj.abstract: - code(' return NULL;') - else: - code(' return this->create();') - code('}') - - if is_header: - code() - code('static CxxConfigDirectoryEntry' - ' *${member_prefix}makeDirectoryEntry()') - code('{ return new DirectoryEntry; }') - - if is_header: - code.dedent() - code('};') - - code('} // namespace gem5') - # The metaclass for SimObject. This class controls how new classes # that derive from SimObject are instantiated, and provides inherited # class behavior (just like a class controls how instances of that @@ -708,12 +433,6 @@ class MetaSimObject(type): def pybind_predecls(cls, code): code('#include "${{cls.cxx_header}}"') - # Generate the C++ declaration/definition files for this SimObject's - # param struct to allow C++ initialisation - def cxx_config_param_file(cls, code, is_header): - createCxxConfigDirectoryEntryFile(code, cls.__name__, cls, is_header) - return code - # This *temporary* definition is required to support calls from the # SimObject class definition to the MetaSimObject methods (in # particular _set_param, which gets called for parameters with default