thread_context.hh revision 246
12632SN/A/*
22632SN/A * Copyright (c) 2003 The Regents of The University of Michigan
32632SN/A * All rights reserved.
42632SN/A *
52632SN/A * Redistribution and use in source and binary forms, with or without
62632SN/A * modification, are permitted provided that the following conditions are
72632SN/A * met: redistributions of source code must retain the above copyright
82632SN/A * notice, this list of conditions and the following disclaimer;
92632SN/A * redistributions in binary form must reproduce the above copyright
102632SN/A * notice, this list of conditions and the following disclaimer in the
112632SN/A * documentation and/or other materials provided with the distribution;
122632SN/A * neither the name of the copyright holders nor the names of its
132632SN/A * contributors may be used to endorse or promote products derived from
142632SN/A * this software without specific prior written permission.
152632SN/A *
162632SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172632SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182632SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192632SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202632SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212632SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222632SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232632SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242632SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252632SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262632SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272632SN/A */
282632SN/A
292632SN/A#ifndef __EXEC_CONTEXT_HH__
302632SN/A#define __EXEC_CONTEXT_HH__
312632SN/A
322632SN/A#include "sim/host.hh"
33#include "mem/mem_req.hh"
34#include "sim/serialize.hh"
35
36// forward declaration: see functional_memory.hh
37class FunctionalMemory;
38class PhysicalMemory;
39class BaseCPU;
40
41#ifdef FULL_SYSTEM
42
43#include "targetarch/alpha_memory.hh"
44class MemoryController;
45
46#include "kern/tru64/kernel_stats.hh"
47#include "sim/system.hh"
48
49#else // !FULL_SYSTEM
50
51#include "sim/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
65    {
66        /// Initialized but not running yet.  All CPUs start in
67        /// this state, but most transition to Active on cycle 1.
68        /// In MP or SMT systems, non-primary contexts will stay
69        /// in this state until a thread is assigned to them.
70        Unallocated,
71
72        /// Running.  Instructions should be executed only when
73        /// the context is in this state.
74        Active,
75
76        /// Temporarily inactive.  Entered while waiting for
77        /// synchronization, etc.
78        Suspended,
79
80        /// Permanently shut down.  Entered when target executes
81        /// m5exit pseudo-instruction.  When all contexts enter
82        /// this state, the simulation will terminate.
83        Halted
84    };
85
86  private:
87    Status _status;
88
89  public:
90    Status status() const { return _status; }
91
92    void setStatus(Status new_status);
93
94#ifdef FULL_SYSTEM
95  public:
96    KernelStats kernelStats;
97#endif
98
99  public:
100    RegFile regs;	// correct-path register context
101
102    // pointer to CPU associated with this context
103    BaseCPU *cpu;
104
105    // Index of hardware thread context on the CPU that this represents.
106    int thread_num;
107
108    // ID of this context w.r.t. the System or Process object to which
109    // it belongs.  For full-system mode, this is the system CPU ID.
110    int cpu_id;
111
112#ifdef FULL_SYSTEM
113
114    FunctionalMemory *mem;
115    AlphaItb *itb;
116    AlphaDtb *dtb;
117    System *system;
118
119    // the following two fields are redundant, since we can always
120    // look them up through the system pointer, but we'll leave them
121    // here for now for convenience
122    MemoryController *memCtrl;
123    PhysicalMemory *physmem;
124
125#else
126    Process *process;
127
128    FunctionalMemory *mem;	// functional storage for process address space
129
130    // Address space ID.  Note that this is used for TIMING cache
131    // simulation only; all functional memory accesses should use
132    // one of the FunctionalMemory pointers above.
133    short asid;
134
135#endif
136
137
138    /*
139     * number of executed instructions, for matching with syscall trace
140     * points in EIO files.
141     */
142    Counter func_exe_insn;
143
144    //
145    // Count failed store conditionals so we can warn of apparent
146    // application deadlock situations.
147    unsigned storeCondFailures;
148
149    // constructor: initialize context from given process structure
150#ifdef FULL_SYSTEM
151    ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
152                AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem);
153#else
154    ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
155    ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
156                int _asid);
157#endif
158    virtual ~ExecContext() {}
159
160    virtual void takeOverFrom(ExecContext *oldContext);
161
162    void regStats(const std::string &name);
163
164    void serialize(std::ostream &os);
165    void unserialize(Checkpoint *cp, const std::string &section);
166
167#ifdef FULL_SYSTEM
168    bool validInstAddr(Addr addr) { return true; }
169    bool validDataAddr(Addr addr) { return true; }
170    int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); }
171    int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); }
172
173    Fault translateInstReq(MemReqPtr req)
174    {
175        return itb->translate(req);
176    }
177
178    Fault translateDataReadReq(MemReqPtr req)
179    {
180        return dtb->translate(req, false);
181    }
182
183    Fault translateDataWriteReq(MemReqPtr req)
184    {
185        return dtb->translate(req, true);
186    }
187
188#else
189    bool validInstAddr(Addr addr)
190    { return process->validInstAddr(addr); }
191
192    bool validDataAddr(Addr addr)
193    { return process->validDataAddr(addr); }
194
195    int getInstAsid() { return asid; }
196    int getDataAsid() { return asid; }
197
198    Fault dummyTranslation(MemReqPtr req)
199    {
200#if 0
201        assert((req->vaddr >> 48 & 0xffff) == 0);
202#endif
203
204        // put the asid in the upper 16 bits of the paddr
205        req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
206        req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
207        return No_Fault;
208    }
209    Fault translateInstReq(MemReqPtr req)
210    {
211        return dummyTranslation(req);
212    }
213    Fault translateDataReadReq(MemReqPtr req)
214    {
215        return dummyTranslation(req);
216    }
217    Fault translateDataWriteReq(MemReqPtr req)
218    {
219        return dummyTranslation(req);
220    }
221
222#endif
223
224    template <class T>
225    Fault read(MemReqPtr req, T& data)
226    {
227#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
228        if (req->flags & LOCKED) {
229            MiscRegFile *cregs = &req->xc->regs.miscRegs;
230            cregs->lock_addr = req->paddr;
231            cregs->lock_flag = true;
232        }
233#endif
234        return mem->read(req, data);
235    }
236
237    template <class T>
238    Fault write(MemReqPtr req, T& data)
239    {
240#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
241
242        MiscRegFile *cregs;
243
244        // If this is a store conditional, act appropriately
245        if (req->flags & LOCKED) {
246            cregs = &req->xc->regs.miscRegs;
247
248            if (req->flags & UNCACHEABLE) {
249                // Don't update result register (see stq_c in isa_desc)
250                req->result = 2;
251                req->xc->storeCondFailures = 0;//Needed? [RGD]
252            } else {
253                req->result = cregs->lock_flag;
254                if (!cregs->lock_flag ||
255                    ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) {
256                    cregs->lock_flag = false;
257                    if (((++req->xc->storeCondFailures) % 100000) == 0) {
258                        std::cerr << "Warning: "
259                                  << req->xc->storeCondFailures
260                                  << " consecutive store conditional failures "
261                                  << "on cpu " << req->xc->cpu_id
262                                  << std::endl;
263                    }
264                    return No_Fault;
265                }
266                else req->xc->storeCondFailures = 0;
267            }
268        }
269
270        // Need to clear any locked flags on other proccessors for
271        // this address.  Only do this for succsful Store Conditionals
272        // and all other stores (WH64?).  Unsuccessful Store
273        // Conditionals would have returned above, and wouldn't fall
274        // through.
275        for (int i = 0; i < system->execContexts.size(); i++){
276            cregs = &system->execContexts[i]->regs.miscRegs;
277            if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
278                cregs->lock_flag = false;
279            }
280        }
281
282#endif
283        return mem->write(req, data);
284    }
285
286    virtual bool misspeculating();
287
288
289    //
290    // New accessors for new decoder.
291    //
292    uint64_t readIntReg(int reg_idx)
293    {
294        return regs.intRegFile[reg_idx];
295    }
296
297    float readFloatRegSingle(int reg_idx)
298    {
299        return (float)regs.floatRegFile.d[reg_idx];
300    }
301
302    double readFloatRegDouble(int reg_idx)
303    {
304        return regs.floatRegFile.d[reg_idx];
305    }
306
307    uint64_t readFloatRegInt(int reg_idx)
308    {
309        return regs.floatRegFile.q[reg_idx];
310    }
311
312    void setIntReg(int reg_idx, uint64_t val)
313    {
314        regs.intRegFile[reg_idx] = val;
315    }
316
317    void setFloatRegSingle(int reg_idx, float val)
318    {
319        regs.floatRegFile.d[reg_idx] = (double)val;
320    }
321
322    void setFloatRegDouble(int reg_idx, double val)
323    {
324        regs.floatRegFile.d[reg_idx] = val;
325    }
326
327    void setFloatRegInt(int reg_idx, uint64_t val)
328    {
329        regs.floatRegFile.q[reg_idx] = val;
330    }
331
332    uint64_t readPC()
333    {
334        return regs.pc;
335    }
336
337    void setNextPC(uint64_t val)
338    {
339        regs.npc = val;
340    }
341
342    uint64_t readUniq()
343    {
344        return regs.miscRegs.uniq;
345    }
346
347    void setUniq(uint64_t val)
348    {
349        regs.miscRegs.uniq = val;
350    }
351
352    uint64_t readFpcr()
353    {
354        return regs.miscRegs.fpcr;
355    }
356
357    void setFpcr(uint64_t val)
358    {
359        regs.miscRegs.fpcr = val;
360    }
361
362#ifdef FULL_SYSTEM
363    uint64_t readIpr(int idx, Fault &fault);
364    Fault setIpr(int idx, uint64_t val);
365    Fault hwrei();
366    void ev5_trap(Fault fault);
367    bool simPalCheck(int palFunc);
368#endif
369
370#ifndef FULL_SYSTEM
371    void syscall()
372    {
373        process->syscall(this);
374    }
375#endif
376};
377
378
379// for non-speculative execution context, spec_mode is always false
380inline bool
381ExecContext::misspeculating()
382{
383    return false;
384}
385
386#endif // __EXEC_CONTEXT_HH__
387