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.
31 #include "base/stl_helpers.hh"
32 #include "mem/protocol/RubyRequest.hh"
33 #include "mem/ruby/profiler/AddressProfiler.hh"
34 #include "mem/ruby/profiler/Profiler.hh"
35 #include "mem/ruby/system/System.hh"
38 typedef AddressProfiler::AddressMap AddressMap
;
40 using m5::stl_helpers::operator<<;
43 AccessTraceForAddress
&
44 lookupTraceForAddress(const Address
& addr
, AddressMap
& record_map
)
46 // we create a static default object here that is used to insert
47 // since the insertion will create a copy of the object in the
48 // process. Perhaps this is optimizing early, but it doesn't seem
49 // like it could hurt.
50 static const AccessTraceForAddress dflt
;
52 pair
<AddressMap::iterator
, bool> r
=
53 record_map
.insert(make_pair(addr
, dflt
));
54 AddressMap::iterator i
= r
.first
;
55 AccessTraceForAddress
&access_trace
= i
->second
;
57 // there was nothing there and the insert succeed, so we need
58 // to actually set the address.
59 access_trace
.setAddress(addr
);
66 printSorted(ostream
& out
, int num_of_sequencers
, const AddressMap
&record_map
,
69 const int records_printed
= 100;
72 std::vector
<const AccessTraceForAddress
*> sorted
;
74 AddressMap::const_iterator i
= record_map
.begin();
75 AddressMap::const_iterator end
= record_map
.end();
76 for (; i
!= end
; ++i
) {
77 const AccessTraceForAddress
* record
= &i
->second
;
78 misses
+= record
->getTotal();
79 sorted
.push_back(record
);
81 sort(sorted
.begin(), sorted
.end(), AccessTraceForAddress::less_equal
);
83 out
<< "Total_entries_" << description
<< ": " << record_map
.size()
85 if (g_system_ptr
->getProfiler()->getAllInstructions())
86 out
<< "Total_Instructions_" << description
<< ": " << misses
<< endl
;
88 out
<< "Total_data_misses_" << description
<< ": " << misses
<< endl
;
90 out
<< "total | load store atomic | user supervisor | sharing | touched-by"
93 Histogram
remaining_records(1, 100);
94 Histogram
all_records(1, 100);
95 Histogram
remaining_records_log(-1);
96 Histogram
all_records_log(-1);
98 // Allows us to track how many lines where touched by n processors
99 std::vector
<int64
> m_touched_vec
;
100 std::vector
<int64
> m_touched_weighted_vec
;
101 m_touched_vec
.resize(num_of_sequencers
+1);
102 m_touched_weighted_vec
.resize(num_of_sequencers
+1);
103 for (int j
= 0; j
< m_touched_vec
.size(); j
++) {
104 m_touched_vec
[j
] = 0;
105 m_touched_weighted_vec
[j
] = 0;
109 int max
= sorted
.size();
110 while (counter
< max
&& counter
< records_printed
) {
111 const AccessTraceForAddress
* record
= sorted
[counter
];
112 double percent
= 100.0 * (record
->getTotal() / double(misses
));
113 out
<< description
<< " | " << percent
<< " % " << *record
<< endl
;
114 all_records
.add(record
->getTotal());
115 all_records_log
.add(record
->getTotal());
117 m_touched_vec
[record
->getTouchedBy()]++;
118 m_touched_weighted_vec
[record
->getTouchedBy()] += record
->getTotal();
121 while (counter
< max
) {
122 const AccessTraceForAddress
* record
= sorted
[counter
];
123 all_records
.add(record
->getTotal());
124 remaining_records
.add(record
->getTotal());
125 all_records_log
.add(record
->getTotal());
126 remaining_records_log
.add(record
->getTotal());
127 m_touched_vec
[record
->getTouchedBy()]++;
128 m_touched_weighted_vec
[record
->getTouchedBy()] += record
->getTotal();
131 out
<< "all_records_" << description
<< ": "
132 << all_records
<< endl
133 << "all_records_log_" << description
<< ": "
134 << all_records_log
<< endl
135 << "remaining_records_" << description
<< ": "
136 << remaining_records
<< endl
137 << "remaining_records_log_" << description
<< ": "
138 << remaining_records_log
<< endl
139 << "touched_by_" << description
<< ": "
140 << m_touched_vec
<< endl
141 << "touched_by_weighted_" << description
<< ": "
142 << m_touched_weighted_vec
<< endl
146 AddressProfiler::AddressProfiler(int num_of_sequencers
)
148 m_num_of_sequencers
= num_of_sequencers
;
152 AddressProfiler::~AddressProfiler()
157 AddressProfiler::setHotLines(bool hot_lines
)
159 m_hot_lines
= hot_lines
;
163 AddressProfiler::setAllInstructions(bool all_instructions
)
165 m_all_instructions
= all_instructions
;
169 AddressProfiler::printStats(ostream
& out
) const
173 out
<< "AddressProfiler Stats" << endl
;
174 out
<< "---------------------" << endl
;
177 out
<< "sharing_misses: " << m_sharing_miss_counter
<< endl
;
178 out
<< "getx_sharing_histogram: " << m_getx_sharing_histogram
<< endl
;
179 out
<< "gets_sharing_histogram: " << m_gets_sharing_histogram
<< endl
;
182 out
<< "Hot Data Blocks" << endl
;
183 out
<< "---------------" << endl
;
185 printSorted(out
, m_num_of_sequencers
, m_dataAccessTrace
,
189 out
<< "Hot MacroData Blocks" << endl
;
190 out
<< "--------------------" << endl
;
192 printSorted(out
, m_num_of_sequencers
, m_macroBlockAccessTrace
,
193 "macroblock_address");
195 out
<< "Hot Instructions" << endl
;
196 out
<< "----------------" << endl
;
198 printSorted(out
, m_num_of_sequencers
, m_programCounterAccessTrace
,
202 if (m_all_instructions
) {
204 out
<< "All Instructions Profile:" << endl
;
205 out
<< "-------------------------" << endl
;
207 printSorted(out
, m_num_of_sequencers
, m_programCounterAccessTrace
,
212 if (m_retryProfileHisto
.size() > 0) {
213 out
<< "Retry Profile" << endl
;
214 out
<< "-------------" << endl
;
216 out
<< "retry_histogram_absolute: " << m_retryProfileHisto
<< endl
;
217 out
<< "retry_histogram_write: " << m_retryProfileHistoWrite
<< endl
;
218 out
<< "retry_histogram_read: " << m_retryProfileHistoRead
<< endl
;
220 out
<< "retry_histogram_percent: ";
221 m_retryProfileHisto
.printPercent(out
);
224 printSorted(out
, m_num_of_sequencers
, m_retryProfileMap
,
231 AddressProfiler::clearStats()
234 m_sharing_miss_counter
= 0;
235 m_dataAccessTrace
.clear();
236 m_macroBlockAccessTrace
.clear();
237 m_programCounterAccessTrace
.clear();
238 m_retryProfileMap
.clear();
239 m_retryProfileHisto
.clear();
240 m_retryProfileHistoRead
.clear();
241 m_retryProfileHistoWrite
.clear();
242 m_getx_sharing_histogram
.clear();
243 m_gets_sharing_histogram
.clear();
247 AddressProfiler::profileGetX(const Address
& datablock
, const Address
& PC
,
248 const Set
& owner
, const Set
& sharers
,
252 indirection_set
.addSet(sharers
);
253 indirection_set
.addSet(owner
);
254 indirection_set
.remove(requestor
);
255 int num_indirections
= indirection_set
.count();
257 m_getx_sharing_histogram
.add(num_indirections
);
258 bool indirection_miss
= (num_indirections
> 0);
260 addTraceSample(datablock
, PC
, RubyRequestType_ST
, RubyAccessMode(0),
261 requestor
, indirection_miss
);
265 AddressProfiler::profileGetS(const Address
& datablock
, const Address
& PC
,
266 const Set
& owner
, const Set
& sharers
,
270 indirection_set
.addSet(owner
);
271 indirection_set
.remove(requestor
);
272 int num_indirections
= indirection_set
.count();
274 m_gets_sharing_histogram
.add(num_indirections
);
275 bool indirection_miss
= (num_indirections
> 0);
277 addTraceSample(datablock
, PC
, RubyRequestType_LD
, RubyAccessMode(0),
278 requestor
, indirection_miss
);
282 AddressProfiler::addTraceSample(Address data_addr
, Address pc_addr
,
283 RubyRequestType type
,
284 RubyAccessMode access_mode
, NodeID id
,
287 if (m_all_instructions
) {
289 m_sharing_miss_counter
++;
292 // record data address trace info
293 data_addr
.makeLineAddress();
294 lookupTraceForAddress(data_addr
, m_dataAccessTrace
).
295 update(type
, access_mode
, id
, sharing_miss
);
297 // record macro data address trace info
299 // 6 for datablock, 4 to make it 16x more coarse
300 Address
macro_addr(data_addr
.maskLowOrderBits(10));
301 lookupTraceForAddress(macro_addr
, m_macroBlockAccessTrace
).
302 update(type
, access_mode
, id
, sharing_miss
);
304 // record program counter address trace info
305 lookupTraceForAddress(pc_addr
, m_programCounterAccessTrace
).
306 update(type
, access_mode
, id
, sharing_miss
);
309 if (m_all_instructions
) {
310 // This code is used if the address profiler is an
311 // all-instructions profiler record program counter address
313 lookupTraceForAddress(pc_addr
, m_programCounterAccessTrace
).
314 update(type
, access_mode
, id
, sharing_miss
);
319 AddressProfiler::profileRetry(const Address
& data_addr
, AccessType type
,
322 m_retryProfileHisto
.add(count
);
323 if (type
== AccessType_Read
) {
324 m_retryProfileHistoRead
.add(count
);
326 m_retryProfileHistoWrite
.add(count
);
329 lookupTraceForAddress(data_addr
, m_retryProfileMap
).addSample(count
);