RubySystem.cc revision 7056
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->setSize(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::clearStats() const 152{ 153 m_profiler_ptr->clearStats(); 154 m_network_ptr->clearStats(); 155} 156 157void 158RubySystem::recordCacheContents(CacheRecorder& tr) const 159{ 160} 161 162#ifdef CHECK_COHERENCE 163// This code will check for cases if the given cache block is exclusive in 164// one node and shared in another-- a coherence violation 165// 166// To use, the SLICC specification must call sequencer.checkCoherence(address) 167// when the controller changes to a state with new permissions. Do this 168// in setState. The SLICC spec must also define methods "isBlockShared" 169// and "isBlockExclusive" that are specific to that protocol 170// 171void 172RubySystem::checkGlobalCoherenceInvariant(const Address& addr) 173{ 174#if 0 175 NodeID exclusive = -1; 176 bool sharedDetected = false; 177 NodeID lastShared = -1; 178 179 for (int i = 0; i < m_chip_vector.size(); i++) { 180 if (m_chip_vector[i]->isBlockExclusive(addr)) { 181 if (exclusive != -1) { 182 // coherence violation 183 WARN_EXPR(exclusive); 184 WARN_EXPR(m_chip_vector[i]->getID()); 185 WARN_EXPR(addr); 186 WARN_EXPR(g_eventQueue_ptr->getTime()); 187 ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips"); 188 } else if (sharedDetected) { 189 WARN_EXPR(lastShared); 190 WARN_EXPR(m_chip_vector[i]->getID()); 191 WARN_EXPR(addr); 192 WARN_EXPR(g_eventQueue_ptr->getTime()); 193 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); 194 } else { 195 exclusive = m_chip_vector[i]->getID(); 196 } 197 } else if (m_chip_vector[i]->isBlockShared(addr)) { 198 sharedDetected = true; 199 lastShared = m_chip_vector[i]->getID(); 200 201 if (exclusive != -1) { 202 WARN_EXPR(lastShared); 203 WARN_EXPR(exclusive); 204 WARN_EXPR(addr); 205 WARN_EXPR(g_eventQueue_ptr->getTime()); 206 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); 207 } 208 } 209 } 210#endif 211} 212#endif 213 214RubySystem * 215RubySystemParams::create() 216{ 217 return new RubySystem(this); 218} 219 220/** 221 * virtual process function that is invoked when the callback 222 * queue is executed. 223 */ 224void 225RubyExitCallback::process() 226{ 227 std::ostream *os = simout.create(stats_filename); 228 RubySystem::printConfig(*os); 229 *os << endl; 230 RubySystem::printStats(*os); 231} 232