RubySystem.cc revision 6285
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 * RubySystem.cc 32 * 33 * Description: See System.hh 34 * 35 * $Id$ 36 * 37 */ 38 39 40#include "mem/ruby/system/System.hh" 41#include "mem/ruby/common/Address.hh" 42#include "mem/ruby/profiler/Profiler.hh" 43#include "mem/ruby/network/Network.hh" 44#include "mem/ruby/recorder/Tracer.hh" 45#include "mem/protocol/Protocol.hh" 46#include "mem/ruby/buffers/MessageBuffer.hh" 47#include "mem/ruby/system/Sequencer.hh" 48#include "mem/ruby/system/DMASequencer.hh" 49#include "mem/ruby/system/MemoryVector.hh" 50#include "mem/protocol/ControllerFactory.hh" 51#include "mem/ruby/slicc_interface/AbstractController.hh" 52#include "mem/ruby/system/CacheMemory.hh" 53#include "mem/ruby/system/DirectoryMemory.hh" 54#include "mem/ruby/network/simple/Topology.hh" 55#include "mem/ruby/network/simple/SimpleNetwork.hh" 56#include "mem/ruby/system/RubyPort.hh" 57#include "mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh" 58#include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh" 59#include "mem/ruby/system/MemoryControl.hh" 60 61int RubySystem::m_random_seed; 62bool RubySystem::m_randomization; 63int RubySystem::m_tech_nm; 64int RubySystem::m_freq_mhz; 65int RubySystem::m_block_size_bytes; 66int RubySystem::m_block_size_bits; 67uint64 RubySystem::m_memory_size_bytes; 68int RubySystem::m_memory_size_bits; 69 70map< string, RubyPort* > RubySystem::m_ports; 71map< string, CacheMemory* > RubySystem::m_caches; 72map< string, DirectoryMemory* > RubySystem::m_directories; 73map< string, Sequencer* > RubySystem::m_sequencers; 74map< string, DMASequencer* > RubySystem::m_dma_sequencers; 75map< string, AbstractController* > RubySystem::m_controllers; 76map< string, MemoryControl* > RubySystem::m_memorycontrols; 77 78 79Network* RubySystem::m_network_ptr; 80map< string, Topology*> RubySystem::m_topologies; 81Profiler* RubySystem::m_profiler_ptr; 82Tracer* RubySystem::m_tracer_ptr; 83 84MemoryVector* RubySystem::m_mem_vec_ptr; 85 86 87RubySystem* RubySystem::create(const vector <RubyObjConf> & sys_conf) 88{ 89 if (g_system_ptr == NULL) 90 return new RubySystem(sys_conf); 91 return g_system_ptr; 92} 93 94void RubySystem::init(const vector<string> & argv) 95{ 96 for (size_t i=0; i < argv.size(); i+=2) { 97 if (argv[i] == "random_seed") { 98 m_random_seed = atoi(argv[i+1].c_str()); 99 srandom(m_random_seed); 100 } else if (argv[i] == "randomization") { 101 m_randomization = string_to_bool(argv[i+1]); 102 } else if (argv[i] == "tech_nm") { 103 m_tech_nm = atoi(argv[i+1].c_str()); 104 } else if (argv[i] == "freq_mhz") { 105 m_freq_mhz = atoi(argv[i+1].c_str()); 106 } else if (argv[i] == "block_size_bytes") { 107 m_block_size_bytes = atoi(argv[i+1].c_str()); 108 assert(is_power_of_2(m_block_size_bytes)); 109 m_block_size_bits = log_int(m_block_size_bytes); 110 } else if (argv[i] == "debug") { 111 112 } else if (argv[i] == "tracer") { 113 114 } else if (argv[i] == "profiler") { 115 116 // } else if (argv[i] == "MI_example") { 117 118 } else { 119 cerr << "Error: Unknown RubySystem config parameter -- " << argv[i] << endl; 120 assert(0); 121 } 122 } 123} 124 125RubySystem::RubySystem(const vector <RubyObjConf> & sys_conf) 126{ 127 // DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing"); 128 129 for (size_t i=0;i<sys_conf.size(); i++) { 130 const string & type = sys_conf[i].type; 131 const string & name = sys_conf[i].name; 132 const vector<string> & argv = sys_conf[i].argv; 133 if (type == "RubySystem") { 134 init(argv); // initialize system-wide variables before doing anything else! 135 } else if (type == "Debug") { 136 g_debug_ptr = new Debug(name, argv); 137 } 138 } 139 140 assert( g_debug_ptr != NULL); 141 g_eventQueue_ptr = new RubyEventQueue; 142 g_system_ptr = this; 143 m_mem_vec_ptr = new MemoryVector; 144 145 /* object contruction is broken into two steps (Constructor and init) to avoid cyclic dependencies 146 * e.g. a sequencer needs a pointer to a controller and a controller needs a pointer to a sequencer 147 */ 148 149 vector<string> memory_control_names; 150 151 for (size_t i=0;i<sys_conf.size(); i++) { 152 const string & type = sys_conf[i].type; 153 const string & name = sys_conf[i].name; 154 const vector<string> & argv = sys_conf[i].argv; 155 if (type == "RubySystem" || type == "Debug") 156 continue; 157 else if (type == "SetAssociativeCache") 158 m_caches[name] = new CacheMemory(name); 159 else if (type == "DirectoryMemory") 160 m_directories[name] = new DirectoryMemory(name); 161 else if (type == "Sequencer") { 162 m_sequencers[name] = new Sequencer(name); 163 m_ports[name] = m_sequencers[name]; 164 } else if (type == "DMASequencer") { 165 m_dma_sequencers[name] = new DMASequencer(name); 166 m_ports[name] = m_dma_sequencers[name]; 167 } else if (type == "Topology") { 168 assert(m_topologies.size() == 0); // only one toplogy at a time is supported right now 169 m_topologies[name] = new Topology(name); 170 } else if (type == "SimpleNetwork") { 171 assert(m_network_ptr == NULL); // only one network at a time is supported right now 172 m_network_ptr = new SimpleNetwork(name); 173 } else if (type.find("generated") == 0) { 174 string controller_type = type.substr(10); 175 m_controllers[name] = ControllerFactory::createController(controller_type, name); 176// printf ("ss: generated %s \n", controller_type); 177//added by SS 178 } else if (type == "Tracer") { 179 //m_tracers[name] = new Tracer(name); 180 m_tracer_ptr = new Tracer(name); 181 } else if (type == "Profiler") { 182 m_profiler_ptr = new Profiler(name); 183 } else if (type == "GarnetNetwork") { 184 assert(m_network_ptr == NULL); // only one network at a time is supported right now 185 m_network_ptr = new GarnetNetwork(name); 186 } else if (type == "GarnetNetwork_d") { 187 assert(m_network_ptr == NULL); // only one network at a time is supported right now 188 m_network_ptr = new GarnetNetwork_d(name); 189 } else if (type == "MemoryControl") { 190 m_memorycontrols[name] = new MemoryControl(name); 191 memory_control_names.push_back (name); 192 } else { 193 cerr << "Error: Unknown object type -- " << type << endl; 194 assert(0); 195 } 196 } 197 198 for (size_t i=0;i<sys_conf.size(); i++) { 199 string type = sys_conf[i].type; 200 string name = sys_conf[i].name; 201 const vector<string> & argv = sys_conf[i].argv; 202 if (type == "Topology") 203 m_topologies[name]->init(argv); 204 } 205 206 for (size_t i=0;i<sys_conf.size(); i++) { 207 string type = sys_conf[i].type; 208 string name = sys_conf[i].name; 209 const vector<string> & argv = sys_conf[i].argv; 210 if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d"){ 211 m_network_ptr->init(argv); 212 } 213 } 214 215 for (size_t i=0;i<sys_conf.size(); i++) { 216 string type = sys_conf[i].type; 217 string name = sys_conf[i].name; 218 const vector<string> & argv = sys_conf[i].argv; 219 if (type == "MemoryControl" ){ 220 m_memorycontrols[name]->init(argv); 221 } 222 } 223 224 for (size_t i=0;i<sys_conf.size(); i++) { 225 string type = sys_conf[i].type; 226 string name = sys_conf[i].name; 227 const vector<string> & argv = sys_conf[i].argv; 228 if (type == "RubySystem" || type == "Debug") 229 continue; 230 else if (type == "SetAssociativeCache") 231 m_caches[name]->init(argv); 232 else if (type == "DirectoryMemory") 233 m_directories[name]->init(argv); 234 else if (type == "MemoryControl") 235 continue; 236 else if (type == "Sequencer") 237 m_sequencers[name]->init(argv); 238 else if (type == "DMASequencer") 239 m_dma_sequencers[name]->init(argv); 240 else if (type == "Topology") 241 continue; 242 else if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d") 243 continue; 244 else if (type.find("generated") == 0) { 245 string controller_type = type.substr(11); 246 m_controllers[name]->init(m_network_ptr, argv); 247 } 248//added by SS 249 else if (type == "Tracer") 250 //m_tracers[name]->init(argv); 251 m_tracer_ptr->init(argv); 252 else if (type == "Profiler") 253 m_profiler_ptr->init(argv, memory_control_names); 254// else if (type == "MI_example"){ 255// } 256 else 257 assert(0); 258 } 259 260// m_profiler_ptr = new Profiler; 261 262 // calculate system-wide parameters 263 m_memory_size_bytes = 0; 264 DirectoryMemory* prev = NULL; 265 for (map< string, DirectoryMemory*>::const_iterator it = m_directories.begin(); 266 it != m_directories.end(); it++) { 267 if (prev != NULL) 268 assert((*it).second->getSize() == prev->getSize()); // must be equal for proper address mapping 269 m_memory_size_bytes += (*it).second->getSize(); 270 prev = (*it).second; 271 } 272 m_mem_vec_ptr->setSize(m_memory_size_bytes); 273 m_memory_size_bits = log_int(m_memory_size_bytes); 274 275// m_tracer_ptr = new Tracer; 276 DEBUG_MSG(SYSTEM_COMP, MedPrio,"finished initializing"); 277 DEBUG_NEWLINE(SYSTEM_COMP, MedPrio); 278} 279 280RubySystem::~RubySystem() 281{ 282 /* 283 for (int i=0; i < MachineType_base_level(MachineType_NUM); i++) { 284 for (int j=0; j < RubyConfig::getNumberOfControllersPerType(i); j++ ) { 285 delete m_controllers[i][j]; 286 } 287 } 288 delete m_network_ptr; 289 delete m_profiler_ptr; 290 delete m_tracer_ptr; 291 */ 292} 293 294void RubySystem::printSystemConfig(ostream & out) 295{ 296 out << "RubySystem config:" << endl; 297 out << " random_seed: " << m_random_seed << endl; 298 out << " randomization: " << m_randomization << endl; 299 out << " tech_nm: " << m_tech_nm << endl; 300 out << " freq_mhz: " << m_freq_mhz << endl; 301 out << " block_size_bytes: " << m_block_size_bytes << endl; 302 out << " block_size_bits: " << m_block_size_bits << endl; 303 out << " memory_size_bytes: " << m_memory_size_bytes << endl; 304 out << " memory_size_bits: " << m_memory_size_bits << endl; 305 306} 307 308void RubySystem::printConfig(ostream& out) 309{ 310 out << "\n================ Begin RubySystem Configuration Print ================\n\n"; 311 // RubyConfig::printConfiguration(out); 312 // out << endl; 313 printSystemConfig(out); 314 for (map<string, AbstractController*>::const_iterator it = m_controllers.begin(); 315 it != m_controllers.end(); it++) { 316 (*it).second->printConfig(out); 317 } 318 for (map<string, CacheMemory*>::const_iterator it = m_caches.begin(); 319 it != m_caches.end(); it++) { 320 (*it).second->printConfig(out); 321 } 322 DirectoryMemory::printGlobalConfig(out); 323 for (map<string, DirectoryMemory*>::const_iterator it = m_directories.begin(); 324 it != m_directories.end(); it++) { 325 (*it).second->printConfig(out); 326 } 327 for (map<string, Sequencer*>::const_iterator it = m_sequencers.begin(); 328 it != m_sequencers.end(); it++) { 329 (*it).second->printConfig(out); 330 } 331 332 m_network_ptr->printConfig(out); 333 m_profiler_ptr->printConfig(out); 334 335 out << "\n================ End RubySystem Configuration Print ================\n\n"; 336} 337 338void RubySystem::printStats(ostream& out) 339{ 340 341 const time_t T = time(NULL); 342 tm *localTime = localtime(&T); 343 char buf[100]; 344 strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime); 345 346 out << "Real time: " << buf << endl; 347 348 m_profiler_ptr->printStats(out); 349 m_network_ptr->printStats(out); 350 for (map<string, AbstractController*>::const_iterator it = m_controllers.begin(); 351 it != m_controllers.end(); it++) { 352 (*it).second->printStats(out); 353 } 354} 355 356void RubySystem::clearStats() const 357{ 358 /* 359 m_profiler_ptr->clearStats(); 360 for (int i=0; i<m_rubyRequestQueues.size(); i++) 361 for (int j=0;j<m_rubyRequestQueues[i].size(); j++) 362 m_rubyRequestQueues[i][j]->clearStats(); 363 m_network_ptr->clearStats(); 364 for (int i=0; i < MachineType_base_level(MachineType_NUM); i++) 365 m_controllers[i][0]->clearStats(); 366 */ 367} 368 369void RubySystem::recordCacheContents(CacheRecorder& tr) const 370{ 371 /* 372 for (int i = 0; i < m_chip_vector.size(); i++) { 373 for (int m_version = 0; m_version < RubyConfig::numberOfProcsPerChip(); m_version++) { 374 if (Protocol::m_TwoLevelCache) { 375 m_chip_vector[i]->m_L1Cache_L1IcacheMemory_vec[m_version]->setAsInstructionCache(true); 376 m_chip_vector[i]->m_L1Cache_L1DcacheMemory_vec[m_version]->setAsInstructionCache(false); 377 } else { 378 m_chip_vector[i]->m_L1Cache_cacheMemory_vec[m_version]->setAsInstructionCache(false); 379 } 380 } 381 m_chip_vector[i]->recordCacheContents(tr); 382 } 383 */ 384} 385 386#ifdef CHECK_COHERENCE 387// This code will check for cases if the given cache block is exclusive in 388// one node and shared in another-- a coherence violation 389// 390// To use, the SLICC specification must call sequencer.checkCoherence(address) 391// when the controller changes to a state with new permissions. Do this 392// in setState. The SLICC spec must also define methods "isBlockShared" 393// and "isBlockExclusive" that are specific to that protocol 394// 395void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) { 396 /* 397 NodeID exclusive = -1; 398 bool sharedDetected = false; 399 NodeID lastShared = -1; 400 401 for (int i = 0; i < m_chip_vector.size(); i++) { 402 403 if (m_chip_vector[i]->isBlockExclusive(addr)) { 404 if (exclusive != -1) { 405 // coherence violation 406 WARN_EXPR(exclusive); 407 WARN_EXPR(m_chip_vector[i]->getID()); 408 WARN_EXPR(addr); 409 WARN_EXPR(g_eventQueue_ptr->getTime()); 410 ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips"); 411 } 412 else if (sharedDetected) { 413 WARN_EXPR(lastShared); 414 WARN_EXPR(m_chip_vector[i]->getID()); 415 WARN_EXPR(addr); 416 WARN_EXPR(g_eventQueue_ptr->getTime()); 417 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); 418 } 419 else { 420 exclusive = m_chip_vector[i]->getID(); 421 } 422 } 423 else if (m_chip_vector[i]->isBlockShared(addr)) { 424 sharedDetected = true; 425 lastShared = m_chip_vector[i]->getID(); 426 427 if (exclusive != -1) { 428 WARN_EXPR(lastShared); 429 WARN_EXPR(exclusive); 430 WARN_EXPR(addr); 431 WARN_EXPR(g_eventQueue_ptr->getTime()); 432 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); 433 } 434 } 435 } 436 */ 437} 438#endif 439 440 441 442 443