aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatWai Chong <tatwai.chong@arm.com>2022-06-08 12:17:14 -0700
committerEric Kunze <eric.kunze@arm.com>2022-08-10 23:12:28 +0000
commitf732609a51630c98bc3f448937988fbcf20dc854 (patch)
treec19aeb8919e4ae8db84b13559bd5858f5e785382
parent9391243d1c24d5a4e3c227ba9e3689cdb12d3e60 (diff)
downloadreference_model-f732609a51630c98bc3f448937988fbcf20dc854.tar.gz
Update TOSA resize to match specification
Attribute stride and shift are removed, and has new scale and border. Also add tests in the generator to test tf.resize with all option combinations. Signed-off-by: TatWai Chong <tatwai.chong@arm.com> Signed-off-by: Jeremy Johnson <jeremy.johnson@arm.com> Change-Id: If0f330d04395762d2d907863235eda1532f5e1ff
-rw-r--r--reference_model/src/graph_node.cc9
-rw-r--r--reference_model/src/graph_node.h6
-rw-r--r--reference_model/src/ops/image.cc215
-rw-r--r--reference_model/src/ops/image.h11
-rw-r--r--reference_model/src/ops/op_factory.cc10
-rw-r--r--reference_model/src/ops/op_factory.h28
m---------thirdparty/serialization_lib0
-rw-r--r--verif/frameworks/test_builder.py39
-rwxr-xr-xverif/frameworks/tosa_verif_framework_generator.py24
9 files changed, 207 insertions, 135 deletions
diff --git a/reference_model/src/graph_node.cc b/reference_model/src/graph_node.cc
index 4629156..5f85932 100644
--- a/reference_model/src/graph_node.cc
+++ b/reference_model/src/graph_node.cc
@@ -219,3 +219,12 @@ int GraphNode::validateRequiredRank(const Tensor* t)
return 0;
}
+
+int GraphNode::idiv_check(int input1, int input2, int& result)
+{
+ ERROR_IF(input2 == 0, "idiv_check: input2 must not be zero");
+ ERROR_IF(input1 % input2 != 0, "idiv_check: input1 must be a multiple of input2");
+
+ result = input1 / input2;
+ return 0;
+}
diff --git a/reference_model/src/graph_node.h b/reference_model/src/graph_node.h
index 787e89d..adf81b2 100644
--- a/reference_model/src/graph_node.h
+++ b/reference_model/src/graph_node.h
@@ -37,6 +37,9 @@
#define DEF_INSTANTIATE_TWO_TYPE(OP, DTYPE1, DTYPE2) template class TosaReference::OP<DType_##DTYPE1, DType_##DTYPE2>;
+#define DEF_INSTANTIATE_THREE_TYPE(OP, DTYPE1, DTYPE2, OP_TYPE) \
+ template class TosaReference::OP<DType_##DTYPE1, DType_##DTYPE2, OP_TYPE>;
+
#define DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OP, DTYPE) \
DEF_INSTANTIATE_ONE_RANK_ONE_TYPE(OP, 0, DTYPE) \
DEF_INSTANTIATE_ONE_RANK_ONE_TYPE(OP, 1, DTYPE) \
@@ -232,6 +235,9 @@ public:
return nodeType;
}
+ // Helper functions.
+ int idiv_check(int input1, int input2, int& result);
+
protected:
// Print out a node validation error
int printNodeValidationError(const std::string& msg);
diff --git a/reference_model/src/ops/image.cc b/reference_model/src/ops/image.cc
index 701fdfb..a021226 100644
--- a/reference_model/src/ops/image.cc
+++ b/reference_model/src/ops/image.cc
@@ -16,14 +16,16 @@
#include "image.h"
#include "arith_util.h"
+#include <type_traits>
+
using namespace TosaReference;
using namespace Eigen;
using namespace tosa;
-template <DType InDtype, DType OutDtype>
-OpResize<InDtype, OutDtype>::OpResize(SubgraphTraverser* sgt_,
- TosaAttributeBase* attribute_,
- uint64_t id_)
+template <DType InDtype, DType OutDtype, typename resize_t>
+OpResize<InDtype, OutDtype, resize_t>::OpResize(SubgraphTraverser* sgt_,
+ TosaAttributeBase* attribute_,
+ uint64_t id_)
: GraphNode(sgt_, Op_RESIZE, id_)
{
setRequiredOperands(1, 1);
@@ -32,15 +34,15 @@ OpResize<InDtype, OutDtype>::OpResize(SubgraphTraverser* sgt_,
INIT_ATTRIBUTE(Resize);
}
-template <DType InDtype, DType OutDtype>
-OpResize<InDtype, OutDtype>::~OpResize()
+template <DType InDtype, DType OutDtype, typename resize_t>
+OpResize<InDtype, OutDtype, resize_t>::~OpResize()
{
if (attribute)
delete attribute;
}
-template <DType InDtype, DType OutDtype>
-int OpResize<InDtype, OutDtype>::checkTensorAttributes()
+template <DType InDtype, DType OutDtype, typename resize_t>
+int OpResize<InDtype, OutDtype, resize_t>::checkTensorAttributes()
{
if (validateRequiredOperands())
return 1;
@@ -48,16 +50,16 @@ int OpResize<InDtype, OutDtype>::checkTensorAttributes()
if (validateRequiredRank(inputs[0]) || validateRequiredRank(outputs[0]))
return 1;
- output_size = this->attribute->output_size();
- stride = this->attribute->stride();
- offset = this->attribute->offset();
- shift = this->attribute->shift();
- stride_fp = this->attribute->stride_fp();
- offset_fp = this->attribute->offset_fp();
- mode = this->attribute->mode();
+ if (this->attribute->scale().size() != 4)
+ {
+ printNodeValidationError("OpResize: illegal size for attribute scale");
+ return 1;
+ }
- int output_height = outputs[0]->getShape()[1];
- int output_width = outputs[0]->getShape()[2];
+ scale = this->attribute->scale();
+ offset = this->attribute->offset();
+ border = this->attribute->border();
+ mode = this->attribute->mode();
if (this->mode == ResizeMode_BILINEAR)
{
@@ -76,12 +78,6 @@ int OpResize<InDtype, OutDtype>::checkTensorAttributes()
}
}
- if (output_size[0] != output_height || output_size[1] != output_width)
- {
- printNodeValidationError("OpResize: attribute output_size doesn't match output [height, width]");
- return 1;
- }
-
in = dynamic_cast<TosaReference::TensorTemplate<TIn>*>(inputs[0]);
out = dynamic_cast<TosaReference::TensorTemplate<TOut>*>(outputs[0]);
@@ -90,8 +86,8 @@ int OpResize<InDtype, OutDtype>::checkTensorAttributes()
return 0;
}
-template <DType InDtype, DType OutDtype>
-int OpResize<InDtype, OutDtype>::eval()
+template <DType InDtype, DType OutDtype, typename resize_t>
+int OpResize<InDtype, OutDtype, resize_t>::eval()
{
int in_batch = in->getShape()[0];
int in_height = in->getShape()[1];
@@ -103,105 +99,82 @@ int OpResize<InDtype, OutDtype>::eval()
int out_width = out->getShape()[2];
int out_channels = out->getShape()[3];
+ int16_t scale_y_n = scale[0];
+ int16_t scale_y_d = scale[1];
+ int16_t scale_x_n = scale[2];
+ int16_t scale_x_d = scale[3];
+
+ int16_t offset_y = offset[0];
+ int16_t offset_x = offset[1];
+
+ int16_t border_y = border[0];
+ int16_t border_x = border[1];
+
ERROR_IF(std::max<int>({ in_height, in_width, out_height, out_width }) >= 16384,
"OpResize: exceeds maximum dimension");
- ERROR_IF(shift < 1 || shift > 11, "OpResize: attribute shift should be within [1, 11]");
- ERROR_IF(stride[0] <= 0 || stride[0] >= (16 << shift), "OpResize: invalid attribute stride_x");
- ERROR_IF(stride[1] <= 0 || stride[1] >= (16 << shift), "OpResize: invalid attribute stride_y");
- ERROR_IF(offset[0] <= (-16 << shift) || offset[0] >= (16 << shift), "OpResize: invalid attribute offset_x");
- ERROR_IF(offset[1] <= (-16 << shift) || offset[1] >= (16 << shift), "OpResize: invalid attribute offset_y");
ERROR_IF(in_batch != out_batch, "OpResize: output tensor batch mismatch");
ERROR_IF(in_channels != out_channels, "OpResize: output tensor channel mismatch");
+ ERROR_IF(scale_y_n <= 0 || scale_y_d <= 0 || scale_x_n <= 0 || scale_x_d <= 0,
+ "OpResize: attribute scale must not be negative");
+ // If data type is int8_t then ensure that an int32_t accumulator can be used.
+ ERROR_IF(scale_y_n > (1 << 11) || scale_x_n > (1 << 11), "OpResize: invalid attribute scale");
+ // Set a consistent lower limit of 1/16 downscale to simplify implementations
+ ERROR_IF((scale_y_d >= 16 * scale_y_n) || (scale_x_d >= 16 * scale_x_n), "OpResize: invalid attribute scale");
+ ERROR_IF((offset_y < -scale_y_n) || (offset_y >= 16 * scale_y_n),
+ "OpResize: invalid attribute offset height dimension");
+ ERROR_IF((offset_x < -scale_x_n) || (offset_x >= 16 * scale_x_n),
+ "OpResize: invalid attribute offset width dimension");
+ ERROR_IF((border_y < -16 * scale_y_n || border_y >= scale_y_n),
+ "OpResize: invalid attribute border height dimension");
+ ERROR_IF((border_x < -16 * scale_x_n || border_x >= scale_x_n),
+ "OpResize: invalid attribute border width dimension");
+
+ int32_t res_height = 0;
+ int32_t res_width = 0;
+
+ if (idiv_check((in_height - 1) * scale_y_n - offset_y + border_y, scale_y_d, res_height))
+ return 1;
+
+ if (idiv_check((in_width - 1) * scale_x_n - offset_x + border_x, scale_x_d, res_width))
+ return 1;
+
+ ERROR_IF(out_height != res_height + 1,
+ "OpResize: mismatch between output height dimension provided and expected shape");
+ ERROR_IF(out_width != res_width + 1,
+ "OpResize: mismatch between output width dimension provided and expected shape");
for (int b = 0; b < out_batch; b++)
for (int c = 0; c < out_channels; c++)
for (int oy = 0; oy < out_height; oy++)
for (int ox = 0; ox < out_width; ox++)
{
- int32_t y = oy * stride[0] + offset[0];
- int32_t x = ox * stride[1] + offset[1];
+ int32_t y = oy * scale_y_d + offset_y;
+ int32_t x = ox * scale_x_d + offset_x;
- int32_t iy = y >> shift;
- int32_t dy = y - (iy << shift);
- int32_t ix = x >> shift;
- int32_t dx = x - (ix << shift);
-
- int32_t iy0 = MAX(iy, 0);
- int32_t iy1 = MIN(iy + 1, in_height - 1);
- int32_t ix0 = MAX(ix, 0);
- int32_t ix1 = MIN(ix + 1, in_width - 1);
+ float fy = static_cast<float>(y) / static_cast<float>(scale_y_n);
+ float fx = static_cast<float>(x) / static_cast<float>(scale_x_n);
- REQUIRE(iy0 <= iy1 && ix0 <= ix1, "OpResize: invalid index (iy0, iy1, ix0, ix1)=(%d,%d,%d,%d)", iy0,
- iy1, ix0, ix1);
+ int32_t iy = floor(fy);
+ int32_t ix = floor(fx);
- OutEigenType acc;
- if (mode == ResizeMode_BILINEAR)
+ resize_t dy;
+ resize_t dx;
+ if (std::is_floating_point<resize_t>::value)
{
- InEigenType v00 = in->getTensor()(b, iy0, ix0, c);
- InEigenType v01 = in->getTensor()(b, iy0, ix1, c);
- InEigenType v10 = in->getTensor()(b, iy1, ix0, c);
- InEigenType v11 = in->getTensor()(b, iy1, ix1, c);
-
- acc = (OutEigenType)v00 * ((1 << shift) - dy) * ((1 << shift) - dx);
- acc = acc + (OutEigenType)v01 * ((1 << shift) - dy) * dx;
- acc = acc + (OutEigenType)v10 * dy * ((1 << shift) - dx);
- acc = acc + (OutEigenType)v11 * dy * dx;
+ dy = fy - iy;
+ dx = fx - ix;
}
else
{
- iy = (dy >> (shift - 1)) != 0 ? iy1 : iy0;
- ix = (dx >> (shift - 1)) != 0 ? ix1 : ix0;
- acc = in->getTensor()(b, iy, ix, c);
+ dy = y - (iy * scale_y_n);
+ dx = x - (ix * scale_x_n);
}
- out->getTensor()(b, oy, ox, c) = acc;
- }
-
- return GraphNode::eval();
-}
-
-template <>
-int OpResize<DType_FLOAT, DType_FLOAT>::eval()
-{
- int in_batch = in->getShape()[0];
- int in_height = in->getShape()[1];
- int in_width = in->getShape()[2];
- int in_channels = in->getShape()[3];
-
- int out_batch = out->getShape()[0];
- int out_height = out->getShape()[1];
- int out_width = out->getShape()[2];
- int out_channels = out->getShape()[3];
-
- ERROR_IF(std::max<int>({ in_height, in_width, out_height, out_width }) >= 16384,
- "OpResize: exceeds maximum dimension");
- ERROR_IF(shift != 0, "OpResize: float mode must have 0 shift");
- ERROR_IF(stride_fp[0] <= 0.0f || stride_fp[1] <= 0.0f, "OpResize: invalid attribute stride");
- ERROR_IF(stride_fp[0] > in_height || stride_fp[1] > in_width, "OpResize: stride larger than dimension");
- ERROR_IF(in_batch != out_batch, "OpResize: output tensor batch mismatch");
- ERROR_IF(in_channels != out_channels, "OpResize: output tensor channel mismatch");
-
- for (int b = 0; b < out_batch; b++)
- for (int c = 0; c < out_channels; c++)
- for (int oy = 0; oy < out_height; oy++)
- for (int ox = 0; ox < out_width; ox++)
- {
- float y = oy * stride_fp[0] + offset_fp[0];
- float x = ox * stride_fp[1] + offset_fp[1];
-
- int32_t iy = static_cast<int32_t>(std::floor(y));
- float dy = y - static_cast<float>(iy);
- int32_t ix = static_cast<int32_t>(std::floor(x));
- float dx = x - static_cast<float>(ix);
-
int32_t iy0 = MAX(iy, 0);
int32_t iy1 = MIN(iy + 1, in_height - 1);
int32_t ix0 = MAX(ix, 0);
int32_t ix1 = MIN(ix + 1, in_width - 1);
- REQUIRE(iy0 <= iy1 && ix0 <= ix1, "OpResize: invalid index (iy0, iy1, ix0, ix1)=(%d,%d,%d,%d)", iy0,
- iy1, ix0, ix1);
-
OutEigenType acc;
if (mode == ResizeMode_BILINEAR)
{
@@ -210,18 +183,36 @@ int OpResize<DType_FLOAT, DType_FLOAT>::eval()
InEigenType v10 = in->getTensor()(b, iy1, ix0, c);
InEigenType v11 = in->getTensor()(b, iy1, ix1, c);
- acc = (OutEigenType)v00 * (1.0 - dy) * (1.0 - dx);
- acc = acc + (OutEigenType)v01 * (1.0 - dy) * dx;
- acc = acc + (OutEigenType)v10 * dy * (1.0 - dx);
- acc = acc + (OutEigenType)v11 * dy * dx;
+ if (std::is_floating_point<resize_t>::value)
+ {
+ acc = (OutEigenType)v00 * (1.0 - dy) * (1.0 - dx);
+ acc += (OutEigenType)v01 * (1.0 - dy) * dx;
+ acc += (OutEigenType)v10 * dy * (1.0 - dx);
+ acc += (OutEigenType)v11 * dy * dx;
+ }
+ else
+ {
+ acc = (OutEigenType)v00 * (scale_y_n - dy) * (scale_x_n - dx);
+ acc += (OutEigenType)v01 * (scale_y_n - dy) * dx;
+ acc += (OutEigenType)v10 * dy * (scale_x_n - dx);
+ acc += (OutEigenType)v11 * dy * dx;
+ }
}
else
{
- iy = (dy >= 0.5) ? iy1 : iy0;
- ix = (dx >= 0.5) ? ix1 : ix0;
+ ASSERT_MSG(mode == ResizeMode_NEAREST, "OpResize: invalid mode");
+ if (std::is_floating_point<resize_t>::value)
+ {
+ iy = (dy >= 0.5) ? iy1 : iy0;
+ ix = (dx >= 0.5) ? ix1 : ix0;
+ }
+ else
+ {
+ iy = (2 * dy >= scale_y_n) ? iy1 : iy0;
+ ix = (2 * dx >= scale_x_n) ? ix1 : ix0;
+ }
acc = in->getTensor()(b, iy, ix, c);
}
-
out->getTensor()(b, oy, ox, c) = acc;
}
@@ -229,8 +220,8 @@ int OpResize<DType_FLOAT, DType_FLOAT>::eval()
}
// template explicit instantiation
-DEF_INSTANTIATE_TWO_TYPE(OpResize, INT8, INT32);
-DEF_INSTANTIATE_TWO_TYPE(OpResize, INT8, INT8);
-DEF_INSTANTIATE_TWO_TYPE(OpResize, INT16, INT48);
-DEF_INSTANTIATE_TWO_TYPE(OpResize, INT16, INT16);
-DEF_INSTANTIATE_TWO_TYPE(OpResize, FLOAT, FLOAT);
+DEF_INSTANTIATE_THREE_TYPE(OpResize, INT8, INT32, int16_t);
+DEF_INSTANTIATE_THREE_TYPE(OpResize, INT8, INT8, int16_t);
+DEF_INSTANTIATE_THREE_TYPE(OpResize, INT16, INT48, int16_t);
+DEF_INSTANTIATE_THREE_TYPE(OpResize, INT16, INT16, int16_t);
+DEF_INSTANTIATE_THREE_TYPE(OpResize, FLOAT, FLOAT, float);
diff --git a/reference_model/src/ops/image.h b/reference_model/src/ops/image.h
index fea4885..508d2c8 100644
--- a/reference_model/src/ops/image.h
+++ b/reference_model/src/ops/image.h
@@ -23,7 +23,7 @@ using namespace tosa;
namespace TosaReference
{
-template <DType InDtype, DType OutDtype>
+template <DType InDtype, DType OutDtype, typename resize_t>
class OpResize : public GraphNode
{
public:
@@ -39,12 +39,9 @@ public:
protected:
TosaResizeAttribute* attribute;
- std::vector<int32_t> output_size;
- std::vector<int32_t> stride;
- std::vector<int32_t> offset;
- int32_t shift;
- std::vector<float> stride_fp;
- std::vector<float> offset_fp;
+ std::vector<int16_t> scale;
+ std::vector<int16_t> offset;
+ std::vector<int16_t> border;
ResizeMode mode;
TosaReference::TensorTemplate<TIn>* in;
TosaReference::TensorTemplate<TOut>* out;
diff --git a/reference_model/src/ops/op_factory.cc b/reference_model/src/ops/op_factory.cc
index 62d5b11..b6a2e15 100644
--- a/reference_model/src/ops/op_factory.cc
+++ b/reference_model/src/ops/op_factory.cc
@@ -342,11 +342,11 @@ GraphNode* OpFactory::newOp(SubgraphTraverser* sgt,
// image
case Op_RESIZE:
- DEF_FACTORY_TWO_TYPE_RESIZE(OpResize, INT8, INT32);
- DEF_FACTORY_TWO_TYPE_RESIZE(OpResize, INT8, INT8);
- DEF_FACTORY_TWO_TYPE_RESIZE(OpResize, INT16, INT48);
- DEF_FACTORY_TWO_TYPE_RESIZE(OpResize, INT16, INT16);
- DEF_FACTORY_TWO_TYPE_RESIZE(OpResize, FLOAT, FLOAT);
+ DEF_FACTORY_TWO_TYPE_RESIZE_INT16(OpResize, INT8, INT32);
+ DEF_FACTORY_TWO_TYPE_RESIZE_INT16(OpResize, INT8, INT8);
+ DEF_FACTORY_TWO_TYPE_RESIZE_INT16(OpResize, INT16, INT48);
+ DEF_FACTORY_TWO_TYPE_RESIZE_INT16(OpResize, INT16, INT16);
+ DEF_FACTORY_TWO_TYPE_RESIZE_FLOAT(OpResize, FLOAT, FLOAT);
break;
// data_nodes
diff --git a/reference_model/src/ops/op_factory.h b/reference_model/src/ops/op_factory.h
index 4cb8178..341d7dc 100644
--- a/reference_model/src/ops/op_factory.h
+++ b/reference_model/src/ops/op_factory.h
@@ -41,37 +41,43 @@
switch (inputRank) \
{ \
case 0: \
- return new OP<0>(sgt, attribute, id); \
+ return new OP<0>(sgt, attribute, id); \
case 1: \
- return new OP<1>(sgt, attribute, id); \
+ return new OP<1>(sgt, attribute, id); \
case 2: \
- return new OP<2>(sgt, attribute, id); \
+ return new OP<2>(sgt, attribute, id); \
case 3: \
- return new OP<3>(sgt, attribute, id); \
+ return new OP<3>(sgt, attribute, id); \
case 4: \
- return new OP<4>(sgt, attribute, id); \
+ return new OP<4>(sgt, attribute, id); \
case 5: \
- return new OP<5>(sgt, attribute, id); \
+ return new OP<5>(sgt, attribute, id); \
case 6: \
- return new OP<6>(sgt, attribute, id); \
+ return new OP<6>(sgt, attribute, id); \
}
#define DEF_FACTORY_ONE_TYPE(OP, DTYPE) \
if (inputDType == DType_##DTYPE) \
{ \
- return new OP<DType_##DTYPE>(sgt, attribute, id); \
+ return new OP<DType_##DTYPE>(sgt, attribute, id); \
}
#define DEF_FACTORY_TWO_TYPE(OP, DTYPE1, DTYPE2) \
if (inputDType == DType_##DTYPE1 && weightDType == DType_##DTYPE2) \
{ \
- return new OP<DType_##DTYPE1, DType_##DTYPE2>(sgt, attribute, id); \
+ return new OP<DType_##DTYPE1, DType_##DTYPE2>(sgt, attribute, id); \
}
-#define DEF_FACTORY_TWO_TYPE_RESIZE(OP, DTYPE1, DTYPE2) \
+#define DEF_FACTORY_TWO_TYPE_RESIZE_INT16(OP, DTYPE1, DTYPE2) \
if (inputDType == DType_##DTYPE1 && outputDType == DType_##DTYPE2) \
{ \
- return new OP<DType_##DTYPE1, DType_##DTYPE2>(sgt, attribute, id); \
+ return new OP<DType_##DTYPE1, DType_##DTYPE2, int16_t>(sgt, attribute, id); \
+ }
+
+#define DEF_FACTORY_TWO_TYPE_RESIZE_FLOAT(OP, DTYPE1, DTYPE2) \
+ if (inputDType == DType_##DTYPE1 && outputDType == DType_##DTYPE2) \
+ { \
+ return new OP<DType_##DTYPE1, DType_##DTYPE2, float>(sgt, attribute, id); \
}
#define DEF_FACTORY_RANK0_6_ONE_RANK_ONE_TYPE(OP, DTYPE) \
diff --git a/thirdparty/serialization_lib b/thirdparty/serialization_lib
-Subproject 343d6a703c3a270a01102ec468b59ef2967b595
+Subproject 49b1ca63975d4f1865ca312ed9c9b5e0008e13e
diff --git a/verif/frameworks/test_builder.py b/verif/frameworks/test_builder.py
index 97b9085..8677559 100644
--- a/verif/frameworks/test_builder.py
+++ b/verif/frameworks/test_builder.py
@@ -1021,6 +1021,45 @@ class TBuilder:
)
return tf.identity(resize, name=self.result_name)
+ # New tf resize set (align_corners, half_pixel_centers) = (false, true) by default.
+ # Test the rest option combinations here.
+ # Note that (align_corners, half_pixel_centers) = (true, true) is NOT valid.
+ class ResizeBilinearV1AlignCorners:
+ def __init__(self, name):
+ self.result_name = name
+
+ def eval(self, a):
+ out_shape = []
+ out_shape.append(a.shape[1] * 2)
+ out_shape.append(a.shape[2] * 2)
+
+ resize = tf.compat.v1.image.resize_bilinear(
+ a,
+ out_shape,
+ align_corners=True,
+ name="resize",
+ half_pixel_centers=False,
+ )
+ return tf.identity(resize, name=self.result_name)
+
+ class ResizeBilinearV1None:
+ def __init__(self, name):
+ self.result_name = name
+
+ def eval(self, a):
+ out_shape = []
+ out_shape.append(a.shape[1] * 2)
+ out_shape.append(a.shape[2] * 2)
+
+ resize = tf.compat.v1.image.resize_bilinear(
+ a,
+ out_shape,
+ align_corners=False,
+ name="resize",
+ half_pixel_centers=False,
+ )
+ return tf.identity(resize, name=self.result_name)
+
class LeftShift:
def __init__(self, shift, name):
self.shift = shift
diff --git a/verif/frameworks/tosa_verif_framework_generator.py b/verif/frameworks/tosa_verif_framework_generator.py
index 8d8b155..4167227 100755
--- a/verif/frameworks/tosa_verif_framework_generator.py
+++ b/verif/frameworks/tosa_verif_framework_generator.py
@@ -698,6 +698,30 @@ TF_OP_LIST = {
),
},
},
+ "resize_bilinear_v1_align_corners": {
+ "operands": (1, 0),
+ "build_fcn": (
+ TBuilder.ResizeBilinearV1AlignCorners,
+ TGen.tgPooling,
+ ArgGen.agNone,
+ ),
+ "types": {
+ "tf": TYPE_F,
+ "tflite": list(
+ TYPE_F + [QuantType.ALL_U8, QuantType.ALL_I8, QuantType.ALL_I16]
+ ),
+ },
+ },
+ "resize_bilinear_v1_none": {
+ "operands": (1, 0),
+ "build_fcn": (TBuilder.ResizeBilinearV1None, TGen.tgPooling, ArgGen.agNone),
+ "types": {
+ "tf": TYPE_F,
+ "tflite": list(
+ TYPE_F + [QuantType.ALL_U8, QuantType.ALL_I8, QuantType.ALL_I16]
+ ),
+ },
+ },
"left_shift": {
"operands": (1, 0),
"build_fcn": (TBuilder.LeftShift, TGen.tgBasic, ArgGen.agShift),