/**
* ****************************************************************************
* Copyright (c) 2010-2016 by Min Cai (min.cai.china@gmail.com).
* <p>
* This file is part of the Archimulator multicore architectural simulator.
* <p>
* Archimulator is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* <p>
* Archimulator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License
* along with Archimulator. If not, see <http://www.gnu.org/licenses/>.
* ****************************************************************************
*/
package archimulator.uncore.cache.replacement.deadBlockPrediction;
import java.util.ArrayList;
import java.util.List;
/**
* Dead block prediction sampler.
*
* @author Min Cai
*/
public class DeadBlockPredictionSampler {
/**
* Dead block prediction sampler entry.
*/
public class DeadBlockPredictionSamplerEntry {
private int lruStackPosition;
private int partialTag;
private int trace;
private boolean dead;
private boolean valid;
/**
* Create a dead block prediction sampler entry.
*/
public DeadBlockPredictionSamplerEntry(int lruStackPosition) {
this.lruStackPosition = lruStackPosition;
this.partialTag = 0;
this.trace = 0;
this.dead = false;
this.valid = false;
}
}
private static final int associativity = 12;
private static final int modulus = 8;
private static final int numTagBitsPerEntry = 16;
private static final int counterWidth = 2;
private static final int numPredictorIndexBits = 12;
private int numSets;
private List<List<DeadBlockPredictionSamplerEntry>> entries;
private DeadBlockPredictor deadBlockPredictor;
/**
* Create a dead block prediction sampler.
*
* @param numSetsParentCache the number of sets in the parent cache
*/
public DeadBlockPredictionSampler(int numSetsParentCache) {
this.deadBlockPredictor = new DeadBlockPredictor(
(1 << counterWidth) - 1, numPredictorIndexBits
);
this.numSets = numSetsParentCache / modulus;
this.entries = new ArrayList<>();
for (int i = 0; i < this.numSets; i++) {
List<DeadBlockPredictionSamplerEntry> entriesPerSet = new ArrayList<>();
this.entries.add(entriesPerSet);
for (int j = 0; j < associativity; j++) {
entriesPerSet.add(new DeadBlockPredictionSamplerEntry(j));
}
}
}
/**
* Access with an LLC tag.
*
* @param set the sampler set index
* @param threadId the thread ID
* @param pc the virtual PC address
* @param tag the tag
*/
public void access(int set, int threadId, int pc, int tag) {
List<DeadBlockPredictionSamplerEntry> entriesPerSet = this.entries.get(set);
// get a partial tag to search for
int partialTag = tag & (1 << numTagBitsPerEntry) - 1;
// this will be the way of the sampler entry we end up hitting or replacing
int i;
// search for a matching tag
for (i = 0; i < associativity; i++)
if (entriesPerSet.get(i).valid && entriesPerSet.get(i).partialTag == partialTag) {
// we know this block is not dead; inform the predictor
this.deadBlockPredictor.update(threadId, entriesPerSet.get(i).trace, false);
break;
}
// did we find a match?
if (i == associativity) {
// look for an invalid block to replace
for (i = 0; i < associativity; i++) if (!entriesPerSet.get(i).valid) break;
// no invalid block? look for a dead block.
if (i == associativity) {
// find the LRU dead block
for (i = 0; i < associativity; i++) if (entriesPerSet.get(i).dead) break;
}
// no invalid or dead block? use the LRU block
if (i == associativity) {
int j;
for (j = 0; associativity > j; j++)
if (entriesPerSet.get(j).lruStackPosition == associativity - 1) break;
i = j;
}
// previous trace leads to block being dead; inform the predictor
this.deadBlockPredictor.update(threadId, entriesPerSet.get(i).trace, true);
// fill the victim block
entriesPerSet.get(i).partialTag = partialTag;
entriesPerSet.get(i).valid = true;
}
// record the trace
entriesPerSet.get(i).trace = DeadBlockPredictionBasedLRUPolicy.makeTrace(pc);
// get the next prediction for this entry
entriesPerSet.get(i).dead = this.deadBlockPredictor.predict(threadId, entriesPerSet.get(i).trace);
// now the replaced entry should be moved to the MRU position
int position = entriesPerSet.get(i).lruStackPosition;
for (int way = 0; way < associativity; way++)
if (entriesPerSet.get(way).lruStackPosition < position)
entriesPerSet.get(way).lruStackPosition++;
entriesPerSet.get(i).lruStackPosition = 0;
}
/**
* Get the associativity.
*
* @return the associativity
*/
public static int getAssociativity() {
return associativity;
}
/**
* Get the modulus value that determines which LLC sets are sampler sets.
*
* @return the modulus value that determines which LLC sets are sampler sets
*/
public static int getModulus() {
return modulus;
}
/**
* Get the number of sampler sets.
*
* @return the number of sampler sets
*/
public int getNumSets() {
return numSets;
}
/**
* Get the dead block predictor.
*
* @return the dead block predictor
*/
public DeadBlockPredictor getDeadBlockPredictor() {
return deadBlockPredictor;
}
}