/*
 * Copyright (c) 2013 - 2015 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Radhika Jagtap
 *          Andreas Hansson
 *          Thomas Grass
 */

#include "cpu/o3/probe/elastic_trace.hh"

#include "base/callback.hh"
#include "base/output.hh"
#include "base/trace.hh"
#include "cpu/reg_class.hh"
#include "debug/ElasticTrace.hh"
#include "mem/packet.hh"

ElasticTrace::ElasticTrace(const ElasticTraceParams* params)
    :  ProbeListenerObject(params),
       regEtraceListenersEvent([this]{ regEtraceListeners(); }, name()),
       firstWin(true),
       lastClearedSeqNum(0),
       depWindowSize(params->depWindowSize),
       dataTraceStream(nullptr),
       instTraceStream(nullptr),
       startTraceInst(params->startTraceInst),
       allProbesReg(false),
       traceVirtAddr(params->traceVirtAddr)
{
    cpu = dynamic_cast<FullO3CPU<O3CPUImpl>*>(params->manager);
    fatal_if(!cpu, "Manager of %s is not of type O3CPU and thus does not "\
                "support dependency tracing.\n", name());

    fatal_if(depWindowSize == 0, "depWindowSize parameter must be non-zero. "\
                "Recommended size is 3x ROB size in the O3CPU.\n");

    fatal_if(cpu->numThreads > 1, "numThreads = %i, %s supports tracing for"\
                "single-threaded workload only", cpu->numThreads, name());
    // Initialize the protobuf output stream
    fatal_if(params->instFetchTraceFile == "", "Assign instruction fetch "\
                "trace file path to instFetchTraceFile");
    fatal_if(params->dataDepTraceFile == "", "Assign data dependency "\
                "trace file path to dataDepTraceFile");
    std::string filename = simout.resolve(name() + "." +
                                            params->instFetchTraceFile);
    instTraceStream = new ProtoOutputStream(filename);
    filename = simout.resolve(name() + "." + params->dataDepTraceFile);
    dataTraceStream = new ProtoOutputStream(filename);
    // Create a protobuf message for the header and write it to the stream
    ProtoMessage::PacketHeader inst_pkt_header;
    inst_pkt_header.set_obj_id(name());
    inst_pkt_header.set_tick_freq(SimClock::Frequency);
    instTraceStream->write(inst_pkt_header);
    // Create a protobuf message for the header and write it to
    // the stream
    ProtoMessage::InstDepRecordHeader data_rec_header;
    data_rec_header.set_obj_id(name());
    data_rec_header.set_tick_freq(SimClock::Frequency);
    data_rec_header.set_window_size(depWindowSize);
    dataTraceStream->write(data_rec_header);
    // Register a callback to flush trace records and close the output streams.
    Callback* cb = new MakeCallback<ElasticTrace,
        &ElasticTrace::flushTraces>(this);
    registerExitCallback(cb);
}

void
ElasticTrace::regProbeListeners()
{
    inform("@%llu: regProbeListeners() called, startTraceInst = %llu",
        curTick(), startTraceInst);
    if (startTraceInst == 0) {
        // If we want to start tracing from the start of the simulation,
        // register all elastic trace probes now.
        regEtraceListeners();
    } else {
        // Schedule an event to register all elastic trace probes when
        // specified no. of instructions are committed.
        cpu->comInstEventQueue[(ThreadID)0]->schedule(&regEtraceListenersEvent,
                                                      startTraceInst);
    }
}

void
ElasticTrace::regEtraceListeners()
{
    assert(!allProbesReg);
    inform("@%llu: No. of instructions committed = %llu, registering elastic"
        " probe listeners", curTick(), cpu->numSimulatedInsts());
    // Create new listeners: provide method to be called upon a notify() for
    // each probe point.
    listeners.push_back(new ProbeListenerArg<ElasticTrace, RequestPtr>(this,
                        "FetchRequest", &ElasticTrace::fetchReqTrace));
    listeners.push_back(new ProbeListenerArg<ElasticTrace,
            DynInstConstPtr>(this, "Execute",
                &ElasticTrace::recordExecTick));
    listeners.push_back(new ProbeListenerArg<ElasticTrace,
            DynInstConstPtr>(this, "ToCommit",
                &ElasticTrace::recordToCommTick));
    listeners.push_back(new ProbeListenerArg<ElasticTrace,
            DynInstConstPtr>(this, "Rename",
                &ElasticTrace::updateRegDep));
    listeners.push_back(new ProbeListenerArg<ElasticTrace, SeqNumRegPair>(this,
                        "SquashInRename", &ElasticTrace::removeRegDepMapEntry));
    listeners.push_back(new ProbeListenerArg<ElasticTrace,
            DynInstConstPtr>(this, "Squash",
                &ElasticTrace::addSquashedInst));
    listeners.push_back(new ProbeListenerArg<ElasticTrace,
            DynInstConstPtr>(this, "Commit",
                &ElasticTrace::addCommittedInst));
    allProbesReg = true;
}

