//
// Copyright (c) 2021 Google LLC
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
using System;
using Antmicro.Renode.Core;
using System.Linq;
using Antmicro.Renode.Exceptions;
using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Peripherals.Memory;
using Antmicro.Renode.Logging;

namespace Antmicro.Renode.Peripherals.CPU
{
  /*
   * The WindowMMU performs minimal memory address translation and protection
   * by providing one or more windows of software configurable length and offset
   * into another address space. The configuration of the WindowMMU is intended
   * to be handled by a secure operating context, and in the case of Matcha via
   * the System Management Core through Springbok's configuration register file.
   *
   * The WindowMMU has four implementation defined configuration parameters:
   *   o Number of windows
   *     This defines how many address translation windows the WindowMMU has.
   *     It can be any number, but to keep things small in Matcha we have 2 for
   *     the Vector Core's instruction fetch WindowMMU and 4 for the data
   *     WindowMMU.
   *   o Window size
   *     This defines the input virtual address aperture for each window.
   *     The total virtual address aperture for the WindowMMU is the first power
   *     of two greater or equal to Window Size times Number of Windows (in
   *     other words, log2ceil(WINDOW_SIZE * NUMBER_OF_WINDOWS)). This must be a
   *     power-of-two multiple of page size. In Matcha this is 4 MiB.
   *   o TCM size
   *     This defines the output physical address aperture for the whole
   *     WindowMMU. This does not need to be the same as window size, though in
   *     Matcha it is.
   *   o Page size
   *     This defines the granularity of window offsets and lengths. It must be
   *     a power-of-two multiple of the largest single access size. In Matcha
   *     to simplify hardware design and match this up with the SMC's MMU's page
   *     size it is set to 4 KiB.
   *
   * Pseudo-code describing a translation:
   *
   *   uint window_length[number_of_windows];
   *   uint window_offset[number_of_windows];
   *   bool window_writable[number_of_windows];
   *   bool window_readable[number_of_windows];
   *
   *   uint getTranslation(uint addr, bool write) {
   *     uint window = addr / window_size;
   *     uint local_addr = addr % window_size;
   *     bool permitted = write? window_writable[window] :
   *                             window_readable[window];
   *
   *     if (permitted && local_addr < (window_length[window] + page_size))
   *       return local_addr + window_offset[window];
   *     else
   *       throw access_fault;
   *   }
   */

  public class SpringbokRiscV32_WindowMMU : IBytePeripheral, IWordPeripheral, IDoubleWordPeripheral, IMultibyteWritePeripheral, IKnownSize
  {
    private uint GetNextPowerOfTwo(uint input)
    {
      uint retval = input - 1;
      for (int i = 1; i <= 16; i <<= 1)
      {
        retval |= retval >> i;
      }
      return retval + 1;
    }

    private uint GetLog2Ceil(uint input)
    {
      uint retval = 0;
      uint v = GetNextPowerOfTwo(input);
      while (v > 1)
      {
        retval++;
        v >>= 1;
      }
      return retval;
    }

    public SpringbokRiscV32_WindowMMU(Machine machine,
                                      MappedMemory tcm,
                                      long windowSize,
                                      long tcmSize,
                                      long pageSize,
                                      long numWindows)
    {
      this.tcm = tcm;
      this.windowSize = (uint)windowSize;
      this.tcmSize = (uint)tcmSize;
      this.pageSize = (uint)pageSize;
      this.numWindows = (uint)numWindows;
      this.faultCallback = null;

      windowSizeBits = GetLog2Ceil(this.windowSize);
      tcmSizeBits = GetLog2Ceil(this.tcmSize);
      pageSizeBits = GetLog2Ceil(this.pageSize);
      numWindowsBits = GetLog2Ceil(this.numWindows);

      windowSizeMask = (uint)((1 << (int)windowSizeBits) - 1);
      tcmSizeMask = (uint)((1 << (int)tcmSizeBits) - 1);
      pageSizeMask = (uint)((1 << (int)pageSizeBits) - 1);
      offsetLengthMask = GetNextPowerOfTwo(this.tcmSize) / this.pageSize - 1;

      Reset();
    }

    private enum AccessType {
      Read,
      Write,
      ReadOrWrite,
      ReadAndWrite
    };

    private string AccessTypeToString(AccessType type) {
      switch (type) {
        case AccessType.Read:
          return "Read";
        case AccessType.Write:
          return "Write";
        case AccessType.ReadOrWrite:
          return "ReadOrWrite";
        case AccessType.ReadAndWrite:
          return "ReadAndWrite";
        default:
          return "<unknown>";
      }
    }

