trace_cpu.cc revision 11252
111249Sradhika.jagtap@ARM.com/*
211249Sradhika.jagtap@ARM.com * Copyright (c) 2013 - 2015 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,
5911249Sradhika.jagtap@ARM.com                    params->sizeROB, params->sizeStoreBuffer,
6011249Sradhika.jagtap@ARM.com                    params->sizeLoadBuffer),
6111249Sradhika.jagtap@ARM.com        icacheNextEvent(this),
6211249Sradhika.jagtap@ARM.com        dcacheNextEvent(this),
6311249Sradhika.jagtap@ARM.com        oneTraceComplete(false),
6411249Sradhika.jagtap@ARM.com        firstFetchTick(0),
6511249Sradhika.jagtap@ARM.com        execCompleteEvent(nullptr)
6611249Sradhika.jagtap@ARM.com{
6711249Sradhika.jagtap@ARM.com    // Increment static counter for number of Trace CPUs.
6811249Sradhika.jagtap@ARM.com    ++TraceCPU::numTraceCPUs;
6911249Sradhika.jagtap@ARM.com
7011249Sradhika.jagtap@ARM.com    // Check that the python parameters for sizes of ROB, store buffer and load
7111249Sradhika.jagtap@ARM.com    // buffer do not overflow the corresponding C++ variables.
7211249Sradhika.jagtap@ARM.com    fatal_if(params->sizeROB > UINT16_MAX, "ROB size set to %d exceeds the "
7311249Sradhika.jagtap@ARM.com                "max. value of %d.\n", params->sizeROB, UINT16_MAX);
7411249Sradhika.jagtap@ARM.com    fatal_if(params->sizeStoreBuffer > UINT16_MAX, "ROB size set to %d "
7511249Sradhika.jagtap@ARM.com                "exceeds the max. value of %d.\n", params->sizeROB,
7611249Sradhika.jagtap@ARM.com                UINT16_MAX);
7711249Sradhika.jagtap@ARM.com    fatal_if(params->sizeLoadBuffer > UINT16_MAX, "Load buffer size set to"
7811249Sradhika.jagtap@ARM.com                " %d exceeds the max. value of %d.\n",
7911249Sradhika.jagtap@ARM.com                params->sizeLoadBuffer, UINT16_MAX);
8011249Sradhika.jagtap@ARM.com}
8111249Sradhika.jagtap@ARM.com
8211249Sradhika.jagtap@ARM.comTraceCPU::~TraceCPU()
8311249Sradhika.jagtap@ARM.com{
8411249Sradhika.jagtap@ARM.com
8511249Sradhika.jagtap@ARM.com}
8611249Sradhika.jagtap@ARM.com
8711249Sradhika.jagtap@ARM.comTraceCPU*
8811249Sradhika.jagtap@ARM.comTraceCPUParams::create()
8911249Sradhika.jagtap@ARM.com{
9011249Sradhika.jagtap@ARM.com    return new TraceCPU(this);
9111249Sradhika.jagtap@ARM.com}
9211249Sradhika.jagtap@ARM.com
9311249Sradhika.jagtap@ARM.comvoid
9411249Sradhika.jagtap@ARM.comTraceCPU::takeOverFrom(BaseCPU *oldCPU)
9511249Sradhika.jagtap@ARM.com{
9611249Sradhika.jagtap@ARM.com    // Unbind the ports of the old CPU and bind the ports of the TraceCPU.
9711249Sradhika.jagtap@ARM.com    assert(!getInstPort().isConnected());
9811249Sradhika.jagtap@ARM.com    assert(oldCPU->getInstPort().isConnected());
9911249Sradhika.jagtap@ARM.com    BaseSlavePort &inst_peer_port = oldCPU->getInstPort().getSlavePort();
10011249Sradhika.jagtap@ARM.com    oldCPU->getInstPort().unbind();
10111249Sradhika.jagtap@ARM.com    getInstPort().bind(inst_peer_port);
10211249Sradhika.jagtap@ARM.com
10311249Sradhika.jagtap@ARM.com    assert(!getDataPort().isConnected());
10411249Sradhika.jagtap@ARM.com    assert(oldCPU->getDataPort().isConnected());
10511249Sradhika.jagtap@ARM.com    BaseSlavePort &data_peer_port = oldCPU->getDataPort().getSlavePort();
10611249Sradhika.jagtap@ARM.com    oldCPU->getDataPort().unbind();
10711249Sradhika.jagtap@ARM.com    getDataPort().bind(data_peer_port);
10811249Sradhika.jagtap@ARM.com}
10911249Sradhika.jagtap@ARM.com
11011249Sradhika.jagtap@ARM.comvoid
11111249Sradhika.jagtap@ARM.comTraceCPU::init()
11211249Sradhika.jagtap@ARM.com{
11311249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "Instruction fetch request trace file is \"%s\"."
11411249Sradhika.jagtap@ARM.com            "\n", instTraceFile);
11511249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Data memory request trace file is \"%s\".\n",
11611249Sradhika.jagtap@ARM.com            dataTraceFile);
11711249Sradhika.jagtap@ARM.com
11811249Sradhika.jagtap@ARM.com    BaseCPU::init();
11911249Sradhika.jagtap@ARM.com
12011249Sradhika.jagtap@ARM.com    // Get the send tick of the first instruction read request and schedule
12111249Sradhika.jagtap@ARM.com    // icacheNextEvent at that tick.
12211249Sradhika.jagtap@ARM.com    Tick first_icache_tick = icacheGen.init();
12311249Sradhika.jagtap@ARM.com    schedule(icacheNextEvent, first_icache_tick);
12411249Sradhika.jagtap@ARM.com
12511249Sradhika.jagtap@ARM.com    // Get the send tick of the first data read/write request and schedule
12611249Sradhika.jagtap@ARM.com    // dcacheNextEvent at that tick.
12711249Sradhika.jagtap@ARM.com    Tick first_dcache_tick = dcacheGen.init();
12811249Sradhika.jagtap@ARM.com    schedule(dcacheNextEvent, first_dcache_tick);
12911249Sradhika.jagtap@ARM.com
13011249Sradhika.jagtap@ARM.com    // The static counter for number of Trace CPUs is correctly set at this
13111249Sradhika.jagtap@ARM.com    // point so create an event and pass it.
13211249Sradhika.jagtap@ARM.com    execCompleteEvent = new CountedExitEvent("end of all traces reached.",
13311249Sradhika.jagtap@ARM.com                                                numTraceCPUs);
13411249Sradhika.jagtap@ARM.com    // Save the first fetch request tick to dump it as tickOffset
13511249Sradhika.jagtap@ARM.com    firstFetchTick = first_icache_tick;
13611249Sradhika.jagtap@ARM.com}
13711249Sradhika.jagtap@ARM.com
13811249Sradhika.jagtap@ARM.comvoid
13911249Sradhika.jagtap@ARM.comTraceCPU::schedIcacheNext()
14011249Sradhika.jagtap@ARM.com{
14111249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "IcacheGen event.\n");
14211249Sradhika.jagtap@ARM.com
14311249Sradhika.jagtap@ARM.com    // Try to send the current packet or a retry packet if there is one
14411249Sradhika.jagtap@ARM.com    bool sched_next = icacheGen.tryNext();
14511249Sradhika.jagtap@ARM.com    // If packet sent successfully, schedule next event
14611249Sradhika.jagtap@ARM.com    if (sched_next) {
14711249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUInst, "Scheduling next icacheGen event "
14811249Sradhika.jagtap@ARM.com                "at %d.\n", curTick() + icacheGen.tickDelta());
14911249Sradhika.jagtap@ARM.com        schedule(icacheNextEvent, curTick() + icacheGen.tickDelta());
15011249Sradhika.jagtap@ARM.com        ++numSchedIcacheEvent;
15111249Sradhika.jagtap@ARM.com    } else {
15211249Sradhika.jagtap@ARM.com        // check if traceComplete. If not, do nothing because sending failed
15311249Sradhika.jagtap@ARM.com        // and next event will be scheduled via RecvRetry()
15411249Sradhika.jagtap@ARM.com        if (icacheGen.isTraceComplete()) {
15511249Sradhika.jagtap@ARM.com            // If this is the first trace to complete, set the variable. If it
15611249Sradhika.jagtap@ARM.com            // is already set then both traces are complete to exit sim.
15711249Sradhika.jagtap@ARM.com            checkAndSchedExitEvent();
15811249Sradhika.jagtap@ARM.com        }
15911249Sradhika.jagtap@ARM.com    }
16011249Sradhika.jagtap@ARM.com    return;
16111249Sradhika.jagtap@ARM.com}
16211249Sradhika.jagtap@ARM.com
16311249Sradhika.jagtap@ARM.comvoid
16411249Sradhika.jagtap@ARM.comTraceCPU::schedDcacheNext()
16511249Sradhika.jagtap@ARM.com{
16611249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "DcacheGen event.\n");
16711249Sradhika.jagtap@ARM.com
16811249Sradhika.jagtap@ARM.com    dcacheGen.execute();
16911249Sradhika.jagtap@ARM.com    if (dcacheGen.isExecComplete()) {
17011249Sradhika.jagtap@ARM.com        checkAndSchedExitEvent();
17111249Sradhika.jagtap@ARM.com    }
17211249Sradhika.jagtap@ARM.com}
17311249Sradhika.jagtap@ARM.com
17411249Sradhika.jagtap@ARM.comvoid
17511249Sradhika.jagtap@ARM.comTraceCPU::checkAndSchedExitEvent()
17611249Sradhika.jagtap@ARM.com{
17711249Sradhika.jagtap@ARM.com    if (!oneTraceComplete) {
17811249Sradhika.jagtap@ARM.com        oneTraceComplete = true;
17911249Sradhika.jagtap@ARM.com    } else {
18011249Sradhika.jagtap@ARM.com        // Schedule event to indicate execution is complete as both
18111249Sradhika.jagtap@ARM.com        // instruction and data access traces have been played back.
18211249Sradhika.jagtap@ARM.com        inform("%s: Execution complete.\n", name());
18311249Sradhika.jagtap@ARM.com
18411249Sradhika.jagtap@ARM.com        // Record stats which are computed at the end of simulation
18511249Sradhika.jagtap@ARM.com        tickOffset = firstFetchTick;
18611249Sradhika.jagtap@ARM.com        numCycles = (clockEdge() - firstFetchTick) / clockPeriod();
18711249Sradhika.jagtap@ARM.com        numOps = dcacheGen.getMicroOpCount();
18811249Sradhika.jagtap@ARM.com        schedule(*execCompleteEvent, curTick());
18911249Sradhika.jagtap@ARM.com    }
19011249Sradhika.jagtap@ARM.com}
19111249Sradhika.jagtap@ARM.com
19211249Sradhika.jagtap@ARM.comvoid
19311249Sradhika.jagtap@ARM.comTraceCPU::regStats()
19411249Sradhika.jagtap@ARM.com{
19511249Sradhika.jagtap@ARM.com
19611249Sradhika.jagtap@ARM.com    BaseCPU::regStats();
19711249Sradhika.jagtap@ARM.com
19811249Sradhika.jagtap@ARM.com    numSchedDcacheEvent
19911249Sradhika.jagtap@ARM.com    .name(name() + ".numSchedDcacheEvent")
20011249Sradhika.jagtap@ARM.com    .desc("Number of events scheduled to trigger data request generator")
20111249Sradhika.jagtap@ARM.com    ;
20211249Sradhika.jagtap@ARM.com
20311249Sradhika.jagtap@ARM.com    numSchedIcacheEvent
20411249Sradhika.jagtap@ARM.com    .name(name() + ".numSchedIcacheEvent")
20511249Sradhika.jagtap@ARM.com    .desc("Number of events scheduled to trigger instruction request generator")
20611249Sradhika.jagtap@ARM.com    ;
20711249Sradhika.jagtap@ARM.com
20811249Sradhika.jagtap@ARM.com    numOps
20911249Sradhika.jagtap@ARM.com    .name(name() + ".numOps")
21011249Sradhika.jagtap@ARM.com    .desc("Number of micro-ops simulated by the Trace CPU")
21111249Sradhika.jagtap@ARM.com    ;
21211249Sradhika.jagtap@ARM.com
21311249Sradhika.jagtap@ARM.com    cpi
21411249Sradhika.jagtap@ARM.com    .name(name() + ".cpi")
21511249Sradhika.jagtap@ARM.com    .desc("Cycles per micro-op used as a proxy for CPI")
21611249Sradhika.jagtap@ARM.com    .precision(6)
21711249Sradhika.jagtap@ARM.com    ;
21811249Sradhika.jagtap@ARM.com    cpi = numCycles/numOps;
21911249Sradhika.jagtap@ARM.com
22011249Sradhika.jagtap@ARM.com    tickOffset
22111249Sradhika.jagtap@ARM.com    .name(name() + ".tickOffset")
22211249Sradhika.jagtap@ARM.com    .desc("The first execution tick for the root node of elastic traces")
22311249Sradhika.jagtap@ARM.com    ;
22411249Sradhika.jagtap@ARM.com
22511249Sradhika.jagtap@ARM.com    icacheGen.regStats();
22611249Sradhika.jagtap@ARM.com    dcacheGen.regStats();
22711249Sradhika.jagtap@ARM.com}
22811249Sradhika.jagtap@ARM.com
22911249Sradhika.jagtap@ARM.comvoid
23011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::regStats()
23111249Sradhika.jagtap@ARM.com{
23211249Sradhika.jagtap@ARM.com    using namespace Stats;
23311249Sradhika.jagtap@ARM.com
23411249Sradhika.jagtap@ARM.com    maxDependents
23511249Sradhika.jagtap@ARM.com    .name(name() + ".maxDependents")
23611249Sradhika.jagtap@ARM.com    .desc("Max number of dependents observed on a node")
23711249Sradhika.jagtap@ARM.com    ;
23811249Sradhika.jagtap@ARM.com
23911249Sradhika.jagtap@ARM.com    maxReadyListSize
24011249Sradhika.jagtap@ARM.com    .name(name() + ".maxReadyListSize")
24111249Sradhika.jagtap@ARM.com    .desc("Max size of the ready list observed")
24211249Sradhika.jagtap@ARM.com    ;
24311249Sradhika.jagtap@ARM.com
24411249Sradhika.jagtap@ARM.com    numSendAttempted
24511249Sradhika.jagtap@ARM.com    .name(name() + ".numSendAttempted")
24611249Sradhika.jagtap@ARM.com    .desc("Number of first attempts to send a request")
24711249Sradhika.jagtap@ARM.com    ;
24811249Sradhika.jagtap@ARM.com
24911249Sradhika.jagtap@ARM.com    numSendSucceeded
25011249Sradhika.jagtap@ARM.com    .name(name() + ".numSendSucceeded")
25111249Sradhika.jagtap@ARM.com    .desc("Number of successful first attempts")
25211249Sradhika.jagtap@ARM.com    ;
25311249Sradhika.jagtap@ARM.com
25411249Sradhika.jagtap@ARM.com    numSendFailed
25511249Sradhika.jagtap@ARM.com    .name(name() + ".numSendFailed")
25611249Sradhika.jagtap@ARM.com    .desc("Number of failed first attempts")
25711249Sradhika.jagtap@ARM.com    ;
25811249Sradhika.jagtap@ARM.com
25911249Sradhika.jagtap@ARM.com    numRetrySucceeded
26011249Sradhika.jagtap@ARM.com    .name(name() + ".numRetrySucceeded")
26111249Sradhika.jagtap@ARM.com    .desc("Number of successful retries")
26211249Sradhika.jagtap@ARM.com    ;
26311249Sradhika.jagtap@ARM.com
26411249Sradhika.jagtap@ARM.com    numSplitReqs
26511249Sradhika.jagtap@ARM.com    .name(name() + ".numSplitReqs")
26611249Sradhika.jagtap@ARM.com    .desc("Number of split requests")
26711249Sradhika.jagtap@ARM.com    ;
26811249Sradhika.jagtap@ARM.com
26911249Sradhika.jagtap@ARM.com    numSOLoads
27011249Sradhika.jagtap@ARM.com    .name(name() + ".numSOLoads")
27111249Sradhika.jagtap@ARM.com    .desc("Number of strictly ordered loads")
27211249Sradhika.jagtap@ARM.com    ;
27311249Sradhika.jagtap@ARM.com
27411249Sradhika.jagtap@ARM.com    numSOStores
27511249Sradhika.jagtap@ARM.com    .name(name() + ".numSOStores")
27611249Sradhika.jagtap@ARM.com    .desc("Number of strictly ordered stores")
27711249Sradhika.jagtap@ARM.com    ;
27811249Sradhika.jagtap@ARM.com
27911249Sradhika.jagtap@ARM.com    dataLastTick
28011249Sradhika.jagtap@ARM.com    .name(name() + ".dataLastTick")
28111249Sradhika.jagtap@ARM.com    .desc("Last tick simulated from the elastic data trace")
28211249Sradhika.jagtap@ARM.com    ;
28311249Sradhika.jagtap@ARM.com}
28411249Sradhika.jagtap@ARM.com
28511249Sradhika.jagtap@ARM.comTick
28611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::init()
28711249Sradhika.jagtap@ARM.com{
28811249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Initializing data memory request generator "
28911249Sradhika.jagtap@ARM.com            "DcacheGen: elastic issue with retry.\n");
29011249Sradhika.jagtap@ARM.com
29111249Sradhika.jagtap@ARM.com    if (!readNextWindow())
29211249Sradhika.jagtap@ARM.com        panic("Trace has %d elements. It must have at least %d elements.\n",
29311249Sradhika.jagtap@ARM.com              depGraph.size(), 2 * windowSize);
29411249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "After 1st read, depGraph size:%d.\n",
29511249Sradhika.jagtap@ARM.com            depGraph.size());
29611249Sradhika.jagtap@ARM.com
29711249Sradhika.jagtap@ARM.com    if (!readNextWindow())
29811249Sradhika.jagtap@ARM.com        panic("Trace has %d elements. It must have at least %d elements.\n",
29911249Sradhika.jagtap@ARM.com              depGraph.size(), 2 * windowSize);
30011249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "After 2st read, depGraph size:%d.\n",
30111249Sradhika.jagtap@ARM.com            depGraph.size());
30211249Sradhika.jagtap@ARM.com
30311249Sradhika.jagtap@ARM.com    // Print readyList
30411249Sradhika.jagtap@ARM.com    if (DTRACE(TraceCPUData)) {
30511249Sradhika.jagtap@ARM.com        printReadyList();
30611249Sradhika.jagtap@ARM.com    }
30711249Sradhika.jagtap@ARM.com    auto free_itr = readyList.begin();
30811249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Execute tick of the first dependency free node %lli"
30911249Sradhika.jagtap@ARM.com            " is %d.\n", free_itr->seqNum, free_itr->execTick);
31011249Sradhika.jagtap@ARM.com    // Return the execute tick of the earliest ready node so that an event
31111249Sradhika.jagtap@ARM.com    // can be scheduled to call execute()
31211249Sradhika.jagtap@ARM.com    return (free_itr->execTick);
31311249Sradhika.jagtap@ARM.com}
31411249Sradhika.jagtap@ARM.com
31511249Sradhika.jagtap@ARM.comvoid
31611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::exit()
31711249Sradhika.jagtap@ARM.com{
31811249Sradhika.jagtap@ARM.com    trace.reset();
31911249Sradhika.jagtap@ARM.com}
32011249Sradhika.jagtap@ARM.com
32111249Sradhika.jagtap@ARM.combool
32211249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::readNextWindow()
32311249Sradhika.jagtap@ARM.com{
32411249Sradhika.jagtap@ARM.com
32511249Sradhika.jagtap@ARM.com    // Read and add next window
32611249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Reading next window from file.\n");
32711249Sradhika.jagtap@ARM.com
32811249Sradhika.jagtap@ARM.com    if (traceComplete) {
32911249Sradhika.jagtap@ARM.com        // We are at the end of the file, thus we have no more records.
33011249Sradhika.jagtap@ARM.com        // Return false.
33111249Sradhika.jagtap@ARM.com        return false;
33211249Sradhika.jagtap@ARM.com    }
33311249Sradhika.jagtap@ARM.com
33411249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Start read: Size of depGraph is %d.\n",
33511249Sradhika.jagtap@ARM.com            depGraph.size());
33611249Sradhika.jagtap@ARM.com
33711249Sradhika.jagtap@ARM.com    uint32_t num_read = 0;
33811249Sradhika.jagtap@ARM.com    while (num_read != windowSize) {
33911249Sradhika.jagtap@ARM.com
34011249Sradhika.jagtap@ARM.com        // Create a new graph node
34111249Sradhika.jagtap@ARM.com        GraphNode* new_node = new GraphNode;
34211249Sradhika.jagtap@ARM.com
34311249Sradhika.jagtap@ARM.com        // Read the next line to get the next record. If that fails then end of
34411249Sradhika.jagtap@ARM.com        // trace has been reached and traceComplete needs to be set in addition
34511249Sradhika.jagtap@ARM.com        // to returning false.
34611249Sradhika.jagtap@ARM.com        if (!trace.read(new_node)) {
34711249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUData, "\tTrace complete!\n");
34811249Sradhika.jagtap@ARM.com            traceComplete = true;
34911249Sradhika.jagtap@ARM.com            return false;
35011249Sradhika.jagtap@ARM.com        }
35111249Sradhika.jagtap@ARM.com
35211249Sradhika.jagtap@ARM.com        // Annotate the ROB dependencies of the new node onto the parent nodes.
35311249Sradhika.jagtap@ARM.com        addDepsOnParent(new_node, new_node->robDep, new_node->numRobDep);
35411249Sradhika.jagtap@ARM.com        // Annotate the register dependencies of the new node onto the parent
35511249Sradhika.jagtap@ARM.com        // nodes.
35611249Sradhika.jagtap@ARM.com        addDepsOnParent(new_node, new_node->regDep, new_node->numRegDep);
35711249Sradhika.jagtap@ARM.com
35811249Sradhika.jagtap@ARM.com        num_read++;
35911249Sradhika.jagtap@ARM.com        // Add to map
36011249Sradhika.jagtap@ARM.com        depGraph[new_node->seqNum] = new_node;
36111249Sradhika.jagtap@ARM.com        if (new_node->numRobDep == 0 && new_node->numRegDep == 0) {
36211249Sradhika.jagtap@ARM.com            // Source dependencies are already complete, check if resources
36311249Sradhika.jagtap@ARM.com            // are available and issue. The execution time is approximated
36411249Sradhika.jagtap@ARM.com            // to current time plus the computational delay.
36511249Sradhika.jagtap@ARM.com            checkAndIssue(new_node);
36611249Sradhika.jagtap@ARM.com        }
36711249Sradhika.jagtap@ARM.com    }
36811249Sradhika.jagtap@ARM.com
36911249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "End read: Size of depGraph is %d.\n",
37011249Sradhika.jagtap@ARM.com            depGraph.size());
37111249Sradhika.jagtap@ARM.com    return true;
37211249Sradhika.jagtap@ARM.com}
37311249Sradhika.jagtap@ARM.com
37411249Sradhika.jagtap@ARM.comtemplate<typename T> void
37511249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::addDepsOnParent(GraphNode *new_node,
37611249Sradhika.jagtap@ARM.com                                            T& dep_array, uint8_t& num_dep)
37711249Sradhika.jagtap@ARM.com{
37811249Sradhika.jagtap@ARM.com    for (auto& a_dep : dep_array) {
37911249Sradhika.jagtap@ARM.com        // The convention is to set the dependencies starting with the first
38011249Sradhika.jagtap@ARM.com        // index in the ROB and register dependency arrays. Thus, when we reach
38111249Sradhika.jagtap@ARM.com        // a dependency equal to the initialisation value of zero, we know have
38211249Sradhika.jagtap@ARM.com        // iterated over all dependencies and can break.
38311249Sradhika.jagtap@ARM.com        if (a_dep == 0)
38411249Sradhika.jagtap@ARM.com            break;
38511249Sradhika.jagtap@ARM.com        // We look up the valid dependency, i.e. the parent of this node
38611249Sradhika.jagtap@ARM.com        auto parent_itr = depGraph.find(a_dep);
38711249Sradhika.jagtap@ARM.com        if (parent_itr != depGraph.end()) {
38811249Sradhika.jagtap@ARM.com            // If the parent is found, it is yet to be executed. Append a
38911249Sradhika.jagtap@ARM.com            // pointer to the new node to the dependents list of the parent
39011249Sradhika.jagtap@ARM.com            // node.
39111249Sradhika.jagtap@ARM.com            parent_itr->second->dependents.push_back(new_node);
39211249Sradhika.jagtap@ARM.com            auto num_depts = parent_itr->second->dependents.size();
39311249Sradhika.jagtap@ARM.com            maxDependents = std::max<double>(num_depts, maxDependents.value());
39411249Sradhika.jagtap@ARM.com        } else {
39511249Sradhika.jagtap@ARM.com            // The dependency is not found in the graph. So consider
39611249Sradhika.jagtap@ARM.com            // the execution of the parent is complete, i.e. remove this
39711249Sradhika.jagtap@ARM.com            // dependency.
39811249Sradhika.jagtap@ARM.com            a_dep = 0;
39911249Sradhika.jagtap@ARM.com            num_dep--;
40011249Sradhika.jagtap@ARM.com        }
40111249Sradhika.jagtap@ARM.com    }
40211249Sradhika.jagtap@ARM.com}
40311249Sradhika.jagtap@ARM.com
40411249Sradhika.jagtap@ARM.comvoid
40511249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::execute()
40611249Sradhika.jagtap@ARM.com{
40711249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Execute start occupancy:\n");
40811249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "\tdepGraph = %d, readyList = %d, "
40911249Sradhika.jagtap@ARM.com            "depFreeQueue = %d ,", depGraph.size(), readyList.size(),
41011249Sradhika.jagtap@ARM.com            depFreeQueue.size());
41111249Sradhika.jagtap@ARM.com    hwResource.printOccupancy();
41211249Sradhika.jagtap@ARM.com
41311249Sradhika.jagtap@ARM.com    // Read next window to make sure that dependents of all dep-free nodes
41411249Sradhika.jagtap@ARM.com    // are in the depGraph
41511249Sradhika.jagtap@ARM.com    if (nextRead) {
41611249Sradhika.jagtap@ARM.com        readNextWindow();
41711249Sradhika.jagtap@ARM.com        nextRead = false;
41811249Sradhika.jagtap@ARM.com    }
41911249Sradhika.jagtap@ARM.com
42011249Sradhika.jagtap@ARM.com    // First attempt to issue the pending dependency-free nodes held
42111249Sradhika.jagtap@ARM.com    // in depFreeQueue. If resources have become available for a node,
42211249Sradhika.jagtap@ARM.com    // then issue it, i.e. add the node to readyList.
42311249Sradhika.jagtap@ARM.com    while (!depFreeQueue.empty()) {
42411249Sradhika.jagtap@ARM.com        if (checkAndIssue(depFreeQueue.front(), false)) {
42511249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUData, "Removing from depFreeQueue: seq. num "
42611249Sradhika.jagtap@ARM.com                "%lli.\n", (depFreeQueue.front())->seqNum);
42711249Sradhika.jagtap@ARM.com            depFreeQueue.pop();
42811249Sradhika.jagtap@ARM.com        } else {
42911249Sradhika.jagtap@ARM.com            break;
43011249Sradhika.jagtap@ARM.com        }
43111249Sradhika.jagtap@ARM.com    }
43211249Sradhika.jagtap@ARM.com    // Proceed to execute from readyList
43311249Sradhika.jagtap@ARM.com    auto graph_itr = depGraph.begin();
43411249Sradhika.jagtap@ARM.com    auto free_itr = readyList.begin();
43511249Sradhika.jagtap@ARM.com    // Iterate through readyList until the next free node has its execute
43611249Sradhika.jagtap@ARM.com    // tick later than curTick or the end of readyList is reached
43711249Sradhika.jagtap@ARM.com    while (free_itr->execTick <= curTick() && free_itr != readyList.end()) {
43811249Sradhika.jagtap@ARM.com
43911249Sradhika.jagtap@ARM.com        // Get pointer to the node to be executed
44011249Sradhika.jagtap@ARM.com        graph_itr = depGraph.find(free_itr->seqNum);
44111249Sradhika.jagtap@ARM.com        assert(graph_itr != depGraph.end());
44211249Sradhika.jagtap@ARM.com        GraphNode* node_ptr = graph_itr->second;
44311249Sradhika.jagtap@ARM.com
44411249Sradhika.jagtap@ARM.com        // If there is a retryPkt send that else execute the load
44511249Sradhika.jagtap@ARM.com        if (retryPkt) {
44611249Sradhika.jagtap@ARM.com            // The retryPkt must be the request that was created by the
44711249Sradhika.jagtap@ARM.com            // first node in the readyList.
44811249Sradhika.jagtap@ARM.com            if (retryPkt->req->getReqInstSeqNum() != node_ptr->seqNum) {
44911249Sradhika.jagtap@ARM.com                panic("Retry packet's seqence number does not match "
45011249Sradhika.jagtap@ARM.com                      "the first node in the readyList.\n");
45111249Sradhika.jagtap@ARM.com            }
45211249Sradhika.jagtap@ARM.com            if (port.sendTimingReq(retryPkt)) {
45311249Sradhika.jagtap@ARM.com                ++numRetrySucceeded;
45411249Sradhika.jagtap@ARM.com                retryPkt = nullptr;
45511249Sradhika.jagtap@ARM.com            }
45611252Sradhika.jagtap@ARM.com        } else if (node_ptr->isLoad() || node_ptr->isStore()) {
45711249Sradhika.jagtap@ARM.com            // If there is no retryPkt, attempt to send a memory request in
45811249Sradhika.jagtap@ARM.com            // case of a load or store node. If the send fails, executeMemReq()
45911249Sradhika.jagtap@ARM.com            // returns a packet pointer, which we save in retryPkt. In case of
46011249Sradhika.jagtap@ARM.com            // a comp node we don't do anything and simply continue as if the
46111249Sradhika.jagtap@ARM.com            // execution of the comp node succedded.
46211249Sradhika.jagtap@ARM.com            retryPkt = executeMemReq(node_ptr);
46311249Sradhika.jagtap@ARM.com        }
46411249Sradhika.jagtap@ARM.com        // If the retryPkt or a new load/store node failed, we exit from here
46511249Sradhika.jagtap@ARM.com        // as a retry from cache will bring the control to execute(). The
46611249Sradhika.jagtap@ARM.com        // first node in readyList then, will be the failed node.
46711249Sradhika.jagtap@ARM.com        if (retryPkt) {
46811249Sradhika.jagtap@ARM.com            break;
46911249Sradhika.jagtap@ARM.com        }
47011249Sradhika.jagtap@ARM.com
47111249Sradhika.jagtap@ARM.com        // Proceed to remove dependencies for the successfully executed node.
47211249Sradhika.jagtap@ARM.com        // If it is a load which is not strictly ordered and we sent a
47311249Sradhika.jagtap@ARM.com        // request for it successfully, we do not yet mark any register
47411249Sradhika.jagtap@ARM.com        // dependencies complete. But as per dependency modelling we need
47511249Sradhika.jagtap@ARM.com        // to mark ROB dependencies of load and non load/store nodes which
47611249Sradhika.jagtap@ARM.com        // are based on successful sending of the load as complete.
47711252Sradhika.jagtap@ARM.com        if (node_ptr->isLoad() && !node_ptr->isStrictlyOrdered()) {
47811249Sradhika.jagtap@ARM.com            // If execute succeeded mark its dependents as complete
47911249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUData, "Node seq. num %lli sent. Waking up "
48011249Sradhika.jagtap@ARM.com                    "dependents..\n", node_ptr->seqNum);
48111249Sradhika.jagtap@ARM.com
48211249Sradhika.jagtap@ARM.com            auto child_itr = (node_ptr->dependents).begin();
48311249Sradhika.jagtap@ARM.com            while (child_itr != (node_ptr->dependents).end()) {
48411249Sradhika.jagtap@ARM.com                // ROB dependency of a store on a load must not be removed
48511249Sradhika.jagtap@ARM.com                // after load is sent but after response is received
48611252Sradhika.jagtap@ARM.com                if (!(*child_itr)->isStore() &&
48711249Sradhika.jagtap@ARM.com                    (*child_itr)->removeRobDep(node_ptr->seqNum)) {
48811249Sradhika.jagtap@ARM.com
48911249Sradhika.jagtap@ARM.com                    // Check if the child node has become dependency free
49011249Sradhika.jagtap@ARM.com                    if ((*child_itr)->numRobDep == 0 &&
49111249Sradhika.jagtap@ARM.com                        (*child_itr)->numRegDep == 0) {
49211249Sradhika.jagtap@ARM.com
49311249Sradhika.jagtap@ARM.com                        // Source dependencies are complete, check if
49411249Sradhika.jagtap@ARM.com                        // resources are available and issue
49511249Sradhika.jagtap@ARM.com                        checkAndIssue(*child_itr);
49611249Sradhika.jagtap@ARM.com                    }
49711249Sradhika.jagtap@ARM.com                    // Remove this child for the sent load and point to new
49811249Sradhika.jagtap@ARM.com                    // location of the element following the erased element
49911249Sradhika.jagtap@ARM.com                    child_itr = node_ptr->dependents.erase(child_itr);
50011249Sradhika.jagtap@ARM.com                } else {
50111249Sradhika.jagtap@ARM.com                    // This child is not dependency-free, point to the next
50211249Sradhika.jagtap@ARM.com                    // child
50311249Sradhika.jagtap@ARM.com                    child_itr++;
50411249Sradhika.jagtap@ARM.com                }
50511249Sradhika.jagtap@ARM.com            }
50611249Sradhika.jagtap@ARM.com        } else {
50711249Sradhika.jagtap@ARM.com            // If it is a strictly ordered load mark its dependents as complete
50811249Sradhika.jagtap@ARM.com            // as we do not send a request for this case. If it is a store or a
50911249Sradhika.jagtap@ARM.com            // comp node we also mark all its dependents complete.
51011249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUData, "Node seq. num %lli done. Waking"
51111249Sradhika.jagtap@ARM.com                    " up dependents..\n", node_ptr->seqNum);
51211249Sradhika.jagtap@ARM.com
51311249Sradhika.jagtap@ARM.com            for (auto child : node_ptr->dependents) {
51411249Sradhika.jagtap@ARM.com                // If the child node is dependency free removeDepOnInst()
51511249Sradhika.jagtap@ARM.com                // returns true.
51611249Sradhika.jagtap@ARM.com                if (child->removeDepOnInst(node_ptr->seqNum)) {
51711249Sradhika.jagtap@ARM.com                    // Source dependencies are complete, check if resources
51811249Sradhika.jagtap@ARM.com                    // are available and issue
51911249Sradhika.jagtap@ARM.com                    checkAndIssue(child);
52011249Sradhika.jagtap@ARM.com                }
52111249Sradhika.jagtap@ARM.com            }
52211249Sradhika.jagtap@ARM.com        }
52311249Sradhika.jagtap@ARM.com
52411249Sradhika.jagtap@ARM.com        // After executing the node, remove from readyList and delete node.
52511249Sradhika.jagtap@ARM.com        readyList.erase(free_itr);
52611249Sradhika.jagtap@ARM.com        // If it is a cacheable load which was sent, don't delete
52711249Sradhika.jagtap@ARM.com        // just yet.  Delete it in completeMemAccess() after the
52811249Sradhika.jagtap@ARM.com        // response is received. If it is an strictly ordered
52911249Sradhika.jagtap@ARM.com        // load, it was not sent and all dependencies were simply
53011249Sradhika.jagtap@ARM.com        // marked complete. Thus it is safe to delete it. For
53111249Sradhika.jagtap@ARM.com        // stores and non load/store nodes all dependencies were
53211249Sradhika.jagtap@ARM.com        // marked complete so it is safe to delete it.
53311252Sradhika.jagtap@ARM.com        if (!node_ptr->isLoad() || node_ptr->isStrictlyOrdered()) {
53411249Sradhika.jagtap@ARM.com            // Release all resources occupied by the completed node
53511249Sradhika.jagtap@ARM.com            hwResource.release(node_ptr);
53611249Sradhika.jagtap@ARM.com            // clear the dynamically allocated set of dependents
53711249Sradhika.jagtap@ARM.com            (node_ptr->dependents).clear();
53811249Sradhika.jagtap@ARM.com            // delete node
53911249Sradhika.jagtap@ARM.com            delete node_ptr;
54011249Sradhika.jagtap@ARM.com            // remove from graph
54111249Sradhika.jagtap@ARM.com            depGraph.erase(graph_itr);
54211249Sradhika.jagtap@ARM.com        }
54311249Sradhika.jagtap@ARM.com        // Point to first node to continue to next iteration of while loop
54411249Sradhika.jagtap@ARM.com        free_itr = readyList.begin();
54511249Sradhika.jagtap@ARM.com    } // end of while loop
54611249Sradhika.jagtap@ARM.com
54711249Sradhika.jagtap@ARM.com    // Print readyList, sizes of queues and resource status after updating
54811249Sradhika.jagtap@ARM.com    if (DTRACE(TraceCPUData)) {
54911249Sradhika.jagtap@ARM.com        printReadyList();
55011249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Execute end occupancy:\n");
55111249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\tdepGraph = %d, readyList = %d, "
55211249Sradhika.jagtap@ARM.com                "depFreeQueue = %d ,", depGraph.size(), readyList.size(),
55311249Sradhika.jagtap@ARM.com                depFreeQueue.size());
55411249Sradhika.jagtap@ARM.com        hwResource.printOccupancy();
55511249Sradhika.jagtap@ARM.com    }
55611249Sradhika.jagtap@ARM.com
55711249Sradhika.jagtap@ARM.com    if (retryPkt) {
55811249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Not scheduling an event as expecting a retry"
55911249Sradhika.jagtap@ARM.com                "event from the cache for seq. num %lli.\n",
56011249Sradhika.jagtap@ARM.com                retryPkt->req->getReqInstSeqNum());
56111249Sradhika.jagtap@ARM.com        return;
56211249Sradhika.jagtap@ARM.com    }
56311249Sradhika.jagtap@ARM.com    // If the size of the dependency graph is less than the dependency window
56411249Sradhika.jagtap@ARM.com    // then read from the trace file to populate the graph next time we are in
56511249Sradhika.jagtap@ARM.com    // execute.
56611249Sradhika.jagtap@ARM.com    if (depGraph.size() < windowSize && !traceComplete)
56711249Sradhika.jagtap@ARM.com        nextRead = true;
56811249Sradhika.jagtap@ARM.com
56911249Sradhika.jagtap@ARM.com    // If cache is not blocked, schedule an event for the first execTick in
57011249Sradhika.jagtap@ARM.com    // readyList else retry from cache will schedule the event. If the ready
57111249Sradhika.jagtap@ARM.com    // list is empty then check if the next pending node has resources
57211249Sradhika.jagtap@ARM.com    // available to issue. If yes, then schedule an event for the next cycle.
57311249Sradhika.jagtap@ARM.com    if (!readyList.empty()) {
57411249Sradhika.jagtap@ARM.com        Tick next_event_tick = std::max(readyList.begin()->execTick,
57511249Sradhika.jagtap@ARM.com                                        curTick());
57611249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
57711249Sradhika.jagtap@ARM.com                next_event_tick);
57811249Sradhika.jagtap@ARM.com        owner.schedDcacheNextEvent(next_event_tick);
57911249Sradhika.jagtap@ARM.com    } else if (readyList.empty() && !depFreeQueue.empty() &&
58011249Sradhika.jagtap@ARM.com                hwResource.isAvailable(depFreeQueue.front())) {
58111249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
58211249Sradhika.jagtap@ARM.com                owner.clockEdge(Cycles(1)));
58311249Sradhika.jagtap@ARM.com        owner.schedDcacheNextEvent(owner.clockEdge(Cycles(1)));
58411249Sradhika.jagtap@ARM.com    }
58511249Sradhika.jagtap@ARM.com
58611249Sradhika.jagtap@ARM.com    // If trace is completely read, readyList is empty and depGraph is empty,
58711249Sradhika.jagtap@ARM.com    // set execComplete to true
58811249Sradhika.jagtap@ARM.com    if (depGraph.empty() && readyList.empty() && traceComplete &&
58911249Sradhika.jagtap@ARM.com        !hwResource.awaitingResponse()) {
59011249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "\tExecution Complete!\n");
59111249Sradhika.jagtap@ARM.com        execComplete = true;
59211249Sradhika.jagtap@ARM.com        dataLastTick = curTick();
59311249Sradhika.jagtap@ARM.com    }
59411249Sradhika.jagtap@ARM.com}
59511249Sradhika.jagtap@ARM.com
59611249Sradhika.jagtap@ARM.comPacketPtr
59711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr)
59811249Sradhika.jagtap@ARM.com{
59911249Sradhika.jagtap@ARM.com
60011249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Executing memory request %lli (addr %d, pc %#x, "
60111249Sradhika.jagtap@ARM.com            "size %d, flags %d).\n", node_ptr->seqNum, node_ptr->addr,
60211249Sradhika.jagtap@ARM.com            node_ptr->pc, node_ptr->size, node_ptr->flags);
60311249Sradhika.jagtap@ARM.com
60411249Sradhika.jagtap@ARM.com    // If the request is strictly ordered, do not send it. Just return nullptr
60511249Sradhika.jagtap@ARM.com    // as if it was succesfully sent.
60611249Sradhika.jagtap@ARM.com    if (node_ptr->isStrictlyOrdered()) {
60711252Sradhika.jagtap@ARM.com        node_ptr->isLoad() ? ++numSOLoads : ++numSOStores;
60811249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Skipping strictly ordered request %lli.\n",
60911249Sradhika.jagtap@ARM.com                node_ptr->seqNum);
61011249Sradhika.jagtap@ARM.com        return nullptr;
61111249Sradhika.jagtap@ARM.com    }
61211249Sradhika.jagtap@ARM.com
61311249Sradhika.jagtap@ARM.com    // Check if the request spans two cache lines as this condition triggers
61411249Sradhika.jagtap@ARM.com    // an assert fail in the L1 cache. If it does then truncate the size to
61511249Sradhika.jagtap@ARM.com    // access only until the end of that line and ignore the remainder. The
61611249Sradhika.jagtap@ARM.com    // stat counting this is useful to keep a check on how frequently this
61711249Sradhika.jagtap@ARM.com    // happens. If required the code could be revised to mimick splitting such
61811249Sradhika.jagtap@ARM.com    // a request into two.
61911249Sradhika.jagtap@ARM.com    unsigned blk_size = owner.cacheLineSize();
62011249Sradhika.jagtap@ARM.com    Addr blk_offset = (node_ptr->addr & (Addr)(blk_size - 1));
62111249Sradhika.jagtap@ARM.com    if (!(blk_offset + node_ptr->size <= blk_size)) {
62211249Sradhika.jagtap@ARM.com        node_ptr->size = blk_size - blk_offset;
62311249Sradhika.jagtap@ARM.com        ++numSplitReqs;
62411249Sradhika.jagtap@ARM.com    }
62511249Sradhika.jagtap@ARM.com
62611249Sradhika.jagtap@ARM.com    // Create a request and the packet containing request
62711249Sradhika.jagtap@ARM.com    Request* req = new Request(node_ptr->addr, node_ptr->size, node_ptr->flags,
62811249Sradhika.jagtap@ARM.com                               masterID, node_ptr->seqNum,
62911249Sradhika.jagtap@ARM.com                               ContextID(0), ThreadID(0));
63011249Sradhika.jagtap@ARM.com    req->setPC(node_ptr->pc);
63111249Sradhika.jagtap@ARM.com    PacketPtr pkt;
63211249Sradhika.jagtap@ARM.com    uint8_t* pkt_data = new uint8_t[req->getSize()];
63311252Sradhika.jagtap@ARM.com    if (node_ptr->isLoad()) {
63411249Sradhika.jagtap@ARM.com        pkt = Packet::createRead(req);
63511249Sradhika.jagtap@ARM.com    } else {
63611249Sradhika.jagtap@ARM.com        pkt = Packet::createWrite(req);
63711249Sradhika.jagtap@ARM.com        memset(pkt_data, 0xA, req->getSize());
63811249Sradhika.jagtap@ARM.com    }
63911249Sradhika.jagtap@ARM.com    pkt->dataDynamic(pkt_data);
64011249Sradhika.jagtap@ARM.com
64111249Sradhika.jagtap@ARM.com    // Call MasterPort method to send a timing request for this packet
64211249Sradhika.jagtap@ARM.com    bool success = port.sendTimingReq(pkt);
64311249Sradhika.jagtap@ARM.com    ++numSendAttempted;
64411249Sradhika.jagtap@ARM.com
64511249Sradhika.jagtap@ARM.com    if (!success) {
64611249Sradhika.jagtap@ARM.com        // If it fails, return the packet to retry when a retry is signalled by
64711249Sradhika.jagtap@ARM.com        // the cache
64811249Sradhika.jagtap@ARM.com        ++numSendFailed;
64911249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Send failed. Saving packet for retry.\n");
65011249Sradhika.jagtap@ARM.com        return pkt;
65111249Sradhika.jagtap@ARM.com    } else {
65211249Sradhika.jagtap@ARM.com        // It is succeeds, return nullptr
65311249Sradhika.jagtap@ARM.com        ++numSendSucceeded;
65411249Sradhika.jagtap@ARM.com        return nullptr;
65511249Sradhika.jagtap@ARM.com    }
65611249Sradhika.jagtap@ARM.com}
65711249Sradhika.jagtap@ARM.com
65811249Sradhika.jagtap@ARM.combool
65911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::checkAndIssue(const GraphNode* node_ptr, bool first)
66011249Sradhika.jagtap@ARM.com{
66111249Sradhika.jagtap@ARM.com    // Assert the node is dependency-free
66211249Sradhika.jagtap@ARM.com    assert(node_ptr->numRobDep == 0 && node_ptr->numRegDep == 0);
66311249Sradhika.jagtap@ARM.com
66411249Sradhika.jagtap@ARM.com    // If this is the first attempt, print a debug message to indicate this.
66511249Sradhika.jagtap@ARM.com    if (first) {
66611249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tseq. num %lli(%s) with rob num %lli is now"
66711252Sradhika.jagtap@ARM.com            " dependency free.\n", node_ptr->seqNum, node_ptr->typeToStr(),
66811249Sradhika.jagtap@ARM.com            node_ptr->robNum);
66911249Sradhika.jagtap@ARM.com    }
67011249Sradhika.jagtap@ARM.com
67111249Sradhika.jagtap@ARM.com    // Check if resources are available to issue the specific node
67211249Sradhika.jagtap@ARM.com    if (hwResource.isAvailable(node_ptr)) {
67311249Sradhika.jagtap@ARM.com        // If resources are free only then add to readyList
67411249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tResources available for seq. num %lli. Adding"
67511249Sradhika.jagtap@ARM.com            " to readyList, occupying resources.\n", node_ptr->seqNum);
67611249Sradhika.jagtap@ARM.com        // Compute the execute tick by adding the compute delay for the node
67711249Sradhika.jagtap@ARM.com        // and add the ready node to the ready list
67811249Sradhika.jagtap@ARM.com        addToSortedReadyList(node_ptr->seqNum,
67911249Sradhika.jagtap@ARM.com                                owner.clockEdge() + node_ptr->compDelay);
68011249Sradhika.jagtap@ARM.com        // Account for the resources taken up by this issued node.
68111249Sradhika.jagtap@ARM.com        hwResource.occupy(node_ptr);
68211249Sradhika.jagtap@ARM.com        return true;
68311249Sradhika.jagtap@ARM.com
68411249Sradhika.jagtap@ARM.com    } else {
68511249Sradhika.jagtap@ARM.com        if (first) {
68611249Sradhika.jagtap@ARM.com            // Although dependencies are complete, resources are not available.
68711249Sradhika.jagtap@ARM.com            DPRINTFR(TraceCPUData, "\t\tResources unavailable for seq. num %lli."
68811249Sradhika.jagtap@ARM.com                " Adding to depFreeQueue.\n", node_ptr->seqNum);
68911249Sradhika.jagtap@ARM.com            depFreeQueue.push(node_ptr);
69011249Sradhika.jagtap@ARM.com        } else {
69111249Sradhika.jagtap@ARM.com            DPRINTFR(TraceCPUData, "\t\tResources unavailable for seq. num %lli. "
69211249Sradhika.jagtap@ARM.com                "Still pending issue.\n", node_ptr->seqNum);
69311249Sradhika.jagtap@ARM.com        }
69411249Sradhika.jagtap@ARM.com        return false;
69511249Sradhika.jagtap@ARM.com    }
69611249Sradhika.jagtap@ARM.com}
69711249Sradhika.jagtap@ARM.com
69811249Sradhika.jagtap@ARM.comvoid
69911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::completeMemAccess(PacketPtr pkt)
70011249Sradhika.jagtap@ARM.com{
70111249Sradhika.jagtap@ARM.com    // Release the resources for this completed node.
70211249Sradhika.jagtap@ARM.com    if (pkt->isWrite()) {
70311249Sradhika.jagtap@ARM.com        // Consider store complete.
70411249Sradhika.jagtap@ARM.com        hwResource.releaseStoreBuffer();
70511249Sradhika.jagtap@ARM.com        // If it is a store response then do nothing since we do not model
70611249Sradhika.jagtap@ARM.com        // dependencies on store completion in the trace. But if we were
70711249Sradhika.jagtap@ARM.com        // blocking execution due to store buffer fullness, we need to schedule
70811249Sradhika.jagtap@ARM.com        // an event and attempt to progress.
70911249Sradhika.jagtap@ARM.com    } else {
71011249Sradhika.jagtap@ARM.com        // If it is a load response then release the dependents waiting on it.
71111249Sradhika.jagtap@ARM.com        // Get pointer to the completed load
71211249Sradhika.jagtap@ARM.com        auto graph_itr = depGraph.find(pkt->req->getReqInstSeqNum());
71311249Sradhika.jagtap@ARM.com        assert(graph_itr != depGraph.end());
71411249Sradhika.jagtap@ARM.com        GraphNode* node_ptr = graph_itr->second;
71511249Sradhika.jagtap@ARM.com
71611249Sradhika.jagtap@ARM.com        // Release resources occupied by the load
71711249Sradhika.jagtap@ARM.com        hwResource.release(node_ptr);
71811249Sradhika.jagtap@ARM.com
71911249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Load seq. num %lli response received. Waking up"
72011249Sradhika.jagtap@ARM.com                " dependents..\n", node_ptr->seqNum);
72111249Sradhika.jagtap@ARM.com
72211249Sradhika.jagtap@ARM.com        for (auto child : node_ptr->dependents) {
72311249Sradhika.jagtap@ARM.com            if (child->removeDepOnInst(node_ptr->seqNum)) {
72411249Sradhika.jagtap@ARM.com                checkAndIssue(child);
72511249Sradhika.jagtap@ARM.com            }
72611249Sradhika.jagtap@ARM.com        }
72711249Sradhika.jagtap@ARM.com
72811249Sradhika.jagtap@ARM.com        // clear the dynamically allocated set of dependents
72911249Sradhika.jagtap@ARM.com        (node_ptr->dependents).clear();
73011249Sradhika.jagtap@ARM.com        // delete node
73111249Sradhika.jagtap@ARM.com        delete node_ptr;
73211249Sradhika.jagtap@ARM.com        // remove from graph
73311249Sradhika.jagtap@ARM.com        depGraph.erase(graph_itr);
73411249Sradhika.jagtap@ARM.com    }
73511249Sradhika.jagtap@ARM.com
73611249Sradhika.jagtap@ARM.com    if (DTRACE(TraceCPUData)) {
73711249Sradhika.jagtap@ARM.com        printReadyList();
73811249Sradhika.jagtap@ARM.com    }
73911249Sradhika.jagtap@ARM.com
74011249Sradhika.jagtap@ARM.com    // If the size of the dependency graph is less than the dependency window
74111249Sradhika.jagtap@ARM.com    // then read from the trace file to populate the graph next time we are in
74211249Sradhika.jagtap@ARM.com    // execute.
74311249Sradhika.jagtap@ARM.com    if (depGraph.size() < windowSize && !traceComplete)
74411249Sradhika.jagtap@ARM.com        nextRead = true;
74511249Sradhika.jagtap@ARM.com
74611249Sradhika.jagtap@ARM.com    // If not waiting for retry, attempt to schedule next event
74711249Sradhika.jagtap@ARM.com    if (!retryPkt) {
74811249Sradhika.jagtap@ARM.com        // We might have new dep-free nodes in the list which will have execute
74911249Sradhika.jagtap@ARM.com        // tick greater than or equal to curTick. But a new dep-free node might
75011249Sradhika.jagtap@ARM.com        // have its execute tick earlier. Therefore, attempt to reschedule. It
75111249Sradhika.jagtap@ARM.com        // could happen that the readyList is empty and we got here via a
75211249Sradhika.jagtap@ARM.com        // last remaining response. So, either the trace is complete or there
75311249Sradhika.jagtap@ARM.com        // are pending nodes in the depFreeQueue. The checking is done in the
75411249Sradhika.jagtap@ARM.com        // execute() control flow, so schedule an event to go via that flow.
75511249Sradhika.jagtap@ARM.com        Tick next_event_tick = readyList.empty() ? owner.clockEdge(Cycles(1)) :
75611249Sradhika.jagtap@ARM.com            std::max(readyList.begin()->execTick, owner.clockEdge(Cycles(1)));
75711249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
75811249Sradhika.jagtap@ARM.com                next_event_tick);
75911249Sradhika.jagtap@ARM.com        owner.schedDcacheNextEvent(next_event_tick);
76011249Sradhika.jagtap@ARM.com    }
76111249Sradhika.jagtap@ARM.com}
76211249Sradhika.jagtap@ARM.com
76311249Sradhika.jagtap@ARM.comvoid
76411249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::addToSortedReadyList(NodeSeqNum seq_num,
76511249Sradhika.jagtap@ARM.com                                                    Tick exec_tick)
76611249Sradhika.jagtap@ARM.com{
76711249Sradhika.jagtap@ARM.com    ReadyNode ready_node;
76811249Sradhika.jagtap@ARM.com    ready_node.seqNum = seq_num;
76911249Sradhika.jagtap@ARM.com    ready_node.execTick = exec_tick;
77011249Sradhika.jagtap@ARM.com
77111249Sradhika.jagtap@ARM.com    // Iterator to readyList
77211249Sradhika.jagtap@ARM.com    auto itr = readyList.begin();
77311249Sradhika.jagtap@ARM.com
77411249Sradhika.jagtap@ARM.com    // If the readyList is empty, simply insert the new node at the beginning
77511249Sradhika.jagtap@ARM.com    // and return
77611249Sradhika.jagtap@ARM.com    if (itr == readyList.end()) {
77711249Sradhika.jagtap@ARM.com        readyList.insert(itr, ready_node);
77811249Sradhika.jagtap@ARM.com        maxReadyListSize = std::max<double>(readyList.size(),
77911249Sradhika.jagtap@ARM.com                                              maxReadyListSize.value());
78011249Sradhika.jagtap@ARM.com        return;
78111249Sradhika.jagtap@ARM.com    }
78211249Sradhika.jagtap@ARM.com
78311249Sradhika.jagtap@ARM.com    // If the new node has its execution tick equal to the first node in the
78411249Sradhika.jagtap@ARM.com    // list then go to the next node. If the first node in the list failed
78511249Sradhika.jagtap@ARM.com    // to execute, its position as the first is thus maintained.
78611249Sradhika.jagtap@ARM.com    if (retryPkt)
78711249Sradhika.jagtap@ARM.com        if (retryPkt->req->getReqInstSeqNum() == itr->seqNum)
78811249Sradhika.jagtap@ARM.com            itr++;
78911249Sradhika.jagtap@ARM.com
79011249Sradhika.jagtap@ARM.com    // Increment the iterator and compare the node pointed to by it to the new
79111249Sradhika.jagtap@ARM.com    // node till the position to insert the new node is found.
79211249Sradhika.jagtap@ARM.com    bool found = false;
79311249Sradhika.jagtap@ARM.com    while (!found && itr != readyList.end()) {
79411249Sradhika.jagtap@ARM.com        // If the execution tick of the new node is less than the node then
79511249Sradhika.jagtap@ARM.com        // this is the position to insert
79611249Sradhika.jagtap@ARM.com        if (exec_tick < itr->execTick)
79711249Sradhika.jagtap@ARM.com            found = true;
79811249Sradhika.jagtap@ARM.com        // If the execution tick of the new node is equal to the node then
79911249Sradhika.jagtap@ARM.com        // sort in ascending order of sequence numbers
80011249Sradhika.jagtap@ARM.com        else if (exec_tick == itr->execTick) {
80111249Sradhika.jagtap@ARM.com            // If the sequence number of the new node is less than the node
80211249Sradhika.jagtap@ARM.com            // then this is the position to insert
80311249Sradhika.jagtap@ARM.com            if (seq_num < itr->seqNum)
80411249Sradhika.jagtap@ARM.com                found = true;
80511249Sradhika.jagtap@ARM.com            // Else go to next node
80611249Sradhika.jagtap@ARM.com            else
80711249Sradhika.jagtap@ARM.com                itr++;
80811249Sradhika.jagtap@ARM.com        }
80911249Sradhika.jagtap@ARM.com        // If the execution tick of the new node is greater than the node then
81011249Sradhika.jagtap@ARM.com        // go to the next node
81111249Sradhika.jagtap@ARM.com        else
81211249Sradhika.jagtap@ARM.com            itr++;
81311249Sradhika.jagtap@ARM.com    }
81411249Sradhika.jagtap@ARM.com    readyList.insert(itr, ready_node);
81511249Sradhika.jagtap@ARM.com    // Update the stat for max size reached of the readyList
81611249Sradhika.jagtap@ARM.com    maxReadyListSize = std::max<double>(readyList.size(),
81711249Sradhika.jagtap@ARM.com                                          maxReadyListSize.value());
81811249Sradhika.jagtap@ARM.com}
81911249Sradhika.jagtap@ARM.com
82011249Sradhika.jagtap@ARM.comvoid
82111249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::printReadyList() {
82211249Sradhika.jagtap@ARM.com
82311249Sradhika.jagtap@ARM.com    auto itr = readyList.begin();
82411249Sradhika.jagtap@ARM.com    if (itr == readyList.end()) {
82511249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "readyList is empty.\n");
82611249Sradhika.jagtap@ARM.com        return;
82711249Sradhika.jagtap@ARM.com    }
82811249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Printing readyList:\n");
82911249Sradhika.jagtap@ARM.com    while (itr != readyList.end()) {
83011249Sradhika.jagtap@ARM.com        auto graph_itr = depGraph.find(itr->seqNum);
83111249Sradhika.jagtap@ARM.com        GraphNode* node_ptr M5_VAR_USED = graph_itr->second;
83211249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t%lld(%s), %lld\n", itr->seqNum,
83311252Sradhika.jagtap@ARM.com            node_ptr->typeToStr(), itr->execTick);
83411249Sradhika.jagtap@ARM.com        itr++;
83511249Sradhika.jagtap@ARM.com    }
83611249Sradhika.jagtap@ARM.com}
83711249Sradhika.jagtap@ARM.com
83811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::HardwareResource(
83911249Sradhika.jagtap@ARM.com    uint16_t max_rob, uint16_t max_stores, uint16_t max_loads)
84011249Sradhika.jagtap@ARM.com  : sizeROB(max_rob),
84111249Sradhika.jagtap@ARM.com    sizeStoreBuffer(max_stores),
84211249Sradhika.jagtap@ARM.com    sizeLoadBuffer(max_loads),
84311249Sradhika.jagtap@ARM.com    oldestInFlightRobNum(UINT64_MAX),
84411249Sradhika.jagtap@ARM.com    numInFlightLoads(0),
84511249Sradhika.jagtap@ARM.com    numInFlightStores(0)
84611249Sradhika.jagtap@ARM.com{}
84711249Sradhika.jagtap@ARM.com
84811249Sradhika.jagtap@ARM.comvoid
84911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::occupy(const GraphNode* new_node)
85011249Sradhika.jagtap@ARM.com{
85111249Sradhika.jagtap@ARM.com    // Occupy ROB entry for the issued node
85211249Sradhika.jagtap@ARM.com    // Merely maintain the oldest node, i.e. numerically least robNum by saving
85311249Sradhika.jagtap@ARM.com    // it in the variable oldestInFLightRobNum.
85411249Sradhika.jagtap@ARM.com    inFlightNodes[new_node->seqNum] = new_node->robNum;
85511249Sradhika.jagtap@ARM.com    oldestInFlightRobNum = inFlightNodes.begin()->second;
85611249Sradhika.jagtap@ARM.com
85711249Sradhika.jagtap@ARM.com    // Occupy Load/Store Buffer entry for the issued node if applicable
85811252Sradhika.jagtap@ARM.com    if (new_node->isLoad()) {
85911249Sradhika.jagtap@ARM.com        ++numInFlightLoads;
86011252Sradhika.jagtap@ARM.com    } else if (new_node->isStore()) {
86111249Sradhika.jagtap@ARM.com        ++numInFlightStores;
86211249Sradhika.jagtap@ARM.com    } // else if it is a non load/store node, no buffer entry is occupied
86311249Sradhika.jagtap@ARM.com
86411249Sradhika.jagtap@ARM.com    printOccupancy();
86511249Sradhika.jagtap@ARM.com}
86611249Sradhika.jagtap@ARM.com
86711249Sradhika.jagtap@ARM.comvoid
86811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::release(const GraphNode* done_node)
86911249Sradhika.jagtap@ARM.com{
87011249Sradhika.jagtap@ARM.com    assert(!inFlightNodes.empty());
87111249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "\tClearing done seq. num %d from inFlightNodes..\n",
87211249Sradhika.jagtap@ARM.com        done_node->seqNum);
87311249Sradhika.jagtap@ARM.com
87411249Sradhika.jagtap@ARM.com    assert(inFlightNodes.find(done_node->seqNum) != inFlightNodes.end());
87511249Sradhika.jagtap@ARM.com    inFlightNodes.erase(done_node->seqNum);
87611249Sradhika.jagtap@ARM.com
87711249Sradhika.jagtap@ARM.com    if (inFlightNodes.empty()) {
87811249Sradhika.jagtap@ARM.com        // If we delete the only in-flight node and then the
87911249Sradhika.jagtap@ARM.com        // oldestInFlightRobNum is set to it's initialized (max) value.
88011249Sradhika.jagtap@ARM.com        oldestInFlightRobNum = UINT64_MAX;
88111249Sradhika.jagtap@ARM.com    } else {
88211249Sradhika.jagtap@ARM.com        // Set the oldest in-flight node rob number equal to the first node in
88311249Sradhika.jagtap@ARM.com        // the inFlightNodes since that will have the numerically least value.
88411249Sradhika.jagtap@ARM.com        oldestInFlightRobNum = inFlightNodes.begin()->second;
88511249Sradhika.jagtap@ARM.com    }
88611249Sradhika.jagtap@ARM.com
88711249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "\tCleared. inFlightNodes.size() = %d, "
88811249Sradhika.jagtap@ARM.com        "oldestInFlightRobNum = %d\n", inFlightNodes.size(),
88911249Sradhika.jagtap@ARM.com        oldestInFlightRobNum);
89011249Sradhika.jagtap@ARM.com
89111249Sradhika.jagtap@ARM.com    // A store is considered complete when a request is sent, thus ROB entry is
89211249Sradhika.jagtap@ARM.com    // freed. But it occupies an entry in the Store Buffer until its response
89311249Sradhika.jagtap@ARM.com    // is received. A load is considered complete when a response is received,
89411249Sradhika.jagtap@ARM.com    // thus both ROB and Load Buffer entries can be released.
89511252Sradhika.jagtap@ARM.com    if (done_node->isLoad()) {
89611249Sradhika.jagtap@ARM.com        assert(numInFlightLoads != 0);
89711249Sradhika.jagtap@ARM.com        --numInFlightLoads;
89811249Sradhika.jagtap@ARM.com    }
89911249Sradhika.jagtap@ARM.com    // For normal writes, we send the requests out and clear a store buffer
90011249Sradhika.jagtap@ARM.com    // entry on response. For writes which are strictly ordered, for e.g.
90111249Sradhika.jagtap@ARM.com    // writes to device registers, we do that within release() which is called
90211249Sradhika.jagtap@ARM.com    // when node is executed and taken off from readyList.
90311252Sradhika.jagtap@ARM.com    if (done_node->isStore() && done_node->isStrictlyOrdered()) {
90411249Sradhika.jagtap@ARM.com        releaseStoreBuffer();
90511249Sradhika.jagtap@ARM.com    }
90611249Sradhika.jagtap@ARM.com}
90711249Sradhika.jagtap@ARM.com
90811249Sradhika.jagtap@ARM.comvoid
90911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::releaseStoreBuffer()
91011249Sradhika.jagtap@ARM.com{
91111249Sradhika.jagtap@ARM.com    assert(numInFlightStores != 0);
91211249Sradhika.jagtap@ARM.com    --numInFlightStores;
91311249Sradhika.jagtap@ARM.com}
91411249Sradhika.jagtap@ARM.com
91511249Sradhika.jagtap@ARM.combool
91611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::isAvailable(
91711249Sradhika.jagtap@ARM.com    const GraphNode* new_node) const
91811249Sradhika.jagtap@ARM.com{
91911249Sradhika.jagtap@ARM.com    uint16_t num_in_flight_nodes;
92011249Sradhika.jagtap@ARM.com    if (inFlightNodes.empty()) {
92111249Sradhika.jagtap@ARM.com        num_in_flight_nodes = 0;
92211249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
92311249Sradhika.jagtap@ARM.com            " #in-flight nodes = 0", new_node->seqNum);
92411249Sradhika.jagtap@ARM.com    } else if (new_node->robNum > oldestInFlightRobNum) {
92511249Sradhika.jagtap@ARM.com        // This is the intuitive case where new dep-free node is younger
92611249Sradhika.jagtap@ARM.com        // instruction than the oldest instruction in-flight. Thus we make sure
92711249Sradhika.jagtap@ARM.com        // in_flight_nodes does not overflow.
92811249Sradhika.jagtap@ARM.com        num_in_flight_nodes = new_node->robNum - oldestInFlightRobNum;
92911249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
93011249Sradhika.jagtap@ARM.com            " #in-flight nodes = %d - %d =  %d", new_node->seqNum,
93111249Sradhika.jagtap@ARM.com             new_node->robNum, oldestInFlightRobNum, num_in_flight_nodes);
93211249Sradhika.jagtap@ARM.com    } else {
93311249Sradhika.jagtap@ARM.com        // This is the case where an instruction older than the oldest in-
93411249Sradhika.jagtap@ARM.com        // flight instruction becomes dep-free. Thus we must have already
93511249Sradhika.jagtap@ARM.com        // accounted for the entry in ROB for this new dep-free node.
93611249Sradhika.jagtap@ARM.com        // Immediately after this check returns true, oldestInFlightRobNum will
93711249Sradhika.jagtap@ARM.com        // be updated in occupy(). We simply let this node issue now.
93811249Sradhika.jagtap@ARM.com        num_in_flight_nodes = 0;
93911249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
94011249Sradhika.jagtap@ARM.com            " new oldestInFlightRobNum = %d, #in-flight nodes ignored",
94111249Sradhika.jagtap@ARM.com            new_node->seqNum, new_node->robNum);
94211249Sradhika.jagtap@ARM.com    }
94311249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, ", LQ = %d/%d, SQ  = %d/%d.\n",
94411249Sradhika.jagtap@ARM.com        numInFlightLoads, sizeLoadBuffer,
94511249Sradhika.jagtap@ARM.com        numInFlightStores, sizeStoreBuffer);
94611249Sradhika.jagtap@ARM.com    // Check if resources are available to issue the specific node
94711249Sradhika.jagtap@ARM.com    if (num_in_flight_nodes >= sizeROB) {
94811249Sradhika.jagtap@ARM.com        return false;
94911249Sradhika.jagtap@ARM.com    }
95011252Sradhika.jagtap@ARM.com    if (new_node->isLoad() && numInFlightLoads >= sizeLoadBuffer) {
95111249Sradhika.jagtap@ARM.com        return false;
95211249Sradhika.jagtap@ARM.com    }
95311252Sradhika.jagtap@ARM.com    if (new_node->isStore() && numInFlightStores >= sizeStoreBuffer) {
95411249Sradhika.jagtap@ARM.com        return false;
95511249Sradhika.jagtap@ARM.com    }
95611249Sradhika.jagtap@ARM.com    return true;
95711249Sradhika.jagtap@ARM.com}
95811249Sradhika.jagtap@ARM.com
95911249Sradhika.jagtap@ARM.combool
96011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::awaitingResponse() const {
96111249Sradhika.jagtap@ARM.com    // Return true if there is at least one read or write request in flight
96211249Sradhika.jagtap@ARM.com    return (numInFlightStores != 0 || numInFlightLoads != 0);
96311249Sradhika.jagtap@ARM.com}
96411249Sradhika.jagtap@ARM.com
96511249Sradhika.jagtap@ARM.comvoid
96611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::printOccupancy() {
96711249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "oldestInFlightRobNum = %d, "
96811249Sradhika.jagtap@ARM.com            "LQ = %d/%d, SQ  = %d/%d.\n",
96911249Sradhika.jagtap@ARM.com            oldestInFlightRobNum,
97011249Sradhika.jagtap@ARM.com            numInFlightLoads, sizeLoadBuffer,
97111249Sradhika.jagtap@ARM.com            numInFlightStores, sizeStoreBuffer);
97211249Sradhika.jagtap@ARM.com}
97311249Sradhika.jagtap@ARM.com
97411249Sradhika.jagtap@ARM.comvoid
97511249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::regStats()
97611249Sradhika.jagtap@ARM.com{
97711249Sradhika.jagtap@ARM.com    using namespace Stats;
97811249Sradhika.jagtap@ARM.com
97911249Sradhika.jagtap@ARM.com    numSendAttempted
98011249Sradhika.jagtap@ARM.com    .name(name() + ".numSendAttempted")
98111249Sradhika.jagtap@ARM.com    .desc("Number of first attempts to send a request")
98211249Sradhika.jagtap@ARM.com    ;
98311249Sradhika.jagtap@ARM.com
98411249Sradhika.jagtap@ARM.com    numSendSucceeded
98511249Sradhika.jagtap@ARM.com    .name(name() + ".numSendSucceeded")
98611249Sradhika.jagtap@ARM.com    .desc("Number of successful first attempts")
98711249Sradhika.jagtap@ARM.com    ;
98811249Sradhika.jagtap@ARM.com
98911249Sradhika.jagtap@ARM.com    numSendFailed
99011249Sradhika.jagtap@ARM.com    .name(name() + ".numSendFailed")
99111249Sradhika.jagtap@ARM.com    .desc("Number of failed first attempts")
99211249Sradhika.jagtap@ARM.com    ;
99311249Sradhika.jagtap@ARM.com
99411249Sradhika.jagtap@ARM.com    numRetrySucceeded
99511249Sradhika.jagtap@ARM.com    .name(name() + ".numRetrySucceeded")
99611249Sradhika.jagtap@ARM.com    .desc("Number of successful retries")
99711249Sradhika.jagtap@ARM.com    ;
99811249Sradhika.jagtap@ARM.com
99911249Sradhika.jagtap@ARM.com    instLastTick
100011249Sradhika.jagtap@ARM.com    .name(name() + ".instLastTick")
100111249Sradhika.jagtap@ARM.com    .desc("Last tick simulated from the fixed inst trace")
100211249Sradhika.jagtap@ARM.com    ;
100311249Sradhika.jagtap@ARM.com}
100411249Sradhika.jagtap@ARM.com
100511249Sradhika.jagtap@ARM.comTick
100611249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::init()
100711249Sradhika.jagtap@ARM.com{
100811249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "Initializing instruction fetch request generator"
100911249Sradhika.jagtap@ARM.com            " IcacheGen: fixed issue with retry.\n");
101011249Sradhika.jagtap@ARM.com
101111249Sradhika.jagtap@ARM.com    if (nextExecute()) {
101211249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUInst, "\tFirst tick = %d.\n", currElement.tick);
101311249Sradhika.jagtap@ARM.com        return currElement.tick;
101411249Sradhika.jagtap@ARM.com    } else {
101511249Sradhika.jagtap@ARM.com        panic("Read of first message in the trace failed.\n");
101611249Sradhika.jagtap@ARM.com        return MaxTick;
101711249Sradhika.jagtap@ARM.com    }
101811249Sradhika.jagtap@ARM.com}
101911249Sradhika.jagtap@ARM.com
102011249Sradhika.jagtap@ARM.combool
102111249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::tryNext()
102211249Sradhika.jagtap@ARM.com{
102311249Sradhika.jagtap@ARM.com    // If there is a retry packet, try to send it
102411249Sradhika.jagtap@ARM.com    if (retryPkt) {
102511249Sradhika.jagtap@ARM.com
102611249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUInst, "Trying to send retry packet.\n");
102711249Sradhika.jagtap@ARM.com
102811249Sradhika.jagtap@ARM.com        if (!port.sendTimingReq(retryPkt)) {
102911249Sradhika.jagtap@ARM.com            // Still blocked! This should never occur.
103011249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUInst, "Retry packet sending failed.\n");
103111249Sradhika.jagtap@ARM.com            return false;
103211249Sradhika.jagtap@ARM.com        }
103311249Sradhika.jagtap@ARM.com        ++numRetrySucceeded;
103411249Sradhika.jagtap@ARM.com    } else {
103511249Sradhika.jagtap@ARM.com
103611249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUInst, "Trying to send packet for currElement.\n");
103711249Sradhika.jagtap@ARM.com
103811249Sradhika.jagtap@ARM.com        // try sending current element
103911249Sradhika.jagtap@ARM.com        assert(currElement.isValid());
104011249Sradhika.jagtap@ARM.com
104111249Sradhika.jagtap@ARM.com        ++numSendAttempted;
104211249Sradhika.jagtap@ARM.com
104311249Sradhika.jagtap@ARM.com        if (!send(currElement.addr, currElement.blocksize,
104411249Sradhika.jagtap@ARM.com                    currElement.cmd, currElement.flags, currElement.pc)) {
104511249Sradhika.jagtap@ARM.com            DPRINTF(TraceCPUInst, "currElement sending failed.\n");
104611249Sradhika.jagtap@ARM.com            ++numSendFailed;
104711249Sradhika.jagtap@ARM.com            // return false to indicate not to schedule next event
104811249Sradhika.jagtap@ARM.com            return false;
104911249Sradhika.jagtap@ARM.com        } else {
105011249Sradhika.jagtap@ARM.com            ++numSendSucceeded;
105111249Sradhika.jagtap@ARM.com        }
105211249Sradhika.jagtap@ARM.com    }
105311249Sradhika.jagtap@ARM.com    // If packet was sent successfully, either retryPkt or currElement, return
105411249Sradhika.jagtap@ARM.com    // true to indicate to schedule event at current Tick plus delta. If packet
105511249Sradhika.jagtap@ARM.com    // was sent successfully and there is no next packet to send, return false.
105611249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "Packet sent successfully, trying to read next "
105711249Sradhika.jagtap@ARM.com        "element.\n");
105811249Sradhika.jagtap@ARM.com    retryPkt = nullptr;
105911249Sradhika.jagtap@ARM.com    // Read next element into currElement, currElement gets cleared so save the
106011249Sradhika.jagtap@ARM.com    // tick to calculate delta
106111249Sradhika.jagtap@ARM.com    Tick last_tick = currElement.tick;
106211249Sradhika.jagtap@ARM.com    if (nextExecute()) {
106311249Sradhika.jagtap@ARM.com        assert(currElement.tick >= last_tick);
106411249Sradhika.jagtap@ARM.com        delta = currElement.tick - last_tick;
106511249Sradhika.jagtap@ARM.com    }
106611249Sradhika.jagtap@ARM.com    return !traceComplete;
106711249Sradhika.jagtap@ARM.com}
106811249Sradhika.jagtap@ARM.com
106911249Sradhika.jagtap@ARM.comvoid
107011249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::exit()
107111249Sradhika.jagtap@ARM.com{
107211249Sradhika.jagtap@ARM.com    trace.reset();
107311249Sradhika.jagtap@ARM.com}
107411249Sradhika.jagtap@ARM.com
107511249Sradhika.jagtap@ARM.combool
107611249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::nextExecute()
107711249Sradhika.jagtap@ARM.com{
107811249Sradhika.jagtap@ARM.com    if (traceComplete)
107911249Sradhika.jagtap@ARM.com        // We are at the end of the file, thus we have no more messages.
108011249Sradhika.jagtap@ARM.com        // Return false.
108111249Sradhika.jagtap@ARM.com        return false;
108211249Sradhika.jagtap@ARM.com
108311249Sradhika.jagtap@ARM.com
108411249Sradhika.jagtap@ARM.com    //Reset the currElement to the default values
108511249Sradhika.jagtap@ARM.com    currElement.clear();
108611249Sradhika.jagtap@ARM.com
108711249Sradhika.jagtap@ARM.com    // Read the next line to get the next message. If that fails then end of
108811249Sradhika.jagtap@ARM.com    // trace has been reached and traceComplete needs to be set in addition
108911249Sradhika.jagtap@ARM.com    // to returning false. If successful then next message is in currElement.
109011249Sradhika.jagtap@ARM.com    if (!trace.read(&currElement)) {
109111249Sradhika.jagtap@ARM.com        traceComplete = true;
109211249Sradhika.jagtap@ARM.com        instLastTick = curTick();
109311249Sradhika.jagtap@ARM.com        return false;
109411249Sradhika.jagtap@ARM.com    }
109511249Sradhika.jagtap@ARM.com
109611249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "inst fetch: %c addr %d pc %#x size %d tick %d\n",
109711249Sradhika.jagtap@ARM.com            currElement.cmd.isRead() ? 'r' : 'w',
109811249Sradhika.jagtap@ARM.com            currElement.addr,
109911249Sradhika.jagtap@ARM.com            currElement.pc,
110011249Sradhika.jagtap@ARM.com            currElement.blocksize,
110111249Sradhika.jagtap@ARM.com            currElement.tick);
110211249Sradhika.jagtap@ARM.com
110311249Sradhika.jagtap@ARM.com    return true;
110411249Sradhika.jagtap@ARM.com}
110511249Sradhika.jagtap@ARM.com
110611249Sradhika.jagtap@ARM.combool
110711249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::send(Addr addr, unsigned size, const MemCmd& cmd,
110811249Sradhika.jagtap@ARM.com              Request::FlagsType flags, Addr pc)
110911249Sradhika.jagtap@ARM.com{
111011249Sradhika.jagtap@ARM.com
111111249Sradhika.jagtap@ARM.com    // Create new request
111211249Sradhika.jagtap@ARM.com    Request* req = new Request(addr, size, flags, masterID);
111311249Sradhika.jagtap@ARM.com    req->setPC(pc);
111411249Sradhika.jagtap@ARM.com
111511249Sradhika.jagtap@ARM.com    // If this is not done it triggers assert in L1 cache for invalid contextId
111611249Sradhika.jagtap@ARM.com    req->setThreadContext(ContextID(0), ThreadID(0));
111711249Sradhika.jagtap@ARM.com
111811249Sradhika.jagtap@ARM.com    // Embed it in a packet
111911249Sradhika.jagtap@ARM.com    PacketPtr pkt = new Packet(req, cmd);
112011249Sradhika.jagtap@ARM.com
112111249Sradhika.jagtap@ARM.com    uint8_t* pkt_data = new uint8_t[req->getSize()];
112211249Sradhika.jagtap@ARM.com    pkt->dataDynamic(pkt_data);
112311249Sradhika.jagtap@ARM.com
112411249Sradhika.jagtap@ARM.com    if (cmd.isWrite()) {
112511249Sradhika.jagtap@ARM.com        memset(pkt_data, 0xA, req->getSize());
112611249Sradhika.jagtap@ARM.com    }
112711249Sradhika.jagtap@ARM.com
112811249Sradhika.jagtap@ARM.com    // Call MasterPort method to send a timing request for this packet
112911249Sradhika.jagtap@ARM.com    bool success = port.sendTimingReq(pkt);
113011249Sradhika.jagtap@ARM.com    if (!success) {
113111249Sradhika.jagtap@ARM.com        // If it fails, save the packet to retry when a retry is signalled by
113211249Sradhika.jagtap@ARM.com        // the cache
113311249Sradhika.jagtap@ARM.com        retryPkt = pkt;
113411249Sradhika.jagtap@ARM.com    }
113511249Sradhika.jagtap@ARM.com    return success;
113611249Sradhika.jagtap@ARM.com}
113711249Sradhika.jagtap@ARM.com
113811249Sradhika.jagtap@ARM.comvoid
113911249Sradhika.jagtap@ARM.comTraceCPU::icacheRetryRecvd()
114011249Sradhika.jagtap@ARM.com{
114111249Sradhika.jagtap@ARM.com    // Schedule an event to go through the control flow in the same tick as
114211249Sradhika.jagtap@ARM.com    // retry is received
114311249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUInst, "Icache retry received. Scheduling next IcacheGen"
114411249Sradhika.jagtap@ARM.com            " event @%lli.\n", curTick());
114511249Sradhika.jagtap@ARM.com    schedule(icacheNextEvent, curTick());
114611249Sradhika.jagtap@ARM.com}
114711249Sradhika.jagtap@ARM.com
114811249Sradhika.jagtap@ARM.comvoid
114911249Sradhika.jagtap@ARM.comTraceCPU::dcacheRetryRecvd()
115011249Sradhika.jagtap@ARM.com{
115111249Sradhika.jagtap@ARM.com    // Schedule an event to go through the execute flow in the same tick as
115211249Sradhika.jagtap@ARM.com    // retry is received
115311249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Dcache retry received. Scheduling next DcacheGen"
115411249Sradhika.jagtap@ARM.com            " event @%lli.\n", curTick());
115511249Sradhika.jagtap@ARM.com    schedule(dcacheNextEvent, curTick());
115611249Sradhika.jagtap@ARM.com}
115711249Sradhika.jagtap@ARM.com
115811249Sradhika.jagtap@ARM.comvoid
115911249Sradhika.jagtap@ARM.comTraceCPU::schedDcacheNextEvent(Tick when)
116011249Sradhika.jagtap@ARM.com{
116111249Sradhika.jagtap@ARM.com    if (!dcacheNextEvent.scheduled()) {
116211249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Scheduling next DcacheGen event at %lli.\n",
116311249Sradhika.jagtap@ARM.com                when);
116411249Sradhika.jagtap@ARM.com        schedule(dcacheNextEvent, when);
116511249Sradhika.jagtap@ARM.com        ++numSchedDcacheEvent;
116611249Sradhika.jagtap@ARM.com    } else if (when < dcacheNextEvent.when()) {
116711249Sradhika.jagtap@ARM.com        DPRINTF(TraceCPUData, "Re-scheduling next dcache event from %lli"
116811249Sradhika.jagtap@ARM.com                " to %lli.\n", dcacheNextEvent.when(), when);
116911249Sradhika.jagtap@ARM.com        reschedule(dcacheNextEvent, when);
117011249Sradhika.jagtap@ARM.com    }
117111249Sradhika.jagtap@ARM.com
117211249Sradhika.jagtap@ARM.com}
117311249Sradhika.jagtap@ARM.com
117411249Sradhika.jagtap@ARM.combool
117511249Sradhika.jagtap@ARM.comTraceCPU::IcachePort::recvTimingResp(PacketPtr pkt)
117611249Sradhika.jagtap@ARM.com{
117711249Sradhika.jagtap@ARM.com    // All responses on the instruction fetch side are ignored. Simply delete
117811249Sradhika.jagtap@ARM.com    // the request and packet to free allocated memory
117911249Sradhika.jagtap@ARM.com    delete pkt->req;
118011249Sradhika.jagtap@ARM.com    delete pkt;
118111249Sradhika.jagtap@ARM.com
118211249Sradhika.jagtap@ARM.com    return true;
118311249Sradhika.jagtap@ARM.com}
118411249Sradhika.jagtap@ARM.com
118511249Sradhika.jagtap@ARM.comvoid
118611249Sradhika.jagtap@ARM.comTraceCPU::IcachePort::recvReqRetry()
118711249Sradhika.jagtap@ARM.com{
118811249Sradhika.jagtap@ARM.com    owner->icacheRetryRecvd();
118911249Sradhika.jagtap@ARM.com}
119011249Sradhika.jagtap@ARM.com
119111249Sradhika.jagtap@ARM.comvoid
119211249Sradhika.jagtap@ARM.comTraceCPU::dcacheRecvTimingResp(PacketPtr pkt)
119311249Sradhika.jagtap@ARM.com{
119411249Sradhika.jagtap@ARM.com    DPRINTF(TraceCPUData, "Received timing response from Dcache.\n");
119511249Sradhika.jagtap@ARM.com    dcacheGen.completeMemAccess(pkt);
119611249Sradhika.jagtap@ARM.com}
119711249Sradhika.jagtap@ARM.com
119811249Sradhika.jagtap@ARM.combool
119911249Sradhika.jagtap@ARM.comTraceCPU::DcachePort::recvTimingResp(PacketPtr pkt)
120011249Sradhika.jagtap@ARM.com{
120111249Sradhika.jagtap@ARM.com    // Handle the responses for data memory requests which is done inside the
120211249Sradhika.jagtap@ARM.com    // elastic data generator
120311249Sradhika.jagtap@ARM.com    owner->dcacheRecvTimingResp(pkt);
120411249Sradhika.jagtap@ARM.com    // After processing the response delete the request and packet to free
120511249Sradhika.jagtap@ARM.com    // memory
120611249Sradhika.jagtap@ARM.com    delete pkt->req;
120711249Sradhika.jagtap@ARM.com    delete pkt;
120811249Sradhika.jagtap@ARM.com
120911249Sradhika.jagtap@ARM.com    return true;
121011249Sradhika.jagtap@ARM.com}
121111249Sradhika.jagtap@ARM.com
121211249Sradhika.jagtap@ARM.comvoid
121311249Sradhika.jagtap@ARM.comTraceCPU::DcachePort::recvReqRetry()
121411249Sradhika.jagtap@ARM.com{
121511249Sradhika.jagtap@ARM.com    owner->dcacheRetryRecvd();
121611249Sradhika.jagtap@ARM.com}
121711249Sradhika.jagtap@ARM.com
121811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::InputStream::InputStream(const std::string& filename)
121911249Sradhika.jagtap@ARM.com    : trace(filename),
122011249Sradhika.jagtap@ARM.com      microOpCount(0)
122111249Sradhika.jagtap@ARM.com{
122211249Sradhika.jagtap@ARM.com    // Create a protobuf message for the header and read it from the stream
122311249Sradhika.jagtap@ARM.com    ProtoMessage::InstDepRecordHeader header_msg;
122411249Sradhika.jagtap@ARM.com    if (!trace.read(header_msg)) {
122511249Sradhika.jagtap@ARM.com        panic("Failed to read packet header from %s\n", filename);
122611249Sradhika.jagtap@ARM.com
122711249Sradhika.jagtap@ARM.com        if (header_msg.tick_freq() != SimClock::Frequency) {
122811249Sradhika.jagtap@ARM.com            panic("Trace %s was recorded with a different tick frequency %d\n",
122911249Sradhika.jagtap@ARM.com                  header_msg.tick_freq());
123011249Sradhika.jagtap@ARM.com        }
123111249Sradhika.jagtap@ARM.com    } else {
123211249Sradhika.jagtap@ARM.com        // Assign window size equal to the field in the trace that was recorded
123311249Sradhika.jagtap@ARM.com        // when the data dependency trace was captured in the o3cpu model
123411249Sradhika.jagtap@ARM.com        windowSize = header_msg.window_size();
123511249Sradhika.jagtap@ARM.com    }
123611249Sradhika.jagtap@ARM.com}
123711249Sradhika.jagtap@ARM.com
123811249Sradhika.jagtap@ARM.comvoid
123911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::InputStream::reset()
124011249Sradhika.jagtap@ARM.com{
124111249Sradhika.jagtap@ARM.com    trace.reset();
124211249Sradhika.jagtap@ARM.com}
124311249Sradhika.jagtap@ARM.com
124411249Sradhika.jagtap@ARM.combool
124511249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::InputStream::read(GraphNode* element)
124611249Sradhika.jagtap@ARM.com{
124711249Sradhika.jagtap@ARM.com    ProtoMessage::InstDepRecord pkt_msg;
124811249Sradhika.jagtap@ARM.com    if (trace.read(pkt_msg)) {
124911249Sradhika.jagtap@ARM.com        // Required fields
125011249Sradhika.jagtap@ARM.com        element->seqNum = pkt_msg.seq_num();
125111252Sradhika.jagtap@ARM.com        element->type = pkt_msg.type();
125211249Sradhika.jagtap@ARM.com        element->compDelay = pkt_msg.comp_delay();
125311249Sradhika.jagtap@ARM.com
125411249Sradhika.jagtap@ARM.com        // Repeated field robDepList
125511249Sradhika.jagtap@ARM.com        element->clearRobDep();
125611249Sradhika.jagtap@ARM.com        assert((pkt_msg.rob_dep()).size() <= element->maxRobDep);
125711249Sradhika.jagtap@ARM.com        for (int i = 0; i < (pkt_msg.rob_dep()).size(); i++) {
125811249Sradhika.jagtap@ARM.com            element->robDep[element->numRobDep] = pkt_msg.rob_dep(i);
125911249Sradhika.jagtap@ARM.com            element->numRobDep += 1;
126011249Sradhika.jagtap@ARM.com        }
126111249Sradhika.jagtap@ARM.com
126211249Sradhika.jagtap@ARM.com        // Repeated field
126311249Sradhika.jagtap@ARM.com        element->clearRegDep();
126411249Sradhika.jagtap@ARM.com        assert((pkt_msg.reg_dep()).size() <= TheISA::MaxInstSrcRegs);
126511249Sradhika.jagtap@ARM.com        for (int i = 0; i < (pkt_msg.reg_dep()).size(); i++) {
126611249Sradhika.jagtap@ARM.com            // There is a possibility that an instruction has both, a register
126711249Sradhika.jagtap@ARM.com            // and order dependency on an instruction. In such a case, the
126811249Sradhika.jagtap@ARM.com            // register dependency is omitted
126911249Sradhika.jagtap@ARM.com            bool duplicate = false;
127011249Sradhika.jagtap@ARM.com            for (int j = 0; j < element->numRobDep; j++) {
127111249Sradhika.jagtap@ARM.com                duplicate |= (pkt_msg.reg_dep(i) == element->robDep[j]);
127211249Sradhika.jagtap@ARM.com            }
127311249Sradhika.jagtap@ARM.com            if (!duplicate) {
127411249Sradhika.jagtap@ARM.com                element->regDep[element->numRegDep] = pkt_msg.reg_dep(i);
127511249Sradhika.jagtap@ARM.com                element->numRegDep += 1;
127611249Sradhika.jagtap@ARM.com            }
127711249Sradhika.jagtap@ARM.com        }
127811249Sradhika.jagtap@ARM.com
127911249Sradhika.jagtap@ARM.com        // Optional fields
128011249Sradhika.jagtap@ARM.com        if (pkt_msg.has_addr())
128111249Sradhika.jagtap@ARM.com            element->addr = pkt_msg.addr();
128211249Sradhika.jagtap@ARM.com        else
128311249Sradhika.jagtap@ARM.com            element->addr = 0;
128411249Sradhika.jagtap@ARM.com
128511249Sradhika.jagtap@ARM.com        if (pkt_msg.has_size())
128611249Sradhika.jagtap@ARM.com            element->size = pkt_msg.size();
128711249Sradhika.jagtap@ARM.com        else
128811249Sradhika.jagtap@ARM.com            element->size = 0;
128911249Sradhika.jagtap@ARM.com
129011249Sradhika.jagtap@ARM.com        if (pkt_msg.has_flags())
129111249Sradhika.jagtap@ARM.com            element->flags = pkt_msg.flags();
129211249Sradhika.jagtap@ARM.com        else
129311249Sradhika.jagtap@ARM.com            element->flags = 0;
129411249Sradhika.jagtap@ARM.com
129511249Sradhika.jagtap@ARM.com        if (pkt_msg.has_pc())
129611249Sradhika.jagtap@ARM.com            element->pc = pkt_msg.pc();
129711249Sradhika.jagtap@ARM.com        else
129811249Sradhika.jagtap@ARM.com            element->pc = 0;
129911249Sradhika.jagtap@ARM.com
130011249Sradhika.jagtap@ARM.com        // ROB occupancy number
130111249Sradhika.jagtap@ARM.com        ++microOpCount;
130211249Sradhika.jagtap@ARM.com        if (pkt_msg.has_weight()) {
130311249Sradhika.jagtap@ARM.com            microOpCount += pkt_msg.weight();
130411249Sradhika.jagtap@ARM.com        }
130511249Sradhika.jagtap@ARM.com        element->robNum = microOpCount;
130611249Sradhika.jagtap@ARM.com        return true;
130711249Sradhika.jagtap@ARM.com    }
130811249Sradhika.jagtap@ARM.com
130911249Sradhika.jagtap@ARM.com    // We have reached the end of the file
131011249Sradhika.jagtap@ARM.com    return false;
131111249Sradhika.jagtap@ARM.com}
131211249Sradhika.jagtap@ARM.com
131311249Sradhika.jagtap@ARM.combool
131411249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeRegDep(NodeSeqNum reg_dep)
131511249Sradhika.jagtap@ARM.com{
131611249Sradhika.jagtap@ARM.com    for (auto& own_reg_dep : regDep) {
131711249Sradhika.jagtap@ARM.com        if (own_reg_dep == reg_dep) {
131811249Sradhika.jagtap@ARM.com            // If register dependency is found, make it zero and return true
131911249Sradhika.jagtap@ARM.com            own_reg_dep = 0;
132011249Sradhika.jagtap@ARM.com            --numRegDep;
132111249Sradhika.jagtap@ARM.com            assert(numRegDep >= 0);
132211249Sradhika.jagtap@ARM.com            DPRINTFR(TraceCPUData, "\tFor %lli: Marking register dependency %lli "
132311249Sradhika.jagtap@ARM.com                    "done.\n", seqNum, reg_dep);
132411249Sradhika.jagtap@ARM.com            return true;
132511249Sradhika.jagtap@ARM.com        }
132611249Sradhika.jagtap@ARM.com    }
132711249Sradhika.jagtap@ARM.com
132811249Sradhika.jagtap@ARM.com    // Return false if the dependency is not found
132911249Sradhika.jagtap@ARM.com    return false;
133011249Sradhika.jagtap@ARM.com}
133111249Sradhika.jagtap@ARM.com
133211249Sradhika.jagtap@ARM.combool
133311249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeRobDep(NodeSeqNum rob_dep)
133411249Sradhika.jagtap@ARM.com{
133511249Sradhika.jagtap@ARM.com    for (auto& own_rob_dep : robDep) {
133611249Sradhika.jagtap@ARM.com        if (own_rob_dep == rob_dep) {
133711249Sradhika.jagtap@ARM.com            // If the rob dependency is found, make it zero and return true
133811249Sradhika.jagtap@ARM.com            own_rob_dep = 0;
133911249Sradhika.jagtap@ARM.com            --numRobDep;
134011249Sradhika.jagtap@ARM.com            assert(numRobDep >= 0);
134111249Sradhika.jagtap@ARM.com            DPRINTFR(TraceCPUData, "\tFor %lli: Marking ROB dependency %lli "
134211249Sradhika.jagtap@ARM.com                "done.\n", seqNum, rob_dep);
134311249Sradhika.jagtap@ARM.com            return true;
134411249Sradhika.jagtap@ARM.com        }
134511249Sradhika.jagtap@ARM.com    }
134611249Sradhika.jagtap@ARM.com    return false;
134711249Sradhika.jagtap@ARM.com}
134811249Sradhika.jagtap@ARM.com
134911249Sradhika.jagtap@ARM.comvoid
135011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::clearRegDep() {
135111249Sradhika.jagtap@ARM.com    for (auto& own_reg_dep : regDep) {
135211249Sradhika.jagtap@ARM.com        own_reg_dep = 0;
135311249Sradhika.jagtap@ARM.com    }
135411249Sradhika.jagtap@ARM.com    numRegDep = 0;
135511249Sradhika.jagtap@ARM.com}
135611249Sradhika.jagtap@ARM.com
135711249Sradhika.jagtap@ARM.comvoid
135811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::clearRobDep() {
135911249Sradhika.jagtap@ARM.com    for (auto& own_rob_dep : robDep) {
136011249Sradhika.jagtap@ARM.com        own_rob_dep = 0;
136111249Sradhika.jagtap@ARM.com    }
136211249Sradhika.jagtap@ARM.com    numRobDep = 0;
136311249Sradhika.jagtap@ARM.com}
136411249Sradhika.jagtap@ARM.com
136511249Sradhika.jagtap@ARM.combool
136611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeDepOnInst(NodeSeqNum done_seq_num)
136711249Sradhika.jagtap@ARM.com{
136811249Sradhika.jagtap@ARM.com    // If it is an rob dependency then remove it
136911249Sradhika.jagtap@ARM.com    if (!removeRobDep(done_seq_num)) {
137011249Sradhika.jagtap@ARM.com        // If it is not an rob dependency then it must be a register dependency
137111249Sradhika.jagtap@ARM.com        // If the register dependency is not found, it violates an assumption
137211249Sradhika.jagtap@ARM.com        // and must be caught by assert.
137311249Sradhika.jagtap@ARM.com        bool regdep_found M5_VAR_USED = removeRegDep(done_seq_num);
137411249Sradhika.jagtap@ARM.com        assert(regdep_found);
137511249Sradhika.jagtap@ARM.com    }
137611249Sradhika.jagtap@ARM.com    // Return true if the node is dependency free
137711249Sradhika.jagtap@ARM.com    return (numRobDep == 0 && numRegDep == 0);
137811249Sradhika.jagtap@ARM.com}
137911249Sradhika.jagtap@ARM.com
138011249Sradhika.jagtap@ARM.comvoid
138111249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace() const
138211249Sradhika.jagtap@ARM.com{
138311249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "%lli", seqNum);
138411252Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, ",%s", typeToStr());
138511252Sradhika.jagtap@ARM.com    if (isLoad() || isStore()) {
138611249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%i", addr);
138711249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%i", size);
138811249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%i", flags);
138911249Sradhika.jagtap@ARM.com    }
139011249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, ",%lli", compDelay);
139111249Sradhika.jagtap@ARM.com    int i = 0;
139211249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "robDep:");
139311249Sradhika.jagtap@ARM.com    while (robDep[i] != 0) {
139411249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%lli", robDep[i]);
139511249Sradhika.jagtap@ARM.com        i++;
139611249Sradhika.jagtap@ARM.com    }
139711249Sradhika.jagtap@ARM.com    i = 0;
139811249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "regDep:");
139911249Sradhika.jagtap@ARM.com    while (regDep[i] != 0) {
140011249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ",%lli", regDep[i]);
140111249Sradhika.jagtap@ARM.com        i++;
140211249Sradhika.jagtap@ARM.com    }
140311249Sradhika.jagtap@ARM.com    auto child_itr = dependents.begin();
140411249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "dependents:");
140511249Sradhika.jagtap@ARM.com    while (child_itr != dependents.end()) {
140611249Sradhika.jagtap@ARM.com        DPRINTFR(TraceCPUData, ":%lli", (*child_itr)->seqNum);
140711249Sradhika.jagtap@ARM.com        child_itr++;
140811249Sradhika.jagtap@ARM.com    }
140911249Sradhika.jagtap@ARM.com
141011249Sradhika.jagtap@ARM.com    DPRINTFR(TraceCPUData, "\n");
141111249Sradhika.jagtap@ARM.com}
141211249Sradhika.jagtap@ARM.com
141311252Sradhika.jagtap@ARM.comstd::string
141411252Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::typeToStr() const
141511252Sradhika.jagtap@ARM.com{
141611252Sradhika.jagtap@ARM.com    return Record::RecordType_Name(type);
141711252Sradhika.jagtap@ARM.com}
141811252Sradhika.jagtap@ARM.com
141911249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::InputStream(const std::string& filename)
142011249Sradhika.jagtap@ARM.com    : trace(filename)
142111249Sradhika.jagtap@ARM.com{
142211249Sradhika.jagtap@ARM.com    // Create a protobuf message for the header and read it from the stream
142311249Sradhika.jagtap@ARM.com    ProtoMessage::PacketHeader header_msg;
142411249Sradhika.jagtap@ARM.com    if (!trace.read(header_msg)) {
142511249Sradhika.jagtap@ARM.com        panic("Failed to read packet header from %s\n", filename);
142611249Sradhika.jagtap@ARM.com
142711249Sradhika.jagtap@ARM.com        if (header_msg.tick_freq() != SimClock::Frequency) {
142811249Sradhika.jagtap@ARM.com            panic("Trace %s was recorded with a different tick frequency %d\n",
142911249Sradhika.jagtap@ARM.com                  header_msg.tick_freq());
143011249Sradhika.jagtap@ARM.com        }
143111249Sradhika.jagtap@ARM.com    }
143211249Sradhika.jagtap@ARM.com}
143311249Sradhika.jagtap@ARM.com
143411249Sradhika.jagtap@ARM.comvoid
143511249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::reset()
143611249Sradhika.jagtap@ARM.com{
143711249Sradhika.jagtap@ARM.com    trace.reset();
143811249Sradhika.jagtap@ARM.com}
143911249Sradhika.jagtap@ARM.com
144011249Sradhika.jagtap@ARM.combool
144111249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::read(TraceElement* element)
144211249Sradhika.jagtap@ARM.com{
144311249Sradhika.jagtap@ARM.com    ProtoMessage::Packet pkt_msg;
144411249Sradhika.jagtap@ARM.com    if (trace.read(pkt_msg)) {
144511249Sradhika.jagtap@ARM.com        element->cmd = pkt_msg.cmd();
144611249Sradhika.jagtap@ARM.com        element->addr = pkt_msg.addr();
144711249Sradhika.jagtap@ARM.com        element->blocksize = pkt_msg.size();
144811249Sradhika.jagtap@ARM.com        element->tick = pkt_msg.tick();
144911249Sradhika.jagtap@ARM.com        element->flags = pkt_msg.has_flags() ? pkt_msg.flags() : 0;
145011249Sradhika.jagtap@ARM.com        element->pc = pkt_msg.has_pc() ? pkt_msg.pc() : 0;
145111249Sradhika.jagtap@ARM.com        return true;
145211249Sradhika.jagtap@ARM.com    }
145311249Sradhika.jagtap@ARM.com
145411249Sradhika.jagtap@ARM.com    // We have reached the end of the file
145511249Sradhika.jagtap@ARM.com    return false;
145611249Sradhika.jagtap@ARM.com}
1457