|
|
@@ -1,36 +1,47 @@ |
|
|
/* |
|
|
|
|
|
* A sample prefetcher which does sequential one-block lookahead. |
|
|
|
|
|
* This means that the prefetcher fetches the next block _after_ the one that |
|
|
|
|
|
* was just accessed. It also ignores requests to blocks already in the cache. |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#include "interface.hh" |
|
|
#include "interface.hh" |
|
|
|
|
|
#include <map> |
|
|
|
|
|
|
|
|
|
|
|
typedef struct Stride { |
|
|
|
|
|
/* list of strides */ |
|
|
|
|
|
unsigned stride_distance; |
|
|
|
|
|
unsigned last_addr; |
|
|
|
|
|
unsigned successive_misses; |
|
|
|
|
|
} Stride; |
|
|
|
|
|
|
|
|
void prefetch_init(void) |
|
|
|
|
|
{ |
|
|
|
|
|
/* Called before any calls to prefetch_access. */ |
|
|
|
|
|
/* This is the place to initialize data structures. */ |
|
|
|
|
|
|
|
|
typedef std::map<Addr, Stride> StrideMap; |
|
|
|
|
|
static StrideMap stride_map; |
|
|
|
|
|
|
|
|
//DPRINTF(HWPrefetch, "Initialized sequential-on-access prefetcher\n"); |
|
|
|
|
|
|
|
|
/* naive stride distance, takes the stride between the previous two */ |
|
|
|
|
|
void set_stride(Addr mem_addr, Stride *stride) { |
|
|
|
|
|
stride->stride_distance = mem_addr - stride->last_addr; |
|
|
|
|
|
stride->last_addr = mem_addr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void prefetch_access(AccessStat stat) |
|
|
|
|
|
{ |
|
|
|
|
|
/* pf_addr is now an address within the _next_ cache block */ |
|
|
|
|
|
Addr pf_addr = stat.mem_addr + BLOCK_SIZE; |
|
|
|
|
|
|
|
|
void prefetch_init(void) { |
|
|
|
|
|
/* Called before any calls to prefetch_access. */ |
|
|
|
|
|
/* This is the place to initialize data structures. */ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
* Issue a prefetch request if a demand miss occured, |
|
|
|
|
|
* and the block is not already in cache. |
|
|
|
|
|
*/ |
|
|
|
|
|
if (stat.miss && !in_cache(pf_addr)) { |
|
|
|
|
|
issue_prefetch(pf_addr); |
|
|
|
|
|
|
|
|
void prefetch_access(AccessStat stat) { |
|
|
|
|
|
// never loaded from here before |
|
|
|
|
|
// check if stride_map[stat.pc] is set. |
|
|
|
|
|
if (stride_map.find(stat.pc) == stride_map.end()) { |
|
|
|
|
|
// pf_addr += BLOCK_SIZE; // just load next block, it's a good guess. |
|
|
|
|
|
// basically means stride of 1. |
|
|
|
|
|
stride_map[stat.pc].last_addr = stat.mem_addr; |
|
|
|
|
|
} else { |
|
|
|
|
|
set_stride(stat.mem_addr, &stride_map[stat.pc]); |
|
|
|
|
|
DPRINTF(HWPrefetch, "stride distance: %d\n", |
|
|
|
|
|
stride_map[stat.pc].stride_distance); |
|
|
|
|
|
Addr pf_addr = stat.mem_addr + stride_map[stat.pc].stride_distance; |
|
|
|
|
|
if (!in_cache(pf_addr) && pf_addr < MAX_PHYS_MEM_ADDR) { |
|
|
|
|
|
issue_prefetch(pf_addr); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void prefetch_complete(Addr addr) { |
|
|
void prefetch_complete(Addr addr) { |
|
|
/* |
|
|
|
|
|
* Called when a block requested by the prefetcher has been loaded. |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
* Called when a block requested by the prefetcher has been loaded. |
|
|
|
|
|
*/ |
|
|
} |
|
|
} |