diff --git a/cache/coh_policy.hpp b/cache/coh_policy.hpp index e29ee1f..22a7ce1 100644 --- a/cache/coh_policy.hpp +++ b/cache/coh_policy.hpp @@ -30,6 +30,7 @@ class CohPolicyBase { static const uint32_t release_msg = 2; static const uint32_t probe_msg = 3; static const uint32_t flush_msg = 4; + static const uint32_t finish_msg = 5; static const uint32_t fetch_read_act = 0; static const uint32_t fetch_write_act = 1; static const uint32_t evict_act = 2; @@ -48,6 +49,7 @@ class CohPolicyBase { bool is_release(coh_cmd_t cmd) const { return cmd.msg == release_msg; } bool is_probe(coh_cmd_t cmd) const { return cmd.msg == probe_msg; } bool is_flush(coh_cmd_t cmd) const { return cmd.msg == flush_msg; } + bool is_finish(coh_cmd_t cmd) const { return cmd.msg == finish_msg; } // action type bool is_fetch_read(coh_cmd_t cmd) const { return cmd.act == fetch_read_act; } @@ -73,6 +75,7 @@ class CohPolicyBase { coh_cmd_t cmd_for_probe_writeback(int32_t id) const { return {id, probe_msg, writeback_act }; } coh_cmd_t cmd_for_probe_release(int32_t id) const { return {id, probe_msg, evict_act }; } coh_cmd_t cmd_for_probe_downgrade(int32_t id) const { return {id, probe_msg, downgrade_act }; } + coh_cmd_t cmd_for_finish(int32_t id) const { return {id, finish_msg, 0 }; } virtual coh_cmd_t cmd_for_outer_acquire(coh_cmd_t cmd) const = 0; diff --git a/cache/coherence.hpp b/cache/coherence.hpp index 0803a31..0335279 100644 --- a/cache/coherence.hpp +++ b/cache/coherence.hpp @@ -39,7 +39,10 @@ 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 std::pair probe_resp(uint64_t addr, CMMetadataBase *meta, CMDataBase *data, coh_cmd_t cmd, uint64_t *delay) { return std::make_pair(false,false); } // may not implement if not supported + + // 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); } + virtual void finish_req(uint64_t addr) {} bool is_uncached() const { return coh_id == -1; } virtual void query_loc_req(uint64_t addr, std::list *locs) = 0; @@ -69,8 +72,12 @@ 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 cmd, uint64_t *delay) = 0; - 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); } // may not implement if not supported + virtual void writeback_resp(uint64_t addr, CMDataBase *data_inner, CMMetadataBase *meta_inner, 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); } + virtual void finish_record(uint64_t addr, coh_cmd_t outer_cmd) {}; + virtual void finish_resp(uint64_t addr, coh_cmd_t outer_cmd) {}; virtual void query_loc_resp(uint64_t addr, std::list *locs) = 0; @@ -102,8 +109,21 @@ class OuterCohPortUncached : public OuterCohPortBase } }; +// common behvior for cached outer ports +class OuterCohPortCachedBase : public OuterCohPortUncached +{ +public: + OuterCohPortCachedBase(policy_ptr policy) : OuterCohPortUncached(policy) {} + virtual ~OuterCohPortCachedBase() {} + + virtual void finish_req(uint64_t addr){ + assert(!is_uncached()); + coh->finish_resp(addr, policy->cmd_for_finish(coh_id)); + } +}; + // common behavior for cached outer ports -template requires C_DERIVE(OPUC, OuterCohPortUncached) +template requires C_DERIVE(OPUC, OuterCohPortCachedBase) class OuterCohPortT : public OPUC { protected: @@ -140,9 +160,10 @@ class OuterCohPortT : public OPUC cache->hook_manage(addr, ai, s, w, hit, OPUC::policy->is_outer_evict(outer_cmd), writeback, meta, data, delay); return std::make_pair(hit, writeback); } + }; -typedef OuterCohPortT OuterCohPort; +typedef OuterCohPortT OuterCohPort; class InnerCohPortUncached : public InnerCohPortBase { @@ -156,6 +177,8 @@ 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); + if(!hit) finish_record(addr, policy->cmd_for_finish(cmd.id)); + if(cmd.id == -1) finish_resp(addr, policy->cmd_for_finish(cmd.id)); } virtual void writeback_resp(uint64_t addr, CMDataBase *data_inner, CMMetadataBase *meta_inner, coh_cmd_t cmd, uint64_t *delay) { @@ -262,10 +285,16 @@ class InnerCohPortUncached : public InnerCohPortBase template requires C_DERIVE(IPUC, InnerCohPortUncached) class InnerCohPortT : public IPUC { +private: + // record the pending finish message from inner caches + // replace the single storage to a set in multi-thread sim + uint64_t addr_pending_finish; + int32_t id_pending_finish; protected: using IPUC::coh; + using IPUC::outer; public: - InnerCohPortT(policy_ptr policy) : IPUC(policy) {} + InnerCohPortT(policy_ptr policy) : IPUC(policy), addr_pending_finish(0) {} virtual ~InnerCohPortT() {} virtual std::pair probe_req(uint64_t addr, CMMetadataBase *meta, CMDataBase *data, coh_cmd_t cmd, uint64_t *delay) { @@ -280,6 +309,21 @@ class InnerCohPortT : public IPUC } return std::make_pair(hit, writeback); } + + // record pending finish + virtual void finish_record(uint64_t addr, coh_cmd_t outer_cmd) { + addr_pending_finish = addr; + id_pending_finish = outer_cmd.id; + } + + // only forward the finish message recorded by previous acquire + virtual void finish_resp(uint64_t addr, coh_cmd_t outer_cmd) { + assert(addr_pending_finish == 0 || (addr_pending_finish == addr && id_pending_finish == outer_cmd.id)); + if(addr_pending_finish == addr && id_pending_finish == outer_cmd.id) { + outer->finish_req(addr); + addr_pending_finish = 0; + } + } }; typedef InnerCohPortT InnerCohPort; @@ -317,6 +361,7 @@ class CoreInterface : public InnerCohPortUncached, public CoreInterfaceBase { auto cmd = policy->cmd_for_read(); auto [meta, data, ai, s, w, hit] = access_line(addr, cmd, delay); cache->hook_read(addr, ai, s, w, hit, meta, data, delay); + if(!hit) outer->finish_req(addr); return data; } @@ -327,6 +372,7 @@ class CoreInterface : public InnerCohPortUncached, public CoreInterfaceBase { meta->to_dirty(); if(data) data->copy(m_data); cache->hook_write(addr, ai, s, w, hit, false, meta, data, delay); + if(!hit) outer->finish_req(addr); } virtual void flush(uint64_t addr, uint64_t *delay) { addr = normalize(addr); flush_line(addr, policy->cmd_for_flush(), delay); } @@ -436,6 +482,9 @@ class SliceDispatcher : public CohMasterBase virtual void query_loc_resp(uint64_t addr, std::list *locs){ cohm[hasher(addr)]->query_loc_resp(addr, locs); } + virtual void finish_resp(uint64_t addr, coh_cmd_t cmd){ + cohm[hasher(addr)]->finish_resp(addr, cmd); + } }; #endif diff --git a/cache/exclusive.hpp b/cache/exclusive.hpp index 6a43e31..01b4e1a 100644 --- a/cache/exclusive.hpp +++ b/cache/exclusive.hpp @@ -203,6 +203,9 @@ class ExclusiveInnerCohPortUncachedBroadcast : public InnerCohPortUncached cache->meta_return_buffer(meta); cache->data_return_buffer(data); + + if(!hit) finish_record(addr, policy->cmd_for_finish(cmd.id)); + if(cmd.id == -1) finish_resp(addr, policy->cmd_for_finish(cmd.id)); } @@ -365,6 +368,9 @@ class ExclusiveInnerCohPortUncachedDirectory : public InnerCohPortUncached // difficult to know when data is borrowed from buffer, just return it. cache->data_return_buffer(data); + + if(!hit) finish_record(addr, policy->cmd_for_finish(outer_cmd.id)); + if(outer_cmd.id == -1) finish_resp(addr, policy->cmd_for_finish(outer_cmd.id)); } protected: @@ -516,7 +522,7 @@ class ExclusiveInnerCohPortUncachedDirectory : public InnerCohPortUncached typedef InnerCohPortT ExclusiveInnerCohPortDirectory; -template requires C_DERIVE(OPUC, OuterCohPortUncached) +template requires C_DERIVE(OPUC, OuterCohPortCachedBase) class ExclusiveOuterCohPortBroadcastT : public OPUC { protected: @@ -564,10 +570,10 @@ class ExclusiveOuterCohPortBroadcastT : public OPUC }; -typedef ExclusiveOuterCohPortBroadcastT ExclusiveOuterCohPortBroadcast; +typedef ExclusiveOuterCohPortBroadcastT ExclusiveOuterCohPortBroadcast; -template requires C_DERIVE(OPUC, OuterCohPortUncached) +template requires C_DERIVE(OPUC, OuterCohPortCachedBase) class ExclusiveOuterCohPortDirectoryT : public OPUC { protected: @@ -615,7 +621,7 @@ class ExclusiveOuterCohPortDirectoryT : public OPUC }; -typedef ExclusiveOuterCohPortDirectoryT ExclusiveOuterCohPortDirectory; +typedef ExclusiveOuterCohPortDirectoryT ExclusiveOuterCohPortDirectory; template using ExclusiveL2CacheBroadcast = CoherentCacheNorm;