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