void
ElasticTrace::fetchReqTrace(const RequestPtr &req)
{

    DPRINTFR(ElasticTrace, "Fetch Req %i,(%lli,%lli,%lli),%i,%i,%lli\n",
             (MemCmd::ReadReq),
             req->getPC(), req->getVaddr(), req->getPaddr(),
             req->getFlags(), req->getSize(), curTick());

    // Create a protobuf message including the request fields necessary to
    // recreate the request in the TraceCPU.
    ProtoMessage::Packet inst_fetch_pkt;
    inst_fetch_pkt.set_tick(curTick());
    inst_fetch_pkt.set_cmd(MemCmd::ReadReq);
    inst_fetch_pkt.set_pc(req->getPC());
    inst_fetch_pkt.set_flags(req->getFlags());
    inst_fetch_pkt.set_addr(req->getPaddr());
    inst_fetch_pkt.set_size(req->getSize());
    // Write the message to the stream.
    instTraceStream->write(inst_fetch_pkt);
}

void
ElasticTrace::recordExecTick(const DynInstConstPtr& dyn_inst)
{

    // In a corner case, a retired instruction is propagated backward to the
    // IEW instruction queue to handle some side-channel information. But we
    // must not process an instruction again. So we test the sequence number
    // against the lastClearedSeqNum and skip adding the instruction for such
    // corner cases.
    if (dyn_inst->seqNum <= lastClearedSeqNum) {
        DPRINTFR(ElasticTrace, "[sn:%lli] Ignoring in execute as instruction \
        has already retired (mostly squashed)", dyn_inst->seqNum);
        // Do nothing as program has proceeded and this inst has been
        // propagated backwards to handle something.
        return;
    }

    DPRINTFR(ElasticTrace, "[sn:%lli] Execute Tick = %i\n", dyn_inst->seqNum,
                curTick());
    // Either the execution info object will already exist if this
    // instruction had a register dependency recorded in the rename probe
    // listener before entering execute stage or it will not exist and will
    // need to be created here.
    InstExecInfo* exec_info_ptr;
    auto itr_exec_info = tempStore.find(dyn_inst->seqNum);
    if (itr_exec_info != tempStore.end()) {
        exec_info_ptr = itr_exec_info->second;
    } else {
        exec_info_ptr = new InstExecInfo;
        tempStore[dyn_inst->seqNum] = exec_info_ptr;
    }

    exec_info_ptr->executeTick = curTick();
    maxTempStoreSize = std::max(tempStore.size(),
                                (std::size_t)maxTempStoreSize.value());
}

void
ElasticTrace::recordToCommTick(const DynInstConstPtr& dyn_inst)
{
    // If tracing has just been enabled then the instruction at this stage of
    // execution is far enough that we cannot gather info about its past like
    // the tick it started execution. Simply return until we see an instruction
    // that is found in the tempStore.
    auto itr_exec_info = tempStore.find(dyn_inst->seqNum);
    if (itr_exec_info == tempStore.end()) {
        DPRINTFR(ElasticTrace, "recordToCommTick: [sn:%lli] Not in temp store,"
                    " skipping.\n", dyn_inst->seqNum);
        return;
    }

    DPRINTFR(ElasticTrace, "[sn:%lli] To Commit Tick = %i\n", dyn_inst->seqNum,
                curTick());
    InstExecInfo* exec_info_ptr = itr_exec_info->second;
    exec_info_ptr->toCommitTick = curTick();

}

