[Format] Revise the format of whole source codes
[platform/adaptation/npu/trix-engine.git] / tests / apptests / tvn_triv2_dmabuf.cc
1 /**
2  * Proprietary
3  * Copyright (C) 2020 Samsung Electronics
4  * Copyright (C) 2020 Dongju Chae <dongju.chae@samsung.com>
5  */
6 /**
7  * @file tvn_triv2_dmabuf.cc
8  * @date 25 May 2020
9  * @brief AppTest to test dmabuf-sharing capability in TRIV2 device
10  * @author Dongju Chae <dongju.chae@samsung.com>
11  * @bug No known bugs except for NYI items
12  */
13
14 #include <libnpuhost.h>
15 #include <ne_test_utils.h>
16 #include <string.h>
17
18 #include <iostream>
19 #include <fstream>
20
21 /** ./include/typedef.h */
22 #define TRIV2_TYPE NPUCOND_TRIV2_CONN_SOCIP
23
24 #define NPU_MODEL_NAME "model.tvn"
25
26 /** @brief c++ class to describe how to use npu-engine library */
27 class TesterTRIV2 {
28  public:
29   TesterTRIV2 () : dev_ (nullptr), dev_tmp_ (nullptr), meta_ (nullptr), model_id_ (0) {
30     memset (&input_, '\x00', sizeof (input_buffers));
31     memset (&input_tmp_, '\x00', sizeof (input_buffers));
32   }
33
34   ~TesterTRIV2 () {
35     /** release resources */
36     if (dev_ != nullptr) {
37       if (model_id_ > 0)
38         unregisterNPUmodel (dev_, model_id_);
39
40       if (meta_ != nullptr)
41         free (meta_);
42
43       putNPUdevice (dev_);
44     }
45
46     if (dev_tmp_ != nullptr) {
47       for (uint32_t idx = 0; idx < input_tmp_.num_buffers; idx++) {
48         cleanNPU_inputBuffer (dev_tmp_, &input_tmp_.bufs[idx]);
49       }
50
51       putNPUdevice (dev_tmp_);
52     }
53   }
54
55   /** @brief initilize the device handle */
56   int init (const std::string dir) {
57     dir_ = dir;
58     /* use /dev/triv2-0 */
59     return getNPUdeviceByType (&dev_, TRIV2_TYPE, 0);
60   }
61
62   /** @brief run the inference (with dummy data) */
63   int run () {
64     int status = prepare_model ();
65     if (status != 0)
66       return status;
67
68     status = prepare_input ();
69     if (status != 0)
70       return status;
71
72     status = set_data_info ();
73     if (status != 0)
74       return status;
75
76     output_buffers output;
77     status = runNPU_sync (dev_, model_id_, &input_, &output);
78     if (status < 0)
79       return status;
80
81     return compare_result (output);
82   }
83
84  private:
85   int prepare_model () {
86     generic_buffer model;
87     std::string model_path;
88     uint32_t i;
89
90     model_path = dir_ + "/" + NPU_MODEL_NAME;
91
92     meta_ = getNPUmodel_metadata (model_path.c_str (), false);
93     if (meta_ == nullptr)
94       return -EINVAL;
95
96     if (NPUBIN_VERSION (meta_->magiccode) != 3)
97       return -EINVAL;
98
99     for (i = 0; i < meta_->segment_num; ++i) {
100       if (meta_->input_seg_off[i] != 0)
101         return test_ret::test_ret_skipped_not_compatible;
102     }
103
104     model.type = BUFFER_FILE;
105     model.size = meta_->size;
106     model.filepath = model_path.c_str ();
107
108     int status = allocNPU_modelBuffer (dev_, &model);
109     if (status != 0)
110       return status;
111
112     status = registerNPUmodel (dev_, &model, &model_id_);
113     cleanNPU_modelBuffer (dev_, &model);
114
115     return status;
116   }
117
118   int prepare_input () {
119     /* use /dev/triv2-1 for external dmabuf */
120     int status = getNPUdeviceByType (&dev_tmp_, TRIV2_TYPE, 1);
121     if (status != 0)
122       return status;
123
124     input_.num_buffers = meta_->input_seg_num;
125     input_tmp_.num_buffers = meta_->input_seg_num;
126     for (uint32_t idx = 0; idx < meta_->input_seg_num; idx++) {
127       uint32_t input_seg_idx = meta_->input_seg_idx[idx];
128       uint32_t input_seg_size = meta_->segment_size[input_seg_idx];
129       off_t input_seg_off = meta_->input_seg_off[idx];
130
131       std::string input_path;
132       input_path = dir_ + "/input_fmap_" + std::to_string (idx) + ".bin";
133
134       input_tmp_.bufs[idx].type = BUFFER_MAPPED;
135       input_tmp_.bufs[idx].size = input_seg_size;
136       status = allocNPU_inputBuffer (dev_tmp_, &input_tmp_.bufs[idx]);
137       if (status != 0)
138         return status;
139
140       std::ifstream ifs (input_path, std::ios::binary);
141       if (!ifs.good ())
142         return -EINVAL;
143
144       ifs.seekg (0, std::ios::end);
145       size_t size = ifs.tellg ();
146
147       ifs.seekg (0);
148       ifs.read (static_cast<char *> (input_tmp_.bufs[idx].addr) + input_seg_off, size);
149       ifs.close ();
150
151       input_.bufs[idx].type = BUFFER_DMABUF;
152       input_.bufs[idx].size = size;
153       input_.bufs[idx].dmabuf = input_tmp_.bufs[idx].dmabuf;
154       input_.bufs[idx].offset = input_seg_off;
155     }
156
157     return 0;
158   }
159
160   int set_data_info () {
161     tensors_data_info info_in;
162     tensors_data_info info_out;
163
164     /* No data manipulation & quantization in this test */
165
166     info_in.num_info = meta_->input_seg_num;
167     for (uint32_t idx = 0; idx < info_in.num_info; idx++) {
168       info_in.info[idx].layout = DATA_LAYOUT_TRIV2;
169       info_in.info[idx].type = DATA_TYPE_QASYMM8;
170     }
171
172     info_out.num_info = meta_->output_seg_num;
173     for (uint32_t idx = 0; idx < info_out.num_info; idx++) {
174       info_out.info[idx].layout = DATA_LAYOUT_TRIV2;
175       info_out.info[idx].type = DATA_TYPE_QASYMM8;
176     }
177
178     return setNPU_dataInfo (dev_, model_id_, &info_in, &info_out);
179   }
180
181   int compare_result (output_buffers &output) {
182     int err = 0;
183
184     for (uint32_t idx = 0; idx < output.num_buffers; idx++) {
185       char *output_data = static_cast<char *> (output.bufs[idx].addr);
186       off_t output_size = output.bufs[idx].size;
187       std::string golden_path;
188
189       golden_path = dir_ + "/output_fmap_" + std::to_string (idx) + ".bin";
190
191       err = compare_data (golden_path.c_str (), output_data, output_size);
192
193       assert (output.bufs[idx].type == BUFFER_MAPPED);
194       free (output_data);
195
196       if (err != 0)
197         break;
198     }
199
200     return err;
201   }
202
203   std::string dir_;
204
205   npudev_h dev_;
206   npudev_h dev_tmp_;
207
208   npubin_meta *meta_;
209   uint32_t model_id_;
210   input_buffers input_;
211   input_buffers input_tmp_;
212 };
213
214 /** @brief apptest main  */
215 int
216 main (int argc, char **argv) {
217   TesterTRIV2 tester;
218   int status;
219
220   if (argc != 2) {
221     status = test_ret::test_ret_skipped_wrong_num_args;
222     goto skipped;
223   }
224
225   /** initialize triv2 device */
226   status = tester.init (argv[1]);
227   if (status < test_ret::test_ret_success)
228     goto err;
229
230   /** run the inference with the device */
231   status = tester.run ();
232   if (status < test_ret::test_ret_success)
233     goto err;
234   else if (status > test_ret::test_ret_skipped)
235     goto skipped;
236
237   std::cerr << "[APPTEST] " << argv[0] << ": PASSED\n";
238   return 0;
239
240 err:
241   std::cerr << "[APPTEST] " << argv[0] << ": FAILED (" << status << ")\n";
242   return status;
243
244 skipped:
245   std::cerr << "[APPTEST] " << argv[0] << ": SKIPPED\n";
246   std::cerr << "\t" << msg_skipped_reason[status] << std::endl;
247   return 0;
248 }