// Copyright 2023 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 <signal.h>

#include <cstdint>
#include <fstream>
#include <ios>
#include <iostream>
#include <optional>
#include <ostream>
#include <string>
#include <vector>

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "mpact/sim/generic/core_debug_interface.h"
#include "mpact/sim/generic/type_helpers.h"
#include "mpact/sim/util/memory/atomic_memory.h"
#include "mpact/sim/util/memory/flat_demand_memory.h"
#include "mpact/sim/util/memory/memory_watcher.h"
#include "mpact/sim/util/program_loader/elf_program_loader.h"
#include "riscv/riscv32_decoder.h"
#include "riscv/riscv_fp_state.h"
#include "riscv/riscv_register.h"
#include "riscv/riscv_register_aliases.h"
#include "riscv/riscv_state.h"
#include "riscv/riscv_top.h"

// This top level is customized to execute tests generated by
// https://github.com/riscv-software-src/riscv-tests and report the results.

using HaltReason = ::mpact::sim::generic::CoreDebugInterface::HaltReason;
using AddressRange = ::mpact::sim::util::MemoryWatcher::AddressRange;
using ::mpact::sim::generic::operator*;  // NOLINT: clang-tidy false positive.
using ::mpact::sim::riscv::RiscV32Decoder;
using ::mpact::sim::riscv::RiscVFPState;
using ::mpact::sim::riscv::RiscVState;
using ::mpact::sim::riscv::RiscVTop;
using ::mpact::sim::riscv::RiscVXlen;
using ::mpact::sim::riscv::RV32Register;
using ::mpact::sim::riscv::RVFpRegister;

constexpr char kBeginSignature[] = "begin_signature";
constexpr char kEndSignature[] = "end_signature";

ABSL_FLAG(std::optional<std::string>, dump_signature, std::nullopt,
          "Dump signature file name (riscv torture test)");

int main(int argc, char **argv) {
  auto arg_vec = absl::ParseCommandLine(argc, argv);

  if (arg_vec.size() > 2) {
    std::cerr << "Only a single input file allowed" << std::endl;
    return -1;
  }
  std::string full_file_name = arg_vec[1];
  std::string file_name =
      full_file_name.substr(full_file_name.find_last_of('/') + 1);
  std::string file_basename = file_name.substr(0, file_name.find_first_of('.'));

  mpact::sim::util::FlatDemandMemory memory;
  auto *watcher = new mpact::sim::util::MemoryWatcher(&memory);
  auto *atomic_memory = new mpact::sim::util::AtomicMemory(watcher);
  // Load the elf segments into memory.
  mpact::sim::util::ElfProgramLoader elf_loader(&memory);
  auto load_result = elf_loader.LoadProgram(full_file_name);
  if (!load_result.ok()) {
    std::cerr << "Error while loading '" << full_file_name
              << "': " << load_result.status().message();
    return -1;
  }

  // Set up architectural state and decoder.
  RiscVState rv_state("RiscV32", RiscVXlen::RV32, watcher, atomic_memory);
  // For floating point support add the fp state.
  RiscVFPState rv_fp_state(rv_state.csr_set(), &rv_state);
  rv_state.set_rv_fp(&rv_fp_state);
  // Create the instruction decoder.
  RiscV32Decoder rv_decoder(&rv_state, watcher);

  // Make sure the architectural and abi register aliases are added.
  std::string reg_name;
  for (int i = 0; i < 32; i++) {
    reg_name = absl::StrCat(RiscVState::kXregPrefix, i);
    (void)rv_state.AddRegister<RV32Register>(reg_name);
    (void)rv_state.AddRegisterAlias<RV32Register>(
        reg_name, ::mpact::sim::riscv::kXRegisterAliases[i]);
  }
  for (int i = 0; i < 32; i++) {
    reg_name = absl::StrCat(RiscVState::kFregPrefix, i);
    (void)rv_state.AddRegister<RVFpRegister>(reg_name);
    (void)rv_state.AddRegisterAlias<RVFpRegister>(
        reg_name, ::mpact::sim::riscv::kFRegisterAliases[i]);
  }

  RiscVTop riscv_top("RiscV32TestSim", &rv_state, &rv_decoder);

  // Initialize the PC to the entry point.
  uint32_t entry_point = load_result.value();
  auto pc_write = riscv_top.WriteRegister("pc", entry_point);
  if (!pc_write.ok()) {
    std::cerr << "Error writing to pc: " << pc_write.message();
    return -1;
  }

  // The test result gets stored to label <tohost>, so set a watchpoint there.
  auto result = elf_loader.GetSymbol("tohost");
  if (!result.ok()) {
    std::cerr << "Cannot find symbol 'tohost'";
    return -1;
  }
  auto tohost = result.value().first;
  auto status = watcher->SetStoreWatchCallback(
      AddressRange(tohost), [&riscv_top](uint64_t, int) -> void {
        riscv_top.RequestHalt(RiscVTop::HaltReason::kUserRequest, nullptr);
      });

  if (!status.ok()) {
    std::cerr << "Cannot set watcher callback";
    return -1;
  }

  // Run the executable.
  auto run_status = riscv_top.Run();
  if (!run_status.ok()) {
    std::cerr << run_status.message() << std::endl;
    return -1;
  }

  // Wait for halt.
  auto wait_status = riscv_top.Wait();
  if (!wait_status.ok()) {
    std::cerr << wait_status.message() << std::endl;
    return -1;
  }

  // Get halt reason.
  auto halt_reason = riscv_top.GetLastHaltReason();
  if (!halt_reason.ok()) {
    std::cerr << "Failed to get halt reason: "
              << halt_reason.status().message();
    return -1;
  }

  // Read PC, see where we halted.
  auto pc_read = riscv_top.ReadRegister("pc");
  if (!pc_read.ok()) {
    std::cerr << "Failed to read pc: " << pc_read.status().message();
    return -1;
  }

  int ret = -1;
  if (halt_reason.value() == *HaltReason::kUserRequest) {
    auto db = riscv_top.state()->db_factory()->Allocate<uint32_t>(1);
    memory.Load(tohost, db, nullptr, nullptr);
    auto value = db->Get<uint32_t>(0);
    db->DecRef();
    if (value == 1) {
      std::cerr << "PASS (" << value << ")\n";
      ret = 0;
    } else {
      std::cerr << "FAIL (" << value << ")\n";
      ret = -1;
    }
  }

  // Check to see if we need to dump the riscv torture signature section.
  if (absl::GetFlag(FLAGS_dump_signature).has_value()) {
    std::string file_name = absl::GetFlag(FLAGS_dump_signature).value();
    std::fstream sig_file(file_name.c_str(), std::ios_base::out);
    auto begin_res = elf_loader.GetSymbol(kBeginSignature);
    auto end_res = elf_loader.GetSymbol(kEndSignature);
    if (!begin_res.ok() || !end_res.ok()) {
      std::cerr << "Unable to find signature symbols";
    } else {
      uint64_t begin_sig = begin_res.value().first;
      uint64_t end_sig = end_res.value().first;
      uint64_t length = end_sig - begin_sig;
      uint64_t *buffer = new uint64_t[length >> 3];
      auto status = riscv_top.ReadMemory(begin_sig, buffer, length);
      for (int i = 0; i < length >> 3; ++i) {
        sig_file << std::hex << buffer[i] << std::endl;
      }
      delete[] buffer;
      sig_file.close();
    }
  }

  delete atomic_memory;
  delete watcher;
  return ret;
}
