base.cc revision 5250:42577371ff31
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Steve Reinhardt 29 */ 30 31#include "arch/utility.hh" 32#include "arch/faults.hh" 33#include "base/cprintf.hh" 34#include "base/inifile.hh" 35#include "base/loader/symtab.hh" 36#include "base/misc.hh" 37#include "base/pollevent.hh" 38#include "base/range.hh" 39#include "base/stats/events.hh" 40#include "base/trace.hh" 41#include "cpu/base.hh" 42#include "cpu/exetrace.hh" 43#include "cpu/profile.hh" 44#include "cpu/simple/base.hh" 45#include "cpu/simple_thread.hh" 46#include "cpu/smt.hh" 47#include "cpu/static_inst.hh" 48#include "cpu/thread_context.hh" 49#include "mem/packet.hh" 50#include "sim/byteswap.hh" 51#include "sim/debug.hh" 52#include "sim/host.hh" 53#include "sim/sim_events.hh" 54#include "sim/sim_object.hh" 55#include "sim/stats.hh" 56#include "sim/system.hh" 57 58#if FULL_SYSTEM 59#include "arch/kernel_stats.hh" 60#include "arch/stacktrace.hh" 61#include "arch/tlb.hh" 62#include "arch/vtophys.hh" 63#include "base/remote_gdb.hh" 64#else // !FULL_SYSTEM 65#include "mem/mem_object.hh" 66#endif // FULL_SYSTEM 67 68using namespace std; 69using namespace TheISA; 70 71BaseSimpleCPU::BaseSimpleCPU(Params *p) 72 : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL) 73{ 74#if FULL_SYSTEM 75 thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); 76#else 77 thread = new SimpleThread(this, /* thread_num */ 0, p->process, 78 p->itb, p->dtb, /* asid */ 0); 79#endif // !FULL_SYSTEM 80 81 thread->setStatus(ThreadContext::Unallocated); 82 83 tc = thread->getTC(); 84 85 numInst = 0; 86 startNumInst = 0; 87 numLoad = 0; 88 startNumLoad = 0; 89 lastIcacheStall = 0; 90 lastDcacheStall = 0; 91 92 threadContexts.push_back(tc); 93 94 cpuId = tc->readCpuId(); 95 96 fetchOffset = 0; 97 stayAtPC = false; 98} 99 100BaseSimpleCPU::~BaseSimpleCPU() 101{ 102} 103 104void 105BaseSimpleCPU::deallocateContext(int thread_num) 106{ 107 // for now, these are equivalent 108 suspendContext(thread_num); 109} 110 111 112void 113BaseSimpleCPU::haltContext(int thread_num) 114{ 115 // for now, these are equivalent 116 suspendContext(thread_num); 117} 118 119 120void 121BaseSimpleCPU::regStats() 122{ 123 using namespace Stats; 124 125 BaseCPU::regStats(); 126 127 numInsts 128 .name(name() + ".num_insts") 129 .desc("Number of instructions executed") 130 ; 131 132 numMemRefs 133 .name(name() + ".num_refs") 134 .desc("Number of memory references") 135 ; 136 137 notIdleFraction 138 .name(name() + ".not_idle_fraction") 139 .desc("Percentage of non-idle cycles") 140 ; 141 142 idleFraction 143 .name(name() + ".idle_fraction") 144 .desc("Percentage of idle cycles") 145 ; 146 147 icacheStallCycles 148 .name(name() + ".icache_stall_cycles") 149 .desc("ICache total stall cycles") 150 .prereq(icacheStallCycles) 151 ; 152 153 dcacheStallCycles 154 .name(name() + ".dcache_stall_cycles") 155 .desc("DCache total stall cycles") 156 .prereq(dcacheStallCycles) 157 ; 158 159 icacheRetryCycles 160 .name(name() + ".icache_retry_cycles") 161 .desc("ICache total retry cycles") 162 .prereq(icacheRetryCycles) 163 ; 164 165 dcacheRetryCycles 166 .name(name() + ".dcache_retry_cycles") 167 .desc("DCache total retry cycles") 168 .prereq(dcacheRetryCycles) 169 ; 170 171 idleFraction = constant(1.0) - notIdleFraction; 172} 173 174void 175BaseSimpleCPU::resetStats() 176{ 177// startNumInst = numInst; 178 // notIdleFraction = (_status != Idle); 179} 180 181void 182BaseSimpleCPU::serialize(ostream &os) 183{ 184 BaseCPU::serialize(os); 185// SERIALIZE_SCALAR(inst); 186 nameOut(os, csprintf("%s.xc.0", name())); 187 thread->serialize(os); 188} 189 190void 191BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 192{ 193 BaseCPU::unserialize(cp, section); 194// UNSERIALIZE_SCALAR(inst); 195 thread->unserialize(cp, csprintf("%s.xc.0", section)); 196} 197 198void 199change_thread_state(int thread_number, int activate, int priority) 200{ 201} 202 203Fault 204BaseSimpleCPU::copySrcTranslate(Addr src) 205{ 206#if 0 207 static bool no_warn = true; 208 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 209 // Only support block sizes of 64 atm. 210 assert(blk_size == 64); 211 int offset = src & (blk_size - 1); 212 213 // Make sure block doesn't span page 214 if (no_warn && 215 (src & PageMask) != ((src + blk_size) & PageMask) && 216 (src >> 40) != 0xfffffc) { 217 warn("Copied block source spans pages %x.", src); 218 no_warn = false; 219 } 220 221 memReq->reset(src & ~(blk_size - 1), blk_size); 222 223 // translate to physical address 224 Fault fault = thread->translateDataReadReq(req); 225 226 if (fault == NoFault) { 227 thread->copySrcAddr = src; 228 thread->copySrcPhysAddr = memReq->paddr + offset; 229 } else { 230 assert(!fault->isAlignmentFault()); 231 232 thread->copySrcAddr = 0; 233 thread->copySrcPhysAddr = 0; 234 } 235 return fault; 236#else 237 return NoFault; 238#endif 239} 240 241Fault 242BaseSimpleCPU::copy(Addr dest) 243{ 244#if 0 245 static bool no_warn = true; 246 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 247 // Only support block sizes of 64 atm. 248 assert(blk_size == 64); 249 uint8_t data[blk_size]; 250 //assert(thread->copySrcAddr); 251 int offset = dest & (blk_size - 1); 252 253 // Make sure block doesn't span page 254 if (no_warn && 255 (dest & PageMask) != ((dest + blk_size) & PageMask) && 256 (dest >> 40) != 0xfffffc) { 257 no_warn = false; 258 warn("Copied block destination spans pages %x. ", dest); 259 } 260 261 memReq->reset(dest & ~(blk_size -1), blk_size); 262 // translate to physical address 263 Fault fault = thread->translateDataWriteReq(req); 264 265 if (fault == NoFault) { 266 Addr dest_addr = memReq->paddr + offset; 267 // Need to read straight from memory since we have more than 8 bytes. 268 memReq->paddr = thread->copySrcPhysAddr; 269 thread->mem->read(memReq, data); 270 memReq->paddr = dest_addr; 271 thread->mem->write(memReq, data); 272 if (dcacheInterface) { 273 memReq->cmd = Copy; 274 memReq->completionEvent = NULL; 275 memReq->paddr = thread->copySrcPhysAddr; 276 memReq->dest = dest_addr; 277 memReq->size = 64; 278 memReq->time = curTick; 279 memReq->flags &= ~INST_READ; 280 dcacheInterface->access(memReq); 281 } 282 } 283 else 284 assert(!fault->isAlignmentFault()); 285 286 return fault; 287#else 288 panic("copy not implemented"); 289 return NoFault; 290#endif 291} 292 293#if FULL_SYSTEM 294Addr 295BaseSimpleCPU::dbg_vtophys(Addr addr) 296{ 297 return vtophys(tc, addr); 298} 299#endif // FULL_SYSTEM 300 301#if FULL_SYSTEM 302void 303BaseSimpleCPU::post_interrupt(int int_num, int index) 304{ 305 BaseCPU::post_interrupt(int_num, index); 306 307 if (thread->status() == ThreadContext::Suspended) { 308 DPRINTF(Quiesce,"Suspended Processor awoke\n"); 309 thread->activate(); 310 } 311} 312#endif // FULL_SYSTEM 313 314void 315BaseSimpleCPU::checkForInterrupts() 316{ 317#if FULL_SYSTEM 318 if (check_interrupts(tc)) { 319 Fault interrupt = interrupts.getInterrupt(tc); 320 321 if (interrupt != NoFault) { 322 interrupts.updateIntrInfo(tc); 323 interrupt->invoke(tc); 324 } 325 } 326#endif 327} 328 329 330Fault 331BaseSimpleCPU::setupFetchRequest(Request *req) 332{ 333 Addr threadPC = thread->readPC(); 334 335 // set up memory request for instruction fetch 336#if ISA_HAS_DELAY_SLOT 337 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC, 338 thread->readNextPC(),thread->readNextNPC()); 339#else 340 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC, 341 thread->readNextPC()); 342#endif 343 344 Addr fetchPC = (threadPC & PCMask) + fetchOffset; 345 req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC); 346 347 Fault fault = thread->translateInstReq(req); 348 349 return fault; 350} 351 352 353void 354BaseSimpleCPU::preExecute() 355{ 356 // maintain $r0 semantics 357 thread->setIntReg(ZeroReg, 0); 358#if THE_ISA == ALPHA_ISA 359 thread->setFloatReg(ZeroReg, 0.0); 360#endif // ALPHA_ISA 361 362 // check for instruction-count-based events 363 comInstEventQueue[0]->serviceEvents(numInst); 364 365 // decode the instruction 366 inst = gtoh(inst); 367 368 //If we're not in the middle of a macro instruction 369 if (!curMacroStaticInst) { 370 371 StaticInstPtr instPtr = NULL; 372 373 //Predecode, ie bundle up an ExtMachInst 374 //This should go away once the constructor can be set up properly 375 predecoder.setTC(thread->getTC()); 376 //If more fetch data is needed, pass it in. 377 Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset; 378 //if(predecoder.needMoreBytes()) 379 predecoder.moreBytes(thread->readPC(), fetchPC, inst); 380 //else 381 // predecoder.process(); 382 383 //If an instruction is ready, decode it. Otherwise, we'll have to 384 //fetch beyond the MachInst at the current pc. 385 if (predecoder.extMachInstReady()) { 386#if THE_ISA == X86_ISA 387 thread->setNextPC(thread->readPC() + predecoder.getInstSize()); 388#endif // X86_ISA 389 stayAtPC = false; 390 instPtr = StaticInst::decode(predecoder.getExtMachInst(), 391 thread->readPC()); 392 } else { 393 stayAtPC = true; 394 fetchOffset += sizeof(MachInst); 395 } 396 397 //If we decoded an instruction and it's microcoded, start pulling 398 //out micro ops 399 if (instPtr && instPtr->isMacroop()) { 400 curMacroStaticInst = instPtr; 401 curStaticInst = curMacroStaticInst-> 402 fetchMicroop(thread->readMicroPC()); 403 } else { 404 curStaticInst = instPtr; 405 } 406 } else { 407 //Read the next micro op from the macro op 408 curStaticInst = curMacroStaticInst-> 409 fetchMicroop(thread->readMicroPC()); 410 } 411 412 //If we decoded an instruction this "tick", record information about it. 413 if(curStaticInst) 414 { 415#if TRACING_ON 416 traceData = tracer->getInstRecord(curTick, tc, curStaticInst, 417 thread->readPC()); 418 419 DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", 420 curStaticInst->getName(), curStaticInst->machInst); 421#endif // TRACING_ON 422 423#if FULL_SYSTEM 424 thread->setInst(inst); 425#endif // FULL_SYSTEM 426 } 427} 428 429void 430BaseSimpleCPU::postExecute() 431{ 432#if FULL_SYSTEM 433 if (thread->profile && curStaticInst) { 434 bool usermode = TheISA::inUserMode(tc); 435 thread->profilePC = usermode ? 1 : thread->readPC(); 436 ProfileNode *node = thread->profile->consume(tc, curStaticInst); 437 if (node) 438 thread->profileNode = node; 439 } 440#endif 441 442 if (curStaticInst->isMemRef()) { 443 numMemRefs++; 444 } 445 446 if (curStaticInst->isLoad()) { 447 ++numLoad; 448 comLoadEventQueue[0]->serviceEvents(numLoad); 449 } 450 451 traceFunctions(thread->readPC()); 452 453 if (traceData) { 454 traceData->dump(); 455 delete traceData; 456 traceData = NULL; 457 } 458} 459 460 461void 462BaseSimpleCPU::advancePC(Fault fault) 463{ 464 //Since we're moving to a new pc, zero out the offset 465 fetchOffset = 0; 466 if (fault != NoFault) { 467 curMacroStaticInst = StaticInst::nullStaticInstPtr; 468 predecoder.reset(); 469 fault->invoke(tc); 470 thread->setMicroPC(0); 471 thread->setNextMicroPC(1); 472 } else { 473 //If we're at the last micro op for this instruction 474 if (curStaticInst && curStaticInst->isLastMicroop()) { 475 //We should be working with a macro op 476 assert(curMacroStaticInst); 477 //Close out this macro op, and clean up the 478 //microcode state 479 curMacroStaticInst = StaticInst::nullStaticInstPtr; 480 thread->setMicroPC(0); 481 thread->setNextMicroPC(1); 482 } 483 //If we're still in a macro op 484 if (curMacroStaticInst) { 485 //Advance the micro pc 486 thread->setMicroPC(thread->readNextMicroPC()); 487 //Advance the "next" micro pc. Note that there are no delay 488 //slots, and micro ops are "word" addressed. 489 thread->setNextMicroPC(thread->readNextMicroPC() + 1); 490 } else { 491 // go to the next instruction 492 thread->setPC(thread->readNextPC()); 493 thread->setNextPC(thread->readNextNPC()); 494 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 495 assert(thread->readNextPC() != thread->readNextNPC()); 496 } 497 } 498 499 Addr oldpc; 500 do { 501 oldpc = thread->readPC(); 502 system->pcEventQueue.service(tc); 503 } while (oldpc != thread->readPC()); 504} 505 506/*Fault 507BaseSimpleCPU::CacheOp(uint8_t Op, Addr EffAddr) 508{ 509 // translate to physical address 510 Fault fault = NoFault; 511 int CacheID = Op & 0x3; // Lower 3 bits identify Cache 512 int CacheOP = Op >> 2; // Upper 3 bits identify Cache Operation 513 if(CacheID > 1) 514 { 515 warn("CacheOps not implemented for secondary/tertiary caches\n"); 516 } 517 else 518 { 519 switch(CacheOP) 520 { // Fill Packet Type 521 case 0: warn("Invalidate Cache Op\n"); 522 break; 523 case 1: warn("Index Load Tag Cache Op\n"); 524 break; 525 case 2: warn("Index Store Tag Cache Op\n"); 526 break; 527 case 4: warn("Hit Invalidate Cache Op\n"); 528 break; 529 case 5: warn("Fill/Hit Writeback Invalidate Cache Op\n"); 530 break; 531 case 6: warn("Hit Writeback\n"); 532 break; 533 case 7: warn("Fetch & Lock Cache Op\n"); 534 break; 535 default: warn("Unimplemented Cache Op\n"); 536 } 537 } 538 return fault; 539}*/ 540