From 2e1a630b47a60ffb1227ea993cabbf93e78aa1a8 Mon Sep 17 00:00:00 2001 From: Sravankumar allu Date: Mon, 15 Jul 2024 14:09:33 +0530 Subject: [PATCH] VITIS-11024 enable hw_context support for xrt::graph objects 3rd commit --- src/runtime_src/core/common/ishim.h | 148 +------ .../core/common/shim/graph_handle.h | 7 +- src/runtime_src/core/edge/user/aie/aie.h | 4 +- src/runtime_src/core/edge/user/aie/aied.cpp | 4 +- src/runtime_src/core/edge/user/aie/aied.h | 13 +- .../user/aie/common_layer/adf_runtime_api.cpp | 2 + .../user/aie/common_layer/adf_runtime_api.h | 2 + src/runtime_src/core/edge/user/aie/graph.cpp | 373 +----------------- .../core/edge/user/device_linux.cpp | 83 +++- src/runtime_src/core/edge/user/device_linux.h | 28 ++ .../core/edge/user/graph_object.cpp | 339 +++++++++++----- src/runtime_src/core/edge/user/graph_object.h | 47 ++- .../core/edge/user/hwctx_object.cpp | 4 + 13 files changed, 430 insertions(+), 624 deletions(-) diff --git a/src/runtime_src/core/common/ishim.h b/src/runtime_src/core/common/ishim.h index 640a6def82a..069c29df693 100755 --- a/src/runtime_src/core/common/ishim.h +++ b/src/runtime_src/core/common/ishim.h @@ -208,31 +208,40 @@ struct ishim #ifdef XRT_ENABLE_AIE virtual void - open_aie_context(xrt::aie::access_mode) = 0; + open_aie_context(xrt::aie::access_mode) + { throw not_supported_error{__func__}; } virtual void - sync_aie_bo(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) = 0; + sync_aie_bo(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) + { throw not_supported_error{__func__}; } virtual void - reset_aie() = 0; + reset_aie() + { throw not_supported_error{__func__}; } virtual void - sync_aie_bo_nb(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) = 0; + sync_aie_bo_nb(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) + { throw not_supported_error{__func__}; } virtual void - wait_gmio(const char *gmioName) = 0; + wait_gmio(const char *gmioName) + { throw not_supported_error{__func__}; } virtual int - start_profiling(int option, const char* port1Name, const char* port2Name, uint32_t value) = 0; + start_profiling(int option, const char* port1Name, const char* port2Name, uint32_t value) + { throw not_supported_error{__func__}; } virtual uint64_t - read_profiling(int phdl) = 0; + read_profiling(int phdl) + { throw not_supported_error{__func__}; } virtual void - stop_profiling(int phdl) = 0; + stop_profiling(int phdl) + { throw not_supported_error{__func__}; } virtual void - load_axlf_meta(const axlf*) = 0; + load_axlf_meta(const axlf*) + { throw not_supported_error{__func__}; } virtual std::vector read_aie_mem(uint16_t /*col*/, uint16_t /*row*/, uint32_t /*offset*/, uint32_t /*size*/) @@ -404,70 +413,6 @@ struct shim : public DeviceType if (auto ret = xclInternalResetDevice(DeviceType::get_device_handle(), kind)) throw error(ret, "failed to reset device"); } - -#ifdef XRT_ENABLE_AIE - - void - open_aie_context(xrt::aie::access_mode am) override - { - if (auto ret = xclAIEOpenContext(DeviceType::get_device_handle(), am)) - throw error(ret, "fail to open aie context"); - } - - void - sync_aie_bo(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) override - { - if (auto ret = xclSyncBOAIE(DeviceType::get_device_handle(), bo, gmioName, dir, size, offset)) - throw system_error(ret, "fail to sync aie bo"); - } - - void - reset_aie() override - { - if (auto ret = xclResetAIEArray(DeviceType::get_device_handle())) - throw system_error(ret, "fail to reset aie"); - } - - void - sync_aie_bo_nb(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) override - { - if (auto ret = xclSyncBOAIENB(DeviceType::get_device_handle(), bo, gmioName, dir, size, offset)) - throw system_error(ret, "fail to sync aie non-blocking bo"); - } - - void - wait_gmio(const char *gmioName) override - { - if (auto ret = xclGMIOWait(DeviceType::get_device_handle(), gmioName)) - throw system_error(ret, "fail to wait gmio"); - } - - int - start_profiling(int option, const char* port1Name, const char* port2Name, uint32_t value) override - { - return xclStartProfiling(DeviceType::get_device_handle(), option, port1Name, port2Name, value); - } - - uint64_t - read_profiling(int phdl) override - { - return xclReadProfiling(DeviceType::get_device_handle(), phdl); - } - - void - stop_profiling(int phdl) override - { - if (auto ret = xclStopProfiling(DeviceType::get_device_handle(), phdl)) - throw system_error(ret, "failed to stop profiling"); - } - - void - load_axlf_meta(const axlf* buffer) override - { - if (auto ret = xclLoadXclBinMeta(DeviceType::get_device_handle(), buffer)) - throw system_error(ret, "failed to load xclbin"); - } -#endif }; // Stub out all xrt_core::ishim functions to throw not supported. A @@ -588,63 +533,6 @@ struct noshim : public DeviceType { throw ishim::not_supported_error(__func__); } - -#ifdef XRT_ENABLE_AIE - - void - open_aie_context(xrt::aie::access_mode) override - { - throw ishim::not_supported_error(__func__); - } - - void - sync_aie_bo(xrt::bo&, const char*, xclBOSyncDirection, size_t, size_t) override - { - throw ishim::not_supported_error(__func__); - } - - void - reset_aie() override - { - throw ishim::not_supported_error(__func__); - } - - void - sync_aie_bo_nb(xrt::bo&, const char*, xclBOSyncDirection, size_t, size_t) override - { - throw ishim::not_supported_error(__func__); - } - - void - wait_gmio(const char*) override - { - throw ishim::not_supported_error(__func__); - } - - int - start_profiling(int, const char*, const char*, uint32_t) override - { - throw ishim::not_supported_error(__func__); - } - - uint64_t - read_profiling(int) override - { - throw ishim::not_supported_error(__func__); - } - - void - stop_profiling(int) override - { - throw ishim::not_supported_error(__func__); - } - - void - load_axlf_meta(const axlf*) override - { - throw ishim::not_supported_error(__func__); - } -#endif }; } // xrt_core diff --git a/src/runtime_src/core/common/shim/graph_handle.h b/src/runtime_src/core/common/shim/graph_handle.h index 1c7a921b761..88f64b9b0fc 100755 --- a/src/runtime_src/core/common/shim/graph_handle.h +++ b/src/runtime_src/core/common/shim/graph_handle.h @@ -1,5 +1,7 @@ -#ifndef XRT_CORE_GRAPH_HANDLE_H -#define XRT_CORE_GRAPH_HANDLE_H +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + +#pragma once namespace xrt_core { class graph_handle @@ -39,4 +41,3 @@ class graph_handle }; } // xrt_core -#endif diff --git a/src/runtime_src/core/edge/user/aie/aie.h b/src/runtime_src/core/edge/user/aie/aie.h index 34771cc41d2..f9fb65e4a6e 100755 --- a/src/runtime_src/core/edge/user/aie/aie.h +++ b/src/runtime_src/core/edge/user/aie/aie.h @@ -30,10 +30,12 @@ #include "common_layer/adf_api_config.h" #include "common_layer/adf_runtime_api.h" #include "common_layer/adf_profiling_api.h" + +#ifdef XRT_ENABLE_AIE extern "C" { #include } - +#endif //#define XAIEGBL_NOC_DMASTA_STARTQ_MAX 4 #define XAIEDMA_SHIM_MAX_NUM_CHANNELS 4 #define XAIEDMA_SHIM_TXFER_LEN32_MASK 3 diff --git a/src/runtime_src/core/edge/user/aie/aied.cpp b/src/runtime_src/core/edge/user/aie/aied.cpp index a83fb51b3c6..9ad1d2a0269 100644 --- a/src/runtime_src/core/edge/user/aie/aied.cpp +++ b/src/runtime_src/core/edge/user/aie/aied.cpp @@ -98,13 +98,13 @@ aied::poll_aie(void* arg) } void -aied::register_graph(const graph_instance *graph) +aied::register_graph(const graph_object *graph) { m_graphs.push_back(graph); } void -aied::deregister_graph(const graph_instance *graph) +aied::deregister_graph(const graph_object *graph) { m_graphs.erase(std::remove(m_graphs.begin(), m_graphs.end(), graph), m_graphs.end()); } diff --git a/src/runtime_src/core/edge/user/aie/aied.h b/src/runtime_src/core/edge/user/aie/aied.h index 4c8cbc7cb61..efd2a73c6f1 100644 --- a/src/runtime_src/core/edge/user/aie/aied.h +++ b/src/runtime_src/core/edge/user/aie/aied.h @@ -15,8 +15,7 @@ * under the License. */ -#ifndef AIE_D_H -#define AIE_D_H +#pragma once #include #include @@ -24,7 +23,7 @@ #include #include #include "core/common/device.h" -#include "core/edge/user/aie/graph.h" +#include "core/edge/user/graph_object.h" /* * It receives commands from zocl and dispatches back the output. @@ -37,16 +36,14 @@ class aied public: aied(xrt_core::device* device); ~aied(); - void register_graph(const graph_instance *graph); - void deregister_graph(const graph_instance *graph); + void register_graph(const graph_object *graph); + void deregister_graph(const graph_object *graph); private: bool done; static void* poll_aie(void *arg); xrt_core::device *m_device; - std::vector m_graphs; + std::vector m_graphs; pthread_t ptid; }; } // end namespace - -#endif diff --git a/src/runtime_src/core/edge/user/aie/common_layer/adf_runtime_api.cpp b/src/runtime_src/core/edge/user/aie/common_layer/adf_runtime_api.cpp index 2c2fbb2f9af..94dedea15fa 100755 --- a/src/runtime_src/core/edge/user/aie/common_layer/adf_runtime_api.cpp +++ b/src/runtime_src/core/edge/user/aie/common_layer/adf_runtime_api.cpp @@ -21,6 +21,7 @@ #include #include +#ifdef XRT_ENABLE_AIE extern "C" { #include "xaiengine.h" @@ -931,3 +932,4 @@ err_code lock_api::releaseLock(int tileType, uint8_t column, uint8_t row, unsign } } +#endif \ No newline at end of file diff --git a/src/runtime_src/core/edge/user/aie/common_layer/adf_runtime_api.h b/src/runtime_src/core/edge/user/aie/common_layer/adf_runtime_api.h index b684202420e..707a05d727e 100755 --- a/src/runtime_src/core/edge/user/aie/common_layer/adf_runtime_api.h +++ b/src/runtime_src/core/edge/user/aie/common_layer/adf_runtime_api.h @@ -23,6 +23,7 @@ #include #include +#ifdef XRT_ENABLE_AIE extern "C" { #include "xaiengine/xaiegbl.h" @@ -103,3 +104,4 @@ err_code checkRTPConfigForUpdate(const rtp_config* pRTPConfig, const graph_confi err_code checkRTPConfigForRead(const rtp_config* pRTPConfig, const graph_config* pGraphConfig, size_t numBytes); } +#endif diff --git a/src/runtime_src/core/edge/user/aie/graph.cpp b/src/runtime_src/core/edge/user/aie/graph.cpp index ec9869500f3..846c33dc81c 100755 --- a/src/runtime_src/core/edge/user/aie/graph.cpp +++ b/src/runtime_src/core/edge/user/aie/graph.cpp @@ -16,15 +16,12 @@ * under the License. */ -#include "graph.h" -#ifndef __AIESIM__ #include "core/edge/user/shim.h" #include "core/common/message.h" #ifndef __HWEM__ #include "core/edge/user/plugin/xdp/aie_trace.h" #include "core/edge/user/plugin/xdp/aie_profile.h" #endif -#endif #include "core/common/error.h" #include @@ -38,342 +35,7 @@ extern "C" #include } -#ifdef __AIESIM__ -zynqaie::Aie* getAieArray() -{ - static zynqaie::Aie s_aie(xrt_core::get_userpf_device(0)); - return &s_aie; -} -#endif - -namespace zynqaie { - -graph_instance:: -graph_instance(std::shared_ptr dev, std::string graph_name, - xrt::graph::access_mode am, const zynqaie::hwctx_object* hwctx, const xrt_core::uuid uuid) - : device{std::move(dev)}, name{std::move(graph_name)}, m_hwctxHandle{hwctx} -{ - auto xclbin_uuid = m_hwctxHandle ? m_hwctxHandle->get_xclbin_uuid() : uuid; -#ifndef __AIESIM__ - auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); - - if (!drv->isAieRegistered()) - throw xrt_core::error(-EINVAL, "No AIE presented"); - aieArray = drv->getAieArray(); -#else - aieArray = getAieArray(); -#endif - -#ifndef __AIESIM__ - id = xrt_core::edge::aie::get_graph_id(device.get(), name, m_hwctxHandle); - if (id == xrt_core::edge::aie::NON_EXIST_ID) - throw xrt_core::error(-EINVAL, "Can not get id for Graph '" + name + "'"); - - int ret = drv->openGraphContext(xclbin_uuid.get(), id, am); - if (ret) - throw xrt_core::error(ret, "Can not open Graph context"); -#endif - access_mode = am; - - /* Initialize graph tile metadata */ - graph_config = xrt_core::edge::aie::get_graph(device.get(), name, m_hwctxHandle); - - /* Initialize graph rtp metadata */ - rtps = xrt_core::edge::aie::get_rtp(device.get(), graph_config.id, m_hwctxHandle); - - pAIEConfigAPI = std::make_shared(&graph_config); - pAIEConfigAPI->configure(); - - state = graph_state::reset; -#ifndef __AIESIM__ - drv->getAied()->register_graph(this); -#endif -} - -graph_instance:: -~graph_instance() -{ -#ifndef __AIESIM__ - auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); - if (!drv || !drv->getAied()) { - std::stringstream warnMsg; - warnMsg << "There is no active device open. Unable to close Graph `" << name << "`"; - xrt_core::message::send(xrt_core::message::severity_level::warning, "XRT", warnMsg.str()); - return; - } - drv->closeGraphContext(id); - drv->getAied()->deregister_graph(this); -#endif -} - -std::string -graph_instance:: -getname() const -{ - return name; -} - -unsigned short -graph_instance:: -getstatus() const -{ - return static_cast(state); -} - -void -graph_instance:: -reset() -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not reset graph"); - - for (int i = 0; i < graph_config.coreColumns.size(); i++) { - XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[i], graph_config.coreRows[i] + adf::config_manager::s_num_reserved_rows + 1); - XAie_CoreDisable(aieArray->getDevInst(), coreTile); - } - - state = graph_state::reset; -} - -uint64_t -graph_instance:: -get_timestamp() -{ - /* TODO just use the first tile to get the timestamp? */ - XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[0], graph_config.coreRows[0] + adf::config_manager::s_num_reserved_rows + 1); - - uint64_t timeStamp; - AieRC rc = XAie_ReadTimer(aieArray->getDevInst(), coreTile, XAIE_CORE_MOD, &timeStamp); - if (rc != XAIE_OK) - throw xrt_core::error(-EINVAL, "Fail to read timestamp for Graph '" + name); - - return timeStamp; -} - -void -graph_instance:: -run() -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not run graph"); - - if (state != graph_state::stop && state != graph_state::reset) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is already running or has ended"); - - pAIEConfigAPI->run(); - - state = graph_state::running; -} - -void -graph_instance:: -run(int iterations) -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not run graph"); - - if (state != graph_state::stop && state != graph_state::reset) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is already running or has ended"); - - pAIEConfigAPI->run(iterations); - - state = graph_state::running; -} - -void -graph_instance:: -wait_done(int timeout_ms) -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not wait on graph"); - - if (state == graph_state::stop) - return; - - if (state != graph_state::running) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running, cannot wait"); - - auto begin = std::chrono::high_resolution_clock::now(); - - /* - * We are using busy waiting here. Until every tile in the graph - * is done, we keep polling each tile. - */ - while (1) { - uint8_t done; - for (int i = 0; i < graph_config.coreColumns.size(); i++){ - /* Skip multi-rate core */ - if (graph_config.triggered[i]) { - done = 1; - continue; - } - - XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[i], graph_config.coreRows[i] + adf::config_manager::s_num_reserved_rows + 1); - XAie_CoreReadDoneBit(aieArray->getDevInst(), coreTile, &done); - if (!done) - break; - } - - if (done) { - state = graph_state::stop; - for (int i = 0; i < graph_config.coreColumns.size(); i++){ - if (graph_config.triggered[i]) - continue; - - XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[i], graph_config.coreRows[i] + adf::config_manager::s_num_reserved_rows + 1); - XAie_CoreDisable(aieArray->getDevInst(), coreTile); - } - return; - } - - auto current = std::chrono::high_resolution_clock::now(); - auto dur = current - begin; - auto ms = std::chrono::duration_cast(dur).count(); - if (timeout_ms >= 0 && timeout_ms < ms) - throw xrt_core::error(-ETIME, "Wait graph '" + name + "' timeout."); - } -} - -void -graph_instance:: -wait() -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not wait on graph"); - - if (state == graph_state::stop) - return; - - if (state != graph_state::running) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running, cannot wait"); - - pAIEConfigAPI->wait(); - - state = graph_state::stop; -} - -void -graph_instance:: -wait(uint64_t cycle) -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not wait on graph"); - - if (state == graph_state::suspend) - return; - - if (state != graph_state::running) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running, cannot wait"); - - pAIEConfigAPI->wait(cycle); - - state = graph_state::suspend; -} - -void -graph_instance:: -suspend() -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not suspend graph"); - - if (state != graph_state::running) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running, cannot suspend"); - - for (int i = 0; i < graph_config.coreColumns.size(); i++) { - XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[i], graph_config.coreRows[i] + adf::config_manager::s_num_reserved_rows + 1); - XAie_CoreDisable(aieArray->getDevInst(), coreTile); - } - - state = graph_state::suspend; -} - -void -graph_instance:: -resume() -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not resume on graph"); - - if (state != graph_state::suspend) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not suspended (wait(cycle)), cannot resume"); - - pAIEConfigAPI->resume(); - - state = graph_state::running; -} - -void -graph_instance:: -end() -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not end graph"); - - if (state != graph_state::running && state != graph_state::stop) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running or stop, cannot end"); - - pAIEConfigAPI->end(); - - state = graph_state::end; -} - -void -graph_instance:: -end(uint64_t cycle) -{ - if (access_mode == xrt::graph::access_mode::shared) - throw xrt_core::error(-EPERM, "Shared context can not end graph"); - - if (state != graph_state::running && state != graph_state::suspend) - throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running or suspended, cannot end(cycle_timeout)"); - - pAIEConfigAPI->end(cycle); - - state = graph_state::end; -} - - -void -graph_instance:: -update_rtp(const std::string& port, const char* buffer, size_t size) -{ - auto it = rtps.find(port); - if (it == rtps.end()) - throw xrt_core::error(-EINVAL, "Can't update graph '" + name + "': RTP port '" + port + "' not found"); - auto& rtp = it->second; - - if (access_mode == xrt::graph::access_mode::shared && !rtp.isAsync) - throw xrt_core::error(-EPERM, "Shared context can not update sync RTP"); - - if (rtp.isPL) - throw xrt_core::error(-EINVAL, "Can't update graph '" + name + "': RTP port '" + port + "' is not AIE RTP"); - - pAIEConfigAPI->update(&rtp, (const void*)buffer, size); -} - -void -graph_instance:: -read_rtp(const std::string& port, char* buffer, size_t size) -{ - auto it = rtps.find(port); - if (it == rtps.end()) - throw xrt_core::error(-EINVAL, "Can't read graph '" + name + "': RTP port '" + port + "' not found"); - auto& rtp = it->second; - - if (rtp.isPL) - throw xrt_core::error(-EINVAL, "Can't read graph '" + name + "': RTP port '" + port + "' is not AIE RTP"); - - pAIEConfigAPI->read(&rtp, (void*)buffer, size); -} - -} // zynqaie - -using graph_instance = zynqaie::graph_instance; - -namespace api { - -using graph_instance = zynqaie::graph_instance; +typedef xclDeviceHandle xrtDeviceHandle; static inline std::string value_or_empty(const char* s) @@ -381,10 +43,11 @@ std::string value_or_empty(const char* s) return s == nullptr ? "" : s; } +namespace api { + void xclAIEOpenContext(xclDeviceHandle handle, xrt::aie::access_mode am) { -#ifndef __AIESIM__ auto device = xrt_core::get_userpf_device(handle); auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); @@ -393,22 +56,17 @@ xclAIEOpenContext(xclDeviceHandle handle, xrt::aie::access_mode am) throw xrt_core::error(ret, "Fail to open AIE context"); drv->setAIEAccessMode(am); -#endif } void xclSyncBOAIE(xclDeviceHandle handle, xrt::bo& bo, const char *gmioName, enum xclBOSyncDirection dir, size_t size, size_t offset) { -#ifndef __AIESIM__ auto device = xrt_core::get_userpf_device(handle); auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); if (!drv->isAieRegistered()) throw xrt_core::error(-EINVAL, "No AIE presented"); auto aieArray = drv->getAieArray(); -#else - auto aieArray = getAieArray(); -#endif if (!aieArray->is_context_set()) { aieArray->open_context(device.get(), xrt::aie::access_mode::primary); @@ -425,16 +83,12 @@ xclSyncBOAIE(xclDeviceHandle handle, xrt::bo& bo, const char *gmioName, enum xcl void xclSyncBOAIENB(xclDeviceHandle handle, xrt::bo& bo, const char *gmioName, enum xclBOSyncDirection dir, size_t size, size_t offset) { -#ifndef __AIESIM__ auto device = xrt_core::get_userpf_device(handle); auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); if (!drv->isAieRegistered()) throw xrt_core::error(-EINVAL, "No AIE presented"); auto aieArray = drv->getAieArray(); -#else - auto aieArray = getAieArray(); -#endif if (!aieArray->is_context_set()) { aieArray->open_context(device.get(), xrt::aie::access_mode::primary); @@ -451,16 +105,12 @@ xclSyncBOAIENB(xclDeviceHandle handle, xrt::bo& bo, const char *gmioName, enum x void xclGMIOWait(xclDeviceHandle handle, const char *gmioName) { -#ifndef __AIESIM__ auto device = xrt_core::get_userpf_device(handle); auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); if (!drv->isAieRegistered()) throw xrt_core::error(-EINVAL, "No AIE presented"); auto aieArray = drv->getAieArray(); -#else - auto aieArray = getAieArray(); -#endif if (!aieArray->is_context_set()) { aieArray->open_context(device.get(), xrt::aie::access_mode::primary); @@ -472,7 +122,6 @@ xclGMIOWait(xclDeviceHandle handle, const char *gmioName) void xclResetAieArray(xclDeviceHandle handle) { -#ifndef __AIESIM__ auto device = xrt_core::get_userpf_device(handle); auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); @@ -483,17 +132,12 @@ xclResetAieArray(xclDeviceHandle handle) if (!aieArray->is_context_set()) { aieArray->open_context(device.get(), xrt::aie::access_mode::primary); } - aieArray->reset(device.get()); -#else - auto aieArray = getAieArray(); -#endif } int xclStartProfiling(xclDeviceHandle handle, int option, const char* port1Name, const char* port2Name, uint32_t value) { -#ifndef __AIESIM__ auto device = xrt_core::get_userpf_device(handle); auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); @@ -501,9 +145,6 @@ xclStartProfiling(xclDeviceHandle handle, int option, const char* port1Name, con throw xrt_core::error(-EINVAL, "No AIE presented"); auto aieArray = drv->getAieArray(); -#else - auto aieArray = getAieArray(); -#endif if (!aieArray->is_context_set()) { aieArray->open_context(device.get(), xrt::aie::access_mode::primary); @@ -515,7 +156,6 @@ xclStartProfiling(xclDeviceHandle handle, int option, const char* port1Name, con uint64_t xclReadProfiling(xclDeviceHandle handle, int phdl) { -#ifndef __AIESIM__ auto device = xrt_core::get_userpf_device(handle); auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); @@ -523,9 +163,6 @@ xclReadProfiling(xclDeviceHandle handle, int phdl) throw xrt_core::error(-EINVAL, "No AIE presented"); auto aieArray = drv->getAieArray(); -#else - auto aieArray = getAieArray(); -#endif if (!aieArray->is_context_set()) { aieArray->open_context(device.get(), xrt::aie::access_mode::primary); @@ -537,7 +174,6 @@ xclReadProfiling(xclDeviceHandle handle, int phdl) void xclStopProfiling(xclDeviceHandle handle, int phdl) { -#ifndef __AIESIM__ auto device = xrt_core::get_userpf_device(handle); auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); @@ -545,9 +181,6 @@ xclStopProfiling(xclDeviceHandle handle, int phdl) throw xrt_core::error(-EINVAL, "No AIE presented"); auto aieArray = drv->getAieArray(); -#else - auto aieArray = getAieArray(); -#endif if (!aieArray->is_context_set()) { aieArray->open_context(device.get(), xrt::aie::access_mode::primary); diff --git a/src/runtime_src/core/edge/user/device_linux.cpp b/src/runtime_src/core/edge/user/device_linux.cpp index 26182c0422d..31e1dddd75f 100644 --- a/src/runtime_src/core/edge/user/device_linux.cpp +++ b/src/runtime_src/core/edge/user/device_linux.cpp @@ -24,18 +24,17 @@ #include #include -#ifdef XRT_ENABLE_AIE #include "core/edge/include/zynq_ioctl.h" #include "aie/aiereg.h" #include +#ifdef XRT_ENABLE_AIE extern "C" { #include } -#ifndef __AIESIM__ #include "xaiengine/xlnx-ai-engine.h" -#include -#endif #endif +#include + namespace { @@ -1136,8 +1135,12 @@ std::unique_ptr device_linux:: open_graph_handle(const xrt::uuid& xclbin_id, const char* name, xrt::graph::access_mode am) { +#ifdef XRT_ENABLE_AIE return std::make_unique( static_cast(get_device_handle()), xclbin_id, name, am); +#else + return nullptr; +#endif } std::unique_ptr @@ -1171,6 +1174,78 @@ get_sysfs_path(const std::string& subdev, const std::string& entry) return path_buf; } +#ifdef XRT_ENABLE_AIE + +void +device_linux:: +open_aie_context(xrt::aie::access_mode am) +{ + if (auto ret = xclAIEOpenContext(get_device_handle(), am)) + throw error(ret, "fail to open aie context"); +} + +void +device_linux:: +sync_aie_bo(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) +{ + if (auto ret = xclSyncBOAIE(get_device_handle(), bo, gmioName, dir, size, offset)) + throw system_error(ret, "fail to sync aie bo"); +} + +void +device_linux:: +reset_aie() +{ + if (auto ret = xclResetAIEArray(get_device_handle())) + throw system_error(ret, "fail to reset aie"); +} + +void +device_linux:: +sync_aie_bo_nb(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) +{ + if (auto ret = xclSyncBOAIENB(get_device_handle(), bo, gmioName, dir, size, offset)) + throw system_error(ret, "fail to sync aie non-blocking bo"); +} + +void +device_linux:: +wait_gmio(const char *gmioName) +{ + if (auto ret = xclGMIOWait(get_device_handle(), gmioName)) + throw system_error(ret, "fail to wait gmio"); +} + +int +device_linux:: +start_profiling(int option, const char* port1Name, const char* port2Name, uint32_t value) +{ + return xclStartProfiling(get_device_handle(), option, port1Name, port2Name, value); +} + +uint64_t +device_linux:: +read_profiling(int phdl) +{ + return xclReadProfiling(get_device_handle(), phdl); +} + +void +device_linux:: +stop_profiling(int phdl) +{ + if (auto ret = xclStopProfiling(get_device_handle(), phdl)) + throw system_error(ret, "failed to stop profiling"); +} + +void +device_linux:: +load_axlf_meta(const axlf* buffer) +{ + if (auto ret = xclLoadXclBinMeta(get_device_handle(), buffer)) + throw system_error(ret, "failed to load xclbin"); +} +#endif //////////////////////////////////////////////////////////////// // Custom IP interrupt handling //////////////////////////////////////////////////////////////// diff --git a/src/runtime_src/core/edge/user/device_linux.h b/src/runtime_src/core/edge/user/device_linux.h index 3f743f27d81..2d47bcf9b35 100644 --- a/src/runtime_src/core/edge/user/device_linux.h +++ b/src/runtime_src/core/edge/user/device_linux.h @@ -45,6 +45,34 @@ class device_linux : public shim std::string get_sysfs_path(const std::string& subdev, const std::string& entry) override; +#ifdef XRT_ENABLE_AIE + void + open_aie_context(xrt::aie::access_mode am) override; + + void + sync_aie_bo(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) override; + + void + reset_aie() override; + + void + sync_aie_bo_nb(xrt::bo& bo, const char *gmioName, xclBOSyncDirection dir, size_t size, size_t offset) override; + + void + wait_gmio(const char *gmioName) override; + + int + start_profiling(int option, const char* port1Name, const char* port2Name, uint32_t value) override; + + uint64_t + read_profiling(int phdl) override; + + void + stop_profiling(int phdl) override; + + void + load_axlf_meta(const axlf* buffer) override; +#endif //////////////////////////////////////////////////////////////// // Custom ip interrupt handling // Redefined from xrt_core::ishim diff --git a/src/runtime_src/core/edge/user/graph_object.cpp b/src/runtime_src/core/edge/user/graph_object.cpp index 26cb056b0f7..6b44ed18391 100644 --- a/src/runtime_src/core/edge/user/graph_object.cpp +++ b/src/runtime_src/core/edge/user/graph_object.cpp @@ -1,168 +1,305 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + +#ifdef XRT_ENABLE_AIE #include "graph_object.h" -#include "core/edge/user/aie/graph.h" #include "core/common/system.h" #include +#include "shim.h" namespace zynqaie { - graph_object::graph_object(ZYNQ::shim* shim, const xrt::uuid& uuid , const char* name, + graph_object::graph_object(ZYNQ::shim* shim, const xrt::uuid& uuid , const char* gname, xrt::graph::access_mode am, const zynqaie::hwctx_object* hwctx) - : m_shim{shim} + : m_shim{shim}, + name{gname}, + access_mode{am} + { + auto device{xrt_core::get_userpf_device(m_shim)}; + auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); + + if (!drv->isAieRegistered()) + throw xrt_core::error(-EINVAL, "No AIE presented"); + aieArray = drv->getAieArray(); + id = xrt_core::edge::aie::get_graph_id(device.get(), name, hwctx); + if (id == xrt_core::edge::aie::NON_EXIST_ID) + throw xrt_core::error(-EINVAL, "Can not get id for Graph '" + name + "'"); + + int ret = drv->openGraphContext(uuid.get(), id, am); + if (ret) + throw xrt_core::error(ret, "Can not open Graph context"); + + /* Initialize graph tile metadata */ + graph_config = xrt_core::edge::aie::get_graph(device.get(), name, hwctx); + + /* Initialize graph rtp metadata */ + rtps = xrt_core::edge::aie::get_rtp(device.get(), graph_config.id, hwctx); + pAIEConfigAPI = std::make_shared(&graph_config); + pAIEConfigAPI->configure(); + state = graph_state::reset; + drv->getAied()->register_graph(this); + } + + graph_object::~graph_object() { auto device{xrt_core::get_userpf_device(m_shim)}; - m_graphInstance = std::make_unique(device, name, am, hwctx,uuid); + auto drv = ZYNQ::shim::handleCheck(device->get_device_handle()); + if (!drv || !drv->getAied()) + { + std::stringstream warnMsg; + warnMsg << "There is no active device open. Unable to close Graph `" << name << "`"; + xrt_core::message::send(xrt_core::message::severity_level::warning, "XRT", warnMsg.str()); + return; + } + drv->closeGraphContext(id); + drv->getAied()->deregister_graph(this); + } + + std::string + graph_object::getname() const + { + return name; + } + + unsigned short + graph_object::getstatus() const + { + return static_cast(state); } void graph_object::reset_graph() { - try { - m_graphInstance->reset(); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to reset graph: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to reset graph")); - } + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not reset graph"); + + for (int i = 0; i < graph_config.coreColumns.size(); i++) + { + XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[i], graph_config.coreRows[i] + adf::config_manager::s_num_reserved_rows + 1); + XAie_CoreDisable(aieArray->getDevInst(), coreTile); + } + + state = graph_state::reset; } uint64_t graph_object::get_timestamp() { - try { - m_graphInstance->get_timestamp(); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to get graph timestamp: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to get graph timestamp")); - } - return -1; + /* TODO just use the first tile to get the timestamp? */ + XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[0], graph_config.coreRows[0] + adf::config_manager::s_num_reserved_rows + 1); + + uint64_t timeStamp; + AieRC rc = XAie_ReadTimer(aieArray->getDevInst(), coreTile, XAIE_CORE_MOD, &timeStamp); + if (rc != XAIE_OK) + throw xrt_core::error(-EINVAL, "Fail to read timestamp for Graph '" + name); + + return timeStamp; } void graph_object::run_graph(int iterations) { - try { if (iterations == 0) - m_graphInstance->run(); + { + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not run graph"); + + if (state != graph_state::stop && state != graph_state::reset) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is already running or has ended"); + + pAIEConfigAPI->run(); + state = graph_state::running; + } else - m_graphInstance->run(iterations); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to run graph: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to run graph")); - } + { + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not run graph"); + + if (state != graph_state::stop && state != graph_state::reset) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is already running or has ended"); + + pAIEConfigAPI->run(iterations); + state = graph_state::running; + } } int - graph_object::wait_graph_done(int timeout) + graph_object::wait_graph_done(int timeout_ms) { - try { - m_graphInstance->wait_done(timeout); - return 0; - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to wait graph done: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to wait graph done")); - } - return -1; + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not wait on graph"); + + if (state == graph_state::stop) + return 0; + + if (state != graph_state::running) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running, cannot wait"); + + auto begin = std::chrono::high_resolution_clock::now(); + + /* + * We are using busy waiting here. Until every tile in the graph + * is done, we keep polling each tile. + */ + while (1) + { + uint8_t done; + for (int i = 0; i < graph_config.coreColumns.size(); i++) + { + /* Skip multi-rate core */ + if (graph_config.triggered[i]) + { + done = 1; + continue; + } + + XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[i], graph_config.coreRows[i] + adf::config_manager::s_num_reserved_rows + 1); + XAie_CoreReadDoneBit(aieArray->getDevInst(), coreTile, &done); + if (!done) + break; + } + + if (done) + { + state = graph_state::stop; + for (int i = 0; i < graph_config.coreColumns.size(); i++) + { + if (graph_config.triggered[i]) + continue; + + XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[i], graph_config.coreRows[i] + adf::config_manager::s_num_reserved_rows + 1); + XAie_CoreDisable(aieArray->getDevInst(), coreTile); + } + return 0; + } + + auto current = std::chrono::high_resolution_clock::now(); + auto dur = current - begin; + auto ms = std::chrono::duration_cast(dur).count(); + if (timeout_ms >= 0 && timeout_ms < ms) + throw xrt_core::error(-ETIME, "Wait graph '" + name + "' timeout."); + } + return -1; } void graph_object::wait_graph(uint64_t cycle) { - try { if (cycle == 0) - m_graphInstance->wait(); + { + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not wait on graph"); + + if (state == graph_state::stop) + return; + + if (state != graph_state::running) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running, cannot wait"); + + pAIEConfigAPI->wait(); + state = graph_state::stop; + } else - m_graphInstance->wait(cycle); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to wait graph: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to wait graph")); - } + { + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not wait on graph"); + + if (state == graph_state::suspend) + return; + + if (state != graph_state::running) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running, cannot wait"); + + pAIEConfigAPI->wait(cycle); + state = graph_state::suspend; + } } void graph_object::suspend_graph() { - try { - m_graphInstance->suspend(); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to suspend graph: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to suspend graph")); - } + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not suspend graph"); + + if (state != graph_state::running) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running, cannot suspend"); + + for (int i = 0; i < graph_config.coreColumns.size(); i++) + { + XAie_LocType coreTile = XAie_TileLoc(graph_config.coreColumns[i], graph_config.coreRows[i] + adf::config_manager::s_num_reserved_rows + 1); + XAie_CoreDisable(aieArray->getDevInst(), coreTile); + } + state = graph_state::suspend; } void graph_object::resume_graph() { - try { - m_graphInstance->resume(); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to resume graph: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to resume graph")); - } + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not resume on graph"); + + if (state != graph_state::suspend) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not suspended (wait(cycle)), cannot resume"); + + pAIEConfigAPI->resume(); + state = graph_state::running; } void graph_object::end_graph(uint64_t cycle) { - try { if (cycle == 0) - m_graphInstance->end(); + { + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not end graph"); + + if (state != graph_state::running && state != graph_state::stop) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running or stop, cannot end"); + + pAIEConfigAPI->end(); + state = graph_state::end; + } else - m_graphInstance->end(cycle); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to end graph: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to end graph")); - } + { + if (access_mode == xrt::graph::access_mode::shared) + throw xrt_core::error(-EPERM, "Shared context can not end graph"); + + if (state != graph_state::running && state != graph_state::suspend) + throw xrt_core::error(-EINVAL, "Graph '" + name + "' is not running or suspended, cannot end(cycle_timeout)"); + + pAIEConfigAPI->end(cycle); + state = graph_state::end; + } } void graph_object::update_graph_rtp(const char* port, const char* buffer, size_t size) { - try { - m_graphInstance->update_rtp(port, buffer, size); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to update graph rtp: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to update graph rtp")); - } + auto it = rtps.find(port); + if (it == rtps.end()) + throw xrt_core::error(-EINVAL, "Can't update graph '" + name + "': RTP port '" + port + "' not found"); + auto& rtp = it->second; + + if (access_mode == xrt::graph::access_mode::shared && !rtp.isAsync) + throw xrt_core::error(-EPERM, "Shared context can not update sync RTP"); + + if (rtp.isPL) + throw xrt_core::error(-EINVAL, "Can't update graph '" + name + "': RTP port '" + port + "' is not AIE RTP"); + + pAIEConfigAPI->update(&rtp, (const void*)buffer, size); } void graph_object::read_graph_rtp(const char* port, char* buffer, size_t size) { - try { - m_graphInstance->read_rtp(port, buffer, size); - } - catch (const std::exception& e) { - xrt_core::send_exception_message(std::string("fail to read graph rtp: ") + e.what()); - } - catch (...) { - xrt_core::send_exception_message(std::string("fail to read graph rtp")); - } + auto it = rtps.find(port); + if (it == rtps.end()) + throw xrt_core::error(-EINVAL, "Can't read graph '" + name + "': RTP port '" + port + "' not found"); + auto& rtp = it->second; + + if (rtp.isPL) + throw xrt_core::error(-EINVAL, "Can't read graph '" + name + "': RTP port '" + port + "' is not AIE RTP"); + + pAIEConfigAPI->read(&rtp, (void*)buffer, size); } } +#endif \ No newline at end of file diff --git a/src/runtime_src/core/edge/user/graph_object.h b/src/runtime_src/core/edge/user/graph_object.h index 9f523c10ead..ca4f1e65872 100644 --- a/src/runtime_src/core/edge/user/graph_object.h +++ b/src/runtime_src/core/edge/user/graph_object.h @@ -1,15 +1,17 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. -#ifndef _ZYNQ_GRAPH_OBJECT_H_ -#define _ZYNQ_GRAPH_OBJECT_H_ +#pragma once + +#ifdef XRT_ENABLE_AIE +#include "core/edge/user/aie/aie.h" +#include "core/edge/user/aie/common_layer/adf_api_config.h" #include "core/common/message.h" #include "core/common/shim/shared_handle.h" #include "core/common/shim/graph_handle.h" #include "core/include/xrt/xrt_uuid.h" #include "xrt/xrt_graph.h" - #include namespace ZYNQ { @@ -17,16 +19,51 @@ namespace ZYNQ { } namespace zynqaie { // Shim handle for graph object - class graph_instance; class hwctx_object; class graph_object : public xrt_core::graph_handle { ZYNQ::shim* m_shim; - std::unique_ptr m_graphInstance; + enum class graph_state : unsigned short + { + stop = 0, + reset = 1, + running = 2, + suspend = 3, + end = 4, + }; + int id; + graph_state state; + std::string name; + xrt::graph::access_mode access_mode; + + /** + * This is the pointer to the AIE array where the AIE part of + * the graph resides. The Aie is an obect that holds the whole + * AIE resources, configurations etc. + */ + Aie* aieArray; + + /** + * This is the collections of tiles that this graph uses. + * A tile is represented by a pair of number + * It represents the tile position in the AIE array. + */ + adf::graph_config graph_config; + std::shared_ptr pAIEConfigAPI; + /* This is the collections of rtps that are used. */ + std::unordered_map rtps; public: graph_object(ZYNQ::shim* shim, const xrt::uuid& uuid , const char* name, xrt::graph::access_mode am, const zynqaie::hwctx_object* hwctx = nullptr); + + ~graph_object(); + + std::string + getname() const; + + unsigned short + getstatus() const; void reset_graph() override; diff --git a/src/runtime_src/core/edge/user/hwctx_object.cpp b/src/runtime_src/core/edge/user/hwctx_object.cpp index aec4e8da1ea..5743dad561d 100644 --- a/src/runtime_src/core/edge/user/hwctx_object.cpp +++ b/src/runtime_src/core/edge/user/hwctx_object.cpp @@ -52,6 +52,10 @@ namespace zynqaie { std::unique_ptr hwctx_object::open_graph_handle(const char* name, xrt::graph::access_mode am) { +#ifdef XRT_ENABLE_AIE return std::make_unique(m_shim, m_uuid, name, am, this); +#else + return nullptr; +#endif } }