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