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