/* * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * RubySystem.cc * * Description: See System.hh * * $Id$ * */ #include "mem/ruby/system/System.hh" #include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/network/Network.hh" #include "mem/ruby/tester/Tester.hh" #include "mem/ruby/tester/SyntheticDriver.hh" #include "mem/ruby/tester/DeterministicDriver.hh" #include "mem/protocol/Chip.hh" //#include "mem/ruby/recorder/Tracer.hh" #include "mem/protocol/Protocol.hh" RubySystem::RubySystem() { init(); m_preinitialized_driver = false; createDriver(); /* gem5:Binkert for decomissiong of tracer m_tracer_ptr = new Tracer; */ /* gem5:Arka for decomissiong of log_tm if (XACT_MEMORY) { m_xact_isolation_checker = new XactIsolationChecker; m_xact_commit_arbiter = new XactCommitArbiter; m_xact_visualizer = new XactVisualizer; } */ } RubySystem::RubySystem(Driver* _driver) { init(); m_preinitialized_driver = true; m_driver_ptr = _driver; } RubySystem::~RubySystem() { for (int i = 0; i < m_chip_vector.size(); i++) { delete m_chip_vector[i]; } if (!m_preinitialized_driver) delete m_driver_ptr; delete m_network_ptr; delete m_profiler_ptr; /* gem5:Binkert for decomissiong of tracer delete m_tracer_ptr; */ } void RubySystem::init() { DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing"); m_driver_ptr = NULL; m_profiler_ptr = new Profiler; // NETWORK INITIALIZATION // create the network by calling a function that calls new m_network_ptr = Network::createNetwork(RubyConfig::numberOfChips()); DEBUG_MSG(SYSTEM_COMP, MedPrio,"Constructed network"); // CHIP INITIALIZATION m_chip_vector.setSize(RubyConfig::numberOfChips());// create the vector of pointers to processors for(int i=0; iprintConfig(out); m_network_ptr->printConfig(out); m_driver_ptr->printConfig(out); m_profiler_ptr->printConfig(out); out << "\n================ End RubySystem Configuration Print ================\n\n"; } void RubySystem::printStats(ostream& out) { const time_t T = time(NULL); tm *localTime = localtime(&T); char buf[100]; strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime); out << "Real time: " << buf << endl; m_profiler_ptr->printStats(out); for(int i=0; im_L1Cache_mandatoryQueue_vec[p]->printStats(out); } } m_network_ptr->printStats(out); m_driver_ptr->printStats(out); Chip::printStats(out); } void RubySystem::clearStats() const { m_profiler_ptr->clearStats(); m_network_ptr->clearStats(); m_driver_ptr->clearStats(); Chip::clearStats(); for(int i=0; im_L1Cache_mandatoryQueue_vec[p]->clearStats(); } } } void RubySystem::recordCacheContents(CacheRecorder& tr) const { for (int i = 0; i < m_chip_vector.size(); i++) { for (int m_version = 0; m_version < RubyConfig::numberOfProcsPerChip(); m_version++) { if (Protocol::m_TwoLevelCache) { m_chip_vector[i]->m_L1Cache_L1IcacheMemory_vec[m_version]->setAsInstructionCache(true); m_chip_vector[i]->m_L1Cache_L1DcacheMemory_vec[m_version]->setAsInstructionCache(false); } else { m_chip_vector[i]->m_L1Cache_cacheMemory_vec[m_version]->setAsInstructionCache(false); } } m_chip_vector[i]->recordCacheContents(tr); } } #ifdef CHECK_COHERENCE // This code will check for cases if the given cache block is exclusive in // one node and shared in another-- a coherence violation // // To use, the SLICC specification must call sequencer.checkCoherence(address) // when the controller changes to a state with new permissions. Do this // in setState. The SLICC spec must also define methods "isBlockShared" // and "isBlockExclusive" that are specific to that protocol // void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) { NodeID exclusive = -1; bool sharedDetected = false; NodeID lastShared = -1; for (int i = 0; i < m_chip_vector.size(); i++) { if (m_chip_vector[i]->isBlockExclusive(addr)) { if (exclusive != -1) { // coherence violation WARN_EXPR(exclusive); WARN_EXPR(m_chip_vector[i]->getID()); WARN_EXPR(addr); WARN_EXPR(g_eventQueue_ptr->getTime()); ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips"); } else if (sharedDetected) { WARN_EXPR(lastShared); WARN_EXPR(m_chip_vector[i]->getID()); WARN_EXPR(addr); WARN_EXPR(g_eventQueue_ptr->getTime()); ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); } else { exclusive = m_chip_vector[i]->getID(); } } else if (m_chip_vector[i]->isBlockShared(addr)) { sharedDetected = true; lastShared = m_chip_vector[i]->getID(); if (exclusive != -1) { WARN_EXPR(lastShared); WARN_EXPR(exclusive); WARN_EXPR(addr); WARN_EXPR(g_eventQueue_ptr->getTime()); ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); } } } } #endif