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