RubySystem.cc revision 7562
1/* 2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "base/intmath.hh" 30#include "base/output.hh" 31#include "mem/ruby/buffers/MessageBuffer.hh" 32#include "mem/ruby/common/Address.hh" 33#include "mem/ruby/network/Network.hh" 34#include "mem/ruby/profiler/Profiler.hh" 35#include "mem/ruby/recorder/Tracer.hh" 36#include "mem/ruby/slicc_interface/AbstractController.hh" 37#include "mem/ruby/system/MemoryVector.hh" 38#include "mem/ruby/system/System.hh" 39 40using namespace std; 41 42int RubySystem::m_random_seed; 43bool RubySystem::m_randomization; 44Tick RubySystem::m_clock; 45int RubySystem::m_block_size_bytes; 46int RubySystem::m_block_size_bits; 47uint64 RubySystem::m_memory_size_bytes; 48int RubySystem::m_memory_size_bits; 49 50Network* RubySystem::m_network_ptr; 51Profiler* RubySystem::m_profiler_ptr; 52Tracer* RubySystem::m_tracer_ptr; 53MemoryVector* RubySystem::m_mem_vec_ptr; 54 55RubySystem::RubySystem(const Params *p) 56 : SimObject(p) 57{ 58 if (g_system_ptr != NULL) 59 fatal("Only one RubySystem object currently allowed.\n"); 60 61 m_random_seed = p->random_seed; 62 srandom(m_random_seed); 63 m_randomization = p->randomization; 64 m_clock = p->clock; 65 66 m_block_size_bytes = p->block_size_bytes; 67 assert(isPowerOf2(m_block_size_bytes)); 68 m_block_size_bits = floorLog2(m_block_size_bytes); 69 70 m_memory_size_bytes = p->mem_size; 71 if (m_memory_size_bytes == 0) { 72 m_memory_size_bits = 0; 73 } else { 74 m_memory_size_bits = floorLog2(m_memory_size_bytes); 75 } 76 77 m_network_ptr = p->network; 78 g_debug_ptr = p->debug; 79 m_profiler_ptr = p->profiler; 80 m_tracer_ptr = p->tracer; 81 82 g_eventQueue_ptr = new RubyEventQueue(p->eventq, m_clock); 83 g_system_ptr = this; 84 if (p->no_mem_vec) { 85 m_mem_vec_ptr = NULL; 86 } else { 87 m_mem_vec_ptr = new MemoryVector; 88 m_mem_vec_ptr->resize(m_memory_size_bytes); 89 } 90 91 // 92 // Print ruby configuration and stats at exit 93 // 94 RubyExitCallback* rubyExitCB = new RubyExitCallback(p->stats_filename); 95 registerExitCallback(rubyExitCB); 96} 97 98void 99RubySystem::init() 100{ 101 m_profiler_ptr->clearStats(); 102} 103 104RubySystem::~RubySystem() 105{ 106 delete m_network_ptr; 107 delete m_profiler_ptr; 108 delete m_tracer_ptr; 109 if (m_mem_vec_ptr) 110 delete m_mem_vec_ptr; 111} 112 113void 114RubySystem::printSystemConfig(ostream & out) 115{ 116 out << "RubySystem config:" << endl 117 << " random_seed: " << m_random_seed << endl 118 << " randomization: " << m_randomization << endl 119 << " cycle_period: " << m_clock << endl 120 << " block_size_bytes: " << m_block_size_bytes << endl 121 << " block_size_bits: " << m_block_size_bits << endl 122 << " memory_size_bytes: " << m_memory_size_bytes << endl 123 << " memory_size_bits: " << m_memory_size_bits << endl; 124} 125 126void 127RubySystem::printConfig(ostream& out) 128{ 129 out << "\n================ Begin RubySystem Configuration Print ================\n\n"; 130 printSystemConfig(out); 131 m_network_ptr->printConfig(out); 132 m_profiler_ptr->printConfig(out); 133 out << "\n================ End RubySystem Configuration Print ================\n\n"; 134} 135 136void 137RubySystem::printStats(ostream& out) 138{ 139 const time_t T = time(NULL); 140 tm *localTime = localtime(&T); 141 char buf[100]; 142 strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime); 143 144 out << "Real time: " << buf << endl; 145 146 m_profiler_ptr->printStats(out); 147 m_network_ptr->printStats(out); 148} 149 150void 151RubySystem::serialize(std::ostream &os) 152{ 153 154} 155 156void 157RubySystem::unserialize(Checkpoint *cp, const string §ion) 158{ 159 // 160 // The main purpose for clearing stats in the unserialize process is so 161 // that the profiler can correctly set its start time to the unserialized 162 // value of curTick 163 // 164 clearStats(); 165} 166 167void 168RubySystem::clearStats() const 169{ 170 m_profiler_ptr->clearStats(); 171 m_network_ptr->clearStats(); 172} 173 174void 175RubySystem::recordCacheContents(CacheRecorder& tr) const 176{ 177} 178 179#ifdef CHECK_COHERENCE 180// This code will check for cases if the given cache block is exclusive in 181// one node and shared in another-- a coherence violation 182// 183// To use, the SLICC specification must call sequencer.checkCoherence(address) 184// when the controller changes to a state with new permissions. Do this 185// in setState. The SLICC spec must also define methods "isBlockShared" 186// and "isBlockExclusive" that are specific to that protocol 187// 188void 189RubySystem::checkGlobalCoherenceInvariant(const Address& addr) 190{ 191#if 0 192 NodeID exclusive = -1; 193 bool sharedDetected = false; 194 NodeID lastShared = -1; 195 196 for (int i = 0; i < m_chip_vector.size(); i++) { 197 if (m_chip_vector[i]->isBlockExclusive(addr)) { 198 if (exclusive != -1) { 199 // coherence violation 200 WARN_EXPR(exclusive); 201 WARN_EXPR(m_chip_vector[i]->getID()); 202 WARN_EXPR(addr); 203 WARN_EXPR(g_eventQueue_ptr->getTime()); 204 ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips"); 205 } else if (sharedDetected) { 206 WARN_EXPR(lastShared); 207 WARN_EXPR(m_chip_vector[i]->getID()); 208 WARN_EXPR(addr); 209 WARN_EXPR(g_eventQueue_ptr->getTime()); 210 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); 211 } else { 212 exclusive = m_chip_vector[i]->getID(); 213 } 214 } else if (m_chip_vector[i]->isBlockShared(addr)) { 215 sharedDetected = true; 216 lastShared = m_chip_vector[i]->getID(); 217 218 if (exclusive != -1) { 219 WARN_EXPR(lastShared); 220 WARN_EXPR(exclusive); 221 WARN_EXPR(addr); 222 WARN_EXPR(g_eventQueue_ptr->getTime()); 223 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); 224 } 225 } 226 } 227#endif 228} 229#endif 230 231RubySystem * 232RubySystemParams::create() 233{ 234 return new RubySystem(this); 235} 236 237/** 238 * virtual process function that is invoked when the callback 239 * queue is executed. 240 */ 241void 242RubyExitCallback::process() 243{ 244 std::ostream *os = simout.create(stats_filename); 245 RubySystem::printConfig(*os); 246 *os << endl; 247 RubySystem::printStats(*os); 248} 249