base.cc revision 2984:797622d7b311
16899SN/A/* 26899SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 36899SN/A * All rights reserved. 46899SN/A * 56899SN/A * Redistribution and use in source and binary forms, with or without 66899SN/A * modification, are permitted provided that the following conditions are 76899SN/A * met: redistributions of source code must retain the above copyright 86899SN/A * notice, this list of conditions and the following disclaimer; 96899SN/A * redistributions in binary form must reproduce the above copyright 106899SN/A * notice, this list of conditions and the following disclaimer in the 116899SN/A * documentation and/or other materials provided with the distribution; 126899SN/A * neither the name of the copyright holders nor the names of its 136899SN/A * contributors may be used to endorse or promote products derived from 146899SN/A * this software without specific prior written permission. 156899SN/A * 166899SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176899SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186899SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196899SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206899SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216899SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226899SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236899SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246899SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256899SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266899SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276899SN/A * 286899SN/A * Authors: Steve Reinhardt 296899SN/A */ 306899SN/A 3112564Sgabeblack@google.com#include "arch/utility.hh" 3212564Sgabeblack@google.com#include "arch/faults.hh" 336899SN/A#include "base/cprintf.hh" 346899SN/A#include "base/inifile.hh" 356899SN/A#include "base/loader/symtab.hh" 366899SN/A#include "base/misc.hh" 376899SN/A#include "base/pollevent.hh" 3811682Sandreas.hansson@arm.com#include "base/range.hh" 3911670Sandreas.hansson@arm.com#include "base/stats/events.hh" 406899SN/A#include "base/trace.hh" 4111682Sandreas.hansson@arm.com#include "cpu/base.hh" 4211670Sandreas.hansson@arm.com#include "cpu/exetrace.hh" 436899SN/A#include "cpu/profile.hh" 446899SN/A#include "cpu/simple/base.hh" 456899SN/A#include "cpu/simple_thread.hh" 466899SN/A#include "cpu/smt.hh" 476899SN/A#include "cpu/static_inst.hh" 486899SN/A#include "cpu/thread_context.hh" 496899SN/A#include "kern/kernel_stats.hh" 5011688Sandreas.hansson@arm.com#include "mem/packet_impl.hh" 516899SN/A#include "sim/builder.hh" 5210524Snilay@cs.wisc.edu#include "sim/byteswap.hh" 537553SN/A#include "sim/debug.hh" 546899SN/A#include "sim/host.hh" 556899SN/A#include "sim/sim_events.hh" 569365Snilay@cs.wisc.edu#include "sim/sim_object.hh" 579365Snilay@cs.wisc.edu#include "sim/stats.hh" 589365Snilay@cs.wisc.edu#include "sim/system.hh" 599365Snilay@cs.wisc.edu 609365Snilay@cs.wisc.edu#if FULL_SYSTEM 619365Snilay@cs.wisc.edu#include "base/remote_gdb.hh" 626899SN/A#include "arch/tlb.hh" 636899SN/A#include "arch/stacktrace.hh" 647538SN/A#include "arch/vtophys.hh" 656899SN/A#else // !FULL_SYSTEM 667538SN/A#include "mem/mem_object.hh" 676899SN/A#endif // FULL_SYSTEM 686899SN/A 696899SN/Ausing namespace std; 7012564Sgabeblack@google.comusing namespace TheISA; 716899SN/A 726899SN/ABaseSimpleCPU::BaseSimpleCPU(Params *p) 736899SN/A : BaseCPU(p), mem(p->mem), thread(NULL) 747632SBrad.Beckmann@amd.com{ 756899SN/A#if FULL_SYSTEM 767553SN/A thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); 777553SN/A#else 789365Snilay@cs.wisc.edu thread = new SimpleThread(this, /* thread_num */ 0, p->process, 797553SN/A /* asid */ 0, mem); 807553SN/A#endif // !FULL_SYSTEM 819365Snilay@cs.wisc.edu 829365Snilay@cs.wisc.edu thread->setStatus(ThreadContext::Suspended); 839365Snilay@cs.wisc.edu 849365Snilay@cs.wisc.edu tc = thread->getTC(); 857553SN/A 867553SN/A numInst = 0; 877553SN/A startNumInst = 0; 8812564Sgabeblack@google.com numLoad = 0; 897553SN/A startNumLoad = 0; 906899SN/A lastIcacheStall = 0; 9110524Snilay@cs.wisc.edu lastDcacheStall = 0; 9210524Snilay@cs.wisc.edu 939870Sandreas.hansson@arm.com threadContexts.push_back(tc); 949870Sandreas.hansson@arm.com} 959870Sandreas.hansson@arm.com 969870Sandreas.hansson@arm.comBaseSimpleCPU::~BaseSimpleCPU() 979870Sandreas.hansson@arm.com{ 989870Sandreas.hansson@arm.com} 999870Sandreas.hansson@arm.com 1009793Sakash.bagdia@arm.comvoid 1017553SN/ABaseSimpleCPU::deallocateContext(int thread_num) 10210524Snilay@cs.wisc.edu{ 10310524Snilay@cs.wisc.edu // for now, these are equivalent 1047553SN/A suspendContext(thread_num); 10510519Snilay@cs.wisc.edu} 1066899SN/A 1079793Sakash.bagdia@arm.com 1089870Sandreas.hansson@arm.comvoid 1099870Sandreas.hansson@arm.comBaseSimpleCPU::haltContext(int thread_num) 1109793Sakash.bagdia@arm.com{ 11110120Snilay@cs.wisc.edu // for now, these are equivalent 1126899SN/A suspendContext(thread_num); 11310120Snilay@cs.wisc.edu} 1146899SN/A 1156899SN/A 1166899SN/Avoid 11710524Snilay@cs.wisc.eduBaseSimpleCPU::regStats() 1186899SN/A{ 1196899SN/A using namespace Stats; 1206899SN/A 1216899SN/A BaseCPU::regStats(); 1226899SN/A 1238801Sgblack@eecs.umich.edu numInsts 1246899SN/A .name(name() + ".num_insts") 1256899SN/A .desc("Number of instructions executed") 1266899SN/A ; 1276899SN/A 1286899SN/A numMemRefs 1296899SN/A .name(name() + ".num_refs") 1307525SN/A .desc("Number of memory references") 1316899SN/A ; 1326899SN/A 1339909Snilay@cs.wisc.edu notIdleFraction 1346899SN/A .name(name() + ".not_idle_fraction") 13512564Sgabeblack@google.com .desc("Percentage of non-idle cycles") 136 ; 137 138 idleFraction 139 .name(name() + ".idle_fraction") 140 .desc("Percentage of idle cycles") 141 ; 142 143 icacheStallCycles 144 .name(name() + ".icache_stall_cycles") 145 .desc("ICache total stall cycles") 146 .prereq(icacheStallCycles) 147 ; 148 149 dcacheStallCycles 150 .name(name() + ".dcache_stall_cycles") 151 .desc("DCache total stall cycles") 152 .prereq(dcacheStallCycles) 153 ; 154 155 icacheRetryCycles 156 .name(name() + ".icache_retry_cycles") 157 .desc("ICache total retry cycles") 158 .prereq(icacheRetryCycles) 159 ; 160 161 dcacheRetryCycles 162 .name(name() + ".dcache_retry_cycles") 163 .desc("DCache total retry cycles") 164 .prereq(dcacheRetryCycles) 165 ; 166 167 idleFraction = constant(1.0) - notIdleFraction; 168} 169 170void 171BaseSimpleCPU::resetStats() 172{ 173 startNumInst = numInst; 174 // notIdleFraction = (_status != Idle); 175} 176 177void 178BaseSimpleCPU::serialize(ostream &os) 179{ 180 BaseCPU::serialize(os); 181// SERIALIZE_SCALAR(inst); 182 nameOut(os, csprintf("%s.xc.0", name())); 183 thread->serialize(os); 184} 185 186void 187BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 188{ 189 BaseCPU::unserialize(cp, section); 190// UNSERIALIZE_SCALAR(inst); 191 thread->unserialize(cp, csprintf("%s.xc.0", section)); 192} 193 194void 195change_thread_state(int thread_number, int activate, int priority) 196{ 197} 198 199Fault 200BaseSimpleCPU::copySrcTranslate(Addr src) 201{ 202#if 0 203 static bool no_warn = true; 204 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 205 // Only support block sizes of 64 atm. 206 assert(blk_size == 64); 207 int offset = src & (blk_size - 1); 208 209 // Make sure block doesn't span page 210 if (no_warn && 211 (src & PageMask) != ((src + blk_size) & PageMask) && 212 (src >> 40) != 0xfffffc) { 213 warn("Copied block source spans pages %x.", src); 214 no_warn = false; 215 } 216 217 memReq->reset(src & ~(blk_size - 1), blk_size); 218 219 // translate to physical address 220 Fault fault = thread->translateDataReadReq(req); 221 222 if (fault == NoFault) { 223 thread->copySrcAddr = src; 224 thread->copySrcPhysAddr = memReq->paddr + offset; 225 } else { 226 assert(!fault->isAlignmentFault()); 227 228 thread->copySrcAddr = 0; 229 thread->copySrcPhysAddr = 0; 230 } 231 return fault; 232#else 233 return NoFault; 234#endif 235} 236 237Fault 238BaseSimpleCPU::copy(Addr dest) 239{ 240#if 0 241 static bool no_warn = true; 242 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 243 // Only support block sizes of 64 atm. 244 assert(blk_size == 64); 245 uint8_t data[blk_size]; 246 //assert(thread->copySrcAddr); 247 int offset = dest & (blk_size - 1); 248 249 // Make sure block doesn't span page 250 if (no_warn && 251 (dest & PageMask) != ((dest + blk_size) & PageMask) && 252 (dest >> 40) != 0xfffffc) { 253 no_warn = false; 254 warn("Copied block destination spans pages %x. ", dest); 255 } 256 257 memReq->reset(dest & ~(blk_size -1), blk_size); 258 // translate to physical address 259 Fault fault = thread->translateDataWriteReq(req); 260 261 if (fault == NoFault) { 262 Addr dest_addr = memReq->paddr + offset; 263 // Need to read straight from memory since we have more than 8 bytes. 264 memReq->paddr = thread->copySrcPhysAddr; 265 thread->mem->read(memReq, data); 266 memReq->paddr = dest_addr; 267 thread->mem->write(memReq, data); 268 if (dcacheInterface) { 269 memReq->cmd = Copy; 270 memReq->completionEvent = NULL; 271 memReq->paddr = thread->copySrcPhysAddr; 272 memReq->dest = dest_addr; 273 memReq->size = 64; 274 memReq->time = curTick; 275 memReq->flags &= ~INST_READ; 276 dcacheInterface->access(memReq); 277 } 278 } 279 else 280 assert(!fault->isAlignmentFault()); 281 282 return fault; 283#else 284 panic("copy not implemented"); 285 return NoFault; 286#endif 287} 288 289#if FULL_SYSTEM 290Addr 291BaseSimpleCPU::dbg_vtophys(Addr addr) 292{ 293 return vtophys(tc, addr); 294} 295#endif // FULL_SYSTEM 296 297#if FULL_SYSTEM 298void 299BaseSimpleCPU::post_interrupt(int int_num, int index) 300{ 301 BaseCPU::post_interrupt(int_num, index); 302 303 if (thread->status() == ThreadContext::Suspended) { 304 DPRINTF(IPI,"Suspended Processor awoke\n"); 305 thread->activate(); 306 } 307} 308#endif // FULL_SYSTEM 309 310void 311BaseSimpleCPU::checkForInterrupts() 312{ 313#if FULL_SYSTEM 314 if (checkInterrupts && check_interrupts() && !thread->inPalMode()) { 315 int ipl = 0; 316 int summary = 0; 317 checkInterrupts = false; 318 319 if (thread->readMiscReg(IPR_SIRR)) { 320 for (int i = INTLEVEL_SOFTWARE_MIN; 321 i < INTLEVEL_SOFTWARE_MAX; i++) { 322 if (thread->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { 323 // See table 4-19 of 21164 hardware reference 324 ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; 325 summary |= (ULL(1) << i); 326 } 327 } 328 } 329 330 uint64_t interrupts = thread->cpu->intr_status(); 331 for (int i = INTLEVEL_EXTERNAL_MIN; 332 i < INTLEVEL_EXTERNAL_MAX; i++) { 333 if (interrupts & (ULL(1) << i)) { 334 // See table 4-19 of 21164 hardware reference 335 ipl = i; 336 summary |= (ULL(1) << i); 337 } 338 } 339 340 if (thread->readMiscReg(IPR_ASTRR)) 341 panic("asynchronous traps not implemented\n"); 342 343 if (ipl && ipl > thread->readMiscReg(IPR_IPLR)) { 344 thread->setMiscReg(IPR_ISR, summary); 345 thread->setMiscReg(IPR_INTID, ipl); 346 347 Fault(new InterruptFault)->invoke(tc); 348 349 DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", 350 thread->readMiscReg(IPR_IPLR), ipl, summary); 351 } 352 } 353#endif 354} 355 356 357Fault 358BaseSimpleCPU::setupFetchRequest(Request *req) 359{ 360 // set up memory request for instruction fetch 361#if THE_ISA == ALPHA_ISA 362 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p",thread->readPC(), 363 thread->readNextPC()); 364#else 365 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",thread->readPC(), 366 thread->readNextPC(),thread->readNextNPC()); 367#endif 368 369 req->setVirt(0, thread->readPC() & ~3, sizeof(MachInst), 370 (FULL_SYSTEM && (thread->readPC() & 1)) ? PHYSICAL : 0, 371 thread->readPC()); 372 373 Fault fault = thread->translateInstReq(req); 374 375 return fault; 376} 377 378 379void 380BaseSimpleCPU::preExecute() 381{ 382 // maintain $r0 semantics 383 thread->setIntReg(ZeroReg, 0); 384#if THE_ISA == ALPHA_ISA 385 thread->setFloatReg(ZeroReg, 0.0); 386#endif // ALPHA_ISA 387 388 // keep an instruction count 389 numInst++; 390 numInsts++; 391 392 thread->funcExeInst++; 393 394 // check for instruction-count-based events 395 comInstEventQueue[0]->serviceEvents(numInst); 396 397 // decode the instruction 398 inst = gtoh(inst); 399 curStaticInst = StaticInst::decode(makeExtMI(inst, thread->readPC())); 400 401 traceData = Trace::getInstRecord(curTick, tc, this, curStaticInst, 402 thread->readPC()); 403 404 DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n", 405 curStaticInst->getName(), curStaticInst->getOpcode(), 406 curStaticInst->machInst); 407 408#if FULL_SYSTEM 409 thread->setInst(inst); 410#endif // FULL_SYSTEM 411} 412 413void 414BaseSimpleCPU::postExecute() 415{ 416#if FULL_SYSTEM 417 if (thread->profile) { 418 bool usermode = 419 (thread->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; 420 thread->profilePC = usermode ? 1 : thread->readPC(); 421 ProfileNode *node = thread->profile->consume(tc, inst); 422 if (node) 423 thread->profileNode = node; 424 } 425#endif 426 427 if (curStaticInst->isMemRef()) { 428 numMemRefs++; 429 } 430 431 if (curStaticInst->isLoad()) { 432 ++numLoad; 433 comLoadEventQueue[0]->serviceEvents(numLoad); 434 } 435 436 traceFunctions(thread->readPC()); 437 438 if (traceData) { 439 traceData->finalize(); 440 } 441} 442 443 444void 445BaseSimpleCPU::advancePC(Fault fault) 446{ 447 if (fault != NoFault) { 448 fault->invoke(tc); 449 } 450 else { 451 // go to the next instruction 452 thread->setPC(thread->readNextPC()); 453#if THE_ISA == ALPHA_ISA 454 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 455#else 456 thread->setNextPC(thread->readNextNPC()); 457 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 458 assert(thread->readNextPC() != thread->readNextNPC()); 459#endif 460 461 } 462 463#if FULL_SYSTEM 464 Addr oldpc; 465 do { 466 oldpc = thread->readPC(); 467 system->pcEventQueue.service(tc); 468 } while (oldpc != thread->readPC()); 469#endif 470} 471 472