blob: d27594d232f0f158dde263c0b2a0566892ebbf1d [file] [log] [blame]
/*
* Copyright (c) 2012-2013, 2015 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.
*
* Authors: Thomas Grass
* Andreas Hansson
* Rahul Thakur
* Pierre-Yves Peneau
*/
#ifndef __MEM_COMM_MONITOR_HH__
#define __MEM_COMM_MONITOR_HH__
#include "base/statistics.hh"
#include "mem/mem_object.hh"
#include "params/CommMonitor.hh"
#include "sim/probe/mem.hh"
/**
* The communication monitor is a MemObject which can monitor statistics of
* the communication happening between two ports in the memory system.
*
* Currently the following stats are implemented: Histograms of read/write
* transactions, read/write burst lengths, read/write bandwidth,
* outstanding read/write requests, read latency and inter transaction time
* (read-read, write-write, read/write-read/write). Furthermore it allows
* to capture the number of accesses to an address over time ("heat map").
* All stats can be disabled from Python.
*/
class CommMonitor : public MemObject
{
public: // Construction & SimObject interfaces
/** Parameters of communication monitor */
typedef CommMonitorParams Params;
const Params* params() const
{ return reinterpret_cast<const Params*>(_params); }
/**
* Constructor based on the Python params
*
* @param params Python parameters
*/
CommMonitor(Params* params);
void init() override;
void regStats() override;
void startup() override;
void regProbePoints() override;
public: // MemObject interfaces
BaseMasterPort& getMasterPort(const std::string& if_name,
PortID idx = InvalidPortID) override;
BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID) override;
private:
/**
* Sender state class for the monitor so that we can annotate
* packets with a transmit time and receive time.
*/
class CommMonitorSenderState : public Packet::SenderState
{
public:
/**
* Construct a new sender state and store the time so we can
* calculate round-trip latency.
*
* @param _transmitTime Time of packet transmission
*/
CommMonitorSenderState(Tick _transmitTime)
: transmitTime(_transmitTime)
{ }
/** Destructor */
~CommMonitorSenderState() { }
/** Tick when request is transmitted */
Tick transmitTime;
};
/**
* This is the master port of the communication monitor. All recv
* functions call a function in CommMonitor, where the
* send function of the slave port is called. Besides this, these
* functions can also perform actions for capturing statistics.
*/
class MonitorMasterPort : public MasterPort
{
public:
MonitorMasterPort(const std::string& _name, CommMonitor& _mon)
: MasterPort(_name, &_mon), mon(_mon)
{ }
protected:
void recvFunctionalSnoop(PacketPtr pkt)
{
mon.recvFunctionalSnoop(pkt);
}
Tick recvAtomicSnoop(PacketPtr pkt)
{
return mon.recvAtomicSnoop(pkt);
}
bool recvTimingResp(PacketPtr pkt)
{
return mon.recvTimingResp(pkt);
}
void recvTimingSnoopReq(PacketPtr pkt)
{
mon.recvTimingSnoopReq(pkt);
}
void recvRangeChange()
{
mon.recvRangeChange();
}
bool isSnooping() const
{
return mon.isSnooping();
}
void recvReqRetry()
{
mon.recvReqRetry();
}
void recvRetrySnoopResp()
{
mon.recvRetrySnoopResp();
}
private:
CommMonitor& mon;
};
/** Instance of master port, facing the memory side */
MonitorMasterPort masterPort;
/**
* This is the slave port of the communication monitor. All recv
* functions call a function in CommMonitor, where the
* send function of the master port is called. Besides this, these
* functions can also perform actions for capturing statistics.
*/
class MonitorSlavePort : public SlavePort
{
public:
MonitorSlavePort(const std::string& _name, CommMonitor& _mon)
: SlavePort(_name, &_mon), mon(_mon)
{ }
protected:
void recvFunctional(PacketPtr pkt)
{
mon.recvFunctional(pkt);
}
Tick recvAtomic(PacketPtr pkt)
{
return mon.recvAtomic(pkt);
}
bool recvTimingReq(PacketPtr pkt)
{
return mon.recvTimingReq(pkt);
}
bool recvTimingSnoopResp(PacketPtr pkt)
{
return mon.recvTimingSnoopResp(pkt);
}
AddrRangeList getAddrRanges() const
{
return mon.getAddrRanges();
}
void recvRespRetry()
{
mon.recvRespRetry();
}
private:
CommMonitor& mon;
};
/** Instance of slave port, i.e. on the CPU side */
MonitorSlavePort slavePort;
void recvFunctional(PacketPtr pkt);
void recvFunctionalSnoop(PacketPtr pkt);
Tick recvAtomic(PacketPtr pkt);
Tick recvAtomicSnoop(PacketPtr pkt);
bool recvTimingReq(PacketPtr pkt);
bool recvTimingResp(PacketPtr pkt);
void recvTimingSnoopReq(PacketPtr pkt);
bool recvTimingSnoopResp(PacketPtr pkt);
void recvRetrySnoopResp();
AddrRangeList getAddrRanges() const;
bool isSnooping() const;
void recvReqRetry();
void recvRespRetry();
void recvRangeChange();
/** Stats declarations, all in a struct for convenience. */
struct MonitorStats
{
/** Disable flag for burst length histograms **/
bool disableBurstLengthHists;
/** Histogram of read burst lengths */
Stats::Histogram readBurstLengthHist;
/** Histogram of write burst lengths */
Stats::Histogram writeBurstLengthHist;
/** Disable flag for the bandwidth histograms */
bool disableBandwidthHists;
/**
* Histogram for read bandwidth per sample window. The
* internal counter is an unsigned int rather than a stat.
*/
unsigned int readBytes;
Stats::Histogram readBandwidthHist;
Stats::Formula averageReadBW;
Stats::Scalar totalReadBytes;
/**
* Histogram for write bandwidth per sample window. The
* internal counter is an unsigned int rather than a stat.
*/
unsigned int writtenBytes;
Stats::Histogram writeBandwidthHist;
Stats::Formula averageWriteBW;
Stats::Scalar totalWrittenBytes;
/** Disable flag for latency histograms. */
bool disableLatencyHists;
/** Histogram of read request-to-response latencies */
Stats::Histogram readLatencyHist;
/** Histogram of write request-to-response latencies */
Stats::Histogram writeLatencyHist;
/** Disable flag for ITT distributions. */
bool disableITTDists;
/**
* Inter transaction time (ITT) distributions. There are
* histograms of the time between two read, write or arbitrary
* accesses. The time of a request is the tick at which the
* request is forwarded by the monitor.
*/
Stats::Distribution ittReadRead;
Stats::Distribution ittWriteWrite;
Stats::Distribution ittReqReq;
Tick timeOfLastRead;
Tick timeOfLastWrite;
Tick timeOfLastReq;
/** Disable flag for outstanding histograms. */
bool disableOutstandingHists;
/**
* Histogram of outstanding read requests. Counter for
* outstanding read requests is an unsigned integer because
* it should not be reset when stats are reset.
*/
Stats::Histogram outstandingReadsHist;
unsigned int outstandingReadReqs;
/**
* Histogram of outstanding write requests. Counter for
* outstanding write requests is an unsigned integer because
* it should not be reset when stats are reset.
*/
Stats::Histogram outstandingWritesHist;
unsigned int outstandingWriteReqs;
/** Disable flag for transaction histograms. */
bool disableTransactionHists;
/** Histogram of number of read transactions per time bin */
Stats::Histogram readTransHist;
unsigned int readTrans;
/** Histogram of number of timing write transactions per time bin */
Stats::Histogram writeTransHist;
unsigned int writeTrans;
/** Disable flag for address distributions. */
bool disableAddrDists;
/** Address mask for sources of read accesses to be captured */
const Addr readAddrMask;
/** Address mask for sources of write accesses to be captured */
const Addr writeAddrMask;
/**
* Histogram of number of read accesses to addresses over
* time.
*/
Stats::SparseHistogram readAddrDist;
/**
* Histogram of number of write accesses to addresses over
* time.
*/
Stats::SparseHistogram writeAddrDist;
/**
* Create the monitor stats and initialise all the members
* that are not statistics themselves, but used to control the
* stats or track values during a sample period.
*/
MonitorStats(const CommMonitorParams* params) :
disableBurstLengthHists(params->disable_burst_length_hists),
disableBandwidthHists(params->disable_bandwidth_hists),
readBytes(0), writtenBytes(0),
disableLatencyHists(params->disable_latency_hists),
disableITTDists(params->disable_itt_dists),
timeOfLastRead(0), timeOfLastWrite(0), timeOfLastReq(0),
disableOutstandingHists(params->disable_outstanding_hists),
outstandingReadReqs(0), outstandingWriteReqs(0),
disableTransactionHists(params->disable_transaction_hists),
readTrans(0), writeTrans(0),
disableAddrDists(params->disable_addr_dists),
readAddrMask(params->read_addr_mask),
writeAddrMask(params->write_addr_mask)
{ }
void updateReqStats(const ProbePoints::PacketInfo& pkt, bool is_atomic,
bool expects_response);
void updateRespStats(const ProbePoints::PacketInfo& pkt, Tick latency,
bool is_atomic);
};
/** This function is called periodically at the end of each time bin */
void samplePeriodic();
/** Periodic event called at the end of each simulation time bin */
EventFunctionWrapper samplePeriodicEvent;
/**
*@{
* @name Configuration
*/
/** Length of simulation time bin*/
const Tick samplePeriodTicks;
/** Sample period in seconds */
const double samplePeriod;
/** @} */
/** Instantiate stats */
MonitorStats stats;
protected: // Probe points
/**
* @{
* @name Memory system probe points
*/
/** Successfully forwarded request packet */
ProbePoints::PacketUPtr ppPktReq;
/** Successfully forwarded response packet */
ProbePoints::PacketUPtr ppPktResp;
/** @} */
};
#endif //__MEM_COMM_MONITOR_HH__