/*
 * Copyright (c) 2011,2013,2017 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Kevin Lim
 *          Geoffrey Blake
 */

#include "cpu/checker/cpu.hh"

#include <list>
#include <string>

#include "arch/generic/tlb.hh"
#include "arch/kernel_stats.hh"
#include "arch/vtophys.hh"
#include "cpu/base.hh"
#include "cpu/simple_thread.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "params/CheckerCPU.hh"
#include "sim/full_system.hh"

using namespace std;
using namespace TheISA;

void
CheckerCPU::init()
{
    masterId = systemPtr->getMasterId(name());
}

CheckerCPU::CheckerCPU(Params *p)
    : BaseCPU(p, true), systemPtr(NULL), icachePort(NULL), dcachePort(NULL),
      tc(NULL), thread(NULL)
{
    memReq = NULL;
    curStaticInst = NULL;
    curMacroStaticInst = NULL;

    numInst = 0;
    startNumInst = 0;
    numLoad = 0;
    startNumLoad = 0;
    youngestSN = 0;

    changedPC = willChangePC = false;

    exitOnError = p->exitOnError;
    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
    itb = p->itb;
    dtb = p->dtb;
    workload = p->workload;

    updateOnError = true;
}

CheckerCPU::~CheckerCPU()
{
}

void
CheckerCPU::setSystem(System *system)
{
    const Params *p(dynamic_cast<const Params *>(_params));

    systemPtr = system;

    if (FullSystem) {
        thread = new SimpleThread(this, 0, systemPtr, itb, dtb,
                                  p->isa[0], false);
    } else {
        thread = new SimpleThread(this, 0, systemPtr,
                                  workload.size() ? workload[0] : NULL,
                                  itb, dtb, p->isa[0]);
    }

    tc = thread->getTC();
    threadContexts.push_back(tc);
    thread->kernelStats = NULL;
    // Thread should never be null after this
    assert(thread != NULL);
}

void
CheckerCPU::setIcachePort(MasterPort *icache_port)
{
    icachePort = icache_port;
}

void
CheckerCPU::setDcachePort(MasterPort *dcache_port)
{
    dcachePort = dcache_port;
}

void
CheckerCPU::serialize(ostream &os) const
{
}

void
CheckerCPU::unserialize(CheckpointIn &cp)
{
}

Fault
CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size,
                    Request::Flags flags)
{
    Fault fault = NoFault;
    int fullSize = size;
    Addr secondAddr = roundDown(addr + size - 1, cacheLineSize());
    bool checked_flags = false;
    bool flags_match = true;
    Addr pAddr = 0x0;


    if (secondAddr > addr)
       size = secondAddr - addr;

    // Need to account for multiple accesses like the Atomic and TimingSimple
    while (1) {
        memReq = new Request(0, addr, size, flags, masterId,
                             thread->pcState().instAddr(), tc->contextId());

        // translate to physical address
        fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read);

        if (!checked_flags && fault == NoFault && unverifiedReq) {
            flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
                                     memReq->getPaddr(), memReq->getFlags());
            pAddr = memReq->getPaddr();
            checked_flags = true;
        }

        // Now do the access
        if (fault == NoFault &&
            !memReq->getFlags().isSet(Request::NO_ACCESS)) {
            PacketPtr pkt = Packet::createRead(memReq);

            pkt->dataStatic(data);

            if (!(memReq->isUncacheable() || memReq->isMmappedIpr())) {
                // Access memory to see if we have the same data
                dcachePort->sendFunctional(pkt);
            } else {
                // Assume the data is correct if it's an uncached access
                memcpy(data, unverifiedMemData, size);
            }

            delete memReq;
            memReq = NULL;
            delete pkt;
        }

        if (fault != NoFault) {
            if (memReq->isPrefetch()) {
                fault = NoFault;
            }
            delete memReq;
            memReq = NULL;
            break;
        }

        if (memReq != NULL) {
            delete memReq;
        }

        //If we don't need to access a second cache line, stop now.
        if (secondAddr <= addr)
        {
            break;
        }

        // Setup for accessing next cache line
        data += size;
        unverifiedMemData += size;
        size = addr + fullSize - secondAddr;
        addr = secondAddr;
    }

    if (!flags_match) {
        warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n",
             curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
             unverifiedReq->getFlags(), addr, pAddr, flags);
        handleError();
    }

    return fault;
}

