ruby: Converted old ruby debug calls to M5 debug calls
[gem5.git] / src / cpu / testers / rubytest / RubyTester.cc
1 /*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * Copyright (c) 2009 Advanced Micro Devices, Inc.
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 #include "cpu/testers/rubytest/Check.hh"
31 #include "cpu/testers/rubytest/RubyTester.hh"
32 #include "mem/ruby/common/Global.hh"
33 #include "mem/ruby/common/SubBlock.hh"
34 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
35 #include "mem/ruby/system/System.hh"
36 #include "sim/sim_exit.hh"
37
38 RubyTester::RubyTester(const Params *p)
39 : MemObject(p), checkStartEvent(this),
40 m_checks_to_complete(p->checks_to_complete),
41 m_deadlock_threshold(p->deadlock_threshold),
42 m_wakeup_frequency(p->wakeup_frequency)
43 {
44 m_checks_completed = 0;
45
46 // add the check start event to the event queue
47 schedule(checkStartEvent, 1);
48 }
49
50 RubyTester::~RubyTester()
51 {
52 delete m_checkTable_ptr;
53 for (int i = 0; i < ports.size(); i++)
54 delete ports[i];
55 }
56
57 void
58 RubyTester::init()
59 {
60 assert(ports.size() > 0);
61
62 m_last_progress_vector.resize(ports.size());
63 for (int i = 0; i < m_last_progress_vector.size(); i++) {
64 m_last_progress_vector[i] = 0;
65 }
66
67 m_num_cpu_sequencers = ports.size();
68
69 m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this);
70 }
71
72 Port *
73 RubyTester::getPort(const std::string &if_name, int idx)
74 {
75 if (if_name != "cpuPort") {
76 panic("RubyTester::getPort: unknown port %s requested", if_name);
77 }
78
79 if (idx >= (int)ports.size()) {
80 ports.resize(idx + 1);
81 }
82
83 if (ports[idx] != NULL) {
84 panic("RubyTester::getPort: port %d already assigned", idx);
85 }
86
87 CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx);
88
89 ports[idx] = port;
90 return port;
91 }
92
93 Tick
94 RubyTester::CpuPort::recvAtomic(PacketPtr pkt)
95 {
96 panic("RubyTester::CpuPort::recvAtomic() not implemented!\n");
97 return 0;
98 }
99
100 bool
101 RubyTester::CpuPort::recvTiming(PacketPtr pkt)
102 {
103 // retrieve the subblock and call hitCallback
104 RubyTester::SenderState* senderState =
105 safe_cast<RubyTester::SenderState*>(pkt->senderState);
106 SubBlock* subblock = senderState->subBlock;
107 assert(subblock != NULL);
108
109 // pop the sender state from the packet
110 pkt->senderState = senderState->saved;
111
112 tester->hitCallback(idx, subblock);
113
114 // Now that the tester has completed, delete the senderState
115 // (includes sublock) and the packet, then return
116 delete senderState;
117 delete pkt->req;
118 delete pkt;
119 return true;
120 }
121
122 Port*
123 RubyTester::getCpuPort(int idx)
124 {
125 assert(idx >= 0 && idx < ports.size());
126
127 return ports[idx];
128 }
129
130 void
131 RubyTester::hitCallback(NodeID proc, SubBlock* data)
132 {
133 // Mark that we made progress
134 m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
135
136 DPRINTF(RubyTest, "completed request for proc: %d\n", proc);
137 DPRINTF(RubyTest, "addr: 0x%x, size: %d, data: ",
138 data->getAddress(), data->getSize());
139 for (int byte = 0; byte < data->getSize(); byte++) {
140 DPRINTF(RubyTest, "%d", data->getByte(byte));
141 }
142 DPRINTF(RubyTest, "\n");
143
144 // This tells us our store has 'completed' or for a load gives us
145 // back the data to make the check
146 Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress());
147 assert(check_ptr != NULL);
148 check_ptr->performCallback(proc, data);
149 }
150
151 void
152 RubyTester::wakeup()
153 {
154 if (m_checks_completed < m_checks_to_complete) {
155 // Try to perform an action or check
156 Check* check_ptr = m_checkTable_ptr->getRandomCheck();
157 assert(check_ptr != NULL);
158 check_ptr->initiate();
159
160 checkForDeadlock();
161
162 schedule(checkStartEvent, curTick + m_wakeup_frequency);
163 } else {
164 exitSimLoop("Ruby Tester completed");
165 }
166 }
167
168 void
169 RubyTester::checkForDeadlock()
170 {
171 int size = m_last_progress_vector.size();
172 Time current_time = g_eventQueue_ptr->getTime();
173 for (int processor = 0; processor < size; processor++) {
174 if ((current_time - m_last_progress_vector[processor]) >
175 m_deadlock_threshold) {
176 WARN_EXPR(current_time);
177 WARN_EXPR(m_last_progress_vector[processor]);
178 WARN_EXPR(current_time - m_last_progress_vector[processor]);
179 WARN_EXPR(processor);
180 ERROR_MSG("Deadlock detected.");
181 }
182 }
183 }
184
185 void
186 RubyTester::print(std::ostream& out) const
187 {
188 out << "[RubyTester]" << std::endl;
189 }
190
191 RubyTester *
192 RubyTesterParams::create()
193 {
194 return new RubyTester(this);
195 }