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