* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "gtest/gtest.h"
#include "ascir_ops.h"
#include "codegen_kernel.h"
#include "utils/api_call_utils.h"
using namespace std;
using namespace af::ops;
using namespace codegen;
using namespace af::ascir_op;
* Axis: z0 z1 z2
* repeat: s0 s1 s2
* stride: s1*s2 s2 one
* vectorized stride: s2 one
*/
TEST(CodegenLoadStore, CalculateDmaParams_UbGMContinus) {
af::SizeVar s0(af::Symbol("s0"));
af::SizeVar s1(af::Symbol("s1"));
af::SizeVar s2(af::Symbol("s2"));
af::Axis z0{.id = 0, .name = "z0", .type = af::Axis::Type::kAxisTypeTileOuter, .size = s0.expr};
af::Axis z1{.id = 1, .name = "z1", .type = af::Axis::Type::kAxisTypeTileInner, .size = s1.expr};
af::Axis z2{.id = 2, .name = "z2", .type = af::Axis::Type::kAxisTypeOriginal, .size = s2.expr};
codegen::Tiler tiler;
tiler.AddSizeVar(af::SizeVar(s0));
tiler.AddSizeVar(af::SizeVar(s1));
tiler.AddSizeVar(af::SizeVar(s2));
tiler.AddAxis(z0);
tiler.AddAxis(z1);
tiler.AddAxis(z2);
codegen::TPipe tpipe("tpipe", tiler);
af::AscGraph graph("test");
af::ascir_op::Data x("x", graph);
auto node = graph.FindNode("x");
af::AscTensor tensor = node->outputs[0];
tensor.attr.axis = {z0.id, z1.id, z2.id};
tensor.attr.vectorized_axis = {z1.id, z2.id};
tensor.attr.repeats = {z0.size, z1.size, z2.size};
tensor.attr.strides = {z1.size*z2.size, z2.size, One};
vector<af::Expression> vectorized_strides{One, One};
vectorized_strides[0] = z2.size;
tensor.attr.vectorized_strides = vectorized_strides;
std::string dtype_name;
Tensor::DtypeName(tensor.attr.dtype, dtype_name);
DataCopyParams param;
Tensor tensor1(tensor, dtype_name);
Tensor tensor2(tensor, dtype_name);
tensor1.vectorized_axis_pos = {1, 2};
tensor2.vectorized_axis_pos = {1, 2};
EXPECT_EQ(CalculateDmaParams(tpipe, tensor1, tensor2, param), true);
EXPECT_EQ(param.repeats.size(), 1);
EXPECT_EQ(param.repeats[0], af::Expression::Parse("s1*s2"));
EXPECT_EQ(param.gm_strides.size(), 1);
EXPECT_EQ(param.gm_strides[0], af::Expression::Parse("1"));
EXPECT_EQ(param.ub_strides.size(), 1);
EXPECT_EQ(param.ub_strides[0], af::Expression::Parse("1"));
}
* Axis: z0 z1 z2
* repeat: s0 s1 s2
* stride: s1*s2 s2 one
* vectorized stride: align(s2) one
*/
TEST(CodegenLoadStore, CalculateDmaParams_DiscreteUbContinusGM) {
af::SizeVar s0(af::Symbol("s0"));
af::SizeVar s1(af::Symbol("s1"));
af::SizeVar s2(af::Symbol("s2"));
af::Axis z0{.id = 0, .name = "z0", .type = af::Axis::Type::kAxisTypeTileOuter, .size = s0.expr};
af::Axis z1{.id = 1, .name = "z1", .type = af::Axis::Type::kAxisTypeTileInner, .size = s1.expr};
af::Axis z2{.id = 2, .name = "z2", .type = af::Axis::Type::kAxisTypeOriginal, .size = s2.expr};
codegen::Tiler tiler;
tiler.AddSizeVar(af::SizeVar(s0));
tiler.AddSizeVar(af::SizeVar(s1));
tiler.AddSizeVar(af::SizeVar(s2));
tiler.AddAxis(z0);
tiler.AddAxis(z1);
tiler.AddAxis(z2);
codegen::TPipe tpipe("tpipe", tiler);
af::AscGraph graph("test");
af::ascir_op::Data x("x", graph);
auto node = graph.FindNode("x");
af::AscTensor tensor = node->outputs[0];
tensor.attr.axis = {z0.id, z1.id, z2.id};
tensor.attr.vectorized_axis = {z1.id, z2.id};
tensor.attr.repeats = {z0.size, z1.size, z2.size};
tensor.attr.strides = {z1.size*z2.size, z2.size, One};
vector<af::Expression> vectorized_strides{One, One};
vectorized_strides[0] = af::sym::Align(z2.size, 32);
tensor.attr.vectorized_strides = vectorized_strides;
std::string dtype_name;
Tensor::DtypeName(tensor.attr.dtype, dtype_name);
DataCopyParams param;
Tensor tensor1(tensor, dtype_name);
Tensor tensor2(tensor, dtype_name);
tensor1.vectorized_axis_pos = {1, 2};
tensor2.vectorized_axis_pos = {1, 2};
EXPECT_EQ(CalculateDmaParams(tpipe, tensor1, tensor2, param), true);
EXPECT_EQ(param.repeats.size(), 2);
EXPECT_EQ(param.repeats[0], af::Expression::Parse("s1"));
EXPECT_EQ(param.repeats[1], af::Expression::Parse("s2"));
EXPECT_EQ(param.gm_strides.size(), 2);
EXPECT_EQ(param.gm_strides[0], af::Expression::Parse("s2"));
EXPECT_EQ(param.gm_strides[1], af::Expression::Parse("1"));
EXPECT_EQ(param.ub_strides.size(), 2);
EXPECT_EQ(param.ub_strides[0], af::sym::Align(z2.size, 32));
EXPECT_EQ(param.ub_strides[1], af::Expression::Parse("1"));
}
* Axis: z0 z1 z2
* repeat: s0 s1 s2
* stride: 2*s1*s2 2*s2 one
* vectorized stride: s2 one
*/
TEST(CodegenLoadStore, CalculateDmaParams_ContinusUbDiscreteGM) {
af::SizeVar s0(af::Symbol("s0"));
af::SizeVar s1(af::Symbol("s1"));
af::SizeVar s2(af::Symbol("s2"));
af::Axis z0{.id = 0, .name = "z0", .type = af::Axis::Type::kAxisTypeTileOuter, .size = s0.expr};
af::Axis z1{.id = 1, .name = "z1", .type = af::Axis::Type::kAxisTypeTileInner, .size = s1.expr};
af::Axis z2{.id = 2, .name = "z2", .type = af::Axis::Type::kAxisTypeOriginal, .size = s2.expr};
codegen::Tiler tiler;
tiler.AddSizeVar(af::SizeVar(s0));
tiler.AddSizeVar(af::SizeVar(s1));
tiler.AddSizeVar(af::SizeVar(s2));
tiler.AddAxis(z0);
tiler.AddAxis(z1);
tiler.AddAxis(z2);
codegen::TPipe tpipe("tpipe", tiler);
af::AscGraph graph("test");
af::ascir_op::Data x("x", graph);
auto node = graph.FindNode("x");
af::AscTensor tensor = node->outputs[0];
tensor.attr.axis = {z0.id, z1.id, z2.id};
tensor.attr.vectorized_axis = {z1.id, z2.id};
tensor.attr.repeats = {z0.size, z1.size, z2.size};
tensor.attr.strides = {z1.size*(z2.size + z2.size), z2.size + z2.size, One};
vector<af::Expression> vectorized_strides{One, One};
vectorized_strides[0] = z2.size;
tensor.attr.vectorized_strides = vectorized_strides;
std::string dtype_name;
Tensor::DtypeName(tensor.attr.dtype, dtype_name);
DataCopyParams param;
Tensor tensor1(tensor, dtype_name);
Tensor tensor2(tensor, dtype_name);
tensor1.vectorized_axis_pos = {1, 2};
tensor2.vectorized_axis_pos = {1, 2};
EXPECT_EQ(CalculateDmaParams(tpipe, tensor1, tensor2, param), true);
EXPECT_EQ(param.repeats.size(), 2);
EXPECT_EQ(param.repeats[0], af::Expression::Parse("s1"));
EXPECT_EQ(param.repeats[1], af::Expression::Parse("s2"));
EXPECT_EQ(param.gm_strides.size(), 2);
EXPECT_EQ(param.gm_strides[0], af::Expression::Parse("2 * s2"));
EXPECT_EQ(param.gm_strides[1], af::Expression::Parse("1"));
EXPECT_EQ(param.ub_strides.size(), 2);
EXPECT_EQ(param.ub_strides[0], af::Expression::Parse("s2"));
EXPECT_EQ(param.ub_strides[1], af::Expression::Parse("1"));
}
* Axis: z0 z1 z2 z3 z4
* repeat: s0 s1 s2 s3 s4
* stride: 2*s1*s2*(s3*s4+s3*s4) (s2+s2)*(s3*s4+s3*s4) 2*s3*s4 2*s4 one
* vectorized stride: s2*s3*s4 s3*s4 s4 one
*/
TEST(CodegenLoadStore, CalculateDmaParams_4DContinusUbDiscreteGM) {
af::SizeVar s0(af::Symbol("s0"));
af::SizeVar s1(af::Symbol("s1"));
af::SizeVar s2(af::Symbol("s2"));
af::SizeVar s3(af::Symbol("s3"));
af::SizeVar s4(af::Symbol("s4"));
af::Axis z0{.id = 0, .name = "z0", .type = af::Axis::Type::kAxisTypeTileOuter, .size = s0.expr};
af::Axis z1{.id = 1, .name = "z1", .type = af::Axis::Type::kAxisTypeTileInner, .size = s1.expr};
af::Axis z2{.id = 2, .name = "z2", .type = af::Axis::Type::kAxisTypeOriginal, .size = s2.expr};
af::Axis z3{.id = 3, .name = "z3", .type = af::Axis::Type::kAxisTypeOriginal, .size = s3.expr};
af::Axis z4{.id = 4, .name = "z4", .type = af::Axis::Type::kAxisTypeOriginal, .size = s4.expr};
codegen::Tiler tiler;
tiler.AddSizeVar(af::SizeVar(s0));
tiler.AddSizeVar(af::SizeVar(s1));
tiler.AddSizeVar(af::SizeVar(s2));
tiler.AddSizeVar(af::SizeVar(s3));
tiler.AddSizeVar(af::SizeVar(s4));
tiler.AddAxis(z0);
tiler.AddAxis(z1);
tiler.AddAxis(z2);
tiler.AddAxis(z3);
tiler.AddAxis(z4);
codegen::TPipe tpipe("tpipe", tiler);
af::AscGraph graph("test");
af::ascir_op::Data x("x", graph);
auto node = graph.FindNode("x");
af::AscTensor tensor = node->outputs[0];
tensor.attr.axis = {z0.id, z1.id, z2.id, z3.id, z4.id};
tensor.attr.vectorized_axis = {z1.id, z2.id, z3.id, z4.id};
tensor.attr.repeats = {z0.size, z1.size, z2.size, z3.size, z4.size};
tensor.attr.strides = {z1.size*(z2.size+z2.size)*(z3.size*(z4.size + z4.size)),
(z2.size+z2.size)*(z3.size*(z4.size + z4.size)),
z3.size*(z4.size + z4.size), z4.size + z4.size, One};
vector<af::Expression> vectorized_strides{z2.size*z3.size*z4.size, z3.size*z4.size, z4.size, One};
tensor.attr.vectorized_strides = vectorized_strides;
std::string dtype_name;
Tensor::DtypeName(tensor.attr.dtype, dtype_name);
DataCopyParams param;
Tensor tensor1(tensor, dtype_name);
Tensor tensor2(tensor, dtype_name);
tensor1.vectorized_axis_pos = {1, 2, 3, 4};
tensor2.vectorized_axis_pos = {1, 2, 3, 4};
EXPECT_EQ(CalculateDmaParams(tpipe, tensor1, tensor2, param), true);
EXPECT_EQ(param.repeats.size(), 3);
EXPECT_EQ(param.repeats[0], af::Expression::Parse("s1"));
EXPECT_EQ(param.repeats[1], af::Expression::Parse("s2*s3"));
EXPECT_EQ(param.repeats[2], af::Expression::Parse("s4"));
EXPECT_EQ(param.gm_strides.size(), 3);
EXPECT_EQ(param.gm_strides[0], af::Expression::Parse("4*s2*s3*s4"));
EXPECT_EQ(param.gm_strides[1], af::Expression::Parse("2*s4"));
EXPECT_EQ(param.gm_strides[2], af::Expression::Parse("1"));
EXPECT_EQ(param.ub_strides.size(), 3);
EXPECT_EQ(param.ub_strides[0], af::Expression::Parse("s2*s3*s4"));
EXPECT_EQ(param.ub_strides[1], af::Expression::Parse("s4"));
EXPECT_EQ(param.ub_strides[2], af::Expression::Parse("1"));
}
* Axis: z0 z1 z2 z3 z4
* repeat: s0 s1 s2 s3 s4
* stride: 2*s1*s2*(s3*s4+s3*s4) (s2+s2)*(s3*s4+s3*s4) 2*s3*s4 2*s4 one
* vectorized stride: s2*align(s3*s4) align(s3*s4) s4 one
*/
TEST(CodegenLoadStore, CalculateDmaParams_4DDiscreteUbDiscreteGM) {
af::SizeVar s0(af::Symbol("s0"));
af::SizeVar s1(af::Symbol("s1"));
af::SizeVar s2(af::Symbol("s2"));
af::SizeVar s3(af::Symbol("s3"));
af::SizeVar s4(af::Symbol("s4"));
af::Axis z0{.id = 0, .name = "z0", .type = af::Axis::Type::kAxisTypeTileOuter, .size = s0.expr};
af::Axis z1{.id = 1, .name = "z1", .type = af::Axis::Type::kAxisTypeTileInner, .size = s1.expr};
af::Axis z2{.id = 2, .name = "z2", .type = af::Axis::Type::kAxisTypeOriginal, .size = s2.expr};
af::Axis z3{.id = 3, .name = "z3", .type = af::Axis::Type::kAxisTypeOriginal, .size = s3.expr};
af::Axis z4{.id = 4, .name = "z4", .type = af::Axis::Type::kAxisTypeOriginal, .size = s4.expr};
codegen::Tiler tiler;
tiler.AddSizeVar(af::SizeVar(s0));
tiler.AddSizeVar(af::SizeVar(s1));
tiler.AddSizeVar(af::SizeVar(s2));
tiler.AddSizeVar(af::SizeVar(s3));
tiler.AddSizeVar(af::SizeVar(s4));
tiler.AddAxis(z0);
tiler.AddAxis(z1);
tiler.AddAxis(z2);
tiler.AddAxis(z3);
tiler.AddAxis(z4);
codegen::TPipe tpipe("tpipe", tiler);
af::AscGraph graph("test");
af::ascir_op::Data x("x", graph);
auto node = graph.FindNode("x");
af::AscTensor tensor = node->outputs[0];
tensor.attr.axis = {z0.id, z1.id, z2.id, z3.id, z4.id};
tensor.attr.vectorized_axis = {z1.id, z2.id, z3.id, z4.id};
tensor.attr.repeats = {z0.size, z1.size, z2.size, z3.size, z4.size};
tensor.attr.strides = {z1.size*(z2.size+z2.size)*(z3.size*(z4.size + z4.size)),
(z2.size+z2.size)*(z3.size*(z4.size + z4.size)),
z3.size*(z4.size + z4.size), z4.size + z4.size, One};
vector<af::Expression> vectorized_strides{z2.size*af::sym::Align(z3.size*z4.size, 32),
af::sym::Align(z3.size*z4.size, 32), z4.size, One};
tensor.attr.vectorized_strides = vectorized_strides;
std::string dtype_name;
Tensor::DtypeName(tensor.attr.dtype, dtype_name);
DataCopyParams param;
Tensor tensor1(tensor, dtype_name);
Tensor tensor2(tensor, dtype_name);
tensor1.vectorized_axis_pos = {1, 2, 3, 4};
tensor2.vectorized_axis_pos = {1, 2, 3, 4};
EXPECT_EQ(CalculateDmaParams(tpipe, tensor1, tensor2, param), true);
EXPECT_EQ(param.repeats.size(), 4);
EXPECT_EQ(param.gm_strides.size(), 4);
EXPECT_EQ(param.gm_strides[0], af::Expression::Parse("4*s2*s3*s4"));
EXPECT_EQ(param.gm_strides[1], af::Expression::Parse("2*s3*s4"));
EXPECT_EQ(param.ub_strides.size(), 4);
EXPECT_EQ(param.ub_strides[0], z2.size*af::sym::Align(z3.size*z4.size, 32));
EXPECT_EQ(param.ub_strides[1], af::sym::Align(z3.size*z4.size, 32));
}
* Axis: z0 z1 z2 z3 z4
* repeat: s0 s1 s2 s3 s4
* stride: s1*s2*(s3*s4+s3*s4) s2*(s3*s4+s3*s4) 2*s3*s4 2*s4 one
* vectorized axis: z2 z1 z3 z4
* vectorized stride: s1*s3*s4 s3*s4 s4 one
*/
TEST(CodegenLoadStore, CalculateDmaParams_ReorderContinusUbDiscreteGM) {
af::SizeVar s0(af::Symbol("s0"));
af::SizeVar s1(af::Symbol("s1"));
af::SizeVar s2(af::Symbol("s2"));
af::SizeVar s3(af::Symbol("s3"));
af::SizeVar s4(af::Symbol("s4"));
af::Axis z0{.id = 0, .name = "z0", .type = af::Axis::Type::kAxisTypeTileOuter, .size = s0.expr};
af::Axis z1{.id = 1, .name = "z1", .type = af::Axis::Type::kAxisTypeTileInner, .size = s1.expr};
af::Axis z2{.id = 2, .name = "z2", .type = af::Axis::Type::kAxisTypeOriginal, .size = s2.expr};
af::Axis z3{.id = 3, .name = "z3", .type = af::Axis::Type::kAxisTypeOriginal, .size = s3.expr};
af::Axis z4{.id = 4, .name = "z4", .type = af::Axis::Type::kAxisTypeOriginal, .size = s4.expr};
codegen::Tiler tiler;
tiler.AddSizeVar(af::SizeVar(s0));
tiler.AddSizeVar(af::SizeVar(s1));
tiler.AddSizeVar(af::SizeVar(s2));
tiler.AddSizeVar(af::SizeVar(s3));
tiler.AddSizeVar(af::SizeVar(s4));
tiler.AddAxis(z0);
tiler.AddAxis(z1);
tiler.AddAxis(z2);
tiler.AddAxis(z3);
tiler.AddAxis(z4);
codegen::TPipe tpipe("tpipe", tiler);
af::AscGraph graph("test");
af::ascir_op::Data x("x", graph);
auto node = graph.FindNode("x");
af::AscTensor tensor = node->outputs[0];
tensor.attr.axis = {z0.id, z1.id, z2.id, z3.id, z4.id};
tensor.attr.vectorized_axis = {z2.id, z1.id, z3.id, z4.id};
tensor.attr.repeats = {z0.size, z1.size, z2.size, z3.size, z4.size};
tensor.attr.strides = {z1.size*z2.size*(z3.size*(z4.size + z4.size)),
(z2.size)*(z3.size*(z4.size + z4.size)),
z3.size*(z4.size + z4.size), z4.size + z4.size, One};
vector<af::Expression> vectorized_strides{z1.size*z3.size*z4.size, z3.size*z4.size, z4.size, One};
tensor.attr.vectorized_strides = vectorized_strides;
std::string dtype_name;
Tensor::DtypeName(tensor.attr.dtype, dtype_name);
DataCopyParams param;
Tensor tensor1(tensor, dtype_name);
Tensor tensor2(tensor, dtype_name);
tensor1.vectorized_axis_pos = {2, 1, 3, 4};
tensor2.vectorized_axis_pos = {2, 1, 3, 4};
EXPECT_EQ(CalculateDmaParams(tpipe, tensor1, tensor2, param), true);
EXPECT_EQ(param.repeats.size(), 4);
EXPECT_EQ(param.repeats[0], af::Expression::Parse("s2"));
EXPECT_EQ(param.repeats[1], af::Expression::Parse("s1"));
EXPECT_EQ(param.gm_strides.size(), 4);
EXPECT_EQ(param.gm_strides[0], af::Expression::Parse("2*s3*s4"));
EXPECT_EQ(param.gm_strides[1], af::Expression::Parse("2*s2*s3*s4"));
EXPECT_EQ(param.ub_strides.size(), 4);
EXPECT_EQ(param.ub_strides[0], af::Expression::Parse("s1*s3*s4"));
EXPECT_EQ(param.ub_strides[1], af::Expression::Parse("s3*s4"));
}
* Axis: z0 z1 z2
* repeat: s0 s1 s2
* stride: s1*s2 s2 Zero
* vectorized stride: s2 one
*/
TEST(CodegenLoadStore, CalculateDmaParams_scalar) {
af::SizeVar s0(af::Symbol("s0"));
af::SizeVar s1(af::Symbol("s1"));
af::SizeVar s2(af::Symbol("s2"));
af::Axis z0{.id = 0, .name = "z0", .type = af::Axis::Type::kAxisTypeTileOuter, .size = s0.expr};
af::Axis z1{.id = 1, .name = "z1", .type = af::Axis::Type::kAxisTypeTileInner, .size = s1.expr};
af::Axis z2{.id = 2, .name = "z2", .type = af::Axis::Type::kAxisTypeOriginal, .size = s2.expr};
codegen::Tiler tiler;
tiler.AddSizeVar(af::SizeVar(s0));
tiler.AddSizeVar(af::SizeVar(s1));
tiler.AddSizeVar(af::SizeVar(s2));
tiler.AddAxis(z0);
tiler.AddAxis(z1);
tiler.AddAxis(z2);
codegen::TPipe tpipe("tpipe", tiler);
af::AscGraph graph("test");
af::ascir_op::Data x("x", graph);
auto node = graph.FindNode("x");
af::AscTensor tensor = node->outputs[0];
tensor.attr.axis = {z0.id, z1.id, z2.id};
tensor.attr.vectorized_axis = {z1.id, z2.id};
tensor.attr.repeats = {One, One, One};
tensor.attr.strides = {Zero, Zero, Zero};
vector<af::Expression> vectorized_strides{One, One};
tensor.attr.vectorized_strides = vectorized_strides;
std::string dtype_name;
Tensor::DtypeName(tensor.attr.dtype, dtype_name);
DataCopyParams param;
Tensor tensor1(tensor, dtype_name);
Tensor tensor2(tensor, dtype_name);
tensor1.vectorized_axis_pos = {1, 2};
tensor2.vectorized_axis_pos = {1, 2};
EXPECT_EQ(CalculateDmaParams(tpipe, tensor1, tensor2, param), true);
EXPECT_EQ(param.repeats.size(), 1);
EXPECT_EQ(param.gm_strides.size(), 1);
EXPECT_EQ(param.ub_strides.size(), 1);
}
TEST(CodegenLoadStore, CalculateDmaParams_LastAxisDisContinuous) {
af::SizeVar s0(af::Symbol("s0"));
af::SizeVar s1(af::Symbol("s1"));
af::SizeVar s2(af::Symbol("s2"));
af::Axis z0{.id = 0, .name = "z0", .type = af::Axis::Type::kAxisTypeTileOuter, .size = s0.expr};
af::Axis z1{.id = 1, .name = "z1", .type = af::Axis::Type::kAxisTypeTileInner, .size = s1.expr};
af::Axis z2{.id = 2, .name = "z2", .type = af::Axis::Type::kAxisTypeOriginal, .size = s2.expr};
codegen::Tiler tiler;
tiler.AddSizeVar(af::SizeVar(s0));
tiler.AddSizeVar(af::SizeVar(s1));
tiler.AddSizeVar(af::SizeVar(s2));
tiler.AddAxis(z0);
tiler.AddAxis(z1);
tiler.AddAxis(z2);
codegen::TPipe tpipe("tpipe", tiler);
af::AscGraph graph("test");
af::ascir_op::Data x("x", graph);
auto node = graph.FindNode("x");
af::AscTensor tensor = node->outputs[0];
tensor.attr.axis = {z0.id, z1.id, z2.id};
tensor.attr.vectorized_axis = {z1.id, z2.id};
tensor.attr.repeats = {z0.size, z1.size, z2.size};
tensor.attr.strides = {z1.size * z2.size * af::Symbol(2), z2.size * af::Symbol(2), af::Symbol(2)};
vector<af::Expression> vectorized_strides{z2.size * af::Symbol(2), af::Symbol(2)};
tensor.attr.vectorized_strides = vectorized_strides;
std::string dtype_name;
Tensor::DtypeName(tensor.attr.dtype, dtype_name);
DataCopyParams param;
Tensor tensor1(tensor, dtype_name);
Tensor tensor2(tensor, dtype_name);
tensor1.vectorized_axis_pos = {1, 2};
tensor2.vectorized_axis_pos = {1, 2};
EXPECT_EQ(CalculateDmaParams(tpipe, tensor1, tensor2, param), true);
EXPECT_EQ(param.repeats.size(), 2);
EXPECT_EQ(param.gm_strides.size(), 2);
EXPECT_EQ(param.ub_strides.size(), 2);
}