void
ElasticTrace::updateRegDep(const DynInstConstPtr& dyn_inst)
{
    // Get the sequence number of the instruction
    InstSeqNum seq_num = dyn_inst->seqNum;

    assert(dyn_inst->seqNum > lastClearedSeqNum);

    // Since this is the first probe activated in the pipeline, create
    // a new execution info object to track this instruction as it
    // progresses through the pipeline.
    InstExecInfo* exec_info_ptr = new InstExecInfo;
    tempStore[seq_num] = exec_info_ptr;

    // Loop through the source registers and look up the dependency map. If
    // the source register entry is found in the dependency map, add a
    // dependency on the last writer.
    int8_t max_regs = dyn_inst->numSrcRegs();
    for (int src_idx = 0; src_idx < max_regs; src_idx++) {

        const RegId& src_reg = dyn_inst->srcRegIdx(src_idx);
        if (!src_reg.isMiscReg() &&
            !src_reg.isZeroReg()) {
            // Get the physical register index of the i'th source register.
            PhysRegIdPtr phys_src_reg = dyn_inst->renamedSrcRegIdx(src_idx);
            DPRINTFR(ElasticTrace, "[sn:%lli] Check map for src reg"
                     " %i (%s)\n", seq_num,
                     phys_src_reg->flatIndex(), phys_src_reg->className());
            auto itr_writer = physRegDepMap.find(phys_src_reg->flatIndex());
            if (itr_writer != physRegDepMap.end()) {
                InstSeqNum last_writer = itr_writer->second;
                // Additionally the dependency distance is kept less than the
                // window size parameter to limit the memory allocation to
                // nodes in the graph. If the window were tending to infinite
                // we would have to load a large number of node objects during
                // replay.
                if (seq_num - last_writer < depWindowSize) {
                    // Record a physical register dependency.
                    exec_info_ptr->physRegDepSet.insert(last_writer);
                }
            }

        }

    }

    // Loop through the destination registers of this instruction and update
    // the physical register dependency map for last writers to registers.
    max_regs = dyn_inst->numDestRegs();
    for (int dest_idx = 0; dest_idx < max_regs; dest_idx++) {
        // For data dependency tracking the register must be an int, float or
        // CC register and not a Misc register.
        const RegId& dest_reg = dyn_inst->destRegIdx(dest_idx);
        if (!dest_reg.isMiscReg() &&
            !dest_reg.isZeroReg()) {
            // Get the physical register index of the i'th destination
            // register.
            PhysRegIdPtr phys_dest_reg = dyn_inst->renamedDestRegIdx(dest_idx);
            DPRINTFR(ElasticTrace, "[sn:%lli] Update map for dest reg"
                     " %i (%s)\n", seq_num, phys_dest_reg->flatIndex(),
                     dest_reg.className());
            physRegDepMap[phys_dest_reg->flatIndex()] = seq_num;
        }
    }
    maxPhysRegDepMapSize = std::max(physRegDepMap.size(),
                                    (std::size_t)maxPhysRegDepMapSize.value());
}

void
ElasticTrace::removeRegDepMapEntry(const SeqNumRegPair &inst_reg_pair)
{
    DPRINTFR(ElasticTrace, "Remove Map entry for Reg %i\n",
            inst_reg_pair.second);
    auto itr_regdep_map = physRegDepMap.find(inst_reg_pair.second);
    if (itr_regdep_map != physRegDepMap.end())
        physRegDepMap.erase(itr_regdep_map);
}

void
ElasticTrace::addSquashedInst(const DynInstConstPtr& head_inst)
{
    // If the squashed instruction was squashed before being processed by
    // execute stage then it will not be in the temporary store. In this case
    // do nothing and return.
    auto itr_exec_info = tempStore.find(head_inst->seqNum);
    if (itr_exec_info == tempStore.end())
        return;

    // If there is a squashed load for which a read request was
    // sent before it got squashed then add it to the trace.
    DPRINTFR(ElasticTrace, "Attempt to add squashed inst [sn:%lli]\n",
                head_inst->seqNum);
    // Get pointer to the execution info object corresponding to the inst.
    InstExecInfo* exec_info_ptr = itr_exec_info->second;
    if (head_inst->isLoad() && exec_info_ptr->executeTick != MaxTick &&
        exec_info_ptr->toCommitTick != MaxTick &&
        head_inst->hasRequest() &&
        head_inst->getFault() == NoFault) {
        // Add record to depTrace with commit parameter as false.
        addDepTraceRecord(head_inst, exec_info_ptr, false);
    }
    // As the information contained is no longer needed, remove the execution
    // info object from the temporary store.
    clearTempStoreUntil(head_inst);
}

