// 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
//
//     http://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 "cheriot/cheriot_test_rig.h"

#include <cstdint>
#include <cstring>
#include <string>

#include "absl/functional/bind_front.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "cheriot/cheriot_register.h"
#include "cheriot/cheriot_state.h"
#include "cheriot/cheriot_test_rig_decoder.h"
#include "cheriot/riscv_cheriot_minstret.h"
#include "cheriot/riscv_cheriot_register_aliases.h"
#include "cheriot/test_rig_packets.h"
#include "mpact/sim/generic/component.h"
#include "mpact/sim/util/memory/tagged_flat_demand_memory.h"
#include "mpact/sim/util/memory/tagged_memory_watcher.h"
#include "riscv//riscv_register.h"
#include "riscv//riscv_state.h"

namespace mpact::sim::cheriot {

using EC = ::mpact::sim::riscv::ExceptionCode;
using PB = ::mpact::sim::cheriot::CheriotRegister::PermissionBits;
using CheriotEC = ::mpact::sim::cheriot::ExceptionCode;
using ::mpact::sim::util::TaggedFlatDemandMemory;
using ::mpact::sim::util::TaggedMemoryWatcher;

constexpr char kCheriotTestRigName[] = "CheriotTestRig";

CheriotTestRig::CheriotTestRig()
    : generic::Component(kCheriotTestRigName),
      counter_num_instructions_("num_instructions", 0) {
  // Set up memory.
  tagged_memory_ = new TaggedFlatDemandMemory(8);
  // Set up watcher and add callbacks.
  tagged_memory_watcher_ = new TaggedMemoryWatcher(tagged_memory_);
  CHECK_OK(tagged_memory_watcher_->SetLoadWatchCallback(
      TaggedMemoryWatcher::AddressRange{0, 0x1'0000'0000ULL},
      absl::bind_front(&CheriotTestRig::OnLoad, this)));
  CHECK_OK(tagged_memory_watcher_->SetStoreWatchCallback(
      TaggedMemoryWatcher::AddressRange{0, 0x1'0000'0000ULL},
      absl::bind_front(&CheriotTestRig::OnStore, this)));
  // Set up sim state.
  state_ = new CheriotState(kCheriotTestRigName, tagged_memory_watcher_);
  fp_state_ = new RiscVCheriotFPState(state_);
  state_->set_rv_fp(fp_state_);
  // Initialize pcc to 0x8000'0000.
  pcc_ = static_cast<CheriotRegister *>(
      state_->registers()->at(CheriotState::kPcName));
  pcc_->set_address(0x8000'0000);
  cheriot_decoder_ = new CheriotTestRigDecoder(state_);
  // Register instruction counter.
  CHECK_OK(AddCounter(&counter_num_instructions_))
      << "Failed to register counter";
  // Make sure the architectural and abi register aliases are added.
  std::string reg_name;
  std::string xreg_name;
  // Add aliases for capability registers.
  for (int i = 0; i < 32; i++) {
    reg_name = absl::StrCat(CheriotState::kCregPrefix, i);
    // Alias the register with x register names.
    // E.g., 'c10' === 'x10'
    xreg_name = absl::StrCat(CheriotState::kXregPrefix, i);
    CHECK_OK(state_->AddRegisterAlias<CheriotRegister>(reg_name, xreg_name));
    // Alias the register with capability abi register names.
    // E.g., 'c10' === 'ca0'
    CHECK_OK(state_->AddRegisterAlias<CheriotRegister>(reg_name,
                                                       kCRegisterAliases[i]));
    // Alias the register with abi register names.
    // E.g., 'c10' === 'a0'
    CHECK_OK(state_->AddRegisterAlias<CheriotRegister>(reg_name,
                                                       kXRegisterAliases[i]));
  }

  for (int i = 0; i < 32; i++) {
    reg_name = absl::StrCat(CheriotState::kFregPrefix, i);
    (void)state_->AddRegister<riscv::RVFpRegister>(reg_name);
    CHECK_OK(state_->AddRegisterAlias<riscv::RVFpRegister>(
        reg_name, kFRegisterAliases[i]));
  }
  // Register trap monitor.
  state_->set_on_trap(absl::bind_front(&CheriotTestRig::OnTrap, this));
  // Allocate data buffers.
  db1_ = db_factory_.Allocate<uint8_t>(1);
  db2_ = db_factory_.Allocate<uint16_t>(1);
  db4_ = db_factory_.Allocate<uint32_t>(1);
  db8_ = db_factory_.Allocate<uint64_t>(1);
  // Initialize minstret/minstreth. Bind the instruction counter to those
  // registers.
  auto minstret_res = state_->csr_set()->GetCsr("minstret");
  auto minstreth_res = state_->csr_set()->GetCsr("minstreth");
  if (!minstret_res.ok() || !minstreth_res.ok()) {
    LOG(ERROR) << "Error while initializing minstret/minstreth";
  }
  auto *minstret = static_cast<RiscVCheriotMInstret *>(minstret_res.value());
  auto *minstreth = static_cast<RiscVCheriotMInstreth *>(minstreth_res.value());
  minstret->set_counter(&counter_num_instructions_);
  minstreth->set_counter(&counter_num_instructions_);
  // Set memory limits according to the memory space for TestRIG.
  state_->set_max_physical_address(0x8000'0000ULL + 64 * 1024);
  state_->set_min_physical_address(0x8000'0000ULL);
  ResetArch();
}

CheriotTestRig::~CheriotTestRig() {
  delete cheriot_decoder_;
  delete state_;
  delete fp_state_;
  delete tagged_memory_;
  delete tagged_memory_watcher_;
  // Deallocate data buffers.
  db1_->DecRef();
  db2_->DecRef();
  db4_->DecRef();
  db8_->DecRef();
}

absl::Status CheriotTestRig::Execute(
    const test_rig::InstructionPacket &inst_packet, int fd) {
  switch (trace_version_) {
    case 1:
      return ExecuteV1(inst_packet, fd);
      break;
    case 2:
      return ExecuteV2(inst_packet, fd);
      break;
    default:
      return absl::UnimplementedError(
          absl::StrCat("Trace version ", trace_version_, " is not supported"));
  }
}

absl::Status CheriotTestRig::SetVersion(int version) {
  if (version > 2)
    return absl::UnimplementedError(
        absl::StrCat("Trace version ", version, " is not supported"));
  trace_version_ = version;
  return absl::OkStatus();
}

absl::Status CheriotTestRig::ExecuteV1(
    const test_rig::InstructionPacket &inst_packet, int fd) {
  test_rig::ExecutionPacket ep;
  uint32_t inst_word = inst_packet.rvfi_insn;
  ep.rvfi_halt = 0;
  // Clear memory related fields.
  mem_addr_ = 0;
  mem_r_mask_ = 0;
  mem_w_mask_ = 0;
  std::memset(mem_r_data_, 0, sizeof(mem_r_data_));
  std::memset(mem_w_data_, 0, sizeof(mem_w_data_));
  // If trap was set last time around, set indicator for trap handler.
  ep.rvfi_intr = trap_set_ ? 1 : 0;
  trap_set_ = false;
  uint64_t pc = pcc_->address();
  ep.rvfi_pc_rdata = pc;
  // Decode fills in rd_addr, rs2_addr, rs1_addr.
  CheriotTestRigDecoder::DecodeInfo decode_info;
  auto *inst = cheriot_decoder_->DecodeInstruction(pc, inst_word, decode_info);
  ep.rvfi_rd_addr = decode_info.rd;
  ep.rvfi_rs1_addr = decode_info.rs1;
  ep.rvfi_rs2_addr = decode_info.rs2;
  ep.rvfi_rs1_data = GetRegister(ep.rvfi_rs1_addr);
  ep.rvfi_rs2_data = GetRegister(ep.rvfi_rs2_addr);
  uint64_t next_pc = pc + inst->size();
  // Execute the instruction.
  if (!pcc_->HasPermission(PB::kPermitExecute)) {
    state_->HandleCheriRegException(
        inst, inst->address(), CheriotEC::kCapExPermitExecuteViolation, pcc_);
    inst_word = 0;
  } else if (!pcc_->IsInBounds(pc, state_->has_compact() ? sizeof(uint16_t)
                                                         : sizeof(uint32_t))) {
    state_->HandleCheriRegException(inst, inst->address(),
                                    CheriotEC::kCapExBoundsViolation, pcc_);
    inst_word = 0;
  } else {
    inst->Execute(nullptr);
  }
  // Check for trap.
  if (trap_set_) {
    next_pc = pcc_->address();
    // If there's a trap, clear relevant fields.
    ep.rvfi_trap = 1;
    ep.rvfi_rd_addr = 0;
    ep.rvfi_rs2_addr = 0;
    ep.rvfi_rs1_addr = 0;
    ep.rvfi_rd_wdata = 0;
    ep.rvfi_rs2_data = 0;
    ep.rvfi_rs1_data = 0;
    ep.rvfi_mem_addr = 0;
    ep.rvfi_mem_rdata = 0;
    ep.rvfi_mem_wdata = 0;
    ep.rvfi_mem_rmask = 0;
    ep.rvfi_mem_wmask = 0;
    // If the trap was a memory access trap, set the memory address.
    auto res = state_->csr_set()->GetCsr("mcause");
    auto cause = res.value()->AsUint32();
    if (cause == *EC::kLoadAccessFault || cause == *EC::kStoreAccessFault) {
      res = state_->csr_set()->GetCsr("mtval");
      ep.rvfi_mem_addr = res.value()->AsUint32();
    }
  } else {
    if (state_->branch()) {
      next_pc = pcc_->address();
    }
    ep.rvfi_trap = 0;
    // Update register write data.
    ep.rvfi_rd_wdata = GetRegister(ep.rvfi_rd_addr);
    // Update memory fields.
    ep.rvfi_mem_addr = mem_addr_;
    ep.rvfi_mem_rdata = mem_r_data_[0];
    ep.rvfi_mem_wdata = mem_w_data_[0];
    ep.rvfi_mem_rmask = mem_r_mask_;
    ep.rvfi_mem_wmask = mem_w_mask_;
  }
  state_->set_branch(false);
  counter_num_instructions_.Increment(1);
  ep.rvfi_insn = inst_word;
  ep.rvfi_pc_wdata = next_pc;
  ep.rvfi_order = counter_num_instructions_.GetValue();
  pcc_->set_address(next_pc);
  inst->DecRef();
  auto res = write(fd, &ep, sizeof(ep));
  if (res != sizeof(ep)) {
    LOG(ERROR) << "Error writing to trace socket (" << res << ")\n";
    return absl::InternalError("Error writing to trace socket");
  }
  return absl::OkStatus();
}

absl::Status CheriotTestRig::ExecuteV2(
    const test_rig::InstructionPacket &inst_packet, int fd) {
  test_rig::ExecutionPacketExtInteger ep_ext_integer;
  test_rig::ExecutionPacketExtMemAccess ep_ext_mem_access;
  test_rig::ExecutionPacketV2 ep_v2;
  test_rig::ExecutionPacketMetaData &ep_metadata = ep_v2.basic_data;
  test_rig::ExecutionPacketPC &ep_pc = ep_v2.pc_data;

  uint32_t inst_word = inst_packet.rvfi_insn;
  ep_metadata.rvfi_halt = 0;
  // Clear memory related fields.
  mem_addr_ = 0;
  mem_r_mask_ = 0;
  mem_w_mask_ = 0;
  std::memset(mem_r_data_, 0, sizeof(mem_r_data_));
  std::memset(mem_w_data_, 0, sizeof(mem_w_data_));
  // If trap was set last time around, set indicator for trap handler.
  ep_metadata.rvfi_intr = trap_set_ ? 1 : 0;
  trap_set_ = false;
  uint64_t pc = pcc_->address();
  ep_pc.rvfi_pc_rdata = pc;
  // Decode fills in rd_addr, rs2_addr, rs1_addr.
  CheriotTestRigDecoder::DecodeInfo decode_info;
  auto *inst = cheriot_decoder_->DecodeInstruction(pc, inst_word, decode_info);
  ep_ext_integer.rvfi_rd_addr = decode_info.rd;
  ep_ext_integer.rvfi_rs1_addr = decode_info.rs1;
  ep_ext_integer.rvfi_rs2_addr = decode_info.rs2;
  // Get register source values.
  ep_ext_integer.rvfi_rs1_rdata = GetRegister(ep_ext_integer.rvfi_rs1_addr);
  ep_ext_integer.rvfi_rs2_rdata = GetRegister(ep_ext_integer.rvfi_rs2_addr);
  uint64_t next_pc = pc + inst->size();
  // Execute the instruction.
  if (!pcc_->tag()) {
    state_->HandleCheriRegException(inst, inst->address(),
                                    CheriotEC::kCapExTagViolation, pcc_);
    inst_word = 0;
  } else if (!pcc_->HasPermission(PB::kPermitExecute)) {
    state_->HandleCheriRegException(
        inst, inst->address(), CheriotEC::kCapExPermitExecuteViolation, pcc_);
    inst_word = 0;
  } else if (!pcc_->IsInBounds(pc, state_->has_compact() ? sizeof(uint16_t)
                                                         : sizeof(uint32_t))) {
    state_->HandleCheriRegException(inst, inst->address(),
                                    CheriotEC::kCapExBoundsViolation, pcc_);
    inst_word = 0;
  } else {
    inst->Execute(nullptr);
  }

  // Check for trap.
  if (trap_set_) {
    next_pc = pcc_->address();
    // If there's a trap, clear relevant fields.
    ep_metadata.rvfi_trap = 1;
    ep_ext_integer.rvfi_rd_addr = 0;
    ep_ext_integer.rvfi_rs2_addr = 0;
    ep_ext_integer.rvfi_rs1_addr = 0;
    ep_ext_integer.rvfi_rd_wdata = 0;
    ep_ext_integer.rvfi_rs2_rdata = 0;
    ep_ext_integer.rvfi_rs1_rdata = 0;
    ep_ext_mem_access.rvfi_mem_addr = 0;
    std::memset(ep_ext_mem_access.rvfi_mem_rdata, 0,
                sizeof(ep_ext_mem_access.rvfi_mem_rdata));
    std::memset(ep_ext_mem_access.rvfi_mem_wdata, 0,
                sizeof(ep_ext_mem_access.rvfi_mem_wdata));
    ep_ext_mem_access.rvfi_mem_rmask = 0;
    ep_ext_mem_access.rvfi_mem_wmask = 0;
    // If the trap was a memory access trap, set the memory address.
    auto res = state_->csr_set()->GetCsr("mcause");
    auto cause = res.value()->AsUint32();
    if (cause == *EC::kLoadAccessFault || cause == *EC::kStoreAccessFault) {
      res = state_->csr_set()->GetCsr("mtval");
      ep_ext_mem_access.rvfi_mem_addr = res.value()->AsUint32();
    }
  } else {
    if (state_->branch()) {
      next_pc = pcc_->address();
    }
    ep_metadata.rvfi_trap = 0;
    // Update register write data.
    ep_ext_integer.rvfi_rd_wdata = GetRegister(ep_ext_integer.rvfi_rd_addr);
    // Update memory fields.
    ep_ext_mem_access.rvfi_mem_addr = mem_addr_;
    std::memcpy(ep_ext_mem_access.rvfi_mem_rdata, mem_r_data_,
                sizeof(ep_ext_mem_access.rvfi_mem_rdata));
    std::memcpy(ep_ext_mem_access.rvfi_mem_wdata, mem_w_data_,
                sizeof(ep_ext_mem_access.rvfi_mem_wdata));
    ep_ext_mem_access.rvfi_mem_rmask = mem_r_mask_;
    ep_ext_mem_access.rvfi_mem_wmask = mem_w_mask_;
  }
  state_->set_branch(false);
  counter_num_instructions_.Increment(1);
  ep_metadata.rvfi_mode = test_rig::kMachineMode;
  ep_metadata.rvfi_ixl = test_rig::kXL32;
  ep_metadata.rvfi_insn = inst_word;
  ep_pc.rvfi_pc_wdata = next_pc;
  ep_metadata.rvfi_order = counter_num_instructions_.GetValue();
  ep_metadata.rvfi_valid = 1;
  pcc_->set_address(next_pc);
  inst->DecRef();
  ep_v2.trace_size = sizeof(ep_v2);
  ep_v2.available_fields = 0;
  // Check to see if the memory access extension should be added.
  if ((ep_ext_mem_access.rvfi_mem_rmask != 0) ||
      (ep_ext_mem_access.rvfi_mem_wmask != 0) ||
      (ep_ext_mem_access.rvfi_mem_addr != 0)) {
    ep_v2.trace_size += sizeof(ep_ext_mem_access);
    ep_v2.available_fields |= test_rig::kMemoryAccess;
  }
  // Check to see if the integer data extension should be added.
  if ((ep_ext_integer.rvfi_rd_addr != 0) ||
      (ep_ext_integer.rvfi_rs1_addr != 0) ||
      (ep_ext_integer.rvfi_rs2_addr != 0)) {
    ep_v2.trace_size += sizeof(ep_ext_integer);
    ep_v2.available_fields |= test_rig::kIntegerData;
  }

  // Write out the execution packet.
  auto res = write(fd, &ep_v2, sizeof(ep_v2));
  if (res != sizeof(ep_v2)) {
    LOG(ERROR) << "Error writing to trace socket (" << res << ")\n";
    return absl::InternalError("Error writing to trace socket");
  }
  // Write out the extension packets.
  if (ep_v2.available_fields & test_rig::kIntegerData) {
    auto res = write(fd, &ep_ext_integer, sizeof(ep_ext_integer));
    if (res != sizeof(ep_ext_integer)) {
      LOG(ERROR) << "Error writing to trace socket (" << res << ")\n";
      return absl::InternalError("Error writing to trace socket");
    }
  }
  if (ep_v2.available_fields & test_rig::kMemoryAccess) {
    auto res = write(fd, &ep_ext_mem_access, sizeof(ep_ext_mem_access));
    if (res != sizeof(ep_ext_mem_access)) {
      LOG(ERROR) << "Error writing to trace socket (" << res << ")\n";
      return absl::InternalError("Error writing to trace socket");
    }
  }
  return absl::OkStatus();
}

// Reset state.
void CheriotTestRig::ResetArch() {
  // Reset state.
  state_->Reset();
  // Reset pcc.
  pcc_->ResetExecuteRoot();
  pcc_->set_address(0x8000'0000);
  // Clear 64KB memory.
  db8_->Set<uint64_t>(0, 0);
  for (uint64_t addr = 0x8000'0000ULL; addr < 0x8001'0000; addr += 8) {
    tagged_memory_->Store(addr, db8_);
  }
  // Reset instruction counter.
  counter_num_instructions_.SetValue(0);
  // Set all capability registers to memory root capability.
  for (auto const &name :
       {"c1",  "c2",  "c3",  "c4",  "c5",  "c6",  "c7",  "c8",
        "c9",  "c10", "c11", "c12", "c13", "c14", "c15", "c16",
        "c17", "c18", "c19", "c20", "c21", "c22", "c23", "c24",
        "c25", "c26", "c27", "c28", "c29", "c30", "c31"}) {
    auto *cap_reg = state_->GetRegister<CheriotRegister>(name).first;
    cap_reg->ResetMemoryRoot();
  }
}

absl::Status CheriotTestRig::Reset(uint8_t halt, int fd) {
  ResetArch();
  trap_set_ = false;
  // Write the appropriate trace packet out.
  switch (trace_version_) {
    case 1:
      return ResetV1(halt, fd);
      break;
    case 2:
      return ResetV2(halt, fd);

    default:
      return absl::UnimplementedError(
          absl::StrCat("Trace version ", trace_version_, " is not supported"));
  }
}

absl::Status CheriotTestRig::ResetV1(uint8_t halt, int fd) {
  test_rig::ExecutionPacket ep;
  std::memset(&ep, 0, sizeof(ep));
  ep.rvfi_halt = halt;
  auto res = write(fd, &ep, sizeof(ep));
  if (res != sizeof(ep)) {
    LOG(ERROR) << "Error writing to trace socket (" << res << ")\n";
    return absl::InternalError("Error writing to trace socket");
  }
  return absl::OkStatus();
}

absl::Status CheriotTestRig::ResetV2(uint8_t halt, int fd) {
  test_rig::ExecutionPacketV2 ep_v2;
  ep_v2.trace_size = sizeof(ep_v2);
  ep_v2.available_fields = 0;
  std::memset(&ep_v2.pc_data, 0, sizeof(ep_v2.pc_data));
  std::memset(&ep_v2.basic_data, 0, sizeof(ep_v2.basic_data));
  ep_v2.basic_data.rvfi_halt = halt;
  auto res = write(fd, &ep_v2, sizeof(ep_v2));
  if (res != sizeof(ep_v2)) {
    LOG(ERROR) << "Error writing to trace socket (" << res << ")\n";
    return absl::InternalError("Error writing to trace socket");
  }
  return absl::OkStatus();
}

// Just capture that a trap occurred.
bool CheriotTestRig::OnTrap(bool is_interrupt, uint64_t trap_value,
                            uint64_t exception_code, uint64_t epc,
                            const Instruction *inst) {
  trap_set_ = true;
  return false;
}

// Capture load information.
void CheriotTestRig::OnLoad(uint64_t address, int size) {
  mem_addr_ = address;
  switch (size) {
    case 1:
      tagged_memory_->Load(address, db1_, nullptr, nullptr);
      mem_r_mask_ = 0x1ULL;
      mem_r_data_[0] = db1_->Get<uint8_t>(0);
      break;
    case 2:
      tagged_memory_->Load(address, db2_, nullptr, nullptr);
      mem_r_mask_ = 0x3ULL;
      mem_r_data_[0] = db2_->Get<uint16_t>(0);
      break;
    case 4:
      tagged_memory_->Load(address, db4_, nullptr, nullptr);
      mem_r_mask_ = 0xfULL;
      mem_r_data_[0] = db4_->Get<uint32_t>(0);
      break;
    case 8:
      tagged_memory_->Load(address, db8_, nullptr, nullptr);
      mem_r_mask_ = 0xffULL;
      mem_r_data_[0] = db8_->Get<uint64_t>(0);
      break;
    default:
      break;
  }
}

// Capture store information.
void CheriotTestRig::OnStore(uint64_t address, int size) {
  mem_addr_ = address;
  switch (size) {
    case 1:
      tagged_memory_->Load(address, db1_, nullptr, nullptr);
      mem_w_mask_ = 0x1ULL;
      mem_w_data_[0] = db1_->Get<uint8_t>(0);
      break;
    case 2:
      tagged_memory_->Load(address, db2_, nullptr, nullptr);
      mem_w_mask_ = 0x3ULL;
      mem_w_data_[0] = db2_->Get<uint16_t>(0);
      break;
    case 4:
      tagged_memory_->Load(address, db4_, nullptr, nullptr);
      mem_w_mask_ = 0xfULL;
      mem_w_data_[0] = db4_->Get<uint32_t>(0);
      break;
    case 8:
      tagged_memory_->Load(address, db8_, nullptr, nullptr);
      mem_w_mask_ = 0xffULL;
      mem_w_data_[0] = db8_->Get<uint64_t>(0);
      break;
    default:
      break;
  }
}

// Get the register value.
uint32_t CheriotTestRig::GetRegister(uint32_t reg_id) {
  auto reg_name = absl::StrCat(CheriotState::kXregPrefix, reg_id);
  auto ptr = state_->registers()->find(reg_name);
  if (ptr == state_->registers()->end()) {
    return 0;
  } else {
    auto *reg = ptr->second;
    auto *creg = static_cast<CheriotRegister *>(reg);
    return creg->address();
  }
}

}  // namespace mpact::sim::cheriot
