RubySystem.cc revision 7039
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/output.hh" 30#include "mem/ruby/buffers/MessageBuffer.hh" 31#include "mem/ruby/common/Address.hh" 32#include "mem/ruby/network/Network.hh" 33#include "mem/ruby/profiler/Profiler.hh" 34#include "mem/ruby/recorder/Tracer.hh" 35#include "mem/ruby/slicc_interface/AbstractController.hh" 36#include "mem/ruby/system/MemoryVector.hh" 37#include "mem/ruby/system/System.hh" 38 39int RubySystem::m_random_seed; 40bool RubySystem::m_randomization; 41Tick RubySystem::m_clock; 42int RubySystem::m_block_size_bytes; 43int RubySystem::m_block_size_bits; 44uint64 RubySystem::m_memory_size_bytes; 45int RubySystem::m_memory_size_bits; 46 47Network* RubySystem::m_network_ptr; 48Profiler* RubySystem::m_profiler_ptr; 49Tracer* RubySystem::m_tracer_ptr; 50MemoryVector* RubySystem::m_mem_vec_ptr; 51 52RubySystem::RubySystem(const Params *p) 53 : SimObject(p) 54{ 55 if (g_system_ptr != NULL) 56 fatal("Only one RubySystem object currently allowed.\n"); 57 58 m_random_seed = p->random_seed; 59 srandom(m_random_seed); 60 m_randomization = p->randomization; 61 m_clock = p->clock; 62 63 m_block_size_bytes = p->block_size_bytes; 64 assert(is_power_of_2(m_block_size_bytes)); 65 m_block_size_bits = log_int(m_block_size_bytes); 66 67 m_memory_size_bytes = p->mem_size; 68 if (m_memory_size_bytes == 0) { 69 m_memory_size_bits = 0; 70 } else { 71 m_memory_size_bits = log_int(m_memory_size_bytes); 72 } 73 74 m_network_ptr = p->network; 75 g_debug_ptr = p->debug; 76 m_profiler_ptr = p->profiler; 77 m_tracer_ptr = p->tracer; 78 79 g_eventQueue_ptr = new RubyEventQueue(p->eventq, m_clock); 80 g_system_ptr = this; 81 if (p->no_mem_vec) { 82 m_mem_vec_ptr = NULL; 83 } else { 84 m_mem_vec_ptr = new MemoryVector; 85 m_mem_vec_ptr->setSize(m_memory_size_bytes); 86 } 87 88 // 89 // Print ruby configuration and stats at exit 90 // 91 RubyExitCallback* rubyExitCB = new RubyExitCallback(p->stats_filename); 92 registerExitCallback(rubyExitCB); 93} 94 95void 96RubySystem::init() 97{ 98 m_profiler_ptr->clearStats(); 99} 100 101RubySystem::~RubySystem() 102{ 103 delete m_network_ptr; 104 delete m_profiler_ptr; 105 delete m_tracer_ptr; 106 if (m_mem_vec_ptr) 107 delete m_mem_vec_ptr; 108} 109 110void 111RubySystem::printSystemConfig(ostream & out) 112{ 113 out << "RubySystem config:" << endl 114 << " random_seed: " << m_random_seed << endl 115 << " randomization: " << m_randomization << endl 116 << " cycle_period: " << m_clock << endl 117 << " block_size_bytes: " << m_block_size_bytes << endl 118 << " block_size_bits: " << m_block_size_bits << endl 119 << " memory_size_bytes: " << m_memory_size_bytes << endl 120 << " memory_size_bits: " << m_memory_size_bits << endl; 121} 122 123void 124RubySystem::printConfig(ostream& out) 125{ 126 out << "\n================ Begin RubySystem Configuration Print ================\n\n"; 127 printSystemConfig(out); 128 m_network_ptr->printConfig(out); 129 m_profiler_ptr->printConfig(out); 130 out << "\n================ End RubySystem Configuration Print ================\n\n"; 131} 132 133void 134RubySystem::printStats(ostream& out) 135{ 136 const time_t T = time(NULL); 137 tm *localTime = localtime(&T); 138 char buf[100]; 139 strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime); 140 141 out << "Real time: " << buf << endl; 142 143 m_profiler_ptr->printStats(out); 144 m_network_ptr->printStats(out); 145} 146 147void 148RubySystem::clearStats() const 149{ 150 m_profiler_ptr->clearStats(); 151 m_network_ptr->clearStats(); 152} 153 154void 155RubySystem::recordCacheContents(CacheRecorder& tr) const 156{ 157} 158 159#ifdef CHECK_COHERENCE 160// This code will check for cases if the given cache block is exclusive in 161// one node and shared in another-- a coherence violation 162// 163// To use, the SLICC specification must call sequencer.checkCoherence(address) 164// when the controller changes to a state with new permissions. Do this 165// in setState. The SLICC spec must also define methods "isBlockShared" 166// and "isBlockExclusive" that are specific to that protocol 167// 168void 169RubySystem::checkGlobalCoherenceInvariant(const Address& addr) 170{ 171#if 0 172 NodeID exclusive = -1; 173 bool sharedDetected = false; 174 NodeID lastShared = -1; 175 176 for (int i = 0; i < m_chip_vector.size(); i++) { 177 if (m_chip_vector[i]->isBlockExclusive(addr)) { 178 if (exclusive != -1) { 179 // coherence violation 180 WARN_EXPR(exclusive); 181 WARN_EXPR(m_chip_vector[i]->getID()); 182 WARN_EXPR(addr); 183 WARN_EXPR(g_eventQueue_ptr->getTime()); 184 ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips"); 185 } else if (sharedDetected) { 186 WARN_EXPR(lastShared); 187 WARN_EXPR(m_chip_vector[i]->getID()); 188 WARN_EXPR(addr); 189 WARN_EXPR(g_eventQueue_ptr->getTime()); 190 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); 191 } else { 192 exclusive = m_chip_vector[i]->getID(); 193 } 194 } else if (m_chip_vector[i]->isBlockShared(addr)) { 195 sharedDetected = true; 196 lastShared = m_chip_vector[i]->getID(); 197 198 if (exclusive != -1) { 199 WARN_EXPR(lastShared); 200 WARN_EXPR(exclusive); 201 WARN_EXPR(addr); 202 WARN_EXPR(g_eventQueue_ptr->getTime()); 203 ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); 204 } 205 } 206 } 207#endif 208} 209#endif 210 211RubySystem * 212RubySystemParams::create() 213{ 214 return new RubySystem(this); 215} 216 217/** 218 * virtual process function that is invoked when the callback 219 * queue is executed. 220 */ 221void 222RubyExitCallback::process() 223{ 224 std::ostream *os = simout.create(stats_filename); 225 RubySystem::printConfig(*os); 226 *os << endl; 227 RubySystem::printStats(*os); 228} 229