comm_monitor.cc (9294:8fb03b13de02) comm_monitor.cc (9356:b279bad40aa3)
1/*
2 * Copyright (c) 2012 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
1/*
2 * Copyright (c) 2012 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#include "base/trace.hh"
41#include "debug/CommMonitor.hh"
42#include "mem/comm_monitor.hh"
43#include "sim/stats.hh"
44
45CommMonitor::CommMonitor(Params* params)
46 : MemObject(params),
47 masterPort(name() + "-master", *this),
48 slavePort(name() + "-slave", *this),
49 samplePeriodicEvent(this),
50 samplePeriodTicks(params->sample_period),
51 readAddrMask(params->read_addr_mask),
52 writeAddrMask(params->write_addr_mask),
53 stats(params)
54{
55 // keep track of the sample period both in ticks and absolute time
56 samplePeriod.setTick(params->sample_period);
57
58 DPRINTF(CommMonitor,
59 "Created monitor %s with sample period %d ticks (%f s)\n",
60 name(), samplePeriodTicks, samplePeriod);
61}
62
63CommMonitor*
64CommMonitorParams::create()
65{
66 return new CommMonitor(this);
67}
68
69void
70CommMonitor::init()
71{
72 // make sure both sides of the monitor are connected
73 if (!slavePort.isConnected() || !masterPort.isConnected())
74 fatal("Communication monitor is not connected on both sides.\n");
75}
76
77BaseMasterPort&
78CommMonitor::getMasterPort(const std::string& if_name, PortID idx)
79{
80 if (if_name == "master") {
81 return masterPort;
82 } else {
83 return MemObject::getMasterPort(if_name, idx);
84 }
85}
86
87BaseSlavePort&
88CommMonitor::getSlavePort(const std::string& if_name, PortID idx)
89{
90 if (if_name == "slave") {
91 return slavePort;
92 } else {
93 return MemObject::getSlavePort(if_name, idx);
94 }
95}
96
97void
98CommMonitor::recvFunctional(PacketPtr pkt)
99{
100 masterPort.sendFunctional(pkt);
101}
102
103void
104CommMonitor::recvFunctionalSnoop(PacketPtr pkt)
105{
106 slavePort.sendFunctionalSnoop(pkt);
107}
108
109Tick
110CommMonitor::recvAtomic(PacketPtr pkt)
111{
112 return masterPort.sendAtomic(pkt);
113}
114
115Tick
116CommMonitor::recvAtomicSnoop(PacketPtr pkt)
117{
118 return slavePort.sendAtomicSnoop(pkt);
119}
120
121bool
122CommMonitor::recvTimingReq(PacketPtr pkt)
123{
124 // should always see a request
125 assert(pkt->isRequest());
126
127 // Store relevant fields of packet, because packet may be modified
128 // or even deleted when sendTiming() is called.
129 bool isRead = pkt->isRead();
130 bool isWrite = pkt->isWrite();
131 unsigned size = pkt->getSize();
132 Addr addr = pkt->getAddr();
133 bool needsResponse = pkt->needsResponse();
134 bool memInhibitAsserted = pkt->memInhibitAsserted();
135 Packet::SenderState* senderState = pkt->senderState;
136
137 // If a cache miss is served by a cache, a monitor near the memory
138 // would see a request which needs a response, but this response
139 // would be inhibited and not come back from the memory. Therefore
140 // we additionally have to check the inhibit flag.
141 if (needsResponse && !memInhibitAsserted && !stats.disableLatencyHists) {
142 pkt->senderState = new CommMonitorSenderState(senderState,
143 curTick());
144 }
145
146 // Attempt to send the packet (always succeeds for inhibited
147 // packets)
148 bool successful = masterPort.sendTimingReq(pkt);
149
150 // If not successful, restore the sender state
151 if (!successful && needsResponse && !stats.disableLatencyHists) {
152 delete pkt->senderState;
153 pkt->senderState = senderState;
154 }
155
156 if (successful && isRead) {
157 DPRINTF(CommMonitor, "Forwarded read request\n");
158
159 // Increment number of observed read transactions
160 if (!stats.disableTransactionHists) {
161 ++stats.readTrans;
162 }
163
164 // Get sample of burst length
165 if (!stats.disableBurstLengthHists) {
166 stats.readBurstLengthHist.sample(size);
167 }
168
169 // Sample the masked address
170 if (!stats.disableAddrDists) {
171 stats.readAddrDist.sample(addr & readAddrMask);
172 }
173
174 // If it needs a response increment number of outstanding read
175 // requests
176 if (!stats.disableOutstandingHists && needsResponse) {
177 ++stats.outstandingReadReqs;
178 }
179
180 if (!stats.disableITTDists) {
181 // Sample value of read-read inter transaction time
182 if (stats.timeOfLastRead != 0) {
183 stats.ittReadRead.sample(curTick() - stats.timeOfLastRead);
184 }
185 stats.timeOfLastRead = curTick();
186
187 // Sample value of req-req inter transaction time
188 if (stats.timeOfLastReq != 0) {
189 stats.ittReqReq.sample(curTick() - stats.timeOfLastReq);
190 }
191 stats.timeOfLastReq = curTick();
192 }
193 } else if (successful && isWrite) {
194 DPRINTF(CommMonitor, "Forwarded write request\n");
195
196 // Same as for reads
197 if (!stats.disableTransactionHists) {
198 ++stats.writeTrans;
199 }
200
201 if (!stats.disableBurstLengthHists) {
202 stats.writeBurstLengthHist.sample(size);
203 }
204
205 // Update the bandwidth stats on the request
206 if (!stats.disableBandwidthHists) {
207 stats.writtenBytes += size;
208 stats.totalWrittenBytes += size;
209 }
210
211 // Sample the masked write address
212 if (!stats.disableAddrDists) {
213 stats.writeAddrDist.sample(addr & writeAddrMask);
214 }
215
216 if (!stats.disableOutstandingHists && needsResponse) {
217 ++stats.outstandingWriteReqs;
218 }
219
220 if (!stats.disableITTDists) {
221 // Sample value of write-to-write inter transaction time
222 if (stats.timeOfLastWrite != 0) {
223 stats.ittWriteWrite.sample(curTick() - stats.timeOfLastWrite);
224 }
225 stats.timeOfLastWrite = curTick();
226
227 // Sample value of req-to-req inter transaction time
228 if (stats.timeOfLastReq != 0) {
229 stats.ittReqReq.sample(curTick() - stats.timeOfLastReq);
230 }
231 stats.timeOfLastReq = curTick();
232 }
233 } else if (successful) {
234 DPRINTF(CommMonitor, "Forwarded non read/write request\n");
235 }
236
237 return successful;
238}
239
240bool
241CommMonitor::recvTimingResp(PacketPtr pkt)
242{
243 // should always see responses
244 assert(pkt->isResponse());
245
246 // Store relevant fields of packet, because packet may be modified
247 // or even deleted when sendTiming() is called.
248 bool isRead = pkt->isRead();
249 bool isWrite = pkt->isWrite();
250 unsigned size = pkt->getSize();
251 Tick latency = 0;
252 CommMonitorSenderState* commReceivedState =
253 dynamic_cast<CommMonitorSenderState*>(pkt->senderState);
254
255 if (!stats.disableLatencyHists) {
256 // Restore initial sender state
257 if (commReceivedState == NULL)
258 panic("Monitor got a response without monitor sender state\n");
259
260 // Restore the sate
261 pkt->senderState = commReceivedState->origSenderState;
262 }
263
264 // Attempt to send the packet
265 bool successful = slavePort.sendTimingResp(pkt);
266
267 if (!stats.disableLatencyHists) {
268 // If packet successfully send, sample value of latency,
269 // afterwards delete sender state, otherwise restore state
270 if (successful) {
271 latency = curTick() - commReceivedState->transmitTime;
272 DPRINTF(CommMonitor, "Latency: %d\n", latency);
273 delete commReceivedState;
274 } else {
275 // Don't delete anything and let the packet look like we
276 // did not touch it
277 pkt->senderState = commReceivedState;
278 }
279 }
280
281 if (successful && isRead) {
282 // Decrement number of outstanding read requests
283 DPRINTF(CommMonitor, "Received read response\n");
284 if (!stats.disableOutstandingHists) {
285 assert(stats.outstandingReadReqs != 0);
286 --stats.outstandingReadReqs;
287 }
288
289 if (!stats.disableLatencyHists) {
290 stats.readLatencyHist.sample(latency);
291 }
292
293 // Update the bandwidth stats based on responses for reads
294 if (!stats.disableBandwidthHists) {
295 stats.readBytes += size;
296 stats.totalReadBytes += size;
297 }
298
299 } else if (successful && isWrite) {
300 // Decrement number of outstanding write requests
301 DPRINTF(CommMonitor, "Received write response\n");
302 if (!stats.disableOutstandingHists) {
303 assert(stats.outstandingWriteReqs != 0);
304 --stats.outstandingWriteReqs;
305 }
306
307 if (!stats.disableLatencyHists) {
308 stats.writeLatencyHist.sample(latency);
309 }
310 } else if (successful) {
311 DPRINTF(CommMonitor, "Received non read/write response\n");
312 }
313 return successful;
314}
315
316void
317CommMonitor::recvTimingSnoopReq(PacketPtr pkt)
318{
319 slavePort.sendTimingSnoopReq(pkt);
320}
321
322bool
323CommMonitor::recvTimingSnoopResp(PacketPtr pkt)
324{
325 return masterPort.sendTimingSnoopResp(pkt);
326}
327
328bool
329CommMonitor::isSnooping() const
330{
331 // check if the connected master port is snooping
332 return slavePort.isSnooping();
333}
334
335unsigned
336CommMonitor::deviceBlockSizeMaster()
337{
338 return slavePort.peerBlockSize();
339}
340
341unsigned
342CommMonitor::deviceBlockSizeSlave()
343{
344 return masterPort.peerBlockSize();
345}
346
347AddrRangeList
348CommMonitor::getAddrRanges() const
349{
350 // get the address ranges of the connected slave port
351 return masterPort.getAddrRanges();
352}
353
354void
355CommMonitor::recvRetryMaster()
356{
357 slavePort.sendRetry();
358}
359
360void
361CommMonitor::recvRetrySlave()
362{
363 masterPort.sendRetry();
364}
365
366void
367CommMonitor::recvRangeChange()
368{
369 slavePort.sendRangeChange();
370}
371
372void
373CommMonitor::regStats()
374{
375 // Initialise all the monitor stats
376 using namespace Stats;
377
378 stats.readBurstLengthHist
379 .init(params()->burst_length_bins)
380 .name(name() + ".readBurstLengthHist")
381 .desc("Histogram of burst lengths of transmitted packets")
382 .flags(stats.disableBurstLengthHists ? nozero : pdf);
383
384 stats.writeBurstLengthHist
385 .init(params()->burst_length_bins)
386 .name(name() + ".writeBurstLengthHist")
387 .desc("Histogram of burst lengths of transmitted packets")
388 .flags(stats.disableBurstLengthHists ? nozero : pdf);
389
390 // Stats based on received responses
391 stats.readBandwidthHist
392 .init(params()->bandwidth_bins)
393 .name(name() + ".readBandwidthHist")
394 .desc("Histogram of read bandwidth per sample period (bytes/s)")
395 .flags(stats.disableBandwidthHists ? nozero : pdf);
396
397 stats.averageReadBW
398 .name(name() + ".averageReadBandwidth")
399 .desc("Average read bandwidth (bytes/s)")
400 .flags(stats.disableBandwidthHists ? nozero : pdf);
401
402 stats.totalReadBytes
403 .name(name() + ".totalReadBytes")
404 .desc("Number of bytes read")
405 .flags(stats.disableBandwidthHists ? nozero : pdf);
406
407 stats.averageReadBW = stats.totalReadBytes / simSeconds;
408
409 // Stats based on successfully sent requests
410 stats.writeBandwidthHist
411 .init(params()->bandwidth_bins)
412 .name(name() + ".writeBandwidthHist")
413 .desc("Histogram of write bandwidth (bytes/s)")
414 .flags(stats.disableBandwidthHists ? (pdf | nozero) : pdf);
415
416 stats.averageWriteBW
417 .name(name() + ".averageWriteBandwidth")
418 .desc("Average write bandwidth (bytes/s)")
419 .flags(stats.disableBandwidthHists ? nozero : pdf);
420
421 stats.totalWrittenBytes
422 .name(name() + ".totalWrittenBytes")
423 .desc("Number of bytes written")
424 .flags(stats.disableBandwidthHists ? nozero : pdf);
425
426 stats.averageWriteBW = stats.totalWrittenBytes / simSeconds;
427
428 stats.readLatencyHist
429 .init(params()->latency_bins)
430 .name(name() + ".readLatencyHist")
431 .desc("Read request-response latency")
432 .flags(stats.disableLatencyHists ? nozero : pdf);
433
434 stats.writeLatencyHist
435 .init(params()->latency_bins)
436 .name(name() + ".writeLatencyHist")
437 .desc("Write request-response latency")
438 .flags(stats.disableLatencyHists ? nozero : pdf);
439
440 stats.ittReadRead
441 .init(1, params()->itt_max_bin, params()->itt_max_bin /
442 params()->itt_bins)
443 .name(name() + ".ittReadRead")
444 .desc("Read-to-read inter transaction time")
445 .flags(stats.disableITTDists ? nozero : pdf);
446
447 stats.ittWriteWrite
448 .init(1, params()->itt_max_bin, params()->itt_max_bin /
449 params()->itt_bins)
450 .name(name() + ".ittWriteWrite")
451 .desc("Write-to-write inter transaction time")
452 .flags(stats.disableITTDists ? nozero : pdf);
453
454 stats.ittReqReq
455 .init(1, params()->itt_max_bin, params()->itt_max_bin /
456 params()->itt_bins)
457 .name(name() + ".ittReqReq")
458 .desc("Request-to-request inter transaction time")
459 .flags(stats.disableITTDists ? nozero : pdf);
460
461 stats.outstandingReadsHist
462 .init(params()->outstanding_bins)
463 .name(name() + ".outstandingReadsHist")
464 .desc("Outstanding read transactions")
465 .flags(stats.disableOutstandingHists ? nozero : pdf);
466
467 stats.outstandingWritesHist
468 .init(params()->outstanding_bins)
469 .name(name() + ".outstandingWritesHist")
470 .desc("Outstanding write transactions")
471 .flags(stats.disableOutstandingHists ? nozero : pdf);
472
473 stats.readTransHist
474 .init(params()->transaction_bins)
475 .name(name() + ".readTransHist")
476 .desc("Histogram of read transactions per sample period")
477 .flags(stats.disableTransactionHists ? nozero : pdf);
478
479 stats.writeTransHist
480 .init(params()->transaction_bins)
481 .name(name() + ".writeTransHist")
482 .desc("Histogram of read transactions per sample period")
483 .flags(stats.disableTransactionHists ? nozero : pdf);
484
485 stats.readAddrDist
486 .init(0)
487 .name(name() + ".readAddrDist")
488 .desc("Read address distribution")
489 .flags(stats.disableAddrDists ? nozero : pdf);
490
491 stats.writeAddrDist
492 .init(0)
493 .name(name() + ".writeAddrDist")
494 .desc("Write address distribution")
495 .flags(stats.disableAddrDists ? nozero : pdf);
496}
497
498void
499CommMonitor::samplePeriodic()
500{
501 // the periodic stats update runs on the granularity of sample
502 // periods, but in combination with this there may also be a
503 // external resets and dumps of the stats (through schedStatEvent)
504 // causing the stats themselves to capture less than a sample
505 // period
506
507 // only capture if we have not reset the stats during the last
508 // sample period
509 if (simTicks.value() >= samplePeriodTicks) {
510 if (!stats.disableTransactionHists) {
511 stats.readTransHist.sample(stats.readTrans);
512 stats.writeTransHist.sample(stats.writeTrans);
513 }
514
515 if (!stats.disableBandwidthHists) {
516 stats.readBandwidthHist.sample(stats.readBytes / samplePeriod);
517 stats.writeBandwidthHist.sample(stats.writtenBytes / samplePeriod);
518 }
519
520 if (!stats.disableOutstandingHists) {
521 stats.outstandingReadsHist.sample(stats.outstandingReadReqs);
522 stats.outstandingWritesHist.sample(stats.outstandingWriteReqs);
523 }
524 }
525
526 // reset the sampled values
527 stats.readTrans = 0;
528 stats.writeTrans = 0;
529
530 stats.readBytes = 0;
531 stats.writtenBytes = 0;
532
533 schedule(samplePeriodicEvent, curTick() + samplePeriodTicks);
534}
535
536void
537CommMonitor::startup()
538{
539 schedule(samplePeriodicEvent, curTick() + samplePeriodTicks);
540}
42#include "debug/CommMonitor.hh"
43#include "mem/comm_monitor.hh"
44#include "sim/stats.hh"
45
46CommMonitor::CommMonitor(Params* params)
47 : MemObject(params),
48 masterPort(name() + "-master", *this),
49 slavePort(name() + "-slave", *this),
50 samplePeriodicEvent(this),
51 samplePeriodTicks(params->sample_period),
52 readAddrMask(params->read_addr_mask),
53 writeAddrMask(params->write_addr_mask),
54 stats(params)
55{
56 // keep track of the sample period both in ticks and absolute time
57 samplePeriod.setTick(params->sample_period);
58
59 DPRINTF(CommMonitor,
60 "Created monitor %s with sample period %d ticks (%f s)\n",
61 name(), samplePeriodTicks, samplePeriod);
62}
63
64CommMonitor*
65CommMonitorParams::create()
66{
67 return new CommMonitor(this);
68}
69
70void
71CommMonitor::init()
72{
73 // make sure both sides of the monitor are connected
74 if (!slavePort.isConnected() || !masterPort.isConnected())
75 fatal("Communication monitor is not connected on both sides.\n");
76}
77
78BaseMasterPort&
79CommMonitor::getMasterPort(const std::string& if_name, PortID idx)
80{
81 if (if_name == "master") {
82 return masterPort;
83 } else {
84 return MemObject::getMasterPort(if_name, idx);
85 }
86}
87
88BaseSlavePort&
89CommMonitor::getSlavePort(const std::string& if_name, PortID idx)
90{
91 if (if_name == "slave") {
92 return slavePort;
93 } else {
94 return MemObject::getSlavePort(if_name, idx);
95 }
96}
97
98void
99CommMonitor::recvFunctional(PacketPtr pkt)
100{
101 masterPort.sendFunctional(pkt);
102}
103
104void
105CommMonitor::recvFunctionalSnoop(PacketPtr pkt)
106{
107 slavePort.sendFunctionalSnoop(pkt);
108}
109
110Tick
111CommMonitor::recvAtomic(PacketPtr pkt)
112{
113 return masterPort.sendAtomic(pkt);
114}
115
116Tick
117CommMonitor::recvAtomicSnoop(PacketPtr pkt)
118{
119 return slavePort.sendAtomicSnoop(pkt);
120}
121
122bool
123CommMonitor::recvTimingReq(PacketPtr pkt)
124{
125 // should always see a request
126 assert(pkt->isRequest());
127
128 // Store relevant fields of packet, because packet may be modified
129 // or even deleted when sendTiming() is called.
130 bool isRead = pkt->isRead();
131 bool isWrite = pkt->isWrite();
132 unsigned size = pkt->getSize();
133 Addr addr = pkt->getAddr();
134 bool needsResponse = pkt->needsResponse();
135 bool memInhibitAsserted = pkt->memInhibitAsserted();
136 Packet::SenderState* senderState = pkt->senderState;
137
138 // If a cache miss is served by a cache, a monitor near the memory
139 // would see a request which needs a response, but this response
140 // would be inhibited and not come back from the memory. Therefore
141 // we additionally have to check the inhibit flag.
142 if (needsResponse && !memInhibitAsserted && !stats.disableLatencyHists) {
143 pkt->senderState = new CommMonitorSenderState(senderState,
144 curTick());
145 }
146
147 // Attempt to send the packet (always succeeds for inhibited
148 // packets)
149 bool successful = masterPort.sendTimingReq(pkt);
150
151 // If not successful, restore the sender state
152 if (!successful && needsResponse && !stats.disableLatencyHists) {
153 delete pkt->senderState;
154 pkt->senderState = senderState;
155 }
156
157 if (successful && isRead) {
158 DPRINTF(CommMonitor, "Forwarded read request\n");
159
160 // Increment number of observed read transactions
161 if (!stats.disableTransactionHists) {
162 ++stats.readTrans;
163 }
164
165 // Get sample of burst length
166 if (!stats.disableBurstLengthHists) {
167 stats.readBurstLengthHist.sample(size);
168 }
169
170 // Sample the masked address
171 if (!stats.disableAddrDists) {
172 stats.readAddrDist.sample(addr & readAddrMask);
173 }
174
175 // If it needs a response increment number of outstanding read
176 // requests
177 if (!stats.disableOutstandingHists && needsResponse) {
178 ++stats.outstandingReadReqs;
179 }
180
181 if (!stats.disableITTDists) {
182 // Sample value of read-read inter transaction time
183 if (stats.timeOfLastRead != 0) {
184 stats.ittReadRead.sample(curTick() - stats.timeOfLastRead);
185 }
186 stats.timeOfLastRead = curTick();
187
188 // Sample value of req-req inter transaction time
189 if (stats.timeOfLastReq != 0) {
190 stats.ittReqReq.sample(curTick() - stats.timeOfLastReq);
191 }
192 stats.timeOfLastReq = curTick();
193 }
194 } else if (successful && isWrite) {
195 DPRINTF(CommMonitor, "Forwarded write request\n");
196
197 // Same as for reads
198 if (!stats.disableTransactionHists) {
199 ++stats.writeTrans;
200 }
201
202 if (!stats.disableBurstLengthHists) {
203 stats.writeBurstLengthHist.sample(size);
204 }
205
206 // Update the bandwidth stats on the request
207 if (!stats.disableBandwidthHists) {
208 stats.writtenBytes += size;
209 stats.totalWrittenBytes += size;
210 }
211
212 // Sample the masked write address
213 if (!stats.disableAddrDists) {
214 stats.writeAddrDist.sample(addr & writeAddrMask);
215 }
216
217 if (!stats.disableOutstandingHists && needsResponse) {
218 ++stats.outstandingWriteReqs;
219 }
220
221 if (!stats.disableITTDists) {
222 // Sample value of write-to-write inter transaction time
223 if (stats.timeOfLastWrite != 0) {
224 stats.ittWriteWrite.sample(curTick() - stats.timeOfLastWrite);
225 }
226 stats.timeOfLastWrite = curTick();
227
228 // Sample value of req-to-req inter transaction time
229 if (stats.timeOfLastReq != 0) {
230 stats.ittReqReq.sample(curTick() - stats.timeOfLastReq);
231 }
232 stats.timeOfLastReq = curTick();
233 }
234 } else if (successful) {
235 DPRINTF(CommMonitor, "Forwarded non read/write request\n");
236 }
237
238 return successful;
239}
240
241bool
242CommMonitor::recvTimingResp(PacketPtr pkt)
243{
244 // should always see responses
245 assert(pkt->isResponse());
246
247 // Store relevant fields of packet, because packet may be modified
248 // or even deleted when sendTiming() is called.
249 bool isRead = pkt->isRead();
250 bool isWrite = pkt->isWrite();
251 unsigned size = pkt->getSize();
252 Tick latency = 0;
253 CommMonitorSenderState* commReceivedState =
254 dynamic_cast<CommMonitorSenderState*>(pkt->senderState);
255
256 if (!stats.disableLatencyHists) {
257 // Restore initial sender state
258 if (commReceivedState == NULL)
259 panic("Monitor got a response without monitor sender state\n");
260
261 // Restore the sate
262 pkt->senderState = commReceivedState->origSenderState;
263 }
264
265 // Attempt to send the packet
266 bool successful = slavePort.sendTimingResp(pkt);
267
268 if (!stats.disableLatencyHists) {
269 // If packet successfully send, sample value of latency,
270 // afterwards delete sender state, otherwise restore state
271 if (successful) {
272 latency = curTick() - commReceivedState->transmitTime;
273 DPRINTF(CommMonitor, "Latency: %d\n", latency);
274 delete commReceivedState;
275 } else {
276 // Don't delete anything and let the packet look like we
277 // did not touch it
278 pkt->senderState = commReceivedState;
279 }
280 }
281
282 if (successful && isRead) {
283 // Decrement number of outstanding read requests
284 DPRINTF(CommMonitor, "Received read response\n");
285 if (!stats.disableOutstandingHists) {
286 assert(stats.outstandingReadReqs != 0);
287 --stats.outstandingReadReqs;
288 }
289
290 if (!stats.disableLatencyHists) {
291 stats.readLatencyHist.sample(latency);
292 }
293
294 // Update the bandwidth stats based on responses for reads
295 if (!stats.disableBandwidthHists) {
296 stats.readBytes += size;
297 stats.totalReadBytes += size;
298 }
299
300 } else if (successful && isWrite) {
301 // Decrement number of outstanding write requests
302 DPRINTF(CommMonitor, "Received write response\n");
303 if (!stats.disableOutstandingHists) {
304 assert(stats.outstandingWriteReqs != 0);
305 --stats.outstandingWriteReqs;
306 }
307
308 if (!stats.disableLatencyHists) {
309 stats.writeLatencyHist.sample(latency);
310 }
311 } else if (successful) {
312 DPRINTF(CommMonitor, "Received non read/write response\n");
313 }
314 return successful;
315}
316
317void
318CommMonitor::recvTimingSnoopReq(PacketPtr pkt)
319{
320 slavePort.sendTimingSnoopReq(pkt);
321}
322
323bool
324CommMonitor::recvTimingSnoopResp(PacketPtr pkt)
325{
326 return masterPort.sendTimingSnoopResp(pkt);
327}
328
329bool
330CommMonitor::isSnooping() const
331{
332 // check if the connected master port is snooping
333 return slavePort.isSnooping();
334}
335
336unsigned
337CommMonitor::deviceBlockSizeMaster()
338{
339 return slavePort.peerBlockSize();
340}
341
342unsigned
343CommMonitor::deviceBlockSizeSlave()
344{
345 return masterPort.peerBlockSize();
346}
347
348AddrRangeList
349CommMonitor::getAddrRanges() const
350{
351 // get the address ranges of the connected slave port
352 return masterPort.getAddrRanges();
353}
354
355void
356CommMonitor::recvRetryMaster()
357{
358 slavePort.sendRetry();
359}
360
361void
362CommMonitor::recvRetrySlave()
363{
364 masterPort.sendRetry();
365}
366
367void
368CommMonitor::recvRangeChange()
369{
370 slavePort.sendRangeChange();
371}
372
373void
374CommMonitor::regStats()
375{
376 // Initialise all the monitor stats
377 using namespace Stats;
378
379 stats.readBurstLengthHist
380 .init(params()->burst_length_bins)
381 .name(name() + ".readBurstLengthHist")
382 .desc("Histogram of burst lengths of transmitted packets")
383 .flags(stats.disableBurstLengthHists ? nozero : pdf);
384
385 stats.writeBurstLengthHist
386 .init(params()->burst_length_bins)
387 .name(name() + ".writeBurstLengthHist")
388 .desc("Histogram of burst lengths of transmitted packets")
389 .flags(stats.disableBurstLengthHists ? nozero : pdf);
390
391 // Stats based on received responses
392 stats.readBandwidthHist
393 .init(params()->bandwidth_bins)
394 .name(name() + ".readBandwidthHist")
395 .desc("Histogram of read bandwidth per sample period (bytes/s)")
396 .flags(stats.disableBandwidthHists ? nozero : pdf);
397
398 stats.averageReadBW
399 .name(name() + ".averageReadBandwidth")
400 .desc("Average read bandwidth (bytes/s)")
401 .flags(stats.disableBandwidthHists ? nozero : pdf);
402
403 stats.totalReadBytes
404 .name(name() + ".totalReadBytes")
405 .desc("Number of bytes read")
406 .flags(stats.disableBandwidthHists ? nozero : pdf);
407
408 stats.averageReadBW = stats.totalReadBytes / simSeconds;
409
410 // Stats based on successfully sent requests
411 stats.writeBandwidthHist
412 .init(params()->bandwidth_bins)
413 .name(name() + ".writeBandwidthHist")
414 .desc("Histogram of write bandwidth (bytes/s)")
415 .flags(stats.disableBandwidthHists ? (pdf | nozero) : pdf);
416
417 stats.averageWriteBW
418 .name(name() + ".averageWriteBandwidth")
419 .desc("Average write bandwidth (bytes/s)")
420 .flags(stats.disableBandwidthHists ? nozero : pdf);
421
422 stats.totalWrittenBytes
423 .name(name() + ".totalWrittenBytes")
424 .desc("Number of bytes written")
425 .flags(stats.disableBandwidthHists ? nozero : pdf);
426
427 stats.averageWriteBW = stats.totalWrittenBytes / simSeconds;
428
429 stats.readLatencyHist
430 .init(params()->latency_bins)
431 .name(name() + ".readLatencyHist")
432 .desc("Read request-response latency")
433 .flags(stats.disableLatencyHists ? nozero : pdf);
434
435 stats.writeLatencyHist
436 .init(params()->latency_bins)
437 .name(name() + ".writeLatencyHist")
438 .desc("Write request-response latency")
439 .flags(stats.disableLatencyHists ? nozero : pdf);
440
441 stats.ittReadRead
442 .init(1, params()->itt_max_bin, params()->itt_max_bin /
443 params()->itt_bins)
444 .name(name() + ".ittReadRead")
445 .desc("Read-to-read inter transaction time")
446 .flags(stats.disableITTDists ? nozero : pdf);
447
448 stats.ittWriteWrite
449 .init(1, params()->itt_max_bin, params()->itt_max_bin /
450 params()->itt_bins)
451 .name(name() + ".ittWriteWrite")
452 .desc("Write-to-write inter transaction time")
453 .flags(stats.disableITTDists ? nozero : pdf);
454
455 stats.ittReqReq
456 .init(1, params()->itt_max_bin, params()->itt_max_bin /
457 params()->itt_bins)
458 .name(name() + ".ittReqReq")
459 .desc("Request-to-request inter transaction time")
460 .flags(stats.disableITTDists ? nozero : pdf);
461
462 stats.outstandingReadsHist
463 .init(params()->outstanding_bins)
464 .name(name() + ".outstandingReadsHist")
465 .desc("Outstanding read transactions")
466 .flags(stats.disableOutstandingHists ? nozero : pdf);
467
468 stats.outstandingWritesHist
469 .init(params()->outstanding_bins)
470 .name(name() + ".outstandingWritesHist")
471 .desc("Outstanding write transactions")
472 .flags(stats.disableOutstandingHists ? nozero : pdf);
473
474 stats.readTransHist
475 .init(params()->transaction_bins)
476 .name(name() + ".readTransHist")
477 .desc("Histogram of read transactions per sample period")
478 .flags(stats.disableTransactionHists ? nozero : pdf);
479
480 stats.writeTransHist
481 .init(params()->transaction_bins)
482 .name(name() + ".writeTransHist")
483 .desc("Histogram of read transactions per sample period")
484 .flags(stats.disableTransactionHists ? nozero : pdf);
485
486 stats.readAddrDist
487 .init(0)
488 .name(name() + ".readAddrDist")
489 .desc("Read address distribution")
490 .flags(stats.disableAddrDists ? nozero : pdf);
491
492 stats.writeAddrDist
493 .init(0)
494 .name(name() + ".writeAddrDist")
495 .desc("Write address distribution")
496 .flags(stats.disableAddrDists ? nozero : pdf);
497}
498
499void
500CommMonitor::samplePeriodic()
501{
502 // the periodic stats update runs on the granularity of sample
503 // periods, but in combination with this there may also be a
504 // external resets and dumps of the stats (through schedStatEvent)
505 // causing the stats themselves to capture less than a sample
506 // period
507
508 // only capture if we have not reset the stats during the last
509 // sample period
510 if (simTicks.value() >= samplePeriodTicks) {
511 if (!stats.disableTransactionHists) {
512 stats.readTransHist.sample(stats.readTrans);
513 stats.writeTransHist.sample(stats.writeTrans);
514 }
515
516 if (!stats.disableBandwidthHists) {
517 stats.readBandwidthHist.sample(stats.readBytes / samplePeriod);
518 stats.writeBandwidthHist.sample(stats.writtenBytes / samplePeriod);
519 }
520
521 if (!stats.disableOutstandingHists) {
522 stats.outstandingReadsHist.sample(stats.outstandingReadReqs);
523 stats.outstandingWritesHist.sample(stats.outstandingWriteReqs);
524 }
525 }
526
527 // reset the sampled values
528 stats.readTrans = 0;
529 stats.writeTrans = 0;
530
531 stats.readBytes = 0;
532 stats.writtenBytes = 0;
533
534 schedule(samplePeriodicEvent, curTick() + samplePeriodTicks);
535}
536
537void
538CommMonitor::startup()
539{
540 schedule(samplePeriodicEvent, curTick() + samplePeriodTicks);
541}