From fdd48036925fdbb30914bb81208268ddf5751733 Mon Sep 17 00:00:00 2001 From: Wei Song Date: Fri, 13 Sep 2024 15:00:28 +0800 Subject: [PATCH 1/3] support prefetch in hook_read() --- cache/cache.hpp | 4 ++-- cache/coh_policy.hpp | 3 +++ cache/coherence.hpp | 4 ++-- cache/exclusive.hpp | 20 ++++++++++---------- cache/memory.hpp | 4 ++-- cache/mirage.hpp | 8 ++++---- util/monitor.hpp | 4 ++-- 7 files changed, 25 insertions(+), 22 deletions(-) diff --git a/cache/cache.hpp b/cache/cache.hpp index 7044305..5d98c01 100644 --- a/cache/cache.hpp +++ b/cache/cache.hpp @@ -316,8 +316,8 @@ class CacheSkewed : public CacheBase } } - virtual void hook_read(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, const CMMetadataBase * meta, const CMDataBase *data, uint64_t *delay) override { - if(ai < P) replacer[ai].access(s, w, true, false); + virtual void hook_read(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, bool prefetch, const CMMetadataBase * meta, const CMDataBase *data, uint64_t *delay) override { + if(ai < P) replacer[ai].access(s, w, true, prefetch); if constexpr (EnMon || !C_VOID) monitors->hook_read(addr, ai, s, w, hit, meta, data, delay); } diff --git a/cache/coh_policy.hpp b/cache/coh_policy.hpp index 9642050..a441110 100644 --- a/cache/coh_policy.hpp +++ b/cache/coh_policy.hpp @@ -30,6 +30,7 @@ namespace coh { const uint32_t evict_act = 2; const uint32_t writeback_act = 3; const uint32_t downgrade_act = 4; + const uint32_t prefetch_act = 5; // message type constexpr inline bool is_acquire(coh_cmd_t cmd) { return cmd.msg == acquire_msg; } @@ -45,10 +46,12 @@ namespace coh { constexpr inline bool is_writeback(coh_cmd_t cmd) { return cmd.act == writeback_act; } constexpr inline bool is_downgrade(coh_cmd_t cmd) { return cmd.act == downgrade_act; } constexpr inline bool is_write(coh_cmd_t cmd) { return cmd.act == fetch_write_act || cmd.act == evict_act || cmd.act == writeback_act; } + constexpr inline bool is_prefetch(coh_cmd_t cmd) { return cmd.act == prefetch_act; } // generate command constexpr inline coh_cmd_t cmd_for_read() { return {-1, acquire_msg, fetch_read_act }; } constexpr inline coh_cmd_t cmd_for_write() { return {-1, acquire_msg, fetch_write_act}; } + constexpr inline coh_cmd_t cmd_for_prefetch() { return {-1, acquire_msg, prefetch_act }; } constexpr inline coh_cmd_t cmd_for_flush() { return {-1, flush_msg, evict_act }; } constexpr inline coh_cmd_t cmd_for_writeback() { return {-1, flush_msg, writeback_act }; } constexpr inline coh_cmd_t cmd_for_release() { return {-1, release_msg, evict_act }; } diff --git a/cache/coherence.hpp b/cache/coherence.hpp index 39fc8c1..b8dc90d 100644 --- a/cache/coherence.hpp +++ b/cache/coherence.hpp @@ -221,7 +221,7 @@ class InnerCohPortUncached : public InnerCohPortBase if (data_inner && data) data_inner->copy(data); Policy::meta_after_grant(cmd, meta, meta_inner); - cache->hook_read(addr, ai, s, w, hit, meta, data, delay); + cache->hook_read(addr, ai, s, w, hit, coh::is_prefetch(cmd), meta, data, delay); finish_record(addr, coh::cmd_for_finish(cmd.id), !hit, meta, ai, s); if(cmd.id == -1) finish_resp(addr, coh::cmd_for_finish(cmd.id)); } @@ -447,7 +447,7 @@ class CoreInterface : public InnerCohPortUncached, public CoreInte addr = normalize(addr); auto cmd = coh::cmd_for_read(); auto [meta, data, ai, s, w, hit] = this->access_line(addr, cmd, XactPrio::acquire, delay); - cache->hook_read(addr, ai, s, w, hit, meta, data, delay); + cache->hook_read(addr, ai, s, w, hit, false, meta, data, delay); if constexpr (EnMT) { meta->unlock(); cache->reset_mt_state(ai, s, XactPrio::acquire);} if(!hit) outer->finish_req(addr); #ifdef CHECK_MULTI diff --git a/cache/exclusive.hpp b/cache/exclusive.hpp index 94d9399..0b3c9b4 100644 --- a/cache/exclusive.hpp +++ b/cache/exclusive.hpp @@ -131,10 +131,10 @@ class CacheSkewedExclusive : public CacheSkewed= NW) ext_replacer[ai].access(s, w-NW, true, false); - else replacer[ai].access(s, w, true, false); + if(w >= NW) ext_replacer[ai].access(s, w-NW, true, prefetch); + else replacer[ai].access(s, w, true, prefetch); if constexpr (EnMon || !C_VOID) monitors->hook_read(addr, ai, s, w, hit, meta, data, delay); } else { if constexpr (EnMon || !C_VOID) monitors->hook_read(addr, -1, -1, -1, hit, meta, data, delay); @@ -187,7 +187,7 @@ class ExclusiveInnerCohPortUncachedBroadcast : public InnerCohPortUncachedcopy(data); Policy::meta_after_grant(cmd, meta, meta_inner); - cache->hook_read(addr, ai, s, w, hit, meta, data, delay); + cache->hook_read(addr, ai, s, w, hit, coh::is_prefetch(cmd), meta, data, delay); cache->meta_return_buffer(meta); cache->data_return_buffer(data); @@ -355,18 +355,18 @@ class ExclusiveInnerCohPortUncachedDirectory : public InnerCohPortUncachedcopy(data); - Policy::meta_after_grant(outer_cmd, meta, meta_inner); - cache->hook_read(addr, ai, s, w, hit, meta, data, delay); + Policy::meta_after_grant(cmd, meta, meta_inner); + cache->hook_read(addr, ai, s, w, hit, coh::is_prefetch(cmd), meta, data, delay); // difficult to know when data is borrowed from buffer, just return it. cache->data_return_buffer(data); - this->finish_record(addr, coh::cmd_for_finish(outer_cmd.id), !hit, meta, ai, s); - if(outer_cmd.id == -1) this->finish_resp(addr, coh::cmd_for_finish(outer_cmd.id)); + this->finish_record(addr, coh::cmd_for_finish(cmd.id), !hit, meta, ai, s); + if(cmd.id == -1) this->finish_resp(addr, coh::cmd_for_finish(cmd.id)); } protected: diff --git a/cache/memory.hpp b/cache/memory.hpp index a6be9de..c15c0d4 100644 --- a/cache/memory.hpp +++ b/cache/memory.hpp @@ -101,7 +101,7 @@ class SimpleMemoryModel : public InnerCohPortUncached, publ data_inner->write(mem_addr); } if(meta_inner) meta_inner->to_modified(-1); - hook_read(addr, 0, 0, 0, true, meta_inner, data_inner, delay); + hook_read(addr, 0, 0, 0, true, false, meta_inner, data_inner, delay); #ifdef CHECK_MULTI if constexpr (EnMT) active_addr_remove(addr); #endif @@ -130,7 +130,7 @@ class SimpleMemoryModel : public InnerCohPortUncached, publ // support run-time assign/reassign mointors void detach_monitor() { monitors->detach_monitor(); } - virtual void hook_read(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, const CMMetadataBase *meta, const CMDataBase *data, uint64_t *delay) override { + virtual void hook_read(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, bool prefetch, const CMMetadataBase *meta, const CMDataBase *data, uint64_t *delay) override { if constexpr (EnMon || !C_VOID) monitors->hook_read(addr, -1, -1, -1, hit, meta, data, delay); } diff --git a/cache/mirage.hpp b/cache/mirage.hpp index 96f7642..a84bf9b 100644 --- a/cache/mirage.hpp +++ b/cache/mirage.hpp @@ -156,12 +156,12 @@ class MirageCache : public CacheSkewed(this->access(ai, s, w))->pointer(); - d_replacer.access(ds, dw, true, false); + d_replacer.access(ds, dw, true, prefetch); } - CacheT::hook_read(addr, ai, s, w, hit, meta, data, delay); + CacheT::hook_read(addr, ai, s, w, hit, prefetch, meta, data, delay); } virtual void hook_write(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, bool demand_acc, const CMMetadataBase * meta, const CMDataBase *data, uint64_t *delay) override { @@ -206,7 +206,7 @@ class MirageCache : public CacheSkewedrelocate(m_ai, m_s, m_w, *ai, *s, *w); get_data_meta(static_cast(meta))->bind(*ai, *s, *w); CacheT::hook_manage(addr, m_ai, m_s, m_w, true, true, false, nullptr, nullptr, delay); - CacheT::hook_read(addr, *ai, *s, *w, false, nullptr, nullptr, delay); // read or write? // hit is true or false? may have impact on delay + CacheT::hook_read(addr, *ai, *s, *w, false, false, nullptr, nullptr, delay); // read or write? // hit is true or false? may have impact on delay std::tie(*ai, *s, *w) = std::make_tuple(m_ai, m_s, m_w); } } diff --git a/util/monitor.hpp b/util/monitor.hpp index 4da53eb..37b0e69 100644 --- a/util/monitor.hpp +++ b/util/monitor.hpp @@ -65,8 +65,8 @@ class CacheMonitorSupport MonitorContainerBase *monitors; // monitor container // hook interface for replacer state update, Monitor and delay estimation - virtual void hook_read(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, const CMMetadataBase *meta, const CMDataBase *data, uint64_t *delay) = 0; - virtual void hook_write(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, bool is_release, const CMMetadataBase *meta, const CMDataBase *data, uint64_t *delay) = 0; + virtual void hook_read(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, bool prefetch, const CMMetadataBase *meta, const CMDataBase *data, uint64_t *delay) = 0; + virtual void hook_write(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, bool demand_acc, const CMMetadataBase *meta, const CMDataBase *data, uint64_t *delay) = 0; // probe, invalidate and writeback virtual void hook_manage(uint64_t addr, uint32_t ai, uint32_t s, uint32_t w, bool hit, bool evict, bool writeback, const CMMetadataBase *meta, const CMDataBase *data, uint64_t *delay) = 0; // an interface for special communication with a specific monitor if attached From a7db14eebbc735443f515b40f66193a986cdfb86 Mon Sep 17 00:00:00 2001 From: Wei Song Date: Fri, 13 Sep 2024 15:03:52 +0800 Subject: [PATCH 2/3] simplify flush_line() --- cache/coherence.hpp | 87 +++++++++++++++++---------------------- cache/exclusive.hpp | 99 +++++++++++++++++++-------------------------- cache/mi.hpp | 14 +++---- cache/msi.hpp | 19 ++++----- 4 files changed, 90 insertions(+), 129 deletions(-) diff --git a/cache/coherence.hpp b/cache/coherence.hpp index b8dc90d..9ab6df5 100644 --- a/cache/coherence.hpp +++ b/cache/coherence.hpp @@ -254,24 +254,26 @@ class InnerCohPortUncached : public InnerCohPortBase cache->hook_manage(addr, ai, s, w, true, true, writeback.first, meta, data, delay); } - virtual std::tuple - access_line(uint64_t addr, coh_cmd_t cmd, uint16_t prio, uint64_t *delay) { // common function for access a line in the cache + virtual std::tuple + check_hit_or_replace(uint64_t addr, uint16_t prio, bool do_replace, bool prefetch, uint64_t *delay) { // check hit or get a replacement target uint32_t ai, s, w; - CMMetadataBase *meta; - CMDataBase *data; + CMMetadataBase *meta = nullptr; + CMDataBase *data = nullptr; bool hit; - if constexpr (EnMT) { while(true) { - hit = cache->hit(addr, &ai, &s, &w, prio, true); + hit = cache->hit(addr, &ai, &s, &w, prio, !prefetch); if(hit) { - std::tie(meta, data) = cache->access_line(ai, s, w); meta->lock(); - if(!cache->check_mt_state(ai, s, prio) || !meta->match(addr)) { // hitted acquire is intercepted by a probe and even invalidated - meta->unlock(); meta = nullptr; data = nullptr; - cache->reset_mt_state(ai, s, prio); - continue; // redo the hit check + std::tie(meta, data) = cache->access_line(ai, s, w); + if(!prefetch) { // no need to lock for prefetch + meta->lock(); + if(!cache->check_mt_state(ai, s, prio) || !meta->match(addr)) { // acquire is intercepted by a probe and even invalidated + meta->unlock(); meta = nullptr; data = nullptr; + cache->reset_mt_state(ai, s, prio); + continue; // redo the hit check + } } - } else { // miss + } else if(do_replace) { // miss if(cache->replace(addr, &ai, &s, &w, prio)) { // lock the cache set and get a replacement candidate std::tie(meta, data) = cache->access_line(ai, s, w); meta->lock(); @@ -287,9 +289,15 @@ class InnerCohPortUncached : public InnerCohPortBase } } else { hit = cache->hit(addr, &ai, &s, &w); - if(!hit) cache->replace(addr, &ai, &s, &w, prio); - std::tie(meta, data) = cache->access_line(ai, s, w); + if(!hit && do_replace) cache->replace(addr, &ai, &s, &w, prio); + if(hit || do_replace) std::tie(meta, data) = cache->access_line(ai, s, w); } + return std::make_tuple(hit, meta, data, ai, s, w); + } + + virtual std::tuple + access_line(uint64_t addr, coh_cmd_t cmd, uint16_t prio, uint64_t *delay) { // common function for access a line in the cache + auto [hit, meta, data, ai, s, w] = check_hit_or_replace(addr, prio, true, false, delay); if(hit) { auto sync = Policy::access_need_sync(cmd, meta); @@ -318,49 +326,26 @@ class InnerCohPortUncached : public InnerCohPortBase } virtual void flush_line(uint64_t addr, coh_cmd_t cmd, uint64_t *delay) { - uint32_t ai, s, w; - CMMetadataBase *meta = nullptr; - CMDataBase *data = nullptr; - bool hit; + if constexpr (!Policy::is_uncached()) + outer->writeback_req(addr, nullptr, nullptr, coh::cmd_for_flush(), delay); + else { + auto [hit, meta, data, ai, s, w] = check_hit_or_replace(addr, XactPrio::flush, false, false, delay); + auto [probe, probe_cmd] = Policy::flush_need_sync(cmd, meta); + if(!hit) return; - if constexpr (EnMT) { - while(true) { - hit = cache->hit(addr, &ai, &s, &w, XactPrio::flush, true); - if(hit) { - std::tie(meta, data) = cache->access_line(ai, s, w); meta->lock(); - if(!meta->match(addr)) { // cache line is invalidated by transactions with higher priority - meta->unlock(); meta = nullptr; data = nullptr; - cache->reset_mt_state(ai, s, XactPrio::flush); continue; // redo the hit check - } - } - break; + if(probe) { + auto [phit, pwb] = probe_req(addr, meta, data, probe_cmd, delay); // sync if necessary + if(pwb) cache->hook_write(addr, ai, s, w, true, false, meta, data, delay); // a write occurred during the probe } - } else { - hit = cache->hit(addr, &ai, &s, &w); - if(hit) std::tie(meta, data) = cache->access_line(ai, s, w); - } - auto [flush, probe, probe_cmd] = Policy::flush_need_sync(cmd, meta); - if(!flush) { - // do not handle flush at this level, and send it to the outer cache - outer->writeback_req(addr, nullptr, nullptr, coh::cmd_for_flush(), delay); - return; - } + auto writeback = Policy::writeback_need_writeback(meta); + if(writeback.first) outer->writeback_req(addr, meta, data, writeback.second, delay); // writeback if dirty - if(!hit) return; + Policy::meta_after_flush(cmd, meta, cache); + cache->hook_manage(addr, ai, s, w, hit, coh::is_evict(cmd), writeback.first, meta, data, delay); - if(probe) { - auto [phit, pwb] = probe_req(addr, meta, data, probe_cmd, delay); // sync if necessary - if(pwb) cache->hook_write(addr, ai, s, w, true, false, meta, data, delay); // a write occurred during the probe + if constexpr (EnMT) { meta->unlock(); cache->reset_mt_state(ai, s, XactPrio::flush); } } - - auto writeback = Policy::writeback_need_writeback(meta); - if(writeback.first) outer->writeback_req(addr, meta, data, writeback.second, delay); // writeback if dirty - - Policy::meta_after_flush(cmd, meta, cache); - cache->hook_manage(addr, ai, s, w, hit, coh::is_evict(cmd), writeback.first, meta, data, delay); - - if constexpr (EnMT) { meta->unlock(); cache->reset_mt_state(ai, s, XactPrio::flush); } } }; diff --git a/cache/exclusive.hpp b/cache/exclusive.hpp index 0b3c9b4..eb132b7 100644 --- a/cache/exclusive.hpp +++ b/cache/exclusive.hpp @@ -56,15 +56,11 @@ struct ExclusiveMSIPolicy : public MSIPolicy // alway return std::make_pair(true, coh::cmd_for_release()); } - static __always_inline std::tuple flush_need_sync(coh_cmd_t cmd, const CMMetadataBase *meta) { - if constexpr (uncached) { - if(coh::is_evict(cmd)) return std::make_tuple(true, true, coh::cmd_for_probe_release()); - else if(meta && meta->is_shared()) - return std::make_tuple(true, false, coh::cmd_for_null()); - else - return std::make_tuple(true, true, coh::cmd_for_probe_writeback()); - } else - return std::make_tuple(false, false, coh::cmd_for_null()); + static __always_inline std::pair flush_need_sync(coh_cmd_t cmd, const CMMetadataBase *meta) { + assert(uncached); + if(coh::is_evict(cmd)) return std::make_pair(true, coh::cmd_for_probe_release()); + else if(meta && meta->is_shared()) return std::make_pair(false, coh::cmd_for_null()); + else return std::make_pair(true, coh::cmd_for_probe_writeback()); } }; @@ -297,38 +293,32 @@ class ExclusiveInnerCohPortUncachedBroadcast : public InnerCohPortUncachedhit(addr, &ai, &s, &w, XactPrio::flush, false); // ToDo, here may be buggy do to concurrency - if(hit) std::tie(meta, data) = cache->access_line(ai, s, w); - - auto [flush, probe, probe_cmd] = Policy::flush_need_sync(cmd, meta); - if(!flush) { - // do not handle flush at this level, and send it to the outer cache + if constexpr (!Policy::is_uncached()) { outer->writeback_req(addr, nullptr, nullptr, coh::cmd_for_flush(), delay); - return; - } + } else { + auto [hit, meta, data, ai, s, w] = this->check_hit_or_replace(addr, XactPrio::flush, false, false, delay); + auto [probe, probe_cmd] = Policy::flush_need_sync(cmd, meta); - if(!hit) { - meta = cache->meta_copy_buffer(); meta->init(addr); meta->get_outer_meta()->to_invalid(); - data = cache->data_copy_buffer(); - } + if(!hit) { + meta = cache->meta_copy_buffer(); meta->init(addr); meta->get_outer_meta()->to_invalid(); + data = cache->data_copy_buffer(); + } - if(probe) { - auto [phit, pwb] = this->probe_req(addr, meta, data, probe_cmd, delay); // sync if necessary - if(pwb) cache->hook_write(addr, ai, s, w, true, false, meta, data, delay); // a write occurred during the probe - } + if(probe) { + auto [phit, pwb] = this->probe_req(addr, meta, data, probe_cmd, delay); // sync if necessary + if(pwb) cache->hook_write(addr, ai, s, w, true, false, meta, data, delay); // a write occurred during the probe + } - auto writeback = Policy::writeback_need_writeback(meta); - if(writeback.first) outer->writeback_req(addr, meta, data, writeback.second, delay); // writeback if dirty + auto writeback = Policy::writeback_need_writeback(meta); + if(writeback.first) outer->writeback_req(addr, meta, data, writeback.second, delay); // writeback if dirty - Policy::meta_after_flush(cmd, meta, cache); - cache->hook_manage(addr, ai, s, w, hit, coh::is_evict(cmd), writeback.first, meta, data, delay); + Policy::meta_after_flush(cmd, meta, cache); + cache->hook_manage(addr, ai, s, w, hit, coh::is_evict(cmd), writeback.first, meta, data, delay); - if(!hit) { - cache->meta_return_buffer(meta); - cache->data_return_buffer(data); + if(!hit) { + cache->meta_return_buffer(meta); + cache->data_return_buffer(data); + } } } @@ -487,35 +477,28 @@ class ExclusiveInnerCohPortUncachedDirectory : public InnerCohPortUncachedhit(addr, &ai, &s, &w, XactPrio::flush, true); - if(hit) std::tie(meta, data) = cache->access_line(ai, s, w); - - auto [flush, probe, probe_cmd] = Policy::flush_need_sync(cmd, meta); - if(!flush) { - // do not handle flush at this level, and send it to the outer cache + if constexpr (!Policy::is_uncached()) { outer->writeback_req(addr, nullptr, nullptr, coh::cmd_for_flush(), delay); - return; - } - - if(!hit) return; + } else { + auto [hit, meta, data, ai, s, w] = this->check_hit_or_replace(addr, XactPrio::flush, false, false, delay); + auto [probe, probe_cmd] = Policy::flush_need_sync(cmd, meta); + if(!hit) return; - if(meta->is_extend()) data = cache->data_copy_buffer(); + if(meta->is_extend()) data = cache->data_copy_buffer(); - if(probe) { - auto [phit, pwb] = this->probe_req(addr, meta, data, probe_cmd, delay); // sync if necessary - if(pwb) cache->hook_write(addr, ai, s, w, true, false, meta, data, delay); // a write occurred during the probe - } + if(probe) { + auto [phit, pwb] = this->probe_req(addr, meta, data, probe_cmd, delay); // sync if necessary + if(pwb) cache->hook_write(addr, ai, s, w, true, false, meta, data, delay); // a write occurred during the probe + } - auto writeback = Policy::writeback_need_writeback(meta); - if(writeback.first) outer->writeback_req(addr, meta, data, writeback.second, delay); // writeback if dirty + auto writeback = Policy::writeback_need_writeback(meta); + if(writeback.first) outer->writeback_req(addr, meta, data, writeback.second, delay); // writeback if dirty - Policy::meta_after_flush(cmd, meta, cache); - cache->hook_manage(addr, ai, s, w, hit, coh::is_evict(cmd), writeback.first, meta, data, delay); + Policy::meta_after_flush(cmd, meta, cache); + cache->hook_manage(addr, ai, s, w, hit, coh::is_evict(cmd), writeback.first, meta, data, delay); - if(meta->is_extend()) cache->data_return_buffer(data); + if(meta->is_extend()) cache->data_return_buffer(data); + } } }; diff --git a/cache/mi.hpp b/cache/mi.hpp index 01dbc0b..910102d 100644 --- a/cache/mi.hpp +++ b/cache/mi.hpp @@ -70,14 +70,12 @@ struct MIPolicy : public CohPolicyBase } } - static __always_inline std::tuple flush_need_sync(coh_cmd_t cmd, const CMMetadataBase *meta) { - if constexpr (uncached) { - if(meta){ - if(coh::is_evict(cmd)) return std::make_tuple(true, true, coh::cmd_for_probe_release()); - else return std::make_tuple(true, true, coh::cmd_for_probe_writeback()); - } else return std::make_tuple(true, false, coh::cmd_for_null()); - } else - return std::make_tuple(false, false, coh::cmd_for_null()); + static __always_inline std::pair flush_need_sync(coh_cmd_t cmd, const CMMetadataBase *meta) { + assert(uncached); + if(meta){ + if(coh::is_evict(cmd)) return std::make_pair(true, coh::cmd_for_probe_release()); + else return std::make_pair(true, coh::cmd_for_probe_writeback()); + } else return std::make_pair(false, coh::cmd_for_null()); } }; diff --git a/cache/msi.hpp b/cache/msi.hpp index 0494dce..5e62a5d 100644 --- a/cache/msi.hpp +++ b/cache/msi.hpp @@ -93,18 +93,13 @@ struct MSIPolicy : public MIPolicy } } - static __always_inline std::tuple flush_need_sync(coh_cmd_t cmd, const CMMetadataBase *meta) { - if constexpr (uncached) { - if(meta) { - if(coh::is_evict(cmd)) return std::make_tuple(true, true, coh::cmd_for_probe_release()); - else if(meta->is_shared()) - return std::make_tuple(true, false, coh::cmd_for_null()); - else - return std::make_tuple(true, true, coh::cmd_for_probe_writeback()); - } else - return std::make_tuple(true, false, coh::cmd_for_null()); - } else - return std::make_tuple(false, false, coh::cmd_for_null()); + static __always_inline std::pair flush_need_sync(coh_cmd_t cmd, const CMMetadataBase *meta) { + assert(uncached); + if(meta) { + if(coh::is_evict(cmd)) return std::make_pair(true, coh::cmd_for_probe_release()); + else if(meta->is_shared()) return std::make_pair(false, coh::cmd_for_null()); + else return std::make_pair(true, coh::cmd_for_probe_writeback()); + } else return std::make_pair(false, coh::cmd_for_null()); } }; From e2dbc1289eabf52ec75da5aa65046b5cc00d3a26 Mon Sep 17 00:00:00 2001 From: Wei Song Date: Fri, 13 Sep 2024 15:05:10 +0800 Subject: [PATCH 3/3] add the prefetch api to core interface --- cache/coherence.hpp | 35 +++++++++++++++++++++++++++++++++-- cache/msi.hpp | 2 +- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/cache/coherence.hpp b/cache/coherence.hpp index 9ab6df5..00c7437 100644 --- a/cache/coherence.hpp +++ b/cache/coherence.hpp @@ -47,6 +47,7 @@ class OuterCohPortBase virtual void acquire_req(uint64_t addr, CMMetadataBase *meta, CMDataBase *data, coh_cmd_t cmd, uint64_t *delay) = 0; virtual void writeback_req(uint64_t addr, CMMetadataBase *meta, CMDataBase *data, coh_cmd_t cmd, uint64_t *delay) = 0; + virtual void prefetch_req(uint64_t addr, coh_cmd_t cmd, uint64_t *delay) = 0; // may not implement probe_resp() and finish_req() if the port is uncached virtual std::pair probe_resp(uint64_t addr, CMMetadataBase *meta, CMDataBase *data, coh_cmd_t cmd, uint64_t *delay) { return std::make_pair(false,false); } @@ -77,6 +78,7 @@ class InnerCohPortBase virtual void acquire_resp(uint64_t addr, CMDataBase *data_inner, CMMetadataBase *meta_inner, coh_cmd_t outer_cmd, uint64_t *delay) = 0; virtual void writeback_resp(uint64_t addr, CMDataBase *data_inner, CMMetadataBase *meta_inner, coh_cmd_t outer_cmd, uint64_t *delay) = 0; + virtual void prefetch_resp(uint64_t addr, coh_cmd_t outer_cmd, uint64_t *delay) = 0; // may not implement probe_req() and finish_resp() if the port is uncached virtual std::pair probe_req(uint64_t addr, CMMetadataBase *meta, CMDataBase *data, coh_cmd_t cmd, uint64_t *delay) { return std::make_pair(false,false); } @@ -142,6 +144,11 @@ class OuterCohPortUncached : public OuterCohPortBase Policy::meta_after_writeback(outer_cmd, meta); } + virtual void prefetch_req(uint64_t addr, coh_cmd_t outer_cmd, uint64_t *delay) override { + outer_cmd.id = coh_id; + coh->prefetch_resp(addr, outer_cmd, delay); + } + virtual void query_loc_req(uint64_t addr, std::list *locs) override { coh->query_loc_resp(addr, locs); } @@ -233,6 +240,10 @@ class InnerCohPortUncached : public InnerCohPortBase write_line(addr, data_inner, meta_inner, cmd, delay); } + virtual void prefetch_resp(uint64_t addr, coh_cmd_t cmd, uint64_t *delay) override { + prefetch_line(addr, cmd, delay); + } + virtual void query_loc_resp(uint64_t addr, std::list *locs) override { outer->query_loc_req(addr, locs); locs->push_front(cache->query_loc(addr)); @@ -348,6 +359,20 @@ class InnerCohPortUncached : public InnerCohPortBase } } + virtual void prefetch_line(uint64_t addr, coh_cmd_t cmd, uint64_t *delay) { + if constexpr (!Policy::is_uncached()) + outer->prefetch_req(addr, coh::cmd_for_prefetch(), delay); + else { + auto [hit, meta, data, ai, s, w] = check_hit_or_replace(addr, XactPrio::acquire, true, true, delay); + if(!hit) { + if(meta->is_valid()) evict(meta, data, ai, s, w, delay); + outer->acquire_req(addr, meta, data, coh::cmd_for_prefetch(), delay); // fetch the missing block + cache->hook_read(addr, ai, s, w, hit, true, meta, data, delay); + finish_record(addr, coh::cmd_for_finish(-1), !hit, meta, ai, s); + finish_resp(addr, coh::cmd_for_finish(-1)); + } + } + } }; template