diff --git a/src/mem/cache/replacement_policies/ReplacementPolicies.py b/src/mem/cache/replacement_policies/ReplacementPolicies.py index 11de0b23ec..7003abec1b 100644 --- a/src/mem/cache/replacement_policies/ReplacementPolicies.py +++ b/src/mem/cache/replacement_policies/ReplacementPolicies.py @@ -114,6 +114,31 @@ class NRURP(BRRIPRP): btp = 100 num_bits = 1 +class SHiPRP(BRRIPRP): + type = 'SHiPRP' + abstract = True + cxx_class = 'replacement_policy::SHiP' + cxx_header = "mem/cache/replacement_policies/ship_rp.hh" + + shct_size = Param.Unsigned(16384, "Number of SHCT entries") + # By default any value greater than 0 is enough to change insertion policy + insertion_threshold = Param.Percent(1, + "Percentage at which an entry changes insertion policy") + # Always make hits mark entries as last to be evicted + hit_priority = True + # Let the predictor decide when to change insertion policy + btp = 0 + +class SHiPMemRP(SHiPRP): + type = 'SHiPMemRP' + cxx_class = 'replacement_policy::SHiPMem' + cxx_header = "mem/cache/replacement_policies/ship_rp.hh" + +class SHiPPCRP(SHiPRP): + type = 'SHiPPCRP' + cxx_class = 'replacement_policy::SHiPPC' + cxx_header = "mem/cache/replacement_policies/ship_rp.hh" + class TreePLRURP(BaseReplacementPolicy): type = 'TreePLRURP' cxx_class = 'replacement_policy::TreePLRU' diff --git a/src/mem/cache/replacement_policies/SConscript b/src/mem/cache/replacement_policies/SConscript index 29152a0a01..63700525c7 100644 --- a/src/mem/cache/replacement_policies/SConscript +++ b/src/mem/cache/replacement_policies/SConscript @@ -39,5 +39,6 @@ Source('lru_rp.cc') Source('mru_rp.cc') Source('random_rp.cc') Source('second_chance_rp.cc') +Source('ship_rp.cc') Source('tree_plru_rp.cc') Source('weighted_lru_rp.cc') diff --git a/src/mem/cache/replacement_policies/ship_rp.cc b/src/mem/cache/replacement_policies/ship_rp.cc new file mode 100644 index 0000000000..7e16306d78 --- /dev/null +++ b/src/mem/cache/replacement_policies/ship_rp.cc @@ -0,0 +1,171 @@ +/** + * Copyright (c) 2019, 2020 Inria + * All rights reserved. + * + * 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 + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mem/cache/replacement_policies/ship_rp.hh" + +#include "base/logging.hh" +#include "params/SHiPMemRP.hh" +#include "params/SHiPPCRP.hh" +#include "params/SHiPRP.hh" + +namespace replacement_policy +{ + +SHiP::SHiPReplData::SHiPReplData(int num_bits) + : BRRIPReplData(num_bits), signature(0), outcome(false) +{ +} + +SHiP::SignatureType +SHiP::SHiPReplData::getSignature() const +{ + return signature; +} + +void +SHiP::SHiPReplData::setSignature(SignatureType new_signature) +{ + signature = new_signature; + outcome = false; +} + +void +SHiP::SHiPReplData::setReReferenced() +{ + outcome = true; +} + +bool +SHiP::SHiPReplData::wasReReferenced() const +{ + return outcome; +} + +SHiP::SHiP(const Params &p) + : BRRIP(p), insertionThreshold(p.insertion_threshold / 100.0), + SHCT(p.shct_size, SatCounter(numRRPVBits)) +{ +} + +void +SHiP::invalidate(const std::shared_ptr& replacement_data) +{ + std::shared_ptr casted_replacement_data = + std::static_pointer_cast(replacement_data); + + // The predictor is detrained when an entry that has not been re- + // referenced since insertion is invalidated + if (casted_replacement_data->wasReReferenced()) { + SHCT[casted_replacement_data->getSignature()]--; + } + + BRRIP::invalidate(replacement_data); +} + +void +SHiP::touch(const std::shared_ptr& replacement_data, + const PacketPtr pkt) +{ + std::shared_ptr casted_replacement_data = + std::static_pointer_cast(replacement_data); + + // When a hit happens the SHCT entry indexed by the signature is + // incremented + SHCT[getSignature(pkt)]++; + casted_replacement_data->setReReferenced(); + + // This was a hit; update replacement data accordingly + BRRIP::touch(replacement_data); +} + +void +SHiP::touch(const std::shared_ptr& replacement_data) + const +{ + panic("Cant train SHiP's predictor without access information."); +} + +void +SHiP::reset(const std::shared_ptr& replacement_data, + const PacketPtr pkt) +{ + std::shared_ptr casted_replacement_data = + std::static_pointer_cast(replacement_data); + + // Get signature + const SignatureType signature = getSignature(pkt); + + // Store signature + casted_replacement_data->setSignature(signature); + + // If SHCT for signature is set, predict intermediate re-reference. + // Predict distant re-reference otherwise + BRRIP::reset(replacement_data); + if (SHCT[signature].calcSaturation() >= insertionThreshold) { + casted_replacement_data->rrpv--; + } +} + +void +SHiP::reset(const std::shared_ptr& replacement_data) + const +{ + panic("Cant train SHiP's predictor without access information."); +} + +std::shared_ptr +SHiP::instantiateEntry() +{ + return std::shared_ptr(new SHiPReplData(numRRPVBits)); +} + +SHiPMem::SHiPMem(const SHiPMemRPParams &p) : SHiP(p) {} + +SHiP::SignatureType +SHiPMem::getSignature(const PacketPtr pkt) const +{ + return static_cast(pkt->getAddr() % SHCT.size()); +} + +SHiPPC::SHiPPC(const SHiPPCRPParams &p) : SHiP(p) {} + +SHiP::SignatureType +SHiPPC::getSignature(const PacketPtr pkt) const +{ + SignatureType signature; + + if (pkt->req->hasPC()) { + signature = static_cast(pkt->req->getPC()); + } else { + signature = NO_PC_SIGNATURE; + } + + return signature % SHCT.size(); +} + +} // namespace replacement_policy diff --git a/src/mem/cache/replacement_policies/ship_rp.hh b/src/mem/cache/replacement_policies/ship_rp.hh new file mode 100644 index 0000000000..1001a7bd64 --- /dev/null +++ b/src/mem/cache/replacement_policies/ship_rp.hh @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2019, 2020 Inria + * All rights reserved. + * + * 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 + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of a the SHiP Replacement Policy, as described in "SHiP: + * Signature-based Hit Predictor for High Performance Caching", by + * Wu et al. + */ + +#ifndef __MEM_CACHE_REPLACEMENT_POLICIES_SHIP_RP_HH__ +#define __MEM_CACHE_REPLACEMENT_POLICIES_SHIP_RP_HH__ + +#include +#include + +#include "base/compiler.hh" +#include "base/sat_counter.hh" +#include "mem/cache/replacement_policies/brrip_rp.hh" +#include "mem/packet.hh" + +struct SHiPRPParams; +struct SHiPMemRPParams; +struct SHiPPCRPParams; + +GEM5_DEPRECATED_NAMESPACE(ReplacementPolicy, replacement_policy); +namespace replacement_policy +{ + +class SHiP : public BRRIP +{ + protected: + typedef std::size_t SignatureType; + + /** SHiP-specific implementation of replacement data. */ + class SHiPReplData : public BRRIPReplData + { + private: + /** Signature that caused the insertion of this entry. */ + SignatureType signature; + + /** Outcome of insertion; set to one if entry is re-referenced. */ + bool outcome; + + public: + SHiPReplData(int num_bits); + + /** Get entry's signature. */ + SignatureType getSignature() const; + + /** + * Set this entry's signature and reset outcome. + * + * @param signature New signature value/ + */ + void setSignature(SignatureType signature); + + /** Set that this entry has been re-referenced. */ + void setReReferenced(); + + /** + * Get whether entry has been re-referenced since insertion. + * + * @return True if entry has been re-referenced since insertion. + */ + bool wasReReferenced() const; + }; + + /** + * Saturation percentage at which an entry starts being inserted as + * intermediate re-reference. + */ + const double insertionThreshold; + + /** + * Signature History Counter Table; learns the re-reference behavior + * of a signature. A zero entry provides a strong indication that + * future lines brought by that signature will not receive any hits. + */ + std::vector SHCT; + + /** + * Extract signature from packet. + * + * @param pkt The packet to extract a signature from. + * @return The signature extracted. + */ + virtual SignatureType getSignature(const PacketPtr pkt) const = 0; + + public: + typedef SHiPRPParams Params; + SHiP(const Params &p); + ~SHiP() = default; + + /** + * Invalidate replacement data to set it as the next probable victim. + * Updates predictor and invalidate data. + * + * @param replacement_data Replacement data to be invalidated. + */ + void invalidate(const std::shared_ptr& replacement_data) + override; + + /** + * Touch an entry to update its replacement data. + * Updates predictor and assigns RRPV values of Table 3. + * + * @param replacement_data Replacement data to be touched. + * @param pkt Packet that generated this hit. + */ + void touch(const std::shared_ptr& replacement_data, + const PacketPtr pkt) override; + void touch(const std::shared_ptr& replacement_data) const + override; + + /** + * Reset replacement data. Used when an entry is inserted. + * Updates predictor and assigns RRPV values of Table 3. + * + * @param replacement_data Replacement data to be reset. + * @param pkt Packet that generated this miss. + */ + void reset(const std::shared_ptr& replacement_data, + const PacketPtr pkt) override; + void reset(const std::shared_ptr& replacement_data) const + override; + + /** + * Instantiate a replacement data entry. + * + * @return A shared pointer to the new replacement data. + */ + std::shared_ptr instantiateEntry() override; +}; + +/** SHiP that Uses memory addresses as signatures. */ +class SHiPMem : public SHiP +{ + protected: + SignatureType getSignature(const PacketPtr pkt) const override; + + public: + SHiPMem(const SHiPMemRPParams &p); + ~SHiPMem() = default; +}; + +/** SHiP that Uses PCs as signatures. */ +class SHiPPC : public SHiP +{ + private: + /** Signature to be used when no PC is provided in an access. */ + const SignatureType NO_PC_SIGNATURE = 0; + + protected: + SignatureType getSignature(const PacketPtr pkt) const override; + + public: + SHiPPC(const SHiPPCRPParams &p); + ~SHiPPC() = default; +}; + +} // namespace replacement_policy + +#endif // __MEM_CACHE_REPLACEMENT_POLICIES_SHIP_RP_HH__