Sequencer.cc revision 6151:bc6b84108443
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 "Global.hh"
36#include "Sequencer.hh"
37#include "System.hh"
38#include "Protocol.hh"
39#include "Profiler.hh"
40#include "CacheMemory.hh"
41#include "RubyConfig.hh"
42//#include "Tracer.hh"
43#include "AbstractChip.hh"
44#include "Chip.hh"
45#include "Tester.hh"
46#include "SubBlock.hh"
47#include "Protocol.hh"
48#include "Map.hh"
49#include "interface.hh"
50//#include "XactCommitArbiter.hh"
51// #include "TransactionInterfaceManager.hh"
52//#include "TransactionVersionManager.hh"
53//#include "LazyTransactionVersionManager.hh"
54
55//#define XACT_MGR g_system_ptr->getChip(m_chip_ptr->getID())->getTransactionInterfaceManager(m_version)
56
57Sequencer::Sequencer(AbstractChip* chip_ptr, int version) {
58  m_chip_ptr = chip_ptr;
59  m_version = version;
60
61  m_deadlock_check_scheduled = false;
62  m_outstanding_count = 0;
63
64  int smt_threads = RubyConfig::numberofSMTThreads();
65  m_writeRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads];
66  m_readRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads];
67
68  for(int p=0; p < smt_threads; ++p){
69    m_writeRequestTable_ptr[p] = new Map<Address, CacheMsg>;
70    m_readRequestTable_ptr[p] = new Map<Address, CacheMsg>;
71  }
72
73}
74
75Sequencer::~Sequencer() {
76  int smt_threads = RubyConfig::numberofSMTThreads();
77  for(int i=0; i < smt_threads; ++i){
78    if(m_writeRequestTable_ptr[i]){
79      delete m_writeRequestTable_ptr[i];
80    }
81    if(m_readRequestTable_ptr[i]){
82      delete m_readRequestTable_ptr[i];
83    }
84  }
85  if(m_writeRequestTable_ptr){
86    delete [] m_writeRequestTable_ptr;
87  }
88  if(m_readRequestTable_ptr){
89    delete [] m_readRequestTable_ptr;
90  }
91}
92
93void Sequencer::wakeup() {
94  // Check for deadlock of any of the requests
95  Time current_time = g_eventQueue_ptr->getTime();
96  bool deadlock = false;
97
98  // Check across all outstanding requests
99  int smt_threads = RubyConfig::numberofSMTThreads();
100  int total_outstanding = 0;
101  for(int p=0; p < smt_threads; ++p){
102    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
103    for (int i=0; i<keys.size(); i++) {
104      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
105      if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) {
106        WARN_MSG("Possible Deadlock detected");
107        WARN_EXPR(request);
108        WARN_EXPR(m_chip_ptr->getID());
109        WARN_EXPR(m_version);
110        WARN_EXPR(keys.size());
111        WARN_EXPR(current_time);
112        WARN_EXPR(request.getTime());
113        WARN_EXPR(current_time - request.getTime());
114        WARN_EXPR(*m_readRequestTable_ptr[p]);
115        ERROR_MSG("Aborting");
116        deadlock = true;
117      }
118    }
119
120    keys = m_writeRequestTable_ptr[p]->keys();
121    for (int i=0; i<keys.size(); i++) {
122      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
123      if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) {
124        WARN_MSG("Possible Deadlock detected");
125        WARN_EXPR(request);
126        WARN_EXPR(m_chip_ptr->getID());
127        WARN_EXPR(m_version);
128        WARN_EXPR(current_time);
129        WARN_EXPR(request.getTime());
130        WARN_EXPR(current_time - request.getTime());
131        WARN_EXPR(keys.size());
132        WARN_EXPR(*m_writeRequestTable_ptr[p]);
133        ERROR_MSG("Aborting");
134        deadlock = true;
135      }
136    }
137    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
138  }  // across all request tables
139  assert(m_outstanding_count == total_outstanding);
140
141  if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking
142    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
143  } else {
144    m_deadlock_check_scheduled = false;
145  }
146}
147
148//returns the total number of requests
149int Sequencer::getNumberOutstanding(){
150  return m_outstanding_count;
151}
152
153// returns the total number of demand requests
154int Sequencer::getNumberOutstandingDemand(){
155  int smt_threads = RubyConfig::numberofSMTThreads();
156  int total_demand = 0;
157  for(int p=0; p < smt_threads; ++p){
158    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
159    for (int i=0; i< keys.size(); i++) {
160      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
161      // don't count transactional begin/commit requests
162      if(request.getType() != CacheRequestType_BEGIN_XACT && request.getType() != CacheRequestType_COMMIT_XACT){
163        if(request.getPrefetch() == PrefetchBit_No){
164          total_demand++;
165        }
166      }
167    }
168
169    keys = m_writeRequestTable_ptr[p]->keys();
170    for (int i=0; i< keys.size(); i++) {
171      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
172      if(request.getPrefetch() == PrefetchBit_No){
173        total_demand++;
174      }
175    }
176  }
177
178  return total_demand;
179}
180
181int Sequencer::getNumberOutstandingPrefetch(){
182  int smt_threads = RubyConfig::numberofSMTThreads();
183  int total_prefetch = 0;
184  for(int p=0; p < smt_threads; ++p){
185    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
186    for (int i=0; i< keys.size(); i++) {
187      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
188      if(request.getPrefetch() == PrefetchBit_Yes){
189        total_prefetch++;
190      }
191    }
192
193    keys = m_writeRequestTable_ptr[p]->keys();
194    for (int i=0; i< keys.size(); i++) {
195      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
196      if(request.getPrefetch() == PrefetchBit_Yes){
197        total_prefetch++;
198      }
199    }
200  }
201
202  return total_prefetch;
203}
204
205bool Sequencer::isPrefetchRequest(const Address & lineaddr){
206  int smt_threads = RubyConfig::numberofSMTThreads();
207  for(int p=0; p < smt_threads; ++p){
208    // check load requests
209    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
210    for (int i=0; i< keys.size(); i++) {
211      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
212      if(line_address(request.getAddress()) == lineaddr){
213        if(request.getPrefetch() == PrefetchBit_Yes){
214          return true;
215        }
216        else{
217          return false;
218        }
219      }
220    }
221
222    // check store requests
223    keys = m_writeRequestTable_ptr[p]->keys();
224    for (int i=0; i< keys.size(); i++) {
225      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
226      if(line_address(request.getAddress()) == lineaddr){
227        if(request.getPrefetch() == PrefetchBit_Yes){
228          return true;
229        }
230        else{
231          return false;
232        }
233      }
234    }
235  }
236  // we should've found a matching request
237  cout << "isRequestPrefetch() ERROR request NOT FOUND : " << lineaddr << endl;
238  printProgress(cout);
239  assert(0);
240}
241
242AccessModeType Sequencer::getAccessModeOfRequest(Address addr, int thread){
243  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
244    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
245    return request.getAccessMode();
246  } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
247    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
248    return request.getAccessMode();
249  } else {
250    printProgress(cout);
251    ERROR_MSG("Request not found in RequestTables");
252  }
253}
254
255Address Sequencer::getLogicalAddressOfRequest(Address addr, int thread){
256  assert(thread >= 0);
257  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
258    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
259    return request.getLogicalAddress();
260  } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
261    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
262    return request.getLogicalAddress();
263  } else {
264    printProgress(cout);
265    WARN_MSG("Request not found in RequestTables");
266    WARN_MSG(addr);
267    WARN_MSG(thread);
268    ASSERT(0);
269  }
270}
271
272// returns the ThreadID of the request
273int Sequencer::getRequestThreadID(const Address & addr){
274  int smt_threads = RubyConfig::numberofSMTThreads();
275  int thread = -1;
276  int num_found = 0;
277  for(int p=0; p < smt_threads; ++p){
278    if(m_readRequestTable_ptr[p]->exist(addr)){
279      num_found++;
280      thread = p;
281    }
282    if(m_writeRequestTable_ptr[p]->exist(addr)){
283      num_found++;
284      thread = p;
285    }
286  }
287  if(num_found != 1){
288    cout << "getRequestThreadID ERROR too many matching requests addr = " << addr << endl;
289    printProgress(cout);
290  }
291  ASSERT(num_found == 1);
292  ASSERT(thread != -1);
293
294  return thread;
295}
296
297// given a line address, return the request's physical address
298Address Sequencer::getRequestPhysicalAddress(const Address & lineaddr){
299  int smt_threads = RubyConfig::numberofSMTThreads();
300  Address physaddr;
301  int num_found = 0;
302  for(int p=0; p < smt_threads; ++p){
303    if(m_readRequestTable_ptr[p]->exist(lineaddr)){
304      num_found++;
305      physaddr = (m_readRequestTable_ptr[p]->lookup(lineaddr)).getAddress();
306    }
307    if(m_writeRequestTable_ptr[p]->exist(lineaddr)){
308      num_found++;
309      physaddr = (m_writeRequestTable_ptr[p]->lookup(lineaddr)).getAddress();
310    }
311  }
312  if(num_found != 1){
313    cout << "getRequestPhysicalAddress ERROR too many matching requests addr = " << lineaddr << endl;
314    printProgress(cout);
315  }
316  ASSERT(num_found == 1);
317
318  return physaddr;
319}
320
321void Sequencer::printProgress(ostream& out) const{
322
323  int total_demand = 0;
324  out << "Sequencer Stats Version " << m_version << endl;
325  out << "Current time = " << g_eventQueue_ptr->getTime() << endl;
326  out << "---------------" << endl;
327  out << "outstanding requests" << endl;
328
329  int smt_threads = RubyConfig::numberofSMTThreads();
330  for(int p=0; p < smt_threads; ++p){
331    Vector<Address> rkeys = m_readRequestTable_ptr[p]->keys();
332    int read_size = rkeys.size();
333    out << "proc " << m_chip_ptr->getID() << " thread " << p << " Read Requests = " << read_size << endl;
334    // print the request table
335    for(int i=0; i < read_size; ++i){
336      CacheMsg & request = m_readRequestTable_ptr[p]->lookup(rkeys[i]);
337      out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << rkeys[i]  << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl;
338      if( request.getPrefetch() == PrefetchBit_No ){
339        total_demand++;
340      }
341    }
342
343    Vector<Address> wkeys = m_writeRequestTable_ptr[p]->keys();
344    int write_size = wkeys.size();
345    out << "proc " << m_chip_ptr->getID() << " thread " << p << " Write Requests = " << write_size << endl;
346    // print the request table
347    for(int i=0; i < write_size; ++i){
348      CacheMsg & request = m_writeRequestTable_ptr[p]->lookup(wkeys[i]);
349      out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << wkeys[i]  << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl;
350      if( request.getPrefetch() == PrefetchBit_No ){
351        total_demand++;
352      }
353    }
354
355    out << endl;
356  }
357  out << "Total Number Outstanding: " << m_outstanding_count << endl;
358  out << "Total Number Demand     : " << total_demand << endl;
359  out << "Total Number Prefetches : " << m_outstanding_count - total_demand << endl;
360  out << endl;
361  out << endl;
362
363}
364
365void Sequencer::printConfig(ostream& out) {
366  if (TSO) {
367    out << "sequencer: Sequencer - TSO" << endl;
368  } else {
369    out << "sequencer: Sequencer - SC" << endl;
370  }
371  out << "  max_outstanding_requests: " << g_SEQUENCER_OUTSTANDING_REQUESTS << endl;
372}
373
374bool Sequencer::empty() const {
375  return m_outstanding_count == 0;
376}
377
378// Insert the request on the correct request table.  Return true if
379// the entry was already present.
380bool Sequencer::insertRequest(const CacheMsg& request) {
381  int thread = request.getThreadID();
382  assert(thread >= 0);
383  int total_outstanding = 0;
384  int smt_threads = RubyConfig::numberofSMTThreads();
385  for(int p=0; p < smt_threads; ++p){
386    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
387  }
388  assert(m_outstanding_count == total_outstanding);
389
390  // See if we should schedule a deadlock check
391  if (m_deadlock_check_scheduled == false) {
392    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
393    m_deadlock_check_scheduled = true;
394  }
395
396  if ((request.getType() == CacheRequestType_ST) ||
397      (request.getType() == CacheRequestType_ST_XACT) ||
398      (request.getType() == CacheRequestType_LDX_XACT) ||
399      (request.getType() == CacheRequestType_ATOMIC)) {
400    if (m_writeRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) {
401      m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
402      return true;
403    }
404    m_writeRequestTable_ptr[thread]->allocate(line_address(request.getAddress()));
405    m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
406    m_outstanding_count++;
407  } else {
408    if (m_readRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) {
409      m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
410      return true;
411    }
412    m_readRequestTable_ptr[thread]->allocate(line_address(request.getAddress()));
413    m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
414    m_outstanding_count++;
415  }
416
417  g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count);
418
419  total_outstanding = 0;
420  for(int p=0; p < smt_threads; ++p){
421    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
422  }
423
424  assert(m_outstanding_count == total_outstanding);
425  return false;
426}
427
428void Sequencer::removeRequest(const CacheMsg& request) {
429  int thread = request.getThreadID();
430  assert(thread >= 0);
431  int total_outstanding = 0;
432  int smt_threads = RubyConfig::numberofSMTThreads();
433  for(int p=0; p < smt_threads; ++p){
434    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
435  }
436  assert(m_outstanding_count == total_outstanding);
437
438  if ((request.getType() == CacheRequestType_ST) ||
439      (request.getType() == CacheRequestType_ST_XACT) ||
440      (request.getType() == CacheRequestType_LDX_XACT) ||
441      (request.getType() == CacheRequestType_ATOMIC)) {
442    m_writeRequestTable_ptr[thread]->deallocate(line_address(request.getAddress()));
443  } else {
444    m_readRequestTable_ptr[thread]->deallocate(line_address(request.getAddress()));
445  }
446  m_outstanding_count--;
447
448  total_outstanding = 0;
449  for(int p=0; p < smt_threads; ++p){
450    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
451  }
452  assert(m_outstanding_count == total_outstanding);
453}
454
455void Sequencer::writeCallback(const Address& address) {
456  DataBlock data;
457  writeCallback(address, data);
458}
459
460void Sequencer::writeCallback(const Address& address, DataBlock& data) {
461  // process oldest thread first
462  int thread = -1;
463  Time oldest_time = 0;
464  int smt_threads = RubyConfig::numberofSMTThreads();
465  for(int t=0; t < smt_threads; ++t){
466    if(m_writeRequestTable_ptr[t]->exist(address)){
467      CacheMsg & request = m_writeRequestTable_ptr[t]->lookup(address);
468      if(thread == -1 || (request.getTime() < oldest_time) ){
469        thread = t;
470        oldest_time = request.getTime();
471      }
472    }
473  }
474  // make sure we found an oldest thread
475  ASSERT(thread != -1);
476
477  CacheMsg & request = m_writeRequestTable_ptr[thread]->lookup(address);
478
479  writeCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread);
480}
481
482void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) {
483
484  assert(address == line_address(address));
485  assert(thread >= 0);
486  assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
487
488  writeCallback(address, data, respondingMach, thread);
489
490}
491
492void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) {
493  assert(address == line_address(address));
494  assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
495  CacheMsg request = m_writeRequestTable_ptr[thread]->lookup(address);
496  assert( request.getThreadID() == thread);
497  removeRequest(request);
498
499  assert((request.getType() == CacheRequestType_ST) ||
500         (request.getType() == CacheRequestType_ST_XACT) ||
501         (request.getType() == CacheRequestType_LDX_XACT) ||
502         (request.getType() == CacheRequestType_ATOMIC));
503
504  hitCallback(request, data, respondingMach, thread);
505
506}
507
508void Sequencer::readCallback(const Address& address) {
509  DataBlock data;
510  readCallback(address, data);
511}
512
513void Sequencer::readCallback(const Address& address, DataBlock& data) {
514  // process oldest thread first
515  int thread = -1;
516  Time oldest_time = 0;
517  int smt_threads = RubyConfig::numberofSMTThreads();
518  for(int t=0; t < smt_threads; ++t){
519    if(m_readRequestTable_ptr[t]->exist(address)){
520      CacheMsg & request = m_readRequestTable_ptr[t]->lookup(address);
521      if(thread == -1 || (request.getTime() < oldest_time) ){
522        thread = t;
523        oldest_time = request.getTime();
524      }
525    }
526  }
527  // make sure we found an oldest thread
528  ASSERT(thread != -1);
529
530  CacheMsg & request = m_readRequestTable_ptr[thread]->lookup(address);
531
532  readCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread);
533}
534
535void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) {
536
537  assert(address == line_address(address));
538  assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
539
540  readCallback(address, data, respondingMach, thread);
541}
542
543void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) {
544  assert(address == line_address(address));
545  assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
546
547  CacheMsg request = m_readRequestTable_ptr[thread]->lookup(address);
548  assert( request.getThreadID() == thread );
549  removeRequest(request);
550
551  assert((request.getType() == CacheRequestType_LD) ||
552         (request.getType() == CacheRequestType_LD_XACT) ||
553         (request.getType() == CacheRequestType_IFETCH)
554         );
555
556  hitCallback(request, data, respondingMach, thread);
557}
558
559void Sequencer::hitCallback(const CacheMsg& request, DataBlock& data, GenericMachineType respondingMach, int thread) {
560  int size = request.getSize();
561  Address request_address = request.getAddress();
562  Address request_logical_address = request.getLogicalAddress();
563  Address request_line_address = line_address(request_address);
564  CacheRequestType type = request.getType();
565  int threadID = request.getThreadID();
566  Time issued_time = request.getTime();
567  int logical_proc_no = ((m_chip_ptr->getID() * RubyConfig::numberOfProcsPerChip()) + m_version) * RubyConfig::numberofSMTThreads() + threadID;
568
569  DEBUG_MSG(SEQUENCER_COMP, MedPrio, size);
570
571  // Set this cache entry to the most recently used
572  if (type == CacheRequestType_IFETCH) {
573    if (Protocol::m_TwoLevelCache) {
574      if (m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
575        m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->setMRU(request_line_address);
576      }
577    }
578    else {
579      if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
580        m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address);
581      }
582    }
583  } else {
584    if (Protocol::m_TwoLevelCache) {
585      if (m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
586        m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->setMRU(request_line_address);
587      }
588    }
589    else {
590      if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
591        m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address);
592      }
593    }
594  }
595
596  assert(g_eventQueue_ptr->getTime() >= issued_time);
597  Time miss_latency = g_eventQueue_ptr->getTime() - issued_time;
598
599  if (PROTOCOL_DEBUG_TRACE) {
600    g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), -1, request.getAddress(), "", "Done", "",
601                                                   int_to_string(miss_latency)+" cycles "+GenericMachineType_to_string(respondingMach)+" "+CacheRequestType_to_string(request.getType())+" "+PrefetchBit_to_string(request.getPrefetch()));
602  }
603
604  DEBUG_MSG(SEQUENCER_COMP, MedPrio, request_address);
605  DEBUG_MSG(SEQUENCER_COMP, MedPrio, request.getPrefetch());
606  if (request.getPrefetch() == PrefetchBit_Yes) {
607    DEBUG_MSG(SEQUENCER_COMP, MedPrio, "return");
608    g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach);
609    return; // Ignore the software prefetch, don't callback the driver
610  }
611
612  // Profile the miss latency for all non-zero demand misses
613  if (miss_latency != 0) {
614    g_system_ptr->getProfiler()->missLatency(miss_latency, type, respondingMach);
615
616#if 0
617    uinteger_t tick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick"));
618    uinteger_t tick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick_cmpr"));
619    uinteger_t stick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick"));
620    uinteger_t stick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick_cmpr"));
621    cout << "END PROC " << m_version << hex << " tick = " << tick << " tick_cmpr = " << tick_cmpr << " stick = " << stick << " stick_cmpr = " << stick_cmpr << " cycle = "<< g_eventQueue_ptr->getTime() << dec << endl;
622#endif
623
624  }
625
626  bool write =
627    (type == CacheRequestType_ST) ||
628    (type == CacheRequestType_ST_XACT) ||
629    (type == CacheRequestType_LDX_XACT) ||
630    (type == CacheRequestType_ATOMIC);
631
632  if (TSO && write) {
633    m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->callBack(line_address(request.getAddress()), data);
634  } else {
635
636    // Copy the correct bytes out of the cache line into the subblock
637    SubBlock subblock(request_address, request_logical_address, size);
638    subblock.mergeFrom(data);  // copy the correct bytes from DataBlock in the SubBlock
639
640    // Scan the store buffer to see if there are any outstanding stores we need to collect
641    if (TSO) {
642      m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->updateSubBlock(subblock);
643    }
644
645    // Call into the Driver (Tester or Simics) and let it read and/or modify the sub-block
646    g_system_ptr->getDriver()->hitCallback(m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, subblock, type, threadID);
647
648    // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock
649    // (This is only triggered for the non-TSO case)
650    if (write) {
651      assert(!TSO);
652      subblock.mergeTo(data);    // copy the correct bytes from SubBlock into the DataBlock
653    }
654  }
655}
656
657void Sequencer::readConflictCallback(const Address& address) {
658  // process oldest thread first
659  int thread = -1;
660  Time oldest_time = 0;
661  int smt_threads = RubyConfig::numberofSMTThreads();
662  for(int t=0; t < smt_threads; ++t){
663    if(m_readRequestTable_ptr[t]->exist(address)){
664      CacheMsg & request = m_readRequestTable_ptr[t]->lookup(address);
665      if(thread == -1 || (request.getTime() < oldest_time) ){
666        thread = t;
667        oldest_time = request.getTime();
668      }
669    }
670  }
671  // make sure we found an oldest thread
672  ASSERT(thread != -1);
673
674  CacheMsg & request = m_readRequestTable_ptr[thread]->lookup(address);
675
676  readConflictCallback(address, GenericMachineType_NULL, thread);
677}
678
679void Sequencer::readConflictCallback(const Address& address, GenericMachineType respondingMach, int thread) {
680  assert(address == line_address(address));
681  assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
682
683  CacheMsg request = m_readRequestTable_ptr[thread]->lookup(address);
684  assert( request.getThreadID() == thread );
685  removeRequest(request);
686
687  assert((request.getType() == CacheRequestType_LD) ||
688         (request.getType() == CacheRequestType_LD_XACT) ||
689         (request.getType() == CacheRequestType_IFETCH)
690         );
691
692  conflictCallback(request, respondingMach, thread);
693}
694
695void Sequencer::writeConflictCallback(const Address& address) {
696  // process oldest thread first
697  int thread = -1;
698  Time oldest_time = 0;
699  int smt_threads = RubyConfig::numberofSMTThreads();
700  for(int t=0; t < smt_threads; ++t){
701    if(m_writeRequestTable_ptr[t]->exist(address)){
702      CacheMsg & request = m_writeRequestTable_ptr[t]->lookup(address);
703      if(thread == -1 || (request.getTime() < oldest_time) ){
704        thread = t;
705        oldest_time = request.getTime();
706      }
707    }
708  }
709  // make sure we found an oldest thread
710  ASSERT(thread != -1);
711
712  CacheMsg & request = m_writeRequestTable_ptr[thread]->lookup(address);
713
714  writeConflictCallback(address, GenericMachineType_NULL, thread);
715}
716
717void Sequencer::writeConflictCallback(const Address& address, GenericMachineType respondingMach, int thread) {
718  assert(address == line_address(address));
719  assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
720  CacheMsg request = m_writeRequestTable_ptr[thread]->lookup(address);
721  assert( request.getThreadID() == thread);
722  removeRequest(request);
723
724  assert((request.getType() == CacheRequestType_ST) ||
725         (request.getType() == CacheRequestType_ST_XACT) ||
726         (request.getType() == CacheRequestType_LDX_XACT) ||
727         (request.getType() == CacheRequestType_ATOMIC));
728
729  conflictCallback(request, respondingMach, thread);
730
731}
732
733void Sequencer::conflictCallback(const CacheMsg& request, GenericMachineType respondingMach, int thread) {
734  assert(XACT_MEMORY);
735  int size = request.getSize();
736  Address request_address = request.getAddress();
737  Address request_logical_address = request.getLogicalAddress();
738  Address request_line_address = line_address(request_address);
739  CacheRequestType type = request.getType();
740  int threadID = request.getThreadID();
741  Time issued_time = request.getTime();
742  int logical_proc_no = ((m_chip_ptr->getID() * RubyConfig::numberOfProcsPerChip()) + m_version) * RubyConfig::numberofSMTThreads() + threadID;
743
744  DEBUG_MSG(SEQUENCER_COMP, MedPrio, size);
745
746  assert(g_eventQueue_ptr->getTime() >= issued_time);
747  Time miss_latency = g_eventQueue_ptr->getTime() - issued_time;
748
749  if (PROTOCOL_DEBUG_TRACE) {
750    g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), -1, request.getAddress(), "", "Conflict", "",
751                                                   int_to_string(miss_latency)+" cycles "+GenericMachineType_to_string(respondingMach)+" "+CacheRequestType_to_string(request.getType())+" "+PrefetchBit_to_string(request.getPrefetch()));
752  }
753
754  DEBUG_MSG(SEQUENCER_COMP, MedPrio, request_address);
755  DEBUG_MSG(SEQUENCER_COMP, MedPrio, request.getPrefetch());
756  if (request.getPrefetch() == PrefetchBit_Yes) {
757    DEBUG_MSG(SEQUENCER_COMP, MedPrio, "return");
758    g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach);
759    return; // Ignore the software prefetch, don't callback the driver
760  }
761
762  bool write =
763    (type == CacheRequestType_ST) ||
764    (type == CacheRequestType_ST_XACT) ||
765    (type == CacheRequestType_LDX_XACT) ||
766    (type == CacheRequestType_ATOMIC);
767
768  // Copy the correct bytes out of the cache line into the subblock
769  SubBlock subblock(request_address, request_logical_address, size);
770
771  // Call into the Driver (Tester or Simics)
772  g_system_ptr->getDriver()->conflictCallback(m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, subblock, type, threadID);
773
774  // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock
775  // (This is only triggered for the non-TSO case)
776  if (write) {
777    assert(!TSO);
778  }
779}
780
781void Sequencer::printDebug(){
782  //notify driver of debug
783  g_system_ptr->getDriver()->printDebug();
784}
785
786// Returns true if the sequencer already has a load or store outstanding
787bool
788Sequencer::isReady(const Packet* pkt) const
789{
790
791  int cpu_number = pkt->req->contextId();
792  la_t logical_addr = pkt->req->getVaddr();
793  pa_t physical_addr = pkt->req->getPaddr();
794  CacheRequestType type_of_request;
795  if ( pkt->req->isInstFetch() ) {
796    type_of_request = CacheRequestType_IFETCH;
797  } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) {
798    type_of_request = CacheRequestType_ATOMIC;
799  } else if ( pkt->isRead() ) {
800    type_of_request = CacheRequestType_LD;
801  } else if ( pkt->isWrite() ) {
802    type_of_request = CacheRequestType_ST;
803  } else {
804    assert(false);
805  }
806  int thread = pkt->req->threadId();
807
808  CacheMsg request(Address( physical_addr ),
809                   Address( physical_addr ),
810                   type_of_request,
811                   Address(0),
812                   AccessModeType_UserMode,   // User/supervisor mode
813                   0,   // Size in bytes of request
814                   PrefetchBit_No,  // Not a prefetch
815                   0,              // Version number
816                   Address(logical_addr),   // Virtual Address
817                   thread,              // SMT thread
818                   0,          // TM specific - timestamp of memory request
819                   false      // TM specific - whether request is part of escape action
820                   );
821  isReady(request);
822}
823
824bool
825Sequencer::isReady(const CacheMsg& request) const
826{
827  if (m_outstanding_count >= g_SEQUENCER_OUTSTANDING_REQUESTS) {
828    //cout << "TOO MANY OUTSTANDING: " << m_outstanding_count << " " << g_SEQUENCER_OUTSTANDING_REQUESTS << " VER " << m_version << endl;
829    //printProgress(cout);
830    return false;
831  }
832
833  // This code allows reads to be performed even when we have a write
834  // request outstanding for the line
835  bool write =
836    (request.getType() == CacheRequestType_ST) ||
837    (request.getType() == CacheRequestType_ST_XACT) ||
838    (request.getType() == CacheRequestType_LDX_XACT) ||
839    (request.getType() == CacheRequestType_ATOMIC);
840
841  // LUKE - disallow more than one request type per address
842  //     INVARIANT: at most one request type per address, per processor
843  int smt_threads = RubyConfig::numberofSMTThreads();
844  for(int p=0; p < smt_threads; ++p){
845    if( m_writeRequestTable_ptr[p]->exist(line_address(request.getAddress())) ||
846        m_readRequestTable_ptr[p]->exist(line_address(request.getAddress())) ){
847      //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl;
848      //printProgress(cout);
849      return false;
850    }
851  }
852
853  if (TSO) {
854    return m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady();
855  }
856  return true;
857}
858
859// Called by Driver (Simics or Tester).
860void
861Sequencer::makeRequest(const Packet* pkt, void* data)
862{
863  int cpu_number = pkt->req->contextId();
864  la_t logical_addr = pkt->req->getVaddr();
865  pa_t physical_addr = pkt->req->getPaddr();
866  int request_size = pkt->getSize();
867  CacheRequestType type_of_request;
868  if ( pkt->req->isInstFetch() ) {
869    type_of_request = CacheRequestType_IFETCH;
870  } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) {
871    type_of_request = CacheRequestType_ATOMIC;
872  } else if ( pkt->isRead() ) {
873    type_of_request = CacheRequestType_LD;
874  } else if ( pkt->isWrite() ) {
875    type_of_request = CacheRequestType_ST;
876  } else {
877    assert(false);
878  }
879  la_t virtual_pc = pkt->req->getPC();
880  int isPriv = false;  // TODO: get permission data
881  int thread = pkt->req->threadId();
882
883  AccessModeType access_mode = AccessModeType_UserMode; // TODO: get actual permission
884
885  CacheMsg request(Address( physical_addr ),
886                   Address( physical_addr ),
887                   type_of_request,
888                   Address(virtual_pc),
889                   access_mode,   // User/supervisor mode
890                   request_size,   // Size in bytes of request
891                   PrefetchBit_No, // Not a prefetch
892                   0,              // Version number
893                   Address(logical_addr),   // Virtual Address
894                   thread,         // SMT thread
895                   0,              // TM specific - timestamp of memory request
896                   false           // TM specific - whether request is part of escape action
897                   );
898  makeRequest(request);
899}
900
901void
902Sequencer::makeRequest(const CacheMsg& request)
903{
904  bool write = (request.getType() == CacheRequestType_ST) ||
905    (request.getType() == CacheRequestType_ST_XACT) ||
906    (request.getType() == CacheRequestType_LDX_XACT) ||
907    (request.getType() == CacheRequestType_ATOMIC);
908
909  if (TSO && (request.getPrefetch() == PrefetchBit_No) && write) {
910    assert(m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady());
911    m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->insertStore(request);
912    return;
913  }
914
915  bool hit = doRequest(request);
916
917}
918
919bool Sequencer::doRequest(const CacheMsg& request) {
920  bool hit = false;
921  // Check the fast path
922  DataBlock* data_ptr;
923
924  int thread = request.getThreadID();
925
926  hit = tryCacheAccess(line_address(request.getAddress()),
927                       request.getType(),
928                       request.getProgramCounter(),
929                       request.getAccessMode(),
930                       request.getSize(),
931                       data_ptr);
932
933  if (hit && (request.getType() == CacheRequestType_IFETCH || !REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) ) {
934    DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path hit");
935    hitCallback(request, *data_ptr, GenericMachineType_L1Cache, thread);
936    return true;
937  }
938
939#if 0
940  uinteger_t tick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick"));
941  uinteger_t tick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick_cmpr"));
942  uinteger_t stick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick"));
943  uinteger_t stick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick_cmpr"));
944  cout << "START PROC " << m_version << hex << " tick = " << tick << " tick_cmpr = " << tick_cmpr << " stick = " << stick << " stick_cmpr = " << stick_cmpr << " cycle = "<< g_eventQueue_ptr->getTime() << dec << endl;;
945#endif
946
947  if (TSO && (request.getType() == CacheRequestType_LD || request.getType() == CacheRequestType_IFETCH)) {
948
949    // See if we can satisfy the load entirely from the store buffer
950    SubBlock subblock(line_address(request.getAddress()), request.getSize());
951    if (m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->trySubBlock(subblock)) {
952      DataBlock dummy;
953      hitCallback(request, dummy, GenericMachineType_NULL, thread);  // Call with an 'empty' datablock, since the data is in the store buffer
954      return true;
955    }
956  }
957
958  DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path miss");
959  issueRequest(request);
960  return hit;
961}
962
963void Sequencer::issueRequest(const CacheMsg& request) {
964  bool found = insertRequest(request);
965
966  if (!found) {
967    CacheMsg msg = request;
968    msg.getAddress() = line_address(request.getAddress()); // Make line address
969
970    // Fast Path L1 misses are profiled here - all non-fast path misses are profiled within the generated protocol code
971    if (!REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) {
972      g_system_ptr->getProfiler()->addPrimaryStatSample(msg, m_chip_ptr->getID());
973    }
974
975    if (PROTOCOL_DEBUG_TRACE) {
976      g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip() + m_version), -1, msg.getAddress(),"", "Begin", "", CacheRequestType_to_string(request.getType()));
977    }
978
979#if 0
980    // Commented out by nate binkert because I removed the trace stuff
981    if (g_system_ptr->getTracer()->traceEnabled()) {
982      g_system_ptr->getTracer()->traceRequest((m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), msg.getAddress(), msg.getProgramCounter(),
983                                              msg.getType(), g_eventQueue_ptr->getTime());
984    }
985#endif
986
987    Time latency = 0;  // initialzed to an null value
988
989    latency = SEQUENCER_TO_CONTROLLER_LATENCY;
990
991    // Send the message to the cache controller
992    assert(latency > 0);
993    m_chip_ptr->m_L1Cache_mandatoryQueue_vec[m_version]->enqueue(msg, latency);
994
995  }  // !found
996}
997
998bool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type,
999                               const Address& pc, AccessModeType access_mode,
1000                               int size, DataBlock*& data_ptr) {
1001  if (type == CacheRequestType_IFETCH) {
1002    if (Protocol::m_TwoLevelCache) {
1003      return m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
1004    }
1005    else {
1006      return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
1007    }
1008  } else {
1009    if (Protocol::m_TwoLevelCache) {
1010      return m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
1011    }
1012    else {
1013      return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
1014    }
1015  }
1016}
1017
1018void Sequencer::resetRequestTime(const Address& addr, int thread){
1019  assert(thread >= 0);
1020  //reset both load and store requests, if they exist
1021  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
1022    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
1023    if( request.m_AccessMode != AccessModeType_UserMode){
1024      cout << "resetRequestType ERROR read request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl;
1025      printProgress(cout);
1026    }
1027    //ASSERT(request.m_AccessMode == AccessModeType_UserMode);
1028    request.setTime(g_eventQueue_ptr->getTime());
1029  }
1030  if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
1031    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
1032    if( request.m_AccessMode != AccessModeType_UserMode){
1033      cout << "resetRequestType ERROR write request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl;
1034      printProgress(cout);
1035    }
1036    //ASSERT(request.m_AccessMode == AccessModeType_UserMode);
1037    request.setTime(g_eventQueue_ptr->getTime());
1038  }
1039}
1040
1041// removes load request from queue
1042void Sequencer::removeLoadRequest(const Address & addr, int thread){
1043  removeRequest(getReadRequest(addr, thread));
1044}
1045
1046void Sequencer::removeStoreRequest(const Address & addr, int thread){
1047  removeRequest(getWriteRequest(addr, thread));
1048}
1049
1050// returns the read CacheMsg
1051CacheMsg & Sequencer::getReadRequest( const Address & addr, int thread ){
1052  Address temp = addr;
1053  assert(thread >= 0);
1054  assert(temp == line_address(temp));
1055  assert(m_readRequestTable_ptr[thread]->exist(addr));
1056  return m_readRequestTable_ptr[thread]->lookup(addr);
1057}
1058
1059CacheMsg & Sequencer::getWriteRequest( const Address & addr, int thread){
1060  Address temp = addr;
1061  assert(thread >= 0);
1062  assert(temp == line_address(temp));
1063  assert(m_writeRequestTable_ptr[thread]->exist(addr));
1064  return m_writeRequestTable_ptr[thread]->lookup(addr);
1065}
1066
1067void Sequencer::print(ostream& out) const {
1068  out << "[Sequencer: " << m_chip_ptr->getID()
1069      << ", outstanding requests: " << m_outstanding_count;
1070
1071  int smt_threads = RubyConfig::numberofSMTThreads();
1072  for(int p=0; p < smt_threads; ++p){
1073    out << ", read request table[ " << p << " ]: " << *m_readRequestTable_ptr[p]
1074        << ", write request table[ " << p << " ]: " << *m_writeRequestTable_ptr[p];
1075  }
1076  out << "]";
1077}
1078
1079// this can be called from setState whenever coherence permissions are upgraded
1080// when invoked, coherence violations will be checked for the given block
1081void Sequencer::checkCoherence(const Address& addr) {
1082#ifdef CHECK_COHERENCE
1083  g_system_ptr->checkGlobalCoherenceInvariant(addr);
1084#endif
1085}
1086
1087bool Sequencer::getRubyMemoryValue(const Address& addr, char* value,
1088                                   unsigned int size_in_bytes ) {
1089  if(g_SIMICS){
1090    for(unsigned int i=0; i < size_in_bytes; i++) {
1091      value[i] = SIMICS_read_physical_memory( m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version,
1092                                              addr.getAddress() + i, 1 );
1093    }
1094    return false; // Do nothing?
1095  } else {
1096    bool found = false;
1097    const Address lineAddr = line_address(addr);
1098    DataBlock data;
1099    PhysAddress paddr(addr);
1100    DataBlock* dataPtr = &data;
1101    Chip* n = dynamic_cast<Chip*>(m_chip_ptr);
1102    // LUKE - use variable names instead of macros
1103    assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL);
1104    assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL);
1105
1106    MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() );
1107    int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip();
1108
1109    if (Protocol::m_TwoLevelCache) {
1110      if(Protocol::m_CMP){
1111        assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL);
1112      }
1113      else{
1114        assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL);
1115      }
1116    }
1117
1118    if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){
1119      n->m_L1Cache_L1IcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes);
1120      found = true;
1121    } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
1122      n->m_L1Cache_L1DcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes);
1123      found = true;
1124    } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
1125      n->m_L2Cache_L2cacheMemory_vec[l2_ver]->getMemoryValue(addr, value, size_in_bytes);
1126      found = true;
1127      // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr)){
1128      //       ASSERT(n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr));
1129      //       L1Cache_TBE tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr);
1130
1131      //       int offset = addr.getOffset();
1132      //       for(int i=0; i<size_in_bytes; ++i){
1133      //         value[i] = tbeEntry.getDataBlk().getByte(offset + i);
1134      //       }
1135
1136      //       found = true;
1137    } else {
1138      // Address not found
1139      //cout << "  " << m_chip_ptr->getID() << " NOT IN CACHE, Value at Directory is: " << (int) value[0] << endl;
1140      n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip()));
1141      int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip();
1142      for(unsigned int i=0; i<size_in_bytes; ++i){
1143        int offset = addr.getOffset();
1144        value[i] = n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.getByte(offset + i);
1145      }
1146      // Address not found
1147      //WARN_MSG("Couldn't find address");
1148      //WARN_EXPR(addr);
1149      found = false;
1150    }
1151    return true;
1152  }
1153}
1154
1155bool Sequencer::setRubyMemoryValue(const Address& addr, char *value,
1156                                   unsigned int size_in_bytes) {
1157  char test_buffer[64];
1158
1159  if(g_SIMICS){
1160    return false; // Do nothing?
1161  } else {
1162    // idea here is that coherent cache should find the
1163    // latest data, the update it
1164    bool found = false;
1165    const Address lineAddr = line_address(addr);
1166    PhysAddress paddr(addr);
1167    DataBlock data;
1168    DataBlock* dataPtr = &data;
1169    Chip* n = dynamic_cast<Chip*>(m_chip_ptr);
1170
1171    MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() );
1172    int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip();
1173    // LUKE - use variable names instead of macros
1174    //cout << "number of L2caches per chip = " << RubyConfig::numberOfL2CachePerChip(m_version) << endl;
1175    //cout << "L1I cache vec size = " << n->m_L1Cache_L1IcacheMemory_vec.size() << endl;
1176    //cout << "L1D cache vec size = " << n->m_L1Cache_L1DcacheMemory_vec.size() << endl;
1177    //cout << "L1cache_cachememory size = " << n->m_L1Cache_cacheMemory_vec.size() << endl;
1178    //cout << "L1cache_l2cachememory size = " << n->m_L1Cache_L2cacheMemory_vec.size() << endl;
1179    // if (Protocol::m_TwoLevelCache) {
1180    //       if(Protocol::m_CMP){
1181    //         cout << "CMP L2 cache vec size = " << n->m_L2Cache_L2cacheMemory_vec.size() << endl;
1182    //       }
1183    //       else{
1184    //        cout << "L2 cache vec size = " << n->m_L1Cache_cacheMemory_vec.size() << endl;
1185    //       }
1186    //     }
1187
1188    assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL);
1189    assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL);
1190    if (Protocol::m_TwoLevelCache) {
1191      if(Protocol::m_CMP){
1192        assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL);
1193      }
1194      else{
1195        assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL);
1196      }
1197    }
1198
1199    if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){
1200      n->m_L1Cache_L1IcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes);
1201      found = true;
1202    } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
1203      n->m_L1Cache_L1DcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes);
1204      found = true;
1205    } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
1206      n->m_L2Cache_L2cacheMemory_vec[l2_ver]->setMemoryValue(addr, value, size_in_bytes);
1207      found = true;
1208      // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isTagPresent(lineAddr)){
1209      //       L1Cache_TBE& tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr);
1210      //       DataBlock tmpData;
1211      //       int offset = addr.getOffset();
1212      //       for(int i=0; i<size_in_bytes; ++i){
1213      //         tmpData.setByte(offset + i, value[i]);
1214      //       }
1215      //       tbeEntry.setDataBlk(tmpData);
1216      //       tbeEntry.setDirty(true);
1217    } else {
1218      // Address not found
1219      n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip()));
1220      int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip();
1221      for(unsigned int i=0; i<size_in_bytes; ++i){
1222        int offset = addr.getOffset();
1223        n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.setByte(offset + i, value[i]);
1224      }
1225      found = false;
1226    }
1227
1228    if (found){
1229      found = getRubyMemoryValue(addr, test_buffer, size_in_bytes);
1230      assert(found);
1231      if(value[0] != test_buffer[0]){
1232        WARN_EXPR((int) value[0]);
1233        WARN_EXPR((int) test_buffer[0]);
1234        ERROR_MSG("setRubyMemoryValue failed to set value.");
1235      }
1236    }
1237
1238    return true;
1239  }
1240}
1241