void
ElasticTrace::addCommittedInst(const DynInstConstPtr& head_inst)
{
    DPRINTFR(ElasticTrace, "Attempt to add committed inst [sn:%lli]\n",
                head_inst->seqNum);

    // Add the instruction to the depTrace.
    if (!head_inst->isNop()) {

        // If tracing has just been enabled then the instruction at this stage
        // of execution is far enough that we cannot gather info about its past
        // like the tick it started execution. Simply return until we see an
        // instruction that is found in the tempStore.
        auto itr_temp_store = tempStore.find(head_inst->seqNum);
        if (itr_temp_store == tempStore.end()) {
            DPRINTFR(ElasticTrace, "addCommittedInst: [sn:%lli] Not in temp "
                "store, skipping.\n", head_inst->seqNum);
            return;
        }

        // Get pointer to the execution info object corresponding to the inst.
        InstExecInfo* exec_info_ptr = itr_temp_store->second;
        assert(exec_info_ptr->executeTick != MaxTick);
        assert(exec_info_ptr->toCommitTick != MaxTick);

        // Check if the instruction had a fault, if it predicated false and
        // thus previous register values were restored or if it was a
        // load/store that did not have a request (e.g. when the size of the
        // request is zero). In all these cases the instruction is set as
        // executed and is picked up by the commit probe listener. But a
        // request is not issued and registers are not written. So practically,
        // skipping these should not hurt as execution would not stall on them.
        // Alternatively, these could be included merely as a compute node in
        // the graph. Removing these for now. If correlation accuracy needs to
        // be improved in future these can be turned into comp nodes at the
        // cost of bigger traces.
        if (head_inst->getFault() != NoFault) {
            DPRINTF(ElasticTrace, "%s [sn:%lli] has faulted so "
                    "skip adding it to the trace\n",
                    (head_inst->isMemRef() ? "Load/store" : "Comp inst."),
                    head_inst->seqNum);
        } else if (head_inst->isMemRef() && !head_inst->hasRequest()) {
            DPRINTF(ElasticTrace, "Load/store [sn:%lli]  has no request so "
                    "skip adding it to the trace\n", head_inst->seqNum);
        } else if (!head_inst->readPredicate()) {
            DPRINTF(ElasticTrace, "%s [sn:%lli] is predicated false so "
                    "skip adding it to the trace\n",
                    (head_inst->isMemRef() ? "Load/store" : "Comp inst."),
                    head_inst->seqNum);
        } else {
            // Add record to depTrace with commit parameter as true.
            addDepTraceRecord(head_inst, exec_info_ptr, true);
        }
    }
    // As the information contained is no longer needed, remove the execution
    // info object from the temporary store.
    clearTempStoreUntil(head_inst);
}

void
ElasticTrace::addDepTraceRecord(const DynInstConstPtr& head_inst,
                                InstExecInfo* exec_info_ptr, bool commit)
{
    // Create a record to assign dynamic intruction related fields.
    TraceInfo* new_record = new TraceInfo;
    // Add to map for sequence number look up to retrieve the TraceInfo pointer
    traceInfoMap[head_inst->seqNum] = new_record;

    // Assign fields from the instruction
    new_record->instNum = head_inst->seqNum;
    new_record->commit = commit;
    new_record->type = head_inst->isLoad() ? Record::LOAD :
                        (head_inst->isStore() ? Record::STORE :
                        Record::COMP);

    // Assign fields for creating a request in case of a load/store
    new_record->reqFlags = head_inst->memReqFlags;
    new_record->virtAddr = head_inst->effAddr;
    new_record->asid = head_inst->asid;
    new_record->physAddr = head_inst->physEffAddrLow;
    // Currently the tracing does not support split requests.
    new_record->size = head_inst->effSize;
    new_record->pc = head_inst->instAddr();

    // Assign the timing information stored in the execution info object
    new_record->executeTick = exec_info_ptr->executeTick;
    new_record->toCommitTick = exec_info_ptr->toCommitTick;
    new_record->commitTick = curTick();

    // Assign initial values for number of dependents and computational delay
    new_record->numDepts = 0;
    new_record->compDelay = -1;

    // The physical register dependency set of the first instruction is
    // empty. Since there are no records in the depTrace at this point, the
    // case of adding an ROB dependency by using a reverse iterator is not
    // applicable. Thus, populate the fields of the record corresponding to the
    // first instruction and return.
    if (depTrace.empty()) {
        // Store the record in depTrace.
        depTrace.push_back(new_record);
        DPRINTF(ElasticTrace, "Added first inst record %lli to DepTrace.\n",
                new_record->instNum);
        return;
    }

    // Clear register dependencies for squashed loads as they may be dependent
    // on squashed instructions and we do not add those to the trace.
    if (head_inst->isLoad() && !commit) {
         (exec_info_ptr->physRegDepSet).clear();
    }

    // Assign the register dependencies stored in the execution info object
    std::set<InstSeqNum>::const_iterator dep_set_it;
    for (dep_set_it = (exec_info_ptr->physRegDepSet).begin();
         dep_set_it != (exec_info_ptr->physRegDepSet).end();
         ++dep_set_it) {
        auto trace_info_itr = traceInfoMap.find(*dep_set_it);
        if (trace_info_itr != traceInfoMap.end()) {
            // The register dependency is valid. Assign it and calculate
            // computational delay
            new_record->physRegDepList.push_back(*dep_set_it);
            DPRINTF(ElasticTrace, "Inst %lli has register dependency on "
                    "%lli\n", new_record->instNum, *dep_set_it);
            TraceInfo* reg_dep = trace_info_itr->second;
            reg_dep->numDepts++;
            compDelayPhysRegDep(reg_dep, new_record);
            ++numRegDep;
        } else {
            // The instruction that this has a register dependency on was
            // not added to the trace because of one of the following
            // 1. it was an instruction that had a fault
            // 2. it was an instruction that was predicated false and
            // previous register values were restored
            // 3. it was load/store that did not have a request (e.g. when
            // the size of the request is zero but this may not be a fault)
            // In all these cases the instruction is set as executed and is
            // picked up by the commit probe listener. But a request is not
            // issued and registers are not written to in these cases.
            DPRINTF(ElasticTrace, "Inst %lli has register dependency on "
                    "%lli is skipped\n",new_record->instNum, *dep_set_it);
        }
    }

    // Check for and assign an ROB dependency in addition to register
    // dependency before adding the record to the trace.
    // As stores have to commit in order a store is dependent on the last
    // committed load/store. This is recorded in the ROB dependency.
    if (head_inst->isStore()) {
        // Look up store-after-store order dependency
        updateCommitOrderDep(new_record, false);
        // Look up store-after-load order dependency
        updateCommitOrderDep(new_record, true);
    }

    // In case a node is dependency-free or its dependency got discarded
    // because it was outside the window, it is marked ready in the ROB at the
    // time of issue. A request is sent as soon as possible. To model this, a
    // node is assigned an issue order dependency on a committed instruction
    // that completed earlier than it. This is done to avoid the problem of
    // determining the issue times of such dependency-free nodes during replay
    // which could lead to too much parallelism, thinking conservatively.
    if (new_record->robDepList.empty() && new_record->physRegDepList.empty()) {
        updateIssueOrderDep(new_record);
    }

    // Store the record in depTrace.
    depTrace.push_back(new_record);
    DPRINTF(ElasticTrace, "Added %s inst %lli to DepTrace.\n",
            (commit ? "committed" : "squashed"), new_record->instNum);

    // To process the number of records specified by depWindowSize in the
    // forward direction, the depTrace must have twice as many records
    // to check for dependencies.
    if (depTrace.size() == 2 * depWindowSize) {

        DPRINTF(ElasticTrace, "Writing out trace...\n");

        // Write out the records which have been processed to the trace
        // and remove them from the depTrace.
        writeDepTrace(depWindowSize);

        // After the first window, writeDepTrace() must check for valid
        // compDelay.
        firstWin = false;
    }
}