    private bool GetTranslatedAddress(uint offset,
                                      AccessType accessType,
                                      out uint translatedAddress)
    {
      if (enabled)
      {
        uint window = offset >> (int)windowSizeBits;
        if (window >= numWindows) {
          translatedAddress = 0;
          this.Log(LogLevel.Error,
                   "Translation request for {0} at 0x{1:X}: failure, no window at address",
                   AccessTypeToString(accessType), offset);
          return false;
        }

        uint windowAddr = offset & windowSizeMask;
        uint windowOffset = windowOffsets[window];
        uint windowLength = windowLengths[window] + pageSize;
        uint windowPermission = windowPermissions[window];
        bool hasPermission = false;
        switch (accessType) {
          case AccessType.Read:
            hasPermission = (windowPermission & 1) != 0;
            break;
          case AccessType.Write:
            hasPermission = (windowPermission & 2) != 0;
            break;
          case AccessType.ReadOrWrite:
            hasPermission = (windowPermission & 3) != 0;
            break;
          case AccessType.ReadAndWrite:
            hasPermission = (windowPermission & 3) == 3;
            break;
        }

        if (!hasPermission || (windowAddr >= windowLength))
        {
          translatedAddress = 0;
          if (!hasPermission) {
            this.Log(LogLevel.Error,
                     "Translation request for {0} at 0x{1:X}: failure on window {2}, no permission, window permissions are 0x{3:X}",
                     AccessTypeToString(accessType), offset, window, windowPermission);
          }
          else
          {
            this.Log(LogLevel.Error,
                     "Translation request for {0} at 0x{1:X}: failure on window {2}, out of range, window size is 0x{3:X}",
                     AccessTypeToString(accessType), offset, window, windowLength);
          }
          return false;
        }

        translatedAddress = windowOffset + windowAddr;
        this.Log(LogLevel.Noisy,
                 "Translation request for {0} at 0x{1:X}: success on window {2}, to tcm+0x{3:X}",
                 AccessTypeToString(accessType), offset, window, translatedAddress);
        return true;
      }
      else
      {
        translatedAddress = offset;
        this.Log(LogLevel.Noisy,
                 "Translation request for {0} at 0x{1:X}: pass-through, to tcm+0x{2:X}",
                 AccessTypeToString(accessType), offset, translatedAddress);
        return true;
      }
    }

    public byte ReadByte(long offset)
    {
      uint translatedAddress;
      if (GetTranslatedAddress(checked((uint)offset), AccessType.Read, out translatedAddress))
      {
        return tcm.ReadByte(translatedAddress);
      }
      else
      {
        // Trigger interrupt
        if (faultCallback != null)
        {
          faultCallback();
        }
        return 0;
      }
    }

    public void WriteByte(long offset, byte value)
    {
      uint translatedAddress;
      if (GetTranslatedAddress(checked((uint)offset), AccessType.Write, out translatedAddress))
      {
        tcm.WriteByte(translatedAddress, value);
      }
      else
      {
        // Trigger interrupt
        if (faultCallback != null)
        {
          faultCallback();
        }
      }
    }

    public ushort ReadWord(long offset)
    {
      uint translatedAddress;
      if (GetTranslatedAddress(checked((uint)offset), AccessType.Read, out translatedAddress))
      {
        return tcm.ReadWord(translatedAddress);
      }
      else
      {
        // Trigger interrupt
        if (faultCallback != null)
        {
          faultCallback();
        }
        return 0;
      }
    }

    public void WriteWord(long offset, ushort value)
    {
      uint translatedAddress;
      if (GetTranslatedAddress(checked((uint)offset), AccessType.Write, out translatedAddress))
      {
        tcm.WriteWord(translatedAddress, value);
      }
      else
      {
        // Trigger interrupt
        if (faultCallback != null)
        {
          faultCallback();
        }
      }
    }

    public uint ReadDoubleWord(long offset)
    {
      uint translatedAddress;
      if (GetTranslatedAddress(checked((uint)offset), AccessType.Read, out translatedAddress))
      {
        return tcm.ReadDoubleWord(translatedAddress);
      }
      else
      {
        // Trigger interrupt
        if (faultCallback != null)
        {
          faultCallback();
        }
        return 0;
      }
    }

    public void WriteDoubleWord(long offset, uint value)
    {
      uint translatedAddress;
      if (GetTranslatedAddress(checked((uint)offset), AccessType.Write, out translatedAddress))
      {
        tcm.WriteDoubleWord(translatedAddress, value);
      }
      else
      {
        // Trigger interrupt
        if (faultCallback != null)
        {
          faultCallback();
        }
      }
    }

