/*
 * Copyright (c) 2012-2013, 2015, 2018-2019 ARM Limited
 * Copyright (c) 2016 Google Inc.
 * Copyright (c) 2017, Centre National de la Recherche Scientifique
 * 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.
 */

#include "mem/comm_monitor.hh"

#include "base/trace.hh"
#include "debug/CommMonitor.hh"
#include "sim/stats.hh"

CommMonitor::CommMonitor(const Params &params)
    : SimObject(params),
      memSidePort(name() + "-mem_side_port", *this),
      cpuSidePort(name() + "-cpu_side_port", *this),
      samplePeriodicEvent([this]{ samplePeriodic(); }, name()),
      samplePeriodTicks(params.sample_period),
      samplePeriod(params.sample_period / SimClock::Float::s),
      stats(this, params)
{
    DPRINTF(CommMonitor,
            "Created monitor %s with sample period %d ticks (%f ms)\n",
            name(), samplePeriodTicks, samplePeriod * 1E3);
}

void
CommMonitor::init()
{
    // make sure both sides of the monitor are connected
    if (!cpuSidePort.isConnected() || !memSidePort.isConnected())
        fatal("Communication monitor is not connected on both sides.\n");
}

void
CommMonitor::regProbePoints()
{
    ppPktReq.reset(new ProbePoints::Packet(getProbeManager(), "PktRequest"));
    ppPktResp.reset(new ProbePoints::Packet(getProbeManager(), "PktResponse"));
}

Port &
CommMonitor::getPort(const std::string &if_name, PortID idx)
{
    if (if_name == "mem_side_port") {
        return memSidePort;
    } else if (if_name == "cpu_side_port") {
        return cpuSidePort;
    } else {
        return SimObject::getPort(if_name, idx);
    }
}

void
CommMonitor::recvFunctional(PacketPtr pkt)
{
    memSidePort.sendFunctional(pkt);
}

void
CommMonitor::recvFunctionalSnoop(PacketPtr pkt)
{
    cpuSidePort.sendFunctionalSnoop(pkt);
}

