summaryrefslogtreecommitdiff
path: root/src/mem/cache/prefetch/stride.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/cache/prefetch/stride.cc')
-rw-r--r--src/mem/cache/prefetch/stride.cc203
1 files changed, 116 insertions, 87 deletions
diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc
index d4a31f9da..3ff7acda0 100644
--- a/src/mem/cache/prefetch/stride.cc
+++ b/src/mem/cache/prefetch/stride.cc
@@ -46,133 +46,162 @@
* Stride Prefetcher template instantiations.
*/
-#include "base/trace.hh"
#include "debug/HWPrefetch.hh"
#include "mem/cache/prefetch/stride.hh"
+StridePrefetcher::StridePrefetcher(const StridePrefetcherParams *p)
+ : QueuedPrefetcher(p),
+ maxConf(p->max_conf),
+ threshConf(p->thresh_conf),
+ minConf(p->min_conf),
+ startConf(p->start_conf),
+ pcTableAssoc(p->table_assoc),
+ pcTableSets(p->table_sets),
+ useMasterId(p->use_master_id),
+ degree(p->degree)
+{
+ // Don't consult stride prefetcher on instruction accesses
+ onInst = false;
+
+ assert(isPowerOf2(pcTableSets));
+
+ for (int c = 0; c < maxContexts; c++) {
+ pcTable[c] = new StrideEntry*[pcTableSets];
+ for (int s = 0; s < pcTableSets; s++) {
+ pcTable[c][s] = new StrideEntry[pcTableAssoc];
+ }
+ }
+}
+
+StridePrefetcher::~StridePrefetcher()
+{
+ for (int c = 0; c < maxContexts; c++) {
+ for (int s = 0; s < pcTableSets; s++) {
+ delete[] pcTable[c][s];
+ }
+ }
+}
+
void
-StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
- std::list<Cycles> &delays)
+StridePrefetcher::calculatePrefetch(const PacketPtr &pkt,
+ std::vector<Addr> &addresses)
{
if (!pkt->req->hasPC()) {
- DPRINTF(HWPrefetch, "ignoring request with no PC");
+ DPRINTF(HWPrefetch, "Ignoring request with no PC.\n");
return;
}
- Addr data_addr = pkt->getAddr();
+ // Get required packet info
+ Addr pkt_addr = pkt->getAddr();
+ Addr pc = pkt->req->getPC();
bool is_secure = pkt->isSecure();
MasterID master_id = useMasterId ? pkt->req->masterId() : 0;
- Addr pc = pkt->req->getPC();
- assert(master_id < Max_Contexts);
- std::list<StrideEntry*> &tab = table[master_id];
- // Revert to simple N-block ahead prefetch for instruction fetches
- if (instTagged && pkt->req->isInstFetch()) {
- for (int d = 1; d <= degree; d++) {
- Addr new_addr = data_addr + d * blkSize;
- if (pageStop && !samePage(data_addr, new_addr)) {
- // Spanned the page, so now stop
- pfSpanPage += degree - d + 1;
- return;
- }
- DPRINTF(HWPrefetch, "queuing prefetch to %x @ %d\n",
- new_addr, latency);
- addresses.push_back(new_addr);
- delays.push_back(latency);
- }
- return;
- }
+ assert(master_id < maxContexts);
- /* Scan Table for instAddr Match */
- std::list<StrideEntry*>::iterator iter;
- for (iter = tab.begin(); iter != tab.end(); iter++) {
- // Entries have to match on the security state as well
- if ((*iter)->instAddr == pc && (*iter)->isSecure == is_secure)
- break;
- }
+ // Lookup pc-based information
+ StrideEntry *entry;
- if (iter != tab.end()) {
+ if(pcTableHit(pc, is_secure, master_id, entry)) {
// Hit in table
+ int new_stride = pkt_addr - entry->lastAddr;
+ bool stride_match = (new_stride == entry->stride);
- int new_stride = data_addr - (*iter)->missAddr;
- bool stride_match = (new_stride == (*iter)->stride);
-
+ // Adjust confidence for stride entry
if (stride_match && new_stride != 0) {
- (*iter)->tolerance = true;
- if ((*iter)->confidence < Max_Conf)
- (*iter)->confidence++;
+ if (entry->confidence < maxConf)
+ entry->confidence++;
} else {
- if (!((*iter)->tolerance)) {
- (*iter)->stride = new_stride;
- if ((*iter)->confidence > Min_Conf)
- (*iter)->confidence = 0;
- } else {
- (*iter)->tolerance = false;
- }
+ if (entry->confidence > minConf)
+ entry->confidence--;
+ // If confidence has dropped below the threshold, train new stride
+ if (entry->confidence < threshConf)
+ entry->stride = new_stride;
}
- DPRINTF(HWPrefetch, "hit: PC %x data_addr %x (%s) stride %d (%s), "
- "conf %d\n", pc, data_addr, is_secure ? "s" : "ns", new_stride,
+ DPRINTF(HWPrefetch, "Hit: PC %x pkt_addr %x (%s) stride %d (%s), "
+ "conf %d\n", pc, pkt_addr, is_secure ? "s" : "ns", new_stride,
stride_match ? "match" : "change",
- (*iter)->confidence);
+ entry->confidence);
- (*iter)->missAddr = data_addr;
- (*iter)->isSecure = is_secure;
+ entry->lastAddr = pkt_addr;
- if ((*iter)->confidence <= 0)
+ // Abort prefetch generation if below confidence threshold
+ if (entry->confidence < threshConf)
return;
+ // Generate up to degree prefetches
for (int d = 1; d <= degree; d++) {
- Addr new_addr = data_addr + d * (*iter)->stride;
- if (pageStop && !samePage(data_addr, new_addr)) {
- // Spanned the page, so now stop
+ // Round strides up to atleast 1 cacheline
+ int prefetch_stride = new_stride;
+ if (abs(new_stride) < blkSize) {
+ prefetch_stride = (new_stride < 0) ? -blkSize : blkSize;
+ }
+
+ Addr new_addr = pkt_addr + d * prefetch_stride;
+ if (samePage(pkt_addr, new_addr)) {
+ DPRINTF(HWPrefetch, "Queuing prefetch to %#x.\n", new_addr);
+ addresses.push_back(new_addr);
+ } else {
+ // Record the number of page crossing prefetches generated
pfSpanPage += degree - d + 1;
+ DPRINTF(HWPrefetch, "Ignoring page crossing prefetch.\n");
return;
- } else {
- DPRINTF(HWPrefetch, " queuing prefetch to %x (%s) @ %d\n",
- new_addr, is_secure ? "s" : "ns", latency);
- addresses.push_back(new_addr);
- delays.push_back(latency);
}
}
} else {
// Miss in table
- // Find lowest confidence and replace
-
- DPRINTF(HWPrefetch, "miss: PC %x data_addr %x (%s)\n", pc, data_addr,
+ DPRINTF(HWPrefetch, "Miss: PC %x pkt_addr %x (%s)\n", pc, pkt_addr,
is_secure ? "s" : "ns");
- if (tab.size() >= 256) { //set default table size is 256
- std::list<StrideEntry*>::iterator min_pos = tab.begin();
- int min_conf = (*min_pos)->confidence;
- for (iter = min_pos, ++iter; iter != tab.end(); ++iter) {
- if ((*iter)->confidence < min_conf){
- min_pos = iter;
- min_conf = (*iter)->confidence;
- }
- }
- DPRINTF(HWPrefetch, " replacing PC %x (%s)\n",
- (*min_pos)->instAddr, (*min_pos)->isSecure ? "s" : "ns");
+ StrideEntry* entry = pcTableVictim(pc, master_id);
+ entry->instAddr = pc;
+ entry->lastAddr = pkt_addr;
+ entry->isSecure= is_secure;
+ entry->stride = 0;
+ entry->confidence = startConf;
+ }
+}
- // free entry and delete it
- delete *min_pos;
- tab.erase(min_pos);
- }
+inline Addr
+StridePrefetcher::pcHash(Addr pc) const
+{
+ Addr hash1 = pc >> 1;
+ Addr hash2 = hash1 >> floorLog2(pcTableSets);
+ return (hash1 ^ hash2) & (Addr)(pcTableSets - 1);
+}
- StrideEntry *new_entry = new StrideEntry;
- new_entry->instAddr = pc;
- new_entry->missAddr = data_addr;
- new_entry->isSecure = is_secure;
- new_entry->stride = 0;
- new_entry->confidence = 0;
- new_entry->tolerance = false;
- tab.push_back(new_entry);
- }
+inline StridePrefetcher::StrideEntry*
+StridePrefetcher::pcTableVictim(Addr pc, int master_id)
+{
+ // Rand replacement for now
+ int set = pcHash(pc);
+ int way = rand() % pcTableAssoc;
+
+ DPRINTF(HWPrefetch, "Victimizing lookup table[%d][%d].\n", set, way);
+ return &pcTable[master_id][set][way];
}
+inline bool
+StridePrefetcher::pcTableHit(Addr pc, bool is_secure, int master_id,
+ StrideEntry* &entry)
+{
+ int set = pcHash(pc);
+ StrideEntry* set_entries = pcTable[master_id][set];
+ for (int way = 0; way < pcTableAssoc; way++) {
+ // Search ways for match
+ if (set_entries[way].instAddr == pc &&
+ set_entries[way].isSecure == is_secure) {
+ DPRINTF(HWPrefetch, "Lookup hit table[%d][%d].\n", set, way);
+ entry = &set_entries[way];
+ return true;
+ }
+ }
+ return false;
+}
StridePrefetcher*
StridePrefetcherParams::create()
{
- return new StridePrefetcher(this);
+ return new StridePrefetcher(this);
}