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