void
ElasticTrace::updateCommitOrderDep(TraceInfo* new_record,
                                    bool find_load_not_store)
{
    assert(new_record->isStore());
    // Iterate in reverse direction to search for the last committed
    // load/store that completed earlier than the new record
    depTraceRevItr from_itr(depTrace.end());
    depTraceRevItr until_itr(depTrace.begin());
    TraceInfo* past_record = *from_itr;
    uint32_t num_go_back = 0;

    // The execution time of this store is when it is sent, that is committed
    Tick execute_tick = curTick();
    // Search for store-after-load or store-after-store order dependency
    while (num_go_back < depWindowSize && from_itr != until_itr) {
        if (find_load_not_store) {
            // Check if previous inst is a load completed earlier by comparing
            // with execute tick
            if (hasLoadCompleted(past_record, execute_tick)) {
                // Assign rob dependency and calculate the computational delay
                assignRobDep(past_record, new_record);
                ++numOrderDepStores;
                return;
            }
        } else {
            // Check if previous inst is a store sent earlier by comparing with
            // execute tick
            if (hasStoreCommitted(past_record, execute_tick)) {
                // Assign rob dependency and calculate the computational delay
                assignRobDep(past_record, new_record);
                ++numOrderDepStores;
                return;
            }
        }
        ++from_itr;
        past_record = *from_itr;
        ++num_go_back;
    }
}

