cpu.cc revision 2723:4c47709f88ab
16019Shines@cs.fsu.edu/*
211496Sandreas.sandberg@arm.com * Copyright (c) 2006 The Regents of The University of Michigan
37093Sgblack@eecs.umich.edu * All rights reserved.
47093Sgblack@eecs.umich.edu *
57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
146019Shines@cs.fsu.edu * this software without specific prior written permission.
156019Shines@cs.fsu.edu *
166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019Shines@cs.fsu.edu *
286019Shines@cs.fsu.edu * Authors: Kevin Lim
296019Shines@cs.fsu.edu */
306019Shines@cs.fsu.edu
316019Shines@cs.fsu.edu#include <list>
326019Shines@cs.fsu.edu#include <string>
336019Shines@cs.fsu.edu
346019Shines@cs.fsu.edu#include "base/refcnt.hh"
356019Shines@cs.fsu.edu#include "cpu/base.hh"
366019Shines@cs.fsu.edu#include "cpu/base_dyn_inst.hh"
376019Shines@cs.fsu.edu#include "cpu/checker/cpu.hh"
386019Shines@cs.fsu.edu#include "cpu/simple_thread.hh"
396019Shines@cs.fsu.edu#include "cpu/thread_context.hh"
406019Shines@cs.fsu.edu#include "cpu/static_inst.hh"
416735Sgblack@eecs.umich.edu#include "mem/packet_impl.hh"
426735Sgblack@eecs.umich.edu#include "sim/byteswap.hh"
4310037SARM gem5 Developers#include "sim/sim_object.hh"
4410037SARM gem5 Developers#include "sim/stats.hh"
456019Shines@cs.fsu.edu
466019Shines@cs.fsu.edu#include "cpu/o3/alpha_dyn_inst.hh"
476019Shines@cs.fsu.edu#include "cpu/o3/alpha_impl.hh"
4810037SARM gem5 Developers
4910037SARM gem5 Developers//#include "cpu/ozone/dyn_inst.hh"
5010037SARM gem5 Developers//#include "cpu/ozone/ozone_impl.hh"
5110037SARM gem5 Developers//#include "cpu/ozone/simple_impl.hh"
528229Snate@binkert.org
538229Snate@binkert.org#if FULL_SYSTEM
546019Shines@cs.fsu.edu#include "sim/system.hh"
558232Snate@binkert.org#include "arch/vtophys.hh"
568782Sgblack@eecs.umich.edu#endif // FULL_SYSTEM
576019Shines@cs.fsu.edu
586019Shines@cs.fsu.eduusing namespace std;
596019Shines@cs.fsu.edu//The CheckerCPU does alpha only
606019Shines@cs.fsu.eduusing namespace AlphaISA;
6110037SARM gem5 Developers
6210037SARM gem5 Developersvoid
6310037SARM gem5 DevelopersCheckerCPU::init()
6410037SARM gem5 Developers{
6510037SARM gem5 Developers}
6610037SARM gem5 Developers
6710037SARM gem5 DevelopersCheckerCPU::CheckerCPU(Params *p)
6810037SARM gem5 Developers    : BaseCPU(p), thread(NULL), tc(NULL)
6910037SARM gem5 Developers{
7010037SARM gem5 Developers    memReq = NULL;
7110037SARM gem5 Developers
7210037SARM gem5 Developers    numInst = 0;
7310037SARM gem5 Developers    startNumInst = 0;
7410037SARM gem5 Developers    numLoad = 0;
7510037SARM gem5 Developers    startNumLoad = 0;
7610037SARM gem5 Developers    youngestSN = 0;
7710037SARM gem5 Developers
7810037SARM gem5 Developers    changedPC = willChangePC = changedNextPC = false;
7910037SARM gem5 Developers
8010037SARM gem5 Developers    exitOnError = p->exitOnError;
8110037SARM gem5 Developers#if FULL_SYSTEM
8210037SARM gem5 Developers    itb = p->itb;
8310037SARM gem5 Developers    dtb = p->dtb;
8410037SARM gem5 Developers    systemPtr = NULL;
8510037SARM gem5 Developers#else
8610037SARM gem5 Developers    process = p->process;
8710037SARM gem5 Developers#endif
8810037SARM gem5 Developers
8910037SARM gem5 Developers    result.integer = 0;
9010037SARM gem5 Developers}
9110037SARM gem5 Developers
9210037SARM gem5 DevelopersCheckerCPU::~CheckerCPU()
9310037SARM gem5 Developers{
9410037SARM gem5 Developers}
9510037SARM gem5 Developers
9610037SARM gem5 Developersvoid
9710037SARM gem5 DevelopersCheckerCPU::setMemory(MemObject *mem)
9810037SARM gem5 Developers{
9910037SARM gem5 Developers#if !FULL_SYSTEM
10010037SARM gem5 Developers    memPtr = mem;
1016019Shines@cs.fsu.edu    thread = new SimpleThread(this, /* thread_num */ 0, process,
10210037SARM gem5 Developers                              /* asid */ 0, mem);
10310037SARM gem5 Developers
10410037SARM gem5 Developers    thread->setStatus(ThreadContext::Suspended);
1056019Shines@cs.fsu.edu    tc = thread->getTC();
10610037SARM gem5 Developers    threadContexts.push_back(tc);
10710037SARM gem5 Developers#endif
10810037SARM gem5 Developers}
10910037SARM gem5 Developers
11010037SARM gem5 Developersvoid
11110037SARM gem5 DevelopersCheckerCPU::setSystem(System *system)
11210037SARM gem5 Developers{
11310037SARM gem5 Developers#if FULL_SYSTEM
11410037SARM gem5 Developers    systemPtr = system;
11510037SARM gem5 Developers
11610037SARM gem5 Developers    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
11710037SARM gem5 Developers
11810037SARM gem5 Developers    thread->setStatus(ThreadContext::Suspended);
11910037SARM gem5 Developers    tc = thread->getTC();
12010037SARM gem5 Developers    threadContexts.push_back(tc);
12110037SARM gem5 Developers    delete thread->kernelStats;
12210037SARM gem5 Developers    thread->kernelStats = NULL;
12310037SARM gem5 Developers#endif
12410037SARM gem5 Developers}
12510037SARM gem5 Developers
12610037SARM gem5 Developersvoid
12710037SARM gem5 DevelopersCheckerCPU::setIcachePort(Port *icache_port)
12810037SARM gem5 Developers{
12910037SARM gem5 Developers    icachePort = icache_port;
13010037SARM gem5 Developers}
13110037SARM gem5 Developers
13210037SARM gem5 Developersvoid
13310037SARM gem5 DevelopersCheckerCPU::setDcachePort(Port *dcache_port)
13410037SARM gem5 Developers{
13510037SARM gem5 Developers    dcachePort = dcache_port;
13610037SARM gem5 Developers}
13710037SARM gem5 Developers
13810037SARM gem5 Developersvoid
13910037SARM gem5 DevelopersCheckerCPU::serialize(ostream &os)
14010037SARM gem5 Developers{
14110037SARM gem5 Developers/*
14210037SARM gem5 Developers    BaseCPU::serialize(os);
14310037SARM gem5 Developers    SERIALIZE_SCALAR(inst);
14410037SARM gem5 Developers    nameOut(os, csprintf("%s.xc", name()));
14510037SARM gem5 Developers    thread->serialize(os);
1466019Shines@cs.fsu.edu    cacheCompletionEvent.serialize(os);
14710037SARM gem5 Developers*/
14810037SARM gem5 Developers}
14910037SARM gem5 Developers
1506019Shines@cs.fsu.eduvoid
15110037SARM gem5 DevelopersCheckerCPU::unserialize(Checkpoint *cp, const string &section)
15210037SARM gem5 Developers{
15310037SARM gem5 Developers/*
15410037SARM gem5 Developers    BaseCPU::unserialize(cp, section);
15510037SARM gem5 Developers    UNSERIALIZE_SCALAR(inst);
15610037SARM gem5 Developers    thread->unserialize(cp, csprintf("%s.xc", section));
15710037SARM gem5 Developers*/
15810037SARM gem5 Developers}
15910037SARM gem5 Developers
16010037SARM gem5 DevelopersFault
16110037SARM gem5 DevelopersCheckerCPU::copySrcTranslate(Addr src)
16210037SARM gem5 Developers{
16310037SARM gem5 Developers    panic("Unimplemented!");
16410037SARM gem5 Developers}
16510037SARM gem5 Developers
16610037SARM gem5 DevelopersFault
16710037SARM gem5 DevelopersCheckerCPU::copy(Addr dest)
16810037SARM gem5 Developers{
16910037SARM gem5 Developers    panic("Unimplemented!");
17010037SARM gem5 Developers}
17110037SARM gem5 Developers
17210037SARM gem5 Developerstemplate <class T>
17310037SARM gem5 DevelopersFault
17410037SARM gem5 DevelopersCheckerCPU::read(Addr addr, T &data, unsigned flags)
17510037SARM gem5 Developers{
17610037SARM gem5 Developers    // need to fill in CPU & thread IDs here
17710037SARM gem5 Developers    memReq = new Request();
17810037SARM gem5 Developers
17910037SARM gem5 Developers    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
18010037SARM gem5 Developers
18110037SARM gem5 Developers    // translate to physical address
18210037SARM gem5 Developers    translateDataReadReq(memReq);
18310037SARM gem5 Developers
18410037SARM gem5 Developers    Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
18510037SARM gem5 Developers
18610037SARM gem5 Developers    pkt->dataStatic(&data);
18710037SARM gem5 Developers
18810037SARM gem5 Developers    if (!(memReq->getFlags() & UNCACHEABLE)) {
18910037SARM gem5 Developers        // Access memory to see if we have the same data
19010037SARM gem5 Developers        dcachePort->sendFunctional(pkt);
19110037SARM gem5 Developers    } else {
1926019Shines@cs.fsu.edu        // Assume the data is correct if it's an uncached access
19310037SARM gem5 Developers        memcpy(&data, &unverifiedResult.integer, sizeof(T));
19410037SARM gem5 Developers    }
19510037SARM gem5 Developers
1966019Shines@cs.fsu.edu    delete pkt;
19710037SARM gem5 Developers
19810037SARM gem5 Developers    return NoFault;
19910037SARM gem5 Developers}
20010037SARM gem5 Developers
20110037SARM gem5 Developers#ifndef DOXYGEN_SHOULD_SKIP_THIS
20210037SARM gem5 Developers
20310037SARM gem5 Developerstemplate
20410037SARM gem5 DevelopersFault
20510037SARM gem5 DevelopersCheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
20610037SARM gem5 Developers
20710037SARM gem5 Developerstemplate
20810037SARM gem5 DevelopersFault
20910037SARM gem5 DevelopersCheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
21010037SARM gem5 Developers
21110037SARM gem5 Developerstemplate
21210037SARM gem5 DevelopersFault
21310037SARM gem5 DevelopersCheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
21410037SARM gem5 Developers
21510037SARM gem5 Developerstemplate
21610037SARM gem5 DevelopersFault
21710037SARM gem5 DevelopersCheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
21810037SARM gem5 Developers
21910037SARM gem5 Developers#endif //DOXYGEN_SHOULD_SKIP_THIS
22010037SARM gem5 Developers
22110037SARM gem5 Developerstemplate<>
22210037SARM gem5 DevelopersFault
22310037SARM gem5 DevelopersCheckerCPU::read(Addr addr, double &data, unsigned flags)
22410037SARM gem5 Developers{
22510037SARM gem5 Developers    return read(addr, *(uint64_t*)&data, flags);
22610037SARM gem5 Developers}
22710037SARM gem5 Developers
22810037SARM gem5 Developerstemplate<>
22910037SARM gem5 DevelopersFault
23010037SARM gem5 DevelopersCheckerCPU::read(Addr addr, float &data, unsigned flags)
23110037SARM gem5 Developers{
23210037SARM gem5 Developers    return read(addr, *(uint32_t*)&data, flags);
23310037SARM gem5 Developers}
23410037SARM gem5 Developers
23510037SARM gem5 Developerstemplate<>
23610037SARM gem5 DevelopersFault
23710037SARM gem5 DevelopersCheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
23810037SARM gem5 Developers{
23910037SARM gem5 Developers    return read(addr, (uint32_t&)data, flags);
24010037SARM gem5 Developers}
24110037SARM gem5 Developers
24210037SARM gem5 Developerstemplate <class T>
24310037SARM gem5 DevelopersFault
24410037SARM gem5 DevelopersCheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
24510037SARM gem5 Developers{
24610037SARM gem5 Developers    // need to fill in CPU & thread IDs here
24710037SARM gem5 Developers    memReq = new Request();
24810037SARM gem5 Developers
24910037SARM gem5 Developers    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
25010037SARM gem5 Developers
25110037SARM gem5 Developers    // translate to physical address
25210037SARM gem5 Developers    thread->translateDataWriteReq(memReq);
25310037SARM gem5 Developers
25410037SARM gem5 Developers    // Can compare the write data and result only if it's cacheable,
25510037SARM gem5 Developers    // not a store conditional, or is a store conditional that
25610037SARM gem5 Developers    // succeeded.
25710037SARM gem5 Developers    // @todo: Verify that actual memory matches up with these values.
25810037SARM gem5 Developers    // Right now it only verifies that the instruction data is the
25910037SARM gem5 Developers    // same as what was in the request that got sent to memory; there
26010037SARM gem5 Developers    // is no verification that it is the same as what is in memory.
26110037SARM gem5 Developers    // This is because the LSQ would have to be snooped in the CPU to
26210037SARM gem5 Developers    // verify this data.
26310037SARM gem5 Developers    if (unverifiedReq &&
26410037SARM gem5 Developers        !(unverifiedReq->getFlags() & UNCACHEABLE) &&
26510037SARM gem5 Developers        (!(unverifiedReq->getFlags() & LOCKED) ||
26610037SARM gem5 Developers         ((unverifiedReq->getFlags() & LOCKED) &&
26710037SARM gem5 Developers          unverifiedReq->getScResult() == 1))) {
26810037SARM gem5 Developers        T inst_data;
26910037SARM gem5 Developers/*
27010037SARM gem5 Developers        // This code would work if the LSQ allowed for snooping.
27110037SARM gem5 Developers        Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
27210037SARM gem5 Developers        pkt.dataStatic(&inst_data);
27310037SARM gem5 Developers
27410037SARM gem5 Developers        dcachePort->sendFunctional(pkt);
27510037SARM gem5 Developers
27610037SARM gem5 Developers        delete pkt;
27710037SARM gem5 Developers*/
27810037SARM gem5 Developers        memcpy(&inst_data, unverifiedMemData, sizeof(T));
27910037SARM gem5 Developers
28010037SARM gem5 Developers        if (data != inst_data) {
28110037SARM gem5 Developers            warn("%lli: Store value does not match value in memory! "
28210037SARM gem5 Developers                 "Instruction: %#x, memory: %#x",
28310037SARM gem5 Developers                 curTick, inst_data, data);
28410037SARM gem5 Developers            handleError();
28510037SARM gem5 Developers        }
28610037SARM gem5 Developers    }
28710037SARM gem5 Developers
28810037SARM gem5 Developers    // Assume the result was the same as the one passed in.  This checker
28910037SARM gem5 Developers    // doesn't check if the SC should succeed or fail, it just checks the
29010037SARM gem5 Developers    // value.
29110037SARM gem5 Developers    if (res && unverifiedReq->scResultValid())
29210037SARM gem5 Developers        *res = unverifiedReq->getScResult();
29310037SARM gem5 Developers
29410037SARM gem5 Developers    return NoFault;
2956019Shines@cs.fsu.edu}
29610037SARM gem5 Developers
2977362Sgblack@eecs.umich.edu
2986735Sgblack@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
29910037SARM gem5 Developerstemplate
3006019Shines@cs.fsu.eduFault
30110037SARM gem5 DevelopersCheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
30210037SARM gem5 Developers
3037400SAli.Saidi@ARM.comtemplate
3046735Sgblack@eecs.umich.eduFault
3056735Sgblack@eecs.umich.eduCheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
30610037SARM gem5 Developers
3076735Sgblack@eecs.umich.edutemplate
30810037SARM gem5 DevelopersFault
30910037SARM gem5 DevelopersCheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
31010037SARM gem5 Developers
31110037SARM gem5 Developerstemplate
3127400SAli.Saidi@ARM.comFault
31310037SARM gem5 DevelopersCheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
31410037SARM gem5 Developers
31510037SARM gem5 Developers#endif //DOXYGEN_SHOULD_SKIP_THIS
31610037SARM gem5 Developers
31710037SARM gem5 Developerstemplate<>
31810037SARM gem5 DevelopersFault
31910037SARM gem5 DevelopersCheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
32010037SARM gem5 Developers{
32110037SARM gem5 Developers    return write(*(uint64_t*)&data, addr, flags, res);
32210037SARM gem5 Developers}
32310037SARM gem5 Developers
32410037SARM gem5 Developerstemplate<>
32510037SARM gem5 DevelopersFault
32610037SARM gem5 DevelopersCheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
32710037SARM gem5 Developers{
32810037SARM gem5 Developers    return write(*(uint32_t*)&data, addr, flags, res);
32910037SARM gem5 Developers}
3306019Shines@cs.fsu.edu
3316019Shines@cs.fsu.edutemplate<>
33210037SARM gem5 DevelopersFault
33310037SARM gem5 DevelopersCheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
33410037SARM gem5 Developers{
33510037SARM gem5 Developers    return write((uint32_t)data, addr, flags, res);
33610037SARM gem5 Developers}
33710037SARM gem5 Developers
33810037SARM gem5 Developers
33910037SARM gem5 Developers#if FULL_SYSTEM
34010037SARM gem5 DevelopersAddr
34110037SARM gem5 DevelopersCheckerCPU::dbg_vtophys(Addr addr)
34210037SARM gem5 Developers{
34310037SARM gem5 Developers    return vtophys(tc, addr);
34410037SARM gem5 Developers}
34510037SARM gem5 Developers#endif // FULL_SYSTEM
34610037SARM gem5 Developers
34710037SARM gem5 Developersbool
34810037SARM gem5 DevelopersCheckerCPU::translateInstReq(Request *req)
34910037SARM gem5 Developers{
35010037SARM gem5 Developers#if FULL_SYSTEM
35110037SARM gem5 Developers    return (thread->translateInstReq(req) == NoFault);
35210037SARM gem5 Developers#else
35310037SARM gem5 Developers    thread->translateInstReq(req);
35410037SARM gem5 Developers    return true;
35510037SARM gem5 Developers#endif
35610037SARM gem5 Developers}
35710037SARM gem5 Developers
35810037SARM gem5 Developersvoid
35910037SARM gem5 DevelopersCheckerCPU::translateDataReadReq(Request *req)
36010037SARM gem5 Developers{
36110037SARM gem5 Developers    thread->translateDataReadReq(req);
36210037SARM gem5 Developers
36310037SARM gem5 Developers    if (req->getVaddr() != unverifiedReq->getVaddr()) {
36410037SARM gem5 Developers        warn("%lli: Request virtual addresses do not match! Inst: %#x, "
36510037SARM gem5 Developers             "checker: %#x",
36610037SARM gem5 Developers             curTick, unverifiedReq->getVaddr(), req->getVaddr());
36710037SARM gem5 Developers        handleError();
36810037SARM gem5 Developers    }
36910037SARM gem5 Developers    req->setPaddr(unverifiedReq->getPaddr());
37010037SARM gem5 Developers
37110037SARM gem5 Developers    if (checkFlags(req)) {
37210037SARM gem5 Developers        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
37310037SARM gem5 Developers             curTick, unverifiedReq->getFlags(), req->getFlags());
37410037SARM gem5 Developers        handleError();
37510037SARM gem5 Developers    }
37610037SARM gem5 Developers}
37710037SARM gem5 Developers
37810037SARM gem5 Developersvoid
37910037SARM gem5 DevelopersCheckerCPU::translateDataWriteReq(Request *req)
38010037SARM gem5 Developers{
38110037SARM gem5 Developers    thread->translateDataWriteReq(req);
38210037SARM gem5 Developers
38310037SARM gem5 Developers    if (req->getVaddr() != unverifiedReq->getVaddr()) {
38410037SARM gem5 Developers        warn("%lli: Request virtual addresses do not match! Inst: %#x, "
38510037SARM gem5 Developers             "checker: %#x",
38610037SARM gem5 Developers             curTick, unverifiedReq->getVaddr(), req->getVaddr());
38710037SARM gem5 Developers        handleError();
38810037SARM gem5 Developers    }
38910037SARM gem5 Developers    req->setPaddr(unverifiedReq->getPaddr());
39010037SARM gem5 Developers
39110037SARM gem5 Developers    if (checkFlags(req)) {
39210037SARM gem5 Developers        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
39310037SARM gem5 Developers             curTick, unverifiedReq->getFlags(), req->getFlags());
39410037SARM gem5 Developers        handleError();
39510037SARM gem5 Developers    }
39610037SARM gem5 Developers}
39710037SARM gem5 Developers
39810037SARM gem5 Developersbool
39910037SARM gem5 DevelopersCheckerCPU::checkFlags(Request *req)
40010037SARM gem5 Developers{
40110037SARM gem5 Developers    // Remove any dynamic flags that don't have to do with the request itself.
40210037SARM gem5 Developers    unsigned flags = unverifiedReq->getFlags();
40310037SARM gem5 Developers    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
40410037SARM gem5 Developers    flags = flags & (mask);
40510037SARM gem5 Developers    if (flags == req->getFlags()) {
40610037SARM gem5 Developers        return false;
40710037SARM gem5 Developers    } else {
40810037SARM gem5 Developers        return true;
40910037SARM gem5 Developers    }
41010037SARM gem5 Developers}
41110037SARM gem5 Developers
41210037SARM gem5 Developerstemplate <class DynInstPtr>
41310037SARM gem5 Developersvoid
41410037SARM gem5 DevelopersChecker<DynInstPtr>::tick(DynInstPtr &completed_inst)
41510037SARM gem5 Developers{
41610037SARM gem5 Developers    DynInstPtr inst;
41710037SARM gem5 Developers
41810037SARM gem5 Developers    // Either check this instruction, or add it to a list of
41910037SARM gem5 Developers    // instructions waiting to be checked.  Instructions must be
42010037SARM gem5 Developers    // checked in program order, so if a store has committed yet not
42110037SARM gem5 Developers    // completed, there may be some instructions that are waiting
42210037SARM gem5 Developers    // behind it that have completed and must be checked.
42310037SARM gem5 Developers    if (!instList.empty()) {
42410037SARM gem5 Developers        if (youngestSN < completed_inst->seqNum) {
42510037SARM gem5 Developers            DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
42610037SARM gem5 Developers                    completed_inst->seqNum, completed_inst->readPC());
42710037SARM gem5 Developers            instList.push_back(completed_inst);
42810037SARM gem5 Developers            youngestSN = completed_inst->seqNum;
42910417Sandreas.hansson@arm.com        }
4306019Shines@cs.fsu.edu
43110037SARM gem5 Developers        if (!instList.front()->isCompleted()) {
43210037SARM gem5 Developers            return;
43310037SARM gem5 Developers        } else {
43410037SARM gem5 Developers            inst = instList.front();
43510037SARM gem5 Developers            instList.pop_front();
43610037SARM gem5 Developers        }
43710037SARM gem5 Developers    } else {
43810037SARM gem5 Developers        if (!completed_inst->isCompleted()) {
43910037SARM gem5 Developers            if (youngestSN < completed_inst->seqNum) {
44010037SARM gem5 Developers                DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
44110037SARM gem5 Developers                        completed_inst->seqNum, completed_inst->readPC());
44210037SARM gem5 Developers                instList.push_back(completed_inst);
44310037SARM gem5 Developers                youngestSN = completed_inst->seqNum;
44410037SARM gem5 Developers            }
44510037SARM gem5 Developers            return;
44610037SARM gem5 Developers        } else {
44710037SARM gem5 Developers            if (youngestSN < completed_inst->seqNum) {
44810037SARM gem5 Developers                inst = completed_inst;
44910037SARM gem5 Developers                youngestSN = completed_inst->seqNum;
45010037SARM gem5 Developers            } else {
45110037SARM gem5 Developers                return;
45210037SARM gem5 Developers            }
45310037SARM gem5 Developers        }
45410037SARM gem5 Developers    }
45510037SARM gem5 Developers
45610037SARM gem5 Developers    // Try to check all instructions that are completed, ending if we
45710037SARM gem5 Developers    // run out of instructions to check or if an instruction is not
45810037SARM gem5 Developers    // yet completed.
45910037SARM gem5 Developers    while (1) {
46010037SARM gem5 Developers        DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
4616735Sgblack@eecs.umich.edu                inst->seqNum, inst->readPC());
4628782Sgblack@eecs.umich.edu        unverifiedResult.integer = inst->readIntResult();
4638782Sgblack@eecs.umich.edu        unverifiedReq = inst->req;
4646735Sgblack@eecs.umich.edu        unverifiedMemData = inst->memData;
4656019Shines@cs.fsu.edu        numCycles++;
4666735Sgblack@eecs.umich.edu
46710037SARM gem5 Developers        Fault fault = NoFault;
4688303SAli.Saidi@ARM.com
46910338SCurtis.Dunham@arm.com        // maintain $r0 semantics
47010338SCurtis.Dunham@arm.com        thread->setIntReg(ZeroReg, 0);
47110338SCurtis.Dunham@arm.com#ifdef TARGET_ALPHA
47210338SCurtis.Dunham@arm.com        thread->setFloatRegDouble(ZeroReg, 0.0);
4738303SAli.Saidi@ARM.com#endif // TARGET_ALPHA
4747720Sgblack@eecs.umich.edu
4758205SAli.Saidi@ARM.com        // Check if any recent PC changes match up with anything we
4768205SAli.Saidi@ARM.com        // expect to happen.  This is mostly to check if traps or
4778205SAli.Saidi@ARM.com        // PC-based events have occurred in both the checker and CPU.
4786735Sgblack@eecs.umich.edu        if (changedPC) {
47910037SARM gem5 Developers            DPRINTF(Checker, "Changed PC recently to %#x\n",
48010037SARM gem5 Developers                    thread->readPC());
48110037SARM gem5 Developers            if (willChangePC) {
48210037SARM gem5 Developers                if (newPC == thread->readPC()) {
48310037SARM gem5 Developers                    DPRINTF(Checker, "Changed PC matches expected PC\n");
48410037SARM gem5 Developers                } else {
48510037SARM gem5 Developers                    warn("%lli: Changed PC does not match expected PC, "
48610037SARM gem5 Developers                         "changed: %#x, expected: %#x",
48710037SARM gem5 Developers                         curTick, thread->readPC(), newPC);
48810037SARM gem5 Developers                    handleError();
48910037SARM gem5 Developers                }
49010037SARM gem5 Developers                willChangePC = false;
49110037SARM gem5 Developers            }
49210037SARM gem5 Developers            changedPC = false;
49310037SARM gem5 Developers        }
49410037SARM gem5 Developers        if (changedNextPC) {
49510037SARM gem5 Developers            DPRINTF(Checker, "Changed NextPC recently to %#x\n",
49610037SARM gem5 Developers                    thread->readNextPC());
49710037SARM gem5 Developers            changedNextPC = false;
49810037SARM gem5 Developers        }
49910037SARM gem5 Developers
50010037SARM gem5 Developers        // Try to fetch the instruction
50110037SARM gem5 Developers
50210037SARM gem5 Developers#if FULL_SYSTEM
50310037SARM gem5 Developers#define IFETCH_FLAGS(pc)	((pc) & 1) ? PHYSICAL : 0
50410037SARM gem5 Developers#else
50510037SARM gem5 Developers#define IFETCH_FLAGS(pc)	0
50610037SARM gem5 Developers#endif
50710037SARM gem5 Developers
50810037SARM gem5 Developers        uint64_t fetch_PC = thread->readPC() & ~3;
50910037SARM gem5 Developers
51010037SARM gem5 Developers        // set up memory request for instruction fetch
51110037SARM gem5 Developers        memReq = new Request(inst->threadNumber, fetch_PC,
51210037SARM gem5 Developers                             sizeof(uint32_t),
51310037SARM gem5 Developers                             IFETCH_FLAGS(thread->readPC()),
51410037SARM gem5 Developers                             fetch_PC, thread->readCpuId(), inst->threadNumber);
51510037SARM gem5 Developers
51610037SARM gem5 Developers        bool succeeded = translateInstReq(memReq);
51710037SARM gem5 Developers
51810037SARM gem5 Developers        if (!succeeded) {
51910037SARM gem5 Developers            if (inst->getFault() == NoFault) {
52010037SARM gem5 Developers                // In this case the instruction was not a dummy
52110037SARM gem5 Developers                // instruction carrying an ITB fault.  In the single
52210037SARM gem5 Developers                // threaded case the ITB should still be able to
52310037SARM gem5 Developers                // translate this instruction; in the SMT case it's
52410037SARM gem5 Developers                // possible that its ITB entry was kicked out.
52510037SARM gem5 Developers                warn("%lli: Instruction PC %#x was not found in the ITB!",
52610037SARM gem5 Developers                     curTick, thread->readPC());
5276735Sgblack@eecs.umich.edu                handleError();
5286735Sgblack@eecs.umich.edu
5296735Sgblack@eecs.umich.edu                // go to the next instruction
53010037SARM gem5 Developers                thread->setPC(thread->readNextPC());
5318518Sgeoffrey.blake@arm.com                thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
5328518Sgeoffrey.blake@arm.com
5336735Sgblack@eecs.umich.edu                return;
53410037SARM gem5 Developers            } else {
53510037SARM gem5 Developers                // The instruction is carrying an ITB fault.  Handle
53610037SARM gem5 Developers                // the fault and see if our results match the CPU on
53710037SARM gem5 Developers                // the next tick().
53810037SARM gem5 Developers                fault = inst->getFault();
53910037SARM gem5 Developers            }
54010037SARM gem5 Developers        }
54110037SARM gem5 Developers
54210037SARM gem5 Developers        if (fault == NoFault) {
54310037SARM gem5 Developers            Packet *pkt = new Packet(memReq, Packet::ReadReq,
54410037SARM gem5 Developers                                     Packet::Broadcast);
54510037SARM gem5 Developers
5466735Sgblack@eecs.umich.edu            pkt->dataStatic(&machInst);
5476735Sgblack@eecs.umich.edu
5486735Sgblack@eecs.umich.edu            icachePort->sendFunctional(pkt);
5496735Sgblack@eecs.umich.edu
5506735Sgblack@eecs.umich.edu            delete pkt;
5516735Sgblack@eecs.umich.edu
5526735Sgblack@eecs.umich.edu            // keep an instruction count
5536735Sgblack@eecs.umich.edu            numInst++;
5546735Sgblack@eecs.umich.edu
55510037SARM gem5 Developers            // decode the instruction
55610037SARM gem5 Developers            machInst = gtoh(machInst);
55710037SARM gem5 Developers            // Checks that the instruction matches what we expected it to be.
5586735Sgblack@eecs.umich.edu            // Checks both the machine instruction and the PC.
5596735Sgblack@eecs.umich.edu            validateInst(inst);
5606735Sgblack@eecs.umich.edu
5616735Sgblack@eecs.umich.edu            curStaticInst = StaticInst::decode(makeExtMI(machInst,
56210037SARM gem5 Developers                                                         thread->readPC()));
56310037SARM gem5 Developers
56410037SARM gem5 Developers#if FULL_SYSTEM
56510037SARM gem5 Developers            thread->setInst(machInst);
56610037SARM gem5 Developers#endif // FULL_SYSTEM
56710037SARM gem5 Developers
56810037SARM gem5 Developers            fault = inst->getFault();
56910037SARM gem5 Developers        }
57010037SARM gem5 Developers
57110037SARM gem5 Developers        // Discard fetch's memReq.
5726735Sgblack@eecs.umich.edu        delete memReq;
5736735Sgblack@eecs.umich.edu        memReq = NULL;
5747093Sgblack@eecs.umich.edu
5757093Sgblack@eecs.umich.edu        // Either the instruction was a fault and we should process the fault,
5767720Sgblack@eecs.umich.edu        // or we should just go ahead execute the instruction.  This assumes
5777585SAli.Saidi@arm.com        // that the instruction is properly marked as a fault.
5787720Sgblack@eecs.umich.edu        if (fault == NoFault) {
5797720Sgblack@eecs.umich.edu
5807720Sgblack@eecs.umich.edu            thread->funcExeInst++;
5817720Sgblack@eecs.umich.edu
5827720Sgblack@eecs.umich.edu            fault = curStaticInst->execute(this, NULL);
5837720Sgblack@eecs.umich.edu
58410037SARM gem5 Developers            // Checks to make sure instrution results are correct.
58510037SARM gem5 Developers            validateExecution(inst);
5867720Sgblack@eecs.umich.edu
5876019Shines@cs.fsu.edu            if (curStaticInst->isLoad()) {
5887189Sgblack@eecs.umich.edu                ++numLoad;
5897400SAli.Saidi@ARM.com            }
59010417Sandreas.hansson@arm.com        }
59110037SARM gem5 Developers
59210037SARM gem5 Developers        if (fault != NoFault) {
59310037SARM gem5 Developers#if FULL_SYSTEM
59410037SARM gem5 Developers            fault->invoke(tc);
59510037SARM gem5 Developers            willChangePC = true;
59610037SARM gem5 Developers            newPC = thread->readPC();
59710037SARM gem5 Developers            DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
59810037SARM gem5 Developers#else // !FULL_SYSTEM
59910037SARM gem5 Developers            fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC());
60010037SARM gem5 Developers#endif // FULL_SYSTEM
60110037SARM gem5 Developers        } else {
60210037SARM gem5 Developers#if THE_ISA != MIPS_ISA
60310037SARM gem5 Developers            // go to the next instruction
60410037SARM gem5 Developers            thread->setPC(thread->readNextPC());
60510037SARM gem5 Developers            thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
60610037SARM gem5 Developers#else
60710037SARM gem5 Developers            // go to the next instruction
60810037SARM gem5 Developers            thread->setPC(thread->readNextPC());
60910037SARM gem5 Developers            thread->setNextPC(thread->readNextNPC());
61010037SARM gem5 Developers            thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
61110037SARM gem5 Developers#endif
61210037SARM gem5 Developers
61310037SARM gem5 Developers        }
61410037SARM gem5 Developers
61510037SARM gem5 Developers#if FULL_SYSTEM
61610037SARM gem5 Developers        // @todo: Determine if these should happen only if the
61710037SARM gem5 Developers        // instruction hasn't faulted.  In the SimpleCPU case this may
61810338SCurtis.Dunham@arm.com        // not be true, but in the O3 or Ozone case this may be true.
61910338SCurtis.Dunham@arm.com        Addr oldpc;
62010338SCurtis.Dunham@arm.com        int count = 0;
62110037SARM gem5 Developers        do {
62210037SARM gem5 Developers            oldpc = thread->readPC();
62310037SARM gem5 Developers            system->pcEventQueue.service(tc);
62410037SARM gem5 Developers            count++;
62510037SARM gem5 Developers        } while (oldpc != thread->readPC());
62610037SARM gem5 Developers        if (count > 1) {
62710037SARM gem5 Developers            willChangePC = true;
62810037SARM gem5 Developers            newPC = thread->readPC();
62910037SARM gem5 Developers            DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
63010037SARM gem5 Developers        }
63110338SCurtis.Dunham@arm.com#endif
63210037SARM gem5 Developers
63310037SARM gem5 Developers        // @todo:  Optionally can check all registers. (Or just those
63410037SARM gem5 Developers        // that have been modified).
63510037SARM gem5 Developers        validateState();
63610037SARM gem5 Developers
63710037SARM gem5 Developers        if (memReq) {
63810037SARM gem5 Developers            delete memReq;
63910037SARM gem5 Developers            memReq = NULL;
64010037SARM gem5 Developers        }
64110037SARM gem5 Developers
64210037SARM gem5 Developers        // Continue verifying instructions if there's another completed
64310037SARM gem5 Developers        // instruction waiting to be verified.
64410037SARM gem5 Developers        if (instList.empty()) {
64510037SARM gem5 Developers            break;
64610037SARM gem5 Developers        } else if (instList.front()->isCompleted()) {
64710037SARM gem5 Developers            inst = instList.front();
64810037SARM gem5 Developers            instList.pop_front();
64910037SARM gem5 Developers        } else {
65010037SARM gem5 Developers            break;
65110037SARM gem5 Developers        }
65210037SARM gem5 Developers    }
65310037SARM gem5 Developers}
65410037SARM gem5 Developers
65510037SARM gem5 Developerstemplate <class DynInstPtr>
65610037SARM gem5 Developersvoid
65710037SARM gem5 DevelopersChecker<DynInstPtr>::switchOut(Sampler *s)
65810037SARM gem5 Developers{
65910037SARM gem5 Developers    instList.clear();
66010037SARM gem5 Developers}
66110037SARM gem5 Developers
66210037SARM gem5 Developerstemplate <class DynInstPtr>
66310037SARM gem5 Developersvoid
66410037SARM gem5 DevelopersChecker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
66510037SARM gem5 Developers{
66610037SARM gem5 Developers}
66710037SARM gem5 Developers
66810037SARM gem5 Developerstemplate <class DynInstPtr>
66910037SARM gem5 Developersvoid
67010037SARM gem5 DevelopersChecker<DynInstPtr>::validateInst(DynInstPtr &inst)
67110037SARM gem5 Developers{
67210037SARM gem5 Developers    if (inst->readPC() != thread->readPC()) {
67310037SARM gem5 Developers        warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
67410037SARM gem5 Developers             curTick, inst->readPC(), thread->readPC());
67510037SARM gem5 Developers        if (changedPC) {
67610037SARM gem5 Developers            warn("%lli: Changed PCs recently, may not be an error",
67710037SARM gem5 Developers                 curTick);
67810037SARM gem5 Developers        } else {
67910037SARM gem5 Developers            handleError();
68010037SARM gem5 Developers        }
68110417Sandreas.hansson@arm.com    }
6827400SAli.Saidi@ARM.com
6838782Sgblack@eecs.umich.edu    MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
68411150Smitch.hayenga@arm.com
6858782Sgblack@eecs.umich.edu    if (mi != machInst) {
6868782Sgblack@eecs.umich.edu        warn("%lli: Binary instructions do not match! Inst: %#x, "
68710037SARM gem5 Developers             "checker: %#x",
68810037SARM gem5 Developers             curTick, mi, machInst);
68910037SARM gem5 Developers        handleError();
69010037SARM gem5 Developers    }
69110037SARM gem5 Developers}
69210037SARM gem5 Developers
69310037SARM gem5 Developerstemplate <class DynInstPtr>
69410037SARM gem5 Developersvoid
69510037SARM gem5 DevelopersChecker<DynInstPtr>::validateExecution(DynInstPtr &inst)
69610037SARM gem5 Developers{
69710037SARM gem5 Developers    if (inst->numDestRegs()) {
69810037SARM gem5 Developers        // @todo: Support more destination registers.
69910037SARM gem5 Developers        if (inst->isUnverifiable()) {
70010037SARM gem5 Developers            // Unverifiable instructions assume they were executed
70110037SARM gem5 Developers            // properly by the CPU. Grab the result from the
70210037SARM gem5 Developers            // instruction and write it to the register.
70310037SARM gem5 Developers            RegIndex idx = inst->destRegIdx(0);
70410037SARM gem5 Developers            if (idx < TheISA::FP_Base_DepTag) {
70510037SARM gem5 Developers                thread->setIntReg(idx, inst->readIntResult());
7067400SAli.Saidi@ARM.com            } else if (idx < TheISA::Fpcr_DepTag) {
7077400SAli.Saidi@ARM.com                thread->setFloatRegBits(idx, inst->readIntResult());
7087189Sgblack@eecs.umich.edu            } else {
70910417Sandreas.hansson@arm.com                thread->setMiscReg(idx, inst->readIntResult());
7107189Sgblack@eecs.umich.edu            }
7118782Sgblack@eecs.umich.edu        } else if (result.integer != inst->readIntResult()) {
7128782Sgblack@eecs.umich.edu            warn("%lli: Instruction results do not match! (Values may not "
7138806Sgblack@eecs.umich.edu                 "actually be integers) Inst: %#x, checker: %#x",
7148806Sgblack@eecs.umich.edu                 curTick, inst->readIntResult(), result.integer);
7158806Sgblack@eecs.umich.edu            handleError();
7168806Sgblack@eecs.umich.edu        }
7178806Sgblack@eecs.umich.edu    }
7188806Sgblack@eecs.umich.edu
7198806Sgblack@eecs.umich.edu    if (inst->readNextPC() != thread->readNextPC()) {
7208806Sgblack@eecs.umich.edu        warn("%lli: Instruction next PCs do not match! Inst: %#x, "
7218806Sgblack@eecs.umich.edu             "checker: %#x",
7228806Sgblack@eecs.umich.edu             curTick, inst->readNextPC(), thread->readNextPC());
7238806Sgblack@eecs.umich.edu        handleError();
7247189Sgblack@eecs.umich.edu    }
7258806Sgblack@eecs.umich.edu
7268806Sgblack@eecs.umich.edu    // Checking side effect registers can be difficult if they are not
7277189Sgblack@eecs.umich.edu    // checked simultaneously with the execution of the instruction.
7287189Sgblack@eecs.umich.edu    // This is because other valid instructions may have modified
7297189Sgblack@eecs.umich.edu    // these registers in the meantime, and their values are not
73010037SARM gem5 Developers    // stored within the DynInst.
73110037SARM gem5 Developers    while (!miscRegIdxs.empty()) {
73210037SARM gem5 Developers        int misc_reg_idx = miscRegIdxs.front();
73310037SARM gem5 Developers        miscRegIdxs.pop();
73410037SARM gem5 Developers
73510037SARM gem5 Developers        if (inst->tcBase()->readMiscReg(misc_reg_idx) !=
73610037SARM gem5 Developers            thread->readMiscReg(misc_reg_idx)) {
73710037SARM gem5 Developers            warn("%lli: Misc reg idx %i (side effect) does not match! "
73810037SARM gem5 Developers                 "Inst: %#x, checker: %#x",
73910037SARM gem5 Developers                 curTick, misc_reg_idx,
74010037SARM gem5 Developers                 inst->tcBase()->readMiscReg(misc_reg_idx),
74110037SARM gem5 Developers                 thread->readMiscReg(misc_reg_idx));
74210037SARM gem5 Developers            handleError();
74310037SARM gem5 Developers        }
74410037SARM gem5 Developers    }
74510037SARM gem5 Developers}
74610037SARM gem5 Developers
74710037SARM gem5 Developerstemplate <class DynInstPtr>
74810037SARM gem5 Developersvoid
74910037SARM gem5 DevelopersChecker<DynInstPtr>::validateState()
75010037SARM gem5 Developers{
75110037SARM gem5 Developers}
75210037SARM gem5 Developers
75310037SARM gem5 Developerstemplate <class DynInstPtr>
75410037SARM gem5 Developersvoid
75510037SARM gem5 DevelopersChecker<DynInstPtr>::dumpInsts()
75610037SARM gem5 Developers{
75710037SARM gem5 Developers    int num = 0;
75810037SARM gem5 Developers
75910037SARM gem5 Developers    InstListIt inst_list_it = --(instList.end());
76010037SARM gem5 Developers
76110037SARM gem5 Developers    cprintf("Inst list size: %i\n", instList.size());
76210037SARM gem5 Developers
76310037SARM gem5 Developers    while (inst_list_it != instList.end())
76410037SARM gem5 Developers    {
76510037SARM gem5 Developers        cprintf("Instruction:%i\n",
76610037SARM gem5 Developers                num);
76710037SARM gem5 Developers
76810037SARM gem5 Developers        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
7697197Sgblack@eecs.umich.edu                "Completed:%i\n",
77010417Sandreas.hansson@arm.com                (*inst_list_it)->readPC(),
7717197Sgblack@eecs.umich.edu                (*inst_list_it)->seqNum,
7728782Sgblack@eecs.umich.edu                (*inst_list_it)->threadNumber,
7738782Sgblack@eecs.umich.edu                (*inst_list_it)->isCompleted());
7748806Sgblack@eecs.umich.edu
7758806Sgblack@eecs.umich.edu        cprintf("\n");
7767197Sgblack@eecs.umich.edu
7778806Sgblack@eecs.umich.edu        inst_list_it--;
7788806Sgblack@eecs.umich.edu        ++num;
7798806Sgblack@eecs.umich.edu    }
78010037SARM gem5 Developers
78110037SARM gem5 Developers}
78210037SARM gem5 Developers
78310037SARM gem5 Developers//template
78410037SARM gem5 Developers//class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
78510037SARM gem5 Developers
7868806Sgblack@eecs.umich.edutemplate
7878806Sgblack@eecs.umich.educlass Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
7888806Sgblack@eecs.umich.edu