InvalidateGenerator.cc revision 6145
1
2/*
3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * $Id$
32 *
33 */
34
35// This Deterministic Generator generates GETX requests for all nodes in the system
36// The GETX requests are generated one at a time in round-robin fashion 0...1...2...etc.
37
38#include "DetermGETXGenerator.hh"
39#include "DetermGETXGeneratorStatus.hh"
40#include "LockStatus.hh"
41#include "Sequencer.hh"
42#include "System.hh"
43#include "RubyConfig.hh"
44#include "SubBlock.hh"
45#include "DeterministicDriver.hh"
46#include "Chip.hh"
47
48DetermGETXGenerator::DetermGETXGenerator(NodeID node, DeterministicDriver& driver) :
49  m_driver(driver)
50{
51  m_status = DetermGETXGeneratorStatus_Thinking;
52  m_last_transition = 0;
53  m_node = node;
54  m_address = Address(9999);  // initialize to null value
55  m_counter = 0;
56
57  // don't know exactly when this node needs to request so just guess randomly
58  g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
59}
60
61DetermGETXGenerator::~DetermGETXGenerator()
62{
63}
64
65void DetermGETXGenerator::wakeup()
66{
67  DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
68  DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
69
70  // determine if this node is next for the GETX round robin request
71  if (m_status == DetermGETXGeneratorStatus_Thinking) {
72    if (m_driver.isStoreReady(m_node)) {
73      pickAddress();
74      m_status = DetermGETXGeneratorStatus_Store_Pending;  // Store Pending
75      m_last_transition = g_eventQueue_ptr->getTime();
76      initiateStore();  // GETX
77    } else { // I'll check again later
78      g_eventQueue_ptr->scheduleEvent(this, thinkTime());
79    }
80  } else {
81    WARN_EXPR(m_status);
82    ERROR_MSG("Invalid status");
83  }
84
85}
86
87void DetermGETXGenerator::performCallback(NodeID proc, SubBlock& data)
88{
89  Address address = data.getAddress();
90  assert(proc == m_node);
91  assert(address == m_address);
92
93  DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
94  DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
95  DEBUG_EXPR(TESTER_COMP, LowPrio, address);
96  DEBUG_EXPR(TESTER_COMP, LowPrio, data);
97
98  if (m_status == DetermGETXGeneratorStatus_Store_Pending) {
99    m_driver.recordStoreLatency(g_eventQueue_ptr->getTime() - m_last_transition);
100    data.writeByte(m_node);
101    m_driver.storeCompleted(m_node, data.getAddress());  // advance the store queue
102
103    m_counter++;
104    if (m_counter < g_tester_length) {
105      m_status = DetermGETXGeneratorStatus_Thinking;
106      m_last_transition = g_eventQueue_ptr->getTime();
107      g_eventQueue_ptr->scheduleEvent(this, waitTime());
108    } else {
109      m_driver.reportDone();
110      m_status = DetermGETXGeneratorStatus_Done;
111      m_last_transition = g_eventQueue_ptr->getTime();
112    }
113
114  } else {
115    WARN_EXPR(m_status);
116    ERROR_MSG("Invalid status");
117  }
118}
119
120int DetermGETXGenerator::thinkTime() const
121{
122  return g_think_time;
123}
124
125int DetermGETXGenerator::waitTime() const
126{
127  return g_wait_time;
128}
129
130void DetermGETXGenerator::pickAddress()
131{
132  assert(m_status == DetermGETXGeneratorStatus_Thinking);
133
134  m_address = m_driver.getNextStoreAddr(m_node);
135}
136
137void DetermGETXGenerator::initiateStore()
138{
139  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Store");
140  sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, Address(0), 0 /* only 1 SMT thread */, 0, false));
141}
142
143Sequencer* DetermGETXGenerator::sequencer() const
144{
145  return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
146}
147
148void DetermGETXGenerator::print(ostream& out) const
149{
150}
151
152