//
// Copyright (c) 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Linq;
using System.Text;

using Antmicro.Renode.Core;
using Antmicro.Renode.Core.Structure.Registers;
using Antmicro.Renode.Exceptions;
using Antmicro.Renode.Logging;
using Antmicro.Renode.Peripherals.Miscellaneous;
using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Utilities;
using Antmicro.Renode.Debugging;

using Endianess = ELFSharp.ELF.Endianess;

namespace Antmicro.Renode.Peripherals.CPU
{
    public class SpringbokRiscV32 : RiscV32
    {
        public SpringbokRiscV32(Core.Machine machine,
                                uint hartId = 0,
                                PrivilegeArchitecture privilegeArchitecture = PrivilegeArchitecture.Priv1_11,
                                Endianess endianness = Endianess.LittleEndian,
                                string cpuType = "rv32imfv_zicsr")
            : base(null, cpuType, machine, hartId, privilegeArchitecture, endianness)
        {
            RegisterCustomCSRs();

            //               funct7            -------
            //               rs2                      -----
            //               rs1                           -----
            //               funct3                             ---
            //               rd                                    -----
            InstallCustomInstruction(pattern: "-------------------------1111011", handler: HandleSpringbokCustom3); // custom-3

            Reset();
            // Placing these before reset results in them being reset (this is not intended behavior)
            // These should be moved withing Tlib out of the reset function.
            VectorRegisterLength = 512;
            VectorElementMaxWidth = 32;
        }

        public override void Reset()
        {
            base.Reset();

            // This core comes out of reset paused.
            this.IsHalted = true;

            if(ControlBlockRegistered)
            {
                ControlBlock.Reset();
            }
        }

        public void RegisterControlBlock(SpringbokRiscV32_ControlBlock controlBlock)
        {
            ControlBlock = controlBlock;
            ControlBlockRegistered = true;
        }

        // A no-op API to match the KelvinCPU interface
        public string CpuLibraryPath { get; set; }

        private SpringbokRiscV32_ControlBlock ControlBlock;
        private bool ControlBlockRegistered = false;

        private void HandleSpringbokCustom3(UInt64 opcode)
        {
            int rd = (int)BitHelper.GetValue(opcode, 7, 5);
            int funct3 = (int)BitHelper.GetValue(opcode, 12, 3);
            int rs1 = (int)BitHelper.GetValue(opcode, 15, 5);
            int rs2 = (int)BitHelper.GetValue(opcode, 20, 5);
            // int funct7 = (int)BitHelper.GetValue(opcode, 25, 7); // Unused for now

            switch(funct3)
            {
                case 0:
                    // simprint
                    // rd is logging level
                    // rs1 is pointer to null-terminated string to print
                    // rs2 is number to print
                    int levelNum = (int)(X[rd].RawValue);
                    LogLevel level = LogLevel.Error;

                    switch(levelNum)
                    {
                        case 0:
                            level = LogLevel.Error;
                            break;
                        case 1:
                            level = LogLevel.Warning;
                            break;
                        case 2:
                            level = LogLevel.Info;
                            break;
                        case 3:
                            level = LogLevel.Debug;
                            break;
                        case 4:
                            level = LogLevel.Noisy;
                            break;
                        default:
                            this.Log(LogLevel.Error, "Unrecognized logging level for simprint instruction! {0}: {1}", rd, levelNum);
                            return;
                    }

                    uint messagePtr = (uint)this.TranslateAddress((uint)(X[rs1].RawValue), MpuAccess.Read);
                    uint number = (uint)(X[rs2].RawValue);

                    byte[] messageArray = new byte[256];

                    for(int i = 0; i < 255; i++)
                    {
                        messageArray[i] = (byte)(ReadByteFromBus(messagePtr++) & 127); // Just in case we read garbage, let's restrict it to ASCII garbage.
                        if(messageArray[i] == 0)
                        {
                            break;
                        }
                    }

                    String message = Encoding.ASCII.GetString(messageArray).TrimEnd((Char)0);

                    this.Log(level, "simprint: \"{0}\", {1} (0x{1:X})", message, number);

                    break;
                case 1:
                    // xcount
                    switch(rs1)
                    {
                        case 0:
                            // icount
                            X[rd] = ExecutedInstructions;
                            break;
                        case 1:
                            // ccount
                            // Renode simulates one cycle per instruction
                            X[rd] = ExecutedInstructions;
                            break;
                        default:
                            this.Log(LogLevel.Error, "xcount: unrecognized source: {0} (0x{0:X})", rs1);
                            break;
                    }
                    break;
                case 2:
                    // hostreq
                    if(ControlBlockRegistered)
                    {
                        ControlBlock.ExecHostReq();
                    }
                    break;
                case 3:
                    // finish
                    if(ControlBlockRegistered)
                    {
                        ControlBlock.ExecFinish();
                    }
                    break;
                default:
                    // Unrecognized
                    this.Log(LogLevel.Error, "custom-3: unrecognized funct3: {0} (0x{0:X})", funct3);
                    break;
            }
        }

