Sequencer.cc revision 6165:2d26c346f1be
1
2/*
3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * $Id: Sequencer.C 1.131 2006/11/06 17:41:01-06:00 bobba@gratiano.cs.wisc.edu $
32 *
33 */
34
35#include "mem/ruby/common/Global.hh"
36#include "mem/ruby/system/Sequencer.hh"
37#include "mem/ruby/system/System.hh"
38#include "mem/protocol/Protocol.hh"
39#include "mem/ruby/profiler/Profiler.hh"
40#include "mem/ruby/system/CacheMemory.hh"
41#include "mem/ruby/config/RubyConfig.hh"
42//#include "mem/ruby/recorder/Tracer.hh"
43#include "mem/ruby/slicc_interface/AbstractChip.hh"
44#include "mem/protocol/Chip.hh"
45#include "mem/ruby/tester/Tester.hh"
46#include "mem/ruby/common/SubBlock.hh"
47#include "mem/protocol/Protocol.hh"
48#include "mem/gems_common/Map.hh"
49#include "mem/packet.hh"
50
51Sequencer::Sequencer(AbstractChip* chip_ptr, int version) {
52  m_chip_ptr = chip_ptr;
53  m_version = version;
54
55  m_deadlock_check_scheduled = false;
56  m_outstanding_count = 0;
57
58  int smt_threads = RubyConfig::numberofSMTThreads();
59  m_writeRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads];
60  m_readRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads];
61
62  m_packetTable_ptr = new Map<Address, Packet*>;
63
64  for(int p=0; p < smt_threads; ++p){
65    m_writeRequestTable_ptr[p] = new Map<Address, CacheMsg>;
66    m_readRequestTable_ptr[p] = new Map<Address, CacheMsg>;
67  }
68
69}
70
71Sequencer::~Sequencer() {
72  int smt_threads = RubyConfig::numberofSMTThreads();
73  for(int i=0; i < smt_threads; ++i){
74    if(m_writeRequestTable_ptr[i]){
75      delete m_writeRequestTable_ptr[i];
76    }
77    if(m_readRequestTable_ptr[i]){
78      delete m_readRequestTable_ptr[i];
79    }
80  }
81  if(m_writeRequestTable_ptr){
82    delete [] m_writeRequestTable_ptr;
83  }
84  if(m_readRequestTable_ptr){
85    delete [] m_readRequestTable_ptr;
86  }
87}
88
89void Sequencer::wakeup() {
90  // Check for deadlock of any of the requests
91  Time current_time = g_eventQueue_ptr->getTime();
92  bool deadlock = false;
93
94  // Check across all outstanding requests
95  int smt_threads = RubyConfig::numberofSMTThreads();
96  int total_outstanding = 0;
97  for(int p=0; p < smt_threads; ++p){
98    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
99    for (int i=0; i<keys.size(); i++) {
100      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
101      if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) {
102        WARN_MSG("Possible Deadlock detected");
103        WARN_EXPR(request);
104        WARN_EXPR(m_chip_ptr->getID());
105        WARN_EXPR(m_version);
106        WARN_EXPR(keys.size());
107        WARN_EXPR(current_time);
108        WARN_EXPR(request.getTime());
109        WARN_EXPR(current_time - request.getTime());
110        WARN_EXPR(*m_readRequestTable_ptr[p]);
111        ERROR_MSG("Aborting");
112        deadlock = true;
113      }
114    }
115
116    keys = m_writeRequestTable_ptr[p]->keys();
117    for (int i=0; i<keys.size(); i++) {
118      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
119      if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) {
120        WARN_MSG("Possible Deadlock detected");
121        WARN_EXPR(request);
122        WARN_EXPR(m_chip_ptr->getID());
123        WARN_EXPR(m_version);
124        WARN_EXPR(current_time);
125        WARN_EXPR(request.getTime());
126        WARN_EXPR(current_time - request.getTime());
127        WARN_EXPR(keys.size());
128        WARN_EXPR(*m_writeRequestTable_ptr[p]);
129        ERROR_MSG("Aborting");
130        deadlock = true;
131      }
132    }
133    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
134  }  // across all request tables
135  assert(m_outstanding_count == total_outstanding);
136
137  if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking
138    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
139  } else {
140    m_deadlock_check_scheduled = false;
141  }
142}
143
144//returns the total number of requests
145int Sequencer::getNumberOutstanding(){
146  return m_outstanding_count;
147}
148
149// returns the total number of demand requests
150int Sequencer::getNumberOutstandingDemand(){
151  int smt_threads = RubyConfig::numberofSMTThreads();
152  int total_demand = 0;
153  for(int p=0; p < smt_threads; ++p){
154    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
155    for (int i=0; i< keys.size(); i++) {
156      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
157      if(request.getPrefetch() == PrefetchBit_No){
158        total_demand++;
159      }
160    }
161
162    keys = m_writeRequestTable_ptr[p]->keys();
163    for (int i=0; i< keys.size(); i++) {
164      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
165      if(request.getPrefetch() == PrefetchBit_No){
166        total_demand++;
167      }
168    }
169  }
170
171  return total_demand;
172}
173
174int Sequencer::getNumberOutstandingPrefetch(){
175  int smt_threads = RubyConfig::numberofSMTThreads();
176  int total_prefetch = 0;
177  for(int p=0; p < smt_threads; ++p){
178    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
179    for (int i=0; i< keys.size(); i++) {
180      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
181      if(request.getPrefetch() == PrefetchBit_Yes){
182        total_prefetch++;
183      }
184    }
185
186    keys = m_writeRequestTable_ptr[p]->keys();
187    for (int i=0; i< keys.size(); i++) {
188      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
189      if(request.getPrefetch() == PrefetchBit_Yes){
190        total_prefetch++;
191      }
192    }
193  }
194
195  return total_prefetch;
196}
197
198bool Sequencer::isPrefetchRequest(const Address & lineaddr){
199  int smt_threads = RubyConfig::numberofSMTThreads();
200  for(int p=0; p < smt_threads; ++p){
201    // check load requests
202    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
203    for (int i=0; i< keys.size(); i++) {
204      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
205      if(line_address(request.getAddress()) == lineaddr){
206        if(request.getPrefetch() == PrefetchBit_Yes){
207          return true;
208        }
209        else{
210          return false;
211        }
212      }
213    }
214
215    // check store requests
216    keys = m_writeRequestTable_ptr[p]->keys();
217    for (int i=0; i< keys.size(); i++) {
218      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
219      if(line_address(request.getAddress()) == lineaddr){
220        if(request.getPrefetch() == PrefetchBit_Yes){
221          return true;
222        }
223        else{
224          return false;
225        }
226      }
227    }
228  }
229  // we should've found a matching request
230  cout << "isRequestPrefetch() ERROR request NOT FOUND : " << lineaddr << endl;
231  printProgress(cout);
232  assert(0);
233}
234
235AccessModeType Sequencer::getAccessModeOfRequest(Address addr, int thread){
236  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
237    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
238    return request.getAccessMode();
239  } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
240    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
241    return request.getAccessMode();
242  } else {
243    printProgress(cout);
244    ERROR_MSG("Request not found in RequestTables");
245  }
246}
247
248Address Sequencer::getLogicalAddressOfRequest(Address addr, int thread){
249  assert(thread >= 0);
250  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
251    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
252    return request.getLogicalAddress();
253  } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
254    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
255    return request.getLogicalAddress();
256  } else {
257    printProgress(cout);
258    WARN_MSG("Request not found in RequestTables");
259    WARN_MSG(addr);
260    WARN_MSG(thread);
261    ASSERT(0);
262  }
263}
264
265// returns the ThreadID of the request
266int Sequencer::getRequestThreadID(const Address & addr){
267  int smt_threads = RubyConfig::numberofSMTThreads();
268  int thread = -1;
269  int num_found = 0;
270  for(int p=0; p < smt_threads; ++p){
271    if(m_readRequestTable_ptr[p]->exist(addr)){
272      num_found++;
273      thread = p;
274    }
275    if(m_writeRequestTable_ptr[p]->exist(addr)){
276      num_found++;
277      thread = p;
278    }
279  }
280  if(num_found != 1){
281    cout << "getRequestThreadID ERROR too many matching requests addr = " << addr << endl;
282    printProgress(cout);
283  }
284  ASSERT(num_found == 1);
285  ASSERT(thread != -1);
286
287  return thread;
288}
289
290// given a line address, return the request's physical address
291Address Sequencer::getRequestPhysicalAddress(const Address & lineaddr){
292  int smt_threads = RubyConfig::numberofSMTThreads();
293  Address physaddr;
294  int num_found = 0;
295  for(int p=0; p < smt_threads; ++p){
296    if(m_readRequestTable_ptr[p]->exist(lineaddr)){
297      num_found++;
298      physaddr = (m_readRequestTable_ptr[p]->lookup(lineaddr)).getAddress();
299    }
300    if(m_writeRequestTable_ptr[p]->exist(lineaddr)){
301      num_found++;
302      physaddr = (m_writeRequestTable_ptr[p]->lookup(lineaddr)).getAddress();
303    }
304  }
305  if(num_found != 1){
306    cout << "getRequestPhysicalAddress ERROR too many matching requests addr = " << lineaddr << endl;
307    printProgress(cout);
308  }
309  ASSERT(num_found == 1);
310
311  return physaddr;
312}
313
314void Sequencer::printProgress(ostream& out) const{
315
316  int total_demand = 0;
317  out << "Sequencer Stats Version " << m_version << endl;
318  out << "Current time = " << g_eventQueue_ptr->getTime() << endl;
319  out << "---------------" << endl;
320  out << "outstanding requests" << endl;
321
322  int smt_threads = RubyConfig::numberofSMTThreads();
323  for(int p=0; p < smt_threads; ++p){
324    Vector<Address> rkeys = m_readRequestTable_ptr[p]->keys();
325    int read_size = rkeys.size();
326    out << "proc " << m_chip_ptr->getID() << " thread " << p << " Read Requests = " << read_size << endl;
327    // print the request table
328    for(int i=0; i < read_size; ++i){
329      CacheMsg & request = m_readRequestTable_ptr[p]->lookup(rkeys[i]);
330      out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << rkeys[i]  << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl;
331      if( request.getPrefetch() == PrefetchBit_No ){
332        total_demand++;
333      }
334    }
335
336    Vector<Address> wkeys = m_writeRequestTable_ptr[p]->keys();
337    int write_size = wkeys.size();
338    out << "proc " << m_chip_ptr->getID() << " thread " << p << " Write Requests = " << write_size << endl;
339    // print the request table
340    for(int i=0; i < write_size; ++i){
341      CacheMsg & request = m_writeRequestTable_ptr[p]->lookup(wkeys[i]);
342      out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << wkeys[i]  << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl;
343      if( request.getPrefetch() == PrefetchBit_No ){
344        total_demand++;
345      }
346    }
347
348    out << endl;
349  }
350  out << "Total Number Outstanding: " << m_outstanding_count << endl;
351  out << "Total Number Demand     : " << total_demand << endl;
352  out << "Total Number Prefetches : " << m_outstanding_count - total_demand << endl;
353  out << endl;
354  out << endl;
355
356}
357
358void Sequencer::printConfig(ostream& out) {
359  if (TSO) {
360    out << "sequencer: Sequencer - TSO" << endl;
361  } else {
362    out << "sequencer: Sequencer - SC" << endl;
363  }
364  out << "  max_outstanding_requests: " << g_SEQUENCER_OUTSTANDING_REQUESTS << endl;
365}
366
367bool Sequencer::empty() const {
368  return m_outstanding_count == 0;
369}
370
371// Insert the request on the correct request table.  Return true if
372// the entry was already present.
373bool Sequencer::insertRequest(const CacheMsg& request) {
374  int thread = request.getThreadID();
375  assert(thread >= 0);
376  int total_outstanding = 0;
377  int smt_threads = RubyConfig::numberofSMTThreads();
378  for(int p=0; p < smt_threads; ++p){
379    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
380  }
381  assert(m_outstanding_count == total_outstanding);
382
383  // See if we should schedule a deadlock check
384  if (m_deadlock_check_scheduled == false) {
385    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
386    m_deadlock_check_scheduled = true;
387  }
388
389  if ((request.getType() == CacheRequestType_ST) ||
390      (request.getType() == CacheRequestType_ATOMIC)) {
391    if (m_writeRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) {
392      m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
393      return true;
394    }
395    m_writeRequestTable_ptr[thread]->allocate(line_address(request.getAddress()));
396    m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
397    m_outstanding_count++;
398  } else {
399    if (m_readRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) {
400      m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
401      return true;
402    }
403    m_readRequestTable_ptr[thread]->allocate(line_address(request.getAddress()));
404    m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
405    m_outstanding_count++;
406  }
407
408  g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count);
409
410  total_outstanding = 0;
411  for(int p=0; p < smt_threads; ++p){
412    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
413  }
414
415  assert(m_outstanding_count == total_outstanding);
416  return false;
417}
418
419void Sequencer::removeRequest(const CacheMsg& request) {
420  int thread = request.getThreadID();
421  assert(thread >= 0);
422  int total_outstanding = 0;
423  int smt_threads = RubyConfig::numberofSMTThreads();
424  for(int p=0; p < smt_threads; ++p){
425    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
426  }
427  assert(m_outstanding_count == total_outstanding);
428
429  if ((request.getType() == CacheRequestType_ST) ||
430      (request.getType() == CacheRequestType_ATOMIC)) {
431    m_writeRequestTable_ptr[thread]->deallocate(line_address(request.getAddress()));
432  } else {
433    m_readRequestTable_ptr[thread]->deallocate(line_address(request.getAddress()));
434  }
435  m_outstanding_count--;
436
437  total_outstanding = 0;
438  for(int p=0; p < smt_threads; ++p){
439    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
440  }
441  assert(m_outstanding_count == total_outstanding);
442}
443
444void Sequencer::writeCallback(const Address& address) {
445  DataBlock data;
446  writeCallback(address, data);
447}
448
449void Sequencer::writeCallback(const Address& address, DataBlock& data) {
450  // process oldest thread first
451  int thread = -1;
452  Time oldest_time = 0;
453  int smt_threads = RubyConfig::numberofSMTThreads();
454  for(int t=0; t < smt_threads; ++t){
455    if(m_writeRequestTable_ptr[t]->exist(address)){
456      CacheMsg & request = m_writeRequestTable_ptr[t]->lookup(address);
457      if(thread == -1 || (request.getTime() < oldest_time) ){
458        thread = t;
459        oldest_time = request.getTime();
460      }
461    }
462  }
463  // make sure we found an oldest thread
464  ASSERT(thread != -1);
465
466  CacheMsg & request = m_writeRequestTable_ptr[thread]->lookup(address);
467
468  writeCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread);
469}
470
471void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) {
472
473  assert(address == line_address(address));
474  assert(thread >= 0);
475  assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
476
477  writeCallback(address, data, respondingMach, thread);
478
479}
480
481void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) {
482  assert(address == line_address(address));
483  assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
484  CacheMsg request = m_writeRequestTable_ptr[thread]->lookup(address);
485  assert( request.getThreadID() == thread);
486  removeRequest(request);
487
488  assert((request.getType() == CacheRequestType_ST) ||
489         (request.getType() == CacheRequestType_ATOMIC));
490
491  hitCallback(request, data, respondingMach, thread);
492
493}
494
495void Sequencer::readCallback(const Address& address) {
496  DataBlock data;
497  readCallback(address, data);
498}
499
500void Sequencer::readCallback(const Address& address, DataBlock& data) {
501  // process oldest thread first
502  int thread = -1;
503  Time oldest_time = 0;
504  int smt_threads = RubyConfig::numberofSMTThreads();
505  for(int t=0; t < smt_threads; ++t){
506    if(m_readRequestTable_ptr[t]->exist(address)){
507      CacheMsg & request = m_readRequestTable_ptr[t]->lookup(address);
508      if(thread == -1 || (request.getTime() < oldest_time) ){
509        thread = t;
510        oldest_time = request.getTime();
511      }
512    }
513  }
514  // make sure we found an oldest thread
515  ASSERT(thread != -1);
516
517  CacheMsg & request = m_readRequestTable_ptr[thread]->lookup(address);
518
519  readCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread);
520}
521
522void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) {
523
524  assert(address == line_address(address));
525  assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
526
527  readCallback(address, data, respondingMach, thread);
528}
529
530void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) {
531  assert(address == line_address(address));
532  assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
533
534  CacheMsg request = m_readRequestTable_ptr[thread]->lookup(address);
535  assert( request.getThreadID() == thread );
536  removeRequest(request);
537
538  assert((request.getType() == CacheRequestType_LD) ||
539         (request.getType() == CacheRequestType_IFETCH)
540         );
541
542  hitCallback(request, data, respondingMach, thread);
543}
544
545void Sequencer::hitCallback(const CacheMsg& request, DataBlock& data, GenericMachineType respondingMach, int thread) {
546  int size = request.getSize();
547  Address request_address = request.getAddress();
548  Address request_logical_address = request.getLogicalAddress();
549  Address request_line_address = line_address(request_address);
550  CacheRequestType type = request.getType();
551  int threadID = request.getThreadID();
552  Time issued_time = request.getTime();
553  int logical_proc_no = ((m_chip_ptr->getID() * RubyConfig::numberOfProcsPerChip()) + m_version) * RubyConfig::numberofSMTThreads() + threadID;
554
555  DEBUG_MSG(SEQUENCER_COMP, MedPrio, size);
556
557  // Set this cache entry to the most recently used
558  if (type == CacheRequestType_IFETCH) {
559    if (Protocol::m_TwoLevelCache) {
560      if (m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
561        m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->setMRU(request_line_address);
562      }
563    }
564    else {
565      if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
566        m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address);
567      }
568    }
569  } else {
570    if (Protocol::m_TwoLevelCache) {
571      if (m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
572        m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->setMRU(request_line_address);
573      }
574    }
575    else {
576      if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
577        m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address);
578      }
579    }
580  }
581
582  assert(g_eventQueue_ptr->getTime() >= issued_time);
583  Time miss_latency = g_eventQueue_ptr->getTime() - issued_time;
584
585  if (PROTOCOL_DEBUG_TRACE) {
586    g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), -1, request.getAddress(), "", "Done", "",
587                                                   int_to_string(miss_latency)+" cycles "+GenericMachineType_to_string(respondingMach)+" "+CacheRequestType_to_string(request.getType())+" "+PrefetchBit_to_string(request.getPrefetch()));
588  }
589
590  DEBUG_MSG(SEQUENCER_COMP, MedPrio, request_address);
591  DEBUG_MSG(SEQUENCER_COMP, MedPrio, request.getPrefetch());
592  if (request.getPrefetch() == PrefetchBit_Yes) {
593    DEBUG_MSG(SEQUENCER_COMP, MedPrio, "return");
594    g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach);
595    return; // Ignore the software prefetch, don't callback the driver
596  }
597
598  // Profile the miss latency for all non-zero demand misses
599  if (miss_latency != 0) {
600    g_system_ptr->getProfiler()->missLatency(miss_latency, type, respondingMach);
601
602  }
603
604  bool write =
605    (type == CacheRequestType_ST) ||
606    (type == CacheRequestType_ATOMIC);
607
608  if (TSO && write) {
609    m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->callBack(line_address(request.getAddress()), data,
610                                                               m_packetTable_ptr->lookup(request.getAddress()));
611  } else {
612
613    // Copy the correct bytes out of the cache line into the subblock
614    SubBlock subblock(request_address, request_logical_address, size);
615    subblock.mergeFrom(data);  // copy the correct bytes from DataBlock in the SubBlock
616
617    // Scan the store buffer to see if there are any outstanding stores we need to collect
618    if (TSO) {
619      m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->updateSubBlock(subblock);
620    }
621
622    // Call into the Driver and let it read and/or modify the sub-block
623    Packet* pkt = m_packetTable_ptr->lookup(request.getAddress());
624
625    // update data if this is a store/atomic
626
627    /*
628    if (pkt->req->isCondSwap()) {
629      L1Cache_Entry entry = m_L1Cache_vec[m_version]->lookup(Address(pkt->req->physAddr()));
630      DataBlk datablk = entry->getDataBlk();
631      uint8_t *orig_data = datablk.getArray();
632      if ( datablk.equal(pkt->req->getExtraData()) )
633        datablk->setArray(pkt->getData());
634      pkt->setData(orig_data);
635    }
636    */
637
638    g_system_ptr->getDriver()->hitCallback(pkt);
639    m_packetTable_ptr->remove(request.getAddress());
640
641    // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock
642    // (This is only triggered for the non-TSO case)
643    if (write) {
644      assert(!TSO);
645      subblock.mergeTo(data);    // copy the correct bytes from SubBlock into the DataBlock
646    }
647  }
648}
649
650void Sequencer::printDebug(){
651  //notify driver of debug
652  g_system_ptr->getDriver()->printDebug();
653}
654
655//dsm: breaks build, delayed
656// Returns true if the sequencer already has a load or store outstanding
657bool
658Sequencer::isReady(const Packet* pkt) const
659{
660
661  int cpu_number = pkt->req->contextId();
662  la_t logical_addr = pkt->req->getVaddr();
663  pa_t physical_addr = pkt->req->getPaddr();
664  CacheRequestType type_of_request;
665  if ( pkt->req->isInstFetch() ) {
666    type_of_request = CacheRequestType_IFETCH;
667  } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) {
668    type_of_request = CacheRequestType_ATOMIC;
669  } else if ( pkt->isRead() ) {
670    type_of_request = CacheRequestType_LD;
671  } else if ( pkt->isWrite() ) {
672    type_of_request = CacheRequestType_ST;
673  } else {
674    assert(false);
675  }
676  int thread = pkt->req->threadId();
677
678  CacheMsg request(Address( physical_addr ),
679                   Address( physical_addr ),
680                   type_of_request,
681                   Address(0),
682                   AccessModeType_UserMode,   // User/supervisor mode
683                   0,   // Size in bytes of request
684                   PrefetchBit_No,  // Not a prefetch
685                   0,              // Version number
686                   Address(logical_addr),   // Virtual Address
687                   thread              // SMT thread
688                   );
689  return isReady(request);
690}
691
692bool
693Sequencer::isReady(const CacheMsg& request) const
694{
695  if (m_outstanding_count >= g_SEQUENCER_OUTSTANDING_REQUESTS) {
696    //cout << "TOO MANY OUTSTANDING: " << m_outstanding_count << " " << g_SEQUENCER_OUTSTANDING_REQUESTS << " VER " << m_version << endl;
697    //printProgress(cout);
698    return false;
699  }
700
701  // This code allows reads to be performed even when we have a write
702  // request outstanding for the line
703  bool write =
704    (request.getType() == CacheRequestType_ST) ||
705    (request.getType() == CacheRequestType_ATOMIC);
706
707  // LUKE - disallow more than one request type per address
708  //     INVARIANT: at most one request type per address, per processor
709  int smt_threads = RubyConfig::numberofSMTThreads();
710  for(int p=0; p < smt_threads; ++p){
711    if( m_writeRequestTable_ptr[p]->exist(line_address(request.getAddress())) ||
712        m_readRequestTable_ptr[p]->exist(line_address(request.getAddress())) ){
713      //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl;
714      //printProgress(cout);
715      return false;
716    }
717  }
718
719  if (TSO) {
720    return m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady();
721  }
722  return true;
723}
724
725//dsm: breaks build, delayed
726// Called by Driver (Simics or Tester).
727void
728Sequencer::makeRequest(Packet* pkt)
729{
730  int cpu_number = pkt->req->contextId();
731  la_t logical_addr = pkt->req->getVaddr();
732  pa_t physical_addr = pkt->req->getPaddr();
733  int request_size = pkt->getSize();
734  CacheRequestType type_of_request;
735  PrefetchBit prefetch;
736  bool write = false;
737  if ( pkt->req->isInstFetch() ) {
738    type_of_request = CacheRequestType_IFETCH;
739  } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) {
740    type_of_request = CacheRequestType_ATOMIC;
741    write = true;
742  } else if ( pkt->isRead() ) {
743    type_of_request = CacheRequestType_LD;
744  } else if ( pkt->isWrite() ) {
745    type_of_request = CacheRequestType_ST;
746    write = true;
747  } else {
748    assert(false);
749  }
750  if (pkt->req->isPrefetch()) {
751    prefetch = PrefetchBit_Yes;
752  } else {
753    prefetch = PrefetchBit_No;
754  }
755  la_t virtual_pc = pkt->req->getPC();
756  int isPriv = false;  // TODO: get permission data
757  int thread = pkt->req->threadId();
758
759  AccessModeType access_mode = AccessModeType_UserMode; // TODO: get actual permission
760
761  CacheMsg request(Address( physical_addr ),
762                   Address( physical_addr ),
763                   type_of_request,
764                   Address(virtual_pc),
765                   access_mode,   // User/supervisor mode
766                   request_size,   // Size in bytes of request
767                   prefetch,
768                   0,              // Version number
769                   Address(logical_addr),   // Virtual Address
770                   thread         // SMT thread
771                   );
772
773  if ( TSO && write && !pkt->req->isPrefetch() ) {
774    assert(m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady());
775    m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->insertStore(pkt, request);
776    return;
777  }
778
779  m_packetTable_ptr->insert(Address( physical_addr ), pkt);
780
781  doRequest(request);
782}
783
784bool Sequencer::doRequest(const CacheMsg& request) {
785  bool hit = false;
786  // Check the fast path
787  DataBlock* data_ptr;
788
789  int thread = request.getThreadID();
790
791  hit = tryCacheAccess(line_address(request.getAddress()),
792                       request.getType(),
793                       request.getProgramCounter(),
794                       request.getAccessMode(),
795                       request.getSize(),
796                       data_ptr);
797
798  if (hit && (request.getType() == CacheRequestType_IFETCH || !REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) ) {
799    DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path hit");
800    hitCallback(request, *data_ptr, GenericMachineType_L1Cache, thread);
801    return true;
802  }
803
804  if (TSO && (request.getType() == CacheRequestType_LD || request.getType() == CacheRequestType_IFETCH)) {
805
806    // See if we can satisfy the load entirely from the store buffer
807    SubBlock subblock(line_address(request.getAddress()), request.getSize());
808    if (m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->trySubBlock(subblock)) {
809      DataBlock dummy;
810      hitCallback(request, dummy, GenericMachineType_NULL, thread);  // Call with an 'empty' datablock, since the data is in the store buffer
811      return true;
812    }
813  }
814
815  DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path miss");
816  issueRequest(request);
817  return hit;
818}
819
820void Sequencer::issueRequest(const CacheMsg& request) {
821  bool found = insertRequest(request);
822
823  if (!found) {
824    CacheMsg msg = request;
825    msg.getAddress() = line_address(request.getAddress()); // Make line address
826
827    // Fast Path L1 misses are profiled here - all non-fast path misses are profiled within the generated protocol code
828    if (!REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) {
829      g_system_ptr->getProfiler()->addPrimaryStatSample(msg, m_chip_ptr->getID());
830    }
831
832    if (PROTOCOL_DEBUG_TRACE) {
833      g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip() + m_version), -1, msg.getAddress(),"", "Begin", "", CacheRequestType_to_string(request.getType()));
834    }
835
836#if 0
837    // Commented out by nate binkert because I removed the trace stuff
838    if (g_system_ptr->getTracer()->traceEnabled()) {
839      g_system_ptr->getTracer()->traceRequest((m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), msg.getAddress(), msg.getProgramCounter(),
840                                              msg.getType(), g_eventQueue_ptr->getTime());
841    }
842#endif
843
844    Time latency = 0;  // initialzed to an null value
845
846    latency = SEQUENCER_TO_CONTROLLER_LATENCY;
847
848    // Send the message to the cache controller
849    assert(latency > 0);
850    m_chip_ptr->m_L1Cache_mandatoryQueue_vec[m_version]->enqueue(msg, latency);
851
852  }  // !found
853}
854
855bool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type,
856                               const Address& pc, AccessModeType access_mode,
857                               int size, DataBlock*& data_ptr) {
858  if (type == CacheRequestType_IFETCH) {
859    if (Protocol::m_TwoLevelCache) {
860      return m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
861    }
862    else {
863      return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
864    }
865  } else {
866    if (Protocol::m_TwoLevelCache) {
867      return m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
868    }
869    else {
870      return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
871    }
872  }
873}
874
875void Sequencer::resetRequestTime(const Address& addr, int thread){
876  assert(thread >= 0);
877  //reset both load and store requests, if they exist
878  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
879    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
880    if( request.m_AccessMode != AccessModeType_UserMode){
881      cout << "resetRequestType ERROR read request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl;
882      printProgress(cout);
883    }
884    //ASSERT(request.m_AccessMode == AccessModeType_UserMode);
885    request.setTime(g_eventQueue_ptr->getTime());
886  }
887  if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
888    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
889    if( request.m_AccessMode != AccessModeType_UserMode){
890      cout << "resetRequestType ERROR write request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl;
891      printProgress(cout);
892    }
893    //ASSERT(request.m_AccessMode == AccessModeType_UserMode);
894    request.setTime(g_eventQueue_ptr->getTime());
895  }
896}
897
898// removes load request from queue
899void Sequencer::removeLoadRequest(const Address & addr, int thread){
900  removeRequest(getReadRequest(addr, thread));
901}
902
903void Sequencer::removeStoreRequest(const Address & addr, int thread){
904  removeRequest(getWriteRequest(addr, thread));
905}
906
907// returns the read CacheMsg
908CacheMsg & Sequencer::getReadRequest( const Address & addr, int thread ){
909  Address temp = addr;
910  assert(thread >= 0);
911  assert(temp == line_address(temp));
912  assert(m_readRequestTable_ptr[thread]->exist(addr));
913  return m_readRequestTable_ptr[thread]->lookup(addr);
914}
915
916CacheMsg & Sequencer::getWriteRequest( const Address & addr, int thread){
917  Address temp = addr;
918  assert(thread >= 0);
919  assert(temp == line_address(temp));
920  assert(m_writeRequestTable_ptr[thread]->exist(addr));
921  return m_writeRequestTable_ptr[thread]->lookup(addr);
922}
923
924void Sequencer::print(ostream& out) const {
925  out << "[Sequencer: " << m_chip_ptr->getID()
926      << ", outstanding requests: " << m_outstanding_count;
927
928  int smt_threads = RubyConfig::numberofSMTThreads();
929  for(int p=0; p < smt_threads; ++p){
930    out << ", read request table[ " << p << " ]: " << *m_readRequestTable_ptr[p]
931        << ", write request table[ " << p << " ]: " << *m_writeRequestTable_ptr[p];
932  }
933  out << "]";
934}
935
936// this can be called from setState whenever coherence permissions are upgraded
937// when invoked, coherence violations will be checked for the given block
938void Sequencer::checkCoherence(const Address& addr) {
939#ifdef CHECK_COHERENCE
940  g_system_ptr->checkGlobalCoherenceInvariant(addr);
941#endif
942}
943
944bool Sequencer::getRubyMemoryValue(const Address& addr, char* value,
945                                   unsigned int size_in_bytes ) {
946  for(unsigned int i=0; i < size_in_bytes; i++) {
947    std::cerr << __FILE__ << "(" << __LINE__ << "): Not implemented. " << std::endl;
948    value[i] = 0; // _read_physical_memory( m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version,
949                  //                          addr.getAddress() + i, 1 );
950  }
951  return false; // Do nothing?
952}
953
954bool Sequencer::setRubyMemoryValue(const Address& addr, char *value,
955                                   unsigned int size_in_bytes) {
956  char test_buffer[64];
957
958  return false; // Do nothing?
959}
960
961