* 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.
*/
#ifndef CCU_VARIABLE_HPP
#define CCU_VARIABLE_HPP
#include <cstdint>
#include <type_traits>
#include "ccu_types.h"
#include "ccu_utils.hpp"
#include "ccu_primitives_impl.h"
namespace AscendC {
namespace ccu {
class Variable;
class Address;
class LocalAddr;
class RemoteAddr;
template <typename U>
class Array;
template <typename T>
T GetResByChannel(ChannelHandle channel, uint32_t index);
struct CondExpr {
Variable* var{nullptr};
const Variable* rhsVar{nullptr};
uint64_t imm{0};
CcuConditionType cond{CCU_CONDITION_EQ};
bool isVarCompare{false};
};
class Variable final {
public:
Variable() { CCU_THROW_IF_FAILED(CcuVariableAlloc(&this->handle), "CcuVariableAlloc: failed"); }
explicit Variable(CcuVariableHandle varHandle, uint32_t index = 0)
{
CCU_THROW_IF_FAILED(
CcuVariableGetByIndex(varHandle, index, &this->handle), "CcuVariableGetByIndex: failed");
}
Variable(const Variable& other) { this->handle = other.handle; }
Variable(Variable&& other) noexcept { this->handle = other.handle; }
void operator=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableAssignVar(this->handle, other.handle),
"Variable::operator=(Variable): CcuVariableAssignVar failed");
}
void operator=(Variable&& other) { this->handle = other.handle; }
void operator=(uint64_t immediate) const
{
CCU_THROW_IF_FAILED(
CcuVariableAssignImm(this->handle, immediate),
"Variable::operator=(uint64_t): CcuVariableAssignImm failed");
}
void operator=(detail::CcuArithmeticOperator<Variable, Variable> op) const
{
switch (op.type) {
case detail::CcuArithmeticOperatorType::ADDITION:
CCU_THROW_IF_FAILED(
CcuVariableAddVarToVar(this->handle, op.lhs.handle, op.rhs.handle),
"Variable::operator=(Var+Var): CcuVariableAddVarToVar failed");
break;
case detail::CcuArithmeticOperatorType::SUBTRACTION:
CCU_THROW_IF_FAILED(
CcuVariableSubVarToVar(this->handle, op.lhs.handle, op.rhs.handle),
"Variable::operator=(Var-Var): CcuVariableSubVarToVar failed");
break;
case detail::CcuArithmeticOperatorType::MULTIPLICATION:
CCU_THROW_IF_FAILED(
CcuVariableMulVarToVar(this->handle, op.lhs.handle, op.rhs.handle),
"Variable::operator=(Var*Var): CcuVariableMulVarToVar failed");
break;
default:
throw detail::CcuException(
CcuResult::CCU_E_PARA, "Variable::operator=: invalid arithmetic operator type");
}
}
void operator=(detail::CcuArithmeticOperator<Variable, uint16_t> op) const
{
switch (op.type) {
case detail::CcuArithmeticOperatorType::ADDITION:
CCU_THROW_IF_FAILED(
CcuVariableAddImmToVar(this->handle, op.lhs.handle, op.rhs),
"Variable::operator=(Var+Imm): CcuVariableAddImmToVar failed");
break;
case detail::CcuArithmeticOperatorType::SUBTRACTION:
CCU_THROW_IF_FAILED(
CcuVariableSubImmToVar(this->handle, op.lhs.handle, op.rhs),
"Variable::operator=(Var-Imm): CcuVariableSubImmToVar failed");
break;
case detail::CcuArithmeticOperatorType::MULTIPLICATION:
CCU_THROW_IF_FAILED(
CcuVariableMulImmToVar(this->handle, op.lhs.handle, op.rhs),
"Variable::operator=(Var*Imm): CcuVariableMulImmToVar failed");
break;
default:
throw detail::CcuException(
CcuResult::CCU_E_PARA, "Variable::operator=: invalid arithmetic operator type");
}
}
void operator+=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableAddVarToVar(this->handle, this->handle, other.handle),
"Variable::operator+=(Variable): CcuVariableAddVarToVar failed");
}
void operator-=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableSubVarToVar(this->handle, this->handle, other.handle),
"Variable::operator-=(Variable): CcuVariableSubVarToVar failed");
}
void operator*=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableMulVarToVar(this->handle, this->handle, other.handle),
"Variable::operator*=(Variable): CcuVariableMulVarToVar failed");
}
void operator+=(uint16_t immediate) const
{
CCU_THROW_IF_FAILED(
CcuVariableAddImmToVar(this->handle, this->handle, immediate),
"Variable::operator+=(uint16_t): CcuVariableAddImmToVar failed");
}
void operator-=(uint16_t immediate) const
{
CCU_THROW_IF_FAILED(
CcuVariableSubImmToVar(this->handle, this->handle, immediate),
"Variable::operator-=(uint16_t): CcuVariableSubImmToVar failed");
}
void operator*=(uint16_t immediate) const
{
CCU_THROW_IF_FAILED(
CcuVariableMulImmToVar(this->handle, this->handle, immediate),
"Variable::operator*=(uint16_t): CcuVariableMulImmToVar failed");
}
detail::CcuArithmeticOperator<Variable, Variable> operator+(const Variable& that) const
{
return detail::CcuArithmeticOperator<Variable, Variable>(
*this, that, detail::CcuArithmeticOperatorType::ADDITION);
}
detail::CcuArithmeticOperator<Variable, Variable> operator-(const Variable& that) const
{
return detail::CcuArithmeticOperator<Variable, Variable>(
*this, that, detail::CcuArithmeticOperatorType::SUBTRACTION);
}
detail::CcuArithmeticOperator<Variable, Variable> operator*(const Variable& that) const
{
return detail::CcuArithmeticOperator<Variable, Variable>(
*this, that, detail::CcuArithmeticOperatorType::MULTIPLICATION);
}
detail::CcuArithmeticOperator<Variable, uint16_t> operator+(uint16_t immediate) const
{
return detail::CcuArithmeticOperator<Variable, uint16_t>(
*this, immediate, detail::CcuArithmeticOperatorType::ADDITION);
}
detail::CcuArithmeticOperator<Variable, uint16_t> operator-(uint16_t immediate) const
{
return detail::CcuArithmeticOperator<Variable, uint16_t>(
*this, immediate, detail::CcuArithmeticOperatorType::SUBTRACTION);
}
detail::CcuArithmeticOperator<Variable, uint16_t> operator*(uint16_t immediate) const
{
return detail::CcuArithmeticOperator<Variable, uint16_t>(
*this, immediate, detail::CcuArithmeticOperatorType::MULTIPLICATION);
}
void operator=(detail::CcuLogicOperator<Variable, Variable> op) const
{
switch (op.type) {
case detail::CcuLogicOperatorType::AND:
CCU_THROW_IF_FAILED(
CcuVariableAndVarToVar(this->handle, op.lhs.handle, op.rhs.handle),
"Variable::operator=(Var&Var): CcuVariableAndVarToVar failed");
break;
case detail::CcuLogicOperatorType::OR:
CCU_THROW_IF_FAILED(
CcuVariableOrVarToVar(this->handle, op.lhs.handle, op.rhs.handle),
"Variable::operator=(Var|Var): CcuVariableOrVarToVar failed");
break;
case detail::CcuLogicOperatorType::XOR:
CCU_THROW_IF_FAILED(
CcuVariableXorVarToVar(this->handle, op.lhs.handle, op.rhs.handle),
"Variable::operator=(Var^Var): CcuVariableXorVarToVar failed");
break;
default:
throw detail::CcuException(
CcuResult::CCU_E_PARA, "Variable::operator=: invalid logic operator type");
}
}
void operator=(detail::CcuLogicUnaryOperator<Variable> op) const
{
switch (op.type) {
case detail::CcuLogicOperatorType::NOT:
CCU_THROW_IF_FAILED(
CcuVariableNotVar(this->handle, op.lhs.handle),
"Variable::operator=(~Var): CcuVariableNotVar failed");
break;
default:
throw detail::CcuException(
CcuResult::CCU_E_PARA, "Variable::operator=: invalid unary logic operator type");
}
}
void operator=(detail::CcuShiftOperator<Variable, Variable> op) const
{
switch (op.type) {
case detail::CcuShiftOperatorType::LEFT:
CCU_THROW_IF_FAILED(
CcuVariableShlVarToVar(this->handle, op.lhs.handle, op.rhs.handle),
"Variable::operator=(Var<<Var): CcuVariableShlVarToVar failed");
break;
case detail::CcuShiftOperatorType::RIGHT:
CCU_THROW_IF_FAILED(
CcuVariableShrVarToVar(this->handle, op.lhs.handle, op.rhs.handle),
"Variable::operator=(Var>>Var): CcuVariableShrVarToVar failed");
break;
default:
throw detail::CcuException(
CcuResult::CCU_E_PARA, "Variable::operator=: invalid shift operator type");
}
}
detail::CcuLogicOperator<Variable, Variable> operator&(const Variable& that) const
{
return detail::CcuLogicOperator<Variable, Variable>(*this, that, detail::CcuLogicOperatorType::AND);
}
detail::CcuLogicOperator<Variable, Variable> operator|(const Variable& that) const
{
return detail::CcuLogicOperator<Variable, Variable>(*this, that, detail::CcuLogicOperatorType::OR);
}
detail::CcuLogicOperator<Variable, Variable> operator^(const Variable& that) const
{
return detail::CcuLogicOperator<Variable, Variable>(*this, that, detail::CcuLogicOperatorType::XOR);
}
detail::CcuLogicUnaryOperator<Variable> operator~() const
{
return detail::CcuLogicUnaryOperator<Variable>(*this, detail::CcuLogicOperatorType::NOT);
}
void operator&=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableAndVarToVar(this->handle, this->handle, other.handle),
"Variable::operator&=(Variable): CcuVariableAndVarToVar failed");
}
void operator|=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableOrVarToVar(this->handle, this->handle, other.handle),
"Variable::operator|=(Variable): CcuVariableOrVarToVar failed");
}
void operator^=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableXorVarToVar(this->handle, this->handle, other.handle),
"Variable::operator^=(Variable): CcuVariableXorVarToVar failed");
}
detail::CcuShiftOperator<Variable, Variable> operator<<(const Variable& that) const
{
return detail::CcuShiftOperator<Variable, Variable>(*this, that, detail::CcuShiftOperatorType::LEFT);
}
detail::CcuShiftOperator<Variable, Variable> operator>>(const Variable& that) const
{
return detail::CcuShiftOperator<Variable, Variable>(*this, that, detail::CcuShiftOperatorType::RIGHT);
}
void operator<<=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableShlVarToVar(this->handle, this->handle, other.handle),
"Variable::operator<<=(Variable): CcuVariableShlVarToVar failed");
}
void operator>>=(const Variable& other) const
{
CCU_THROW_IF_FAILED(
CcuVariableShrVarToVar(this->handle, this->handle, other.handle),
"Variable::operator>>=(Variable): CcuVariableShrVarToVar failed");
}
CondExpr operator==(uint64_t immediate) { return CondExpr{this, nullptr, immediate, CCU_CONDITION_EQ, false}; }
CondExpr operator!=(uint64_t immediate) { return CondExpr{this, nullptr, immediate, CCU_CONDITION_NE, false}; }
CondExpr operator<(uint64_t immediate) { return CondExpr{this, nullptr, immediate, CCU_CONDITION_LT, false}; }
CondExpr operator<=(uint64_t immediate) { return CondExpr{this, nullptr, immediate, CCU_CONDITION_LE, false}; }
CondExpr operator>(uint64_t immediate) { return CondExpr{this, nullptr, immediate, CCU_CONDITION_GT, false}; }
CondExpr operator>=(uint64_t immediate) { return CondExpr{this, nullptr, immediate, CCU_CONDITION_GE, false}; }
CondExpr operator==(const Variable& other) { return CondExpr{this, &other, 0, CCU_CONDITION_EQ, true}; }
CondExpr operator!=(const Variable& other) { return CondExpr{this, &other, 0, CCU_CONDITION_NE, true}; }
CondExpr operator<(const Variable& other) { return CondExpr{this, &other, 0, CCU_CONDITION_LT, true}; }
CondExpr operator<=(const Variable& other) { return CondExpr{this, &other, 0, CCU_CONDITION_LE, true}; }
CondExpr operator>(const Variable& other) { return CondExpr{this, &other, 0, CCU_CONDITION_GT, true}; }
CondExpr operator>=(const Variable& other) { return CondExpr{this, &other, 0, CCU_CONDITION_GE, true}; }
CcuVariableHandle handle{0};
private:
explicit Variable(detail::NoAllocTag) {}
template <typename U>
friend class Array;
friend class LocalAddr;
friend class RemoteAddr;
template <typename T>
friend T GetResByChannel(ChannelHandle channel, uint32_t index);
};
}
}
template <>
inline void AscendC::ccu::detail::CcuArithmeticOperator<AscendC::ccu::Variable, AscendC::ccu::Variable>::Check() const
{}
template <>
inline void AscendC::ccu::detail::CcuArithmeticOperator<AscendC::ccu::Variable, uint16_t>::Check() const
{}
template <>
inline void AscendC::ccu::detail::CcuLogicOperator<AscendC::ccu::Variable, AscendC::ccu::Variable>::Check() const
{}
template <>
inline void AscendC::ccu::detail::CcuLogicUnaryOperator<AscendC::ccu::Variable>::Check() const
{}
template <>
inline void AscendC::ccu::detail::CcuShiftOperator<AscendC::ccu::Variable, AscendC::ccu::Variable>::Check() const
{}
#endif