trace_cpu.cc revision 11632
111249Sradhika.jagtap@ARM.com/*
211631Sradhika.jagtap@arm.com * Copyright (c) 2013 - 2016 ARM Limited
311249Sradhika.jagtap@ARM.com * All rights reserved
411249Sradhika.jagtap@ARM.com *
511249Sradhika.jagtap@ARM.com * The license below extends only to copyright in the software and shall
611249Sradhika.jagtap@ARM.com * not be construed as granting a license to any other intellectual
711249Sradhika.jagtap@ARM.com * property including but not limited to intellectual property relating
811249Sradhika.jagtap@ARM.com * to a hardware implementation of the functionality of the software
911249Sradhika.jagtap@ARM.com * licensed hereunder.  You may use the software subject to the license
1011249Sradhika.jagtap@ARM.com * terms below provided that you ensure that this notice is replicated
1111249Sradhika.jagtap@ARM.com * unmodified and in its entirety in all distributions of the software,
1211249Sradhika.jagtap@ARM.com * modified or unmodified, in source code or in binary form.
1311249Sradhika.jagtap@ARM.com *
1411249Sradhika.jagtap@ARM.com * Redistribution and use in source and binary forms, with or without
1511249Sradhika.jagtap@ARM.com * modification, are permitted provided that the following conditions are
1611249Sradhika.jagtap@ARM.com * met: redistributions of source code must retain the above copyright
1711249Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer;
1811249Sradhika.jagtap@ARM.com * redistributions in binary form must reproduce the above copyright
1911249Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer in the
2011249Sradhika.jagtap@ARM.com * documentation and/or other materials provided with the distribution;
2111249Sradhika.jagtap@ARM.com * neither the name of the copyright holders nor the names of its
2211249Sradhika.jagtap@ARM.com * contributors may be used to endorse or promote products derived from
2311249Sradhika.jagtap@ARM.com * this software without specific prior written permission.
2411249Sradhika.jagtap@ARM.com *
2511249Sradhika.jagtap@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2611249Sradhika.jagtap@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2711249Sradhika.jagtap@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2811249Sradhika.jagtap@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2911249Sradhika.jagtap@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3011249Sradhika.jagtap@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3111249Sradhika.jagtap@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3211249Sradhika.jagtap@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3311249Sradhika.jagtap@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3411249Sradhika.jagtap@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3511249Sradhika.jagtap@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3611249Sradhika.jagtap@ARM.com *
3711249Sradhika.jagtap@ARM.com * Authors: Radhika Jagtap
3811249Sradhika.jagtap@ARM.com *          Andreas Hansson
3911249Sradhika.jagtap@ARM.com *          Thomas Grass
4011249Sradhika.jagtap@ARM.com */
4111249Sradhika.jagtap@ARM.com
4211249Sradhika.jagtap@ARM.com#include "cpu/trace/trace_cpu.hh"
4311249Sradhika.jagtap@ARM.com
4411249Sradhika.jagtap@ARM.com#include "sim/sim_exit.hh"
4511249Sradhika.jagtap@ARM.com
4611249Sradhika.jagtap@ARM.com// Declare and initialize the static counter for number of trace CPUs.
4711249Sradhika.jagtap@ARM.comint TraceCPU::numTraceCPUs = 0;
4811249Sradhika.jagtap@ARM.com
4911249Sradhika.jagtap@ARM.comTraceCPU::TraceCPU(TraceCPUParams *params)
5011249Sradhika.jagtap@ARM.com    :   BaseCPU(params),
5111249Sradhika.jagtap@ARM.com        icachePort(this),
5211249Sradhika.jagtap@ARM.com        dcachePort(this),
5311249Sradhika.jagtap@ARM.com        instMasterID(params->system->getMasterId(name() + ".inst")),
5411249Sradhika.jagtap@ARM.com        dataMasterID(params->system->getMasterId(name() + ".data")),
5511249Sradhika.jagtap@ARM.com        instTraceFile(params->instTraceFile),
5611249Sradhika.jagtap@ARM.com        dataTraceFile(params->dataTraceFile),
5711249Sradhika.jagtap@ARM.com        icacheGen(*this, ".iside", icachePort, instMasterID, instTraceFile),
5811249Sradhika.jagtap@ARM.com        dcacheGen(*this, ".dside", dcachePort, dataMasterID, dataTraceFile,
5911631Sradhika.jagtap@arm.com                  params),
6011249Sradhika.jagtap@ARM.com        icacheNextEvent(this),
6111249Sradhika.jagtap@ARM.com        dcacheNextEvent(this),
6211249Sradhika.jagtap@ARM.com        oneTraceComplete(false),
6311632Sradhika.jagtap@arm.com        traceOffset(0),
6411249Sradhika.jagtap@ARM.com        execCompleteEvent(nullptr)
6511249Sradhika.jagtap@ARM.com{
6611249Sradhika.jagtap@ARM.com    // Increment static counter for number of Trace CPUs.
6711249Sradhika.jagtap@ARM.com    ++TraceCPU::numTraceCPUs;
6811249Sradhika.jagtap@ARM.com
6911249Sradhika.jagtap@ARM.com    // Check that the python parameters for sizes of ROB, store buffer and load
7011249Sradhika.jagtap@ARM.com    // buffer do not overflow the corresponding C++ variables.
7111249Sradhika.jagtap@ARM.com    fatal_if(params->sizeROB > UINT16_MAX, "ROB size set to %d exceeds the "
7211249Sradhika.jagtap@ARM.com                "max. value of %d.\n", params->sizeROB, UINT16_MAX);
7311249Sradhika.jagtap@ARM.com    fatal_if(params->sizeStoreBuffer > UINT16_MAX, "ROB size set to %d "
7411249Sradhika.jagtap@ARM.com                "exceeds the max. value of %d.\n", params->sizeROB,
7511249Sradhika.jagtap@ARM.com                UINT16_MAX);
7611249Sradhika.jagtap@ARM.com    fatal_if(params->sizeLoadBuffer > UINT16_MAX, "Load buffer size set to"
7711249Sradhika.jagtap@ARM.com                " %d exceeds the max. value of %d.\n",
7811249Sradhika.jagtap@ARM.com                params->sizeLoadBuffer, UINT16_MAX);
7911249Sradhika.jagtap@ARM.com}
8011249Sradhika.jagtap@ARM.com
8111249Sradhika.jagtap@ARM.comTraceCPU::~TraceCPU()
8211249Sradhika.jagtap@ARM.com{
8311249Sradhika.jagtap@ARM.com
8411249Sradhika.jagtap@ARM.com}
8511249Sradhika.jagtap@ARM.com
8611249Sradhika.jagtap@ARM.comTraceCPU*
8711249Sradhika.jagtap@ARM.comTraceCPUParams::create()
8811249Sradhika.jagtap@ARM.com{
8911249Sradhika.jagtap@ARM.com    return new TraceCPU(this);
9011249Sradhika.jagtap@ARM.com}
9111249Sradhika.jagtap@ARM.com
9211249Sradhika.jagtap@ARM.comvoid
9311249Sradhika.jagtap@ARM.comTraceCPU::takeOverFrom(BaseCPU *oldCPU)
9411249Sradhika.jagtap@ARM.com{
9511249Sradhika.jagtap@ARM.com    // Unbind the ports of the old CPU and bind the ports of the TraceCPU.
9611249Sradhika.jagtap@ARM.com    assert(!getInstPort().isConnected());
9711249Sradhika.jagtap@ARM.com    assert(oldCPU->getInstPort().isConnected());
9811249Sradhika.jagtap@ARM.com    BaseSlavePort &inst_peer_port = oldCPU->getInstPort().getSlavePort();
9911249Sradhika.jagtap@ARM.com    oldCPU->getInstPort().unbind();
10011249Sradhika.jagtap@ARM.com    getInstPort().bind(inst_peer_port);
10111249Sradhika.jagtap@ARM.com
10211249Sradhika.jagtap@ARM.com    assert(!getDataPort().isConnected());
10311249Sradhika.jagtap@ARM.com    assert(oldCPU->getDataPort().isConnected());
10411249Sradhika.jagtap@ARM.com    BaseSlavePort &data_peer_port = oldCPU->getDataPort().getSlavePort();
10511249Sradhika.jagtap@ARM.com    oldCPU->getDataPort().unbind();
10611249Sradhika.jagtap@ARM.com    getDataPort().bind(data_peer_port);
10711249Sradhika.jagtap@ARM.com}
10811249Sradhika.jagtap@ARM.com
10911249Sradhika.jagtap@ARM.comvoid
11011249Sradhika.jagtap@ARM.comTraceCPU::init()
11111249Sradhika.jagtap@ARM.com{
11211249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "Instruction fetch request trace file is \"%s\"."
11311249Sradhika.jagtap@ARM.com            "\n", instTraceFile);
11411249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Data memory request trace file is \"%s\".\n",
11511249Sradhika.jagtap@ARM.com            dataTraceFile);
11611249Sradhika.jagtap@ARM.com
11711249Sradhika.jagtap@ARM.com    BaseCPU::init();
11811249Sradhika.jagtap@ARM.com
11911632Sradhika.jagtap@arm.com    // Get the send tick of the first instruction read request
12011249Sradhika.jagtap@ARM.com    Tick first_icache_tick = icacheGen.init();
12111249Sradhika.jagtap@ARM.com
12211632Sradhika.jagtap@arm.com    // Get the send tick of the first data read/write request
12311249Sradhika.jagtap@ARM.com    Tick first_dcache_tick = dcacheGen.init();
12411632Sradhika.jagtap@arm.com
12511632Sradhika.jagtap@arm.com    // Set the trace offset as the minimum of that in both traces
12611632Sradhika.jagtap@arm.com    traceOffset = std::min(first_icache_tick, first_dcache_tick);
12711632Sradhika.jagtap@arm.com    inform("%s: Time offset (tick) found as min of both traces is %lli.\n",
12811632Sradhika.jagtap@arm.com            name(), traceOffset);
12911632Sradhika.jagtap@arm.com
13011632Sradhika.jagtap@arm.com    // Schedule next icache and dcache event by subtracting the offset
13111632Sradhika.jagtap@arm.com    schedule(icacheNextEvent, first_icache_tick - traceOffset);
13211632Sradhika.jagtap@arm.com    schedule(dcacheNextEvent, first_dcache_tick - traceOffset);
13311632Sradhika.jagtap@arm.com
13411632Sradhika.jagtap@arm.com    // Adjust the trace offset for the dcache generator's ready nodes
13511632Sradhika.jagtap@arm.com    // We don't need to do this for the icache generator as it will
13611632Sradhika.jagtap@arm.com    // send its first request at the first event and schedule subsequent
13711632Sradhika.jagtap@arm.com    // events using a relative tick delta
13811632Sradhika.jagtap@arm.com    dcacheGen.adjustInitTraceOffset(traceOffset);
13911249Sradhika.jagtap@ARM.com
14011249Sradhika.jagtap@ARM.com    // The static counter for number of Trace CPUs is correctly set at this
14111249Sradhika.jagtap@ARM.com    // point so create an event and pass it.
14211249Sradhika.jagtap@ARM.com    execCompleteEvent = new CountedExitEvent("end of all traces reached.",
14311249Sradhika.jagtap@ARM.com                                                numTraceCPUs);
14411249Sradhika.jagtap@ARM.com}
14511249Sradhika.jagtap@ARM.com
14611249Sradhika.jagtap@ARM.comvoid
14711249Sradhika.jagtap@ARM.comTraceCPU::schedIcacheNext()
14811249Sradhika.jagtap@ARM.com{
14911249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "IcacheGen event.\n");
15011249Sradhika.jagtap@ARM.com
15111249Sradhika.jagtap@ARM.com    // Try to send the current packet or a retry packet if there is one
15211249Sradhika.jagtap@ARM.com    bool sched_next = icacheGen.tryNext();
15311249Sradhika.jagtap@ARM.com    // If packet sent successfully, schedule next event
15411249Sradhika.jagtap@ARM.com    if (sched_next) {
15511249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUInst, "Scheduling next icacheGen event "
15611249Sradhika.jagtap@ARM.com                "at %d.\n", curTick() + icacheGen.tickDelta());
15711249Sradhika.jagtap@ARM.com        schedule(icacheNextEvent, curTick() + icacheGen.tickDelta());
15811249Sradhika.jagtap@ARM.com        ++numSchedIcacheEvent;
15911249Sradhika.jagtap@ARM.com    } else {
16011249Sradhika.jagtap@ARM.com        // check if traceComplete. If not, do nothing because sending failed
16111249Sradhika.jagtap@ARM.com        // and next event will be scheduled via RecvRetry()
16211249Sradhika.jagtap@ARM.com        if (icacheGen.isTraceComplete()) {
16311249Sradhika.jagtap@ARM.com            // If this is the first trace to complete, set the variable. If it
16411249Sradhika.jagtap@ARM.com            // is already set then both traces are complete to exit sim.
16511249Sradhika.jagtap@ARM.com            checkAndSchedExitEvent();
16611249Sradhika.jagtap@ARM.com        }
16711249Sradhika.jagtap@ARM.com    }
16811249Sradhika.jagtap@ARM.com    return;
16911249Sradhika.jagtap@ARM.com}
17011249Sradhika.jagtap@ARM.com
17111249Sradhika.jagtap@ARM.comvoid
17211249Sradhika.jagtap@ARM.comTraceCPU::schedDcacheNext()
17311249Sradhika.jagtap@ARM.com{
17411249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "DcacheGen event.\n");
17511249Sradhika.jagtap@ARM.com
17611632Sradhika.jagtap@arm.com    // Update stat for numCycles
17711632Sradhika.jagtap@arm.com    numCycles = clockEdge() / clockPeriod();
17811632Sradhika.jagtap@arm.com
17911249Sradhika.jagtap@ARM.com    dcacheGen.execute();
18011249Sradhika.jagtap@ARM.com    if (dcacheGen.isExecComplete()) {
18111249Sradhika.jagtap@ARM.com        checkAndSchedExitEvent();
18211249Sradhika.jagtap@ARM.com    }
18311249Sradhika.jagtap@ARM.com}
18411249Sradhika.jagtap@ARM.com
18511249Sradhika.jagtap@ARM.comvoid
18611249Sradhika.jagtap@ARM.comTraceCPU::checkAndSchedExitEvent()
18711249Sradhika.jagtap@ARM.com{
18811249Sradhika.jagtap@ARM.com    if (!oneTraceComplete) {
18911249Sradhika.jagtap@ARM.com        oneTraceComplete = true;
19011249Sradhika.jagtap@ARM.com    } else {
19111249Sradhika.jagtap@ARM.com        // Schedule event to indicate execution is complete as both
19211249Sradhika.jagtap@ARM.com        // instruction and data access traces have been played back.
19311249Sradhika.jagtap@ARM.com        inform("%s: Execution complete.\n", name());
19411249Sradhika.jagtap@ARM.com        schedule(*execCompleteEvent, curTick());
19511249Sradhika.jagtap@ARM.com    }
19611249Sradhika.jagtap@ARM.com}
19711249Sradhika.jagtap@ARM.com
19811249Sradhika.jagtap@ARM.comvoid
19911249Sradhika.jagtap@ARM.comTraceCPU::regStats()
20011249Sradhika.jagtap@ARM.com{
20111249Sradhika.jagtap@ARM.com
20211249Sradhika.jagtap@ARM.com    BaseCPU::regStats();
20311249Sradhika.jagtap@ARM.com
20411249Sradhika.jagtap@ARM.com    numSchedDcacheEvent
20511249Sradhika.jagtap@ARM.com    .name(name() + ".numSchedDcacheEvent")
20611249Sradhika.jagtap@ARM.com    .desc("Number of events scheduled to trigger data request generator")
20711249Sradhika.jagtap@ARM.com    ;
20811249Sradhika.jagtap@ARM.com
20911249Sradhika.jagtap@ARM.com    numSchedIcacheEvent
21011249Sradhika.jagtap@ARM.com    .name(name() + ".numSchedIcacheEvent")
21111249Sradhika.jagtap@ARM.com    .desc("Number of events scheduled to trigger instruction request generator")
21211249Sradhika.jagtap@ARM.com    ;
21311249Sradhika.jagtap@ARM.com
21411249Sradhika.jagtap@ARM.com    numOps
21511249Sradhika.jagtap@ARM.com    .name(name() + ".numOps")
21611249Sradhika.jagtap@ARM.com    .desc("Number of micro-ops simulated by the Trace CPU")
21711249Sradhika.jagtap@ARM.com    ;
21811249Sradhika.jagtap@ARM.com
21911249Sradhika.jagtap@ARM.com    cpi
22011249Sradhika.jagtap@ARM.com    .name(name() + ".cpi")
22111249Sradhika.jagtap@ARM.com    .desc("Cycles per micro-op used as a proxy for CPI")
22211249Sradhika.jagtap@ARM.com    .precision(6)
22311249Sradhika.jagtap@ARM.com    ;
22411249Sradhika.jagtap@ARM.com    cpi = numCycles/numOps;
22511249Sradhika.jagtap@ARM.com
22611249Sradhika.jagtap@ARM.com    icacheGen.regStats();
22711249Sradhika.jagtap@ARM.com    dcacheGen.regStats();
22811249Sradhika.jagtap@ARM.com}
22911249Sradhika.jagtap@ARM.com
23011249Sradhika.jagtap@ARM.comvoid
23111249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::regStats()
23211249Sradhika.jagtap@ARM.com{
23311249Sradhika.jagtap@ARM.com    using namespace Stats;
23411249Sradhika.jagtap@ARM.com
23511249Sradhika.jagtap@ARM.com    maxDependents
23611249Sradhika.jagtap@ARM.com    .name(name() + ".maxDependents")
23711249Sradhika.jagtap@ARM.com    .desc("Max number of dependents observed on a node")
23811249Sradhika.jagtap@ARM.com    ;
23911249Sradhika.jagtap@ARM.com
24011249Sradhika.jagtap@ARM.com    maxReadyListSize
24111249Sradhika.jagtap@ARM.com    .name(name() + ".maxReadyListSize")
24211249Sradhika.jagtap@ARM.com    .desc("Max size of the ready list observed")
24311249Sradhika.jagtap@ARM.com    ;
24411249Sradhika.jagtap@ARM.com
24511249Sradhika.jagtap@ARM.com    numSendAttempted
24611249Sradhika.jagtap@ARM.com    .name(name() + ".numSendAttempted")
24711249Sradhika.jagtap@ARM.com    .desc("Number of first attempts to send a request")
24811249Sradhika.jagtap@ARM.com    ;
24911249Sradhika.jagtap@ARM.com
25011249Sradhika.jagtap@ARM.com    numSendSucceeded
25111249Sradhika.jagtap@ARM.com    .name(name() + ".numSendSucceeded")
25211249Sradhika.jagtap@ARM.com    .desc("Number of successful first attempts")
25311249Sradhika.jagtap@ARM.com    ;
25411249Sradhika.jagtap@ARM.com
25511249Sradhika.jagtap@ARM.com    numSendFailed
25611249Sradhika.jagtap@ARM.com    .name(name() + ".numSendFailed")
25711249Sradhika.jagtap@ARM.com    .desc("Number of failed first attempts")
25811249Sradhika.jagtap@ARM.com    ;
25911249Sradhika.jagtap@ARM.com
26011249Sradhika.jagtap@ARM.com    numRetrySucceeded
26111249Sradhika.jagtap@ARM.com    .name(name() + ".numRetrySucceeded")
26211249Sradhika.jagtap@ARM.com    .desc("Number of successful retries")
26311249Sradhika.jagtap@ARM.com    ;
26411249Sradhika.jagtap@ARM.com
26511249Sradhika.jagtap@ARM.com    numSplitReqs
26611249Sradhika.jagtap@ARM.com    .name(name() + ".numSplitReqs")
26711249Sradhika.jagtap@ARM.com    .desc("Number of split requests")
26811249Sradhika.jagtap@ARM.com    ;
26911249Sradhika.jagtap@ARM.com
27011249Sradhika.jagtap@ARM.com    numSOLoads
27111249Sradhika.jagtap@ARM.com    .name(name() + ".numSOLoads")
27211249Sradhika.jagtap@ARM.com    .desc("Number of strictly ordered loads")
27311249Sradhika.jagtap@ARM.com    ;
27411249Sradhika.jagtap@ARM.com
27511249Sradhika.jagtap@ARM.com    numSOStores
27611249Sradhika.jagtap@ARM.com    .name(name() + ".numSOStores")
27711249Sradhika.jagtap@ARM.com    .desc("Number of strictly ordered stores")
27811249Sradhika.jagtap@ARM.com    ;
27911249Sradhika.jagtap@ARM.com
28011249Sradhika.jagtap@ARM.com    dataLastTick
28111249Sradhika.jagtap@ARM.com    .name(name() + ".dataLastTick")
28211249Sradhika.jagtap@ARM.com    .desc("Last tick simulated from the elastic data trace")
28311249Sradhika.jagtap@ARM.com    ;
28411249Sradhika.jagtap@ARM.com}
28511249Sradhika.jagtap@ARM.com
28611249Sradhika.jagtap@ARM.comTick
28711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::init()
28811249Sradhika.jagtap@ARM.com{
28911249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Initializing data memory request generator "
29011249Sradhika.jagtap@ARM.com            "DcacheGen: elastic issue with retry.\n");
29111249Sradhika.jagtap@ARM.com
29211249Sradhika.jagtap@ARM.com    if (!readNextWindow())
29311249Sradhika.jagtap@ARM.com        panic("Trace has %d elements. It must have at least %d elements.\n",
29411249Sradhika.jagtap@ARM.com              depGraph.size(), 2 * windowSize);
29511249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "After 1st read, depGraph size:%d.\n",
29611249Sradhika.jagtap@ARM.com            depGraph.size());
29711249Sradhika.jagtap@ARM.com
29811249Sradhika.jagtap@ARM.com    if (!readNextWindow())
29911249Sradhika.jagtap@ARM.com        panic("Trace has %d elements. It must have at least %d elements.\n",
30011249Sradhika.jagtap@ARM.com              depGraph.size(), 2 * windowSize);
30111249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "After 2st read, depGraph size:%d.\n",
30211249Sradhika.jagtap@ARM.com            depGraph.size());
30311249Sradhika.jagtap@ARM.com
30411249Sradhika.jagtap@ARM.com    // Print readyList
30511249Sradhika.jagtap@ARM.com    if (DTRACE(TraceCPUData)) {
30611249Sradhika.jagtap@ARM.com        printReadyList();
30711249Sradhika.jagtap@ARM.com    }
30811249Sradhika.jagtap@ARM.com    auto free_itr = readyList.begin();
30911249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Execute tick of the first dependency free node %lli"
31011249Sradhika.jagtap@ARM.com            " is %d.\n", free_itr->seqNum, free_itr->execTick);
31111249Sradhika.jagtap@ARM.com    // Return the execute tick of the earliest ready node so that an event
31211249Sradhika.jagtap@ARM.com    // can be scheduled to call execute()
31311249Sradhika.jagtap@ARM.com    return (free_itr->execTick);
31411249Sradhika.jagtap@ARM.com}
31511249Sradhika.jagtap@ARM.com
31611249Sradhika.jagtap@ARM.comvoid
31711632Sradhika.jagtap@arm.comTraceCPU::ElasticDataGen::adjustInitTraceOffset(Tick& offset) {
31811632Sradhika.jagtap@arm.com    for (auto& free_node : readyList) {
31911632Sradhika.jagtap@arm.com        free_node.execTick -= offset;
32011632Sradhika.jagtap@arm.com    }
32111632Sradhika.jagtap@arm.com}
32211632Sradhika.jagtap@arm.com
32311632Sradhika.jagtap@arm.comvoid
32411249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::exit()
32511249Sradhika.jagtap@ARM.com{
32611249Sradhika.jagtap@ARM.com    trace.reset();
32711249Sradhika.jagtap@ARM.com}
32811249Sradhika.jagtap@ARM.com
32911249Sradhika.jagtap@ARM.combool
33011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::readNextWindow()
33111249Sradhika.jagtap@ARM.com{
33211249Sradhika.jagtap@ARM.com
33311249Sradhika.jagtap@ARM.com    // Read and add next window
33411249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Reading next window from file.\n");
33511249Sradhika.jagtap@ARM.com
33611249Sradhika.jagtap@ARM.com    if (traceComplete) {
33711249Sradhika.jagtap@ARM.com        // We are at the end of the file, thus we have no more records.
33811249Sradhika.jagtap@ARM.com        // Return false.
33911249Sradhika.jagtap@ARM.com        return false;
34011249Sradhika.jagtap@ARM.com    }
34111249Sradhika.jagtap@ARM.com
34211249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Start read: Size of depGraph is %d.\n",
34311249Sradhika.jagtap@ARM.com            depGraph.size());
34411249Sradhika.jagtap@ARM.com
34511249Sradhika.jagtap@ARM.com    uint32_t num_read = 0;
34611249Sradhika.jagtap@ARM.com    while (num_read != windowSize) {
34711249Sradhika.jagtap@ARM.com
34811249Sradhika.jagtap@ARM.com        // Create a new graph node
34911249Sradhika.jagtap@ARM.com        GraphNode* new_node = new GraphNode;
35011249Sradhika.jagtap@ARM.com
35111249Sradhika.jagtap@ARM.com        // Read the next line to get the next record. If that fails then end of
35211249Sradhika.jagtap@ARM.com        // trace has been reached and traceComplete needs to be set in addition
35311249Sradhika.jagtap@ARM.com        // to returning false.
35411249Sradhika.jagtap@ARM.com        if (!trace.read(new_node)) {
35511249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUData, "\tTrace complete!\n");
35611249Sradhika.jagtap@ARM.com            traceComplete = true;
35711249Sradhika.jagtap@ARM.com            return false;
35811249Sradhika.jagtap@ARM.com        }
35911249Sradhika.jagtap@ARM.com
36011249Sradhika.jagtap@ARM.com        // Annotate the ROB dependencies of the new node onto the parent nodes.
36111249Sradhika.jagtap@ARM.com        addDepsOnParent(new_node, new_node->robDep, new_node->numRobDep);
36211249Sradhika.jagtap@ARM.com        // Annotate the register dependencies of the new node onto the parent
36311249Sradhika.jagtap@ARM.com        // nodes.
36411249Sradhika.jagtap@ARM.com        addDepsOnParent(new_node, new_node->regDep, new_node->numRegDep);
36511249Sradhika.jagtap@ARM.com
36611249Sradhika.jagtap@ARM.com        num_read++;
36711249Sradhika.jagtap@ARM.com        // Add to map
36811249Sradhika.jagtap@ARM.com        depGraph[new_node->seqNum] = new_node;
36911249Sradhika.jagtap@ARM.com        if (new_node->numRobDep == 0 && new_node->numRegDep == 0) {
37011249Sradhika.jagtap@ARM.com            // Source dependencies are already complete, check if resources
37111249Sradhika.jagtap@ARM.com            // are available and issue. The execution time is approximated
37211249Sradhika.jagtap@ARM.com            // to current time plus the computational delay.
37311249Sradhika.jagtap@ARM.com            checkAndIssue(new_node);
37411249Sradhika.jagtap@ARM.com        }
37511249Sradhika.jagtap@ARM.com    }
37611249Sradhika.jagtap@ARM.com
37711249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "End read: Size of depGraph is %d.\n",
37811249Sradhika.jagtap@ARM.com            depGraph.size());
37911249Sradhika.jagtap@ARM.com    return true;
38011249Sradhika.jagtap@ARM.com}
38111249Sradhika.jagtap@ARM.com
38211249Sradhika.jagtap@ARM.comtemplate<typename T> void
38311249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::addDepsOnParent(GraphNode *new_node,
38411249Sradhika.jagtap@ARM.com                                            T& dep_array, uint8_t& num_dep)
38511249Sradhika.jagtap@ARM.com{
38611249Sradhika.jagtap@ARM.com    for (auto& a_dep : dep_array) {
38711249Sradhika.jagtap@ARM.com        // The convention is to set the dependencies starting with the first
38811249Sradhika.jagtap@ARM.com        // index in the ROB and register dependency arrays. Thus, when we reach
38911249Sradhika.jagtap@ARM.com        // a dependency equal to the initialisation value of zero, we know have
39011249Sradhika.jagtap@ARM.com        // iterated over all dependencies and can break.
39111249Sradhika.jagtap@ARM.com        if (a_dep == 0)
39211249Sradhika.jagtap@ARM.com            break;
39311249Sradhika.jagtap@ARM.com        // We look up the valid dependency, i.e. the parent of this node
39411249Sradhika.jagtap@ARM.com        auto parent_itr = depGraph.find(a_dep);
39511249Sradhika.jagtap@ARM.com        if (parent_itr != depGraph.end()) {
39611249Sradhika.jagtap@ARM.com            // If the parent is found, it is yet to be executed. Append a
39711249Sradhika.jagtap@ARM.com            // pointer to the new node to the dependents list of the parent
39811249Sradhika.jagtap@ARM.com            // node.
39911249Sradhika.jagtap@ARM.com            parent_itr->second->dependents.push_back(new_node);
40011249Sradhika.jagtap@ARM.com            auto num_depts = parent_itr->second->dependents.size();
40111249Sradhika.jagtap@ARM.com            maxDependents = std::max<double>(num_depts, maxDependents.value());
40211249Sradhika.jagtap@ARM.com        } else {
40311249Sradhika.jagtap@ARM.com            // The dependency is not found in the graph. So consider
40411249Sradhika.jagtap@ARM.com            // the execution of the parent is complete, i.e. remove this
40511249Sradhika.jagtap@ARM.com            // dependency.
40611249Sradhika.jagtap@ARM.com            a_dep = 0;
40711249Sradhika.jagtap@ARM.com            num_dep--;
40811249Sradhika.jagtap@ARM.com        }
40911249Sradhika.jagtap@ARM.com    }
41011249Sradhika.jagtap@ARM.com}
41111249Sradhika.jagtap@ARM.com
41211249Sradhika.jagtap@ARM.comvoid
41311249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::execute()
41411249Sradhika.jagtap@ARM.com{
41511249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Execute start occupancy:\n");
41611249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "\tdepGraph = %d, readyList = %d, "
41711249Sradhika.jagtap@ARM.com            "depFreeQueue = %d ,", depGraph.size(), readyList.size(),
41811249Sradhika.jagtap@ARM.com            depFreeQueue.size());
41911249Sradhika.jagtap@ARM.com    hwResource.printOccupancy();
42011249Sradhika.jagtap@ARM.com
42111249Sradhika.jagtap@ARM.com    // Read next window to make sure that dependents of all dep-free nodes
42211249Sradhika.jagtap@ARM.com    // are in the depGraph
42311249Sradhika.jagtap@ARM.com    if (nextRead) {
42411249Sradhika.jagtap@ARM.com        readNextWindow();
42511249Sradhika.jagtap@ARM.com        nextRead = false;
42611249Sradhika.jagtap@ARM.com    }
42711249Sradhika.jagtap@ARM.com
42811249Sradhika.jagtap@ARM.com    // First attempt to issue the pending dependency-free nodes held
42911249Sradhika.jagtap@ARM.com    // in depFreeQueue. If resources have become available for a node,
43011249Sradhika.jagtap@ARM.com    // then issue it, i.e. add the node to readyList.
43111249Sradhika.jagtap@ARM.com    while (!depFreeQueue.empty()) {
43211249Sradhika.jagtap@ARM.com        if (checkAndIssue(depFreeQueue.front(), false)) {
43311249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUData, "Removing from depFreeQueue: seq. num "
43411249Sradhika.jagtap@ARM.com                "%lli.\n", (depFreeQueue.front())->seqNum);
43511249Sradhika.jagtap@ARM.com            depFreeQueue.pop();
43611249Sradhika.jagtap@ARM.com        } else {
43711249Sradhika.jagtap@ARM.com            break;
43811249Sradhika.jagtap@ARM.com        }
43911249Sradhika.jagtap@ARM.com    }
44011249Sradhika.jagtap@ARM.com    // Proceed to execute from readyList
44111249Sradhika.jagtap@ARM.com    auto graph_itr = depGraph.begin();
44211249Sradhika.jagtap@ARM.com    auto free_itr = readyList.begin();
44311249Sradhika.jagtap@ARM.com    // Iterate through readyList until the next free node has its execute
44411249Sradhika.jagtap@ARM.com    // tick later than curTick or the end of readyList is reached
44511249Sradhika.jagtap@ARM.com    while (free_itr->execTick <= curTick() && free_itr != readyList.end()) {
44611249Sradhika.jagtap@ARM.com
44711249Sradhika.jagtap@ARM.com        // Get pointer to the node to be executed
44811249Sradhika.jagtap@ARM.com        graph_itr = depGraph.find(free_itr->seqNum);
44911249Sradhika.jagtap@ARM.com        assert(graph_itr != depGraph.end());
45011249Sradhika.jagtap@ARM.com        GraphNode* node_ptr = graph_itr->second;
45111249Sradhika.jagtap@ARM.com
45211249Sradhika.jagtap@ARM.com        // If there is a retryPkt send that else execute the load
45311249Sradhika.jagtap@ARM.com        if (retryPkt) {
45411249Sradhika.jagtap@ARM.com            // The retryPkt must be the request that was created by the
45511249Sradhika.jagtap@ARM.com            // first node in the readyList.
45611249Sradhika.jagtap@ARM.com            if (retryPkt->req->getReqInstSeqNum() != node_ptr->seqNum) {
45711249Sradhika.jagtap@ARM.com                panic("Retry packet's seqence number does not match "
45811249Sradhika.jagtap@ARM.com                      "the first node in the readyList.\n");
45911249Sradhika.jagtap@ARM.com            }
46011249Sradhika.jagtap@ARM.com            if (port.sendTimingReq(retryPkt)) {
46111249Sradhika.jagtap@ARM.com                ++numRetrySucceeded;
46211249Sradhika.jagtap@ARM.com                retryPkt = nullptr;
46311249Sradhika.jagtap@ARM.com            }
46411252Sradhika.jagtap@ARM.com        } else if (node_ptr->isLoad() || node_ptr->isStore()) {
46511249Sradhika.jagtap@ARM.com            // If there is no retryPkt, attempt to send a memory request in
46611249Sradhika.jagtap@ARM.com            // case of a load or store node. If the send fails, executeMemReq()
46711249Sradhika.jagtap@ARM.com            // returns a packet pointer, which we save in retryPkt. In case of
46811249Sradhika.jagtap@ARM.com            // a comp node we don't do anything and simply continue as if the
46911249Sradhika.jagtap@ARM.com            // execution of the comp node succedded.
47011249Sradhika.jagtap@ARM.com            retryPkt = executeMemReq(node_ptr);
47111249Sradhika.jagtap@ARM.com        }
47211249Sradhika.jagtap@ARM.com        // If the retryPkt or a new load/store node failed, we exit from here
47311249Sradhika.jagtap@ARM.com        // as a retry from cache will bring the control to execute(). The
47411249Sradhika.jagtap@ARM.com        // first node in readyList then, will be the failed node.
47511249Sradhika.jagtap@ARM.com        if (retryPkt) {
47611249Sradhika.jagtap@ARM.com            break;
47711249Sradhika.jagtap@ARM.com        }
47811249Sradhika.jagtap@ARM.com
47911249Sradhika.jagtap@ARM.com        // Proceed to remove dependencies for the successfully executed node.
48011249Sradhika.jagtap@ARM.com        // If it is a load which is not strictly ordered and we sent a
48111249Sradhika.jagtap@ARM.com        // request for it successfully, we do not yet mark any register
48211249Sradhika.jagtap@ARM.com        // dependencies complete. But as per dependency modelling we need
48311249Sradhika.jagtap@ARM.com        // to mark ROB dependencies of load and non load/store nodes which
48411249Sradhika.jagtap@ARM.com        // are based on successful sending of the load as complete.
48511252Sradhika.jagtap@ARM.com        if (node_ptr->isLoad() && !node_ptr->isStrictlyOrdered()) {
48611249Sradhika.jagtap@ARM.com            // If execute succeeded mark its dependents as complete
48711249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUData, "Node seq. num %lli sent. Waking up "
48811249Sradhika.jagtap@ARM.com                    "dependents..\n", node_ptr->seqNum);
48911249Sradhika.jagtap@ARM.com
49011249Sradhika.jagtap@ARM.com            auto child_itr = (node_ptr->dependents).begin();
49111249Sradhika.jagtap@ARM.com            while (child_itr != (node_ptr->dependents).end()) {
49211249Sradhika.jagtap@ARM.com                // ROB dependency of a store on a load must not be removed
49311249Sradhika.jagtap@ARM.com                // after load is sent but after response is received
49411252Sradhika.jagtap@ARM.com                if (!(*child_itr)->isStore() &&
49511249Sradhika.jagtap@ARM.com                    (*child_itr)->removeRobDep(node_ptr->seqNum)) {
49611249Sradhika.jagtap@ARM.com
49711249Sradhika.jagtap@ARM.com                    // Check if the child node has become dependency free
49811249Sradhika.jagtap@ARM.com                    if ((*child_itr)->numRobDep == 0 &&
49911249Sradhika.jagtap@ARM.com                        (*child_itr)->numRegDep == 0) {
50011249Sradhika.jagtap@ARM.com
50111249Sradhika.jagtap@ARM.com                        // Source dependencies are complete, check if
50211249Sradhika.jagtap@ARM.com                        // resources are available and issue
50311249Sradhika.jagtap@ARM.com                        checkAndIssue(*child_itr);
50411249Sradhika.jagtap@ARM.com                    }
50511249Sradhika.jagtap@ARM.com                    // Remove this child for the sent load and point to new
50611249Sradhika.jagtap@ARM.com                    // location of the element following the erased element
50711249Sradhika.jagtap@ARM.com                    child_itr = node_ptr->dependents.erase(child_itr);
50811249Sradhika.jagtap@ARM.com                } else {
50911249Sradhika.jagtap@ARM.com                    // This child is not dependency-free, point to the next
51011249Sradhika.jagtap@ARM.com                    // child
51111249Sradhika.jagtap@ARM.com                    child_itr++;
51211249Sradhika.jagtap@ARM.com                }
51311249Sradhika.jagtap@ARM.com            }
51411249Sradhika.jagtap@ARM.com        } else {
51511249Sradhika.jagtap@ARM.com            // If it is a strictly ordered load mark its dependents as complete
51611249Sradhika.jagtap@ARM.com            // as we do not send a request for this case. If it is a store or a
51711249Sradhika.jagtap@ARM.com            // comp node we also mark all its dependents complete.
51811249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUData, "Node seq. num %lli done. Waking"
51911249Sradhika.jagtap@ARM.com                    " up dependents..\n", node_ptr->seqNum);
52011249Sradhika.jagtap@ARM.com
52111249Sradhika.jagtap@ARM.com            for (auto child : node_ptr->dependents) {
52211249Sradhika.jagtap@ARM.com                // If the child node is dependency free removeDepOnInst()
52311249Sradhika.jagtap@ARM.com                // returns true.
52411249Sradhika.jagtap@ARM.com                if (child->removeDepOnInst(node_ptr->seqNum)) {
52511249Sradhika.jagtap@ARM.com                    // Source dependencies are complete, check if resources
52611249Sradhika.jagtap@ARM.com                    // are available and issue
52711249Sradhika.jagtap@ARM.com                    checkAndIssue(child);
52811249Sradhika.jagtap@ARM.com                }
52911249Sradhika.jagtap@ARM.com            }
53011249Sradhika.jagtap@ARM.com        }
53111249Sradhika.jagtap@ARM.com
53211249Sradhika.jagtap@ARM.com        // After executing the node, remove from readyList and delete node.
53311249Sradhika.jagtap@ARM.com        readyList.erase(free_itr);
53411249Sradhika.jagtap@ARM.com        // If it is a cacheable load which was sent, don't delete
53511249Sradhika.jagtap@ARM.com        // just yet.  Delete it in completeMemAccess() after the
53611249Sradhika.jagtap@ARM.com        // response is received. If it is an strictly ordered
53711249Sradhika.jagtap@ARM.com        // load, it was not sent and all dependencies were simply
53811249Sradhika.jagtap@ARM.com        // marked complete. Thus it is safe to delete it. For
53911249Sradhika.jagtap@ARM.com        // stores and non load/store nodes all dependencies were
54011249Sradhika.jagtap@ARM.com        // marked complete so it is safe to delete it.
54111252Sradhika.jagtap@ARM.com        if (!node_ptr->isLoad() || node_ptr->isStrictlyOrdered()) {
54211249Sradhika.jagtap@ARM.com            // Release all resources occupied by the completed node
54311249Sradhika.jagtap@ARM.com            hwResource.release(node_ptr);
54411249Sradhika.jagtap@ARM.com            // clear the dynamically allocated set of dependents
54511249Sradhika.jagtap@ARM.com            (node_ptr->dependents).clear();
54611632Sradhika.jagtap@arm.com            // Update the stat for numOps simulated
54711632Sradhika.jagtap@arm.com            owner.updateNumOps(node_ptr->robNum);
54811249Sradhika.jagtap@ARM.com            // delete node
54911249Sradhika.jagtap@ARM.com            delete node_ptr;
55011249Sradhika.jagtap@ARM.com            // remove from graph
55111249Sradhika.jagtap@ARM.com            depGraph.erase(graph_itr);
55211249Sradhika.jagtap@ARM.com        }
55311249Sradhika.jagtap@ARM.com        // Point to first node to continue to next iteration of while loop
55411249Sradhika.jagtap@ARM.com        free_itr = readyList.begin();
55511249Sradhika.jagtap@ARM.com    } // end of while loop
55611249Sradhika.jagtap@ARM.com
55711249Sradhika.jagtap@ARM.com    // Print readyList, sizes of queues and resource status after updating
55811249Sradhika.jagtap@ARM.com    if (DTRACE(TraceCPUData)) {
55911249Sradhika.jagtap@ARM.com        printReadyList();
56011249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Execute end occupancy:\n");
56111249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\tdepGraph = %d, readyList = %d, "
56211249Sradhika.jagtap@ARM.com                "depFreeQueue = %d ,", depGraph.size(), readyList.size(),
56311249Sradhika.jagtap@ARM.com                depFreeQueue.size());
56411249Sradhika.jagtap@ARM.com        hwResource.printOccupancy();
56511249Sradhika.jagtap@ARM.com    }
56611249Sradhika.jagtap@ARM.com
56711249Sradhika.jagtap@ARM.com    if (retryPkt) {
56811249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Not scheduling an event as expecting a retry"
56911249Sradhika.jagtap@ARM.com                "event from the cache for seq. num %lli.\n",
57011249Sradhika.jagtap@ARM.com                retryPkt->req->getReqInstSeqNum());
57111249Sradhika.jagtap@ARM.com        return;
57211249Sradhika.jagtap@ARM.com    }
57311249Sradhika.jagtap@ARM.com    // If the size of the dependency graph is less than the dependency window
57411249Sradhika.jagtap@ARM.com    // then read from the trace file to populate the graph next time we are in
57511249Sradhika.jagtap@ARM.com    // execute.
57611249Sradhika.jagtap@ARM.com    if (depGraph.size() < windowSize && !traceComplete)
57711249Sradhika.jagtap@ARM.com        nextRead = true;
57811249Sradhika.jagtap@ARM.com
57911249Sradhika.jagtap@ARM.com    // If cache is not blocked, schedule an event for the first execTick in
58011249Sradhika.jagtap@ARM.com    // readyList else retry from cache will schedule the event. If the ready
58111249Sradhika.jagtap@ARM.com    // list is empty then check if the next pending node has resources
58211249Sradhika.jagtap@ARM.com    // available to issue. If yes, then schedule an event for the next cycle.
58311249Sradhika.jagtap@ARM.com    if (!readyList.empty()) {
58411249Sradhika.jagtap@ARM.com        Tick next_event_tick = std::max(readyList.begin()->execTick,
58511249Sradhika.jagtap@ARM.com                                        curTick());
58611249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
58711249Sradhika.jagtap@ARM.com                next_event_tick);
58811249Sradhika.jagtap@ARM.com        owner.schedDcacheNextEvent(next_event_tick);
58911249Sradhika.jagtap@ARM.com    } else if (readyList.empty() && !depFreeQueue.empty() &&
59011249Sradhika.jagtap@ARM.com                hwResource.isAvailable(depFreeQueue.front())) {
59111249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
59211249Sradhika.jagtap@ARM.com                owner.clockEdge(Cycles(1)));
59311249Sradhika.jagtap@ARM.com        owner.schedDcacheNextEvent(owner.clockEdge(Cycles(1)));
59411249Sradhika.jagtap@ARM.com    }
59511249Sradhika.jagtap@ARM.com
59611249Sradhika.jagtap@ARM.com    // If trace is completely read, readyList is empty and depGraph is empty,
59711249Sradhika.jagtap@ARM.com    // set execComplete to true
59811249Sradhika.jagtap@ARM.com    if (depGraph.empty() && readyList.empty() && traceComplete &&
59911249Sradhika.jagtap@ARM.com        !hwResource.awaitingResponse()) {
60011249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "\tExecution Complete!\n");
60111249Sradhika.jagtap@ARM.com        execComplete = true;
60211249Sradhika.jagtap@ARM.com        dataLastTick = curTick();
60311249Sradhika.jagtap@ARM.com    }
60411249Sradhika.jagtap@ARM.com}
60511249Sradhika.jagtap@ARM.com
60611249Sradhika.jagtap@ARM.comPacketPtr
60711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr)
60811249Sradhika.jagtap@ARM.com{
60911249Sradhika.jagtap@ARM.com
61011253Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Executing memory request %lli (phys addr %d, "
61111253Sradhika.jagtap@ARM.com            "virt addr %d, pc %#x, size %d, flags %d).\n",
61211253Sradhika.jagtap@ARM.com            node_ptr->seqNum, node_ptr->physAddr, node_ptr->virtAddr,
61311249Sradhika.jagtap@ARM.com            node_ptr->pc, node_ptr->size, node_ptr->flags);
61411249Sradhika.jagtap@ARM.com
61511249Sradhika.jagtap@ARM.com    // If the request is strictly ordered, do not send it. Just return nullptr
61611249Sradhika.jagtap@ARM.com    // as if it was succesfully sent.
61711249Sradhika.jagtap@ARM.com    if (node_ptr->isStrictlyOrdered()) {
61811252Sradhika.jagtap@ARM.com        node_ptr->isLoad() ? ++numSOLoads : ++numSOStores;
61911249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Skipping strictly ordered request %lli.\n",
62011249Sradhika.jagtap@ARM.com                node_ptr->seqNum);
62111249Sradhika.jagtap@ARM.com        return nullptr;
62211249Sradhika.jagtap@ARM.com    }
62311249Sradhika.jagtap@ARM.com
62411249Sradhika.jagtap@ARM.com    // Check if the request spans two cache lines as this condition triggers
62511249Sradhika.jagtap@ARM.com    // an assert fail in the L1 cache. If it does then truncate the size to
62611249Sradhika.jagtap@ARM.com    // access only until the end of that line and ignore the remainder. The
62711249Sradhika.jagtap@ARM.com    // stat counting this is useful to keep a check on how frequently this
62811249Sradhika.jagtap@ARM.com    // happens. If required the code could be revised to mimick splitting such
62911249Sradhika.jagtap@ARM.com    // a request into two.
63011249Sradhika.jagtap@ARM.com    unsigned blk_size = owner.cacheLineSize();
63111253Sradhika.jagtap@ARM.com    Addr blk_offset = (node_ptr->physAddr & (Addr)(blk_size - 1));
63211249Sradhika.jagtap@ARM.com    if (!(blk_offset + node_ptr->size <= blk_size)) {
63311249Sradhika.jagtap@ARM.com        node_ptr->size = blk_size - blk_offset;
63411249Sradhika.jagtap@ARM.com        ++numSplitReqs;
63511249Sradhika.jagtap@ARM.com    }
63611249Sradhika.jagtap@ARM.com
63711249Sradhika.jagtap@ARM.com    // Create a request and the packet containing request
63811253Sradhika.jagtap@ARM.com    Request* req = new Request(node_ptr->physAddr, node_ptr->size,
63911253Sradhika.jagtap@ARM.com                               node_ptr->flags, masterID, node_ptr->seqNum,
64011435Smitch.hayenga@arm.com                               ContextID(0));
64111249Sradhika.jagtap@ARM.com    req->setPC(node_ptr->pc);
64211253Sradhika.jagtap@ARM.com    // If virtual address is valid, set the asid and virtual address fields
64311253Sradhika.jagtap@ARM.com    // of the request.
64411253Sradhika.jagtap@ARM.com    if (node_ptr->virtAddr != 0) {
64511253Sradhika.jagtap@ARM.com        req->setVirt(node_ptr->asid, node_ptr->virtAddr, node_ptr->size,
64611253Sradhika.jagtap@ARM.com                        node_ptr->flags, masterID, node_ptr->pc);
64711253Sradhika.jagtap@ARM.com        req->setPaddr(node_ptr->physAddr);
64811253Sradhika.jagtap@ARM.com        req->setReqInstSeqNum(node_ptr->seqNum);
64911253Sradhika.jagtap@ARM.com    }
65011253Sradhika.jagtap@ARM.com
65111249Sradhika.jagtap@ARM.com    PacketPtr pkt;
65211249Sradhika.jagtap@ARM.com    uint8_t* pkt_data = new uint8_t[req->getSize()];
65311252Sradhika.jagtap@ARM.com    if (node_ptr->isLoad()) {
65411249Sradhika.jagtap@ARM.com        pkt = Packet::createRead(req);
65511249Sradhika.jagtap@ARM.com    } else {
65611249Sradhika.jagtap@ARM.com        pkt = Packet::createWrite(req);
65711249Sradhika.jagtap@ARM.com        memset(pkt_data, 0xA, req->getSize());
65811249Sradhika.jagtap@ARM.com    }
65911249Sradhika.jagtap@ARM.com    pkt->dataDynamic(pkt_data);
66011249Sradhika.jagtap@ARM.com
66111249Sradhika.jagtap@ARM.com    // Call MasterPort method to send a timing request for this packet
66211249Sradhika.jagtap@ARM.com    bool success = port.sendTimingReq(pkt);
66311249Sradhika.jagtap@ARM.com    ++numSendAttempted;
66411249Sradhika.jagtap@ARM.com
66511249Sradhika.jagtap@ARM.com    if (!success) {
66611249Sradhika.jagtap@ARM.com        // If it fails, return the packet to retry when a retry is signalled by
66711249Sradhika.jagtap@ARM.com        // the cache
66811249Sradhika.jagtap@ARM.com        ++numSendFailed;
66911249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Send failed. Saving packet for retry.\n");
67011249Sradhika.jagtap@ARM.com        return pkt;
67111249Sradhika.jagtap@ARM.com    } else {
67211249Sradhika.jagtap@ARM.com        // It is succeeds, return nullptr
67311249Sradhika.jagtap@ARM.com        ++numSendSucceeded;
67411249Sradhika.jagtap@ARM.com        return nullptr;
67511249Sradhika.jagtap@ARM.com    }
67611249Sradhika.jagtap@ARM.com}
67711249Sradhika.jagtap@ARM.com
67811249Sradhika.jagtap@ARM.combool
67911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::checkAndIssue(const GraphNode* node_ptr, bool first)
68011249Sradhika.jagtap@ARM.com{
68111249Sradhika.jagtap@ARM.com    // Assert the node is dependency-free
68211249Sradhika.jagtap@ARM.com    assert(node_ptr->numRobDep == 0 && node_ptr->numRegDep == 0);
68311249Sradhika.jagtap@ARM.com
68411249Sradhika.jagtap@ARM.com    // If this is the first attempt, print a debug message to indicate this.
68511249Sradhika.jagtap@ARM.com    if (first) {
68611249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tseq. num %lli(%s) with rob num %lli is now"
68711252Sradhika.jagtap@ARM.com            " dependency free.\n", node_ptr->seqNum, node_ptr->typeToStr(),
68811249Sradhika.jagtap@ARM.com            node_ptr->robNum);
68911249Sradhika.jagtap@ARM.com    }
69011249Sradhika.jagtap@ARM.com
69111249Sradhika.jagtap@ARM.com    // Check if resources are available to issue the specific node
69211249Sradhika.jagtap@ARM.com    if (hwResource.isAvailable(node_ptr)) {
69311249Sradhika.jagtap@ARM.com        // If resources are free only then add to readyList
69411249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tResources available for seq. num %lli. Adding"
69511249Sradhika.jagtap@ARM.com            " to readyList, occupying resources.\n", node_ptr->seqNum);
69611249Sradhika.jagtap@ARM.com        // Compute the execute tick by adding the compute delay for the node
69711249Sradhika.jagtap@ARM.com        // and add the ready node to the ready list
69811249Sradhika.jagtap@ARM.com        addToSortedReadyList(node_ptr->seqNum,
69911249Sradhika.jagtap@ARM.com                                owner.clockEdge() + node_ptr->compDelay);
70011249Sradhika.jagtap@ARM.com        // Account for the resources taken up by this issued node.
70111249Sradhika.jagtap@ARM.com        hwResource.occupy(node_ptr);
70211249Sradhika.jagtap@ARM.com        return true;
70311249Sradhika.jagtap@ARM.com
70411249Sradhika.jagtap@ARM.com    } else {
70511249Sradhika.jagtap@ARM.com        if (first) {
70611249Sradhika.jagtap@ARM.com            // Although dependencies are complete, resources are not available.
70711249Sradhika.jagtap@ARM.com            DPRINTFR(TraceCPUData, "\t\tResources unavailable for seq. num %lli."
70811249Sradhika.jagtap@ARM.com                " Adding to depFreeQueue.\n", node_ptr->seqNum);
70911249Sradhika.jagtap@ARM.com            depFreeQueue.push(node_ptr);
71011249Sradhika.jagtap@ARM.com        } else {
71111249Sradhika.jagtap@ARM.com            DPRINTFR(TraceCPUData, "\t\tResources unavailable for seq. num %lli. "
71211249Sradhika.jagtap@ARM.com                "Still pending issue.\n", node_ptr->seqNum);
71311249Sradhika.jagtap@ARM.com        }
71411249Sradhika.jagtap@ARM.com        return false;
71511249Sradhika.jagtap@ARM.com    }
71611249Sradhika.jagtap@ARM.com}
71711249Sradhika.jagtap@ARM.com
71811249Sradhika.jagtap@ARM.comvoid
71911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::completeMemAccess(PacketPtr pkt)
72011249Sradhika.jagtap@ARM.com{
72111249Sradhika.jagtap@ARM.com    // Release the resources for this completed node.
72211249Sradhika.jagtap@ARM.com    if (pkt->isWrite()) {
72311249Sradhika.jagtap@ARM.com        // Consider store complete.
72411249Sradhika.jagtap@ARM.com        hwResource.releaseStoreBuffer();
72511249Sradhika.jagtap@ARM.com        // If it is a store response then do nothing since we do not model
72611249Sradhika.jagtap@ARM.com        // dependencies on store completion in the trace. But if we were
72711249Sradhika.jagtap@ARM.com        // blocking execution due to store buffer fullness, we need to schedule
72811249Sradhika.jagtap@ARM.com        // an event and attempt to progress.
72911249Sradhika.jagtap@ARM.com    } else {
73011249Sradhika.jagtap@ARM.com        // If it is a load response then release the dependents waiting on it.
73111249Sradhika.jagtap@ARM.com        // Get pointer to the completed load
73211249Sradhika.jagtap@ARM.com        auto graph_itr = depGraph.find(pkt->req->getReqInstSeqNum());
73311249Sradhika.jagtap@ARM.com        assert(graph_itr != depGraph.end());
73411249Sradhika.jagtap@ARM.com        GraphNode* node_ptr = graph_itr->second;
73511249Sradhika.jagtap@ARM.com
73611249Sradhika.jagtap@ARM.com        // Release resources occupied by the load
73711249Sradhika.jagtap@ARM.com        hwResource.release(node_ptr);
73811249Sradhika.jagtap@ARM.com
73911249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Load seq. num %lli response received. Waking up"
74011249Sradhika.jagtap@ARM.com                " dependents..\n", node_ptr->seqNum);
74111249Sradhika.jagtap@ARM.com
74211249Sradhika.jagtap@ARM.com        for (auto child : node_ptr->dependents) {
74311249Sradhika.jagtap@ARM.com            if (child->removeDepOnInst(node_ptr->seqNum)) {
74411249Sradhika.jagtap@ARM.com                checkAndIssue(child);
74511249Sradhika.jagtap@ARM.com            }
74611249Sradhika.jagtap@ARM.com        }
74711249Sradhika.jagtap@ARM.com
74811249Sradhika.jagtap@ARM.com        // clear the dynamically allocated set of dependents
74911249Sradhika.jagtap@ARM.com        (node_ptr->dependents).clear();
75011632Sradhika.jagtap@arm.com        // Update the stat for numOps completed
75111632Sradhika.jagtap@arm.com        owner.updateNumOps(node_ptr->robNum);
75211249Sradhika.jagtap@ARM.com        // delete node
75311249Sradhika.jagtap@ARM.com        delete node_ptr;
75411249Sradhika.jagtap@ARM.com        // remove from graph
75511249Sradhika.jagtap@ARM.com        depGraph.erase(graph_itr);
75611249Sradhika.jagtap@ARM.com    }
75711249Sradhika.jagtap@ARM.com
75811249Sradhika.jagtap@ARM.com    if (DTRACE(TraceCPUData)) {
75911249Sradhika.jagtap@ARM.com        printReadyList();
76011249Sradhika.jagtap@ARM.com    }
76111249Sradhika.jagtap@ARM.com
76211249Sradhika.jagtap@ARM.com    // If the size of the dependency graph is less than the dependency window
76311249Sradhika.jagtap@ARM.com    // then read from the trace file to populate the graph next time we are in
76411249Sradhika.jagtap@ARM.com    // execute.
76511249Sradhika.jagtap@ARM.com    if (depGraph.size() < windowSize && !traceComplete)
76611249Sradhika.jagtap@ARM.com        nextRead = true;
76711249Sradhika.jagtap@ARM.com
76811249Sradhika.jagtap@ARM.com    // If not waiting for retry, attempt to schedule next event
76911249Sradhika.jagtap@ARM.com    if (!retryPkt) {
77011249Sradhika.jagtap@ARM.com        // We might have new dep-free nodes in the list which will have execute
77111249Sradhika.jagtap@ARM.com        // tick greater than or equal to curTick. But a new dep-free node might
77211249Sradhika.jagtap@ARM.com        // have its execute tick earlier. Therefore, attempt to reschedule. It
77311249Sradhika.jagtap@ARM.com        // could happen that the readyList is empty and we got here via a
77411249Sradhika.jagtap@ARM.com        // last remaining response. So, either the trace is complete or there
77511249Sradhika.jagtap@ARM.com        // are pending nodes in the depFreeQueue. The checking is done in the
77611249Sradhika.jagtap@ARM.com        // execute() control flow, so schedule an event to go via that flow.
77711249Sradhika.jagtap@ARM.com        Tick next_event_tick = readyList.empty() ? owner.clockEdge(Cycles(1)) :
77811249Sradhika.jagtap@ARM.com            std::max(readyList.begin()->execTick, owner.clockEdge(Cycles(1)));
77911249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
78011249Sradhika.jagtap@ARM.com                next_event_tick);
78111249Sradhika.jagtap@ARM.com        owner.schedDcacheNextEvent(next_event_tick);
78211249Sradhika.jagtap@ARM.com    }
78311249Sradhika.jagtap@ARM.com}
78411249Sradhika.jagtap@ARM.com
78511249Sradhika.jagtap@ARM.comvoid
78611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::addToSortedReadyList(NodeSeqNum seq_num,
78711249Sradhika.jagtap@ARM.com                                                    Tick exec_tick)
78811249Sradhika.jagtap@ARM.com{
78911249Sradhika.jagtap@ARM.com    ReadyNode ready_node;
79011249Sradhika.jagtap@ARM.com    ready_node.seqNum = seq_num;
79111249Sradhika.jagtap@ARM.com    ready_node.execTick = exec_tick;
79211249Sradhika.jagtap@ARM.com
79311249Sradhika.jagtap@ARM.com    // Iterator to readyList
79411249Sradhika.jagtap@ARM.com    auto itr = readyList.begin();
79511249Sradhika.jagtap@ARM.com
79611249Sradhika.jagtap@ARM.com    // If the readyList is empty, simply insert the new node at the beginning
79711249Sradhika.jagtap@ARM.com    // and return
79811249Sradhika.jagtap@ARM.com    if (itr == readyList.end()) {
79911249Sradhika.jagtap@ARM.com        readyList.insert(itr, ready_node);
80011249Sradhika.jagtap@ARM.com        maxReadyListSize = std::max<double>(readyList.size(),
80111249Sradhika.jagtap@ARM.com                                              maxReadyListSize.value());
80211249Sradhika.jagtap@ARM.com        return;
80311249Sradhika.jagtap@ARM.com    }
80411249Sradhika.jagtap@ARM.com
80511249Sradhika.jagtap@ARM.com    // If the new node has its execution tick equal to the first node in the
80611249Sradhika.jagtap@ARM.com    // list then go to the next node. If the first node in the list failed
80711249Sradhika.jagtap@ARM.com    // to execute, its position as the first is thus maintained.
80811249Sradhika.jagtap@ARM.com    if (retryPkt)
80911249Sradhika.jagtap@ARM.com        if (retryPkt->req->getReqInstSeqNum() == itr->seqNum)
81011249Sradhika.jagtap@ARM.com            itr++;
81111249Sradhika.jagtap@ARM.com
81211249Sradhika.jagtap@ARM.com    // Increment the iterator and compare the node pointed to by it to the new
81311249Sradhika.jagtap@ARM.com    // node till the position to insert the new node is found.
81411249Sradhika.jagtap@ARM.com    bool found = false;
81511249Sradhika.jagtap@ARM.com    while (!found && itr != readyList.end()) {
81611249Sradhika.jagtap@ARM.com        // If the execution tick of the new node is less than the node then
81711249Sradhika.jagtap@ARM.com        // this is the position to insert
81811249Sradhika.jagtap@ARM.com        if (exec_tick < itr->execTick)
81911249Sradhika.jagtap@ARM.com            found = true;
82011249Sradhika.jagtap@ARM.com        // If the execution tick of the new node is equal to the node then
82111249Sradhika.jagtap@ARM.com        // sort in ascending order of sequence numbers
82211249Sradhika.jagtap@ARM.com        else if (exec_tick == itr->execTick) {
82311249Sradhika.jagtap@ARM.com            // If the sequence number of the new node is less than the node
82411249Sradhika.jagtap@ARM.com            // then this is the position to insert
82511249Sradhika.jagtap@ARM.com            if (seq_num < itr->seqNum)
82611249Sradhika.jagtap@ARM.com                found = true;
82711249Sradhika.jagtap@ARM.com            // Else go to next node
82811249Sradhika.jagtap@ARM.com            else
82911249Sradhika.jagtap@ARM.com                itr++;
83011249Sradhika.jagtap@ARM.com        }
83111249Sradhika.jagtap@ARM.com        // If the execution tick of the new node is greater than the node then
83211249Sradhika.jagtap@ARM.com        // go to the next node
83311249Sradhika.jagtap@ARM.com        else
83411249Sradhika.jagtap@ARM.com            itr++;
83511249Sradhika.jagtap@ARM.com    }
83611249Sradhika.jagtap@ARM.com    readyList.insert(itr, ready_node);
83711249Sradhika.jagtap@ARM.com    // Update the stat for max size reached of the readyList
83811249Sradhika.jagtap@ARM.com    maxReadyListSize = std::max<double>(readyList.size(),
83911249Sradhika.jagtap@ARM.com                                          maxReadyListSize.value());
84011249Sradhika.jagtap@ARM.com}
84111249Sradhika.jagtap@ARM.com
84211249Sradhika.jagtap@ARM.comvoid
84311249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::printReadyList() {
84411249Sradhika.jagtap@ARM.com
84511249Sradhika.jagtap@ARM.com    auto itr = readyList.begin();
84611249Sradhika.jagtap@ARM.com    if (itr == readyList.end()) {
84711249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "readyList is empty.\n");
84811249Sradhika.jagtap@ARM.com        return;
84911249Sradhika.jagtap@ARM.com    }
85011249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Printing readyList:\n");
85111249Sradhika.jagtap@ARM.com    while (itr != readyList.end()) {
85211249Sradhika.jagtap@ARM.com        auto graph_itr = depGraph.find(itr->seqNum);
85311249Sradhika.jagtap@ARM.com        GraphNode* node_ptr M5_VAR_USED = graph_itr->second;
85411249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t%lld(%s), %lld\n", itr->seqNum,
85511252Sradhika.jagtap@ARM.com            node_ptr->typeToStr(), itr->execTick);
85611249Sradhika.jagtap@ARM.com        itr++;
85711249Sradhika.jagtap@ARM.com    }
85811249Sradhika.jagtap@ARM.com}
85911249Sradhika.jagtap@ARM.com
86011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::HardwareResource(
86111249Sradhika.jagtap@ARM.com    uint16_t max_rob, uint16_t max_stores, uint16_t max_loads)
86211249Sradhika.jagtap@ARM.com  : sizeROB(max_rob),
86311249Sradhika.jagtap@ARM.com    sizeStoreBuffer(max_stores),
86411249Sradhika.jagtap@ARM.com    sizeLoadBuffer(max_loads),
86511249Sradhika.jagtap@ARM.com    oldestInFlightRobNum(UINT64_MAX),
86611249Sradhika.jagtap@ARM.com    numInFlightLoads(0),
86711249Sradhika.jagtap@ARM.com    numInFlightStores(0)
86811249Sradhika.jagtap@ARM.com{}
86911249Sradhika.jagtap@ARM.com
87011249Sradhika.jagtap@ARM.comvoid
87111249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::occupy(const GraphNode* new_node)
87211249Sradhika.jagtap@ARM.com{
87311249Sradhika.jagtap@ARM.com    // Occupy ROB entry for the issued node
87411249Sradhika.jagtap@ARM.com    // Merely maintain the oldest node, i.e. numerically least robNum by saving
87511249Sradhika.jagtap@ARM.com    // it in the variable oldestInFLightRobNum.
87611249Sradhika.jagtap@ARM.com    inFlightNodes[new_node->seqNum] = new_node->robNum;
87711249Sradhika.jagtap@ARM.com    oldestInFlightRobNum = inFlightNodes.begin()->second;
87811249Sradhika.jagtap@ARM.com
87911249Sradhika.jagtap@ARM.com    // Occupy Load/Store Buffer entry for the issued node if applicable
88011252Sradhika.jagtap@ARM.com    if (new_node->isLoad()) {
88111249Sradhika.jagtap@ARM.com        ++numInFlightLoads;
88211252Sradhika.jagtap@ARM.com    } else if (new_node->isStore()) {
88311249Sradhika.jagtap@ARM.com        ++numInFlightStores;
88411249Sradhika.jagtap@ARM.com    } // else if it is a non load/store node, no buffer entry is occupied
88511249Sradhika.jagtap@ARM.com
88611249Sradhika.jagtap@ARM.com    printOccupancy();
88711249Sradhika.jagtap@ARM.com}
88811249Sradhika.jagtap@ARM.com
88911249Sradhika.jagtap@ARM.comvoid
89011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::release(const GraphNode* done_node)
89111249Sradhika.jagtap@ARM.com{
89211249Sradhika.jagtap@ARM.com    assert(!inFlightNodes.empty());
89311249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "\tClearing done seq. num %d from inFlightNodes..\n",
89411249Sradhika.jagtap@ARM.com        done_node->seqNum);
89511249Sradhika.jagtap@ARM.com
89611249Sradhika.jagtap@ARM.com    assert(inFlightNodes.find(done_node->seqNum) != inFlightNodes.end());
89711249Sradhika.jagtap@ARM.com    inFlightNodes.erase(done_node->seqNum);
89811249Sradhika.jagtap@ARM.com
89911249Sradhika.jagtap@ARM.com    if (inFlightNodes.empty()) {
90011249Sradhika.jagtap@ARM.com        // If we delete the only in-flight node and then the
90111249Sradhika.jagtap@ARM.com        // oldestInFlightRobNum is set to it's initialized (max) value.
90211249Sradhika.jagtap@ARM.com        oldestInFlightRobNum = UINT64_MAX;
90311249Sradhika.jagtap@ARM.com    } else {
90411249Sradhika.jagtap@ARM.com        // Set the oldest in-flight node rob number equal to the first node in
90511249Sradhika.jagtap@ARM.com        // the inFlightNodes since that will have the numerically least value.
90611249Sradhika.jagtap@ARM.com        oldestInFlightRobNum = inFlightNodes.begin()->second;
90711249Sradhika.jagtap@ARM.com    }
90811249Sradhika.jagtap@ARM.com
90911249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "\tCleared. inFlightNodes.size() = %d, "
91011249Sradhika.jagtap@ARM.com        "oldestInFlightRobNum = %d\n", inFlightNodes.size(),
91111249Sradhika.jagtap@ARM.com        oldestInFlightRobNum);
91211249Sradhika.jagtap@ARM.com
91311249Sradhika.jagtap@ARM.com    // A store is considered complete when a request is sent, thus ROB entry is
91411249Sradhika.jagtap@ARM.com    // freed. But it occupies an entry in the Store Buffer until its response
91511249Sradhika.jagtap@ARM.com    // is received. A load is considered complete when a response is received,
91611249Sradhika.jagtap@ARM.com    // thus both ROB and Load Buffer entries can be released.
91711252Sradhika.jagtap@ARM.com    if (done_node->isLoad()) {
91811249Sradhika.jagtap@ARM.com        assert(numInFlightLoads != 0);
91911249Sradhika.jagtap@ARM.com        --numInFlightLoads;
92011249Sradhika.jagtap@ARM.com    }
92111249Sradhika.jagtap@ARM.com    // For normal writes, we send the requests out and clear a store buffer
92211249Sradhika.jagtap@ARM.com    // entry on response. For writes which are strictly ordered, for e.g.
92311249Sradhika.jagtap@ARM.com    // writes to device registers, we do that within release() which is called
92411249Sradhika.jagtap@ARM.com    // when node is executed and taken off from readyList.
92511252Sradhika.jagtap@ARM.com    if (done_node->isStore() && done_node->isStrictlyOrdered()) {
92611249Sradhika.jagtap@ARM.com        releaseStoreBuffer();
92711249Sradhika.jagtap@ARM.com    }
92811249Sradhika.jagtap@ARM.com}
92911249Sradhika.jagtap@ARM.com
93011249Sradhika.jagtap@ARM.comvoid
93111249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::releaseStoreBuffer()
93211249Sradhika.jagtap@ARM.com{
93311249Sradhika.jagtap@ARM.com    assert(numInFlightStores != 0);
93411249Sradhika.jagtap@ARM.com    --numInFlightStores;
93511249Sradhika.jagtap@ARM.com}
93611249Sradhika.jagtap@ARM.com
93711249Sradhika.jagtap@ARM.combool
93811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::isAvailable(
93911249Sradhika.jagtap@ARM.com    const GraphNode* new_node) const
94011249Sradhika.jagtap@ARM.com{
94111249Sradhika.jagtap@ARM.com    uint16_t num_in_flight_nodes;
94211249Sradhika.jagtap@ARM.com    if (inFlightNodes.empty()) {
94311249Sradhika.jagtap@ARM.com        num_in_flight_nodes = 0;
94411249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
94511249Sradhika.jagtap@ARM.com            " #in-flight nodes = 0", new_node->seqNum);
94611249Sradhika.jagtap@ARM.com    } else if (new_node->robNum > oldestInFlightRobNum) {
94711249Sradhika.jagtap@ARM.com        // This is the intuitive case where new dep-free node is younger
94811249Sradhika.jagtap@ARM.com        // instruction than the oldest instruction in-flight. Thus we make sure
94911249Sradhika.jagtap@ARM.com        // in_flight_nodes does not overflow.
95011249Sradhika.jagtap@ARM.com        num_in_flight_nodes = new_node->robNum - oldestInFlightRobNum;
95111249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
95211249Sradhika.jagtap@ARM.com            " #in-flight nodes = %d - %d =  %d", new_node->seqNum,
95311249Sradhika.jagtap@ARM.com             new_node->robNum, oldestInFlightRobNum, num_in_flight_nodes);
95411249Sradhika.jagtap@ARM.com    } else {
95511249Sradhika.jagtap@ARM.com        // This is the case where an instruction older than the oldest in-
95611249Sradhika.jagtap@ARM.com        // flight instruction becomes dep-free. Thus we must have already
95711249Sradhika.jagtap@ARM.com        // accounted for the entry in ROB for this new dep-free node.
95811249Sradhika.jagtap@ARM.com        // Immediately after this check returns true, oldestInFlightRobNum will
95911249Sradhika.jagtap@ARM.com        // be updated in occupy(). We simply let this node issue now.
96011249Sradhika.jagtap@ARM.com        num_in_flight_nodes = 0;
96111249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
96211249Sradhika.jagtap@ARM.com            " new oldestInFlightRobNum = %d, #in-flight nodes ignored",
96311249Sradhika.jagtap@ARM.com            new_node->seqNum, new_node->robNum);
96411249Sradhika.jagtap@ARM.com    }
96511249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, ", LQ = %d/%d, SQ  = %d/%d.\n",
96611249Sradhika.jagtap@ARM.com        numInFlightLoads, sizeLoadBuffer,
96711249Sradhika.jagtap@ARM.com        numInFlightStores, sizeStoreBuffer);
96811249Sradhika.jagtap@ARM.com    // Check if resources are available to issue the specific node
96911249Sradhika.jagtap@ARM.com    if (num_in_flight_nodes >= sizeROB) {
97011249Sradhika.jagtap@ARM.com        return false;
97111249Sradhika.jagtap@ARM.com    }
97211252Sradhika.jagtap@ARM.com    if (new_node->isLoad() && numInFlightLoads >= sizeLoadBuffer) {
97311249Sradhika.jagtap@ARM.com        return false;
97411249Sradhika.jagtap@ARM.com    }
97511252Sradhika.jagtap@ARM.com    if (new_node->isStore() && numInFlightStores >= sizeStoreBuffer) {
97611249Sradhika.jagtap@ARM.com        return false;
97711249Sradhika.jagtap@ARM.com    }
97811249Sradhika.jagtap@ARM.com    return true;
97911249Sradhika.jagtap@ARM.com}
98011249Sradhika.jagtap@ARM.com
98111249Sradhika.jagtap@ARM.combool
98211249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::awaitingResponse() const {
98311249Sradhika.jagtap@ARM.com    // Return true if there is at least one read or write request in flight
98411249Sradhika.jagtap@ARM.com    return (numInFlightStores != 0 || numInFlightLoads != 0);
98511249Sradhika.jagtap@ARM.com}
98611249Sradhika.jagtap@ARM.com
98711249Sradhika.jagtap@ARM.comvoid
98811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::printOccupancy() {
98911249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "oldestInFlightRobNum = %d, "
99011249Sradhika.jagtap@ARM.com            "LQ = %d/%d, SQ  = %d/%d.\n",
99111249Sradhika.jagtap@ARM.com            oldestInFlightRobNum,
99211249Sradhika.jagtap@ARM.com            numInFlightLoads, sizeLoadBuffer,
99311249Sradhika.jagtap@ARM.com            numInFlightStores, sizeStoreBuffer);
99411249Sradhika.jagtap@ARM.com}
99511249Sradhika.jagtap@ARM.com
99611249Sradhika.jagtap@ARM.comvoid
99711249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::regStats()
99811249Sradhika.jagtap@ARM.com{
99911249Sradhika.jagtap@ARM.com    using namespace Stats;
100011249Sradhika.jagtap@ARM.com
100111249Sradhika.jagtap@ARM.com    numSendAttempted
100211249Sradhika.jagtap@ARM.com    .name(name() + ".numSendAttempted")
100311249Sradhika.jagtap@ARM.com    .desc("Number of first attempts to send a request")
100411249Sradhika.jagtap@ARM.com    ;
100511249Sradhika.jagtap@ARM.com
100611249Sradhika.jagtap@ARM.com    numSendSucceeded
100711249Sradhika.jagtap@ARM.com    .name(name() + ".numSendSucceeded")
100811249Sradhika.jagtap@ARM.com    .desc("Number of successful first attempts")
100911249Sradhika.jagtap@ARM.com    ;
101011249Sradhika.jagtap@ARM.com
101111249Sradhika.jagtap@ARM.com    numSendFailed
101211249Sradhika.jagtap@ARM.com    .name(name() + ".numSendFailed")
101311249Sradhika.jagtap@ARM.com    .desc("Number of failed first attempts")
101411249Sradhika.jagtap@ARM.com    ;
101511249Sradhika.jagtap@ARM.com
101611249Sradhika.jagtap@ARM.com    numRetrySucceeded
101711249Sradhika.jagtap@ARM.com    .name(name() + ".numRetrySucceeded")
101811249Sradhika.jagtap@ARM.com    .desc("Number of successful retries")
101911249Sradhika.jagtap@ARM.com    ;
102011249Sradhika.jagtap@ARM.com
102111249Sradhika.jagtap@ARM.com    instLastTick
102211249Sradhika.jagtap@ARM.com    .name(name() + ".instLastTick")
102311249Sradhika.jagtap@ARM.com    .desc("Last tick simulated from the fixed inst trace")
102411249Sradhika.jagtap@ARM.com    ;
102511249Sradhika.jagtap@ARM.com}
102611249Sradhika.jagtap@ARM.com
102711249Sradhika.jagtap@ARM.comTick
102811249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::init()
102911249Sradhika.jagtap@ARM.com{
103011249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "Initializing instruction fetch request generator"
103111249Sradhika.jagtap@ARM.com            " IcacheGen: fixed issue with retry.\n");
103211249Sradhika.jagtap@ARM.com
103311249Sradhika.jagtap@ARM.com    if (nextExecute()) {
103411249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUInst, "\tFirst tick = %d.\n", currElement.tick);
103511249Sradhika.jagtap@ARM.com        return currElement.tick;
103611249Sradhika.jagtap@ARM.com    } else {
103711249Sradhika.jagtap@ARM.com        panic("Read of first message in the trace failed.\n");
103811249Sradhika.jagtap@ARM.com        return MaxTick;
103911249Sradhika.jagtap@ARM.com    }
104011249Sradhika.jagtap@ARM.com}
104111249Sradhika.jagtap@ARM.com
104211249Sradhika.jagtap@ARM.combool
104311249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::tryNext()
104411249Sradhika.jagtap@ARM.com{
104511249Sradhika.jagtap@ARM.com    // If there is a retry packet, try to send it
104611249Sradhika.jagtap@ARM.com    if (retryPkt) {
104711249Sradhika.jagtap@ARM.com
104811249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUInst, "Trying to send retry packet.\n");
104911249Sradhika.jagtap@ARM.com
105011249Sradhika.jagtap@ARM.com        if (!port.sendTimingReq(retryPkt)) {
105111249Sradhika.jagtap@ARM.com            // Still blocked! This should never occur.
105211249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUInst, "Retry packet sending failed.\n");
105311249Sradhika.jagtap@ARM.com            return false;
105411249Sradhika.jagtap@ARM.com        }
105511249Sradhika.jagtap@ARM.com        ++numRetrySucceeded;
105611249Sradhika.jagtap@ARM.com    } else {
105711249Sradhika.jagtap@ARM.com
105811249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUInst, "Trying to send packet for currElement.\n");
105911249Sradhika.jagtap@ARM.com
106011249Sradhika.jagtap@ARM.com        // try sending current element
106111249Sradhika.jagtap@ARM.com        assert(currElement.isValid());
106211249Sradhika.jagtap@ARM.com
106311249Sradhika.jagtap@ARM.com        ++numSendAttempted;
106411249Sradhika.jagtap@ARM.com
106511249Sradhika.jagtap@ARM.com        if (!send(currElement.addr, currElement.blocksize,
106611249Sradhika.jagtap@ARM.com                    currElement.cmd, currElement.flags, currElement.pc)) {
106711249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUInst, "currElement sending failed.\n");
106811249Sradhika.jagtap@ARM.com            ++numSendFailed;
106911249Sradhika.jagtap@ARM.com            // return false to indicate not to schedule next event
107011249Sradhika.jagtap@ARM.com            return false;
107111249Sradhika.jagtap@ARM.com        } else {
107211249Sradhika.jagtap@ARM.com            ++numSendSucceeded;
107311249Sradhika.jagtap@ARM.com        }
107411249Sradhika.jagtap@ARM.com    }
107511249Sradhika.jagtap@ARM.com    // If packet was sent successfully, either retryPkt or currElement, return
107611249Sradhika.jagtap@ARM.com    // true to indicate to schedule event at current Tick plus delta. If packet
107711249Sradhika.jagtap@ARM.com    // was sent successfully and there is no next packet to send, return false.
107811249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "Packet sent successfully, trying to read next "
107911249Sradhika.jagtap@ARM.com        "element.\n");
108011249Sradhika.jagtap@ARM.com    retryPkt = nullptr;
108111249Sradhika.jagtap@ARM.com    // Read next element into currElement, currElement gets cleared so save the
108211249Sradhika.jagtap@ARM.com    // tick to calculate delta
108311249Sradhika.jagtap@ARM.com    Tick last_tick = currElement.tick;
108411249Sradhika.jagtap@ARM.com    if (nextExecute()) {
108511249Sradhika.jagtap@ARM.com        assert(currElement.tick >= last_tick);
108611249Sradhika.jagtap@ARM.com        delta = currElement.tick - last_tick;
108711249Sradhika.jagtap@ARM.com    }
108811249Sradhika.jagtap@ARM.com    return !traceComplete;
108911249Sradhika.jagtap@ARM.com}
109011249Sradhika.jagtap@ARM.com
109111249Sradhika.jagtap@ARM.comvoid
109211249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::exit()
109311249Sradhika.jagtap@ARM.com{
109411249Sradhika.jagtap@ARM.com    trace.reset();
109511249Sradhika.jagtap@ARM.com}
109611249Sradhika.jagtap@ARM.com
109711249Sradhika.jagtap@ARM.combool
109811249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::nextExecute()
109911249Sradhika.jagtap@ARM.com{
110011249Sradhika.jagtap@ARM.com    if (traceComplete)
110111249Sradhika.jagtap@ARM.com        // We are at the end of the file, thus we have no more messages.
110211249Sradhika.jagtap@ARM.com        // Return false.
110311249Sradhika.jagtap@ARM.com        return false;
110411249Sradhika.jagtap@ARM.com
110511249Sradhika.jagtap@ARM.com
110611249Sradhika.jagtap@ARM.com    //Reset the currElement to the default values
110711249Sradhika.jagtap@ARM.com    currElement.clear();
110811249Sradhika.jagtap@ARM.com
110911249Sradhika.jagtap@ARM.com    // Read the next line to get the next message. If that fails then end of
111011249Sradhika.jagtap@ARM.com    // trace has been reached and traceComplete needs to be set in addition
111111249Sradhika.jagtap@ARM.com    // to returning false. If successful then next message is in currElement.
111211249Sradhika.jagtap@ARM.com    if (!trace.read(&currElement)) {
111311249Sradhika.jagtap@ARM.com        traceComplete = true;
111411249Sradhika.jagtap@ARM.com        instLastTick = curTick();
111511249Sradhika.jagtap@ARM.com        return false;
111611249Sradhika.jagtap@ARM.com    }
111711249Sradhika.jagtap@ARM.com
111811249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "inst fetch: %c addr %d pc %#x size %d tick %d\n",
111911249Sradhika.jagtap@ARM.com            currElement.cmd.isRead() ? 'r' : 'w',
112011249Sradhika.jagtap@ARM.com            currElement.addr,
112111249Sradhika.jagtap@ARM.com            currElement.pc,
112211249Sradhika.jagtap@ARM.com            currElement.blocksize,
112311249Sradhika.jagtap@ARM.com            currElement.tick);
112411249Sradhika.jagtap@ARM.com
112511249Sradhika.jagtap@ARM.com    return true;
112611249Sradhika.jagtap@ARM.com}
112711249Sradhika.jagtap@ARM.com
112811249Sradhika.jagtap@ARM.combool
112911249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::send(Addr addr, unsigned size, const MemCmd& cmd,
113011249Sradhika.jagtap@ARM.com              Request::FlagsType flags, Addr pc)
113111249Sradhika.jagtap@ARM.com{
113211249Sradhika.jagtap@ARM.com
113311249Sradhika.jagtap@ARM.com    // Create new request
113411249Sradhika.jagtap@ARM.com    Request* req = new Request(addr, size, flags, masterID);
113511249Sradhika.jagtap@ARM.com    req->setPC(pc);
113611249Sradhika.jagtap@ARM.com
113711249Sradhika.jagtap@ARM.com    // If this is not done it triggers assert in L1 cache for invalid contextId
113811435Smitch.hayenga@arm.com    req->setContext(ContextID(0));
113911249Sradhika.jagtap@ARM.com
114011249Sradhika.jagtap@ARM.com    // Embed it in a packet
114111249Sradhika.jagtap@ARM.com    PacketPtr pkt = new Packet(req, cmd);
114211249Sradhika.jagtap@ARM.com
114311249Sradhika.jagtap@ARM.com    uint8_t* pkt_data = new uint8_t[req->getSize()];
114411249Sradhika.jagtap@ARM.com    pkt->dataDynamic(pkt_data);
114511249Sradhika.jagtap@ARM.com
114611249Sradhika.jagtap@ARM.com    if (cmd.isWrite()) {
114711249Sradhika.jagtap@ARM.com        memset(pkt_data, 0xA, req->getSize());
114811249Sradhika.jagtap@ARM.com    }
114911249Sradhika.jagtap@ARM.com
115011249Sradhika.jagtap@ARM.com    // Call MasterPort method to send a timing request for this packet
115111249Sradhika.jagtap@ARM.com    bool success = port.sendTimingReq(pkt);
115211249Sradhika.jagtap@ARM.com    if (!success) {
115311249Sradhika.jagtap@ARM.com        // If it fails, save the packet to retry when a retry is signalled by
115411249Sradhika.jagtap@ARM.com        // the cache
115511249Sradhika.jagtap@ARM.com        retryPkt = pkt;
115611249Sradhika.jagtap@ARM.com    }
115711249Sradhika.jagtap@ARM.com    return success;
115811249Sradhika.jagtap@ARM.com}
115911249Sradhika.jagtap@ARM.com
116011249Sradhika.jagtap@ARM.comvoid
116111249Sradhika.jagtap@ARM.comTraceCPU::icacheRetryRecvd()
116211249Sradhika.jagtap@ARM.com{
116311249Sradhika.jagtap@ARM.com    // Schedule an event to go through the control flow in the same tick as
116411249Sradhika.jagtap@ARM.com    // retry is received
116511249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "Icache retry received. Scheduling next IcacheGen"
116611249Sradhika.jagtap@ARM.com            " event @%lli.\n", curTick());
116711249Sradhika.jagtap@ARM.com    schedule(icacheNextEvent, curTick());
116811249Sradhika.jagtap@ARM.com}
116911249Sradhika.jagtap@ARM.com
117011249Sradhika.jagtap@ARM.comvoid
117111249Sradhika.jagtap@ARM.comTraceCPU::dcacheRetryRecvd()
117211249Sradhika.jagtap@ARM.com{
117311249Sradhika.jagtap@ARM.com    // Schedule an event to go through the execute flow in the same tick as
117411249Sradhika.jagtap@ARM.com    // retry is received
117511249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Dcache retry received. Scheduling next DcacheGen"
117611249Sradhika.jagtap@ARM.com            " event @%lli.\n", curTick());
117711249Sradhika.jagtap@ARM.com    schedule(dcacheNextEvent, curTick());
117811249Sradhika.jagtap@ARM.com}
117911249Sradhika.jagtap@ARM.com
118011249Sradhika.jagtap@ARM.comvoid
118111249Sradhika.jagtap@ARM.comTraceCPU::schedDcacheNextEvent(Tick when)
118211249Sradhika.jagtap@ARM.com{
118311249Sradhika.jagtap@ARM.com    if (!dcacheNextEvent.scheduled()) {
118411249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Scheduling next DcacheGen event at %lli.\n",
118511249Sradhika.jagtap@ARM.com                when);
118611249Sradhika.jagtap@ARM.com        schedule(dcacheNextEvent, when);
118711249Sradhika.jagtap@ARM.com        ++numSchedDcacheEvent;
118811249Sradhika.jagtap@ARM.com    } else if (when < dcacheNextEvent.when()) {
118911249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Re-scheduling next dcache event from %lli"
119011249Sradhika.jagtap@ARM.com                " to %lli.\n", dcacheNextEvent.when(), when);
119111249Sradhika.jagtap@ARM.com        reschedule(dcacheNextEvent, when);
119211249Sradhika.jagtap@ARM.com    }
119311249Sradhika.jagtap@ARM.com
119411249Sradhika.jagtap@ARM.com}
119511249Sradhika.jagtap@ARM.com
119611249Sradhika.jagtap@ARM.combool
119711249Sradhika.jagtap@ARM.comTraceCPU::IcachePort::recvTimingResp(PacketPtr pkt)
119811249Sradhika.jagtap@ARM.com{
119911249Sradhika.jagtap@ARM.com    // All responses on the instruction fetch side are ignored. Simply delete
120011249Sradhika.jagtap@ARM.com    // the request and packet to free allocated memory
120111249Sradhika.jagtap@ARM.com    delete pkt->req;
120211249Sradhika.jagtap@ARM.com    delete pkt;
120311249Sradhika.jagtap@ARM.com
120411249Sradhika.jagtap@ARM.com    return true;
120511249Sradhika.jagtap@ARM.com}
120611249Sradhika.jagtap@ARM.com
120711249Sradhika.jagtap@ARM.comvoid
120811249Sradhika.jagtap@ARM.comTraceCPU::IcachePort::recvReqRetry()
120911249Sradhika.jagtap@ARM.com{
121011249Sradhika.jagtap@ARM.com    owner->icacheRetryRecvd();
121111249Sradhika.jagtap@ARM.com}
121211249Sradhika.jagtap@ARM.com
121311249Sradhika.jagtap@ARM.comvoid
121411249Sradhika.jagtap@ARM.comTraceCPU::dcacheRecvTimingResp(PacketPtr pkt)
121511249Sradhika.jagtap@ARM.com{
121611249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Received timing response from Dcache.\n");
121711249Sradhika.jagtap@ARM.com    dcacheGen.completeMemAccess(pkt);
121811249Sradhika.jagtap@ARM.com}
121911249Sradhika.jagtap@ARM.com
122011249Sradhika.jagtap@ARM.combool
122111249Sradhika.jagtap@ARM.comTraceCPU::DcachePort::recvTimingResp(PacketPtr pkt)
122211249Sradhika.jagtap@ARM.com{
122311249Sradhika.jagtap@ARM.com    // Handle the responses for data memory requests which is done inside the
122411249Sradhika.jagtap@ARM.com    // elastic data generator
122511249Sradhika.jagtap@ARM.com    owner->dcacheRecvTimingResp(pkt);
122611249Sradhika.jagtap@ARM.com    // After processing the response delete the request and packet to free
122711249Sradhika.jagtap@ARM.com    // memory
122811249Sradhika.jagtap@ARM.com    delete pkt->req;
122911249Sradhika.jagtap@ARM.com    delete pkt;
123011249Sradhika.jagtap@ARM.com
123111249Sradhika.jagtap@ARM.com    return true;
123211249Sradhika.jagtap@ARM.com}
123311249Sradhika.jagtap@ARM.com
123411249Sradhika.jagtap@ARM.comvoid
123511249Sradhika.jagtap@ARM.comTraceCPU::DcachePort::recvReqRetry()
123611249Sradhika.jagtap@ARM.com{
123711249Sradhika.jagtap@ARM.com    owner->dcacheRetryRecvd();
123811249Sradhika.jagtap@ARM.com}
123911249Sradhika.jagtap@ARM.com
124011631Sradhika.jagtap@arm.comTraceCPU::ElasticDataGen::InputStream::InputStream(
124111631Sradhika.jagtap@arm.com    const std::string& filename,
124211631Sradhika.jagtap@arm.com    const double time_multiplier)
124311249Sradhika.jagtap@ARM.com    : trace(filename),
124411631Sradhika.jagtap@arm.com      timeMultiplier(time_multiplier),
124511249Sradhika.jagtap@ARM.com      microOpCount(0)
124611249Sradhika.jagtap@ARM.com{
124711249Sradhika.jagtap@ARM.com    // Create a protobuf message for the header and read it from the stream
124811249Sradhika.jagtap@ARM.com    ProtoMessage::InstDepRecordHeader header_msg;
124911249Sradhika.jagtap@ARM.com    if (!trace.read(header_msg)) {
125011249Sradhika.jagtap@ARM.com        panic("Failed to read packet header from %s\n", filename);
125111249Sradhika.jagtap@ARM.com
125211249Sradhika.jagtap@ARM.com        if (header_msg.tick_freq() != SimClock::Frequency) {
125311249Sradhika.jagtap@ARM.com            panic("Trace %s was recorded with a different tick frequency %d\n",
125411249Sradhika.jagtap@ARM.com                  header_msg.tick_freq());
125511249Sradhika.jagtap@ARM.com        }
125611249Sradhika.jagtap@ARM.com    } else {
125711249Sradhika.jagtap@ARM.com        // Assign window size equal to the field in the trace that was recorded
125811249Sradhika.jagtap@ARM.com        // when the data dependency trace was captured in the o3cpu model
125911249Sradhika.jagtap@ARM.com        windowSize = header_msg.window_size();
126011249Sradhika.jagtap@ARM.com    }
126111249Sradhika.jagtap@ARM.com}
126211249Sradhika.jagtap@ARM.com
126311249Sradhika.jagtap@ARM.comvoid
126411249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::InputStream::reset()
126511249Sradhika.jagtap@ARM.com{
126611249Sradhika.jagtap@ARM.com    trace.reset();
126711249Sradhika.jagtap@ARM.com}
126811249Sradhika.jagtap@ARM.com
126911249Sradhika.jagtap@ARM.combool
127011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::InputStream::read(GraphNode* element)
127111249Sradhika.jagtap@ARM.com{
127211249Sradhika.jagtap@ARM.com    ProtoMessage::InstDepRecord pkt_msg;
127311249Sradhika.jagtap@ARM.com    if (trace.read(pkt_msg)) {
127411249Sradhika.jagtap@ARM.com        // Required fields
127511249Sradhika.jagtap@ARM.com        element->seqNum = pkt_msg.seq_num();
127611252Sradhika.jagtap@ARM.com        element->type = pkt_msg.type();
127711631Sradhika.jagtap@arm.com        // Scale the compute delay to effectively scale the Trace CPU frequency
127811631Sradhika.jagtap@arm.com        element->compDelay = pkt_msg.comp_delay() * timeMultiplier;
127911249Sradhika.jagtap@ARM.com
128011249Sradhika.jagtap@ARM.com        // Repeated field robDepList
128111249Sradhika.jagtap@ARM.com        element->clearRobDep();
128211249Sradhika.jagtap@ARM.com        assert((pkt_msg.rob_dep()).size() <= element->maxRobDep);
128311249Sradhika.jagtap@ARM.com        for (int i = 0; i < (pkt_msg.rob_dep()).size(); i++) {
128411249Sradhika.jagtap@ARM.com            element->robDep[element->numRobDep] = pkt_msg.rob_dep(i);
128511249Sradhika.jagtap@ARM.com            element->numRobDep += 1;
128611249Sradhika.jagtap@ARM.com        }
128711249Sradhika.jagtap@ARM.com
128811249Sradhika.jagtap@ARM.com        // Repeated field
128911249Sradhika.jagtap@ARM.com        element->clearRegDep();
129011249Sradhika.jagtap@ARM.com        assert((pkt_msg.reg_dep()).size() <= TheISA::MaxInstSrcRegs);
129111249Sradhika.jagtap@ARM.com        for (int i = 0; i < (pkt_msg.reg_dep()).size(); i++) {
129211249Sradhika.jagtap@ARM.com            // There is a possibility that an instruction has both, a register
129311249Sradhika.jagtap@ARM.com            // and order dependency on an instruction. In such a case, the
129411249Sradhika.jagtap@ARM.com            // register dependency is omitted
129511249Sradhika.jagtap@ARM.com            bool duplicate = false;
129611249Sradhika.jagtap@ARM.com            for (int j = 0; j < element->numRobDep; j++) {
129711249Sradhika.jagtap@ARM.com                duplicate |= (pkt_msg.reg_dep(i) == element->robDep[j]);
129811249Sradhika.jagtap@ARM.com            }
129911249Sradhika.jagtap@ARM.com            if (!duplicate) {
130011249Sradhika.jagtap@ARM.com                element->regDep[element->numRegDep] = pkt_msg.reg_dep(i);
130111249Sradhika.jagtap@ARM.com                element->numRegDep += 1;
130211249Sradhika.jagtap@ARM.com            }
130311249Sradhika.jagtap@ARM.com        }
130411249Sradhika.jagtap@ARM.com
130511249Sradhika.jagtap@ARM.com        // Optional fields
130611253Sradhika.jagtap@ARM.com        if (pkt_msg.has_p_addr())
130711253Sradhika.jagtap@ARM.com            element->physAddr = pkt_msg.p_addr();
130811249Sradhika.jagtap@ARM.com        else
130911253Sradhika.jagtap@ARM.com            element->physAddr = 0;
131011253Sradhika.jagtap@ARM.com
131111253Sradhika.jagtap@ARM.com        if (pkt_msg.has_v_addr())
131211253Sradhika.jagtap@ARM.com            element->virtAddr = pkt_msg.v_addr();
131311253Sradhika.jagtap@ARM.com        else
131411253Sradhika.jagtap@ARM.com            element->virtAddr = 0;
131511253Sradhika.jagtap@ARM.com
131611253Sradhika.jagtap@ARM.com        if (pkt_msg.has_asid())
131711253Sradhika.jagtap@ARM.com            element->asid = pkt_msg.asid();
131811253Sradhika.jagtap@ARM.com        else
131911253Sradhika.jagtap@ARM.com            element->asid = 0;
132011249Sradhika.jagtap@ARM.com
132111249Sradhika.jagtap@ARM.com        if (pkt_msg.has_size())
132211249Sradhika.jagtap@ARM.com            element->size = pkt_msg.size();
132311249Sradhika.jagtap@ARM.com        else
132411249Sradhika.jagtap@ARM.com            element->size = 0;
132511249Sradhika.jagtap@ARM.com
132611249Sradhika.jagtap@ARM.com        if (pkt_msg.has_flags())
132711249Sradhika.jagtap@ARM.com            element->flags = pkt_msg.flags();
132811249Sradhika.jagtap@ARM.com        else
132911249Sradhika.jagtap@ARM.com            element->flags = 0;
133011249Sradhika.jagtap@ARM.com
133111249Sradhika.jagtap@ARM.com        if (pkt_msg.has_pc())
133211249Sradhika.jagtap@ARM.com            element->pc = pkt_msg.pc();
133311249Sradhika.jagtap@ARM.com        else
133411249Sradhika.jagtap@ARM.com            element->pc = 0;
133511249Sradhika.jagtap@ARM.com
133611249Sradhika.jagtap@ARM.com        // ROB occupancy number
133711249Sradhika.jagtap@ARM.com        ++microOpCount;
133811249Sradhika.jagtap@ARM.com        if (pkt_msg.has_weight()) {
133911249Sradhika.jagtap@ARM.com            microOpCount += pkt_msg.weight();
134011249Sradhika.jagtap@ARM.com        }
134111249Sradhika.jagtap@ARM.com        element->robNum = microOpCount;
134211249Sradhika.jagtap@ARM.com        return true;
134311249Sradhika.jagtap@ARM.com    }
134411249Sradhika.jagtap@ARM.com
134511249Sradhika.jagtap@ARM.com    // We have reached the end of the file
134611249Sradhika.jagtap@ARM.com    return false;
134711249Sradhika.jagtap@ARM.com}
134811249Sradhika.jagtap@ARM.com
134911249Sradhika.jagtap@ARM.combool
135011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeRegDep(NodeSeqNum reg_dep)
135111249Sradhika.jagtap@ARM.com{
135211249Sradhika.jagtap@ARM.com    for (auto& own_reg_dep : regDep) {
135311249Sradhika.jagtap@ARM.com        if (own_reg_dep == reg_dep) {
135411249Sradhika.jagtap@ARM.com            // If register dependency is found, make it zero and return true
135511249Sradhika.jagtap@ARM.com            own_reg_dep = 0;
135611294Sandreas.hansson@arm.com            assert(numRegDep > 0);
135711249Sradhika.jagtap@ARM.com            --numRegDep;
135811249Sradhika.jagtap@ARM.com            DPRINTFR(TraceCPUData, "\tFor %lli: Marking register dependency %lli "
135911249Sradhika.jagtap@ARM.com                    "done.\n", seqNum, reg_dep);
136011249Sradhika.jagtap@ARM.com            return true;
136111249Sradhika.jagtap@ARM.com        }
136211249Sradhika.jagtap@ARM.com    }
136311249Sradhika.jagtap@ARM.com
136411249Sradhika.jagtap@ARM.com    // Return false if the dependency is not found
136511249Sradhika.jagtap@ARM.com    return false;
136611249Sradhika.jagtap@ARM.com}
136711249Sradhika.jagtap@ARM.com
136811249Sradhika.jagtap@ARM.combool
136911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeRobDep(NodeSeqNum rob_dep)
137011249Sradhika.jagtap@ARM.com{
137111249Sradhika.jagtap@ARM.com    for (auto& own_rob_dep : robDep) {
137211249Sradhika.jagtap@ARM.com        if (own_rob_dep == rob_dep) {
137311249Sradhika.jagtap@ARM.com            // If the rob dependency is found, make it zero and return true
137411249Sradhika.jagtap@ARM.com            own_rob_dep = 0;
137511294Sandreas.hansson@arm.com            assert(numRobDep > 0);
137611249Sradhika.jagtap@ARM.com            --numRobDep;
137711249Sradhika.jagtap@ARM.com            DPRINTFR(TraceCPUData, "\tFor %lli: Marking ROB dependency %lli "
137811249Sradhika.jagtap@ARM.com                "done.\n", seqNum, rob_dep);
137911249Sradhika.jagtap@ARM.com            return true;
138011249Sradhika.jagtap@ARM.com        }
138111249Sradhika.jagtap@ARM.com    }
138211249Sradhika.jagtap@ARM.com    return false;
138311249Sradhika.jagtap@ARM.com}
138411249Sradhika.jagtap@ARM.com
138511249Sradhika.jagtap@ARM.comvoid
138611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::clearRegDep() {
138711249Sradhika.jagtap@ARM.com    for (auto& own_reg_dep : regDep) {
138811249Sradhika.jagtap@ARM.com        own_reg_dep = 0;
138911249Sradhika.jagtap@ARM.com    }
139011249Sradhika.jagtap@ARM.com    numRegDep = 0;
139111249Sradhika.jagtap@ARM.com}
139211249Sradhika.jagtap@ARM.com
139311249Sradhika.jagtap@ARM.comvoid
139411249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::clearRobDep() {
139511249Sradhika.jagtap@ARM.com    for (auto& own_rob_dep : robDep) {
139611249Sradhika.jagtap@ARM.com        own_rob_dep = 0;
139711249Sradhika.jagtap@ARM.com    }
139811249Sradhika.jagtap@ARM.com    numRobDep = 0;
139911249Sradhika.jagtap@ARM.com}
140011249Sradhika.jagtap@ARM.com
140111249Sradhika.jagtap@ARM.combool
140211249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeDepOnInst(NodeSeqNum done_seq_num)
140311249Sradhika.jagtap@ARM.com{
140411249Sradhika.jagtap@ARM.com    // If it is an rob dependency then remove it
140511249Sradhika.jagtap@ARM.com    if (!removeRobDep(done_seq_num)) {
140611249Sradhika.jagtap@ARM.com        // If it is not an rob dependency then it must be a register dependency
140711249Sradhika.jagtap@ARM.com        // If the register dependency is not found, it violates an assumption
140811249Sradhika.jagtap@ARM.com        // and must be caught by assert.
140911249Sradhika.jagtap@ARM.com        bool regdep_found M5_VAR_USED = removeRegDep(done_seq_num);
141011249Sradhika.jagtap@ARM.com        assert(regdep_found);
141111249Sradhika.jagtap@ARM.com    }
141211249Sradhika.jagtap@ARM.com    // Return true if the node is dependency free
141311249Sradhika.jagtap@ARM.com    return (numRobDep == 0 && numRegDep == 0);
141411249Sradhika.jagtap@ARM.com}
141511249Sradhika.jagtap@ARM.com
141611249Sradhika.jagtap@ARM.comvoid
141711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace() const
141811249Sradhika.jagtap@ARM.com{
141911249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "%lli", seqNum);
142011252Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, ",%s", typeToStr());
142111252Sradhika.jagtap@ARM.com    if (isLoad() || isStore()) {
142211253Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%i", physAddr);
142311249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%i", size);
142411249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%i", flags);
142511249Sradhika.jagtap@ARM.com    }
142611249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, ",%lli", compDelay);
142711249Sradhika.jagtap@ARM.com    int i = 0;
142811249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "robDep:");
142911249Sradhika.jagtap@ARM.com    while (robDep[i] != 0) {
143011249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%lli", robDep[i]);
143111249Sradhika.jagtap@ARM.com        i++;
143211249Sradhika.jagtap@ARM.com    }
143311249Sradhika.jagtap@ARM.com    i = 0;
143411249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "regDep:");
143511249Sradhika.jagtap@ARM.com    while (regDep[i] != 0) {
143611249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%lli", regDep[i]);
143711249Sradhika.jagtap@ARM.com        i++;
143811249Sradhika.jagtap@ARM.com    }
143911249Sradhika.jagtap@ARM.com    auto child_itr = dependents.begin();
144011249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "dependents:");
144111249Sradhika.jagtap@ARM.com    while (child_itr != dependents.end()) {
144211249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ":%lli", (*child_itr)->seqNum);
144311249Sradhika.jagtap@ARM.com        child_itr++;
144411249Sradhika.jagtap@ARM.com    }
144511249Sradhika.jagtap@ARM.com
144611249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "\n");
144711249Sradhika.jagtap@ARM.com}
144811249Sradhika.jagtap@ARM.com
144911252Sradhika.jagtap@ARM.comstd::string
145011252Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::typeToStr() const
145111252Sradhika.jagtap@ARM.com{
145211252Sradhika.jagtap@ARM.com    return Record::RecordType_Name(type);
145311252Sradhika.jagtap@ARM.com}
145411252Sradhika.jagtap@ARM.com
145511249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::InputStream(const std::string& filename)
145611249Sradhika.jagtap@ARM.com    : trace(filename)
145711249Sradhika.jagtap@ARM.com{
145811249Sradhika.jagtap@ARM.com    // Create a protobuf message for the header and read it from the stream
145911249Sradhika.jagtap@ARM.com    ProtoMessage::PacketHeader header_msg;
146011249Sradhika.jagtap@ARM.com    if (!trace.read(header_msg)) {
146111249Sradhika.jagtap@ARM.com        panic("Failed to read packet header from %s\n", filename);
146211249Sradhika.jagtap@ARM.com
146311249Sradhika.jagtap@ARM.com        if (header_msg.tick_freq() != SimClock::Frequency) {
146411249Sradhika.jagtap@ARM.com            panic("Trace %s was recorded with a different tick frequency %d\n",
146511249Sradhika.jagtap@ARM.com                  header_msg.tick_freq());
146611249Sradhika.jagtap@ARM.com        }
146711249Sradhika.jagtap@ARM.com    }
146811249Sradhika.jagtap@ARM.com}
146911249Sradhika.jagtap@ARM.com
147011249Sradhika.jagtap@ARM.comvoid
147111249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::reset()
147211249Sradhika.jagtap@ARM.com{
147311249Sradhika.jagtap@ARM.com    trace.reset();
147411249Sradhika.jagtap@ARM.com}
147511249Sradhika.jagtap@ARM.com
147611249Sradhika.jagtap@ARM.combool
147711249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::read(TraceElement* element)
147811249Sradhika.jagtap@ARM.com{
147911249Sradhika.jagtap@ARM.com    ProtoMessage::Packet pkt_msg;
148011249Sradhika.jagtap@ARM.com    if (trace.read(pkt_msg)) {
148111249Sradhika.jagtap@ARM.com        element->cmd = pkt_msg.cmd();
148211249Sradhika.jagtap@ARM.com        element->addr = pkt_msg.addr();
148311249Sradhika.jagtap@ARM.com        element->blocksize = pkt_msg.size();
148411249Sradhika.jagtap@ARM.com        element->tick = pkt_msg.tick();
148511249Sradhika.jagtap@ARM.com        element->flags = pkt_msg.has_flags() ? pkt_msg.flags() : 0;
148611249Sradhika.jagtap@ARM.com        element->pc = pkt_msg.has_pc() ? pkt_msg.pc() : 0;
148711249Sradhika.jagtap@ARM.com        return true;
148811249Sradhika.jagtap@ARM.com    }
148911249Sradhika.jagtap@ARM.com
149011249Sradhika.jagtap@ARM.com    // We have reached the end of the file
149111249Sradhika.jagtap@ARM.com    return false;
149211249Sradhika.jagtap@ARM.com}
1493