summaryrefslogtreecommitdiff
path: root/src/mem/cache/tags/iic.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/cache/tags/iic.cc')
-rw-r--r--src/mem/cache/tags/iic.cc649
1 files changed, 0 insertions, 649 deletions
diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc
deleted file mode 100644
index b9e582c29..000000000
--- a/src/mem/cache/tags/iic.cc
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Erik Hallnor
- */
-
-/**
- * @file
- * Definitions of the Indirect Index Cache tagstore.
- */
-
-#include <algorithm>
-#include <cmath>
-#include <string>
-#include <vector>
-
-#include "base/intmath.hh"
-#include "base/trace.hh"
-#include "debug/Cache.hh"
-#include "debug/IIC.hh"
-#include "debug/IICMore.hh"
-#include "mem/cache/tags/iic.hh"
-#include "mem/cache/base.hh"
-#include "sim/core.hh"
-
-using namespace std;
-
-/** Track the number of accesses to each cache set. */
-#define PROFILE_IIC 1
-
-IIC::IIC(IIC::Params &params) :
- hashSets(params.numSets), blkSize(params.blkSize), assoc(params.assoc),
- hitLatency(params.hitLatency), subSize(params.subblockSize),
- numSub(blkSize/subSize),
- trivialSize((floorLog2(params.size/subSize)*numSub)/8),
- tagShift(floorLog2(blkSize)), blkMask(blkSize - 1),
- subShift(floorLog2(subSize)), subMask(numSub - 1),
- hashDelay(params.hashDelay),
- numTags(hashSets * assoc + params.size/blkSize -1),
- numSecondary(params.size/blkSize),
- tagNull(numTags),
- primaryBound(hashSets * assoc)
-{
- // Check parameters
- if (blkSize < 4 || !isPowerOf2(blkSize)) {
- fatal("Block size must be at least 4 and a power of 2");
- }
- if (hashSets <= 0 || !isPowerOf2(hashSets)) {
- fatal("# of hashsets must be non-zero and a power of 2");
- }
- if (assoc <= 0) {
- fatal("associativity must be greater than zero");
- }
- if (hitLatency <= 0) {
- fatal("access latency must be greater than zero");
- }
- if (numSub*subSize != blkSize) {
- fatal("blocksize must be evenly divisible by subblock size");
- }
-
- // debug stuff
- freeSecond = numSecondary;
-
- warmedUp = false;
- warmupBound = params.size/blkSize;
- numBlocks = params.size/subSize;
-
- // Replacement Policy Initialization
- repl = params.rp;
- repl->setIIC(this);
-
- //last_miss_time = 0
-
- // allocate data reference counters
- dataReferenceCount = new int[numBlocks];
- memset(dataReferenceCount, 0, numBlocks*sizeof(int));
-
- // Allocate storage for both internal data and block fast access data.
- // We allocate it as one large chunk to reduce overhead and to make
- // deletion easier.
- unsigned data_index = 0;
- dataStore = new uint8_t[(numBlocks + numTags) * blkSize];
- dataBlks = new uint8_t*[numBlocks];
- for (unsigned i = 0; i < numBlocks; ++i) {
- dataBlks[i] = &dataStore[data_index];
- freeDataBlock(i);
- data_index += subSize;
- }
-
- assert(data_index == numBlocks * subSize);
-
- // allocate and init tag store
- tagStore = new IICTag[numTags];
-
- unsigned blkIndex = 0;
- // allocate and init sets
- sets = new IICSet[hashSets];
- for (unsigned i = 0; i < hashSets; ++i) {
- sets[i].assoc = assoc;
- sets[i].tags = new IICTag*[assoc];
- sets[i].chain_ptr = tagNull;
-
- for (unsigned j = 0; j < assoc; ++j) {
- IICTag *tag = &tagStore[blkIndex++];
- tag->chain_ptr = tagNull;
- tag->data_ptr.resize(numSub);
- tag->size = blkSize;
- tag->trivialData = new uint8_t[trivialSize];
- tag->numData = 0;
- sets[i].tags[j] = tag;
- tag->set = i;
- tag->data = &dataStore[data_index];
- data_index += blkSize;
- }
- }
-
- assert(blkIndex == primaryBound);
-
- for (unsigned i = primaryBound; i < tagNull; i++) {
- tagStore[i].chain_ptr = i+1;
- //setup data ptrs to subblocks
- tagStore[i].data_ptr.resize(numSub);
- tagStore[i].size = blkSize;
- tagStore[i].trivialData = new uint8_t[trivialSize];
- tagStore[i].numData = 0;
- tagStore[i].set = 0;
- tagStore[i].data = &dataStore[data_index];
- data_index += blkSize;
- }
- freelist = primaryBound;
-}
-
-IIC::~IIC()
-{
- delete [] dataReferenceCount;
- delete [] dataStore;
- delete [] tagStore;
- delete [] sets;
- delete [] dataBlks;
-}
-
-/* register cache stats */
-void
-IIC::regStats(const string &name)
-{
- using namespace Stats;
-
- BaseTags::regStats(name);
-
- hitHashDepth.init(0, 20, 1);
- missHashDepth.init(0, 20, 1);
- setAccess.init(0, hashSets, 1);
-
- /** IIC Statistics */
- hitHashDepth
- .name(name + ".hit_hash_depth_dist")
- .desc("Dist. of Hash lookup depths")
- .flags(pdf)
- ;
-
- missHashDepth
- .name(name + ".miss_hash_depth_dist")
- .desc("Dist. of Hash lookup depths")
- .flags(pdf)
- ;
-
- repl->regStatsWithSuffix(name);
-
- if (PROFILE_IIC)
- setAccess
- .name(name + ".set_access_dist")
- .desc("Dist. of Accesses across sets")
- .flags(pdf)
- ;
-
- missDepthTotal
- .name(name + ".miss_depth_total")
- .desc("Total of miss depths")
- ;
-
- hashMiss
- .name(name + ".hash_miss")
- .desc("Total of misses in hash table")
- ;
-
- hitDepthTotal
- .name(name + ".hit_depth_total")
- .desc("Total of hit depths")
- ;
-
- hashHit
- .name(name + ".hash_hit")
- .desc("Total of hites in hash table")
- ;
-}
-
-
-IICTag*
-IIC::accessBlock(Addr addr, Cycles &lat, int context_src)
-{
- Addr tag = extractTag(addr);
- unsigned set = hash(addr);
- Cycles set_lat;
-
- unsigned long chain_ptr = tagNull;
-
- if (PROFILE_IIC)
- setAccess.sample(set);
-
- IICTag *tag_ptr = sets[set].findTag(tag, chain_ptr);
- set_lat = Cycles(1);
- if (tag_ptr == NULL && chain_ptr != tagNull) {
- int secondary_depth;
- tag_ptr = secondaryChain(tag, chain_ptr, &secondary_depth);
- set_lat += Cycles(secondary_depth);
- // set depth for statistics fix this later!!! egh
- sets[set].depth = set_lat;
-
- if (tag_ptr != NULL) {
- /* need to move tag into primary table */
- // need to preserve chain: fix this egh
- sets[set].tags[assoc-1]->chain_ptr = tag_ptr->chain_ptr;
- tagSwap(tag_ptr - tagStore, sets[set].tags[assoc-1] - tagStore);
- tag_ptr = sets[set].findTag(tag, chain_ptr);
- assert(tag_ptr!=NULL);
- }
-
- }
- set_lat = Cycles(set_lat * hashDelay + hitLatency);
- if (tag_ptr != NULL) {
- // IIC replacement: if this is not the first element of
- // list, reorder
- sets[set].moveToHead(tag_ptr);
-
- hitHashDepth.sample(sets[set].depth);
- hashHit++;
- hitDepthTotal += sets[set].depth;
- tag_ptr->status |= BlkReferenced;
- lat = set_lat;
- if (tag_ptr->whenReady > curTick() &&
- cache->ticksToCycles(tag_ptr->whenReady - curTick()) > set_lat) {
- lat = cache->ticksToCycles(tag_ptr->whenReady - curTick());
- }
-
- tag_ptr->refCount += 1;
- }
- else {
- // fall through: cache block not found, not a hit...
- missHashDepth.sample(sets[set].depth);
- hashMiss++;
- missDepthTotal += sets[set].depth;
- lat = set_lat;
- }
- return tag_ptr;
-}
-
-
-IICTag*
-IIC::findBlock(Addr addr) const
-{
- Addr tag = extractTag(addr);
- unsigned set = hash(addr);
-
- unsigned long chain_ptr = tagNull;
-
- IICTag *tag_ptr = sets[set].findTag(tag, chain_ptr);
- if (tag_ptr == NULL && chain_ptr != tagNull) {
- int secondary_depth;
- tag_ptr = secondaryChain(tag, chain_ptr, &secondary_depth);
- }
- return tag_ptr;
-}
-
-
-IICTag*
-IIC::findVictim(Addr addr, PacketList &writebacks)
-{
- DPRINTF(IIC, "Finding Replacement for %x\n", addr);
- unsigned set = hash(addr);
- IICTag *tag_ptr;
- unsigned long *tmp_data = new unsigned long[numSub];
-
- // Get a enough subblocks for a full cache line
- for (unsigned i = 0; i < numSub; ++i){
- tmp_data[i] = getFreeDataBlock(writebacks);
- assert(dataReferenceCount[tmp_data[i]]==0);
- }
-
- tag_ptr = getFreeTag(set, writebacks);
-
- tag_ptr->set = set;
- for (unsigned i = 0; i < numSub; ++i) {
- tag_ptr->data_ptr[i] = tmp_data[i];
- dataReferenceCount[tag_ptr->data_ptr[i]]++;
- }
- tag_ptr->numData = numSub;
- assert(tag_ptr - tagStore < primaryBound); // make sure it is in primary
- tag_ptr->chain_ptr = tagNull;
- sets[set].moveToHead(tag_ptr);
- delete [] tmp_data;
-
- list<unsigned long> tag_indexes;
- repl->doAdvance(tag_indexes);
-/*
- while (!tag_indexes.empty()) {
- if (!tagStore[tag_indexes.front()].isCompressed()) {
- compress_blocks.push_back(&tagStore[tag_indexes.front()]);
- }
- tag_indexes.pop_front();
- }
-*/
-
- tag_ptr->re = (void*)repl->add(tag_ptr-tagStore);
-
- return tag_ptr;
-}
-
-void
-IIC::insertBlock(Addr addr, BlkType* blk, int context_src)
-{
-}
-
-void
-IIC::freeReplacementBlock(PacketList & writebacks)
-{
- IICTag *tag_ptr;
- unsigned long data_ptr;
- /* consult replacement policy */
- tag_ptr = &tagStore[repl->getRepl()];
- assert(tag_ptr != NULL);
- assert(tag_ptr->isValid());
-
- DPRINTF(Cache, "Replacing %x in IIC: %s\n",
- regenerateBlkAddr(tag_ptr->tag,0),
- tag_ptr->isDirty() ? "writeback" : "clean");
- /* write back replaced block data */
- replacements[0]++;
- totalRefs += tag_ptr->refCount;
- ++sampledRefs;
- tag_ptr->refCount = 0;
-
- if (tag_ptr->isDirty()) {
-/* PacketPtr writeback =
- buildWritebackReq(regenerateBlkAddr(tag_ptr->tag, 0),
- tag_ptr->req->asid, tag_ptr->xc, blkSize,
- tag_ptr->data,
- tag_ptr->size);
-*/
- Request *writebackReq = new Request(regenerateBlkAddr(tag_ptr->tag, 0),
- blkSize, 0, Request::wbMasterId);
- PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback);
- writeback->allocate();
- memcpy(writeback->getPtr<uint8_t>(), tag_ptr->data, blkSize);
-
- writebacks.push_back(writeback);
- }
-
- // free the data blocks
- for (int i = 0; i < tag_ptr->numData; ++i) {
- data_ptr = tag_ptr->data_ptr[i];
- assert(dataReferenceCount[data_ptr]>0);
- if (--dataReferenceCount[data_ptr] == 0) {
- freeDataBlock(data_ptr);
- }
- }
- freeTag(tag_ptr);
-}
-
-unsigned long
-IIC::getFreeDataBlock(PacketList & writebacks)
-{
- unsigned long data_ptr;
-
- /* find data block */
- while (blkFreelist.empty()) {
- freeReplacementBlock(writebacks);
- }
-
- data_ptr = blkFreelist.front();
- blkFreelist.pop_front();
- DPRINTF(IICMore,"Found free data at %d\n",data_ptr);
- return data_ptr;
-}
-
-
-
-IICTag*
-IIC::getFreeTag(int set, PacketList & writebacks)
-{
- unsigned long tag_index;
- IICTag *tag_ptr;
- // Add new tag
- tag_ptr = sets[set].findFree();
- // if no free in primary, and secondary exists
- if (!tag_ptr && numSecondary) {
- // need to spill a tag into secondary storage
- while (freelist == tagNull) {
- // get replacements until one is in secondary
- freeReplacementBlock(writebacks);
- }
-
- tag_index = freelist;
- freelist = tagStore[freelist].chain_ptr;
- freeSecond--;
-
- assert(tag_index != tagNull);
- tagSwap(tag_index, sets[set].tags[assoc-1] - tagStore);
- tagStore[tag_index].chain_ptr = sets[set].chain_ptr;
- sets[set].chain_ptr = tag_index;
-
- tag_ptr = sets[set].tags[assoc-1];
- }
- DPRINTF(IICMore,"Found free tag at %d\n",tag_ptr - tagStore);
- tagsInUse++;
- if (!warmedUp && tagsInUse.value() >= warmupBound) {
- warmedUp = true;
- warmupCycle = curTick();
- }
-
- return tag_ptr;
-}
-
-void
-IIC::freeTag(IICTag *tag_ptr)
-{
- unsigned long tag_index, tmp_index;
- // Fix tag_ptr
- if (tag_ptr) {
- // we have a tag to clear
- DPRINTF(IICMore,"Freeing Tag for %x\n",
- regenerateBlkAddr(tag_ptr->tag,0));
- tagsInUse--;
- tag_ptr->status = 0;
- tag_ptr->numData = 0;
- tag_ptr->re = NULL;
- tag_index = tag_ptr - tagStore;
- if (tag_index >= primaryBound) {
- // tag_ptr points to secondary store
- assert(tag_index < tagNull); // remove this?? egh
- if (tag_ptr->chain_ptr == tagNull) {
- // need to fix chain list
- unsigned tmp_set = hash(tag_ptr->tag << tagShift);
- if (sets[tmp_set].chain_ptr == tag_index) {
- sets[tmp_set].chain_ptr = tagNull;
- } else {
- tmp_index = sets[tmp_set].chain_ptr;
- while (tmp_index != tagNull
- && tagStore[tmp_index].chain_ptr != tag_index) {
- tmp_index = tagStore[tmp_index].chain_ptr;
- }
- assert(tmp_index != tagNull);
- tagStore[tmp_index].chain_ptr = tagNull;
- }
- tag_ptr->chain_ptr = freelist;
- freelist = tag_index;
- freeSecond++;
- } else {
- // copy next chained entry to this tag location
- tmp_index = tag_ptr->chain_ptr;
- tagSwap(tmp_index, tag_index);
- tagStore[tmp_index].chain_ptr = freelist;
- freelist = tmp_index;
- freeSecond++;
- }
- } else {
- // tag_ptr in primary hash table
- assert(tag_index < primaryBound);
- tag_ptr->status = 0;
- unsigned tmp_set = hash(tag_ptr->tag << tagShift);
- if (sets[tmp_set].chain_ptr != tagNull) { // collapse chain
- tmp_index = sets[tmp_set].chain_ptr;
- tagSwap(tag_index, tmp_index);
- tagStore[tmp_index].chain_ptr = freelist;
- freelist = tmp_index;
- freeSecond++;
- sets[tmp_set].chain_ptr = tag_ptr->chain_ptr;
- sets[tmp_set].moveToTail(tag_ptr);
- }
- }
- }
-}
-
-void
-IIC::freeDataBlock(unsigned long data_ptr)
-{
- assert(dataReferenceCount[data_ptr] == 0);
- DPRINTF(IICMore, "Freeing data at %d\n", data_ptr);
- blkFreelist.push_front(data_ptr);
-}
-
-/** Use a simple modulo hash. */
-#define SIMPLE_HASH 0
-
-unsigned
-IIC::hash(Addr addr) const {
-#if SIMPLE_HASH
- return extractTag(addr) % iic_hash_size;
-#else
- Addr tag, mask, x, y;
- tag = extractTag(addr);
- mask = hashSets-1; /* assumes iic_hash_size is a power of 2 */
- x = tag & mask;
- y = (tag >> (int)(::log((double)hashSets)/::log((double)2))) & mask;
- assert (x < hashSets && y < hashSets);
- return x ^ y;
-#endif
-}
-
-
-void
-IICSet::moveToHead(IICTag *tag)
-{
- if (tags[0] == tag)
- return;
-
- // write 'next' block into blks[i], moving up from MRU toward LRU
- // until we overwrite the block we moved to head.
-
- // start by setting up to write 'blk' into blks[0]
- int i = 0;
- IICTag *next = tag;
-
- do {
- assert(i < assoc);
- // swap blks[i] and next
- IICTag *tmp = tags[i];
- tags[i] = next;
- next = tmp;
- ++i;
- } while (next != tag);
-}
-
-void
-IICSet::moveToTail(IICTag *tag)
-{
- if (tags[assoc-1] == tag)
- return;
-
- // write 'next' block into blks[i], moving up from MRU toward LRU
- // until we overwrite the block we moved to head.
-
- // start by setting up to write 'blk' into blks[0]
- int i = assoc - 1;
- IICTag *next = tag;
-
- do {
- assert(i >= 0);
- // swap blks[i] and next
- IICTag *tmp = tags[i];
- tags[i] = next;
- next = tmp;
- --i;
- } while (next != tag);
-}
-
-void
-IIC::tagSwap(unsigned long index1, unsigned long index2)
-{
- DPRINTF(IIC,"Swapping tag[%d]=%x for tag[%d]=%x\n",index1,
- tagStore[index1].tag<<tagShift, index2,
- tagStore[index2].tag<<tagShift);
- IICTag tmp_tag;
- tmp_tag = tagStore[index1];
- tagStore[index1] = tagStore[index2];
- tagStore[index2] = tmp_tag;
- if (tagStore[index1].isValid())
- repl->fixTag(tagStore[index1].re, index2, index1);
- if (tagStore[index2].isValid())
- repl->fixTag(tagStore[index2].re, index1, index2);
-}
-
-
-IICTag *
-IIC::secondaryChain(Addr tag, unsigned long chain_ptr,
- int *_depth) const
-{
- int depth = 0;
- while (chain_ptr != tagNull) {
- DPRINTF(IIC,"Searching secondary at %d for %x\n", chain_ptr,
- tag<<tagShift);
- if (tagStore[chain_ptr].tag == tag &&
- (tagStore[chain_ptr].isValid())) {
- *_depth = depth;
- return &tagStore[chain_ptr];
- }
- depth++;
- chain_ptr = tagStore[chain_ptr].chain_ptr;
- }
- *_depth = depth;
- return NULL;
-}
-
-void
-IIC::invalidate(IIC::BlkType *tag_ptr)
-{
- if (tag_ptr) {
- for (int i = 0; i < tag_ptr->numData; ++i) {
- dataReferenceCount[tag_ptr->data_ptr[i]]--;
- if (dataReferenceCount[tag_ptr->data_ptr[i]] == 0) {
- freeDataBlock(tag_ptr->data_ptr[i]);
- }
- }
- repl->removeEntry(tag_ptr->re);
- freeTag(tag_ptr);
- }
-}
-
-void
-IIC::clearLocks()
-{
- for (int i = 0; i < numTags; i++){
- tagStore[i].clearLoadLocks();
- }
-}
-
-void
-IIC::cleanupRefs()
-{
- for (unsigned i = 0; i < numTags; ++i) {
- if (tagStore[i].isValid()) {
- totalRefs += tagStore[i].refCount;
- ++sampledRefs;
- }
- }
-}