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