/**
* ****************************************************************************
* 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.reuseDistancePrediction;
import archimulator.common.*;
import archimulator.util.math.Quantizer;
import java.util.ArrayList;
import java.util.List;
/**
* Reuse distance sampler.
*
* @author Min Cai
*/
public class ReuseDistanceSampler
extends BasicSimulationObject<CPUExperiment, Simulation>
implements SimulationObject<CPUExperiment, Simulation> {
private String name;
protected List<ReuseDistanceSamplerEntry> entries;
protected int samplingPeriod;
protected int samplingCounter;
protected Quantizer reuseDistanceQuantizer;
/**
* Create a reuse distance sampler.
*
* @param parent the parent simulation object
* @param samplingPeriod the sampling period
* @param maxReuseDistance the maximum reuse distance
* @param reuseDistanceQuantizer the reuse distance quantizer
*/
public ReuseDistanceSampler(SimulationObject parent, String name, int samplingPeriod, int maxReuseDistance, Quantizer reuseDistanceQuantizer) {
super(parent);
this.name = name;
this.samplingPeriod = samplingPeriod;
this.reuseDistanceQuantizer = reuseDistanceQuantizer;
this.samplingCounter = 0;
this.entries = new ArrayList<>();
for (int i = 0; i < maxReuseDistance / this.samplingPeriod; i++) {
this.entries.add(new ReuseDistanceSamplerEntry());
}
}
/**
* Update.
*
* @param threadId the thread ID
* @param pc the value of the program counter (PC)
* @param address the address
*/
public void update(int threadId, int pc, int address) {
for (int i = 0; i < this.entries.size(); i++) {
ReuseDistanceSamplerEntry entry = this.entries.get(i);
if (entry.isValid() && entry.getAddress() == address) {
entry.setValid(false);
this.getBlockingEventDispatcher().dispatch(new ReuseDistanceSampledEvent(this, entry.getThreadId(), threadId, entry.getPc(), this.reuseDistanceQuantizer.quantize(i * this.samplingPeriod)));
break;
}
}
if (this.samplingCounter == 0) {
ReuseDistanceSamplerEntry victimEntry = this.entries.get(this.entries.size() - 1);
if (victimEntry.isValid()) {
this.getBlockingEventDispatcher().dispatch(new ReuseDistanceSampledEvent(this, victimEntry.getThreadId(), -1, victimEntry.getPc(), this.reuseDistanceQuantizer.getMaxValue()));
}
this.entries.remove(victimEntry);
this.entries.add(0, victimEntry);
victimEntry.setValid(true);
victimEntry.setThreadId(threadId);
victimEntry.setPc(pc);
victimEntry.setAddress(address);
this.samplingCounter = this.samplingPeriod - 1;
} else {
samplingCounter--;
}
}
@Override
public String getName() {
return name;
}
/**
* Get the list of entries.
*
* @return the list of entries
*/
public List<ReuseDistanceSamplerEntry> getEntries() {
return entries;
}
/**
* Get the sampling period.
*
* @return the sampling period
*/
public int getSamplingPeriod() {
return samplingPeriod;
}
/**
* Get the value of the sampling counter.
*
* @return the value of the sampling counter
*/
public int getSamplingCounter() {
return samplingCounter;
}
/**
* Get the reuse distance quantizer.
*
* @return the reuse distance quantizer
*/
public Quantizer getReuseDistanceQuantizer() {
return reuseDistanceQuantizer;
}
/**
* The event fired when a reuse distance is sampled.
*/
public class ReuseDistanceSampledEvent extends SimulationEvent {
private int leaderThreadId;
private int followerThreadId;
private int pc;
private int reuseDistance;
/**
* Create a event when a reuse distance is sampled.
*
* @param sender the sender simulation object
* @param leaderThreadId the leader thread ID
* @param followerThreadId the follower thread ID
* @param pc the value of the program counter (PC)
* @param reuseDistance the reuse distance
*/
public ReuseDistanceSampledEvent(SimulationObject sender, int leaderThreadId, int followerThreadId, int pc, int reuseDistance) {
super(sender);
this.leaderThreadId = leaderThreadId;
this.followerThreadId = followerThreadId;
this.pc = pc;
this.reuseDistance = reuseDistance;
}
/**
* Get the leader thread ID.
*
* @return the leader thread ID
*/
public int getLeaderThreadId() {
return leaderThreadId;
}
/**
* Get the follower thread ID.
*
* @return the follower thread ID
*/
public int getFollowerThreadId() {
return followerThreadId;
}
/**
* Get the value of the program counter (PC).
*
* @return the value of the program counter (PC)
*/
public int getPc() {
return pc;
}
/**
* Get the reuse distance.
*
* @return the reuse distance
*/
public int getReuseDistance() {
return reuseDistance;
}
}
}