46template <
class NodeType>
void setupShape(
const mir::Shape &shape, NodeType *node)
48 node->rank(shape.
rank());
49 for (int32_t i = 0; i < shape.
rank(); i++)
51 node->dim(i) =
static_cast<uint32_t
>(shape.
dim(i));
55std::unique_ptr<loco::TensorShape> make_tensor_shape(
const mir::Shape &shape)
57 auto res = std::make_unique<loco::TensorShape>();
58 setupShape(shape, res.get());
59 return std::move(res);
62void setupPad(
const std::vector<std::int32_t> &padding_before,
65 assert(padding_before.size() == 2 && padding_after.size() == 2);
66 pad->
top(padding_before[0]);
67 pad->
left(padding_before[1]);
68 pad->
bottom(padding_after[0]);
69 pad->
right(padding_after[1]);
72void setupWindow(
const std::vector<std::int32_t> &window_size,
loco::Window<2> *window)
74 assert(window_size.size() == 2);
75 window->vertical(window_size[0]);
76 window->horizontal(window_size[1]);
79void setupStride(
const std::vector<std::int32_t> &strides,
loco::Stride<2> *stride)
81 assert(strides.size() == 2);
82 stride->vertical(strides[0]);
83 stride->horizontal(strides[1]);
107std::unique_ptr<loco::FeatureEncoder> createFeatureEncoder(
mir::DataFormat data_format)
109 auto perm = createFeaturePermutation(data_format);
110 return std::make_unique<loco::PermutingEncoder<loco::Domain::Feature>>(perm);
113std::unique_ptr<loco::FeatureDecoder> createFeatureDecoder(
mir::DataFormat data_format)
115 auto perm = createFeaturePermutation(data_format);
116 return std::make_unique<loco::PermutingDecoder<loco::Domain::Feature>>(perm);
119std::unique_ptr<loco::FilterEncoder> createOHWIFilterEncoder()
126 return std::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>(perm);
129std::unique_ptr<loco::FilterEncoder> createHWOIFilterEncoder()
136 return std::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>(perm);
139std::unique_ptr<loco::DepthwiseFilterEncoder> createHWIMDepthwiseFilterEncoder()
146 return std::make_unique<loco::PermutingEncoder<loco::Domain::DepthwiseFilter>>(perm);
149std::unique_ptr<loco::DepthwiseFilterEncoder> createIHWMDepthwiseFilterEncoder()
156 return std::make_unique<loco::PermutingEncoder<loco::Domain::DepthwiseFilter>>(perm);
159std::unique_ptr<loco::MatrixEncoder> createHWMatrixEncoder()
164 return std::make_unique<loco::PermutingEncoder<loco::Domain::Matrix>>(perm);
167std::unique_ptr<loco::MatrixDecoder> createHWMatrixDecoder()
172 return std::make_unique<loco::PermutingDecoder<loco::Domain::Matrix>>(perm);
179 case mir::DataType::UNKNOWN:
180 return loco::DataType::Unknown;
181 case mir::DataType::FLOAT32:
182 return loco::DataType::FLOAT32;
183 case mir::DataType::FLOAT64:
184 return loco::DataType::FLOAT64;
185 case mir::DataType::INT32:
186 return loco::DataType::S32;
187 case mir::DataType::INT64:
188 return loco::DataType::S64;
192 throw std::runtime_error(
"Unsupported data type");
200 if (shape == out_shape)
203 int32_t out_rank = out_shape.
rank();
204 int32_t rank_diff = out_rank - shape.
rank();
208 if (shape.
rank() != out_rank)
213 broadcast->input(reshape);
215 for (int32_t dim = 0; dim < out_rank; dim++)
220 reshape->dim(dim) = shape.
dim(dim - rank_diff);
225 broadcast->input(node);
228 bool compatible_shapes =
true;
229 for (int32_t dim = 0; dim < out_rank; dim++)
232 if (dim < rank_diff || (shape.
dim(dim - rank_diff) == 1 && out_shape.
dim(dim) != 1))
233 broadcast->mapping()->dim(dim) = out_shape.
dim(dim);
235 if (dim >= rank_diff && shape.
dim(dim - rank_diff) != 1 &&
236 shape.
dim(dim - rank_diff) != out_shape.
dim(dim))
237 compatible_shapes =
false;
240 if (!compatible_shapes)
241 throw std::runtime_error(
"Not compatible shapes for broadcasting!");
246template <
typename NodeType>
256 auto lhs_node = createBroadcastIfNeeded(lhs, lhs_shape, out_shape);
257 auto rhs_node = createBroadcastIfNeeded(rhs, rhs_shape, out_shape);
269 auto lhs = _mir2loco_map.at(op.
getInput(0));
270 auto rhs = _mir2loco_map.at(op.
getInput(1));
271 auto result = createEltwiseBinary<loco::EltwiseAdd>(op, lhs, rhs);
274 _mir2loco_map.emplace(op.
getOutput(0), result);
282 encoded_input->
input(input);
283 encoded_input->encoder(createFeatureEncoder(op.
getDataFormat()));
286 avg_pool_node->
ifm(encoded_input);
290 setupStride(op.
getStrides(), avg_pool_node->stride());
294 output->input(avg_pool_node);
297 _mir2loco_map.emplace(op.
getOutput(0), output);
303 throw std::runtime_error(
"Not enough tensors for concatenation!");
313 lhs = _mir2loco_map.at(mir_lhs);
320 concat_node->
lhs(lhs);
321 concat_node->rhs(rhs);
323 concat_node->axis(op.
getAxis());
325 last_concat = concat_node;
329 _mir2loco_map.emplace(op.
getOutput(0), last_concat);
338 setupShape(out_shape, const_node);
341 const_node->dtype(convertDataType(value.getElementType()));
343 switch (const_node->dtype())
345 case loco::DataType::FLOAT32:
347 const_node->size<loco::DataType::FLOAT32>(out_shape.numElements());
348 float &const_float = const_node->
at<loco::DataType::FLOAT32>(0);
349 char *loco_ptr =
reinterpret_cast<char *
>(&const_float);
350 char *mir_ptr = value.at(
mir::Index(out_shape.rank()));
351 std::memcpy(loco_ptr, mir_ptr, out_shape.numElements() *
sizeof(
float));
354 case loco::DataType::FLOAT64:
357 const_node->dtype(loco::DataType::FLOAT32);
358 const_node->size<loco::DataType::FLOAT32>(out_shape.numElements());
359 float &const_float = const_node->at<loco::DataType::FLOAT32>(0);
360 char *mir_ptr = value.at(
mir::Index(out_shape.rank()));
361 double *mir_double =
reinterpret_cast<double *
>(mir_ptr);
362 float *loco_float = &const_float;
365 *loco_float =
static_cast<float>(*mir_double);
371 case loco::DataType::S32:
373 const_node->size<loco::DataType::S32>(out_shape.numElements());
374 int32_t &const_int32 = const_node->at<loco::DataType::S32>(0);
375 char *loco_ptr =
reinterpret_cast<char *
>(&const_int32);
376 char *mir_ptr = value.at(
mir::Index(out_shape.rank()));
377 std::memcpy(loco_ptr, mir_ptr, out_shape.numElements() *
sizeof(int32_t));
380 case loco::DataType::S64:
383 const_node->dtype(loco::DataType::S32);
384 const_node->size<loco::DataType::S32>(out_shape.numElements());
385 int32_t &const_int32 = const_node->at<loco::DataType::S32>(0);
386 char *mir_ptr = value.at(
mir::Index(out_shape.rank()));
387 int64_t *mir_int64 =
reinterpret_cast<int64_t *
>(mir_ptr);
388 int32_t *loco_int32 = &const_int32;
391 *loco_int32 =
static_cast<float>(*mir_int64);
398 std::runtime_error(
"Unsupported data type");
401 _mir2loco_map.emplace(op.
getOutput(0), const_node);
409 loco::Node *input = _mir2loco_map.at(mir_input);
410 loco::Node *filter = _mir2loco_map.at(mir_filter);
415 const std::int32_t group_size = mir_filter->
getShape().
dim(3);
416 const std::int32_t num_in_channels = group_size * op.
getNumGroups();
417 const std::int32_t num_out_channels = mir_filter->
getShape().
dim(0);
421 if (group_size == 1 && (num_out_channels == num_in_channels))
425 encoded_input->
input(input);
426 encoded_input->encoder(createFeatureEncoder(op.
getDataFormat()));
429 encoded_filter->
input(filter);
430 encoded_filter->encoder(createIHWMDepthwiseFilterEncoder());
433 dw_conv2d_node->
ifm(encoded_input);
434 dw_conv2d_node->ker(encoded_filter);
435 setupStride(op.
getStrides(), dw_conv2d_node->stride());
439 output->input(dw_conv2d_node);
442 _mir2loco_map.emplace(op.
getOutput(0), output);
452 throw std::runtime_error(
"Grouped Conv2D operation is not fully supported.");
458 encoded_input->
input(input);
459 encoded_input->encoder(createFeatureEncoder(op.
getDataFormat()));
462 encoded_filter->
input(filter);
463 encoded_filter->encoder(createOHWIFilterEncoder());
465 auto *conv2d_node = _loco_graph->nodes()->create<
loco::Conv2D>();
466 conv2d_node->
ifm(encoded_input);
467 conv2d_node->ker(encoded_filter);
468 setupStride(op.
getStrides(), conv2d_node->stride());
472 output->input(conv2d_node);
475 _mir2loco_map.emplace(op.
getOutput(0), output);
484 loco::Node *input = _mir2loco_map.at(mir_input);
485 loco::Node *filter = _mir2loco_map.at(mir_filter);
488 encoded_input->
input(input);
489 encoded_input->encoder(createFeatureEncoder(op.
getDataFormat()));
492 encoded_filter->
input(filter);
493 encoded_filter->encoder(createHWOIFilterEncoder());
496 tr_conv2d_node->
ifm(encoded_input);
497 tr_conv2d_node->ker(encoded_filter);
498 setupStride(op.
getStrides(), tr_conv2d_node->stride());
502 throw std::runtime_error(
"Not supported non explicit paddings on loco!");
505 output->input(tr_conv2d_node);
508 _mir2loco_map.emplace(op.
getOutput(0), output);
516 loco::Node *input = _mir2loco_map.at(mir_input);
517 loco::Node *filter = _mir2loco_map.at(mir_filter);
520 encoded_input->
input(input);
521 encoded_input->encoder(createFeatureEncoder(op.
getDataFormat()));
524 encoded_filter->
input(filter);
525 encoded_filter->encoder(createHWIMDepthwiseFilterEncoder());
528 dw_conv2d_node->
ifm(encoded_input);
529 dw_conv2d_node->ker(encoded_filter);
530 setupStride(op.
getStrides(), dw_conv2d_node->stride());
534 output->input(dw_conv2d_node);
537 _mir2loco_map.emplace(op.
getOutput(0), output);
545 auto result = createEltwiseBinary<loco::EltwiseDiv>(op, lhs, rhs);
548 _mir2loco_map.emplace(op.
getOutput(0), result);
563 encoded_lhs->
input(lhs);
564 encoded_lhs->encoder(createHWMatrixEncoder());
567 encoded_rhs->
input(rhs);
568 encoded_rhs->encoder(createHWMatrixEncoder());
570 auto *mat_mul = _loco_graph->nodes()->create<
loco::MatMul>();
571 mat_mul->
lhs(encoded_lhs);
572 mat_mul->rhs(encoded_rhs);
575 output->input(mat_mul);
576 output->decoder(createHWMatrixDecoder());
578 _mir2loco_map.emplace(op.
getOutput(0), output);
586 graph_input->name(mir_output->
getName());
589 auto *pull_node = _loco_graph->nodes()->create<
loco::Pull>();
590 setupShape(mir_output->
getShape(), pull_node);
594 _mir2loco_map.emplace(mir_output, pull_node);
602 encoded_input->
input(input);
603 encoded_input->encoder(createFeatureEncoder(op.
getDataFormat()));
606 max_pool_node->
ifm(encoded_input);
608 setupStride(op.
getStrides(), max_pool_node->stride());
612 output->input(max_pool_node);
615 _mir2loco_map.emplace(op.
getOutput(0), output);
623 auto result = createEltwiseBinary<loco::EltwiseMul>(op, lhs, rhs);
626 _mir2loco_map.emplace(op.
getOutput(0), result);
632 loco::Node *input = _mir2loco_map.at(mir_input);
635 graph_output->name(mir_input->
getName());
637 graph_output->
shape(make_tensor_shape(mir_input->
getShape()));
639 auto *push_node = _loco_graph->nodes()->create<
loco::Push>();
640 push_node->
from(input);
649 auto relu_node = _loco_graph->nodes()->create<
loco::ReLU>();
650 relu_node->
input(input);
653 _mir2loco_map.emplace(op.
getOutput(0), relu_node);
661 reshape_node->input(input);
664 setupShape(out_shape, reshape_node);
666 _mir2loco_map.emplace(op.
getOutput(0), reshape_node);
674 softmax_node->
input(input);
676 softmax_node->axis(op.
getAxis());
678 _mir2loco_map.emplace(op.
getOutput(0), softmax_node);
686 auto result = createEltwiseBinary<loco::EltwiseSub>(op, lhs, rhs);
689 _mir2loco_map.emplace(op.
getOutput(0), result);
698 transpose_node->
input(input);
700 transpose_node->perm()->size(axis_order.size());
701 for (
size_t i = 0; i < axis_order.size(); i++)
702 transpose_node->perm()->axis(i) = axis_order[i];
705 _mir2loco_map.emplace(op.
getOutput(0), transpose_node);
712 _mir2loco_map.clear();
722 return std::move(_loco_graph);
Create a value from constant byte array.
Depthwise 2D Convolution.
Create a depthwise filter from a tensor.
Create a tensor from a feature map.
Create a feature map from a tensor.
Create a filter from a tensor.
Graph-level Output Metadata.
Matrix Multiplication lhs and rhs.
Create Tensor from Matrix.
Create Matrix from Tensor.
const DataType & dtype(void) const
const TensorShape * shape(void) const
Logical unit of computation.
uint32_t left(void) const
uint32_t bottom(void) const
uint32_t right(void) const
Create a value from user data.
Make a value visible to user.
Create a new value that rectifies its input.
Reshape a tensor to another tensor whose shape is known at compile time.
Computes softmax activations for Tensor domain.
Stride configuration for N-dimensional spatial operations.
Duplicate elements along specified axes.
2D Transposed Convolution
ND Receptive Field Shape.
void accept(IVisitor *visitor)
Represents an output of a node.
DataType getElementType() const
const std::string & getName() const
const Shape & getShape() const
std::size_t getNumInputs() const
Output * getInput(std::size_t index)
Output * getOutput(std::size_t index)
const Shape & getOutputShape(std::size_t index) const
int32_t & dim(int32_t axis) noexcept
char * at(const Index &idx) const
const std::vector< std::int32_t > & getWindowSize() const
const std::vector< std::int32_t > & getPaddingBefore() const
const std::vector< std::int32_t > & getPaddingAfter() const
DataFormat getDataFormat() const
bool getIncludePad() const
const std::vector< std::int32_t > & getStrides() const
Description of tensor concatenation operation.
const TensorVariant & getValue() const
DataFormat getDataFormat() const
std::int32_t getNumGroups() const
const std::vector< std::int32_t > & getPaddingAfter() const
const std::vector< std::int32_t > & getPaddingBefore() const
const std::vector< std::int32_t > & getStrides() const
const std::vector< std::int32_t > & getPaddingBefore() const
PaddingType getPaddingType() const
const std::vector< std::int32_t > & getPaddingAfter() const
DataFormat getDataFormat() const
const std::vector< std::int32_t > & getStrides() const
const std::vector< std::int32_t > & getStrides() const
const std::vector< std::int32_t > & getPaddingAfter() const
DataFormat getDataFormat() const
const std::vector< std::int32_t > & getPaddingBefore() const
const std::vector< std::int32_t > & getPaddingBefore() const
const std::vector< std::int32_t > & getPaddingAfter() const
DataFormat getDataFormat() const
const std::vector< std::int32_t > & getWindowSize() const
const std::vector< std::int32_t > & getStrides() const
description of softmax operation.
Tensor transpose operation.
const std::vector< std::size_t > & getAxisOrder() const
void link(GraphOutput *, Push *push)
bool valid(Graph *g, std::unique_ptr< ErrorListener > &&l=nullptr)
Validate a loco graph.
DataType
"scalar" value type
std::unique_ptr< Graph > make_graph(void)
data_type convertDataType(const ir::DataType type)
Convert type of data from onert type to npu type.