// Copyright 2024 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.

#include "mpact/sim/util/renode/renode_cli_top.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <string>

#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/synchronization/mutex.h"
#include "mpact/sim/generic/core_debug_interface.h"
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/type_helpers.h"

namespace mpact {
namespace sim {
namespace util {
namespace renode {

using ::mpact::sim::generic::CoreDebugInterface;
using ::mpact::sim::generic::operator*;  // NOLINT: used below (clang error).

RenodeCLITop::RenodeCLITop(CoreDebugInterface* top, bool wait_for_cli)
    : top_(top), wait_for_cli_(wait_for_cli) {
  absl::MutexLock lock(&run_control_mutex_);
  cli_status_ = wait_for_cli_ ? RunStatus::kHalted : RunStatus::kRunning;
  cli_steps_taken_ = 0;
  cli_steps_to_take_ = 0;
  renode_steps_taken_ = 0;
  renode_steps_to_take_ = 0;
}

void RenodeCLITop::SetConnected(bool connected) {
  // Only act upon changes in connectivity.
  if (connected == cli_connected_) return;
  cli_connected_ = connected;
  absl::MutexLock lock(&run_control_mutex_);
  cli_status_ = cli_connected_ ? RunStatus::kHalted : RunStatus::kRunning;
}

absl::StatusOr<int> RenodeCLITop::RenodeStep(int num) {
  run_control_mutex_.Lock();
  renode_steps_taken_ = 0;
  renode_steps_to_take_ = num;
  auto renode_take_control = [this]() -> bool {
    return (cli_status_ == RunStatus::kRunning) ||
           (renode_steps_taken_ >= renode_steps_to_take_);
  };
  // CLI was either idle, running, or stepping previously when cli run control
  // was turned off. If it was idle, then don't step, just wait for change to
  // running or stepping. If it was running, step like normal. If it was
  // stepping, step for the smaller of the renode and step count and the
  // remaining cli step count.
  absl::Status status = absl::OkStatus();
  while (true) {
    uint64_t stepped = 0;
    run_control_mutex_.Await(absl::Condition(&renode_take_control));
    // See if there is any stepping left to do now that renode has control
    // again. The steps might have been taken while the CLI was stepping.
    if (renode_steps_to_take_ <= renode_steps_taken_) break;

    auto res = top_->Step(renode_steps_to_take_ - renode_steps_taken_);
    if (res.ok()) {
      stepped = res.value();
      renode_steps_taken_ += stepped;
      // Check halt reason.
      auto halt_result = top_->GetLastHaltReason();
      CHECK_OK(halt_result.status());
      auto halt_reason = halt_result.value();
      // If it is a program halt request that is not ProgramDone, give control
      // to CLI but prepare to continue stepping once control is returned.
      if ((halt_reason != *HaltReason::kProgramDone) &&
          (halt_reason != *HaltReason::kNone)) {
        cli_status_ = RunStatus::kHalted;
        program_done_ = true;
        continue;
      }
      // ProgramHalted request halts the simulation. So transfer control and
      // return.
      if (halt_reason == *HaltReason::kProgramDone) {
        cli_status_ = RunStatus::kHalted;
        program_done_ = true;
        break;
      }
      // If we have stepped enough, just return.
      if (renode_steps_to_take_ <= renode_steps_taken_) break;
    } else {
      status = res.status();
      break;
    }
  }
  run_control_mutex_.Unlock();
  if (!status.ok()) return status;
  return renode_steps_taken_;
}

// There should be no reason to guard these calls from renode with mutexes,
// as they will only be done while renode has control.
absl::StatusOr<HaltReasonValueType> RenodeCLITop::RenodeGetLastHaltReason() {
  return top_->GetLastHaltReason();
}

absl::StatusOr<uint64_t> RenodeCLITop::RenodeReadRegister(
    const std::string& name) {
  return top_->ReadRegister(name);
}

absl::Status RenodeCLITop::RenodeWriteRegister(const std::string& name,
                                               uint64_t value) {
  return top_->WriteRegister(name, value);
}

absl::StatusOr<size_t> RenodeCLITop::RenodeReadMemory(uint64_t address,
                                                      void* buf,
                                                      size_t length) {
  return top_->ReadMemory(address, buf, length);
}

absl::StatusOr<size_t> RenodeCLITop::RenodeWriteMemory(uint64_t address,
                                                       const void* buf,
                                                       size_t length) {
  return top_->WriteMemory(address, buf, length);
}

// Command line interface handlers.
absl::Status RenodeCLITop::CLIHalt() {
  // Halt the simulator and claim run control.
  auto status = top_->Halt();
  {
    absl::MutexLock lock(&run_control_mutex_);
    cli_status_ = RunStatus::kHalted;
  }
  return status;
}

absl::Status RenodeCLITop::CLIRun() {
  // This predicate is used to determine when the command line interface is
  // in control for the purposes of issuing a run command.
  auto cli_is_not_running = [this] {
    return cli_status_ != RunStatus::kRunning;
  };
  run_control_mutex_.LockWhen(absl::Condition(&cli_is_not_running));
  if (top_->GetLastHaltReason().value() == *HaltReason::kProgramDone) {
    run_control_mutex_.Unlock();
    return absl::UnavailableError("Program terminated");
  }
  cli_status_ = RunStatus::kRunning;
  // Wait for cli to be back in control.
  run_control_mutex_.Await(absl::Condition(&cli_is_not_running));
  // Unlock and return to CLI.
  run_control_mutex_.Unlock();
  return absl::OkStatus();
}

absl::Status RenodeCLITop::CLIWait() {
  // No need to lock for this call.
  return top_->Wait();
}

absl::StatusOr<int> RenodeCLITop::CLIStep(int num) {
  run_control_mutex_.Lock();
  if (top_->GetLastHaltReason().value() == *HaltReason::kProgramDone) {
    run_control_mutex_.Unlock();
    return absl::UnavailableError("Program terminated");
  }
  // Lambda used in Await below.
  auto cli_is_in_control = [this] {
    return program_done_ || ((cli_status_ != RunStatus::kRunning) &&
                             (renode_steps_to_take_ > renode_steps_taken_));
  };

  cli_steps_to_take_ = num;
  cli_steps_taken_ = 0;
  absl::Status status = absl::OkStatus();
  while (true) {
    // Release the lock and regain the lock when the CLI is in control. This
    // allows control to switch between ReNode and CLI while each makes progress
    // towards their step count.
    run_control_mutex_.Await(absl::Condition(&cli_is_in_control));
    if (cli_steps_to_take_ <= cli_steps_taken_) {
      cli_status_ = RunStatus::kHalted;
      break;
    }
    cli_status_ = RunStatus::kSingleStep;
    auto steps_to_take = std::min(cli_steps_to_take_ - cli_steps_taken_,
                                  renode_steps_to_take_ - renode_steps_taken_);
    auto step_result = top_->Step(steps_to_take);
    if (!step_result.ok()) {
      status = step_result.status();
      break;
    }
    auto steps_taken = step_result.value();
    cli_steps_taken_ += steps_taken;
    renode_steps_taken_ += steps_taken;
    auto halt_result = top_->GetLastHaltReason();
    CHECK_OK(halt_result.status());
    auto halt_reason = halt_result.value();
    // Check if the program is done.
    if (halt_reason == *HaltReason::kProgramDone) {
      // Set cli state as kRunning to give control to ReNode to return.
      cli_status_ = RunStatus::kRunning;
      program_done_ = true;
      break;
    }
    // If we're done with renode steps, then go to the top of the loop so
    // that renode can get control and start stepping again.
    if ((halt_reason == *HaltReason::kNone) &&
        (renode_steps_taken_ >= renode_steps_to_take_)) {
      continue;
    }
    cli_status_ = RunStatus::kHalted;
    break;
  }
  run_control_mutex_.Unlock();
  if (!status.ok()) return status;
  return cli_steps_taken_;
}

absl::StatusOr<RunStatus> RenodeCLITop::CLIGetRunStatus() {
  return DoWhenInControl<absl::StatusOr<RunStatus>>(
      [this]() { return top_->GetRunStatus(); });
}

absl::StatusOr<HaltReasonValueType> RenodeCLITop::CLIGetLastHaltReason() {
  return DoWhenInControl<absl::StatusOr<HaltReasonValueType>>(
      [this]() { return top_->GetLastHaltReason(); });
}

absl::StatusOr<uint64_t> RenodeCLITop::CLIReadRegister(
    const std::string& name) {
  return DoWhenInControl<absl::StatusOr<uint64_t>>(
      [this, &name]() { return top_->ReadRegister(name); });
}

absl::Status RenodeCLITop::CLIWriteRegister(const std::string& name,
                                            uint64_t value) {
  return DoWhenInControl<absl::Status>(
      [this, &name, &value]() { return top_->WriteRegister(name, value); });
}

absl::StatusOr<generic::DataBuffer*> RenodeCLITop::CLIGetRegisterDataBuffer(
    const std::string& name) {
  return DoWhenInControl<absl::StatusOr<generic::DataBuffer*>>(
      [this, &name]() { return top_->GetRegisterDataBuffer(name); });
}

absl::StatusOr<size_t> RenodeCLITop::CLIReadMemory(uint64_t address, void* buf,
                                                   size_t length) {
  return DoWhenInControl<absl::StatusOr<size_t>>(
      [this, &address, &buf, &length]() {
        return top_->ReadMemory(address, buf, length);
      });
}

absl::StatusOr<size_t> RenodeCLITop::CLIWriteMemory(uint64_t address,
                                                    const void* buf,
                                                    size_t length) {
  return DoWhenInControl<absl::StatusOr<size_t>>(
      [this, &address, &buf, &length]() {
        return top_->WriteMemory(address, buf, length);
      });
}

bool RenodeCLITop::CLIHasBreakpoint(uint64_t address) {
  return DoWhenInControl<bool>(
      [this, &address]() { return top_->HasBreakpoint(address); });
}

absl::Status RenodeCLITop::CLISetSwBreakpoint(uint64_t address) {
  return DoWhenInControl<absl::Status>(
      [this, &address]() { return top_->SetSwBreakpoint(address); });
}

absl::Status RenodeCLITop::CLIClearSwBreakpoint(uint64_t address) {
  return DoWhenInControl<absl::Status>(
      [this, &address]() { return top_->ClearSwBreakpoint(address); });
}

absl::Status RenodeCLITop::CLIClearAllSwBreakpoints() {
  return DoWhenInControl<absl::Status>(
      [this]() { return top_->ClearAllSwBreakpoints(); });
}

absl::StatusOr<Instruction*> RenodeCLITop::CLIGetInstruction(uint64_t address) {
  return DoWhenInControl<absl::StatusOr<Instruction*>>(
      [this, &address]() { return top_->GetInstruction(address); });
}

absl::StatusOr<std::string> RenodeCLITop::CLIGetDisassembly(uint64_t address) {
  return DoWhenInControl<absl::StatusOr<std::string>>(
      [this, &address]() { return top_->GetDisassembly(address); });
}

void RenodeCLITop::CLIRequestHalt(HaltReason halt_reason,
                                  const Instruction* inst) {
  (void)top_->Halt(halt_reason);
}

void RenodeCLITop::CLIRequestHalt(HaltReasonValueType halt_reason,
                                  const Instruction* inst) {
  (void)top_->Halt(halt_reason);
}

}  // namespace renode
}  // namespace util
}  // namespace sim
}  // namespace mpact
