/*
 * =============================================================================
 *   ROC Runtime Conformance Release License
 * =============================================================================
 * The University of Illinois/NCSA
 * Open Source License (NCSA)
 *
 * Copyright (c) 2017, Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Developed by:
 *
 *                 AMD Research and AMD ROC Software Development
 *
 *                 Advanced Micro Devices, Inc.
 *
 *                 www.amd.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal with the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimers.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimers in
 *    the documentation and/or other materials provided with the distribution.
 *  - Neither the names of <Name of Development Group, Name of Institution>,
 *    nor the names of its contributors may be used to endorse or promote
 *    products derived from this Software without specific prior written
 *    permission.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS WITH THE SOFTWARE.
 *
 */

/// \file
/// File containg base class declaration needed for all RocR tests and samples
/// that allow derived classes to use utility functions.

#ifndef ROCRTST_COMMON_BASE_ROCR_H_
#define ROCRTST_COMMON_BASE_ROCR_H_
#include <stdint.h>
#include <stdio.h>
#include <string>
#include "common/common.h"
#include "common/hsatimer.h"
#include "hsa/hsa.h"
#include "hsa/hsa_ext_amd.h"
#include "common/rocr.h"

namespace rocrtst {

/// Common interface for RocR tests and samples, required for several
/// common functions
class BaseRocR {
 public:
  BaseRocR(void);

  virtual ~BaseRocR(void);

  ///< Setters and Getters

  void set_gpu_device1(hsa_agent_t in_dev) {
    gpu_device1_.handle = in_dev.handle;
  }
  hsa_agent_t* gpu_device1(void) {
    return &gpu_device1_;
  }

  void set_cpu_device(hsa_agent_t in_dev) {
    cpu_device_.handle = in_dev.handle;
  }
  hsa_agent_t* cpu_device(void) {
    return &cpu_device_;
  }

  void set_kernel_file_name(const char* in_file_name) {
    kernel_file_name_ = in_file_name;
  }
  std::string const kernel_file_name(void) const {
    return kernel_file_name_;
  }
  const

  void set_kernel_name(std::string in_kernel_name) {
    kernel_name_ = in_kernel_name;
  }
  std::string const kernel_name(void) const {
    return kernel_name_;
  }

  void set_agent_name(std::string in_agent_name) {
    agent_name_ = in_agent_name;
  }
  std::string const get_agent_name(void) const {
    return agent_name_;
  }

  void set_kernel_object(uint64_t in_kernel_object) {
    kernel_object_ = in_kernel_object;
  }
  uint64_t kernel_object(void) const {
    return kernel_object_;
  }

  void set_profile(hsa_profile_t in_prof) {
    profile_ = in_prof;
  }
  hsa_profile_t profile(void) const {
    return profile_;
  }

  uint32_t private_segment_size(void) const {
    return private_segment_size_;
  }
  void set_private_segment_size(uint32_t sz) {
    private_segment_size_ = sz;
  }

  void set_group_segment_size(uint32_t sz) {
    group_segment_size_ = sz;
  }
  uint32_t group_segment_size(void) const {
    return group_segment_size_;
  }

  void set_group_size(uint32_t sz) {
    group_size_ = sz;
  }
  uint32_t group_size(void) const {
    return group_size_;
  }

  void set_main_queue(hsa_queue_t* q) {
    main_queue_ = q;
  }
  hsa_queue_t* main_queue(void) const {
    return main_queue_;
  }

  void clear_code_object() {
    for(std::vector<CodeObject *>::iterator  it = objs_.begin(); it != objs_.end(); ++it) {
      delete *it;
    }
    objs_.clear();
  }
  void set_code_object(CodeObject* obj) {
    objs_.push_back(obj);
  }

  hsa_kernel_dispatch_packet_t& aql(void) {
    return aql_;
  }

  void set_num_iteration(int num) {
    num_iteration_ = num;
  }
  uint32_t num_iteration(void) const {
    return num_iteration_;
  }

