/*
 * Copyright (c) 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.
 *
 * Authors: Andreas Sandberg
 */

#ifndef __BASE_CHANNEL_ADDR_HH__
#define __BASE_CHANNEL_ADDR_HH__

#include <ostream>

#include "base/addr_range.hh"

/**
 * Class holding a guest address in a contiguous channel-local address
 * space.
 */
class ChannelAddr
{
  public:
    using Type = Addr;

    /** Explicit constructor assigning a value. */
    explicit constexpr ChannelAddr(Type _a) : a(_a) { }

    /** Converting back to the value type. */
    explicit constexpr operator Type() const { return a; }

    /** Converting back to the value type. */
    constexpr Type value() const { return a; }

    constexpr ChannelAddr() : a(0) { }

    ChannelAddr(const AddrRange &range, Addr _a)
        : a(range.removeIntlvBits(_a)) {}

    ChannelAddr(const ChannelAddr &) = default;
    ChannelAddr &operator=(const ChannelAddr &) = default;


    Addr getPA(const AddrRange &range) const {
        return range.addIntlvBits(a);
    }

    constexpr ChannelAddr operator|(const Type b) const {
        return ChannelAddr(a | b);
    }
    constexpr ChannelAddr operator&(const Type b) const {
        return ChannelAddr(a & b);
    }

    constexpr ChannelAddr operator>>(const int b) const {
        return ChannelAddr(a >> b);
    }

    constexpr ChannelAddr operator<<(const int b) const {
        return ChannelAddr(a << b);
    }

    constexpr ChannelAddr operator*(const Type &b) const {
        return ChannelAddr(a * b);
    }

    constexpr ChannelAddr operator/(const Type &b) const {
        return ChannelAddr(a / b);
    }

    constexpr ChannelAddr operator+(const Type &b) const {
        return ChannelAddr(a + b);
    }

    constexpr ChannelAddr operator-(const Type &b) const {
        return ChannelAddr(a - b);
    }

    constexpr ChannelAddr operator|(const ChannelAddr &b) const {
        return ChannelAddr(a | b.a);
    }

    constexpr ChannelAddr operator&(const ChannelAddr &b) const {
        return ChannelAddr(a & b.a);
    }

    constexpr ChannelAddr operator^(const ChannelAddr &b) const {
        return ChannelAddr(a ^ b.a);
    }

    constexpr ChannelAddr operator+(const ChannelAddr &b) const {
        return ChannelAddr(a + b.a);
    }

    constexpr ChannelAddr operator-(const ChannelAddr &b) const {
        return ChannelAddr(a - b.a);
    }

    constexpr bool operator>(const ChannelAddr &b) const { return a > b.a; }
    constexpr bool operator>=(const ChannelAddr &b) const { return a >= b.a; }
    constexpr bool operator<(const ChannelAddr &b) const { return a < b.a; }
    constexpr bool operator<=(const ChannelAddr &b) const { return a <= b.a; }
    constexpr bool operator==(const ChannelAddr &b) const { return a == b.a; }
    constexpr bool operator!=(const ChannelAddr &b) const { return a != b.a; }

  private:
    /** Member holding the actual value. */
    Type a;
};

/**
 * The ChanneelAddrRange class describes a contiguous range of
 * addresses in a contiguous channel-local address space.
 */
class ChannelAddrRange
{
  public:
    constexpr ChannelAddrRange()
        : ChannelAddrRange(ChannelAddr(1), ChannelAddr(0)) {}

    constexpr ChannelAddrRange(ChannelAddr start, ChannelAddr end)
        : _start(start), _end(end) {}

    ChannelAddrRange(AddrRange ch_range, Addr start, Addr end);
    ChannelAddrRange(AddrRange ch_range, AddrRange range);

    constexpr ChannelAddrRange(const ChannelAddrRange &) = default;

    constexpr ChannelAddr size() const { return _end - _start + 1; }

    constexpr bool valid() const { return _start <= _end; }

    constexpr ChannelAddr start() const { return _start; }
    constexpr ChannelAddr end() const { return _end; }

    constexpr bool contains(ChannelAddr a) const {
        return a >= _start && a <= _end;
    }

  protected:
    ChannelAddr _start;
    ChannelAddr _end;
};

namespace std
{
    template<>
    struct hash<ChannelAddr>
    {
        typedef ChannelAddr argument_type;
        typedef std::size_t result_type;

        result_type
        operator()(argument_type const &a) const noexcept {
            return std::hash<ChannelAddr::Type>{}(
                static_cast<argument_type::Type>(a));
        }
    };
}

std::ostream &operator<<(std::ostream &out, const ChannelAddr &addr);

#endif // __BASE_CHANNEL_ADDR_HH__
