/*
 * Copyright (c) 2020 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) 2010 Gabe Black
 * 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.
 */

#ifndef __ARCH_GENERIC_TYPES_HH__
#define __ARCH_GENERIC_TYPES_HH__

#include <iostream>
#include <memory>
#include <type_traits>

#include "base/compiler.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "sim/serialize.hh"

namespace gem5
{

// The guaranteed interface.
class PCStateBase : public Serializable
{
  protected:
    Addr _pc = 0;
    MicroPC _upc = 0;

    PCStateBase(const PCStateBase &other) : _pc(other._pc), _upc(other._upc) {}
    PCStateBase &operator=(const PCStateBase &other) = default;
    PCStateBase() {}

  public:
    virtual ~PCStateBase() = default;

    template<class Target>
    Target &
    as()
    {
        return static_cast<Target &>(*this);
    }

    template<class Target>
    const Target &
    as() const
    {
        return static_cast<const Target &>(*this);
    }

    virtual PCStateBase *clone() const = 0;
    virtual void
    update(const PCStateBase &other)
    {
        _pc = other._pc;
        _upc = other._upc;
    }
    void update(const PCStateBase *ptr) { update(*ptr); }

    virtual void output(std::ostream &os) const = 0;

    virtual bool
    equals(const PCStateBase &other) const
    {
        return _pc == other._pc && _upc == other._upc;
    }

    /**
     * Returns the memory address of the instruction this PC points to.
     *
     * @return Memory address of the instruction this PC points to.
     */
    Addr
    instAddr() const
    {
        return _pc;
    }

    /**
     * Returns the current micropc.
     *
     * @return The current micropc.
     */
    MicroPC
    microPC() const
    {
        return _upc;
    }

    virtual void
    uReset()
    {
        _upc = 0;
    }

    void
    serialize(CheckpointOut &cp) const override
    {
        SERIALIZE_SCALAR(_pc);
        SERIALIZE_SCALAR(_upc);
    }

    void
    unserialize(CheckpointIn &cp) override
    {
        UNSERIALIZE_SCALAR(_pc);
        UNSERIALIZE_SCALAR(_upc);
    }
};

static inline std::ostream &
operator<<(std::ostream & os, const PCStateBase &pc)
{
    pc.output(os);
    return os;
}

static inline bool
operator==(const PCStateBase &a, const PCStateBase &b)
{
    return a.equals(b);
}

static inline bool
operator!=(const PCStateBase &a, const PCStateBase &b)
{
    return !a.equals(b);
}

namespace
{

inline void
set(PCStateBase *&dest, const PCStateBase *src)
{
    if (GEM5_LIKELY(dest)) {
        if (GEM5_LIKELY(src)) {
            // Both src and dest already have storage, so just copy contents.
            dest->update(src);
        } else {
            // src is empty, so clear out dest.
            dest = nullptr;
        }
    } else {
        if (GEM5_LIKELY(src)) {
            // dest doesn't have storage, so create some as a copy of src.
            dest = src->clone();
        } else {
            // dest is already nullptr, so nothing to do.
        }
    }
}

inline void
set(std::unique_ptr<PCStateBase> &dest, const PCStateBase *src)
{
    PCStateBase *dest_ptr = dest.get();
    set(dest_ptr, src);
    if (dest.get() != dest_ptr)
        dest.reset(dest_ptr);
}

inline void
set(PCStateBase *&dest, const std::unique_ptr<PCStateBase> &src)
{
    const PCStateBase *src_ptr = src.get();
    set(dest, src_ptr);
}

inline void
set(std::unique_ptr<PCStateBase> &dest,
        const std::unique_ptr<PCStateBase> &src)
{
    PCStateBase *dest_ptr = dest.get();
    const PCStateBase *src_ptr = src.get();
    set(dest_ptr, src_ptr);
    if (dest.get() != dest_ptr)
        dest.reset(dest_ptr);
}

inline void
set(PCStateBase *&dest, const PCStateBase &src)
{
    if (GEM5_LIKELY(dest)) {
        // Update dest with the contents of src.
        dest->update(src);
    } else {
        // Clone src over to dest.
        dest = src.clone();
    }
}

inline void
set(std::unique_ptr<PCStateBase> &dest, const PCStateBase &src)
{
    PCStateBase *dest_ptr = dest.get();
    set(dest_ptr, src);
    if (dest.get() != dest_ptr)
        dest.reset(dest_ptr);
}

inline void
set(PCStateBase &dest, const PCStateBase &src)
{
    dest.update(src);
}

} // anonymous namespace

namespace GenericISA
{

class PCStateCommon : public PCStateBase
{
  protected:
    Addr _npc = 0;

