comm_monitor.hh revision 11168
112771Sqtt2@cornell.edu/*
212771Sqtt2@cornell.edu * Copyright (c) 2012-2013, 2015 ARM Limited
312771Sqtt2@cornell.edu * All rights reserved
412771Sqtt2@cornell.edu *
512771Sqtt2@cornell.edu * The license below extends only to copyright in the software and shall
612771Sqtt2@cornell.edu * not be construed as granting a license to any other intellectual
712771Sqtt2@cornell.edu * property including but not limited to intellectual property relating
812771Sqtt2@cornell.edu * to a hardware implementation of the functionality of the software
912771Sqtt2@cornell.edu * licensed hereunder.  You may use the software subject to the license
1012771Sqtt2@cornell.edu * terms below provided that you ensure that this notice is replicated
1112771Sqtt2@cornell.edu * unmodified and in its entirety in all distributions of the software,
1212771Sqtt2@cornell.edu * modified or unmodified, in source code or in binary form.
1312771Sqtt2@cornell.edu *
1412771Sqtt2@cornell.edu * Redistribution and use in source and binary forms, with or without
1512771Sqtt2@cornell.edu * modification, are permitted provided that the following conditions are
1612771Sqtt2@cornell.edu * met: redistributions of source code must retain the above copyright
1712771Sqtt2@cornell.edu * notice, this list of conditions and the following disclaimer;
1812771Sqtt2@cornell.edu * redistributions in binary form must reproduce the above copyright
1912771Sqtt2@cornell.edu * notice, this list of conditions and the following disclaimer in the
2012771Sqtt2@cornell.edu * documentation and/or other materials provided with the distribution;
2112771Sqtt2@cornell.edu * neither the name of the copyright holders nor the names of its
2212771Sqtt2@cornell.edu * contributors may be used to endorse or promote products derived from
2312771Sqtt2@cornell.edu * this software without specific prior written permission.
2412771Sqtt2@cornell.edu *
2512771Sqtt2@cornell.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612771Sqtt2@cornell.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712771Sqtt2@cornell.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812771Sqtt2@cornell.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912771Sqtt2@cornell.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012771Sqtt2@cornell.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3112771Sqtt2@cornell.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212771Sqtt2@cornell.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312771Sqtt2@cornell.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412771Sqtt2@cornell.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512771Sqtt2@cornell.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612771Sqtt2@cornell.edu *
3712771Sqtt2@cornell.edu * Authors: Thomas Grass
3812771Sqtt2@cornell.edu *          Andreas Hansson
3912771Sqtt2@cornell.edu */
4012771Sqtt2@cornell.edu
4112771Sqtt2@cornell.edu#ifndef __MEM_COMM_MONITOR_HH__
4212771Sqtt2@cornell.edu#define __MEM_COMM_MONITOR_HH__
4312771Sqtt2@cornell.edu
4412771Sqtt2@cornell.edu#include "base/statistics.hh"
4512771Sqtt2@cornell.edu#include "mem/mem_object.hh"
4612771Sqtt2@cornell.edu#include "params/CommMonitor.hh"
4712771Sqtt2@cornell.edu#include "sim/probe/mem.hh"
4812771Sqtt2@cornell.edu
4912771Sqtt2@cornell.edu/**
5012771Sqtt2@cornell.edu * The communication monitor is a MemObject which can monitor statistics of
5112771Sqtt2@cornell.edu * the communication happening between two ports in the memory system.
5212771Sqtt2@cornell.edu *
5312771Sqtt2@cornell.edu * Currently the following stats are implemented: Histograms of read/write
5412771Sqtt2@cornell.edu * transactions, read/write burst lengths, read/write bandwidth,
5512771Sqtt2@cornell.edu * outstanding read/write requests, read latency and inter transaction time
5612771Sqtt2@cornell.edu * (read-read, write-write, read/write-read/write). Furthermore it allows
5712771Sqtt2@cornell.edu * to capture the number of accesses to an address over time ("heat map").
5812771Sqtt2@cornell.edu * All stats can be disabled from Python.
5912771Sqtt2@cornell.edu */
6012771Sqtt2@cornell.educlass CommMonitor : public MemObject
6112771Sqtt2@cornell.edu{
6212771Sqtt2@cornell.edu
6312771Sqtt2@cornell.edu  public: // Construction & SimObject interfaces
6412771Sqtt2@cornell.edu
6512771Sqtt2@cornell.edu    /** Parameters of communication monitor */
6612771Sqtt2@cornell.edu    typedef CommMonitorParams Params;
6712771Sqtt2@cornell.edu    const Params* params() const
6812771Sqtt2@cornell.edu    { return reinterpret_cast<const Params*>(_params); }
6912771Sqtt2@cornell.edu
7012771Sqtt2@cornell.edu    /**
7112771Sqtt2@cornell.edu     * Constructor based on the Python params
7212771Sqtt2@cornell.edu     *
7312771Sqtt2@cornell.edu     * @param params Python parameters
7412771Sqtt2@cornell.edu     */
7512771Sqtt2@cornell.edu    CommMonitor(Params* params);
7612771Sqtt2@cornell.edu
7712771Sqtt2@cornell.edu    void init() override;
7812771Sqtt2@cornell.edu    void regStats() override;
7912771Sqtt2@cornell.edu    void startup() override;
8012771Sqtt2@cornell.edu    void regProbePoints() override;
8112771Sqtt2@cornell.edu
8212771Sqtt2@cornell.edu  public: // MemObject interfaces
8312771Sqtt2@cornell.edu    BaseMasterPort& getMasterPort(const std::string& if_name,
8412771Sqtt2@cornell.edu                                  PortID idx = InvalidPortID) override;
8512771Sqtt2@cornell.edu
8612771Sqtt2@cornell.edu    BaseSlavePort& getSlavePort(const std::string& if_name,
8712771Sqtt2@cornell.edu                                PortID idx = InvalidPortID) override;
8812771Sqtt2@cornell.edu
8912771Sqtt2@cornell.edu  private:
9012771Sqtt2@cornell.edu
9112771Sqtt2@cornell.edu    /**
9212771Sqtt2@cornell.edu     * Sender state class for the monitor so that we can annotate
9312771Sqtt2@cornell.edu     * packets with a transmit time and receive time.
9412771Sqtt2@cornell.edu     */
9512771Sqtt2@cornell.edu    class CommMonitorSenderState : public Packet::SenderState
9612771Sqtt2@cornell.edu    {
9712771Sqtt2@cornell.edu
9812771Sqtt2@cornell.edu      public:
9912771Sqtt2@cornell.edu
10012771Sqtt2@cornell.edu        /**
10112771Sqtt2@cornell.edu         * Construct a new sender state and store the time so we can
10212771Sqtt2@cornell.edu         * calculate round-trip latency.
10312771Sqtt2@cornell.edu         *
10412771Sqtt2@cornell.edu         * @param _transmitTime Time of packet transmission
10512771Sqtt2@cornell.edu         */
10612771Sqtt2@cornell.edu        CommMonitorSenderState(Tick _transmitTime)
10712771Sqtt2@cornell.edu            : transmitTime(_transmitTime)
10812771Sqtt2@cornell.edu        { }
10912771Sqtt2@cornell.edu
11012771Sqtt2@cornell.edu        /** Destructor */
11112771Sqtt2@cornell.edu        ~CommMonitorSenderState() { }
11212771Sqtt2@cornell.edu
11312771Sqtt2@cornell.edu        /** Tick when request is transmitted */
11412771Sqtt2@cornell.edu        Tick transmitTime;
11512771Sqtt2@cornell.edu
11612771Sqtt2@cornell.edu    };
11712771Sqtt2@cornell.edu
11812771Sqtt2@cornell.edu    /**
11912771Sqtt2@cornell.edu     * This is the master port of the communication monitor. All recv
12012771Sqtt2@cornell.edu     * functions call a function in CommMonitor, where the
12112771Sqtt2@cornell.edu     * send function of the slave port is called. Besides this, these
12212771Sqtt2@cornell.edu     * functions can also perform actions for capturing statistics.
12312771Sqtt2@cornell.edu     */
12412771Sqtt2@cornell.edu    class MonitorMasterPort : public MasterPort
12512771Sqtt2@cornell.edu    {
12612771Sqtt2@cornell.edu
12712771Sqtt2@cornell.edu      public:
12812771Sqtt2@cornell.edu
12912771Sqtt2@cornell.edu        MonitorMasterPort(const std::string& _name, CommMonitor& _mon)
13012771Sqtt2@cornell.edu            : MasterPort(_name, &_mon), mon(_mon)
13112771Sqtt2@cornell.edu        { }
13212771Sqtt2@cornell.edu
13312771Sqtt2@cornell.edu      protected:
13412771Sqtt2@cornell.edu
13512771Sqtt2@cornell.edu        void recvFunctionalSnoop(PacketPtr pkt)
13612771Sqtt2@cornell.edu        {
13712771Sqtt2@cornell.edu            mon.recvFunctionalSnoop(pkt);
13812771Sqtt2@cornell.edu        }
13912771Sqtt2@cornell.edu
14012771Sqtt2@cornell.edu        Tick recvAtomicSnoop(PacketPtr pkt)
14112771Sqtt2@cornell.edu        {
142            return mon.recvAtomicSnoop(pkt);
143        }
144
145        bool recvTimingResp(PacketPtr pkt)
146        {
147            return mon.recvTimingResp(pkt);
148        }
149
150        void recvTimingSnoopReq(PacketPtr pkt)
151        {
152            mon.recvTimingSnoopReq(pkt);
153        }
154
155        void recvRangeChange()
156        {
157            mon.recvRangeChange();
158        }
159
160        bool isSnooping() const
161        {
162            return mon.isSnooping();
163        }
164
165        void recvReqRetry()
166        {
167            mon.recvReqRetry();
168        }
169
170      private:
171
172        CommMonitor& mon;
173
174    };
175
176    /** Instance of master port, facing the memory side */
177    MonitorMasterPort masterPort;
178
179    /**
180     * This is the slave port of the communication monitor. All recv
181     * functions call a function in CommMonitor, where the
182     * send function of the master port is called. Besides this, these
183     * functions can also perform actions for capturing statistics.
184     */
185    class MonitorSlavePort : public SlavePort
186    {
187
188      public:
189
190        MonitorSlavePort(const std::string& _name, CommMonitor& _mon)
191            : SlavePort(_name, &_mon), mon(_mon)
192        { }
193
194      protected:
195
196        void recvFunctional(PacketPtr pkt)
197        {
198            mon.recvFunctional(pkt);
199        }
200
201        Tick recvAtomic(PacketPtr pkt)
202        {
203            return mon.recvAtomic(pkt);
204        }
205
206        bool recvTimingReq(PacketPtr pkt)
207        {
208            return mon.recvTimingReq(pkt);
209        }
210
211        bool recvTimingSnoopResp(PacketPtr pkt)
212        {
213            return mon.recvTimingSnoopResp(pkt);
214        }
215
216        AddrRangeList getAddrRanges() const
217        {
218            return mon.getAddrRanges();
219        }
220
221        void recvRespRetry()
222        {
223            mon.recvRespRetry();
224        }
225
226      private:
227
228        CommMonitor& mon;
229
230    };
231
232    /** Instance of slave port, i.e. on the CPU side */
233    MonitorSlavePort slavePort;
234
235    void recvFunctional(PacketPtr pkt);
236
237    void recvFunctionalSnoop(PacketPtr pkt);
238
239    Tick recvAtomic(PacketPtr pkt);
240
241    Tick recvAtomicSnoop(PacketPtr pkt);
242
243    bool recvTimingReq(PacketPtr pkt);
244
245    bool recvTimingResp(PacketPtr pkt);
246
247    void recvTimingSnoopReq(PacketPtr pkt);
248
249    bool recvTimingSnoopResp(PacketPtr pkt);
250
251    AddrRangeList getAddrRanges() const;
252
253    bool isSnooping() const;
254
255    void recvReqRetry();
256
257    void recvRespRetry();
258
259    void recvRangeChange();
260
261    /** Stats declarations, all in a struct for convenience. */
262    struct MonitorStats
263    {
264
265        /** Disable flag for burst length historgrams **/
266        bool disableBurstLengthHists;
267
268        /** Histogram of read burst lengths */
269        Stats::Histogram readBurstLengthHist;
270
271        /** Histogram of write burst lengths */
272        Stats::Histogram writeBurstLengthHist;
273
274        /** Disable flag for the bandwidth histograms */
275        bool disableBandwidthHists;
276
277        /**
278         * Histogram for read bandwidth per sample window. The
279         * internal counter is an unsigned int rather than a stat.
280         */
281        unsigned int readBytes;
282        Stats::Histogram readBandwidthHist;
283        Stats::Formula averageReadBW;
284        Stats::Scalar totalReadBytes;
285
286        /**
287         * Histogram for write bandwidth per sample window. The
288         * internal counter is an unsigned int rather than a stat.
289         */
290        unsigned int writtenBytes;
291        Stats::Histogram writeBandwidthHist;
292        Stats::Formula averageWriteBW;
293        Stats::Scalar totalWrittenBytes;
294
295        /** Disable flag for latency histograms. */
296        bool disableLatencyHists;
297
298        /** Histogram of read request-to-response latencies */
299        Stats::Histogram readLatencyHist;
300
301        /** Histogram of write request-to-response latencies */
302        Stats::Histogram writeLatencyHist;
303
304        /** Disable flag for ITT distributions. */
305        bool disableITTDists;
306
307        /**
308         * Inter transaction time (ITT) distributions. There are
309         * histograms of the time between two read, write or arbitrary
310         * accesses. The time of a request is the tick at which the
311         * request is forwarded by the monitor.
312         */
313        Stats::Distribution ittReadRead;
314        Stats::Distribution ittWriteWrite;
315        Stats::Distribution ittReqReq;
316        Tick timeOfLastRead;
317        Tick timeOfLastWrite;
318        Tick timeOfLastReq;
319
320        /** Disable flag for outstanding histograms. */
321        bool disableOutstandingHists;
322
323        /**
324         * Histogram of outstanding read requests. Counter for
325         * outstanding read requests is an unsigned integer because
326         * it should not be reset when stats are reset.
327         */
328        Stats::Histogram outstandingReadsHist;
329        unsigned int outstandingReadReqs;
330
331        /**
332         * Histogram of outstanding write requests. Counter for
333         * outstanding write requests is an unsigned integer because
334         * it should not be reset when stats are reset.
335         */
336        Stats::Histogram outstandingWritesHist;
337        unsigned int outstandingWriteReqs;
338
339        /** Disable flag for transaction histograms. */
340        bool disableTransactionHists;
341
342        /** Histogram of number of read transactions per time bin */
343        Stats::Histogram readTransHist;
344        unsigned int readTrans;
345
346        /** Histogram of number of timing write transactions per time bin */
347        Stats::Histogram writeTransHist;
348        unsigned int writeTrans;
349
350        /** Disable flag for address distributions. */
351        bool disableAddrDists;
352
353        /**
354         * Histogram of number of read accesses to addresses over
355         * time.
356         */
357        Stats::SparseHistogram readAddrDist;
358
359        /**
360         * Histogram of number of write accesses to addresses over
361         * time.
362         */
363        Stats::SparseHistogram writeAddrDist;
364
365        /**
366         * Create the monitor stats and initialise all the members
367         * that are not statistics themselves, but used to control the
368         * stats or track values during a sample period.
369         */
370        MonitorStats(const CommMonitorParams* params) :
371            disableBurstLengthHists(params->disable_burst_length_hists),
372            disableBandwidthHists(params->disable_bandwidth_hists),
373            readBytes(0), writtenBytes(0),
374            disableLatencyHists(params->disable_latency_hists),
375            disableITTDists(params->disable_itt_dists),
376            timeOfLastRead(0), timeOfLastWrite(0), timeOfLastReq(0),
377            disableOutstandingHists(params->disable_outstanding_hists),
378            outstandingReadReqs(0), outstandingWriteReqs(0),
379            disableTransactionHists(params->disable_transaction_hists),
380            readTrans(0), writeTrans(0),
381            disableAddrDists(params->disable_addr_dists)
382        { }
383
384    };
385
386    /** This function is called periodically at the end of each time bin */
387    void samplePeriodic();
388
389    /** Periodic event called at the end of each simulation time bin */
390    EventWrapper<CommMonitor, &CommMonitor::samplePeriodic> samplePeriodicEvent;
391
392    /**
393     *@{
394     * @name Configuration
395     */
396
397    /** Length of simulation time bin*/
398    const Tick samplePeriodTicks;
399    /** Sample period in seconds */
400    const double samplePeriod;
401
402    /** Address mask for sources of read accesses to be captured */
403    const Addr readAddrMask;
404
405    /** Address mask for sources of write accesses to be captured */
406    const Addr writeAddrMask;
407
408    /** @} */
409
410    /** Instantiate stats */
411    MonitorStats stats;
412
413  protected: // Probe points
414    /**
415     * @{
416     * @name Memory system probe points
417     */
418
419    /** Successfully forwarded request packet */
420    ProbePoints::PacketUPtr ppPktReq;
421
422    /** Successfully forwarded response packet */
423    ProbePoints::PacketUPtr ppPktResp;
424
425    /** @} */
426};
427
428#endif //__MEM_COMM_MONITOR_HH__
429