* Copyright (c) 2026 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.
*/
* \file test_memref.cpp
* \brief Unit tests for IR memory reference structures
*/
#include "gtest/gtest.h"
#include <memory>
#include "core/dtype.h"
#include "ir/memref.h"
#include "ir/scalar_expr.h"
namespace pypto {
namespace ir {
TEST(IRMemRefTest, TestMemRefBasicConstructor)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::DDR, addr, 1024);
ASSERT_EQ(memref.memorySpace_, MemorySpace::DDR);
ASSERT_EQ(memref.addr_, addr);
ASSERT_EQ(memref.size_, 1024);
}
TEST(IRMemRefTest, TestMemRefWithDifferentSpaces)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef ddrRef(MemorySpace::DDR, addr, 1024);
MemRef ubRef(MemorySpace::Vec, addr, 2048);
MemRef l1Ref(MemorySpace::Mat, addr, 512);
MemRef l0aRef(MemorySpace::Left, addr, 256);
ASSERT_EQ(ddrRef.memorySpace_, MemorySpace::DDR);
ASSERT_EQ(ubRef.memorySpace_, MemorySpace::Vec);
ASSERT_EQ(l1Ref.memorySpace_, MemorySpace::Mat);
ASSERT_EQ(l0aRef.memorySpace_, MemorySpace::Left);
}
TEST(IRMemRefTest, TestMemRefWithL0Spaces)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef l0aRef(MemorySpace::Left, addr, 128);
MemRef l0bRef(MemorySpace::Right, addr, 128);
MemRef l0cRef(MemorySpace::Acc, addr, 128);
ASSERT_EQ(l0aRef.memorySpace_, MemorySpace::Left);
ASSERT_EQ(l0bRef.memorySpace_, MemorySpace::Right);
ASSERT_EQ(l0cRef.memorySpace_, MemorySpace::Acc);
}
TEST(IRMemRefTest, TestMemRefWithDDRSpace)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::DDR, addr, 1024);
ASSERT_EQ(memref.memorySpace_, MemorySpace::DDR);
}
TEST(IRMemRefTest, TestMemRefWithZeroAddress)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::DDR, addr, 1024);
ASSERT_NE(memref.addr_, nullptr);
auto constAddr = std::dynamic_pointer_cast<const ConstInt>(memref.addr_);
ASSERT_NE(constAddr, nullptr);
ASSERT_EQ(constAddr->value_, 0);
}
TEST(IRMemRefTest, TestMemRefWithNonZeroAddress)
{
auto addr = std::make_shared<ConstInt>(0x1000, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::Vec, addr, 2048);
ASSERT_NE(memref.addr_, nullptr);
auto constAddr = std::dynamic_pointer_cast<const ConstInt>(memref.addr_);
ASSERT_NE(constAddr, nullptr);
ASSERT_EQ(constAddr->value_, 0x1000);
}
TEST(IRMemRefTest, TestMemRefWithVariableAddress)
{
auto base = std::make_shared<ConstInt>(0x1000, DataType::INT64, Span::Unknown());
auto offset = std::make_shared<ConstInt>(256, DataType::INT64, Span::Unknown());
auto addr = std::make_shared<Add>(base, offset, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::Mat, addr, 512);
ASSERT_NE(memref.addr_, nullptr);
ASSERT_EQ(memref.addr_->TypeName(), "Add");
}
TEST(IRMemRefTest, TestMemRefWithZeroSize)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::DDR, addr, 0);
ASSERT_EQ(memref.size_, 0);
}
TEST(IRMemRefTest, TestMemRefWithSmallSize)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::Left, addr, 64);
ASSERT_EQ(memref.size_, 64);
}
TEST(IRMemRefTest, TestMemRefWithLargeSize)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::DDR, addr, 1024 * 1024 * 1024);
ASSERT_EQ(memref.size_, 1024 * 1024 * 1024);
}
TEST(IRMemRefTest, TestMemRefWithVariousSizes)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
MemRef ref1(MemorySpace::DDR, addr, 128);
MemRef ref2(MemorySpace::Vec, addr, 256);
MemRef ref3(MemorySpace::Mat, addr, 512);
MemRef ref4(MemorySpace::Vec, addr, 1024);
ASSERT_EQ(ref1.size_, 128);
ASSERT_EQ(ref2.size_, 256);
ASSERT_EQ(ref3.size_, 512);
ASSERT_EQ(ref4.size_, 1024);
}
TEST(IRMemRefTest, TestMemRefCopyConstructor)
{
auto addr = std::make_shared<ConstInt>(0x1000, DataType::INT64, Span::Unknown());
auto original = std::make_shared<MemRef>(MemorySpace::DDR, addr, 1024);
ASSERT_EQ(original->memorySpace_, MemorySpace::DDR);
ASSERT_EQ(original->addr_, addr);
ASSERT_EQ(original->size_, 1024);
auto another = std::make_shared<MemRef>(MemorySpace::DDR, addr, 1024);
ASSERT_EQ(another->memorySpace_, original->memorySpace_);
ASSERT_EQ(another->addr_, original->addr_);
ASSERT_EQ(another->size_, original->size_);
}
TEST(IRMemRefTest, TestMemRefAssignment)
{
auto addr1 = std::make_shared<ConstInt>(0x1000, DataType::INT64, Span::Unknown());
auto addr2 = std::make_shared<ConstInt>(0x2000, DataType::INT64, Span::Unknown());
auto ref1 = std::make_shared<MemRef>(MemorySpace::DDR, addr1, 1024);
auto ref2 = std::make_shared<MemRef>(MemorySpace::Vec, addr2, 2048);
ASSERT_NE(ref1->memorySpace_, ref2->memorySpace_);
ASSERT_NE(ref1->addr_, ref2->addr_);
ASSERT_NE(ref1->size_, ref2->size_);
}
TEST(IRMemRefTest, TestMemRefForTensorAllocation)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
size_t tensorSize = 10 * 20 * sizeof(float);
MemRef memref(MemorySpace::DDR, addr, tensorSize);
ASSERT_EQ(memref.memorySpace_, MemorySpace::DDR);
ASSERT_EQ(memref.size_, tensorSize);
}
TEST(IRMemRefTest, TestMemRefForTileAllocation)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
size_t tileSize = 16 * 16 * sizeof(float);
MemRef memref(MemorySpace::Left, addr, tileSize);
ASSERT_EQ(memref.memorySpace_, MemorySpace::Left);
ASSERT_EQ(memref.size_, tileSize);
}
TEST(IRMemRefTest, TestMemRefForBufferAllocation)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
size_t bufferSize = 4096;
MemRef memref(MemorySpace::Vec, addr, bufferSize);
ASSERT_EQ(memref.memorySpace_, MemorySpace::Vec);
ASSERT_EQ(memref.size_, bufferSize);
}
TEST(IRMemRefTest, TestMemRefWithOffsetAddress)
{
auto baseAddr = std::make_shared<ConstInt>(0x10000, DataType::INT64, Span::Unknown());
auto offset = std::make_shared<ConstInt>(1024, DataType::INT64, Span::Unknown());
auto addr = std::make_shared<Add>(baseAddr, offset, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::Mat, addr, 512);
ASSERT_EQ(memref.memorySpace_, MemorySpace::Mat);
ASSERT_EQ(memref.size_, 512);
ASSERT_EQ(memref.addr_->TypeName(), "Add");
}
TEST(IRMemRefTest, TestMemRefEquality)
{
auto addr = std::make_shared<ConstInt>(0x1000, DataType::INT64, Span::Unknown());
MemRef ref1(MemorySpace::DDR, addr, 1024);
MemRef ref2(MemorySpace::DDR, addr, 1024);
ASSERT_EQ(ref1.memorySpace_, ref2.memorySpace_);
ASSERT_EQ(ref1.addr_, ref2.addr_);
ASSERT_EQ(ref1.size_, ref2.size_);
}
TEST(IRMemRefTest, TestMemRefInequality)
{
auto addr1 = std::make_shared<ConstInt>(0x1000, DataType::INT64, Span::Unknown());
auto addr2 = std::make_shared<ConstInt>(0x2000, DataType::INT64, Span::Unknown());
MemRef ref1(MemorySpace::DDR, addr1, 1024);
MemRef ref2(MemorySpace::Vec, addr2, 2048);
ASSERT_NE(ref1.memorySpace_, ref2.memorySpace_);
ASSERT_NE(ref1.addr_, ref2.addr_);
ASSERT_NE(ref1.size_, ref2.size_);
}
TEST(IRMemRefTest, TestMemRefWithMaxSize)
{
auto addr = std::make_shared<ConstInt>(0, DataType::INT64, Span::Unknown());
size_t maxSize = std::numeric_limits<size_t>::max();
MemRef memref(MemorySpace::DDR, addr, maxSize);
ASSERT_EQ(memref.size_, maxSize);
}
TEST(IRMemRefTest, TestMemRefWithComplexAddressExpression)
{
auto base = std::make_shared<ConstInt>(0x10000, DataType::INT64, Span::Unknown());
auto index = std::make_shared<ConstInt>(5, DataType::INT64, Span::Unknown());
auto stride = std::make_shared<ConstInt>(256, DataType::INT64, Span::Unknown());
auto offset = std::make_shared<Mul>(index, stride, DataType::INT64, Span::Unknown());
auto addr = std::make_shared<Add>(base, offset, DataType::INT64, Span::Unknown());
MemRef memref(MemorySpace::Mat, addr, 256);
ASSERT_NE(memref.addr_, nullptr);
ASSERT_EQ(memref.addr_->TypeName(), "Add");
}
}
}