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