Search code examples
pythoninheritancegem5

How are attributes such as clk_domain of the System object passed between Python and C++ in gem5?


I am very new to gem5 and I come from C++. Perhaps this is a Python problem. So I was doing the tutorials and I do not understand how you can you know what attributes the System() object has. For example, I can see in "Creating a simple configuration script" that system has an attribute clk_domain, which corresponds to ClockedObject. But System is a class that inherits from SimObject, and none of them inherits from ClockedObject. Any help would be apprecieated. Thanks in advance.


Solution

  • gem5 uses code generation heavily.

    Every SimObject Python class automatically generates a param C++ class under the build directory that gets passed as the constructor of the C++ object. This is described in further details at: https://cirosantilli.com/linux-kernel-module-cheat/#gem5-python-c-interaction and was also mentioned at: Viewing the parameters of the branch predictor in gem5

    But basically, if you grep for generated C++ files in the build directory (ignore symlinks, which scons sets up to point back to the main source tree), you will be able to understand everything.

    I haven't fully studied/understood how ClockedObject is used in particular, but the following should clarify the Python/C++ magic interaction part at least

    The specific case of ClockedObject.clk_domain, the default value for the parameter is hte magic Parent.clk_domain, which links it to its parent's (in the SimObject tree) clk_domain by default if another value is not given:

    class ClockedObject(SimObject):
        type = 'ClockedObject'
        abstract = True
        cxx_header = "sim/clocked_object.hh"
    
        # The clock domain this clocked object belongs to, inheriting the
        # parent's clock domain by default
        clk_domain = Param.ClockDomain(Parent.clk_domain, "Clock domain")
    
        # Power model for this ClockedObject
        power_model = VectorParam.PowerModel([], "Power models")
    
        power_state = Param.PowerState(PowerState(), "Power state")
    

    The autogenerated class from that is build/ARM/params/ClockedObject.hh is:

    struct ClockedObjectParams
        : public SimObjectParams
    {
        ClockDomain * clk_domain;
        std::vector< PowerModel * > power_model;
        PowerState * power_state;
    };
    

    and the corresponding pybind11 bindings link that object from python to C++:

    static void
    module_init(py::module &m_internal)
    {
        py::module m = m_internal.def_submodule("param_ClockedObject");
        py::class_<ClockedObjectParams, SimObjectParams, std::unique_ptr<ClockedObjectParams, py::nodelete>>(m, "ClockedObjectParams")
            .def_readwrite("clk_domain", &ClockedObjectParams::clk_domain)
            .def_readwrite("power_model", &ClockedObjectParams::power_model)
            .def_readwrite("power_state", &ClockedObjectParams::power_state)
            ;
    
        py::class_<ClockedObject, SimObject, std::unique_ptr<ClockedObject, py::nodelete>>(m, "ClockedObject")
            ;
    
    }
    
    static EmbeddedPyBind embed_obj("ClockedObject", module_init, "SimObject");
    

    and then when the C++ ClockedObject object gets created (this is also from the Python via bindings after the full SimObject tree has been built), it receives ClockedObjectParams as input at src/sim/clock_domain.hh which contains:

    class ClockDomain : public SimObject
    {
    
      public:
    
        typedef ClockDomainParams Params;
        ClockDomain(const Params *p, VoltageDomain *voltage_domain);
    

    Looking at fs.py, clk_domain is actually a SrcClockDomain initialized as:

        # Create a source clock for the system and set the clock period
        test_sys.clk_domain = SrcClockDomain(clock =  options.sys_clock,
                voltage_domain = test_sys.voltage_domain)
    

    but things are analogous, there is a Python SrcClockDomain which inherits from ClockDomain and corresponding C++ classes.

    Observed in gem5 3ca404da175a66e0b958165ad75eb5f54cb5e772.