/** Returns the name of the IQ. */
std::string name() const;
- /** Registers statistics. */
- void regStats();
-
/** Resets all instruction queue state. */
void resetState();
*/
void dumpInsts();
- /** Stat for number of instructions added. */
- Stats::Scalar iqInstsAdded;
- /** Stat for number of non-speculative instructions added. */
- Stats::Scalar iqNonSpecInstsAdded;
-
- Stats::Scalar iqInstsIssued;
- /** Stat for number of integer instructions issued. */
- Stats::Scalar iqIntInstsIssued;
- /** Stat for number of floating point instructions issued. */
- Stats::Scalar iqFloatInstsIssued;
- /** Stat for number of branch instructions issued. */
- Stats::Scalar iqBranchInstsIssued;
- /** Stat for number of memory instructions issued. */
- Stats::Scalar iqMemInstsIssued;
- /** Stat for number of miscellaneous instructions issued. */
- Stats::Scalar iqMiscInstsIssued;
- /** Stat for number of squashed instructions that were ready to issue. */
- Stats::Scalar iqSquashedInstsIssued;
- /** Stat for number of squashed instructions examined when squashing. */
- Stats::Scalar iqSquashedInstsExamined;
- /** Stat for number of squashed instruction operands examined when
- * squashing.
- */
- Stats::Scalar iqSquashedOperandsExamined;
- /** Stat for number of non-speculative instructions removed due to a squash.
- */
- Stats::Scalar iqSquashedNonSpecRemoved;
- // Also include number of instructions rescheduled and replayed.
-
- /** Distribution of number of instructions in the queue.
- * @todo: Need to create struct to track the entry time for each
- * instruction. */
-// Stats::VectorDistribution queueResDist;
- /** Distribution of the number of instructions issued. */
- Stats::Distribution numIssuedDist;
- /** Distribution of the cycles it takes to issue an instruction.
- * @todo: Need to create struct to track the ready time for each
- * instruction. */
-// Stats::VectorDistribution issueDelayDist;
-
- /** Number of times an instruction could not be issued because a
- * FU was busy.
- */
- Stats::Vector statFuBusy;
-// Stats::Vector dist_unissued;
- /** Stat for total number issued for each instruction type. */
- Stats::Vector2d statIssuedInstType;
-
- /** Number of instructions issued per cycle. */
- Stats::Formula issueRate;
-
- /** Number of times the FU was busy. */
- Stats::Vector fuBusy;
- /** Number of times the FU was busy per instruction issued. */
- Stats::Formula fuBusyRate;
+ struct IQStats : public Stats::Group
+ {
+ IQStats(O3CPU *cpu, const unsigned &total_width);
+ /** Stat for number of instructions added. */
+ Stats::Scalar instsAdded;
+ /** Stat for number of non-speculative instructions added. */
+ Stats::Scalar nonSpecInstsAdded;
+
+ Stats::Scalar instsIssued;
+ /** Stat for number of integer instructions issued. */
+ Stats::Scalar intInstsIssued;
+ /** Stat for number of floating point instructions issued. */
+ Stats::Scalar floatInstsIssued;
+ /** Stat for number of branch instructions issued. */
+ Stats::Scalar branchInstsIssued;
+ /** Stat for number of memory instructions issued. */
+ Stats::Scalar memInstsIssued;
+ /** Stat for number of miscellaneous instructions issued. */
+ Stats::Scalar miscInstsIssued;
+ /** Stat for number of squashed instructions that were ready to
+ * issue. */
+ Stats::Scalar squashedInstsIssued;
+ /** Stat for number of squashed instructions examined when
+ * squashing. */
+ Stats::Scalar squashedInstsExamined;
+ /** Stat for number of squashed instruction operands examined when
+ * squashing.
+ */
+ Stats::Scalar squashedOperandsExamined;
+ /** Stat for number of non-speculative instructions removed due to
+ * a squash.
+ */
+ Stats::Scalar squashedNonSpecRemoved;
+ // Also include number of instructions rescheduled and replayed.
+
+ /** Distribution of number of instructions in the queue.
+ * @todo: Need to create struct to track the entry time for each
+ * instruction. */
+ // Stats::VectorDistribution queueResDist;
+ /** Distribution of the number of instructions issued. */
+ Stats::Distribution numIssuedDist;
+ /** Distribution of the cycles it takes to issue an instruction.
+ * @todo: Need to create struct to track the ready time for each
+ * instruction. */
+ // Stats::VectorDistribution issueDelayDist;
+
+ /** Number of times an instruction could not be issued because a
+ * FU was busy.
+ */
+ Stats::Vector statFuBusy;
+ // Stats::Vector dist_unissued;
+ /** Stat for total number issued for each instruction type. */
+ Stats::Vector2d statIssuedInstType;
+
+ /** Number of instructions issued per cycle. */
+ Stats::Formula issueRate;
+
+ /** Number of times the FU was busy. */
+ Stats::Vector fuBusy;
+ /** Number of times the FU was busy per instruction issued. */
+ Stats::Formula fuBusyRate;
+ } iqStats;
+
public:
- Stats::Scalar intInstQueueReads;
- Stats::Scalar intInstQueueWrites;
- Stats::Scalar intInstQueueWakeupAccesses;
- Stats::Scalar fpInstQueueReads;
- Stats::Scalar fpInstQueueWrites;
- Stats::Scalar fpInstQueueWakeupAccesses;
- Stats::Scalar vecInstQueueReads;
- Stats::Scalar vecInstQueueWrites;
- Stats::Scalar vecInstQueueWakeupAccesses;
-
- Stats::Scalar intAluAccesses;
- Stats::Scalar fpAluAccesses;
- Stats::Scalar vecAluAccesses;
+ struct IQIOStats : public Stats::Group
+ {
+ IQIOStats(Stats::Group *parent);
+ Stats::Scalar intInstQueueReads;
+ Stats::Scalar intInstQueueWrites;
+ Stats::Scalar intInstQueueWakeupAccesses;
+ Stats::Scalar fpInstQueueReads;
+ Stats::Scalar fpInstQueueWrites;
+ Stats::Scalar fpInstQueueWakeupAccesses;
+ Stats::Scalar vecInstQueueReads;
+ Stats::Scalar vecInstQueueWrites;
+ Stats::Scalar vecInstQueueWakeupAccesses;
+
+ Stats::Scalar intAluAccesses;
+ Stats::Scalar fpAluAccesses;
+ Stats::Scalar vecAluAccesses;
+ } iqIOStats;
};
#endif //__CPU_O3_INST_QUEUE_HH__
iewStage(iew_ptr),
fuPool(params.fuPool),
iqPolicy(params.smtIQPolicy),
+ numThreads(params.numThreads),
numEntries(params.numIQEntries),
totalWidth(params.issueWidth),
- commitToIEWDelay(params.commitToIEWDelay)
+ commitToIEWDelay(params.commitToIEWDelay),
+ iqStats(cpu, totalWidth),
+ iqIOStats(cpu)
{
assert(fuPool);
- numThreads = params.numThreads;
-
// Set the number of total physical registers
// As the vector registers have two addressing modes, they are added twice
numPhysRegs = params.numPhysIntRegs + params.numPhysFloatRegs +
}
template <class Impl>
-void
-InstructionQueue<Impl>::regStats()
+InstructionQueue<Impl>::
+IQStats::IQStats(O3CPU *cpu, const unsigned &total_width)
+ : Stats::Group(cpu),
+ ADD_STAT(instsAdded,
+ "Number of instructions added to the IQ (excludes non-spec)"),
+ ADD_STAT(nonSpecInstsAdded,
+ "Number of non-speculative instructions added to the IQ"),
+ ADD_STAT(instsIssued, "Number of instructions issued"),
+ ADD_STAT(intInstsIssued, "Number of integer instructions issued"),
+ ADD_STAT(floatInstsIssued, "Number of float instructions issued"),
+ ADD_STAT(branchInstsIssued, "Number of branch instructions issued"),
+ ADD_STAT(memInstsIssued, "Number of memory instructions issued"),
+ ADD_STAT(miscInstsIssued, "Number of miscellaneous instructions issued"),
+ ADD_STAT(squashedInstsIssued, "Number of squashed instructions issued"),
+ ADD_STAT(squashedInstsExamined,
+ "Number of squashed instructions iterated over during squash; "
+ "mainly for profiling"),
+ ADD_STAT(squashedOperandsExamined,
+ "Number of squashed operands that are examined and possibly "
+ "removed from graph"),
+ ADD_STAT(squashedNonSpecRemoved,
+ "Number of squashed non-spec instructions that were removed"),
+ ADD_STAT(numIssuedDist, "Number of insts issued each cycle"),
+ ADD_STAT(statFuBusy, "attempts to use FU when none available"),
+ ADD_STAT(statIssuedInstType, "Type of FU issued"),
+ ADD_STAT(issueRate, "Inst issue rate", instsIssued / cpu->numCycles),
+ ADD_STAT(fuBusy, "FU busy when requested"),
+ ADD_STAT(fuBusyRate, "FU busy rate (busy events/executed inst)")
{
- using namespace Stats;
- iqInstsAdded
- .name(name() + ".iqInstsAdded")
- .desc("Number of instructions added to the IQ (excludes non-spec)")
- .prereq(iqInstsAdded);
-
- iqNonSpecInstsAdded
- .name(name() + ".iqNonSpecInstsAdded")
- .desc("Number of non-speculative instructions added to the IQ")
- .prereq(iqNonSpecInstsAdded);
-
- iqInstsIssued
- .name(name() + ".iqInstsIssued")
- .desc("Number of instructions issued")
- .prereq(iqInstsIssued);
-
- iqIntInstsIssued
- .name(name() + ".iqIntInstsIssued")
- .desc("Number of integer instructions issued")
- .prereq(iqIntInstsIssued);
-
- iqFloatInstsIssued
- .name(name() + ".iqFloatInstsIssued")
- .desc("Number of float instructions issued")
- .prereq(iqFloatInstsIssued);
-
- iqBranchInstsIssued
- .name(name() + ".iqBranchInstsIssued")
- .desc("Number of branch instructions issued")
- .prereq(iqBranchInstsIssued);
-
- iqMemInstsIssued
- .name(name() + ".iqMemInstsIssued")
- .desc("Number of memory instructions issued")
- .prereq(iqMemInstsIssued);
-
- iqMiscInstsIssued
- .name(name() + ".iqMiscInstsIssued")
- .desc("Number of miscellaneous instructions issued")
- .prereq(iqMiscInstsIssued);
-
- iqSquashedInstsIssued
- .name(name() + ".iqSquashedInstsIssued")
- .desc("Number of squashed instructions issued")
- .prereq(iqSquashedInstsIssued);
-
- iqSquashedInstsExamined
- .name(name() + ".iqSquashedInstsExamined")
- .desc("Number of squashed instructions iterated over during squash;"
- " mainly for profiling")
- .prereq(iqSquashedInstsExamined);
-
- iqSquashedOperandsExamined
- .name(name() + ".iqSquashedOperandsExamined")
- .desc("Number of squashed operands that are examined and possibly "
- "removed from graph")
- .prereq(iqSquashedOperandsExamined);
-
- iqSquashedNonSpecRemoved
- .name(name() + ".iqSquashedNonSpecRemoved")
- .desc("Number of squashed non-spec instructions that were removed")
- .prereq(iqSquashedNonSpecRemoved);
+ instsAdded
+ .prereq(instsAdded);
+
+ nonSpecInstsAdded
+ .prereq(nonSpecInstsAdded);
+
+ instsIssued
+ .prereq(instsIssued);
+
+ intInstsIssued
+ .prereq(intInstsIssued);
+
+ floatInstsIssued
+ .prereq(floatInstsIssued);
+
+ branchInstsIssued
+ .prereq(branchInstsIssued);
+
+ memInstsIssued
+ .prereq(memInstsIssued);
+
+ miscInstsIssued
+ .prereq(miscInstsIssued);
+
+ squashedInstsIssued
+ .prereq(squashedInstsIssued);
+
+ squashedInstsExamined
+ .prereq(squashedInstsExamined);
+
+ squashedOperandsExamined
+ .prereq(squashedOperandsExamined);
+
+ squashedNonSpecRemoved
+ .prereq(squashedNonSpecRemoved);
/*
queueResDist
.init(Num_OpClasses, 0, 99, 2)
}
*/
numIssuedDist
- .init(0,totalWidth,1)
- .name(name() + ".issued_per_cycle")
- .desc("Number of insts issued each cycle")
- .flags(pdf)
+ .init(0,total_width,1)
+ .flags(Stats::pdf)
;
/*
dist_unissued
}
*/
statIssuedInstType
- .init(numThreads,Enums::Num_OpClass)
- .name(name() + ".FU_type")
- .desc("Type of FU issued")
- .flags(total | pdf | dist)
+ .init(cpu->numThreads,Enums::Num_OpClass)
+ .flags(Stats::total | Stats::pdf | Stats::dist)
;
statIssuedInstType.ysubnames(Enums::OpClassStrings);
.desc("cycles from operands ready to issue")
.flags(pdf | cdf)
;
-
for (int i=0; i<Num_OpClasses; ++i) {
std::stringstream subname;
subname << opClassStrings[i] << "_delay";
}
*/
issueRate
- .name(name() + ".rate")
- .desc("Inst issue rate")
- .flags(total)
+ .flags(Stats::total)
;
- issueRate = iqInstsIssued / cpu->numCycles;
statFuBusy
.init(Num_OpClasses)
- .name(name() + ".fu_full")
- .desc("attempts to use FU when none available")
- .flags(pdf | dist)
+ .flags(Stats::pdf | Stats::dist)
;
for (int i=0; i < Num_OpClasses; ++i) {
statFuBusy.subname(i, Enums::OpClassStrings[i]);
}
fuBusy
- .init(numThreads)
- .name(name() + ".fu_busy_cnt")
- .desc("FU busy when requested")
- .flags(total)
+ .init(cpu->numThreads)
+ .flags(Stats::total)
;
fuBusyRate
- .name(name() + ".fu_busy_rate")
- .desc("FU busy rate (busy events/executed inst)")
- .flags(total)
+ .flags(Stats::total)
;
- fuBusyRate = fuBusy / iqInstsIssued;
-
- for (ThreadID tid = 0; tid < numThreads; tid++) {
- // Tell mem dependence unit to reg stats as well.
- memDepUnit[tid].regStats();
- }
+ fuBusyRate = fuBusy / instsIssued;
+}
+template <class Impl>
+InstructionQueue<Impl>::
+IQIOStats::IQIOStats(Stats::Group *parent)
+ : Stats::Group(parent),
+ ADD_STAT(intInstQueueReads, "Number of integer instruction queue reads"),
+ ADD_STAT(intInstQueueWrites, "Number of integer instruction queue writes"),
+ ADD_STAT(intInstQueueWakeupAccesses, "Number of integer instruction queue "
+ "wakeup accesses"),
+ ADD_STAT(fpInstQueueReads, "Number of floating instruction queue reads"),
+ ADD_STAT(fpInstQueueWrites, "Number of floating instruction queue writes"),
+ ADD_STAT(fpInstQueueWakeupAccesses, "Number of floating instruction queue "
+ "wakeup accesses"),
+ ADD_STAT(vecInstQueueReads, "Number of vector instruction queue reads"),
+ ADD_STAT(vecInstQueueWrites, "Number of vector instruction queue writes"),
+ ADD_STAT(vecInstQueueWakeupAccesses, "Number of vector instruction queue "
+ "wakeup accesses"),
+ ADD_STAT(intAluAccesses, "Number of integer alu accesses"),
+ ADD_STAT(fpAluAccesses, "Number of floating point alu accesses"),
+ ADD_STAT(vecAluAccesses, "Number of vector alu accesses")
+{
+ using namespace Stats;
intInstQueueReads
- .name(name() + ".int_inst_queue_reads")
- .desc("Number of integer instruction queue reads")
.flags(total);
intInstQueueWrites
- .name(name() + ".int_inst_queue_writes")
- .desc("Number of integer instruction queue writes")
.flags(total);
intInstQueueWakeupAccesses
- .name(name() + ".int_inst_queue_wakeup_accesses")
- .desc("Number of integer instruction queue wakeup accesses")
.flags(total);
fpInstQueueReads
- .name(name() + ".fp_inst_queue_reads")
- .desc("Number of floating instruction queue reads")
.flags(total);
fpInstQueueWrites
- .name(name() + ".fp_inst_queue_writes")
- .desc("Number of floating instruction queue writes")
.flags(total);
fpInstQueueWakeupAccesses
- .name(name() + ".fp_inst_queue_wakeup_accesses")
- .desc("Number of floating instruction queue wakeup accesses")
.flags(total);
vecInstQueueReads
- .name(name() + ".vec_inst_queue_reads")
- .desc("Number of vector instruction queue reads")
.flags(total);
vecInstQueueWrites
- .name(name() + ".vec_inst_queue_writes")
- .desc("Number of vector instruction queue writes")
.flags(total);
vecInstQueueWakeupAccesses
- .name(name() + ".vec_inst_queue_wakeup_accesses")
- .desc("Number of vector instruction queue wakeup accesses")
.flags(total);
intAluAccesses
- .name(name() + ".int_alu_accesses")
- .desc("Number of integer alu accesses")
.flags(total);
fpAluAccesses
- .name(name() + ".fp_alu_accesses")
- .desc("Number of floating point alu accesses")
.flags(total);
vecAluAccesses
- .name(name() + ".vec_alu_accesses")
- .desc("Number of vector alu accesses")
.flags(total);
-
}
template <class Impl>
InstructionQueue<Impl>::insert(const DynInstPtr &new_inst)
{
if (new_inst->isFloating()) {
- fpInstQueueWrites++;
+ iqIOStats.fpInstQueueWrites++;
} else if (new_inst->isVector()) {
- vecInstQueueWrites++;
+ iqIOStats.vecInstQueueWrites++;
} else {
- intInstQueueWrites++;
+ iqIOStats.intInstQueueWrites++;
}
// Make sure the instruction is valid
assert(new_inst);
addIfReady(new_inst);
}
- ++iqInstsAdded;
+ ++iqStats.instsAdded;
count[new_inst->threadNumber]++;
// @todo: Clean up this code; can do it by setting inst as unable
// to issue, then calling normal insert on the inst.
if (new_inst->isFloating()) {
- fpInstQueueWrites++;
+ iqIOStats.fpInstQueueWrites++;
} else if (new_inst->isVector()) {
- vecInstQueueWrites++;
+ iqIOStats.vecInstQueueWrites++;
} else {
- intInstQueueWrites++;
+ iqIOStats.intInstQueueWrites++;
}
assert(new_inst);
memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
}
- ++iqNonSpecInstsAdded;
+ ++iqStats.nonSpecInstsAdded;
count[new_inst->threadNumber]++;
DynInstPtr inst = std::move(instsToExecute.front());
instsToExecute.pop_front();
if (inst->isFloating()) {
- fpInstQueueReads++;
+ iqIOStats.fpInstQueueReads++;
} else if (inst->isVector()) {
- vecInstQueueReads++;
+ iqIOStats.vecInstQueueReads++;
} else {
- intInstQueueReads++;
+ iqIOStats.intInstQueueReads++;
}
return inst;
}
DynInstPtr issuing_inst = readyInsts[op_class].top();
if (issuing_inst->isFloating()) {
- fpInstQueueReads++;
+ iqIOStats.fpInstQueueReads++;
} else if (issuing_inst->isVector()) {
- vecInstQueueReads++;
+ iqIOStats.vecInstQueueReads++;
} else {
- intInstQueueReads++;
+ iqIOStats.intInstQueueReads++;
}
assert(issuing_inst->seqNum == (*order_it).oldestInst);
listOrder.erase(order_it++);
- ++iqSquashedInstsIssued;
+ ++iqStats.squashedInstsIssued;
continue;
}
if (op_class != No_OpClass) {
idx = fuPool->getUnit(op_class);
if (issuing_inst->isFloating()) {
- fpAluAccesses++;
+ iqIOStats.fpAluAccesses++;
} else if (issuing_inst->isVector()) {
- vecAluAccesses++;
+ iqIOStats.vecAluAccesses++;
} else {
- intAluAccesses++;
+ iqIOStats.intAluAccesses++;
}
if (idx > FUPool::NoFreeFU) {
op_latency = fuPool->getOpLatency(op_class);
}
listOrder.erase(order_it++);
- statIssuedInstType[tid][op_class]++;
+ iqStats.statIssuedInstType[tid][op_class]++;
} else {
- statFuBusy[op_class]++;
- fuBusy[tid]++;
+ iqStats.statFuBusy[op_class]++;
+ iqStats.fuBusy[tid]++;
++order_it;
}
}
- numIssuedDist.sample(total_issued);
- iqInstsIssued+= total_issued;
+ iqStats.numIssuedDist.sample(total_issued);
+ iqStats.instsIssued+= total_issued;
// If we issued any instructions, tell the CPU we had activity.
// @todo If the way deferred memory instructions are handeled due to
// The instruction queue here takes care of both floating and int ops
if (completed_inst->isFloating()) {
- fpInstQueueWakeupAccesses++;
+ iqIOStats.fpInstQueueWakeupAccesses++;
} else if (completed_inst->isVector()) {
- vecInstQueueWakeupAccesses++;
+ iqIOStats.vecInstQueueWakeupAccesses++;
} else {
- intInstQueueWakeupAccesses++;
+ iqIOStats.intInstQueueWakeupAccesses++;
}
DPRINTF(IQ, "Waking dependents of completed instruction.\n");
InstructionQueue<Impl>::violation(const DynInstPtr &store,
const DynInstPtr &faulting_load)
{
- intInstQueueWrites++;
+ iqIOStats.intInstQueueWrites++;
memDepUnit[store->threadNumber].violation(store, faulting_load);
}
DynInstPtr squashed_inst = (*squash_it);
if (squashed_inst->isFloating()) {
- fpInstQueueWrites++;
+ iqIOStats.fpInstQueueWrites++;
} else if (squashed_inst->isVector()) {
- vecInstQueueWrites++;
+ iqIOStats.vecInstQueueWrites++;
} else {
- intInstQueueWrites++;
+ iqIOStats.intInstQueueWrites++;
}
// Only handle the instruction if it actually is in the IQ and
squashed_inst);
}
- ++iqSquashedOperandsExamined;
+ ++iqStats.squashedOperandsExamined;
}
} else if (!squashed_inst->isStoreConditional() ||
nonSpecInsts.erase(ns_inst_it);
- ++iqSquashedNonSpecRemoved;
+ ++iqStats.squashedNonSpecRemoved;
}
}
dependGraph.clearInst(dest_reg->flatIndex());
}
instList[tid].erase(squash_it--);
- ++iqSquashedInstsExamined;
+ ++iqStats.squashedInstsExamined;
}
}