/*
 * Copyright (c) 2014 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.
 *
 * 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: Rune Holm
 *          Marco Elver
 */

#include <cassert>

#include "mem/mem_checker.hh"

void
MemChecker::WriteCluster::startWrite(MemChecker::Serial serial, Tick _start,
                                     uint8_t data)
{
    assert(!isComplete());

    if (start == TICK_FUTURE) {
        // Initialize a fresh write cluster
        start = _start;
    }
    chatty_assert(start <= _start, "WriteClusters must filled in order!");

    ++numIncomplete;

    if (complete != TICK_FUTURE) {
       // Reopen a closed write cluster
        assert(_start < complete);  // should open a new write cluster, instead;
        // also somewhat fishy wrt causality / ordering of calls vs time
        // progression TODO: Check me!
        complete = TICK_FUTURE;
    }

    // Create new transaction, and denote completion time to be in the future.
    writes.insert(std::make_pair(serial,
                  MemChecker::Transaction(serial, _start, TICK_FUTURE, data)));
}

void
MemChecker::WriteCluster::completeWrite(MemChecker::Serial serial, Tick _complete)
{
    auto it = writes.find(serial);

    if (it == writes.end()) {
        warn("Could not locate write transaction: serial = %d, complete = %d\n",
             serial, _complete);
        return;
    }

    // Record completion time of the write
    assert(it->second.complete == TICK_FUTURE);
    it->second.complete = _complete;

    // Update max completion time for the cluster
    if (completeMax < _complete) {
        completeMax = _complete;
    }

    if (--numIncomplete == 0) {
        // All writes have completed, this cluster is now complete and will be
        // assigned the max of completion tick values among all writes.
        //
        // Note that we cannot simply keep updating complete, because that would
        // count the cluster as closed already.  Instead, we keep TICK_FUTURE
        // until all writes have completed.
        complete = completeMax;
    }
}

void
MemChecker::WriteCluster::abortWrite(MemChecker::Serial serial)
{
    if (!writes.erase(serial)) {
        warn("Could not locate write transaction: serial = %d\n", serial);
        return;
    }

    if (--numIncomplete == 0 && !writes.empty()) {
        // This write cluster is now complete, and we can assign the current
        // completeMax value.
        complete = completeMax;
    }

    // Note: this WriteCluster is in pristine state if this was the only
    // write present; the cluster will get reused through
    // getIncompleteWriteCluster().
}

void
MemChecker::ByteTracker::startRead(MemChecker::Serial serial, Tick start)
{
    outstandingReads.insert(std::make_pair(serial,
            MemChecker::Transaction(serial, start, TICK_FUTURE)));
}

bool
MemChecker::ByteTracker::inExpectedData(Tick start, Tick complete, uint8_t data)
{
    _lastExpectedData.clear();

    bool wc_overlap = true;

    // Find the last value read from the location
    const Transaction& last_obs =
        *lastCompletedTransaction(&readObservations, start);
    bool last_obs_valid = (last_obs.complete != TICK_INITIAL);

    // Scan backwards through the write clusters to find the closest younger
    // preceding & overlapping writes.
    for (auto cluster = writeClusters.rbegin();
         cluster != writeClusters.rend() && wc_overlap; ++cluster) {
        for (const auto& addr_write : cluster->writes) {
            const Transaction& write = addr_write.second;

            if (write.complete < last_obs.start) {
                // If this write transaction completed before the last
                // observation, we ignore it as the last_observation has the
                // correct value
                continue;
            }

            if (write.data == data) {
                // Found a match, end search.
                return true;
            }

            // Record possible, but non-matching data for debugging
            _lastExpectedData.push_back(write.data);

            if (write.complete > start) {
                // This write overlapped with the transaction we want to check
                // -> continue checking the overlapping write cluster
                continue;
            }

            // This write cluster has writes that have completed before the
            // checked transaction. There is no need to check an earlier
            // write-cluster -> set the exit condition for the outer loop
            wc_overlap = false;

            if (last_obs.complete < write.start) {
                // We found a write which started after the last observed read,
                // therefore we can not longer consider the value seen by the
                // last observation as a valid expected value.
                //
                // Once all writes have been iterated through, we can check if
                // the last observation is still valid to compare against.
                last_obs_valid = false;
            }
        }
    }

    // We have not found any matching write, so far; check other sources of
    // confirmation
    if (last_obs_valid) {
        // The last observation is not outdated according to the writes we have
        // seen so far.
        assert(last_obs.complete <= start);
        if (last_obs.data == data) {
            // Matched data from last observation -> all good
            return true;
        }
        // Record non-matching, but possible value
        _lastExpectedData.push_back(last_obs.data);
    }

    if (_lastExpectedData.empty()) {
        assert(last_obs.complete == TICK_INITIAL);
        // We have not found any possible (non-matching data). Can happen in
        // initial system state
        DPRINTF(MemChecker, "no last observation nor write! start = %d, "\
                "complete = %d, data = %#x\n", start, complete, data);
        return true;
    }
    return false;
}

