cpu.cc revision 8793
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
348793Sgblack@eecs.umich.edu#include "arch/kernel_stats.hh"
358793Sgblack@eecs.umich.edu#include "arch/vtophys.hh"
368229Snate@binkert.org#include "cpu/checker/cpu.hh"
372789Sktlim@umich.edu#include "cpu/base.hh"
382789Sktlim@umich.edu#include "cpu/simple_thread.hh"
393348Sbinkertn@umich.edu#include "cpu/static_inst.hh"
402789Sktlim@umich.edu#include "cpu/thread_context.hh"
412789Sktlim@umich.edu
422789Sktlim@umich.eduusing namespace std;
432789Sktlim@umich.edu//The CheckerCPU does alpha only
442789Sktlim@umich.eduusing namespace AlphaISA;
452789Sktlim@umich.edu
462789Sktlim@umich.eduvoid
472789Sktlim@umich.eduCheckerCPU::init()
482789Sktlim@umich.edu{
492789Sktlim@umich.edu}
502789Sktlim@umich.edu
512789Sktlim@umich.eduCheckerCPU::CheckerCPU(Params *p)
522789Sktlim@umich.edu    : BaseCPU(p), thread(NULL), tc(NULL)
532789Sktlim@umich.edu{
542789Sktlim@umich.edu    memReq = NULL;
552789Sktlim@umich.edu
562789Sktlim@umich.edu    numInst = 0;
572789Sktlim@umich.edu    startNumInst = 0;
582789Sktlim@umich.edu    numLoad = 0;
592789Sktlim@umich.edu    startNumLoad = 0;
602789Sktlim@umich.edu    youngestSN = 0;
612789Sktlim@umich.edu
622789Sktlim@umich.edu    changedPC = willChangePC = changedNextPC = false;
632789Sktlim@umich.edu
642789Sktlim@umich.edu    exitOnError = p->exitOnError;
652789Sktlim@umich.edu    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
662789Sktlim@umich.edu    itb = p->itb;
672789Sktlim@umich.edu    dtb = p->dtb;
682789Sktlim@umich.edu    systemPtr = NULL;
692789Sktlim@umich.edu    process = p->process;
706331Sgblack@eecs.umich.edu    thread = new SimpleThread(this, /* thread_num */ 0, process);
713402Sktlim@umich.edu
723402Sktlim@umich.edu    tc = thread->getTC();
733402Sktlim@umich.edu    threadContexts.push_back(tc);
742789Sktlim@umich.edu
752789Sktlim@umich.edu    result.integer = 0;
762789Sktlim@umich.edu}
772789Sktlim@umich.edu
782789Sktlim@umich.eduCheckerCPU::~CheckerCPU()
792789Sktlim@umich.edu{
802789Sktlim@umich.edu}
812789Sktlim@umich.edu
822789Sktlim@umich.eduvoid
832789Sktlim@umich.eduCheckerCPU::setSystem(System *system)
842789Sktlim@umich.edu{
852789Sktlim@umich.edu    systemPtr = system;
862789Sktlim@umich.edu
872789Sktlim@umich.edu    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
882789Sktlim@umich.edu
892789Sktlim@umich.edu    tc = thread->getTC();
902789Sktlim@umich.edu    threadContexts.push_back(tc);
912789Sktlim@umich.edu    delete thread->kernelStats;
922789Sktlim@umich.edu    thread->kernelStats = NULL;
932789Sktlim@umich.edu}
942789Sktlim@umich.edu
952789Sktlim@umich.eduvoid
962789Sktlim@umich.eduCheckerCPU::setIcachePort(Port *icache_port)
972789Sktlim@umich.edu{
982789Sktlim@umich.edu    icachePort = icache_port;
992789Sktlim@umich.edu}
1002789Sktlim@umich.edu
1012789Sktlim@umich.eduvoid
1022789Sktlim@umich.eduCheckerCPU::setDcachePort(Port *dcache_port)
1032789Sktlim@umich.edu{
1042789Sktlim@umich.edu    dcachePort = dcache_port;
1052789Sktlim@umich.edu}
1062789Sktlim@umich.edu
1072789Sktlim@umich.eduvoid
1082789Sktlim@umich.eduCheckerCPU::serialize(ostream &os)
1092789Sktlim@umich.edu{
1102789Sktlim@umich.edu/*
1112789Sktlim@umich.edu    BaseCPU::serialize(os);
1122789Sktlim@umich.edu    SERIALIZE_SCALAR(inst);
1132789Sktlim@umich.edu    nameOut(os, csprintf("%s.xc", name()));
1142789Sktlim@umich.edu    thread->serialize(os);
1152789Sktlim@umich.edu    cacheCompletionEvent.serialize(os);
1162789Sktlim@umich.edu*/
1172789Sktlim@umich.edu}
1182789Sktlim@umich.edu
1192789Sktlim@umich.eduvoid
1202789Sktlim@umich.eduCheckerCPU::unserialize(Checkpoint *cp, const string &section)
1212789Sktlim@umich.edu{
1222789Sktlim@umich.edu/*
1232789Sktlim@umich.edu    BaseCPU::unserialize(cp, section);
1242789Sktlim@umich.edu    UNSERIALIZE_SCALAR(inst);
1252789Sktlim@umich.edu    thread->unserialize(cp, csprintf("%s.xc", section));
1262789Sktlim@umich.edu*/
1272789Sktlim@umich.edu}
1282789Sktlim@umich.edu
1292789Sktlim@umich.edutemplate <class T>
1302789Sktlim@umich.eduFault
1312789Sktlim@umich.eduCheckerCPU::read(Addr addr, T &data, unsigned flags)
1322789Sktlim@umich.edu{
1332789Sktlim@umich.edu    // need to fill in CPU & thread IDs here
1342789Sktlim@umich.edu    memReq = new Request();
1352789Sktlim@umich.edu
1362789Sktlim@umich.edu    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
1372789Sktlim@umich.edu
1382789Sktlim@umich.edu    // translate to physical address
1395891Sgblack@eecs.umich.edu    dtb->translateAtomic(memReq, tc, false);
1402789Sktlim@umich.edu
1413349Sbinkertn@umich.edu    PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
1422789Sktlim@umich.edu
1432789Sktlim@umich.edu    pkt->dataStatic(&data);
1442789Sktlim@umich.edu
1453172Sstever@eecs.umich.edu    if (!(memReq->isUncacheable())) {
1462789Sktlim@umich.edu        // Access memory to see if we have the same data
1472789Sktlim@umich.edu        dcachePort->sendFunctional(pkt);
1482789Sktlim@umich.edu    } else {
1492789Sktlim@umich.edu        // Assume the data is correct if it's an uncached access
1502789Sktlim@umich.edu        memcpy(&data, &unverifiedResult.integer, sizeof(T));
1512789Sktlim@umich.edu    }
1522789Sktlim@umich.edu
1532789Sktlim@umich.edu    delete pkt;
1542789Sktlim@umich.edu
1552789Sktlim@umich.edu    return NoFault;
1562789Sktlim@umich.edu}
1572789Sktlim@umich.edu
1582789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
1592789Sktlim@umich.edu
1602789Sktlim@umich.edutemplate
1612789Sktlim@umich.eduFault
1622789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
1632789Sktlim@umich.edu
1642789Sktlim@umich.edutemplate
1652789Sktlim@umich.eduFault
1662789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
1672789Sktlim@umich.edu
1682789Sktlim@umich.edutemplate
1692789Sktlim@umich.eduFault
1702789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
1712789Sktlim@umich.edu
1722789Sktlim@umich.edutemplate
1732789Sktlim@umich.eduFault
1742789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
1752789Sktlim@umich.edu
1762789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
1772789Sktlim@umich.edu
1782789Sktlim@umich.edutemplate<>
1792789Sktlim@umich.eduFault
1802789Sktlim@umich.eduCheckerCPU::read(Addr addr, double &data, unsigned flags)
1812789Sktlim@umich.edu{
1822789Sktlim@umich.edu    return read(addr, *(uint64_t*)&data, flags);
1832789Sktlim@umich.edu}
1842789Sktlim@umich.edu
1852789Sktlim@umich.edutemplate<>
1862789Sktlim@umich.eduFault
1872789Sktlim@umich.eduCheckerCPU::read(Addr addr, float &data, unsigned flags)
1882789Sktlim@umich.edu{
1892789Sktlim@umich.edu    return read(addr, *(uint32_t*)&data, flags);
1902789Sktlim@umich.edu}
1912789Sktlim@umich.edu
1922789Sktlim@umich.edutemplate<>
1932789Sktlim@umich.eduFault
1942789Sktlim@umich.eduCheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
1952789Sktlim@umich.edu{
1962789Sktlim@umich.edu    return read(addr, (uint32_t&)data, flags);
1972789Sktlim@umich.edu}
1982789Sktlim@umich.edu
1992789Sktlim@umich.edutemplate <class T>
2002789Sktlim@umich.eduFault
2012789Sktlim@umich.eduCheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
2022789Sktlim@umich.edu{
2032789Sktlim@umich.edu    // need to fill in CPU & thread IDs here
2042789Sktlim@umich.edu    memReq = new Request();
2052789Sktlim@umich.edu
2062789Sktlim@umich.edu    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
2072789Sktlim@umich.edu
2082789Sktlim@umich.edu    // translate to physical address
2095891Sgblack@eecs.umich.edu    dtb->translateAtomic(memReq, tc, true);
2102789Sktlim@umich.edu
2112789Sktlim@umich.edu    // Can compare the write data and result only if it's cacheable,
2122789Sktlim@umich.edu    // not a store conditional, or is a store conditional that
2132789Sktlim@umich.edu    // succeeded.
2142789Sktlim@umich.edu    // @todo: Verify that actual memory matches up with these values.
2152789Sktlim@umich.edu    // Right now it only verifies that the instruction data is the
2162789Sktlim@umich.edu    // same as what was in the request that got sent to memory; there
2172789Sktlim@umich.edu    // is no verification that it is the same as what is in memory.
2182789Sktlim@umich.edu    // This is because the LSQ would have to be snooped in the CPU to
2192789Sktlim@umich.edu    // verify this data.
2202789Sktlim@umich.edu    if (unverifiedReq &&
2213172Sstever@eecs.umich.edu        !(unverifiedReq->isUncacheable()) &&
2226102Sgblack@eecs.umich.edu        (!(unverifiedReq->isLLSC()) ||
2236102Sgblack@eecs.umich.edu         ((unverifiedReq->isLLSC()) &&
2244052Ssaidi@eecs.umich.edu          unverifiedReq->getExtraData() == 1))) {
2252789Sktlim@umich.edu        T inst_data;
2262789Sktlim@umich.edu/*
2272789Sktlim@umich.edu        // This code would work if the LSQ allowed for snooping.
2283349Sbinkertn@umich.edu        PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
2292789Sktlim@umich.edu        pkt.dataStatic(&inst_data);
2302789Sktlim@umich.edu
2312789Sktlim@umich.edu        dcachePort->sendFunctional(pkt);
2322789Sktlim@umich.edu
2332789Sktlim@umich.edu        delete pkt;
2342789Sktlim@umich.edu*/
2352789Sktlim@umich.edu        memcpy(&inst_data, unverifiedMemData, sizeof(T));
2362789Sktlim@umich.edu
2372789Sktlim@umich.edu        if (data != inst_data) {
2382789Sktlim@umich.edu            warn("%lli: Store value does not match value in memory! "
2392789Sktlim@umich.edu                 "Instruction: %#x, memory: %#x",
2407823Ssteve.reinhardt@amd.com                 curTick(), inst_data, data);
2412789Sktlim@umich.edu            handleError();
2422789Sktlim@umich.edu        }
2432789Sktlim@umich.edu    }
2442789Sktlim@umich.edu
2452789Sktlim@umich.edu    // Assume the result was the same as the one passed in.  This checker
2462789Sktlim@umich.edu    // doesn't check if the SC should succeed or fail, it just checks the
2472789Sktlim@umich.edu    // value.
2482789Sktlim@umich.edu    if (res && unverifiedReq->scResultValid())
2494052Ssaidi@eecs.umich.edu        *res = unverifiedReq->getExtraData();
2502789Sktlim@umich.edu
2512789Sktlim@umich.edu    return NoFault;
2522789Sktlim@umich.edu}
2532789Sktlim@umich.edu
2542789Sktlim@umich.edu
2552789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
2562789Sktlim@umich.edutemplate
2572789Sktlim@umich.eduFault
2582789Sktlim@umich.eduCheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
2592789Sktlim@umich.edu
2602789Sktlim@umich.edutemplate
2612789Sktlim@umich.eduFault
2622789Sktlim@umich.eduCheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
2632789Sktlim@umich.edu
2642789Sktlim@umich.edutemplate
2652789Sktlim@umich.eduFault
2662789Sktlim@umich.eduCheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
2672789Sktlim@umich.edu
2682789Sktlim@umich.edutemplate
2692789Sktlim@umich.eduFault
2702789Sktlim@umich.eduCheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
2712789Sktlim@umich.edu
2722789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
2732789Sktlim@umich.edu
2742789Sktlim@umich.edutemplate<>
2752789Sktlim@umich.eduFault
2762789Sktlim@umich.eduCheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
2772789Sktlim@umich.edu{
2782789Sktlim@umich.edu    return write(*(uint64_t*)&data, addr, flags, res);
2792789Sktlim@umich.edu}
2802789Sktlim@umich.edu
2812789Sktlim@umich.edutemplate<>
2822789Sktlim@umich.eduFault
2832789Sktlim@umich.eduCheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
2842789Sktlim@umich.edu{
2852789Sktlim@umich.edu    return write(*(uint32_t*)&data, addr, flags, res);
2862789Sktlim@umich.edu}
2872789Sktlim@umich.edu
2882789Sktlim@umich.edutemplate<>
2892789Sktlim@umich.eduFault
2902789Sktlim@umich.eduCheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
2912789Sktlim@umich.edu{
2922789Sktlim@umich.edu    return write((uint32_t)data, addr, flags, res);
2932789Sktlim@umich.edu}
2942789Sktlim@umich.edu
2952789Sktlim@umich.edu
2962789Sktlim@umich.eduAddr
2972789Sktlim@umich.eduCheckerCPU::dbg_vtophys(Addr addr)
2982789Sktlim@umich.edu{
2992789Sktlim@umich.edu    return vtophys(tc, addr);
3002789Sktlim@umich.edu}
3012789Sktlim@umich.edu
3022789Sktlim@umich.edubool
3032789Sktlim@umich.eduCheckerCPU::checkFlags(Request *req)
3042789Sktlim@umich.edu{
3052789Sktlim@umich.edu    // Remove any dynamic flags that don't have to do with the request itself.
3062789Sktlim@umich.edu    unsigned flags = unverifiedReq->getFlags();
3076739Sgblack@eecs.umich.edu    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH;
3082789Sktlim@umich.edu    flags = flags & (mask);
3092789Sktlim@umich.edu    if (flags == req->getFlags()) {
3102789Sktlim@umich.edu        return false;
3112789Sktlim@umich.edu    } else {
3122789Sktlim@umich.edu        return true;
3132789Sktlim@umich.edu    }
3142789Sktlim@umich.edu}
3152789Sktlim@umich.edu
3162789Sktlim@umich.eduvoid
3172789Sktlim@umich.eduCheckerCPU::dumpAndExit()
3182789Sktlim@umich.edu{
3192789Sktlim@umich.edu    warn("%lli: Checker PC:%#x, next PC:%#x",
3207823Ssteve.reinhardt@amd.com         curTick(), thread->readPC(), thread->readNextPC());
3212789Sktlim@umich.edu    panic("Checker found an error!");
3222789Sktlim@umich.edu}
323