simple_thread.cc revision 5482
1955SN/A/*
2955SN/A * Copyright (c) 2001-2006 The Regents of The University of Michigan
31762SN/A * All rights reserved.
4955SN/A *
5955SN/A * Redistribution and use in source and binary forms, with or without
6955SN/A * modification, are permitted provided that the following conditions are
7955SN/A * met: redistributions of source code must retain the above copyright
8955SN/A * notice, this list of conditions and the following disclaimer;
9955SN/A * redistributions in binary form must reproduce the above copyright
10955SN/A * notice, this list of conditions and the following disclaimer in the
11955SN/A * documentation and/or other materials provided with the distribution;
12955SN/A * neither the name of the copyright holders nor the names of its
13955SN/A * contributors may be used to endorse or promote products derived from
14955SN/A * this software without specific prior written permission.
15955SN/A *
16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27955SN/A *
282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
292665Ssaidi@eecs.umich.edu *          Nathan Binkert
30955SN/A *          Lisa Hsu
31955SN/A *          Kevin Lim
32955SN/A */
331608SN/A
34955SN/A#include <string>
35955SN/A
36955SN/A#include "arch/isa_traits.hh"
37955SN/A#include "cpu/base.hh"
38955SN/A#include "cpu/simple_thread.hh"
39955SN/A#include "cpu/thread_context.hh"
40955SN/A
41955SN/A#if FULL_SYSTEM
42955SN/A#include "arch/kernel_stats.hh"
43955SN/A#include "base/callback.hh"
44955SN/A#include "base/cprintf.hh"
45955SN/A#include "base/output.hh"
46955SN/A#include "base/trace.hh"
47955SN/A#include "cpu/profile.hh"
482023SN/A#include "cpu/quiesce_event.hh"
49955SN/A#include "sim/serialize.hh"
50955SN/A#include "sim/sim_exit.hh"
51955SN/A#include "arch/stacktrace.hh"
52955SN/A#else
53955SN/A#include "sim/process.hh"
54955SN/A#include "sim/system.hh"
55955SN/A#include "mem/translating_port.hh"
56955SN/A#endif
57955SN/A
581031SN/Ausing namespace std;
59955SN/A
601388SN/A// constructor
61955SN/A#if FULL_SYSTEM
62955SN/ASimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
631296SN/A                           TheISA::ITB *_itb, TheISA::DTB *_dtb,
64955SN/A                           bool use_kernel_stats)
652609SN/A    : ThreadState(_cpu, -1, _thread_num), cpu(_cpu), system(_sys), itb(_itb),
66955SN/A      dtb(_dtb)
67955SN/A
68955SN/A{
69955SN/A    tc = new ProxyThreadContext<SimpleThread>(this);
70955SN/A
71955SN/A    quiesceEvent = new EndQuiesceEvent(tc);
72955SN/A
73955SN/A    regs.clear();
74955SN/A
75955SN/A    if (cpu->params->profile) {
76955SN/A        profile = new FunctionProfile(system->kernelSymtab);
77955SN/A        Callback *cb =
78955SN/A            new MakeCallback<SimpleThread,
79955SN/A            &SimpleThread::dumpFuncProfile>(this);
80955SN/A        registerExitCallback(cb);
81955SN/A    }
82955SN/A
83955SN/A    // let's fill with a dummy node for now so we don't get a segfault
841717SN/A    // on the first cycle when there's no node available.
852190SN/A    static ProfileNode dummyNode;
862652Ssaidi@eecs.umich.edu    profileNode = &dummyNode;
87955SN/A    profilePC = 3;
882410SN/A
89955SN/A    if (use_kernel_stats)
90955SN/A        kernelStats = new TheISA::Kernel::Statistics(system);
911717SN/A}
922568SN/A#else
932568SN/ASimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
942568SN/A                           TheISA::ITB *_itb, TheISA::DTB *_dtb, int _asid)
952499SN/A    : ThreadState(_cpu, -1, _thread_num, _process, _asid),
962462SN/A      cpu(_cpu), itb(_itb), dtb(_dtb)
972568SN/A{
982395SN/A    regs.clear();
992405SN/A    tc = new ProxyThreadContext<SimpleThread>(this);
100955SN/A}
101955SN/A
102955SN/A#endif
103955SN/A
104955SN/ASimpleThread::SimpleThread()
1052090SN/A#if FULL_SYSTEM
106955SN/A    : ThreadState(NULL, -1, -1)
1072667Sstever@eecs.umich.edu#else
108955SN/A    : ThreadState(NULL, -1, -1, NULL, -1)
109955SN/A#endif
1101696SN/A{
111955SN/A    tc = new ProxyThreadContext<SimpleThread>(this);
112955SN/A    regs.clear();
113955SN/A}
1141127SN/A
115955SN/ASimpleThread::~SimpleThread()
116955SN/A{
1172379SN/A#if FULL_SYSTEM
118955SN/A    delete physPort;
119955SN/A    delete virtPort;
120955SN/A#endif
1212155SN/A    delete tc;
1222155SN/A}
1232155SN/A
1242155SN/Avoid
1252155SN/ASimpleThread::takeOverFrom(ThreadContext *oldContext)
1262155SN/A{
1272155SN/A    // some things should already be set up
1282155SN/A#if FULL_SYSTEM
1292155SN/A    assert(system == oldContext->getSystemPtr());
1302155SN/A#else
1312155SN/A    assert(process == oldContext->getProcessPtr());
1322155SN/A#endif
1332155SN/A
1342155SN/A    copyState(oldContext);
1352155SN/A#if FULL_SYSTEM
1362155SN/A    EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
1372155SN/A    if (quiesce) {
1382155SN/A        // Point the quiesce event's TC at this TC so that it wakes up
1392155SN/A        // the proper CPU.
1402155SN/A        quiesce->tc = tc;
1412155SN/A    }
1422155SN/A    if (quiesceEvent) {
1432155SN/A        quiesceEvent->tc = tc;
1442155SN/A    }
1452155SN/A
1462155SN/A    TheISA::Kernel::Statistics *stats = oldContext->getKernelStats();
1472155SN/A    if (stats) {
1482155SN/A        kernelStats = stats;
1492155SN/A    }
1502155SN/A#endif
1512155SN/A
1522155SN/A    storeCondFailures = 0;
1532155SN/A
1542155SN/A    oldContext->setStatus(ThreadContext::Unallocated);
1552155SN/A}
1562155SN/A
1572155SN/Avoid
1582155SN/ASimpleThread::copyTC(ThreadContext *context)
1592155SN/A{
1602422SN/A    copyState(context);
1612422SN/A
1622422SN/A#if FULL_SYSTEM
1632422SN/A    EndQuiesceEvent *quiesce = context->getQuiesceEvent();
1642422SN/A    if (quiesce) {
1652422SN/A        quiesceEvent = quiesce;
1662422SN/A    }
1672397SN/A    TheISA::Kernel::Statistics *stats = context->getKernelStats();
1682397SN/A    if (stats) {
1692422SN/A        kernelStats = stats;
1702422SN/A    }
171955SN/A#endif
172955SN/A}
173955SN/A
174955SN/Avoid
175955SN/ASimpleThread::copyState(ThreadContext *oldContext)
176955SN/A{
177955SN/A    // copy over functional state
178955SN/A    _status = oldContext->status();
1791078SN/A    copyArchRegs(oldContext);
180955SN/A    cpuId = oldContext->readCpuId();
181955SN/A#if !FULL_SYSTEM
182955SN/A    funcExeInst = oldContext->readFuncExeInst();
183955SN/A#endif
1841917SN/A    inst = oldContext->getInst();
185955SN/A}
186955SN/A
187955SN/Avoid
188955SN/ASimpleThread::serialize(ostream &os)
189974SN/A{
190955SN/A    ThreadState::serialize(os);
191955SN/A    regs.serialize(os);
192955SN/A    // thread_num and cpu_id are deterministic from the config
193955SN/A}
1942566SN/A
1952566SN/A
196955SN/Avoid
197955SN/ASimpleThread::unserialize(Checkpoint *cp, const std::string &section)
1982539SN/A{
199955SN/A    ThreadState::unserialize(cp, section);
200955SN/A    regs.unserialize(cp, section);
201955SN/A    // thread_num and cpu_id are deterministic from the config
2021817SN/A}
2031154SN/A
2041840SN/A#if FULL_SYSTEM
2052522SN/Avoid
2062522SN/ASimpleThread::dumpFuncProfile()
2072629SN/A{
208955SN/A    std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
209955SN/A    profile->dump(tc, *os);
210955SN/A}
2112539SN/A#endif
212955SN/A
2132539SN/Avoid
214955SN/ASimpleThread::activate(int delay)
2151730SN/A{
216955SN/A    if (status() == ThreadContext::Active)
2171070SN/A        return;
218955SN/A
219955SN/A    lastActivate = curTick;
2202212SN/A
221955SN/A//    if (status() == ThreadContext::Unallocated) {
2221040SN/A//	cpu->activateWhenReady(tid);
2232507SN/A//	return;
2242521SN/A//   }
2252521SN/A
2262507SN/A    _status = ThreadContext::Active;
2272507SN/A
2282507SN/A    // status() == Suspended
2292521SN/A    cpu->activateContext(tid, delay);
2302507SN/A}
2312507SN/A
232955SN/Avoid
233955SN/ASimpleThread::suspend()
234955SN/A{
235955SN/A    if (status() == ThreadContext::Suspended)
236955SN/A        return;
237955SN/A
2381742SN/A    lastActivate = curTick;
2391742SN/A    lastSuspend = curTick;
2401742SN/A/*
2411742SN/A#if FULL_SYSTEM
2421742SN/A    // Don't change the status from active if there are pending interrupts
2431742SN/A    if (cpu->check_interrupts()) {
2441742SN/A        assert(status() == ThreadContext::Active);
2451742SN/A        return;
2461742SN/A    }
2471742SN/A#endif
2481742SN/A*/
2491742SN/A    _status = ThreadContext::Suspended;
2501742SN/A    cpu->suspendContext(tid);
2511742SN/A}
2521742SN/A
2531742SN/Avoid
2541742SN/ASimpleThread::deallocate()
2551742SN/A{
2561742SN/A    if (status() == ThreadContext::Unallocated)
2571742SN/A        return;
258955SN/A
259955SN/A    _status = ThreadContext::Unallocated;
2602520SN/A    cpu->deallocateContext(tid);
2612517SN/A}
2622253SN/A
2632253SN/Avoid
2642253SN/ASimpleThread::halt()
2652253SN/A{
2662553SN/A    if (status() == ThreadContext::Halted)
2672553SN/A        return;
2682553SN/A
2692553SN/A    _status = ThreadContext::Halted;
2702507SN/A    cpu->haltContext(tid);
2712470SN/A}
2721744SN/A
2731744SN/A
2742470SN/Avoid
2752470SN/ASimpleThread::regStats(const string &name)
2762470SN/A{
2772470SN/A#if FULL_SYSTEM
2782470SN/A    if (kernelStats)
2792470SN/A        kernelStats->regStats(name + ".kern");
2802400SN/A#endif
2812400SN/A}
282955SN/A
283955SN/Avoid
2842667Sstever@eecs.umich.eduSimpleThread::copyArchRegs(ThreadContext *src_tc)
2852667Sstever@eecs.umich.edu{
2862667Sstever@eecs.umich.edu    TheISA::copyRegs(src_tc, tc);
2872667Sstever@eecs.umich.edu}
2882667Sstever@eecs.umich.edu
2892667Sstever@eecs.umich.edu#if FULL_SYSTEM
2902037SN/AVirtualPort*
2912037SN/ASimpleThread::getVirtPort(ThreadContext *src_tc)
2922037SN/A{
2932667Sstever@eecs.umich.edu    if (!src_tc)
2942139SN/A        return virtPort;
2952667Sstever@eecs.umich.edu
2962155SN/A    VirtualPort *vp = new VirtualPort("tc-vport", src_tc);
2972155SN/A    connectToMemFunc(vp);
2982155SN/A    return vp;
2992155SN/A}
3002155SN/A
3012155SN/Avoid
302955SN/ASimpleThread::delVirtPort(VirtualPort *vp)
3032155SN/A{
304955SN/A    if (vp != virtPort) {
305955SN/A        vp->removeConn();
306955SN/A        delete vp;
3071742SN/A    }
3081742SN/A}
309955SN/A
310955SN/A#endif
311955SN/A
3121858SN/A