/*
 * Copyright (c) 2013-2016,2019 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.
 */

/**
 * @file
 * Definition of a snoop filter.
 */

#ifndef __MEM_SNOOP_FILTER_HH__
#define __MEM_SNOOP_FILTER_HH__

#include <bitset>
#include <unordered_map>
#include <utility>

#include "mem/packet.hh"
#include "mem/port.hh"
#include "mem/qport.hh"
#include "params/SnoopFilter.hh"
#include "sim/sim_object.hh"
#include "sim/system.hh"

/**
 * This snoop filter keeps track of which connected port has a
 * particular line of data. It can be queried (through lookup*) on
 * memory requests from above (reads / writes / ...); and also from
 * below (snoops). The snoop filter precisely knows about the location
 * of lines "above" it through a map from cache line address to
 * sharers/ports. The snoop filter ties into the flows of requests
 * (when they succeed at the lower interface), regular responses from
 * below and also responses from sideway's caches (in update*). This
 * allows the snoop filter to model cache-line residency by snooping
 * the messages.
 *
 * The tracking happens in two fields to be able to distinguish
 * between in-flight requests (in requested) and already pulled in
 * lines (in holder). This distinction is used for producing tighter
 * assertions and tracking request completion. For safety, (requested
 * | holder) should be notified and the requesting MSHRs will take
 * care of ordering.
 *
 * Overall, some trickery is required because:
 * (1) snoops are not followed by an ACK, but only evoke a response if
 *     they need to (hit dirty)
 * (2) side-channel information is funnelled through direct modifications of
 *     pkt, instead of proper messages through the bus
 * (3) there are no clean evict messages telling the snoop filter that a local,
 *     upper cache dropped a line, making the snoop filter pessimistic for now
 * (4) ordering: there is no single point of order in the system.  Instead,
 *     requesting MSHRs track order between local requests and remote snoops
 */
class SnoopFilter : public SimObject {
  public:

    // Change for systems with more than 256 ports tracked by this object
    static const int SNOOP_MASK_SIZE = 256;

    typedef std::vector<QueuedSlavePort*> SnoopList;

    SnoopFilter (const SnoopFilterParams *p) :
        SimObject(p), reqLookupResult(cachedLocations.end()),
        linesize(p->system->cacheLineSize()), lookupLatency(p->lookup_latency),
        maxEntryCount(p->max_capacity / p->system->cacheLineSize())
    {
    }

    /**
     * Init a new snoop filter and tell it about all the slave ports
     * of the enclosing bus.
     *
     * @param slave_ports Slave ports that the bus is attached to.
     */
    void setSlavePorts(const SnoopList& slave_ports) {
        localSlavePortIds.resize(slave_ports.size(), InvalidPortID);

        PortID id = 0;
        for (const auto& p : slave_ports) {
            // no need to track this port if it is not snooping
            if (p->isSnooping()) {
                slavePorts.push_back(p);
                localSlavePortIds[p->getId()] = id++;
            }
        }

        // make sure we can deal with this many ports
        fatal_if(id > SNOOP_MASK_SIZE,
                 "Snoop filter only supports %d snooping ports, got %d\n",
                 SNOOP_MASK_SIZE, id);
    }

    /**
     * Lookup a request (from a slave port) in the snoop filter and
     * return a list of other slave ports that need forwarding of the
     * resulting snoops.  Additionally, update the tracking structures
     * with new request information. Note that the caller must also
     * call finishRequest once it is known if the request needs to
     * retry or not.
     *
     * @param cpkt          Pointer to the request packet. Not changed.
     * @param slave_port    Slave port where the request came from.
     * @return Pair of a vector of snoop target ports and lookup latency.
     */
    std::pair<SnoopList, Cycles> lookupRequest(const Packet* cpkt,
                                               const ResponsePort& slave_port);

    /**
     * For an un-successful request, revert the change to the snoop
     * filter. Also take care of erasing any null entries. This method
     * relies on the result from lookupRequest being stored in
     * reqLookupResult.
     *
     * @param will_retry    This request will retry on this bus / snoop filter
     * @param addr          Packet address, merely for sanity checking
     */
    void finishRequest(bool will_retry, Addr addr, bool is_secure);

    /**
     * Handle an incoming snoop from below (the master port). These
     * can upgrade the tracking logic and may also benefit from
     * additional steering thanks to the snoop filter.
     *
     * @param cpkt Pointer to const Packet containing the snoop.
     * @return Pair with a vector of ResponsePorts that need snooping and a
     * lookup latency.
     */
    std::pair<SnoopList, Cycles> lookupSnoop(const Packet* cpkt);

    /**
     * Let the snoop filter see any snoop responses that turn into
     * request responses and indicate cache to cache transfers. These
     * will update the corresponding state in the filter.
     *
     * @param cpkt     Pointer to const Packet holding the snoop response.
     * @param rsp_port ResponsePort that sends the response.
     * @param req_port ResponsePort that made the original request and is the
     *                 destination of the snoop response.
     */
    void updateSnoopResponse(const Packet *cpkt, const ResponsePort& rsp_port,
                             const ResponsePort& req_port);

