cpu.cc revision 8229
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
348229Snate@binkert.org#include "cpu/checker/cpu.hh"
352789Sktlim@umich.edu#include "cpu/base.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;
756331Sgblack@eecs.umich.edu    thread = new SimpleThread(this, /* thread_num */ 0, process);
763402Sktlim@umich.edu
773402Sktlim@umich.edu    tc = thread->getTC();
783402Sktlim@umich.edu    threadContexts.push_back(tc);
792789Sktlim@umich.edu#endif
802789Sktlim@umich.edu
812789Sktlim@umich.edu    result.integer = 0;
822789Sktlim@umich.edu}
832789Sktlim@umich.edu
842789Sktlim@umich.eduCheckerCPU::~CheckerCPU()
852789Sktlim@umich.edu{
862789Sktlim@umich.edu}
872789Sktlim@umich.edu
882789Sktlim@umich.eduvoid
892789Sktlim@umich.eduCheckerCPU::setSystem(System *system)
902789Sktlim@umich.edu{
912789Sktlim@umich.edu#if FULL_SYSTEM
922789Sktlim@umich.edu    systemPtr = system;
932789Sktlim@umich.edu
942789Sktlim@umich.edu    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
952789Sktlim@umich.edu
962789Sktlim@umich.edu    tc = thread->getTC();
972789Sktlim@umich.edu    threadContexts.push_back(tc);
982789Sktlim@umich.edu    delete thread->kernelStats;
992789Sktlim@umich.edu    thread->kernelStats = NULL;
1002789Sktlim@umich.edu#endif
1012789Sktlim@umich.edu}
1022789Sktlim@umich.edu
1032789Sktlim@umich.eduvoid
1042789Sktlim@umich.eduCheckerCPU::setIcachePort(Port *icache_port)
1052789Sktlim@umich.edu{
1062789Sktlim@umich.edu    icachePort = icache_port;
1072789Sktlim@umich.edu}
1082789Sktlim@umich.edu
1092789Sktlim@umich.eduvoid
1102789Sktlim@umich.eduCheckerCPU::setDcachePort(Port *dcache_port)
1112789Sktlim@umich.edu{
1122789Sktlim@umich.edu    dcachePort = dcache_port;
1132789Sktlim@umich.edu}
1142789Sktlim@umich.edu
1152789Sktlim@umich.eduvoid
1162789Sktlim@umich.eduCheckerCPU::serialize(ostream &os)
1172789Sktlim@umich.edu{
1182789Sktlim@umich.edu/*
1192789Sktlim@umich.edu    BaseCPU::serialize(os);
1202789Sktlim@umich.edu    SERIALIZE_SCALAR(inst);
1212789Sktlim@umich.edu    nameOut(os, csprintf("%s.xc", name()));
1222789Sktlim@umich.edu    thread->serialize(os);
1232789Sktlim@umich.edu    cacheCompletionEvent.serialize(os);
1242789Sktlim@umich.edu*/
1252789Sktlim@umich.edu}
1262789Sktlim@umich.edu
1272789Sktlim@umich.eduvoid
1282789Sktlim@umich.eduCheckerCPU::unserialize(Checkpoint *cp, const string &section)
1292789Sktlim@umich.edu{
1302789Sktlim@umich.edu/*
1312789Sktlim@umich.edu    BaseCPU::unserialize(cp, section);
1322789Sktlim@umich.edu    UNSERIALIZE_SCALAR(inst);
1332789Sktlim@umich.edu    thread->unserialize(cp, csprintf("%s.xc", section));
1342789Sktlim@umich.edu*/
1352789Sktlim@umich.edu}
1362789Sktlim@umich.edu
1372789Sktlim@umich.edutemplate <class T>
1382789Sktlim@umich.eduFault
1392789Sktlim@umich.eduCheckerCPU::read(Addr addr, T &data, unsigned flags)
1402789Sktlim@umich.edu{
1412789Sktlim@umich.edu    // need to fill in CPU & thread IDs here
1422789Sktlim@umich.edu    memReq = new Request();
1432789Sktlim@umich.edu
1442789Sktlim@umich.edu    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
1452789Sktlim@umich.edu
1462789Sktlim@umich.edu    // translate to physical address
1475891Sgblack@eecs.umich.edu    dtb->translateAtomic(memReq, tc, false);
1482789Sktlim@umich.edu
1493349Sbinkertn@umich.edu    PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
1502789Sktlim@umich.edu
1512789Sktlim@umich.edu    pkt->dataStatic(&data);
1522789Sktlim@umich.edu
1533172Sstever@eecs.umich.edu    if (!(memReq->isUncacheable())) {
1542789Sktlim@umich.edu        // Access memory to see if we have the same data
1552789Sktlim@umich.edu        dcachePort->sendFunctional(pkt);
1562789Sktlim@umich.edu    } else {
1572789Sktlim@umich.edu        // Assume the data is correct if it's an uncached access
1582789Sktlim@umich.edu        memcpy(&data, &unverifiedResult.integer, sizeof(T));
1592789Sktlim@umich.edu    }
1602789Sktlim@umich.edu
1612789Sktlim@umich.edu    delete pkt;
1622789Sktlim@umich.edu
1632789Sktlim@umich.edu    return NoFault;
1642789Sktlim@umich.edu}
1652789Sktlim@umich.edu
1662789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
1672789Sktlim@umich.edu
1682789Sktlim@umich.edutemplate
1692789Sktlim@umich.eduFault
1702789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
1712789Sktlim@umich.edu
1722789Sktlim@umich.edutemplate
1732789Sktlim@umich.eduFault
1742789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
1752789Sktlim@umich.edu
1762789Sktlim@umich.edutemplate
1772789Sktlim@umich.eduFault
1782789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
1792789Sktlim@umich.edu
1802789Sktlim@umich.edutemplate
1812789Sktlim@umich.eduFault
1822789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
1832789Sktlim@umich.edu
1842789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
1852789Sktlim@umich.edu
1862789Sktlim@umich.edutemplate<>
1872789Sktlim@umich.eduFault
1882789Sktlim@umich.eduCheckerCPU::read(Addr addr, double &data, unsigned flags)
1892789Sktlim@umich.edu{
1902789Sktlim@umich.edu    return read(addr, *(uint64_t*)&data, flags);
1912789Sktlim@umich.edu}
1922789Sktlim@umich.edu
1932789Sktlim@umich.edutemplate<>
1942789Sktlim@umich.eduFault
1952789Sktlim@umich.eduCheckerCPU::read(Addr addr, float &data, unsigned flags)
1962789Sktlim@umich.edu{
1972789Sktlim@umich.edu    return read(addr, *(uint32_t*)&data, flags);
1982789Sktlim@umich.edu}
1992789Sktlim@umich.edu
2002789Sktlim@umich.edutemplate<>
2012789Sktlim@umich.eduFault
2022789Sktlim@umich.eduCheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
2032789Sktlim@umich.edu{
2042789Sktlim@umich.edu    return read(addr, (uint32_t&)data, flags);
2052789Sktlim@umich.edu}
2062789Sktlim@umich.edu
2072789Sktlim@umich.edutemplate <class T>
2082789Sktlim@umich.eduFault
2092789Sktlim@umich.eduCheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
2102789Sktlim@umich.edu{
2112789Sktlim@umich.edu    // need to fill in CPU & thread IDs here
2122789Sktlim@umich.edu    memReq = new Request();
2132789Sktlim@umich.edu
2142789Sktlim@umich.edu    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
2152789Sktlim@umich.edu
2162789Sktlim@umich.edu    // translate to physical address
2175891Sgblack@eecs.umich.edu    dtb->translateAtomic(memReq, tc, true);
2182789Sktlim@umich.edu
2192789Sktlim@umich.edu    // Can compare the write data and result only if it's cacheable,
2202789Sktlim@umich.edu    // not a store conditional, or is a store conditional that
2212789Sktlim@umich.edu    // succeeded.
2222789Sktlim@umich.edu    // @todo: Verify that actual memory matches up with these values.
2232789Sktlim@umich.edu    // Right now it only verifies that the instruction data is the
2242789Sktlim@umich.edu    // same as what was in the request that got sent to memory; there
2252789Sktlim@umich.edu    // is no verification that it is the same as what is in memory.
2262789Sktlim@umich.edu    // This is because the LSQ would have to be snooped in the CPU to
2272789Sktlim@umich.edu    // verify this data.
2282789Sktlim@umich.edu    if (unverifiedReq &&
2293172Sstever@eecs.umich.edu        !(unverifiedReq->isUncacheable()) &&
2306102Sgblack@eecs.umich.edu        (!(unverifiedReq->isLLSC()) ||
2316102Sgblack@eecs.umich.edu         ((unverifiedReq->isLLSC()) &&
2324052Ssaidi@eecs.umich.edu          unverifiedReq->getExtraData() == 1))) {
2332789Sktlim@umich.edu        T inst_data;
2342789Sktlim@umich.edu/*
2352789Sktlim@umich.edu        // This code would work if the LSQ allowed for snooping.
2363349Sbinkertn@umich.edu        PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
2372789Sktlim@umich.edu        pkt.dataStatic(&inst_data);
2382789Sktlim@umich.edu
2392789Sktlim@umich.edu        dcachePort->sendFunctional(pkt);
2402789Sktlim@umich.edu
2412789Sktlim@umich.edu        delete pkt;
2422789Sktlim@umich.edu*/
2432789Sktlim@umich.edu        memcpy(&inst_data, unverifiedMemData, sizeof(T));
2442789Sktlim@umich.edu
2452789Sktlim@umich.edu        if (data != inst_data) {
2462789Sktlim@umich.edu            warn("%lli: Store value does not match value in memory! "
2472789Sktlim@umich.edu                 "Instruction: %#x, memory: %#x",
2487823Ssteve.reinhardt@amd.com                 curTick(), inst_data, data);
2492789Sktlim@umich.edu            handleError();
2502789Sktlim@umich.edu        }
2512789Sktlim@umich.edu    }
2522789Sktlim@umich.edu
2532789Sktlim@umich.edu    // Assume the result was the same as the one passed in.  This checker
2542789Sktlim@umich.edu    // doesn't check if the SC should succeed or fail, it just checks the
2552789Sktlim@umich.edu    // value.
2562789Sktlim@umich.edu    if (res && unverifiedReq->scResultValid())
2574052Ssaidi@eecs.umich.edu        *res = unverifiedReq->getExtraData();
2582789Sktlim@umich.edu
2592789Sktlim@umich.edu    return NoFault;
2602789Sktlim@umich.edu}
2612789Sktlim@umich.edu
2622789Sktlim@umich.edu
2632789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
2642789Sktlim@umich.edutemplate
2652789Sktlim@umich.eduFault
2662789Sktlim@umich.eduCheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
2672789Sktlim@umich.edu
2682789Sktlim@umich.edutemplate
2692789Sktlim@umich.eduFault
2702789Sktlim@umich.eduCheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
2712789Sktlim@umich.edu
2722789Sktlim@umich.edutemplate
2732789Sktlim@umich.eduFault
2742789Sktlim@umich.eduCheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
2752789Sktlim@umich.edu
2762789Sktlim@umich.edutemplate
2772789Sktlim@umich.eduFault
2782789Sktlim@umich.eduCheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
2792789Sktlim@umich.edu
2802789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
2812789Sktlim@umich.edu
2822789Sktlim@umich.edutemplate<>
2832789Sktlim@umich.eduFault
2842789Sktlim@umich.eduCheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
2852789Sktlim@umich.edu{
2862789Sktlim@umich.edu    return write(*(uint64_t*)&data, addr, flags, res);
2872789Sktlim@umich.edu}
2882789Sktlim@umich.edu
2892789Sktlim@umich.edutemplate<>
2902789Sktlim@umich.eduFault
2912789Sktlim@umich.eduCheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
2922789Sktlim@umich.edu{
2932789Sktlim@umich.edu    return write(*(uint32_t*)&data, addr, flags, res);
2942789Sktlim@umich.edu}
2952789Sktlim@umich.edu
2962789Sktlim@umich.edutemplate<>
2972789Sktlim@umich.eduFault
2982789Sktlim@umich.eduCheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
2992789Sktlim@umich.edu{
3002789Sktlim@umich.edu    return write((uint32_t)data, addr, flags, res);
3012789Sktlim@umich.edu}
3022789Sktlim@umich.edu
3032789Sktlim@umich.edu
3042789Sktlim@umich.edu#if FULL_SYSTEM
3052789Sktlim@umich.eduAddr
3062789Sktlim@umich.eduCheckerCPU::dbg_vtophys(Addr addr)
3072789Sktlim@umich.edu{
3082789Sktlim@umich.edu    return vtophys(tc, addr);
3092789Sktlim@umich.edu}
3102789Sktlim@umich.edu#endif // FULL_SYSTEM
3112789Sktlim@umich.edu
3122789Sktlim@umich.edubool
3132789Sktlim@umich.eduCheckerCPU::checkFlags(Request *req)
3142789Sktlim@umich.edu{
3152789Sktlim@umich.edu    // Remove any dynamic flags that don't have to do with the request itself.
3162789Sktlim@umich.edu    unsigned flags = unverifiedReq->getFlags();
3176739Sgblack@eecs.umich.edu    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH;
3182789Sktlim@umich.edu    flags = flags & (mask);
3192789Sktlim@umich.edu    if (flags == req->getFlags()) {
3202789Sktlim@umich.edu        return false;
3212789Sktlim@umich.edu    } else {
3222789Sktlim@umich.edu        return true;
3232789Sktlim@umich.edu    }
3242789Sktlim@umich.edu}
3252789Sktlim@umich.edu
3262789Sktlim@umich.eduvoid
3272789Sktlim@umich.eduCheckerCPU::dumpAndExit()
3282789Sktlim@umich.edu{
3292789Sktlim@umich.edu    warn("%lli: Checker PC:%#x, next PC:%#x",
3307823Ssteve.reinhardt@amd.com         curTick(), thread->readPC(), thread->readNextPC());
3312789Sktlim@umich.edu    panic("Checker found an error!");
3322789Sktlim@umich.edu}
333