void
ElasticTrace::updateIssueOrderDep(TraceInfo* new_record)
{
    // Interate in reverse direction to search for the last committed
    // record that completed earlier than the new record
    depTraceRevItr from_itr(depTrace.end());
    depTraceRevItr until_itr(depTrace.begin());
    TraceInfo* past_record = *from_itr;

    uint32_t num_go_back = 0;
    Tick execute_tick = 0;

    if (new_record->isLoad()) {
        // The execution time of a load is when a request is sent
        execute_tick = new_record->executeTick;
        ++numIssueOrderDepLoads;
    } else if (new_record->isStore()) {
        // The execution time of a store is when it is sent, i.e. committed
        execute_tick = curTick();
        ++numIssueOrderDepStores;
    } else {
        // The execution time of a non load/store is when it completes
        execute_tick = new_record->toCommitTick;
        ++numIssueOrderDepOther;
    }

    // We search if this record has an issue order dependency on a past record.
    // Once we find it, we update both the new record and the record it depends
    // on and return.
    while (num_go_back < depWindowSize && from_itr != until_itr) {
        // Check if a previous inst is a load sent earlier, or a store sent
        // earlier, or a comp inst completed earlier by comparing with execute
        // tick
        if (hasLoadBeenSent(past_record, execute_tick) ||
            hasStoreCommitted(past_record, execute_tick) ||
            hasCompCompleted(past_record, execute_tick)) {
            // Assign rob dependency and calculate the computational delay
            assignRobDep(past_record, new_record);
            return;
        }
        ++from_itr;
        past_record = *from_itr;
        ++num_go_back;
    }
}

void
ElasticTrace::assignRobDep(TraceInfo* past_record, TraceInfo* new_record) {
    DPRINTF(ElasticTrace, "%s %lli has ROB dependency on %lli\n",
            new_record->typeToStr(), new_record->instNum,
            past_record->instNum);
    // Add dependency on past record
    new_record->robDepList.push_back(past_record->instNum);
    // Update new_record's compute delay with respect to the past record
    compDelayRob(past_record, new_record);
    // Increment number of dependents of the past record
    ++(past_record->numDepts);
    // Update stat to log max number of dependents
    maxNumDependents = std::max(past_record->numDepts,
                                (uint32_t)maxNumDependents.value());
}

bool
ElasticTrace::hasStoreCommitted(TraceInfo* past_record,
                                    Tick execute_tick) const
{
    return (past_record->isStore() && past_record->commitTick <= execute_tick);
}

bool
ElasticTrace::hasLoadCompleted(TraceInfo* past_record,
                                    Tick execute_tick) const
{
    return(past_record->isLoad() && past_record->commit &&
                past_record->toCommitTick <= execute_tick);
}

bool
ElasticTrace::hasLoadBeenSent(TraceInfo* past_record,
                                Tick execute_tick) const
{
    // Check if previous inst is a load sent earlier than this
    return (past_record->isLoad() && past_record->commit &&
        past_record->executeTick <= execute_tick);
}

bool
ElasticTrace::hasCompCompleted(TraceInfo* past_record,
                                    Tick execute_tick) const
{
    return(past_record->isComp() && past_record->toCommitTick <= execute_tick);
}

void
ElasticTrace::clearTempStoreUntil(const DynInstConstPtr& head_inst)
{
    // Clear from temp store starting with the execution info object
    // corresponding the head_inst and continue clearing by decrementing the
    // sequence number until the last cleared sequence number.
    InstSeqNum temp_sn = (head_inst->seqNum);
    while (temp_sn > lastClearedSeqNum) {
        auto itr_exec_info = tempStore.find(temp_sn);
        if (itr_exec_info != tempStore.end()) {
            InstExecInfo* exec_info_ptr = itr_exec_info->second;
            // Free allocated memory for the info object
            delete exec_info_ptr;
            // Remove entry from temporary store
            tempStore.erase(itr_exec_info);
        }
        temp_sn--;
    }
    // Update the last cleared sequence number to that of the head_inst
    lastClearedSeqNum = head_inst->seqNum;
}

void
ElasticTrace::compDelayRob(TraceInfo* past_record, TraceInfo* new_record)
{
    // The computation delay is the delay between the completion tick of the
    // inst. pointed to by past_record and the execution tick of its dependent
    // inst. pointed to by new_record.
    int64_t comp_delay = -1;
    Tick execution_tick = 0, completion_tick = 0;

    DPRINTF(ElasticTrace, "Seq num %lli has ROB dependency on seq num %lli.\n",
            new_record->instNum, past_record->instNum);

    // Get the tick when the node is executed as per the modelling of
    // computation delay
    execution_tick = new_record->getExecuteTick();

    if (past_record->isLoad()) {
        if (new_record->isStore()) {
            completion_tick = past_record->toCommitTick;
        } else {
            completion_tick = past_record->executeTick;
        }
    } else if (past_record->isStore()) {
        completion_tick = past_record->commitTick;
    } else if (past_record->isComp()){
        completion_tick = past_record->toCommitTick;
    }
    assert(execution_tick >= completion_tick);
    comp_delay = execution_tick - completion_tick;

    DPRINTF(ElasticTrace, "Computational delay is %lli - %lli = %lli\n",
            execution_tick, completion_tick, comp_delay);

    // Assign the computational delay with respect to the dependency which
    // completes the latest.
    if (new_record->compDelay == -1)
        new_record->compDelay = comp_delay;
    else
        new_record->compDelay = std::min(comp_delay, new_record->compDelay);
    DPRINTF(ElasticTrace, "Final computational delay = %lli.\n",
            new_record->compDelay);
}

