49d48
< #include "base/trace.hh"
52a52,84
> 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];
> }
> }
> }
>
54,55c86,87
< StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list<Addr> &addresses,
< std::list<Cycles> &delays)
---
> StridePrefetcher::calculatePrefetch(const PacketPtr &pkt,
> std::vector<Addr> &addresses)
58c90
< DPRINTF(HWPrefetch, "ignoring request with no PC");
---
> DPRINTF(HWPrefetch, "Ignoring request with no PC.\n");
62c94,96
< Addr data_addr = pkt->getAddr();
---
> // Get required packet info
> Addr pkt_addr = pkt->getAddr();
> Addr pc = pkt->req->getPC();
65,67d98
< Addr pc = pkt->req->getPC();
< assert(master_id < Max_Contexts);
< std::list<StrideEntry*> &tab = table[master_id];
69,84c100
< // 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);
86,92c102,103
< /* 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;
94c105
< if (iter != tab.end()) {
---
> if(pcTableHit(pc, is_secure, master_id, entry)) {
95a107,108
> int new_stride = pkt_addr - entry->lastAddr;
> bool stride_match = (new_stride == entry->stride);
97,99c110
< int new_stride = data_addr - (*iter)->missAddr;
< bool stride_match = (new_stride == (*iter)->stride);
<
---
> // Adjust confidence for stride entry
101,103c112,113
< (*iter)->tolerance = true;
< if ((*iter)->confidence < Max_Conf)
< (*iter)->confidence++;
---
> if (entry->confidence < maxConf)
> entry->confidence++;
105,111c115,119
< 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;
114,115c122,123
< 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,
117c125
< (*iter)->confidence);
---
> entry->confidence);
119,120c127
< (*iter)->missAddr = data_addr;
< (*iter)->isSecure = is_secure;
---
> entry->lastAddr = pkt_addr;
122c129,130
< if ((*iter)->confidence <= 0)
---
> // Abort prefetch generation if below confidence threshold
> if (entry->confidence < threshConf)
124a133
> // Generate up to degree prefetches
126,128c135,146
< 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
129a148
> DPRINTF(HWPrefetch, "Ignoring page crossing prefetch.\n");
131,135d149
< } 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);
140,142c154
< // 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,
145,155c157,164
< 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;
> }
> }
157,160c166,172
< // 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);
> }
162,169c174,198
< 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;
> }
170a200
> return false;
173d202
<
177c206
< return new StridePrefetcher(this);
---
> return new StridePrefetcher(this);