RubySystem.cc revision 9208
19243SN/A/*
211846Swendy.elsasser@arm.com * Copyright (c) 1999-2011 Mark D. Hill and David A. Wood
39243SN/A * All rights reserved.
49243SN/A *
59243SN/A * Redistribution and use in source and binary forms, with or without
69243SN/A * modification, are permitted provided that the following conditions are
79243SN/A * met: redistributions of source code must retain the above copyright
89243SN/A * notice, this list of conditions and the following disclaimer;
99243SN/A * redistributions in binary form must reproduce the above copyright
109243SN/A * notice, this list of conditions and the following disclaimer in the
119243SN/A * documentation and/or other materials provided with the distribution;
129243SN/A * neither the name of the copyright holders nor the names of its
139243SN/A * contributors may be used to endorse or promote products derived from
149831SN/A * this software without specific prior written permission.
159831SN/A *
169831SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179243SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189243SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199243SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209243SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219243SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229243SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239243SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249243SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259243SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269243SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279243SN/A */
289243SN/A
299243SN/A#include <fcntl.h>
309243SN/A#include <zlib.h>
319243SN/A
329243SN/A#include <cstdio>
339243SN/A
349243SN/A#include "base/intmath.hh"
359243SN/A#include "base/output.hh"
369243SN/A#include "debug/RubyCacheTrace.hh"
379243SN/A#include "mem/ruby/common/Address.hh"
389243SN/A#include "mem/ruby/network/Network.hh"
399243SN/A#include "mem/ruby/profiler/Profiler.hh"
409243SN/A#include "mem/ruby/system/System.hh"
419243SN/A#include "sim/eventq.hh"
429967SN/A#include "sim/simulate.hh"
4310618SOmar.Naji@arm.com
4411678Swendy.elsasser@arm.comusing namespace std;
459243SN/A
469243SN/Aint RubySystem::m_random_seed;
4711793Sbrandon.potter@amd.combool RubySystem::m_randomization;
4811793Sbrandon.potter@amd.comint RubySystem::m_block_size_bytes;
4910146Sandreas.hansson@arm.comint RubySystem::m_block_size_bits;
509356SN/Auint64 RubySystem::m_memory_size_bytes;
5110146Sandreas.hansson@arm.comint RubySystem::m_memory_size_bits;
5210247Sandreas.hansson@arm.com
5310208Sandreas.hansson@arm.comNetwork* RubySystem::m_network_ptr;
549352SN/AProfiler* RubySystem::m_profiler_ptr;
559814SN/AMemoryVector* RubySystem::m_mem_vec_ptr;
569243SN/A
579243SN/ARubySystem::RubySystem(const Params *p)
5810432SOmar.Naji@arm.com    : ClockedObject(p)
599243SN/A{
6010146Sandreas.hansson@arm.com    if (g_system_ptr != NULL)
619243SN/A        fatal("Only one RubySystem object currently allowed.\n");
6210619Sandreas.hansson@arm.com
639243SN/A    m_random_seed = p->random_seed;
6410211Sandreas.hansson@arm.com    srandom(m_random_seed);
6511678Swendy.elsasser@arm.com    m_randomization = p->randomization;
6610618SOmar.Naji@arm.com
6710489SOmar.Naji@arm.com    m_block_size_bytes = p->block_size_bytes;
689831SN/A    assert(isPowerOf2(m_block_size_bytes));
699831SN/A    m_block_size_bits = floorLog2(m_block_size_bytes);
709831SN/A
719831SN/A    m_memory_size_bytes = p->mem_size;
729831SN/A    if (m_memory_size_bytes == 0) {
7310140SN/A        m_memory_size_bits = 0;
7410646Sandreas.hansson@arm.com    } else {
759243SN/A        m_memory_size_bits = floorLog2(m_memory_size_bytes);
7610394Swendy.elsasser@arm.com    }
7710394Swendy.elsasser@arm.com
789566SN/A    g_system_ptr = this;
799243SN/A    if (p->no_mem_vec) {
809243SN/A        m_mem_vec_ptr = NULL;
8110140SN/A    } else {
8210140SN/A        m_mem_vec_ptr = new MemoryVector;
8310147Sandreas.hansson@arm.com        m_mem_vec_ptr->resize(m_memory_size_bytes);
8410147Sandreas.hansson@arm.com    }
8510393Swendy.elsasser@arm.com
8610394Swendy.elsasser@arm.com    //
8710394Swendy.elsasser@arm.com    // Print ruby configuration and stats at exit
8811673SOmar.Naji@arm.com    //
8911673SOmar.Naji@arm.com    RubyExitCallback* rubyExitCB = new RubyExitCallback(p->stats_filename);
909243SN/A    registerExitCallback(rubyExitCB);
919243SN/A    m_warmup_enabled = false;
9210141SN/A    m_cooldown_enabled = false;
939726SN/A}
949726SN/A
9510618SOmar.Naji@arm.comvoid
9610618SOmar.Naji@arm.comRubySystem::init()
979243SN/A{
9810620Sandreas.hansson@arm.com    m_profiler_ptr->clearStats();
9910620Sandreas.hansson@arm.com}
10010620Sandreas.hansson@arm.com
10110620Sandreas.hansson@arm.comvoid
10210620Sandreas.hansson@arm.comRubySystem::registerNetwork(Network* network_ptr)
10310889Sandreas.hansson@arm.com{
10410889Sandreas.hansson@arm.com  m_network_ptr = network_ptr;
10510889Sandreas.hansson@arm.com}
10610618SOmar.Naji@arm.com
10712081Sspwilson2@wisc.eduvoid
10810618SOmar.Naji@arm.comRubySystem::registerProfiler(Profiler* profiler_ptr)
10910246Sandreas.hansson@arm.com{
11010246Sandreas.hansson@arm.com  m_profiler_ptr = profiler_ptr;
11110140SN/A}
11210140SN/A
11310140SN/Avoid
11410140SN/ARubySystem::registerAbstractController(AbstractController* cntrl)
11510140SN/A{
1169243SN/A  m_abs_cntrl_vec.push_back(cntrl);
1179243SN/A}
1189567SN/A
1199243SN/Avoid
12010489SOmar.Naji@arm.comRubySystem::registerSparseMemory(SparseMemory* s)
12110489SOmar.Naji@arm.com{
12210489SOmar.Naji@arm.com    m_sparse_memory_vector.push_back(s);
12310489SOmar.Naji@arm.com}
12410489SOmar.Naji@arm.com
12510489SOmar.Naji@arm.comvoid
12610489SOmar.Naji@arm.comRubySystem::registerMemController(MemoryControl *mc) {
12710489SOmar.Naji@arm.com    m_memory_controller = mc;
12810489SOmar.Naji@arm.com}
12910489SOmar.Naji@arm.com
1309243SN/ARubySystem::~RubySystem()
1319243SN/A{
1329831SN/A    delete m_network_ptr;
1339831SN/A    delete m_profiler_ptr;
1349831SN/A    if (m_mem_vec_ptr)
1359831SN/A        delete m_mem_vec_ptr;
1369831SN/A}
1379243SN/A
13810207Sandreas.hansson@arm.comvoid
13910207Sandreas.hansson@arm.comRubySystem::printStats(ostream& out)
14010207Sandreas.hansson@arm.com{
14110207Sandreas.hansson@arm.com    const time_t T = time(NULL);
14210207Sandreas.hansson@arm.com    tm *localTime = localtime(&T);
14310394Swendy.elsasser@arm.com    char buf[100];
14410394Swendy.elsasser@arm.com    strftime(buf, 100, "%b/%d/%Y %H:%M:%S", localTime);
14510394Swendy.elsasser@arm.com
14610394Swendy.elsasser@arm.com    out << "Real time: " << buf << endl;
14710394Swendy.elsasser@arm.com
14810394Swendy.elsasser@arm.com    m_profiler_ptr->printStats(out);
14910394Swendy.elsasser@arm.com    m_network_ptr->printStats(out);
15010394Swendy.elsasser@arm.com}
15110394Swendy.elsasser@arm.com
15210394Swendy.elsasser@arm.comvoid
15310394Swendy.elsasser@arm.comRubySystem::writeCompressedTrace(uint8_t *raw_data, string filename,
15410394Swendy.elsasser@arm.com                                 uint64 uncompressed_trace_size)
15510394Swendy.elsasser@arm.com{
15610394Swendy.elsasser@arm.com    // Create the checkpoint file for the memory
15710394Swendy.elsasser@arm.com    string thefile = Checkpoint::dir() + "/" + filename.c_str();
15810394Swendy.elsasser@arm.com
15910394Swendy.elsasser@arm.com    int fd = creat(thefile.c_str(), 0664);
16010394Swendy.elsasser@arm.com    if (fd < 0) {
16110394Swendy.elsasser@arm.com        perror("creat");
16210394Swendy.elsasser@arm.com        fatal("Can't open memory trace file '%s'\n", filename);
16310394Swendy.elsasser@arm.com    }
16410394Swendy.elsasser@arm.com
16510561SOmar.Naji@arm.com    gzFile compressedMemory = gzdopen(fd, "wb");
16610561SOmar.Naji@arm.com    if (compressedMemory == NULL)
16710394Swendy.elsasser@arm.com        fatal("Insufficient memory to allocate compression state for %s\n",
16810394Swendy.elsasser@arm.com              filename);
16910394Swendy.elsasser@arm.com
17010394Swendy.elsasser@arm.com    if (gzwrite(compressedMemory, raw_data, uncompressed_trace_size) !=
17110394Swendy.elsasser@arm.com        uncompressed_trace_size) {
17210394Swendy.elsasser@arm.com        fatal("Write failed on memory trace file '%s'\n", filename);
1739243SN/A    }
1749243SN/A
1759243SN/A    if (gzclose(compressedMemory)) {
17610146Sandreas.hansson@arm.com        fatal("Close failed on memory trace file '%s'\n", filename);
17710140SN/A    }
17810466Sandreas.hansson@arm.com    delete raw_data;
17910466Sandreas.hansson@arm.com}
18010466Sandreas.hansson@arm.com
18110146Sandreas.hansson@arm.comvoid
18210140SN/ARubySystem::serialize(std::ostream &os)
18310140SN/A{
18410140SN/A    m_cooldown_enabled = true;
18510646Sandreas.hansson@arm.com
18610646Sandreas.hansson@arm.com    vector<Sequencer*> sequencer_map;
18710646Sandreas.hansson@arm.com    Sequencer* sequencer_ptr = NULL;
18810646Sandreas.hansson@arm.com    int cntrl_id = -1;
18910646Sandreas.hansson@arm.com
19010646Sandreas.hansson@arm.com
19110646Sandreas.hansson@arm.com    for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) {
19210646Sandreas.hansson@arm.com        sequencer_map.push_back(m_abs_cntrl_vec[cntrl]->getSequencer());
19310646Sandreas.hansson@arm.com        if (sequencer_ptr == NULL) {
19410646Sandreas.hansson@arm.com            sequencer_ptr = sequencer_map[cntrl];
19510646Sandreas.hansson@arm.com            cntrl_id = cntrl;
19610646Sandreas.hansson@arm.com        }
19710646Sandreas.hansson@arm.com    }
19810646Sandreas.hansson@arm.com
19910646Sandreas.hansson@arm.com    assert(sequencer_ptr != NULL);
20010646Sandreas.hansson@arm.com
20110646Sandreas.hansson@arm.com    for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) {
20210646Sandreas.hansson@arm.com        if (sequencer_map[cntrl] == NULL) {
20310646Sandreas.hansson@arm.com            sequencer_map[cntrl] = sequencer_ptr;
20410646Sandreas.hansson@arm.com        }
20510646Sandreas.hansson@arm.com    }
20610646Sandreas.hansson@arm.com
20710646Sandreas.hansson@arm.com    DPRINTF(RubyCacheTrace, "Recording Cache Trace\n");
20810646Sandreas.hansson@arm.com    // Create the CacheRecorder and record the cache trace
20910646Sandreas.hansson@arm.com    m_cache_recorder = new CacheRecorder(NULL, 0, sequencer_map);
21010646Sandreas.hansson@arm.com
21110646Sandreas.hansson@arm.com    for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) {
21210646Sandreas.hansson@arm.com        m_abs_cntrl_vec[cntrl]->recordCacheTrace(cntrl, m_cache_recorder);
21310646Sandreas.hansson@arm.com    }
21410646Sandreas.hansson@arm.com
21510646Sandreas.hansson@arm.com    DPRINTF(RubyCacheTrace, "Cache Trace Complete\n");
21610646Sandreas.hansson@arm.com    // save the current tick value
21710646Sandreas.hansson@arm.com    Tick curtick_original = curTick();
21810646Sandreas.hansson@arm.com    // save the event queue head
21910646Sandreas.hansson@arm.com    Event* eventq_head = eventq->replaceHead(NULL);
22010646Sandreas.hansson@arm.com    DPRINTF(RubyCacheTrace, "Recording current tick %ld and event queue\n",
22110646Sandreas.hansson@arm.com            curtick_original);
22210646Sandreas.hansson@arm.com
22310646Sandreas.hansson@arm.com    // Schedule an event to start cache cooldown
22410646Sandreas.hansson@arm.com    DPRINTF(RubyCacheTrace, "Starting cache flush\n");
22510140SN/A    enqueueRubyEvent(curTick());
22610140SN/A    simulate();
22710140SN/A    DPRINTF(RubyCacheTrace, "Cache flush complete\n");
22810146Sandreas.hansson@arm.com
2299243SN/A    // Restore eventq head
23010619Sandreas.hansson@arm.com    eventq_head = eventq->replaceHead(eventq_head);
23110619Sandreas.hansson@arm.com    // Restore curTick
23210618SOmar.Naji@arm.com    curTick(curtick_original);
23310619Sandreas.hansson@arm.com
23410619Sandreas.hansson@arm.com    uint8_t *raw_data = NULL;
23510619Sandreas.hansson@arm.com
23610619Sandreas.hansson@arm.com    if (m_mem_vec_ptr != NULL) {
23710619Sandreas.hansson@arm.com        uint64 memory_trace_size = m_mem_vec_ptr->collatePages(raw_data);
23810619Sandreas.hansson@arm.com
23910619Sandreas.hansson@arm.com        string memory_trace_file = name() + ".memory.gz";
24010619Sandreas.hansson@arm.com        writeCompressedTrace(raw_data, memory_trace_file,
24110619Sandreas.hansson@arm.com                             memory_trace_size);
24210619Sandreas.hansson@arm.com
24310619Sandreas.hansson@arm.com        SERIALIZE_SCALAR(memory_trace_file);
24410619Sandreas.hansson@arm.com        SERIALIZE_SCALAR(memory_trace_size);
24510619Sandreas.hansson@arm.com
24610619Sandreas.hansson@arm.com    } else {
24710619Sandreas.hansson@arm.com        for (int i = 0; i < m_sparse_memory_vector.size(); ++i) {
24810618SOmar.Naji@arm.com            m_sparse_memory_vector[i]->recordBlocks(cntrl_id,
2499243SN/A                                                    m_cache_recorder);
2509243SN/A        }
2519243SN/A    }
25210146Sandreas.hansson@arm.com
2539243SN/A    // Aggergate the trace entries together into a single array
2549243SN/A    raw_data = new uint8_t[4096];
2559243SN/A    uint64 cache_trace_size = m_cache_recorder->aggregateRecords(&raw_data,
25611334Sandreas.hansson@arm.com                                                                 4096);
25711334Sandreas.hansson@arm.com    string cache_trace_file = name() + ".cache.gz";
25811334Sandreas.hansson@arm.com    writeCompressedTrace(raw_data, cache_trace_file, cache_trace_size);
2599243SN/A
2609243SN/A    SERIALIZE_SCALAR(cache_trace_file);
2619243SN/A    SERIALIZE_SCALAR(cache_trace_size);
2629243SN/A
26311334Sandreas.hansson@arm.com    m_cooldown_enabled = false;
2649243SN/A}
2659243SN/A
2669243SN/Avoid
2679243SN/ARubySystem::readCompressedTrace(string filename, uint8_t *&raw_data,
2689243SN/A                                uint64& uncompressed_trace_size)
2699243SN/A{
2709243SN/A    // Read the trace file
2719243SN/A    gzFile compressedTrace;
27210146Sandreas.hansson@arm.com
2739243SN/A    // trace file
2749831SN/A    int fd = open(filename.c_str(), O_RDONLY);
2759831SN/A    if (fd < 0) {
2769831SN/A        perror("open");
2779243SN/A        fatal("Unable to open trace file %s", filename);
2789831SN/A    }
2799831SN/A
2809243SN/A    compressedTrace = gzdopen(fd, "rb");
2819243SN/A    if (compressedTrace == NULL) {
2829243SN/A        fatal("Insufficient memory to allocate compression state for %s\n",
28310146Sandreas.hansson@arm.com              filename);
2849243SN/A    }
2859831SN/A
2869831SN/A    raw_data = new uint8_t[uncompressed_trace_size];
2879831SN/A    if (gzread(compressedTrace, raw_data, uncompressed_trace_size) <
2889243SN/A            uncompressed_trace_size) {
2899243SN/A        fatal("Unable to read complete trace from file %s\n", filename);
29010146Sandreas.hansson@arm.com    }
29110146Sandreas.hansson@arm.com
29210143SN/A    if (gzclose(compressedTrace)) {
2939243SN/A        fatal("Failed to close cache trace file '%s'\n", filename);
2949669SN/A    }
29510136SN/A}
29610136SN/A
2979243SN/Avoid
2989967SN/ARubySystem::unserialize(Checkpoint *cp, const string &section)
29910245Sandreas.hansson@arm.com{
30010245Sandreas.hansson@arm.com    //
30110245Sandreas.hansson@arm.com    // The main purpose for clearing stats in the unserialize process is so
3029243SN/A    // that the profiler can correctly set its start time to the unserialized
30310286Sandreas.hansson@arm.com    // value of curTick()
30410286Sandreas.hansson@arm.com    //
3059831SN/A    clearStats();
3069243SN/A    uint8_t *uncompressed_trace = NULL;
3079491SN/A
3089831SN/A    if (m_mem_vec_ptr != NULL) {
30910136SN/A        string memory_trace_file;
3109491SN/A        uint64 memory_trace_size = 0;
3119491SN/A
3129831SN/A        UNSERIALIZE_SCALAR(memory_trace_file);
3139243SN/A        UNSERIALIZE_SCALAR(memory_trace_size);
3149669SN/A        memory_trace_file = cp->cptDir + "/" + memory_trace_file;
3159566SN/A
3169566SN/A        readCompressedTrace(memory_trace_file, uncompressed_trace,
3179669SN/A                            memory_trace_size);
3189669SN/A        m_mem_vec_ptr->populatePages(uncompressed_trace);
3199669SN/A
3209669SN/A        delete uncompressed_trace;
3219669SN/A        uncompressed_trace = NULL;
3229669SN/A    }
3239669SN/A
3249669SN/A    string cache_trace_file;
3259669SN/A    uint64 cache_trace_size = 0;
3269669SN/A
32711189Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(cache_trace_file);
3289669SN/A    UNSERIALIZE_SCALAR(cache_trace_size);
32910136SN/A    cache_trace_file = cp->cptDir + "/" + cache_trace_file;
33010286Sandreas.hansson@arm.com
33110286Sandreas.hansson@arm.com    readCompressedTrace(cache_trace_file, uncompressed_trace,
33210286Sandreas.hansson@arm.com                        cache_trace_size);
3339669SN/A    m_warmup_enabled = true;
3349669SN/A
3359669SN/A    vector<Sequencer*> sequencer_map;
33610286Sandreas.hansson@arm.com    Sequencer* t = NULL;
33710286Sandreas.hansson@arm.com    for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) {
3389669SN/A        sequencer_map.push_back(m_abs_cntrl_vec[cntrl]->getSequencer());
3399669SN/A        if(t == NULL) t = sequencer_map[cntrl];
3409491SN/A    }
3419243SN/A
3429243SN/A    assert(t != NULL);
3439243SN/A
3449491SN/A    for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) {
3459491SN/A        if (sequencer_map[cntrl] == NULL) {
3469243SN/A            sequencer_map[cntrl] = t;
3479243SN/A        }
3489243SN/A    }
34911189Sandreas.hansson@arm.com
3509243SN/A    m_cache_recorder = new CacheRecorder(uncompressed_trace, cache_trace_size,
35110136SN/A                                         sequencer_map);
3529491SN/A}
3539491SN/A
3549491SN/Avoid
35510286Sandreas.hansson@arm.comRubySystem::startup()
35610286Sandreas.hansson@arm.com{
35710286Sandreas.hansson@arm.com    if (m_warmup_enabled) {
3589566SN/A        // save the current tick value
3599566SN/A        Tick curtick_original = curTick();
3609566SN/A        // save the event queue head
3619566SN/A        Event* eventq_head = eventq->replaceHead(NULL);
3629566SN/A        // set curTick to 0
3639491SN/A        curTick(0);
3649491SN/A
3659243SN/A        // Schedule an event to start cache warmup
3669243SN/A        enqueueRubyEvent(curTick());
3679243SN/A        simulate();
3689491SN/A
3699243SN/A        delete m_cache_recorder;
3709243SN/A        m_cache_recorder = NULL;
3719243SN/A        m_warmup_enabled = false;
37210286Sandreas.hansson@arm.com        // reset DRAM so that it's not waiting for events on the old event
37310286Sandreas.hansson@arm.com        // queue
3749243SN/A        m_memory_controller->reset();
37511189Sandreas.hansson@arm.com        // Restore eventq head
3769243SN/A        eventq_head = eventq->replaceHead(eventq_head);
3779243SN/A        // Restore curTick
3789243SN/A        curTick(curtick_original);
3799243SN/A    }
3809243SN/A}
3819243SN/A
3829243SN/Avoid
38310245Sandreas.hansson@arm.comRubySystem::RubyEvent::process()
3849243SN/A{
3859243SN/A    if (ruby_system->m_warmup_enabled) {
3869831SN/A        ruby_system->m_cache_recorder->enqueueNextFetchRequest();
3879243SN/A    }  else if (ruby_system->m_cooldown_enabled) {
3889243SN/A        ruby_system->m_cache_recorder->enqueueNextFlushRequest();
3899567SN/A    }
3909567SN/A}
3919967SN/A
3929967SN/Avoid
39310618SOmar.Naji@arm.comRubySystem::clearStats() const
3949243SN/A{
3959243SN/A    m_profiler_ptr->clearStats();
3969243SN/A    m_network_ptr->clearStats();
39710146Sandreas.hansson@arm.com}
3989243SN/A
3999243SN/A#ifdef CHECK_COHERENCE
4009243SN/A// This code will check for cases if the given cache block is exclusive in
4019243SN/A// one node and shared in another-- a coherence violation
4029243SN/A//
4039831SN/A// To use, the SLICC specification must call sequencer.checkCoherence(address)
4049831SN/A// when the controller changes to a state with new permissions.  Do this
4059831SN/A// in setState.  The SLICC spec must also define methods "isBlockShared"
4069831SN/A// and "isBlockExclusive" that are specific to that protocol
4079831SN/A//
4089831SN/Avoid
4099831SN/ARubySystem::checkGlobalCoherenceInvariant(const Address& addr)
4109831SN/A{
4119243SN/A#if 0
4129831SN/A    NodeID exclusive = -1;
4139831SN/A    bool sharedDetected = false;
4149831SN/A    NodeID lastShared = -1;
4159831SN/A
4169831SN/A    for (int i = 0; i < m_chip_vector.size(); i++) {
4179831SN/A        if (m_chip_vector[i]->isBlockExclusive(addr)) {
4189831SN/A            if (exclusive != -1) {
4199243SN/A                // coherence violation
4209831SN/A                WARN_EXPR(exclusive);
4219831SN/A                WARN_EXPR(m_chip_vector[i]->getID());
4229831SN/A                WARN_EXPR(addr);
42310889Sandreas.hansson@arm.com                WARN_EXPR(getTime());
42410889Sandreas.hansson@arm.com                ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips");
42510889Sandreas.hansson@arm.com            } else if (sharedDetected) {
42610889Sandreas.hansson@arm.com                WARN_EXPR(lastShared);
42710889Sandreas.hansson@arm.com                WARN_EXPR(m_chip_vector[i]->getID());
42810889Sandreas.hansson@arm.com                WARN_EXPR(addr);
42910889Sandreas.hansson@arm.com                WARN_EXPR(getTime());
43010889Sandreas.hansson@arm.com                ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
43110889Sandreas.hansson@arm.com            } else {
43210889Sandreas.hansson@arm.com                exclusive = m_chip_vector[i]->getID();
43310889Sandreas.hansson@arm.com            }
43410889Sandreas.hansson@arm.com        } else if (m_chip_vector[i]->isBlockShared(addr)) {
43510889Sandreas.hansson@arm.com            sharedDetected = true;
43610889Sandreas.hansson@arm.com            lastShared = m_chip_vector[i]->getID();
43710889Sandreas.hansson@arm.com
43810889Sandreas.hansson@arm.com            if (exclusive != -1) {
4399831SN/A                WARN_EXPR(lastShared);
4409243SN/A                WARN_EXPR(exclusive);
4419831SN/A                WARN_EXPR(addr);
4429831SN/A                WARN_EXPR(getTime());
4439831SN/A                ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
4449831SN/A            }
4459831SN/A        }
4469831SN/A    }
4479831SN/A#endif
4489831SN/A}
4499831SN/A#endif
4509831SN/A
4519831SN/ARubySystem *
4529831SN/ARubySystemParams::create()
4539966SN/A{
4549831SN/A    return new RubySystem(this);
4559831SN/A}
4569831SN/A
4579831SN/A/**
4589831SN/A * virtual process function that is invoked when the callback
4599831SN/A * queue is executed.
4609831SN/A */
4619831SN/Avoid
4629831SN/ARubyExitCallback::process()
46311678Swendy.elsasser@arm.com{
46411678Swendy.elsasser@arm.com    std::ostream *os = simout.create(stats_filename);
46511678Swendy.elsasser@arm.com    RubySystem::printStats(*os);
4669831SN/A}
4679831SN/A