Skip to main content

Creating a New Statistic

When you create a new statistic, you will need to recompile the gem5 source code, which can be quite time-consuming depending on your setup and resources available. This is where it becomes important to be able to read and proofread your code before compiling, and unfortunately without the help of robust code analysis like you may be used to.

Creating a new statistic in an existing simObject is pretty straightforward, you just need to follow the procedure that we went through with the extant statistics. In this page, we will walk you though how to implement a counter for every time an execution unit performs an execution.

Registering Your Statistic

We will be looking at the iew files in src/cpu/o3 of the gem5 source repository.

First step, we need to register our statistic. In order to do this, we can simply add the statistic to the struct of the IEWStats that we saw in the existing statistics:

struct IEWStats : public statistics::Group
{
IEWStats(CPU *cpu);

/** My statistic for counting number of executions */
statistics::Scalar execStageUses;
/** Stat for total number of idle cycles. */
statistics::Scalar idleCycles;
...

Now we have a statistic registered to the program, next we instantiate

Instantiating Your Statistic

We can now add it to the pool of instructions that we use to work with in the iew.cc file:

IEW::IEWStats::IEWStats(CPU *cpu)
: statistics::Group(cpu, "iew"),
ADD_STAT(execStageUses, statistics::units::Count::get(),
"Number of times the Execution stage is used"),
ADD_STAT(idleCycles, statistics::units::Cycle::get(),
"Number of cycles IEW is idle"),
ADD_STAT(squashCycles, statistics::units::Cycle::get(),
"Number of cycles IEW is squashing"),
...

Using the Statistic

This is really the trickiest part of this statistic, we need to find every time that we actually dispatch an instruction for execution in the simulation. In order to do so, you need to READ THE CODE.

Fortunately for us, I can guide you to where we actually implement this. Since we want to track any time an instruction begins executing, we will want to find the executeInsts function. Now, this is where you can get some subjectivity in what your statistic is actually tracking. In this case, even if an instruction is squashed, I want to know that it touched an execution unit. So for my purposes, I will place the call to increment my statistic at line 1130 of iew.cc:

for (; inst_num < insts_to_execute;
++inst_num) {

DPRINTF(IEW, "Execute: Executing instructions from IQ.\n");

DynInstPtr inst = instQueue.getInstToExecute();

DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%llu].\n",
inst->pcState(), inst->threadNumber,inst->seqNum);

// Notify potential listeners that this instruction has started
// executing
ppExecute->notify(inst);

iewStats.execStageUses++;

// Check if the instruction is squashed; if so then skip it
if (inst->isSquashed()) {

Recompile

Since we only added a statistic to an existing system, we do not need to modify the sconscript files. If, on the other hand, you created your own custom component, then you will need to add your component to the build system.