CommMonitor::MonitorStats::MonitorStats(Stats::Group *parent,
                                        const CommMonitorParams &params)
    : Stats::Group(parent),

      disableBurstLengthHists(params.disable_burst_length_hists),
      ADD_STAT(readBurstLengthHist, UNIT_BYTE,
               "Histogram of burst lengths of transmitted packets"),
      ADD_STAT(writeBurstLengthHist, UNIT_BYTE,
               "Histogram of burst lengths of transmitted packets"),

      disableBandwidthHists(params.disable_bandwidth_hists),
      readBytes(0),
      ADD_STAT(readBandwidthHist,
               UNIT_RATE(Stats::Units::Byte, Stats::Units::Second),
               "Histogram of read bandwidth per sample period"),
      ADD_STAT(totalReadBytes, UNIT_BYTE, "Number of bytes read"),
      ADD_STAT(averageReadBandwidth,
               UNIT_RATE(Stats::Units::Byte, Stats::Units::Second),
               "Average read bandwidth",
               totalReadBytes / simSeconds),

      writtenBytes(0),
      ADD_STAT(writeBandwidthHist,
               UNIT_RATE(Stats::Units::Byte, Stats::Units::Second),
               "Histogram of write bandwidth"),
      ADD_STAT(totalWrittenBytes,
               UNIT_RATE(Stats::Units::Byte, Stats::Units::Second),
               "Number of bytes written"),
      ADD_STAT(averageWriteBandwidth,
               UNIT_RATE(Stats::Units::Byte, Stats::Units::Second),
               "Average write bandwidth",
               totalWrittenBytes / simSeconds),

      disableLatencyHists(params.disable_latency_hists),
      ADD_STAT(readLatencyHist, UNIT_TICK, "Read request-response latency"),
      ADD_STAT(writeLatencyHist, UNIT_TICK, "Write request-response latency"),

      disableITTDists(params.disable_itt_dists),
      ADD_STAT(ittReadRead, UNIT_TICK, "Read-to-read inter transaction time"),
      ADD_STAT(ittWriteWrite, UNIT_TICK,
               "Write-to-write inter transaction time"),
      ADD_STAT(ittReqReq, UNIT_TICK,
               "Request-to-request inter transaction time"),
      timeOfLastRead(0), timeOfLastWrite(0), timeOfLastReq(0),

      disableOutstandingHists(params.disable_outstanding_hists),
      ADD_STAT(outstandingReadsHist, UNIT_COUNT,
               "Outstanding read transactions"),
      outstandingReadReqs(0),
      ADD_STAT(outstandingWritesHist, UNIT_COUNT,
               "Outstanding write transactions"),
      outstandingWriteReqs(0),

      disableTransactionHists(params.disable_transaction_hists),
      ADD_STAT(readTransHist, UNIT_COUNT,
               "Histogram of read transactions per sample period"),
      readTrans(0),
      ADD_STAT(writeTransHist, UNIT_COUNT,
               "Histogram of write transactions per sample period"),
      writeTrans(0),

      disableAddrDists(params.disable_addr_dists),
      readAddrMask(params.read_addr_mask),
      writeAddrMask(params.write_addr_mask),
      ADD_STAT(readAddrDist, UNIT_COUNT, "Read address distribution"),
      ADD_STAT(writeAddrDist, UNIT_COUNT, "Write address distribution")
{
    using namespace Stats;

    readBurstLengthHist
        .init(params.burst_length_bins)
        .flags(disableBurstLengthHists ? nozero : pdf);

    writeBurstLengthHist
        .init(params.burst_length_bins)
        .flags(disableBurstLengthHists ? nozero : pdf);

    // Stats based on received responses
    readBandwidthHist
        .init(params.bandwidth_bins)
        .flags(disableBandwidthHists ? nozero : pdf);

    averageReadBandwidth
        .flags(disableBandwidthHists ? nozero : pdf);

    totalReadBytes
        .flags(disableBandwidthHists ? nozero : pdf);

    // Stats based on successfully sent requests
    writeBandwidthHist
        .init(params.bandwidth_bins)
        .flags(disableBandwidthHists ? (pdf | nozero) : pdf);

    averageWriteBandwidth
        .flags(disableBandwidthHists ? nozero : pdf);

    totalWrittenBytes
        .flags(disableBandwidthHists ? nozero : pdf);


    readLatencyHist
        .init(params.latency_bins)
        .flags(disableLatencyHists ? nozero : pdf);

    writeLatencyHist
        .init(params.latency_bins)
        .flags(disableLatencyHists ? nozero : pdf);

    ittReadRead
        .init(1, params.itt_max_bin, params.itt_max_bin /
              params.itt_bins)
        .flags(disableITTDists ? nozero : pdf);

    ittWriteWrite
        .init(1, params.itt_max_bin, params.itt_max_bin /
              params.itt_bins)
        .flags(disableITTDists ? nozero : pdf);

    ittReqReq
        .init(1, params.itt_max_bin, params.itt_max_bin /
              params.itt_bins)
        .flags(disableITTDists ? nozero : pdf);

    outstandingReadsHist
        .init(params.outstanding_bins)
        .flags(disableOutstandingHists ? nozero : pdf);

    outstandingWritesHist
        .init(params.outstanding_bins)
        .flags(disableOutstandingHists ? nozero : pdf);

    readTransHist
        .init(params.transaction_bins)
        .flags(disableTransactionHists ? nozero : pdf);

    writeTransHist
        .init(params.transaction_bins)
        .flags(disableTransactionHists ? nozero : pdf);

    readAddrDist
        .init(0)
        .flags(disableAddrDists ? nozero : pdf);

    writeAddrDist
        .init(0)
        .flags(disableAddrDists ? nozero : pdf);
}