    MicroPC _nupc = 1;

    PCStateCommon(const PCStateCommon &other) : PCStateBase(other),
        _npc(other._npc), _nupc(other._nupc)
    {}
    PCStateCommon &operator=(const PCStateCommon &other) = default;
    PCStateCommon() {}

  public:
    Addr pc() const { return _pc; }
    void pc(Addr val) { _pc = val; }

    Addr npc() const { return _npc; }
    void npc(Addr val) { _npc = val; }

    MicroPC upc() const { return _upc; }
    void upc(MicroPC val) { _upc = val; }

    MicroPC nupc() const { return _nupc; }
    void nupc(MicroPC val) { _nupc = val; }

    // Reset the macroop's upc without advancing the regular pc.
    void
    uReset() override
    {
        PCStateBase::uReset();
        _nupc = 1;
    }

    void
    setNPC(Addr val)
    {
        npc(val);
    }

    void
    output(std::ostream &os) const override
    {
        ccprintf(os, "(%#x=>%#x)", this->pc(), this->npc());
    }

    void
    update(const PCStateBase &other) override
    {
        PCStateBase::update(other);
        auto &pcstate = other.as<PCStateCommon>();
        _npc = pcstate._npc;
        _nupc = pcstate._nupc;
    }

    bool
    equals(const PCStateBase &other) const override
    {
        auto &ps = other.as<PCStateCommon>();
        return PCStateBase::equals(other) &&
            _npc == ps._npc && _nupc == ps._nupc;
    }

    void
    serialize(CheckpointOut &cp) const override
    {
        PCStateBase::serialize(cp);
        SERIALIZE_SCALAR(_npc);
        SERIALIZE_SCALAR(_nupc);
    }

    void
    unserialize(CheckpointIn &cp) override
    {
        PCStateBase::unserialize(cp);
        UNSERIALIZE_SCALAR(_npc);
        UNSERIALIZE_SCALAR(_nupc);
    }
};


/*
 * Different flavors of PC state. Only ISA specific code should rely on
 * any particular type of PC state being available. All other code should
 * use the interface above.
 */

// The most basic type of PC.
template <int InstWidth>
class SimplePCState : public PCStateCommon
{
  protected:
    typedef PCStateCommon Base;

  public:
    SimplePCState(const SimplePCState &other) : Base(other) {}
    SimplePCState &operator=(const SimplePCState &other) = default;
    SimplePCState() {}
    explicit SimplePCState(Addr val) { set(val); }

    PCStateBase *
    clone() const override
    {
        return new SimplePCState<InstWidth>(*this);
    }

    /**
     * Force this PC to reflect a particular value, resetting all its other
     * fields around it. This is useful for in place (re)initialization.
     *
     * @param val The value to set the PC to.
     */
    void
    set(Addr val)
    {
        this->pc(val);
        this->npc(val + InstWidth);
    };

    bool
    branching() const
    {
        return this->npc() != this->pc() + InstWidth;
    }

    // Advance the PC.
    void
    advance()
    {
        this->_pc = this->_npc;
        this->_npc += InstWidth;
    }
};

// A PC and microcode PC.
template <int InstWidth>
class UPCState : public SimplePCState<InstWidth>
{
  protected:
    typedef SimplePCState<InstWidth> Base;

  public:
    void
    output(std::ostream &os) const override
    {
        Base::output(os);
        ccprintf(os, ".(%d=>%d)", this->upc(), this->nupc());
    }

    PCStateBase *
    clone() const override
    {
        return new UPCState<InstWidth>(*this);
    }

