cpu_impl.hh revision 2315
1/*
2 * Copyright (c) 2002-2005 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 <cmath>
30#include <cstdio>
31//#include <cstdlib>
32#include <iostream>
33#include <iomanip>
34#include <list>
35//#include <sstream>
36#include <string>
37
38//#include "base/cprintf.hh"
39//#include "base/inifile.hh"
40//#include "base/loader/symtab.hh"
41#include "base/misc.hh"
42//#include "base/pollevent.hh"
43//#include "base/range.hh"
44#include "base/refcnt.hh"
45//#include "base/stats/events.hh"
46#include "cpu/base.hh"
47#include "cpu/base_dyn_inst.hh"
48#include "cpu/checker/cpu.hh"
49#include "cpu/cpu_exec_context.hh"
50#include "cpu/exec_context.hh"
51//#include "cpu/exetrace.hh"
52//#include "cpu/profile.hh"
53#include "cpu/sampler/sampler.hh"
54//#include "cpu/smt.hh"
55#include "cpu/static_inst.hh"
56//#include "kern/kernel_stats.hh"
57#include "mem/base_mem.hh"
58#include "mem/mem_interface.hh"
59#include "sim/byteswap.hh"
60#include "sim/builder.hh"
61//#include "sim/debug.hh"
62//#include "sim/host.hh"
63//#include "sim/sim_events.hh"
64#include "sim/sim_object.hh"
65#include "sim/stats.hh"
66
67#include "cpu/o3/alpha_dyn_inst.hh"
68#include "cpu/o3/alpha_impl.hh"
69
70#include "cpu/ozone/dyn_inst.hh"
71#include "cpu/ozone/ozone_impl.hh"
72#include "cpu/ozone/simple_impl.hh"
73
74#if FULL_SYSTEM
75#include "base/remote_gdb.hh"
76#include "mem/functional/memory_control.hh"
77#include "mem/functional/physical.hh"
78#include "sim/system.hh"
79#include "arch/tlb.hh"
80#include "arch/stacktrace.hh"
81#include "arch/vtophys.hh"
82#else // !FULL_SYSTEM
83#include "mem/functional/functional.hh"
84#endif // FULL_SYSTEM
85
86using namespace std;
87//The CheckerCPU does alpha only
88using namespace AlphaISA;
89
90void
91CheckerCPU::init()
92{
93/*
94    BaseCPU::init();
95#if FULL_SYSTEM
96    for (int i = 0; i < execContexts.size(); ++i) {
97        ExecContext *xc = execContexts[i];
98
99        // initialize CPU, including PC
100        TheISA::initCPU(xc, xc->readCpuId());
101    }
102#endif
103*/
104}
105
106CheckerCPU::CheckerCPU(Params *p)
107    : BaseCPU(p), cpuXC(NULL), xcProxy(NULL)
108{
109    memReq = new MemReq();
110    memReq->xc = xcProxy;
111    memReq->asid = 0;
112    memReq->data = new uint8_t[64];
113
114    numInst = 0;
115    startNumInst = 0;
116    numLoad = 0;
117    startNumLoad = 0;
118    youngestSN = 0;
119
120    changedPC = willChangePC = changedNextPC = false;
121
122    exitOnError = p->exitOnError;
123#if FULL_SYSTEM
124    itb = p->itb;
125    dtb = p->dtb;
126    systemPtr = NULL;
127    memPtr = NULL;
128#endif
129}
130
131CheckerCPU::~CheckerCPU()
132{
133}
134
135void
136CheckerCPU::setMemory(FunctionalMemory *mem)
137{
138    memPtr = mem;
139#if !FULL_SYSTEM
140    cpuXC = new CPUExecContext(this, /* thread_num */ 0, mem,
141                               /* asid */ 0);
142
143    cpuXC->setStatus(ExecContext::Suspended);
144    xcProxy = cpuXC->getProxy();
145    execContexts.push_back(xcProxy);
146#else
147    if (systemPtr) {
148        cpuXC = new CPUExecContext(this, 0, systemPtr, itb, dtb, memPtr);
149
150        cpuXC->setStatus(ExecContext::Suspended);
151        xcProxy = cpuXC->getProxy();
152        execContexts.push_back(xcProxy);
153        memReq->xc = xcProxy;
154    }
155#endif
156}
157
158#if FULL_SYSTEM
159void
160CheckerCPU::setSystem(System *system)
161{
162    systemPtr = system;
163
164    if (memPtr) {
165        cpuXC = new CPUExecContext(this, 0, systemPtr, itb, dtb, memPtr);
166
167        cpuXC->setStatus(ExecContext::Suspended);
168        xcProxy = cpuXC->getProxy();
169        execContexts.push_back(xcProxy);
170        memReq->xc = xcProxy;
171    }
172}
173#endif
174
175void
176CheckerCPU::serialize(ostream &os)
177{
178/*
179    BaseCPU::serialize(os);
180    SERIALIZE_SCALAR(inst);
181    nameOut(os, csprintf("%s.xc", name()));
182    cpuXC->serialize(os);
183    cacheCompletionEvent.serialize(os);
184*/
185}
186
187void
188CheckerCPU::unserialize(Checkpoint *cp, const string &section)
189{
190/*
191    BaseCPU::unserialize(cp, section);
192    UNSERIALIZE_SCALAR(inst);
193    cpuXC->unserialize(cp, csprintf("%s.xc", section));
194*/
195}
196
197Fault
198CheckerCPU::copySrcTranslate(Addr src)
199{
200    static bool no_warn = true;
201    int blk_size = 64;
202    // Only support block sizes of 64 atm.
203    assert(blk_size == 64);
204    int offset = src & (blk_size - 1);
205
206    // Make sure block doesn't span page
207    if (no_warn &&
208        (src & PageMask) != ((src + blk_size) & PageMask) &&
209        (src >> 40) != 0xfffffc) {
210        warn("Copied block source spans pages %x.", src);
211        no_warn = false;
212    }
213
214    memReq->reset(src & ~(blk_size - 1), blk_size);
215
216    // translate to physical address
217    Fault fault = cpuXC->translateDataReadReq(memReq);
218
219    if (fault == NoFault) {
220        cpuXC->copySrcAddr = src;
221        cpuXC->copySrcPhysAddr = memReq->paddr + offset;
222    } else {
223        assert(!fault->isAlignmentFault());
224
225        cpuXC->copySrcAddr = 0;
226        cpuXC->copySrcPhysAddr = 0;
227    }
228    return fault;
229}
230
231Fault
232CheckerCPU::copy(Addr dest)
233{
234    static bool no_warn = true;
235    int blk_size = 64;
236    // Only support block sizes of 64 atm.
237    assert(blk_size == 64);
238    uint8_t data[blk_size];
239    //assert(cpuXC->copySrcAddr);
240    int offset = dest & (blk_size - 1);
241
242    // Make sure block doesn't span page
243    if (no_warn &&
244        (dest & PageMask) != ((dest + blk_size) & PageMask) &&
245        (dest >> 40) != 0xfffffc) {
246        no_warn = false;
247        warn("Copied block destination spans pages %x. ", dest);
248    }
249
250    memReq->reset(dest & ~(blk_size -1), blk_size);
251    // translate to physical address
252    Fault fault = cpuXC->translateDataWriteReq(memReq);
253
254    if (fault == NoFault) {
255        Addr dest_addr = memReq->paddr + offset;
256        // Need to read straight from memory since we have more than 8 bytes.
257        memReq->paddr = cpuXC->copySrcPhysAddr;
258        cpuXC->mem->read(memReq, data);
259        memReq->paddr = dest_addr;
260        cpuXC->mem->write(memReq, data);
261        memReq->cmd = Copy;
262        memReq->completionEvent = NULL;
263        memReq->paddr = cpuXC->copySrcPhysAddr;
264        memReq->dest = dest_addr;
265        memReq->size = 64;
266        memReq->time = curTick;
267        memReq->flags &= ~INST_READ;
268    }
269    else
270        assert(!fault->isAlignmentFault());
271
272    return fault;
273}
274
275// precise architected memory state accessor macros
276template <class T>
277Fault
278CheckerCPU::read(Addr addr, T &data, unsigned flags)
279{
280    memReq->reset(addr, sizeof(T), flags);
281
282    // translate to physical address
283    // Should I probe the DTB?  Or should I just take the physical address
284    // and assume correct translation?
285    translateDataReadReq(memReq);
286
287    // if we have a cache, do cache access too
288    memReq->cmd = Read;
289    memReq->completionEvent = NULL;
290    memReq->time = curTick;
291    memReq->flags &= ~INST_READ;
292
293    if (!(memReq->flags & UNCACHEABLE)) {
294        cpuXC->read(memReq, data);
295    } else {
296        // Assume the data is correct if it's an uncached access
297        memcpy(&data, &unverifiedResult.integer, sizeof(T));
298    }
299
300    return NoFault;
301}
302
303#ifndef DOXYGEN_SHOULD_SKIP_THIS
304
305template
306Fault
307CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
308
309template
310Fault
311CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
312
313template
314Fault
315CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
316
317template
318Fault
319CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
320
321#endif //DOXYGEN_SHOULD_SKIP_THIS
322
323template<>
324Fault
325CheckerCPU::read(Addr addr, double &data, unsigned flags)
326{
327    return read(addr, *(uint64_t*)&data, flags);
328}
329
330template<>
331Fault
332CheckerCPU::read(Addr addr, float &data, unsigned flags)
333{
334    return read(addr, *(uint32_t*)&data, flags);
335}
336
337template<>
338Fault
339CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
340{
341    return read(addr, (uint32_t&)data, flags);
342}
343
344template <class T>
345Fault
346CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
347{
348    memReq->reset(addr, sizeof(T), flags);
349
350    // translate to physical address
351    cpuXC->translateDataWriteReq(memReq);
352
353    if ((!(unverifiedReq->flags & LOCKED) ||
354        ((unverifiedReq->flags & LOCKED) &&
355         unverifiedReq->result == 1)) &&
356        !(unverifiedReq->flags & UNCACHEABLE)) {
357        // do functional access
358//        cpuXC->read(memReq, data);
359
360        memReq->cmd = Write;
361//    memcpy(memReq->data,(uint8_t *)&data,memReq->size);
362        T inst_data;
363        memcpy(&inst_data, unverifiedReq->data, sizeof(T));
364        memReq->completionEvent = NULL;
365        memReq->time = curTick;
366        memReq->flags &= ~INST_READ;
367
368        // Hard to verify this as the data writes back after the
369        // instruction commits.  May only be able to check that the
370        // value produced from execute() matches the value produced
371        // from the instruction's first execution.
372        if (data != inst_data) {
373            warn("Store value does not match value in memory! "
374                 "Instruction: %#x, memory: %#x",
375                 inst_data, data);
376            handleError();
377        }
378    }
379
380    // Assume the result was the same as the one passed in.  This checker
381    // doesn't check if the SC should succeed or fail, it just checks the
382    // value.
383    if (res)
384        *res = unverifiedReq->result;
385
386    return NoFault;
387}
388
389
390#ifndef DOXYGEN_SHOULD_SKIP_THIS
391template
392Fault
393CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
394
395template
396Fault
397CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
398
399template
400Fault
401CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
402
403template
404Fault
405CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
406
407#endif //DOXYGEN_SHOULD_SKIP_THIS
408
409template<>
410Fault
411CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
412{
413    return write(*(uint64_t*)&data, addr, flags, res);
414}
415
416template<>
417Fault
418CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
419{
420    return write(*(uint32_t*)&data, addr, flags, res);
421}
422
423template<>
424Fault
425CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
426{
427    return write((uint32_t)data, addr, flags, res);
428}
429
430
431#if FULL_SYSTEM
432Addr
433CheckerCPU::dbg_vtophys(Addr addr)
434{
435    return vtophys(xcProxy, addr);
436}
437#endif // FULL_SYSTEM
438
439#if FULL_SYSTEM
440void
441CheckerCPU::post_interrupt(int int_num, int index)
442{
443    BaseCPU::post_interrupt(int_num, index);
444
445    if (cpuXC->status() == ExecContext::Suspended) {
446                DPRINTF(IPI,"Suspended Processor awoke\n");
447        cpuXC->activate();
448    }
449}
450#endif // FULL_SYSTEM
451
452bool
453CheckerCPU::translateInstReq(MemReqPtr &req)
454{
455#if FULL_SYSTEM
456    return (cpuXC->translateInstReq(req) == NoFault);
457#else
458    cpuXC->translateInstReq(req);
459    return true;
460#endif
461}
462
463void
464CheckerCPU::translateDataReadReq(MemReqPtr &req)
465{
466    cpuXC->translateDataReadReq(req);
467
468    if (req->vaddr != unverifiedReq->vaddr) {
469        warn("Request virtual addresses do not match! Inst: %#x, checker:"
470             " %#x",
471             unverifiedReq->vaddr, req->vaddr);
472    }
473    req->paddr = unverifiedReq->paddr;
474
475    if (checkFlags(req)) {
476        warn("Request flags do not match! Inst: %#x, checker: %#x",
477             unverifiedReq->flags, req->flags);
478        handleError();
479    }
480}
481
482void
483CheckerCPU::translateDataWriteReq(MemReqPtr &req)
484{
485    cpuXC->translateDataWriteReq(req);
486
487    if (req->vaddr != unverifiedReq->vaddr) {
488        warn("Request virtual addresses do not match! Inst: %#x, checker:"
489             " %#x",
490             unverifiedReq->vaddr, req->vaddr);
491    }
492    req->paddr = unverifiedReq->paddr;
493
494    if (checkFlags(req)) {
495        warn("Request flags do not match! Inst: %#x, checker: %#x",
496             unverifiedReq->flags, req->flags);
497        handleError();
498    }
499}
500
501bool
502CheckerCPU::checkFlags(MemReqPtr &req)
503{
504    // Remove any dynamic flags that don't have to do with the request itself.
505    unsigned flags = unverifiedReq->flags;
506    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
507    flags = flags & (mask);
508    if (flags == req->flags) {
509        return false;
510    } else {
511        return true;
512    }
513}
514
515/* start simulation, program loaded, processor precise state initialized */
516template <class DynInstPtr>
517void
518Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
519{
520    DynInstPtr inst;
521
522    if (!instList.empty()) {
523        if (youngestSN < completed_inst->seqNum) {
524            DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
525                    completed_inst->seqNum, completed_inst->readPC());
526            instList.push_back(completed_inst);
527            youngestSN = completed_inst->seqNum;
528        }
529
530        if (!instList.front()->isCompleted()) {
531            return;
532        } else {
533            inst = instList.front();
534            instList.pop_front();
535        }
536    } else {
537        if (!completed_inst->isCompleted()) {
538            if (youngestSN < completed_inst->seqNum) {
539                DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
540                        completed_inst->seqNum, completed_inst->readPC());
541                instList.push_back(completed_inst);
542                youngestSN = completed_inst->seqNum;
543            }
544            return;
545        } else {
546            if (youngestSN < completed_inst->seqNum) {
547                inst = completed_inst;
548                youngestSN = completed_inst->seqNum;
549            } else {
550//                panic("SN already seen yet the list is empty!");
551                return;
552            }
553        }
554    }
555
556    while (1) {
557        DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
558                inst->seqNum, inst->readPC());
559//    verifyInst = completed_inst;
560        unverifiedResult.integer = inst->readIntResult();
561        unverifiedReq = inst->req;
562        numCycles++;
563
564        Fault fault = NoFault;
565
566        // maintain $r0 semantics
567        cpuXC->setIntReg(ZeroReg, 0);
568#ifdef TARGET_ALPHA
569        cpuXC->setFloatRegDouble(ZeroReg, 0.0);
570#endif // TARGET_ALPHA
571
572        // Try to fetch an instruction
573
574        // set up memory request for instruction fetch
575#if FULL_SYSTEM
576#define IFETCH_FLAGS(pc)	((pc) & 1) ? PHYSICAL : 0
577#else
578#define IFETCH_FLAGS(pc)	0
579#endif
580
581        if (changedPC) {
582            DPRINTF(Checker, "Changed PC recently to %#x\n",
583                    cpuXC->readPC());
584            if (willChangePC) {
585                if (newPC == cpuXC->readPC()) {
586                    DPRINTF(Checker, "Changed PC matches expected PC\n");
587                } else {
588                    warn("Changed PC does not match expected PC, changed: %#x, "
589                         "expected: %#x",
590                         cpuXC->readPC(), newPC);
591                    handleError();
592                }
593                willChangePC = false;
594            }
595            changedPC = false;
596        }
597        if (changedNextPC) {
598            DPRINTF(Checker, "Changed NextPC recently to %#x\n",
599                    cpuXC->readNextPC());
600            changedNextPC = false;
601        }
602
603        memReq->cmd = Read;
604        memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
605                      IFETCH_FLAGS(cpuXC->readPC()));
606
607        bool succeeded = translateInstReq(memReq);
608
609        if (!succeeded) {
610            warn("Instruction PC %#x was not found in the ITB!",
611                 cpuXC->readPC());
612            handleError();
613
614            // go to the next instruction
615            cpuXC->setPC(cpuXC->readNextPC());
616            cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
617
618            return;
619        }
620
621//    if (fault == NoFault)
622//        fault = cpuXC->mem->read(memReq, machInst);
623        cpuXC->mem->read(memReq, machInst);
624
625        // If we've got a valid instruction (i.e., no fault on instruction
626        // fetch), then execute it.
627
628        // keep an instruction count
629        numInst++;
630//	numInsts++;
631
632        // decode the instruction
633        machInst = gtoh(machInst);
634        // Checks that the instruction matches what we expected it to be.
635        // Checks both the machine instruction and the PC.
636        validateInst(inst);
637
638        curStaticInst = StaticInst::decode(makeExtMI(machInst, cpuXC->readPC()));
639
640#if FULL_SYSTEM
641        cpuXC->setInst(machInst);
642#endif // FULL_SYSTEM
643
644        fault = inst->getFault();
645
646        // Either the instruction was a fault and we should process the fault,
647        // or we should just go ahead execute the instruction.  This assumes
648        // that the instruction is properly marked as a fault.
649        if (fault == NoFault) {
650
651            cpuXC->func_exe_inst++;
652
653            fault = curStaticInst->execute(this, NULL);
654
655            // Checks to make sure instrution results are correct.
656            validateExecution(inst);
657
658//	if (curStaticInst->isMemRef()) {
659//	    numMemRefs++;
660//	}
661
662            if (curStaticInst->isLoad()) {
663                ++numLoad;
664            }
665        }
666
667        if (fault != NoFault) {
668#if FULL_SYSTEM
669            fault->invoke(xcProxy);
670            willChangePC = true;
671            newPC = cpuXC->readPC();
672            DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
673#else // !FULL_SYSTEM
674            fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC());
675#endif // FULL_SYSTEM
676        } else {
677#if THE_ISA != MIPS_ISA
678            // go to the next instruction
679            cpuXC->setPC(cpuXC->readNextPC());
680            cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
681#else
682            // go to the next instruction
683            cpuXC->setPC(cpuXC->readNextPC());
684            cpuXC->setNextPC(cpuXC->readNextNPC());
685            cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
686#endif
687
688        }
689
690#if FULL_SYSTEM
691        Addr oldpc;
692        int count = 0;
693        do {
694            oldpc = cpuXC->readPC();
695            system->pcEventQueue.service(xcProxy);
696            count++;
697        } while (oldpc != cpuXC->readPC());
698        if (count > 1) {
699            willChangePC = true;
700            newPC = cpuXC->readPC();
701            DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
702        }
703#endif
704
705        // Checks PC, next PC.  Optionally can check all registers. (Or just those
706        // that have been modified).
707        validateState();
708
709        if (instList.empty()) {
710            break;
711        } else if (instList.front()->isCompleted()) {
712            inst = instList.front();
713            instList.pop_front();
714        } else {
715            break;
716        }
717    }
718}
719
720template <class DynInstPtr>
721void
722Checker<DynInstPtr>::switchOut(Sampler *s)
723{
724    sampler = s;
725    instList.clear();
726}
727
728template <class DynInstPtr>
729void
730Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
731{
732//    BaseCPU::takeOverFrom(oldCPU);
733
734    // if any of this CPU's ExecContexts are active, mark the CPU as
735    // running and schedule its tick event.
736/*
737    for (int i = 0; i < execContexts.size(); ++i) {
738        ExecContext *xc = execContexts[i];
739    }
740*/
741}
742
743template <class DynInstPtr>
744void
745Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
746{
747    if (inst->readPC() != cpuXC->readPC()) {
748        warn("PCs do not match! Inst: %#x, checker: %#x",
749             inst->readPC(), cpuXC->readPC());
750        if (changedPC) {
751            warn("Changed PCs recently, may not be an error");
752        } else {
753            handleError();
754        }
755    }
756
757    if (static_cast<MachInst>(inst->staticInst->machInst) !=
758        machInst) {
759        warn("Binary instructions do not match! Inst: %#x, checker: %#x",
760             static_cast<MachInst>(inst->staticInst->machInst),
761             machInst);
762        handleError();
763    }
764}
765
766template <class DynInstPtr>
767void
768Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
769{
770    if (inst->numDestRegs()) {
771        if (inst->isUnverifiable()) {
772            // @todo: Support more destination registers.
773            // Grab the result from the instruction and write it to the
774            // register.
775            RegIndex idx = inst->destRegIdx(0);
776            if (idx < TheISA::FP_Base_DepTag) {
777                cpuXC->setIntReg(idx, inst->readIntResult());
778            } else if (idx < TheISA::Fpcr_DepTag) {
779                cpuXC->setFloatRegInt(idx, inst->readIntResult());
780            } else {
781                cpuXC->setMiscReg(idx, inst->readIntResult());
782            }
783        } else if (result.integer != inst->readIntResult()) {
784            warn("Instruction results do not match! (May not be integer results) "
785                 "Inst: %#x, checker: %#x",
786                 inst->readIntResult(), result.integer);
787            handleError();
788        }
789    }
790
791    if (inst->readNextPC() != cpuXC->readNextPC()) {
792        warn("Instruction next PCs do not match! Inst: %#x, checker: %#x",
793             inst->readNextPC(), cpuXC->readNextPC());
794        handleError();
795    }
796
797    // Checking side effect registers can be difficult if they are not
798    // checked simultaneously with the execution of the instruction.
799    // This is because other valid instructions may have modified
800    // these registers in the meantime, and their values are not
801    // stored within the DynInst.
802    while (!miscRegIdxs.empty()) {
803        int misc_reg_idx = miscRegIdxs.front();
804        miscRegIdxs.pop();
805
806        if (inst->xcBase()->readMiscReg(misc_reg_idx) !=
807            cpuXC->readMiscReg(misc_reg_idx)) {
808            warn("Misc reg idx %i (side effect) does not match! Inst: %#x, "
809                 "checker: %#x",
810                 misc_reg_idx, inst->xcBase()->readMiscReg(misc_reg_idx),
811                 cpuXC->readMiscReg(misc_reg_idx));
812            handleError();
813        }
814    }
815}
816
817template <class DynInstPtr>
818void
819Checker<DynInstPtr>::validateState()
820{
821}
822
823template <class DynInstPtr>
824void
825Checker<DynInstPtr>::dumpInsts()
826{
827    int num = 0;
828
829    InstListIt inst_list_it = --(instList.end());
830
831    cprintf("Inst list size: %i\n", instList.size());
832
833    while (inst_list_it != instList.end())
834    {
835        cprintf("Instruction:%i\n",
836                num);
837
838        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
839                "Completed:%i\n",
840                (*inst_list_it)->readPC(),
841                (*inst_list_it)->seqNum,
842                (*inst_list_it)->threadNumber,
843                (*inst_list_it)->isCompleted());
844
845        cprintf("\n");
846
847        inst_list_it--;
848        ++num;
849    }
850
851}
852
853template
854class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
855
856template
857class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
858