--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2021 Samsung Electronics
+ * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file tvn_triv2_preempt.cc
+ * @date 15 Mar 2021
+ * @brief AppTest to test task preemption
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#include <ne_test_utils.h>
+
+#define NPU_TIMEOUT_MS 5000
+#define MID_MODEL_NAME "MOBILENET_V1"
+#define HIGH_MODEL_NAME "MAX_POOL_2D_000"
+
+using namespace std;
+
+/** @brief C++ class to describe how to use npu-engine library */
+class Tester : public UtilTRIV2
+{
+ public:
+ Tester () : mid_model_id_ (0), high_model_id_ (0) {}
+
+ /** @brief initilize the device handle */
+ int init (std::string models_dir) {
+ int status = UtilTRIV2::init ();
+ if (status != test_ret_success) {
+ cerr << "Failed to initialize\n";
+ return status;
+ }
+
+ status = UtilTRIV2::loadModel (models_dir + "/" + MID_MODEL_NAME,
+ &mid_model_id_, NPU_PRIORITY_MID, NPU_TIMEOUT_MS);
+ if (status != test_ret_success) {
+ cerr << "Failed to find a model: " << MID_MODEL_NAME << "\n";
+ return status;
+ }
+
+ status = UtilTRIV2::loadModel (models_dir + "/" + HIGH_MODEL_NAME,
+ &high_model_id_, NPU_PRIORITY_HIGH, NPU_TIMEOUT_MS);
+ if (status != test_ret_success) {
+ cerr << "Failed to find a model: " << HIGH_MODEL_NAME << "\n";
+ return status;
+ }
+
+ return 0;
+ }
+
+ /** @brief run the inference */
+ int run () {
+ if (mid_model_id_ == 0 || high_model_id_ == 0)
+ return test_ret_failure;
+
+ int mid_task_id = UtilTRIV2::run (mid_model_id_);
+ if (mid_task_id < 0)
+ return mid_task_id;
+
+ int high_task_id = UtilTRIV2::run (high_model_id_);
+ if (high_task_id < 0)
+ return high_task_id;
+
+ int result = wait () == 2 ? test_ret_success : test_ret_failure;
+
+ if (result == test_ret_success) {
+ int64_t mid_last_seq = get_last_sequence (mid_task_id);
+ int64_t high_last_seq = get_last_sequence (high_task_id);
+
+ /** The expected execution order: mid --> high --> mid */
+ if (high_last_seq > mid_last_seq) {
+ cerr << "Unable to confirm the evidence of preemption\n";
+ result = test_ret_failure;
+ }
+ }
+
+ return result;
+ }
+
+ /** @brief get the last sequence */
+ int64_t get_last_sequence (int task_id) {
+ npu_profile profile;
+ int64_t sequence = -1;
+ int status;
+
+ status = UtilTRIV2::getProfile (task_id, &profile);
+ if (status == 0) {
+ if (profile.layers != nullptr)
+ sequence = profile.layers[profile.num_layers - 1].visa_exec_seq;
+
+ putNPU_profile (&profile);
+ } else {
+ cerr << "Failed to get profile: " << status << "\n";
+ sequence = status;
+ }
+
+ return sequence;
+ }
+
+ private:
+ uint32_t mid_model_id_;
+ uint32_t high_model_id_;
+};
+
+/** @brief apptest main */
+int
+main (int argc, char **argv)
+{
+ Tester tester;
+ char * dir;
+ int status;
+
+ status = tester.parseArgs (argc, argv, &dir, "[models' dir]");
+ if (status == test_ret_skipped || dir == nullptr)
+ goto skip;
+ else if (status != test_ret_success)
+ goto err;
+
+ /** initialize triv2 device */
+ status = tester.init (dir);
+ if (status < test_ret_success)
+ goto err;
+
+ /** run the inference with the device */
+ status = tester.run ();
+ if (status < test_ret_success)
+ goto err;
+
+ cerr << "[APPTEST] " << argv[0] << ": PASSED\n";
+ return 0;
+
+err:
+ cerr << "[APPTEST] " << argv[0] << ": FAILED (" << status << ")\n";
+ return status;
+
+skip:
+ cerr << "[APPTEST] " << argv[0] << ": SKIPPED\n";
+ return 0;
+}