simple_thread.cc revision 7823:dac01f14f20f
12SN/A/*
21762SN/A * Copyright (c) 2001-2006 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282760Sbinkertn@umich.edu * Authors: Steve Reinhardt
292760Sbinkertn@umich.edu *          Nathan Binkert
302665Ssaidi@eecs.umich.edu *          Lisa Hsu
312SN/A *          Kevin Lim
322SN/A */
332SN/A
34363SN/A#include <string>
35363SN/A
361354SN/A#include "arch/isa_traits.hh"
372SN/A#include "arch/utility.hh"
382SN/A#include "config/the_isa.hh"
392SN/A#include "cpu/base.hh"
402SN/A#include "cpu/simple_thread.hh"
412SN/A#include "cpu/thread_context.hh"
422SN/A#include "params/BaseCPU.hh"
43363SN/A
4456SN/A#if FULL_SYSTEM
451388SN/A#include "arch/kernel_stats.hh"
46217SN/A#include "arch/stacktrace.hh"
47363SN/A#include "base/callback.hh"
4856SN/A#include "base/cprintf.hh"
4956SN/A#include "base/output.hh"
5056SN/A#include "base/trace.hh"
511638SN/A#include "cpu/profile.hh"
5256SN/A#include "cpu/quiesce_event.hh"
532SN/A#include "mem/vport.hh"
542356SN/A#include "sim/serialize.hh"
552356SN/A#include "sim/sim_exit.hh"
562356SN/A#else
572SN/A#include "mem/translating_port.hh"
582SN/A#include "sim/process.hh"
594000Ssaidi@eecs.umich.edu#include "sim/system.hh"
604000Ssaidi@eecs.umich.edu#endif
614762Snate@binkert.org
624762Snate@binkert.orgusing namespace std;
634762Snate@binkert.org
644762Snate@binkert.org// constructor
654762Snate@binkert.org#if FULL_SYSTEM
664762Snate@binkert.orgSimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
674762Snate@binkert.org                           TheISA::TLB *_itb, TheISA::TLB *_dtb,
684762Snate@binkert.org                           bool use_kernel_stats)
694762Snate@binkert.org    : ThreadState(_cpu, _thread_num),
704762Snate@binkert.org      cpu(_cpu), system(_sys), itb(_itb), dtb(_dtb)
714762Snate@binkert.org
724762Snate@binkert.org{
734762Snate@binkert.org    tc = new ProxyThreadContext<SimpleThread>(this);
744762Snate@binkert.org
754762Snate@binkert.org    quiesceEvent = new EndQuiesceEvent(tc);
764762Snate@binkert.org
774762Snate@binkert.org    clearArchRegs();
784762Snate@binkert.org
794762Snate@binkert.org    if (cpu->params()->profile) {
804762Snate@binkert.org        profile = new FunctionProfile(system->kernelSymtab);
814762Snate@binkert.org        Callback *cb =
824762Snate@binkert.org            new MakeCallback<SimpleThread,
834762Snate@binkert.org            &SimpleThread::dumpFuncProfile>(this);
844762Snate@binkert.org        registerExitCallback(cb);
854762Snate@binkert.org    }
864762Snate@binkert.org
874762Snate@binkert.org    // let's fill with a dummy node for now so we don't get a segfault
884762Snate@binkert.org    // on the first cycle when there's no node available.
894762Snate@binkert.org    static ProfileNode dummyNode;
904762Snate@binkert.org    profileNode = &dummyNode;
914762Snate@binkert.org    profilePC = 3;
924762Snate@binkert.org
934762Snate@binkert.org    if (use_kernel_stats)
944762Snate@binkert.org        kernelStats = new TheISA::Kernel::Statistics(system);
954762Snate@binkert.org}
964762Snate@binkert.org#else
974762Snate@binkert.orgSimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
984762Snate@binkert.org                           TheISA::TLB *_itb, TheISA::TLB *_dtb)
994762Snate@binkert.org    : ThreadState(_cpu, _thread_num, _process),
1004762Snate@binkert.org      cpu(_cpu), itb(_itb), dtb(_dtb)
1014762Snate@binkert.org{
1024762Snate@binkert.org    clearArchRegs();
1034762Snate@binkert.org    tc = new ProxyThreadContext<SimpleThread>(this);
1044762Snate@binkert.org}
1054762Snate@binkert.org
1064762Snate@binkert.org#endif
1074762Snate@binkert.org
1084762Snate@binkert.orgSimpleThread::SimpleThread()
1094762Snate@binkert.org#if FULL_SYSTEM
1104762Snate@binkert.org    : ThreadState(NULL, -1)
1114762Snate@binkert.org#else
1124762Snate@binkert.org    : ThreadState(NULL, -1, NULL)
1134762Snate@binkert.org#endif
1144762Snate@binkert.org{
1154762Snate@binkert.org    tc = new ProxyThreadContext<SimpleThread>(this);
1164762Snate@binkert.org}
1174762Snate@binkert.org
1184762Snate@binkert.orgSimpleThread::~SimpleThread()
1194762Snate@binkert.org{
1204762Snate@binkert.org#if FULL_SYSTEM
1214762Snate@binkert.org    delete physPort;
1224762Snate@binkert.org    delete virtPort;
1234762Snate@binkert.org#endif
1244762Snate@binkert.org    delete tc;
1254762Snate@binkert.org}
1264762Snate@binkert.org
1274762Snate@binkert.orgvoid
1284762Snate@binkert.orgSimpleThread::takeOverFrom(ThreadContext *oldContext)
1294762Snate@binkert.org{
1304762Snate@binkert.org    // some things should already be set up
1314762Snate@binkert.org#if FULL_SYSTEM
1324762Snate@binkert.org    assert(system == oldContext->getSystemPtr());
1334762Snate@binkert.org#else
1344762Snate@binkert.org    assert(process == oldContext->getProcessPtr());
1354762Snate@binkert.org#endif
1364762Snate@binkert.org
1374762Snate@binkert.org    copyState(oldContext);
1384762Snate@binkert.org#if FULL_SYSTEM
1394762Snate@binkert.org    EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
1404762Snate@binkert.org    if (quiesce) {
1414762Snate@binkert.org        // Point the quiesce event's TC at this TC so that it wakes up
1424762Snate@binkert.org        // the proper CPU.
1434762Snate@binkert.org        quiesce->tc = tc;
1444762Snate@binkert.org    }
1454762Snate@binkert.org    if (quiesceEvent) {
1464762Snate@binkert.org        quiesceEvent->tc = tc;
1474762Snate@binkert.org    }
1484762Snate@binkert.org
1494762Snate@binkert.org    TheISA::Kernel::Statistics *stats = oldContext->getKernelStats();
1504762Snate@binkert.org    if (stats) {
1514762Snate@binkert.org        kernelStats = stats;
1524762Snate@binkert.org    }
1534762Snate@binkert.org#endif
1544762Snate@binkert.org
1554762Snate@binkert.org    storeCondFailures = 0;
1562287SN/A
1572287SN/A    oldContext->setStatus(ThreadContext::Halted);
1582287SN/A}
1591637SN/A
1602SN/Avoid
161395SN/ASimpleThread::copyTC(ThreadContext *context)
1622SN/A{
163217SN/A    copyState(context);
1642SN/A
1652SN/A#if FULL_SYSTEM
1662SN/A    EndQuiesceEvent *quiesce = context->getQuiesceEvent();
167395SN/A    if (quiesce) {
1682SN/A        quiesceEvent = quiesce;
169217SN/A    }
1702SN/A    TheISA::Kernel::Statistics *stats = context->getKernelStats();
1712SN/A    if (stats) {
172217SN/A        kernelStats = stats;
1732SN/A    }
174502SN/A#endif
1752SN/A}
176217SN/A
177217SN/Avoid
178217SN/ASimpleThread::copyState(ThreadContext *oldContext)
1792SN/A{
1802SN/A    // copy over functional state
181217SN/A    _status = oldContext->status();
182217SN/A    copyArchRegs(oldContext);
183217SN/A#if !FULL_SYSTEM
184237SN/A    funcExeInst = oldContext->readFuncExeInst();
185502SN/A#endif
1862SN/A
187217SN/A    _threadId = oldContext->threadId();
188237SN/A    _contextId = oldContext->contextId();
189217SN/A}
190217SN/A
1912SN/Avoid
1922SN/ASimpleThread::serialize(ostream &os)
193217SN/A{
194217SN/A    ThreadState::serialize(os);
195217SN/A    SERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs);
196217SN/A    SERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
197217SN/A    _pcState.serialize(os);
198217SN/A    // thread_num and cpu_id are deterministic from the config
199217SN/A
200217SN/A    //
201217SN/A    // Now must serialize all the ISA dependent state
202217SN/A    //
203217SN/A    isa.serialize(cpu, os);
204217SN/A}
205217SN/A
206217SN/A
207217SN/Avoid
208217SN/ASimpleThread::unserialize(Checkpoint *cp, const std::string &section)
209217SN/A{
210217SN/A    ThreadState::unserialize(cp, section);
211217SN/A    UNSERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs);
212237SN/A    UNSERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
213217SN/A    _pcState.unserialize(cp, section);
214217SN/A    // thread_num and cpu_id are deterministic from the config
215217SN/A
216237SN/A    //
217217SN/A    // Now must unserialize all the ISA dependent state
218217SN/A    //
219217SN/A    isa.unserialize(cpu, cp, section);
220217SN/A}
221217SN/A
222217SN/A#if FULL_SYSTEM
223217SN/Avoid
224217SN/ASimpleThread::dumpFuncProfile()
225217SN/A{
226217SN/A    std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
227217SN/A    profile->dump(tc, *os);
228217SN/A}
229217SN/A#endif
230217SN/A
231217SN/Avoid
232217SN/ASimpleThread::activate(int delay)
233217SN/A{
234217SN/A    if (status() == ThreadContext::Active)
235217SN/A        return;
236217SN/A
237217SN/A    lastActivate = curTick();
238217SN/A
239217SN/A//    if (status() == ThreadContext::Unallocated) {
240217SN/A//      cpu->activateWhenReady(_threadId);
241217SN/A//      return;
242217SN/A//   }
243217SN/A
244217SN/A    _status = ThreadContext::Active;
245217SN/A
246217SN/A    // status() == Suspended
247217SN/A    cpu->activateContext(_threadId, delay);
248217SN/A}
249217SN/A
250217SN/Avoid
251217SN/ASimpleThread::suspend()
252217SN/A{
253217SN/A    if (status() == ThreadContext::Suspended)
254217SN/A        return;
255237SN/A
256237SN/A    lastActivate = curTick();
2574000Ssaidi@eecs.umich.edu    lastSuspend = curTick();
258237SN/A/*
259237SN/A#if FULL_SYSTEM
260237SN/A    // Don't change the status from active if there are pending interrupts
261237SN/A    if (cpu->checkInterrupts()) {
262237SN/A        assert(status() == ThreadContext::Active);
263237SN/A        return;
264237SN/A    }
265221SN/A#endif
266221SN/A*/
267237SN/A    _status = ThreadContext::Suspended;
268221SN/A    cpu->suspendContext(_threadId);
269237SN/A}
270221SN/A
271221SN/A
272221SN/Avoid
273237SN/ASimpleThread::halt()
274221SN/A{
275237SN/A    if (status() == ThreadContext::Halted)
276217SN/A        return;
277217SN/A
2781642SN/A    _status = ThreadContext::Halted;
2791642SN/A    cpu->haltContext(_threadId);
2801642SN/A}
2811642SN/A
2821642SN/A
2831642SN/Avoid
2841642SN/ASimpleThread::regStats(const string &name)
2851642SN/A{
2861642SN/A#if FULL_SYSTEM
2871642SN/A    if (kernelStats)
288219SN/A        kernelStats->regStats(name + ".kern");
289217SN/A#endif
290217SN/A}
291217SN/A
292395SN/Avoid
293395SN/ASimpleThread::copyArchRegs(ThreadContext *src_tc)
294395SN/A{
295395SN/A    TheISA::copyRegs(src_tc, tc);
296395SN/A}
2972SN/A
298395SN/A