thread_context.hh revision 2
1/*
2 * Copyright (c) 2003 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#ifndef __EXEC_CONTEXT_HH__
30#define __EXEC_CONTEXT_HH__
31
32#include "host.hh"
33#include "stats.hh"
34#include "mem_req.hh"
35
36// forward declaration: see functional_memory.hh
37class FunctionalMemory;
38class PhysicalMemory;
39class BaseCPU;
40
41#ifdef FULL_SYSTEM
42
43#include "alpha_memory.hh"
44class MemoryController;
45
46#include "kernel_stats.hh"
47#include "system.hh"
48
49#else // !FULL_SYSTEM
50
51#include "prog.hh"
52
53#endif // FULL_SYSTEM
54
55//
56// The ExecContext object represents a functional context for
57// instruction execution.  It incorporates everything required for
58// architecture-level functional simulation of a single thread.
59//
60
61class ExecContext
62{
63  public:
64    enum Status { Unallocated, Active, Suspended, Halted };
65
66  private:
67    Status _status;
68
69  public:
70    Status status() const { return _status; }
71    void setStatus(Status new_status);
72
73#ifdef FULL_SYSTEM
74  public:
75    KernelStats kernelStats;
76#endif
77
78  public:
79    RegFile regs;	// correct-path register context
80
81    // pointer to CPU associated with this context
82    BaseCPU *cpu;
83
84    // Index of hardware thread context on the CPU that this represents.
85    int thread_num;
86
87#ifdef FULL_SYSTEM
88
89    FunctionalMemory *mem;
90    AlphaItb *itb;
91    AlphaDtb *dtb;
92    int cpu_id;
93    System *system;
94
95    // the following two fields are redundant, since we can always
96    // look them up through the system pointer, but we'll leave them
97    // here for now for convenience
98    MemoryController *memCtrl;
99    PhysicalMemory *physmem;
100
101#else
102    Process *process;
103
104    FunctionalMemory *mem;	// functional storage for process address space
105
106    // Address space ID.  Note that this is used for TIMING cache
107    // simulation only; all functional memory accesses should use
108    // one of the FunctionalMemory pointers above.
109    short asid;
110
111#endif
112
113
114    /*
115     * number of executed instructions, for matching with syscall trace
116     * points in EIO files.
117     */
118    Counter func_exe_insn;
119
120    //
121    // Count failed store conditionals so we can warn of apparent
122    // application deadlock situations.
123    unsigned storeCondFailures;
124
125    // constructor: initialize context from given process structure
126#ifdef FULL_SYSTEM
127    ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
128                AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem,
129                int _cpu_id);
130#else
131    ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
132    ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
133                int _asid);
134#endif
135    virtual ~ExecContext() {}
136
137    void regStats(const std::string &name);
138
139#ifdef FULL_SYSTEM
140    bool validInstAddr(Addr addr) { return true; }
141    bool validDataAddr(Addr addr) { return true; }
142    int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); }
143    int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); }
144
145    Fault translateInstReq(MemReqPtr req)
146    {
147        return itb->translate(req);
148    }
149
150    Fault translateDataReadReq(MemReqPtr req)
151    {
152        return dtb->translate(req, false);
153    }
154
155    Fault translateDataWriteReq(MemReqPtr req)
156    {
157        return dtb->translate(req, true);
158    }
159
160
161#else
162    bool validInstAddr(Addr addr)
163    { return process->validInstAddr(addr); }
164
165    bool validDataAddr(Addr addr)
166    { return process->validDataAddr(addr); }
167
168    int getInstAsid() { return asid; }
169    int getDataAsid() { return asid; }
170
171    Fault dummyTranslation(MemReqPtr req)
172    {
173#if 0
174        assert((req->vaddr >> 48 & 0xffff) == 0);
175#endif
176
177        // put the asid in the upper 16 bits of the paddr
178        req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
179        req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
180        return No_Fault;
181    }
182    Fault translateInstReq(MemReqPtr req)
183    {
184        return dummyTranslation(req);
185    }
186    Fault translateDataReadReq(MemReqPtr req)
187    {
188        return dummyTranslation(req);
189    }
190    Fault translateDataWriteReq(MemReqPtr req)
191    {
192        return dummyTranslation(req);
193    }
194
195#endif
196
197    template <class T>
198    Fault read(MemReqPtr req, T& data)
199    {
200#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
201        if (req->flags & LOCKED) {
202            MiscRegFile *cregs = &req->xc->regs.miscRegs;
203            cregs->lock_addr = req->paddr;
204            cregs->lock_flag = true;
205        }
206#endif
207        return mem->read(req, data);
208    }
209
210    template <class T>
211    Fault write(MemReqPtr req, T& data)
212    {
213#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
214
215        MiscRegFile *cregs;
216
217        // If this is a store conditional, act appropriately
218        if (req->flags & LOCKED) {
219            cregs = &req->xc->regs.miscRegs;
220
221            if (req->flags & UNCACHEABLE) {
222                // Don't update result register (see machine.def)
223                req->result = 2;
224                req->xc->storeCondFailures = 0;//Needed? [RGD]
225            } else {
226                req->result = cregs->lock_flag;
227                if (!cregs->lock_flag ||
228                    ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) {
229                    cregs->lock_flag = false;
230                    if (((++req->xc->storeCondFailures) % 100000) == 0) {
231                        std::cerr << "Warning: "
232                                  << req->xc->storeCondFailures
233                                  << " consecutive store conditional failures "
234                                  << "on cpu " << req->xc->cpu_id
235                                  << std::endl;
236                    }
237                    return No_Fault;
238                }
239                else req->xc->storeCondFailures = 0;
240            }
241        }
242
243        // Need to clear any locked flags on other proccessors for this
244        // address
245        // Only do this for succsful Store Conditionals and all other
246        // stores (WH64?)
247        // Unsuccesful Store Conditionals would have returned above,
248        // and wouldn't fall through
249        for(int i = 0; i < system->num_cpus; i++){
250            cregs = &system->xc_array[i]->regs.miscRegs;
251            if((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
252                cregs->lock_flag = false;
253            }
254        }
255
256#endif
257        return mem->write(req, data);
258    }
259
260    virtual bool misspeculating();
261
262
263    //
264    // New accessors for new decoder.
265    //
266    uint64_t readIntReg(int reg_idx)
267    {
268        return regs.intRegFile[reg_idx];
269    }
270
271    float readFloatRegSingle(int reg_idx)
272    {
273        return (float)regs.floatRegFile.d[reg_idx];
274    }
275
276    double readFloatRegDouble(int reg_idx)
277    {
278        return regs.floatRegFile.d[reg_idx];
279    }
280
281    uint64_t readFloatRegInt(int reg_idx)
282    {
283        return regs.floatRegFile.q[reg_idx];
284    }
285
286    void setIntReg(int reg_idx, uint64_t val)
287    {
288        regs.intRegFile[reg_idx] = val;
289    }
290
291    void setFloatRegSingle(int reg_idx, float val)
292    {
293        regs.floatRegFile.d[reg_idx] = (double)val;
294    }
295
296    void setFloatRegDouble(int reg_idx, double val)
297    {
298        regs.floatRegFile.d[reg_idx] = val;
299    }
300
301    void setFloatRegInt(int reg_idx, uint64_t val)
302    {
303        regs.floatRegFile.q[reg_idx] = val;
304    }
305
306    uint64_t readPC()
307    {
308        return regs.pc;
309    }
310
311    void setNextPC(uint64_t val)
312    {
313        regs.npc = val;
314    }
315
316    uint64_t readUniq()
317    {
318        return regs.miscRegs.uniq;
319    }
320
321    void setUniq(uint64_t val)
322    {
323        regs.miscRegs.uniq = val;
324    }
325
326    uint64_t readFpcr()
327    {
328        return regs.miscRegs.fpcr;
329    }
330
331    void setFpcr(uint64_t val)
332    {
333        regs.miscRegs.fpcr = val;
334    }
335
336#ifdef FULL_SYSTEM
337    uint64_t readIpr(int idx, Fault &fault);
338    Fault setIpr(int idx, uint64_t val);
339    Fault hwrei();
340    void ev5_trap(Fault fault);
341    bool simPalCheck(int palFunc);
342#endif
343
344#ifndef FULL_SYSTEM
345    void syscall()
346    {
347        process->syscall(this);
348    }
349#endif
350};
351
352
353// for non-speculative execution context, spec_mode is always false
354inline bool
355ExecContext::misspeculating()
356{
357    return false;
358}
359
360#endif // __EXEC_CONTEXT_HH__
361