//
// Copyright (c) 2010-2024 Antmicro
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
//
// Copyright (c) 2024 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
//

// This file specializes the MpactCPU class to add custom interfaces and
// properties required for the mpact_cheriot simulator.

using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Concurrent;
using Antmicro.Renode.Core;
using Antmicro.Renode.Debugging;
using Antmicro.Renode.Exceptions;
using Antmicro.Renode.Hooks;
using Antmicro.Renode.Logging;
using Antmicro.Renode.Peripherals;
using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Peripherals.CPU;
using Antmicro.Renode.Peripherals.Timers;
using Antmicro.Renode.Peripherals.CPU.Disassembler;
using Antmicro.Renode.Peripherals.CPU.Registers;
using Antmicro.Renode.Utilities;
using Antmicro.Renode.Time;
using Antmicro.Renode.Utilities.Binding;
using Antmicro.Renode.Peripherals.MpactCPU;
using ELFSharp.ELF;
using ELFSharp.UImage;

namespace Antmicro.Renode.Peripherals.MpactCPU
{

// The MpactRiscvCPU class. This class derives from BaseCPU, which implements
// a CPU in ReNode. It is the interface between ReNode and the mpact_riscv32/64
// simulator libraries.
public class MpactRiscVCPU : MpactBaseCPU, ICluster<MpactRiscVCPU>,
                             ICpuSupportingGdb {

    public MpactRiscVCPU(uint id, UInt64 memoryBase, UInt64 memorySize,
                         string cpuType, IMachine machine,
                         Endianess endianness,
                         CpuBitness bitness = CpuBitness.Bits32)
        : base(id, memoryBase, memorySize, cpuType, machine, endianness,
               bitness) {
        Clustered = new MpactRiscVCPU[] { this };
    }

    ~MpactRiscVCPU() {
    }


    public override string Architecture { get { return "MpactRiscV";} }

    public override void SetMpactConfig(List<string> config_names,
                                        List<string> config_values) {
        base.SetMpactConfig(config_names, config_values);
        if (inst_profile) {
            config_names.Add("instProfile");
            config_values.Add("0x1");
        }
        if (mem_profile) {
            config_names.Add("memProfile");
            config_values.Add("0x1");
        }
        // Stack
        if (stack_size_set) {
            config_names.Add("stackSize");
            config_values.Add(stack_size.ToString("X"));
        }
        if (stack_end_set) {
            config_names.Add("stackEnd");
            config_values.Add(stack_end.ToString("X"));
        }
        if (icache_config != "") {
            config_names.Add("iCache");
            config_values.Add(icache_config);
        }
        if (dcache_config != "") {
            config_names.Add("dCache");
            config_values.Add(dcache_config);
        }
    }

    public bool InstProfile {
        get => inst_profile;
        set => inst_profile = value;
    }

    public bool MemProfile {
        get => mem_profile;
        set => mem_profile = value;
    }

    public ulong StackSize {
        get => stack_size;
        set {
            stack_size = value;
            stack_size_set = true;
        }
    }

    public ulong StackEnd {
        get => stack_end;
        set {
            stack_end = value;
            stack_end_set = true;
        }
    }

    public string ICache {
        get => icache_config;
        set => icache_config = value;
    }

    public string DCache {
        get => dcache_config;
        set => dcache_config = value;
    }

    // ICPUWithHooks methods.

    public void AddHookAtInterruptBegin(Action<ulong> hook) {
        throw new RecoverableException(
                        "Interrupt hooks not currently supported");
    }
    public void AddHookAtInterruptEnd(Action<ulong> hook) {
        throw new RecoverableException(
                        "Interrupt hooks not currently supported");
    }
    public void AddHookAtWfiStateChange(Action<bool> hook) {
        throw new RecoverableException(
                        "Wfi state change hook not currently supported");
    }

    public void AddHook(ulong addr, Action<ICpuSupportingGdb, ulong> hook) {
        throw new RecoverableException("Hooks not currently supported");
    }
    public void RemoveHook(ulong addr, Action<ICpuSupportingGdb, ulong> hook) {
        /* empty */
    }
    public void RemoveHooksAt(ulong addr) { /* empty */ }
    public void RemoveAllHooks() { /* empty */ }

    // ICluster methods.
    public new IEnumerable<ICluster<MpactRiscVCPU>> Clusters {get; } = new List<ICluster<MpactRiscVCPU>>(0);
    public new IEnumerable<MpactRiscVCPU> Clustered {get; }

    // ICPUSupportingGdb methods.

    public void EnterSingleStepModeSafely(HaltArguments args) {
        // this method should only be called from CPU thread,
        // but we should check it anyway
        CheckCpuThreadId();

        ExecutionMode = ExecutionMode.SingleStep;

        UpdateHaltedState();
        InvokeHalted(args);
    }

    public string GDBArchitecture { get { return "riscv:riscv"; } }

    public List<GDBFeatureDescriptor> GDBFeatures {
        get {
            if (gdbFeatures.Any()) return gdbFeatures;

            // Populate the register map if it hasn't been done yet.
            if (registerNamesMap.Count == 0) {
                GetMpactRegisters();
            }
            var cpuGroup = new GDBFeatureDescriptor("org.gnu.gdb.riscv.cpu");
            var intType = $"uint32";
            var c0_index = registerNamesMap["c0"];
            for (var i = 0u; i < 16; ++i) {
                cpuGroup.Registers.Add(
                        new GDBRegisterDescriptor((uint)c0_index + i, 32u,
                                                  $"c{i}", intType, "general"));
            }
            var pcc_index = registerNamesMap["pcc"];
            cpuGroup.Registers.Add(
                        new GDBRegisterDescriptor((uint)pcc_index, 32u, "pcc",
                                                  "code_ptr", "general"));
            gdbFeatures.Add(cpuGroup);

            return gdbFeatures;
        }
    }

    // End of ICpuSupportingGdb methods.

    private bool inst_profile = false;
    private bool mem_profile = false;
    private ulong stack_size;
    private bool stack_size_set = false;
    private ulong stack_end;
    private bool stack_end_set = false;
    private string icache_config = "";
    private string dcache_config = "";
    private List<GDBFeatureDescriptor>
                gdbFeatures = new List<GDBFeatureDescriptor>();
}  // class MpactRiscVCPU

}  // namespace Antmicro.Renode.Peripherals.MpactCPU

