/*
 * 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"

namespace gem5
{

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 / sim_clock::as_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 probing::Packet(getProbeManager(), "PktRequest"));
    ppPktResp.reset(new probing::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(statistics::Group *parent,
                                        const CommMonitorParams &params)
    : statistics::Group(parent),

      disableBurstLengthHists(params.disable_burst_length_hists),
      ADD_STAT(readBurstLengthHist, statistics::units::Byte::get(),
               "Histogram of burst lengths of transmitted packets"),
      ADD_STAT(writeBurstLengthHist, statistics::units::Byte::get(),
               "Histogram of burst lengths of transmitted packets"),

      disableBandwidthHists(params.disable_bandwidth_hists),
      readBytes(0),
      ADD_STAT(readBandwidthHist, statistics::units::Rate<
                    statistics::units::Byte, statistics::units::Second>::get(),
               "Histogram of read bandwidth per sample period"),
      ADD_STAT(totalReadBytes, statistics::units::Byte::get(),
               "Number of bytes read"),
      ADD_STAT(averageReadBandwidth, statistics::units::Rate<
                    statistics::units::Byte, statistics::units::Second>::get(),
               "Average read bandwidth",
               totalReadBytes / simSeconds),

      writtenBytes(0),
      ADD_STAT(writeBandwidthHist, statistics::units::Rate<
                    statistics::units::Byte, statistics::units::Second>::get(),
               "Histogram of write bandwidth"),
      ADD_STAT(totalWrittenBytes, statistics::units::Rate<
                    statistics::units::Byte, statistics::units::Second>::get(),
               "Number of bytes written"),
      ADD_STAT(averageWriteBandwidth, statistics::units::Rate<
                    statistics::units::Byte, statistics::units::Second>::get(),
               "Average write bandwidth",
               totalWrittenBytes / simSeconds),

      disableLatencyHists(params.disable_latency_hists),
      ADD_STAT(readLatencyHist, statistics::units::Tick::get(),
               "Read request-response latency"),
      ADD_STAT(writeLatencyHist, statistics::units::Tick::get(),
               "Write request-response latency"),

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

      disableOutstandingHists(params.disable_outstanding_hists),
      ADD_STAT(outstandingReadsHist, statistics::units::Count::get(),
               "Outstanding read transactions"),
      outstandingReadReqs(0),
      ADD_STAT(outstandingWritesHist, statistics::units::Count::get(),
               "Outstanding write transactions"),
      outstandingWriteReqs(0),

      disableTransactionHists(params.disable_transaction_hists),
      ADD_STAT(readTransHist, statistics::units::Count::get(),
               "Histogram of read transactions per sample period"),
      readTrans(0),
      ADD_STAT(writeTransHist, statistics::units::Count::get(),
               "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, statistics::units::Count::get(),
               "Read address distribution"),
      ADD_STAT(writeAddrDist, statistics::units::Count::get(),
               "Write address distribution")
{
    using namespace statistics;

    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 probing::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 probing::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());
    probing::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);
    probing::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 probing::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 probing::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);
}

} // namespace gem5
