// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GARNET_BIN_CPUPERF_PROVIDER_IMPORTER_H_
#define GARNET_BIN_CPUPERF_PROVIDER_IMPORTER_H_

#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <unordered_map>

#include <lib/zircon-internal/device/cpu-trace/perf-mon.h>
#include <src/lib/fxl/logging.h>
#include <trace-engine/context.h>

#include "garnet/bin/cpuperf_provider/categories.h"
#include "garnet/lib/perfmon/reader.h"
#include "garnet/lib/perfmon/events.h"

namespace cpuperf_provider {

class Importer {
 public:
  Importer(trace_context* context, const TraceConfig* trace_config, trace_ticks_t start_time,
           trace_ticks_t stop_time);
  ~Importer();

  bool Import(perfmon::Reader& reader, const perfmon::Config& perfmon_config);

 private:
  static constexpr size_t kMaxNumCpus = 32;
  static_assert(kMaxNumCpus <= TRACE_ENCODED_THREAD_REF_MAX_INDEX, "bad value for kMaxNumCpus");

  class EventTracker final {
   public:
    EventTracker(trace_ticks_t start_time) : start_time_(start_time) {}

    bool HaveValue(unsigned cpu, perfmon::EventId id) const {
      Key key = GenKey(cpu, id);
      EventData::const_iterator iter = data_.find(key);
      return iter != data_.end();
    }

    void UpdateTime(unsigned cpu, perfmon::EventId id, trace_ticks_t time) {
      Key key = GenKey(cpu, id);
      data_[key].time = time;
    }

    trace_ticks_t GetTime(unsigned cpu, perfmon::EventId id) const {
      Key key = GenKey(cpu, id);
      EventData::const_iterator iter = data_.find(key);
      if (iter == data_.end())
        return start_time_;
      return iter->second.time;
    }

    void UpdateValue(unsigned cpu, perfmon::EventId id, uint64_t value) {
      Key key = GenKey(cpu, id);
      data_[key].is_value = true;
      data_[key].count_or_value = value;
    }

    void AccumulateCount(unsigned cpu, perfmon::EventId id, uint64_t value) {
      Key key = GenKey(cpu, id);
      data_[key].is_value = false;
      data_[key].count_or_value += value;
    }

    bool IsValue(unsigned cpu, perfmon::EventId id) const {
      Key key = GenKey(cpu, id);
      EventData::const_iterator iter = data_.find(key);
      FXL_DCHECK(iter != data_.end());
      return iter->second.is_value;
    }

    uint64_t GetCountOrValue(unsigned cpu, perfmon::EventId id) const {
      Key key = GenKey(cpu, id);
      EventData::const_iterator iter = data_.find(key);
      if (iter == data_.end())
        return 0;
      return iter->second.count_or_value;
    }

   private:
    using Key = uint32_t;
    struct Data {
      trace_ticks_t time = 0;
      // false -> count (perfmon::kRecordTypeCount),
      // true -> value (perfmon::kRecordTypeValue).
      bool is_value;
      // This is either a count or a value.
      // Records for any particular event should only be using one
      // of |perfmon::kRecordType{Count,Value}|.
      uint64_t count_or_value = 0;
    };
    using EventData = std::unordered_map<Key, Data>;

    Key GenKey(unsigned cpu, perfmon::EventId id) const {
      FXL_DCHECK(cpu < kMaxNumCpus);
      static_assert(sizeof(id) == 2, "");
      return (cpu << 16) | id;
    }

    const trace_ticks_t start_time_;
    EventData data_;
  };

  uint64_t ImportRecords(perfmon::Reader& reader, const perfmon::Config& perfmon_config);

  void ImportSampleRecord(trace_cpu_number_t cpu, const perfmon::SampleRecord& record,
                          trace_ticks_t previous_time, trace_ticks_t current_time,
                          uint64_t ticks_per_second, uint64_t event_value);

  void EmitSampleRecord(trace_cpu_number_t cpu, const perfmon::EventDetails* details,
                        const perfmon::SampleRecord& record, trace_ticks_t start_time,
                        trace_ticks_t end_time, uint64_t ticks_per_second, uint64_t value);

  void EmitLastBranchRecordBlob(trace_cpu_number_t cpu, const perfmon::SampleRecord& record,
                                trace_ticks_t time);

  void EmitTallyCounts(perfmon::Reader& reader, const perfmon::Config& perfmon_config,
                       const EventTracker& event_data);

  void EmitTallyRecord(trace_cpu_number_t cpu, perfmon::EventId event_id, trace_ticks_t time,
                       bool is_value, uint64_t value);

  trace_string_ref_t GetCpuNameRef(trace_cpu_number_t cpu);

  trace_thread_ref_t GetCpuThreadRef(trace_cpu_number_t cpu, perfmon::EventId id);

  trace_context* const context_;
  const TraceConfig* trace_config_;
  trace_ticks_t start_time_;
  trace_ticks_t stop_time_;

  trace_string_ref_t const cpu_string_ref_;
  // Our use of the "category" argument to trace_context_write_* functions
  // is a bit abnormal. The argument "should" be the name of the category
  // the user provided. However, users can select individual events or
  // collections of events and the mapping from user-provided category
  // name to our output is problematic. So just use a single category to
  // encompass all of them ("cpu:perf") and use the name argument to
  // identify each event.
  trace_string_ref_t const cpuperf_category_ref_;
  trace_string_ref_t const count_name_ref_;
  trace_string_ref_t const value_name_ref_;
  trace_string_ref_t const rate_name_ref_;
  trace_string_ref_t const aspace_name_ref_;
  trace_string_ref_t const pc_name_ref_;

  // Add one for events that are system-wide (e.g., memory controller events).
  trace_thread_ref_t cpu_thread_refs_[kMaxNumCpus + 1];

  // Add one for events that are system-wide (e.g., memory controller events).
  trace_string_ref_t cpu_name_refs_[kMaxNumCpus + 1];

  Importer(const Importer&) = delete;
  Importer(Importer&&) = delete;
  Importer& operator=(const Importer&) = delete;
  Importer& operator=(Importer&&) = delete;
};

}  // namespace cpuperf_provider

#endif  // GARNET_BIN_CPUPERF_PROVIDER_IMPORTER_H_
