cpu.cc revision 6102
12789Sktlim@umich.edu/*
22789Sktlim@umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
32789Sktlim@umich.edu * All rights reserved.
42789Sktlim@umich.edu *
52789Sktlim@umich.edu * Redistribution and use in source and binary forms, with or without
62789Sktlim@umich.edu * modification, are permitted provided that the following conditions are
72789Sktlim@umich.edu * met: redistributions of source code must retain the above copyright
82789Sktlim@umich.edu * notice, this list of conditions and the following disclaimer;
92789Sktlim@umich.edu * redistributions in binary form must reproduce the above copyright
102789Sktlim@umich.edu * notice, this list of conditions and the following disclaimer in the
112789Sktlim@umich.edu * documentation and/or other materials provided with the distribution;
122789Sktlim@umich.edu * neither the name of the copyright holders nor the names of its
132789Sktlim@umich.edu * contributors may be used to endorse or promote products derived from
142789Sktlim@umich.edu * this software without specific prior written permission.
152789Sktlim@umich.edu *
162789Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172789Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182789Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192789Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202789Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212789Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222789Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232789Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242789Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252789Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262789Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272789Sktlim@umich.edu *
282789Sktlim@umich.edu * Authors: Kevin Lim
292789Sktlim@umich.edu */
302789Sktlim@umich.edu
312789Sktlim@umich.edu#include <list>
322789Sktlim@umich.edu#include <string>
332789Sktlim@umich.edu
342789Sktlim@umich.edu#include "cpu/base.hh"
352789Sktlim@umich.edu#include "cpu/checker/cpu.hh"
362789Sktlim@umich.edu#include "cpu/simple_thread.hh"
373348Sbinkertn@umich.edu#include "cpu/static_inst.hh"
382789Sktlim@umich.edu#include "cpu/thread_context.hh"
392789Sktlim@umich.edu
402789Sktlim@umich.edu#if FULL_SYSTEM
413565Sgblack@eecs.umich.edu#include "arch/kernel_stats.hh"
422789Sktlim@umich.edu#include "arch/vtophys.hh"
432789Sktlim@umich.edu#endif // FULL_SYSTEM
442789Sktlim@umich.edu
452789Sktlim@umich.eduusing namespace std;
462789Sktlim@umich.edu//The CheckerCPU does alpha only
472789Sktlim@umich.eduusing namespace AlphaISA;
482789Sktlim@umich.edu
492789Sktlim@umich.eduvoid
502789Sktlim@umich.eduCheckerCPU::init()
512789Sktlim@umich.edu{
522789Sktlim@umich.edu}
532789Sktlim@umich.edu
542789Sktlim@umich.eduCheckerCPU::CheckerCPU(Params *p)
552789Sktlim@umich.edu    : BaseCPU(p), thread(NULL), tc(NULL)
562789Sktlim@umich.edu{
572789Sktlim@umich.edu    memReq = NULL;
582789Sktlim@umich.edu
592789Sktlim@umich.edu    numInst = 0;
602789Sktlim@umich.edu    startNumInst = 0;
612789Sktlim@umich.edu    numLoad = 0;
622789Sktlim@umich.edu    startNumLoad = 0;
632789Sktlim@umich.edu    youngestSN = 0;
642789Sktlim@umich.edu
652789Sktlim@umich.edu    changedPC = willChangePC = changedNextPC = false;
662789Sktlim@umich.edu
672789Sktlim@umich.edu    exitOnError = p->exitOnError;
682789Sktlim@umich.edu    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
692789Sktlim@umich.edu#if FULL_SYSTEM
702789Sktlim@umich.edu    itb = p->itb;
712789Sktlim@umich.edu    dtb = p->dtb;
722789Sktlim@umich.edu    systemPtr = NULL;
732789Sktlim@umich.edu#else
742789Sktlim@umich.edu    process = p->process;
753402Sktlim@umich.edu    thread = new SimpleThread(this, /* thread_num */ 0, process,
763402Sktlim@umich.edu                              /* asid */ 0);
773402Sktlim@umich.edu
783402Sktlim@umich.edu    tc = thread->getTC();
793402Sktlim@umich.edu    threadContexts.push_back(tc);
802789Sktlim@umich.edu#endif
812789Sktlim@umich.edu
822789Sktlim@umich.edu    result.integer = 0;
832789Sktlim@umich.edu}
842789Sktlim@umich.edu
852789Sktlim@umich.eduCheckerCPU::~CheckerCPU()
862789Sktlim@umich.edu{
872789Sktlim@umich.edu}
882789Sktlim@umich.edu
892789Sktlim@umich.eduvoid
902789Sktlim@umich.eduCheckerCPU::setSystem(System *system)
912789Sktlim@umich.edu{
922789Sktlim@umich.edu#if FULL_SYSTEM
932789Sktlim@umich.edu    systemPtr = system;
942789Sktlim@umich.edu
952789Sktlim@umich.edu    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
962789Sktlim@umich.edu
972789Sktlim@umich.edu    tc = thread->getTC();
982789Sktlim@umich.edu    threadContexts.push_back(tc);
992789Sktlim@umich.edu    delete thread->kernelStats;
1002789Sktlim@umich.edu    thread->kernelStats = NULL;
1012789Sktlim@umich.edu#endif
1022789Sktlim@umich.edu}
1032789Sktlim@umich.edu
1042789Sktlim@umich.eduvoid
1052789Sktlim@umich.eduCheckerCPU::setIcachePort(Port *icache_port)
1062789Sktlim@umich.edu{
1072789Sktlim@umich.edu    icachePort = icache_port;
1082789Sktlim@umich.edu}
1092789Sktlim@umich.edu
1102789Sktlim@umich.eduvoid
1112789Sktlim@umich.eduCheckerCPU::setDcachePort(Port *dcache_port)
1122789Sktlim@umich.edu{
1132789Sktlim@umich.edu    dcachePort = dcache_port;
1142789Sktlim@umich.edu}
1152789Sktlim@umich.edu
1162789Sktlim@umich.eduvoid
1172789Sktlim@umich.eduCheckerCPU::serialize(ostream &os)
1182789Sktlim@umich.edu{
1192789Sktlim@umich.edu/*
1202789Sktlim@umich.edu    BaseCPU::serialize(os);
1212789Sktlim@umich.edu    SERIALIZE_SCALAR(inst);
1222789Sktlim@umich.edu    nameOut(os, csprintf("%s.xc", name()));
1232789Sktlim@umich.edu    thread->serialize(os);
1242789Sktlim@umich.edu    cacheCompletionEvent.serialize(os);
1252789Sktlim@umich.edu*/
1262789Sktlim@umich.edu}
1272789Sktlim@umich.edu
1282789Sktlim@umich.eduvoid
1292789Sktlim@umich.eduCheckerCPU::unserialize(Checkpoint *cp, const string &section)
1302789Sktlim@umich.edu{
1312789Sktlim@umich.edu/*
1322789Sktlim@umich.edu    BaseCPU::unserialize(cp, section);
1332789Sktlim@umich.edu    UNSERIALIZE_SCALAR(inst);
1342789Sktlim@umich.edu    thread->unserialize(cp, csprintf("%s.xc", section));
1352789Sktlim@umich.edu*/
1362789Sktlim@umich.edu}
1372789Sktlim@umich.edu
1382789Sktlim@umich.eduFault
1392789Sktlim@umich.eduCheckerCPU::copySrcTranslate(Addr src)
1402789Sktlim@umich.edu{
1412789Sktlim@umich.edu    panic("Unimplemented!");
1422789Sktlim@umich.edu}
1432789Sktlim@umich.edu
1442789Sktlim@umich.eduFault
1452789Sktlim@umich.eduCheckerCPU::copy(Addr dest)
1462789Sktlim@umich.edu{
1472789Sktlim@umich.edu    panic("Unimplemented!");
1482789Sktlim@umich.edu}
1492789Sktlim@umich.edu
1502789Sktlim@umich.edutemplate <class T>
1512789Sktlim@umich.eduFault
1522789Sktlim@umich.eduCheckerCPU::read(Addr addr, T &data, unsigned flags)
1532789Sktlim@umich.edu{
1542789Sktlim@umich.edu    // need to fill in CPU & thread IDs here
1552789Sktlim@umich.edu    memReq = new Request();
1562789Sktlim@umich.edu
1572789Sktlim@umich.edu    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
1582789Sktlim@umich.edu
1592789Sktlim@umich.edu    // translate to physical address
1605891Sgblack@eecs.umich.edu    dtb->translateAtomic(memReq, tc, false);
1612789Sktlim@umich.edu
1623349Sbinkertn@umich.edu    PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
1632789Sktlim@umich.edu
1642789Sktlim@umich.edu    pkt->dataStatic(&data);
1652789Sktlim@umich.edu
1663172Sstever@eecs.umich.edu    if (!(memReq->isUncacheable())) {
1672789Sktlim@umich.edu        // Access memory to see if we have the same data
1682789Sktlim@umich.edu        dcachePort->sendFunctional(pkt);
1692789Sktlim@umich.edu    } else {
1702789Sktlim@umich.edu        // Assume the data is correct if it's an uncached access
1712789Sktlim@umich.edu        memcpy(&data, &unverifiedResult.integer, sizeof(T));
1722789Sktlim@umich.edu    }
1732789Sktlim@umich.edu
1742789Sktlim@umich.edu    delete pkt;
1752789Sktlim@umich.edu
1762789Sktlim@umich.edu    return NoFault;
1772789Sktlim@umich.edu}
1782789Sktlim@umich.edu
1792789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
1802789Sktlim@umich.edu
1812789Sktlim@umich.edutemplate
1822789Sktlim@umich.eduFault
1832789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
1842789Sktlim@umich.edu
1852789Sktlim@umich.edutemplate
1862789Sktlim@umich.eduFault
1872789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
1882789Sktlim@umich.edu
1892789Sktlim@umich.edutemplate
1902789Sktlim@umich.eduFault
1912789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
1922789Sktlim@umich.edu
1932789Sktlim@umich.edutemplate
1942789Sktlim@umich.eduFault
1952789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
1962789Sktlim@umich.edu
1972789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
1982789Sktlim@umich.edu
1992789Sktlim@umich.edutemplate<>
2002789Sktlim@umich.eduFault
2012789Sktlim@umich.eduCheckerCPU::read(Addr addr, double &data, unsigned flags)
2022789Sktlim@umich.edu{
2032789Sktlim@umich.edu    return read(addr, *(uint64_t*)&data, flags);
2042789Sktlim@umich.edu}
2052789Sktlim@umich.edu
2062789Sktlim@umich.edutemplate<>
2072789Sktlim@umich.eduFault
2082789Sktlim@umich.eduCheckerCPU::read(Addr addr, float &data, unsigned flags)
2092789Sktlim@umich.edu{
2102789Sktlim@umich.edu    return read(addr, *(uint32_t*)&data, flags);
2112789Sktlim@umich.edu}
2122789Sktlim@umich.edu
2132789Sktlim@umich.edutemplate<>
2142789Sktlim@umich.eduFault
2152789Sktlim@umich.eduCheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
2162789Sktlim@umich.edu{
2172789Sktlim@umich.edu    return read(addr, (uint32_t&)data, flags);
2182789Sktlim@umich.edu}
2192789Sktlim@umich.edu
2202789Sktlim@umich.edutemplate <class T>
2212789Sktlim@umich.eduFault
2222789Sktlim@umich.eduCheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
2232789Sktlim@umich.edu{
2242789Sktlim@umich.edu    // need to fill in CPU & thread IDs here
2252789Sktlim@umich.edu    memReq = new Request();
2262789Sktlim@umich.edu
2272789Sktlim@umich.edu    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
2282789Sktlim@umich.edu
2292789Sktlim@umich.edu    // translate to physical address
2305891Sgblack@eecs.umich.edu    dtb->translateAtomic(memReq, tc, true);
2312789Sktlim@umich.edu
2322789Sktlim@umich.edu    // Can compare the write data and result only if it's cacheable,
2332789Sktlim@umich.edu    // not a store conditional, or is a store conditional that
2342789Sktlim@umich.edu    // succeeded.
2352789Sktlim@umich.edu    // @todo: Verify that actual memory matches up with these values.
2362789Sktlim@umich.edu    // Right now it only verifies that the instruction data is the
2372789Sktlim@umich.edu    // same as what was in the request that got sent to memory; there
2382789Sktlim@umich.edu    // is no verification that it is the same as what is in memory.
2392789Sktlim@umich.edu    // This is because the LSQ would have to be snooped in the CPU to
2402789Sktlim@umich.edu    // verify this data.
2412789Sktlim@umich.edu    if (unverifiedReq &&
2423172Sstever@eecs.umich.edu        !(unverifiedReq->isUncacheable()) &&
2436102Sgblack@eecs.umich.edu        (!(unverifiedReq->isLLSC()) ||
2446102Sgblack@eecs.umich.edu         ((unverifiedReq->isLLSC()) &&
2454052Ssaidi@eecs.umich.edu          unverifiedReq->getExtraData() == 1))) {
2462789Sktlim@umich.edu        T inst_data;
2472789Sktlim@umich.edu/*
2482789Sktlim@umich.edu        // This code would work if the LSQ allowed for snooping.
2493349Sbinkertn@umich.edu        PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
2502789Sktlim@umich.edu        pkt.dataStatic(&inst_data);
2512789Sktlim@umich.edu
2522789Sktlim@umich.edu        dcachePort->sendFunctional(pkt);
2532789Sktlim@umich.edu
2542789Sktlim@umich.edu        delete pkt;
2552789Sktlim@umich.edu*/
2562789Sktlim@umich.edu        memcpy(&inst_data, unverifiedMemData, sizeof(T));
2572789Sktlim@umich.edu
2582789Sktlim@umich.edu        if (data != inst_data) {
2592789Sktlim@umich.edu            warn("%lli: Store value does not match value in memory! "
2602789Sktlim@umich.edu                 "Instruction: %#x, memory: %#x",
2612789Sktlim@umich.edu                 curTick, inst_data, data);
2622789Sktlim@umich.edu            handleError();
2632789Sktlim@umich.edu        }
2642789Sktlim@umich.edu    }
2652789Sktlim@umich.edu
2662789Sktlim@umich.edu    // Assume the result was the same as the one passed in.  This checker
2672789Sktlim@umich.edu    // doesn't check if the SC should succeed or fail, it just checks the
2682789Sktlim@umich.edu    // value.
2692789Sktlim@umich.edu    if (res && unverifiedReq->scResultValid())
2704052Ssaidi@eecs.umich.edu        *res = unverifiedReq->getExtraData();
2712789Sktlim@umich.edu
2722789Sktlim@umich.edu    return NoFault;
2732789Sktlim@umich.edu}
2742789Sktlim@umich.edu
2752789Sktlim@umich.edu
2762789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
2772789Sktlim@umich.edutemplate
2782789Sktlim@umich.eduFault
2792789Sktlim@umich.eduCheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
2802789Sktlim@umich.edu
2812789Sktlim@umich.edutemplate
2822789Sktlim@umich.eduFault
2832789Sktlim@umich.eduCheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
2842789Sktlim@umich.edu
2852789Sktlim@umich.edutemplate
2862789Sktlim@umich.eduFault
2872789Sktlim@umich.eduCheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
2882789Sktlim@umich.edu
2892789Sktlim@umich.edutemplate
2902789Sktlim@umich.eduFault
2912789Sktlim@umich.eduCheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
2922789Sktlim@umich.edu
2932789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
2942789Sktlim@umich.edu
2952789Sktlim@umich.edutemplate<>
2962789Sktlim@umich.eduFault
2972789Sktlim@umich.eduCheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
2982789Sktlim@umich.edu{
2992789Sktlim@umich.edu    return write(*(uint64_t*)&data, addr, flags, res);
3002789Sktlim@umich.edu}
3012789Sktlim@umich.edu
3022789Sktlim@umich.edutemplate<>
3032789Sktlim@umich.eduFault
3042789Sktlim@umich.eduCheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
3052789Sktlim@umich.edu{
3062789Sktlim@umich.edu    return write(*(uint32_t*)&data, addr, flags, res);
3072789Sktlim@umich.edu}
3082789Sktlim@umich.edu
3092789Sktlim@umich.edutemplate<>
3102789Sktlim@umich.eduFault
3112789Sktlim@umich.eduCheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
3122789Sktlim@umich.edu{
3132789Sktlim@umich.edu    return write((uint32_t)data, addr, flags, res);
3142789Sktlim@umich.edu}
3152789Sktlim@umich.edu
3162789Sktlim@umich.edu
3172789Sktlim@umich.edu#if FULL_SYSTEM
3182789Sktlim@umich.eduAddr
3192789Sktlim@umich.eduCheckerCPU::dbg_vtophys(Addr addr)
3202789Sktlim@umich.edu{
3212789Sktlim@umich.edu    return vtophys(tc, addr);
3222789Sktlim@umich.edu}
3232789Sktlim@umich.edu#endif // FULL_SYSTEM
3242789Sktlim@umich.edu
3252789Sktlim@umich.edubool
3262789Sktlim@umich.eduCheckerCPU::checkFlags(Request *req)
3272789Sktlim@umich.edu{
3282789Sktlim@umich.edu    // Remove any dynamic flags that don't have to do with the request itself.
3292789Sktlim@umich.edu    unsigned flags = unverifiedReq->getFlags();
3302789Sktlim@umich.edu    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
3312789Sktlim@umich.edu    flags = flags & (mask);
3322789Sktlim@umich.edu    if (flags == req->getFlags()) {
3332789Sktlim@umich.edu        return false;
3342789Sktlim@umich.edu    } else {
3352789Sktlim@umich.edu        return true;
3362789Sktlim@umich.edu    }
3372789Sktlim@umich.edu}
3382789Sktlim@umich.edu
3392789Sktlim@umich.eduvoid
3402789Sktlim@umich.eduCheckerCPU::dumpAndExit()
3412789Sktlim@umich.edu{
3422789Sktlim@umich.edu    warn("%lli: Checker PC:%#x, next PC:%#x",
3432789Sktlim@umich.edu         curTick, thread->readPC(), thread->readNextPC());
3442789Sktlim@umich.edu    panic("Checker found an error!");
3452789Sktlim@umich.edu}
346