[Python] Unable to build Gem5 after creation of custom replacement policy: undefined reference...

Discussão em 'Python' iniciado por Stack, Julho 28, 2025.

  1. Stack

    Stack Membro Participativo

    I have been implementing a custom replacement policy for the gem5 cache. I followed the model of the DuelingRP, including the initialization of parameters. But when I try to build gem5 with scons, it fails during the linking stage with the following error.

    /usr/bin/ld: build/X86/python/_m5/param_TSelRP.o: in function void pybind11::cpp_function::initialize<pybind11::cpp_function::initialize<gem5::replacement_policy::TSel*, gem5::TSelRPParams, , pybind11::name, pybind11::is_method, pybind11::sibling>(gem5::replacement_policy::TSel* (gem5::TSelRPParams::*)() const, pybind11::name const&, pybind11::is_method const&, pybind11::sibling const&)::{lambda(gem5::TSelRPParams const*)#1}, gem5::replacement_policy::TSel*, gem5::TSelRPParams const*, pybind11::name, pybind11::is_method, pybind11::sibling>(pybind11::cpp_function::initialize<gem5::replacement_policy::TSel*, gem5::TSelRPParams, , pybind11::name, pybind11::is_method, pybind11::sibling>(gem5::replacement_policy::TSel* (gem5::TSelRPParams::*)() const, pybind11::name const&, pybind11::is_method const&, pybind11::sibling const&)::{lambda(gem5::TSelRPParams const*)#1}&&, gem5::replacement_policy::TSel* (*)(gem5::TSelRPParams const*), pybind11::name const&, pybind11::is_method const&, pybind11::sibling const&)':
    /.../ext/pybind11/include/pybind11/pybind11.h:210: undefined reference to gem5::TSelRPParams::create() const'


    Listed below is the relevant code for the class definition.

    tsel_rp.cc

    /** TSel class constructor */
    TSel::TSel(const Params &p)
    : Base(p), replPolicyA(p.replacement_policy_a),
    indexPolicyA(p.index_policy_a),
    replPolicyB(p.replacement_policy_b),
    indexPolicyB(p.index_policy_b)
    {

    }


    tsel_rp.hh

    #ifndef __MEM_CACHE_REPLACEMENT_POLICIES_TSEL_RP_HH__
    #define __MEM_CACHE_REPLACEMENT_POLICIES_TSEL_RP_HH__

    #include <cstddef>
    #include <cstdint>
    #include <memory>

    #include "base/compiler.hh"
    #include "base/sat_counter.hh"
    #include "base/statistics.hh"
    #include "mem/cache/cache.hh"
    #include "mem/cache/replacement_policies/base.hh"
    #include "mem/cache/tags/indexing_policies/base.hh"

    namespace gem5
    {

    struct TSelRPParams;

    GEM5_DEPRECATED_NAMESPACE(ReplacementPolicy, replacement_policy);
    namespace replacement_policy
    {

    class TSel : public Base
    {
    protected:
    /**
    * TSel-specific implementation of replacement data. Contains all
    * sub-replacement policies' replacement data.
    */
    struct TSelReplData : ReplacementData
    {
    std::shared_ptr<ReplacementData> replDataA;
    std::shared_ptr<ReplacementData> replDataB;

    /** Default constructor. Initialize sub-replacement data. */
    TSelReplData(const std::shared_ptr<ReplacementData>& repl_data_a,
    const std::shared_ptr<ReplacementData>& repl_data_b)
    : ReplacementData(), replDataA(repl_data_a),
    replDataB(repl_data_b)
    {
    }
    };

    /** Sub-replacement policy used in this multiple container. */
    Base* const replPolicyA;
    /** Sub-indexing policy used in this multiple container. */
    BaseIndexingPolicy* const indexPolicyA;

    /** Sub-replacement policy used in this multiple container. */
    Base* const replPolicyB;
    /** Sub-indexing policy used in this multiple container. */
    BaseIndexingPolicy* const indexPolicyB;

    /** List of saturating counters to use for each set in the cache */
    std::vector<SatCounter16> SCTRs;

    /** Pointer to the actual implementation of the cache */
    Cache *cache;

    private:

    bool isAddressInEntries(const Addr addr,
    const ReplacementCandidates& entries);
    void updateAuxiliaryDirectories(const Addr addr, uint8_t costq);
    SatCounter16 getCounter(const Addr addr);

    public:
    // This follows the model of the Dueling Replacement Policy
    PARAMS(TSelRP);
    TSel(const Params &p);
    ~TSel() = default;

    void invalidate(const std::shared_ptr<ReplacementData>& replacement_data) override;
    void touch(const std::shared_ptr<ReplacementData>& replacement_data, const PacketPtr pkt) override;
    void reset(const std::shared_ptr<ReplacementData>& replacement_data) const override;
    ReplaceableEntry* getVictim(const ReplacementCandidates& candidates, Addr addr) override;
    std::shared_ptr<ReplacementData> instantiateEntry() override;

    };

    } // namespace replacement_policy
    } // namespace gem5

    #endif // __MEM_CACHE_REPLACEMENT_POLICIES_TSEL_RP_HH__


    mem/cache/replacement_policies/SConscript

    SimObject('ReplacementPolicies.py', sim_objects=[
    'BaseReplacementPolicy', 'DuelingRP' ... 'TSelRP'])

    Source('dueling_rp.cc')
    Source('tsel_rp.cc')


    /mem/cache/replacement_policies/ReplacementPolicies.py

    class BaseReplacementPolicy(SimObject):
    type = 'BaseReplacementPolicy'
    abstract = True
    cxx_class = 'gem5::replacement_policy::Base'
    cxx_header = "mem/cache/replacement_policies/base.hh"

    class DuelingRP(BaseReplacementPolicy):
    type = 'DuelingRP'
    cxx_class = 'gem5::replacement_policy::Dueling'
    cxx_header = "mem/cache/replacement_policies/dueling_rp.hh"

    constituency_size = Param.Unsigned(
    "The size of a region containing one sample")
    team_size = Param.Unsigned(
    "Number of entries in a sampling set that belong to a team")
    replacement_policy_a = Param.BaseReplacementPolicy(
    "Sub-replacement policy A")
    replacement_policy_b = Param.BaseReplacementPolicy(
    "Sub-replacement policy B")

    class TSelRP(BaseReplacementPolicy):
    type = 'TSelRP'
    cxx_class = 'gem5::replacement_policy::TSel'
    cxx_header = "mem/cache/replacement_policies/tsel_rp.hh"

    # Auxiliary Indexing Policies
    index_policy_a = Param.BaseIndexingPolicy(
    "Auxiliary indexing policy A")
    index_policy_b = Param.BaseIndexingPolicy(
    "Auxiliary indexing policy B")

    # Replacement Policies for TSel
    replacement_policy_a = Param.BaseReplacementPolicy(
    "Sub-replacement policy A")
    replacement_policy_b = Param.BaseReplacementPolicy(
    "Sub-replacement policy B")

    # Number of counter bits
    num_counter_bits = Param.Int(3, "Number of counter bits")


    The relevant params files, including param_TSelRP.cc which has the DummyShunt implementation of create, have also been correctly generated.

    param_TSelRP.cc

    /**
    * DO NOT EDIT THIS FILE!
    * File automatically generated by
    * build_tools/sim_object_param_struct_cc.py:62
    */

    #include "pybind11/pybind11.h"
    #include "pybind11/stl.h"

    #include <type_traits>

    #include "base/compiler.hh"
    #include "params/TSelRP.hh"
    #include "sim/init.hh"
    #include "sim/sim_object.hh"

    #include "mem/cache/replacement_policies/tsel_rp.hh"

    #include "mem/cache/tags/indexing_policies/base.hh"
    #include "mem/cache/tags/indexing_policies/base.hh"
    #include "base/types.hh"
    #include "mem/cache/replacement_policies/base.hh"
    #include "mem/cache/replacement_policies/base.hh"
    namespace py = pybind11;

    namespace gem5
    {

    static void
    module_init(py::module_ &m_internal)
    {
    py::module_ m = m_internal.def_submodule("param_TSelRP");
    py::class_<TSelRPParams, BaseReplacementPolicyParams, std::unique_ptr<TSelRPParams, py::nodelete>>(m, "TSelRPParams")
    .def(py::init<>())
    .def("create", &TSelRPParams::create)
    .def_readwrite("index_policy_a", &TSelRPParams::index_policy_a)
    .def_readwrite("index_policy_b", &TSelRPParams::index_policy_b)
    .def_readwrite("num_counter_bits", &TSelRPParams::num_counter_bits)
    .def_readwrite("replacement_policy_a", &TSelRPParams::replacement_policy_a)
    .def_readwrite("replacement_policy_b", &TSelRPParams::replacement_policy_b)
    ;

    py::class_<gem5::replacement_policy::TSel, gem5::replacement_policy::Base, std::unique_ptr<gem5::replacement_policy::TSel, py::nodelete>>(m, "gem5_COLONS_replacement_policy_COLONS_TSel")
    ;

    }

    static EmbeddedPyBind embed_obj("TSelRP", module_init, "BaseReplacementPolicy");

    } // namespace gem5

    namespace gem5
    {

    namespace
    {

    class DummyTSelRPParamsClass
    {
    public:
    gem5::replacement_policy::TSel *create() const;
    };

    template <class CxxClass, class Enable=void>
    class DummyTSelRPShunt;

    template <class CxxClass>
    class DummyTSelRPShunt<CxxClass, std::enable_if_t<
    std::is_constructible_v<CxxClass,
    const TSelRPParams &>>>
    {
    public:
    using Params = TSelRPParams;
    static gem5::replacement_policy::TSel *
    create(const Params &p)
    {
    return new CxxClass(p);
    }
    };

    template <class CxxClass>
    class DummyTSelRPShunt<CxxClass, std::enable_if_t<
    !std::is_constructible_v<CxxClass,
    const TSelRPParams &>>>
    {
    public:
    using Params = DummyTSelRPParamsClass;
    static gem5::replacement_policy::TSel *
    create(const Params &p)
    {
    return nullptr;
    }
    };

    } // anonymous namespace

    [[maybe_unused]] gem5::replacement_policy::TSel *
    DummyTSelRPShunt<gem5::replacement_policy::TSel>::params::create() const
    {
    return DummyTSelRPShunt<gem5::replacement_policy::TSel>::
    create(*this);
    }

    } // namespace gem5


    and TSelRP.hh

    /**
    * DO NOT EDIT THIS FILE!
    * File automatically generated by
    * build_tools/sim_object_param_struct_hh.py:50
    */

    #ifndef __PARAMS__TSelRP__
    #define __PARAMS__TSelRP__

    namespace gem5 {
    namespace replacement_policy {
    class TSel;
    } // namespace replacement_policy
    } // namespace gem5
    #include <cstddef>
    #include "params/BaseIndexingPolicy.hh"
    #include <cstddef>
    #include "params/BaseIndexingPolicy.hh"
    #include <cstddef>
    #include "base/types.hh"
    #include <cstddef>
    #include "params/BaseReplacementPolicy.hh"
    #include <cstddef>
    #include "params/BaseReplacementPolicy.hh"

    #include "params/BaseReplacementPolicy.hh"

    namespace gem5
    {
    struct TSelRPParams
    : public BaseReplacementPolicyParams
    {
    gem5::replacement_policy::TSel * create() const;
    gem5::BaseIndexingPolicy * index_policy_a;
    gem5::BaseIndexingPolicy * index_policy_b;
    int num_counter_bits;
    gem5::replacement_policy::Base * replacement_policy_a;
    gem5::replacement_policy::Base * replacement_policy_b;
    };

    } // namespace gem5

    #endif // __PARAMS__TSelRP__



    I have tried rebuilding Gem5 from scratch, but it continues to fail during the link stage. Other references to this error can be found here and here. However it appears that these other errors are a result of the relevant params files not being auto-generated.

    Any help would be graciously appreciated.

    Continue reading...

Compartilhe esta Página