cpu_impl.hh revision 2765:2962455d1c0a
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
52using namespace std;
53//The CheckerCPU does alpha only
54using namespace AlphaISA;
55
56void
57CheckerCPU::init()
58{
59}
60
61CheckerCPU::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
87CheckerCPU::~CheckerCPU()
88{
89}
90
91void
92CheckerCPU::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
105void
106CheckerCPU::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
121void
122CheckerCPU::setIcachePort(Port *icache_port)
123{
124    icachePort = icache_port;
125}
126
127void
128CheckerCPU::setDcachePort(Port *dcache_port)
129{
130    dcachePort = dcache_port;
131}
132
133void
134CheckerCPU::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
145void
146CheckerCPU::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
155Fault
156CheckerCPU::copySrcTranslate(Addr src)
157{
158    panic("Unimplemented!");
159}
160
161Fault
162CheckerCPU::copy(Addr dest)
163{
164    panic("Unimplemented!");
165}
166
167template <class T>
168Fault
169CheckerCPU::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
198template
199Fault
200CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
201
202template
203Fault
204CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
205
206template
207Fault
208CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
209
210template
211Fault
212CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
213
214#endif //DOXYGEN_SHOULD_SKIP_THIS
215
216template<>
217Fault
218CheckerCPU::read(Addr addr, double &data, unsigned flags)
219{
220    return read(addr, *(uint64_t*)&data, flags);
221}
222
223template<>
224Fault
225CheckerCPU::read(Addr addr, float &data, unsigned flags)
226{
227    return read(addr, *(uint32_t*)&data, flags);
228}
229
230template<>
231Fault
232CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
233{
234    return read(addr, (uint32_t&)data, flags);
235}
236
237template <class T>
238Fault
239CheckerCPU::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
294template
295Fault
296CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
297
298template
299Fault
300CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
301
302template
303Fault
304CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
305
306template
307Fault
308CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
309
310#endif //DOXYGEN_SHOULD_SKIP_THIS
311
312template<>
313Fault
314CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
315{
316    return write(*(uint64_t*)&data, addr, flags, res);
317}
318
319template<>
320Fault
321CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
322{
323    return write(*(uint32_t*)&data, addr, flags, res);
324}
325
326template<>
327Fault
328CheckerCPU::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
335Addr
336CheckerCPU::dbg_vtophys(Addr addr)
337{
338    return vtophys(tc, addr);
339}
340#endif // FULL_SYSTEM
341
342bool
343CheckerCPU::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
353void
354CheckerCPU::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
373void
374CheckerCPU::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
393bool
394CheckerCPU::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
407void
408CheckerCPU::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
415template <class DynInstPtr>
416void
417Checker<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
658template <class DynInstPtr>
659void
660Checker<DynInstPtr>::switchOut(Sampler *s)
661{
662    instList.clear();
663}
664
665template <class DynInstPtr>
666void
667Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
668{
669}
670
671template <class DynInstPtr>
672void
673Checker<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
696template <class DynInstPtr>
697void
698Checker<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
758template <class DynInstPtr>
759void
760Checker<DynInstPtr>::validateState()
761{
762}
763
764template <class DynInstPtr>
765void
766Checker<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
778template <class DynInstPtr>
779void
780Checker<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
794template <class DynInstPtr>
795void
796Checker<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}
823