| 131 | } |
| 132 | |
| 133 | static TinyNNStatus execute_subtensor(Instruction* inst, VM* vm) { |
| 134 | Tensor **inputs = inst->workload.subtensor.inputs, |
| 135 | *output = inst->workload.subtensor.output; |
| 136 | SubTensor* subtensor = &inst->workload.subtensor; |
| 137 | Tensor input_copy = *(inputs[0]); |
| 138 | //! deduce output shape, and modify the input stride |
| 139 | output->layout = input_copy.layout; |
| 140 | output->dtype = inputs[0]->dtype; |
| 141 | update_layout( |
| 142 | inputs, &input_copy, output, subtensor->descs, subtensor->flags, |
| 143 | subtensor->nr_descs); |
| 144 | //! alloc output |
| 145 | TINYNN_ASSERT_MSG(output->is_dynamic, "Subtensor output tensor should be dynamic."); |
| 146 | alloc_tensor(output, vm); |
| 147 | //! do subtensor |
| 148 | size_t nr_elem = 1; |
| 149 | for (int i = 0; i < output->layout.nr_dim; ++i) { |
| 150 | nr_elem *= output->layout.dims[i]; |
| 151 | } |
| 152 | |
| 153 | NoconIter src_iter = init_iter(input_copy.layout); |
| 154 | NoconIter dst_iter = init_iter(output->layout); |
| 155 | if (dtype_length((input_copy).dtype.type_enum, NULL) == 1) { |
| 156 | char* dst_data = output->ptr; |
| 157 | char* src_data = input_copy.ptr; |
| 158 | for (size_t i = 0; i < nr_elem; ++i) { |
| 159 | dst_data[dst_iter.offset] = src_data[src_iter.offset]; |
| 160 | inc_iter(input_copy.layout, &src_iter); |
| 161 | inc_iter(output->layout, &dst_iter); |
| 162 | } |
| 163 | } else if (dtype_length((input_copy).dtype.type_enum, NULL) == 2) { |
| 164 | int16_t* dst_data = output->ptr; |
| 165 | int16_t* src_data = input_copy.ptr; |
| 166 | for (size_t i = 0; i < nr_elem; ++i) { |
| 167 | dst_data[dst_iter.offset] = src_data[src_iter.offset]; |
| 168 | inc_iter(input_copy.layout, &src_iter); |
| 169 | inc_iter(output->layout, &dst_iter); |
| 170 | } |
| 171 | } else if (dtype_length((input_copy).dtype.type_enum, NULL) == 4) { |
| 172 | int32_t* dst_data = output->ptr; |
| 173 | int32_t* src_data = input_copy.ptr; |
| 174 | for (size_t i = 0; i < nr_elem; ++i) { |
| 175 | dst_data[dst_iter.offset] = src_data[src_iter.offset]; |
| 176 | inc_iter(input_copy.layout, &src_iter); |
| 177 | inc_iter(output->layout, &dst_iter); |
| 178 | } |
| 179 | } else { |
| 180 | LOG_ERROR("unsupport dtype in subtensor.\n"); |
| 181 | return TinyNN_ERROR_UNSUPPORTED_DTYPE_TYPE; |
| 182 | } |
| 183 | #if TINYNN_DUMP_TENSOR |
| 184 | log_tensor(subtensor->output, "subtensor", subtensor->inputs[0]); |
| 185 | #endif |
| 186 | return TinyNN_SUCCESS; |
| 187 | } |
| 188 | static TinyNNStatus destruct_subtensor(VM* vm, Instruction* inst) { |
| 189 | FREE(inst->workload.subtensor.inputs); |
| 190 | FREE(inst->workload.subtensor.descs); |
nothing calls this directly
no test coverage detected