This patch fixes runInternal() APi for HW input service.
It requires extra variables in run_input ioctl structure.
Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
* @param[in] dev The NPU device handle
* @param[in] modelid The model to be inferred.
* @param[in] opmode NPU has different opmode with auto-inputs. Choose one.
- * @param[in] input The input buffer where input data comes.
- * @param[in] output The output buffer where output data is filled.
+ * @param[in] hw_dev The target device feeding input data
* @return @c 0 or positive id if no error. otherwise a negative error value
+ * @note input and output are handled internally by third-party HW (e.g., DSP)
*/
int runNPU_internalInput(npudev_h dev, uint32_t modelid, npu_input_opmode opmode,
- const input_buffers *input, const output_buffers *output);
+ const char * hw_dev);
/**
* @brief Stop the request with the given id
* @param[in] dev The NPU device handle
* @param[in] modelid The model to be inferred.
* @param[in] opmode NPU has different opmode with auto-inputs. Choose one.
- * @param[in] input The input buffer where input data comes.
- * @param[in] output The output buffer where output data is filled.
+ * @param[in] hw_dev The target device feeding input data
* @return @c 0 if no error. otherwise a negative error value
*/
int runNPU_internalInput(npudev_h dev, uint32_t modelid, npu_input_opmode opmode,
- const input_buffers *input, const output_buffers *output)
+ const char * hw_dev)
{
INIT_HOST_HANDLER (host_handler, dev);
- return host_handler->runInternal (modelid, opmode, input, output);
+ return host_handler->runInternal (modelid, opmode, hw_dev);
}
/**
* @brief Let NPU accept input frames from its internal source continuously
* @param[in] modelid The model to be inferred.
* @param[in] opmode NPU has different opmode with auto-inputs. Choose one.
- * @param[in] input The input buffer where input data comes.
- * @param[in] output The output buffer where output data is filled.
+ * @param[in] hw_dev The target device feeding input data
* @return @c 0 if no error. otherwise a negative error value
*/
int
HostHandler::runInternal (uint32_t modelid, npu_input_opmode opmode,
- const input_buffers *input, const output_buffers *output)
+ std::string hw_dev)
{
Model *model = nullptr;
return -EINVAL;
}
- return device_->runInternal (opmode, model, input, output);
+ return device_->runInternal (opmode, model, hw_dev);
}
/**
TrinityVision2::prepareSegmentTable (const Model *model, const input_buffers *input,
const output_buffers *output)
{
- if (model == nullptr || input == nullptr) {
+ if (model == nullptr) {
logerr (TAG, "Invalid arguments provided\n");
return nullptr;
}
const Metadata *meta = model->getMetadata ();
- if (meta == nullptr ||
- meta->getInputNum() != input->num_buffers) {
+ if (meta == nullptr || (input != nullptr &&
+ meta->getInputNum() != input->num_buffers)) {
logerr (TAG, "Invalid metadata info provided\n");
return nullptr;
}
/** @brief implementation of TRIV2's runInternal() */
int
TrinityVision2::runInternal (npu_input_opmode opmode, const Model *model,
- const input_buffers *input, const output_buffers *output)
+ std::string hw_dev)
{
if (!initialized ()) {
logerr (TAG, "Uninitialized device; should use libnpuhost APIs\n");
return -EINVAL;
/** this device uses segment table */
- SegmentTable * segt = prepareSegmentTable (model, input, output);
+ SegmentTable * segt = prepareSegmentTable (model, nullptr, nullptr);
if (segt == nullptr) {
logerr (TAG, "Failed to create segment table instance\n");
return -EINVAL;
Request *req = new Request (opmode);
req->setModel (model);
req->setSegmentTable (segt);
+ req->setHwDevice (hw_dev);
return scheduler_->submitRequest (req);
}
int runAsync (uint32_t modelid, const input_buffers *input,
npuOutputNotify cb = nullptr, void *cb_data = nullptr,
npu_async_mode mode = NPUASYNC_WAIT, uint64_t *sequence = nullptr);
- int runInternal (uint32_t modelid, npu_input_opmode opmode,
- const input_buffers *input, const output_buffers *output);
+ int runInternal (uint32_t modelid, npu_input_opmode opmode, std::string hw_dev);
int stopInternal (int id);
/** @brief get statistics */
void *cb_data = nullptr, uint64_t *sequence = nullptr) = 0;
virtual int runInternal (npu_input_opmode opmode, const Model *model,
- const input_buffers *input, const output_buffers *output) { return -EPERM; }
+ std::string hw_dev) { return -EPERM; }
protected:
/** the device instance has ownership of all related components */
int run (npu_input_opmode opmode, const Model *model,
const input_buffers *input, npuOutputNotify cb = nullptr,
void *cb_data = nullptr, uint64_t *sequence = nullptr);
- int runInternal (npu_input_opmode opmode, const Model *model,
- const input_buffers *input, const output_buffers *output);
+ int runInternal (npu_input_opmode opmode, const Model *model, std::string hw_dev);
private:
void callback (Request *req, npuOutputNotify cb, void *cb_data);
HwInputService::invoke (const DriverAPI *api, const Model *model,
SegmentTable *segt, outputCallback callback)
{
+ const Metadata * meta = model->getMetadata ();
input_config_t input_config;
device_state_t state;
npuConstraint constraint;
input_config.input_mode = INPUT_HW;
input_config.output_mode = OUTPUT_HW;
+ /** Assumption: only a sigle pair of input/output segments in HW input service */
+ input_config.hw_input_seg = meta->getInputSegmentIndex (0);
+ input_config.hw_output_seg = meta->getOutputSegmentIndex (0);
+ input_config.hw_devpath = segt->getHwDevice ().c_str ();
+ input_config.hw_devlen = segt->getHwDevice ().length ();
+
/** run the inference with the input */
ret = api->runInput (&input_config);
- if (ret != 0 && ret != -ECANCELED)
+ if (ret < 0 && ret != -ECANCELED)
logerr (TAG, "Failed to run the NPU inference: %d\n", ret);
handle_callback:
auto callback = std::bind (&Scheduler::handleCallback, this, req);
/** consider NOP cases */
- if (req->getBuffer () != nullptr)
+ if (req->getBuffer () != nullptr) {
status = InferenceEngine::invokeInputService (api_, req->getOpmode(),
req->getID(), req->getModel(), req->getBuffer(), callback);
- else if (req->getSegmentTable () != nullptr)
+ } else if (req->getSegmentTable () != nullptr) {
+ req->getSegmentTable()->setHwDevice (req->getHwDevice ());
+
status = InferenceEngine::invokeInputService (api_, req->getOpmode(),
req->getID(), req->getModel(), req->getSegmentTable(), callback);
- else
+ } else
status = -EINVAL;
if (status != 0) {
void setStopped () { stopped_ = true; }
bool isStopped () { return stopped_; }
+ void setHwDevice (std::string hw_dev) { hw_dev_ = hw_dev; }
+ std::string getHwDevice () { return hw_dev_; }
+
private:
static std::atomic<uint32_t> global_request_id_;
uint32_t request_id_; /**< request id */
SegmentTable *segt_; /**< segment table of the request */
outputCallback cb_; /**< request callback */
+ std::string hw_dev_; /**< HW device path */
};
/** @brief class def. of scheduler to handle requests */
SegmentTable::createSegments (const Model *model,
const input_buffers *input, const output_buffers *output)
{
- if (model == nullptr || input == nullptr) {
- logerr (TAG, "No model/input provided\n");
+ if (model == nullptr) {
+ logerr (TAG, "No model provided\n");
return -EINVAL;
}
hwmem->setOffset (0);
} else {
/** check input segments */
- for (uint32_t j = 0; j < meta->getInputNum (); j++) {
- /** user provides a external segment */
- if (i == meta->getInputSegmentIndex (j)) {
- if (input->bufs[j].type == BUFFER_DMABUF) {
- hwmem = new HWmem (new HWmemExternal);
- hwmem->setDriverAPI (getDriverAPI ());
- /** it assume that dmabuf indicates the base address of segment */
- hwmem->setDmabuf (input->bufs[j].dmabuf);
- hwmem->setOffset (0);
- hwmem->setSize (size);
- break;
+ if (input != nullptr) {
+ for (uint32_t j = 0; j < meta->getInputNum (); j++) {
+ /** user provides a external segment */
+ if (i == meta->getInputSegmentIndex (j)) {
+ if (input->bufs[j].type == BUFFER_DMABUF) {
+ hwmem = new HWmem (new HWmemExternal);
+ hwmem->setDriverAPI (getDriverAPI ());
+ /** it assume that dmabuf indicates the base address of segment */
+ hwmem->setDmabuf (input->bufs[j].dmabuf);
+ hwmem->setOffset (0);
+ hwmem->setSize (size);
+ break;
+ }
}
}
}
uint32_t getNumInputSegments () const { return num_input_segments_; }
uint32_t getNumOutputSegments () const { return num_output_segments_; }
+ std::string getHwDevice () { return hw_dev_; }
+ void setHwDevice (std::string hw_dev) { hw_dev_ = hw_dev; }
+
private:
bool setSegmentSlot (HWmem *hwmem, int slot);
uint32_t num_weight_segments_; /**< number of weight segments */
uint32_t num_input_segments_; /**< number of input segments */
uint32_t num_output_segments_; /**< number of output segments */
+
+ std::string hw_dev_; /**< hw device for recurring task */
};
#endif /* __NPU_ENGINE_SEGMENT_TABLE_H__ */
#include <ne_test_utils.h>
#include <string.h>
#include <unistd.h>
+#include <sys/stat.h>
#include <iostream>
#include <fstream>
public:
TesterTRIV2 () : dev_ (nullptr), meta_ (nullptr), model_id_ (0) {
model_.size = 0;
- input_.num_buffers = 0;
- output_.num_buffers = 0;
time_ = DEFAULT_TIME;
}
}
/** @brief initilize the device handle */
- int init (const std::string dir) {
+ int init (const std::string dir, const std::string hw_dev) {
+ struct stat stat_buf;
+ if (stat (hw_dev.c_str(), &stat_buf) != 0)
+ return -EEXIST;
+
int num_devices = getnumNPUdeviceByType (TRIV2_TYPE);
if (num_devices <= 0)
return -ENODEV;
int dev_id = num_devices - 1;
dir_ = dir;
+ hw_dev_ = hw_dev;
+
return getNPUdeviceByType (&dev_, TRIV2_TYPE, dev_id);
}
if (status != 0)
return status;
- status = prepare_input ();
- if (status != 0)
- return status;
-
- status = prepare_output ();
- if (status != 0)
- return status;
-
status = set_data_info ();
if (status != 0)
return status;
int id = runNPU_internalInput (dev_, model_id_, NPUINPUT_HW_RECURRING,
- &input_, &output_);
+ hw_dev_.c_str());
if (id < 0)
return id;
return registerNPUmodel (dev_, &model_, &model_id_);
}
- int prepare_input () {
- input_.num_buffers = meta_->input_seg_num;
- for (uint32_t idx = 0; idx < meta_->input_seg_num; idx++) {
- uint32_t input_seg_idx = meta_->input_seg_idx[idx];
- uint32_t input_seg_size = meta_->segment_size[input_seg_idx];
- uint32_t input_seg_off = meta_->input_seg_off[idx];
-
- input_.bufs[idx].type = BUFFER_DMABUF;
- input_.bufs[idx].size = input_seg_size - input_seg_off;
- input_.bufs[idx].offset = input_seg_off;
- input_.bufs[idx].dmabuf = hw_.get_input_dmabuf (idx);
- }
-
- return 0;
- }
-
- int prepare_output () {
- output_.num_buffers = meta_->output_seg_num;
- for (uint32_t idx = 0; idx < meta_->output_seg_num; idx++) {
- uint32_t output_seg_idx = meta_->output_seg_idx[idx];
- uint32_t output_seg_size = meta_->segment_size[output_seg_idx];
- uint32_t output_seg_off = meta_->output_seg_off[idx];
-
- output_.bufs[idx].type = BUFFER_DMABUF;
- output_.bufs[idx].size = output_seg_size - output_seg_off;
- output_.bufs[idx].offset = output_seg_off;
- output_.bufs[idx].dmabuf = hw_.get_output_dmabuf (idx);
- }
-
- return 0;
- }
-
int set_data_info () {
tensors_data_info info_in;
tensors_data_info info_out;
}
std::string dir_;
+ std::string hw_dev_;
npudev_h dev_;
npubin_meta *meta_;
uint32_t model_id_;
generic_buffer model_;
- input_buffers input_;
- output_buffers output_;
uint32_t time_;
ThirdPartyHW hw_;
};
+static void
+print_usage (const char *prog_name)
+{
+ std::cerr << "Usage: " << prog_name << " [options] model_dir target_dev\n";
+ std::cerr << "Options: \n";
+ std::cerr << " -t <arg> \t Set timeout of recurring task\n";
+ std::cerr << " -h \t\t Show the usage of this program\n";
+}
+
/** @brief apptest main */
int
main (int argc, char **argv)
{
TesterTRIV2 tester;
- int status;
+ int c, status;
+
+ optind = 0;
+ opterr = 0;
+ while ((c = getopt (argc, argv, "ht:")) != -1) {
+ switch (c) {
+ case 't':
+ tester.set_time (atoi(optarg));
+ break;
+ case '?':
+ if (optopt == 't')
+ std::cerr << "Option -t requires an extra argument";
+ else
+ std::cerr << "Unknown flag: " << c;
+ std::cerr << std::endl;
+ case 'h':
+ print_usage(argv[0]);
+ return 0;
+ }
+ }
- if (argc < 2) {
+ if (optind + 1 >= argc) {
std::cerr << "[APPTEST] " << argv[0] << ": SKIPPED\n";
return 0;
}
/** initialize triv2 device */
- status = tester.init (argv[1]);
+ status = tester.init (argv[optind], argv[optind + 1]);
if (status != 0)
goto err;
- if (argc > 2)
- tester.set_time (atoi(argv[2]));
-
/** run the inference with the device */
status = tester.run ();
if (status != 0)