+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "FixPaddingTransform.h"
-
-#include "Annotations/PaddingData.h"
-#include "Annotations/PadData.h"
-#include "Annotations/ShapeInferenceData.h"
-#include "Annotations/StrideData.h"
-#include "Annotations/WindowData.h"
-#include "Dialect/TFNodes.h"
-
-#include <loco.h>
-#include <moco/Log.h>
-#include <stdex/Memory.h>
-#include <locoex/COpCall.h>
-
-#include <cassert>
-#include <stdexcept>
-
-/**
- * @note To fix padding, output shape of the node needs to be fixed first.
- * fix_padding() checks if fix padding is needed by existance of
- * PaddingData annotation, then output shape is checked by existance
- * of ShapeInferenceData.
- */
-
-namespace
-{
-
-using namespace moco::tf;
-
-bool fix_padding(loco::AvgPool2D *node)
-{
- LOGGER(fixpad_avgpool2d);
-
- auto padding_data = node->annot<PaddingData>();
- if (padding_data == nullptr)
- {
- // padding conversion is already done
- return false;
- }
- auto ofm_shapedata = node->annot<ShapeInferenceData>();
- if (ofm_shapedata == nullptr)
- {
- // need output shape to calculate padding values
- return false;
- }
- auto ifm = node->ifm();
- assert(ifm != nullptr);
- auto ifm_shapedata = ifm->annot<ShapeInferenceData>();
- if (ifm_shapedata == nullptr)
- {
- // need input shape to calculate padding values
- return false;
- }
-
- auto padding = padding_data->padding();
- assert(padding == "VALID" || padding == "SAME");
- assert(ofm_shapedata->rank() == 4);
- assert(ifm_shapedata->rank() == 4);
-
- auto ifm_feature_shape = ifm_shapedata->feature_shape();
- auto ofm_feature_shape = ofm_shapedata->feature_shape();
-
- uint32_t input_height = ifm_feature_shape.height().value();
- uint32_t input_width = ifm_feature_shape.width().value();
- uint32_t stride_height = node->stride()->vertical();
- uint32_t stride_width = node->stride()->horizontal();
- uint32_t window_height = node->window()->vertical();
- uint32_t window_width = node->window()->horizontal();
- uint32_t output_height = ofm_feature_shape.height().value();
- uint32_t output_width = ofm_feature_shape.width().value();
- uint32_t dilation_height = 1; // dilation for AvgPool2D is 1
- uint32_t dilation_width = 1;
- uint32_t effective_window_height = dilation_height * (window_height - 1) + 1;
- uint32_t effective_window_width = dilation_width * (window_width - 1) + 1;
- // calculate padding height, width
- int32_t i_height = (output_height - 1) * stride_height + effective_window_height - input_height;
- int32_t i_width = (output_width - 1) * stride_width + effective_window_width - input_width;
- uint32_t height = i_height >= 0 ? i_height : 0U;
- uint32_t width = i_width >= 0 ? i_width : 0U;
-
- // set padding values
- node->pad()->top(height / 2);
- node->pad()->bottom(height - node->pad()->top());
- node->pad()->left(width / 2);
- node->pad()->right(width - node->pad()->left());
-
- INFO(fixpad_avgpool2d) << "Fix AvgPool2D pad = T " << node->pad()->top() << ", L "
- << node->pad()->left() << ", B " << node->pad()->bottom() << ", R "
- << node->pad()->right() << std::endl;
-
- // clear annotation PaddingData
- node->annot<PaddingData>(nullptr);
- return true;
-}
-
-bool fix_padding(loco::BiasAdd<loco::Domain::Tensor> *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::BiasEncode *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::ConstGen *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::Conv2D *node)
-{
- LOGGER(fixpad_conv2d);
-
- auto padding_data = node->annot<PaddingData>();
- if (padding_data == nullptr)
- {
- // padding conversion is already done
- return false;
- }
-
- auto ofm_shapedata = node->annot<ShapeInferenceData>();
- if (ofm_shapedata == nullptr)
- {
- // need output shape to calculate padding values
- return false;
- }
-
- auto ifm = node->ifm();
- assert(ifm != nullptr);
- auto ifm_shapedata = ifm->annot<ShapeInferenceData>();
- if (ifm_shapedata == nullptr)
- {
- // need input shape to calculate padding values
- return false;
- }
-
- auto ker = node->ker();
- assert(ker != nullptr);
- auto ker_shapedata = ker->annot<ShapeInferenceData>();
- if (ker_shapedata == nullptr)
- {
- return false;
- }
-
- auto padding = padding_data->padding();
- assert(padding == "VALID" || padding == "SAME");
- assert(ofm_shapedata->rank() == 4);
- assert(ifm_shapedata->rank() == 4);
-
- auto ifm_feature_shape = ifm_shapedata->feature_shape();
- auto ker_filter_shape = ker_shapedata->filter_shape();
- auto ofm_feature_shape = ofm_shapedata->feature_shape();
-
- uint32_t input_height = ifm_feature_shape.height().value();
- uint32_t input_width = ifm_feature_shape.width().value();
- uint32_t stride_height = node->stride()->vertical();
- uint32_t stride_width = node->stride()->horizontal();
- uint32_t ker_height = ker_filter_shape.height().value();
- uint32_t ker_width = ker_filter_shape.width().value();
- uint32_t output_height = ofm_feature_shape.height().value();
- uint32_t output_width = ofm_feature_shape.width().value();
- uint32_t dilation_height = 1; // TODO Consider dilation
- uint32_t dilation_width = 1;
- uint32_t effective_ker_height = dilation_height * (ker_height - 1) + 1;
- uint32_t effective_ker_width = dilation_width * (ker_width - 1) + 1;
- // calculate padding height, width
- int32_t i_height = (output_height - 1) * stride_height + effective_ker_height - input_height;
- int32_t i_width = (output_width - 1) * stride_width + effective_ker_width - input_width;
- uint32_t height = i_height >= 0 ? i_height : 0U;
- uint32_t width = i_width >= 0 ? i_width : 0U;
-
- // set padding values
- node->pad()->top(height / 2);
- node->pad()->bottom(height - node->pad()->top());
- node->pad()->left(width / 2);
- node->pad()->right(width - node->pad()->left());
-
- // clang-format off
- INFO(fixpad_conv2d) << "Fix Conv2D pad "
- << "= T " << node->pad()->top()
- << ", L " << node->pad()->left()
- << ", B " << node->pad()->bottom()
- << ", R " << node->pad()->right() << std::endl;
- // clang-format on
-
- // clear annotation PaddingData
- node->annot<PaddingData>(nullptr);
- return true;
-}
-
-bool fix_padding(loco::FeatureDecode *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::FeatureEncode *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::FilterEncode *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::Forward *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::MaxPool2D *node)
-{
- auto padding_data = node->annot<PaddingData>();
- if (padding_data == nullptr)
- {
- // padding conversion is already done
- return false;
- }
- auto ofm_shapedata = node->annot<ShapeInferenceData>();
- if (ofm_shapedata == nullptr)
- {
- // need output shape to calculate padding values
- return false;
- }
- auto ifm = node->ifm();
- assert(ifm != nullptr);
- auto ifm_shapedata = ifm->annot<ShapeInferenceData>();
- if (ifm_shapedata == nullptr)
- {
- // need input shape to calculate padding values
- return false;
- }
-
- auto padding = padding_data->padding();
- assert(padding == "VALID" || padding == "SAME");
- assert(ofm_shapedata->rank() == 4);
- assert(ifm_shapedata->rank() == 4);
-
- auto ifm_feature_shape = ifm_shapedata->feature_shape();
- auto ofm_feature_shape = ofm_shapedata->feature_shape();
-
- uint32_t input_height = ifm_feature_shape.height().value();
- uint32_t input_width = ifm_feature_shape.width().value();
- uint32_t stride_height = node->stride()->vertical();
- uint32_t stride_width = node->stride()->horizontal();
- uint32_t window_height = node->window()->vertical();
- uint32_t window_width = node->window()->horizontal();
- uint32_t output_height = ofm_feature_shape.height().value();
- uint32_t output_width = ofm_feature_shape.width().value();
- uint32_t dilation_height = 1; // dilation for MaxPool2D is 1
- uint32_t dilation_width = 1;
- uint32_t effective_window_height = dilation_height * (window_height - 1) + 1;
- uint32_t effective_window_width = dilation_width * (window_width - 1) + 1;
- // calculate padding height, width
- int32_t i_height = (output_height - 1) * stride_height + effective_window_height - input_height;
- int32_t i_width = (output_width - 1) * stride_width + effective_window_width - input_width;
- uint32_t height = i_height >= 0 ? i_height : 0U;
- uint32_t width = i_width >= 0 ? i_width : 0U;
-
- // set padding values
- node->pad()->top(height / 2);
- node->pad()->bottom(height - node->pad()->top());
- node->pad()->left(width / 2);
- node->pad()->right(width - node->pad()->left());
-
- // clear annotation PaddingData
- node->annot<PaddingData>(nullptr);
- return true;
-}
-
-bool fix_padding(loco::Pull *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::Push *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::ReLU *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::ReLU6 *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(loco::TensorConcat *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFAdd *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFAvgPool *node)
-{
- LOGGER(l);
-
- auto pad_data_c = node->annot<PadData>();
- if (pad_data_c != nullptr)
- {
- // padding conversion is already done
- return false;
- }
-
- auto ofm_shapedata = node->annot<ShapeInferenceData>();
- if (ofm_shapedata == nullptr)
- {
- // need output shape to calculate padding values
- return false;
- }
- auto value = node->value();
- assert(value != nullptr);
- auto value_shapedata = value->annot<ShapeInferenceData>();
- if (value_shapedata == nullptr)
- {
- // need input shape to calculate padding values
- return false;
- }
- auto stride_data = node->annot<StrideData>();
- if (stride_data == nullptr)
- {
- // need stride_data from FixShape
- return false;
- }
- auto window_data = node->annot<WindowData>();
- if (window_data == nullptr)
- {
- // need window_data from FixShape
- return false;
- }
-
- auto padding = node->padding();
- assert(padding == "VALID" || padding == "SAME");
- assert(ofm_shapedata->rank() == 4);
- assert(value_shapedata->rank() == 4);
-
- auto value_feature_shape = as_feature_shape(*value_shapedata, node->data_layout());
- auto ofm_feature_shape = as_feature_shape(*ofm_shapedata, node->data_layout());
-
- uint32_t input_height = value_feature_shape.height().value();
- uint32_t input_width = value_feature_shape.width().value();
- uint32_t stride_height = stride_data->stride()->vertical();
- uint32_t stride_width = stride_data->stride()->horizontal();
- uint32_t window_height = window_data->window()->vertical();
- uint32_t window_width = window_data->window()->horizontal();
- uint32_t output_height = ofm_feature_shape.height().value();
- uint32_t output_width = ofm_feature_shape.width().value();
- uint32_t dilation_height = 1; // dilation for AvgPool is 1
- uint32_t dilation_width = 1;
- uint32_t effective_window_height = dilation_height * (window_height - 1) + 1;
- uint32_t effective_window_width = dilation_width * (window_width - 1) + 1;
- // calculate padding height, width
- int32_t i_height = (output_height - 1) * stride_height + effective_window_height - input_height;
- int32_t i_width = (output_width - 1) * stride_width + effective_window_width - input_width;
- uint32_t height = i_height >= 0 ? i_height : 0U;
- uint32_t width = i_width >= 0 ? i_width : 0U;
-
- // annotation of pad data
- auto pad_data = stdex::make_unique<PadData>();
-
- pad_data->pad()->top(height / 2);
- pad_data->pad()->bottom(height - pad_data->pad()->top());
- pad_data->pad()->left(width / 2);
- pad_data->pad()->right(width - pad_data->pad()->left());
-
- node->annot(std::move(pad_data));
-
- {
- auto pad_data = node->annot<PadData>();
- assert(pad_data != nullptr);
-
- // clang-format off
- INFO(l) << "Fix TFAvgPool pad "
- << "= T " << pad_data->pad()->top()
- << ", L " << pad_data->pad()->left()
- << ", B " << pad_data->pad()->bottom()
- << ", R " << pad_data->pad()->right() << std::endl;
- // clang-format on
- }
- return true;
-}
-
-bool fix_padding(moco::tf::TFBiasAdd *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFConcatV2 *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFConst *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFConv2D *node)
-{
- LOGGER(l);
-
- auto pad_data_c = node->annot<PadData>();
- if (pad_data_c != nullptr)
- {
- // padding conversion is already done
- return false;
- }
-
- auto stride_data = node->annot<StrideData>();
- if (stride_data == nullptr)
- {
- // need stride data but not ready yet
- return false;
- }
-
- auto ofm_shapedata = node->annot<ShapeInferenceData>();
- if (ofm_shapedata == nullptr)
- {
- // need output shape to calculate padding values
- return false;
- }
-
- auto ifm = node->ifm();
- assert(ifm != nullptr);
- auto ifm_shapedata = ifm->annot<ShapeInferenceData>();
- if (ifm_shapedata == nullptr)
- {
- // need input shape to calculate padding values
- return false;
- }
-
- auto ker = node->ker();
- assert(ker != nullptr);
- auto ker_shapedata = ker->annot<ShapeInferenceData>();
- if (ker_shapedata == nullptr)
- {
- return false;
- }
-
- auto padding = node->padding();
- assert(padding == "VALID" || padding == "SAME");
-
- auto data_layout = node->data_layout();
- assert(data_layout == "NHWC");
-
- auto ifm_tensor_shape = ifm_shapedata->tensor_shape(); // in NHWC
- auto ker_tensor_shape = ker_shapedata->tensor_shape(); // in HWIO
- auto ofm_tensor_shape = ofm_shapedata->tensor_shape(); // in NHWC
- assert(ifm_tensor_shape.rank() == 4);
- assert(ker_tensor_shape.rank() == 4);
- assert(ofm_tensor_shape.rank() == 4);
-
- uint32_t input_height = ifm_tensor_shape.dim(1).value();
- uint32_t input_width = ifm_tensor_shape.dim(2).value();
- uint32_t stride_height = stride_data->stride()->vertical();
- uint32_t stride_width = stride_data->stride()->horizontal();
- uint32_t ker_height = ker_tensor_shape.dim(0).value();
- uint32_t ker_width = ker_tensor_shape.dim(1).value();
- uint32_t output_height = ofm_tensor_shape.dim(1).value();
- uint32_t output_width = ofm_tensor_shape.dim(2).value();
-
- uint32_t dilation_height = 1; // TODO Consider dilation
- uint32_t dilation_width = 1;
- uint32_t effective_ker_height = dilation_height * (ker_height - 1) + 1;
- uint32_t effective_ker_width = dilation_width * (ker_width - 1) + 1;
- // calculate padding height, width
- int32_t i_height = (output_height - 1) * stride_height + effective_ker_height - input_height;
- int32_t i_width = (output_width - 1) * stride_width + effective_ker_width - input_width;
- uint32_t height = i_height >= 0 ? i_height : 0U;
- uint32_t width = i_width >= 0 ? i_width : 0U;
-
- // annotation of pad data
- auto pad_data = stdex::make_unique<PadData>();
-
- pad_data->pad()->top(height / 2);
- pad_data->pad()->bottom(height - pad_data->pad()->top());
- pad_data->pad()->left(width / 2);
- pad_data->pad()->right(width - pad_data->pad()->left());
-
- node->annot(std::move(pad_data));
-
- {
- auto pad_data = node->annot<PadData>();
- assert(pad_data != nullptr);
-
- // clang-format off
- INFO(l) << "Fix TFConv2D pad "
- << "= T " << pad_data->pad()->top()
- << ", L " << pad_data->pad()->left()
- << ", B " << pad_data->pad()->bottom()
- << ", R " << pad_data->pad()->right() << std::endl;
- // clang-format on
- }
-
- return true;
-}
-
-bool fix_padding(moco::tf::TFDepthwiseConv2dNative *node)
-{
- LOGGER(l);
-
- auto pad_data_c = node->annot<PadData>();
- if (pad_data_c != nullptr)
- {
- // padding conversion is already done
- return false;
- }
-
- auto ofm_shapedata = node->annot<ShapeInferenceData>();
- if (ofm_shapedata == nullptr)
- {
- // need output shape to calculate padding values
- return false;
- }
-
- auto ifm = node->ifm();
- assert(ifm != nullptr);
- auto ifm_shapedata = ifm->annot<ShapeInferenceData>();
- if (ifm_shapedata == nullptr)
- {
- // need input shape to calculate padding values
- return false;
- }
-
- auto ker = node->ker();
- assert(ker != nullptr);
- auto ker_shapedata = ker->annot<ShapeInferenceData>();
- if (ker_shapedata == nullptr)
- {
- return false;
- }
-
- auto stride_data = node->annot<StrideData>();
- if (stride_data == nullptr)
- {
- // need stride data but not ready yet
- return false;
- }
-
- auto padding = node->padding();
- assert(padding == "VALID" || padding == "SAME");
-
- auto data_layout = node->data_layout();
- assert(data_layout == "NHWC");
-
- auto ifm_tensor_shape = ifm_shapedata->tensor_shape(); // in NHWC
- auto ker_tensor_shape = ker_shapedata->tensor_shape(); // in HWCM
- auto ofm_tensor_shape = ofm_shapedata->tensor_shape(); // in NHWC
- assert(ifm_tensor_shape.rank() == 4);
- assert(ker_tensor_shape.rank() == 4);
- assert(ofm_tensor_shape.rank() == 4);
-
- uint32_t input_height = ifm_tensor_shape.dim(1).value();
- uint32_t input_width = ifm_tensor_shape.dim(2).value();
- uint32_t stride_height = stride_data->stride()->vertical();
- uint32_t stride_width = stride_data->stride()->horizontal();
- uint32_t ker_height = ker_tensor_shape.dim(0).value();
- uint32_t ker_width = ker_tensor_shape.dim(1).value();
- uint32_t output_height = ofm_tensor_shape.dim(1).value();
- uint32_t output_width = ofm_tensor_shape.dim(2).value();
-
- uint32_t dilation_height = 1; // TODO Consider dilation
- uint32_t dilation_width = 1;
- uint32_t effective_ker_height = dilation_height * (ker_height - 1) + 1;
- uint32_t effective_ker_width = dilation_width * (ker_width - 1) + 1;
- // calculate padding height, width
- int32_t i_height = (output_height - 1) * stride_height + effective_ker_height - input_height;
- int32_t i_width = (output_width - 1) * stride_width + effective_ker_width - input_width;
- uint32_t height = i_height >= 0 ? i_height : 0U;
- uint32_t width = i_width >= 0 ? i_width : 0U;
-
- // annotation of pad data
- auto pad_data = stdex::make_unique<PadData>();
-
- pad_data->pad()->top(height / 2);
- pad_data->pad()->bottom(height - pad_data->pad()->top());
- pad_data->pad()->left(width / 2);
- pad_data->pad()->right(width - pad_data->pad()->left());
-
- node->annot(std::move(pad_data));
-
- {
- auto pad_data = node->annot<PadData>();
- assert(pad_data != nullptr);
-
- // clang-format off
- INFO(l) << "Fix TFDepthwiseConv2dNative pad "
- << "= T " << pad_data->pad()->top()
- << ", L " << pad_data->pad()->left()
- << ", B " << pad_data->pad()->bottom()
- << ", R " << pad_data->pad()->right() << std::endl;
- // clang-format on
- }
-
- return true;
-}
-
-bool fix_padding(moco::tf::TFFusedBatchNorm *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFIdentity *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFMaxPool *node)
-{
- LOGGER(l);
-
- auto pad_data_c = node->annot<PadData>();
- if (pad_data_c != nullptr)
- {
- // padding conversion is already done
- return false;
- }
-
- auto ofm_shapedata = node->annot<ShapeInferenceData>();
- if (ofm_shapedata == nullptr)
- {
- // need output shape to calculate padding values
- return false;
- }
- auto value = node->value();
- assert(value != nullptr);
- auto value_shapedata = value->annot<ShapeInferenceData>();
- if (value_shapedata == nullptr)
- {
- // need input shape to calculate padding values
- return false;
- }
- auto stride_data = node->annot<StrideData>();
- if (stride_data == nullptr)
- {
- // need stride_data from FixShape
- return false;
- }
- auto window_data = node->annot<WindowData>();
- if (window_data == nullptr)
- {
- // need window_data from FixShape
- return false;
- }
-
- auto padding = node->padding();
- assert(padding == "VALID" || padding == "SAME");
- assert(ofm_shapedata->rank() == 4);
- assert(value_shapedata->rank() == 4);
-
- auto value_feature_shape = as_feature_shape(*value_shapedata, node->data_layout());
- auto ofm_feature_shape = as_feature_shape(*ofm_shapedata, node->data_layout());
-
- uint32_t input_height = value_feature_shape.height().value();
- uint32_t input_width = value_feature_shape.width().value();
- uint32_t stride_height = stride_data->stride()->vertical();
- uint32_t stride_width = stride_data->stride()->horizontal();
- uint32_t window_height = window_data->window()->vertical();
- uint32_t window_width = window_data->window()->horizontal();
- uint32_t output_height = ofm_feature_shape.height().value();
- uint32_t output_width = ofm_feature_shape.width().value();
- uint32_t dilation_height = 1; // dilation is 1
- uint32_t dilation_width = 1;
- uint32_t effective_window_height = dilation_height * (window_height - 1) + 1;
- uint32_t effective_window_width = dilation_width * (window_width - 1) + 1;
- // calculate padding height, width
- int32_t i_height = (output_height - 1) * stride_height + effective_window_height - input_height;
- int32_t i_width = (output_width - 1) * stride_width + effective_window_width - input_width;
- uint32_t height = i_height >= 0 ? i_height : 0U;
- uint32_t width = i_width >= 0 ? i_width : 0U;
-
- // annotation of pad data
- auto pad_data = stdex::make_unique<PadData>();
-
- pad_data->pad()->top(height / 2);
- pad_data->pad()->bottom(height - pad_data->pad()->top());
- pad_data->pad()->left(width / 2);
- pad_data->pad()->right(width - pad_data->pad()->left());
-
- node->annot(std::move(pad_data));
-
- {
- auto pad_data = node->annot<PadData>();
- assert(pad_data != nullptr);
-
- // clang-format off
- INFO(l) << "Fix TFMaxPool pad "
- << "= T " << pad_data->pad()->top()
- << ", L " << pad_data->pad()->left()
- << ", B " << pad_data->pad()->bottom()
- << ", R " << pad_data->pad()->right() << std::endl;
- // clang-format on
- }
- return true;
-}
-
-bool fix_padding(moco::tf::TFMul *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFRealDiv *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFRelu *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFRelu6 *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFReshape *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFRsqrt *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFShape *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFSqueeze *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(moco::tf::TFSub *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-bool fix_padding(locoex::COpCall *node)
-{
- // Nothing to do with padding
- return false;
-}
-
-} // namespace
-
-namespace moco
-{
-namespace tf
-{
-
-bool FixPaddingTransform::run(loco::Graph *graph)
-{
- bool changed = false;
-#if 0
- for (auto node : loco::active_nodes(loco::output_nodes(graph)))
- {
-// clang-format off
-#define CANONICAL_NODE(TYPE_NAME) \
- if (as<loco::TYPE_NAME>(node)) \
- { \
- if (fix_padding(as<loco::TYPE_NAME>(node))) \
- changed = true; \
- } \
- else
-#include "CanonicalNodes.lst"
-#undef CANONICAL_NODE
-
-#define TENSORFLOW_NODE(OPCODE,CLASS) \
- if (as<moco::tf::CLASS>(node)) \
- { \
- if (fix_padding(as<moco::tf::CLASS>(node))) \
- changed = true; \
- } \
- else
-#include "Dialect/TFNodes.lst"
-#undef TENSORFLOW_NODE
- // clang-format on
-
- if (as<locoex::COpCall>(node))
- {
- if (fix_padding(as<locoex::COpCall>(node)))
- changed = true;
- }
- else
- {
- throw std::runtime_error("Not supported loco::Node type in FixPaddingTransform");
- }
- }
-#endif
-
- return changed;
-}
-
-} // namespace tf
-} // namespace moco
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "FixPaddingTransform.h"
-#include "FixShapeTransform.h"
-
-#include "TestHelper.h"
-
-#include "Annotations/PaddingData.h"
-#include "Annotations/ShapeInferenceData.h"
-
-#include <loco.h>
-
-#include <stdex/Memory.h>
-
-#include <gtest/gtest.h>
-
-using namespace moco::tf::test;
-
-TEST(FixPaddingTransform, ctor)
-{
- moco::tf::FixPaddingTransform fptransform;
- loco::Graph graph;
-
- ASSERT_FALSE(fptransform.run(&graph));
-}
-
-namespace
-{
-
-void conv2d_test(const std::array<uint32_t, 4> ifm_shape, const std::array<uint32_t, 4> ker_shape,
- const std::array<uint32_t, 2> stride_h_w, std::string padding,
- const loco::Pad<2> &&expected_pad)
-{
- loco::Graph graph;
-
- auto conv2d_node = graph.nodes()->create<loco::Conv2D>();
-
- auto stride = conv2d_node->stride();
- stride->vertical(stride_h_w[0]);
- stride->horizontal(stride_h_w[1]);
-
- auto ifm_node = graph.nodes()->create<loco::ConstGen>();
- {
- auto shapedata = stdex::make_unique<moco::tf::ShapeInferenceData>();
- loco::FeatureShape cshape;
- cshape.count() = ifm_shape[0];
- cshape.height() = ifm_shape[1];
- cshape.width() = ifm_shape[2];
- cshape.depth() = ifm_shape[3];
- shapedata->feature_shape(cshape);
- ifm_node->annot(std::move(shapedata));
- }
-
- auto ker_node = graph.nodes()->create<loco::ConstGen>();
- {
- auto shapedata = stdex::make_unique<moco::tf::ShapeInferenceData>();
- loco::FilterShape cshape;
- cshape.height() = ker_shape[0];
- cshape.width() = ker_shape[1];
- cshape.depth() = ker_shape[2];
- cshape.count() = ker_shape[3];
- shapedata->filter_shape(cshape);
- ker_node->annot(std::move(shapedata));
- }
-
- conv2d_node->ifm(ifm_node);
- conv2d_node->ker(ker_node);
-
- setup_output_node(&graph, conv2d_node);
-
- auto padding_data = stdex::make_unique<moco::tf::PaddingData>(padding);
- conv2d_node->annot(std::move(padding_data));
-
- moco::tf::FixShapeTransform transform_shape;
- moco::tf::FixPaddingTransform transform_padding;
- transform_shape.run(&graph);
- transform_padding.run(&graph);
-
- ASSERT_EQ(conv2d_node->pad()->top(), expected_pad.top());
- ASSERT_EQ(conv2d_node->pad()->bottom(), expected_pad.bottom());
- ASSERT_EQ(conv2d_node->pad()->left(), expected_pad.left());
- ASSERT_EQ(conv2d_node->pad()->right(), expected_pad.right());
-
- // ignore memory leaks of annotation
-}
-
-} // namespace
-
-TEST(FixPaddingTransform, conv2d_VALID)
-{
- conv2d_test({1, 299, 299, 3}, // ifm (NHWC)
- {3, 3, 3, 32}, // ker (HWIO = HWCN)
- {2, 2}, // strides (HW)
- "VALID", // padding
- loco::Pad<2>(0, 0, 0, 0)); // expect padding value (Top, Botton, Left, Right)
-}
-
-TEST(FixPaddingTransform, conv2d_SAME_01)
-{
- conv2d_test({1, 147, 147, 32}, // ifm (NHWC)
- {3, 3, 32, 64}, // ker (HWIO = HWCN)
- {1, 1}, // strides (HW)
- "SAME", // padding
- loco::Pad<2>(1, 1, 1, 1)); // expected shape after FixShape (Top, Botton, Left, Right)
-}
-
-// test case from
-// https://stackoverflow.com/questions/37674306/what-is-the-difference-between-same-and-valid-padding-in-tf-nn-max-pool-of-t
-TEST(FixPaddingTransform, conv2d_SAME_02)
-{
- conv2d_test({1, 13, 13, 3}, // ifm (NHWC)
- {6, 6, 3, 3}, // ker (HWIO = HWCN)
- {5, 5}, // strides (HW)
- "SAME", // padding
- loco::Pad<2>(1, 2, 1, 2)); // expected shape after FixShape (Top, Botton, Left, Right)
-}