simple_thread.hh revision 2423
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"
56class TranslatingPort;
57
58#endif // FULL_SYSTEM
59
60//
61// The CPUExecContext object represents a functional context for
62// instruction execution.  It incorporates everything required for
63// architecture-level functional simulation of a single thread.
64//
65
66class CPUExecContext
67{
68  protected:
69    typedef TheISA::RegFile RegFile;
70    typedef TheISA::MachInst MachInst;
71    typedef TheISA::MiscRegFile MiscRegFile;
72    typedef TheISA::MiscReg MiscReg;
73  public:
74    typedef ExecContext::Status Status;
75
76  private:
77    Status _status;
78
79  public:
80    Status status() const { return _status; }
81
82    void setStatus(Status newStatus) { _status = newStatus; }
83
84    /// Set the status to Active.  Optional delay indicates number of
85    /// cycles to wait before beginning execution.
86    void activate(int delay = 1);
87
88    /// Set the status to Suspended.
89    void suspend();
90
91    /// Set the status to Unallocated.
92    void deallocate();
93
94    /// Set the status to Halted.
95    void halt();
96
97  protected:
98    RegFile regs;	// correct-path register context
99
100  public:
101    // pointer to CPU associated with this context
102    BaseCPU *cpu;
103
104    ProxyExecContext<CPUExecContext> *proxy;
105
106    // Current instruction
107    MachInst inst;
108
109    // Index of hardware thread context on the CPU that this represents.
110    int thread_num;
111
112    // ID of this context w.r.t. the System or Process object to which
113    // it belongs.  For full-system mode, this is the system CPU ID.
114    int cpu_id;
115
116    Tick lastActivate;
117    Tick lastSuspend;
118
119    System *system;
120
121    /// Port that syscalls can use to access memory (provides translation step).
122    TranslatingPort *port;
123//    Memory *mem;
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    Process *process;
168
169    // Address space ID.  Note that this is used for TIMING cache
170    // simulation only; all functional memory accesses should use
171    // one of the FunctionalMemory pointers above.
172    short asid;
173
174#endif
175
176    /**
177     * Temporary storage to pass the source address from copy_load to
178     * copy_store.
179     * @todo Remove this temporary when we have a better way to do it.
180     */
181    Addr copySrcAddr;
182    /**
183     * Temp storage for the physical source address of a copy.
184     * @todo Remove this temporary when we have a better way to do it.
185     */
186    Addr copySrcPhysAddr;
187
188
189    /*
190     * number of executed instructions, for matching with syscall trace
191     * points in EIO files.
192     */
193    Counter func_exe_inst;
194
195    //
196    // Count failed store conditionals so we can warn of apparent
197    // application deadlock situations.
198    unsigned storeCondFailures;
199
200    // constructor: initialize context from given process structure
201#if FULL_SYSTEM
202    CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
203                   AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
204#else
205    CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, Port *mem_port);
206    // Constructor to use XC to pass reg file around.  Not used for anything
207    // else.
208    CPUExecContext(RegFile *regFile);
209#endif
210    virtual ~CPUExecContext();
211
212    virtual void takeOverFrom(ExecContext *oldContext);
213
214    void regStats(const std::string &name);
215
216    void serialize(std::ostream &os);
217    void unserialize(Checkpoint *cp, const std::string &section);
218
219    BaseCPU *getCpuPtr() { return cpu; }
220
221    ExecContext *getProxy() { return proxy; }
222
223    int getThreadNum() { return thread_num; }
224
225#if FULL_SYSTEM
226    System *getSystemPtr() { return system; }
227
228    PhysicalMemory *getPhysMemPtr() { return physmem; }
229
230    AlphaITB *getITBPtr() { return itb; }
231
232    AlphaDTB *getDTBPtr() { return dtb; }
233
234    bool validInstAddr(Addr addr) { return true; }
235    bool validDataAddr(Addr addr) { return true; }
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    Process *getProcessPtr() { return process; }
256
257    bool validInstAddr(Addr addr)
258    { return process->validInstAddr(addr); }
259
260    bool validDataAddr(Addr addr)
261    { return process->validDataAddr(addr); }
262
263    int getInstAsid() { return asid; }
264    int getDataAsid() { return asid; }
265
266    Fault translateInstReq(CpuRequestPtr &req)
267    {
268        return process->pTable->translate(req);
269    }
270
271    Fault translateDataReadReq(CpuRequestPtr &req)
272    {
273        return process->pTable->translate(req);
274    }
275
276    Fault translateDataWriteReq(CpuRequestPtr &req)
277    {
278        return process->pTable->translate(req);
279    }
280
281#endif
282
283/*
284    template <class T>
285    Fault read(CpuRequestPtr &req, T &data)
286    {
287#if FULL_SYSTEM && defined(TARGET_ALPHA)
288        if (req->flags & LOCKED) {
289            req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
290            req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
291        }
292#endif
293
294        Fault error;
295        error = mem->prot_read(req->paddr, data, req->size);
296        data = LittleEndianGuest::gtoh(data);
297        return error;
298    }
299
300    template <class T>
301    Fault write(CpuRequestPtr &req, T &data)
302    {
303#if FULL_SYSTEM && defined(TARGET_ALPHA)
304        ExecContext *xc;
305
306        // If this is a store conditional, act appropriately
307        if (req->flags & LOCKED) {
308            xc = req->xc;
309
310            if (req->flags & UNCACHEABLE) {
311                // Don't update result register (see stq_c in isa_desc)
312                req->result = 2;
313                xc->setStCondFailures(0);//Needed? [RGD]
314            } else {
315                bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
316                Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
317                req->result = lock_flag;
318                if (!lock_flag ||
319                    ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
320                    xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
321                    xc->setStCondFailures(xc->readStCondFailures() + 1);
322                    if (((xc->readStCondFailures()) % 100000) == 0) {
323                        std::cerr << "Warning: "
324                                  << xc->readStCondFailures()
325                                  << " consecutive store conditional failures "
326                                  << "on cpu " << req->xc->readCpuId()
327                                  << std::endl;
328                    }
329                    return NoFault;
330                }
331                else xc->setStCondFailures(0);
332            }
333        }
334
335        // Need to clear any locked flags on other proccessors for
336        // this address.  Only do this for succsful Store Conditionals
337        // and all other stores (WH64?).  Unsuccessful Store
338        // Conditionals would have returned above, and wouldn't fall
339        // through.
340        for (int i = 0; i < system->execContexts.size(); i++){
341            xc = system->execContexts[i];
342            if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
343                (req->paddr & ~0xf)) {
344                xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
345            }
346        }
347
348#endif
349        return mem->prot_write(req->paddr, (T)htog(data), req->size);
350    }
351*/
352    virtual bool misspeculating();
353
354
355    MachInst getInst() { return inst; }
356
357    void setInst(MachInst new_inst)
358    {
359        inst = new_inst;
360    }
361
362    Fault instRead(CpuRequestPtr &req)
363    {
364        panic("instRead not implemented");
365        // return funcPhysMem->read(req, inst);
366        return NoFault;
367    }
368
369    void setCpuId(int id) { cpu_id = id; }
370
371    int readCpuId() { return cpu_id; }
372
373    void copyArchRegs(ExecContext *xc);
374
375    //
376    // New accessors for new decoder.
377    //
378    uint64_t readIntReg(int reg_idx)
379    {
380        return regs.intRegFile[reg_idx];
381    }
382
383    float readFloatRegSingle(int reg_idx)
384    {
385        return (float)regs.floatRegFile.d[reg_idx];
386    }
387
388    double readFloatRegDouble(int reg_idx)
389    {
390        return regs.floatRegFile.d[reg_idx];
391    }
392
393    uint64_t readFloatRegInt(int reg_idx)
394    {
395        return regs.floatRegFile.q[reg_idx];
396    }
397
398    void setIntReg(int reg_idx, uint64_t val)
399    {
400        regs.intRegFile[reg_idx] = val;
401    }
402
403    void setFloatRegSingle(int reg_idx, float val)
404    {
405        regs.floatRegFile.d[reg_idx] = (double)val;
406    }
407
408    void setFloatRegDouble(int reg_idx, double val)
409    {
410        regs.floatRegFile.d[reg_idx] = val;
411    }
412
413    void setFloatRegInt(int reg_idx, uint64_t val)
414    {
415        regs.floatRegFile.q[reg_idx] = val;
416    }
417
418    uint64_t readPC()
419    {
420        return regs.pc;
421    }
422
423    void setPC(uint64_t val)
424    {
425        regs.pc = val;
426    }
427
428    uint64_t readNextPC()
429    {
430        return regs.npc;
431    }
432
433    void setNextPC(uint64_t val)
434    {
435        regs.npc = val;
436    }
437
438    uint64_t readNextNPC()
439    {
440        return regs.nnpc;
441    }
442
443    void setNextNPC(uint64_t val)
444    {
445        regs.nnpc = val;
446    }
447
448
449    MiscReg readMiscReg(int misc_reg)
450    {
451        return regs.miscRegs.readReg(misc_reg);
452    }
453
454    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
455    {
456        return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy);
457    }
458
459    Fault setMiscReg(int misc_reg, const MiscReg &val)
460    {
461        return regs.miscRegs.setReg(misc_reg, val);
462    }
463
464    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
465    {
466        return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy);
467    }
468
469    unsigned readStCondFailures() { return storeCondFailures; }
470
471    void setStCondFailures(unsigned sc_failures)
472    { storeCondFailures = sc_failures; }
473
474    void clearArchRegs() { memset(&regs, 0, sizeof(regs)); }
475
476#if FULL_SYSTEM
477    int readIntrFlag() { return regs.intrflag; }
478    void setIntrFlag(int val) { regs.intrflag = val; }
479    Fault hwrei();
480    bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
481    bool simPalCheck(int palFunc);
482#endif
483
484#if !FULL_SYSTEM
485    TheISA::IntReg getSyscallArg(int i)
486    {
487        return regs.intRegFile[TheISA::ArgumentReg0 + i];
488    }
489
490    // used to shift args for indirect syscall
491    void setSyscallArg(int i, TheISA::IntReg val)
492    {
493        regs.intRegFile[TheISA::ArgumentReg0 + i] = val;
494    }
495
496    void setSyscallReturn(SyscallReturn return_value)
497    {
498        TheISA::setSyscallReturn(return_value, &regs);
499    }
500
501    void syscall()
502    {
503        process->syscall(proxy);
504    }
505
506    Counter readFuncExeInst() { return func_exe_inst; }
507
508    void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; }
509#endif
510};
511
512
513// for non-speculative execution context, spec_mode is always false
514inline bool
515CPUExecContext::misspeculating()
516{
517    return false;
518}
519
520#endif // __CPU_CPU_EXEC_CONTEXT_HH__
521