    void
    set(Addr val)
    {
        Base::set(val);
        this->upc(0);
        this->nupc(1);
    }

    UPCState(const UPCState &other) : Base(other) {}
    UPCState &operator=(const UPCState &other) = default;
    UPCState() {}
    explicit UPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return this->npc() != this->pc() + InstWidth ||
               this->nupc() != this->upc() + 1;
    }

    // Advance the upc within the instruction.
    void
    uAdvance()
    {
        this->upc(this->nupc());
        this->nupc(this->nupc() + 1);
    }

    // End the macroop by resetting the upc and advancing the regular pc.
    void
    uEnd()
    {
        this->advance();
        this->upc(0);
        this->nupc(1);
    }
};

// A PC with a delay slot.
template <int InstWidth>
class DelaySlotPCState : public SimplePCState<InstWidth>
{
  protected:
    typedef SimplePCState<InstWidth> Base;

    Addr _nnpc;

  public:
    void
    output(std::ostream &os) const override
    {
        ccprintf(os, "(%#x=>%#x=>%#x)", this->pc(), this->npc(), nnpc());
    }

    PCStateBase *
    clone() const override
    {
        return new DelaySlotPCState<InstWidth>(*this);
    }

    void
    update(const PCStateBase &other) override
    {
        Base::update(other);
        auto &pcstate = other.as<DelaySlotPCState<InstWidth>>();
        _nnpc = pcstate._nnpc;
    }

    Addr nnpc() const { return _nnpc; }
    void nnpc(Addr val) { _nnpc = val; }

    void
    set(Addr val)
    {
        Base::set(val);
        nnpc(val + 2 * InstWidth);
    }

    DelaySlotPCState(const DelaySlotPCState &other) :
        Base(other), _nnpc(other._nnpc)
    {}
    DelaySlotPCState &operator=(const DelaySlotPCState &other) = default;
    DelaySlotPCState() {}
    explicit DelaySlotPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return !(this->nnpc() == this->npc() + InstWidth &&
                 (this->npc() == this->pc() + InstWidth ||
                  this->npc() == this->pc() + 2 * InstWidth));
    }

    // Advance the PC.
    void
    advance()
    {
        this->_pc = this->_npc;
        this->_npc = this->_nnpc;
        this->_nnpc += InstWidth;
    }

    bool
    equals(const PCStateBase &other) const override
    {
        auto &ps = other.as<DelaySlotPCState<InstWidth>>();
        return Base::equals(other) && ps._nnpc == this->_nnpc;
    }

    void
    serialize(CheckpointOut &cp) const override
    {
        Base::serialize(cp);
        SERIALIZE_SCALAR(_nnpc);
    }

    void
    unserialize(CheckpointIn &cp) override
    {
        Base::unserialize(cp);
        UNSERIALIZE_SCALAR(_nnpc);
    }
};

// A PC with a delay slot and a microcode PC.
template <int InstWidth>
class DelaySlotUPCState : public DelaySlotPCState<InstWidth>
{
  protected:
    typedef DelaySlotPCState<InstWidth> Base;

  public:
    void
    output(std::ostream &os) const override
    {
        Base::output(os);
        ccprintf(os, ".(%d=>%d)", this->upc(), this->nupc());
    }

    PCStateBase *
    clone() const override
    {
        return new DelaySlotUPCState<InstWidth>(*this);
    }

    void
    set(Addr val)
    {
        Base::set(val);
        this->upc(0);
        this->nupc(1);
    }

    DelaySlotUPCState(const DelaySlotUPCState &other) : Base(other) {}
    DelaySlotUPCState &operator=(const DelaySlotUPCState &other) = default;
    DelaySlotUPCState() {}
    explicit DelaySlotUPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return Base::branching() || this->nupc() != this->upc() + 1;
    }

    // Advance the upc within the instruction.
    void
    uAdvance()
    {
        this->_upc = this->_nupc;
        this->_nupc++;
    }

    // End the macroop by resetting the upc and advancing the regular pc.
    void
    uEnd()
    {
        this->advance();
        this->_upc = 0;
        this->_nupc = 1;
    }
};

}

} // namespace gem5

#endif
