pseudo_inst.cc revision 5505:90d6811d5ea6
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 <fstream>
36#include <string>
37
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 "arch/kernel_stats.hh"
44#include "sim/pseudo_inst.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 PseudoInst {
59
60void
61arm(ThreadContext *tc)
62{
63    if (tc->getKernelStats())
64        tc->getKernelStats()->arm();
65}
66
67void
68quiesce(ThreadContext *tc)
69{
70    if (!tc->getCpuPtr()->params->do_quiesce)
71        return;
72
73    DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
74
75    tc->suspend();
76    if (tc->getKernelStats())
77        tc->getKernelStats()->quiesce();
78}
79
80void
81quiesceNs(ThreadContext *tc, uint64_t ns)
82{
83    if (!tc->getCpuPtr()->params->do_quiesce || ns == 0)
84        return;
85
86    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
87
88    Tick resume = curTick + Clock::Int::ns * ns;
89
90    quiesceEvent->reschedule(resume, true);
91
92    DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
93            tc->getCpuPtr()->name(), ns, resume);
94
95    tc->suspend();
96    if (tc->getKernelStats())
97        tc->getKernelStats()->quiesce();
98}
99
100void
101quiesceCycles(ThreadContext *tc, uint64_t cycles)
102{
103    if (!tc->getCpuPtr()->params->do_quiesce || cycles == 0)
104        return;
105
106    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
107
108    Tick resume = curTick + tc->getCpuPtr()->ticks(cycles);
109
110    quiesceEvent->reschedule(resume, true);
111
112    DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
113            tc->getCpuPtr()->name(), cycles, resume);
114
115    tc->suspend();
116    if (tc->getKernelStats())
117        tc->getKernelStats()->quiesce();
118}
119
120uint64_t
121quiesceTime(ThreadContext *tc)
122{
123    return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns;
124}
125
126void
127m5exit(ThreadContext *tc, Tick delay)
128{
129    Tick when = curTick + delay * Clock::Int::ns;
130    schedExitSimLoop("m5_exit instruction encountered", when);
131}
132
133void
134loadsymbol(ThreadContext *tc)
135{
136    const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
137    if (filename.empty()) {
138        return;
139    }
140
141    std::string buffer;
142    ifstream file(filename.c_str());
143
144    if (!file)
145        fatal("file error: Can't open symbol table file %s\n", filename);
146
147    while (!file.eof()) {
148        getline(file, buffer);
149
150        if (buffer.empty())
151            continue;
152
153        int idx = buffer.find(' ');
154        if (idx == string::npos)
155            continue;
156
157        string address = "0x" + buffer.substr(0, idx);
158        eat_white(address);
159        if (address.empty())
160            continue;
161
162        // Skip over letter and space
163        string symbol = buffer.substr(idx + 3);
164        eat_white(symbol);
165        if (symbol.empty())
166            continue;
167
168        Addr addr;
169        if (!to_number(address, addr))
170            continue;
171
172        if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
173            continue;
174
175
176        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
177    }
178    file.close();
179}
180
181void
182resetstats(ThreadContext *tc, Tick delay, Tick period)
183{
184    if (!tc->getCpuPtr()->params->do_statistics_insts)
185        return;
186
187
188    Tick when = curTick + delay * Clock::Int::ns;
189    Tick repeat = period * Clock::Int::ns;
190
191    Stats::StatEvent(false, true, when, repeat);
192}
193
194void
195dumpstats(ThreadContext *tc, Tick delay, Tick period)
196{
197    if (!tc->getCpuPtr()->params->do_statistics_insts)
198        return;
199
200
201    Tick when = curTick + delay * Clock::Int::ns;
202    Tick repeat = period * Clock::Int::ns;
203
204    Stats::StatEvent(true, false, when, repeat);
205}
206
207void
208addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
209{
210    char symb[100];
211    CopyStringOut(tc, symb, symbolAddr, 100);
212    std::string symbol(symb);
213
214    DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
215
216    tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
217}
218
219void
220dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
221{
222    if (!tc->getCpuPtr()->params->do_statistics_insts)
223        return;
224
225
226    Tick when = curTick + delay * Clock::Int::ns;
227    Tick repeat = period * Clock::Int::ns;
228
229    Stats::StatEvent(true, true, when, repeat);
230}
231
232void
233m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
234{
235    if (!tc->getCpuPtr()->params->do_checkpoint_insts)
236        return;
237
238    Tick when = curTick + delay * Clock::Int::ns;
239    Tick repeat = period * Clock::Int::ns;
240
241    schedExitSimLoop("checkpoint", when, repeat);
242}
243
244uint64_t
245readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
246{
247    const string &file = tc->getSystemPtr()->params()->readfile;
248    if (file.empty()) {
249        return ULL(0);
250    }
251
252    uint64_t result = 0;
253
254    int fd = ::open(file.c_str(), O_RDONLY, 0);
255    if (fd < 0)
256        panic("could not open file %s\n", file);
257
258    if (::lseek(fd, offset, SEEK_SET) < 0)
259        panic("could not seek: %s", strerror(errno));
260
261    char *buf = new char[len];
262    char *p = buf;
263    while (len > 0) {
264        int bytes = ::read(fd, p, len);
265        if (bytes <= 0)
266            break;
267
268        p += bytes;
269        result += bytes;
270        len -= bytes;
271    }
272
273    close(fd);
274    CopyIn(tc, vaddr, buf, result);
275    delete [] buf;
276    return result;
277}
278
279void
280debugbreak(ThreadContext *tc)
281{
282    debug_break();
283}
284
285void
286switchcpu(ThreadContext *tc)
287{
288    exitSimLoop("switchcpu");
289}
290
291/* namespace PseudoInst */ }
292