comm_monitor.hh revision 10615:cd8aae15f89a
1/* 2 * Copyright (c) 2012-2013 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Thomas Grass 38 * Andreas Hansson 39 */ 40 41#ifndef __MEM_COMM_MONITOR_HH__ 42#define __MEM_COMM_MONITOR_HH__ 43 44#include "base/statistics.hh" 45#include "base/time.hh" 46#include "mem/mem_object.hh" 47#include "mem/stack_dist_calc.hh" 48#include "params/CommMonitor.hh" 49#include "proto/protoio.hh" 50#include "sim/system.hh" 51 52/** 53 * The communication monitor is a MemObject which can monitor statistics of 54 * the communication happening between two ports in the memory system. 55 * 56 * Currently the following stats are implemented: Histograms of read/write 57 * transactions, read/write burst lengths, read/write bandwidth, 58 * outstanding read/write requests, read latency and inter transaction time 59 * (read-read, write-write, read/write-read/write). Furthermore it allows 60 * to capture the number of accesses to an address over time ("heat map"). 61 * All stats can be disabled from Python. 62 */ 63class CommMonitor : public MemObject 64{ 65 66 public: 67 68 /** Parameters of communication monitor */ 69 typedef CommMonitorParams Params; 70 const Params* params() const 71 { return reinterpret_cast<const Params*>(_params); } 72 73 /** 74 * Constructor based on the Python params 75 * 76 * @param params Python parameters 77 */ 78 CommMonitor(Params* params); 79 80 /** Destructor */ 81 ~CommMonitor(); 82 83 /** 84 * Callback to flush and close all open output streams on exit. If 85 * we were calling the destructor it could be done there. 86 */ 87 void closeStreams(); 88 89 virtual BaseMasterPort& getMasterPort(const std::string& if_name, 90 PortID idx = InvalidPortID); 91 92 virtual BaseSlavePort& getSlavePort(const std::string& if_name, 93 PortID idx = InvalidPortID); 94 95 virtual void init(); 96 97 /** Register statistics */ 98 void regStats(); 99 100 private: 101 102 /** 103 * Sender state class for the monitor so that we can annotate 104 * packets with a transmit time and receive time. 105 */ 106 class CommMonitorSenderState : public Packet::SenderState 107 { 108 109 public: 110 111 /** 112 * Construct a new sender state and store the time so we can 113 * calculate round-trip latency. 114 * 115 * @param _transmitTime Time of packet transmission 116 */ 117 CommMonitorSenderState(Tick _transmitTime) 118 : transmitTime(_transmitTime) 119 { } 120 121 /** Destructor */ 122 ~CommMonitorSenderState() { } 123 124 /** Tick when request is transmitted */ 125 Tick transmitTime; 126 127 }; 128 129 /** 130 * This is the master port of the communication monitor. All recv 131 * functions call a function in CommMonitor, where the 132 * send function of the slave port is called. Besides this, these 133 * functions can also perform actions for capturing statistics. 134 */ 135 class MonitorMasterPort : public MasterPort 136 { 137 138 public: 139 140 MonitorMasterPort(const std::string& _name, CommMonitor& _mon) 141 : MasterPort(_name, &_mon), mon(_mon) 142 { } 143 144 protected: 145 146 void recvFunctionalSnoop(PacketPtr pkt) 147 { 148 mon.recvFunctionalSnoop(pkt); 149 } 150 151 Tick recvAtomicSnoop(PacketPtr pkt) 152 { 153 return mon.recvAtomicSnoop(pkt); 154 } 155 156 bool recvTimingResp(PacketPtr pkt) 157 { 158 return mon.recvTimingResp(pkt); 159 } 160 161 void recvTimingSnoopReq(PacketPtr pkt) 162 { 163 mon.recvTimingSnoopReq(pkt); 164 } 165 166 void recvRangeChange() 167 { 168 mon.recvRangeChange(); 169 } 170 171 bool isSnooping() const 172 { 173 return mon.isSnooping(); 174 } 175 176 void recvRetry() 177 { 178 mon.recvRetryMaster(); 179 } 180 181 private: 182 183 CommMonitor& mon; 184 185 }; 186 187 /** Instance of master port, facing the memory side */ 188 MonitorMasterPort masterPort; 189 190 /** 191 * This is the slave port of the communication monitor. All recv 192 * functions call a function in CommMonitor, where the 193 * send function of the master port is called. Besides this, these 194 * functions can also perform actions for capturing statistics. 195 */ 196 class MonitorSlavePort : public SlavePort 197 { 198 199 public: 200 201 MonitorSlavePort(const std::string& _name, CommMonitor& _mon) 202 : SlavePort(_name, &_mon), mon(_mon) 203 { } 204 205 protected: 206 207 void recvFunctional(PacketPtr pkt) 208 { 209 mon.recvFunctional(pkt); 210 } 211 212 Tick recvAtomic(PacketPtr pkt) 213 { 214 return mon.recvAtomic(pkt); 215 } 216 217 bool recvTimingReq(PacketPtr pkt) 218 { 219 return mon.recvTimingReq(pkt); 220 } 221 222 bool recvTimingSnoopResp(PacketPtr pkt) 223 { 224 return mon.recvTimingSnoopResp(pkt); 225 } 226 227 AddrRangeList getAddrRanges() const 228 { 229 return mon.getAddrRanges(); 230 } 231 232 void recvRetry() 233 { 234 mon.recvRetrySlave(); 235 } 236 237 private: 238 239 CommMonitor& mon; 240 241 }; 242 243 /** Instance of slave port, i.e. on the CPU side */ 244 MonitorSlavePort slavePort; 245 246 void recvFunctional(PacketPtr pkt); 247 248 void recvFunctionalSnoop(PacketPtr pkt); 249 250 Tick recvAtomic(PacketPtr pkt); 251 252 Tick recvAtomicSnoop(PacketPtr pkt); 253 254 bool recvTimingReq(PacketPtr pkt); 255 256 bool recvTimingResp(PacketPtr pkt); 257 258 void recvTimingSnoopReq(PacketPtr pkt); 259 260 bool recvTimingSnoopResp(PacketPtr pkt); 261 262 AddrRangeList getAddrRanges() const; 263 264 bool isSnooping() const; 265 266 void recvRetryMaster(); 267 268 void recvRetrySlave(); 269 270 void recvRangeChange(); 271 272 /** Stats declarations, all in a struct for convenience. */ 273 struct MonitorStats 274 { 275 276 /** Disable flag for burst length historgrams **/ 277 bool disableBurstLengthHists; 278 279 /** Histogram of read burst lengths */ 280 Stats::Histogram readBurstLengthHist; 281 282 /** Histogram of write burst lengths */ 283 Stats::Histogram writeBurstLengthHist; 284 285 /** Disable flag for the bandwidth histograms */ 286 bool disableBandwidthHists; 287 288 /** 289 * Histogram for read bandwidth per sample window. The 290 * internal counter is an unsigned int rather than a stat. 291 */ 292 unsigned int readBytes; 293 Stats::Histogram readBandwidthHist; 294 Stats::Formula averageReadBW; 295 Stats::Scalar totalReadBytes; 296 297 /** 298 * Histogram for write bandwidth per sample window. The 299 * internal counter is an unsigned int rather than a stat. 300 */ 301 unsigned int writtenBytes; 302 Stats::Histogram writeBandwidthHist; 303 Stats::Formula averageWriteBW; 304 Stats::Scalar totalWrittenBytes; 305 306 /** Disable flag for latency histograms. */ 307 bool disableLatencyHists; 308 309 /** Histogram of read request-to-response latencies */ 310 Stats::Histogram readLatencyHist; 311 312 /** Histogram of write request-to-response latencies */ 313 Stats::Histogram writeLatencyHist; 314 315 /** Disable flag for ITT distributions. */ 316 bool disableITTDists; 317 318 /** 319 * Inter transaction time (ITT) distributions. There are 320 * histograms of the time between two read, write or arbitrary 321 * accesses. The time of a request is the tick at which the 322 * request is forwarded by the monitor. 323 */ 324 Stats::Distribution ittReadRead; 325 Stats::Distribution ittWriteWrite; 326 Stats::Distribution ittReqReq; 327 Tick timeOfLastRead; 328 Tick timeOfLastWrite; 329 Tick timeOfLastReq; 330 331 /** Disable flag for outstanding histograms. */ 332 bool disableOutstandingHists; 333 334 /** 335 * Histogram of outstanding read requests. Counter for 336 * outstanding read requests is an unsigned integer because 337 * it should not be reset when stats are reset. 338 */ 339 Stats::Histogram outstandingReadsHist; 340 unsigned int outstandingReadReqs; 341 342 /** 343 * Histogram of outstanding write requests. Counter for 344 * outstanding write requests is an unsigned integer because 345 * it should not be reset when stats are reset. 346 */ 347 Stats::Histogram outstandingWritesHist; 348 unsigned int outstandingWriteReqs; 349 350 /** Disable flag for transaction histograms. */ 351 bool disableTransactionHists; 352 353 /** Histogram of number of read transactions per time bin */ 354 Stats::Histogram readTransHist; 355 unsigned int readTrans; 356 357 /** Histogram of number of timing write transactions per time bin */ 358 Stats::Histogram writeTransHist; 359 unsigned int writeTrans; 360 361 /** Disable flag for address distributions. */ 362 bool disableAddrDists; 363 364 /** 365 * Histogram of number of read accesses to addresses over 366 * time. 367 */ 368 Stats::SparseHistogram readAddrDist; 369 370 /** 371 * Histogram of number of write accesses to addresses over 372 * time. 373 */ 374 Stats::SparseHistogram writeAddrDist; 375 376 /** 377 * Create the monitor stats and initialise all the members 378 * that are not statistics themselves, but used to control the 379 * stats or track values during a sample period. 380 */ 381 MonitorStats(const CommMonitorParams* params) : 382 disableBurstLengthHists(params->disable_burst_length_hists), 383 disableBandwidthHists(params->disable_bandwidth_hists), 384 readBytes(0), writtenBytes(0), 385 disableLatencyHists(params->disable_latency_hists), 386 disableITTDists(params->disable_itt_dists), 387 timeOfLastRead(0), timeOfLastWrite(0), timeOfLastReq(0), 388 disableOutstandingHists(params->disable_outstanding_hists), 389 outstandingReadReqs(0), outstandingWriteReqs(0), 390 disableTransactionHists(params->disable_transaction_hists), 391 readTrans(0), writeTrans(0), 392 disableAddrDists(params->disable_addr_dists) 393 { } 394 395 }; 396 397 /** This function is called periodically at the end of each time bin */ 398 void samplePeriodic(); 399 400 /** Schedule the first periodic event */ 401 void startup(); 402 403 /** Periodic event called at the end of each simulation time bin */ 404 EventWrapper<CommMonitor, &CommMonitor::samplePeriodic> samplePeriodicEvent; 405 406 /** Length of simulation time bin*/ 407 Tick samplePeriodTicks; 408 Time samplePeriod; 409 410 /** Address mask for sources of read accesses to be captured */ 411 Addr readAddrMask; 412 413 /** Address mask for sources of write accesses to be captured */ 414 Addr writeAddrMask; 415 416 /** Instantiate stats */ 417 MonitorStats stats; 418 419 /** Optional stack distance calculator */ 420 StackDistCalc* stackDistCalc; 421 422 /** Output stream for a potential trace. */ 423 ProtoOutputStream* traceStream; 424 425 /** The system in which the monitor lives */ 426 System *system; 427}; 428 429#endif //__MEM_COMM_MONITOR_HH__ 430