simple_thread.hh revision 2521
110428Sandreas.hansson@arm.com/*
210428Sandreas.hansson@arm.com * Copyright (c) 2001-2006 The Regents of The University of Michigan
310428Sandreas.hansson@arm.com * All rights reserved.
410428Sandreas.hansson@arm.com *
510428Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
610428Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
710428Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
810428Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
910428Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
1010428Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
1110428Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
1210428Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
1310428Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
1410428Sandreas.hansson@arm.com * this software without specific prior written permission.
1510428Sandreas.hansson@arm.com *
1610428Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710428Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810428Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910428Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010428Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110428Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210428Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310428Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410428Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510428Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610428Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710428Sandreas.hansson@arm.com */
2810428Sandreas.hansson@arm.com
2910428Sandreas.hansson@arm.com#ifndef __CPU_CPU_EXEC_CONTEXT_HH__
3010428Sandreas.hansson@arm.com#define __CPU_CPU_EXEC_CONTEXT_HH__
3110428Sandreas.hansson@arm.com
3210428Sandreas.hansson@arm.com#include "arch/isa_traits.hh"
3310428Sandreas.hansson@arm.com#include "config/full_system.hh"
3410428Sandreas.hansson@arm.com#include "cpu/exec_context.hh"
3510428Sandreas.hansson@arm.com#include "mem/physical.hh"
3610428Sandreas.hansson@arm.com#include "mem/request.hh"
3710428Sandreas.hansson@arm.com#include "sim/byteswap.hh"
3810428Sandreas.hansson@arm.com#include "sim/eventq.hh"
3910428Sandreas.hansson@arm.com#include "sim/host.hh"
4010428Sandreas.hansson@arm.com#include "sim/serialize.hh"
4110428Sandreas.hansson@arm.com
4210428Sandreas.hansson@arm.comclass BaseCPU;
4310428Sandreas.hansson@arm.com
4410428Sandreas.hansson@arm.com#if FULL_SYSTEM
4510428Sandreas.hansson@arm.com
4610428Sandreas.hansson@arm.com#include "sim/system.hh"
4710428Sandreas.hansson@arm.com#include "arch/tlb.hh"
4810428Sandreas.hansson@arm.com
4910428Sandreas.hansson@arm.comclass FunctionProfile;
5010428Sandreas.hansson@arm.comclass ProfileNode;
5110428Sandreas.hansson@arm.comclass FunctionalPort;
5210428Sandreas.hansson@arm.comclass PhysicalPort;
5310428Sandreas.hansson@arm.com
5410428Sandreas.hansson@arm.com
5510428Sandreas.hansson@arm.com#else // !FULL_SYSTEM
5612266Sradhika.jagtap@arm.com
5712266Sradhika.jagtap@arm.com#include "sim/process.hh"
5812266Sradhika.jagtap@arm.com#include "mem/page_table.hh"
5912266Sradhika.jagtap@arm.comclass TranslatingPort;
6012266Sradhika.jagtap@arm.com
6112266Sradhika.jagtap@arm.com
6212266Sradhika.jagtap@arm.com#endif // FULL_SYSTEM
6312266Sradhika.jagtap@arm.com
6412266Sradhika.jagtap@arm.com//
6512266Sradhika.jagtap@arm.com// The CPUExecContext object represents a functional context for
6612266Sradhika.jagtap@arm.com// instruction execution.  It incorporates everything required for
6712266Sradhika.jagtap@arm.com// architecture-level functional simulation of a single thread.
6812266Sradhika.jagtap@arm.com//
6912266Sradhika.jagtap@arm.com
7010428Sandreas.hansson@arm.comclass CPUExecContext
7110428Sandreas.hansson@arm.com{
7210428Sandreas.hansson@arm.com  protected:
7310428Sandreas.hansson@arm.com    typedef TheISA::RegFile RegFile;
7410428Sandreas.hansson@arm.com    typedef TheISA::MachInst MachInst;
7510428Sandreas.hansson@arm.com    typedef TheISA::MiscRegFile MiscRegFile;
7610428Sandreas.hansson@arm.com    typedef TheISA::MiscReg MiscReg;
7710428Sandreas.hansson@arm.com    typedef TheISA::FloatReg FloatReg;
7812266Sradhika.jagtap@arm.com    typedef TheISA::FloatRegBits FloatRegBits;
7912266Sradhika.jagtap@arm.com  public:
8012266Sradhika.jagtap@arm.com    typedef ExecContext::Status Status;
8112266Sradhika.jagtap@arm.com
8212266Sradhika.jagtap@arm.com  private:
8312266Sradhika.jagtap@arm.com    Status _status;
8412266Sradhika.jagtap@arm.com
8512266Sradhika.jagtap@arm.com  public:
8612266Sradhika.jagtap@arm.com    Status status() const { return _status; }
8712266Sradhika.jagtap@arm.com
8812266Sradhika.jagtap@arm.com    void setStatus(Status newStatus) { _status = newStatus; }
8912266Sradhika.jagtap@arm.com
9012266Sradhika.jagtap@arm.com    /// Set the status to Active.  Optional delay indicates number of
9112266Sradhika.jagtap@arm.com    /// cycles to wait before beginning execution.
9212266Sradhika.jagtap@arm.com    void activate(int delay = 1);
9310428Sandreas.hansson@arm.com
9410428Sandreas.hansson@arm.com    /// Set the status to Suspended.
9511555Sjungma@eit.uni-kl.de    void suspend();
9610428Sandreas.hansson@arm.com
9710428Sandreas.hansson@arm.com    /// Set the status to Unallocated.
9811555Sjungma@eit.uni-kl.de    void deallocate();
9910428Sandreas.hansson@arm.com
10010428Sandreas.hansson@arm.com    /// Set the status to Halted.
10110428Sandreas.hansson@arm.com    void halt();
10211555Sjungma@eit.uni-kl.de
10310428Sandreas.hansson@arm.com  protected:
10410428Sandreas.hansson@arm.com    RegFile regs;	// correct-path register context
10510428Sandreas.hansson@arm.com
10610428Sandreas.hansson@arm.com  public:
10710428Sandreas.hansson@arm.com    // pointer to CPU associated with this context
10810428Sandreas.hansson@arm.com    BaseCPU *cpu;
10910428Sandreas.hansson@arm.com
11010428Sandreas.hansson@arm.com    ProxyExecContext<CPUExecContext> *proxy;
11110428Sandreas.hansson@arm.com
11210428Sandreas.hansson@arm.com    // Current instruction
11310428Sandreas.hansson@arm.com    MachInst inst;
11410428Sandreas.hansson@arm.com
11510428Sandreas.hansson@arm.com    // Index of hardware thread context on the CPU that this represents.
11610428Sandreas.hansson@arm.com    int thread_num;
11711555Sjungma@eit.uni-kl.de
11810428Sandreas.hansson@arm.com    // ID of this context w.r.t. the System or Process object to which
11910428Sandreas.hansson@arm.com    // it belongs.  For full-system mode, this is the system CPU ID.
12010428Sandreas.hansson@arm.com    int cpu_id;
12110428Sandreas.hansson@arm.com
12210428Sandreas.hansson@arm.com    Tick lastActivate;
12310428Sandreas.hansson@arm.com    Tick lastSuspend;
12410428Sandreas.hansson@arm.com
12511555Sjungma@eit.uni-kl.de    System *system;
12610428Sandreas.hansson@arm.com
12710428Sandreas.hansson@arm.com
12810428Sandreas.hansson@arm.com#if FULL_SYSTEM
12910428Sandreas.hansson@arm.com    AlphaITB *itb;
13010428Sandreas.hansson@arm.com    AlphaDTB *dtb;
13110428Sandreas.hansson@arm.com
13210428Sandreas.hansson@arm.com    /** A functional port outgoing only for functional accesses to physical
13310428Sandreas.hansson@arm.com     * addresses.*/
13410428Sandreas.hansson@arm.com    FunctionalPort *physPort;
13510428Sandreas.hansson@arm.com
13610428Sandreas.hansson@arm.com    /** A functional port, outgoing only, for functional accesse to virtual
13710428Sandreas.hansson@arm.com     * addresses. That doen't require execution context information */
13810428Sandreas.hansson@arm.com    VirtualPort *virtPort;
13910428Sandreas.hansson@arm.com
14010428Sandreas.hansson@arm.com    FunctionProfile *profile;
14112266Sradhika.jagtap@arm.com    ProfileNode *profileNode;
14210428Sandreas.hansson@arm.com    Addr profilePC;
14310428Sandreas.hansson@arm.com    void dumpFuncProfile();
14410428Sandreas.hansson@arm.com
14511555Sjungma@eit.uni-kl.de    /** Event for timing out quiesce instruction */
14611555Sjungma@eit.uni-kl.de    struct EndQuiesceEvent : public Event
14711555Sjungma@eit.uni-kl.de    {
14811555Sjungma@eit.uni-kl.de        /** A pointer to the execution context that is quiesced */
14911555Sjungma@eit.uni-kl.de        CPUExecContext *cpuXC;
15012266Sradhika.jagtap@arm.com
15111555Sjungma@eit.uni-kl.de        EndQuiesceEvent(CPUExecContext *_cpuXC);
15211555Sjungma@eit.uni-kl.de
15311555Sjungma@eit.uni-kl.de        /** Event process to occur at interrupt*/
15411555Sjungma@eit.uni-kl.de        virtual void process();
15511555Sjungma@eit.uni-kl.de
15611555Sjungma@eit.uni-kl.de        /** Event description */
15711555Sjungma@eit.uni-kl.de        virtual const char *description();
15811555Sjungma@eit.uni-kl.de    };
15911555Sjungma@eit.uni-kl.de    EndQuiesceEvent quiesceEvent;
16011555Sjungma@eit.uni-kl.de
16111555Sjungma@eit.uni-kl.de    Event *getQuiesceEvent() { return &quiesceEvent; }
16211555Sjungma@eit.uni-kl.de
16311555Sjungma@eit.uni-kl.de    Tick readLastActivate() { return lastActivate; }
16411555Sjungma@eit.uni-kl.de
16510428Sandreas.hansson@arm.com    Tick readLastSuspend() { return lastSuspend; }
16610428Sandreas.hansson@arm.com
16710428Sandreas.hansson@arm.com    void profileClear();
16810428Sandreas.hansson@arm.com
16910428Sandreas.hansson@arm.com    void profileSample();
17011555Sjungma@eit.uni-kl.de
17110428Sandreas.hansson@arm.com#else
17210428Sandreas.hansson@arm.com    /// Port that syscalls can use to access memory (provides translation step).
17310428Sandreas.hansson@arm.com    TranslatingPort *port;
17410428Sandreas.hansson@arm.com
17510428Sandreas.hansson@arm.com    Process *process;
17610428Sandreas.hansson@arm.com
17710428Sandreas.hansson@arm.com    // Address space ID.  Note that this is used for TIMING cache
17810428Sandreas.hansson@arm.com    // simulation only; all functional memory accesses should use
17910428Sandreas.hansson@arm.com    // one of the FunctionalMemory pointers above.
18010428Sandreas.hansson@arm.com    short asid;
18110490Sandreas.hansson@arm.com
18210428Sandreas.hansson@arm.com#endif
18310428Sandreas.hansson@arm.com
18410428Sandreas.hansson@arm.com    /**
18510428Sandreas.hansson@arm.com     * Temporary storage to pass the source address from copy_load to
18610428Sandreas.hansson@arm.com     * copy_store.
18711555Sjungma@eit.uni-kl.de     * @todo Remove this temporary when we have a better way to do it.
18810428Sandreas.hansson@arm.com     */
18910428Sandreas.hansson@arm.com    Addr copySrcAddr;
19010428Sandreas.hansson@arm.com    /**
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