cpu.cc revision 2723:4c47709f88ab
1/* 2 * Copyright (c) 2006 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: Kevin Lim 29 */ 30 31#include <list> 32#include <string> 33 34#include "base/refcnt.hh" 35#include "cpu/base.hh" 36#include "cpu/base_dyn_inst.hh" 37#include "cpu/checker/cpu.hh" 38#include "cpu/simple_thread.hh" 39#include "cpu/thread_context.hh" 40#include "cpu/static_inst.hh" 41#include "mem/packet_impl.hh" 42#include "sim/byteswap.hh" 43#include "sim/sim_object.hh" 44#include "sim/stats.hh" 45 46#include "cpu/o3/alpha_dyn_inst.hh" 47#include "cpu/o3/alpha_impl.hh" 48 49//#include "cpu/ozone/dyn_inst.hh" 50//#include "cpu/ozone/ozone_impl.hh" 51//#include "cpu/ozone/simple_impl.hh" 52 53#if FULL_SYSTEM 54#include "sim/system.hh" 55#include "arch/vtophys.hh" 56#endif // FULL_SYSTEM 57 58using namespace std; 59//The CheckerCPU does alpha only 60using namespace AlphaISA; 61 62void 63CheckerCPU::init() 64{ 65} 66 67CheckerCPU::CheckerCPU(Params *p) 68 : BaseCPU(p), thread(NULL), tc(NULL) 69{ 70 memReq = NULL; 71 72 numInst = 0; 73 startNumInst = 0; 74 numLoad = 0; 75 startNumLoad = 0; 76 youngestSN = 0; 77 78 changedPC = willChangePC = changedNextPC = false; 79 80 exitOnError = p->exitOnError; 81#if FULL_SYSTEM 82 itb = p->itb; 83 dtb = p->dtb; 84 systemPtr = NULL; 85#else 86 process = p->process; 87#endif 88 89 result.integer = 0; 90} 91 92CheckerCPU::~CheckerCPU() 93{ 94} 95 96void 97CheckerCPU::setMemory(MemObject *mem) 98{ 99#if !FULL_SYSTEM 100 memPtr = mem; 101 thread = new SimpleThread(this, /* thread_num */ 0, process, 102 /* asid */ 0, mem); 103 104 thread->setStatus(ThreadContext::Suspended); 105 tc = thread->getTC(); 106 threadContexts.push_back(tc); 107#endif 108} 109 110void 111CheckerCPU::setSystem(System *system) 112{ 113#if FULL_SYSTEM 114 systemPtr = system; 115 116 thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 117 118 thread->setStatus(ThreadContext::Suspended); 119 tc = thread->getTC(); 120 threadContexts.push_back(tc); 121 delete thread->kernelStats; 122 thread->kernelStats = NULL; 123#endif 124} 125 126void 127CheckerCPU::setIcachePort(Port *icache_port) 128{ 129 icachePort = icache_port; 130} 131 132void 133CheckerCPU::setDcachePort(Port *dcache_port) 134{ 135 dcachePort = dcache_port; 136} 137 138void 139CheckerCPU::serialize(ostream &os) 140{ 141/* 142 BaseCPU::serialize(os); 143 SERIALIZE_SCALAR(inst); 144 nameOut(os, csprintf("%s.xc", name())); 145 thread->serialize(os); 146 cacheCompletionEvent.serialize(os); 147*/ 148} 149 150void 151CheckerCPU::unserialize(Checkpoint *cp, const string §ion) 152{ 153/* 154 BaseCPU::unserialize(cp, section); 155 UNSERIALIZE_SCALAR(inst); 156 thread->unserialize(cp, csprintf("%s.xc", section)); 157*/ 158} 159 160Fault 161CheckerCPU::copySrcTranslate(Addr src) 162{ 163 panic("Unimplemented!"); 164} 165 166Fault 167CheckerCPU::copy(Addr dest) 168{ 169 panic("Unimplemented!"); 170} 171 172template <class T> 173Fault 174CheckerCPU::read(Addr addr, T &data, unsigned flags) 175{ 176 // need to fill in CPU & thread IDs here 177 memReq = new Request(); 178 179 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 180 181 // translate to physical address 182 translateDataReadReq(memReq); 183 184 Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 185 186 pkt->dataStatic(&data); 187 188 if (!(memReq->getFlags() & UNCACHEABLE)) { 189 // Access memory to see if we have the same data 190 dcachePort->sendFunctional(pkt); 191 } else { 192 // Assume the data is correct if it's an uncached access 193 memcpy(&data, &unverifiedResult.integer, sizeof(T)); 194 } 195 196 delete pkt; 197 198 return NoFault; 199} 200 201#ifndef DOXYGEN_SHOULD_SKIP_THIS 202 203template 204Fault 205CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 206 207template 208Fault 209CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 210 211template 212Fault 213CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 214 215template 216Fault 217CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 218 219#endif //DOXYGEN_SHOULD_SKIP_THIS 220 221template<> 222Fault 223CheckerCPU::read(Addr addr, double &data, unsigned flags) 224{ 225 return read(addr, *(uint64_t*)&data, flags); 226} 227 228template<> 229Fault 230CheckerCPU::read(Addr addr, float &data, unsigned flags) 231{ 232 return read(addr, *(uint32_t*)&data, flags); 233} 234 235template<> 236Fault 237CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 238{ 239 return read(addr, (uint32_t&)data, flags); 240} 241 242template <class T> 243Fault 244CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 245{ 246 // need to fill in CPU & thread IDs here 247 memReq = new Request(); 248 249 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 250 251 // translate to physical address 252 thread->translateDataWriteReq(memReq); 253 254 // Can compare the write data and result only if it's cacheable, 255 // not a store conditional, or is a store conditional that 256 // succeeded. 257 // @todo: Verify that actual memory matches up with these values. 258 // Right now it only verifies that the instruction data is the 259 // same as what was in the request that got sent to memory; there 260 // is no verification that it is the same as what is in memory. 261 // This is because the LSQ would have to be snooped in the CPU to 262 // verify this data. 263 if (unverifiedReq && 264 !(unverifiedReq->getFlags() & UNCACHEABLE) && 265 (!(unverifiedReq->getFlags() & LOCKED) || 266 ((unverifiedReq->getFlags() & LOCKED) && 267 unverifiedReq->getScResult() == 1))) { 268 T inst_data; 269/* 270 // This code would work if the LSQ allowed for snooping. 271 Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 272 pkt.dataStatic(&inst_data); 273 274 dcachePort->sendFunctional(pkt); 275 276 delete pkt; 277*/ 278 memcpy(&inst_data, unverifiedMemData, sizeof(T)); 279 280 if (data != inst_data) { 281 warn("%lli: Store value does not match value in memory! " 282 "Instruction: %#x, memory: %#x", 283 curTick, inst_data, data); 284 handleError(); 285 } 286 } 287 288 // Assume the result was the same as the one passed in. This checker 289 // doesn't check if the SC should succeed or fail, it just checks the 290 // value. 291 if (res && unverifiedReq->scResultValid()) 292 *res = unverifiedReq->getScResult(); 293 294 return NoFault; 295} 296 297 298#ifndef DOXYGEN_SHOULD_SKIP_THIS 299template 300Fault 301CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 302 303template 304Fault 305CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 306 307template 308Fault 309CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 310 311template 312Fault 313CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 314 315#endif //DOXYGEN_SHOULD_SKIP_THIS 316 317template<> 318Fault 319CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 320{ 321 return write(*(uint64_t*)&data, addr, flags, res); 322} 323 324template<> 325Fault 326CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 327{ 328 return write(*(uint32_t*)&data, addr, flags, res); 329} 330 331template<> 332Fault 333CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 334{ 335 return write((uint32_t)data, addr, flags, res); 336} 337 338 339#if FULL_SYSTEM 340Addr 341CheckerCPU::dbg_vtophys(Addr addr) 342{ 343 return vtophys(tc, addr); 344} 345#endif // FULL_SYSTEM 346 347bool 348CheckerCPU::translateInstReq(Request *req) 349{ 350#if FULL_SYSTEM 351 return (thread->translateInstReq(req) == NoFault); 352#else 353 thread->translateInstReq(req); 354 return true; 355#endif 356} 357 358void 359CheckerCPU::translateDataReadReq(Request *req) 360{ 361 thread->translateDataReadReq(req); 362 363 if (req->getVaddr() != unverifiedReq->getVaddr()) { 364 warn("%lli: Request virtual addresses do not match! Inst: %#x, " 365 "checker: %#x", 366 curTick, unverifiedReq->getVaddr(), req->getVaddr()); 367 handleError(); 368 } 369 req->setPaddr(unverifiedReq->getPaddr()); 370 371 if (checkFlags(req)) { 372 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 373 curTick, unverifiedReq->getFlags(), req->getFlags()); 374 handleError(); 375 } 376} 377 378void 379CheckerCPU::translateDataWriteReq(Request *req) 380{ 381 thread->translateDataWriteReq(req); 382 383 if (req->getVaddr() != unverifiedReq->getVaddr()) { 384 warn("%lli: Request virtual addresses do not match! Inst: %#x, " 385 "checker: %#x", 386 curTick, unverifiedReq->getVaddr(), req->getVaddr()); 387 handleError(); 388 } 389 req->setPaddr(unverifiedReq->getPaddr()); 390 391 if (checkFlags(req)) { 392 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 393 curTick, unverifiedReq->getFlags(), req->getFlags()); 394 handleError(); 395 } 396} 397 398bool 399CheckerCPU::checkFlags(Request *req) 400{ 401 // Remove any dynamic flags that don't have to do with the request itself. 402 unsigned flags = unverifiedReq->getFlags(); 403 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; 404 flags = flags & (mask); 405 if (flags == req->getFlags()) { 406 return false; 407 } else { 408 return true; 409 } 410} 411 412template <class DynInstPtr> 413void 414Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) 415{ 416 DynInstPtr inst; 417 418 // Either check this instruction, or add it to a list of 419 // instructions waiting to be checked. Instructions must be 420 // checked in program order, so if a store has committed yet not 421 // completed, there may be some instructions that are waiting 422 // behind it that have completed and must be checked. 423 if (!instList.empty()) { 424 if (youngestSN < completed_inst->seqNum) { 425 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 426 completed_inst->seqNum, completed_inst->readPC()); 427 instList.push_back(completed_inst); 428 youngestSN = completed_inst->seqNum; 429 } 430 431 if (!instList.front()->isCompleted()) { 432 return; 433 } else { 434 inst = instList.front(); 435 instList.pop_front(); 436 } 437 } else { 438 if (!completed_inst->isCompleted()) { 439 if (youngestSN < completed_inst->seqNum) { 440 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 441 completed_inst->seqNum, completed_inst->readPC()); 442 instList.push_back(completed_inst); 443 youngestSN = completed_inst->seqNum; 444 } 445 return; 446 } else { 447 if (youngestSN < completed_inst->seqNum) { 448 inst = completed_inst; 449 youngestSN = completed_inst->seqNum; 450 } else { 451 return; 452 } 453 } 454 } 455 456 // Try to check all instructions that are completed, ending if we 457 // run out of instructions to check or if an instruction is not 458 // yet completed. 459 while (1) { 460 DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", 461 inst->seqNum, inst->readPC()); 462 unverifiedResult.integer = inst->readIntResult(); 463 unverifiedReq = inst->req; 464 unverifiedMemData = inst->memData; 465 numCycles++; 466 467 Fault fault = NoFault; 468 469 // maintain $r0 semantics 470 thread->setIntReg(ZeroReg, 0); 471#ifdef TARGET_ALPHA 472 thread->setFloatRegDouble(ZeroReg, 0.0); 473#endif // TARGET_ALPHA 474 475 // Check if any recent PC changes match up with anything we 476 // expect to happen. This is mostly to check if traps or 477 // PC-based events have occurred in both the checker and CPU. 478 if (changedPC) { 479 DPRINTF(Checker, "Changed PC recently to %#x\n", 480 thread->readPC()); 481 if (willChangePC) { 482 if (newPC == thread->readPC()) { 483 DPRINTF(Checker, "Changed PC matches expected PC\n"); 484 } else { 485 warn("%lli: Changed PC does not match expected PC, " 486 "changed: %#x, expected: %#x", 487 curTick, thread->readPC(), newPC); 488 handleError(); 489 } 490 willChangePC = false; 491 } 492 changedPC = false; 493 } 494 if (changedNextPC) { 495 DPRINTF(Checker, "Changed NextPC recently to %#x\n", 496 thread->readNextPC()); 497 changedNextPC = false; 498 } 499 500 // Try to fetch the instruction 501 502#if FULL_SYSTEM 503#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 504#else 505#define IFETCH_FLAGS(pc) 0 506#endif 507 508 uint64_t fetch_PC = thread->readPC() & ~3; 509 510 // set up memory request for instruction fetch 511 memReq = new Request(inst->threadNumber, fetch_PC, 512 sizeof(uint32_t), 513 IFETCH_FLAGS(thread->readPC()), 514 fetch_PC, thread->readCpuId(), inst->threadNumber); 515 516 bool succeeded = translateInstReq(memReq); 517 518 if (!succeeded) { 519 if (inst->getFault() == NoFault) { 520 // In this case the instruction was not a dummy 521 // instruction carrying an ITB fault. In the single 522 // threaded case the ITB should still be able to 523 // translate this instruction; in the SMT case it's 524 // possible that its ITB entry was kicked out. 525 warn("%lli: Instruction PC %#x was not found in the ITB!", 526 curTick, thread->readPC()); 527 handleError(); 528 529 // go to the next instruction 530 thread->setPC(thread->readNextPC()); 531 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 532 533 return; 534 } else { 535 // The instruction is carrying an ITB fault. Handle 536 // the fault and see if our results match the CPU on 537 // the next tick(). 538 fault = inst->getFault(); 539 } 540 } 541 542 if (fault == NoFault) { 543 Packet *pkt = new Packet(memReq, Packet::ReadReq, 544 Packet::Broadcast); 545 546 pkt->dataStatic(&machInst); 547 548 icachePort->sendFunctional(pkt); 549 550 delete pkt; 551 552 // keep an instruction count 553 numInst++; 554 555 // decode the instruction 556 machInst = gtoh(machInst); 557 // Checks that the instruction matches what we expected it to be. 558 // Checks both the machine instruction and the PC. 559 validateInst(inst); 560 561 curStaticInst = StaticInst::decode(makeExtMI(machInst, 562 thread->readPC())); 563 564#if FULL_SYSTEM 565 thread->setInst(machInst); 566#endif // FULL_SYSTEM 567 568 fault = inst->getFault(); 569 } 570 571 // Discard fetch's memReq. 572 delete memReq; 573 memReq = NULL; 574 575 // Either the instruction was a fault and we should process the fault, 576 // or we should just go ahead execute the instruction. This assumes 577 // that the instruction is properly marked as a fault. 578 if (fault == NoFault) { 579 580 thread->funcExeInst++; 581 582 fault = curStaticInst->execute(this, NULL); 583 584 // Checks to make sure instrution results are correct. 585 validateExecution(inst); 586 587 if (curStaticInst->isLoad()) { 588 ++numLoad; 589 } 590 } 591 592 if (fault != NoFault) { 593#if FULL_SYSTEM 594 fault->invoke(tc); 595 willChangePC = true; 596 newPC = thread->readPC(); 597 DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); 598#else // !FULL_SYSTEM 599 fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC()); 600#endif // FULL_SYSTEM 601 } else { 602#if THE_ISA != MIPS_ISA 603 // go to the next instruction 604 thread->setPC(thread->readNextPC()); 605 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 606#else 607 // go to the next instruction 608 thread->setPC(thread->readNextPC()); 609 thread->setNextPC(thread->readNextNPC()); 610 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 611#endif 612 613 } 614 615#if FULL_SYSTEM 616 // @todo: Determine if these should happen only if the 617 // instruction hasn't faulted. In the SimpleCPU case this may 618 // not be true, but in the O3 or Ozone case this may be true. 619 Addr oldpc; 620 int count = 0; 621 do { 622 oldpc = thread->readPC(); 623 system->pcEventQueue.service(tc); 624 count++; 625 } while (oldpc != thread->readPC()); 626 if (count > 1) { 627 willChangePC = true; 628 newPC = thread->readPC(); 629 DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); 630 } 631#endif 632 633 // @todo: Optionally can check all registers. (Or just those 634 // that have been modified). 635 validateState(); 636 637 if (memReq) { 638 delete memReq; 639 memReq = NULL; 640 } 641 642 // Continue verifying instructions if there's another completed 643 // instruction waiting to be verified. 644 if (instList.empty()) { 645 break; 646 } else if (instList.front()->isCompleted()) { 647 inst = instList.front(); 648 instList.pop_front(); 649 } else { 650 break; 651 } 652 } 653} 654 655template <class DynInstPtr> 656void 657Checker<DynInstPtr>::switchOut(Sampler *s) 658{ 659 instList.clear(); 660} 661 662template <class DynInstPtr> 663void 664Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU) 665{ 666} 667 668template <class DynInstPtr> 669void 670Checker<DynInstPtr>::validateInst(DynInstPtr &inst) 671{ 672 if (inst->readPC() != thread->readPC()) { 673 warn("%lli: PCs do not match! Inst: %#x, checker: %#x", 674 curTick, inst->readPC(), thread->readPC()); 675 if (changedPC) { 676 warn("%lli: Changed PCs recently, may not be an error", 677 curTick); 678 } else { 679 handleError(); 680 } 681 } 682 683 MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); 684 685 if (mi != machInst) { 686 warn("%lli: Binary instructions do not match! Inst: %#x, " 687 "checker: %#x", 688 curTick, mi, machInst); 689 handleError(); 690 } 691} 692 693template <class DynInstPtr> 694void 695Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) 696{ 697 if (inst->numDestRegs()) { 698 // @todo: Support more destination registers. 699 if (inst->isUnverifiable()) { 700 // Unverifiable instructions assume they were executed 701 // properly by the CPU. Grab the result from the 702 // instruction and write it to the register. 703 RegIndex idx = inst->destRegIdx(0); 704 if (idx < TheISA::FP_Base_DepTag) { 705 thread->setIntReg(idx, inst->readIntResult()); 706 } else if (idx < TheISA::Fpcr_DepTag) { 707 thread->setFloatRegBits(idx, inst->readIntResult()); 708 } else { 709 thread->setMiscReg(idx, inst->readIntResult()); 710 } 711 } else if (result.integer != inst->readIntResult()) { 712 warn("%lli: Instruction results do not match! (Values may not " 713 "actually be integers) Inst: %#x, checker: %#x", 714 curTick, inst->readIntResult(), result.integer); 715 handleError(); 716 } 717 } 718 719 if (inst->readNextPC() != thread->readNextPC()) { 720 warn("%lli: Instruction next PCs do not match! Inst: %#x, " 721 "checker: %#x", 722 curTick, inst->readNextPC(), thread->readNextPC()); 723 handleError(); 724 } 725 726 // Checking side effect registers can be difficult if they are not 727 // checked simultaneously with the execution of the instruction. 728 // This is because other valid instructions may have modified 729 // these registers in the meantime, and their values are not 730 // stored within the DynInst. 731 while (!miscRegIdxs.empty()) { 732 int misc_reg_idx = miscRegIdxs.front(); 733 miscRegIdxs.pop(); 734 735 if (inst->tcBase()->readMiscReg(misc_reg_idx) != 736 thread->readMiscReg(misc_reg_idx)) { 737 warn("%lli: Misc reg idx %i (side effect) does not match! " 738 "Inst: %#x, checker: %#x", 739 curTick, misc_reg_idx, 740 inst->tcBase()->readMiscReg(misc_reg_idx), 741 thread->readMiscReg(misc_reg_idx)); 742 handleError(); 743 } 744 } 745} 746 747template <class DynInstPtr> 748void 749Checker<DynInstPtr>::validateState() 750{ 751} 752 753template <class DynInstPtr> 754void 755Checker<DynInstPtr>::dumpInsts() 756{ 757 int num = 0; 758 759 InstListIt inst_list_it = --(instList.end()); 760 761 cprintf("Inst list size: %i\n", instList.size()); 762 763 while (inst_list_it != instList.end()) 764 { 765 cprintf("Instruction:%i\n", 766 num); 767 768 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 769 "Completed:%i\n", 770 (*inst_list_it)->readPC(), 771 (*inst_list_it)->seqNum, 772 (*inst_list_it)->threadNumber, 773 (*inst_list_it)->isCompleted()); 774 775 cprintf("\n"); 776 777 inst_list_it--; 778 ++num; 779 } 780 781} 782 783//template 784//class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >; 785 786template 787class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >; 788