1 .. _using-tidl-api:
3 ******************
4 Using the TIDL API
5 ******************
7 This example illustrates using the TIDL API to offload deep learning network processing from a Linux application to the C66x DSPs or EVEs on AM57x devices. The API consists of three classes: ``Configuration``, ``Executor`` and ``ExecutionObject``.
9 Step 1
10 ======
12 Determine if there are any TIDL capable devices on the AM57x SoC:
14 .. code-block:: c++
16 uint32_t num_eve = Executor::GetNumDevices(DeviceType::EVE);
17 uint32_t num_dsp = Executor::GetNumDevices(DeviceType::DSP);
19 Step 2
20 ======
21 Create a Configuration object by reading it from a file or by initializing it directly. The example below parses a configuration file and initializes the Configuration object. See ``examples/test/testvecs/config/infer`` for examples of configuration files.
23 .. code::
25 Configuration configuration;
26 bool status = configuration.ReadFromFile(config_file);
28 .. note::
29 Refer `Processor SDK Linux Software Developer's Guide`_ for creating TIDL network and parameter binary files from TensorFlow and Caffe.
31 Step 3
32 ======
33 Create an Executor with the appropriate device type, set of devices and a configuration. In the snippet below, an Executor is created on 2 EVEs.
35 .. code-block:: c++
37 DeviceIds ids = {DeviceId::ID0, DeviceId::ID1};
38 Executor executor(DeviceType::EVE, ids, configuration);
40 Step 4
41 ======
42 Get the set of available ExecutionObjects and allocate input and output buffers for each ExecutionObject.
44 .. code-block:: c++
46 const ExecutionObjects& execution_objects = executor.GetExecutionObjects();
47 int num_eos = execution_objects.size();
49 // Allocate input and output buffers for each execution object
50 std::vector<void *> buffers;
51 for (auto &eo : execution_objects)
52 {
53 ArgInfo in = { ArgInfo(malloc(frame_sz), frame_sz)};
54 ArgInfo out = { ArgInfo(malloc(frame_sz), frame_sz)};
55 eo->SetInputOutputBuffer(in, out);
57 buffers.push_back(in.ptr());
58 buffers.push_back(out.ptr());
59 }
61 Step 5
62 ======
63 Run the network on each input frame. The frames are processed with available execution objects in a pipelined manner with additional num_eos iterations to flush the pipeline (epilogue).
65 .. code-block:: c++
67 for (int frame_idx = 0; frame_idx < configuration.numFrames + num_eos; frame_idx++)
68 {
69 ExecutionObject* eo = execution_objects[frame_idx % num_eos].get();
71 // Wait for previous frame on the same eo to finish processing
72 if (eo->ProcessFrameWait())
73 WriteFrame(*eo, output_data_file);
75 // Read a frame and start processing it with current eo
76 if (ReadFrame(*eo, frame_idx, configuration, input_data_file))
77 eo->ProcessFrameStartAsync();
78 }
80 For a complete example of using the API, refer any of the examples available at ``/usr/share/ti/tidl/examples`` on the EVM file system.
82 .. _Processor SDK Linux Software Developer's Guide: http://software-dl.ti.com/processor-sdk-linux/esd/docs/latest/linux/index.html