/**
* ****************************************************************************
* 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.helperThread;
import archimulator.common.CPUExperiment;
import archimulator.common.Simulation;
import archimulator.common.SimulationEvent;
import archimulator.common.report.ReportNode;
import archimulator.common.report.Reportable;
import archimulator.core.Thread;
import archimulator.uncore.cache.CacheLine;
import archimulator.uncore.cache.prediction.CacheBasedPredictor;
import archimulator.uncore.cache.prediction.Predictor;
import archimulator.uncore.coherence.event.GeneralCacheControllerLastPutSOrPutMAndDataFromOwnerEvent;
import archimulator.uncore.coherence.event.GeneralCacheControllerNonblockingRequestHitToTransientTagEvent;
import archimulator.uncore.coherence.event.GeneralCacheControllerServiceNonblockingRequestEvent;
import archimulator.uncore.coherence.event.LastLevelCacheControllerLineInsertEvent;
import archimulator.uncore.coherence.msi.controller.DirectoryController;
import archimulator.uncore.coherence.msi.state.DirectoryControllerState;
import java.util.HashMap;
import java.util.Map;
/**
* Helper thread L2 cache request profiling helper.
*
* Redundant: HT->HT (USED=true), REDUNDANT++
* Good: HT->MT, GOOD++
* Bad: HT->HT (victim->INVALID, USED=true), BAD++
* Early: MT->MT (victim->INVALID), EARLY++,UGLY--
*
* @author Min Cai
*/
public class HelperThreadL2RequestProfilingHelper implements Reportable, HelperThreadL2RequestBreakdown {
private DirectoryController l2Controller;
private Map<Integer, Map<Integer, HelperThreadL2RequestState>> helperThreadL2RequestStates;
private long numMainThreadL2Hits;
private long numMainThreadL2Misses;
private long numHelperThreadL2Hits;
private long numHelperThreadL2Misses;
private long numRedundantHitToTransientTagHelperThreadL2Requests;
private long numRedundantHitToCacheHelperThreadL2Requests;
private long numGoodHelperThreadL2Requests;
private long numTimelyHelperThreadL2Requests;
private long numLateHelperThreadL2Requests;
private long numBadHelperThreadL2Requests;
private long numEarlyHelperThreadL2Requests;
private Predictor<HelperThreadL2RequestQuality> helperThreadL2RequestQualityPredictor;
private Predictor<Boolean> helperThreadL2RequestUsefulnessPredictor;
private Predictor<Boolean> helperThreadL2RequestPollutionPredictor;
/**
* Create a helper thread L2 request profiling helper.
*
* @param simulation simulation
*/
public HelperThreadL2RequestProfilingHelper(Simulation simulation) {
this.l2Controller = simulation.getProcessor().getMemoryHierarchy().getL2Controller();
this.helperThreadL2RequestStates = new HashMap<>();
for (int set = 0; set < this.l2Controller.getCache().getNumSets(); set++) {
HashMap<Integer, HelperThreadL2RequestState> helperThreadL2RequestStatesPerSet = new HashMap<>();
this.helperThreadL2RequestStates.put(set, helperThreadL2RequestStatesPerSet);
for (int way = 0; way < this.l2Controller.getCache().getAssociativity(); way++) {
helperThreadL2RequestStatesPerSet.put(way, new HelperThreadL2RequestState());
}
}
this.helperThreadL2RequestQualityPredictor = new CacheBasedPredictor<>(
this.l2Controller,
this.l2Controller.getName() + "/helperThreadL2RequestQualityPredictor",
64,
4,
16,
HelperThreadL2RequestQuality.UGLY
);
this.helperThreadL2RequestUsefulnessPredictor = new CacheBasedPredictor<>(
this.l2Controller,
this.l2Controller.getName() + "/helperThreadL2RequestUsefulnessPredictor",
64,
4,
16,
false
);
this.helperThreadL2RequestPollutionPredictor = new CacheBasedPredictor<>(
this.l2Controller,
this.l2Controller.getName() + "/helperThreadL2RequestPollutionPredictor",
64,
4,
16,
false
);
this.l2Controller.getBlockingEventDispatcher().addListener(GeneralCacheControllerServiceNonblockingRequestEvent.class, event -> {
if (event.getCacheController() == HelperThreadL2RequestProfilingHelper.this.l2Controller) {
boolean requesterIsHelperThread = HelperThreadingHelper.isHelperThread(event.getAccess().getThread());
boolean lineFoundIsHelperThread = helperThreadL2RequestStates.get(event.getSet()).get(event.getWay()).getThreadId() == HelperThreadingHelper.getHelperThreadId();
handleL2Request(event, requesterIsHelperThread, lineFoundIsHelperThread);
}
});
this.l2Controller.getBlockingEventDispatcher().addListener(LastLevelCacheControllerLineInsertEvent.class, event -> {
if (event.getCacheController() == HelperThreadL2RequestProfilingHelper.this.l2Controller) {
boolean lineFoundIsHelperThread = helperThreadL2RequestStates.get(event.getSet()).get(event.getWay()).getThreadId() == HelperThreadingHelper.getHelperThreadId();
handleL2LineInsert(event, lineFoundIsHelperThread);
}
});
this.l2Controller.getBlockingEventDispatcher().addListener(GeneralCacheControllerLastPutSOrPutMAndDataFromOwnerEvent.class, event -> {
if (event.getCacheController() == HelperThreadL2RequestProfilingHelper.this.l2Controller) {
markInvalid(event.getSet(), event.getWay());
}
});
this.l2Controller.getBlockingEventDispatcher().addListener(GeneralCacheControllerNonblockingRequestHitToTransientTagEvent.class, event -> {
if (event.getCacheController() == HelperThreadL2RequestProfilingHelper.this.l2Controller) {
int set = event.getSet();
int requesterThreadId = event.getAccess().getThread().getId();
int lineFoundThreadId = helperThreadL2RequestStates.get(set).get(event.getWay()).getInFlightThreadId();
boolean requesterIsHelperThread = HelperThreadingHelper.isHelperThread(requesterThreadId);
boolean lineFoundIsHelperThread = HelperThreadingHelper.isHelperThread(lineFoundThreadId);
if (!requesterIsHelperThread && lineFoundIsHelperThread) {
markLate(set, event.getWay(), true);
} else if (requesterIsHelperThread && !lineFoundIsHelperThread) {
markLate(set, event.getWay(), true);
}
}
});
this.l2Controller.getBlockingEventDispatcher().addListener(
HelperThreadL2RequestEvent.class,
event -> {
helperThreadL2RequestQualityPredictor.update(event.getPc(), event.getQuality());
helperThreadL2RequestUsefulnessPredictor.update(event.getPc(), event.getQuality().isUseful());
helperThreadL2RequestPollutionPredictor.update(event.getPc(), event.getQuality().isPolluting());
}
);
}
/**
* Handle an L2 cache request.
*
* @param event the event
* @param requesterIsHelperThread a value indicating whether the requester is the main thread or not
* @param lineFoundIsHelperThread a value indicating whether the line found is brought by the helper thread or not
*/
private void handleL2Request(GeneralCacheControllerServiceNonblockingRequestEvent event, boolean requesterIsHelperThread, boolean lineFoundIsHelperThread) {
int victimWay = this.findWayOfL2LineByVictimTag(event.getSet(), event.getTag());
CacheLine<DirectoryControllerState> victimLine = victimWay != -1 ? this.l2Controller.getCache().getLine(event.getSet(), victimWay) : null;
HelperThreadL2RequestState victimLineState = victimWay != -1 ? this.helperThreadL2RequestStates.get(event.getSet()).get(victimWay) : null;
boolean victimHit = victimLine != null;
boolean victimEvicterMainThreadHit = victimHit && this.helperThreadL2RequestStates.get(event.getSet()).get(victimWay).getThreadId() == HelperThreadingHelper.getMainThreadId();
boolean victimEvicterHelperThreadHit = victimHit && !victimLineState.isUsed() && this.helperThreadL2RequestStates.get(event.getSet()).get(victimWay).getThreadId() == HelperThreadingHelper.getHelperThreadId();
boolean victimMainThreadHit = victimHit && this.helperThreadL2RequestStates.get(event.getSet()).get(victimWay).getVictimThreadId() == HelperThreadingHelper.getMainThreadId();
boolean victimHelperThreadHit = victimHit && this.helperThreadL2RequestStates.get(event.getSet()).get(victimWay).getVictimThreadId() == HelperThreadingHelper.getHelperThreadId();
CacheLine<DirectoryControllerState> llcLine = this.l2Controller.getCache().getLine(event.getSet(), event.getWay());
HelperThreadL2RequestState llcLineState = this.helperThreadL2RequestStates.get(event.getSet()).get(event.getWay());
boolean mainThreadHit = event.isHitInCache() && !requesterIsHelperThread && !lineFoundIsHelperThread;
boolean helperThreadHit = event.isHitInCache() && !llcLineState.isUsed() && !requesterIsHelperThread && lineFoundIsHelperThread;
if (!requesterIsHelperThread) {
if (event.isHitInCache()) {
this.numMainThreadL2Hits++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new MainThreadL2HitEvent(
event.getSet(),
event.getAccess().getThread().getId(),
event.getAccess().getVirtualPc(),
event.getTag()
));
if (lineFoundIsHelperThread && !llcLineState.isUsed()) {
this.numGoodHelperThreadL2Requests++;
}
} else {
this.numMainThreadL2Misses++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new MainThreadL2MissEvent(
event.getSet(),
event.getAccess().getThread().getId(),
event.getAccess().getVirtualPc(),
event.getTag()
));
}
} else {
if (event.isHitInCache()) {
this.numHelperThreadL2Hits++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new HelperThreadL2HitEvent(
event.getSet(),
event.getAccess().getThread().getId(),
event.getAccess().getVirtualPc(),
event.getTag()
));
} else {
this.numHelperThreadL2Misses++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new HelperThreadL2MissEvent(
event.getSet(),
event.getAccess().getThread().getId(),
event.getAccess().getVirtualPc(),
event.getTag()
));
}
if (event.isHitInCache() && !lineFoundIsHelperThread) {
redundant(event, llcLineState);
}
}
if (!event.isHitInCache()) {
this.setL2LineBroughterThreadId(event.getSet(), event.getWay(), event.getAccess().getThread().getId(), event.getAccess().getVirtualPc(), true);
}
if (!requesterIsHelperThread) {
if (!mainThreadHit && !helperThreadHit) {
if (!victimHit) {
//No action.
} else if (victimEvicterMainThreadHit && victimMainThreadHit) {
//No action.
} else if (victimEvicterHelperThreadHit && victimMainThreadHit) {
bad(event, victimLine, victimLineState);
} else if (victimEvicterMainThreadHit && victimHelperThreadHit) {
early(event, victimLineState);
} else if (victimEvicterHelperThreadHit && victimHelperThreadHit) {
//Ugly.
}
} else if (helperThreadHit) {
if (!victimHit) {
good(event, llcLine, llcLineState);
} else if (victimEvicterMainThreadHit && victimMainThreadHit) {
good(event, llcLine, llcLineState);
} else if (victimEvicterHelperThreadHit && victimMainThreadHit) {
good(event, llcLine, llcLineState);
bad(event, victimLine, victimLineState);
} else if (victimEvicterMainThreadHit && victimHelperThreadHit) {
good(event, llcLine, llcLineState);
early(event, victimLineState);
} else if (victimEvicterHelperThreadHit && victimHelperThreadHit) {
good(event, llcLine, llcLineState);
}
} else {
if (!victimHit) {
//No action.
} else if (victimEvicterMainThreadHit && victimMainThreadHit) {
//No action.
} else if (victimEvicterHelperThreadHit && victimMainThreadHit) {
//Bandwidth waste.
} else if (victimEvicterMainThreadHit && victimHelperThreadHit) {
//Bandwidth waste.
} else if (victimEvicterHelperThreadHit && victimHelperThreadHit) {
//Bandwidth waste.
}
}
}
if (event.isHitInCache()) {
llcLineState.setVictimThreadId(llcLineState.getThreadId());
llcLineState.setVictimPc(llcLineState.getPc());
llcLineState.setVictimTag(llcLine.getTag());
this.setL2LineBroughterThreadId(event.getSet(), event.getWay(), event.getAccess().getThread().getId(), event.getAccess().getVirtualPc(), false);
if (requesterIsHelperThread && !lineFoundIsHelperThread) {
llcLineState.setUsed(true);
} else {
llcLineState.setUsed(false);
}
}
if (victimHit) {
victimLineState.setVictimThreadId(-1);
victimLineState.setVictimPc(-1);
victimLineState.setVictimTag(CacheLine.INVALID_TAG);
}
}
/**
* A redundant helper thread L2 request has been identified.
*
* @param event the event
* @param llcLineState the LLC line state
*/
private void redundant(GeneralCacheControllerServiceNonblockingRequestEvent event, HelperThreadL2RequestState llcLineState) {
//Redundant.
if (llcLineState.isHitToTransientTag()) {
this.numRedundantHitToTransientTagHelperThreadL2Requests++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new HelperThreadL2RequestEvent(
HelperThreadL2RequestQuality.REDUNDANT_HIT_TO_TRANSIENT_TAG,
event.getSet(),
event.getAccess().getThread().getId(),
event.getAccess().getVirtualPc(),
event.getTag()
));
} else {
this.numRedundantHitToCacheHelperThreadL2Requests++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new HelperThreadL2RequestEvent(
HelperThreadL2RequestQuality.REDUNDANT_HIT_TO_CACHE,
event.getSet(),
event.getAccess().getThread().getId(),
event.getAccess().getVirtualPc(),
event.getTag()
));
}
}
/**
* A good helper thread L2 request has been identified.
*
* @param event the event
* @param llcLine the LLC line
* @param llcLineState the LLC line state
*/
private void good(GeneralCacheControllerServiceNonblockingRequestEvent event, CacheLine<DirectoryControllerState> llcLine, HelperThreadL2RequestState llcLineState) {
//Good.
if (llcLineState.isHitToTransientTag()) {
this.numLateHelperThreadL2Requests++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new HelperThreadL2RequestEvent(
HelperThreadL2RequestQuality.LATE,
event.getSet(),
llcLineState.getThreadId(),
llcLineState.getPc(),
llcLine.getTag()
));
} else {
this.numTimelyHelperThreadL2Requests++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new HelperThreadL2RequestEvent(
HelperThreadL2RequestQuality.TIMELY,
event.getSet(),
llcLineState.getThreadId(),
llcLineState.getPc(),
llcLine.getTag()
));
}
}
/**
* A bad helper thread L2 request has been identified.
*
* @param event the event
* @param victimLine the victim line
* @param victimLineState the victim line state
*/
private void bad(GeneralCacheControllerServiceNonblockingRequestEvent event, CacheLine<DirectoryControllerState> victimLine, HelperThreadL2RequestState victimLineState) {
//Bad.
this.numBadHelperThreadL2Requests++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new HelperThreadL2RequestEvent(
HelperThreadL2RequestQuality.BAD,
event.getSet(),
victimLineState.getThreadId(),
victimLineState.getPc(),
victimLine.getTag()
));
victimLineState.setUsed(true);
}
/**
* An early helper thread L2 request has been identified.
*
* @param event the event
* @param victimLineState the victim line state
*/
private void early(GeneralCacheControllerServiceNonblockingRequestEvent event, HelperThreadL2RequestState victimLineState) {
//Early.
this.numEarlyHelperThreadL2Requests++;
this.l2Controller.getBlockingEventDispatcher().dispatch(new HelperThreadL2RequestEvent(
HelperThreadL2RequestQuality.EARLY,
event.getSet(),
victimLineState.getVictimThreadId(),
victimLineState.getVictimPc(),
victimLineState.getVictimTag()
));
}
/**
* Handle an L2 cache line insertion.
*
* @param event the event
* @param lineFoundIsHelperThread a value indicating whether the LLC line is brought by the helper thread or not
*/
private void handleL2LineInsert(LastLevelCacheControllerLineInsertEvent event, boolean lineFoundIsHelperThread) {
HelperThreadL2RequestState llcLineState = this.helperThreadL2RequestStates.get(event.getSet()).get(event.getWay());
if (!lineFoundIsHelperThread && llcLineState.isUsed()) {
throw new IllegalArgumentException();
}
if (!event.isEviction()) {
llcLineState.setVictimThreadId(-1);
llcLineState.setVictimPc(-1);
llcLineState.setVictimTag(CacheLine.INVALID_TAG);
} else {
llcLineState.setVictimThreadId(llcLineState.getThreadId());
llcLineState.setVictimPc(llcLineState.getPc());
llcLineState.setVictimTag(event.getVictimTag());
}
this.setL2LineBroughterThreadId(event.getSet(), event.getWay(), event.getAccess().getThread().getId(), event.getAccess().getVirtualPc(), false);
llcLineState.setUsed(false);
}
/**
* Find the way of the L2 cache line matching the specified victim tag.
*
* @param set the set index
* @param victimTag the victim tag
* @return the way of the L2 cache line matching the specified victim tag
*/
private int findWayOfL2LineByVictimTag(int set, int victimTag) {
for (int way = 0; way < this.l2Controller.getCache().getAssociativity(); way++) {
HelperThreadL2RequestState state = this.helperThreadL2RequestStates.get(set).get(way);
if (state.getVictimTag() == victimTag) {
return way;
}
}
return -1;
}
/**
* Mark as invalid for the specified set index and way.
*
* @param set the set index
* @param way the way
*/
private void markInvalid(int set, int way) {
HelperThreadL2RequestState llcLineState = this.helperThreadL2RequestStates.get(set).get(way);
this.setL2LineBroughterThreadId(set, way, -1, -1, false);
llcLineState.setPc(-1);
llcLineState.setVictimThreadId(-1);
llcLineState.setVictimPc(-1);
llcLineState.setVictimTag(CacheLine.INVALID_TAG);
llcLineState.setUsed(false);
this.markLate(set, way, false);
}
/**
* Set the L2 cache line's broughter thread ID.
*
* @param set the set index
* @param way the way
* @param l2LineBroughterThreadId the L2 cache line's broughter thread ID
* @param pc the virtual address of the program counter (PC)
* @param inFlight a value indicating whether it is in-flight or not
*/
private void setL2LineBroughterThreadId(int set, int way, int l2LineBroughterThreadId, int pc, boolean inFlight) {
HelperThreadL2RequestState llcLineState = this.helperThreadL2RequestStates.get(set).get(way);
if (inFlight) {
llcLineState.setInFlightThreadId(l2LineBroughterThreadId);
llcLineState.setPc(pc);
} else {
llcLineState.setInFlightThreadId(-1);
llcLineState.setThreadId(l2LineBroughterThreadId);
}
}
/**
* Mark as late for the specified set index and way.
*
* @param set the set index
* @param way the way
* @param late whether its is late or not
*/
private void markLate(int set, int way, boolean late) {
HelperThreadL2RequestState llcLineState = this.helperThreadL2RequestStates.get(set).get(way);
llcLineState.setHitToTransientTag(late);
}
@Override
public void dumpStats(ReportNode reportNode) {
reportNode.getChildren().add(new ReportNode(reportNode, "helperThreadL2RequestProfilingHelper") {{
getChildren().add(new ReportNode(this, "numMainThreadL2Hits", getNumMainThreadL2Hits() + ""));
getChildren().add(new ReportNode(this, "numMainThreadL2Misses", getNumMainThreadL2Misses() + ""));
getChildren().add(new ReportNode(this, "numHelperThreadL2Hits", getNumHelperThreadL2Hits() + ""));
getChildren().add(new ReportNode(this, "numHelperThreadL2Misses", getNumHelperThreadL2Misses() + ""));
getChildren().add(new ReportNode(this, "numTotalHelperThreadL2Requests", getNumTotalHelperThreadL2Requests() + ""));
getChildren().add(new ReportNode(this, "numRedundantHitToTransientTagHelperThreadL2Requests", getNumRedundantHitToTransientTagHelperThreadL2Requests() + ""));
getChildren().add(new ReportNode(this, "numRedundantHitToCacheHelperThreadL2Requests", getNumRedundantHitToCacheHelperThreadL2Requests() + ""));
getChildren().add(new ReportNode(this, "numGoodHelperThreadL2Requests", getNumGoodHelperThreadL2Requests() + ""));
getChildren().add(new ReportNode(this, "numTimelyHelperThreadL2Requests", getNumTimelyHelperThreadL2Requests() + ""));
getChildren().add(new ReportNode(this, "numLateHelperThreadL2Requests", getNumLateHelperThreadL2Requests() + ""));
getChildren().add(new ReportNode(this, "numBadHelperThreadL2Requests", getNumBadHelperThreadL2Requests() + ""));
getChildren().add(new ReportNode(this, "numEarlyHelperThreadL2Requests", getNumEarlyHelperThreadL2Requests() + ""));
getChildren().add(new ReportNode(this, "numUglyHelperThreadL2Requests", getNumUglyHelperThreadL2Requests() + ""));
getHelperThreadL2RequestQualityPredictor().dumpStats(this);
}});
}
/**
* Get the helper thread L2 cache request states.
*
* @return the helper thread L2 cache request states
*/
public Map<Integer, Map<Integer, HelperThreadL2RequestState>> getHelperThreadL2RequestStates() {
return helperThreadL2RequestStates;
}
/**
* Get the helper thread L2 cache request quality predictor.
*
* @return the helper thread L2 cache request quality predictor
*/
public Predictor<HelperThreadL2RequestQuality> getHelperThreadL2RequestQualityPredictor() {
return helperThreadL2RequestQualityPredictor;
}
/**
* Get the helper thread L2 cache request usefulness predictor.
*
* @return the helper thread L2 cache request usefulness predictor
*/
public Predictor<Boolean> getHelperThreadL2RequestUsefulnessPredictor() {
return helperThreadL2RequestUsefulnessPredictor;
}
/**
* Get the helper thread L2 cache request pollution predictor.
*
* @return the helper thread L2 cache request pollution predictor
*/
public Predictor<Boolean> getHelperThreadL2RequestPollutionPredictor() {
return helperThreadL2RequestPollutionPredictor;
}
/**
* Get the number of main thread L2 cache hits.
*
* @return the number of main thread L2 cache hits
*/
public long getNumMainThreadL2Hits() {
return numMainThreadL2Hits;
}
/**
* Get the number of main thread L2 cache misses.
*
* @return the number of main thread L2 cache misses
*/
public long getNumMainThreadL2Misses() {
return numMainThreadL2Misses;
}
/**
* Get the number of helper thread L2 cache hits.
*
* @return the number of helper thread L2 cache hits
*/
public long getNumHelperThreadL2Hits() {
return numHelperThreadL2Hits;
}
/**
* Get the number of helper thread L2 cache misses.
*
* @return the number of helper thread L2 cache misses
*/
public long getNumHelperThreadL2Misses() {
return numHelperThreadL2Misses;
}
/**
* Get the number of redundant "hit to transient tag" helper thread L2 cache requests.
*
* @return the number of redundant "hit to transient tag" helper thread L2 cache requests
*/
public long getNumRedundantHitToTransientTagHelperThreadL2Requests() {
return numRedundantHitToTransientTagHelperThreadL2Requests;
}
/**
* Get the number of redundant "hit to cache" helper thread L2 cache requests.
*
* @return the number of redundant "hit to cache" helper thread L2 cache requests
*/
public long getNumRedundantHitToCacheHelperThreadL2Requests() {
return numRedundantHitToCacheHelperThreadL2Requests;
}
/**
* Get the number of useful helper thread L2 cache requests.
*
* @return the number of useful helper thread L2 cache requests
*/
public long getNumGoodHelperThreadL2Requests() {
return numGoodHelperThreadL2Requests;
}
/**
* Get the number of timely helper thread L2 cache requests.
*
* @return the number of timely helper thread L2 cache requests
*/
public long getNumTimelyHelperThreadL2Requests() {
return numTimelyHelperThreadL2Requests;
}
/**
* Get the number of late helper thread L2 cache requests.
*
* @return the number of late helper thread L2 cache requests
*/
public long getNumLateHelperThreadL2Requests() {
return numLateHelperThreadL2Requests;
}
/**
* Get the number of bad helper thread L2 cache requests.
*
* @return the number of late helper thread L2 cache requests
*/
public long getNumBadHelperThreadL2Requests() {
return numBadHelperThreadL2Requests;
}
/**
* Get the number of early helper thread L2 cache requests.
*
* @return the number of early helper thread L2 cache requests
*/
public long getNumEarlyHelperThreadL2Requests() {
return numEarlyHelperThreadL2Requests;
}
@Override
public long getNumUglyHelperThreadL2Requests() {
return numHelperThreadL2Hits + numHelperThreadL2Misses
- getNumRedundantHitToCacheHelperThreadL2Requests()
- getNumRedundantHitToTransientTagHelperThreadL2Requests()
- getNumTimelyHelperThreadL2Requests()
- getNumLateHelperThreadL2Requests()
- getNumBadHelperThreadL2Requests()
- getNumEarlyHelperThreadL2Requests();
}
/**
* L2 cache request event.
*/
public abstract class L2RequestEvent extends SimulationEvent<CPUExperiment, Simulation> {
private int set;
private int threadId;
private int pc;
private int tag;
/**
* Create a L2 cache request event.
*
* @param set the set
* @param threadId the thread ID
* @param pc the program counter value
* @param tag the tag
*/
public L2RequestEvent(int set, int threadId, int pc, int tag) {
super(l2Controller);
this.set = set;
this.threadId = threadId;
this.pc = pc;
this.tag = tag;
}
/**
* Get the set.
*
* @return the set
*/
public int getSet() {
return set;
}
/**
* Get the thread ID.
*
* @return the thread ID
*/
public int getThreadId() {
return threadId;
}
/**
* Get the core ID.
*
* @return the core ID
*/
public int getCoreId() {
Thread thread = getSender().getSimulation().getProcessor().getThreads().get(threadId);
return thread.getCore().getNum();
}
/**
* Get the program counter value.
*
* @return the program counter value
*/
public int getPc() {
return pc;
}
/**
* Get the tag.
*
* @return the tag
*/
public int getTag() {
return tag;
}
}
/**
* Helper thread L2 cache request event.
*/
public class HelperThreadL2RequestEvent extends L2RequestEvent {
private HelperThreadL2RequestQuality quality;
/**
* Create a helper thread L2 cache request event.
*
* @param quality the quality
* @param set the set
* @param threadId the thread ID
* @param pc the program counter value
* @param tag the tag
*/
public HelperThreadL2RequestEvent(HelperThreadL2RequestQuality quality, int set, int threadId, int pc, int tag) {
super(set, threadId, pc, tag);
this.quality = quality;
}
/**
* Get the quality.
*
* @return the quality
*/
public HelperThreadL2RequestQuality getQuality() {
return quality;
}
}
/**
* Main thread L2 cache hit event.
*/
public class MainThreadL2HitEvent extends L2RequestEvent {
/**
* Create a main thread L2 cache hit event.
*
* @param set the set
* @param threadId the thread ID
* @param pc the program counter value
* @param tag the tag
*/
public MainThreadL2HitEvent(int set, int threadId, int pc, int tag) {
super(set, threadId, pc, tag);
}
}
/**
* Main thread L2 cache miss event.
*/
public class MainThreadL2MissEvent extends L2RequestEvent {
/**
* Create a main thread L2 cache miss event.
*
* @param set the set
* @param threadId the thread ID
* @param pc the program counter value
* @param tag the tag
*/
public MainThreadL2MissEvent(int set, int threadId, int pc, int tag) {
super(set, threadId, pc, tag);
}
}
/**
* Helper thread L2 cache hit event.
*/
public class HelperThreadL2HitEvent extends L2RequestEvent {
/**
* Create a helper thread L2 cache hit event.
*
* @param set the set
* @param threadId the thread ID
* @param pc the program counter value
* @param tag the tag
*/
public HelperThreadL2HitEvent(int set, int threadId, int pc, int tag) {
super(set, threadId, pc, tag);
}
}
/**
* Main thread L2 cache miss event.
*/
public class HelperThreadL2MissEvent extends L2RequestEvent {
/**
* Create a main thread L2 cache miss event.
*
* @param set the set
* @param threadId the thread ID
* @param pc the program counter value
* @param tag the tag
*/
public HelperThreadL2MissEvent(int set, int threadId, int pc, int tag) {
super(set, threadId, pc, tag);
}
}
}