//
// 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
{

public enum CheriotCpu {
    Base = 0,
    Rvv = 1,
    RvvFp = 2,
}

// The MpactCheriotCPU class. This class derives from BaseCPU, which implements
// a CPU in ReNode. It is the interface between ReNode and the mpact_cheriot
// simulator library.
public class MpactCheriotCPU : MpactBaseCPU, ICluster<MpactCheriotCPU>,
                               ICpuSupportingGdb {

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

    ~MpactCheriotCPU() {
    }


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

    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");
        }
        if (clint_mmr_base != 0) {
            config_names.Add("clintMMRBase");
            config_values.Add(clint_mmr_base.ToString("X"));
        }
        if (clint_period != 0) {
            config_names.Add("clintPeriod");
            config_values.Add(clint_period.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);
        }
        // If the core version is greater than 0.5, add it to the config.
        if (core_version > 50) {
            config_names.Add("coreVersion");
            config_values.Add(core_version.ToString("X"));
        }
    }

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

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

    public UInt64 ClintMMRBase {
        get => clint_mmr_base;
        set => clint_mmr_base = value;
    }

    public UInt64 ClintPeriod {
        get => clint_period;
        set => clint_period = value;
    }

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

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

    public uint CoreVersion {
        get => core_version;
        set => core_version = 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<MpactCheriotCPU>> Clusters {get; } = new List<ICluster<MpactCheriotCPU>>(0);
    public new IEnumerable<MpactCheriotCPU> 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:cheriot"; } }

    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 UInt64 revocationMemBase;
    private UInt64 clint_mmr_base = 0x0;
    private UInt64 clint_period = 0;
    private uint core_version = 50;  // Default is 50 (v0.5).
    private string icache_config = "";
    private string dcache_config = "";
    private List<GDBFeatureDescriptor>
                gdbFeatures = new List<GDBFeatureDescriptor>();
}  // class MpactCheriotCPU

}  // namespace Antmicro.Renode.Peripherals.MpactCPU