void
ElasticTrace::compDelayPhysRegDep(TraceInfo* past_record,
                                    TraceInfo* new_record)
{
    // The computation delay is the delay between the completion tick of the
    // inst. pointed to by past_record and the execution tick of its dependent
    // inst. pointed to by new_record.
    int64_t comp_delay = -1;
    Tick execution_tick = 0, completion_tick = 0;

    DPRINTF(ElasticTrace, "Seq. num %lli has register dependency on seq. num"
            " %lli.\n", new_record->instNum, past_record->instNum);

    // Get the tick when the node is executed as per the modelling of
    // computation delay
    execution_tick = new_record->getExecuteTick();

    // When there is a physical register dependency on an instruction, the
    // completion tick of that instruction is when it wrote to the register,
    // that is toCommitTick. In case, of a store updating a destination
    // register, this is approximated to commitTick instead
    if (past_record->isStore()) {
        completion_tick = past_record->commitTick;
    } else {
        completion_tick = past_record->toCommitTick;
    }
    assert(execution_tick >= completion_tick);
    comp_delay = execution_tick - completion_tick;
    DPRINTF(ElasticTrace, "Computational delay is %lli - %lli = %lli\n",
            execution_tick, completion_tick, comp_delay);

    // Assign the computational delay with respect to the dependency which
    // completes the latest.
    if (new_record->compDelay == -1)
        new_record->compDelay = comp_delay;
    else
        new_record->compDelay = std::min(comp_delay, new_record->compDelay);
    DPRINTF(ElasticTrace, "Final computational delay = %lli.\n",
            new_record->compDelay);
}

Tick
ElasticTrace::TraceInfo::getExecuteTick() const
{
    if (isLoad()) {
        // Execution tick for a load instruction is when the request was sent,
        // that is executeTick.
        return executeTick;
    } else if (isStore()) {
        // Execution tick for a store instruction is when the request was sent,
        // that is commitTick.
        return commitTick;
    } else {
        // Execution tick for a non load/store instruction is when the register
        // value was written to, that is commitTick.
        return toCommitTick;
    }
}