        private void RegisterCustomCSRs()
        {
            // validate only privilege level when accessing CSRs
            // do not validate rw bit as VexRiscv custom CSRs do not follow the standard
            CSRValidation = CSRValidationLevel.None;

            RegisterCSR((ulong)CSRs.InstructionCount, () => InstructionCountCSRRead("InstructionCount"), value => { });
            RegisterCSR((ulong)CSRs.CycleCount, () => InstructionCountCSRRead("CycleCount"), value => { });
        }

        private ulong InstructionCountCSRRead(string name)
        {
            this.Log(LogLevel.Noisy, "Reading instruction count CSR {0} 0x{1:X}", name, ExecutedInstructions);
            ulong count = ExecutedInstructions;
            return count;
        }

        private enum CSRs
        {
            InstructionCount = 0x7C0,
            CycleCount = 0x7C1,
        }
    }

    public class SpringbokRiscV32_ControlBlock :
        IDoubleWordPeripheral,
        IProvidesRegisterCollection<DoubleWordRegisterCollection>,
        IKnownSize
    {

        public SpringbokRiscV32_ControlBlock(Machine machine,
                                             SpringbokRiscV32 core,
                                             uint mmuNumWindows,
                                             ulong mmuMemorySize,
                                             ulong mmuVirtualWindowSize,
                                             ulong mmuRangeStart)
        {
            Machine = machine;
            Core = core;

            this.mmuNumWindows = mmuNumWindows;
            this.mmuRangeStart = mmuRangeStart;
            this.mmuMemorySize = mmuMemorySize;
            this.mmuVirtualWindowSize = mmuVirtualWindowSize;

            Mmu = InitMmu(mmuRangeStart, mmuMemorySize, mmuNumWindows, mmuVirtualWindowSize);

            HostReqIRQ = new GPIO();
            FinishIRQ = new GPIO();
            InstructionFaultIRQ = new GPIO();
            DataFaultIRQ = new GPIO();

            Core.RegisterControlBlock(this);

            RegistersCollection = new DoubleWordRegisterCollection(this);
            DefineRegisters();

            Core.AddHookOnMmuFault(HandleFault);

            Reset();
        }

        public void Reset()
        {
            mode = Mode.Freeze | Mode.SwReset;
            RegistersCollection.Reset();
        }

        private ExternalMmuBase InitMmu(ulong rangeStart, ulong memorySize, uint windowsCount, ulong windowSize)
        {
            var mmu = new ExternalMmuBase(this.Core, windowsCount);

            for(uint windowIndex = 0; windowIndex<windowsCount; windowIndex++)
            {
                var windowStart = rangeStart + windowIndex * windowSize;
                var windowEnd = windowStart + windowSize;
                mmu.SetWindowStart(windowIndex, windowStart);
                mmu.SetWindowEnd(windowIndex, windowEnd);
            }
            return mmu;
        }

        private void DefineRegisters()
        {
            Registers.IntrState.Define32(this)
              .WithValueField(0, 4,
                              writeCallback: (_, value) => {
                                this.Log(LogLevel.Noisy, "Got {0} to clear IRQ pending bits", value);
                                irqsPending = irqsPending & ~(InterruptBits)value;
                                IrqUpdate();
                              },
                              valueProviderCallback: (_) => {
                                return (uint)irqsPending;
                              })
            ;

            Registers.IntrEnable.Define32(this)
              .WithValueField(0, 4,
                              writeCallback: (_, value) => {
                                this.Log(LogLevel.Noisy, "Got {0} to write IRQ enable bits", value);
                                irqsEnabled = (InterruptBits)value & InterruptBits.Mask;
                                IrqUpdate();
                              },
                              valueProviderCallback: (_) => {
                                return (uint)irqsEnabled;
                              })
            ;

            Registers.IntrTest.Define32(this)
              .WithValueField(0, 4,
                              writeCallback: (_, value) => {
                                this.Log(LogLevel.Noisy, "Got {0} to set IRQ pending bits", value);
                                irqsPending = irqsPending | ((InterruptBits)value & InterruptBits.Mask);
                                IrqUpdate();
                              })
              ;

            Registers.Control.Define32(this, resetValue: 0x00000003)
                    .WithValueField(0, 19, name: "FREEZE_VC_RESET_PC_START", writeCallback: (_, val) =>
                    {
                        Mode newMode = (Mode)val & Mode.Mask;

                        // Pause the core when either freeze or swreset is asserted.
                        if ((mode == Mode.Run) && (newMode != Mode.Run))
                        {
                            this.Log(LogLevel.Noisy, "Pausing core.");
                            Core.IsHalted = true;
                        }

                        // Trigger the core's reset when SwReset is deasserted.
                        if (((mode & Mode.SwReset) != 0) && ((newMode & Mode.SwReset) == 0))
                        {
                            this.Log(LogLevel.Noisy, "Resetting core.");
                            Core.Reset();
                            ulong startAddress = (val & ~(ulong)Mode.Mask) + mmuRangeStart;
                            this.Log(LogLevel.Noisy, "Setting PC to 0x{0:X}.", startAddress);
                            Core.PC = startAddress;
                        }

                        // Unpause the core when both freeze and SwReset are deasserted.
                        if ((mode != Mode.Run) && (newMode == Mode.Run))
                        {
                            this.Log(LogLevel.Noisy, "Resuming core.");
                            Core.IsHalted = false;

                            Core.Resume();
                        }

                        this.mode = newMode;
                    })
                    .WithIgnoredBits(19, 32 - 19);

            // To-do: Not sure how to implement disablable memory banks.
            Registers.MemoryBankControl.Define32(this)
                    .WithValueField(0, 4, out MemoryEnable, name: "MEM_ENABLE")
                    .WithIgnoredBits(16, 32 - 16);

            // To-do: Not sure how to implement memory access range checks.
            Registers.ErrorStatus.Define32(this)
                    .WithFlag(0, name: "MEM_OUT_OF_RANGE")
                    .WithValueField(2, 4, out MemoryDisableAccess, name: "MEM_DISABLE_ACCESS")
                    .WithIgnoredBits(16, 32 - 16);

            Registers.InitStart.Define32(this)
                    .WithValueField(0, 22, out InitStartAddress, name: "ADDRESS")
                    .WithIgnoredBits(24, 32 - 24);

            Registers.InitEnd.Define32(this)
                    .WithValueField(0, 22, out InitEndAddress, name: "ADDRESS")
                    .WithFlag(22, name: "VALID", mode: FieldMode.Read | FieldMode.Write, writeCallback: (_, val) =>
                    {
                  // If valid, do the memory clear.
                  if (val)
                        {
                            var dataPageMask = ~((ulong)(DataPageSize - 1));
                            InitStatusPending.Value = true;
                            InitStatusDone.Value = false;
                            Machine.LocalTimeSource.ExecuteInNearestSyncedState( __ => {
                                for(ulong writeAddress = InitStartAddress.Value & dataPageMask;
                                    writeAddress < ((InitEndAddress.Value + DataPageSize - 1) & dataPageMask);
                                    writeAddress += DataPageSize)
                                {
                                    Machine.SystemBus.WriteBytes(DataErasePattern, mmuRangeStart + (ulong)writeAddress, (uint)DataPageSize, true);
                                }
                                InitStatusPending.Value = false;
                                InitStatusDone.Value = true;
                            } );
                        }
                    })
                    .WithIgnoredBits(23, 32 - 23);
            Registers.InitStatus.Define32(this)
                    .WithFlag(0, out InitStatusPending, name: "INIT_PENDING")
                    .WithFlag(1, out InitStatusDone, name: "INIT_DONE")
                    .WithIgnoredBits(2, 32 - 2);
        }

        public virtual uint ReadDoubleWord(long offset)
        {
            switch (offset >> 10)
            {
            case 0: /* 0..1023 */
                return RegistersCollection.Read(offset);
            case 1: /* 1024..2047 */
                if (Mmu != null)
                {
                    offset -= 1024;
                    uint window = (uint)(offset >> 4);
                    if(window >= mmuNumWindows)
                    {
                        this.Log(LogLevel.Warning, "Invalid window number {0}", window);
                        return 0;
                    }
                    switch (offset & 15)
                    {
                    case 0:
                        return checked((uint)Mmu.GetWindowStart(window));
                    case 4:
                        return checked((uint)(Mmu.GetWindowEnd(window) - Mmu.GetWindowStart(window))); // windowLength
                    case 8:
                        return checked((uint)Mmu.GetWindowPrivileges(window));
                    default:
                        this.Log(LogLevel.Warning, "No Springbok Mmu register at address 0x{0:X}.", offset);
                        return 0;
                    }
                }
                this.Log(LogLevel.Warning, "Attempting to access Springbok Mmu when it was not included in system.", offset);
                return 0;
            default: /* 2048..4095 */
                return 0;
            }
        }

        public virtual void WriteDoubleWord(long offset, uint value)
        {
            switch(offset >> 10)
            {
            case 0: /* 0..1023 */
                RegistersCollection.Write(offset, value);
                return;
            case 1: /* 1024..2047 */
                if (Mmu != null)
                {
                    offset -= 1024;
                    uint window = (uint)(offset >> 4);
                    if(window >= mmuNumWindows)
                    {
                        this.Log(LogLevel.Warning, "Invalid window number {0}", window);
                        return;
                    }
                    switch (offset & 15)
                    {
                    case 0:
                        var virtualWindowOffset = this.mmuRangeStart + window * this.mmuVirtualWindowSize;
                        Mmu.SetWindowAddend(window, value - virtualWindowOffset);
                        return;
                    case 4:
                        // This assumes that the window start has already been set
                        var windowEnd = Mmu.GetWindowStart(window) + value + 1;
                        Mmu.SetWindowEnd(window, windowEnd); // windowLength
                        return;
                    case 8:
                        Mmu.SetWindowPrivileges(window, value);
                        return;
                    }
                }
                return;
            default: /* 2048..4095 */
                return;
            }
        }

        public void ExecHostReq()
        {
            // Pause the core and trigger a host interrupt signaling a request
            if (mode == Mode.Run)
            {
                this.Log(LogLevel.Noisy, "Pausing core for host request.");
            }
            else
            {
                this.Log(LogLevel.Error, "Pausing core for host request, but core was not expected to be running. Did you clear IsHalted manually?");
            }
            Core.IsHalted = true;
            mode = Mode.Freeze;
            irqsPending |= InterruptBits.HostReq;
            IrqUpdate();
        }

        public void ExecFinish()
        {
            // Pause, reset the core (actual reset occurs when SwReset is cleared) and trigger a host interrupt indicating completion
            if (mode == Mode.Run)
            {
                this.Log(LogLevel.Noisy, "Pausing and resetting core for host completion notification.");
            }
            else
            {
                this.Log(LogLevel.Error, "Pausing and resetting core for host completion notification, but core was not expected to be running. Did you clear IsHalted manually?");
            }
            Core.IsHalted = true;
            mode = Mode.Freeze | Mode.SwReset;
            irqsPending |= InterruptBits.Finish;
            IrqUpdate();
        }

        private void ExecFault()
        {
            // Pause, reset the core (actual reset occurs when SwReset is cleared) and trigger a host interrupt indicating a fault
            if (mode == Mode.Run)
            {
                this.Log(LogLevel.Noisy, "Pausing and resetting core for fault notification.");
            }
            else
            {
                this.Log(LogLevel.Error, "Pausing and resetting core for fault notification, but core was not expected to be running. Did you clear IsHalted manually?");
            }
            Core.IsHalted = true;
            mode = Mode.Freeze | Mode.SwReset;
            irqsPending |= InterruptBits.DataFault;
            IrqUpdate();
            return;
        }

        public DoubleWordRegisterCollection RegistersCollection { get; private set; }

        private void HandleFault(ulong faultAddress, AccessType accessType, int windowIndex)
        {
            LogFaultType(Mmu, faultAddress, accessType, mmuRangeStart, mmuVirtualWindowSize, mmuNumWindows);
            ExecFault();
        }

        private void LogFaultType(ExternalMmuBase mmu, ulong faultAddress, AccessType accessType, ulong rangeStart, ulong virtualWindowSize, uint numberOfWindows)
        {
            var mmuName = mmu.GetType().Name;
            var virtualWindowIndex = (uint)((faultAddress - rangeStart) / virtualWindowSize);

            if(virtualWindowIndex >= numberOfWindows)
            {
                this.Log(LogLevel.Error, "{0}: Translation request for {1} at 0x{2:X}: failure, no window at address", mmuName, accessType, faultAddress);
            }
            else
            {
                var windowEnd = mmu.GetWindowEnd(virtualWindowIndex);
                var windowPrivilege = mmu.GetWindowPrivileges(virtualWindowIndex);

                if(faultAddress > windowEnd)
                {
                    this.Log(LogLevel.Error, "{0}: Translation request for {1} at 0x{2:X}: failure on window {3}, out of range, window ends at 0x{4:X}",
                             mmuName, accessType, faultAddress, virtualWindowIndex, windowEnd);
                }
                else if((windowPrivilege & (uint)accessType) == 0)
                {
                    this.Log(LogLevel.Error, "{0}: Translation request for {1} at 0x{2:X}: failure on window {3}, no permission, window permissions are 0x{4:X}",
                             mmuName, accessType, faultAddress, virtualWindowIndex, windowPrivilege);
                }
                else
                {
                    this.Log(LogLevel.Error, "{0}: Translation request for {1} at 0x{2:X}: failed for unknown reason. This should not occur",
                             mmuName, accessType, faultAddress);
                }
            }
        }

        public GPIO HostReqIRQ { get; }
        public GPIO FinishIRQ { get; }
        public GPIO InstructionFaultIRQ { get; }
        public GPIO DataFaultIRQ { get; }

        private InterruptBits irqsEnabled;
        private InterruptBits irqsPending;

        private void IrqUpdate()
        {
          InterruptBits irqsPassed = irqsEnabled & irqsPending;
          HostReqIRQ.Set((irqsPassed & InterruptBits.HostReq) != 0);
          FinishIRQ.Set((irqsPassed & InterruptBits.Finish) != 0);
          InstructionFaultIRQ.Set((irqsPassed & InterruptBits.InstructionFault) != 0);
          DataFaultIRQ.Set((irqsPassed & InterruptBits.DataFault) != 0);
        }

        // To-do: Set the erase pattern to what the hardware actually does. 0x5A is
        // only for debugging purposes.
        private const int DataPageSize = 64;
        private readonly byte[] DataErasePattern = (byte[])Enumerable.Repeat((byte)0x5A, DataPageSize).ToArray();

        // Disable unused variable warnings. These warnings will go away on their
        // their own when each register's behavior is implemented.
#pragma warning disable 414
        private IValueRegisterField MemoryEnable;
        private IValueRegisterField MemoryDisableAccess;
        private IValueRegisterField InitStartAddress;
        private IValueRegisterField InitEndAddress;
        private IFlagRegisterField InitStatusPending;
        private IFlagRegisterField InitStatusDone;
#pragma warning restore 414

        private Mode mode;
        private readonly Machine Machine;
        private readonly SpringbokRiscV32 Core;
        private readonly ExternalMmuBase Mmu;
        private readonly uint mmuNumWindows;
        private readonly ulong mmuRangeStart;
        private readonly ulong mmuMemorySize;
        private readonly ulong mmuVirtualWindowSize;

        // Length of register space.
        public long Size => 0x1000;
        private enum Registers
        {
            IntrState = 0x00,
            IntrEnable = 0x04,
            IntrTest = 0x08,
            Control = 0x0C,
            MemoryBankControl = 0x10,
            ErrorStatus = 0x14,
            InitStart = 0x18,
            InitEnd = 0x1C,
            InitStatus = 0x20,
        };
        [Flags]
        private enum Mode
        {
            Run = 0x00,
            Freeze = 0x01,
            SwReset = 0x02,
            Mask = 0x03,
        };
        private enum FaultType
        {
            InstructionFetch,
            DataAccess,
        };
        [Flags]
        private enum InterruptBits
        {
            HostReq = 1,
            Finish = 2,
            InstructionFault = 4,
            DataFault = 8,
            Mask = 15,
        };
    }

}
