/*
 * Copyright (c) 2006 The Regents of The University of Michigan
 * 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.
 *
 * Authors: Ali Saidi
 */

#ifndef __ARCH_SPARC_PAGETABLE_HH__
#define __ARCH_SPARC_PAGETABLE_HH__

#include <cassert>

#include "arch/sparc/isa_traits.hh"
#include "base/bitfield.hh"
#include "base/misc.hh"

class Checkpoint;

namespace SparcISA {

struct VAddr
{
    VAddr(Addr a) { panic("not implemented yet."); }
};

class TteTag
{
  private:
    uint64_t entry;
    bool populated;

  public:
    TteTag() : entry(0), populated(false) {}
    TteTag(uint64_t e) : entry(e), populated(true) {}

    const TteTag &
    operator=(uint64_t e) 
    {
        populated = true;
        entry = e;
        return *this;
    }

    bool valid() const { assert(populated); return !bits(entry,62,62); }
    Addr va()    const { assert(populated); return bits(entry,41,0); }
};


class PageTableEntry
{
  public:
    enum EntryType {
      sun4v,
      sun4u,
      invalid
    };

  private:
    uint64_t entry;
    EntryType type;
    uint64_t entry4u;
    bool populated;

  public:
    PageTableEntry() : entry(0), type(invalid), populated(false)
    {}

    PageTableEntry(uint64_t e, EntryType t = sun4u)
        : entry(e), type(t), populated(true)
    {
        populate(entry, type);
    }

    void
    populate(uint64_t e, EntryType t = sun4u)
    {
        entry = e;
        type = t;
        populated = true;

        // If we get a sun4v format TTE, turn it into a sun4u
        if (type == sun4u)
            entry4u = entry;
        else {
            entry4u = 0;
            entry4u |= mbits(entry,63,63);         // valid
            entry4u |= bits(entry,1,0) << 61;      // size[1:0]
            entry4u |= bits(entry,62,62) << 60;    // nfo
            entry4u |= bits(entry,12,12) << 59;    // ie
            entry4u |= bits(entry,2,2) << 48;      // size[2]
            entry4u |= mbits(entry,39,13);         // paddr
            entry4u |= bits(entry,61,61) << 6;;    // locked
            entry4u |= bits(entry,10,10) << 5;     // cp
            entry4u |= bits(entry,9,9) << 4;       // cv
            entry4u |= bits(entry,11,11) << 3;     // e
            entry4u |= bits(entry,8,8) << 2;       // p
            entry4u |= bits(entry,6,6) << 1;       // w
        }
    }

    void
    clear()
    {
        populated = false;
    }

    static int pageSizes[6];

    uint64_t operator()() const { assert(populated); return entry4u; }

    const PageTableEntry &
    operator=(uint64_t e)
    {
        populated = true;
        entry4u = e;
        return *this;
    }

    const PageTableEntry &
    operator=(const PageTableEntry &e)
    {
        populated = true;
        entry4u = e.entry4u;
        type = e.type;
        return *this;
    }

    bool valid() const { return bits(entry4u,63,63) && populated; }

    uint8_t
    _size() const
    {
        assert(populated);
        return bits(entry4u, 62,61) | bits(entry4u, 48,48) << 2;
    }

    Addr size()     const { assert(_size() < 6); return pageSizes[_size()]; }
    Addr sizeMask() const { return size() - 1; }
    bool ie()       const { return bits(entry4u, 59,59); }
    Addr pfn()      const { assert(populated); return bits(entry4u,39,13); }
    Addr paddr()    const { assert(populated); return mbits(entry4u, 39,13);}
    bool locked()   const { assert(populated); return bits(entry4u,6,6); }
    bool cv()       const { assert(populated); return bits(entry4u,4,4); }
    bool cp()       const { assert(populated); return bits(entry4u,5,5); }
    bool priv()     const { assert(populated); return bits(entry4u,2,2); }
    bool writable() const { assert(populated); return bits(entry4u,1,1); }
    bool nofault()  const { assert(populated); return bits(entry4u,60,60); }
    bool sideffect() const { assert(populated); return bits(entry4u,3,3); }
    Addr paddrMask() const { assert(populated); return paddr() & ~sizeMask(); }

    Addr
    translate(Addr vaddr) const
    {
        assert(populated);
        Addr mask = sizeMask();
        return (paddr() & ~mask) | (vaddr & mask);
    }
};

struct TlbRange
{
    Addr va;
    Addr size;
    int contextId;
    int partitionId;
    bool real;

    inline bool
    operator<(const TlbRange &r2) const
    {
        if (real && !r2.real)
            return true;
        if (!real && r2.real)
            return false;

        if (!real && !r2.real) {
            if (contextId < r2.contextId)
                return true;
            else if (contextId > r2.contextId)
                return false;
        }

        if (partitionId < r2.partitionId)
            return true;
        else if (partitionId > r2.partitionId)
            return false;

        if (va < r2.va)
            return true;
        return false;
    }

    inline bool
    operator==(const TlbRange &r2) const
    {
        return va == r2.va &&
               size == r2.size &&
               contextId == r2.contextId &&
               partitionId == r2.partitionId &&
               real == r2.real;
    }
};


struct TlbEntry
{
    TlbEntry()
    {}

    TlbEntry(Addr asn, Addr vaddr, Addr paddr)
    {
        uint64_t entry = 0;
        entry |= 1ULL << 1; // Writable
        entry |= 0ULL << 2; // Available in nonpriveleged mode
        entry |= 0ULL << 3; // No side effects
        entry |= 1ULL << 4; // Virtually cachable
        entry |= 1ULL << 5; // Physically cachable
        entry |= 0ULL << 6; // Not locked
        entry |= mbits(paddr, 39, 13); // Physical address
        entry |= 0ULL << 48; // size = 8k
        entry |= 0uLL << 59; // Endianness not inverted
        entry |= 0ULL << 60; // Not no fault only
        entry |= 0ULL << 61; // size = 8k
        entry |= 1ULL << 63; // valid
        pte = PageTableEntry(entry);

        range.va = vaddr;
        range.size = 8*(1<<10);
        range.contextId = asn;
        range.partitionId = 0;
        range.real = false;

        valid = true;
    }

    TlbRange range;
    PageTableEntry pte;
    bool used;
    bool valid;

    Addr
    pageStart()
    {
        return pte.paddr();
    }

    void
    updateVaddr(Addr new_vaddr)
    {
        range.va = new_vaddr;
    }

    void serialize(std::ostream &os);
    void unserialize(Checkpoint *cp, const std::string &section);
};

} // namespace SparcISA

#endif // __ARCH_SPARC_PAGE_TABLE_HH__

