//
// 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 System.Linq;
using System.Text;

using Antmicro.Renode.Core;
using Antmicro.Renode.Core.Structure.Registers;
using Antmicro.Renode.Logging;
using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Peripherals.Memory;
using Antmicro.Renode.Peripherals.Timers;
using Antmicro.Renode.Utilities;
using Antmicro.Renode.Utilities.Binding;

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")
            : 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;
        }

        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)(X[rs1].RawValue);
                    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,
                                             MappedMemory imem,
                                             MappedMemory dmem,
                                             SpringbokRiscV32_WindowMMU immu=null,
                                             SpringbokRiscV32_WindowMMU dmmu=null)
        {
            Machine = machine;
            Core = core;
            IMem = imem;
            DMem = dmem;
            IMmu = immu;
            DMmu = dmmu;

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

            Core.RegisterControlBlock(this);

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

            if (IMmu != null)
            {
              IMmu.RegisterFaultCallback(() => { ExecFault(FaultType.InstructionFetch); });
            }

            if (DMmu != null)
            {
              DMmu.RegisterFaultCallback(() => { ExecFault(FaultType.DataAccess); });
            }

            Reset();
        }

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

        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) + Machine.SystemBus.GetRegistrationPoints(IMem).First().Range.StartAddress;
                            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 InstructionMemoryEnable, name: "I_MEM_ENABLE")
                    .WithValueField(4, 8, out DataMemoryEnable, name: "D_MEM_ENABLE")
                    .WithIgnoredBits(12, 32 - 12);

            // To-do: Not sure how to implement memory access range checks.
            Registers.ErrorStatus.Define32(this)
                    .WithFlag(0, name: "I_MEM_OUT_OF_RANGE")
                    .WithFlag(1, name: "D_MEM_OUT_OF_RANGE")
                    .WithValueField(2, 4, out InstructionMemoryDisableAccess, name: "I_MEM_DISABLE_ACCESS")
                    .WithValueField(6, 8, out DataMemoryDisableAccess, name: "D_MEM_DISABLE_ACCESS")
                    .WithIgnoredBits(14, 32 - 14);

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

            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)
                        {
                            InitStatusPending.Value = true;
                            InitStatusDone.Value = false;
                            Machine.LocalTimeSource.ExecuteInNearestSyncedState( __ => {
                                if (InitMemSelect.Value)
                                {
                                    for(long writeAddress = InitStartAddress.Value & ~(InstructionPageSize - 1);
                                writeAddress < ((InitEndAddress.Value + InstructionPageSize - 1) & ~(InstructionPageSize - 1));
                                writeAddress += InstructionPageSize)
                                    {
                                        IMem.WriteBytes(writeAddress, InstructionErasePattern, 0, InstructionPageSize);
                                    }
                                }
                                else
                                {
                                    for(long writeAddress = InitStartAddress.Value & ~(DataPageSize - 1);
                                writeAddress < ((InitEndAddress.Value + DataPageSize - 1) & ~(DataPageSize - 1));
                                writeAddress += DataPageSize)
                                    {
                                        DMem.WriteBytes(writeAddress, DataErasePattern, 0, DataPageSize);
                                    }
                                }
                                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 (IMmu != null)
                {
                    offset -= 1024;
                    uint window = (uint)(offset >> 4);
                    switch (offset & 15)
                    {
                    case 0:
                        return IMmu.GetWindowOffset(window);
                    case 4:
                        return IMmu.GetWindowLength(window);
                    case 8:
                        return IMmu.GetWindowPermission(window);
                    default:
                        this.Log(LogLevel.Warning, "No Springbok IMmu register at address 0x{0:X}.", offset);
                        return 0;
                    }
                }
                this.Log(LogLevel.Warning, "Attempting to access Springbok IMmu when it was not included in system.", offset);
                return 0;
            case 2: /* 2048..3071 */
                if (DMmu != null)
                {
                    offset -= 2048;
                    uint window = (uint)(offset >> 4);
                    switch (offset & 15)
                    {
                    case 0:
                        return DMmu.GetWindowOffset(window);
                    case 4:
                        return DMmu.GetWindowLength(window);
                    case 8:
                        return DMmu.GetWindowPermission(window);
                    default:
                        this.Log(LogLevel.Warning, "No Springbok DMmu register at address 0x{0:X}.", offset);
                        return 0;
                    }
                }
                this.Log(LogLevel.Warning, "Attempting to access Springbok DMmu when it was not included in system.", offset);
                return 0;
            default: /* 3072..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 (IMmu != null)
                {
                    offset -= 1024;
                    uint window = (uint)(offset >> 4);
                    switch (offset & 15)
                    {
                    case 0:
                        IMmu.SetWindowOffset(window, value);
                        return;
                    case 4:
                        IMmu.SetWindowLength(window, value);
                        return;
                    case 8:
                        IMmu.SetWindowPermission(window, value);
                        return;
                    }
                }
                return;
            case 2: /* 2048..3071 */
                if (DMmu != null)
                {
                    offset -= 2048;
                    uint window = (uint)(offset >> 4);
                    switch (offset & 15)
                    {
                    case 0:
                        DMmu.SetWindowOffset(window, value);
                        return;
                    case 4:
                        DMmu.SetWindowLength(window, value);
                        return;
                    case 8:
                        DMmu.SetWindowPermission(window, value);
                        return;
                    }
                }
                return;
            default: /* 3072..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(FaultType faultType)
        {
            // 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;
            switch (faultType)
            {
            case FaultType.InstructionFetch:
                irqsPending |= InterruptBits.InstructionFault;
                IrqUpdate();
                return;
            case FaultType.DataAccess:
                irqsPending |= InterruptBits.DataFault;
                IrqUpdate();
                return;
            default:
                this.Log(LogLevel.Error, "Unknown fault type!");
                return;
            }
        }

        public DoubleWordRegisterCollection RegistersCollection { get; private set; }

        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 InstructionPageSize = 4;
        private readonly byte[] InstructionErasePattern = (byte[])Enumerable.Repeat((byte)0x5A, InstructionPageSize).ToArray();
        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 InstructionMemoryEnable;
        private IValueRegisterField DataMemoryEnable;
        private IValueRegisterField InstructionMemoryDisableAccess;
        private IValueRegisterField DataMemoryDisableAccess;
        private IValueRegisterField InitStartAddress;
        private IFlagRegisterField InitMemSelect;
        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 SpringbokRiscV32_WindowMMU IMmu;
        private readonly SpringbokRiscV32_WindowMMU DMmu;
        private readonly MappedMemory IMem;
        private readonly MappedMemory DMem;

        // 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,
        };
    }

}
