InvalidateGenerator.cc revision 6357
1
2/*
3    Copyright (C) 1999-2008 by Mark D. Hill and David A. Wood for the
4    Wisconsin Multifacet Project.  Contact: gems@cs.wisc.edu
5    http://www.cs.wisc.edu/gems/
6
7    --------------------------------------------------------------------
8
9    This file is part of the Ruby Multiprocessor Memory System Simulator,
10    a component of the Multifacet GEMS (General Execution-driven
11    Multiprocessor Simulator) software toolset originally developed at
12    the University of Wisconsin-Madison.
13
14    Ruby was originally developed primarily by Milo Martin and Daniel
15    Sorin with contributions from Ross Dickson, Carl Mauer, and Manoj
16    Plakal.
17
18    Substantial further development of Multifacet GEMS at the
19    University of Wisconsin was performed by Alaa Alameldeen, Brad
20    Beckmann, Jayaram Bobba, Ross Dickson, Dan Gibson, Pacia Harper,
21    Derek Hower, Milo Martin, Michael Marty, Carl Mauer, Michelle Moravan,
22    Kevin Moore, Andrew Phelps, Manoj Plakal, Daniel Sorin, Haris Volos,
23    Min Xu, and Luke Yen.
24    --------------------------------------------------------------------
25
26    If your use of this software contributes to a published paper, we
27    request that you (1) cite our summary paper that appears on our
28    website (http://www.cs.wisc.edu/gems/) and (2) e-mail a citation
29    for your published paper to gems@cs.wisc.edu.
30
31    If you redistribute derivatives of this software, we request that
32    you notify us and either (1) ask people to register with us at our
33    website (http://www.cs.wisc.edu/gems/) or (2) collect registration
34    information and periodically send it to us.
35
36    --------------------------------------------------------------------
37
38    Multifacet GEMS is free software; you can redistribute it and/or
39    modify it under the terms of version 2 of the GNU General Public
40    License as published by the Free Software Foundation.
41
42    Multifacet GEMS is distributed in the hope that it will be useful,
43    but WITHOUT ANY WARRANTY; without even the implied warranty of
44    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
45    General Public License for more details.
46
47    You should have received a copy of the GNU General Public License
48    along with the Multifacet GEMS; if not, write to the Free Software
49    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
50    02111-1307, USA
51
52    The GNU General Public License is contained in the file LICENSE.
53
54### END HEADER ###
55*/
56
57/*
58 * $Id$
59 *
60 */
61
62// This Deterministic Generator generates GETX requests for all nodes in the system
63// The GETX requests are generated one at a time in round-robin fashion 0...1...2...etc.
64
65#include "mem/ruby/tester/DetermGETXGenerator.hh"
66#include "mem/protocol/DetermGETXGeneratorStatus.hh"
67#include "mem/ruby/tester/DeterministicDriver.hh"
68#include "mem/ruby/tester/Tester_Globals.hh"
69#include "mem/ruby/common/Global.hh"
70#include "mem/ruby/tester/SpecifiedGenerator.hh"
71//#include "DMAController.hh"
72#include "mem/ruby/libruby.hh"
73
74
75DetermGETXGenerator::DetermGETXGenerator(NodeID node, DeterministicDriver * driver)
76{
77  m_status = DetermGETXGeneratorStatus_Thinking;
78  m_last_transition = 0;
79  counter = 0;
80  m_node = node;
81  m_address = Address(1);  // initialize to null value
82  m_counter = 0;
83  issued_load = false;
84  parent_driver = driver;
85  // don't know exactly when this node needs to request so just guess randomly
86  parent_driver->eventQueue->scheduleEvent(this, 1+(random() % 200));
87}
88
89DetermGETXGenerator::~DetermGETXGenerator()
90{
91}
92
93void DetermGETXGenerator::wakeup()
94{
95  DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
96  DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
97
98  // determine if this node is next for the GETX round robin request
99  if (m_status == DetermGETXGeneratorStatus_Thinking) {
100    if (parent_driver->isStoreReady(m_node)) {
101      if (!issued_load) {
102        pickAddress();
103      }
104      m_status = DetermGETXGeneratorStatus_Store_Pending;  // Store Pending
105      m_last_transition = parent_driver->eventQueue->getTime();
106      initiateStore();  // GETX
107    } else { // I'll check again later
108      parent_driver->eventQueue->scheduleEvent(this, thinkTime());
109    }
110  } else {
111    WARN_EXPR(m_status);
112    ERROR_MSG("Invalid status");
113  }
114
115}
116
117void DetermGETXGenerator::performCallback(NodeID proc, Address address)
118{
119  assert(proc == m_node);
120  assert(address == m_address);
121
122  DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
123  DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
124  DEBUG_EXPR(TESTER_COMP, LowPrio, address);
125
126  if (m_status == DetermGETXGeneratorStatus_Store_Pending) {
127    parent_driver->recordStoreLatency(parent_driver->eventQueue->getTime() - m_last_transition);
128    parent_driver->storeCompleted(m_node, address);  // advance the store queue
129
130    m_counter++;
131    if (m_counter < parent_driver->m_tester_length) {
132      m_status = DetermGETXGeneratorStatus_Thinking;
133      m_last_transition = parent_driver->eventQueue->getTime();
134      parent_driver->eventQueue->scheduleEvent(this, waitTime());
135    } else {
136      parent_driver->reportDone();
137      m_status = DetermGETXGeneratorStatus_Done;
138      m_last_transition = parent_driver->eventQueue->getTime();
139    }
140
141  } else {
142    WARN_EXPR(m_status);
143    ERROR_MSG("Invalid status");
144  }
145}
146
147int DetermGETXGenerator::thinkTime() const
148{
149  return parent_driver->m_think_time;
150}
151
152int DetermGETXGenerator::waitTime() const
153{
154  return parent_driver->m_wait_time;
155}
156
157void DetermGETXGenerator::pickAddress()
158{
159  assert(m_status == DetermGETXGeneratorStatus_Thinking);
160
161  m_address = parent_driver->getNextStoreAddr(m_node);
162}
163
164void DetermGETXGenerator::initiateStore()
165{
166  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Store");
167  uint8_t *write_data = new uint8_t[64];
168  for(int i=0; i < 64; i++) {
169      write_data[i] = m_node;
170  }
171
172  char name [] = "Sequencer_";
173  char port_name [13];
174  sprintf(port_name, "%s%d", name, m_node);
175  int64_t request_id;
176  if (counter%10 == 0) {
177    if (!issued_load) {
178      cerr << m_node << " RMW_Read to address: " << m_address.getAddress() << endl << flush;
179      request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_RMW_Read, RubyAccessMode_Supervisor));
180      issued_load = true;
181    }
182    else {
183      cerr << m_node << " RMW_Write to address: " << m_address.getAddress() << endl << flush;
184      request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_RMW_Write, RubyAccessMode_Supervisor));
185      issued_load = false;
186      counter++;
187    }
188  }
189  else {
190      cerr << m_node << " ST to address: " << m_address.getAddress() << endl << flush;
191      request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_ST, RubyAccessMode_Supervisor));
192      counter++;
193  }
194
195  // delete [] write_data;
196
197  ASSERT(parent_driver->requests.find(request_id) == parent_driver->requests.end());
198  parent_driver->requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
199}
200
201void DetermGETXGenerator::print(ostream& out) const
202{
203}
204
205