[PATCH 1/3] ml/cnxk: update driver to use TVM C runtime
Srikanth Yalavarthi
syalavarthi at marvell.com
Tue Jun 9 06:42:00 CEST 2026
Updated MVTVM layer of the driver to call TVM C runtime
API functions, instead on the TVMDP wrapper library APIs.
Drop all dependencies on TVMDP wrapper library.
Signed-off-by: Srikanth Yalavarthi <syalavarthi at marvell.com>
---
doc/guides/mldevs/cnxk.rst | 35 +-
drivers/ml/cnxk/cnxk_ml_io.h | 20 +-
drivers/ml/cnxk/cnxk_ml_ops.c | 12 +-
drivers/ml/cnxk/meson.build | 14 +-
drivers/ml/cnxk/mvtvm_ml_dev.h | 3 -
drivers/ml/cnxk/mvtvm_ml_model.c | 638 ++++++++++++++++++++++++++++---
drivers/ml/cnxk/mvtvm_ml_model.h | 81 +++-
drivers/ml/cnxk/mvtvm_ml_ops.c | 440 ++++++++++++++-------
drivers/ml/cnxk/mvtvm_ml_ops.h | 5 +-
drivers/ml/cnxk/mvtvm_ml_stubs.c | 17 -
drivers/ml/cnxk/mvtvm_ml_stubs.h | 2 -
11 files changed, 985 insertions(+), 282 deletions(-)
diff --git a/doc/guides/mldevs/cnxk.rst b/doc/guides/mldevs/cnxk.rst
index fc1bcd9cdb4..17e58d81c0b 100644
--- a/doc/guides/mldevs/cnxk.rst
+++ b/doc/guides/mldevs/cnxk.rst
@@ -111,13 +111,13 @@ on CPU cores or hardware accelerators.
.. note::
- DPDK CNXK ML driver requires TVM version 0.10.0
+ DPDK CNXK ML driver requires TVM version legacy-v0.19.post branch.
.. code-block:: console
git clone https://github.com/apache/tvm.git
cd tvm
- git checkout v0.11.0 -b v0.11.0
+ git checkout legacy-v0.19.post -b legacy-v0.19.post
git submodule update --init
cmake -S ./ -B build \
-DCMAKE_INSTALL_PREFIX=<install_prefix> \
@@ -135,37 +135,6 @@ When cross-compiling, more options must be provided to CMake:
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY
-TVMDP
-~~~~~
-
- Marvell's `TVM Dataplane Library <https://github.com/MarvellEmbeddedProcessors/tvmdp>`_
- works as an interface between TVM runtime and DPDK drivers.
- TVMDP library provides a simplified C interface
- for TVM's runtime based on C++.
-
-.. note::
-
- TVMDP library is dependent on TVM, dlpack, jansson and dmlc-core libraries.
-
-.. code-block:: console
-
- git clone https://github.com/MarvellEmbeddedProcessors/tvmdp.git
- cd tvmdp
- git checkout main
- cmake -S ./ -B build \
- -DCMAKE_INSTALL_PREFIX=<install_prefix> \
- -DBUILD_SHARED_LIBS=ON
- make -C build
- make -C build install
-
-When cross-compiling, more options must be provided to CMake:
-
-.. code-block:: console
-
- -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
- -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
- -DCMAKE_FIND_ROOT_PATH=<install_prefix>
-
libarchive
~~~~~~~~~~
diff --git a/drivers/ml/cnxk/cnxk_ml_io.h b/drivers/ml/cnxk/cnxk_ml_io.h
index 83329c237aa..17f5b4619f0 100644
--- a/drivers/ml/cnxk/cnxk_ml_io.h
+++ b/drivers/ml/cnxk/cnxk_ml_io.h
@@ -6,7 +6,7 @@
#define _CNXK_ML_IO_H_
#ifdef RTE_MLDEV_CNXK_ENABLE_MVTVM
-#include <tvmdp.h>
+#include <dlpack/dlpack.h>
#endif
#include <rte_mldev.h>
@@ -16,7 +16,7 @@
/* Maximum number of layers per model */
#ifdef RTE_MLDEV_CNXK_ENABLE_MVTVM
-#define ML_CNXK_MODEL_MAX_LAYERS TVMDP_MODEL_LAYERS_MAX
+#define ML_CNXK_MODEL_MAX_LAYERS 128
#else
#define ML_CNXK_MODEL_MAX_LAYERS 1
#endif
@@ -41,7 +41,7 @@ struct cnxk_ml_io {
/* Number of dimensions in shape */
uint32_t nb_dims;
- /* Shape of input */
+ /* Shape */
uint32_t shape[ML_CNXK_MODEL_MAX_DIMS];
/* Number of elements */
@@ -58,6 +58,20 @@ struct cnxk_ml_io {
/* Zero point */
int64_t zero_point;
+
+#ifdef RTE_MLDEV_CNXK_ENABLE_MVTVM
+ /* Shape - int64_t */
+ int64_t shape_i64[ML_CNXK_MODEL_MAX_DIMS];
+
+ /* Data type */
+ DLDataType datatype;
+
+ /* Model data type */
+ DLDataType model_datatype;
+
+ /* Device */
+ DLDevice device;
+#endif
};
/* Model / Layer IO structure */
diff --git a/drivers/ml/cnxk/cnxk_ml_ops.c b/drivers/ml/cnxk/cnxk_ml_ops.c
index 9958945670a..938982c7556 100644
--- a/drivers/ml/cnxk/cnxk_ml_ops.c
+++ b/drivers/ml/cnxk/cnxk_ml_ops.c
@@ -634,10 +634,6 @@ cnxk_ml_dev_configure(struct rte_ml_dev *dev, const struct rte_ml_dev_config *co
}
}
- ret = mvtvm_ml_dev_configure(cnxk_mldev, conf);
- if (ret != 0)
- goto error;
-
/* Set device capabilities */
if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI)
cnxk_mldev->max_nb_layers =
@@ -705,9 +701,6 @@ cnxk_ml_dev_close(struct rte_ml_dev *dev)
/* Un-initialize xstats */
cnxk_ml_xstats_uninit(cnxk_mldev);
- if (mvtvm_ml_dev_close(cnxk_mldev) != 0)
- plt_err("Failed to close MVTVM ML Device");
-
if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI) {
if (cn10k_ml_dev_close(cnxk_mldev) != 0)
plt_err("Failed to close CN10K ML Device");
@@ -1234,7 +1227,7 @@ cnxk_ml_model_load(struct rte_ml_dev *dev, struct rte_ml_model_params *params, u
model->layer[layer_id].glow.ocm_map.scratch_pages);
#ifdef RTE_MLDEV_CNXK_ENABLE_MVTVM
} else {
- for (layer_id = 0; layer_id < model->mvtvm.metadata.model.nb_layers; layer_id++) {
+ for (layer_id = 0; layer_id < model->nb_layers; layer_id++) {
if (model->layer[layer_id].type == ML_CNXK_LAYER_TYPE_MRVL) {
total_wb_pages = total_wb_pages +
model->layer[layer_id].glow.ocm_map.wb_pages;
@@ -1256,8 +1249,7 @@ cnxk_ml_model_load(struct rte_ml_dev *dev, struct rte_ml_model_params *params, u
model->layer[layer_id].glow.ocm_map.scratch_pages);
#ifdef RTE_MLDEV_CNXK_ENABLE_MVTVM
} else {
- for (layer_id = 0; layer_id < model->mvtvm.metadata.model.nb_layers;
- layer_id++) {
+ for (layer_id = 0; layer_id < model->nb_layers; layer_id++) {
if (model->layer[layer_id].type == ML_CNXK_LAYER_TYPE_MRVL) {
plt_ml_dbg(
"layer_id = %u: wb_pages = %u, scratch_pages = %u",
diff --git a/drivers/ml/cnxk/meson.build b/drivers/ml/cnxk/meson.build
index ef7e21d7476..5f078bd4fd7 100644
--- a/drivers/ml/cnxk/meson.build
+++ b/drivers/ml/cnxk/meson.build
@@ -19,30 +19,24 @@ if not jansson_dep.found()
enable_mvtvm = false
endif
-dlpack_dep = dependency('dlpack', method: 'cmake', required: false, cmake_args: 'CONFIG')
+dlpack_dep = dependency('dlpack', method: 'cmake', required: false)
if not dlpack_dep.found()
message('drivers/ml/cnxk: dlpack not found')
enable_mvtvm = false
endif
-dmlc_dep = dependency('dmlc', method: 'cmake', required: false, cmake_args: 'CONFIG')
+dmlc_dep = dependency('dmlc', method: 'cmake', required: false)
if not dmlc_dep.found()
message('drivers/ml/cnxk: dmlc not found')
enable_mvtvm = false
endif
-tvm_dep = dependency('tvm', method: 'cmake', required: false, cmake_args: 'CONFIG', modules : ['tvm::tvm_runtime'])
+tvm_dep = dependency('tvm', method: 'cmake', required: false, modules : ['tvm::tvm_runtime'])
if not tvm_dep.found()
message('drivers/ml/cnxk: tvm_runtime not found')
enable_mvtvm = false
endif
-tvmdp_dep = dependency('tvmdp', method: 'pkg-config', required: false)
-if not tvmdp_dep.found()
- message('drivers/ml/cnxk: tvmdp not found')
- enable_mvtvm = false
-endif
-
sources = files(
'cn10k_ml_dev.c',
'cn10k_ml_ops.c',
@@ -68,10 +62,10 @@ sources += files(
)
ext_deps += jansson_dep
+ext_deps += libarchive
ext_deps += dlpack_dep
ext_deps += dmlc_dep
ext_deps += tvm_dep
-ext_deps += tvmdp_dep
stdcpp_dep = cc.find_library('stdc++', required: true)
if not cc.links(min_c_code, dependencies: stdcpp_dep)
error('broken dependency, "libstdc++"')
diff --git a/drivers/ml/cnxk/mvtvm_ml_dev.h b/drivers/ml/cnxk/mvtvm_ml_dev.h
index 6922c193372..05e30f094cd 100644
--- a/drivers/ml/cnxk/mvtvm_ml_dev.h
+++ b/drivers/ml/cnxk/mvtvm_ml_dev.h
@@ -19,9 +19,6 @@ extern struct rte_ml_dev_ops cnxk_ml_ops;
/* Maximum number of descriptors per queue-pair */
#define ML_MVTVM_MAX_DESC_PER_QP 1024
-/* Maximum number of inputs / outputs per model */
-#define ML_MVTVM_MAX_INPUT_OUTPUT 32
-
/* Maximum number of segments for IO data */
#define ML_MVTVM_MAX_SEGMENTS 1
diff --git a/drivers/ml/cnxk/mvtvm_ml_model.c b/drivers/ml/cnxk/mvtvm_ml_model.c
index 4c7aa906da0..e1946607629 100644
--- a/drivers/ml/cnxk/mvtvm_ml_model.c
+++ b/drivers/ml/cnxk/mvtvm_ml_model.c
@@ -2,6 +2,12 @@
* Copyright (c) 2023 Marvell.
*/
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include <archive.h>
#include <archive_entry.h>
@@ -23,6 +29,7 @@ enum cnxk_ml_model_type
mvtvm_ml_model_type_get(struct rte_ml_model_params *params)
{
bool object_found[ML_MVTVM_MODEL_OBJECT_MAX] = {false, false, false};
+ enum cnxk_ml_model_type model_type;
struct archive_entry *entry;
struct archive *a;
uint8_t i;
@@ -33,9 +40,10 @@ mvtvm_ml_model_type_get(struct rte_ml_model_params *params)
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
+ model_type = ML_CNXK_MODEL_TYPE_UNKNOWN;
ret = archive_read_open_memory(a, params->addr, params->size);
if (ret != ARCHIVE_OK)
- return ML_CNXK_MODEL_TYPE_UNKNOWN;
+ goto cleanup;
/* Parse buffer for available objects */
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
@@ -51,11 +59,18 @@ mvtvm_ml_model_type_get(struct rte_ml_model_params *params)
for (i = 0; i < ML_MVTVM_MODEL_OBJECT_MAX; i++) {
if (!object_found[i]) {
plt_err("Object %s not found in archive!", mvtvm_object_list[i]);
- return ML_CNXK_MODEL_TYPE_INVALID;
+ model_type = ML_CNXK_MODEL_TYPE_INVALID;
+ goto cleanup;
}
}
- return ML_CNXK_MODEL_TYPE_TVM;
+ model_type = ML_CNXK_MODEL_TYPE_TVM;
+
+cleanup:
+ archive_read_close(a);
+ archive_read_free(a);
+
+ return model_type;
}
int
@@ -67,14 +82,18 @@ mvtvm_ml_model_blob_parse(struct rte_ml_model_params *params, struct mvtvm_ml_mo
uint8_t i;
int ret;
+ memset(object, 0, ML_MVTVM_MODEL_OBJECT_MAX * sizeof(*object));
+
/* Open archive */
a = archive_read_new();
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
ret = archive_read_open_memory(a, params->addr, params->size);
- if (ret != ARCHIVE_OK)
- return archive_errno(a);
+ if (ret != ARCHIVE_OK) {
+ ret = archive_errno(a);
+ goto cleanup;
+ }
/* Read archive */
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
@@ -84,11 +103,16 @@ mvtvm_ml_model_blob_parse(struct rte_ml_model_params *params, struct mvtvm_ml_mo
memcpy(object[i].name, mvtvm_object_list[i], RTE_ML_STR_MAX);
object[i].size = archive_entry_size(entry);
object[i].buffer = rte_malloc(NULL, object[i].size, 0);
+ if (object[i].buffer == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
if (archive_read_data(a, object[i].buffer, object[i].size) !=
object[i].size) {
plt_err("Failed to read object from model archive: %s",
object[i].name);
+ ret = -EINVAL;
goto error;
}
object_found[i] = true;
@@ -101,17 +125,24 @@ mvtvm_ml_model_blob_parse(struct rte_ml_model_params *params, struct mvtvm_ml_mo
for (i = 0; i < ML_MVTVM_MODEL_OBJECT_MAX; i++) {
if (!object_found[i]) {
plt_err("Object %s not found in archive!", mvtvm_object_list[i]);
+ ret = -EINVAL;
goto error;
}
}
- return 0;
+ ret = 0;
+ goto cleanup;
error:
for (i = 0; i < ML_MVTVM_MODEL_OBJECT_MAX; i++) {
- rte_free(object[i].buffer);
+ if (object[i].buffer != NULL)
+ rte_free(object[i].buffer);
}
- return -EINVAL;
+cleanup:
+ archive_read_close(a);
+ archive_read_free(a);
+
+ return ret;
}
int
@@ -119,12 +150,12 @@ mvtvm_ml_model_get_layer_id(struct cnxk_ml_model *model, const char *layer_name,
{
uint16_t i;
- for (i = 0; i < model->mvtvm.metadata.model.nb_layers; i++) {
+ for (i = 0; i < model->nb_layers; i++) {
if (strcmp(model->layer[i].name, layer_name) == 0)
break;
}
- if (i == model->mvtvm.metadata.model.nb_layers) {
+ if (i == model->nb_layers) {
plt_err("Invalid layer name: %s", layer_name);
return -EINVAL;
}
@@ -139,6 +170,506 @@ mvtvm_ml_model_get_layer_id(struct cnxk_ml_model *model, const char *layer_name,
return 0;
}
+static void
+mvtvm_ml_param_names_free(struct mvtvm_ml_param_names *param_names)
+{
+ size_t i;
+
+ for (i = 0; i < param_names->count; i++)
+ free(param_names->name[i]);
+
+ free(param_names->name);
+ param_names->name = NULL;
+ param_names->count = 0;
+}
+
+static int
+mvtvm_ml_blob_read_u64(const uint8_t *blob, size_t blob_size, size_t *offset, uint64_t *value)
+{
+ if (*offset + sizeof(*value) > blob_size)
+ return -EINVAL;
+
+ memcpy(value, blob + *offset, sizeof(*value));
+ *offset += sizeof(*value);
+
+ return 0;
+}
+
+static int
+mvtvm_ml_param_names_parse(const uint8_t *blob, size_t blob_size,
+ struct mvtvm_ml_param_names *param_names)
+{
+ uint64_t magic = 0;
+ uint64_t reserved = 0;
+ uint64_t count = 0;
+ size_t offset = 0;
+ int ret;
+ size_t i;
+
+ memset(param_names, 0, sizeof(*param_names));
+
+ ret = mvtvm_ml_blob_read_u64(blob, blob_size, &offset, &magic);
+ if (ret != 0)
+ return ret;
+
+ if (magic != TVM_NDARRAY_LIST_MAGIC)
+ return -EINVAL;
+
+ ret = mvtvm_ml_blob_read_u64(blob, blob_size, &offset, &reserved);
+ if (ret != 0)
+ return ret;
+
+ ret = mvtvm_ml_blob_read_u64(blob, blob_size, &offset, &count);
+ if (ret != 0)
+ return ret;
+
+ if (count > SIZE_MAX / sizeof(*param_names->name))
+ return -EINVAL;
+
+ param_names->name = calloc(count, sizeof(*param_names->name));
+ if (count != 0 && param_names->name == NULL)
+ return -ENOMEM;
+
+ param_names->count = count;
+ for (i = 0; i < count; i++) {
+ uint64_t name_len = 0;
+
+ ret = mvtvm_ml_blob_read_u64(blob, blob_size, &offset, &name_len);
+ if (ret != 0)
+ goto error;
+
+ if (name_len == SIZE_MAX) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (offset + name_len > blob_size) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ param_names->name[i] = calloc(name_len + 1, 1);
+ if (param_names->name[i] == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ memcpy(param_names->name[i], blob + offset, name_len);
+ offset += name_len;
+ }
+
+ return 0;
+
+error:
+ mvtvm_ml_param_names_free(param_names);
+ return ret;
+}
+
+static int
+mvtvm_ml_dtype_parse(const char *dtype_str, DLDataType *dtype)
+{
+ const char *lanes_str;
+ char base[32] = {0};
+ long bits;
+ long lanes = 1;
+
+ if (dtype_str == NULL || dtype == NULL)
+ return -EINVAL;
+
+ lanes_str = strchr(dtype_str, 'x');
+ if (lanes_str != NULL) {
+ size_t base_len = lanes_str - dtype_str;
+
+ if (base_len >= sizeof(base))
+ return -EINVAL;
+ memcpy(base, dtype_str, base_len);
+ lanes = strtol(lanes_str + 1, NULL, 10);
+ if (lanes <= 0 || lanes > UINT16_MAX)
+ return -EINVAL;
+ } else {
+ snprintf(base, sizeof(base), "%s", dtype_str);
+ }
+
+ memset(dtype, 0, sizeof(*dtype));
+ dtype->lanes = (uint16_t)lanes;
+
+ if (strncmp(base, "int", 3) == 0) {
+ bits = strtol(base + 3, NULL, 10);
+ dtype->code = kDLInt;
+ } else if (strncmp(base, "uint", 4) == 0) {
+ bits = strtol(base + 4, NULL, 10);
+ dtype->code = kDLUInt;
+ } else if (strncmp(base, "float", 5) == 0) {
+ bits = strtol(base + 5, NULL, 10);
+ dtype->code = kDLFloat;
+ } else if (strncmp(base, "bfloat", 6) == 0) {
+ bits = strtol(base + 6, NULL, 10);
+ dtype->code = kDLBfloat;
+ } else if (strcmp(base, "bool") == 0) {
+ bits = 1;
+ dtype->code = kDLUInt;
+ } else {
+ return -EINVAL;
+ }
+
+ if (bits <= 0 || bits > UINT8_MAX)
+ return -EINVAL;
+
+ dtype->bits = (uint8_t)bits;
+
+ return 0;
+}
+
+static int
+mvtvm_ml_model_io_set(struct cnxk_ml_io *io, const char *name, json_t *shape, const char *dtype_str,
+ DLDevice device)
+{
+ size_t i;
+ int ret;
+
+ memset(io, 0, sizeof(*io));
+ if (name != NULL)
+ snprintf(io->name, sizeof(io->name), "%s", name);
+
+ if (!json_is_array(shape))
+ return -EINVAL;
+
+ io->nb_dims = json_array_size(shape);
+ if (io->nb_dims > ML_CNXK_MODEL_MAX_DIMS)
+ return -ENOTSUP;
+
+ for (i = 0; i < (size_t)io->nb_dims; i++) {
+ json_t *dim = json_array_get(shape, i);
+
+ if (!json_is_integer(dim))
+ return -EINVAL;
+ io->shape_i64[i] = json_integer_value(dim);
+ }
+
+ ret = mvtvm_ml_dtype_parse(dtype_str, &io->datatype);
+ if (ret != 0)
+ return ret;
+
+ io->model_datatype = io->datatype;
+ io->scale = 1.0f;
+ io->device = device;
+
+ return 0;
+}
+
+static int
+mvtvm_ml_json_graph_get_arrays(json_t *json_parsed, json_t **nodes, json_t **arg_nodes,
+ json_t **heads, json_t **node_row_ptr, json_t **shape_values,
+ json_t **dtype_values)
+{
+ json_t *attrs;
+ json_t *shape_attr;
+ json_t *dtype_attr;
+
+ *nodes = json_object_get(json_parsed, "nodes");
+ *arg_nodes = json_object_get(json_parsed, "arg_nodes");
+ *heads = json_object_get(json_parsed, "heads");
+ *node_row_ptr = json_object_get(json_parsed, "node_row_ptr");
+ attrs = json_object_get(json_parsed, "attrs");
+
+ if (!json_is_array(*nodes) || !json_is_array(*arg_nodes) || !json_is_array(*heads) ||
+ !json_is_array(*node_row_ptr) || !json_is_object(attrs))
+ return -EINVAL;
+
+ if (json_array_size(*node_row_ptr) != json_array_size(*nodes) + 1)
+ return -EINVAL;
+
+ shape_attr = json_object_get(attrs, "shape");
+ dtype_attr = json_object_get(attrs, "dltype");
+ if (!json_is_array(shape_attr) || json_array_size(shape_attr) < 2 ||
+ !json_is_array(dtype_attr) || json_array_size(dtype_attr) < 2)
+ return -EINVAL;
+
+ *shape_values = json_array_get(shape_attr, 1);
+ *dtype_values = json_array_get(dtype_attr, 1);
+
+ if (!json_is_array(*shape_values) || !json_is_array(*dtype_values))
+ return -EINVAL;
+
+ return 0;
+}
+
+int
+mvtvm_ml_model_json_parse(struct cnxk_ml_model *model)
+{
+ struct mvtvm_ml_param_names param_names;
+ json_error_t json_error;
+ json_t *json_parsed;
+ json_t *json_nodes;
+ json_t *json_arg_nodes;
+ json_t *json_heads;
+ json_t *json_node_row_ptr;
+ json_t *json_shape_values;
+ json_t *json_dtype_values;
+ uint16_t nb_mrvl_layers;
+ uint16_t nb_llvm_layers;
+ DLDevice device;
+ int ret;
+ size_t i;
+ size_t j;
+
+ /* Parse param names from params buffer */
+ ret = mvtvm_ml_param_names_parse(model->mvtvm.params.buffer, model->mvtvm.params.size,
+ ¶m_names);
+ if (ret != 0)
+ return ret;
+
+ /* Load JSON graph (single load for both stages) */
+ json_parsed = json_loadb((const char *)model->mvtvm.json.buffer, model->mvtvm.json.size, 0,
+ &json_error);
+ if (json_parsed == NULL) {
+ mvtvm_ml_param_names_free(¶m_names);
+ plt_err("TVM runtime: Failed to parse JSON graph, model_id = %u", model->model_id);
+ return -EINVAL;
+ }
+
+ /* Parse nodes to extract layer info */
+ json_nodes = json_object_get(json_parsed, "nodes");
+ if (!json_is_array(json_nodes)) {
+ ret = -EINVAL;
+ plt_err("TVM runtime: Failed to parse JSON nodes, model_id = %u, error = %d",
+ model->model_id, ret);
+ goto error;
+ }
+
+ model->nb_layers = 0;
+ nb_mrvl_layers = 0;
+ nb_llvm_layers = 0;
+ for (i = 0; i < json_array_size(json_nodes); i++) {
+ json_t *node = json_array_get(json_nodes, i);
+ json_t *op = json_object_get(node, "op");
+ json_t *name;
+ json_t *attrs;
+ json_t *compiler;
+
+ if (!json_is_string(op) || strcmp(json_string_value(op), "tvm_op") != 0)
+ continue;
+
+ if (model->nb_layers >= ML_CNXK_MODEL_MAX_LAYERS) {
+ ret = -ENOTSUP;
+ plt_err("TVM runtime: Number of layers exceeds maximum (%u), model_id = %u, error = %d",
+ ML_CNXK_MODEL_MAX_LAYERS, model->model_id, ret);
+ goto error;
+ }
+
+ name = json_object_get(node, "name");
+ if (!json_is_string(name)) {
+ ret = -EINVAL;
+ plt_err("TVM runtime: Failed to parse JSON node name, model_id = %u, error = %d",
+ model->model_id, ret);
+ goto error;
+ }
+
+ if (json_string_value(name) != NULL)
+ snprintf(model->layer[model->nb_layers].name,
+ sizeof(model->layer[model->nb_layers].name), "%s",
+ json_string_value(name));
+ else
+ snprintf(model->layer[model->nb_layers].name,
+ sizeof(model->layer[model->nb_layers].name), "tvm_layer_%u",
+ model->nb_layers);
+
+ attrs = json_object_get(node, "attrs");
+ compiler = json_is_object(attrs) ? json_object_get(attrs, "Compiler") : NULL;
+ if (json_is_string(compiler)) {
+ if (strcmp(json_string_value(compiler), "mrvl") == 0 ||
+ strcmp(json_string_value(compiler), "MRVL") == 0) {
+ model->layer[model->nb_layers].type = ML_CNXK_LAYER_TYPE_MRVL;
+ nb_mrvl_layers++;
+ } else {
+ model->layer[model->nb_layers].type = ML_CNXK_LAYER_TYPE_UNKNOWN;
+ }
+ } else {
+ model->layer[model->nb_layers].type = ML_CNXK_LAYER_TYPE_LLVM;
+ nb_llvm_layers++;
+ }
+ model->nb_layers++;
+ }
+
+ /* Set model fields */
+ snprintf(model->name, sizeof(model->name), "tvm_model_%u", model->model_id);
+ model->batch_size = 1;
+
+ /* Validate layer counts */
+ if ((nb_llvm_layers == 0) && (nb_mrvl_layers == 0)) {
+ plt_err("Invalid model, nb_llvm_layers = %u, nb_mrvl_layers = %u", nb_llvm_layers,
+ nb_mrvl_layers);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (nb_llvm_layers + nb_mrvl_layers != model->nb_layers) {
+ plt_err("Invalid model, nb_llvm_layers = %u, nb_mrvl_layers = %u, nb_layers = %u",
+ nb_llvm_layers, nb_mrvl_layers, model->nb_layers);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* Set model subtype */
+ if ((nb_llvm_layers == 0) && (nb_mrvl_layers == 1))
+ model->subtype = ML_CNXK_MODEL_SUBTYPE_TVM_MRVL;
+ else if ((nb_llvm_layers > 0) && (nb_mrvl_layers == 0))
+ model->subtype = ML_CNXK_MODEL_SUBTYPE_TVM_LLVM;
+ else
+ model->subtype = ML_CNXK_MODEL_SUBTYPE_TVM_HYBRID;
+
+ /* Parse I/O info from the same JSON graph */
+ device.device_type = kDLCPU;
+ device.device_id = 0;
+
+ ret = mvtvm_ml_json_graph_get_arrays(json_parsed, &json_nodes, &json_arg_nodes, &json_heads,
+ &json_node_row_ptr, &json_shape_values,
+ &json_dtype_values);
+ if (ret == 0) {
+ model->mvtvm.info.nb_inputs = 0;
+ model->mvtvm.info.nb_outputs = 0;
+
+ for (i = 0; i < json_array_size(json_arg_nodes); i++) {
+ json_t *arg_node_idx = json_array_get(json_arg_nodes, i);
+ json_t *node;
+ json_t *shape;
+ json_t *dtype;
+ json_t *name;
+ json_int_t node_id;
+
+ if (!json_is_integer(arg_node_idx)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ node_id = json_integer_value(arg_node_idx);
+ node = json_array_get(json_nodes, node_id);
+ shape = json_array_get(json_shape_values, node_id);
+ dtype = json_array_get(json_dtype_values, node_id);
+ name = json_object_get(node, "name");
+ if (!json_is_object(node) || !json_is_array(shape) ||
+ !json_is_string(dtype) || !json_is_string(name)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ for (j = 0; j < param_names.count; j++) {
+ if (strcmp(param_names.name[j], json_string_value(name)) == 0)
+ break;
+ }
+
+ if (j < param_names.count)
+ continue;
+
+ if (model->mvtvm.info.nb_inputs >= ML_CNXK_MODEL_MAX_INPUT_OUTPUT) {
+ ret = -ENOTSUP;
+ break;
+ }
+
+ ret = mvtvm_ml_model_io_set(
+ &model->mvtvm.info.input[model->mvtvm.info.nb_inputs],
+ json_string_value(name), shape, json_string_value(dtype), device);
+ if (ret != 0)
+ break;
+
+ model->mvtvm.info.nb_inputs++;
+ }
+
+ for (i = 0; ret == 0 && i < json_array_size(json_heads); i++) {
+ json_t *head = json_array_get(json_heads, i);
+ json_t *node;
+ json_t *shape;
+ json_t *dtype;
+ json_t *name;
+ json_t *node_id_json;
+ json_t *output_idx_json;
+ json_t *entry_base_json;
+ json_t *entry_limit_json;
+ json_int_t node_id;
+ json_int_t output_idx;
+ json_int_t entry_base;
+ json_int_t entry_limit;
+ size_t entry_id;
+
+ if (!json_is_array(head) || json_array_size(head) < 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ node_id_json = json_array_get(head, 0);
+ output_idx_json = json_array_get(head, 1);
+ if (!json_is_integer(node_id_json) || !json_is_integer(output_idx_json)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ node_id = json_integer_value(node_id_json);
+ output_idx = json_integer_value(output_idx_json);
+ if (node_id < 0 || output_idx < 0) {
+ ret = -EINVAL;
+ break;
+ }
+
+ node = json_array_get(json_nodes, (size_t)node_id);
+ entry_base_json = json_array_get(json_node_row_ptr, (size_t)node_id);
+ entry_limit_json = json_array_get(json_node_row_ptr, (size_t)node_id + 1);
+ if (!json_is_object(node) || !json_is_integer(entry_base_json) ||
+ !json_is_integer(entry_limit_json)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ entry_base = json_integer_value(entry_base_json);
+ entry_limit = json_integer_value(entry_limit_json);
+ if (entry_base < 0 || entry_limit < entry_base) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (output_idx >= (entry_limit - entry_base)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ entry_id = (size_t)entry_base + (size_t)output_idx;
+ shape = json_array_get(json_shape_values, entry_id);
+ dtype = json_array_get(json_dtype_values, entry_id);
+ name = json_object_get(node, "name");
+ if (!json_is_array(shape) || !json_is_string(dtype) ||
+ !json_is_string(name)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (model->mvtvm.info.nb_outputs >= ML_CNXK_MODEL_MAX_INPUT_OUTPUT) {
+ ret = -ENOTSUP;
+ break;
+ }
+
+ ret = mvtvm_ml_model_io_set(
+ &model->mvtvm.info.output[model->mvtvm.info.nb_outputs],
+ json_string_value(name), shape, json_string_value(dtype), device);
+ if (ret != 0)
+ break;
+
+ model->mvtvm.info.nb_outputs++;
+ }
+ }
+
+ if (ret != 0)
+ plt_err("TVM runtime: Failed to get metadata, model_id = %u, error = %d",
+ model->model_id, ret);
+
+ json_decref(json_parsed);
+ mvtvm_ml_param_names_free(¶m_names);
+ return ret;
+
+error:
+ json_decref(json_parsed);
+ mvtvm_ml_param_names_free(¶m_names);
+ return ret;
+}
+
static enum rte_ml_io_type
mvtvm_ml_io_type_map(DLDataType dltype)
{
@@ -185,32 +716,27 @@ mvtvm_ml_io_type_map(DLDataType dltype)
void
mvtvm_ml_model_io_info_set(struct cnxk_ml_model *model)
{
- struct tvmdp_model_metadata *metadata;
int32_t i;
- int32_t j;
+ uint32_t j;
if (model->subtype == ML_CNXK_MODEL_SUBTYPE_TVM_MRVL)
goto tvm_mrvl_model;
- metadata = &model->mvtvm.metadata;
-
/* Inputs, set for layer_id = 0 */
- model->mvtvm.info.nb_inputs = metadata->model.num_input;
model->mvtvm.info.total_input_sz_d = 0;
model->mvtvm.info.total_input_sz_q = 0;
- for (i = 0; i < metadata->model.num_input; i++) {
- rte_strscpy(model->mvtvm.info.input[i].name, metadata->input[i].name,
- TVMDP_NAME_STRLEN);
+ for (i = 0; i < model->mvtvm.info.nb_inputs; i++) {
model->mvtvm.info.input[i].dtype =
- mvtvm_ml_io_type_map(metadata->input[i].datatype);
+ mvtvm_ml_io_type_map(model->mvtvm.info.input[i].datatype);
model->mvtvm.info.input[i].qtype =
- mvtvm_ml_io_type_map(metadata->input[i].model_datatype);
- model->mvtvm.info.input[i].nb_dims = metadata->input[i].ndim;
+ mvtvm_ml_io_type_map(model->mvtvm.info.input[i].model_datatype);
model->mvtvm.info.input[i].nb_elements = 1;
- for (j = 0; j < metadata->input[i].ndim; j++) {
- model->mvtvm.info.input[i].shape[j] = metadata->input[i].shape[j];
- model->mvtvm.info.input[i].nb_elements *= metadata->input[i].shape[j];
+ for (j = 0; j < model->mvtvm.info.input[i].nb_dims; j++) {
+ model->mvtvm.info.input[i].shape[j] =
+ PLT_U32_CAST(model->mvtvm.info.input[i].shape_i64[j]);
+ model->mvtvm.info.input[i].nb_elements *=
+ model->mvtvm.info.input[i].shape[j];
}
model->mvtvm.info.input[i].sz_d =
@@ -219,15 +745,14 @@ mvtvm_ml_model_io_info_set(struct cnxk_ml_model *model)
model->mvtvm.info.input[i].sz_q =
model->mvtvm.info.input[i].nb_elements *
rte_ml_io_type_size_get(model->mvtvm.info.input[i].qtype);
- model->mvtvm.info.input[i].scale = metadata->input[i].scale;
model->mvtvm.info.total_input_sz_d += model->mvtvm.info.input[i].sz_d;
model->mvtvm.info.total_input_sz_q += model->mvtvm.info.input[i].sz_q;
- model->mvtvm.input_tensor[i].device = metadata->input[i].device;
- model->mvtvm.input_tensor[i].ndim = metadata->input[i].ndim;
- model->mvtvm.input_tensor[i].dtype = metadata->input[i].datatype;
- model->mvtvm.input_tensor[i].shape = metadata->input[i].shape;
+ model->mvtvm.input_tensor[i].device = model->mvtvm.info.input[i].device;
+ model->mvtvm.input_tensor[i].ndim = model->mvtvm.info.input[i].nb_dims;
+ model->mvtvm.input_tensor[i].dtype = model->mvtvm.info.input[i].datatype;
+ model->mvtvm.input_tensor[i].shape = model->mvtvm.info.input[i].shape_i64;
model->mvtvm.input_tensor[i].strides = NULL;
model->mvtvm.input_tensor[i].byte_offset = 0;
@@ -236,22 +761,20 @@ mvtvm_ml_model_io_info_set(struct cnxk_ml_model *model)
}
/* Outputs, set for nb_layers - 1 */
- model->mvtvm.info.nb_outputs = metadata->model.num_output;
model->mvtvm.info.total_output_sz_d = 0;
model->mvtvm.info.total_output_sz_q = 0;
- for (i = 0; i < metadata->model.num_output; i++) {
- rte_strscpy(model->mvtvm.info.output[i].name, metadata->output[i].name,
- TVMDP_NAME_STRLEN);
+ for (i = 0; i < model->mvtvm.info.nb_outputs; i++) {
model->mvtvm.info.output[i].dtype =
- mvtvm_ml_io_type_map(metadata->output[i].datatype);
+ mvtvm_ml_io_type_map(model->mvtvm.info.output[i].datatype);
model->mvtvm.info.output[i].qtype =
- mvtvm_ml_io_type_map(metadata->output[i].model_datatype);
- model->mvtvm.info.output[i].nb_dims = metadata->output[i].ndim;
+ mvtvm_ml_io_type_map(model->mvtvm.info.output[i].model_datatype);
model->mvtvm.info.output[i].nb_elements = 1;
- for (j = 0; j < metadata->output[i].ndim; j++) {
- model->mvtvm.info.output[i].shape[j] = metadata->output[i].shape[j];
- model->mvtvm.info.output[i].nb_elements *= metadata->output[i].shape[j];
+ for (j = 0; j < model->mvtvm.info.output[i].nb_dims; j++) {
+ model->mvtvm.info.output[i].shape[j] =
+ PLT_U32_CAST(model->mvtvm.info.output[i].shape_i64[j]);
+ model->mvtvm.info.output[i].nb_elements *=
+ model->mvtvm.info.output[i].shape[j];
}
model->mvtvm.info.output[i].sz_d =
@@ -260,15 +783,14 @@ mvtvm_ml_model_io_info_set(struct cnxk_ml_model *model)
model->mvtvm.info.output[i].sz_q =
model->mvtvm.info.output[i].nb_elements *
rte_ml_io_type_size_get(model->mvtvm.info.output[i].qtype);
- model->mvtvm.info.output[i].scale = metadata->output[i].scale;
model->mvtvm.info.total_output_sz_d += model->mvtvm.info.output[i].sz_d;
model->mvtvm.info.total_output_sz_q += model->mvtvm.info.output[i].sz_q;
- model->mvtvm.output_tensor[i].device = metadata->output[i].device;
- model->mvtvm.output_tensor[i].ndim = metadata->output[i].ndim;
- model->mvtvm.output_tensor[i].dtype = metadata->output[i].datatype;
- model->mvtvm.output_tensor[i].shape = metadata->output[i].shape;
+ model->mvtvm.output_tensor[i].device = model->mvtvm.info.output[i].device;
+ model->mvtvm.output_tensor[i].ndim = model->mvtvm.info.output[i].nb_dims;
+ model->mvtvm.output_tensor[i].dtype = model->mvtvm.info.output[i].datatype;
+ model->mvtvm.output_tensor[i].shape = model->mvtvm.info.output[i].shape_i64;
model->mvtvm.output_tensor[i].strides = NULL;
model->mvtvm.output_tensor[i].byte_offset = 0;
@@ -293,7 +815,6 @@ mvtvm_ml_model_io_info_get(struct cnxk_ml_model *model, uint16_t layer_id)
void
mvtvm_ml_model_info_set(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
{
- struct tvmdp_model_metadata *metadata;
struct rte_ml_model_info *info;
struct rte_ml_io_info *output;
struct rte_ml_io_info *input;
@@ -309,26 +830,23 @@ mvtvm_ml_model_info_set(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *mo
if (model->subtype == ML_CNXK_MODEL_SUBTYPE_TVM_MRVL)
goto tvm_mrvl_model;
- metadata = &model->mvtvm.metadata;
- rte_memcpy(info->name, metadata->model.name, TVMDP_NAME_STRLEN);
- snprintf(info->version, RTE_ML_STR_MAX, "%u.%u.%u.%u", metadata->model.version[0],
- metadata->model.version[1], metadata->model.version[2],
- metadata->model.version[3]);
+ rte_memcpy(info->name, model->name, RTE_ML_STR_MAX);
+ snprintf(info->version, RTE_ML_STR_MAX, "%u.%u.%u.%u", 0, 0, 0, 0);
info->model_id = model->model_id;
info->device_id = cnxk_mldev->mldev->data->dev_id;
info->io_layout = RTE_ML_IO_LAYOUT_SPLIT;
info->min_batches = model->batch_size;
info->max_batches = model->batch_size;
- info->nb_inputs = metadata->model.num_input;
+ info->nb_inputs = model->mvtvm.info.nb_inputs;
info->input_info = input;
- info->nb_outputs = metadata->model.num_output;
+ info->nb_outputs = model->mvtvm.info.nb_outputs;
info->output_info = output;
info->wb_size = 0;
/* Set input info */
for (i = 0; i < info->nb_inputs; i++) {
- rte_memcpy(input[i].name, metadata->input[i].name, MRVL_ML_INPUT_NAME_LEN);
- input[i].nb_dims = metadata->input[i].ndim;
+ rte_memcpy(input[i].name, model->mvtvm.info.input[i].name, MRVL_ML_INPUT_NAME_LEN);
+ input[i].nb_dims = model->mvtvm.info.input[i].nb_dims;
input[i].shape = &model->mvtvm.info.input[i].shape[0];
input[i].type = model->mvtvm.info.input[i].qtype;
input[i].nb_elements = model->mvtvm.info.input[i].nb_elements;
@@ -340,15 +858,16 @@ mvtvm_ml_model_info_set(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *mo
/* Set output info */
for (i = 0; i < info->nb_outputs; i++) {
- rte_memcpy(output[i].name, metadata->output[i].name, MRVL_ML_OUTPUT_NAME_LEN);
- output[i].nb_dims = metadata->output[i].ndim;
+ rte_memcpy(output[i].name, model->mvtvm.info.output[i].name,
+ MRVL_ML_OUTPUT_NAME_LEN);
+ output[i].nb_dims = model->mvtvm.info.output[i].nb_dims;
output[i].shape = &model->mvtvm.info.output[i].shape[0];
output[i].type = model->mvtvm.info.output[i].qtype;
output[i].nb_elements = model->mvtvm.info.output[i].nb_elements;
output[i].size = model->mvtvm.info.output[i].nb_elements *
rte_ml_io_type_size_get(model->mvtvm.info.output[i].qtype);
- input[i].scale = model->mvtvm.info.output[i].scale;
- input[i].zero_point = 0;
+ output[i].scale = model->mvtvm.info.output[i].scale;
+ output[i].zero_point = 0;
}
return;
@@ -357,8 +876,7 @@ mvtvm_ml_model_info_set(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *mo
cn10k_ml_model_info_set(cnxk_mldev, model, &model->mvtvm.info,
&model->layer[0].glow.metadata);
- metadata = &model->mvtvm.metadata;
- strlcpy(info->name, metadata->model.name, TVMDP_NAME_STRLEN);
+ strlcpy(info->name, model->name, RTE_ML_STR_MAX);
info->io_layout = RTE_ML_IO_LAYOUT_PACKED;
}
diff --git a/drivers/ml/cnxk/mvtvm_ml_model.h b/drivers/ml/cnxk/mvtvm_ml_model.h
index 7ffce380945..1151b0a39ed 100644
--- a/drivers/ml/cnxk/mvtvm_ml_model.h
+++ b/drivers/ml/cnxk/mvtvm_ml_model.h
@@ -5,7 +5,21 @@
#ifndef _MVTVM_ML_MODEL_H_
#define _MVTVM_ML_MODEL_H_
-#include <tvmdp.h>
+#include <dlpack/dlpack.h>
+#include <jansson.h>
+#include <rte_common.h>
+
+#if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG)
+__rte_diagnostic_push
+RTE_PRAGMA(GCC diagnostic ignored "-Wstrict-prototypes")
+#include <tvm/runtime/c_runtime_api.h>
+__rte_diagnostic_pop
+#else
+#include <tvm/runtime/c_runtime_api.h>
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
#include <rte_mldev.h>
@@ -18,19 +32,56 @@ struct cnxk_ml_layer;
/* Maximum number of objects per model */
#define ML_MVTVM_MODEL_OBJECT_MAX 3
-/* Objects list */
-extern char mvtvm_object_list[ML_MVTVM_MODEL_OBJECT_MAX][RTE_ML_STR_MAX];
+/* Magic number for TVM parameter blobs. */
+#define TVM_NDARRAY_LIST_MAGIC 0xF7E58D4F05049CB7ULL
-/* Model object structure */
+/* TVM parameter names structure */
+struct mvtvm_ml_param_names {
+ char **name;
+ size_t count;
+};
+
+/* TVM object / artifact info structure */
struct mvtvm_ml_model_object {
/* Name */
char name[RTE_ML_STR_MAX];
- /* Temporary buffer */
+ /* Buffer address */
uint8_t *buffer;
/* Buffer size */
int64_t size;
+
+ /* Offset */
+ uint32_t offset;
+};
+
+/* Glow model callback functions */
+typedef int (*tvmrt_glow_layer_load_cb)(void *device, uint16_t model_id, const char *layer_name,
+ uint8_t *buffer, size_t size, uint16_t *index);
+typedef int (*tvmrt_glow_layer_unload_cb)(void *device, uint16_t model_id, const char *layer_name);
+typedef int (*tvmrt_io_alloc_cb)(void *device, uint16_t model_id, const char *layer_name,
+ uint64_t **input_qbuffer, uint64_t **output_qbuffer);
+typedef int (*tvmrt_io_free_cb)(void *device, uint16_t model_id, const char *layer_name);
+typedef int (*tvmrt_malloc_cb)(const char *name, size_t size, uint32_t align, void **addr);
+typedef int (*tvmrt_free_cb)(const char *name);
+typedef int (*tvmrt_quantize_cb)(void *device, uint16_t model_id, const char *layer_name,
+ const DLTensor **deq_tensor, void *qbuffer);
+typedef int (*tvmrt_dequantize_cb)(void *device, uint16_t model_id, const char *layer_name,
+ void *qbuffer, const DLTensor **deq_tensor);
+typedef int (*tvmrt_inference_cb)(void *device, uint16_t index, void *input, void *output,
+ uint16_t nb_batches);
+
+struct tvmrt_glow_callback {
+ tvmrt_glow_layer_load_cb tvmrt_glow_layer_load;
+ tvmrt_glow_layer_unload_cb tvmrt_glow_layer_unload;
+ tvmrt_io_alloc_cb tvmrt_io_alloc;
+ tvmrt_io_free_cb tvmrt_io_free;
+ tvmrt_malloc_cb tvmrt_malloc;
+ tvmrt_free_cb tvmrt_free;
+ tvmrt_quantize_cb tvmrt_quantize;
+ tvmrt_dequantize_cb tvmrt_dequantize;
+ tvmrt_inference_cb tvmrt_inference;
};
/* Model fast-path stats */
@@ -55,15 +106,26 @@ struct mvtvm_ml_model_xstats {
};
struct mvtvm_ml_model_data {
- /* Model metadata */
- struct tvmdp_model_metadata metadata;
-
/* Model objects */
- struct tvmdp_model_object object;
+ struct mvtvm_ml_model_object so;
+ struct mvtvm_ml_model_object json;
+ struct mvtvm_ml_model_object params;
/* TVM runtime callbacks */
struct tvmrt_glow_callback cb;
+ /* TVM Graph Module */
+ TVMModuleHandle graph_module;
+
+ /* Shared object memfd used to load the TVM module */
+ int fd;
+
+ /* TVM Function Handles */
+ TVMFunctionHandle load_params;
+ TVMFunctionHandle set_input_zero_copy;
+ TVMFunctionHandle set_output_zero_copy;
+ TVMFunctionHandle run;
+
/* Model I/O info */
struct cnxk_ml_io_info info;
@@ -86,5 +148,6 @@ void mvtvm_ml_model_io_info_set(struct cnxk_ml_model *model);
struct cnxk_ml_io_info *mvtvm_ml_model_io_info_get(struct cnxk_ml_model *model, uint16_t layer_id);
void mvtvm_ml_model_info_set(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model);
void mvtvm_ml_layer_print(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_layer *layer, FILE *fp);
+int mvtvm_ml_model_json_parse(struct cnxk_ml_model *model);
#endif /* _MVTVM_ML_MODEL_H_ */
diff --git a/drivers/ml/cnxk/mvtvm_ml_ops.c b/drivers/ml/cnxk/mvtvm_ml_ops.c
index 80b22460db9..bc47a4bbd75 100644
--- a/drivers/ml/cnxk/mvtvm_ml_ops.c
+++ b/drivers/ml/cnxk/mvtvm_ml_ops.c
@@ -2,7 +2,17 @@
* Copyright (c) 2023 Marvell.
*/
+#include <errno.h>
+#include <linux/limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
#include <dlpack/dlpack.h>
+#include <jansson.h>
#include <rte_common.h>
#include <rte_cycles.h>
@@ -19,6 +29,76 @@
/* ML model macros */
#define MVTVM_ML_MODEL_MEMZONE_NAME "ml_mvtvm_model_mz"
+/* Shared memory file descriptor name */
+#define ML_MODEL_SHMFD_NAME "mvtvm_shmfd"
+
+/* Shared memory file descriptor path */
+#define ML_MODEL_SHMFD_PATH "/proc/%d/fd/%d"
+
+static int
+mvtvm_ml_tvm_func_get(struct cnxk_ml_model *model, TVMModuleHandle module, const char *name,
+ TVMFunctionHandle *func)
+{
+ int ret;
+
+ ret = TVMModGetFunction(module, name, 0, func);
+ if (ret != 0) {
+ plt_err("Model load failed, model_id = %u, ret = %d, msg = %s", model->model_id,
+ ret, TVMGetLastError());
+ return ret;
+ }
+
+ if (*func == NULL) {
+ ret = -ENOENT;
+ plt_err("Model load failed, model_id = %u, function '%s' not found",
+ model->model_id, name);
+ }
+
+ return ret;
+}
+
+static int
+mvtvm_ml_tvm_func_call(struct cnxk_ml_model *model, TVMFunctionHandle func, const char *name,
+ TVMValue *values, int *types, int num_args, TVMValue *ret_val, int *ret_type,
+ int ret_type_code)
+{
+ int ret;
+
+ ret = TVMFuncCall(func, values, types, num_args, ret_val, ret_type);
+ if (ret != 0) {
+ plt_err("Error calling TVM function '%s', model_id = %u, ret = %d, msg = %s", name,
+ model->model_id, ret, TVMGetLastError());
+ return ret;
+ }
+
+ if (*ret_type != ret_type_code) {
+ ret = -EINVAL;
+ plt_err("TVM function '%s' returned unexpected type, model_id = %u, expected = %d, "
+ "actual = %d",
+ name, model->model_id, ret_type_code, *ret_type);
+ }
+
+ return ret;
+}
+
+static void
+mvtvm_ml_tvm_func_free(TVMFunctionHandle *func)
+{
+ if ((func != NULL) && (*func != NULL)) {
+ TVMFuncFree(*func);
+ *func = NULL;
+ }
+}
+
+static void
+mvtvm_ml_tvm_mod_free(TVMModuleHandle *mod)
+{
+ if ((mod != NULL) && (*mod != NULL)) {
+ TVMModFree(*mod);
+ *mod = NULL;
+ }
+}
+
__rte_hot static void
mvtvm_ml_set_poll_addr(struct cnxk_ml_req *req)
{
@@ -30,8 +110,8 @@ mvtvm_ml_model_xstat_name_set(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_mod
uint16_t stat_id, uint16_t entry, char *suffix)
{
snprintf(cnxk_mldev->xstats.entries[stat_id].map.name,
- sizeof(cnxk_mldev->xstats.entries[stat_id].map.name), "%s-%s-%s",
- model->mvtvm.metadata.model.name, model_xstats[entry].name, suffix);
+ sizeof(cnxk_mldev->xstats.entries[stat_id].map.name), "%s-%s-%s", model->name,
+ model_xstats[entry].name, suffix);
}
#define ML_AVG_FOREACH_QP_MVTVM(cnxk_mldev, model, qp_id, value, count) \
@@ -106,43 +186,13 @@ mvtvm_ml_dev_info_get(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_dev_info *de
dev_info->max_queue_pairs = mvtvm_mldev->max_nb_qpairs;
dev_info->max_desc = ML_MVTVM_MAX_DESC_PER_QP;
- dev_info->max_io = ML_MVTVM_MAX_INPUT_OUTPUT;
+ dev_info->max_io = ML_CNXK_MODEL_MAX_INPUT_OUTPUT;
dev_info->max_segments = ML_MVTVM_MAX_SEGMENTS;
dev_info->align_size = RTE_CACHE_LINE_SIZE;
return 0;
}
-int
-mvtvm_ml_dev_configure(struct cnxk_ml_dev *cnxk_mldev, const struct rte_ml_dev_config *conf)
-{
- int ret;
-
- RTE_SET_USED(conf);
-
- /* Configure TVMDP library */
- ret = tvmdp_configure(cnxk_mldev->mldev->data->nb_models, rte_get_tsc_cycles);
- if (ret != 0)
- plt_err("TVMDP configuration failed, error = %d", ret);
-
- return ret;
-}
-
-int
-mvtvm_ml_dev_close(struct cnxk_ml_dev *cnxk_mldev)
-{
- int ret;
-
- RTE_SET_USED(cnxk_mldev);
-
- /* Close TVMDP library configuration */
- ret = tvmdp_close();
- if (ret != 0)
- plt_err("TVMDP close failed, error = %d", ret);
-
- return ret;
-}
-
int
mvtvm_ml_dev_dump(struct cnxk_ml_dev *cnxk_mldev, FILE *fp)
{
@@ -159,16 +209,26 @@ mvtvm_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *
struct mvtvm_ml_model_object object[ML_MVTVM_MODEL_OBJECT_MAX];
struct tvmrt_glow_callback *callback;
char str[RTE_MEMZONE_NAMESIZE];
+ char path[PATH_MAX];
const struct plt_memzone *mz;
size_t model_object_size = 0;
size_t model_xstats_size = 0;
- uint16_t nb_mrvl_layers;
- uint16_t nb_llvm_layers;
- uint8_t layer_id = 0;
uint64_t mz_size = 0;
+ TVMFunctionHandle create_fn = NULL;
+ TVMFunctionHandle register_cb_fn = NULL;
+ TVMModuleHandle module_so = NULL;
+ TVMByteArray tvm_params;
+ TVMValue ret_value = {0};
+ TVMValue arg_values[4] = {0};
+ TVMValue tvm_arg_values[1] = {0};
+ int ret_type = kTVMNullptr;
+ int arg_types[4] = {0};
+ int tvm_arg_types[1] = {0};
+ DLDevice device;
int ret;
RTE_SET_USED(cnxk_mldev);
+ model->mvtvm.fd = -1;
ret = mvtvm_ml_model_blob_parse(params, object);
if (ret != 0)
@@ -192,80 +252,39 @@ mvtvm_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *
}
/* Copy mod.so */
- model->mvtvm.object.so.addr = mz->addr;
- model->mvtvm.object.so.size = object[0].size;
- rte_memcpy(model->mvtvm.object.so.name, object[0].name, TVMDP_NAME_STRLEN);
- rte_memcpy(model->mvtvm.object.so.addr, object[0].buffer, object[0].size);
+ model->mvtvm.so.buffer = mz->addr;
+ model->mvtvm.so.size = object[0].size;
+ rte_memcpy(model->mvtvm.so.name, object[0].name, RTE_ML_STR_MAX);
+ rte_memcpy(model->mvtvm.so.buffer, object[0].buffer, object[0].size);
rte_free(object[0].buffer);
/* Copy mod.json */
- model->mvtvm.object.json.addr =
- RTE_PTR_ADD(model->mvtvm.object.so.addr,
- RTE_ALIGN_CEIL(model->mvtvm.object.so.size, RTE_CACHE_LINE_MIN_SIZE));
- model->mvtvm.object.json.size = object[1].size;
- rte_memcpy(model->mvtvm.object.json.name, object[1].name, TVMDP_NAME_STRLEN);
- rte_memcpy(model->mvtvm.object.json.addr, object[1].buffer, object[1].size);
+ model->mvtvm.json.buffer =
+ RTE_PTR_ADD(model->mvtvm.so.buffer,
+ RTE_ALIGN_CEIL(model->mvtvm.so.size, RTE_CACHE_LINE_MIN_SIZE));
+ model->mvtvm.json.size = object[1].size;
+ rte_memcpy(model->mvtvm.json.name, object[1].name, RTE_ML_STR_MAX);
+ rte_memcpy(model->mvtvm.json.buffer, object[1].buffer, object[1].size);
rte_free(object[1].buffer);
/* Copy mod.params */
- model->mvtvm.object.params.addr =
- RTE_PTR_ADD(model->mvtvm.object.json.addr,
- RTE_ALIGN_CEIL(model->mvtvm.object.json.size, RTE_CACHE_LINE_MIN_SIZE));
- model->mvtvm.object.params.size = object[2].size;
- rte_memcpy(model->mvtvm.object.params.name, object[2].name, TVMDP_NAME_STRLEN);
- rte_memcpy(model->mvtvm.object.params.addr, object[2].buffer, object[2].size);
+ model->mvtvm.params.buffer =
+ RTE_PTR_ADD(model->mvtvm.json.buffer,
+ RTE_ALIGN_CEIL(model->mvtvm.json.size, RTE_CACHE_LINE_MIN_SIZE));
+ model->mvtvm.params.size = object[2].size;
+ rte_memcpy(model->mvtvm.params.name, object[2].name, RTE_ML_STR_MAX);
+ rte_memcpy(model->mvtvm.params.buffer, object[2].buffer, object[2].size);
rte_free(object[2].buffer);
- /* Get metadata - stage 1 */
- ret = tvmdp_model_metadata_get_stage1(model->mvtvm.object.json.addr,
- model->mvtvm.object.json.size,
- &model->mvtvm.metadata);
- if (ret != 0) {
- plt_err("TVMDP: Failed to parse metadata - stage 1, model_id = %u, error = %d",
- model->model_id, ret);
- goto error;
- }
-
- /* Set model fields */
- plt_strlcpy(model->name, model->mvtvm.metadata.model.name, TVMDP_NAME_STRLEN);
- model->batch_size = 1;
- model->nb_layers = model->mvtvm.metadata.model.nb_layers;
-
- /* Update layer info */
- nb_mrvl_layers = 0;
- nb_llvm_layers = 0;
- for (layer_id = 0; layer_id < model->mvtvm.metadata.model.nb_layers; layer_id++) {
- rte_strscpy(model->layer[layer_id].name,
- model->mvtvm.metadata.model.layer[layer_id].name, TVMDP_NAME_STRLEN);
- if (strcmp(model->mvtvm.metadata.model.layer[layer_id].type, "mrvl") == 0 ||
- strcmp(model->mvtvm.metadata.model.layer[layer_id].type, "MRVL") == 0) {
- model->layer[layer_id].type = ML_CNXK_LAYER_TYPE_MRVL;
- nb_mrvl_layers++;
- } else if (strcmp(model->mvtvm.metadata.model.layer[layer_id].type, "llvm") == 0 ||
- strcmp(model->mvtvm.metadata.model.layer[layer_id].type, "LLVM") == 0) {
- model->layer[layer_id].type = ML_CNXK_LAYER_TYPE_LLVM;
- nb_llvm_layers++;
- }
- }
-
- if ((nb_llvm_layers == 0) && (nb_mrvl_layers == 0)) {
- plt_err("Invalid model, nb_llvm_layers = %u, nb_mrvl_layers = %u", nb_llvm_layers,
- nb_mrvl_layers);
+ ret = mvtvm_ml_model_json_parse(model);
+ if (ret != 0)
goto error;
- }
-
- /* Set model subtype */
- if ((nb_llvm_layers == 0) && (nb_mrvl_layers == 1))
- model->subtype = ML_CNXK_MODEL_SUBTYPE_TVM_MRVL;
- else if ((nb_llvm_layers > 0) && (nb_mrvl_layers == 0))
- model->subtype = ML_CNXK_MODEL_SUBTYPE_TVM_LLVM;
- else
- model->subtype = ML_CNXK_MODEL_SUBTYPE_TVM_HYBRID;
if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_VDEV &&
model->subtype != ML_CNXK_MODEL_SUBTYPE_TVM_LLVM) {
plt_err("Unsupported model sub-type");
- return -ENOTSUP;
+ ret = -ENOTSUP;
+ goto error;
}
/* Set callback function array */
@@ -284,23 +303,120 @@ mvtvm_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *
callback = NULL;
}
- /* Initialize model in TVMDP */
- ret = tvmdp_model_load(cnxk_mldev, model->model_id, (void *)(&model->mvtvm.object),
- callback);
+ /* Initialize model in TVM runtime */
+ if (model->mvtvm.graph_module != NULL) {
+ ret = -EBUSY;
+ plt_err("TVM runtime: Model load failed, model_id = %u, error = %d",
+ model->model_id, ret);
+ goto error;
+ }
+
+ snprintf(path, sizeof(path), "%s_%d_%u", ML_MODEL_SHMFD_NAME, getpid(), model->model_id);
+ model->mvtvm.fd = memfd_create(path, 0);
+ if (model->mvtvm.fd < 0) {
+ ret = (errno == 0) ? -EIO : -errno;
+ plt_err("TVM runtime: Model load failed, model_id = %u, error = %d",
+ model->model_id, ret);
+ goto error;
+ }
+
+ if (write(model->mvtvm.fd, model->mvtvm.so.buffer, model->mvtvm.so.size) !=
+ (ssize_t)model->mvtvm.so.size) {
+ ret = (errno == 0) ? -EIO : -errno;
+ plt_err("TVM runtime: Model load failed, model_id = %u, error = %d",
+ model->model_id, ret);
+ goto error;
+ }
+
+ if (lseek(model->mvtvm.fd, 0, SEEK_SET) < 0) {
+ ret = (errno == 0) ? -EIO : -errno;
+ plt_err("TVM runtime: Model load failed, model_id = %u, error = %d",
+ model->model_id, ret);
+ goto error;
+ }
+
+ snprintf(path, sizeof(path), ML_MODEL_SHMFD_PATH, getpid(), model->mvtvm.fd);
+ ret = TVMModLoadFromFile(path, "so", &module_so);
if (ret != 0) {
- plt_err("TVMDP: Model load failed, model_id = %u, error = %d", model->model_id,
- ret);
+ plt_err("TVM runtime: Model load failed, model_id = %u, ret = %d, msg = %s",
+ model->model_id, ret, TVMGetLastError());
goto error;
}
- /* Get model metadata - stage 2 */
- ret = tvmdp_model_metadata_get_stage2(model->model_id, &model->mvtvm.metadata);
+ /* Set device info */
+ device.device_type = kDLCPU;
+ device.device_id = 0;
+
+ if (callback != NULL) {
+ ret = mvtvm_ml_tvm_func_get(model, module_so, "register_cb", ®ister_cb_fn);
+ if (ret != 0)
+ goto error;
+
+ arg_values[0].v_handle = callback;
+ arg_types[0] = kTVMOpaqueHandle;
+ arg_values[1].v_handle = cnxk_mldev;
+ arg_types[1] = kTVMOpaqueHandle;
+ arg_values[2].v_int64 = model->model_id;
+ arg_types[2] = kDLInt;
+
+ ret = mvtvm_ml_tvm_func_call(model, register_cb_fn, "register_cb", arg_values,
+ arg_types, 3, &ret_value, &ret_type, kTVMNullptr);
+ if (ret != 0)
+ goto error;
+ }
+
+ ret = TVMFuncGetGlobal("tvm.graph_executor.create", &create_fn);
if (ret != 0) {
- plt_err("TVMDP: Failed to get metadata, model_id = %u, error = %d",
- model->model_id, ret);
+ plt_err("TVM runtime: Model load failed, model_id = %u, ret = %d, msg = %s",
+ model->model_id, ret, TVMGetLastError());
goto error;
}
+ arg_values[0].v_str = (const char *)model->mvtvm.json.buffer;
+ arg_types[0] = kTVMStr;
+ arg_values[1].v_handle = module_so;
+ arg_types[1] = kTVMModuleHandle;
+ arg_values[2].v_int64 = device.device_type;
+ arg_types[2] = kDLInt;
+ arg_values[3].v_int64 = device.device_id;
+ arg_types[3] = kDLInt;
+
+ ret = mvtvm_ml_tvm_func_call(model, create_fn, "tvm.graph_executor.create", arg_values,
+ arg_types, 4, &ret_value, &ret_type, kTVMModuleHandle);
+ if (ret != 0)
+ goto error;
+ model->mvtvm.graph_module = ret_value.v_handle;
+
+ ret = mvtvm_ml_tvm_func_get(model, model->mvtvm.graph_module, "load_params",
+ &model->mvtvm.load_params);
+ if (ret != 0)
+ goto error;
+ ret = mvtvm_ml_tvm_func_get(model, model->mvtvm.graph_module, "set_input_zero_copy",
+ &model->mvtvm.set_input_zero_copy);
+ if (ret != 0)
+ goto error;
+ ret = mvtvm_ml_tvm_func_get(model, model->mvtvm.graph_module, "set_output_zero_copy",
+ &model->mvtvm.set_output_zero_copy);
+ if (ret != 0)
+ goto error;
+ ret = mvtvm_ml_tvm_func_get(model, model->mvtvm.graph_module, "run", &model->mvtvm.run);
+ if (ret != 0)
+ goto error;
+
+ mvtvm_ml_tvm_func_free(®ister_cb_fn);
+ mvtvm_ml_tvm_mod_free(&module_so);
+
+ /* Load model parameters into TVM runtime */
+ tvm_params.data = (const char *)model->mvtvm.params.buffer;
+ tvm_params.size = model->mvtvm.params.size;
+ tvm_arg_values[0].v_handle = &tvm_params;
+ tvm_arg_types[0] = kTVMBytes;
+
+ ret = mvtvm_ml_tvm_func_call(model, model->mvtvm.load_params, "load_params", tvm_arg_values,
+ tvm_arg_types, 1, &ret_value, &ret_type, kTVMNullptr);
+ if (ret != 0)
+ goto error;
+
/* Update model I/O data */
mvtvm_ml_model_io_info_set(model);
@@ -310,9 +426,9 @@ mvtvm_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *
/* Update model xstats name */
cnxk_ml_xstats_model_name_update(cnxk_mldev, model->model_id);
- model->mvtvm.burst_xstats = RTE_PTR_ADD(
- model->mvtvm.object.params.addr,
- RTE_ALIGN_CEIL(model->mvtvm.object.params.size, RTE_CACHE_LINE_MIN_SIZE));
+ model->mvtvm.burst_xstats =
+ RTE_PTR_ADD(model->mvtvm.params.buffer,
+ RTE_ALIGN_CEIL(model->mvtvm.params.size, RTE_CACHE_LINE_MIN_SIZE));
for (int qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) {
model->mvtvm.burst_xstats[qp_id].tvm_rt_latency_tot = 0;
@@ -341,7 +457,20 @@ mvtvm_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *
return 0;
error:
- rte_memzone_free(mz);
+ mvtvm_ml_tvm_func_free(®ister_cb_fn);
+ if (model != NULL) {
+ mvtvm_ml_tvm_func_free(&model->mvtvm.load_params);
+ mvtvm_ml_tvm_func_free(&model->mvtvm.set_input_zero_copy);
+ mvtvm_ml_tvm_func_free(&model->mvtvm.set_output_zero_copy);
+ mvtvm_ml_tvm_func_free(&model->mvtvm.run);
+ mvtvm_ml_tvm_mod_free(&model->mvtvm.graph_module);
+ if (model->mvtvm.fd >= 0)
+ close(model->mvtvm.fd);
+ memset(&model->mvtvm, 0, sizeof(model->mvtvm));
+ model->mvtvm.fd = -1;
+ }
+ mvtvm_ml_tvm_mod_free(&module_so);
+ plt_memzone_free(mz);
return ret;
}
@@ -351,20 +480,28 @@ mvtvm_ml_model_unload(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *mode
{
char str[RTE_MEMZONE_NAMESIZE];
const struct plt_memzone *mz;
- int ret;
RTE_SET_USED(cnxk_mldev);
- /* Initialize model in TVMDP */
- ret = tvmdp_model_unload(model->model_id);
- if (ret != 0) {
- plt_err("TVMDP: Model unload failed, model_id = %u, error = %d", model->model_id,
- ret);
- return ret;
- }
+ /* Unload model from TVM runtime */
+ if (model->model_id >= cnxk_mldev->mldev->data->nb_models)
+ return -EINVAL;
+
+ if (model->mvtvm.graph_module == NULL)
+ return -EINVAL;
+
+ mvtvm_ml_tvm_func_free(&model->mvtvm.load_params);
+ mvtvm_ml_tvm_func_free(&model->mvtvm.set_input_zero_copy);
+ mvtvm_ml_tvm_func_free(&model->mvtvm.set_output_zero_copy);
+ mvtvm_ml_tvm_func_free(&model->mvtvm.run);
+ mvtvm_ml_tvm_mod_free(&model->mvtvm.graph_module);
+ if (model->mvtvm.fd >= 0)
+ close(model->mvtvm.fd);
+ memset(&model->mvtvm, 0, sizeof(model->mvtvm));
+ model->mvtvm.fd = -1;
snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u", MVTVM_ML_MODEL_MEMZONE_NAME, model->model_id);
- mz = rte_memzone_lookup(str);
+ mz = plt_memzone_lookup(str);
if (mz == NULL) {
plt_err("Memzone lookup failed for TVM model: model_id = %u, mz = %s",
model->model_id, str);
@@ -455,13 +592,13 @@ mvtvm_ml_io_quantize(void *device, uint16_t model_id, const char *layer_name,
#endif
/* Get layer id */
- for (layer_id = 0; layer_id < model->mvtvm.metadata.model.nb_layers; layer_id++) {
+ for (layer_id = 0; layer_id < model->nb_layers; layer_id++) {
if (strcmp(model->layer[layer_id].name, layer_name) == 0)
break;
}
#ifdef CNXK_ML_DEV_DEBUG
- if (layer_id == model->mvtvm.metadata.model.nb_layers) {
+ if (layer_id == model->nb_layers) {
plt_err("Invalid layer name: %s", layer_name);
return -EINVAL;
}
@@ -516,13 +653,13 @@ mvtvm_ml_io_dequantize(void *device, uint16_t model_id, const char *layer_name,
}
#endif
- for (layer_id = 0; layer_id < model->mvtvm.metadata.model.nb_layers; layer_id++) {
+ for (layer_id = 0; layer_id < model->nb_layers; layer_id++) {
if (strcmp(model->layer[layer_id].name, layer_name) == 0)
break;
}
#ifdef CNXK_ML_DEV_DEBUG
- if (layer_id == model->mvtvm.metadata.model.nb_layers) {
+ if (layer_id == model->nb_layers) {
plt_err("Invalid layer name: %s", layer_name);
return -EINVAL;
}
@@ -553,28 +690,69 @@ static int
mvtvm_ml_model_run(struct cnxk_ml_model *model, struct rte_ml_op *op, struct cnxk_ml_req *req)
{
uint8_t i;
+ struct mvtvm_ml_result *run_result;
+ TVMValue arg_values[2] = {0};
+ int arg_types[2] = {0};
+ TVMValue ret_value = {0};
+ int ret_type = kTVMNullptr;
+ int ret = 0;
rte_memcpy(req->mvtvm_req.input_tensor, model->mvtvm.input_tensor,
- model->mvtvm.metadata.model.num_input * sizeof(DLTensor));
- for (i = 0; i < model->mvtvm.metadata.model.num_input; i++) {
+ model->mvtvm.info.nb_inputs * sizeof(DLTensor));
+ for (i = 0; i < model->mvtvm.info.nb_inputs; i++) {
req->mvtvm_req.input_tensor[i].data = op->input[i]->addr;
req->mvtvm_req.input_tensor[i].byte_offset = 0;
}
rte_memcpy(req->mvtvm_req.output_tensor, model->mvtvm.output_tensor,
- model->mvtvm.metadata.model.num_output * sizeof(DLTensor));
- for (i = 0; i < model->mvtvm.metadata.model.num_output; i++) {
+ model->mvtvm.info.nb_outputs * sizeof(DLTensor));
+ for (i = 0; i < model->mvtvm.info.nb_outputs; i++) {
req->mvtvm_req.output_tensor[i].data = op->output[i]->addr;
req->mvtvm_req.output_tensor[i].byte_offset = 0;
}
- tvmdp_model_run(model->model_id, model->mvtvm.metadata.model.num_input,
- req->mvtvm_req.input_tensor, model->mvtvm.metadata.model.num_output,
- req->mvtvm_req.output_tensor, &req->mvtvm_req.result,
- &req->mvtvm_req.status);
+ run_result = &req->mvtvm_req.result;
+ run_result->stats.start_ns = rte_get_tsc_cycles();
+ run_result->error_code = 0;
+
+ for (i = 0; i < model->mvtvm.info.nb_inputs; i++) {
+ arg_values[0].v_int64 = i;
+ arg_types[0] = kDLInt;
+ arg_values[1].v_handle = &req->mvtvm_req.input_tensor[i];
+ arg_types[1] = kTVMDLTensorHandle;
+ ret = mvtvm_ml_tvm_func_call(model, model->mvtvm.set_input_zero_copy,
+ "set_input_zero_copy", arg_values, arg_types, 2,
+ &ret_value, &ret_type, kTVMNullptr);
+ if (ret != 0)
+ goto out;
+ }
+
+ for (i = 0; i < model->mvtvm.info.nb_outputs; i++) {
+ arg_values[0].v_int64 = i;
+ arg_types[0] = kDLInt;
+ arg_values[1].v_handle = &req->mvtvm_req.output_tensor[i];
+ arg_types[1] = kTVMDLTensorHandle;
+ ret = mvtvm_ml_tvm_func_call(model, model->mvtvm.set_output_zero_copy,
+ "set_output_zero_copy", arg_values, arg_types, 2,
+ &ret_value, &ret_type, kTVMNullptr);
+ if (ret != 0)
+ goto out;
+ }
+
+ ret = mvtvm_ml_tvm_func_call(model, model->mvtvm.run, "run", NULL, NULL, 0, &ret_value,
+ &ret_type, kTVMNullptr);
+ if (ret != 0)
+ goto out;
+
+out:
+ run_result->stats.end_ns = rte_get_tsc_cycles();
+ req->mvtvm_req.status = 0x1;
plt_write64(ML_CNXK_POLL_JOB_FINISH, req->status);
+ if (ret != 0)
+ run_result->error_code = -EIO;
+
return 0;
}
diff --git a/drivers/ml/cnxk/mvtvm_ml_ops.h b/drivers/ml/cnxk/mvtvm_ml_ops.h
index d8f2f361fb1..593f4585b3c 100644
--- a/drivers/ml/cnxk/mvtvm_ml_ops.h
+++ b/drivers/ml/cnxk/mvtvm_ml_ops.h
@@ -7,11 +7,10 @@
#include <dlpack/dlpack.h>
-#include <tvmdp.h>
-
#include <rte_mldev.h>
#include "cnxk_ml_xstats.h"
+#include "mvtvm_ml_model.h"
struct cnxk_ml_dev;
struct cnxk_ml_model;
@@ -56,8 +55,6 @@ struct mvtvm_ml_req {
};
int mvtvm_ml_dev_info_get(struct cnxk_ml_dev *mldev, struct rte_ml_dev_info *dev_info);
-int mvtvm_ml_dev_configure(struct cnxk_ml_dev *cnxk_mldev, const struct rte_ml_dev_config *conf);
-int mvtvm_ml_dev_close(struct cnxk_ml_dev *cnxk_mldev);
int mvtvm_ml_dev_dump(struct cnxk_ml_dev *cnxk_mldev, FILE *fp);
int mvtvm_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *params,
struct cnxk_ml_model *model);
diff --git a/drivers/ml/cnxk/mvtvm_ml_stubs.c b/drivers/ml/cnxk/mvtvm_ml_stubs.c
index 126a954c916..7c13fac42d6 100644
--- a/drivers/ml/cnxk/mvtvm_ml_stubs.c
+++ b/drivers/ml/cnxk/mvtvm_ml_stubs.c
@@ -76,23 +76,6 @@ mvtvm_ml_dev_info_get(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_dev_info *de
return -ENOTSUP;
}
-int
-mvtvm_ml_dev_configure(struct cnxk_ml_dev *cnxk_mldev, const struct rte_ml_dev_config *conf)
-{
- RTE_SET_USED(cnxk_mldev);
- RTE_SET_USED(conf);
-
- return 0;
-}
-
-int
-mvtvm_ml_dev_close(struct cnxk_ml_dev *cnxk_mldev)
-{
- RTE_SET_USED(cnxk_mldev);
-
- return 0;
-}
-
int
mvtvm_ml_dev_dump(struct cnxk_ml_dev *cnxk_mldev, FILE *fp)
{
diff --git a/drivers/ml/cnxk/mvtvm_ml_stubs.h b/drivers/ml/cnxk/mvtvm_ml_stubs.h
index 4220a963f2d..15985a75bf4 100644
--- a/drivers/ml/cnxk/mvtvm_ml_stubs.h
+++ b/drivers/ml/cnxk/mvtvm_ml_stubs.h
@@ -15,8 +15,6 @@ struct cnxk_ml_layer;
enum cnxk_ml_model_type mvtvm_ml_model_type_get(struct rte_ml_model_params *params);
int mvtvm_ml_dev_info_get(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_dev_info *dev_info);
-int mvtvm_ml_dev_configure(struct cnxk_ml_dev *cnxk_mldev, const struct rte_ml_dev_config *conf);
-int mvtvm_ml_dev_close(struct cnxk_ml_dev *cnxk_mldev);
int mvtvm_ml_dev_dump(struct cnxk_ml_dev *cnxk_mldev, FILE *fp);
int mvtvm_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *params,
struct cnxk_ml_model *model);
--
2.34.1
More information about the dev
mailing list