/**
* ****************************************************************************
* 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.core;
import archimulator.common.BasicSimulationObject;
import archimulator.common.CPUExperiment;
import archimulator.common.Simulation;
import archimulator.core.bpred.*;
import archimulator.isa.ArchitecturalRegisterFile;
import archimulator.isa.Mnemonic;
import archimulator.isa.RegisterDependencyType;
import archimulator.isa.event.InstructionFunctionallyExecutedEvent;
import archimulator.isa.event.SystemCallExecutedEvent;
import archimulator.os.Context;
import java.util.Map;
import java.util.TreeMap;
/**
* Abstract basic thread.
*
* @author Min Cai
*/
public abstract class AbstractBasicThread extends BasicSimulationObject<CPUExperiment, Simulation> implements Thread {
/**
* The number of the thread.
*/
private int num;
/**
* The context.
*/
protected Context context;
/**
* The ID of the thread.
*/
protected int id;
/**
* The name of the thread.
*/
private String name;
/**
* The parent core.
*/
protected Core core;
/**
* The branch predictor.
*/
protected BranchPredictor branchPredictor;
/**
* The rename table.
*/
protected RegisterRenameTable renameTable;
/**
* The decode buffer.
*/
protected PipelineBuffer<DecodeBufferEntry> decodeBuffer;
/**
* The reorder buffer.
*/
protected PipelineBuffer<ReorderBufferEntry> reorderBuffer;
/**
* The load/store queue.
*/
protected PipelineBuffer<LoadStoreQueueEntry> loadStoreQueue;
/**
* The integer physical register file.
*/
protected PhysicalRegisterFile intPhysicalRegisterFile;
/**
* The floating point physical register file.
*/
protected PhysicalRegisterFile fpPhysicalRegisterFile;
/**
* The miscellaneous physical register file.
*/
protected PhysicalRegisterFile miscPhysicalRegisterFile;
/**
* The number of instructions.
*/
protected long numInstructions;
/**
* The number of decode buffer full stalls.
*/
private long numDecodeBufferFullStalls;
/**
* The number of reorder buffer full stalls.
*/
private long numReorderBufferFullStalls;
/**
* The number of load/store queue full stalls.
*/
private long numLoadStoreQueueFullStalls;
/**
* The number of integer physical register file full stalls.
*/
private long numIntPhysicalRegisterFileFullStalls;
/**
* The number of floating point physical register file full stalls.
*/
private long numFpPhysicalRegisterFileFullStalls;
/**
* The number of miscellaneous physical register file full stalls.
*/
private long numMiscPhysicalRegisterFileFullStalls;
/**
* The number of fetch stalls when the decode buffer is full.
*/
protected long numFetchStallsOnDecodeBufferIsFull;
/**
* The number of register rename stalls when the decode buffer is empty.
*/
private long numRegisterRenameStallsOnDecodeBufferIsEmpty;
/**
* The number of register rename stalls when the reorder buffer is full.
*/
private long numRegisterRenameStallsOnReorderBufferIsFull;
/**
* The number of register rename stalls when the load/store queue is full.
*/
protected long numRegisterRenameStallsOnLoadStoreQueueFull;
/**
* The number of selection stalls when loads can not be issued.
*/
private long numSelectionStallsOnCanNotLoad;
/**
* The number of selection stalls when stores can not be issued.
*/
private long numSelectionStallsOnCanNotStore;
/**
* The number of selection stalls when there is no free functional unit for a specific functional unit type.
*/
private long numSelectionStallsOnNoFreeFunctionalUnit;
private Map<Mnemonic, Long> executedMnemonics;
private Map<String, Long> executedSystemCalls;
/**
* Create an abstract basic thread.
*
* @param core the parent core
* @param num the number of the thread
*/
public AbstractBasicThread(Core core, int num) {
super(core);
this.core = core;
this.num = num;
this.id = this.core.getNum() * getExperiment().getConfig().getNumThreadsPerCore() + this.num;
this.name = "c" + this.core.getNum() + "t" + this.num;
switch (getExperiment().getConfig().getBranchPredictorType()) {
case PERFECT:
this.branchPredictor = new PerfectBranchPredictor(this, this.name + "/branchPredictor");
break;
case TAKEN:
this.branchPredictor = new TakenBranchPredictor(this, this.name + "/branchPredictor");
break;
case NOT_TAKEN:
this.branchPredictor = new NotTakenBranchPredictor(this, this.name + "/branchPredictor");
break;
case TWO_BIT:
this.branchPredictor = new TwoBitBranchPredictor(this, this.name + "/branchPredictor");
break;
case TWO_LEVEL:
this.branchPredictor = new TwoLevelBranchPredictor(this, this.name + "/branchPredictor");
break;
case COMBINED:
this.branchPredictor = new CombinedBranchPredictor(this, this.name + "/branchPredictor");
break;
default:
throw new IllegalArgumentException();
}
this.intPhysicalRegisterFile = new PhysicalRegisterFile(
this.name + "/intPhysicalRegisterFile",
getExperiment().getConfig().getPhysicalRegisterFileCapacity()
);
this.fpPhysicalRegisterFile = new PhysicalRegisterFile(
this.name + "/fpPhysicalRegisterFile",
getExperiment().getConfig().getPhysicalRegisterFileCapacity()
);
this.miscPhysicalRegisterFile = new PhysicalRegisterFile(
this.name + "/miscPhysicalRegisterFile",
getExperiment().getConfig().getPhysicalRegisterFileCapacity()
);
this.renameTable = new RegisterRenameTable(this.name + "/renameTable");
for (int i = 0; i < ArchitecturalRegisterFile.NUM_INT_REGISTERS; i++) {
int dep = RegisterDependencyType.toRegisterDependency(RegisterDependencyType.INTEGER, i);
PhysicalRegister physReg = this.intPhysicalRegisterFile.getRegisters().get(i);
physReg.reserve(dep);
this.renameTable.put(dep, physReg);
}
for (int i = 0; i < ArchitecturalRegisterFile.NUM_FLOAT_REGISTERS; i++) {
int dep = RegisterDependencyType.toRegisterDependency(RegisterDependencyType.FLOAT, i);
PhysicalRegister physReg = this.fpPhysicalRegisterFile.getRegisters().get(i);
physReg.reserve(dep);
this.renameTable.put(dep, physReg);
}
for (int i = 0; i < ArchitecturalRegisterFile.NUM_MISC_REGISTERS; i++) {
int dep = RegisterDependencyType.toRegisterDependency(RegisterDependencyType.MISC, i);
PhysicalRegister physReg = this.miscPhysicalRegisterFile.getRegisters().get(i);
physReg.reserve(dep);
this.renameTable.put(dep, physReg);
}
this.decodeBuffer = new PipelineBuffer<>(
getExperiment().getConfig().getDecodeBufferCapacity()
);
this.reorderBuffer = new PipelineBuffer<>(
getExperiment().getConfig().getReorderBufferCapacity()
);
this.loadStoreQueue = new PipelineBuffer<>(
getExperiment().getConfig().getLoadStoreQueueCapacity()
);
this.executedMnemonics = new TreeMap<>();
this.executedSystemCalls = new TreeMap<>();
this.getBlockingEventDispatcher().addListener(InstructionFunctionallyExecutedEvent.class, event -> {
if (event.getContext() == context) {
Mnemonic mnemonic = event.getStaticInstruction().getMnemonic();
if (!executedMnemonics.containsKey(mnemonic)) {
executedMnemonics.put(mnemonic, 0L);
}
executedMnemonics.put(mnemonic, executedMnemonics.get(mnemonic) + 1);
}
});
this.getBlockingEventDispatcher().addListener(SystemCallExecutedEvent.class, event -> {
if (event.getContext() == context) {
String systemCallName = event.getSystemCallName();
if (!executedSystemCalls.containsKey(systemCallName)) {
executedSystemCalls.put(systemCallName, 0L);
}
executedSystemCalls.put(systemCallName, executedSystemCalls.get(systemCallName) + 1);
}
});
}
@Override
public void updatePerCycleStats() {
if (this.decodeBuffer.isFull()) {
this.numDecodeBufferFullStalls++;
}
if (this.reorderBuffer.isFull()) {
this.numReorderBufferFullStalls++;
}
if (this.loadStoreQueue.isFull()) {
this.numLoadStoreQueueFullStalls++;
}
if (this.intPhysicalRegisterFile.isFull()) {
this.numIntPhysicalRegisterFileFullStalls++;
}
if (this.fpPhysicalRegisterFile.isFull()) {
this.numFpPhysicalRegisterFileFullStalls++;
}
if (this.miscPhysicalRegisterFile.isFull()) {
this.numMiscPhysicalRegisterFileFullStalls++;
}
}
@Override
public int getNum() {
return num;
}
@Override
public int getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public Core getCore() {
return core;
}
@Override
public BranchPredictor getBranchPredictor() {
return branchPredictor;
}
@Override
public PipelineBuffer<DecodeBufferEntry> getDecodeBuffer() {
return decodeBuffer;
}
@Override
public PipelineBuffer<ReorderBufferEntry> getReorderBuffer() {
return reorderBuffer;
}
@Override
public PipelineBuffer<LoadStoreQueueEntry> getLoadStoreQueue() {
return loadStoreQueue;
}
@Override
public long getNumInstructions() {
return numInstructions;
}
@Override
public Context getContext() {
return context;
}
@Override
public void setContext(Context context) {
this.context = context;
}
@Override
public void incrementNumRegisterRenameStallsOnDecodeBufferIsEmpty() {
this.numRegisterRenameStallsOnDecodeBufferIsEmpty++;
}
@Override
public void incrementNumRegisterRenameStallsOnReorderBufferIsFull() {
this.numRegisterRenameStallsOnReorderBufferIsFull++;
}
@Override
public void incrementNumSelectionStallsOnCanNotLoad() {
this.numSelectionStallsOnCanNotLoad++;
}
@Override
public void incrementNumSelectionStallsOnCanNotStore() {
this.numSelectionStallsOnCanNotStore++;
}
@Override
public void incrementNumSelectionStallsOnNoFreeFunctionalUnit() {
this.numSelectionStallsOnNoFreeFunctionalUnit++;
}
@Override
public long getNumDecodeBufferFullStalls() {
return numDecodeBufferFullStalls;
}
@Override
public long getNumReorderBufferFullStalls() {
return numReorderBufferFullStalls;
}
@Override
public long getNumLoadStoreQueueFullStalls() {
return numLoadStoreQueueFullStalls;
}
@Override
public long getNumIntPhysicalRegisterFileFullStalls() {
return numIntPhysicalRegisterFileFullStalls;
}
@Override
public long getNumFpPhysicalRegisterFileFullStalls() {
return numFpPhysicalRegisterFileFullStalls;
}
@Override
public long getNumMiscPhysicalRegisterFileFullStalls() {
return numMiscPhysicalRegisterFileFullStalls;
}
@Override
public long getNumFetchStallsOnDecodeBufferIsFull() {
return numFetchStallsOnDecodeBufferIsFull;
}
@Override
public long getNumRegisterRenameStallsOnDecodeBufferIsEmpty() {
return numRegisterRenameStallsOnDecodeBufferIsEmpty;
}
@Override
public long getNumRegisterRenameStallsOnReorderBufferIsFull() {
return numRegisterRenameStallsOnReorderBufferIsFull;
}
@Override
public long getNumRegisterRenameStallsOnLoadStoreQueueFull() {
return numRegisterRenameStallsOnLoadStoreQueueFull;
}
@Override
public long getNumSelectionStallsOnCanNotLoad() {
return numSelectionStallsOnCanNotLoad;
}
@Override
public long getNumSelectionStallsOnCanNotStore() {
return numSelectionStallsOnCanNotStore;
}
@Override
public long getNumSelectionStallsOnNoFreeFunctionalUnit() {
return numSelectionStallsOnNoFreeFunctionalUnit;
}
@Override
public Map<Mnemonic, Long> getExecutedMnemonics() {
return executedMnemonics;
}
@Override
public Map<String, Long> getExecutedSystemCalls() {
return executedSystemCalls;
}
}