void
ElasticTrace::writeDepTrace(uint32_t num_to_write)
{
    // Write the trace with fields as follows:
    // Instruction sequence number
    // If instruction was a load
    // If instruction was a store
    // If instruction has addr
    // If instruction has size
    // If instruction has flags
    // List of order dependencies - optional, repeated
    // Computational delay with respect to last completed dependency
    // List of physical register RAW dependencies - optional, repeated
    // Weight of a node equal to no. of filtered nodes before it - optional
    uint16_t num_filtered_nodes = 0;
    depTraceItr dep_trace_itr(depTrace.begin());
    depTraceItr dep_trace_itr_start = dep_trace_itr;
    while (num_to_write > 0) {
        TraceInfo* temp_ptr = *dep_trace_itr;
        assert(temp_ptr->type != Record::INVALID);
        // If no node dependends on a comp node then there is no reason to
        // track the comp node in the dependency graph. We filter out such
        // nodes but count them and add a weight field to the subsequent node
        // that we do include in the trace.
        if (!temp_ptr->isComp() || temp_ptr->numDepts != 0) {
            DPRINTFR(ElasticTrace, "Instruction with seq. num %lli "
                     "is as follows:\n", temp_ptr->instNum);
            if (temp_ptr->isLoad() || temp_ptr->isStore()) {
                DPRINTFR(ElasticTrace, "\tis a %s\n", temp_ptr->typeToStr());
                DPRINTFR(ElasticTrace, "\thas a request with phys addr %i, "
                         "size %i, flags %i\n", temp_ptr->physAddr,
                         temp_ptr->size, temp_ptr->reqFlags);
            } else {
                 DPRINTFR(ElasticTrace, "\tis a %s\n", temp_ptr->typeToStr());
            }
            if (firstWin && temp_ptr->compDelay == -1) {
                if (temp_ptr->isLoad()) {
                    temp_ptr->compDelay = temp_ptr->executeTick;
                } else if (temp_ptr->isStore()) {
                    temp_ptr->compDelay = temp_ptr->commitTick;
                } else {
                    temp_ptr->compDelay = temp_ptr->toCommitTick;
                }
            }
            assert(temp_ptr->compDelay != -1);
            DPRINTFR(ElasticTrace, "\thas computational delay %lli\n",
                     temp_ptr->compDelay);

            // Create a protobuf message for the dependency record
            ProtoMessage::InstDepRecord dep_pkt;
            dep_pkt.set_seq_num(temp_ptr->instNum);
            dep_pkt.set_type(temp_ptr->type);
            dep_pkt.set_pc(temp_ptr->pc);
            if (temp_ptr->isLoad() || temp_ptr->isStore()) {
                dep_pkt.set_flags(temp_ptr->reqFlags);
                dep_pkt.set_p_addr(temp_ptr->physAddr);
                // If tracing of virtual addresses is enabled, set the optional
                // field for it
                if (traceVirtAddr) {
                    dep_pkt.set_v_addr(temp_ptr->virtAddr);
                    dep_pkt.set_asid(temp_ptr->asid);
                }
                dep_pkt.set_size(temp_ptr->size);
            }
            dep_pkt.set_comp_delay(temp_ptr->compDelay);
            if (temp_ptr->robDepList.empty()) {
                DPRINTFR(ElasticTrace, "\thas no order (rob) dependencies\n");
            }
            while (!temp_ptr->robDepList.empty()) {
                DPRINTFR(ElasticTrace, "\thas order (rob) dependency on %lli\n",
                         temp_ptr->robDepList.front());
                dep_pkt.add_rob_dep(temp_ptr->robDepList.front());
                temp_ptr->robDepList.pop_front();
            }
            if (temp_ptr->physRegDepList.empty()) {
                DPRINTFR(ElasticTrace, "\thas no register dependencies\n");
            }
            while (!temp_ptr->physRegDepList.empty()) {
                DPRINTFR(ElasticTrace, "\thas register dependency on %lli\n",
                         temp_ptr->physRegDepList.front());
                dep_pkt.add_reg_dep(temp_ptr->physRegDepList.front());
                temp_ptr->physRegDepList.pop_front();
            }
            if (num_filtered_nodes != 0) {
                // Set the weight of this node as the no. of filtered nodes
                // between this node and the last node that we wrote to output
                // stream. The weight will be used during replay to model ROB
                // occupancy of filtered nodes.
                dep_pkt.set_weight(num_filtered_nodes);
                num_filtered_nodes = 0;
            }
            // Write the message to the protobuf output stream
            dataTraceStream->write(dep_pkt);
        } else {
            // Don't write the node to the trace but note that we have filtered
            // out a node.
            ++numFilteredNodes;
            ++num_filtered_nodes;
        }
        dep_trace_itr++;
        traceInfoMap.erase(temp_ptr->instNum);
        delete temp_ptr;
        num_to_write--;
    }
    depTrace.erase(dep_trace_itr_start, dep_trace_itr);
}

void
ElasticTrace::regStats() {
    ProbeListenerObject::regStats();

    using namespace Stats;
    numRegDep
        .name(name() + ".numRegDep")
        .desc("Number of register dependencies recorded during tracing")
        ;

    numOrderDepStores
        .name(name() + ".numOrderDepStores")
        .desc("Number of commit order (rob) dependencies for a store recorded"
              " on a past load/store during tracing")
        ;

    numIssueOrderDepLoads
        .name(name() + ".numIssueOrderDepLoads")
        .desc("Number of loads that got assigned issue order dependency"
              " because they were dependency-free")
        ;

    numIssueOrderDepStores
        .name(name() + ".numIssueOrderDepStores")
        .desc("Number of stores that got assigned issue order dependency"
              " because they were dependency-free")
        ;

    numIssueOrderDepOther
        .name(name() + ".numIssueOrderDepOther")
        .desc("Number of non load/store insts that got assigned issue order"
              " dependency because they were dependency-free")
        ;

    numFilteredNodes
        .name(name() + ".numFilteredNodes")
        .desc("No. of nodes filtered out before writing the output trace")
        ;

    maxNumDependents
        .name(name() + ".maxNumDependents")
        .desc("Maximum number or dependents on any instruction")
        ;

    maxTempStoreSize
        .name(name() + ".maxTempStoreSize")
        .desc("Maximum size of the temporary store during the run")
        ;

    maxPhysRegDepMapSize
        .name(name() + ".maxPhysRegDepMapSize")
        .desc("Maximum size of register dependency map")
        ;
}

const std::string&
ElasticTrace::TraceInfo::typeToStr() const
{
    return Record::RecordType_Name(type);
}

const std::string
ElasticTrace::name() const
{
    return ProbeListenerObject::name();
}

void
ElasticTrace::flushTraces()
{
    // Write to trace all records in the depTrace.
    writeDepTrace(depTrace.size());
    // Delete the stream objects
    delete dataTraceStream;
    delete instTraceStream;
}

ElasticTrace*
ElasticTraceParams::create()
{
    return new ElasticTrace(this);
}
