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