base.cc revision 6105
16019Shines@cs.fsu.edu/* 26019Shines@cs.fsu.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 37152Sgblack@eecs.umich.edu * All rights reserved. 47152Sgblack@eecs.umich.edu * 57152Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67152Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77152Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87152Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97152Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107152Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117152Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127152Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137152Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147152Sgblack@eecs.umich.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * Authors: Steve Reinhardt 296019Shines@cs.fsu.edu */ 306019Shines@cs.fsu.edu 316019Shines@cs.fsu.edu#include "arch/utility.hh" 326019Shines@cs.fsu.edu#include "arch/faults.hh" 336019Shines@cs.fsu.edu#include "base/cprintf.hh" 346019Shines@cs.fsu.edu#include "base/cp_annotate.hh" 356019Shines@cs.fsu.edu#include "base/inifile.hh" 366019Shines@cs.fsu.edu#include "base/loader/symtab.hh" 376019Shines@cs.fsu.edu#include "base/misc.hh" 386019Shines@cs.fsu.edu#include "base/pollevent.hh" 396019Shines@cs.fsu.edu#include "base/range.hh" 406019Shines@cs.fsu.edu#include "base/stats/events.hh" 416019Shines@cs.fsu.edu#include "base/trace.hh" 426019Shines@cs.fsu.edu#include "cpu/base.hh" 436019Shines@cs.fsu.edu#include "cpu/exetrace.hh" 446019Shines@cs.fsu.edu#include "cpu/profile.hh" 456019Shines@cs.fsu.edu#include "cpu/simple/base.hh" 466019Shines@cs.fsu.edu#include "cpu/simple_thread.hh" 476019Shines@cs.fsu.edu#include "cpu/smt.hh" 487152Sgblack@eecs.umich.edu#include "cpu/static_inst.hh" 497152Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 507152Sgblack@eecs.umich.edu#include "mem/packet.hh" 517152Sgblack@eecs.umich.edu#include "mem/request.hh" 527152Sgblack@eecs.umich.edu#include "sim/byteswap.hh" 537152Sgblack@eecs.umich.edu#include "sim/debug.hh" 547152Sgblack@eecs.umich.edu#include "sim/host.hh" 557152Sgblack@eecs.umich.edu#include "sim/sim_events.hh" 567152Sgblack@eecs.umich.edu#include "sim/sim_object.hh" 577152Sgblack@eecs.umich.edu#include "sim/stats.hh" 587152Sgblack@eecs.umich.edu#include "sim/system.hh" 597152Sgblack@eecs.umich.edu 607152Sgblack@eecs.umich.edu#if FULL_SYSTEM 617152Sgblack@eecs.umich.edu#include "arch/kernel_stats.hh" 627152Sgblack@eecs.umich.edu#include "arch/stacktrace.hh" 637152Sgblack@eecs.umich.edu#include "arch/tlb.hh" 647152Sgblack@eecs.umich.edu#include "arch/vtophys.hh" 657152Sgblack@eecs.umich.edu#include "base/remote_gdb.hh" 667152Sgblack@eecs.umich.edu#else // !FULL_SYSTEM 677152Sgblack@eecs.umich.edu#include "mem/mem_object.hh" 687152Sgblack@eecs.umich.edu#endif // FULL_SYSTEM 697152Sgblack@eecs.umich.edu 707152Sgblack@eecs.umich.edu#include "params/BaseSimpleCPU.hh" 717152Sgblack@eecs.umich.edu 727152Sgblack@eecs.umich.eduusing namespace std; 737152Sgblack@eecs.umich.eduusing namespace TheISA; 747152Sgblack@eecs.umich.edu 757152Sgblack@eecs.umich.eduBaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p) 767152Sgblack@eecs.umich.edu : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL) 777152Sgblack@eecs.umich.edu{ 787152Sgblack@eecs.umich.edu#if FULL_SYSTEM 797152Sgblack@eecs.umich.edu thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); 807152Sgblack@eecs.umich.edu#else 817152Sgblack@eecs.umich.edu thread = new SimpleThread(this, /* thread_num */ 0, p->workload[0], 827152Sgblack@eecs.umich.edu p->itb, p->dtb, /* asid */ 0); 837152Sgblack@eecs.umich.edu#endif // !FULL_SYSTEM 847152Sgblack@eecs.umich.edu 857152Sgblack@eecs.umich.edu thread->setStatus(ThreadContext::Halted); 867152Sgblack@eecs.umich.edu 877154Sgblack@eecs.umich.edu tc = thread->getTC(); 887154Sgblack@eecs.umich.edu 897154Sgblack@eecs.umich.edu numInst = 0; 907154Sgblack@eecs.umich.edu startNumInst = 0; 917154Sgblack@eecs.umich.edu numLoad = 0; 927154Sgblack@eecs.umich.edu startNumLoad = 0; 937154Sgblack@eecs.umich.edu lastIcacheStall = 0; 947154Sgblack@eecs.umich.edu lastDcacheStall = 0; 957154Sgblack@eecs.umich.edu 967154Sgblack@eecs.umich.edu threadContexts.push_back(tc); 977154Sgblack@eecs.umich.edu 987154Sgblack@eecs.umich.edu 997154Sgblack@eecs.umich.edu fetchOffset = 0; 1007154Sgblack@eecs.umich.edu stayAtPC = false; 1017154Sgblack@eecs.umich.edu} 1027154Sgblack@eecs.umich.edu 1037154Sgblack@eecs.umich.eduBaseSimpleCPU::~BaseSimpleCPU() 1047154Sgblack@eecs.umich.edu{ 1057154Sgblack@eecs.umich.edu} 1067154Sgblack@eecs.umich.edu 1077154Sgblack@eecs.umich.eduvoid 1087154Sgblack@eecs.umich.eduBaseSimpleCPU::deallocateContext(int thread_num) 1097154Sgblack@eecs.umich.edu{ 1107154Sgblack@eecs.umich.edu // for now, these are equivalent 1117154Sgblack@eecs.umich.edu suspendContext(thread_num); 1127154Sgblack@eecs.umich.edu} 1137154Sgblack@eecs.umich.edu 114 115void 116BaseSimpleCPU::haltContext(int thread_num) 117{ 118 // for now, these are equivalent 119 suspendContext(thread_num); 120} 121 122 123void 124BaseSimpleCPU::regStats() 125{ 126 using namespace Stats; 127 128 BaseCPU::regStats(); 129 130 numInsts 131 .name(name() + ".num_insts") 132 .desc("Number of instructions executed") 133 ; 134 135 numMemRefs 136 .name(name() + ".num_refs") 137 .desc("Number of memory references") 138 ; 139 140 notIdleFraction 141 .name(name() + ".not_idle_fraction") 142 .desc("Percentage of non-idle cycles") 143 ; 144 145 idleFraction 146 .name(name() + ".idle_fraction") 147 .desc("Percentage of idle cycles") 148 ; 149 150 icacheStallCycles 151 .name(name() + ".icache_stall_cycles") 152 .desc("ICache total stall cycles") 153 .prereq(icacheStallCycles) 154 ; 155 156 dcacheStallCycles 157 .name(name() + ".dcache_stall_cycles") 158 .desc("DCache total stall cycles") 159 .prereq(dcacheStallCycles) 160 ; 161 162 icacheRetryCycles 163 .name(name() + ".icache_retry_cycles") 164 .desc("ICache total retry cycles") 165 .prereq(icacheRetryCycles) 166 ; 167 168 dcacheRetryCycles 169 .name(name() + ".dcache_retry_cycles") 170 .desc("DCache total retry cycles") 171 .prereq(dcacheRetryCycles) 172 ; 173 174 idleFraction = constant(1.0) - notIdleFraction; 175} 176 177void 178BaseSimpleCPU::resetStats() 179{ 180// startNumInst = numInst; 181 notIdleFraction = (_status != Idle); 182} 183 184void 185BaseSimpleCPU::serialize(ostream &os) 186{ 187 SERIALIZE_ENUM(_status); 188 BaseCPU::serialize(os); 189// SERIALIZE_SCALAR(inst); 190 nameOut(os, csprintf("%s.xc.0", name())); 191 thread->serialize(os); 192} 193 194void 195BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 196{ 197 UNSERIALIZE_ENUM(_status); 198 BaseCPU::unserialize(cp, section); 199// UNSERIALIZE_SCALAR(inst); 200 thread->unserialize(cp, csprintf("%s.xc.0", section)); 201} 202 203void 204change_thread_state(int thread_number, int activate, int priority) 205{ 206} 207 208Fault 209BaseSimpleCPU::copySrcTranslate(Addr src) 210{ 211#if 0 212 static bool no_warn = true; 213 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 214 // Only support block sizes of 64 atm. 215 assert(blk_size == 64); 216 int offset = src & (blk_size - 1); 217 218 // Make sure block doesn't span page 219 if (no_warn && 220 (src & PageMask) != ((src + blk_size) & PageMask) && 221 (src >> 40) != 0xfffffc) { 222 warn("Copied block source spans pages %x.", src); 223 no_warn = false; 224 } 225 226 memReq->reset(src & ~(blk_size - 1), blk_size); 227 228 // translate to physical address 229 Fault fault = thread->translateDataReadReq(req); 230 231 if (fault == NoFault) { 232 thread->copySrcAddr = src; 233 thread->copySrcPhysAddr = memReq->paddr + offset; 234 } else { 235 assert(!fault->isAlignmentFault()); 236 237 thread->copySrcAddr = 0; 238 thread->copySrcPhysAddr = 0; 239 } 240 return fault; 241#else 242 return NoFault; 243#endif 244} 245 246Fault 247BaseSimpleCPU::copy(Addr dest) 248{ 249#if 0 250 static bool no_warn = true; 251 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 252 // Only support block sizes of 64 atm. 253 assert(blk_size == 64); 254 uint8_t data[blk_size]; 255 //assert(thread->copySrcAddr); 256 int offset = dest & (blk_size - 1); 257 258 // Make sure block doesn't span page 259 if (no_warn && 260 (dest & PageMask) != ((dest + blk_size) & PageMask) && 261 (dest >> 40) != 0xfffffc) { 262 no_warn = false; 263 warn("Copied block destination spans pages %x. ", dest); 264 } 265 266 memReq->reset(dest & ~(blk_size -1), blk_size); 267 // translate to physical address 268 Fault fault = thread->translateDataWriteReq(req); 269 270 if (fault == NoFault) { 271 Addr dest_addr = memReq->paddr + offset; 272 // Need to read straight from memory since we have more than 8 bytes. 273 memReq->paddr = thread->copySrcPhysAddr; 274 thread->mem->read(memReq, data); 275 memReq->paddr = dest_addr; 276 thread->mem->write(memReq, data); 277 if (dcacheInterface) { 278 memReq->cmd = Copy; 279 memReq->completionEvent = NULL; 280 memReq->paddr = thread->copySrcPhysAddr; 281 memReq->dest = dest_addr; 282 memReq->size = 64; 283 memReq->time = curTick; 284 memReq->flags &= ~INST_FETCH; 285 dcacheInterface->access(memReq); 286 } 287 } 288 else 289 assert(!fault->isAlignmentFault()); 290 291 return fault; 292#else 293 panic("copy not implemented"); 294 return NoFault; 295#endif 296} 297 298#if FULL_SYSTEM 299Addr 300BaseSimpleCPU::dbg_vtophys(Addr addr) 301{ 302 return vtophys(tc, addr); 303} 304#endif // FULL_SYSTEM 305 306#if FULL_SYSTEM 307void 308BaseSimpleCPU::wakeup() 309{ 310 if (thread->status() != ThreadContext::Suspended) 311 return; 312 313 DPRINTF(Quiesce,"Suspended Processor awoke\n"); 314 thread->activate(); 315} 316#endif // FULL_SYSTEM 317 318void 319BaseSimpleCPU::checkForInterrupts() 320{ 321#if FULL_SYSTEM 322 if (checkInterrupts(tc)) { 323 Fault interrupt = interrupts->getInterrupt(tc); 324 325 if (interrupt != NoFault) { 326 predecoder.reset(); 327 interrupts->updateIntrInfo(tc); 328 interrupt->invoke(tc); 329 } 330 } 331#endif 332} 333 334 335void 336BaseSimpleCPU::setupFetchRequest(Request *req) 337{ 338 Addr threadPC = thread->readPC(); 339 340 // set up memory request for instruction fetch 341#if ISA_HAS_DELAY_SLOT 342 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC, 343 thread->readNextPC(),thread->readNextNPC()); 344#else 345 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC, 346 thread->readNextPC()); 347#endif 348 349 Addr fetchPC = (threadPC & PCMask) + fetchOffset; 350 req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, threadPC); 351} 352 353 354void 355BaseSimpleCPU::preExecute() 356{ 357 // maintain $r0 semantics 358 thread->setIntReg(ZeroReg, 0); 359#if THE_ISA == ALPHA_ISA 360 thread->setFloatReg(ZeroReg, 0.0); 361#endif // ALPHA_ISA 362 363 // check for instruction-count-based events 364 comInstEventQueue[0]->serviceEvents(numInst); 365 366 // decode the instruction 367 inst = gtoh(inst); 368 369 MicroPC upc = thread->readMicroPC(); 370 371 if (isRomMicroPC(upc)) { 372 stayAtPC = false; 373 curStaticInst = microcodeRom.fetchMicroop(upc, curMacroStaticInst); 374 } else if (!curMacroStaticInst) { 375 //We're not in the middle of a macro instruction 376 StaticInstPtr instPtr = NULL; 377 378 //Predecode, ie bundle up an ExtMachInst 379 //This should go away once the constructor can be set up properly 380 predecoder.setTC(thread->getTC()); 381 //If more fetch data is needed, pass it in. 382 Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset; 383 //if(predecoder.needMoreBytes()) 384 predecoder.moreBytes(thread->readPC(), fetchPC, inst); 385 //else 386 // predecoder.process(); 387 388 //If an instruction is ready, decode it. Otherwise, we'll have to 389 //fetch beyond the MachInst at the current pc. 390 if (predecoder.extMachInstReady()) { 391#if THE_ISA == X86_ISA 392 thread->setNextPC(thread->readPC() + predecoder.getInstSize()); 393#endif // X86_ISA 394 stayAtPC = false; 395 instPtr = StaticInst::decode(predecoder.getExtMachInst(), 396 thread->readPC()); 397 } else { 398 stayAtPC = true; 399 fetchOffset += sizeof(MachInst); 400 } 401 402 //If we decoded an instruction and it's microcoded, start pulling 403 //out micro ops 404 if (instPtr && instPtr->isMacroop()) { 405 curMacroStaticInst = instPtr; 406 curStaticInst = curMacroStaticInst->fetchMicroop(upc); 407 } else { 408 curStaticInst = instPtr; 409 } 410 } else { 411 //Read the next micro op from the macro op 412 curStaticInst = curMacroStaticInst->fetchMicroop(upc); 413 } 414 415 //If we decoded an instruction this "tick", record information about it. 416 if(curStaticInst) 417 { 418#if TRACING_ON 419 traceData = tracer->getInstRecord(curTick, tc, 420 curStaticInst, thread->readPC(), 421 curMacroStaticInst, thread->readMicroPC()); 422 423 DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", 424 curStaticInst->getName(), curStaticInst->machInst); 425#endif // TRACING_ON 426 427#if FULL_SYSTEM 428 thread->setInst(inst); 429#endif // FULL_SYSTEM 430 } 431} 432 433void 434BaseSimpleCPU::postExecute() 435{ 436#if FULL_SYSTEM 437 if (thread->profile && curStaticInst) { 438 bool usermode = TheISA::inUserMode(tc); 439 thread->profilePC = usermode ? 1 : thread->readPC(); 440 ProfileNode *node = thread->profile->consume(tc, curStaticInst); 441 if (node) 442 thread->profileNode = node; 443 } 444#endif 445 446 if (curStaticInst->isMemRef()) { 447 numMemRefs++; 448 } 449 450 if (curStaticInst->isLoad()) { 451 ++numLoad; 452 comLoadEventQueue[0]->serviceEvents(numLoad); 453 } 454 455 if (CPA::available()) { 456 CPA::cpa()->swAutoBegin(tc, thread->readNextPC()); 457 } 458 459 traceFunctions(thread->readPC()); 460 461 if (traceData) { 462 traceData->dump(); 463 delete traceData; 464 traceData = NULL; 465 } 466} 467 468 469void 470BaseSimpleCPU::advancePC(Fault fault) 471{ 472 //Since we're moving to a new pc, zero out the offset 473 fetchOffset = 0; 474 if (fault != NoFault) { 475 curMacroStaticInst = StaticInst::nullStaticInstPtr; 476 predecoder.reset(); 477 fault->invoke(tc); 478 } else { 479 //If we're at the last micro op for this instruction 480 if (curStaticInst && curStaticInst->isLastMicroop()) { 481 //We should be working with a macro op or be in the ROM 482 assert(curMacroStaticInst || 483 isRomMicroPC(thread->readMicroPC())); 484 //Close out this macro op, and clean up the 485 //microcode state 486 curMacroStaticInst = StaticInst::nullStaticInstPtr; 487 thread->setMicroPC(normalMicroPC(0)); 488 thread->setNextMicroPC(normalMicroPC(1)); 489 } 490 //If we're still in a macro op 491 if (curMacroStaticInst || isRomMicroPC(thread->readMicroPC())) { 492 //Advance the micro pc 493 thread->setMicroPC(thread->readNextMicroPC()); 494 //Advance the "next" micro pc. Note that there are no delay 495 //slots, and micro ops are "word" addressed. 496 thread->setNextMicroPC(thread->readNextMicroPC() + 1); 497 } else { 498 // go to the next instruction 499 thread->setPC(thread->readNextPC()); 500 thread->setNextPC(thread->readNextNPC()); 501 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 502 assert(thread->readNextPC() != thread->readNextNPC()); 503 } 504 } 505} 506 507/*Fault 508BaseSimpleCPU::CacheOp(uint8_t Op, Addr EffAddr) 509{ 510 // translate to physical address 511 Fault fault = NoFault; 512 int CacheID = Op & 0x3; // Lower 3 bits identify Cache 513 int CacheOP = Op >> 2; // Upper 3 bits identify Cache Operation 514 if(CacheID > 1) 515 { 516 warn("CacheOps not implemented for secondary/tertiary caches\n"); 517 } 518 else 519 { 520 switch(CacheOP) 521 { // Fill Packet Type 522 case 0: warn("Invalidate Cache Op\n"); 523 break; 524 case 1: warn("Index Load Tag Cache Op\n"); 525 break; 526 case 2: warn("Index Store Tag Cache Op\n"); 527 break; 528 case 4: warn("Hit Invalidate Cache Op\n"); 529 break; 530 case 5: warn("Fill/Hit Writeback Invalidate Cache Op\n"); 531 break; 532 case 6: warn("Hit Writeback\n"); 533 break; 534 case 7: warn("Fetch & Lock Cache Op\n"); 535 break; 536 default: warn("Unimplemented Cache Op\n"); 537 } 538 } 539 return fault; 540}*/ 541