24.22.5.1. gem5 execute vs initiateAcc vs completeAcc

These are the key methods defined in instruction definitions, so lets see when each one gets called and what they do more or less.

execute is the only one of the three that gets defined by "non-memory" instructions.

Memory instructions define all three.

The three methods are present in the base class StaticInst:

    virtual Fault execute(ExecContext *xc,
                          Trace::InstRecord *traceData) const = 0;

    virtual Fault initiateAcc(ExecContext *xc,
                              Trace::InstRecord *traceData) const
    {
        panic("initiateAcc not defined!");
    }

    virtual Fault completeAcc(Packet *pkt, ExecContext *xc,
                              Trace::InstRecord *traceData) const
    {
        panic("completeAcc not defined!");
    }

so we see that all instructions must implement execute, while overriding initiateAcc and completeAcc are optional and only done by classes for which those might get called: memory instructions.

execute is what does the actual job for non-memory instructions (obviously, since it is the only one of the three methods that is defined as not panic for those).

Memory instructions however run either:

  • execute in AtomicSimpleCPU: this does the entire memory access in one go

  • initiateAcc + completeAcc in timing CPUs. initiateAcc is called when the instruction starts executing, and completeAcc is called when the memory fetch returns from the memory system.

This can be seen concretely in GDB from the analysis done at: TimingSimpleCPU analysis: LDR stall and for more memory details see gem5 functional vs atomic vs timing memory requests.