1/*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * All rights reserved.
4 *
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;

--- 14 unchanged lines hidden (view full) ---

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.
27 */
28
29#include "base/str.hh"
30#include "cpu/rubytest/RubyTester.hh"
31#include "mem/gems_common/Map.hh"
31#include "mem/protocol/CacheMsg.hh"
32#include "mem/protocol/Protocol.hh"
33#include "mem/protocol/Protocol.hh"
34#include "mem/ruby/buffers/MessageBuffer.hh"
35#include "mem/ruby/common/Global.hh"
36#include "mem/ruby/common/SubBlock.hh"
37#include "mem/ruby/libruby.hh"
38#include "mem/ruby/profiler/Profiler.hh"

--- 47 unchanged lines hidden (view full) ---

86Sequencer::wakeup()
87{
88 // Check for deadlock of any of the requests
89 Time current_time = g_eventQueue_ptr->getTime();
90
91 // Check across all outstanding requests
92 int total_outstanding = 0;
93
95 std::vector<Address> keys = m_readRequestTable.keys();
96 for (int i = 0; i < keys.size(); i++) {
97 SequencerRequest* request = m_readRequestTable.lookup(keys[i]);
98 if (current_time - request->issue_time >= m_deadlock_threshold) {
99 WARN_MSG("Possible Deadlock detected");
100 WARN_EXPR(request);
101 WARN_EXPR(m_version);
102 WARN_EXPR(request->ruby_request.paddr);
103 WARN_EXPR(keys.size());
104 WARN_EXPR(current_time);
105 WARN_EXPR(request->issue_time);
106 WARN_EXPR(current_time - request->issue_time);
107 ERROR_MSG("Aborting");
108 }
94 RequestTable::iterator read = m_readRequestTable.begin();
95 RequestTable::iterator read_end = m_readRequestTable.end();
96 for (; read != read_end; ++read) {
97 SequencerRequest* request = read->second;
98 if (current_time - request->issue_time < m_deadlock_threshold)
99 continue;
100
101 WARN_MSG("Possible Deadlock detected");
102 WARN_EXPR(request);
103 WARN_EXPR(m_version);
104 WARN_EXPR(request->ruby_request.paddr);
105 WARN_EXPR(m_readRequestTable.size());
106 WARN_EXPR(current_time);
107 WARN_EXPR(request->issue_time);
108 WARN_EXPR(current_time - request->issue_time);
109 ERROR_MSG("Aborting");
110 }
111
111 keys = m_writeRequestTable.keys();
112 for (int i = 0; i < keys.size(); i++) {
113 SequencerRequest* request = m_writeRequestTable.lookup(keys[i]);
114 if (current_time - request->issue_time >= m_deadlock_threshold) {
115 WARN_MSG("Possible Deadlock detected");
116 WARN_EXPR(request);
117 WARN_EXPR(m_version);
118 WARN_EXPR(current_time);
119 WARN_EXPR(request->issue_time);
120 WARN_EXPR(current_time - request->issue_time);
121 WARN_EXPR(keys.size());
122 ERROR_MSG("Aborting");
123 }
112 RequestTable::iterator write = m_writeRequestTable.begin();
113 RequestTable::iterator write_end = m_writeRequestTable.end();
114 for (; write != write_end; ++write) {
115 SequencerRequest* request = write->second;
116 if (current_time - request->issue_time < m_deadlock_threshold)
117 continue;
118
119 WARN_MSG("Possible Deadlock detected");
120 WARN_EXPR(request);
121 WARN_EXPR(m_version);
122 WARN_EXPR(current_time);
123 WARN_EXPR(request->issue_time);
124 WARN_EXPR(current_time - request->issue_time);
125 WARN_EXPR(m_writeRequestTable.size());
126 ERROR_MSG("Aborting");
127 }
128
129 total_outstanding += m_writeRequestTable.size();
130 total_outstanding += m_readRequestTable.size();
131
132 assert(m_outstanding_count == total_outstanding);
133
134 if (m_outstanding_count > 0) {

--- 23 unchanged lines hidden (view full) ---

158{
159#if 0
160 int total_demand = 0;
161 out << "Sequencer Stats Version " << m_version << endl;
162 out << "Current time = " << g_eventQueue_ptr->getTime() << endl;
163 out << "---------------" << endl;
164 out << "outstanding requests" << endl;
165
163 std::vector<Address> rkeys = m_readRequestTable.keys();
164 int read_size = rkeys.size();
165 out << "proc " << m_version << " Read Requests = " << read_size << endl;
166 out << "proc " << m_Read
167 << " version Requests = " << m_readRequestTable.size() << endl;
168
169 // print the request table
168 for (int i = 0; i < read_size; ++i) {
169 SequencerRequest *request = m_readRequestTable.lookup(rkeys[i]);
170 RequestTable::iterator read = m_readRequestTable.begin();
171 RequestTable::iterator read_end = m_readRequestTable.end();
172 for (; read != read_end; ++read) {
173 SequencerRequest* request = read->second;
174 out << "\tRequest[ " << i << " ] = " << request->type
175 << " Address " << rkeys[i]
176 << " Posted " << request->issue_time
177 << " PF " << PrefetchBit_No << endl;
178 total_demand++;
179 }
180
177 std::vector<Address> wkeys = m_writeRequestTable.keys();
178 int write_size = wkeys.size();
179 out << "proc " << m_version << " Write Requests = " << write_size << endl;
181 out << "proc " << m_version
182 << " Write Requests = " << m_writeRequestTable.size << endl;
183
184 // print the request table
182 for (int i = 0; i < write_size; ++i){
183 CacheMsg &request = m_writeRequestTable.lookup(wkeys[i]);
185 RequestTable::iterator write = m_writeRequestTable.begin();
186 RequestTable::iterator write_end = m_writeRequestTable.end();
187 for (; write != write_end; ++write) {
188 SequencerRequest* request = write->second;
189 out << "\tRequest[ " << i << " ] = " << request.getType()
190 << " Address " << wkeys[i]
191 << " Posted " << request.getTime()
192 << " PF " << request.getPrefetch() << endl;
193 if (request.getPrefetch() == PrefetchBit_No) {
194 total_demand++;
195 }
196 }

--- 34 unchanged lines hidden (view full) ---

231
232 Address line_addr(request->ruby_request.paddr);
233 line_addr.makeLineAddress();
234 if ((request->ruby_request.type == RubyRequestType_ST) ||
235 (request->ruby_request.type == RubyRequestType_RMW_Read) ||
236 (request->ruby_request.type == RubyRequestType_RMW_Write) ||
237 (request->ruby_request.type == RubyRequestType_Locked_Read) ||
238 (request->ruby_request.type == RubyRequestType_Locked_Write)) {
234 if (m_writeRequestTable.exist(line_addr)) {
235 m_writeRequestTable.lookup(line_addr) = request;
239 pair<RequestTable::iterator, bool> r =
240 m_writeRequestTable.insert(RequestTable::value_type(line_addr, 0));
241 bool success = r.second;
242 RequestTable::iterator i = r.first;
243 if (!success) {
244 i->second = request;
245 // return true;
246
247 // drh5: isn't this an error? do you lose the initial request?
248 assert(0);
249 }
241 m_writeRequestTable.allocate(line_addr);
242 m_writeRequestTable.lookup(line_addr) = request;
250 i->second = request;
251 m_outstanding_count++;
252 } else {
245 if (m_readRequestTable.exist(line_addr)) {
246 m_readRequestTable.lookup(line_addr) = request;
253 pair<RequestTable::iterator, bool> r =
254 m_readRequestTable.insert(RequestTable::value_type(line_addr, 0));
255 bool success = r.second;
256 RequestTable::iterator i = r.first;
257 if (!success) {
258 i->second = request;
259 // return true;
260
261 // drh5: isn't this an error? do you lose the initial request?
262 assert(0);
263 }
252 m_readRequestTable.allocate(line_addr);
253 m_readRequestTable.lookup(line_addr) = request;
264 i->second = request;
265 m_outstanding_count++;
266 }
267
268 g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count);
269
270 total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size();
271 assert(m_outstanding_count == total_outstanding);
272
273 return false;
274}
275
276void
277Sequencer::markRemoved()
278{
279 m_outstanding_count--;
280 assert(m_outstanding_count ==
281 m_writeRequestTable.size() + m_readRequestTable.size());
282}
283
284void
285Sequencer::removeRequest(SequencerRequest* srequest)
286{
287 assert(m_outstanding_count ==
288 m_writeRequestTable.size() + m_readRequestTable.size());
289
290 const RubyRequest & ruby_request = srequest->ruby_request;
291 Address line_addr(ruby_request.paddr);
292 line_addr.makeLineAddress();
293 if ((ruby_request.type == RubyRequestType_ST) ||
294 (ruby_request.type == RubyRequestType_RMW_Read) ||
295 (ruby_request.type == RubyRequestType_RMW_Write) ||
296 (ruby_request.type == RubyRequestType_Locked_Read) ||
297 (ruby_request.type == RubyRequestType_Locked_Write)) {
279 m_writeRequestTable.deallocate(line_addr);
298 m_writeRequestTable.erase(line_addr);
299 } else {
281 m_readRequestTable.deallocate(line_addr);
300 m_readRequestTable.erase(line_addr);
301 }
283 m_outstanding_count--;
302
285 assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size());
303 markRemoved();
304}
305
306void
307Sequencer::writeCallback(const Address& address, DataBlock& data)
308{
309 assert(address == line_address(address));
292 assert(m_writeRequestTable.exist(line_address(address)));
310 assert(m_writeRequestTable.count(line_address(address)));
311
294 SequencerRequest* request = m_writeRequestTable.lookup(address);
312 RequestTable::iterator i = m_writeRequestTable.find(address);
313 assert(i != m_writeRequestTable.end());
314 SequencerRequest* request = i->second;
315
296 removeRequest(request);
316 m_writeRequestTable.erase(i);
317 markRemoved();
318
319 assert((request->ruby_request.type == RubyRequestType_ST) ||
320 (request->ruby_request.type == RubyRequestType_RMW_Read) ||
321 (request->ruby_request.type == RubyRequestType_RMW_Write) ||
322 (request->ruby_request.type == RubyRequestType_Locked_Read) ||
323 (request->ruby_request.type == RubyRequestType_Locked_Write));
324
325 if (request->ruby_request.type == RubyRequestType_Locked_Read) {

--- 6 unchanged lines hidden (view full) ---

332
333 hitCallback(request, data);
334}
335
336void
337Sequencer::readCallback(const Address& address, DataBlock& data)
338{
339 assert(address == line_address(address));
319 assert(m_readRequestTable.exist(line_address(address)));
340 assert(m_readRequestTable.count(line_address(address)));
341
321 SequencerRequest* request = m_readRequestTable.lookup(address);
322 removeRequest(request);
342 RequestTable::iterator i = m_readRequestTable.find(address);
343 assert(i != m_readRequestTable.end());
344 SequencerRequest* request = i->second;
345
346 m_readRequestTable.erase(i);
347 markRemoved();
348
349 assert((request->ruby_request.type == RubyRequestType_LD) ||
350 (request->ruby_request.type == RubyRequestType_RMW_Read) ||
351 (request->ruby_request.type == RubyRequestType_IFETCH));
352
353 hitCallback(request, data);
354}
355
356void

--- 72 unchanged lines hidden (view full) ---

429 delete srequest;
430}
431
432// Returns true if the sequencer already has a load or store outstanding
433RequestStatus
434Sequencer::getRequestStatus(const RubyRequest& request)
435{
436 bool is_outstanding_store =
412 m_writeRequestTable.exist(line_address(Address(request.paddr)));
437 !!m_writeRequestTable.count(line_address(Address(request.paddr)));
438 bool is_outstanding_load =
414 m_readRequestTable.exist(line_address(Address(request.paddr)));
439 !!m_readRequestTable.count(line_address(Address(request.paddr)));
440 if (is_outstanding_store) {
441 if ((request.type == RubyRequestType_LD) ||
442 (request.type == RubyRequestType_IFETCH) ||
443 (request.type == RubyRequestType_RMW_Read)) {
444 m_store_waiting_on_load_cycles++;
445 } else {
446 m_store_waiting_on_store_cycles++;
447 }

--- 13 unchanged lines hidden (view full) ---

461 }
462
463 return RequestStatus_Ready;
464}
465
466bool
467Sequencer::empty() const
468{
444 return m_writeRequestTable.size() == 0 && m_readRequestTable.size() == 0;
469 return m_writeRequestTable.empty() && m_readRequestTable.empty();
470}
471
472RequestStatus
473Sequencer::makeRequest(const RubyRequest &request)
474{
475 assert(Address(request.paddr).getOffset() + request.len <=
476 RubySystem::getBlockSizeBytes());
477 RequestStatus status = getRequestStatus(request);

--- 122 unchanged lines hidden (view full) ---

600{
601 CacheMemory *cache =
602 (type == CacheRequestType_IFETCH) ? m_instCache_ptr : m_dataCache_ptr;
603
604 return cache->tryCacheAccess(line_address(addr), type, data_ptr);
605}
606#endif
607
608template <class KEY, class VALUE>
609std::ostream &
610operator<<(ostream &out, const m5::hash_map<KEY, VALUE> &map)
611{
612 typename m5::hash_map<KEY, VALUE>::const_iterator i = map.begin();
613 typename m5::hash_map<KEY, VALUE>::const_iterator end = map.end();
614
615 out << "[";
616 for (; i != end; ++i)
617 out << " " << i->first << "=" << i->second;
618 out << " ]";
619
620 return out;
621}
622
623void
624Sequencer::print(ostream& out) const
625{
626 out << "[Sequencer: " << m_version
627 << ", outstanding requests: " << m_outstanding_count
628 << ", read request table: " << m_readRequestTable
629 << ", write request table: " << m_writeRequestTable
630 << "]";

--- 12 unchanged lines hidden ---