simple_thread.cc revision 2188
112771Sqtt2@cornell.edu/* 212771Sqtt2@cornell.edu * Copyright (c) 2001-2006 The Regents of The University of Michigan 312771Sqtt2@cornell.edu * All rights reserved. 412771Sqtt2@cornell.edu * 512771Sqtt2@cornell.edu * Redistribution and use in source and binary forms, with or without 612771Sqtt2@cornell.edu * modification, are permitted provided that the following conditions are 712771Sqtt2@cornell.edu * met: redistributions of source code must retain the above copyright 812771Sqtt2@cornell.edu * notice, this list of conditions and the following disclaimer; 912771Sqtt2@cornell.edu * redistributions in binary form must reproduce the above copyright 1012771Sqtt2@cornell.edu * notice, this list of conditions and the following disclaimer in the 1112771Sqtt2@cornell.edu * documentation and/or other materials provided with the distribution; 1212771Sqtt2@cornell.edu * neither the name of the copyright holders nor the names of its 1312771Sqtt2@cornell.edu * contributors may be used to endorse or promote products derived from 1412771Sqtt2@cornell.edu * this software without specific prior written permission. 1512771Sqtt2@cornell.edu * 1612771Sqtt2@cornell.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712771Sqtt2@cornell.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812771Sqtt2@cornell.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912771Sqtt2@cornell.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012771Sqtt2@cornell.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112771Sqtt2@cornell.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212771Sqtt2@cornell.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312771Sqtt2@cornell.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412771Sqtt2@cornell.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512771Sqtt2@cornell.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612771Sqtt2@cornell.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712771Sqtt2@cornell.edu */ 2812771Sqtt2@cornell.edu 2912771Sqtt2@cornell.edu#include <string> 3012771Sqtt2@cornell.edu 3112771Sqtt2@cornell.edu#include "cpu/base.hh" 3212771Sqtt2@cornell.edu#include "cpu/exec_context.hh" 3312771Sqtt2@cornell.edu 3412771Sqtt2@cornell.edu#if FULL_SYSTEM 3512771Sqtt2@cornell.edu#include "base/callback.hh" 3612771Sqtt2@cornell.edu#include "base/cprintf.hh" 3712771Sqtt2@cornell.edu#include "base/output.hh" 3812771Sqtt2@cornell.edu#include "base/trace.hh" 3912771Sqtt2@cornell.edu#include "cpu/profile.hh" 4012771Sqtt2@cornell.edu#include "kern/kernel_stats.hh" 4112771Sqtt2@cornell.edu#include "sim/serialize.hh" 4212771Sqtt2@cornell.edu#include "sim/sim_exit.hh" 4312771Sqtt2@cornell.edu#include "sim/system.hh" 4412771Sqtt2@cornell.edu#include "targetarch/stacktrace.hh" 4512771Sqtt2@cornell.edu#else 4612771Sqtt2@cornell.edu#include "sim/process.hh" 4712771Sqtt2@cornell.edu#endif 4812771Sqtt2@cornell.edu 4912771Sqtt2@cornell.eduusing namespace std; 5012771Sqtt2@cornell.edu 5112771Sqtt2@cornell.edu// constructor 5212771Sqtt2@cornell.edu#if FULL_SYSTEM 5312771Sqtt2@cornell.eduExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, 5412771Sqtt2@cornell.edu AlphaITB *_itb, AlphaDTB *_dtb, 5512771Sqtt2@cornell.edu FunctionalMemory *_mem) 5612771Sqtt2@cornell.edu : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), 5712771Sqtt2@cornell.edu cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb), 5812771Sqtt2@cornell.edu dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem), 5912771Sqtt2@cornell.edu kernelBinning(system->kernelBinning), bin(kernelBinning->bin), 6012771Sqtt2@cornell.edu fnbin(kernelBinning->fnbin), profile(NULL), quiesceEvent(this), 6112771Sqtt2@cornell.edu func_exe_inst(0), storeCondFailures(0) 6212771Sqtt2@cornell.edu{ 6312771Sqtt2@cornell.edu kernelStats = new Kernel::Statistics(this); 6412771Sqtt2@cornell.edu memset(®s, 0, sizeof(RegFile)); 6512771Sqtt2@cornell.edu 6612771Sqtt2@cornell.edu if (cpu->params->profile) { 6712771Sqtt2@cornell.edu profile = new FunctionProfile(system->kernelSymtab); 6812771Sqtt2@cornell.edu Callback *cb = 6912771Sqtt2@cornell.edu new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this); 7012771Sqtt2@cornell.edu registerExitCallback(cb); 7112771Sqtt2@cornell.edu } 7212771Sqtt2@cornell.edu 7312771Sqtt2@cornell.edu // let's fill with a dummy node for now so we don't get a segfault 7412771Sqtt2@cornell.edu // on the first cycle when there's no node available. 7512771Sqtt2@cornell.edu static ProfileNode dummyNode; 7612771Sqtt2@cornell.edu profileNode = &dummyNode; 7712771Sqtt2@cornell.edu profilePC = 3; 7812771Sqtt2@cornell.edu} 7912771Sqtt2@cornell.edu#else 8012771Sqtt2@cornell.eduExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, 8112771Sqtt2@cornell.edu Process *_process, int _asid) 8212771Sqtt2@cornell.edu : _status(ExecContext::Unallocated), 8312771Sqtt2@cornell.edu cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), 8412771Sqtt2@cornell.edu lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid), 8512771Sqtt2@cornell.edu func_exe_inst(0), storeCondFailures(0) 8612771Sqtt2@cornell.edu{ 8712771Sqtt2@cornell.edu memset(®s, 0, sizeof(RegFile)); 8812771Sqtt2@cornell.edu} 8912771Sqtt2@cornell.edu 9012771Sqtt2@cornell.eduExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, 9112771Sqtt2@cornell.edu FunctionalMemory *_mem, int _asid) 9212771Sqtt2@cornell.edu : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid), 93 func_exe_inst(0), storeCondFailures(0) 94{ 95 memset(®s, 0, sizeof(RegFile)); 96} 97#endif 98 99ExecContext::~ExecContext() 100{ 101#if FULL_SYSTEM 102 delete kernelStats; 103#endif 104} 105 106#if FULL_SYSTEM 107void 108ExecContext::dumpFuncProfile() 109{ 110 std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 111 profile->dump(this, *os); 112} 113 114ExecContext::EndQuiesceEvent::EndQuiesceEvent(ExecContext *_xc) 115 : Event(&mainEventQueue), xc(_xc) 116{ 117} 118 119void 120ExecContext::EndQuiesceEvent::process() 121{ 122 xc->activate(); 123} 124 125const char* 126ExecContext::EndQuiesceEvent::description() 127{ 128 return "End Quiesce Event."; 129} 130#endif 131 132void 133ExecContext::takeOverFrom(ExecContext *oldContext) 134{ 135 // some things should already be set up 136 assert(mem == oldContext->mem); 137#if FULL_SYSTEM 138 assert(system == oldContext->system); 139#else 140 assert(process == oldContext->process); 141#endif 142 143 // copy over functional state 144 _status = oldContext->_status; 145 regs = oldContext->regs; 146 cpu_id = oldContext->cpu_id; 147 func_exe_inst = oldContext->func_exe_inst; 148 149 storeCondFailures = 0; 150 151 oldContext->_status = ExecContext::Unallocated; 152} 153 154void 155ExecContext::serialize(ostream &os) 156{ 157 SERIALIZE_ENUM(_status); 158 regs.serialize(os); 159 // thread_num and cpu_id are deterministic from the config 160 SERIALIZE_SCALAR(func_exe_inst); 161 SERIALIZE_SCALAR(inst); 162 163#if FULL_SYSTEM 164 Tick quiesceEndTick = 0; 165 if (quiesceEvent.scheduled()) 166 quiesceEndTick = quiesceEvent.when(); 167 SERIALIZE_SCALAR(quiesceEndTick); 168 kernelStats->serialize(os); 169 170#endif 171} 172 173 174void 175ExecContext::unserialize(Checkpoint *cp, const std::string §ion) 176{ 177 UNSERIALIZE_ENUM(_status); 178 regs.unserialize(cp, section); 179 // thread_num and cpu_id are deterministic from the config 180 UNSERIALIZE_SCALAR(func_exe_inst); 181 UNSERIALIZE_SCALAR(inst); 182 183#if FULL_SYSTEM 184 Tick quiesceEndTick; 185 UNSERIALIZE_SCALAR(quiesceEndTick); 186 if (quiesceEndTick) 187 quiesceEvent.schedule(quiesceEndTick); 188 189 kernelStats->unserialize(cp, section); 190#endif 191} 192 193 194void 195ExecContext::activate(int delay) 196{ 197 if (status() == Active) 198 return; 199 200 lastActivate = curTick; 201 202 _status = Active; 203 cpu->activateContext(thread_num, delay); 204} 205 206void 207ExecContext::suspend() 208{ 209 if (status() == Suspended) 210 return; 211 212 lastActivate = curTick; 213 lastSuspend = curTick; 214/* 215#if FULL_SYSTEM 216 // Don't change the status from active if there are pending interrupts 217 if (cpu->check_interrupts()) { 218 assert(status() == Active); 219 return; 220 } 221#endif 222*/ 223 _status = Suspended; 224 cpu->suspendContext(thread_num); 225} 226 227void 228ExecContext::deallocate() 229{ 230 if (status() == Unallocated) 231 return; 232 233 _status = Unallocated; 234 cpu->deallocateContext(thread_num); 235} 236 237void 238ExecContext::halt() 239{ 240 if (status() == Halted) 241 return; 242 243 _status = Halted; 244 cpu->haltContext(thread_num); 245} 246 247 248void 249ExecContext::regStats(const string &name) 250{ 251#if FULL_SYSTEM 252 kernelStats->regStats(name + ".kern"); 253#endif 254} 255 256void 257ExecContext::trap(Fault fault) 258{ 259 //TheISA::trap(fault); //One possible way to do it... 260 261 /** @todo: Going to hack it for now. Do a true fixup later. */ 262#if FULL_SYSTEM 263 ev5_trap(fault); 264#else 265 fatal("fault (%d) detected @ PC 0x%08p", fault, readPC()); 266#endif 267} 268