simple_thread.hh revision 2455
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    typedef TheISA::FloatReg FloatReg;
74    typedef TheISA::FloatRegBits FloatRegBits;
75  public:
76    typedef ExecContext::Status Status;
77
78  private:
79    Status _status;
80
81  public:
82    Status status() const { return _status; }
83
84    void setStatus(Status newStatus) { _status = newStatus; }
85
86    /// Set the status to Active.  Optional delay indicates number of
87    /// cycles to wait before beginning execution.
88    void activate(int delay = 1);
89
90    /// Set the status to Suspended.
91    void suspend();
92
93    /// Set the status to Unallocated.
94    void deallocate();
95
96    /// Set the status to Halted.
97    void halt();
98
99  protected:
100    RegFile regs;	// correct-path register context
101
102  public:
103    // pointer to CPU associated with this context
104    BaseCPU *cpu;
105
106    ProxyExecContext<CPUExecContext> *proxy;
107
108    // Current instruction
109    MachInst inst;
110
111    // Index of hardware thread context on the CPU that this represents.
112    int thread_num;
113
114    // ID of this context w.r.t. the System or Process object to which
115    // it belongs.  For full-system mode, this is the system CPU ID.
116    int cpu_id;
117
118    Tick lastActivate;
119    Tick lastSuspend;
120
121    System *system;
122
123    /// Port that syscalls can use to access memory (provides translation step).
124    TranslatingPort *port;
125//    Memory *mem;
126
127#if FULL_SYSTEM
128    AlphaITB *itb;
129    AlphaDTB *dtb;
130
131    // the following two fields are redundant, since we can always
132    // look them up through the system pointer, but we'll leave them
133    // here for now for convenience
134    MemoryController *memctrl;
135//    PhysicalMemory *physmem;
136
137    FunctionProfile *profile;
138    ProfileNode *profileNode;
139    Addr profilePC;
140    void dumpFuncProfile();
141
142    /** Event for timing out quiesce instruction */
143    struct EndQuiesceEvent : public Event
144    {
145        /** A pointer to the execution context that is quiesced */
146        CPUExecContext *cpuXC;
147
148        EndQuiesceEvent(CPUExecContext *_cpuXC);
149
150        /** Event process to occur at interrupt*/
151        virtual void process();
152
153        /** Event description */
154        virtual const char *description();
155    };
156    EndQuiesceEvent quiesceEvent;
157
158    Event *getQuiesceEvent() { return &quiesceEvent; }
159
160    Tick readLastActivate() { return lastActivate; }
161
162    Tick readLastSuspend() { return lastSuspend; }
163
164    void profileClear();
165
166    void profileSample();
167
168#else
169    Process *process;
170
171    // Address space ID.  Note that this is used for TIMING cache
172    // simulation only; all functional memory accesses should use
173    // one of the FunctionalMemory pointers above.
174    short asid;
175
176#endif
177
178    /**
179     * Temporary storage to pass the source address from copy_load to
180     * copy_store.
181     * @todo Remove this temporary when we have a better way to do it.
182     */
183    Addr copySrcAddr;
184    /**
185     * Temp storage for the physical source address of a copy.
186     * @todo Remove this temporary when we have a better way to do it.
187     */
188    Addr copySrcPhysAddr;
189
190
191    /*
192     * number of executed instructions, for matching with syscall trace
193     * points in EIO files.
194     */
195    Counter func_exe_inst;
196
197    //
198    // Count failed store conditionals so we can warn of apparent
199    // application deadlock situations.
200    unsigned storeCondFailures;
201
202    // constructor: initialize context from given process structure
203#if FULL_SYSTEM
204    CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
205                   AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
206#else
207    CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, Port *mem_port);
208    // Constructor to use XC to pass reg file around.  Not used for anything
209    // else.
210    CPUExecContext(RegFile *regFile);
211#endif
212    virtual ~CPUExecContext();
213
214    virtual void takeOverFrom(ExecContext *oldContext);
215
216    void regStats(const std::string &name);
217
218    void serialize(std::ostream &os);
219    void unserialize(Checkpoint *cp, const std::string &section);
220
221    TranslatingPort *getMemPort() { return port; }
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    PhysicalMemory *getPhysMemPtr() { return physmem; }
233
234    AlphaITB *getITBPtr() { return itb; }
235
236    AlphaDTB *getDTBPtr() { return dtb; }
237
238    int getInstAsid() { return regs.instAsid(); }
239    int getDataAsid() { return regs.dataAsid(); }
240
241    Fault translateInstReq(CpuRequestPtr &req)
242    {
243        return itb->translate(req);
244    }
245
246    Fault translateDataReadReq(CpuRequestPtr &req)
247    {
248        return dtb->translate(req, false);
249    }
250
251    Fault translateDataWriteReq(CpuRequestPtr &req)
252    {
253        return dtb->translate(req, true);
254    }
255
256#else
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.intRegFile[reg_idx];
377    }
378
379    FloatReg readFloatReg(int reg_idx, int width)
380    {
381        return regs.floatRegFile.readReg(reg_idx, width);
382    }
383
384    FloatReg readFloatReg(int reg_idx)
385    {
386        return regs.floatRegFile.readReg(reg_idx);
387    }
388
389    FloatRegBits readFloatRegBits(int reg_idx, int width)
390    {
391        return regs.floatRegFile.readRegBits(reg_idx, width);
392    }
393
394    FloatRegBits readFloatRegBits(int reg_idx)
395    {
396        return regs.floatRegFile.readRegBits(reg_idx);
397    }
398
399    void setIntReg(int reg_idx, uint64_t val)
400    {
401        regs.intRegFile[reg_idx] = val;
402    }
403
404    void setFloatReg(int reg_idx, FloatReg val, int width)
405    {
406        regs.floatRegFile.setReg(reg_idx, val, width);
407    }
408
409    void setFloatReg(int reg_idx, FloatReg val)
410    {
411        regs.floatRegFile.setReg(reg_idx, val);
412    }
413
414    void setFloatRegBits(int reg_idx, FloatRegBits val, int width)
415    {
416        regs.floatRegFile.setRegBits(reg_idx, val, width);
417    }
418
419    void setFloatRegBits(int reg_idx, FloatRegBits val)
420    {
421        regs.floatRegFile.setRegBits(reg_idx, val);
422    }
423
424    uint64_t readPC()
425    {
426        return regs.pc;
427    }
428
429    void setPC(uint64_t val)
430    {
431        regs.pc = val;
432    }
433
434    uint64_t readNextPC()
435    {
436        return regs.npc;
437    }
438
439    void setNextPC(uint64_t val)
440    {
441        regs.npc = val;
442    }
443
444    uint64_t readNextNPC()
445    {
446        return regs.nnpc;
447    }
448
449    void setNextNPC(uint64_t val)
450    {
451        regs.nnpc = val;
452    }
453
454
455    MiscReg readMiscReg(int misc_reg)
456    {
457        return regs.miscRegs.readReg(misc_reg);
458    }
459
460    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
461    {
462        return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy);
463    }
464
465    Fault setMiscReg(int misc_reg, const MiscReg &val)
466    {
467        return regs.miscRegs.setReg(misc_reg, val);
468    }
469
470    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
471    {
472        return regs.miscRegs.setRegWithEffect(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() { memset(&regs, 0, sizeof(regs)); }
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.intRegFile[TheISA::ArgumentReg0 + i];
494    }
495
496    // used to shift args for indirect syscall
497    void setSyscallArg(int i, TheISA::IntReg val)
498    {
499        regs.intRegFile[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
518
519// for non-speculative execution context, spec_mode is always false
520inline bool
521CPUExecContext::misspeculating()
522{
523    return false;
524}
525
526#endif // __CPU_CPU_EXEC_CONTEXT_HH__
527