cpu_impl.hh revision 2323
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            if (inst->getFault() == NoFault) {
611                warn("Instruction PC %#x was not found in the ITB!",
612                     cpuXC->readPC());
613                handleError();
614
615                // go to the next instruction
616                cpuXC->setPC(cpuXC->readNextPC());
617                cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
618
619                return;
620            } else {
621                fault = inst->getFault();
622            }
623        }
624
625        if (fault == NoFault) {
626//        fault = cpuXC->mem->read(memReq, machInst);
627            cpuXC->mem->read(memReq, machInst);
628
629            // If we've got a valid instruction (i.e., no fault on instruction
630            // fetch), then execute it.
631
632        // keep an instruction count
633            numInst++;
634//	numInsts++;
635
636            // decode the instruction
637            machInst = gtoh(machInst);
638            // Checks that the instruction matches what we expected it to be.
639            // Checks both the machine instruction and the PC.
640            validateInst(inst);
641
642            curStaticInst = StaticInst::decode(makeExtMI(machInst, cpuXC->readPC()));
643
644#if FULL_SYSTEM
645            cpuXC->setInst(machInst);
646#endif // FULL_SYSTEM
647
648            fault = inst->getFault();
649        }
650
651        // Either the instruction was a fault and we should process the fault,
652        // or we should just go ahead execute the instruction.  This assumes
653        // that the instruction is properly marked as a fault.
654        if (fault == NoFault) {
655
656            cpuXC->func_exe_inst++;
657
658            fault = curStaticInst->execute(this, NULL);
659
660            // Checks to make sure instrution results are correct.
661            validateExecution(inst);
662
663//	if (curStaticInst->isMemRef()) {
664//	    numMemRefs++;
665//	}
666
667            if (curStaticInst->isLoad()) {
668                ++numLoad;
669            }
670        }
671
672        if (fault != NoFault) {
673#if FULL_SYSTEM
674            fault->invoke(xcProxy);
675            willChangePC = true;
676            newPC = cpuXC->readPC();
677            DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
678#else // !FULL_SYSTEM
679            fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC());
680#endif // FULL_SYSTEM
681        } else {
682#if THE_ISA != MIPS_ISA
683            // go to the next instruction
684            cpuXC->setPC(cpuXC->readNextPC());
685            cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
686#else
687            // go to the next instruction
688            cpuXC->setPC(cpuXC->readNextPC());
689            cpuXC->setNextPC(cpuXC->readNextNPC());
690            cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
691#endif
692
693        }
694
695#if FULL_SYSTEM
696        Addr oldpc;
697        int count = 0;
698        do {
699            oldpc = cpuXC->readPC();
700            system->pcEventQueue.service(xcProxy);
701            count++;
702        } while (oldpc != cpuXC->readPC());
703        if (count > 1) {
704            willChangePC = true;
705            newPC = cpuXC->readPC();
706            DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
707        }
708#endif
709
710        // Checks PC, next PC.  Optionally can check all registers. (Or just those
711        // that have been modified).
712        validateState();
713
714        if (instList.empty()) {
715            break;
716        } else if (instList.front()->isCompleted()) {
717            inst = instList.front();
718            instList.pop_front();
719        } else {
720            break;
721        }
722    }
723}
724
725template <class DynInstPtr>
726void
727Checker<DynInstPtr>::switchOut(Sampler *s)
728{
729    sampler = s;
730    instList.clear();
731}
732
733template <class DynInstPtr>
734void
735Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
736{
737//    BaseCPU::takeOverFrom(oldCPU);
738
739    // if any of this CPU's ExecContexts are active, mark the CPU as
740    // running and schedule its tick event.
741/*
742    for (int i = 0; i < execContexts.size(); ++i) {
743        ExecContext *xc = execContexts[i];
744    }
745*/
746}
747
748template <class DynInstPtr>
749void
750Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
751{
752    if (inst->readPC() != cpuXC->readPC()) {
753        warn("PCs do not match! Inst: %#x, checker: %#x",
754             inst->readPC(), cpuXC->readPC());
755        if (changedPC) {
756            warn("Changed PCs recently, may not be an error");
757        } else {
758            handleError();
759        }
760    }
761
762    if (static_cast<MachInst>(inst->staticInst->machInst) !=
763        machInst) {
764        warn("Binary instructions do not match! Inst: %#x, checker: %#x",
765             static_cast<MachInst>(inst->staticInst->machInst),
766             machInst);
767        handleError();
768    }
769}
770
771template <class DynInstPtr>
772void
773Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
774{
775    if (inst->numDestRegs()) {
776        if (inst->isUnverifiable()) {
777            // @todo: Support more destination registers.
778            // Grab the result from the instruction and write it to the
779            // register.
780            RegIndex idx = inst->destRegIdx(0);
781            if (idx < TheISA::FP_Base_DepTag) {
782                cpuXC->setIntReg(idx, inst->readIntResult());
783            } else if (idx < TheISA::Fpcr_DepTag) {
784                cpuXC->setFloatRegInt(idx, inst->readIntResult());
785            } else {
786                cpuXC->setMiscReg(idx, inst->readIntResult());
787            }
788        } else if (result.integer != inst->readIntResult()) {
789            warn("Instruction results do not match! (May not be integer results) "
790                 "Inst: %#x, checker: %#x",
791                 inst->readIntResult(), result.integer);
792            handleError();
793        }
794    }
795
796    if (inst->readNextPC() != cpuXC->readNextPC()) {
797        warn("Instruction next PCs do not match! Inst: %#x, checker: %#x",
798             inst->readNextPC(), cpuXC->readNextPC());
799        handleError();
800    }
801
802    // Checking side effect registers can be difficult if they are not
803    // checked simultaneously with the execution of the instruction.
804    // This is because other valid instructions may have modified
805    // these registers in the meantime, and their values are not
806    // stored within the DynInst.
807    while (!miscRegIdxs.empty()) {
808        int misc_reg_idx = miscRegIdxs.front();
809        miscRegIdxs.pop();
810
811        if (inst->xcBase()->readMiscReg(misc_reg_idx) !=
812            cpuXC->readMiscReg(misc_reg_idx)) {
813            warn("Misc reg idx %i (side effect) does not match! Inst: %#x, "
814                 "checker: %#x",
815                 misc_reg_idx, inst->xcBase()->readMiscReg(misc_reg_idx),
816                 cpuXC->readMiscReg(misc_reg_idx));
817            handleError();
818        }
819    }
820}
821
822template <class DynInstPtr>
823void
824Checker<DynInstPtr>::validateState()
825{
826}
827
828template <class DynInstPtr>
829void
830Checker<DynInstPtr>::dumpInsts()
831{
832    int num = 0;
833
834    InstListIt inst_list_it = --(instList.end());
835
836    cprintf("Inst list size: %i\n", instList.size());
837
838    while (inst_list_it != instList.end())
839    {
840        cprintf("Instruction:%i\n",
841                num);
842
843        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
844                "Completed:%i\n",
845                (*inst_list_it)->readPC(),
846                (*inst_list_it)->seqNum,
847                (*inst_list_it)->threadNumber,
848                (*inst_list_it)->isCompleted());
849
850        cprintf("\n");
851
852        inst_list_it--;
853        ++num;
854    }
855
856}
857
858template
859class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
860
861template
862class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
863