diff --git a/clients/drcachesim/simulator/snoop_filter.cpp b/clients/drcachesim/simulator/snoop_filter.cpp index 27db152bac3..c56f099aa22 100644 --- a/clients/drcachesim/simulator/snoop_filter.cpp +++ b/clients/drcachesim/simulator/snoop_filter.cpp @@ -74,14 +74,8 @@ void snoop_filter_t::snoop(addr_t tag, int id, bool is_write) { coherence_table_entry_t *coherence_entry = &coherence_table_[tag]; - // Initialize new snoop filter entry. - if (coherence_entry->sharers.empty()) { - coherence_entry->sharers.resize(num_snooped_caches_, false); - coherence_entry->dirty = false; - } - auto num_sharers = std::count(coherence_entry->sharers.begin(), - coherence_entry->sharers.end(), true); + size_t num_sharers = coherence_entry->sharers.size(); // Check that cache id is valid. assert(id >= 0 && id < num_snooped_caches_); @@ -91,7 +85,8 @@ snoop_filter_t::snoop(addr_t tag, int id, bool is_write) assert(!coherence_entry->dirty || num_sharers == 1); // Check if this request causes a writeback. - if (!coherence_entry->sharers[id] && coherence_entry->dirty) { + if (coherence_entry->sharers.find(id) == coherence_entry->sharers.end() && + coherence_entry->dirty) { num_writebacks_++; coherence_entry->dirty = false; } @@ -101,16 +96,18 @@ snoop_filter_t::snoop(addr_t tag, int id, bool is_write) coherence_entry->dirty = true; if (num_sharers > 0) { // Writes will invalidate other caches_. - for (int i = 0; i < num_snooped_caches_; i++) { - if (coherence_entry->sharers[i] && id != i) { - caches_[i]->invalidate(tag, INVALIDATION_COHERENCE); - num_invalidates_++; - coherence_entry->sharers[i] = false; - } + auto it = coherence_entry->sharers.begin(); + while (it != coherence_entry->sharers.end()) { + int i = *it++; + if (i == id) + continue; + caches_[i]->invalidate(tag, INVALIDATION_COHERENCE); + num_invalidates_++; + coherence_entry->sharers.erase(i); } } } - coherence_entry->sharers[id] = true; + coherence_entry->sharers.insert(id); } /* This function is called whenever a coherent cache evicts a line. */ @@ -120,20 +117,23 @@ snoop_filter_t::snoop_eviction(addr_t tag, int id) coherence_table_entry_t *coherence_entry = &coherence_table_[tag]; // Check if sharer list is initialized. - assert(coherence_entry->sharers.size() == (uint64_t)num_snooped_caches_); + assert(!coherence_entry->sharers.empty()); // Check that cache id is valid. assert(id >= 0 && id < num_snooped_caches_); // Check that tag is valid. assert(tag != TAG_INVALID); // Check that we currently have this cache marked as a sharer. - assert(coherence_entry->sharers[id]); + assert(coherence_entry->sharers.find(id) != coherence_entry->sharers.end()); if (coherence_entry->dirty) { num_writebacks_++; coherence_entry->dirty = false; } - coherence_entry->sharers[id] = false; + coherence_entry->sharers.erase(id); + if (coherence_entry->sharers.empty()) { + coherence_table_.erase(tag); + } } void diff --git a/clients/drcachesim/simulator/snoop_filter.h b/clients/drcachesim/simulator/snoop_filter.h index c4f6c63d069..709b4d891ad 100644 --- a/clients/drcachesim/simulator/snoop_filter.h +++ b/clients/drcachesim/simulator/snoop_filter.h @@ -36,6 +36,7 @@ #include #include +#include #include #include "cache.h" @@ -45,8 +46,8 @@ namespace dynamorio { namespace drmemtrace { struct coherence_table_entry_t { - std::vector sharers; - bool dirty; + std::unordered_set sharers; // IDs of caches sharing this line. + bool dirty = false; }; class snoop_filter_t {