simple_thread.hh revision 2455
110859Sandreas.sandberg@arm.com/*
211461Sandreas.sandberg@arm.com * Copyright (c) 2001-2006 The Regents of The University of Michigan
310859Sandreas.sandberg@arm.com * All rights reserved.
410859Sandreas.sandberg@arm.com *
510859Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
610859Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
710859Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
810859Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
910859Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1010859Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1110859Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1210859Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1310859Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1410859Sandreas.sandberg@arm.com * this software without specific prior written permission.
1510859Sandreas.sandberg@arm.com *
1610859Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710859Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810859Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910859Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010859Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110859Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210859Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310859Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410859Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510859Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610859Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710859Sandreas.sandberg@arm.com */
2810859Sandreas.sandberg@arm.com
2910859Sandreas.sandberg@arm.com#ifndef __CPU_CPU_EXEC_CONTEXT_HH__
3010859Sandreas.sandberg@arm.com#define __CPU_CPU_EXEC_CONTEXT_HH__
3110859Sandreas.sandberg@arm.com
3210859Sandreas.sandberg@arm.com#include "arch/isa_traits.hh"
3310859Sandreas.sandberg@arm.com#include "config/full_system.hh"
3410859Sandreas.sandberg@arm.com#include "cpu/exec_context.hh"
3510859Sandreas.sandberg@arm.com#include "mem/physical.hh"
3610859Sandreas.sandberg@arm.com#include "mem/request.hh"
3710859Sandreas.sandberg@arm.com#include "sim/byteswap.hh"
3810859Sandreas.sandberg@arm.com#include "sim/eventq.hh"
3910859Sandreas.sandberg@arm.com#include "sim/host.hh"
4010859Sandreas.sandberg@arm.com#include "sim/serialize.hh"
4110859Sandreas.sandberg@arm.com
4210859Sandreas.sandberg@arm.comclass BaseCPU;
4310859Sandreas.sandberg@arm.com
4410859Sandreas.sandberg@arm.com#if FULL_SYSTEM
4510859Sandreas.sandberg@arm.com
4610859Sandreas.sandberg@arm.com#include "sim/system.hh"
4711462Sandreas.sandberg@arm.com#include "arch/tlb.hh"
4811462Sandreas.sandberg@arm.com
4911461Sandreas.sandberg@arm.comclass FunctionProfile;
5011461Sandreas.sandberg@arm.comclass ProfileNode;
5111461Sandreas.sandberg@arm.comclass MemoryController;
5211461Sandreas.sandberg@arm.com
5311461Sandreas.sandberg@arm.com#else // !FULL_SYSTEM
5411461Sandreas.sandberg@arm.com
5511461Sandreas.sandberg@arm.com#include "sim/process.hh"
5611461Sandreas.sandberg@arm.comclass TranslatingPort;
5711461Sandreas.sandberg@arm.com
5811462Sandreas.sandberg@arm.com#endif // FULL_SYSTEM
5911462Sandreas.sandberg@arm.com
6011461Sandreas.sandberg@arm.com//
6111461Sandreas.sandberg@arm.com// The CPUExecContext object represents a functional context for
6211461Sandreas.sandberg@arm.com// instruction execution.  It incorporates everything required for
6311461Sandreas.sandberg@arm.com// architecture-level functional simulation of a single thread.
6411461Sandreas.sandberg@arm.com//
6511461Sandreas.sandberg@arm.com
6611461Sandreas.sandberg@arm.comclass CPUExecContext
6711461Sandreas.sandberg@arm.com{
6811461Sandreas.sandberg@arm.com  protected:
6911461Sandreas.sandberg@arm.com    typedef TheISA::RegFile RegFile;
7011461Sandreas.sandberg@arm.com    typedef TheISA::MachInst MachInst;
7111461Sandreas.sandberg@arm.com    typedef TheISA::MiscRegFile MiscRegFile;
7211461Sandreas.sandberg@arm.com    typedef TheISA::MiscReg MiscReg;
7311461Sandreas.sandberg@arm.com    typedef TheISA::FloatReg FloatReg;
7411461Sandreas.sandberg@arm.com    typedef TheISA::FloatRegBits FloatRegBits;
7511461Sandreas.sandberg@arm.com  public:
7611461Sandreas.sandberg@arm.com    typedef ExecContext::Status Status;
7711461Sandreas.sandberg@arm.com
7811461Sandreas.sandberg@arm.com  private:
7911461Sandreas.sandberg@arm.com    Status _status;
8011461Sandreas.sandberg@arm.com
8111461Sandreas.sandberg@arm.com  public:
8211461Sandreas.sandberg@arm.com    Status status() const { return _status; }
8311461Sandreas.sandberg@arm.com
8411461Sandreas.sandberg@arm.com    void setStatus(Status newStatus) { _status = newStatus; }
8511461Sandreas.sandberg@arm.com
8611461Sandreas.sandberg@arm.com    /// Set the status to Active.  Optional delay indicates number of
8711461Sandreas.sandberg@arm.com    /// cycles to wait before beginning execution.
8811461Sandreas.sandberg@arm.com    void activate(int delay = 1);
8911461Sandreas.sandberg@arm.com
9011461Sandreas.sandberg@arm.com    /// Set the status to Suspended.
9111461Sandreas.sandberg@arm.com    void suspend();
9211461Sandreas.sandberg@arm.com
9311461Sandreas.sandberg@arm.com    /// Set the status to Unallocated.
9411461Sandreas.sandberg@arm.com    void deallocate();
9511461Sandreas.sandberg@arm.com
9611461Sandreas.sandberg@arm.com    /// Set the status to Halted.
9711461Sandreas.sandberg@arm.com    void halt();
9811461Sandreas.sandberg@arm.com
9911461Sandreas.sandberg@arm.com  protected:
10011461Sandreas.sandberg@arm.com    RegFile regs;	// correct-path register context
10111461Sandreas.sandberg@arm.com
10211461Sandreas.sandberg@arm.com  public:
10311461Sandreas.sandberg@arm.com    // pointer to CPU associated with this context
10411461Sandreas.sandberg@arm.com    BaseCPU *cpu;
10511461Sandreas.sandberg@arm.com
10610859Sandreas.sandberg@arm.com    ProxyExecContext<CPUExecContext> *proxy;
10710859Sandreas.sandberg@arm.com
10810859Sandreas.sandberg@arm.com    // Current instruction
10911462Sandreas.sandberg@arm.com    MachInst inst;
11011461Sandreas.sandberg@arm.com
11110859Sandreas.sandberg@arm.com    // Index of hardware thread context on the CPU that this represents.
11210859Sandreas.sandberg@arm.com    int thread_num;
11310859Sandreas.sandberg@arm.com
11410859Sandreas.sandberg@arm.com    // ID of this context w.r.t. the System or Process object to which
11510859Sandreas.sandberg@arm.com    // it belongs.  For full-system mode, this is the system CPU ID.
11610859Sandreas.sandberg@arm.com    int cpu_id;
11710859Sandreas.sandberg@arm.com
11810859Sandreas.sandberg@arm.com    Tick lastActivate;
11910905Sandreas.sandberg@arm.com    Tick lastSuspend;
12010859Sandreas.sandberg@arm.com
12110859Sandreas.sandberg@arm.com    System *system;
12210859Sandreas.sandberg@arm.com
12310859Sandreas.sandberg@arm.com    /// Port that syscalls can use to access memory (provides translation step).
12410859Sandreas.sandberg@arm.com    TranslatingPort *port;
12510905Sandreas.sandberg@arm.com//    Memory *mem;
12610859Sandreas.sandberg@arm.com
12710859Sandreas.sandberg@arm.com#if FULL_SYSTEM
12810859Sandreas.sandberg@arm.com    AlphaITB *itb;
12910859Sandreas.sandberg@arm.com    AlphaDTB *dtb;
13010859Sandreas.sandberg@arm.com
13110859Sandreas.sandberg@arm.com    // the following two fields are redundant, since we can always
13210859Sandreas.sandberg@arm.com    // look them up through the system pointer, but we'll leave them
13310859Sandreas.sandberg@arm.com    // here for now for convenience
13410859Sandreas.sandberg@arm.com    MemoryController *memctrl;
13510859Sandreas.sandberg@arm.com//    PhysicalMemory *physmem;
13610859Sandreas.sandberg@arm.com
13710859Sandreas.sandberg@arm.com    FunctionProfile *profile;
13810859Sandreas.sandberg@arm.com    ProfileNode *profileNode;
13910859Sandreas.sandberg@arm.com    Addr profilePC;
14010859Sandreas.sandberg@arm.com    void dumpFuncProfile();
14110859Sandreas.sandberg@arm.com
14210859Sandreas.sandberg@arm.com    /** Event for timing out quiesce instruction */
14310859Sandreas.sandberg@arm.com    struct EndQuiesceEvent : public Event
14410859Sandreas.sandberg@arm.com    {
14510859Sandreas.sandberg@arm.com        /** A pointer to the execution context that is quiesced */
14611461Sandreas.sandberg@arm.com        CPUExecContext *cpuXC;
14710859Sandreas.sandberg@arm.com
14810859Sandreas.sandberg@arm.com        EndQuiesceEvent(CPUExecContext *_cpuXC);
14910859Sandreas.sandberg@arm.com
15010859Sandreas.sandberg@arm.com        /** Event process to occur at interrupt*/
15110859Sandreas.sandberg@arm.com        virtual void process();
15210859Sandreas.sandberg@arm.com
15311461Sandreas.sandberg@arm.com        /** Event description */
15410859Sandreas.sandberg@arm.com        virtual const char *description();
15510859Sandreas.sandberg@arm.com    };
15610859Sandreas.sandberg@arm.com    EndQuiesceEvent quiesceEvent;
15710859Sandreas.sandberg@arm.com
15810859Sandreas.sandberg@arm.com    Event *getQuiesceEvent() { return &quiesceEvent; }
15910859Sandreas.sandberg@arm.com
16011461Sandreas.sandberg@arm.com    Tick readLastActivate() { return lastActivate; }
16110859Sandreas.sandberg@arm.com
16210859Sandreas.sandberg@arm.com    Tick readLastSuspend() { return lastSuspend; }
16310859Sandreas.sandberg@arm.com
16410859Sandreas.sandberg@arm.com    void profileClear();
16510859Sandreas.sandberg@arm.com
16610859Sandreas.sandberg@arm.com    void profileSample();
16711461Sandreas.sandberg@arm.com
16810859Sandreas.sandberg@arm.com#else
16910859Sandreas.sandberg@arm.com    Process *process;
17010859Sandreas.sandberg@arm.com
17110859Sandreas.sandberg@arm.com    // Address space ID.  Note that this is used for TIMING cache
17210859Sandreas.sandberg@arm.com    // simulation only; all functional memory accesses should use
17310859Sandreas.sandberg@arm.com    // one of the FunctionalMemory pointers above.
17410859Sandreas.sandberg@arm.com    short asid;
17510859Sandreas.sandberg@arm.com
17610859Sandreas.sandberg@arm.com#endif
17710859Sandreas.sandberg@arm.com
17810859Sandreas.sandberg@arm.com    /**
17910859Sandreas.sandberg@arm.com     * Temporary storage to pass the source address from copy_load to
18010859Sandreas.sandberg@arm.com     * copy_store.
18110859Sandreas.sandberg@arm.com     * @todo Remove this temporary when we have a better way to do it.
18210859Sandreas.sandberg@arm.com     */
18310859Sandreas.sandberg@arm.com    Addr copySrcAddr;
18410859Sandreas.sandberg@arm.com    /**
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