pseudo_inst.cc revision 2358
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
29#include <errno.h>
30#include <fcntl.h>
31#include <unistd.h>
32#include <cstdio>
33
34#include <string>
35
36#include "sim/pseudo_inst.hh"
37#include "arch/vtophys.hh"
38#include "cpu/base.hh"
39#include "cpu/sampler/sampler.hh"
40#include "cpu/exec_context.hh"
41#include "cpu/quiesce_event.hh"
42#include "kern/kernel_stats.hh"
43#include "sim/param.hh"
44#include "sim/serialize.hh"
45#include "sim/sim_exit.hh"
46#include "sim/stat_control.hh"
47#include "sim/stats.hh"
48#include "sim/system.hh"
49#include "sim/debug.hh"
50#include "sim/vptr.hh"
51
52using namespace std;
53
54extern Sampler *SampCPU;
55
56using namespace Stats;
57using namespace TheISA;
58
59namespace AlphaPseudo
60{
61    bool doStatisticsInsts;
62    bool doCheckpointInsts;
63    bool doQuiesce;
64
65    void
66    arm(ExecContext *xc)
67    {
68        if (xc->getKernelStats())
69            xc->getKernelStats()->arm();
70    }
71
72    void
73    quiesce(ExecContext *xc)
74    {
75        if (!doQuiesce)
76            return;
77
78        xc->suspend();
79        if (xc->getKernelStats())
80            xc->getKernelStats()->quiesce();
81    }
82
83    void
84    quiesceNs(ExecContext *xc, uint64_t ns)
85    {
86        if (!doQuiesce || ns == 0)
87            return;
88
89        EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();
90
91        if (quiesceEvent->scheduled())
92            quiesceEvent->reschedule(curTick + Clock::Int::ns * ns);
93        else
94            quiesceEvent->schedule(curTick + Clock::Int::ns * ns);
95
96        xc->suspend();
97        if (xc->getKernelStats())
98            xc->getKernelStats()->quiesce();
99    }
100
101    void
102    quiesceCycles(ExecContext *xc, uint64_t cycles)
103    {
104        if (!doQuiesce || cycles == 0)
105            return;
106
107        EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();
108
109        if (quiesceEvent->scheduled())
110            quiesceEvent->reschedule(curTick +
111                                     xc->getCpuPtr()->cycles(cycles));
112        else
113            quiesceEvent->schedule(curTick +
114                                   xc->getCpuPtr()->cycles(cycles));
115
116        xc->suspend();
117        if (xc->getKernelStats())
118            xc->getKernelStats()->quiesce();
119    }
120
121    uint64_t
122    quiesceTime(ExecContext *xc)
123    {
124        return (xc->readLastActivate() - xc->readLastSuspend()) / Clock::Int::ns;
125    }
126
127    void
128    ivlb(ExecContext *xc)
129    {
130        if (xc->getKernelStats())
131            xc->getKernelStats()->ivlb();
132    }
133
134    void
135    ivle(ExecContext *xc)
136    {
137    }
138
139    void
140    m5exit_old(ExecContext *xc)
141    {
142        SimExit(curTick, "m5_exit_old instruction encountered");
143    }
144
145    void
146    m5exit(ExecContext *xc, Tick delay)
147    {
148        Tick when = curTick + delay * Clock::Int::ns;
149        SimExit(when, "m5_exit instruction encountered");
150    }
151
152    void
153    loadsymbol(ExecContext *xc)
154    {
155        const string &filename = xc->getCpuPtr()->system->params()->symbolfile;
156        if (filename.empty()) {
157            return;
158        }
159
160        std::string buffer;
161        ifstream file(filename.c_str());
162
163        if (!file)
164            fatal("file error: Can't open symbol table file %s\n", filename);
165
166        while (!file.eof()) {
167            getline(file, buffer);
168
169            if (buffer.empty())
170                continue;
171
172            int idx = buffer.find(' ');
173            if (idx == string::npos)
174                continue;
175
176            string address = "0x" + buffer.substr(0, idx);
177            eat_white(address);
178            if (address.empty())
179                continue;
180
181            // Skip over letter and space
182            string symbol = buffer.substr(idx + 3);
183            eat_white(symbol);
184            if (symbol.empty())
185                continue;
186
187            Addr addr;
188            if (!to_number(address, addr))
189                continue;
190
191            if (!xc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
192                continue;
193
194
195            DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
196        }
197        file.close();
198    }
199
200    void
201    resetstats(ExecContext *xc, Tick delay, Tick period)
202    {
203        if (!doStatisticsInsts)
204            return;
205
206
207        Tick when = curTick + delay * Clock::Int::ns;
208        Tick repeat = period * Clock::Int::ns;
209
210        using namespace Stats;
211        SetupEvent(Reset, when, repeat);
212    }
213
214    void
215    dumpstats(ExecContext *xc, Tick delay, Tick period)
216    {
217        if (!doStatisticsInsts)
218            return;
219
220
221        Tick when = curTick + delay * Clock::Int::ns;
222        Tick repeat = period * Clock::Int::ns;
223
224        using namespace Stats;
225        SetupEvent(Dump, when, repeat);
226    }
227
228    void
229    addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr)
230    {
231        char symb[100];
232        CopyString(xc, symb, symbolAddr, 100);
233        std::string symbol(symb);
234
235        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
236
237        xc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
238    }
239
240    void
241    dumpresetstats(ExecContext *xc, Tick delay, Tick period)
242    {
243        if (!doStatisticsInsts)
244            return;
245
246
247        Tick when = curTick + delay * Clock::Int::ns;
248        Tick repeat = period * Clock::Int::ns;
249
250        using namespace Stats;
251        SetupEvent(Dump|Reset, when, repeat);
252    }
253
254    void
255    m5checkpoint(ExecContext *xc, Tick delay, Tick period)
256    {
257        if (!doCheckpointInsts)
258            return;
259
260
261        Tick when = curTick + delay * Clock::Int::ns;
262        Tick repeat = period * Clock::Int::ns;
263
264        Checkpoint::setup(when, repeat);
265    }
266
267    uint64_t
268    readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset)
269    {
270        const string &file = xc->getCpuPtr()->system->params()->readfile;
271        if (file.empty()) {
272            return ULL(0);
273        }
274
275        uint64_t result = 0;
276
277        int fd = ::open(file.c_str(), O_RDONLY, 0);
278        if (fd < 0)
279            panic("could not open file %s\n", file);
280
281        if (::lseek(fd, offset, SEEK_SET) < 0)
282            panic("could not seek: %s", strerror(errno));
283
284        char *buf = new char[len];
285        char *p = buf;
286        while (len > 0) {
287            int bytes = ::read(fd, p, len);
288            if (bytes <= 0)
289                break;
290
291            p += bytes;
292            result += bytes;
293            len -= bytes;
294        }
295
296        close(fd);
297        CopyIn(xc, vaddr, buf, result);
298        delete [] buf;
299        return result;
300    }
301
302    class Context : public ParamContext
303    {
304      public:
305        Context(const string &section) : ParamContext(section) {}
306        void checkParams();
307    };
308
309    Context context("pseudo_inst");
310
311    Param<bool> __quiesce(&context, "quiesce",
312                          "enable quiesce instructions",
313                          true);
314    Param<bool> __statistics(&context, "statistics",
315                             "enable statistics pseudo instructions",
316                             true);
317    Param<bool> __checkpoint(&context, "checkpoint",
318                             "enable checkpoint pseudo instructions",
319                             true);
320
321    void
322    Context::checkParams()
323    {
324        doQuiesce = __quiesce;
325        doStatisticsInsts = __statistics;
326        doCheckpointInsts = __checkpoint;
327    }
328
329    void debugbreak(ExecContext *xc)
330    {
331        debug_break();
332    }
333
334    void switchcpu(ExecContext *xc)
335    {
336        if (SampCPU)
337            SampCPU->switchCPUs();
338    }
339}
340