simple_thread.cc revision 5606:6da7a58b0bc8
17949SN/A/*
212230Sgiacomo.travaglini@arm.com * Copyright (c) 2001-2006 The Regents of The University of Michigan
37949SN/A * All rights reserved.
47949SN/A *
57949SN/A * Redistribution and use in source and binary forms, with or without
67949SN/A * modification, are permitted provided that the following conditions are
77949SN/A * met: redistributions of source code must retain the above copyright
87949SN/A * notice, this list of conditions and the following disclaimer;
97949SN/A * redistributions in binary form must reproduce the above copyright
107949SN/A * notice, this list of conditions and the following disclaimer in the
117949SN/A * documentation and/or other materials provided with the distribution;
127949SN/A * neither the name of the copyright holders nor the names of its
137949SN/A * contributors may be used to endorse or promote products derived from
147949SN/A * this software without specific prior written permission.
157949SN/A *
167949SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177949SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187949SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197949SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207949SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217949SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227949SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237949SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247949SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257949SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267949SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277949SN/A *
287949SN/A * Authors: Steve Reinhardt
297949SN/A *          Nathan Binkert
307949SN/A *          Lisa Hsu
317949SN/A *          Kevin Lim
327949SN/A */
337949SN/A
347949SN/A#include <string>
357949SN/A
367949SN/A#include "arch/isa_traits.hh"
377949SN/A#include "cpu/base.hh"
387949SN/A#include "cpu/simple_thread.hh"
397949SN/A#include "cpu/thread_context.hh"
407949SN/A#include "params/BaseCPU.hh"
417949SN/A
429330Schander.sudanthi@arm.com#if FULL_SYSTEM
437949SN/A#include "arch/kernel_stats.hh"
447949SN/A#include "arch/stacktrace.hh"
4511793Sbrandon.potter@amd.com#include "base/callback.hh"
4611793Sbrandon.potter@amd.com#include "base/cprintf.hh"
478635SN/A#include "base/output.hh"
487949SN/A#include "base/trace.hh"
4912334Sgabeblack@google.com#include "cpu/profile.hh"
5011800Sbrandon.potter@amd.com#include "cpu/quiesce_event.hh"
5112230Sgiacomo.travaglini@arm.com#include "sim/serialize.hh"
529356Snilay@cs.wisc.edu#include "sim/sim_exit.hh"
538232SN/A#else
547949SN/A#include "mem/translating_port.hh"
557949SN/A#include "sim/process.hh"
567949SN/A#include "sim/system.hh"
579330Schander.sudanthi@arm.com#endif
589330Schander.sudanthi@arm.com
5910839Sandreas.sandberg@arm.comusing namespace std;
6010839Sandreas.sandberg@arm.com
6110839Sandreas.sandberg@arm.com// constructor
6212230Sgiacomo.travaglini@arm.com#if FULL_SYSTEM
6312230Sgiacomo.travaglini@arm.comSimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
647949SN/A                           TheISA::ITB *_itb, TheISA::DTB *_dtb,
658635SN/A                           bool use_kernel_stats)
668635SN/A    : ThreadState(_cpu, -1, _thread_num), cpu(_cpu), system(_sys), itb(_itb),
678635SN/A      dtb(_dtb)
688635SN/A
698635SN/A{
708635SN/A    tc = new ProxyThreadContext<SimpleThread>(this);
718635SN/A
728635SN/A    quiesceEvent = new EndQuiesceEvent(tc);
737949SN/A
747949SN/A    regs.clear();
757949SN/A
7610839Sandreas.sandberg@arm.com    if (cpu->params()->profile) {
777949SN/A        profile = new FunctionProfile(system->kernelSymtab);
7810839Sandreas.sandberg@arm.com        Callback *cb =
7910839Sandreas.sandberg@arm.com            new MakeCallback<SimpleThread,
807949SN/A            &SimpleThread::dumpFuncProfile>(this);
8110839Sandreas.sandberg@arm.com        registerExitCallback(cb);
8210839Sandreas.sandberg@arm.com    }
8312230Sgiacomo.travaglini@arm.com
8412230Sgiacomo.travaglini@arm.com    // let's fill with a dummy node for now so we don't get a segfault
8512230Sgiacomo.travaglini@arm.com    // on the first cycle when there's no node available.
8612230Sgiacomo.travaglini@arm.com    static ProfileNode dummyNode;
8712230Sgiacomo.travaglini@arm.com    profileNode = &dummyNode;
8810839Sandreas.sandberg@arm.com    profilePC = 3;
8910839Sandreas.sandberg@arm.com
9010839Sandreas.sandberg@arm.com    if (use_kernel_stats)
9110839Sandreas.sandberg@arm.com        kernelStats = new TheISA::Kernel::Statistics(system);
9210839Sandreas.sandberg@arm.com}
9310839Sandreas.sandberg@arm.com#else
9410839Sandreas.sandberg@arm.comSimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process,
9510839Sandreas.sandberg@arm.com                           TheISA::ITB *_itb, TheISA::DTB *_dtb, int _asid)
9610839Sandreas.sandberg@arm.com    : ThreadState(_cpu, -1, _thread_num, _process, _asid),
9710839Sandreas.sandberg@arm.com      cpu(_cpu), itb(_itb), dtb(_dtb)
9810839Sandreas.sandberg@arm.com{
9910839Sandreas.sandberg@arm.com    regs.clear();
10010839Sandreas.sandberg@arm.com    tc = new ProxyThreadContext<SimpleThread>(this);
10110839Sandreas.sandberg@arm.com}
10210839Sandreas.sandberg@arm.com
10310839Sandreas.sandberg@arm.com#endif
1047949SN/A
1057949SN/ASimpleThread::SimpleThread()
1067949SN/A#if FULL_SYSTEM
10710839Sandreas.sandberg@arm.com    : ThreadState(NULL, -1, -1)
10810839Sandreas.sandberg@arm.com#else
1097949SN/A    : ThreadState(NULL, -1, -1, NULL, -1)
11010839Sandreas.sandberg@arm.com#endif
11110839Sandreas.sandberg@arm.com{
1127949SN/A    tc = new ProxyThreadContext<SimpleThread>(this);
1137949SN/A    regs.clear();
1148635SN/A}
1159330Schander.sudanthi@arm.com
1168635SN/ASimpleThread::~SimpleThread()
11712230Sgiacomo.travaglini@arm.com{
1188635SN/A#if FULL_SYSTEM
1198635SN/A    delete physPort;
12010839Sandreas.sandberg@arm.com    delete virtPort;
1218635SN/A#endif
1228635SN/A    delete tc;
1238635SN/A}
1248635SN/A
1258635SN/Avoid
1268635SN/ASimpleThread::takeOverFrom(ThreadContext *oldContext)
12712230Sgiacomo.travaglini@arm.com{
12812230Sgiacomo.travaglini@arm.com    // some things should already be set up
12912230Sgiacomo.travaglini@arm.com#if FULL_SYSTEM
1308635SN/A    assert(system == oldContext->getSystemPtr());
1318635SN/A#else
1328635SN/A    assert(process == oldContext->getProcessPtr());
13311359Sandreas@sandberg.pp.se#endif
13412230Sgiacomo.travaglini@arm.com
13511359Sandreas@sandberg.pp.se    copyState(oldContext);
1368635SN/A#if FULL_SYSTEM
1378635SN/A    EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
1388635SN/A    if (quiesce) {
1399330Schander.sudanthi@arm.com        // Point the quiesce event's TC at this TC so that it wakes up
1409330Schander.sudanthi@arm.com        // the proper CPU.
1419330Schander.sudanthi@arm.com        quiesce->tc = tc;
1429330Schander.sudanthi@arm.com    }
1439330Schander.sudanthi@arm.com    if (quiesceEvent) {
1449330Schander.sudanthi@arm.com        quiesceEvent->tc = tc;
1459330Schander.sudanthi@arm.com    }
146
147    TheISA::Kernel::Statistics *stats = oldContext->getKernelStats();
148    if (stats) {
149        kernelStats = stats;
150    }
151#endif
152
153    storeCondFailures = 0;
154
155    oldContext->setStatus(ThreadContext::Unallocated);
156}
157
158void
159SimpleThread::copyTC(ThreadContext *context)
160{
161    copyState(context);
162
163#if FULL_SYSTEM
164    EndQuiesceEvent *quiesce = context->getQuiesceEvent();
165    if (quiesce) {
166        quiesceEvent = quiesce;
167    }
168    TheISA::Kernel::Statistics *stats = context->getKernelStats();
169    if (stats) {
170        kernelStats = stats;
171    }
172#endif
173}
174
175void
176SimpleThread::copyState(ThreadContext *oldContext)
177{
178    // copy over functional state
179    _status = oldContext->status();
180    copyArchRegs(oldContext);
181    cpuId = oldContext->readCpuId();
182#if !FULL_SYSTEM
183    funcExeInst = oldContext->readFuncExeInst();
184#endif
185    inst = oldContext->getInst();
186}
187
188void
189SimpleThread::serialize(ostream &os)
190{
191    ThreadState::serialize(os);
192    regs.serialize(cpu, os);
193    // thread_num and cpu_id are deterministic from the config
194}
195
196
197void
198SimpleThread::unserialize(Checkpoint *cp, const std::string &section)
199{
200    ThreadState::unserialize(cp, section);
201    regs.unserialize(cpu, cp, section);
202    // thread_num and cpu_id are deterministic from the config
203}
204
205#if FULL_SYSTEM
206void
207SimpleThread::dumpFuncProfile()
208{
209    std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
210    profile->dump(tc, *os);
211}
212#endif
213
214void
215SimpleThread::activate(int delay)
216{
217    if (status() == ThreadContext::Active)
218        return;
219
220    lastActivate = curTick;
221
222//    if (status() == ThreadContext::Unallocated) {
223//      cpu->activateWhenReady(tid);
224//      return;
225//   }
226
227    _status = ThreadContext::Active;
228
229    // status() == Suspended
230    cpu->activateContext(tid, delay);
231}
232
233void
234SimpleThread::suspend()
235{
236    if (status() == ThreadContext::Suspended)
237        return;
238
239    lastActivate = curTick;
240    lastSuspend = curTick;
241/*
242#if FULL_SYSTEM
243    // Don't change the status from active if there are pending interrupts
244    if (cpu->check_interrupts()) {
245        assert(status() == ThreadContext::Active);
246        return;
247    }
248#endif
249*/
250    _status = ThreadContext::Suspended;
251    cpu->suspendContext(tid);
252}
253
254void
255SimpleThread::deallocate()
256{
257    if (status() == ThreadContext::Unallocated)
258        return;
259
260    _status = ThreadContext::Unallocated;
261    cpu->deallocateContext(tid);
262}
263
264void
265SimpleThread::halt()
266{
267    if (status() == ThreadContext::Halted)
268        return;
269
270    _status = ThreadContext::Halted;
271    cpu->haltContext(tid);
272}
273
274
275void
276SimpleThread::regStats(const string &name)
277{
278#if FULL_SYSTEM
279    if (kernelStats)
280        kernelStats->regStats(name + ".kern");
281#endif
282}
283
284void
285SimpleThread::copyArchRegs(ThreadContext *src_tc)
286{
287    TheISA::copyRegs(src_tc, tc);
288}
289
290