base.cc revision 5536
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 68#include "params/BaseSimpleCPU.hh" 69 70using namespace std; 71using namespace TheISA; 72 73BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p) 74 : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL) 75{ 76#if FULL_SYSTEM 77 thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); 78#else 79 thread = new SimpleThread(this, /* thread_num */ 0, p->workload[0], 80 p->itb, p->dtb, /* asid */ 0); 81#endif // !FULL_SYSTEM 82 83 thread->setStatus(ThreadContext::Unallocated); 84 85 tc = thread->getTC(); 86 87 numInst = 0; 88 startNumInst = 0; 89 numLoad = 0; 90 startNumLoad = 0; 91 lastIcacheStall = 0; 92 lastDcacheStall = 0; 93 94 threadContexts.push_back(tc); 95 96 97 fetchOffset = 0; 98 stayAtPC = false; 99} 100 101BaseSimpleCPU::~BaseSimpleCPU() 102{ 103} 104 105void 106BaseSimpleCPU::deallocateContext(int thread_num) 107{ 108 // for now, these are equivalent 109 suspendContext(thread_num); 110} 111 112 113void 114BaseSimpleCPU::haltContext(int thread_num) 115{ 116 // for now, these are equivalent 117 suspendContext(thread_num); 118} 119 120 121void 122BaseSimpleCPU::regStats() 123{ 124 using namespace Stats; 125 126 BaseCPU::regStats(); 127 128 numInsts 129 .name(name() + ".num_insts") 130 .desc("Number of instructions executed") 131 ; 132 133 numMemRefs 134 .name(name() + ".num_refs") 135 .desc("Number of memory references") 136 ; 137 138 notIdleFraction 139 .name(name() + ".not_idle_fraction") 140 .desc("Percentage of non-idle cycles") 141 ; 142 143 idleFraction 144 .name(name() + ".idle_fraction") 145 .desc("Percentage of idle cycles") 146 ; 147 148 icacheStallCycles 149 .name(name() + ".icache_stall_cycles") 150 .desc("ICache total stall cycles") 151 .prereq(icacheStallCycles) 152 ; 153 154 dcacheStallCycles 155 .name(name() + ".dcache_stall_cycles") 156 .desc("DCache total stall cycles") 157 .prereq(dcacheStallCycles) 158 ; 159 160 icacheRetryCycles 161 .name(name() + ".icache_retry_cycles") 162 .desc("ICache total retry cycles") 163 .prereq(icacheRetryCycles) 164 ; 165 166 dcacheRetryCycles 167 .name(name() + ".dcache_retry_cycles") 168 .desc("DCache total retry cycles") 169 .prereq(dcacheRetryCycles) 170 ; 171 172 idleFraction = constant(1.0) - notIdleFraction; 173} 174 175void 176BaseSimpleCPU::resetStats() 177{ 178// startNumInst = numInst; 179 notIdleFraction = (_status != Idle); 180} 181 182void 183BaseSimpleCPU::serialize(ostream &os) 184{ 185 SERIALIZE_ENUM(_status); 186 BaseCPU::serialize(os); 187// SERIALIZE_SCALAR(inst); 188 nameOut(os, csprintf("%s.xc.0", name())); 189 thread->serialize(os); 190} 191 192void 193BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 194{ 195 UNSERIALIZE_ENUM(_status); 196 BaseCPU::unserialize(cp, section); 197// UNSERIALIZE_SCALAR(inst); 198 thread->unserialize(cp, csprintf("%s.xc.0", section)); 199} 200 201void 202change_thread_state(int thread_number, int activate, int priority) 203{ 204} 205 206Fault 207BaseSimpleCPU::copySrcTranslate(Addr src) 208{ 209#if 0 210 static bool no_warn = true; 211 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 212 // Only support block sizes of 64 atm. 213 assert(blk_size == 64); 214 int offset = src & (blk_size - 1); 215 216 // Make sure block doesn't span page 217 if (no_warn && 218 (src & PageMask) != ((src + blk_size) & PageMask) && 219 (src >> 40) != 0xfffffc) { 220 warn("Copied block source spans pages %x.", src); 221 no_warn = false; 222 } 223 224 memReq->reset(src & ~(blk_size - 1), blk_size); 225 226 // translate to physical address 227 Fault fault = thread->translateDataReadReq(req); 228 229 if (fault == NoFault) { 230 thread->copySrcAddr = src; 231 thread->copySrcPhysAddr = memReq->paddr + offset; 232 } else { 233 assert(!fault->isAlignmentFault()); 234 235 thread->copySrcAddr = 0; 236 thread->copySrcPhysAddr = 0; 237 } 238 return fault; 239#else 240 return NoFault; 241#endif 242} 243 244Fault 245BaseSimpleCPU::copy(Addr dest) 246{ 247#if 0 248 static bool no_warn = true; 249 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 250 // Only support block sizes of 64 atm. 251 assert(blk_size == 64); 252 uint8_t data[blk_size]; 253 //assert(thread->copySrcAddr); 254 int offset = dest & (blk_size - 1); 255 256 // Make sure block doesn't span page 257 if (no_warn && 258 (dest & PageMask) != ((dest + blk_size) & PageMask) && 259 (dest >> 40) != 0xfffffc) { 260 no_warn = false; 261 warn("Copied block destination spans pages %x. ", dest); 262 } 263 264 memReq->reset(dest & ~(blk_size -1), blk_size); 265 // translate to physical address 266 Fault fault = thread->translateDataWriteReq(req); 267 268 if (fault == NoFault) { 269 Addr dest_addr = memReq->paddr + offset; 270 // Need to read straight from memory since we have more than 8 bytes. 271 memReq->paddr = thread->copySrcPhysAddr; 272 thread->mem->read(memReq, data); 273 memReq->paddr = dest_addr; 274 thread->mem->write(memReq, data); 275 if (dcacheInterface) { 276 memReq->cmd = Copy; 277 memReq->completionEvent = NULL; 278 memReq->paddr = thread->copySrcPhysAddr; 279 memReq->dest = dest_addr; 280 memReq->size = 64; 281 memReq->time = curTick; 282 memReq->flags &= ~INST_READ; 283 dcacheInterface->access(memReq); 284 } 285 } 286 else 287 assert(!fault->isAlignmentFault()); 288 289 return fault; 290#else 291 panic("copy not implemented"); 292 return NoFault; 293#endif 294} 295 296#if FULL_SYSTEM 297Addr 298BaseSimpleCPU::dbg_vtophys(Addr addr) 299{ 300 return vtophys(tc, addr); 301} 302#endif // FULL_SYSTEM 303 304#if FULL_SYSTEM 305void 306BaseSimpleCPU::post_interrupt(int int_num, int index) 307{ 308 BaseCPU::post_interrupt(int_num, index); 309 310 if (thread->status() == ThreadContext::Suspended) { 311 DPRINTF(Quiesce,"Suspended Processor awoke\n"); 312 thread->activate(); 313 } 314} 315#endif // FULL_SYSTEM 316 317void 318BaseSimpleCPU::checkForInterrupts() 319{ 320#if FULL_SYSTEM 321 if (check_interrupts(tc)) { 322 Fault interrupt = interrupts.getInterrupt(tc); 323 324 if (interrupt != NoFault) { 325 interrupts.updateIntrInfo(tc); 326 interrupt->invoke(tc); 327 } 328 } 329#endif 330} 331 332 333Fault 334BaseSimpleCPU::setupFetchRequest(Request *req) 335{ 336 Addr threadPC = thread->readPC(); 337 338 // set up memory request for instruction fetch 339#if ISA_HAS_DELAY_SLOT 340 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC, 341 thread->readNextPC(),thread->readNextNPC()); 342#else 343 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC, 344 thread->readNextPC()); 345#endif 346 347 Addr fetchPC = (threadPC & PCMask) + fetchOffset; 348 req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC); 349 350 Fault fault = thread->translateInstReq(req); 351 352 return fault; 353} 354 355 356void 357BaseSimpleCPU::preExecute() 358{ 359 // maintain $r0 semantics 360 thread->setIntReg(ZeroReg, 0); 361#if THE_ISA == ALPHA_ISA 362 thread->setFloatReg(ZeroReg, 0.0); 363#endif // ALPHA_ISA 364 365 // check for instruction-count-based events 366 comInstEventQueue[0]->serviceEvents(numInst); 367 368 // decode the instruction 369 inst = gtoh(inst); 370 371 //If we're not in the middle of a macro instruction 372 if (!curMacroStaticInst) { 373 374 StaticInstPtr instPtr = NULL; 375 376 //Predecode, ie bundle up an ExtMachInst 377 //This should go away once the constructor can be set up properly 378 predecoder.setTC(thread->getTC()); 379 //If more fetch data is needed, pass it in. 380 Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset; 381 //if(predecoder.needMoreBytes()) 382 predecoder.moreBytes(thread->readPC(), fetchPC, inst); 383 //else 384 // predecoder.process(); 385 386 //If an instruction is ready, decode it. Otherwise, we'll have to 387 //fetch beyond the MachInst at the current pc. 388 if (predecoder.extMachInstReady()) { 389#if THE_ISA == X86_ISA 390 thread->setNextPC(thread->readPC() + predecoder.getInstSize()); 391#endif // X86_ISA 392 stayAtPC = false; 393 instPtr = StaticInst::decode(predecoder.getExtMachInst(), 394 thread->readPC()); 395 } else { 396 stayAtPC = true; 397 fetchOffset += sizeof(MachInst); 398 } 399 400 //If we decoded an instruction and it's microcoded, start pulling 401 //out micro ops 402 if (instPtr && instPtr->isMacroop()) { 403 curMacroStaticInst = instPtr; 404 curStaticInst = curMacroStaticInst-> 405 fetchMicroop(thread->readMicroPC()); 406 } else { 407 curStaticInst = instPtr; 408 } 409 } else { 410 //Read the next micro op from the macro op 411 curStaticInst = curMacroStaticInst-> 412 fetchMicroop(thread->readMicroPC()); 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, curStaticInst, 420 thread->readPC()); 421 422 DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", 423 curStaticInst->getName(), curStaticInst->machInst); 424#endif // TRACING_ON 425 426#if FULL_SYSTEM 427 thread->setInst(inst); 428#endif // FULL_SYSTEM 429 } 430} 431 432void 433BaseSimpleCPU::postExecute() 434{ 435#if FULL_SYSTEM 436 if (thread->profile && curStaticInst) { 437 bool usermode = TheISA::inUserMode(tc); 438 thread->profilePC = usermode ? 1 : thread->readPC(); 439 ProfileNode *node = thread->profile->consume(tc, curStaticInst); 440 if (node) 441 thread->profileNode = node; 442 } 443#endif 444 445 if (curStaticInst->isMemRef()) { 446 numMemRefs++; 447 } 448 449 if (curStaticInst->isLoad()) { 450 ++numLoad; 451 comLoadEventQueue[0]->serviceEvents(numLoad); 452 } 453 454 traceFunctions(thread->readPC()); 455 456 if (traceData) { 457 traceData->dump(); 458 delete traceData; 459 traceData = NULL; 460 } 461} 462 463 464void 465BaseSimpleCPU::advancePC(Fault fault) 466{ 467 //Since we're moving to a new pc, zero out the offset 468 fetchOffset = 0; 469 if (fault != NoFault) { 470 curMacroStaticInst = StaticInst::nullStaticInstPtr; 471 predecoder.reset(); 472 thread->setMicroPC(0); 473 thread->setNextMicroPC(1); 474 fault->invoke(tc); 475 } else { 476 //If we're at the last micro op for this instruction 477 if (curStaticInst && curStaticInst->isLastMicroop()) { 478 //We should be working with a macro op 479 assert(curMacroStaticInst); 480 //Close out this macro op, and clean up the 481 //microcode state 482 curMacroStaticInst = StaticInst::nullStaticInstPtr; 483 thread->setMicroPC(0); 484 thread->setNextMicroPC(1); 485 } 486 //If we're still in a macro op 487 if (curMacroStaticInst) { 488 //Advance the micro pc 489 thread->setMicroPC(thread->readNextMicroPC()); 490 //Advance the "next" micro pc. Note that there are no delay 491 //slots, and micro ops are "word" addressed. 492 thread->setNextMicroPC(thread->readNextMicroPC() + 1); 493 } else { 494 // go to the next instruction 495 thread->setPC(thread->readNextPC()); 496 thread->setNextPC(thread->readNextNPC()); 497 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 498 assert(thread->readNextPC() != thread->readNextNPC()); 499 } 500 } 501} 502 503/*Fault 504BaseSimpleCPU::CacheOp(uint8_t Op, Addr EffAddr) 505{ 506 // translate to physical address 507 Fault fault = NoFault; 508 int CacheID = Op & 0x3; // Lower 3 bits identify Cache 509 int CacheOP = Op >> 2; // Upper 3 bits identify Cache Operation 510 if(CacheID > 1) 511 { 512 warn("CacheOps not implemented for secondary/tertiary caches\n"); 513 } 514 else 515 { 516 switch(CacheOP) 517 { // Fill Packet Type 518 case 0: warn("Invalidate Cache Op\n"); 519 break; 520 case 1: warn("Index Load Tag Cache Op\n"); 521 break; 522 case 2: warn("Index Store Tag Cache Op\n"); 523 break; 524 case 4: warn("Hit Invalidate Cache Op\n"); 525 break; 526 case 5: warn("Fill/Hit Writeback Invalidate Cache Op\n"); 527 break; 528 case 6: warn("Hit Writeback\n"); 529 break; 530 case 7: warn("Fetch & Lock Cache Op\n"); 531 break; 532 default: warn("Unimplemented Cache Op\n"); 533 } 534 } 535 return fault; 536}*/ 537