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 §ion) 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