/*
 * 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/core.hh"
#include "sim/cur_tick.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
