3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
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.
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.
35 #include "mem/ruby/common/Global.hh"
36 #include "mem/ruby/system/System.hh"
37 #include "mem/ruby/tester/DeterministicDriver.hh"
38 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
39 #include "mem/ruby/tester/SpecifiedGenerator.hh"
40 #include "mem/ruby/tester/DetermGETXGenerator.hh"
41 #include "mem/ruby/tester/DetermInvGenerator.hh"
42 #include "mem/ruby/tester/DetermSeriesGETSGenerator.hh"
43 #include "mem/ruby/common/SubBlock.hh"
44 #include "mem/protocol/Chip.hh"
46 DeterministicDriver::DeterministicDriver(RubySystem
* sys_ptr
)
49 ERROR_MSG("g_SIMULATING should not be defined.");
55 m_loads_completed
= 0;
56 m_stores_completed
= 0;
58 m_numCompletionsPerNode
= g_NUM_COMPLETIONS_BEFORE_PASS
;
60 m_last_progress_vector
.setSize(RubyConfig::numberOfProcessors());
61 for (int i
=0; i
<m_last_progress_vector
.size(); i
++) {
62 m_last_progress_vector
[i
] = 0;
65 m_load_vector
.setSize(g_deterministic_addrs
);
66 for (int i
=0; i
<m_load_vector
.size(); i
++) {
67 m_load_vector
[i
] = -1; // No processor last held it
70 m_store_vector
.setSize(g_deterministic_addrs
);
71 for (int i
=0; i
<m_store_vector
.size(); i
++) {
72 m_store_vector
[i
] = -1; // No processor last held it
75 m_generator_vector
.setSize(RubyConfig::numberOfProcessors());
77 SpecifiedGeneratorType generator
= string_to_SpecifiedGeneratorType(g_SpecifiedGenerator
);
79 for (int i
=0; i
<m_generator_vector
.size(); i
++) {
81 case SpecifiedGeneratorType_DetermGETXGenerator
:
82 m_generator_vector
[i
] = new DetermGETXGenerator(i
, *this);
84 case SpecifiedGeneratorType_DetermSeriesGETSGenerator
:
85 m_generator_vector
[i
] = new DetermSeriesGETSGenerator(i
, *this);
87 case SpecifiedGeneratorType_DetermInvGenerator
:
88 m_generator_vector
[i
] = new DetermInvGenerator(i
, *this);
91 ERROR_MSG("Unexpected specified generator type");
95 // add the tester consumer to the global event queue
96 g_eventQueue_ptr
->scheduleEvent(this, 1);
99 DeterministicDriver::~DeterministicDriver()
101 for (int i
=0; i
<m_last_progress_vector
.size(); i
++) {
102 delete m_generator_vector
[i
];
106 void DeterministicDriver::hitCallback(NodeID proc
, SubBlock
& data
, CacheRequestType type
, int thread
)
108 DEBUG_EXPR(TESTER_COMP
, MedPrio
, data
);
110 m_generator_vector
[proc
]->performCallback(proc
, data
);
112 // Mark that we made progress
113 m_last_progress_vector
[proc
] = g_eventQueue_ptr
->getTime();
116 bool DeterministicDriver::isStoreReady(NodeID node
)
118 return isAddrReady(node
, m_store_vector
);
121 bool DeterministicDriver::isStoreReady(NodeID node
, Address addr
)
123 return isAddrReady(node
, m_store_vector
, addr
);
126 bool DeterministicDriver::isLoadReady(NodeID node
)
128 return isAddrReady(node
, m_load_vector
);
131 bool DeterministicDriver::isLoadReady(NodeID node
, Address addr
)
133 return isAddrReady(node
, m_load_vector
, addr
);
136 // searches for any address in the addr_vector
137 bool DeterministicDriver::isAddrReady(NodeID node
, Vector
<NodeID
> addr_vector
)
139 for (int i
=0; i
<addr_vector
.size(); i
++) {
140 if (((addr_vector
[i
]+1)%RubyConfig::numberOfProcessors() == node
) &&
141 (m_loads_completed
+m_stores_completed
>= m_numCompletionsPerNode
*node
) && // is this node next
142 (g_eventQueue_ptr
->getTime() >= m_last_issue
+ 10)) { // controll rate of requests
149 // test for a particular addr
150 bool DeterministicDriver::isAddrReady(NodeID node
, Vector
<NodeID
> addr_vector
, Address addr
)
152 int addr_number
= addr
.getAddress()/RubyConfig::dataBlockBytes();
154 ASSERT ((addr_number
>= 0) && (addr_number
< addr_vector
.size()));
156 if (((addr_vector
[addr_number
]+1)%RubyConfig::numberOfProcessors() == node
) &&
157 (m_loads_completed
+m_stores_completed
>= m_numCompletionsPerNode
*node
) && // is this node next
158 (g_eventQueue_ptr
->getTime() >= m_last_issue
+ 10)) { // controll rate of requests
165 void DeterministicDriver::loadCompleted(NodeID node
, Address addr
)
168 setNextAddr(node
, addr
, m_load_vector
);
171 void DeterministicDriver::storeCompleted(NodeID node
, Address addr
)
173 m_stores_completed
++;
174 setNextAddr(node
, addr
, m_store_vector
);
177 void DeterministicDriver::setNextAddr(NodeID node
, Address addr
, Vector
<NodeID
>& addr_vector
)
179 // mark the addr vector that this proc was the last to use the particular address
180 int addr_number
= addr
.getAddress()/RubyConfig::dataBlockBytes();
181 addr_vector
[addr_number
] = node
;
184 Address
DeterministicDriver::getNextLoadAddr(NodeID node
)
186 return getNextAddr(node
, m_load_vector
);
189 Address
DeterministicDriver::getNextStoreAddr(NodeID node
)
191 return getNextAddr(node
, m_store_vector
);
194 Address
DeterministicDriver::getNextAddr(NodeID node
, Vector
<NodeID
> addr_vector
)
197 // This method deterministically picks the next addr the node should acquirer
198 // The addrs cycle through according to NodeID 0->1->...->lastID->0...
202 // should only be called if we know a addr is ready for the node
203 ASSERT(isAddrReady(node
, addr_vector
));
205 for (int addr_number
=0; addr_number
<addr_vector
.size(); addr_number
++) {
206 //for (int addr_number=addr_vector.size()-1; addr_number>0; addr_number--) {
208 // is this node next in line for the addr
209 if (((addr_vector
[addr_number
]+1)%RubyConfig::numberOfProcessors()) == node
) {
211 // One addr per cache line
212 addr
.setAddress(addr_number
* RubyConfig::dataBlockBytes());
216 m_last_issue
= g_eventQueue_ptr
->getTime();
222 void DeterministicDriver::reportDone()
225 if ((m_done_counter
== RubyConfig::numberOfProcessors())) {
226 //|| (m_done_counter == g_tester_length)) {
227 m_finish_time
= g_eventQueue_ptr
->getTime();
231 void DeterministicDriver::recordLoadLatency(Time time
)
233 m_load_latency
.add(time
);
236 void DeterministicDriver::recordStoreLatency(Time time
)
238 m_store_latency
.add(time
);
241 void DeterministicDriver::wakeup()
243 // checkForDeadlock();
244 if (m_done_counter
< RubyConfig::numberOfProcessors()) {
245 g_eventQueue_ptr
->scheduleEvent(this, g_DEADLOCK_THRESHOLD
);
249 void DeterministicDriver::checkForDeadlock()
251 int size
= m_last_progress_vector
.size();
252 Time current_time
= g_eventQueue_ptr
->getTime();
253 for (int processor
=0; processor
<size
; processor
++) {
254 if ((current_time
- m_last_progress_vector
[processor
]) > g_DEADLOCK_THRESHOLD
) {
255 WARN_EXPR(processor
);
256 Sequencer
* seq_ptr
= g_system_ptr
->getChip(processor
/RubyConfig::numberOfProcsPerChip())->getSequencer(processor
%RubyConfig::numberOfProcsPerChip());
257 assert(seq_ptr
!= NULL
);
258 // if (seq_ptr->isRequestPending()) {
259 // WARN_EXPR(seq_ptr->pendingAddress());
261 WARN_EXPR(current_time
);
262 WARN_EXPR(m_last_progress_vector
[processor
]);
263 WARN_EXPR(current_time
- m_last_progress_vector
[processor
]);
264 ERROR_MSG("Deadlock detected.");
269 void DeterministicDriver::printStats(ostream
& out
) const
272 out
<< "DeterministicDriver Stats" << endl
;
273 out
<< "---------------------" << endl
;
275 out
<< "finish_time: " << m_finish_time
<< endl
;
276 out
<< "load_latency: " << m_load_latency
<< endl
;
277 out
<< "store_latency: " << m_store_latency
<< endl
;
280 void DeterministicDriver::print(ostream
& out
) const