  hsa_amd_memory_pool_t& device_pool(void) {
    return device_pool_;
  }

  hsa_amd_memory_pool_t& cpu_pool(void) {
    return cpu_pool_;
  }

  hsa_amd_memory_pool_t& kern_arg_pool(void) {
    return kern_arg_pool_;
  }

  void set_kernarg_size(uint32_t sz) {
    kernarg_size_ = sz;
  }
  uint32_t kernarg_size(void) const {
    return kernarg_size_;
  }

  void set_kernarg_align(uint32_t align) {
    kernarg_align_ = align;
  }
  uint32_t kernarg_align(void) const {
    return kernarg_align_;
  }

  void* kernarg_buffer(void) const {
    return kernarg_buffer_;
  }
  void set_kernarg_buffer(void* buffer) {
    kernarg_buffer_ = buffer;
  }

  int32_t requires_profile(void) const {
    return requires_profile_;
  }

  char* orig_hsa_enable_interrupt() const {
    return orig_hsa_enable_interrupt_;
  }

  bool enable_interrupt() const {
    return enable_interrupt_;
  }

  void set_title(std::string name) {
    title_ = name;
  }
  std::string title(void) const {
    return title_;
  }

  PerfTimer* hsa_timer(void) {
    return &hsa_timer_;
  }

  void set_verbosity(uint32_t v) {
    verbosity_ = v;
  }
  uint32_t verbosity(void) const {
    return verbosity_;
  }

  void set_monitor_verbosity(uint32_t m) {
    monitor_verbosity_ = m;
  }
  uint32_t monitor_verbosity(void) const {
    return monitor_verbosity_;
  }

 protected:
  void set_requires_profile(int32_t reqd_prof) {
    requires_profile_ = reqd_prof;
  }

  void set_enable_interrupt(bool doEnable) {
    enable_interrupt_ = doEnable;
  }

 private:
  uint64_t num_iteration_;   ///< Number of times to execute test

  hsa_queue_t* main_queue_;   ///< AQL queue used for packets

  std::vector<CodeObject*> objs_; ///< CodeObject vector

  hsa_agent_t gpu_device1_;   ///< Handle to first GPU found

  hsa_agent_t cpu_device_;   ///< Handle to CPU

  hsa_amd_memory_pool_t device_pool_;   ///< Memory pool on gpu pool list

  hsa_amd_memory_pool_t cpu_pool_;   ///< Memory pool on cpu pool list

  hsa_amd_memory_pool_t kern_arg_pool_;   ///< Memory pool suitable for args

  uint64_t kernel_object_;   ///< Handle to kernel code

  std::string kernel_file_name_;   ///< Code object file name

  std::string kernel_name_;   ///< Kernel name

  std::string agent_name_;   ///< Agent name

  hsa_kernel_dispatch_packet_t aql_;   ///< Kernel dispatch packet

  uint32_t group_segment_size_;   ///< Kernel group seg size

  uint32_t kernarg_size_;   ///< Kernarg memory size

  uint32_t kernarg_align_;   ///< Alignment for kern argument memory

  void* kernarg_buffer_;    ///< Unaligned allocated kernel arg. buffer

  hsa_profile_t profile_;   ///< Device profile.

  uint32_t group_size_;   ///< Number of work items in one group

  uint32_t private_segment_size_;   ///< Kernel private seg size

  int32_t requires_profile_;   ///< Profile required by test (-1 if no req.)

  char* orig_hsa_enable_interrupt_;   ///< Orig. value of HSA_ENABLE_INTERRUPT

  bool enable_interrupt_;   ///< Whether to enable/disable interrupts for test

  std::string title_;   ///< Displayed title of test

  uint32_t verbosity_;   ///< How much additional output to produce

  uint32_t monitor_verbosity_;   ///< How much additional output to produce

  PerfTimer hsa_timer_;   ///< Timer to be used for timing parts of test
};

}  // namespace rocrtst
#endif  // ROCRTST_COMMON_BASE_ROCR_H_
