pseudo_inst.cc (3368:3342dd3f5248) pseudo_inst.cc (3373:999202ee312c)
1/*
2 * Copyright (c) 2003-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31#include <errno.h>
32#include <fcntl.h>
33#include <unistd.h>
34
35#include <string>
36
37#include "sim/pseudo_inst.hh"
38#include "arch/vtophys.hh"
39#include "base/annotate.hh"
40#include "cpu/base.hh"
41#include "cpu/thread_context.hh"
42#include "cpu/quiesce_event.hh"
43#include "kern/kernel_stats.hh"
44#include "sim/param.hh"
45#include "sim/serialize.hh"
46#include "sim/sim_exit.hh"
47#include "sim/stat_control.hh"
48#include "sim/stats.hh"
49#include "sim/system.hh"
50#include "sim/debug.hh"
51#include "sim/vptr.hh"
52
53using namespace std;
54
55using namespace Stats;
56using namespace TheISA;
57
58namespace AlphaPseudo
59{
60 bool doStatisticsInsts;
61 bool doCheckpointInsts;
62 bool doQuiesce;
63
64 void
65 arm(ThreadContext *tc)
66 {
67 if (tc->getKernelStats())
68 tc->getKernelStats()->arm();
69 }
70
71 void
72 quiesce(ThreadContext *tc)
73 {
74 if (!doQuiesce)
75 return;
76
1/*
2 * Copyright (c) 2003-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31#include <errno.h>
32#include <fcntl.h>
33#include <unistd.h>
34
35#include <string>
36
37#include "sim/pseudo_inst.hh"
38#include "arch/vtophys.hh"
39#include "base/annotate.hh"
40#include "cpu/base.hh"
41#include "cpu/thread_context.hh"
42#include "cpu/quiesce_event.hh"
43#include "kern/kernel_stats.hh"
44#include "sim/param.hh"
45#include "sim/serialize.hh"
46#include "sim/sim_exit.hh"
47#include "sim/stat_control.hh"
48#include "sim/stats.hh"
49#include "sim/system.hh"
50#include "sim/debug.hh"
51#include "sim/vptr.hh"
52
53using namespace std;
54
55using namespace Stats;
56using namespace TheISA;
57
58namespace AlphaPseudo
59{
60 bool doStatisticsInsts;
61 bool doCheckpointInsts;
62 bool doQuiesce;
63
64 void
65 arm(ThreadContext *tc)
66 {
67 if (tc->getKernelStats())
68 tc->getKernelStats()->arm();
69 }
70
71 void
72 quiesce(ThreadContext *tc)
73 {
74 if (!doQuiesce)
75 return;
76
77 DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
78
77 tc->suspend();
78 if (tc->getKernelStats())
79 tc->getKernelStats()->quiesce();
80 }
81
82 void
83 quiesceNs(ThreadContext *tc, uint64_t ns)
84 {
85 if (!doQuiesce || ns == 0)
86 return;
87
88 EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
89
90 Tick resume = curTick + Clock::Int::ns * ns;
91
92 if (quiesceEvent->scheduled())
93 quiesceEvent->reschedule(resume);
94 else
95 quiesceEvent->schedule(resume);
96
97 DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
98 tc->getCpuPtr()->name(), ns, resume);
99
100 tc->suspend();
101 if (tc->getKernelStats())
102 tc->getKernelStats()->quiesce();
103 }
104
105 void
106 quiesceCycles(ThreadContext *tc, uint64_t cycles)
107 {
108 if (!doQuiesce || cycles == 0)
109 return;
110
111 EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
112
113 Tick resume = curTick + tc->getCpuPtr()->cycles(cycles);
114
115 if (quiesceEvent->scheduled())
116 quiesceEvent->reschedule(resume);
117 else
118 quiesceEvent->schedule(resume);
119
120 DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
121 tc->getCpuPtr()->name(), cycles, resume);
122
123 tc->suspend();
124 if (tc->getKernelStats())
125 tc->getKernelStats()->quiesce();
126 }
127
128 uint64_t
129 quiesceTime(ThreadContext *tc)
130 {
131 return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns;
132 }
133
134 void
135 ivlb(ThreadContext *tc)
136 {
137 if (tc->getKernelStats())
138 tc->getKernelStats()->ivlb();
139 }
140
141 void
142 ivle(ThreadContext *tc)
143 {
144 }
145
146 void
147 m5exit_old(ThreadContext *tc)
148 {
149 exitSimLoop("m5_exit_old instruction encountered");
150 }
151
152 void
153 m5exit(ThreadContext *tc, Tick delay)
154 {
155 Tick when = curTick + delay * Clock::Int::ns;
156 schedExitSimLoop("m5_exit instruction encountered", when);
157 }
158
159 void
160 loadsymbol(ThreadContext *tc)
161 {
162 const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
163 if (filename.empty()) {
164 return;
165 }
166
167 std::string buffer;
168 ifstream file(filename.c_str());
169
170 if (!file)
171 fatal("file error: Can't open symbol table file %s\n", filename);
172
173 while (!file.eof()) {
174 getline(file, buffer);
175
176 if (buffer.empty())
177 continue;
178
179 int idx = buffer.find(' ');
180 if (idx == string::npos)
181 continue;
182
183 string address = "0x" + buffer.substr(0, idx);
184 eat_white(address);
185 if (address.empty())
186 continue;
187
188 // Skip over letter and space
189 string symbol = buffer.substr(idx + 3);
190 eat_white(symbol);
191 if (symbol.empty())
192 continue;
193
194 Addr addr;
195 if (!to_number(address, addr))
196 continue;
197
198 if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
199 continue;
200
201
202 DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
203 }
204 file.close();
205 }
206
207 void
208 resetstats(ThreadContext *tc, Tick delay, Tick period)
209 {
210 if (!doStatisticsInsts)
211 return;
212
213
214 Tick when = curTick + delay * Clock::Int::ns;
215 Tick repeat = period * Clock::Int::ns;
216
217 using namespace Stats;
218 SetupEvent(Reset, when, repeat);
219 }
220
221 void
222 dumpstats(ThreadContext *tc, Tick delay, Tick period)
223 {
224 if (!doStatisticsInsts)
225 return;
226
227
228 Tick when = curTick + delay * Clock::Int::ns;
229 Tick repeat = period * Clock::Int::ns;
230
231 using namespace Stats;
232 SetupEvent(Dump, when, repeat);
233 }
234
235 void
236 addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
237 {
238 char symb[100];
239 CopyStringOut(tc, symb, symbolAddr, 100);
240 std::string symbol(symb);
241
242 DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
243
244 tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
245 }
246
247 void
248 anBegin(ThreadContext *tc, uint64_t cur)
249 {
250 Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur &
251 0xFFFFFFFF, 0,0);
252 }
253
254 void
255 anWait(ThreadContext *tc, uint64_t cur, uint64_t wait)
256 {
257 Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur &
258 0xFFFFFFFF, wait >> 32, wait & 0xFFFFFFFF);
259 }
260
261
262 void
263 dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
264 {
265 if (!doStatisticsInsts)
266 return;
267
268
269 Tick when = curTick + delay * Clock::Int::ns;
270 Tick repeat = period * Clock::Int::ns;
271
272 using namespace Stats;
273 SetupEvent(Dump|Reset, when, repeat);
274 }
275
276 void
277 m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
278 {
279 if (!doCheckpointInsts)
280 return;
281
282 Tick when = curTick + delay * Clock::Int::ns;
283 Tick repeat = period * Clock::Int::ns;
284
285 schedExitSimLoop("checkpoint", when, repeat);
286 }
287
288 uint64_t
289 readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
290 {
291 const string &file = tc->getCpuPtr()->system->params()->readfile;
292 if (file.empty()) {
293 return ULL(0);
294 }
295
296 uint64_t result = 0;
297
298 int fd = ::open(file.c_str(), O_RDONLY, 0);
299 if (fd < 0)
300 panic("could not open file %s\n", file);
301
302 if (::lseek(fd, offset, SEEK_SET) < 0)
303 panic("could not seek: %s", strerror(errno));
304
305 char *buf = new char[len];
306 char *p = buf;
307 while (len > 0) {
308 int bytes = ::read(fd, p, len);
309 if (bytes <= 0)
310 break;
311
312 p += bytes;
313 result += bytes;
314 len -= bytes;
315 }
316
317 close(fd);
318 CopyIn(tc, vaddr, buf, result);
319 delete [] buf;
320 return result;
321 }
322
323 class Context : public ParamContext
324 {
325 public:
326 Context(const string &section) : ParamContext(section) {}
327 void checkParams();
328 };
329
330 Context context("pseudo_inst");
331
332 Param<bool> __quiesce(&context, "quiesce",
333 "enable quiesce instructions",
334 true);
335 Param<bool> __statistics(&context, "statistics",
336 "enable statistics pseudo instructions",
337 true);
338 Param<bool> __checkpoint(&context, "checkpoint",
339 "enable checkpoint pseudo instructions",
340 true);
341
342 void
343 Context::checkParams()
344 {
345 doQuiesce = __quiesce;
346 doStatisticsInsts = __statistics;
347 doCheckpointInsts = __checkpoint;
348 }
349
350 void debugbreak(ThreadContext *tc)
351 {
352 debug_break();
353 }
354
355 void switchcpu(ThreadContext *tc)
356 {
357 exitSimLoop("switchcpu");
358 }
359}
79 tc->suspend();
80 if (tc->getKernelStats())
81 tc->getKernelStats()->quiesce();
82 }
83
84 void
85 quiesceNs(ThreadContext *tc, uint64_t ns)
86 {
87 if (!doQuiesce || ns == 0)
88 return;
89
90 EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
91
92 Tick resume = curTick + Clock::Int::ns * ns;
93
94 if (quiesceEvent->scheduled())
95 quiesceEvent->reschedule(resume);
96 else
97 quiesceEvent->schedule(resume);
98
99 DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
100 tc->getCpuPtr()->name(), ns, resume);
101
102 tc->suspend();
103 if (tc->getKernelStats())
104 tc->getKernelStats()->quiesce();
105 }
106
107 void
108 quiesceCycles(ThreadContext *tc, uint64_t cycles)
109 {
110 if (!doQuiesce || cycles == 0)
111 return;
112
113 EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
114
115 Tick resume = curTick + tc->getCpuPtr()->cycles(cycles);
116
117 if (quiesceEvent->scheduled())
118 quiesceEvent->reschedule(resume);
119 else
120 quiesceEvent->schedule(resume);
121
122 DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
123 tc->getCpuPtr()->name(), cycles, resume);
124
125 tc->suspend();
126 if (tc->getKernelStats())
127 tc->getKernelStats()->quiesce();
128 }
129
130 uint64_t
131 quiesceTime(ThreadContext *tc)
132 {
133 return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns;
134 }
135
136 void
137 ivlb(ThreadContext *tc)
138 {
139 if (tc->getKernelStats())
140 tc->getKernelStats()->ivlb();
141 }
142
143 void
144 ivle(ThreadContext *tc)
145 {
146 }
147
148 void
149 m5exit_old(ThreadContext *tc)
150 {
151 exitSimLoop("m5_exit_old instruction encountered");
152 }
153
154 void
155 m5exit(ThreadContext *tc, Tick delay)
156 {
157 Tick when = curTick + delay * Clock::Int::ns;
158 schedExitSimLoop("m5_exit instruction encountered", when);
159 }
160
161 void
162 loadsymbol(ThreadContext *tc)
163 {
164 const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
165 if (filename.empty()) {
166 return;
167 }
168
169 std::string buffer;
170 ifstream file(filename.c_str());
171
172 if (!file)
173 fatal("file error: Can't open symbol table file %s\n", filename);
174
175 while (!file.eof()) {
176 getline(file, buffer);
177
178 if (buffer.empty())
179 continue;
180
181 int idx = buffer.find(' ');
182 if (idx == string::npos)
183 continue;
184
185 string address = "0x" + buffer.substr(0, idx);
186 eat_white(address);
187 if (address.empty())
188 continue;
189
190 // Skip over letter and space
191 string symbol = buffer.substr(idx + 3);
192 eat_white(symbol);
193 if (symbol.empty())
194 continue;
195
196 Addr addr;
197 if (!to_number(address, addr))
198 continue;
199
200 if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
201 continue;
202
203
204 DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
205 }
206 file.close();
207 }
208
209 void
210 resetstats(ThreadContext *tc, Tick delay, Tick period)
211 {
212 if (!doStatisticsInsts)
213 return;
214
215
216 Tick when = curTick + delay * Clock::Int::ns;
217 Tick repeat = period * Clock::Int::ns;
218
219 using namespace Stats;
220 SetupEvent(Reset, when, repeat);
221 }
222
223 void
224 dumpstats(ThreadContext *tc, Tick delay, Tick period)
225 {
226 if (!doStatisticsInsts)
227 return;
228
229
230 Tick when = curTick + delay * Clock::Int::ns;
231 Tick repeat = period * Clock::Int::ns;
232
233 using namespace Stats;
234 SetupEvent(Dump, when, repeat);
235 }
236
237 void
238 addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
239 {
240 char symb[100];
241 CopyStringOut(tc, symb, symbolAddr, 100);
242 std::string symbol(symb);
243
244 DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
245
246 tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
247 }
248
249 void
250 anBegin(ThreadContext *tc, uint64_t cur)
251 {
252 Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur &
253 0xFFFFFFFF, 0,0);
254 }
255
256 void
257 anWait(ThreadContext *tc, uint64_t cur, uint64_t wait)
258 {
259 Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur &
260 0xFFFFFFFF, wait >> 32, wait & 0xFFFFFFFF);
261 }
262
263
264 void
265 dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
266 {
267 if (!doStatisticsInsts)
268 return;
269
270
271 Tick when = curTick + delay * Clock::Int::ns;
272 Tick repeat = period * Clock::Int::ns;
273
274 using namespace Stats;
275 SetupEvent(Dump|Reset, when, repeat);
276 }
277
278 void
279 m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
280 {
281 if (!doCheckpointInsts)
282 return;
283
284 Tick when = curTick + delay * Clock::Int::ns;
285 Tick repeat = period * Clock::Int::ns;
286
287 schedExitSimLoop("checkpoint", when, repeat);
288 }
289
290 uint64_t
291 readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
292 {
293 const string &file = tc->getCpuPtr()->system->params()->readfile;
294 if (file.empty()) {
295 return ULL(0);
296 }
297
298 uint64_t result = 0;
299
300 int fd = ::open(file.c_str(), O_RDONLY, 0);
301 if (fd < 0)
302 panic("could not open file %s\n", file);
303
304 if (::lseek(fd, offset, SEEK_SET) < 0)
305 panic("could not seek: %s", strerror(errno));
306
307 char *buf = new char[len];
308 char *p = buf;
309 while (len > 0) {
310 int bytes = ::read(fd, p, len);
311 if (bytes <= 0)
312 break;
313
314 p += bytes;
315 result += bytes;
316 len -= bytes;
317 }
318
319 close(fd);
320 CopyIn(tc, vaddr, buf, result);
321 delete [] buf;
322 return result;
323 }
324
325 class Context : public ParamContext
326 {
327 public:
328 Context(const string &section) : ParamContext(section) {}
329 void checkParams();
330 };
331
332 Context context("pseudo_inst");
333
334 Param<bool> __quiesce(&context, "quiesce",
335 "enable quiesce instructions",
336 true);
337 Param<bool> __statistics(&context, "statistics",
338 "enable statistics pseudo instructions",
339 true);
340 Param<bool> __checkpoint(&context, "checkpoint",
341 "enable checkpoint pseudo instructions",
342 true);
343
344 void
345 Context::checkParams()
346 {
347 doQuiesce = __quiesce;
348 doStatisticsInsts = __statistics;
349 doCheckpointInsts = __checkpoint;
350 }
351
352 void debugbreak(ThreadContext *tc)
353 {
354 debug_break();
355 }
356
357 void switchcpu(ThreadContext *tc)
358 {
359 exitSimLoop("switchcpu");
360 }
361}