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

#ifndef MPACT_SIM_UTIL_MEMORY_MEMORY_WATCHER_H_
#define MPACT_SIM_UTIL_MEMORY_MEMORY_WATCHER_H_

#include <cstdint>

#include "absl/container/btree_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/instruction.h"
#include "mpact/sim/generic/ref_count.h"
#include "mpact/sim/util/memory/memory_interface.h"

// This file declares a class that is used to create data watchpoints. Since it
// implements the memory interface, it can easily be inserted between a memory
// requestor and the memory.

namespace mpact {
namespace sim {
namespace util {

using ::mpact::sim::generic::DataBuffer;
using ::mpact::sim::generic::Instruction;
using ::mpact::sim::generic::ReferenceCount;

class MemoryWatcher : public MemoryInterface {
 public:
  // Address range struct used as key in maps from range to callback function.
  struct AddressRange {
    uint64_t start;
    uint64_t end;
    explicit AddressRange(uint64_t address) : start(address), end(address) {}
    AddressRange(uint64_t start_address, uint64_t end_address)
        : start(start_address), end(end_address) {}
  };
  // Comparator used to compare two address ranges. A range is less than another
  // if they do (a) not overlap and (b) the addresses of the first are less than
  // the other.
  struct AddressRangeLess {
    constexpr bool operator()(const AddressRange& lhs,
                              const AddressRange& rhs) const {
      return lhs.end < rhs.start;
    }
  };

  // Callback types. The load callback does not pass the load data, as that is
  // not available in the memory Load call. The call passes the address and the
  // data size.
  using Callback = absl::AnyInvocable<void(uint64_t, int)>;

  // Constructor - default constructor is disabled. Use default destructor.
  explicit MemoryWatcher(MemoryInterface* memory);
  MemoryWatcher() = delete;
  MemoryWatcher(const MemoryWatcher&) = delete;  // no copy constructor.
  MemoryWatcher& operator=(const MemoryWatcher&) = delete;  // no assignment.
  ~MemoryWatcher() override = default;

  // Methods to set/clear watch ranges. No new store (load) range can overlap an
  // existing store (load) range. The address range has to have the start < end.
  // Since there cannot be any overlapping ranges, it is only necessary to
  // specify a single address for the clear call, as it will map to the range
  // that contains it.
  absl::Status SetStoreWatchCallback(const AddressRange& range,
                                     Callback callback);
  absl::Status ClearStoreWatchCallback(uint64_t address);
  absl::Status SetLoadWatchCallback(const AddressRange& range,
                                    Callback callback);
  absl::Status ClearLoadWatchCallback(uint64_t address);

  // The memory interface methods.
  void Load(uint64_t address, DataBuffer* db, Instruction* inst,
            ReferenceCount* context) override;
  void Load(DataBuffer* address_db, DataBuffer* mask_db, int el_size,
            DataBuffer* db, Instruction* inst,
            ReferenceCount* context) override;
  void Store(uint64_t address, DataBuffer* db) override;
  void Store(DataBuffer* address_db, DataBuffer* mask_db, int el_size,
             DataBuffer* db) override;

 private:
  // The memory interface to forward the loads/stores to.
  MemoryInterface* memory_;
  absl::btree_multimap<AddressRange, Callback, AddressRangeLess>
      ld_watch_actions_;
  absl::btree_multimap<AddressRange, Callback, AddressRangeLess>
      st_watch_actions_;
};

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

#endif  // MPACT_SIM_UTIL_MEMORY_MEMORY_WATCHER_H_