    public ulong TranslateAbsolute(ulong address)
    {
      foreach (var range in systemBus.GetRegistrationPoints(this).Select(x => x.Range))
      {
        if (range.Contains(address))
        {
          ulong offset = address - range.StartAddress;
          uint translatedAddress;
          if (GetTranslatedAddress(checked((uint)offset), AccessType.ReadOrWrite, out translatedAddress)) {
            return translatedAddress;
          }
        }
      }
      throw new RecoverableException("Cannot translate address that does not lay in redirector.");
    }

    public byte[] ReadBytes(long offset, int count)
    {
      uint startTranslatedAddress, lastTranslatedAddress;
      bool startValid = GetTranslatedAddress(checked((uint)offset), AccessType.Read, out startTranslatedAddress);
      bool endValid = GetTranslatedAddress(checked((uint)(offset + count - 1)), AccessType.Read, out lastTranslatedAddress);

      if (startValid && endValid)
      {
        return tcm.ReadBytes(startTranslatedAddress, count);
      }
      else
      {
        // Trigger interrupt
        if (faultCallback != null)
        {
          faultCallback();
        }
        return new byte[count];
      }
    }

    public void WriteBytes(long offset, byte[] array, int startingIndex, int count)
    {
      uint startTranslatedAddress, lastTranslatedAddress;
      bool startValid = GetTranslatedAddress(checked((uint)offset), AccessType.Write, out startTranslatedAddress);
      bool endValid = GetTranslatedAddress(checked((uint)(offset + count - 1)), AccessType.Write, out lastTranslatedAddress);

      if (startValid && endValid)
      {
        tcm.WriteBytes(startTranslatedAddress, array, startingIndex, count);
      }
      else
      {
        // Trigger interrupt
        if (faultCallback != null)
        {
          faultCallback();
        }
      }
    }

    public void Reset()
    {
      enabled = true;
      windowOffsets = new uint[numWindows];
      windowLengths = new uint[numWindows];
      windowPermissions = new uint[numWindows];
    }

    public uint GetWindowOffset(uint window)
    {
      if (window < windowSize)
      {
        return windowOffsets[window];
      }
      else
      {
        this.Log(LogLevel.Error, "Invalid window number {0}", window);
        return 0;
      }
    }

    public uint GetWindowLength(uint window)
    {
      if (window < windowSize)
      {
        return windowLengths[window];
      }
      else
      {
        this.Log(LogLevel.Error, "Invalid window number {0}", window);
        return 0;
      }
    }

    public uint GetWindowPermission(uint window)
    {
      if (window < windowSize)
      {
        return windowPermissions[window];
      }
      else
      {
        this.Log(LogLevel.Error, "Invalid window number {0}", window);
        return 0;
      }
    }

    public void SetWindowOffset(uint window, uint value)
    {
      if (value > tcmSizeMask)
      {
        this.Log(LogLevel.Noisy, "Window length value {0} out of range", value);
      }

      if (window < windowSize)
      {
        windowOffsets[window] = value & tcmSizeMask & ~pageSizeMask;
      }
      else
      {
        this.Log(LogLevel.Error, "Invalid window number {0}", window);
      }
    }

    public void SetWindowLength(uint window, uint value)
    {
      if (value > tcmSizeMask)
      {
        this.Log(LogLevel.Noisy, "Window length value {0} out of range", value);
      }

      if (window < windowSize)
      {
        windowLengths[window] = value & tcmSizeMask & ~pageSizeMask;
      }
      else
      {
        this.Log(LogLevel.Error, "Invalid window number {0}", window);
      }
    }

    public void SetWindowPermission(uint window, uint value)
    {
      if (value > 3)
      {
        this.Log(LogLevel.Noisy, "Window permission value {0} out of range", value);
      }

      if (window < windowSize)
      {
        windowPermissions[window] = value & 3;
      }
      else
      {
        this.Log(LogLevel.Error, "Invalid window number {0}", window);
      }
    }

    public void RegisterFaultCallback(Action faultCallback)
    {
      this.faultCallback = faultCallback;
    }

    public long Size => (long)GetNextPowerOfTwo(windowSize * numWindows);

    private readonly SystemBus systemBus;
    private readonly MappedMemory tcm;

    public readonly uint windowSize;
    public readonly uint tcmSize;
    public readonly uint pageSize;
    public readonly uint numWindows;

    public readonly uint windowSizeBits;
    public readonly uint tcmSizeBits;
    public readonly uint pageSizeBits;
    public readonly uint numWindowsBits;

    public readonly uint windowSizeMask;
    public readonly uint tcmSizeMask;
    public readonly uint pageSizeMask;
    public readonly uint offsetLengthMask;

    // TO-DO(jonathantate): Need to plumb the enable bit to the control block register file
    public bool enabled;
    private uint[] windowOffsets;
    private uint[] windowLengths;
    private uint[] windowPermissions;

    private Action faultCallback;
  }
}
