111247Sradhika.jagtap@ARM.com/*
211247Sradhika.jagtap@ARM.com * Copyright (c) 2013 - 2015 ARM Limited
311247Sradhika.jagtap@ARM.com * All rights reserved
411247Sradhika.jagtap@ARM.com *
511247Sradhika.jagtap@ARM.com * The license below extends only to copyright in the software and shall
611247Sradhika.jagtap@ARM.com * not be construed as granting a license to any other intellectual
711247Sradhika.jagtap@ARM.com * property including but not limited to intellectual property relating
811247Sradhika.jagtap@ARM.com * to a hardware implementation of the functionality of the software
911247Sradhika.jagtap@ARM.com * licensed hereunder.  You may use the software subject to the license
1011247Sradhika.jagtap@ARM.com * terms below provided that you ensure that this notice is replicated
1111247Sradhika.jagtap@ARM.com * unmodified and in its entirety in all distributions of the software,
1211247Sradhika.jagtap@ARM.com * modified or unmodified, in source code or in binary form.
1311247Sradhika.jagtap@ARM.com *
1411247Sradhika.jagtap@ARM.com * Redistribution and use in source and binary forms, with or without
1511247Sradhika.jagtap@ARM.com * modification, are permitted provided that the following conditions are
1611247Sradhika.jagtap@ARM.com * met: redistributions of source code must retain the above copyright
1711247Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer;
1811247Sradhika.jagtap@ARM.com * redistributions in binary form must reproduce the above copyright
1911247Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer in the
2011247Sradhika.jagtap@ARM.com * documentation and/or other materials provided with the distribution;
2111247Sradhika.jagtap@ARM.com * neither the name of the copyright holders nor the names of its
2211247Sradhika.jagtap@ARM.com * contributors may be used to endorse or promote products derived from
2311247Sradhika.jagtap@ARM.com * this software without specific prior written permission.
2411247Sradhika.jagtap@ARM.com *
2511247Sradhika.jagtap@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2611247Sradhika.jagtap@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2711247Sradhika.jagtap@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2811247Sradhika.jagtap@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2911247Sradhika.jagtap@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3011247Sradhika.jagtap@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3111247Sradhika.jagtap@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3211247Sradhika.jagtap@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3311247Sradhika.jagtap@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3411247Sradhika.jagtap@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3511247Sradhika.jagtap@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3611247Sradhika.jagtap@ARM.com *
3711247Sradhika.jagtap@ARM.com * Authors: Radhika Jagtap
3811247Sradhika.jagtap@ARM.com *          Andreas Hansson
3911247Sradhika.jagtap@ARM.com *          Thomas Grass
4011247Sradhika.jagtap@ARM.com */
4111247Sradhika.jagtap@ARM.com
4211247Sradhika.jagtap@ARM.com#include "cpu/o3/probe/elastic_trace.hh"
4311247Sradhika.jagtap@ARM.com
4411247Sradhika.jagtap@ARM.com#include "base/callback.hh"
4511247Sradhika.jagtap@ARM.com#include "base/output.hh"
4611247Sradhika.jagtap@ARM.com#include "base/trace.hh"
4711247Sradhika.jagtap@ARM.com#include "cpu/reg_class.hh"
4811247Sradhika.jagtap@ARM.com#include "debug/ElasticTrace.hh"
4911247Sradhika.jagtap@ARM.com#include "mem/packet.hh"
5011247Sradhika.jagtap@ARM.com
5111247Sradhika.jagtap@ARM.comElasticTrace::ElasticTrace(const ElasticTraceParams* params)
5211247Sradhika.jagtap@ARM.com    :  ProbeListenerObject(params),
5312085Sspwilson2@wisc.edu       regEtraceListenersEvent([this]{ regEtraceListeners(); }, name()),
5411247Sradhika.jagtap@ARM.com       firstWin(true),
5511247Sradhika.jagtap@ARM.com       lastClearedSeqNum(0),
5611247Sradhika.jagtap@ARM.com       depWindowSize(params->depWindowSize),
5711247Sradhika.jagtap@ARM.com       dataTraceStream(nullptr),
5811247Sradhika.jagtap@ARM.com       instTraceStream(nullptr),
5911247Sradhika.jagtap@ARM.com       startTraceInst(params->startTraceInst),
6011253Sradhika.jagtap@ARM.com       allProbesReg(false),
6111253Sradhika.jagtap@ARM.com       traceVirtAddr(params->traceVirtAddr)
6211247Sradhika.jagtap@ARM.com{
6311247Sradhika.jagtap@ARM.com    cpu = dynamic_cast<FullO3CPU<O3CPUImpl>*>(params->manager);
6411247Sradhika.jagtap@ARM.com    fatal_if(!cpu, "Manager of %s is not of type O3CPU and thus does not "\
6511247Sradhika.jagtap@ARM.com                "support dependency tracing.\n", name());
6611247Sradhika.jagtap@ARM.com
6711247Sradhika.jagtap@ARM.com    fatal_if(depWindowSize == 0, "depWindowSize parameter must be non-zero. "\
6811247Sradhika.jagtap@ARM.com                "Recommended size is 3x ROB size in the O3CPU.\n");
6911247Sradhika.jagtap@ARM.com
7011247Sradhika.jagtap@ARM.com    fatal_if(cpu->numThreads > 1, "numThreads = %i, %s supports tracing for"\
7111247Sradhika.jagtap@ARM.com                "single-threaded workload only", cpu->numThreads, name());
7211247Sradhika.jagtap@ARM.com    // Initialize the protobuf output stream
7311247Sradhika.jagtap@ARM.com    fatal_if(params->instFetchTraceFile == "", "Assign instruction fetch "\
7411247Sradhika.jagtap@ARM.com                "trace file path to instFetchTraceFile");
7511247Sradhika.jagtap@ARM.com    fatal_if(params->dataDepTraceFile == "", "Assign data dependency "\
7611247Sradhika.jagtap@ARM.com                "trace file path to dataDepTraceFile");
7711247Sradhika.jagtap@ARM.com    std::string filename = simout.resolve(name() + "." +
7811247Sradhika.jagtap@ARM.com                                            params->instFetchTraceFile);
7911247Sradhika.jagtap@ARM.com    instTraceStream = new ProtoOutputStream(filename);
8011247Sradhika.jagtap@ARM.com    filename = simout.resolve(name() + "." + params->dataDepTraceFile);
8111247Sradhika.jagtap@ARM.com    dataTraceStream = new ProtoOutputStream(filename);
8211247Sradhika.jagtap@ARM.com    // Create a protobuf message for the header and write it to the stream
8311247Sradhika.jagtap@ARM.com    ProtoMessage::PacketHeader inst_pkt_header;
8411247Sradhika.jagtap@ARM.com    inst_pkt_header.set_obj_id(name());
8511247Sradhika.jagtap@ARM.com    inst_pkt_header.set_tick_freq(SimClock::Frequency);
8611247Sradhika.jagtap@ARM.com    instTraceStream->write(inst_pkt_header);
8711247Sradhika.jagtap@ARM.com    // Create a protobuf message for the header and write it to
8811247Sradhika.jagtap@ARM.com    // the stream
8911247Sradhika.jagtap@ARM.com    ProtoMessage::InstDepRecordHeader data_rec_header;
9011247Sradhika.jagtap@ARM.com    data_rec_header.set_obj_id(name());
9111247Sradhika.jagtap@ARM.com    data_rec_header.set_tick_freq(SimClock::Frequency);
9211247Sradhika.jagtap@ARM.com    data_rec_header.set_window_size(depWindowSize);
9311247Sradhika.jagtap@ARM.com    dataTraceStream->write(data_rec_header);
9411247Sradhika.jagtap@ARM.com    // Register a callback to flush trace records and close the output streams.
9511247Sradhika.jagtap@ARM.com    Callback* cb = new MakeCallback<ElasticTrace,
9611247Sradhika.jagtap@ARM.com        &ElasticTrace::flushTraces>(this);
9711247Sradhika.jagtap@ARM.com    registerExitCallback(cb);
9811247Sradhika.jagtap@ARM.com}
9911247Sradhika.jagtap@ARM.com
10011247Sradhika.jagtap@ARM.comvoid
10111247Sradhika.jagtap@ARM.comElasticTrace::regProbeListeners()
10211247Sradhika.jagtap@ARM.com{
10311247Sradhika.jagtap@ARM.com    inform("@%llu: regProbeListeners() called, startTraceInst = %llu",
10411247Sradhika.jagtap@ARM.com        curTick(), startTraceInst);
10511247Sradhika.jagtap@ARM.com    if (startTraceInst == 0) {
10611247Sradhika.jagtap@ARM.com        // If we want to start tracing from the start of the simulation,
10711247Sradhika.jagtap@ARM.com        // register all elastic trace probes now.
10811247Sradhika.jagtap@ARM.com        regEtraceListeners();
10911247Sradhika.jagtap@ARM.com    } else {
11011247Sradhika.jagtap@ARM.com        // Schedule an event to register all elastic trace probes when
11111247Sradhika.jagtap@ARM.com        // specified no. of instructions are committed.
11211247Sradhika.jagtap@ARM.com        cpu->comInstEventQueue[(ThreadID)0]->schedule(&regEtraceListenersEvent,
11311247Sradhika.jagtap@ARM.com                                                      startTraceInst);
11411247Sradhika.jagtap@ARM.com    }
11511247Sradhika.jagtap@ARM.com}
11611247Sradhika.jagtap@ARM.com
11711247Sradhika.jagtap@ARM.comvoid
11811247Sradhika.jagtap@ARM.comElasticTrace::regEtraceListeners()
11911247Sradhika.jagtap@ARM.com{
12011247Sradhika.jagtap@ARM.com    assert(!allProbesReg);
12111247Sradhika.jagtap@ARM.com    inform("@%llu: No. of instructions committed = %llu, registering elastic"
12211247Sradhika.jagtap@ARM.com        " probe listeners", curTick(), cpu->numSimulatedInsts());
12311247Sradhika.jagtap@ARM.com    // Create new listeners: provide method to be called upon a notify() for
12411247Sradhika.jagtap@ARM.com    // each probe point.
12511247Sradhika.jagtap@ARM.com    listeners.push_back(new ProbeListenerArg<ElasticTrace, RequestPtr>(this,
12611247Sradhika.jagtap@ARM.com                        "FetchRequest", &ElasticTrace::fetchReqTrace));
12713429Srekai.gonzalezalberquilla@arm.com    listeners.push_back(new ProbeListenerArg<ElasticTrace,
12813429Srekai.gonzalezalberquilla@arm.com            DynInstConstPtr>(this, "Execute",
12913429Srekai.gonzalezalberquilla@arm.com                &ElasticTrace::recordExecTick));
13013429Srekai.gonzalezalberquilla@arm.com    listeners.push_back(new ProbeListenerArg<ElasticTrace,
13113429Srekai.gonzalezalberquilla@arm.com            DynInstConstPtr>(this, "ToCommit",
13213429Srekai.gonzalezalberquilla@arm.com                &ElasticTrace::recordToCommTick));
13313429Srekai.gonzalezalberquilla@arm.com    listeners.push_back(new ProbeListenerArg<ElasticTrace,
13413429Srekai.gonzalezalberquilla@arm.com            DynInstConstPtr>(this, "Rename",
13513429Srekai.gonzalezalberquilla@arm.com                &ElasticTrace::updateRegDep));
13611247Sradhika.jagtap@ARM.com    listeners.push_back(new ProbeListenerArg<ElasticTrace, SeqNumRegPair>(this,
13711247Sradhika.jagtap@ARM.com                        "SquashInRename", &ElasticTrace::removeRegDepMapEntry));
13813429Srekai.gonzalezalberquilla@arm.com    listeners.push_back(new ProbeListenerArg<ElasticTrace,
13913429Srekai.gonzalezalberquilla@arm.com            DynInstConstPtr>(this, "Squash",
14013429Srekai.gonzalezalberquilla@arm.com                &ElasticTrace::addSquashedInst));
14113429Srekai.gonzalezalberquilla@arm.com    listeners.push_back(new ProbeListenerArg<ElasticTrace,
14213429Srekai.gonzalezalberquilla@arm.com            DynInstConstPtr>(this, "Commit",
14313429Srekai.gonzalezalberquilla@arm.com                &ElasticTrace::addCommittedInst));
14411247Sradhika.jagtap@ARM.com    allProbesReg = true;
14511247Sradhika.jagtap@ARM.com}
14611247Sradhika.jagtap@ARM.com
14711247Sradhika.jagtap@ARM.comvoid
14811247Sradhika.jagtap@ARM.comElasticTrace::fetchReqTrace(const RequestPtr &req)
14911247Sradhika.jagtap@ARM.com{
15011247Sradhika.jagtap@ARM.com
15111247Sradhika.jagtap@ARM.com    DPRINTFR(ElasticTrace, "Fetch Req %i,(%lli,%lli,%lli),%i,%i,%lli\n",
15211247Sradhika.jagtap@ARM.com             (MemCmd::ReadReq),
15311247Sradhika.jagtap@ARM.com             req->getPC(), req->getVaddr(), req->getPaddr(),
15411247Sradhika.jagtap@ARM.com             req->getFlags(), req->getSize(), curTick());
15511247Sradhika.jagtap@ARM.com
15611247Sradhika.jagtap@ARM.com    // Create a protobuf message including the request fields necessary to
15711247Sradhika.jagtap@ARM.com    // recreate the request in the TraceCPU.
15811247Sradhika.jagtap@ARM.com    ProtoMessage::Packet inst_fetch_pkt;
15911247Sradhika.jagtap@ARM.com    inst_fetch_pkt.set_tick(curTick());
16011247Sradhika.jagtap@ARM.com    inst_fetch_pkt.set_cmd(MemCmd::ReadReq);
16111247Sradhika.jagtap@ARM.com    inst_fetch_pkt.set_pc(req->getPC());
16211247Sradhika.jagtap@ARM.com    inst_fetch_pkt.set_flags(req->getFlags());
16311247Sradhika.jagtap@ARM.com    inst_fetch_pkt.set_addr(req->getPaddr());
16411247Sradhika.jagtap@ARM.com    inst_fetch_pkt.set_size(req->getSize());
16511247Sradhika.jagtap@ARM.com    // Write the message to the stream.
16611247Sradhika.jagtap@ARM.com    instTraceStream->write(inst_fetch_pkt);
16711247Sradhika.jagtap@ARM.com}
16811247Sradhika.jagtap@ARM.com
16911247Sradhika.jagtap@ARM.comvoid
17013429Srekai.gonzalezalberquilla@arm.comElasticTrace::recordExecTick(const DynInstConstPtr& dyn_inst)
17111247Sradhika.jagtap@ARM.com{
17211247Sradhika.jagtap@ARM.com
17311247Sradhika.jagtap@ARM.com    // In a corner case, a retired instruction is propagated backward to the
17411247Sradhika.jagtap@ARM.com    // IEW instruction queue to handle some side-channel information. But we
17511247Sradhika.jagtap@ARM.com    // must not process an instruction again. So we test the sequence number
17611247Sradhika.jagtap@ARM.com    // against the lastClearedSeqNum and skip adding the instruction for such
17711247Sradhika.jagtap@ARM.com    // corner cases.
17811247Sradhika.jagtap@ARM.com    if (dyn_inst->seqNum <= lastClearedSeqNum) {
17911247Sradhika.jagtap@ARM.com        DPRINTFR(ElasticTrace, "[sn:%lli] Ignoring in execute as instruction \
18011247Sradhika.jagtap@ARM.com        has already retired (mostly squashed)", dyn_inst->seqNum);
18111247Sradhika.jagtap@ARM.com        // Do nothing as program has proceeded and this inst has been
18211247Sradhika.jagtap@ARM.com        // propagated backwards to handle something.
18311247Sradhika.jagtap@ARM.com        return;
18411247Sradhika.jagtap@ARM.com    }
18511247Sradhika.jagtap@ARM.com
18611247Sradhika.jagtap@ARM.com    DPRINTFR(ElasticTrace, "[sn:%lli] Execute Tick = %i\n", dyn_inst->seqNum,
18711247Sradhika.jagtap@ARM.com                curTick());
18811247Sradhika.jagtap@ARM.com    // Either the execution info object will already exist if this
18911247Sradhika.jagtap@ARM.com    // instruction had a register dependency recorded in the rename probe
19011247Sradhika.jagtap@ARM.com    // listener before entering execute stage or it will not exist and will
19111247Sradhika.jagtap@ARM.com    // need to be created here.
19211247Sradhika.jagtap@ARM.com    InstExecInfo* exec_info_ptr;
19311247Sradhika.jagtap@ARM.com    auto itr_exec_info = tempStore.find(dyn_inst->seqNum);
19411247Sradhika.jagtap@ARM.com    if (itr_exec_info != tempStore.end()) {
19511247Sradhika.jagtap@ARM.com        exec_info_ptr = itr_exec_info->second;
19611247Sradhika.jagtap@ARM.com    } else {
19711247Sradhika.jagtap@ARM.com        exec_info_ptr = new InstExecInfo;
19811247Sradhika.jagtap@ARM.com        tempStore[dyn_inst->seqNum] = exec_info_ptr;
19911247Sradhika.jagtap@ARM.com    }
20011247Sradhika.jagtap@ARM.com
20111247Sradhika.jagtap@ARM.com    exec_info_ptr->executeTick = curTick();
20211247Sradhika.jagtap@ARM.com    maxTempStoreSize = std::max(tempStore.size(),
20311247Sradhika.jagtap@ARM.com                                (std::size_t)maxTempStoreSize.value());
20411247Sradhika.jagtap@ARM.com}
20511247Sradhika.jagtap@ARM.com
20611247Sradhika.jagtap@ARM.comvoid
20713429Srekai.gonzalezalberquilla@arm.comElasticTrace::recordToCommTick(const DynInstConstPtr& dyn_inst)
20811247Sradhika.jagtap@ARM.com{
20911247Sradhika.jagtap@ARM.com    // If tracing has just been enabled then the instruction at this stage of
21011247Sradhika.jagtap@ARM.com    // execution is far enough that we cannot gather info about its past like
21111247Sradhika.jagtap@ARM.com    // the tick it started execution. Simply return until we see an instruction
21211247Sradhika.jagtap@ARM.com    // that is found in the tempStore.
21311247Sradhika.jagtap@ARM.com    auto itr_exec_info = tempStore.find(dyn_inst->seqNum);
21411247Sradhika.jagtap@ARM.com    if (itr_exec_info == tempStore.end()) {
21511247Sradhika.jagtap@ARM.com        DPRINTFR(ElasticTrace, "recordToCommTick: [sn:%lli] Not in temp store,"
21611247Sradhika.jagtap@ARM.com                    " skipping.\n", dyn_inst->seqNum);
21711247Sradhika.jagtap@ARM.com        return;
21811247Sradhika.jagtap@ARM.com    }
21911247Sradhika.jagtap@ARM.com
22011247Sradhika.jagtap@ARM.com    DPRINTFR(ElasticTrace, "[sn:%lli] To Commit Tick = %i\n", dyn_inst->seqNum,
22111247Sradhika.jagtap@ARM.com                curTick());
22211247Sradhika.jagtap@ARM.com    InstExecInfo* exec_info_ptr = itr_exec_info->second;
22311247Sradhika.jagtap@ARM.com    exec_info_ptr->toCommitTick = curTick();
22411247Sradhika.jagtap@ARM.com
22511247Sradhika.jagtap@ARM.com}
22611247Sradhika.jagtap@ARM.com
22711247Sradhika.jagtap@ARM.comvoid
22813429Srekai.gonzalezalberquilla@arm.comElasticTrace::updateRegDep(const DynInstConstPtr& dyn_inst)
22911247Sradhika.jagtap@ARM.com{
23011247Sradhika.jagtap@ARM.com    // Get the sequence number of the instruction
23111247Sradhika.jagtap@ARM.com    InstSeqNum seq_num = dyn_inst->seqNum;
23211247Sradhika.jagtap@ARM.com
23311247Sradhika.jagtap@ARM.com    assert(dyn_inst->seqNum > lastClearedSeqNum);
23411247Sradhika.jagtap@ARM.com
23511247Sradhika.jagtap@ARM.com    // Since this is the first probe activated in the pipeline, create
23611247Sradhika.jagtap@ARM.com    // a new execution info object to track this instruction as it
23711247Sradhika.jagtap@ARM.com    // progresses through the pipeline.
23811247Sradhika.jagtap@ARM.com    InstExecInfo* exec_info_ptr = new InstExecInfo;
23911247Sradhika.jagtap@ARM.com    tempStore[seq_num] = exec_info_ptr;
24011247Sradhika.jagtap@ARM.com
24111247Sradhika.jagtap@ARM.com    // Loop through the source registers and look up the dependency map. If
24211247Sradhika.jagtap@ARM.com    // the source register entry is found in the dependency map, add a
24311247Sradhika.jagtap@ARM.com    // dependency on the last writer.
24411247Sradhika.jagtap@ARM.com    int8_t max_regs = dyn_inst->numSrcRegs();
24511247Sradhika.jagtap@ARM.com    for (int src_idx = 0; src_idx < max_regs; src_idx++) {
24612255Sradhika.jagtap@arm.com
24712255Sradhika.jagtap@arm.com        const RegId& src_reg = dyn_inst->srcRegIdx(src_idx);
24812255Sradhika.jagtap@arm.com        if (!src_reg.isMiscReg() &&
24912255Sradhika.jagtap@arm.com            !src_reg.isZeroReg()) {
25012255Sradhika.jagtap@arm.com            // Get the physical register index of the i'th source register.
25112255Sradhika.jagtap@arm.com            PhysRegIdPtr phys_src_reg = dyn_inst->renamedSrcRegIdx(src_idx);
25212255Sradhika.jagtap@arm.com            DPRINTFR(ElasticTrace, "[sn:%lli] Check map for src reg"
25312255Sradhika.jagtap@arm.com                     " %i (%s)\n", seq_num,
25412255Sradhika.jagtap@arm.com                     phys_src_reg->flatIndex(), phys_src_reg->className());
25512255Sradhika.jagtap@arm.com            auto itr_writer = physRegDepMap.find(phys_src_reg->flatIndex());
25612255Sradhika.jagtap@arm.com            if (itr_writer != physRegDepMap.end()) {
25712255Sradhika.jagtap@arm.com                InstSeqNum last_writer = itr_writer->second;
25812255Sradhika.jagtap@arm.com                // Additionally the dependency distance is kept less than the
25912255Sradhika.jagtap@arm.com                // window size parameter to limit the memory allocation to
26012255Sradhika.jagtap@arm.com                // nodes in the graph. If the window were tending to infinite
26112255Sradhika.jagtap@arm.com                // we would have to load a large number of node objects during
26212255Sradhika.jagtap@arm.com                // replay.
26312255Sradhika.jagtap@arm.com                if (seq_num - last_writer < depWindowSize) {
26412255Sradhika.jagtap@arm.com                    // Record a physical register dependency.
26512255Sradhika.jagtap@arm.com                    exec_info_ptr->physRegDepSet.insert(last_writer);
26612255Sradhika.jagtap@arm.com                }
26711247Sradhika.jagtap@ARM.com            }
26812255Sradhika.jagtap@arm.com
26911247Sradhika.jagtap@ARM.com        }
27012255Sradhika.jagtap@arm.com
27111247Sradhika.jagtap@ARM.com    }
27211247Sradhika.jagtap@ARM.com
27311247Sradhika.jagtap@ARM.com    // Loop through the destination registers of this instruction and update
27411247Sradhika.jagtap@ARM.com    // the physical register dependency map for last writers to registers.
27511247Sradhika.jagtap@ARM.com    max_regs = dyn_inst->numDestRegs();
27611247Sradhika.jagtap@ARM.com    for (int dest_idx = 0; dest_idx < max_regs; dest_idx++) {
27711247Sradhika.jagtap@ARM.com        // For data dependency tracking the register must be an int, float or
27811247Sradhika.jagtap@ARM.com        // CC register and not a Misc register.
27912106SRekai.GonzalezAlberquilla@arm.com        const RegId& dest_reg = dyn_inst->destRegIdx(dest_idx);
28012106SRekai.GonzalezAlberquilla@arm.com        if (!dest_reg.isMiscReg() &&
28112104Snathanael.premillieu@arm.com            !dest_reg.isZeroReg()) {
28212104Snathanael.premillieu@arm.com            // Get the physical register index of the i'th destination
28312104Snathanael.premillieu@arm.com            // register.
28412105Snathanael.premillieu@arm.com            PhysRegIdPtr phys_dest_reg = dyn_inst->renamedDestRegIdx(dest_idx);
28512105Snathanael.premillieu@arm.com            DPRINTFR(ElasticTrace, "[sn:%lli] Update map for dest reg"
28612255Sradhika.jagtap@arm.com                     " %i (%s)\n", seq_num, phys_dest_reg->flatIndex(),
28712106SRekai.GonzalezAlberquilla@arm.com                     dest_reg.className());
28812106SRekai.GonzalezAlberquilla@arm.com            physRegDepMap[phys_dest_reg->flatIndex()] = seq_num;
28911247Sradhika.jagtap@ARM.com        }
29011247Sradhika.jagtap@ARM.com    }
29111247Sradhika.jagtap@ARM.com    maxPhysRegDepMapSize = std::max(physRegDepMap.size(),
29211247Sradhika.jagtap@ARM.com                                    (std::size_t)maxPhysRegDepMapSize.value());
29311247Sradhika.jagtap@ARM.com}
29411247Sradhika.jagtap@ARM.com
29511247Sradhika.jagtap@ARM.comvoid
29611247Sradhika.jagtap@ARM.comElasticTrace::removeRegDepMapEntry(const SeqNumRegPair &inst_reg_pair)
29711247Sradhika.jagtap@ARM.com{
29811247Sradhika.jagtap@ARM.com    DPRINTFR(ElasticTrace, "Remove Map entry for Reg %i\n",
29912105Snathanael.premillieu@arm.com            inst_reg_pair.second);
30011247Sradhika.jagtap@ARM.com    auto itr_regdep_map = physRegDepMap.find(inst_reg_pair.second);
30111247Sradhika.jagtap@ARM.com    if (itr_regdep_map != physRegDepMap.end())
30211247Sradhika.jagtap@ARM.com        physRegDepMap.erase(itr_regdep_map);
30311247Sradhika.jagtap@ARM.com}
30411247Sradhika.jagtap@ARM.com
30511247Sradhika.jagtap@ARM.comvoid
30613429Srekai.gonzalezalberquilla@arm.comElasticTrace::addSquashedInst(const DynInstConstPtr& head_inst)
30711247Sradhika.jagtap@ARM.com{
30811247Sradhika.jagtap@ARM.com    // If the squashed instruction was squashed before being processed by
30911247Sradhika.jagtap@ARM.com    // execute stage then it will not be in the temporary store. In this case
31011247Sradhika.jagtap@ARM.com    // do nothing and return.
31111247Sradhika.jagtap@ARM.com    auto itr_exec_info = tempStore.find(head_inst->seqNum);
31211247Sradhika.jagtap@ARM.com    if (itr_exec_info == tempStore.end())
31311247Sradhika.jagtap@ARM.com        return;
31411247Sradhika.jagtap@ARM.com
31511247Sradhika.jagtap@ARM.com    // If there is a squashed load for which a read request was
31611247Sradhika.jagtap@ARM.com    // sent before it got squashed then add it to the trace.
31711247Sradhika.jagtap@ARM.com    DPRINTFR(ElasticTrace, "Attempt to add squashed inst [sn:%lli]\n",
31811247Sradhika.jagtap@ARM.com                head_inst->seqNum);
31911247Sradhika.jagtap@ARM.com    // Get pointer to the execution info object corresponding to the inst.
32011247Sradhika.jagtap@ARM.com    InstExecInfo* exec_info_ptr = itr_exec_info->second;
32111247Sradhika.jagtap@ARM.com    if (head_inst->isLoad() && exec_info_ptr->executeTick != MaxTick &&
32211247Sradhika.jagtap@ARM.com        exec_info_ptr->toCommitTick != MaxTick &&
32311247Sradhika.jagtap@ARM.com        head_inst->hasRequest() &&
32411247Sradhika.jagtap@ARM.com        head_inst->getFault() == NoFault) {
32511247Sradhika.jagtap@ARM.com        // Add record to depTrace with commit parameter as false.
32611247Sradhika.jagtap@ARM.com        addDepTraceRecord(head_inst, exec_info_ptr, false);
32711247Sradhika.jagtap@ARM.com    }
32811247Sradhika.jagtap@ARM.com    // As the information contained is no longer needed, remove the execution
32911247Sradhika.jagtap@ARM.com    // info object from the temporary store.
33011247Sradhika.jagtap@ARM.com    clearTempStoreUntil(head_inst);
33111247Sradhika.jagtap@ARM.com}
33211247Sradhika.jagtap@ARM.com
33311247Sradhika.jagtap@ARM.comvoid
33413429Srekai.gonzalezalberquilla@arm.comElasticTrace::addCommittedInst(const DynInstConstPtr& head_inst)
33511247Sradhika.jagtap@ARM.com{
33611247Sradhika.jagtap@ARM.com    DPRINTFR(ElasticTrace, "Attempt to add committed inst [sn:%lli]\n",
33711247Sradhika.jagtap@ARM.com                head_inst->seqNum);
33811247Sradhika.jagtap@ARM.com
33911247Sradhika.jagtap@ARM.com    // Add the instruction to the depTrace.
34011247Sradhika.jagtap@ARM.com    if (!head_inst->isNop()) {
34111247Sradhika.jagtap@ARM.com
34211247Sradhika.jagtap@ARM.com        // If tracing has just been enabled then the instruction at this stage
34311247Sradhika.jagtap@ARM.com        // of execution is far enough that we cannot gather info about its past
34411247Sradhika.jagtap@ARM.com        // like the tick it started execution. Simply return until we see an
34511247Sradhika.jagtap@ARM.com        // instruction that is found in the tempStore.
34611247Sradhika.jagtap@ARM.com        auto itr_temp_store = tempStore.find(head_inst->seqNum);
34711247Sradhika.jagtap@ARM.com        if (itr_temp_store == tempStore.end()) {
34811247Sradhika.jagtap@ARM.com            DPRINTFR(ElasticTrace, "addCommittedInst: [sn:%lli] Not in temp "
34911247Sradhika.jagtap@ARM.com                "store, skipping.\n", head_inst->seqNum);
35011247Sradhika.jagtap@ARM.com            return;
35111247Sradhika.jagtap@ARM.com        }
35211247Sradhika.jagtap@ARM.com
35311247Sradhika.jagtap@ARM.com        // Get pointer to the execution info object corresponding to the inst.
35411247Sradhika.jagtap@ARM.com        InstExecInfo* exec_info_ptr = itr_temp_store->second;
35511247Sradhika.jagtap@ARM.com        assert(exec_info_ptr->executeTick != MaxTick);
35611247Sradhika.jagtap@ARM.com        assert(exec_info_ptr->toCommitTick != MaxTick);
35711247Sradhika.jagtap@ARM.com
35811247Sradhika.jagtap@ARM.com        // Check if the instruction had a fault, if it predicated false and
35911247Sradhika.jagtap@ARM.com        // thus previous register values were restored or if it was a
36011247Sradhika.jagtap@ARM.com        // load/store that did not have a request (e.g. when the size of the
36111247Sradhika.jagtap@ARM.com        // request is zero). In all these cases the instruction is set as
36211247Sradhika.jagtap@ARM.com        // executed and is picked up by the commit probe listener. But a
36311247Sradhika.jagtap@ARM.com        // request is not issued and registers are not written. So practically,
36411247Sradhika.jagtap@ARM.com        // skipping these should not hurt as execution would not stall on them.
36511247Sradhika.jagtap@ARM.com        // Alternatively, these could be included merely as a compute node in
36611247Sradhika.jagtap@ARM.com        // the graph. Removing these for now. If correlation accuracy needs to
36711247Sradhika.jagtap@ARM.com        // be improved in future these can be turned into comp nodes at the
36811247Sradhika.jagtap@ARM.com        // cost of bigger traces.
36911247Sradhika.jagtap@ARM.com        if (head_inst->getFault() != NoFault) {
37011247Sradhika.jagtap@ARM.com            DPRINTF(ElasticTrace, "%s [sn:%lli] has faulted so "
37111247Sradhika.jagtap@ARM.com                    "skip adding it to the trace\n",
37211247Sradhika.jagtap@ARM.com                    (head_inst->isMemRef() ? "Load/store" : "Comp inst."),
37311247Sradhika.jagtap@ARM.com                    head_inst->seqNum);
37411247Sradhika.jagtap@ARM.com        } else if (head_inst->isMemRef() && !head_inst->hasRequest()) {
37511247Sradhika.jagtap@ARM.com            DPRINTF(ElasticTrace, "Load/store [sn:%lli]  has no request so "
37611247Sradhika.jagtap@ARM.com                    "skip adding it to the trace\n", head_inst->seqNum);
37711247Sradhika.jagtap@ARM.com        } else if (!head_inst->readPredicate()) {
37811247Sradhika.jagtap@ARM.com            DPRINTF(ElasticTrace, "%s [sn:%lli] is predicated false so "
37911247Sradhika.jagtap@ARM.com                    "skip adding it to the trace\n",
38011247Sradhika.jagtap@ARM.com                    (head_inst->isMemRef() ? "Load/store" : "Comp inst."),
38111247Sradhika.jagtap@ARM.com                    head_inst->seqNum);
38211247Sradhika.jagtap@ARM.com        } else {
38311247Sradhika.jagtap@ARM.com            // Add record to depTrace with commit parameter as true.
38411247Sradhika.jagtap@ARM.com            addDepTraceRecord(head_inst, exec_info_ptr, true);
38511247Sradhika.jagtap@ARM.com        }
38611247Sradhika.jagtap@ARM.com    }
38711247Sradhika.jagtap@ARM.com    // As the information contained is no longer needed, remove the execution
38811247Sradhika.jagtap@ARM.com    // info object from the temporary store.
38911247Sradhika.jagtap@ARM.com    clearTempStoreUntil(head_inst);
39011247Sradhika.jagtap@ARM.com}
39111247Sradhika.jagtap@ARM.com
39211247Sradhika.jagtap@ARM.comvoid
39313429Srekai.gonzalezalberquilla@arm.comElasticTrace::addDepTraceRecord(const DynInstConstPtr& head_inst,
39411247Sradhika.jagtap@ARM.com                                InstExecInfo* exec_info_ptr, bool commit)
39511247Sradhika.jagtap@ARM.com{
39611247Sradhika.jagtap@ARM.com    // Create a record to assign dynamic intruction related fields.
39711247Sradhika.jagtap@ARM.com    TraceInfo* new_record = new TraceInfo;
39811247Sradhika.jagtap@ARM.com    // Add to map for sequence number look up to retrieve the TraceInfo pointer
39911247Sradhika.jagtap@ARM.com    traceInfoMap[head_inst->seqNum] = new_record;
40011247Sradhika.jagtap@ARM.com
40111247Sradhika.jagtap@ARM.com    // Assign fields from the instruction
40211247Sradhika.jagtap@ARM.com    new_record->instNum = head_inst->seqNum;
40311247Sradhika.jagtap@ARM.com    new_record->commit = commit;
40411252Sradhika.jagtap@ARM.com    new_record->type = head_inst->isLoad() ? Record::LOAD :
40511252Sradhika.jagtap@ARM.com                        (head_inst->isStore() ? Record::STORE :
40611252Sradhika.jagtap@ARM.com                        Record::COMP);
40711247Sradhika.jagtap@ARM.com
40811247Sradhika.jagtap@ARM.com    // Assign fields for creating a request in case of a load/store
40911247Sradhika.jagtap@ARM.com    new_record->reqFlags = head_inst->memReqFlags;
41011253Sradhika.jagtap@ARM.com    new_record->virtAddr = head_inst->effAddr;
41111253Sradhika.jagtap@ARM.com    new_record->asid = head_inst->asid;
41213590Srekai.gonzalezalberquilla@arm.com    new_record->physAddr = head_inst->physEffAddr;
41311247Sradhika.jagtap@ARM.com    // Currently the tracing does not support split requests.
41411247Sradhika.jagtap@ARM.com    new_record->size = head_inst->effSize;
41511247Sradhika.jagtap@ARM.com    new_record->pc = head_inst->instAddr();
41611247Sradhika.jagtap@ARM.com
41711247Sradhika.jagtap@ARM.com    // Assign the timing information stored in the execution info object
41811247Sradhika.jagtap@ARM.com    new_record->executeTick = exec_info_ptr->executeTick;
41911247Sradhika.jagtap@ARM.com    new_record->toCommitTick = exec_info_ptr->toCommitTick;
42011247Sradhika.jagtap@ARM.com    new_record->commitTick = curTick();
42111247Sradhika.jagtap@ARM.com
42211247Sradhika.jagtap@ARM.com    // Assign initial values for number of dependents and computational delay
42311247Sradhika.jagtap@ARM.com    new_record->numDepts = 0;
42411247Sradhika.jagtap@ARM.com    new_record->compDelay = -1;
42511247Sradhika.jagtap@ARM.com
42611247Sradhika.jagtap@ARM.com    // The physical register dependency set of the first instruction is
42711247Sradhika.jagtap@ARM.com    // empty. Since there are no records in the depTrace at this point, the
42811247Sradhika.jagtap@ARM.com    // case of adding an ROB dependency by using a reverse iterator is not
42911247Sradhika.jagtap@ARM.com    // applicable. Thus, populate the fields of the record corresponding to the
43011247Sradhika.jagtap@ARM.com    // first instruction and return.
43111247Sradhika.jagtap@ARM.com    if (depTrace.empty()) {
43211247Sradhika.jagtap@ARM.com        // Store the record in depTrace.
43311247Sradhika.jagtap@ARM.com        depTrace.push_back(new_record);
43411247Sradhika.jagtap@ARM.com        DPRINTF(ElasticTrace, "Added first inst record %lli to DepTrace.\n",
43511247Sradhika.jagtap@ARM.com                new_record->instNum);
43611247Sradhika.jagtap@ARM.com        return;
43711247Sradhika.jagtap@ARM.com    }
43811247Sradhika.jagtap@ARM.com
43911247Sradhika.jagtap@ARM.com    // Clear register dependencies for squashed loads as they may be dependent
44011247Sradhika.jagtap@ARM.com    // on squashed instructions and we do not add those to the trace.
44111247Sradhika.jagtap@ARM.com    if (head_inst->isLoad() && !commit) {
44211247Sradhika.jagtap@ARM.com         (exec_info_ptr->physRegDepSet).clear();
44311247Sradhika.jagtap@ARM.com    }
44411247Sradhika.jagtap@ARM.com
44511247Sradhika.jagtap@ARM.com    // Assign the register dependencies stored in the execution info object
44611247Sradhika.jagtap@ARM.com    std::set<InstSeqNum>::const_iterator dep_set_it;
44711247Sradhika.jagtap@ARM.com    for (dep_set_it = (exec_info_ptr->physRegDepSet).begin();
44811247Sradhika.jagtap@ARM.com         dep_set_it != (exec_info_ptr->physRegDepSet).end();
44911247Sradhika.jagtap@ARM.com         ++dep_set_it) {
45011247Sradhika.jagtap@ARM.com        auto trace_info_itr = traceInfoMap.find(*dep_set_it);
45111247Sradhika.jagtap@ARM.com        if (trace_info_itr != traceInfoMap.end()) {
45211247Sradhika.jagtap@ARM.com            // The register dependency is valid. Assign it and calculate
45311247Sradhika.jagtap@ARM.com            // computational delay
45411247Sradhika.jagtap@ARM.com            new_record->physRegDepList.push_back(*dep_set_it);
45511247Sradhika.jagtap@ARM.com            DPRINTF(ElasticTrace, "Inst %lli has register dependency on "
45611247Sradhika.jagtap@ARM.com                    "%lli\n", new_record->instNum, *dep_set_it);
45711247Sradhika.jagtap@ARM.com            TraceInfo* reg_dep = trace_info_itr->second;
45811247Sradhika.jagtap@ARM.com            reg_dep->numDepts++;
45911247Sradhika.jagtap@ARM.com            compDelayPhysRegDep(reg_dep, new_record);
46011247Sradhika.jagtap@ARM.com            ++numRegDep;
46111247Sradhika.jagtap@ARM.com        } else {
46211247Sradhika.jagtap@ARM.com            // The instruction that this has a register dependency on was
46311247Sradhika.jagtap@ARM.com            // not added to the trace because of one of the following
46411247Sradhika.jagtap@ARM.com            // 1. it was an instruction that had a fault
46511247Sradhika.jagtap@ARM.com            // 2. it was an instruction that was predicated false and
46611247Sradhika.jagtap@ARM.com            // previous register values were restored
46711247Sradhika.jagtap@ARM.com            // 3. it was load/store that did not have a request (e.g. when
46811247Sradhika.jagtap@ARM.com            // the size of the request is zero but this may not be a fault)
46911247Sradhika.jagtap@ARM.com            // In all these cases the instruction is set as executed and is
47011247Sradhika.jagtap@ARM.com            // picked up by the commit probe listener. But a request is not
47111247Sradhika.jagtap@ARM.com            // issued and registers are not written to in these cases.
47211247Sradhika.jagtap@ARM.com            DPRINTF(ElasticTrace, "Inst %lli has register dependency on "
47311247Sradhika.jagtap@ARM.com                    "%lli is skipped\n",new_record->instNum, *dep_set_it);
47411247Sradhika.jagtap@ARM.com        }
47511247Sradhika.jagtap@ARM.com    }
47611247Sradhika.jagtap@ARM.com
47711247Sradhika.jagtap@ARM.com    // Check for and assign an ROB dependency in addition to register
47811247Sradhika.jagtap@ARM.com    // dependency before adding the record to the trace.
47911247Sradhika.jagtap@ARM.com    // As stores have to commit in order a store is dependent on the last
48011247Sradhika.jagtap@ARM.com    // committed load/store. This is recorded in the ROB dependency.
48111247Sradhika.jagtap@ARM.com    if (head_inst->isStore()) {
48211247Sradhika.jagtap@ARM.com        // Look up store-after-store order dependency
48311247Sradhika.jagtap@ARM.com        updateCommitOrderDep(new_record, false);
48411247Sradhika.jagtap@ARM.com        // Look up store-after-load order dependency
48511247Sradhika.jagtap@ARM.com        updateCommitOrderDep(new_record, true);
48611247Sradhika.jagtap@ARM.com    }
48711247Sradhika.jagtap@ARM.com
48811247Sradhika.jagtap@ARM.com    // In case a node is dependency-free or its dependency got discarded
48911247Sradhika.jagtap@ARM.com    // because it was outside the window, it is marked ready in the ROB at the
49011247Sradhika.jagtap@ARM.com    // time of issue. A request is sent as soon as possible. To model this, a
49111247Sradhika.jagtap@ARM.com    // node is assigned an issue order dependency on a committed instruction
49211247Sradhika.jagtap@ARM.com    // that completed earlier than it. This is done to avoid the problem of
49311247Sradhika.jagtap@ARM.com    // determining the issue times of such dependency-free nodes during replay
49411247Sradhika.jagtap@ARM.com    // which could lead to too much parallelism, thinking conservatively.
49511247Sradhika.jagtap@ARM.com    if (new_record->robDepList.empty() && new_record->physRegDepList.empty()) {
49611247Sradhika.jagtap@ARM.com        updateIssueOrderDep(new_record);
49711247Sradhika.jagtap@ARM.com    }
49811247Sradhika.jagtap@ARM.com
49911247Sradhika.jagtap@ARM.com    // Store the record in depTrace.
50011247Sradhika.jagtap@ARM.com    depTrace.push_back(new_record);
50111247Sradhika.jagtap@ARM.com    DPRINTF(ElasticTrace, "Added %s inst %lli to DepTrace.\n",
50211247Sradhika.jagtap@ARM.com            (commit ? "committed" : "squashed"), new_record->instNum);
50311247Sradhika.jagtap@ARM.com
50411247Sradhika.jagtap@ARM.com    // To process the number of records specified by depWindowSize in the
50511247Sradhika.jagtap@ARM.com    // forward direction, the depTrace must have twice as many records
50611247Sradhika.jagtap@ARM.com    // to check for dependencies.
50711247Sradhika.jagtap@ARM.com    if (depTrace.size() == 2 * depWindowSize) {
50811247Sradhika.jagtap@ARM.com
50911247Sradhika.jagtap@ARM.com        DPRINTF(ElasticTrace, "Writing out trace...\n");
51011247Sradhika.jagtap@ARM.com
51111247Sradhika.jagtap@ARM.com        // Write out the records which have been processed to the trace
51211247Sradhika.jagtap@ARM.com        // and remove them from the depTrace.
51311247Sradhika.jagtap@ARM.com        writeDepTrace(depWindowSize);
51411247Sradhika.jagtap@ARM.com
51511247Sradhika.jagtap@ARM.com        // After the first window, writeDepTrace() must check for valid
51611247Sradhika.jagtap@ARM.com        // compDelay.
51711247Sradhika.jagtap@ARM.com        firstWin = false;
51811247Sradhika.jagtap@ARM.com    }
51911247Sradhika.jagtap@ARM.com}
52011247Sradhika.jagtap@ARM.com
52111247Sradhika.jagtap@ARM.comvoid
52211247Sradhika.jagtap@ARM.comElasticTrace::updateCommitOrderDep(TraceInfo* new_record,
52311247Sradhika.jagtap@ARM.com                                    bool find_load_not_store)
52411247Sradhika.jagtap@ARM.com{
52511252Sradhika.jagtap@ARM.com    assert(new_record->isStore());
52611247Sradhika.jagtap@ARM.com    // Iterate in reverse direction to search for the last committed
52711247Sradhika.jagtap@ARM.com    // load/store that completed earlier than the new record
52811247Sradhika.jagtap@ARM.com    depTraceRevItr from_itr(depTrace.end());
52911247Sradhika.jagtap@ARM.com    depTraceRevItr until_itr(depTrace.begin());
53011247Sradhika.jagtap@ARM.com    TraceInfo* past_record = *from_itr;
53111247Sradhika.jagtap@ARM.com    uint32_t num_go_back = 0;
53211247Sradhika.jagtap@ARM.com
53311247Sradhika.jagtap@ARM.com    // The execution time of this store is when it is sent, that is committed
53411247Sradhika.jagtap@ARM.com    Tick execute_tick = curTick();
53511247Sradhika.jagtap@ARM.com    // Search for store-after-load or store-after-store order dependency
53611247Sradhika.jagtap@ARM.com    while (num_go_back < depWindowSize && from_itr != until_itr) {
53711247Sradhika.jagtap@ARM.com        if (find_load_not_store) {
53811247Sradhika.jagtap@ARM.com            // Check if previous inst is a load completed earlier by comparing
53911247Sradhika.jagtap@ARM.com            // with execute tick
54011247Sradhika.jagtap@ARM.com            if (hasLoadCompleted(past_record, execute_tick)) {
54111247Sradhika.jagtap@ARM.com                // Assign rob dependency and calculate the computational delay
54211247Sradhika.jagtap@ARM.com                assignRobDep(past_record, new_record);
54311247Sradhika.jagtap@ARM.com                ++numOrderDepStores;
54411247Sradhika.jagtap@ARM.com                return;
54511247Sradhika.jagtap@ARM.com            }
54611247Sradhika.jagtap@ARM.com        } else {
54711247Sradhika.jagtap@ARM.com            // Check if previous inst is a store sent earlier by comparing with
54811247Sradhika.jagtap@ARM.com            // execute tick
54911247Sradhika.jagtap@ARM.com            if (hasStoreCommitted(past_record, execute_tick)) {
55011247Sradhika.jagtap@ARM.com                // Assign rob dependency and calculate the computational delay
55111247Sradhika.jagtap@ARM.com                assignRobDep(past_record, new_record);
55211247Sradhika.jagtap@ARM.com                ++numOrderDepStores;
55311247Sradhika.jagtap@ARM.com                return;
55411247Sradhika.jagtap@ARM.com            }
55511247Sradhika.jagtap@ARM.com        }
55611247Sradhika.jagtap@ARM.com        ++from_itr;
55711247Sradhika.jagtap@ARM.com        past_record = *from_itr;
55811247Sradhika.jagtap@ARM.com        ++num_go_back;
55911247Sradhika.jagtap@ARM.com    }
56011247Sradhika.jagtap@ARM.com}
56111247Sradhika.jagtap@ARM.com
56211247Sradhika.jagtap@ARM.comvoid
56311247Sradhika.jagtap@ARM.comElasticTrace::updateIssueOrderDep(TraceInfo* new_record)
56411247Sradhika.jagtap@ARM.com{
56511247Sradhika.jagtap@ARM.com    // Interate in reverse direction to search for the last committed
56611247Sradhika.jagtap@ARM.com    // record that completed earlier than the new record
56711247Sradhika.jagtap@ARM.com    depTraceRevItr from_itr(depTrace.end());
56811247Sradhika.jagtap@ARM.com    depTraceRevItr until_itr(depTrace.begin());
56911247Sradhika.jagtap@ARM.com    TraceInfo* past_record = *from_itr;
57011247Sradhika.jagtap@ARM.com
57111247Sradhika.jagtap@ARM.com    uint32_t num_go_back = 0;
57211247Sradhika.jagtap@ARM.com    Tick execute_tick = 0;
57311247Sradhika.jagtap@ARM.com
57411252Sradhika.jagtap@ARM.com    if (new_record->isLoad()) {
57511247Sradhika.jagtap@ARM.com        // The execution time of a load is when a request is sent
57611247Sradhika.jagtap@ARM.com        execute_tick = new_record->executeTick;
57711247Sradhika.jagtap@ARM.com        ++numIssueOrderDepLoads;
57811252Sradhika.jagtap@ARM.com    } else if (new_record->isStore()) {
57911247Sradhika.jagtap@ARM.com        // The execution time of a store is when it is sent, i.e. committed
58011247Sradhika.jagtap@ARM.com        execute_tick = curTick();
58111247Sradhika.jagtap@ARM.com        ++numIssueOrderDepStores;
58211247Sradhika.jagtap@ARM.com    } else {
58311247Sradhika.jagtap@ARM.com        // The execution time of a non load/store is when it completes
58411247Sradhika.jagtap@ARM.com        execute_tick = new_record->toCommitTick;
58511247Sradhika.jagtap@ARM.com        ++numIssueOrderDepOther;
58611247Sradhika.jagtap@ARM.com    }
58711247Sradhika.jagtap@ARM.com
58811247Sradhika.jagtap@ARM.com    // We search if this record has an issue order dependency on a past record.
58911247Sradhika.jagtap@ARM.com    // Once we find it, we update both the new record and the record it depends
59011247Sradhika.jagtap@ARM.com    // on and return.
59111247Sradhika.jagtap@ARM.com    while (num_go_back < depWindowSize && from_itr != until_itr) {
59211247Sradhika.jagtap@ARM.com        // Check if a previous inst is a load sent earlier, or a store sent
59311247Sradhika.jagtap@ARM.com        // earlier, or a comp inst completed earlier by comparing with execute
59411247Sradhika.jagtap@ARM.com        // tick
59511247Sradhika.jagtap@ARM.com        if (hasLoadBeenSent(past_record, execute_tick) ||
59611247Sradhika.jagtap@ARM.com            hasStoreCommitted(past_record, execute_tick) ||
59711247Sradhika.jagtap@ARM.com            hasCompCompleted(past_record, execute_tick)) {
59811247Sradhika.jagtap@ARM.com            // Assign rob dependency and calculate the computational delay
59911247Sradhika.jagtap@ARM.com            assignRobDep(past_record, new_record);
60011247Sradhika.jagtap@ARM.com            return;
60111247Sradhika.jagtap@ARM.com        }
60211247Sradhika.jagtap@ARM.com        ++from_itr;
60311247Sradhika.jagtap@ARM.com        past_record = *from_itr;
60411247Sradhika.jagtap@ARM.com        ++num_go_back;
60511247Sradhika.jagtap@ARM.com    }
60611247Sradhika.jagtap@ARM.com}
60711247Sradhika.jagtap@ARM.com
60811247Sradhika.jagtap@ARM.comvoid
60911247Sradhika.jagtap@ARM.comElasticTrace::assignRobDep(TraceInfo* past_record, TraceInfo* new_record) {
61011247Sradhika.jagtap@ARM.com    DPRINTF(ElasticTrace, "%s %lli has ROB dependency on %lli\n",
61111252Sradhika.jagtap@ARM.com            new_record->typeToStr(), new_record->instNum,
61211252Sradhika.jagtap@ARM.com            past_record->instNum);
61311247Sradhika.jagtap@ARM.com    // Add dependency on past record
61411247Sradhika.jagtap@ARM.com    new_record->robDepList.push_back(past_record->instNum);
61511247Sradhika.jagtap@ARM.com    // Update new_record's compute delay with respect to the past record
61611247Sradhika.jagtap@ARM.com    compDelayRob(past_record, new_record);
61711247Sradhika.jagtap@ARM.com    // Increment number of dependents of the past record
61811247Sradhika.jagtap@ARM.com    ++(past_record->numDepts);
61911247Sradhika.jagtap@ARM.com    // Update stat to log max number of dependents
62011247Sradhika.jagtap@ARM.com    maxNumDependents = std::max(past_record->numDepts,
62111247Sradhika.jagtap@ARM.com                                (uint32_t)maxNumDependents.value());
62211247Sradhika.jagtap@ARM.com}
62311247Sradhika.jagtap@ARM.com
62411247Sradhika.jagtap@ARM.combool
62511247Sradhika.jagtap@ARM.comElasticTrace::hasStoreCommitted(TraceInfo* past_record,
62611247Sradhika.jagtap@ARM.com                                    Tick execute_tick) const
62711247Sradhika.jagtap@ARM.com{
62811252Sradhika.jagtap@ARM.com    return (past_record->isStore() && past_record->commitTick <= execute_tick);
62911247Sradhika.jagtap@ARM.com}
63011247Sradhika.jagtap@ARM.com
63111247Sradhika.jagtap@ARM.combool
63211247Sradhika.jagtap@ARM.comElasticTrace::hasLoadCompleted(TraceInfo* past_record,
63311247Sradhika.jagtap@ARM.com                                    Tick execute_tick) const
63411247Sradhika.jagtap@ARM.com{
63511252Sradhika.jagtap@ARM.com    return(past_record->isLoad() && past_record->commit &&
63611247Sradhika.jagtap@ARM.com                past_record->toCommitTick <= execute_tick);
63711247Sradhika.jagtap@ARM.com}
63811247Sradhika.jagtap@ARM.com
63911247Sradhika.jagtap@ARM.combool
64011247Sradhika.jagtap@ARM.comElasticTrace::hasLoadBeenSent(TraceInfo* past_record,
64111247Sradhika.jagtap@ARM.com                                Tick execute_tick) const
64211247Sradhika.jagtap@ARM.com{
64311247Sradhika.jagtap@ARM.com    // Check if previous inst is a load sent earlier than this
64411252Sradhika.jagtap@ARM.com    return (past_record->isLoad() && past_record->commit &&
64511247Sradhika.jagtap@ARM.com        past_record->executeTick <= execute_tick);
64611247Sradhika.jagtap@ARM.com}
64711247Sradhika.jagtap@ARM.com
64811247Sradhika.jagtap@ARM.combool
64911247Sradhika.jagtap@ARM.comElasticTrace::hasCompCompleted(TraceInfo* past_record,
65011247Sradhika.jagtap@ARM.com                                    Tick execute_tick) const
65111247Sradhika.jagtap@ARM.com{
65211252Sradhika.jagtap@ARM.com    return(past_record->isComp() && past_record->toCommitTick <= execute_tick);
65311247Sradhika.jagtap@ARM.com}
65411247Sradhika.jagtap@ARM.com
65511247Sradhika.jagtap@ARM.comvoid
65613429Srekai.gonzalezalberquilla@arm.comElasticTrace::clearTempStoreUntil(const DynInstConstPtr& head_inst)
65711247Sradhika.jagtap@ARM.com{
65811247Sradhika.jagtap@ARM.com    // Clear from temp store starting with the execution info object
65911247Sradhika.jagtap@ARM.com    // corresponding the head_inst and continue clearing by decrementing the
66011247Sradhika.jagtap@ARM.com    // sequence number until the last cleared sequence number.
66111247Sradhika.jagtap@ARM.com    InstSeqNum temp_sn = (head_inst->seqNum);
66211247Sradhika.jagtap@ARM.com    while (temp_sn > lastClearedSeqNum) {
66311247Sradhika.jagtap@ARM.com        auto itr_exec_info = tempStore.find(temp_sn);
66411247Sradhika.jagtap@ARM.com        if (itr_exec_info != tempStore.end()) {
66511247Sradhika.jagtap@ARM.com            InstExecInfo* exec_info_ptr = itr_exec_info->second;
66611247Sradhika.jagtap@ARM.com            // Free allocated memory for the info object
66711247Sradhika.jagtap@ARM.com            delete exec_info_ptr;
66811247Sradhika.jagtap@ARM.com            // Remove entry from temporary store
66911247Sradhika.jagtap@ARM.com            tempStore.erase(itr_exec_info);
67011247Sradhika.jagtap@ARM.com        }
67111247Sradhika.jagtap@ARM.com        temp_sn--;
67211247Sradhika.jagtap@ARM.com    }
67311247Sradhika.jagtap@ARM.com    // Update the last cleared sequence number to that of the head_inst
67411247Sradhika.jagtap@ARM.com    lastClearedSeqNum = head_inst->seqNum;
67511247Sradhika.jagtap@ARM.com}
67611247Sradhika.jagtap@ARM.com
67711247Sradhika.jagtap@ARM.comvoid
67811247Sradhika.jagtap@ARM.comElasticTrace::compDelayRob(TraceInfo* past_record, TraceInfo* new_record)
67911247Sradhika.jagtap@ARM.com{
68011247Sradhika.jagtap@ARM.com    // The computation delay is the delay between the completion tick of the
68111247Sradhika.jagtap@ARM.com    // inst. pointed to by past_record and the execution tick of its dependent
68211247Sradhika.jagtap@ARM.com    // inst. pointed to by new_record.
68311247Sradhika.jagtap@ARM.com    int64_t comp_delay = -1;
68411247Sradhika.jagtap@ARM.com    Tick execution_tick = 0, completion_tick = 0;
68511247Sradhika.jagtap@ARM.com
68611247Sradhika.jagtap@ARM.com    DPRINTF(ElasticTrace, "Seq num %lli has ROB dependency on seq num %lli.\n",
68711247Sradhika.jagtap@ARM.com            new_record->instNum, past_record->instNum);
68811247Sradhika.jagtap@ARM.com
68911247Sradhika.jagtap@ARM.com    // Get the tick when the node is executed as per the modelling of
69011247Sradhika.jagtap@ARM.com    // computation delay
69111247Sradhika.jagtap@ARM.com    execution_tick = new_record->getExecuteTick();
69211247Sradhika.jagtap@ARM.com
69311252Sradhika.jagtap@ARM.com    if (past_record->isLoad()) {
69411252Sradhika.jagtap@ARM.com        if (new_record->isStore()) {
69511247Sradhika.jagtap@ARM.com            completion_tick = past_record->toCommitTick;
69611247Sradhika.jagtap@ARM.com        } else {
69711247Sradhika.jagtap@ARM.com            completion_tick = past_record->executeTick;
69811247Sradhika.jagtap@ARM.com        }
69911252Sradhika.jagtap@ARM.com    } else if (past_record->isStore()) {
70011247Sradhika.jagtap@ARM.com        completion_tick = past_record->commitTick;
70111252Sradhika.jagtap@ARM.com    } else if (past_record->isComp()){
70211247Sradhika.jagtap@ARM.com        completion_tick = past_record->toCommitTick;
70311247Sradhika.jagtap@ARM.com    }
70411247Sradhika.jagtap@ARM.com    assert(execution_tick >= completion_tick);
70511247Sradhika.jagtap@ARM.com    comp_delay = execution_tick - completion_tick;
70611247Sradhika.jagtap@ARM.com
70711247Sradhika.jagtap@ARM.com    DPRINTF(ElasticTrace, "Computational delay is %lli - %lli = %lli\n",
70811247Sradhika.jagtap@ARM.com            execution_tick, completion_tick, comp_delay);
70911247Sradhika.jagtap@ARM.com
71011247Sradhika.jagtap@ARM.com    // Assign the computational delay with respect to the dependency which
71111247Sradhika.jagtap@ARM.com    // completes the latest.
71211247Sradhika.jagtap@ARM.com    if (new_record->compDelay == -1)
71311247Sradhika.jagtap@ARM.com        new_record->compDelay = comp_delay;
71411247Sradhika.jagtap@ARM.com    else
71511247Sradhika.jagtap@ARM.com        new_record->compDelay = std::min(comp_delay, new_record->compDelay);
71611247Sradhika.jagtap@ARM.com    DPRINTF(ElasticTrace, "Final computational delay = %lli.\n",
71711247Sradhika.jagtap@ARM.com            new_record->compDelay);
71811247Sradhika.jagtap@ARM.com}
71911247Sradhika.jagtap@ARM.com
72011247Sradhika.jagtap@ARM.comvoid
72111247Sradhika.jagtap@ARM.comElasticTrace::compDelayPhysRegDep(TraceInfo* past_record,
72211247Sradhika.jagtap@ARM.com                                    TraceInfo* new_record)
72311247Sradhika.jagtap@ARM.com{
72411247Sradhika.jagtap@ARM.com    // The computation delay is the delay between the completion tick of the
72511247Sradhika.jagtap@ARM.com    // inst. pointed to by past_record and the execution tick of its dependent
72611247Sradhika.jagtap@ARM.com    // inst. pointed to by new_record.
72711247Sradhika.jagtap@ARM.com    int64_t comp_delay = -1;
72811247Sradhika.jagtap@ARM.com    Tick execution_tick = 0, completion_tick = 0;
72911247Sradhika.jagtap@ARM.com
73011247Sradhika.jagtap@ARM.com    DPRINTF(ElasticTrace, "Seq. num %lli has register dependency on seq. num"
73111247Sradhika.jagtap@ARM.com            " %lli.\n", new_record->instNum, past_record->instNum);
73211247Sradhika.jagtap@ARM.com
73311247Sradhika.jagtap@ARM.com    // Get the tick when the node is executed as per the modelling of
73411247Sradhika.jagtap@ARM.com    // computation delay
73511247Sradhika.jagtap@ARM.com    execution_tick = new_record->getExecuteTick();
73611247Sradhika.jagtap@ARM.com
73711247Sradhika.jagtap@ARM.com    // When there is a physical register dependency on an instruction, the
73811247Sradhika.jagtap@ARM.com    // completion tick of that instruction is when it wrote to the register,
73911247Sradhika.jagtap@ARM.com    // that is toCommitTick. In case, of a store updating a destination
74011247Sradhika.jagtap@ARM.com    // register, this is approximated to commitTick instead
74111252Sradhika.jagtap@ARM.com    if (past_record->isStore()) {
74211247Sradhika.jagtap@ARM.com        completion_tick = past_record->commitTick;
74311247Sradhika.jagtap@ARM.com    } else {
74411247Sradhika.jagtap@ARM.com        completion_tick = past_record->toCommitTick;
74511247Sradhika.jagtap@ARM.com    }
74611247Sradhika.jagtap@ARM.com    assert(execution_tick >= completion_tick);
74711247Sradhika.jagtap@ARM.com    comp_delay = execution_tick - completion_tick;
74811247Sradhika.jagtap@ARM.com    DPRINTF(ElasticTrace, "Computational delay is %lli - %lli = %lli\n",
74911247Sradhika.jagtap@ARM.com            execution_tick, completion_tick, comp_delay);
75011247Sradhika.jagtap@ARM.com
75111247Sradhika.jagtap@ARM.com    // Assign the computational delay with respect to the dependency which
75211247Sradhika.jagtap@ARM.com    // completes the latest.
75311247Sradhika.jagtap@ARM.com    if (new_record->compDelay == -1)
75411247Sradhika.jagtap@ARM.com        new_record->compDelay = comp_delay;
75511247Sradhika.jagtap@ARM.com    else
75611247Sradhika.jagtap@ARM.com        new_record->compDelay = std::min(comp_delay, new_record->compDelay);
75711247Sradhika.jagtap@ARM.com    DPRINTF(ElasticTrace, "Final computational delay = %lli.\n",
75811247Sradhika.jagtap@ARM.com            new_record->compDelay);
75911247Sradhika.jagtap@ARM.com}
76011247Sradhika.jagtap@ARM.com
76111247Sradhika.jagtap@ARM.comTick
76211247Sradhika.jagtap@ARM.comElasticTrace::TraceInfo::getExecuteTick() const
76311247Sradhika.jagtap@ARM.com{
76411252Sradhika.jagtap@ARM.com    if (isLoad()) {
76511247Sradhika.jagtap@ARM.com        // Execution tick for a load instruction is when the request was sent,
76611247Sradhika.jagtap@ARM.com        // that is executeTick.
76711247Sradhika.jagtap@ARM.com        return executeTick;
76811252Sradhika.jagtap@ARM.com    } else if (isStore()) {
76911247Sradhika.jagtap@ARM.com        // Execution tick for a store instruction is when the request was sent,
77011247Sradhika.jagtap@ARM.com        // that is commitTick.
77111247Sradhika.jagtap@ARM.com        return commitTick;
77211247Sradhika.jagtap@ARM.com    } else {
77311247Sradhika.jagtap@ARM.com        // Execution tick for a non load/store instruction is when the register
77411247Sradhika.jagtap@ARM.com        // value was written to, that is commitTick.
77511247Sradhika.jagtap@ARM.com        return toCommitTick;
77611247Sradhika.jagtap@ARM.com    }
77711247Sradhika.jagtap@ARM.com}
77811247Sradhika.jagtap@ARM.com
77911247Sradhika.jagtap@ARM.comvoid
78011247Sradhika.jagtap@ARM.comElasticTrace::writeDepTrace(uint32_t num_to_write)
78111247Sradhika.jagtap@ARM.com{
78211247Sradhika.jagtap@ARM.com    // Write the trace with fields as follows:
78311247Sradhika.jagtap@ARM.com    // Instruction sequence number
78411247Sradhika.jagtap@ARM.com    // If instruction was a load
78511247Sradhika.jagtap@ARM.com    // If instruction was a store
78611247Sradhika.jagtap@ARM.com    // If instruction has addr
78711247Sradhika.jagtap@ARM.com    // If instruction has size
78811247Sradhika.jagtap@ARM.com    // If instruction has flags
78911247Sradhika.jagtap@ARM.com    // List of order dependencies - optional, repeated
79011247Sradhika.jagtap@ARM.com    // Computational delay with respect to last completed dependency
79111247Sradhika.jagtap@ARM.com    // List of physical register RAW dependencies - optional, repeated
79211247Sradhika.jagtap@ARM.com    // Weight of a node equal to no. of filtered nodes before it - optional
79311247Sradhika.jagtap@ARM.com    uint16_t num_filtered_nodes = 0;
79411247Sradhika.jagtap@ARM.com    depTraceItr dep_trace_itr(depTrace.begin());
79511247Sradhika.jagtap@ARM.com    depTraceItr dep_trace_itr_start = dep_trace_itr;
79611247Sradhika.jagtap@ARM.com    while (num_to_write > 0) {
79711247Sradhika.jagtap@ARM.com        TraceInfo* temp_ptr = *dep_trace_itr;
79811252Sradhika.jagtap@ARM.com        assert(temp_ptr->type != Record::INVALID);
79911252Sradhika.jagtap@ARM.com        // If no node dependends on a comp node then there is no reason to
80011252Sradhika.jagtap@ARM.com        // track the comp node in the dependency graph. We filter out such
80111247Sradhika.jagtap@ARM.com        // nodes but count them and add a weight field to the subsequent node
80211247Sradhika.jagtap@ARM.com        // that we do include in the trace.
80311252Sradhika.jagtap@ARM.com        if (!temp_ptr->isComp() || temp_ptr->numDepts != 0) {
80411247Sradhika.jagtap@ARM.com            DPRINTFR(ElasticTrace, "Instruction with seq. num %lli "
80511247Sradhika.jagtap@ARM.com                     "is as follows:\n", temp_ptr->instNum);
80611252Sradhika.jagtap@ARM.com            if (temp_ptr->isLoad() || temp_ptr->isStore()) {
80711252Sradhika.jagtap@ARM.com                DPRINTFR(ElasticTrace, "\tis a %s\n", temp_ptr->typeToStr());
80811253Sradhika.jagtap@ARM.com                DPRINTFR(ElasticTrace, "\thas a request with phys addr %i, "
80911253Sradhika.jagtap@ARM.com                         "size %i, flags %i\n", temp_ptr->physAddr,
81011253Sradhika.jagtap@ARM.com                         temp_ptr->size, temp_ptr->reqFlags);
81111247Sradhika.jagtap@ARM.com            } else {
81211252Sradhika.jagtap@ARM.com                 DPRINTFR(ElasticTrace, "\tis a %s\n", temp_ptr->typeToStr());
81311247Sradhika.jagtap@ARM.com            }
81411247Sradhika.jagtap@ARM.com            if (firstWin && temp_ptr->compDelay == -1) {
81511252Sradhika.jagtap@ARM.com                if (temp_ptr->isLoad()) {
81611247Sradhika.jagtap@ARM.com                    temp_ptr->compDelay = temp_ptr->executeTick;
81711252Sradhika.jagtap@ARM.com                } else if (temp_ptr->isStore()) {
81811247Sradhika.jagtap@ARM.com                    temp_ptr->compDelay = temp_ptr->commitTick;
81911247Sradhika.jagtap@ARM.com                } else {
82011247Sradhika.jagtap@ARM.com                    temp_ptr->compDelay = temp_ptr->toCommitTick;
82111247Sradhika.jagtap@ARM.com                }
82211247Sradhika.jagtap@ARM.com            }
82311247Sradhika.jagtap@ARM.com            assert(temp_ptr->compDelay != -1);
82411247Sradhika.jagtap@ARM.com            DPRINTFR(ElasticTrace, "\thas computational delay %lli\n",
82511247Sradhika.jagtap@ARM.com                     temp_ptr->compDelay);
82611247Sradhika.jagtap@ARM.com
82711247Sradhika.jagtap@ARM.com            // Create a protobuf message for the dependency record
82811247Sradhika.jagtap@ARM.com            ProtoMessage::InstDepRecord dep_pkt;
82911247Sradhika.jagtap@ARM.com            dep_pkt.set_seq_num(temp_ptr->instNum);
83011252Sradhika.jagtap@ARM.com            dep_pkt.set_type(temp_ptr->type);
83111247Sradhika.jagtap@ARM.com            dep_pkt.set_pc(temp_ptr->pc);
83211252Sradhika.jagtap@ARM.com            if (temp_ptr->isLoad() || temp_ptr->isStore()) {
83311247Sradhika.jagtap@ARM.com                dep_pkt.set_flags(temp_ptr->reqFlags);
83411253Sradhika.jagtap@ARM.com                dep_pkt.set_p_addr(temp_ptr->physAddr);
83511253Sradhika.jagtap@ARM.com                // If tracing of virtual addresses is enabled, set the optional
83611253Sradhika.jagtap@ARM.com                // field for it
83711253Sradhika.jagtap@ARM.com                if (traceVirtAddr) {
83811253Sradhika.jagtap@ARM.com                    dep_pkt.set_v_addr(temp_ptr->virtAddr);
83911253Sradhika.jagtap@ARM.com                    dep_pkt.set_asid(temp_ptr->asid);
84011253Sradhika.jagtap@ARM.com                }
84111247Sradhika.jagtap@ARM.com                dep_pkt.set_size(temp_ptr->size);
84211247Sradhika.jagtap@ARM.com            }
84311247Sradhika.jagtap@ARM.com            dep_pkt.set_comp_delay(temp_ptr->compDelay);
84411247Sradhika.jagtap@ARM.com            if (temp_ptr->robDepList.empty()) {
84511247Sradhika.jagtap@ARM.com                DPRINTFR(ElasticTrace, "\thas no order (rob) dependencies\n");
84611247Sradhika.jagtap@ARM.com            }
84711247Sradhika.jagtap@ARM.com            while (!temp_ptr->robDepList.empty()) {
84811247Sradhika.jagtap@ARM.com                DPRINTFR(ElasticTrace, "\thas order (rob) dependency on %lli\n",
84911247Sradhika.jagtap@ARM.com                         temp_ptr->robDepList.front());
85011247Sradhika.jagtap@ARM.com                dep_pkt.add_rob_dep(temp_ptr->robDepList.front());
85111247Sradhika.jagtap@ARM.com                temp_ptr->robDepList.pop_front();
85211247Sradhika.jagtap@ARM.com            }
85311247Sradhika.jagtap@ARM.com            if (temp_ptr->physRegDepList.empty()) {
85411247Sradhika.jagtap@ARM.com                DPRINTFR(ElasticTrace, "\thas no register dependencies\n");
85511247Sradhika.jagtap@ARM.com            }
85611247Sradhika.jagtap@ARM.com            while (!temp_ptr->physRegDepList.empty()) {
85711247Sradhika.jagtap@ARM.com                DPRINTFR(ElasticTrace, "\thas register dependency on %lli\n",
85811247Sradhika.jagtap@ARM.com                         temp_ptr->physRegDepList.front());
85911247Sradhika.jagtap@ARM.com                dep_pkt.add_reg_dep(temp_ptr->physRegDepList.front());
86011247Sradhika.jagtap@ARM.com                temp_ptr->physRegDepList.pop_front();
86111247Sradhika.jagtap@ARM.com            }
86211247Sradhika.jagtap@ARM.com            if (num_filtered_nodes != 0) {
86311247Sradhika.jagtap@ARM.com                // Set the weight of this node as the no. of filtered nodes
86411247Sradhika.jagtap@ARM.com                // between this node and the last node that we wrote to output
86511247Sradhika.jagtap@ARM.com                // stream. The weight will be used during replay to model ROB
86611247Sradhika.jagtap@ARM.com                // occupancy of filtered nodes.
86711247Sradhika.jagtap@ARM.com                dep_pkt.set_weight(num_filtered_nodes);
86811247Sradhika.jagtap@ARM.com                num_filtered_nodes = 0;
86911247Sradhika.jagtap@ARM.com            }
87011247Sradhika.jagtap@ARM.com            // Write the message to the protobuf output stream
87111247Sradhika.jagtap@ARM.com            dataTraceStream->write(dep_pkt);
87211247Sradhika.jagtap@ARM.com        } else {
87311247Sradhika.jagtap@ARM.com            // Don't write the node to the trace but note that we have filtered
87411247Sradhika.jagtap@ARM.com            // out a node.
87511247Sradhika.jagtap@ARM.com            ++numFilteredNodes;
87611247Sradhika.jagtap@ARM.com            ++num_filtered_nodes;
87711247Sradhika.jagtap@ARM.com        }
87811247Sradhika.jagtap@ARM.com        dep_trace_itr++;
87911247Sradhika.jagtap@ARM.com        traceInfoMap.erase(temp_ptr->instNum);
88011247Sradhika.jagtap@ARM.com        delete temp_ptr;
88111247Sradhika.jagtap@ARM.com        num_to_write--;
88211247Sradhika.jagtap@ARM.com    }
88311247Sradhika.jagtap@ARM.com    depTrace.erase(dep_trace_itr_start, dep_trace_itr);
88411247Sradhika.jagtap@ARM.com}
88511247Sradhika.jagtap@ARM.com
88611247Sradhika.jagtap@ARM.comvoid
88711247Sradhika.jagtap@ARM.comElasticTrace::regStats() {
88811523Sdavid.guillen@arm.com    ProbeListenerObject::regStats();
88911523Sdavid.guillen@arm.com
89011247Sradhika.jagtap@ARM.com    using namespace Stats;
89111247Sradhika.jagtap@ARM.com    numRegDep
89211247Sradhika.jagtap@ARM.com        .name(name() + ".numRegDep")
89311247Sradhika.jagtap@ARM.com        .desc("Number of register dependencies recorded during tracing")
89411247Sradhika.jagtap@ARM.com        ;
89511247Sradhika.jagtap@ARM.com
89611247Sradhika.jagtap@ARM.com    numOrderDepStores
89711247Sradhika.jagtap@ARM.com        .name(name() + ".numOrderDepStores")
89811247Sradhika.jagtap@ARM.com        .desc("Number of commit order (rob) dependencies for a store recorded"
89911247Sradhika.jagtap@ARM.com              " on a past load/store during tracing")
90011247Sradhika.jagtap@ARM.com        ;
90111247Sradhika.jagtap@ARM.com
90211247Sradhika.jagtap@ARM.com    numIssueOrderDepLoads
90311247Sradhika.jagtap@ARM.com        .name(name() + ".numIssueOrderDepLoads")
90411247Sradhika.jagtap@ARM.com        .desc("Number of loads that got assigned issue order dependency"
90511247Sradhika.jagtap@ARM.com              " because they were dependency-free")
90611247Sradhika.jagtap@ARM.com        ;
90711247Sradhika.jagtap@ARM.com
90811247Sradhika.jagtap@ARM.com    numIssueOrderDepStores
90911247Sradhika.jagtap@ARM.com        .name(name() + ".numIssueOrderDepStores")
91011247Sradhika.jagtap@ARM.com        .desc("Number of stores that got assigned issue order dependency"
91111247Sradhika.jagtap@ARM.com              " because they were dependency-free")
91211247Sradhika.jagtap@ARM.com        ;
91311247Sradhika.jagtap@ARM.com
91411247Sradhika.jagtap@ARM.com    numIssueOrderDepOther
91511247Sradhika.jagtap@ARM.com        .name(name() + ".numIssueOrderDepOther")
91611247Sradhika.jagtap@ARM.com        .desc("Number of non load/store insts that got assigned issue order"
91711247Sradhika.jagtap@ARM.com              " dependency because they were dependency-free")
91811247Sradhika.jagtap@ARM.com        ;
91911247Sradhika.jagtap@ARM.com
92011247Sradhika.jagtap@ARM.com    numFilteredNodes
92111247Sradhika.jagtap@ARM.com        .name(name() + ".numFilteredNodes")
92211247Sradhika.jagtap@ARM.com        .desc("No. of nodes filtered out before writing the output trace")
92311247Sradhika.jagtap@ARM.com        ;
92411247Sradhika.jagtap@ARM.com
92511247Sradhika.jagtap@ARM.com    maxNumDependents
92611247Sradhika.jagtap@ARM.com        .name(name() + ".maxNumDependents")
92711247Sradhika.jagtap@ARM.com        .desc("Maximum number or dependents on any instruction")
92811247Sradhika.jagtap@ARM.com        ;
92911247Sradhika.jagtap@ARM.com
93011247Sradhika.jagtap@ARM.com    maxTempStoreSize
93111247Sradhika.jagtap@ARM.com        .name(name() + ".maxTempStoreSize")
93211247Sradhika.jagtap@ARM.com        .desc("Maximum size of the temporary store during the run")
93311247Sradhika.jagtap@ARM.com        ;
93411247Sradhika.jagtap@ARM.com
93511247Sradhika.jagtap@ARM.com    maxPhysRegDepMapSize
93611247Sradhika.jagtap@ARM.com        .name(name() + ".maxPhysRegDepMapSize")
93711247Sradhika.jagtap@ARM.com        .desc("Maximum size of register dependency map")
93811247Sradhika.jagtap@ARM.com        ;
93911247Sradhika.jagtap@ARM.com}
94011247Sradhika.jagtap@ARM.com
94111252Sradhika.jagtap@ARM.comconst std::string&
94211252Sradhika.jagtap@ARM.comElasticTrace::TraceInfo::typeToStr() const
94311252Sradhika.jagtap@ARM.com{
94411252Sradhika.jagtap@ARM.com    return Record::RecordType_Name(type);
94511252Sradhika.jagtap@ARM.com}
94611252Sradhika.jagtap@ARM.com
94711247Sradhika.jagtap@ARM.comconst std::string
94811247Sradhika.jagtap@ARM.comElasticTrace::name() const
94911247Sradhika.jagtap@ARM.com{
95011247Sradhika.jagtap@ARM.com    return ProbeListenerObject::name();
95111247Sradhika.jagtap@ARM.com}
95211247Sradhika.jagtap@ARM.com
95311247Sradhika.jagtap@ARM.comvoid
95411247Sradhika.jagtap@ARM.comElasticTrace::flushTraces()
95511247Sradhika.jagtap@ARM.com{
95611247Sradhika.jagtap@ARM.com    // Write to trace all records in the depTrace.
95711247Sradhika.jagtap@ARM.com    writeDepTrace(depTrace.size());
95811247Sradhika.jagtap@ARM.com    // Delete the stream objects
95911247Sradhika.jagtap@ARM.com    delete dataTraceStream;
96011247Sradhika.jagtap@ARM.com    delete instTraceStream;
96111247Sradhika.jagtap@ARM.com}
96211247Sradhika.jagtap@ARM.com
96311247Sradhika.jagtap@ARM.comElasticTrace*
96411247Sradhika.jagtap@ARM.comElasticTraceParams::create()
96511247Sradhika.jagtap@ARM.com{
96611247Sradhika.jagtap@ARM.com    return new ElasticTrace(this);
96711247Sradhika.jagtap@ARM.com}
968