void
CommMonitor::MonitorStats::updateReqStats(
    const ProbePoints::PacketInfo& pkt_info, bool is_atomic,
    bool expects_response)
{
    if (pkt_info.cmd.isRead()) {
        // Increment number of observed read transactions
        if (!disableTransactionHists)
            ++readTrans;

        // Get sample of burst length
        if (!disableBurstLengthHists)
            readBurstLengthHist.sample(pkt_info.size);

        // Sample the masked address
        if (!disableAddrDists)
            readAddrDist.sample(pkt_info.addr & readAddrMask);

        if (!disableITTDists) {
            // Sample value of read-read inter transaction time
            if (timeOfLastRead != 0)
                ittReadRead.sample(curTick() - timeOfLastRead);
            timeOfLastRead = curTick();

            // Sample value of req-req inter transaction time
            if (timeOfLastReq != 0)
                ittReqReq.sample(curTick() - timeOfLastReq);
            timeOfLastReq = curTick();
        }
        if (!is_atomic && !disableOutstandingHists && expects_response)
            ++outstandingReadReqs;

    } else if (pkt_info.cmd.isWrite()) {
        // Same as for reads
        if (!disableTransactionHists)
            ++writeTrans;

        if (!disableBurstLengthHists)
            writeBurstLengthHist.sample(pkt_info.size);

        // Update the bandwidth stats on the request
        if (!disableBandwidthHists) {
            writtenBytes += pkt_info.size;
            totalWrittenBytes += pkt_info.size;
        }

        // Sample the masked write address
        if (!disableAddrDists)
            writeAddrDist.sample(pkt_info.addr & writeAddrMask);

        if (!disableITTDists) {
            // Sample value of write-to-write inter transaction time
            if (timeOfLastWrite != 0)
                ittWriteWrite.sample(curTick() - timeOfLastWrite);
            timeOfLastWrite = curTick();

            // Sample value of req-to-req inter transaction time
            if (timeOfLastReq != 0)
                ittReqReq.sample(curTick() - timeOfLastReq);
            timeOfLastReq = curTick();
        }

        if (!is_atomic && !disableOutstandingHists && expects_response)
            ++outstandingWriteReqs;
    }
}

void
CommMonitor::MonitorStats::updateRespStats(
    const ProbePoints::PacketInfo& pkt_info, Tick latency, bool is_atomic)
{
    if (pkt_info.cmd.isRead()) {
        // Decrement number of outstanding read requests
        if (!is_atomic && !disableOutstandingHists) {
            assert(outstandingReadReqs != 0);
            --outstandingReadReqs;
        }

        if (!disableLatencyHists)
            readLatencyHist.sample(latency);

        // Update the bandwidth stats based on responses for reads
        if (!disableBandwidthHists) {
            readBytes += pkt_info.size;
            totalReadBytes += pkt_info.size;
        }

    } else if (pkt_info.cmd.isWrite()) {
        // Decrement number of outstanding write requests
        if (!is_atomic && !disableOutstandingHists) {
            assert(outstandingWriteReqs != 0);
            --outstandingWriteReqs;
        }

        if (!disableLatencyHists)
            writeLatencyHist.sample(latency);
    }
}

Tick
CommMonitor::recvAtomic(PacketPtr pkt)
{
    const bool expects_response(pkt->needsResponse() &&
                                !pkt->cacheResponding());
    ProbePoints::PacketInfo req_pkt_info(pkt);
    ppPktReq->notify(req_pkt_info);

    const Tick delay(memSidePort.sendAtomic(pkt));

    stats.updateReqStats(req_pkt_info, true, expects_response);
    if (expects_response)
        stats.updateRespStats(req_pkt_info, delay, true);

    // Some packets, such as WritebackDirty, don't need response.
    assert(pkt->isResponse() || !expects_response);
    ProbePoints::PacketInfo resp_pkt_info(pkt);
    ppPktResp->notify(resp_pkt_info);
    return delay;
}

Tick
CommMonitor::recvAtomicSnoop(PacketPtr pkt)
{
    return cpuSidePort.sendAtomicSnoop(pkt);
}

bool
CommMonitor::recvTimingReq(PacketPtr pkt)
{
    // should always see a request
    assert(pkt->isRequest());

    // Store relevant fields of packet, because packet may be modified
    // or even deleted when sendTiming() is called.
    const ProbePoints::PacketInfo pkt_info(pkt);

    const bool expects_response(pkt->needsResponse() &&
                                !pkt->cacheResponding());

    // If a cache miss is served by a cache, a monitor near the memory
    // would see a request which needs a response, but this response
    // would not come back from the memory. Therefore we additionally
    // have to check the cacheResponding flag
    if (expects_response && !stats.disableLatencyHists) {
        pkt->pushSenderState(new CommMonitorSenderState(curTick()));
    }

    // Attempt to send the packet
    bool successful = memSidePort.sendTimingReq(pkt);

    // If not successful, restore the sender state
    if (!successful && expects_response && !stats.disableLatencyHists) {
        delete pkt->popSenderState();
    }

    if (successful) {
        ppPktReq->notify(pkt_info);
    }

    if (successful) {
        DPRINTF(CommMonitor, "Forwarded %s request\n", pkt->isRead() ? "read" :
                pkt->isWrite() ? "write" : "non read/write");
        stats.updateReqStats(pkt_info, false, expects_response);
    }
    return successful;
}