Fault
CheckerCPU::writeMem(uint8_t *data, unsigned size,
                     Addr addr, Request::Flags flags, uint64_t *res)
{
    Fault fault = NoFault;
    bool checked_flags = false;
    bool flags_match = true;
    Addr pAddr = 0x0;
    static uint8_t zero_data[64] = {};

    int fullSize = size;

    Addr secondAddr = roundDown(addr + size - 1, cacheLineSize());

    if (secondAddr > addr)
        size = secondAddr - addr;

    // Need to account for a multiple access like Atomic and Timing CPUs
    while (1) {
        memReq = new Request(0, addr, size, flags, masterId,
                             thread->pcState().instAddr(), tc->contextId());

        // translate to physical address
        fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write);

        if (!checked_flags && fault == NoFault && unverifiedReq) {
           flags_match = checkFlags(unverifiedReq, memReq->getVaddr(),
                                    memReq->getPaddr(), memReq->getFlags());
           pAddr = memReq->getPaddr();
           checked_flags = true;
        }

        /*
         * We don't actually check memory for the store because there
         * is no guarantee it has left the lsq yet, and therefore we
         * can't verify the memory on stores without lsq snooping
         * enabled.  This is left as future work for the Checker: LSQ snooping
         * and memory validation after stores have committed.
         */
        bool was_prefetch = memReq->isPrefetch();

        delete memReq;

        //If we don't need to access a second cache line, stop now.
        if (fault != NoFault || secondAddr <= addr)
        {
            if (fault != NoFault && was_prefetch) {
              fault = NoFault;
            }
            break;
        }

        //Update size and access address
        size = addr + fullSize - secondAddr;
        //And access the right address.
        addr = secondAddr;
   }

   if (!flags_match) {
       warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n",
            curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
            unverifiedReq->getFlags(), addr, pAddr, flags);
       handleError();
   }

   // Assume the result was the same as the one passed in.  This checker
   // doesn't check if the SC should succeed or fail, it just checks the
   // value.
   if (unverifiedReq && res && unverifiedReq->extraDataValid())
       *res = unverifiedReq->getExtraData();

   // Entire purpose here is to make sure we are getting the
   // same data to send to the mem system as the CPU did.
   // Cannot check this is actually what went to memory because
   // there stores can be in ld/st queue or coherent operations
   // overwriting values.
   bool extraData = false;
   if (unverifiedReq) {
       extraData = unverifiedReq->extraDataValid() ?
                        unverifiedReq->getExtraData() : true;
   }

   // If the request is to ZERO a cache block, there is no data to check
   // against, but it's all zero. We need something to compare to, so use a
   // const set of zeros.
   if (flags & Request::STORE_NO_DATA) {
       assert(!data);
       assert(sizeof(zero_data) <= fullSize);
       data = zero_data;
   }

   if (unverifiedReq && unverifiedMemData &&
       memcmp(data, unverifiedMemData, fullSize) && extraData) {
           warn("%lli: Store value does not match value sent to memory! "
                  "data: %#x inst_data: %#x", curTick(), data,
                  unverifiedMemData);
       handleError();
   }

   return fault;
}

Addr
CheckerCPU::dbg_vtophys(Addr addr)
{
    return vtophys(tc, addr);
}

/**
 * Checks if the flags set by the Checker and Checkee match.
 */
bool
CheckerCPU::checkFlags(Request *unverified_req, Addr vAddr,
                       Addr pAddr, int flags)
{
    Addr unverifiedVAddr = unverified_req->getVaddr();
    Addr unverifiedPAddr = unverified_req->getPaddr();
    int unverifiedFlags = unverified_req->getFlags();

    if (unverifiedVAddr != vAddr ||
        unverifiedPAddr != pAddr ||
        unverifiedFlags != flags) {
        return false;
    }

    return true;
}

void
CheckerCPU::dumpAndExit()
{
    warn("%lli: Checker PC:%s",
         curTick(), thread->pcState());
    panic("Checker found an error!");
}
