base.cc revision 2662
15081Sgblack@eecs.umich.edu/* 25081Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 35081Sgblack@eecs.umich.edu * All rights reserved. 45081Sgblack@eecs.umich.edu * 55081Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 65081Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 75081Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 85081Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 95081Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 105081Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 115081Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 125081Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 135081Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 145081Sgblack@eecs.umich.edu * this software without specific prior written permission. 155081Sgblack@eecs.umich.edu * 165081Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175081Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185081Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195081Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205081Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215081Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225081Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235081Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245081Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255081Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265081Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275081Sgblack@eecs.umich.edu */ 285081Sgblack@eecs.umich.edu 295081Sgblack@eecs.umich.edu#include "arch/utility.hh" 305081Sgblack@eecs.umich.edu#include "base/cprintf.hh" 315081Sgblack@eecs.umich.edu#include "base/inifile.hh" 325081Sgblack@eecs.umich.edu#include "base/loader/symtab.hh" 335081Sgblack@eecs.umich.edu#include "base/misc.hh" 345081Sgblack@eecs.umich.edu#include "base/pollevent.hh" 355081Sgblack@eecs.umich.edu#include "base/range.hh" 365081Sgblack@eecs.umich.edu#include "base/stats/events.hh" 375081Sgblack@eecs.umich.edu#include "base/trace.hh" 385081Sgblack@eecs.umich.edu#include "cpu/base.hh" 395081Sgblack@eecs.umich.edu#include "cpu/cpu_exec_context.hh" 405081Sgblack@eecs.umich.edu#include "cpu/exec_context.hh" 415081Sgblack@eecs.umich.edu#include "cpu/exetrace.hh" 425081Sgblack@eecs.umich.edu#include "cpu/profile.hh" 435081Sgblack@eecs.umich.edu#include "cpu/sampler/sampler.hh" 445081Sgblack@eecs.umich.edu#include "cpu/simple/base.hh" 455081Sgblack@eecs.umich.edu#include "cpu/smt.hh" 465081Sgblack@eecs.umich.edu#include "cpu/static_inst.hh" 475081Sgblack@eecs.umich.edu#include "kern/kernel_stats.hh" 485081Sgblack@eecs.umich.edu#include "mem/packet_impl.hh" 495081Sgblack@eecs.umich.edu#include "sim/byteswap.hh" 505081Sgblack@eecs.umich.edu#include "sim/builder.hh" 515081Sgblack@eecs.umich.edu#include "sim/debug.hh" 525081Sgblack@eecs.umich.edu#include "sim/host.hh" 535081Sgblack@eecs.umich.edu#include "sim/sim_events.hh" 545081Sgblack@eecs.umich.edu#include "sim/sim_object.hh" 555081Sgblack@eecs.umich.edu#include "sim/stats.hh" 565081Sgblack@eecs.umich.edu 576584Sgblack@eecs.umich.edu#if FULL_SYSTEM 586584Sgblack@eecs.umich.edu#include "base/remote_gdb.hh" 596584Sgblack@eecs.umich.edu#include "sim/system.hh" 606584Sgblack@eecs.umich.edu#include "arch/tlb.hh" 616584Sgblack@eecs.umich.edu#include "arch/stacktrace.hh" 626584Sgblack@eecs.umich.edu#include "arch/vtophys.hh" 636584Sgblack@eecs.umich.edu#else // !FULL_SYSTEM 646584Sgblack@eecs.umich.edu#include "mem/mem_object.hh" 656584Sgblack@eecs.umich.edu#endif // FULL_SYSTEM 666584Sgblack@eecs.umich.edu 676584Sgblack@eecs.umich.eduusing namespace std; 686584Sgblack@eecs.umich.eduusing namespace TheISA; 696584Sgblack@eecs.umich.edu 706584Sgblack@eecs.umich.eduBaseSimpleCPU::BaseSimpleCPU(Params *p) 716584Sgblack@eecs.umich.edu : BaseCPU(p), mem(p->mem), cpuXC(NULL) 726584Sgblack@eecs.umich.edu{ 736584Sgblack@eecs.umich.edu#if FULL_SYSTEM 746584Sgblack@eecs.umich.edu cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb); 756584Sgblack@eecs.umich.edu#else 766584Sgblack@eecs.umich.edu cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, 776584Sgblack@eecs.umich.edu /* asid */ 0, mem); 786584Sgblack@eecs.umich.edu#endif // !FULL_SYSTEM 796584Sgblack@eecs.umich.edu 806584Sgblack@eecs.umich.edu xcProxy = cpuXC->getProxy(); 816584Sgblack@eecs.umich.edu 826584Sgblack@eecs.umich.edu numInst = 0; 836584Sgblack@eecs.umich.edu startNumInst = 0; 846584Sgblack@eecs.umich.edu numLoad = 0; 856584Sgblack@eecs.umich.edu startNumLoad = 0; 866584Sgblack@eecs.umich.edu lastIcacheStall = 0; 876584Sgblack@eecs.umich.edu lastDcacheStall = 0; 886584Sgblack@eecs.umich.edu 896584Sgblack@eecs.umich.edu execContexts.push_back(xcProxy); 906584Sgblack@eecs.umich.edu} 916584Sgblack@eecs.umich.edu 926584Sgblack@eecs.umich.eduBaseSimpleCPU::~BaseSimpleCPU() 936584Sgblack@eecs.umich.edu{ 946584Sgblack@eecs.umich.edu} 956584Sgblack@eecs.umich.edu 966584Sgblack@eecs.umich.eduvoid 976584Sgblack@eecs.umich.eduBaseSimpleCPU::deallocateContext(int thread_num) 986584Sgblack@eecs.umich.edu{ 996584Sgblack@eecs.umich.edu // for now, these are equivalent 1006584Sgblack@eecs.umich.edu suspendContext(thread_num); 1016584Sgblack@eecs.umich.edu} 1026584Sgblack@eecs.umich.edu 1036584Sgblack@eecs.umich.edu 1046584Sgblack@eecs.umich.eduvoid 1056584Sgblack@eecs.umich.eduBaseSimpleCPU::haltContext(int thread_num) 1066584Sgblack@eecs.umich.edu{ 1076584Sgblack@eecs.umich.edu // for now, these are equivalent 1086584Sgblack@eecs.umich.edu suspendContext(thread_num); 1096584Sgblack@eecs.umich.edu} 1106584Sgblack@eecs.umich.edu 1116584Sgblack@eecs.umich.edu 1126584Sgblack@eecs.umich.eduvoid 1136584Sgblack@eecs.umich.eduBaseSimpleCPU::regStats() 1146584Sgblack@eecs.umich.edu{ 1156584Sgblack@eecs.umich.edu using namespace Stats; 1166584Sgblack@eecs.umich.edu 1176584Sgblack@eecs.umich.edu BaseCPU::regStats(); 1186584Sgblack@eecs.umich.edu 1196584Sgblack@eecs.umich.edu numInsts 1206584Sgblack@eecs.umich.edu .name(name() + ".num_insts") 1216584Sgblack@eecs.umich.edu .desc("Number of instructions executed") 1226584Sgblack@eecs.umich.edu ; 1236584Sgblack@eecs.umich.edu 1246584Sgblack@eecs.umich.edu numMemRefs 1256584Sgblack@eecs.umich.edu .name(name() + ".num_refs") 1265081Sgblack@eecs.umich.edu .desc("Number of memory references") 127 ; 128 129 notIdleFraction 130 .name(name() + ".not_idle_fraction") 131 .desc("Percentage of non-idle cycles") 132 ; 133 134 idleFraction 135 .name(name() + ".idle_fraction") 136 .desc("Percentage of idle cycles") 137 ; 138 139 icacheStallCycles 140 .name(name() + ".icache_stall_cycles") 141 .desc("ICache total stall cycles") 142 .prereq(icacheStallCycles) 143 ; 144 145 dcacheStallCycles 146 .name(name() + ".dcache_stall_cycles") 147 .desc("DCache total stall cycles") 148 .prereq(dcacheStallCycles) 149 ; 150 151 icacheRetryCycles 152 .name(name() + ".icache_retry_cycles") 153 .desc("ICache total retry cycles") 154 .prereq(icacheRetryCycles) 155 ; 156 157 dcacheRetryCycles 158 .name(name() + ".dcache_retry_cycles") 159 .desc("DCache total retry cycles") 160 .prereq(dcacheRetryCycles) 161 ; 162 163 idleFraction = constant(1.0) - notIdleFraction; 164} 165 166void 167BaseSimpleCPU::resetStats() 168{ 169 startNumInst = numInst; 170 // notIdleFraction = (_status != Idle); 171} 172 173void 174BaseSimpleCPU::serialize(ostream &os) 175{ 176 BaseCPU::serialize(os); 177 SERIALIZE_SCALAR(inst); 178 nameOut(os, csprintf("%s.xc", name())); 179 cpuXC->serialize(os); 180} 181 182void 183BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) 184{ 185 BaseCPU::unserialize(cp, section); 186 UNSERIALIZE_SCALAR(inst); 187 cpuXC->unserialize(cp, csprintf("%s.xc", section)); 188} 189 190void 191change_thread_state(int thread_number, int activate, int priority) 192{ 193} 194 195Fault 196BaseSimpleCPU::copySrcTranslate(Addr src) 197{ 198#if 0 199 static bool no_warn = true; 200 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 201 // Only support block sizes of 64 atm. 202 assert(blk_size == 64); 203 int offset = src & (blk_size - 1); 204 205 // Make sure block doesn't span page 206 if (no_warn && 207 (src & PageMask) != ((src + blk_size) & PageMask) && 208 (src >> 40) != 0xfffffc) { 209 warn("Copied block source spans pages %x.", src); 210 no_warn = false; 211 } 212 213 memReq->reset(src & ~(blk_size - 1), blk_size); 214 215 // translate to physical address 216 Fault fault = cpuXC->translateDataReadReq(req); 217 218 if (fault == NoFault) { 219 cpuXC->copySrcAddr = src; 220 cpuXC->copySrcPhysAddr = memReq->paddr + offset; 221 } else { 222 assert(!fault->isAlignmentFault()); 223 224 cpuXC->copySrcAddr = 0; 225 cpuXC->copySrcPhysAddr = 0; 226 } 227 return fault; 228#else 229 return NoFault; 230#endif 231} 232 233Fault 234BaseSimpleCPU::copy(Addr dest) 235{ 236#if 0 237 static bool no_warn = true; 238 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; 239 // Only support block sizes of 64 atm. 240 assert(blk_size == 64); 241 uint8_t data[blk_size]; 242 //assert(cpuXC->copySrcAddr); 243 int offset = dest & (blk_size - 1); 244 245 // Make sure block doesn't span page 246 if (no_warn && 247 (dest & PageMask) != ((dest + blk_size) & PageMask) && 248 (dest >> 40) != 0xfffffc) { 249 no_warn = false; 250 warn("Copied block destination spans pages %x. ", dest); 251 } 252 253 memReq->reset(dest & ~(blk_size -1), blk_size); 254 // translate to physical address 255 Fault fault = cpuXC->translateDataWriteReq(req); 256 257 if (fault == NoFault) { 258 Addr dest_addr = memReq->paddr + offset; 259 // Need to read straight from memory since we have more than 8 bytes. 260 memReq->paddr = cpuXC->copySrcPhysAddr; 261 cpuXC->mem->read(memReq, data); 262 memReq->paddr = dest_addr; 263 cpuXC->mem->write(memReq, data); 264 if (dcacheInterface) { 265 memReq->cmd = Copy; 266 memReq->completionEvent = NULL; 267 memReq->paddr = cpuXC->copySrcPhysAddr; 268 memReq->dest = dest_addr; 269 memReq->size = 64; 270 memReq->time = curTick; 271 memReq->flags &= ~INST_READ; 272 dcacheInterface->access(memReq); 273 } 274 } 275 else 276 assert(!fault->isAlignmentFault()); 277 278 return fault; 279#else 280 panic("copy not implemented"); 281 return NoFault; 282#endif 283} 284 285#if FULL_SYSTEM 286Addr 287BaseSimpleCPU::dbg_vtophys(Addr addr) 288{ 289 return vtophys(xcProxy, addr); 290} 291#endif // FULL_SYSTEM 292 293#if FULL_SYSTEM 294void 295BaseSimpleCPU::post_interrupt(int int_num, int index) 296{ 297 BaseCPU::post_interrupt(int_num, index); 298 299 if (cpuXC->status() == ExecContext::Suspended) { 300 DPRINTF(IPI,"Suspended Processor awoke\n"); 301 cpuXC->activate(); 302 } 303} 304#endif // FULL_SYSTEM 305 306void 307BaseSimpleCPU::checkForInterrupts() 308{ 309#if FULL_SYSTEM 310 if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode()) { 311 int ipl = 0; 312 int summary = 0; 313 checkInterrupts = false; 314 315 if (cpuXC->readMiscReg(IPR_SIRR)) { 316 for (int i = INTLEVEL_SOFTWARE_MIN; 317 i < INTLEVEL_SOFTWARE_MAX; i++) { 318 if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { 319 // See table 4-19 of 21164 hardware reference 320 ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; 321 summary |= (ULL(1) << i); 322 } 323 } 324 } 325 326 uint64_t interrupts = cpuXC->cpu->intr_status(); 327 for (int i = INTLEVEL_EXTERNAL_MIN; 328 i < INTLEVEL_EXTERNAL_MAX; i++) { 329 if (interrupts & (ULL(1) << i)) { 330 // See table 4-19 of 21164 hardware reference 331 ipl = i; 332 summary |= (ULL(1) << i); 333 } 334 } 335 336 if (cpuXC->readMiscReg(IPR_ASTRR)) 337 panic("asynchronous traps not implemented\n"); 338 339 if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) { 340 cpuXC->setMiscReg(IPR_ISR, summary); 341 cpuXC->setMiscReg(IPR_INTID, ipl); 342 343 Fault(new InterruptFault)->invoke(xcProxy); 344 345 DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", 346 cpuXC->readMiscReg(IPR_IPLR), ipl, summary); 347 } 348 } 349#endif 350} 351 352 353Fault 354BaseSimpleCPU::setupFetchRequest(Request *req) 355{ 356 // set up memory request for instruction fetch 357 DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(), 358 cpuXC->readNextPC(),cpuXC->readNextNPC()); 359 360 req->setVaddr(cpuXC->readPC() & ~3); 361 req->setTime(curTick); 362#if FULL_SYSTEM 363 req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0); 364#else 365 req->setFlags(0); 366#endif 367 368 Fault fault = cpuXC->translateInstReq(req); 369 370 return fault; 371} 372 373 374void 375BaseSimpleCPU::preExecute() 376{ 377 // maintain $r0 semantics 378 cpuXC->setIntReg(ZeroReg, 0); 379#if THE_ISA == ALPHA_ISA 380 cpuXC->setFloatReg(ZeroReg, 0.0); 381#endif // ALPHA_ISA 382 383 // keep an instruction count 384 numInst++; 385 numInsts++; 386 387 cpuXC->func_exe_inst++; 388 389 // check for instruction-count-based events 390 comInstEventQueue[0]->serviceEvents(numInst); 391 392 // decode the instruction 393 inst = gtoh(inst); 394 curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC())); 395 396 traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst, 397 cpuXC->readPC()); 398 399 DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n", 400 curStaticInst->getName(), curStaticInst->getOpcode(), 401 curStaticInst->machInst); 402 403#if FULL_SYSTEM 404 cpuXC->setInst(inst); 405#endif // FULL_SYSTEM 406} 407 408void 409BaseSimpleCPU::postExecute() 410{ 411#if FULL_SYSTEM 412 if (system->kernelBinning->fnbin) { 413 assert(kernelStats); 414 system->kernelBinning->execute(xcProxy, inst); 415 } 416 417 if (cpuXC->profile) { 418 bool usermode = 419 (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; 420 cpuXC->profilePC = usermode ? 1 : cpuXC->readPC(); 421 ProfileNode *node = cpuXC->profile->consume(xcProxy, inst); 422 if (node) 423 cpuXC->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(cpuXC->readPC()); 437 438 if (traceData) { 439 traceData->finalize(); 440 } 441} 442 443 444void 445BaseSimpleCPU::advancePC(Fault fault) 446{ 447 if (fault != NoFault) { 448#if FULL_SYSTEM 449 fault->invoke(xcProxy); 450#else // !FULL_SYSTEM 451 fatal("fault (%s) detected @ PC %08p", fault->name(), cpuXC->readPC()); 452#endif // FULL_SYSTEM 453 } 454 else { 455 // go to the next instruction 456 cpuXC->setPC(cpuXC->readNextPC()); 457#if THE_ISA == ALPHA_ISA 458 cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); 459#else 460 cpuXC->setNextPC(cpuXC->readNextNPC()); 461 cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst)); 462#endif 463 464 } 465 466#if FULL_SYSTEM 467 Addr oldpc; 468 do { 469 oldpc = cpuXC->readPC(); 470 system->pcEventQueue.service(xcProxy); 471 } while (oldpc != cpuXC->readPC()); 472#endif 473} 474 475