bool
CommMonitor::recvTimingResp(PacketPtr pkt)
{
    // should always see responses
    assert(pkt->isResponse());

    // Store relevant fields of packet, because packet may be modified
    // or even deleted when sendTiming() is called.
    const ProbePoints::PacketInfo pkt_info(pkt);

    Tick latency = 0;
    CommMonitorSenderState* received_state =
        dynamic_cast<CommMonitorSenderState*>(pkt->senderState);

    if (!stats.disableLatencyHists) {
        // Restore initial sender state
        if (received_state == NULL)
            panic("Monitor got a response without monitor sender state\n");

        // Restore the sate
        pkt->senderState = received_state->predecessor;
    }

    // Attempt to send the packet
    bool successful = cpuSidePort.sendTimingResp(pkt);

    if (!stats.disableLatencyHists) {
        // If packet successfully send, sample value of latency,
        // afterwards delete sender state, otherwise restore state
        if (successful) {
            latency = curTick() - received_state->transmitTime;
            DPRINTF(CommMonitor, "Latency: %d\n", latency);
            delete received_state;
        } else {
            // Don't delete anything and let the packet look like we
            // did not touch it
            pkt->senderState = received_state;
        }
    }

    if (successful) {
        ppPktResp->notify(pkt_info);
        DPRINTF(CommMonitor, "Received %s response\n", pkt->isRead() ? "read" :
                pkt->isWrite() ?  "write" : "non read/write");
        stats.updateRespStats(pkt_info, latency, false);
    }
    return successful;
}

void
CommMonitor::recvTimingSnoopReq(PacketPtr pkt)
{
    cpuSidePort.sendTimingSnoopReq(pkt);
}

bool
CommMonitor::recvTimingSnoopResp(PacketPtr pkt)
{
    return memSidePort.sendTimingSnoopResp(pkt);
}

void
CommMonitor::recvRetrySnoopResp()
{
    cpuSidePort.sendRetrySnoopResp();
}

bool
CommMonitor::isSnooping() const
{
    // check if the connected request port is snooping
    return cpuSidePort.isSnooping();
}

AddrRangeList
CommMonitor::getAddrRanges() const
{
    // get the address ranges of the connected CPU-side port
    return memSidePort.getAddrRanges();
}

void
CommMonitor::recvReqRetry()
{
    cpuSidePort.sendRetryReq();
}

void
CommMonitor::recvRespRetry()
{
    memSidePort.sendRetryResp();
}

bool
CommMonitor::tryTiming(PacketPtr pkt)
{
    return memSidePort.tryTiming(pkt);
}

void
CommMonitor::recvRangeChange()
{
    cpuSidePort.sendRangeChange();
}

void
CommMonitor::samplePeriodic()
{
    // the periodic stats update runs on the granularity of sample
    // periods, but in combination with this there may also be a
    // external resets and dumps of the stats (through schedStatEvent)
    // causing the stats themselves to capture less than a sample
    // period

    // only capture if we have not reset the stats during the last
    // sample period
    if (simTicks.value() >= samplePeriodTicks) {
        if (!stats.disableTransactionHists) {
            stats.readTransHist.sample(stats.readTrans);
            stats.writeTransHist.sample(stats.writeTrans);
        }

        if (!stats.disableBandwidthHists) {
            stats.readBandwidthHist.sample(stats.readBytes / samplePeriod);
            stats.writeBandwidthHist.sample(stats.writtenBytes / samplePeriod);
        }

        if (!stats.disableOutstandingHists) {
            stats.outstandingReadsHist.sample(stats.outstandingReadReqs);
            stats.outstandingWritesHist.sample(stats.outstandingWriteReqs);
        }
    }

    // reset the sampled values
    stats.readTrans = 0;
    stats.writeTrans = 0;

    stats.readBytes = 0;
    stats.writtenBytes = 0;

    schedule(samplePeriodicEvent, curTick() + samplePeriodTicks);
}

void
CommMonitor::startup()
{
    schedule(samplePeriodicEvent, curTick() + samplePeriodTicks);
}
