simple_thread.hh revision 2525
1/*
2 * Copyright (c) 2001-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#ifndef __CPU_CPU_EXEC_CONTEXT_HH__
30#define __CPU_CPU_EXEC_CONTEXT_HH__
31
32#include "arch/isa_traits.hh"
33#include "config/full_system.hh"
34#include "cpu/exec_context.hh"
35#include "mem/physical.hh"
36#include "mem/request.hh"
37#include "sim/byteswap.hh"
38#include "sim/eventq.hh"
39#include "sim/host.hh"
40#include "sim/serialize.hh"
41
42class BaseCPU;
43
44#if FULL_SYSTEM
45
46#include "sim/system.hh"
47#include "arch/tlb.hh"
48
49class FunctionProfile;
50class ProfileNode;
51class MemoryController;
52
53#else // !FULL_SYSTEM
54
55#include "sim/process.hh"
56#include "mem/page_table.hh"
57class TranslatingPort;
58
59#endif // FULL_SYSTEM
60
61//
62// The CPUExecContext object represents a functional context for
63// instruction execution.  It incorporates everything required for
64// architecture-level functional simulation of a single thread.
65//
66
67class CPUExecContext
68{
69  protected:
70    typedef TheISA::RegFile RegFile;
71    typedef TheISA::MachInst MachInst;
72    typedef TheISA::MiscRegFile MiscRegFile;
73    typedef TheISA::MiscReg MiscReg;
74    typedef TheISA::FloatReg FloatReg;
75    typedef TheISA::FloatRegBits FloatRegBits;
76  public:
77    typedef ExecContext::Status Status;
78
79  private:
80    Status _status;
81
82  public:
83    Status status() const { return _status; }
84
85    void setStatus(Status newStatus) { _status = newStatus; }
86
87    /// Set the status to Active.  Optional delay indicates number of
88    /// cycles to wait before beginning execution.
89    void activate(int delay = 1);
90
91    /// Set the status to Suspended.
92    void suspend();
93
94    /// Set the status to Unallocated.
95    void deallocate();
96
97    /// Set the status to Halted.
98    void halt();
99
100  protected:
101    RegFile regs;	// correct-path register context
102
103  public:
104    // pointer to CPU associated with this context
105    BaseCPU *cpu;
106
107    ProxyExecContext<CPUExecContext> *proxy;
108
109    // Current instruction
110    MachInst inst;
111
112    // Index of hardware thread context on the CPU that this represents.
113    int thread_num;
114
115    // ID of this context w.r.t. the System or Process object to which
116    // it belongs.  For full-system mode, this is the system CPU ID.
117    int cpu_id;
118
119    Tick lastActivate;
120    Tick lastSuspend;
121
122    System *system;
123
124
125#if FULL_SYSTEM
126    AlphaITB *itb;
127    AlphaDTB *dtb;
128
129    // the following two fields are redundant, since we can always
130    // look them up through the system pointer, but we'll leave them
131    // here for now for convenience
132    MemoryController *memctrl;
133//    PhysicalMemory *physmem;
134
135    FunctionProfile *profile;
136    ProfileNode *profileNode;
137    Addr profilePC;
138    void dumpFuncProfile();
139
140    /** Event for timing out quiesce instruction */
141    struct EndQuiesceEvent : public Event
142    {
143        /** A pointer to the execution context that is quiesced */
144        CPUExecContext *cpuXC;
145
146        EndQuiesceEvent(CPUExecContext *_cpuXC);
147
148        /** Event process to occur at interrupt*/
149        virtual void process();
150
151        /** Event description */
152        virtual const char *description();
153    };
154    EndQuiesceEvent quiesceEvent;
155
156    Event *getQuiesceEvent() { return &quiesceEvent; }
157
158    Tick readLastActivate() { return lastActivate; }
159
160    Tick readLastSuspend() { return lastSuspend; }
161
162    void profileClear();
163
164    void profileSample();
165
166#else
167    /// Port that syscalls can use to access memory (provides translation step).
168    TranslatingPort *port;
169
170    Process *process;
171
172    // Address space ID.  Note that this is used for TIMING cache
173    // simulation only; all functional memory accesses should use
174    // one of the FunctionalMemory pointers above.
175    short asid;
176
177#endif
178
179    /**
180     * Temporary storage to pass the source address from copy_load to
181     * copy_store.
182     * @todo Remove this temporary when we have a better way to do it.
183     */
184    Addr copySrcAddr;
185    /**
186     * Temp storage for the physical source address of a copy.
187     * @todo Remove this temporary when we have a better way to do it.
188     */
189    Addr copySrcPhysAddr;
190
191
192    /*
193     * number of executed instructions, for matching with syscall trace
194     * points in EIO files.
195     */
196    Counter func_exe_inst;
197
198    //
199    // Count failed store conditionals so we can warn of apparent
200    // application deadlock situations.
201    unsigned storeCondFailures;
202
203    // constructor: initialize context from given process structure
204#if FULL_SYSTEM
205    CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
206                   AlphaITB *_itb, AlphaDTB *_dtb);
207#else
208    CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid,
209            MemObject *memobj);
210    // Constructor to use XC to pass reg file around.  Not used for anything
211    // else.
212    CPUExecContext(RegFile *regFile);
213#endif
214    virtual ~CPUExecContext();
215
216    virtual void takeOverFrom(ExecContext *oldContext);
217
218    void regStats(const std::string &name);
219
220    void serialize(std::ostream &os);
221    void unserialize(Checkpoint *cp, const std::string &section);
222
223    BaseCPU *getCpuPtr() { return cpu; }
224
225    ExecContext *getProxy() { return proxy; }
226
227    int getThreadNum() { return thread_num; }
228
229#if FULL_SYSTEM
230    System *getSystemPtr() { return system; }
231
232    AlphaITB *getITBPtr() { return itb; }
233
234    AlphaDTB *getDTBPtr() { return dtb; }
235
236    int getInstAsid() { return regs.instAsid(); }
237    int getDataAsid() { return regs.dataAsid(); }
238
239    Fault translateInstReq(CpuRequestPtr &req)
240    {
241        return itb->translate(req);
242    }
243
244    Fault translateDataReadReq(CpuRequestPtr &req)
245    {
246        return dtb->translate(req, false);
247    }
248
249    Fault translateDataWriteReq(CpuRequestPtr &req)
250    {
251        return dtb->translate(req, true);
252    }
253
254#else
255    TranslatingPort *getMemPort() { return port; }
256
257    Process *getProcessPtr() { return process; }
258
259    int getInstAsid() { return asid; }
260    int getDataAsid() { return asid; }
261
262    Fault translateInstReq(CpuRequestPtr &req)
263    {
264        return process->pTable->translate(req);
265    }
266
267    Fault translateDataReadReq(CpuRequestPtr &req)
268    {
269        return process->pTable->translate(req);
270    }
271
272    Fault translateDataWriteReq(CpuRequestPtr &req)
273    {
274        return process->pTable->translate(req);
275    }
276
277#endif
278
279/*
280    template <class T>
281    Fault read(CpuRequestPtr &req, T &data)
282    {
283#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
284        if (req->flags & LOCKED) {
285            req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
286            req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
287        }
288#endif
289
290        Fault error;
291        error = mem->prot_read(req->paddr, data, req->size);
292        data = LittleEndianGuest::gtoh(data);
293        return error;
294    }
295
296    template <class T>
297    Fault write(CpuRequestPtr &req, T &data)
298    {
299#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
300        ExecContext *xc;
301
302        // If this is a store conditional, act appropriately
303        if (req->flags & LOCKED) {
304            xc = req->xc;
305
306            if (req->flags & UNCACHEABLE) {
307                // Don't update result register (see stq_c in isa_desc)
308                req->result = 2;
309                xc->setStCondFailures(0);//Needed? [RGD]
310            } else {
311                bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
312                Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
313                req->result = lock_flag;
314                if (!lock_flag ||
315                    ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
316                    xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
317                    xc->setStCondFailures(xc->readStCondFailures() + 1);
318                    if (((xc->readStCondFailures()) % 100000) == 0) {
319                        std::cerr << "Warning: "
320                                  << xc->readStCondFailures()
321                                  << " consecutive store conditional failures "
322                                  << "on cpu " << req->xc->readCpuId()
323                                  << std::endl;
324                    }
325                    return NoFault;
326                }
327                else xc->setStCondFailures(0);
328            }
329        }
330
331        // Need to clear any locked flags on other proccessors for
332        // this address.  Only do this for succsful Store Conditionals
333        // and all other stores (WH64?).  Unsuccessful Store
334        // Conditionals would have returned above, and wouldn't fall
335        // through.
336        for (int i = 0; i < system->execContexts.size(); i++){
337            xc = system->execContexts[i];
338            if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
339                (req->paddr & ~0xf)) {
340                xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
341            }
342        }
343
344#endif
345        return mem->prot_write(req->paddr, (T)htog(data), req->size);
346    }
347*/
348    virtual bool misspeculating();
349
350
351    MachInst getInst() { return inst; }
352
353    void setInst(MachInst new_inst)
354    {
355        inst = new_inst;
356    }
357
358    Fault instRead(CpuRequestPtr &req)
359    {
360        panic("instRead not implemented");
361        // return funcPhysMem->read(req, inst);
362        return NoFault;
363    }
364
365    void setCpuId(int id) { cpu_id = id; }
366
367    int readCpuId() { return cpu_id; }
368
369    void copyArchRegs(ExecContext *xc);
370
371    //
372    // New accessors for new decoder.
373    //
374    uint64_t readIntReg(int reg_idx)
375    {
376        return regs.readIntReg(reg_idx);
377    }
378
379    FloatReg readFloatReg(int reg_idx, int width)
380    {
381        return regs.readFloatReg(reg_idx, width);
382    }
383
384    FloatReg readFloatReg(int reg_idx)
385    {
386        return regs.readFloatReg(reg_idx);
387    }
388
389    FloatRegBits readFloatRegBits(int reg_idx, int width)
390    {
391        return regs.readFloatRegBits(reg_idx, width);
392    }
393
394    FloatRegBits readFloatRegBits(int reg_idx)
395    {
396        return regs.readFloatRegBits(reg_idx);
397    }
398
399    void setIntReg(int reg_idx, uint64_t val)
400    {
401        regs.setIntReg(reg_idx, val);
402    }
403
404    void setFloatReg(int reg_idx, FloatReg val, int width)
405    {
406        regs.setFloatReg(reg_idx, val, width);
407    }
408
409    void setFloatReg(int reg_idx, FloatReg val)
410    {
411        regs.setFloatReg(reg_idx, val);
412    }
413
414    void setFloatRegBits(int reg_idx, FloatRegBits val, int width)
415    {
416        regs.setFloatRegBits(reg_idx, val, width);
417    }
418
419    void setFloatRegBits(int reg_idx, FloatRegBits val)
420    {
421        regs.setFloatRegBits(reg_idx, val);
422    }
423
424    uint64_t readPC()
425    {
426        return regs.readPC();
427    }
428
429    void setPC(uint64_t val)
430    {
431        regs.setPC(val);
432    }
433
434    uint64_t readNextPC()
435    {
436        return regs.readNextPC();
437    }
438
439    void setNextPC(uint64_t val)
440    {
441        regs.setNextPC(val);
442    }
443
444    uint64_t readNextNPC()
445    {
446        return regs.readNextNPC();
447    }
448
449    void setNextNPC(uint64_t val)
450    {
451        regs.setNextNPC(val);
452    }
453
454
455    MiscReg readMiscReg(int misc_reg)
456    {
457        return regs.readMiscReg(misc_reg);
458    }
459
460    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
461    {
462        return regs.readMiscRegWithEffect(misc_reg, fault, proxy);
463    }
464
465    Fault setMiscReg(int misc_reg, const MiscReg &val)
466    {
467        return regs.setMiscReg(misc_reg, val);
468    }
469
470    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
471    {
472        return regs.setMiscRegWithEffect(misc_reg, val, proxy);
473    }
474
475    unsigned readStCondFailures() { return storeCondFailures; }
476
477    void setStCondFailures(unsigned sc_failures)
478    { storeCondFailures = sc_failures; }
479
480    void clearArchRegs() { regs.clear(); }
481
482#if FULL_SYSTEM
483    int readIntrFlag() { return regs.intrflag; }
484    void setIntrFlag(int val) { regs.intrflag = val; }
485    Fault hwrei();
486    bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
487    bool simPalCheck(int palFunc);
488#endif
489
490#if !FULL_SYSTEM
491    TheISA::IntReg getSyscallArg(int i)
492    {
493        return regs.readIntReg(TheISA::ArgumentReg0 + i);
494    }
495
496    // used to shift args for indirect syscall
497    void setSyscallArg(int i, TheISA::IntReg val)
498    {
499        regs.setIntReg(TheISA::ArgumentReg0 + i, val);
500    }
501
502    void setSyscallReturn(SyscallReturn return_value)
503    {
504        TheISA::setSyscallReturn(return_value, &regs);
505    }
506
507    void syscall()
508    {
509        process->syscall(proxy);
510    }
511
512    Counter readFuncExeInst() { return func_exe_inst; }
513
514    void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; }
515#endif
516
517    void changeRegFileContext(RegFile::ContextParam param,
518            RegFile::ContextVal val)
519    {
520        regs.changeContext(param, val);
521    }
522};
523
524
525// for non-speculative execution context, spec_mode is always false
526inline bool
527CPUExecContext::misspeculating()
528{
529    return false;
530}
531
532#endif // __CPU_CPU_EXEC_CONTEXT_HH__
533