tvm-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] [incubator-tvm] kparzysz-quic commented on a change in pull request #5252: [RUNTIME] Initial implementation of Hexagon runtime support
Date Tue, 07 Apr 2020 13:36:43 GMT
kparzysz-quic commented on a change in pull request #5252: [RUNTIME] Initial implementation
of Hexagon runtime support
URL: https://github.com/apache/incubator-tvm/pull/5252#discussion_r404814243
 
 

 ##########
 File path: src/runtime/hexagon/target/hexagon_device_target.cc
 ##########
 @@ -0,0 +1,525 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   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.
+ */
+
+#ifdef __ANDROID__
+
+#include <unistd.h>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "../hexagon_module.h"
+#include "AEEStdErr.h"
+#include "fastrpc/tvm_hexagon_remote.h"
+#include "hexagon_dsprpcapi.h"
+#include "hexagon_stubapi.h"
+#include "hexagon_target_log.h"
+#include "remote64.h"
+#include "rpcmem.h"
+
+#pragma weak remote_session_control
+
+#define RPCMEM_HEAP 25
+
+// All log messages start with "HexagonTarget::%s", where %s is replaced
+// with the function name, so create macros that add that to avoid repetition.
+// The downside is that the format string must be given as a string literal,
+// but it seems to be a minor issue.
+#define VA_EXPANDER(...) , ##__VA_ARGS__
+#define TVM_LOGD_HT(fmt, ...) \
+  TVM_LOGD("HexagonTarget::%s: " fmt, __func__ VA_EXPANDER(__VA_ARGS__))
+#define TVM_LOGE_HT(fmt, ...) \
+  TVM_LOGE("HexagonTarget::%s: " fmt, __func__ VA_EXPANDER(__VA_ARGS__))
+
+namespace tvm {
+namespace runtime {
+namespace hexagon {
+
+static constexpr int kStackSize = 128 * 1024;  // 128kB stack
+
+class HexagonTarget : public tvm::runtime::hexagon::Device {
+ public:
+  HexagonTarget() {}
+  ~HexagonTarget() final {}
+  void* Alloc(unsigned size, unsigned align) final;
+  void Free(void* ptr) final;
+  void* AllocVtcm(unsigned size, unsigned align) final;
+  void FreeVtcm(void* ptr) final;
+  void CopyDeviceToDevice(void* dst, const void* src, unsigned len) final;
+  void CopyDeviceToHost(void* host_dst, const void* src, unsigned len) final;
+  void CopyHostToDevice(void* dst, const void* host_src, unsigned len) final;
+  void* Load(const std::string& data, const std::string& fmt) final;
+  void Unload(void* mod) final;
+  void* Resolve(const std::string& sym) final;
+  void Call(void* func, uint32_t* scalar, unsigned scalar_num, uint32_t* stack,
+            unsigned stack_num) final;
+
+ private:
+  std::pair<void*, size_t> AddAddrMapping(const void* dsp_addr,
+                                          void* apps_addr, size_t size);
+  std::pair<void*, size_t> GetAppsAddr(const void* dsp_addr, bool exact) const;
+  void RemoveAddrMapping(const void* dsp_addr);
+  int OpenDomainChannel(bool set_unsigned_pd);
+  int CloseDomainChannel();
+  void ReleaseLibrary();
+  void FreeMemoryBeforeChannelClose();
+
+  // Mapping from a DSP address to a pair <apps address, buffer size>.
+  // Using void* pointers is ok, since DSP pointers will always fit
+  // in apps's pointers, i.e. sizeof_dsp(void*) <= sizeof_apps(void*).
+  std::map<const void*, std::pair<void*, size_t>> dsp_to_apps_;
+  std::map<const void*, std::pair<void*, size_t>> vtcm_addr_;
+  remote_handle64 domain_channel_handle_ = AEE_EUNKNOWN;
+  tvm_hexagon_remote_handle_t module_pointer_ = AEE_EUNKNOWN;
+  uint64_t count_channel_open_ = 0;
+  // Global lock, used for all critical sections. This can be refined
+  // in the future.
+  mutable std::mutex crit_section_;
+};
+
+std::shared_ptr<Device> CreateHexagonTarget() {
+  return std::make_shared<HexagonTarget>();
+}
+
+std::pair<void*, size_t> HexagonTarget::AddAddrMapping(const void* dsp_addr,
+                                                       void* apps_addr,
+                                                       size_t size) {
+  crit_section_.lock();
+  auto p = dsp_to_apps_.insert({dsp_addr, {apps_addr, size}});
+  crit_section_.unlock();
+  if (!p.second) {
+    TVM_LOGE_HT(
+        "failed to insert address mapping: dsp:%p -> apps:%p, size:%zu",
+        dsp_addr, apps_addr, size);
+    return std::make_pair(nullptr, 0);
+  }
+  TVM_LOGD_HT("added address mapping: dsp:%p -> apps:%p, size:%zu", dsp_addr,
+              apps_addr, size);
+  return p.first->second;
+}
+
+void HexagonTarget::RemoveAddrMapping(const void* dsp_addr) {
+  crit_section_.lock();
+  auto f = dsp_to_apps_.find(dsp_addr);
+  if (f == dsp_to_apps_.end()) {
+    TVM_LOGE_HT("failed to remove address mapping for dsp:%p", dsp_addr);
+    crit_section_.unlock();
+    return;
+  }
+  dsp_to_apps_.erase(f);
+  crit_section_.unlock();
+}
+
+std::pair<void*, size_t> HexagonTarget::GetAppsAddr(const void* dsp_addr,
+                                                    bool exact) const {
+  struct AutoUnlock {
+    explicit AutoUnlock(std::mutex& m) : m(m) {}
+    ~AutoUnlock() { m.unlock(); }
+    std::mutex& m;
+  };
+
+  crit_section_.lock();
+  AutoUnlock u(crit_section_);
+
+  // If the address is in the map, simply return the result.
+  auto f = dsp_to_apps_.find(dsp_addr);
+  if (f != dsp_to_apps_.end()) return f->second;
+  // If exact mapping is requested, then it hasn't been found.
+  if (exact) return std::make_pair(nullptr, 0);
+
+  // If the address is not in the map, maybe it points to somewhere in the
+  // interior of a mapped buffer.
+  uintptr_t dsp_v = reinterpret_cast<uintptr_t>(dsp_addr);
+  for (const auto& v : dsp_to_apps_) {
+    uintptr_t dsp_k = reinterpret_cast<uintptr_t>(v.first);
+    size_t size = v.second.second;
+    if (dsp_v >= dsp_k && dsp_v < dsp_k + size) {
+      uintptr_t apps_k = reinterpret_cast<uintptr_t>(v.second.first);
+      size_t offset = dsp_v - dsp_k;
+      uintptr_t apps_v = apps_k + offset;
+      return std::make_pair(reinterpret_cast<void*>(apps_v), size - offset);
+    }
+  }
+  TVM_LOGE_HT("failed to locate apps address for dsp:%p", dsp_addr);
+  return std::make_pair(nullptr, 0);
+}
+
+int HexagonTarget::OpenDomainChannel(bool use_unsigned_pd) {
+  if (domain_channel_handle_ != AEE_EUNKNOWN) return AEE_SUCCESS;
+
+  const DspRpcAPI* dsp_api = DspRpcAPI::Global();
+  const StubAPI* stub_api = StubAPI::Global();
+
+  stub_api->rpcmem_init_ptr()();
+
+  if (auto* rsc_ptr = dsp_api->remote_session_control_ptr(true)) {
+    remote_rpc_thread_params th_data;
+    th_data.domain = CDSP_DOMAIN_ID;
+    th_data.stack_size = kStackSize;
+    th_data.prio = -1;  // Default priority.
+    int rc = rsc_ptr(FASTRPC_THREAD_PARAMS, &th_data, sizeof(th_data));
+    if (rc != AEE_SUCCESS) {
+      TVM_LOGE_HT("remote_session_control failed rc=%08x for stack size", rc);
+    }
+    if (use_unsigned_pd) {
+      remote_rpc_control_unsigned_module data;
+      data.enable = 1;
+      data.domain = CDSP_DOMAIN_ID;
+      int rc = rsc_ptr(DSPRPC_CONTROL_UNSIGNED_MODULE, &data, sizeof(data));
+      if (rc != AEE_SUCCESS) {
+        TVM_LOGE_HT("remote_session_control failed rc=%08x for unsigned PD",
+                    rc);
+      }
+    }
+  } else {
+    TVM_LOGD_HT("remote_session_control not available");
+  }
+
+  int rc = stub_api->tvm_hexagon_remote_open(
+      tvm_hexagon_remote_URI "&_dom=cdsp", &domain_channel_handle_);
+  if (rc != AEE_SUCCESS) {
+    TVM_LOGE_HT("failed to open channel rc=0x%x", rc);
+  } else {
+    count_channel_open_++;
+    TVM_LOGD_HT("channel open success and rpcmem_init done");
+  }
+  return rc;
+}
+
+int HexagonTarget::CloseDomainChannel() {
+  if (domain_channel_handle_ == AEE_EUNKNOWN) return AEE_SUCCESS;
+
+  const StubAPI* stub_api = StubAPI::Global();
+
+  int rc = stub_api->tvm_hexagon_remote_close(domain_channel_handle_);
+  if (rc == AEE_SUCCESS) {
+    domain_channel_handle_ = AEE_EUNKNOWN;
+    stub_api->rpcmem_deinit_ptr()();
+    TVM_LOGD_HT("channel close success and rpcmem_deinit done");
+  } else {
+    TVM_LOGE_HT("failed to close domain channel rc=0x%x", rc);
+  }
+  return rc;
+}
+
+void HexagonTarget::ReleaseLibrary() {
+  crit_section_.lock();
+  if (module_pointer_ != AEE_EUNKNOWN) {
+    const StubAPI* stub_api = StubAPI::Global();
+    int rc = stub_api->tvm_hexagon_remote_release_library(
+        domain_channel_handle_, module_pointer_);
+    if (rc != AEE_SUCCESS) {
+      TVM_LOGE_HT("failed to unload device library rc=0x%x", rc);
+    } else {
+      module_pointer_ = AEE_EUNKNOWN;
+    }
+  }
+  crit_section_.unlock();
+}
+
+void HexagonTarget::FreeMemoryBeforeChannelClose() {
+  while (!dsp_to_apps_.empty()) {
+    void* dsp_addr = const_cast<void*>((dsp_to_apps_.begin()->first));
+    TVM_LOGD_HT("Freeing up dsp_addr %p", dsp_addr);
+    HexagonTarget::Free(dsp_addr);
+  }
+}
+void* HexagonTarget::Alloc(unsigned size, unsigned align) {
+  const DspRpcAPI* dsp_api = DspRpcAPI::Global();
+  const StubAPI* stub_api = StubAPI::Global();
+
+  // Opening the domain channel should be done once.
+  crit_section_.lock();
+  int rc_oc = OpenDomainChannel(/*use_unsigned_pd*/ true);
+  crit_section_.unlock();
+  if (rc_oc != AEE_SUCCESS) {
+    TVM_LOGE_HT("mem alloc failed: unable to open domain channel");
+    return nullptr;
+  }
+
+  // This is a workaround. If HexagonTarget::Alloc is called from a different
+  // thread then remote_mmap64 fails. FastRPC expects one call to be made to
+  // DSP before calling remote_map64. Hence this call is needed for now untill
+  // FastRPC comes up with a fix.
+  int rc_call_mmap_64 =
+      stub_api->tvm_hexagon_remote_call_mmap64(domain_channel_handle_);
+  if (rc_call_mmap_64 != AEE_SUCCESS) {
+    TVM_LOGE_HT("mmap64 failed for domain channel %lu", domain_channel_handle_);
+    return nullptr;
+  }
+
+  void* mem =
+      stub_api->rpcmem_alloc_ptr()(RPCMEM_HEAP, RPCMEM_DEFAULT_FLAGS, size);
+  if (mem == nullptr) {
+    TVM_LOGE_HT("mem alloc failed for size=0x%x alignment=0x%x", size, align);
+    return nullptr;
+  }
+  int mem_fd = stub_api->rpcmem_to_fd_ptr()(mem);
+  uintptr_t dsp_va = 0;
+  int rc = dsp_api->remote_mmap64_ptr()(
+      mem_fd, 0, reinterpret_cast<uintptr_t>(mem), size, &dsp_va);
+  if (rc != AEE_SUCCESS) {
+    TVM_LOGE_HT(
+        "buffer mapping failed for remote_map64 fd=0x%x rc=0x%x "
+        "apps_addr=0x%lx",
+        mem_fd, rc, reinterpret_cast<uintptr_t>(mem));
+    return nullptr;
+  }
+
+  void* dsp_addr = reinterpret_cast<void*>(dsp_va);
+  AddAddrMapping(dsp_addr, mem, size);
+  return dsp_addr;
+}
+
+void HexagonTarget::Free(void* ptr) {
+  const DspRpcAPI* dsp_api = DspRpcAPI::Global();
+  const StubAPI* stub_api = StubAPI::Global();
+  auto bb = GetAppsAddr(ptr, true);
+  if (bb.first == reinterpret_cast<void*>(~0)) {
+    TVM_LOGD_HT("VTCM mapping found. dsp_addr=0x%p", ptr);
+    RemoveAddrMapping(ptr);
+    FreeVtcm(ptr);
+    return;
+  }
+
+  TVM_LOGD_HT("VTCM mapping not found. dsp_addr=0x%p", ptr);
+  auto aa = GetAppsAddr(ptr, true);
+  if (aa.first == nullptr) return;
+
+  int rc = dsp_api->remote_munmap64_ptr()(reinterpret_cast<uintptr_t>(ptr),
+                                          aa.second);
+  if (rc != AEE_SUCCESS) {
+    TVM_LOGE_HT("buffer unmapping failed rc=0x%x", rc);
+  }
+  RemoveAddrMapping(ptr);
+  stub_api->rpcmem_free_ptr()(aa.first);
+}
+
+void* HexagonTarget::AllocVtcm(unsigned size, unsigned align) {
+  const StubAPI* stub_api = StubAPI::Global();
+
+  unsigned int dsp_va = 0;
+  int rc = stub_api->tvm_hexagon_remote_alloc_vtcm(domain_channel_handle_,
+                                                   size, align, &dsp_va);
+  if (rc != AEE_SUCCESS) {
+    TVM_LOGE_HT("VTCM allocation failed size=%u, align=%u", size, align);
+    return nullptr;
+  }
+  void* dsp_addr = reinterpret_cast<void*>(dsp_va);
+  TVM_LOGD_HT("Done vtcm alloc dsp:%p", dsp_addr);
+  AddAddrMapping(dsp_addr, reinterpret_cast<void*>(~0), size);
+  return dsp_addr;
+}
+
+void HexagonTarget::FreeVtcm(void* ptr) {
+  const StubAPI* stub_api = StubAPI::Global();
+
+  TVM_LOGD_HT("%s:Calling vtcm free. ptr=%p", __func__, ptr);
+  uintptr_t dsp_va = reinterpret_cast<uintptr_t>(ptr);
+  int rc =
+      stub_api->tvm_hexagon_remote_free_vtcm(domain_channel_handle_, dsp_va);
+  if (rc != AEE_SUCCESS) {
+    TVM_LOGE_HT("VTCM deallocation failed");
+  }
+  TVM_LOGD_HT("Done VTCM free from HexagonTarget::FreeVtcm");
+}
+
+void HexagonTarget::CopyDeviceToDevice(void* dst, const void* src,
 
 Review comment:
   Done.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message