/*
 * Copyright (c) 2021 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.
 */

#ifndef __MEM_RUBY_STRUCTURES_TBESTORAGE_HH__
#define __MEM_RUBY_STRUCTURES_TBESTORAGE_HH__

#include <cassert>
#include <stack>
#include <unordered_map>

#include <base/statistics.hh>

// The TBEStorage is used to track the resources consumed by the TBETable,
// i.e. the number of available TBE slots.
//
// TBEStorage resource tracking has two main differences from TBETable:
//
// 1) Allows slot reservation. This is useful to implement protocols that
// employ retry/credit messages instead of stall when the controller runs
// out of TBEs to accept new request.
//
// 2) Can also assign multiple entries to the same slot. This is useful to
// more easily model cases where multiple transactions share the same TBE
// resource (i.e. the slot).
// E.g: a request that triggers a replacement in a system without
// dedicated WB/Eviction buffer; both transactions can can have separate
// logical TBEs associated to the same slot.
//
// The motivation for having a separate structures for tracking TBEs
// availability are twofold:
//
// - Keeps TBETable simple and without the additional overhead for
// protocols that do not need these additional features.
//
// - Having two separate transactions sharing the same TBE resource using
// the current TBETable would be cumbersome since the TBETable is indexed
// by the transaction address.

class TBEStorage {
  public:
    TBEStorage(Stats::Group *parent, int number_of_TBEs);

    // Returns the current number of slots allocated
    int size() const { return m_slots_used.size(); }

    // Returns the total capacity of this TBEStorage table
    int capacity() const { return m_slots_used.size() + m_slots_avail.size(); }

    // Returns number of slots currently reserved
    int reserved() const { return m_reserved; }

    // Returns the number of slots available
    int slotsAvailable() const { return m_slots_avail.size() - m_reserved; }

    // Returns the TBEStorage utilization
    float utilization() const { return size() / (float)capacity(); }

    // Returns true if slotsAvailable() >= n; current_time is always ignored
    // This allows this class to be used with check_allocate in SLICC to
    // trigger resource stalls when there are no slots available
    bool areNSlotsAvailable(int n, Tick current_time = 0) const;

    // Increase/decrease the number of reserved slots. Having reserved slots
    // reduces the number of slots available for allocation
    void incrementReserved();
    void decrementReserved();

    // Assign a TBETable entry to a free slot and returns the slot number.
    // Notice we don't need any info from TBETable and just track the number
    // of entries assigned to each slot.
    // This funcion requires slotsAvailable() > 0
    int addEntryToNewSlot();

    // Assign an entry to an existing non-empty slot
    void addEntryToSlot(int slot);

    // Remove an entry from an existing non-empty slot. The slot becomes
    // available again when the number of assigned entries == 0
    void removeEntryFromSlot(int slot);

  private:
    int m_reserved;
    std::stack<int> m_slots_avail;
    std::unordered_map<int, int> m_slots_used;

    struct TBEStorageStats : public Stats::Group
    {
        TBEStorageStats(Stats::Group *parent);

        // Statistical variables
        Stats::Average avg_size;
        Stats::Average avg_util;
        Stats::Average avg_reserved;
    } m_stats;
};

inline bool
TBEStorage::areNSlotsAvailable(int n, Tick current_time) const
{
    return slotsAvailable() >= n;
}

inline void
TBEStorage::incrementReserved()
{
    ++m_reserved;
    m_stats.avg_reserved = m_reserved;
}

inline void
TBEStorage::decrementReserved()
{
    assert(m_reserved > 0);
    --m_reserved;
    m_stats.avg_reserved = m_reserved;
}

inline int
TBEStorage::addEntryToNewSlot()
{
    assert(slotsAvailable() > 0);
    assert(m_slots_avail.size() > 0);
    int slot = m_slots_avail.top();
    m_slots_used[slot] = 1;
    m_slots_avail.pop();
    m_stats.avg_size = size();
    m_stats.avg_util = utilization();
    return slot;
}

inline void
TBEStorage::addEntryToSlot(int slot)
{
    auto iter = m_slots_used.find(slot);
    assert(iter != m_slots_used.end());
    iter->second += 1;
}

inline void
TBEStorage::removeEntryFromSlot(int slot)
{
    auto iter = m_slots_used.find(slot);
    assert(iter != m_slots_used.end());
    assert(iter->second > 0);
    iter->second -= 1;
    if (iter->second == 0) {
        m_slots_used.erase(iter);
        m_slots_avail.push(slot);
    }
    m_stats.avg_size = size();
    m_stats.avg_util = utilization();
}

#endif
