Build-Depends: ninja-build, meson (>=0.50), debhelper (>=9),
gcc-9 | gcc-8 | gcc-7 | gcc-6 | gcc-5, libgtest-dev, python,
libiniparser-dev, pkg-config, cmake, libdrm-dev,
- linux-fvp-headers, npu-engine-emul
+ linux-fvp-headers, npu-engine-emul, libtinyxml2-dev
Standards-Version: 3.8.2
Homepage: https://research.samsung.com
# test
BuildRequires: gtest-devel
BuildRequires: pkgconfig(libdrm)
+BuildRequires: pkgconfig(tinyxml2)
# test coverage dependency
%if 0%{?test_coverage}
{
Buffer *buffer = req->getBuffer ();
output_buffers output = {
- .num_buffers = 1
+ .num_buffers = 0
};
/** TODO: finalize this impl. when the ASR's working scenario is determined */
install_rpath : ne_libdir,
install_dir : join_paths(ne_bindir, 'apptests')
)
+
+tinyxml2_dep = dependency ('tinyxml2')
+executable ('apptest_tvn_triv2_xml',
+ 'tvn_triv2_xml.cc',
+ include_directories : ne_apptest_inc,
+ dependencies : [ne_test_utils_dep, thread_dep, tinyxml2_dep],
+ link_with : ne_library_shared,
+ install : true,
+ install_rpath : ne_libdir,
+ install_dir : join_paths(ne_bindir, 'apptests')
+)
--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2020 Samsung Electronics
+ * Copyright (C) 2020 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file tvn_triv2_xml.cc
+ * @date 07 Sep 2020
+ * @brief AppTest to test models with different constraints using xml input
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+/**
+ * This program requires model descriptions written in .xml file
+ * The below shows the example xml file.
+ *
+ * <testcases>
+ * <model name="mobilenet_v1" timeout="3000" priority="1">
+ * <dirpath>/usr/share/npu-engine/testdata/npubinfmt_v3/MOBILENET_V1</dirpath>
+ * </model>
+ * <model name="mobilenet_v2" timeout="1000" priority="2">
+ * <dirpath>/usr/share/npu-engine/testdata/npubinfmt_v3/MOBILENET_V2</dirpath>
+ * </model>
+ * ...
+ * </testcases>
+ */
+
+#include <string.h>
+#include <unistd.h>
+
+#include <tinyxml2.h>
+#include <ne_test_utils.h>
+
+using namespace std;
+using namespace tinyxml2;
+
+class Tester : public UtilTRIV2
+{
+ public:
+ Tester () : total_ (0), debug_ (false), sync_ (false) {}
+
+ void set_debug () {
+ debug_ = true;
+ }
+
+ void set_mute () {
+ /** redirect to /dev/null */
+ if (freopen("/dev/null", "w", stdout) == NULL)
+ cerr << "Warning: Failed to reopen stdout\n";
+ if (freopen("/dev/null", "w", stderr) == NULL)
+ cerr << "Warning: Failed to reopen stderr\n";
+ }
+
+ void set_sync () {
+ sync_ = true;
+ }
+
+ int parse_xml (XMLDocument& xml) {
+ XMLElement *root = xml.RootElement ();
+ if (root == nullptr)
+ return -EINVAL;
+
+ XMLElement *elem = root->FirstChildElement ("model");
+ while (elem != nullptr) {
+ int priority = elem->IntAttribute ("priority");
+ int timeout = elem->IntAttribute ("timeout");
+
+ if (priority < NPU_PRIORITY_LOW ||
+ priority > NPU_PRIORITY_HIGH ||
+ timeout < 0)
+ return -EINVAL;
+
+ XMLElement *item = elem->FirstChildElement ("dirpath");
+ if (item == nullptr)
+ return -EINVAL;
+
+ if (UtilTRIV2::loadModel (item->GetText (), nullptr,
+ static_cast<npu_priority>(priority), timeout) != 0)
+ return -EINVAL;
+
+ total_++;
+ elem = elem->NextSiblingElement ("model");
+ }
+
+ return 0;
+ }
+
+ int init (string xml_file) {
+ int status = UtilTRIV2::init ();
+ if (status != 0) {
+ cerr << "Failed to initialize\n";
+ return status;
+ }
+
+ XMLDocument doc;
+ if (doc.LoadFile (xml_file.c_str ()) != XML_NO_ERROR) {
+ cerr << "Unable to find the given xml file\n";
+ return -ENOENT;
+ }
+
+ status = parse_xml (doc);
+ if (status != 0) {
+ cerr << "Invalid model description detected\n";
+ return status;
+ }
+
+ return 0;
+ }
+
+ int run () {
+ passed_ = 0;
+ done_ = 0;
+
+ int status = UtilTRIV2::runAll (callback, sync_);
+ if (status != 0) {
+ cerr << "Failed to run the model: " << status << "\n";
+ return status;
+ }
+
+ wait_runs ();
+
+ return passed_ == total_ ? 0 : -EINVAL;
+ }
+
+ void wait_runs () {
+ unique_lock<mutex> lock (m_);
+ cv_.wait (lock, [this]() { return done_ == total_; });
+ }
+
+ static void callback (output_buffers *output, uint64_t sequence,
+ void *data) {
+ const char *dirpath = static_cast<const char *> (data);
+ int err = 0;
+
+ for (uint32_t idx = 0; idx < output->num_buffers; idx++) {
+ char * output_data = static_cast<char*> (output->bufs[idx].addr);
+ off_t output_size = output->bufs[idx].size;
+ std::string golden_path (dirpath);
+
+ golden_path += "/output_fmap_" + std::to_string (idx) + ".bin";
+ err = compare_data (golden_path.c_str(), output_data, output_size);
+ free (output_data);
+
+ if (err != 0)
+ break;
+ }
+
+ report (err == 0);
+ }
+
+ static void report (bool passed) {
+ unique_lock<mutex> lock (m_);
+ done_++;
+ if (passed)
+ passed_++;
+ cv_.notify_one ();
+ }
+
+ private:
+ static mutex m_;
+ static condition_variable cv_;
+ static uint32_t done_;
+ static uint32_t passed_;
+
+ uint32_t total_;
+ bool debug_;
+ bool sync_;
+};
+
+mutex Tester::m_;
+condition_variable Tester::cv_;
+uint32_t Tester::done_ = 0;
+uint32_t Tester::passed_ = 0;
+
+static void
+print_usage (const char *prog_name)
+{
+ cerr << "Usage: " << prog_name << " [options] [.xml file]\n";
+ cerr << "Options: \n";
+ cerr << " -h \t\t Show help messages\n";
+ cerr << " -m \t\t Mute stdout/stderr messages\n";
+ cerr << " -d \t\t Enable debugging mode\n";
+ cerr << " -s \t\t Enable run sync mode\n";
+}
+
+/** @brief apptest main */
+int
+main (int argc, char **argv)
+{
+ Tester tester;
+ int c, status;
+
+ optind = 0;
+ opterr = 0;
+ while ((c = getopt (argc, argv, "dmsh")) != -1) {
+ switch (c) {
+ case 'd':
+ tester.set_debug ();
+ break;
+ case 'm':
+ tester.set_mute ();
+ break;
+ case 's':
+ tester.set_sync ();
+ break;
+ case 'h':
+ print_usage(argv[0]);
+ return 0;
+ }
+ }
+
+ if (optind >= argc) {
+ cerr << "[APPTEST] " << argv[0] << ": SKIPPED\n";
+ return 0;
+ }
+
+ /** initialize triv2 device */
+ status = tester.init (argv[optind]);
+ if (status != 0)
+ goto err;
+
+ /** run the inference with the device */
+ status = tester.run ();
+ if (status != 0)
+ goto err;
+
+ cerr << "[APPTEST] " << argv[0] << ": PASSED\n";
+ return 0;
+
+err:
+ cerr << "[APPTEST] " << argv[0] << ": FAILED (" << status << ")\n";
+ return status;
+}
putNPUdevice (dev);
}
-class TesterTrinity {
- public:
- TesterTrinity () : done_ (0), repeat_ (0) {}
-
- void wait_runs () {
- std::unique_lock<std::mutex> lock (m_);
- cv_.wait (lock, [this]() { return done_ == repeat_; });
- }
-
- void setRepeat (uint32_t repeat) { repeat_ = repeat; }
-
- static void callback (output_buffers *output, uint64_t sequence,
- void *data) {
- TesterTrinity *tester = static_cast<TesterTrinity *>(data);
- tester->finish (output);
- }
-
- private:
- void finish (output_buffers * output) {
- for (uint32_t idx = 0; idx < output->num_buffers; idx++) {
- char * output_data = static_cast<char*> (output->bufs[idx].addr);
- /* do nothing */
- free (output_data);
-
- }
-
- std::unique_lock<std::mutex> lock (m_);
- done_++;
- cv_.notify_one ();
- }
-
- uint32_t done_;
- uint32_t repeat_;
-
- std::mutex m_;
- std::condition_variable cv_;
+struct test_sync {
+ std::mutex m;
+ std::condition_variable cv;
+ int done;
};
-class TesterTRIA : public TesterTrinity, public UtilTRIA {
- public:
- TesterTRIA () {}
-};
+static struct test_sync tsync;
-class TesterTRIV : public TesterTrinity, public UtilTRIV {
- public:
- TesterTRIV () {}
-};
+static void wait_runs (int total)
+{
+ std::unique_lock<std::mutex> lock (tsync.m);
+ tsync.cv.wait (lock, [&]() { return tsync.done == total; });
+}
-class TesterTRIV2 : public TesterTrinity, public UtilTRIV2 {
- public:
- TesterTRIV2 () {}
-};
+/**
+ * @brief dummy callback for testing
+ */
+static void callback (output_buffers *output,
+ uint64_t sequence, void *data)
+{
+ for (uint32_t idx = 0; idx < output->num_buffers; idx++) {
+ /* do not check the validity of output data */
+ free (output->bufs[idx].addr);
+ }
+
+ std::unique_lock<std::mutex> lock (tsync.m);
+ tsync.done++;
+ tsync.cv.notify_one ();
+}
/**
* @brief test APIs to run model with input data (TRIV)
*/
TEST (ne_libnpuhost_test, run_input_triv_binfmt_v1)
{
- TesterTRIV tester;
+ UtilTRIV tester;
ASSERT_EQ (tester.init (), 0);
std::string model_dir (NE_DATADIR);
model_dir += "/testdata/npubinfmt_v1/testcase1";
- tester.setModelDir (model_dir);
- if (tester.loadModel () != 0)
- return;
-
- const npubin_meta *meta = tester.getMetadata ();
- ASSERT_NE (meta, nullptr);
-
- /* prepare input */
- std::string input_path = model_dir + "/input_fmap.bin";
+ uint32_t model_id = 0;
- input_buffers input;
- input.num_buffers = 1;
+ tsync.done = 0;
- input.bufs[0].size = get_file_size (input_path.c_str ());
- input.bufs[0].filepath = input_path.c_str ();
- input.bufs[0].type = BUFFER_FILE;
+ if (tester.loadModel (model_dir, &model_id) != 0)
+ /* skip */
+ return;
- /* run input */
- output_buffers output;
- EXPECT_EQ (tester.run (&input, &output), 0);
+ EXPECT_EQ (tester.run (model_id, callback, true), 0);
+ EXPECT_EQ (tester.run (model_id, callback, false), 0);
+ EXPECT_EQ (tester.runAll (callback, true), 0);
+ EXPECT_EQ (tester.runAll (callback, false), 0);
- tester.setRepeat (3);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- tester.wait_runs ();
+ wait_runs (4);
}
/**
*/
TEST (ne_libnpuhost_test, run_input_triv_binfmt_v1_n)
{
- TesterTRIV tester;
+ UtilTRIV tester;
+
+ /* without init */
+ EXPECT_NE (tester.run (0, callback, true), 0);
+ EXPECT_NE (tester.run (0, callback, false), 0);
ASSERT_EQ (tester.init (), 0);
+ /* run without model */
+ EXPECT_NE (tester.run (0, callback, true), 0);
+ EXPECT_NE (tester.run (0, callback, false), 0);
+
+ /* invalid model id */
std::string model_dir (NE_DATADIR);
model_dir += "/testdata/npubinfmt_v1/testcase1";
- tester.setModelDir (model_dir);
- if (tester.loadModel () != 0)
- return;
-
- const npubin_meta *meta = tester.getMetadata ();
- ASSERT_NE (meta, nullptr);
-
- /* without input */
- EXPECT_NE (tester.run (nullptr, nullptr), 0);
+ uint32_t model_id = 0;
- input_buffers input;
- output_buffers output;
+ if (tester.loadModel (model_dir, &model_id) != 0)
+ /* skip */
+ return;
- input.num_buffers = 0;
- EXPECT_NE (tester.run (&input, &output), 0);
- EXPECT_NE (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
+ EXPECT_NE (tester.run (model_id + 1, callback, true), 0);
}
/**
*/
TEST (ne_libnpuhost_test, run_input_triv_binfmt_v2)
{
- TesterTRIV tester;
+ UtilTRIV tester;
ASSERT_EQ (tester.init (), 0);
std::string model_dir (NE_DATADIR);
model_dir += "/testdata/npubinfmt_v2/testcase1";
- tester.setModelDir (model_dir);
- if (tester.loadModel () != 0)
- return;
+ uint32_t model_id = 0;
- const npubin_meta *meta = tester.getMetadata ();
- ASSERT_NE (meta, nullptr);
+ tsync.done = 0;
- /* prepare input */
- std::vector<std::string> input_path;
- input_buffers input;
+ if (tester.loadModel (model_dir, &model_id) != 0)
+ /* skip */
+ return;
- input_path.resize (meta->input_num);
- input.num_buffers = meta->input_num;
- for (uint32_t idx = 0; idx < meta->input_num; idx++) {
- input_path[idx] = model_dir + "/input_fmap_" + std::to_string (idx) + ".bin";
- input.bufs[idx].size = get_file_size (input_path[idx].c_str ());
- input.bufs[idx].filepath = input_path[idx].c_str ();
- input.bufs[idx].type = BUFFER_FILE;
- }
+ EXPECT_EQ (tester.run (model_id, callback, true), 0);
+ EXPECT_EQ (tester.run (model_id, callback, false), 0);
+
+ EXPECT_EQ (tester.runAll (callback, true), 0);
+ EXPECT_EQ (tester.runAll (callback, false), 0);
- /* run input */
- output_buffers output;
- EXPECT_EQ (tester.run (&input, &output), 0);
-
- tester.setRepeat (3);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- tester.wait_runs ();
+ wait_runs (4);
}
/**
*/
TEST (ne_libnpuhost_test, run_input_triv_binfmt_v2_n)
{
- TesterTRIV tester;
+ UtilTRIV tester;
+
+ /* without init */
+ EXPECT_NE (tester.run (0, callback, true), 0);
+ EXPECT_NE (tester.run (0, callback, false), 0);
ASSERT_EQ (tester.init (), 0);
+ /* run without model */
+ EXPECT_NE (tester.run (0, callback, true), 0);
+ EXPECT_NE (tester.run (0, callback, false), 0);
+
+ /* invalid model id */
std::string model_dir (NE_DATADIR);
model_dir += "/testdata/npubinfmt_v2/testcase1";
- tester.setModelDir (model_dir);
- if (tester.loadModel () != 0)
- return;
-
- const npubin_meta *meta = tester.getMetadata ();
- ASSERT_NE (meta, nullptr);
-
- /* without input */
- EXPECT_NE (tester.run (nullptr, nullptr), 0);
-
- input_buffers input;
- output_buffers output;
+ uint32_t model_id = 0;
- input.num_buffers = 0;
+ if (tester.loadModel (model_dir, &model_id) != 0)
+ /* skip */
+ return;
- EXPECT_NE (tester.run (&input, &output), 0);
- EXPECT_NE (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
+ EXPECT_NE (tester.run (model_id + 1, callback, true), 0);
}
#if defined(ENABLE_EMUL)
*/
TEST (ne_libnpuhost_test, run_input_tria)
{
- TesterTRIA tester;
+ UtilTRIA tester;
ASSERT_EQ (tester.init (), 0);
- /* run input */
- input_buffers input;
- input.num_buffers = 1;
- input.bufs[0].size = 4096;
- input.bufs[0].type = BUFFER_MAPPED;
-
- ASSERT_EQ (allocNPU_inputBuffers (tester.getDeviceHandle (), &input), 0);
+ tsync.done = 0;
- output_buffers output;
- EXPECT_EQ (tester.run (&input, &output), 0);
+ EXPECT_EQ (tester.run (0, callback, true), 0);
+ EXPECT_EQ (tester.run (0, callback, false), 0);
- tester.setRepeat (3);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- tester.wait_runs ();
-
- cleanNPU_inputBuffers (tester.getDeviceHandle (), &input);
+ wait_runs (2);
}
/**
*/
TEST (ne_libnpuhost_test, run_input_tria_n)
{
- TesterTRIA tester;
+ UtilTRIA tester;
- ASSERT_EQ (tester.init (), 0);
-
- /* without input */
- EXPECT_NE (tester.run (nullptr, nullptr), 0);
-
- input_buffers input;
- output_buffers output;
-
- input.num_buffers = 0;
- EXPECT_NE (tester.run (&input, &output), 0);
- EXPECT_NE (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
+ /* without init */
+ EXPECT_NE (tester.run (0, callback, true), 0);
+ EXPECT_NE (tester.run (0, callback, false), 0);
}
#endif
*/
TEST (ne_libnpuhost_test, run_input_triv2_binfmt_v3)
{
- TesterTRIV2 tester;
+ UtilTRIV2 tester;
ASSERT_EQ (tester.init (), 0);
std::string model_dir (NE_DATADIR);
model_dir += "/testdata/npubinfmt_v3/CONV_I8_008";
- tester.setModelDir (model_dir);
- if (tester.loadModel () != 0)
- return;
-
- const npubin_meta *meta = tester.getMetadata ();
- ASSERT_NE (meta, nullptr);
+ uint32_t model_id = 0;
- /* prepare input */
- std::vector<std::string> input_path;
- input_buffers input;
+ tsync.done = 0;
- input_path.resize (meta->input_seg_num);
- input.num_buffers = meta->input_seg_num;
- for (uint32_t idx = 0; idx < meta->input_seg_num; idx++) {
- input_path[idx] = model_dir + "/input_fmap_" + std::to_string (idx) + ".bin";
- input.bufs[idx].size = get_file_size (input_path[idx].c_str ());
- input.bufs[idx].filepath = input_path[idx].c_str ();
- input.bufs[idx].type = BUFFER_FILE;
- }
+ if (tester.loadModel (model_dir, &model_id) != 0)
+ /* skip */
+ return;
- /* run input */
- output_buffers output;
- EXPECT_EQ (tester.run (&input, &output), 0);
+ EXPECT_EQ (tester.run (model_id, callback, true), 0);
+ EXPECT_EQ (tester.run (model_id, callback, false), 0);
- tester.setRepeat (3);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
- EXPECT_EQ (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
+ EXPECT_EQ (tester.runAll (callback, true), 0);
+ EXPECT_EQ (tester.runAll (callback, false), 0);
- tester.wait_runs ();
+ wait_runs (4);
}
/**
*/
TEST (ne_libnpuhost_test, run_input_triv2_binfmt_v3_n)
{
- TesterTRIV2 tester;
+ UtilTRIV2 tester;
+
+ /* without init */
+ EXPECT_NE (tester.run (0, callback, true), 0);
+ EXPECT_NE (tester.run (0, callback, false), 0);
ASSERT_EQ (tester.init (), 0);
+ /* run without model */
+ EXPECT_NE (tester.run (0, callback, true), 0);
+ EXPECT_NE (tester.run (0, callback, false), 0);
+
+ /* invalid model id */
std::string model_dir (NE_DATADIR);
model_dir += "/testdata/npubinfmt_v3/CONV_I8_008";
- tester.setModelDir (model_dir);
- if (tester.loadModel () != 0)
- return;
-
- const npubin_meta *meta = tester.getMetadata ();
- ASSERT_NE (meta, nullptr);
-
- /* without input */
- EXPECT_NE (tester.run (nullptr, nullptr), 0);
+ uint32_t model_id = 0;
- input_buffers input;
- output_buffers output;
+ if (tester.loadModel (model_dir, &model_id) != 0)
+ /* skip */
+ return;
- input.num_buffers = 0;
- EXPECT_NE (tester.run (&input, &output), 0);
- EXPECT_NE (tester.run (&input, TesterTrinity::callback,
- dynamic_cast<TesterTrinity *>(&tester)), 0);
+ EXPECT_NE (tester.run (model_id + 1, callback, true), 0);
}
/**
*/
TEST (ne_libnpuhost_test, run_internal_triv2_binfmt_v3)
{
- TesterTRIV2 tester;
+ UtilTRIV2 tester;
ASSERT_EQ (tester.init (), 0);
std::string model_dir (NE_DATADIR);
model_dir += "/testdata/npubinfmt_v3/CONV_I8_008";
- tester.setModelDir (model_dir);
- if (tester.loadModel () != 0)
- return;
+ uint32_t model_id = 0;
- const npubin_meta *meta = tester.getMetadata ();
- ASSERT_NE (meta, nullptr);
+ if (tester.loadModel (model_dir, &model_id) != 0)
+ /* skip */
+ return;
/* run internal */
- int id = tester.run ("/dev/triv2-0");
+ int id = tester.runInternal (model_id, "/dev/triv2-0");
EXPECT_GT (id, 0);
usleep (TEST_SLEEP_MS);
- EXPECT_EQ (tester.stop (id), 0);
+ EXPECT_EQ (tester.stopInternal (id), 0);
}
/**
*/
TEST (ne_libnpuhost_test, run_internal_triv2_binfmt_v3_n)
{
- TesterTRIV2 tester;
+ UtilTRIV2 tester;
ASSERT_EQ (tester.init (), 0);
/* without model */
- EXPECT_NE (tester.run ("/dev/triv2-0"), 0);
+ EXPECT_NE (tester.runInternal (0, "/dev/triv2-0"), 0);
/* TODO: taskid of stop() is currently not checked */
#if 0
std::string model_dir (NE_DATADIR);
model_dir += "/testdata/npubinfmt_v3/CONV_I8_008";
- tester.setModelDir (model_dir);
- if (tester.loadModel () != 0)
- return;
+ uint32_t model_id = 0;
- const npubin_meta *meta = tester.getMetadata ();
- ASSERT_NE (meta, nullptr);
+ EXPECT_EQ (tester.loadModel (model_dir, &model_id), 0);
/* invalid id */
- int id = tester.run ("/dev/triv2-0");
+ int id = tester.runInternal (model_id, "/dev/triv2-0");
ASSERT_GT (id, 0);
usleep (TEST_SLEEP_MS);
- EXPECT_NE (tester.stop (id + 1), 0);
- EXPECT_EQ (tester.stop (id), 0);
+ EXPECT_NE (tester.stopInternal (id + 1), 0);
+ EXPECT_EQ (tester.stopInternal (id), 0);
#endif
}
}
/** @brief constructor of UtilTrinity */
-UtilTrinity::UtilTrinity (dev_type type)
+UtilTrinity::UtilTrinity (dev_type type, bool need_model)
{
dev_ = nullptr;
type_ = type;
- meta_ = nullptr;
- version_ = 0;
- model_id_ = 0;
noti_mode_ = NPU_INTERRUPT;
+ need_model_ = need_model;
}
/** @brief destructor of UtilTrinity */
putNPUdevice (dev_);
}
- if (meta_ != nullptr)
- free (meta_);
+ models_.clear ();
}
/** @brief initialize trinity device and get the device handle */
}
/** @brief load NPU model and set relevant info */
-int UtilTrinity::loadModel ()
+int UtilTrinity::loadModel (std::string dirpath, uint32_t *model_id_ptr,
+ npu_priority priority, uint32_t timeout)
{
- if (model_dir_ == "")
+ if (dirpath == "")
return -EINVAL;
- std::string model_path;
-
- model_path = model_dir_ + "/model.tvn";
- meta_ = getNPUmodel_metadata (model_path.c_str(), false);
- if (meta_ == nullptr)
+ std::string model_path = dirpath + "/model.tvn";
+ npubin_meta * meta = getNPUmodel_metadata (model_path.c_str(), false);
+ if (meta == nullptr)
return -EINVAL;
- version_ = NPUBIN_VERSION (meta_->magiccode);
- if (!check_version ())
- return -EINVAL;
+ generic_buffer model_buf;
+ UtilModel *model;
+ uint32_t model_id;
+ int status = -EINVAL;
- generic_buffer model;
- model.type = BUFFER_FILE;
- model.size = meta_->size;
- model.filepath = model_path.c_str();
+ if (!check_version (meta))
+ goto free_meta;
- int status = allocNPU_modelBuffer (dev_, &model);
- if (status != 0)
- return status;
+ model_buf.type = BUFFER_FILE;
+ model_buf.size = meta->size;
+ model_buf.filepath = model_path.c_str();
- status = registerNPUmodel (dev_, &model, &model_id_);
- cleanNPU_modelBuffer (dev_, &model);
+ status = registerNPUmodel (dev_, &model_buf, &model_id);
if (status != 0)
- return status;
+ goto free_meta;
- status = set_data_info ();
+ status = set_data_info (meta, model_id);
if (status != 0)
- return status;
+ goto free_meta;
- status = set_constraint ();
+ status = set_constraint (model_id, timeout, priority);
if (status != 0)
+ goto free_meta;
+
+ model = new UtilModel;
+ model->setMetadata (meta);
+ model->setDirpath (dirpath);
+ model->setModelID (model_id);
+
+ status = prepare_input (model);
+ if (status != 0) {
+ delete model;
return status;
+ }
+
+ models_.push_back (std::unique_ptr<UtilModel>(model));
+ if (model_id_ptr)
+ *model_id_ptr = model_id;
+
+ return 0;
+
+free_meta:
+ free (meta);
+ return status;
+}
+
+/** @brief find the utility model instance */
+UtilModel *UtilTrinity::findModel (uint32_t model_id)
+{
+ for (auto& model : models_) {
+ if (model->getModelID () == model_id)
+ return model.get ();
+ }
+
+ return nullptr;
+}
+
+/** @brief run inference with the given model info */
+int UtilTrinity::run_each (UtilModel *model, npuOutputNotify cb, bool sync)
+{
+ int status = -EINVAL;
+ void *cb_data = nullptr;
+
+ if (cb == nullptr)
+ return -EINVAL;
+
+ if (need_model_ && model == nullptr)
+ return -ENOENT;
+
+ if (model)
+ cb_data = const_cast <char *> (model->getDirpath ().c_str ());
+
+ if (sync) {
+ output_buffers output;
+
+ if (model) {
+ status = runNPU_sync (dev_, model->getModelID (), model->getInput (),
+ &output);
+ } else {
+ /* TODO: revise this when TRIA is implemented */
+ input_buffers input;
+ input.num_buffers = 1;
+ input.bufs[0].size = 4096;
+ input.bufs[0].type = BUFFER_MAPPED;
+
+ status = allocNPU_inputBuffers (dev_, &input);
+ if (status != 0)
+ return status;
+
+ status = runNPU_sync (dev_, 0, &input, &output);
+ cleanNPU_inputBuffers (dev_, &input);
+ }
+
+ if (status != 0)
+ return status;
+
+ cb (&output, 0, cb_data);
+ } else {
+ if (model) {
+ status = runNPU_async (dev_, model->getModelID (), model->getInput (),
+ cb, NULL, cb_data, NPUASYNC_WAIT);
+ } else {
+ /* TODO: revise this when TRIA is implemented */
+ input_buffers input;
+ input.num_buffers = 1;
+ input.bufs[0].size = 4096;
+ input.bufs[0].type = BUFFER_MAPPED;
+
+ status = allocNPU_inputBuffers (dev_, &input);
+ if (status != 0)
+ return status;
+
+ status = runNPU_async (dev_, 0, &input, cb, NULL, cb_data, NPUASYNC_WAIT);
+ cleanNPU_inputBuffers (dev_, &input);
+ }
+
+ if (status != 0)
+ return status;
+ }
return 0;
}
-/** @brief run inference in sync mode */
-int UtilTrinity::run (input_buffers *input, output_buffers *output)
+/** @brief run inference with the given model id */
+int UtilTrinity::run (uint32_t model_id, npuOutputNotify cb, bool sync)
{
- return runNPU_sync (dev_, model_id_, input, output);
+ UtilModel *model = findModel (model_id);
+
+ return run_each (model, cb, sync);
}
-/** @brief run inference in async mode */
-int UtilTrinity::run (input_buffers *input, npuOutputNotify cb,
- void *cb_data)
+/** @brief run inference across all registered models */
+int UtilTrinity::runAll (npuOutputNotify cb, bool sync)
{
- return runNPU_async (dev_, model_id_, input, cb,
- NULL, cb_data, NPUASYNC_WAIT);
+ for (auto& model : models_) {
+ int status = run_each (model.get (), cb, sync);
+ if (status != 0)
+ return status;
+ }
+
+ return 0;
}
/** @brief run inference with internal input */
-int UtilTrinity::run (std::string dev_path)
+int UtilTrinity::runInternal (uint32_t model_id, std::string dev_path)
{
- return runNPU_internalInput (dev_, model_id_, NPUINPUT_HW_RECURRING,
+ return runNPU_internalInput (dev_, model_id, NPUINPUT_HW_RECURRING,
dev_path.c_str ());
}
/** @brief stop inference from run_internal */
-int UtilTrinity::stop (int id)
+int UtilTrinity::stopInternal (int task_id)
{
- return stopNPU_internalInput (dev_, id);
+ return stopNPU_internalInput (dev_, task_id);
+}
+
+/** @brief configure constraint for the model */
+int UtilTrinity::set_constraint (uint32_t model_id, uint32_t timeout,
+ npu_priority priority) {
+ npuConstraint constraint;
+
+ constraint.timeout_ms = timeout;
+ constraint.priority = priority;
+ constraint.notimode = noti_mode_;
+
+ return setNPU_constraint (dev_, model_id, constraint);
}
/** @brief implementation of check_version for TRIV */
-bool UtilTRIV::check_version () {
- if (!meta_)
- return false;
- return (version_ == 1 || version_ == 2);
+bool UtilTRIV::check_version (npubin_meta *meta) {
+ uint64_t version = NPUBIN_VERSION (meta->magiccode);
+ return (version <= 2);
}
/** @brief implementation of set_data_info for TRIV */
-int UtilTRIV::set_data_info () {
+int UtilTRIV::set_data_info (npubin_meta *meta, uint32_t model_id) {
tensors_data_info info_in;
tensors_data_info info_out;
- if (version_ == 1) {
+ if (NPUBIN_VERSION (meta->magiccode) <= 1) {
info_in.num_info = 1;
info_in.info[0].layout = DATA_LAYOUT_SRNPU;
info_in.info[0].type = DATA_TYPE_SRNPU;
info_out.info[0].layout = DATA_LAYOUT_SRNPU;
info_out.info[0].type = DATA_TYPE_SRNPU;
} else {
- info_in.num_info = meta_->input_num;
+ info_in.num_info = meta->input_num;
for (uint32_t idx = 0; idx < info_in.num_info; idx++) {
info_in.info[idx].layout = DATA_LAYOUT_SRNPU;
info_in.info[idx].type = DATA_TYPE_SRNPU;
}
- info_out.num_info = meta_->output_num;
+ info_out.num_info = meta->output_num;
for (uint32_t idx = 0; idx < info_out.num_info; idx++) {
info_out.info[idx].layout = DATA_LAYOUT_SRNPU;
info_out.info[idx].type = DATA_TYPE_SRNPU;
}
}
- return setNPU_dataInfo (dev_, model_id_, &info_in, &info_out);
+ return setNPU_dataInfo (dev_, model_id, &info_in, &info_out);
}
-/** @brief implementation of set_constraint for TRIV */
-int UtilTRIV::set_constraint () {
- npuConstraint constraint;
-
- constraint.timeout_ms = 5000;
- constraint.priority = NPU_PRIORITY_MID;
- constraint.notimode = noti_mode_;
+int UtilTRIV::prepare_input (UtilModel* model) {
+ input_buffers *input = model->getInput ();
+ npubin_meta *meta = model->getMetadata ();
+ std::string dirpath = model->getDirpath ();
+ uint32_t input_num;
- return setNPU_constraint (dev_, model_id_, constraint);
-}
-
-/** @brief implementation of check_version for TRIA */
-bool UtilTRIA::check_version () {
- if (!meta_)
- return false;
- return (version_ == 1 || version_ == 2);
-}
+ if (NPUBIN_VERSION (meta->magiccode) <= 1) {
+ input_num = 1;
+ } else {
+ input_num = meta->input_num;
+ }
-/** @brief implementation of set_data_info for TRIA */
-int UtilTRIA::set_data_info () {
- /* no need to specify data info */
- return 0;
-}
+ model->prepareInputPath (input_num);
+ input->num_buffers = input_num;
-/** @brief implementation of set_constraint for TRIA */
-int UtilTRIA::set_constraint () {
- npuConstraint constraint;
+ for (uint32_t idx = 0; idx < input_num; idx++) {
+ const char *input_path = model->getInputPath (idx);
- constraint.timeout_ms = 5000;
- constraint.priority = NPU_PRIORITY_MID;
- constraint.notimode = noti_mode_;
+ input->bufs[idx].size = get_file_size (input_path);
+ input->bufs[idx].filepath = input_path;
+ input->bufs[idx].type = BUFFER_FILE;
+ }
- return setNPU_constraint (dev_, model_id_, constraint);
+ return 0;
}
/** @brief implementation of check_version for TRIV2 */
-bool UtilTRIV2::check_version () {
- if (!meta_)
- return false;
- return (version_ == 3);
+bool UtilTRIV2::check_version (npubin_meta *meta) {
+ uint64_t version = NPUBIN_VERSION (meta->magiccode);
+ return (version == 3);
}
/** @brief implementation of set_data_info for TRIV2 */
-int UtilTRIV2::set_data_info () {
+int UtilTRIV2::set_data_info (npubin_meta *meta, uint32_t model_id) {
tensors_data_info info_in;
tensors_data_info info_out;
- info_in.num_info = meta_->input_seg_num;
+ info_in.num_info = meta->input_seg_num;
for (uint32_t idx = 0; idx < info_in.num_info; idx++) {
info_in.info[idx].layout = DATA_LAYOUT_TRIV2;
info_in.info[idx].type = DATA_TYPE_QASYMM8;
}
- info_out.num_info = meta_->output_seg_num;
+ info_out.num_info = meta->output_seg_num;
for (uint32_t idx = 0; idx < info_out.num_info; idx++) {
info_out.info[idx].layout = DATA_LAYOUT_TRIV2;
info_out.info[idx].type = DATA_TYPE_QASYMM8;
}
- return setNPU_dataInfo (dev_, model_id_, &info_in, &info_out);
+ return setNPU_dataInfo (dev_, model_id, &info_in, &info_out);
}
-/** @brief implementation of set_constraint for TRIV2 */
-int UtilTRIV2::set_constraint () {
- npuConstraint constraint;
+int UtilTRIV2::prepare_input (UtilModel* model) {
+ input_buffers *input = model->getInput ();
+ npubin_meta *meta = model->getMetadata ();
+ std::string dirpath = model->getDirpath ();
- constraint.timeout_ms = 5000;
- constraint.priority = NPU_PRIORITY_MID;
- constraint.notimode = noti_mode_;
+ model->prepareInputPath (meta->input_seg_num);
+ input->num_buffers = meta->input_seg_num;
- return setNPU_constraint (dev_, model_id_, constraint);
+ for (uint32_t idx = 0; idx < meta->input_seg_num; idx++) {
+ const char *input_path = model->getInputPath (idx);
+
+ input->bufs[idx].size = get_file_size (input_path);
+ input->bufs[idx].filepath = input_path;
+ input->bufs[idx].type = BUFFER_FILE;
+ }
+
+ return 0;
}
#include <string>
#include <mutex>
#include <condition_variable>
+#include <vector>
+/** @brief utility to access test model */
+class UtilModel {
+ public:
+ UtilModel () : meta_ (nullptr) {}
+ ~UtilModel () { if (meta_) free (meta_); }
+
+ void setMetadata (npubin_meta *meta) { meta_ = meta; }
+ void setDirpath (std::string dirpath) { dirpath_ = dirpath; }
+ void setModelID (uint32_t model_id) { model_id_ = model_id; }
+ void prepareInputPath (uint32_t num) {
+ if (NPUBIN_VERSION (meta_->magiccode) <= 1) {
+ inpath_.resize (1);
+ inpath_[0] = dirpath_ + "/input_fmap.bin";
+ } else {
+ inpath_.resize (num);
+ for (uint32_t idx = 0; idx < num; idx++)
+ inpath_[idx] = dirpath_ + "/input_fmap_" + std::to_string (idx) + ".bin";
+ }
+ }
+
+ const char *getInputPath (uint32_t idx) { return inpath_[idx].c_str (); }
+ npubin_meta *getMetadata () { return meta_; }
+ std::string& getDirpath () { return dirpath_; }
+ uint32_t getModelID () { return model_id_; }
+ input_buffers* getInput () { return &input_; }
+
+ private:
+ npubin_meta *meta_;
+ uint32_t model_id_;
+
+ std::string dirpath_;
+
+ input_buffers input_;
+ std::vector<std::string> inpath_;
+};
+
+/** @brief utility to access trinity device */
class UtilTrinity {
public:
- UtilTrinity (dev_type type);
+ UtilTrinity (dev_type type, bool need_model);
~UtilTrinity ();
npudev_h getDeviceHandle () { return dev_; }
- void setModelDir (std::string model_dir) { model_dir_ = model_dir; }
- std::string getModelDir () { return model_dir_; }
-
- const npubin_meta * getMetadata () { return meta_; }
-
void setNotiMode (npu_notimode noti_mode) { noti_mode_ = noti_mode; }
int init ();
- int loadModel ();
+ int loadModel (std::string dirpath, uint32_t *model_id,
+ npu_priority priority = NPU_PRIORITY_MID,
+ uint32_t timeout = 5000);
+ int run (uint32_t model_id, npuOutputNotify cb, bool sync = false);
+ int runAll (npuOutputNotify cb, bool sync = false);
+
+ int runInternal (uint32_t model_id, std::string dev_path);
+ int stopInternal (int task_id);
- int run (input_buffers *input, output_buffers *output);
- int run (input_buffers *input, npuOutputNotify cb, void *cb_data);
- int run (std::string dev_path);
- int stop (int id);
+ UtilModel *findModel (uint32_t model_id);
protected:
npudev_h dev_;
npu_notimode noti_mode_;
-
- /* model parameters */
- uint32_t model_id_;
- uint64_t version_;
- std::string model_dir_;
- npubin_meta *meta_;
+ std::vector<std::unique_ptr<UtilModel>> models_;
+ bool need_model_;
private:
- virtual bool check_version () { return false; }
- virtual int set_data_info () { return -EPERM; }
- virtual int set_constraint () { return -EPERM; }
+ int set_constraint (uint32_t model_id, uint32_t timeout, npu_priority priority);
+ int run_each (UtilModel *model, npuOutputNotify cb, bool sync);
+
+ virtual bool check_version (npubin_meta *meta) { return false; }
+ virtual int prepare_input (UtilModel* model) { return -EPERM; }
+ virtual int set_data_info (npubin_meta *meta, uint32_t model_id) { return -EPERM; }
dev_type type_;
};
class UtilTRIV : public UtilTrinity {
public:
- UtilTRIV () : UtilTrinity (NPUCOND_TRIV_CONN_SOCIP) {}
+ UtilTRIV () : UtilTrinity (NPUCOND_TRIV_CONN_SOCIP, true) {}
private:
- bool check_version ();
- int set_data_info ();
- int set_constraint ();
+ bool check_version (npubin_meta *meta);
+ int set_data_info (npubin_meta *meta, uint32_t model_id);
+ int prepare_input (UtilModel* model);
};
class UtilTRIA : public UtilTrinity {
public:
- UtilTRIA () : UtilTrinity (NPUCOND_TRIA_CONN_SOCIP) {}
-
- private:
- bool check_version ();
- int set_data_info ();
- int set_constraint ();
+ UtilTRIA () : UtilTrinity (NPUCOND_TRIA_CONN_SOCIP, false) {}
};
class UtilTRIV2 : public UtilTrinity {
public:
- UtilTRIV2 () : UtilTrinity (NPUCOND_TRIV2_CONN_SOCIP) {}
+ UtilTRIV2 () : UtilTrinity (NPUCOND_TRIV2_CONN_SOCIP, true) {}
private:
- bool check_version ();
- int set_data_info ();
- int set_constraint ();
+ bool check_version (npubin_meta *meta);
+ int set_data_info (npubin_meta *meta, uint32_t model_id);
+ int prepare_input (UtilModel* model);
};
extern "C" {