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