//
// 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,
                                PrivilegedArchitecture privilegedArchitecture = PrivilegedArchitecture.Priv1_11,
                                Endianess endianness = Endianess.LittleEndian,
                                string cpuType = "rv32imfv_zicsr")
            : base(machine, cpuType, null, hartId, privilegedArchitecture, 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,
        };
    }

}
