// 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/memory/memory_router.h"

#include <cstdint>
#include <string>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "mpact/sim/util/memory/memory_interface.h"
#include "mpact/sim/util/memory/single_initiator_router.h"
#include "mpact/sim/util/memory/tagged_memory_interface.h"

namespace mpact {
namespace sim {
namespace util {

MemoryRouter::MemoryRouter() {}

MemoryRouter::~MemoryRouter() {
  for (auto &[unused, initiator] : initiators_) delete initiator;

  initiators_.clear();
}

// Templated helper method used in implementing the three methods to add named
// initiators to the router (one for each type of initiator interface).
template <typename Interface>
Interface *AddInitiator(MemoryRouter::InitiatorMap &initiators,
                        const std::string &name) {
  // See if it already exists.
  auto it = initiators.find(name);
  if (it != initiators.end()) {
    return static_cast<Interface *>(it->second);
  }
  auto initiator = new SingleInitiatorRouter(name);
  initiators.emplace(std::string(name), initiator);
  return static_cast<Interface *>(initiator);
}

MemoryInterface *MemoryRouter::AddMemoryInitiator(const std::string &name) {
  return AddInitiator<MemoryInterface>(initiators_, name);
}

TaggedMemoryInterface *MemoryRouter::AddTaggedInitiator(
    const std::string &name) {
  return AddInitiator<TaggedMemoryInterface>(initiators_, name);
}

AtomicMemoryOpInterface *MemoryRouter::AddAtomicInitiator(
    const std::string &name) {
  return AddInitiator<AtomicMemoryOpInterface>(initiators_, name);
}

namespace internal {

// Templated helper method used in implementing the next three methods that
// add named targets to the router (one for each type of target interface).
template <typename Interface>
absl::Status AddTargetPrivate(
    MemoryRouter::TargetMap<Interface> &target_interface_map,
    absl::flat_hash_set<std::string> &target_names, const std::string &name,
    Interface *memory) {
  // Only one instance of each target name can exist.
  if (target_names.contains(name)) {
    return absl::AlreadyExistsError(
        absl::StrCat("Target: ", name, " already exists"));
  }
  target_names.insert(name);
  target_interface_map.emplace(std::string(name), memory);
  return absl::OkStatus();
}

}  // namespace internal

absl::Status MemoryRouter::AddTarget(const std::string &name,
                                     MemoryInterface *memory) {
  return internal::AddTargetPrivate<MemoryInterface>(
      memory_targets_, target_names_, name, memory);
}

absl::Status MemoryRouter::AddTarget(const std::string &name,
                                     TaggedMemoryInterface *tagged_memory) {
  return internal::AddTargetPrivate<TaggedMemoryInterface>(
      tagged_targets_, target_names_, name, tagged_memory);
}

absl::Status MemoryRouter::AddTarget(const std::string &name,
                                     AtomicMemoryOpInterface *atomic_memory) {
  return internal::AddTargetPrivate<AtomicMemoryOpInterface>(
      atomic_targets_, target_names_, name, atomic_memory);
}

// Add a mapping between 'initiator_name' and 'target_name' for the given
// address range (inclusive).
absl::Status MemoryRouter::AddMapping(const std::string &initiator_name,
                                      const std::string &target_name,
                                      uint64_t base, uint64_t top) {
  // Return error if the initiator doesn't exist.
  auto it = initiators_.find(initiator_name);
  if (it == initiators_.end()) {
    return absl::NotFoundError(
        absl::StrCat("Initiator: ", initiator_name, " not found"));
  }
  auto *initiator = it->second;

  // Check each type of target and add the one found to the initiator with the
  // given address range.

  auto memory_it = memory_targets_.find(target_name);
  if (memory_it != memory_targets_.end()) {
    return initiator->AddTarget(memory_it->second, base, top);
  }
  auto tagged_it = tagged_targets_.find(target_name);
  if (tagged_it != tagged_targets_.end()) {
    return initiator->AddTarget(tagged_it->second, base, top);
  }
  auto atomic_it = atomic_targets_.find(target_name);
  if (atomic_it != atomic_targets_.end()) {
    return initiator->AddTarget(atomic_it->second, base, top);
  }
  // Return error if there is no such target.
  return absl::NotFoundError(
      absl::StrCat("Target: ", target_name, " not found"));
}

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