code('''#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
+#include <type_traits>
+
+#include "base/compiler.hh"
#include "params/$cls.hh"
#include "python/pybind11/core.hh"
#include "sim/init.hh"
code()
code('static EmbeddedPyBind embed_obj("${0}", module_init, "${1}");',
cls, cls._base.type if cls._base else "")
+ if not hasattr(cls, 'abstract') or not cls.abstract:
+ if 'type' in cls.__dict__:
+ code()
+ # This namespace can't *actually* be anonymous, or the compiler
+ # gets upset about having a weak symbol init.
+ code('namespace anonymous_params')
+ code('{')
+ code()
+ # If we can't define a default create() method for this params
+ # struct because the SimObject doesn't have the right
+ # constructor, use template magic to make it so we're actually
+ # defining a create method for this class instead.
+ code('class Dummy${cls}ParamsClass')
+ code('{')
+ code(' public:')
+ code(' ${{cls.cxx_class}} *create() const;')
+ code('};')
+ code()
+ code('template <class CxxClass, class Enable=void>')
+ code('class DummyShunt;')
+ code()
+ # This version directs to the real Params struct and the
+ # default behavior of create if there's an appropriate
+ # constructor.
+ code('template <class CxxClass>')
+ code('class DummyShunt<CxxClass, std::enable_if_t<')
+ code(' std::is_constructible<CxxClass,')
+ code(' const ${cls}Params &>::value>>')
+ code('{')
+ code(' public:')
+ code(' using Params = ${cls}Params;')
+ code(' static ${{cls.cxx_class}} *')
+ code(' create(const Params &p)')
+ code(' {')
+ code(' return new CxxClass(p);')
+ code(' }')
+ code('};')
+ code()
+ # This version diverts to the DummyParamsClass and a dummy
+ # implementation of create if the appropriate constructor does
+ # not exist.
+ code('template <class CxxClass>')
+ code('class DummyShunt<CxxClass, std::enable_if_t<')
+ code(' !std::is_constructible<CxxClass,')
+ code(' const ${cls}Params &>::value>>')
+ code('{')
+ code(' public:')
+ code(' using Params = Dummy${cls}ParamsClass;')
+ code(' static ${{cls.cxx_class}} *')
+ code(' create(const Params &p)')
+ code(' {')
+ code(' return nullptr;')
+ code(' }')
+ code('};')
+ code()
+ code('} // namespace anonymous_params')
+ code()
+ code('using namespace anonymous_params;')
+ code()
+ # A weak implementation of either the real Params struct's
+ # create method, or the Dummy one if we don't want to have
+ # any default implementation. Either an implementation is
+ # mandantory since this was shunted off to the dummy class, or
+ # one is optional which will override this weak version.
+ code('M5_WEAK ${{cls.cxx_class}} *')
+ code('DummyShunt<${{cls.cxx_class}}>::Params::create() const')
+ code('{')
+ code(' return DummyShunt<${{cls.cxx_class}}>::')
+ code(' create(*this);')
+ code('}')
_warned_about_nested_templates = False
* depth-first traversal is performed (see descendants() in
* SimObject.py). This has the effect of calling the method on the
* parent node <i>before</i> its children.
+ *
+ * The python version of a SimObject class actually represents its Params
+ * structure which holds all its parameter settings and its name. When python
+ * needs to create a C++ instance of one of those classes, it uses the Params
+ * struct's create() method which returns one instance, set up with the
+ * parameters in the struct.
+ *
+ * When writing a SimObject class, there are three different cases as far as
+ * what you need to do to support the create() method, for hypothetical class
+ * Foo.
+ *
+ * If you have a constructor with a signature like this:
+ *
+ * Foo(const FooParams &)
+ *
+ * you don't have to do anything, a create method will be automatically
+ * defined which will call your constructor and return that instance. You
+ * should use this option most of the time.
+ *
+ * If you have a constructor with that signature but still want to define
+ * your own create method for some reason, you can do that by providing an
+ * alternative implementation which will override the default. It should have
+ * this signature:
+ *
+ * Foo *FooParams::create() const;
+ *
+ * If you don't have a constructor with that signature at all, then you must
+ * implement the create method with that signature which will build your
+ * object in some other way.
*/
class SimObject : public EventManager, public Serializable, public Drainable,
public Stats::Group