text: /**
   * Copyright (C) 2016-2017 Xilinx, Inc
   *
   * Licensed under the Apache License, Version 2.0 (the "License"). You may
   * not use this file except in compliance with the License. A copy of the
   * License is located 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.
   */
  
  #ifndef xocl_api_profile_h
  #define xocl_api_profile_h
  
  /**
   * This file contains the API for adapting the xocl
   * data structures to the profiling infrastructure.
   *
   * The implementation of this API still requires old "xcl" data
   * hence profile.cpp currently lives under runtime_src/api/profile.cpp
   */
  
  #include "xocl/core/object.h"
  #include "xocl/core/event.h"
  #include "xocl/core/command_queue.h"
  #include <utility>
  #include <string>
  
  namespace xocl { 
  
  class xclbin;
  
  namespace profile {
  
  /*
   * callback function types called from within action_ lambdas
  */
  using cb_action_ndrange_type = std::function<void (xocl::event* event,cl_int status,const std::string& cu_name, cl_kernel kernel,
                                                     std::string kname, std::string xname, size_t workGroupSize,
                                                     const size_t* globalWorkDim, const size_t* localWorkDim, unsigned int programId)>;
  using cb_action_read_type = std::function<void (xocl::event* event,cl_int status, cl_mem buffer, size_t size,
                                            uint64_t address, const std::string& bank)>;
  using cb_action_map_type = std::function<void (xocl::event* event,cl_int status, cl_mem buffer, size_t size,
                                                 uint64_t address, const std::string& bank, cl_map_flags map_flags)>;
  using cb_action_write_type = std::function<void (xocl::event* event,cl_int status, cl_mem buffer, size_t size,
                                                 uint64_t address, const std::string& bank)>;
  using cb_action_unmap_type = std::function<void (xocl::event* event,cl_int status, cl_mem buffer, size_t size,
                                                   uint64_t address, const std::string& bank)>;
  using cb_action_ndrange_migrate_type = std::function <void (xocl::event* event,cl_int status, cl_mem mem0,
                                                        size_t totalSize, uint64_t address, const std::string & bank)>;
  using cb_action_migrate_type = std::function< void (xocl::event* event,cl_int status, cl_mem mem0, size_t totalSize, uint64_t address,
                                                      const std::string & bank, cl_mem_migration_flags flags)>;
  
  /*
   * callback function types for function logging, dependency ...
   */
  
  using cb_log_function_start_type = std::function<void(const char* functionName, long long queueAddress, unsigned int functionID)>;
  using cb_log_function_end_type = std::function<void(const char* functionName, long long queueAddress, unsigned int functionID)>;
  using cb_log_dependencies_type = std::function<void(xocl::event* event,  cl_uint num_deps, const cl_event* deps)>;
  using cb_add_to_active_devices_type = std::function<void (const std::string& device_name)>;
  using cb_set_kernel_clock_freq_type = std::function<void(const std::string& device_name, unsigned int freq)>;
  using cb_reset_type = std::function<void(const xocl::xclbin&)>;
  using cb_init_type = std::function<void(void)>;
  
  /*
   * callback functions to implementation in Profiling
   */
  using cb_get_device_trace_type = std::function<void(bool forceReadTrace)>;
  using cb_get_device_counters_type = std::function<void(bool firstReadAfterProgram, bool forceReadCounters)>;
  using cb_start_device_profiling_type = std::function<void( size_t numComputeUnit)>;
  using cb_reset_device_profiling_type = std::function<void(void)>;
  using cb_end_device_profiling_type = std::function<void(void)>;
  
  /*
   * callback registration functions called from profile
  */
  void register_cb_action_ndrange (cb_action_ndrange_type&& cb);
  void register_cb_action_read  (cb_action_read_type&& cb);
  void register_cb_action_map (cb_action_map_type&& cb);
  void register_cb_action_write (cb_action_write_type&& cb);
  void register_cb_action_unmap (cb_action_unmap_type&& cb);
  void register_cb_action_ndrange_migrate (cb_action_ndrange_migrate_type&& cb);
  void register_cb_action_migrate (cb_action_migrate_type&& cb);
  
  void register_cb_log_function_start (cb_log_function_start_type&& cb);
  void register_cb_log_function_end (cb_log_function_end_type&& cb);
  void register_cb_log_dependencies(cb_log_dependencies_type && cb);
  void register_cb_add_to_active_devices(cb_add_to_active_devices_type&& cb);
  void register_cb_set_kernel_clock_freq (cb_set_kernel_clock_freq_type&& cb);
  void register_cb_reset(cb_reset_type && cb);
  void register_cb_init (cb_init_type && cb);
  
  
  void register_cb_get_device_trace (cb_get_device_trace_type&& cb);
  void register_cb_get_device_counters (cb_get_device_counters_type&& cb);
  void register_cb_start_device_profiling (cb_start_device_profiling_type&& cb);
  void register_cb_reset_device_profiling (cb_reset_device_profiling_type&& cb);
  void register_cb_end_device_profiling (cb_end_device_profiling_type&& cb);
  
  void get_address_bank(cl_mem buffer, uint64_t &address, int &bank);
  
  std::string
  get_event_string(xocl::event* currEvent);
  
  std::string
  get_event_dependencies_string(xocl::event* currEvent);
  
  xocl::event::action_profile_type
  action_ndrange(cl_event event,cl_kernel kernel);
  
  xocl::event::action_profile_type
  action_read(cl_mem buffer);
  
  xocl::event::action_profile_type
  action_map(cl_mem buffer,cl_map_flags map_flags);
  
  xocl::event::action_profile_type
  action_write(cl_mem buffer);
  
  xocl::event::action_profile_type
  action_unmap(cl_mem buffer);
  
  xocl::event::action_profile_type
  action_ndrange_migrate(cl_event event, cl_kernel kernel);
  
  xocl::event::action_profile_type
  action_migrate(cl_uint num_mem_objects, const cl_mem *mem_objects, cl_mem_migration_flags flags);
  
  template <typename F, typename ...Args>
  inline void
  set_event_action(xocl::event* event, F&& f, Args&&... args)
  {
    // if profiling is off, then avoid creating the lambdas
  #if 0 // For the time being, to preserve old log profile data behavior, 
        // always store the profile action, see comments in xocl/core/event.h
    if (!event->get_command_queue()->is_profiling_enabled())
      return;
  #endif
  
    event->set_profile_action(f(std::forward<Args>(args)...));
  }
  
  void
  log(xocl::event* event, cl_int status);
  
  void
  log(xocl::event* event, cl_int status, const std::string& cuname);
  
  void
  log_dependencies (xocl::event* event,  cl_uint num_deps, const cl_event* deps);
  
  struct function_call_logger
  {
    function_call_logger(const char* function);
    function_call_logger(const char* function, long long address);
    ~function_call_logger();
  
    static std::atomic <unsigned int> m_funcid_global;
    unsigned int m_funcid;
    const char* m_name = nullptr;
    long long m_address = 0;
  };
  
  void
  add_to_active_devices(const std::string& device_name);
  
  void
  set_kernel_clock_freq(const std::string& device_name, unsigned int freq);
  
  void
  reset(const xocl::xclbin& xclbin);
  
  /**
   * Initialize profiling (was RTSignleton::instance() blah blah
   */
  void 
  init();
  
  void
  get_device_trace (bool forceReadTrace);
  
  void
  get_device_counters (bool firstReadAfterProgram, bool forceReadCounters);
  
  void
  start_device_profiling(size_t numComputeUnits);
  
  void
  reset_device_profiling();
  
  void
  end_device_profiling();
  
  }} // profile,xocl
  
  #define PROFILE_LOG_FUNCTION_CALL xocl::profile::function_call_logger function_call_logger_object(__func__);
  #define PROFILE_LOG_FUNCTION_CALL_WITH_QUEUE(Q) xocl::profile::function_call_logger function_call_logger_object(__func__, (long long)Q);
  
  #endif
  
  
  