24.22.4.2.6. TimingSimpleCPU analysis #6

Schedules DRAMCtrl::processNextReqEvent through:

EventManager::schedule
DRAMCtrl::addToReadQueue
DRAMCtrl::recvTimingReq
DRAMCtrl::MemoryPort::recvTimingReq
TimingRequestProtocol::sendReq
MasterPort::sendTimingReq
CoherentXBar::recvTimingReq
CoherentXBar::CoherentXBarSlavePort::recvTimingReq
TimingRequestProtocol::sendReq
MasterPort::sendTimingReq
TimingSimpleCPU::sendFetch
TimingSimpleCPU::FetchTranslation::finish
ArmISA::TLB::translateComplete
ArmISA::TLB::translateTiming
ArmISA::TLB::translateTiming
TimingSimpleCPU::fetch

The event loop has started, and magic initialization schedulings are not happening anymore: now every event is being scheduled from another event:

From the trace, we see that we are already running from the event queue under TimingSimpleCPU::fetch as expected.

From the backtrace we see the tortuous path that the data request takes, going through:

  • ArmISA::TLB

  • CoherentXBar

  • DRAMCtrl

This matches the config.ini system image, since we see that the request goes through the CoherentXBar before reaching memory, like all other CPU memory accesses, see also: gem5 crossbar interconnect.

The scheduling happens at frame DRAMCtrl::addToReadQueue:

     // If we are not already scheduled to get a request out of the
     // queue, do so now
     if (!nextReqEvent.scheduled()) {
         DPRINTF(DRAM, "Request scheduled immediately\n");
         schedule(nextReqEvent, curTick());
     }

From this we deduce that the DRAM has a request queue of some sort, and that the fetch:

  • has added a read request to that queue

  • and has made a future request to read from the queue

The signature of the function is:

DRAMCtrl::addToReadQueue(PacketPtr pkt, unsigned int pktCount)

where PacketPtr is of class `Packet, and so clearly the packet is coming from above.

From:

p/x *pkt

we see:

addr = 0x78

which from TimingSimpleCPU analysis #5 we know is the physical address of the ELF entry point.

Communication goes through certain components via the class Port interface, e.g. at TimingSimpleCPU::sendFetch a call is made to send the packet forward:

icachePort.sendTimingReq(ifetch_pkt)

which ends up calling:

peer->recvTimingReq(pkt);

to reach the receiving side:

CoherentXBar::CoherentXBarSlavePort::recvTimingReq

Ports are also used to connect the XBar and the DRAM.

We will then see that at TimingSimpleCPU analysis #20 a reply packet will come back through the port interface down to the icache port, and only then does the decoding and execution happen.