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