    /**
     * Pass snoop responses that travel downward through the snoop
     * filter and let them update the snoop filter state.  No
     * additional routing happens.
     *
     * @param cpkt     Pointer to const Packet holding the snoop response.
     * @param rsp_port ResponsePort that sends the response.
     * @param req_port RequestPort through which the response is forwarded.
     */
    void updateSnoopForward(const Packet *cpkt, const ResponsePort& rsp_port,
                            const RequestPort& req_port);

    /**
     * Update the snoop filter with a response from below (outer /
     * other cache, or memory) and update the tracking information in
     * the snoop filter.
     *
     * @param cpkt       Pointer to const Packet holding the snoop response.
     * @param slave_port ResponsePort that made the original request and
     *                   is the target of this response.
     */
    void updateResponse(const Packet *cpkt, const ResponsePort& slave_port);

    virtual void regStats();

  protected:

    /**
     * The underlying type for the bitmask we use for tracking. This
     * limits the number of snooping ports supported per crossbar.
     */
    typedef std::bitset<SNOOP_MASK_SIZE> SnoopMask;

    /**
    * Per cache line item tracking a bitmask of ResponsePorts who have an
    * outstanding request to this line (requested) or already share a
    * cache line with this address (holder).
    */
    struct SnoopItem {
        SnoopMask requested;
        SnoopMask holder;
    };
    /**
     * HashMap of SnoopItems indexed by line address
     */
    typedef std::unordered_map<Addr, SnoopItem> SnoopFilterCache;

    /**
     * Simple factory methods for standard return values.
     */
    std::pair<SnoopList, Cycles> snoopAll(Cycles latency) const
    {
        return std::make_pair(slavePorts, latency);
    }
    std::pair<SnoopList, Cycles> snoopSelected(const SnoopList& slave_ports,
                                               Cycles latency) const
    {
        return std::make_pair(slave_ports, latency);
    }
    std::pair<SnoopList, Cycles> snoopDown(Cycles latency) const
    {
        SnoopList empty;
        return std::make_pair(empty , latency);
    }

    /**
     * Convert a single port to a corresponding, one-hot bitmask
     * @param port ResponsePort that should be converted.
     * @return One-hot bitmask corresponding to the port.
     */
    SnoopMask portToMask(const ResponsePort& port) const;
    /**
     * Converts a bitmask of ports into the corresponing list of ports
     * @param ports SnoopMask of the requested ports
     * @return SnoopList containing all the requested ResponsePorts
     */
    SnoopList maskToPortList(SnoopMask ports) const;

  private:

    /**
     * Removes snoop filter items which have no requesters and no holders.
     */
    void eraseIfNullEntry(SnoopFilterCache::iterator& sf_it);

    /** Simple hash set of cached addresses. */
    SnoopFilterCache cachedLocations;

    /**
     * A request lookup must be followed by a call to finishRequest to inform
     * the operation's success. If a retry is needed, however, all changes
     * made to the snoop filter while performing the lookup must be undone.
     * This structure keeps track of the state previous to such changes.
     */
    struct ReqLookupResult {
        /** Iterator used to store the result from lookupRequest. */
        SnoopFilterCache::iterator it;

        /**
         * Variable to temporarily store value of snoopfilter entry
         * in case finishRequest needs to undo changes made in lookupRequest
         * (because of crossbar retry)
         */
        SnoopItem retryItem;

        /**
         * The constructor must be informed of the internal cache's end
         * iterator, so do not allow the compiler to implictly define it.
         *
         * @param end_it Iterator to the end of the internal cache.
         */
        ReqLookupResult(SnoopFilterCache::iterator end_it)
            : it(end_it), retryItem{0, 0}
        {
        }
        ReqLookupResult() = delete;
    } reqLookupResult;

    /** List of all attached snooping slave ports. */
    SnoopList slavePorts;
    /** Track the mapping from port ids to the local mask ids. */
    std::vector<PortID> localSlavePortIds;
    /** Cache line size. */
    const unsigned linesize;
    /** Latency for doing a lookup in the filter */
    const Cycles lookupLatency;
    /** Max capacity in terms of cache blocks tracked, for sanity checking */
    const unsigned maxEntryCount;

    /**
     * Use the lower bits of the address to keep track of the line status
     */
    enum LineStatus {
        /** block holds data from the secure memory space */
        LineSecure = 0x01,
    };

    /** Statistics */
    Stats::Scalar totRequests;
    Stats::Scalar hitSingleRequests;
    Stats::Scalar hitMultiRequests;

    Stats::Scalar totSnoops;
    Stats::Scalar hitSingleSnoops;
    Stats::Scalar hitMultiSnoops;
};

inline SnoopFilter::SnoopMask
SnoopFilter::portToMask(const ResponsePort& port) const
{
    assert(port.getId() != InvalidPortID);
    // if this is not a snooping port, return a zero mask
    return !port.isSnooping() ? 0 :
        ((SnoopMask)1) << localSlavePortIds[port.getId()];
}

inline SnoopFilter::SnoopList
SnoopFilter::maskToPortList(SnoopMask port_mask) const
{
    SnoopList res;
    for (const auto& p : slavePorts)
        if ((port_mask & portToMask(*p)).any())
            res.push_back(p);
    return res;
}

#endif // __MEM_SNOOP_FILTER_HH__