bool
MemChecker::ByteTracker::completeRead(MemChecker::Serial serial,
                                      Tick complete, uint8_t data)
{
    auto it = outstandingReads.find(serial);

    if (it == outstandingReads.end()) {
        // Can happen if concurrent with reset_address_range
        warn("Could not locate read transaction: serial = %d, complete = %d\n",
             serial, complete);
        return true;
    }

    Tick start = it->second.start;
    outstandingReads.erase(it);

    // Verify data
    const bool result = inExpectedData(start, complete, data);

    readObservations.emplace_back(serial, start, complete, data);
    pruneTransactions();

    return result;
}

MemChecker::WriteCluster*
MemChecker::ByteTracker::getIncompleteWriteCluster()
{
    if (writeClusters.empty() || writeClusters.back().isComplete()) {
        writeClusters.emplace_back();
    }

    return &writeClusters.back();
}

void
MemChecker::ByteTracker::startWrite(MemChecker::Serial serial, Tick start,
                                    uint8_t data)
{
    getIncompleteWriteCluster()->startWrite(serial, start, data);
}

void
MemChecker::ByteTracker::completeWrite(MemChecker::Serial serial, Tick complete)
{
    getIncompleteWriteCluster()->completeWrite(serial, complete);
    pruneTransactions();
}

void
MemChecker::ByteTracker::abortWrite(MemChecker::Serial serial)
{
    getIncompleteWriteCluster()->abortWrite(serial);
}

void
MemChecker::ByteTracker::pruneTransactions()
{
    // Obtain tick of first outstanding read. If there are no outstanding
    // reads, we use curTick(), i.e. we will remove all readObservation except
    // the most recent one.
    const Tick before = outstandingReads.empty() ? curTick() :
                        outstandingReads.begin()->second.start;

    // Pruning of readObservations
    readObservations.erase(readObservations.begin(),
                           lastCompletedTransaction(&readObservations, before));

    // Pruning of writeClusters
    if (!writeClusters.empty()) {
        writeClusters.erase(writeClusters.begin(),
                            lastCompletedTransaction(&writeClusters, before));
    }
}

bool
MemChecker::completeRead(MemChecker::Serial serial, Tick complete,
                         Addr addr, size_t size, uint8_t *data)
{
    bool result = true;

    DPRINTF(MemChecker,
            "completing read: serial = %d, complete = %d, "
            "addr = %#llx, size = %d\n", serial, complete, addr, size);

    for (size_t i = 0; i < size; ++i) {
        ByteTracker *tracker = getByteTracker(addr + i);

        if (!tracker->completeRead(serial, complete, data[i])) {
            // Generate error message, and aggregate all failures for the bytes
            // considered in this transaction in one message.
            if (result) {
                result = false;
                errorMessage = "";
            } else {
                errorMessage += "\n";
            }

            errorMessage += csprintf("  Read transaction for address %#llx "
                                     "failed: received %#x, expected ",
                                     (unsigned long long)(addr + i), data[i]);

            for (size_t j = 0; j < tracker->lastExpectedData().size(); ++j) {
                errorMessage +=
                    csprintf("%#x%s",
                             tracker->lastExpectedData()[j],
                             (j == tracker->lastExpectedData().size() - 1)
                             ? "" : "|");
            }
        }
    }

    if (!result) {
        DPRINTF(MemChecker, "read of %#llx @ cycle %d failed:\n%s\n", addr,
                complete, errorMessage);
    }

    return result;
}

void
MemChecker::reset(Addr addr, size_t size)
{
    for (size_t i = 0; i < size; ++i) {
        byte_trackers.erase(addr + i);
    }
}

MemChecker*
MemCheckerParams::create()
{
    return new MemChecker(this);
}
