2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "mem/ruby/profiler/MemCntrlProfiler.hh"
33 MemCntrlProfiler::MemCntrlProfiler(const string
& description
,
34 int banks_per_rank
, int ranks_per_dimm
, int dimms_per_channel
)
36 m_description
= description
;
37 m_banks_per_rank
= banks_per_rank
;
38 m_ranks_per_dimm
= ranks_per_dimm
;
39 m_dimms_per_channel
= dimms_per_channel
;
41 int totalBanks
= banks_per_rank
* ranks_per_dimm
* dimms_per_channel
;
42 m_memBankCount
.resize(totalBanks
);
47 MemCntrlProfiler::~MemCntrlProfiler()
52 MemCntrlProfiler::printStats(ostream
& out
) const
54 if (!m_memReq
&& !m_memRefresh
) {
55 out
<< "Memory Controller: " << m_description
56 << " no stats recorded." << endl
62 // if there's a memory controller at all
63 uint64 total_stalls
= m_memInputQ
+ m_memBankQ
+ m_memWaitCycles
;
64 double stallsPerReq
= total_stalls
* 1.0 / m_memReq
;
65 out
<< "Memory controller: " << m_description
<< ":" << endl
;
67 // does not include refreshes
68 out
<< " memory_total_requests: " << m_memReq
<< endl
;
69 out
<< " memory_reads: " << m_memRead
<< endl
;
70 out
<< " memory_writes: " << m_memWrite
<< endl
;
71 out
<< " memory_refreshes: " << m_memRefresh
<< endl
;
72 out
<< " memory_total_request_delays: " << total_stalls
<< endl
;
73 out
<< " memory_delays_per_request: " << stallsPerReq
<< endl
;
74 out
<< " memory_delays_in_input_queue: " << m_memInputQ
<< endl
;
75 out
<< " memory_delays_behind_head_of_bank_queue: "
76 << m_memBankQ
<< endl
;
77 out
<< " memory_delays_stalled_at_head_of_bank_queue: "
78 << m_memWaitCycles
<< endl
;
80 // Note: The following "memory stalls" entries are a breakdown of
81 // the cycles which already showed up in m_memWaitCycles. The
82 // order is significant; it is the priority of attributing the
83 // cycles. For example, bank_busy is before arbitration because
84 // if the bank was busy, we didn't even check arbitration.
85 // Note: "not old enough" means that since we grouped waiting
86 // heads-of-queues into batches to avoid starvation, a request in
87 // a newer batch didn't try to arbitrate yet because there are
88 // older requests waiting.
89 out
<< " memory_stalls_for_bank_busy: " << m_memBankBusy
<< endl
;
90 out
<< " memory_stalls_for_random_busy: " << m_memRandBusy
<< endl
;
91 out
<< " memory_stalls_for_anti_starvation: " << m_memNotOld
<< endl
;
92 out
<< " memory_stalls_for_arbitration: " << m_memArbWait
<< endl
;
93 out
<< " memory_stalls_for_bus: " << m_memBusBusy
<< endl
;
94 out
<< " memory_stalls_for_tfaw: " << m_memTfawBusy
<< endl
;
95 out
<< " memory_stalls_for_read_write_turnaround: "
96 << m_memReadWriteBusy
<< endl
;
97 out
<< " memory_stalls_for_read_read_turnaround: "
98 << m_memDataBusBusy
<< endl
;
99 out
<< " accesses_per_bank: ";
101 for (int bank
= 0; bank
< m_memBankCount
.size(); bank
++) {
102 out
<< m_memBankCount
[bank
] << " ";
109 MemCntrlProfiler::clearStats()
115 m_memReadWriteBusy
= 0;
116 m_memDataBusBusy
= 0;
127 for (int bank
= 0; bank
< m_memBankCount
.size(); bank
++) {
128 m_memBankCount
[bank
] = 0;
133 MemCntrlProfiler::profileMemReq(int bank
)
136 m_memBankCount
[bank
]++;
140 MemCntrlProfiler::profileMemBankBusy()
146 MemCntrlProfiler::profileMemBusBusy()
152 MemCntrlProfiler::profileMemReadWriteBusy()
154 m_memReadWriteBusy
++;
158 MemCntrlProfiler::profileMemDataBusBusy()
164 MemCntrlProfiler::profileMemTfawBusy()
170 MemCntrlProfiler::profileMemRefresh()
176 MemCntrlProfiler::profileMemRead()
182 MemCntrlProfiler::profileMemWrite()
188 MemCntrlProfiler::profileMemWaitCycles(int cycles
)
190 m_memWaitCycles
+= cycles
;
194 MemCntrlProfiler::profileMemInputQ(int cycles
)
196 m_memInputQ
+= cycles
;
200 MemCntrlProfiler::profileMemBankQ(int cycles
)
202 m_memBankQ
+= cycles
;
206 MemCntrlProfiler::profileMemArbWait(int cycles
)
208 m_memArbWait
+= cycles
;
212 MemCntrlProfiler::profileMemRandBusy()
218 MemCntrlProfiler::profileMemNotOld()