C++ Code Style Standards
Naming Conventions
File Naming
Source files and custom directories use snake_case (lowercase letters + underscores); tool-convention files (e.g., CMakeLists.txt, README.md, CONTRIBUTING.md) keep their standard naming. Suffix conventions are described in directory-structure.md.
Function Naming
Basic API (basic_api/): PascalCase
Add, Sub, Mul, DataCopy, SetVectorMask, PipeBarrier
C API (c_api/): snake_case, asc_ prefix
asc_add, asc_axpy, asc_axpy_sync
High-level API (adv_api/): PascalCase
Axpy, Exp, LayerNorm, GroupedMatmul
Synchronous versions are named by API style (depending on API type and actual need): C API uses the _sync suffix (e.g., asc_add_sync). Not all APIs have synchronous variants.
asc_add_sync, WarpReduceAddSync
Macro Naming
All uppercase letters + underscores.
| Type | Prefix | Example |
|---|---|---|
| Include guard | ASCENDC_ |
ASCENDC_KERNEL_COMMON_H |
| Internal sentinel | __ASCENDC_INCLUDE_INTERNAL_HEADERS__ |
Used only within the guard system |
| General-purpose macro | ASCENDC_ |
ASCENDC_ASSERT, ASCENDC_CHECK_VALUE_RANGE |
| Logging macro | KERNEL_LOG_ |
KERNEL_LOG_KERNEL_ERROR |
| Constant/enum macro | All uppercase | DT_FLOAT, QUE_MAX_DEPTH, FORMAT_NCHW |
Rules:
- Custom
__double-underscore prefixes are prohibited (reserved by the C++ standard) __ASCENDC_INCLUDE_INTERNAL_HEADERS__and__UNDEF_*are the only exceptions
Type/Struct Naming
PascalCase:
LocalTensor, GlobalTensor, TPipe, TQue, FixpipeConfig, DivConfig
Variable Naming
camelCase:
dstTensor, srcTensor, calCount, stackSize, sharedTmpBuffer, repeatTime
Global configuration constants use a lowercase k prefix or all uppercase:
kDefaultNdDmaConfig, DEFAULT_BINARY_CONFIG, QUE_MAX_DEPTH
Template Parameter Naming
Single uppercase letter or CamelCase:
T, U, isReuseSource
Header Guard Standards
Public Header Files (Three-Layer Guard System)
Basic API and high-level API public headers that use the internal header sentinel employ three-layer protection:
// Layer 1: Internal header sentinel (prevents recursive include)
#if !defined(__ASCENDC_INCLUDE_INTERNAL_HEADERS__)
#define __ASCENDC_INCLUDE_INTERNAL_HEADERS__
#define __UNDEF_ASCENDC_INCLUDE_INTERNAL_HEADERS_<FILENAME_UPPER>__
#endif
// Layer 2: Traditional include guard
#ifndef ASCENDC_<MODULE>_H
#define ASCENDC_<MODULE>_H
// ... file content ...
#endif // ASCENDC_<MODULE>_H
// Layer 3: Sentinel cleanup
#if defined(__UNDEF_ASCENDC_INCLUDE_INTERNAL_HEADERS_<FILENAME_UPPER>__)
#undef __ASCENDC_INCLUDE_INTERNAL_HEADERS__
#undef __UNDEF_ASCENDC_INCLUDE_INTERNAL_HEADERS_<FILENAME_UPPER>__
#endif
Guard macro naming formula:
File name: kernel_common.h
→ Layer 2 guard: ASCENDC_KERNEL_COMMON_H
→ Layer 1 undef: __UNDEF_ASCENDC_INCLUDE_INTERNAL_HEADERS_KERNEL_COMMON_H__
File name: kernel_operator_vec_binary_intf.h
→ Layer 2 guard: ASCENDC_MODULE_OPERATOR_VEC_BINARY_INTERFACE_H
→ Layer 1 undef: __UNDEF_ASCENDC_INCLUDE_INTERNAL_HEADERS_KERNEL_OPERATOR_VEC_BINARY_INTF_H__
Naming rule: ASCENDC_ + module path (slashes converted to underscores, all uppercase) + _H
Note: Some high-level API header files (
adv_api/) use theLIB_orADV_API_prefix (e.g.,LIB_MATH_SIN_H,ADV_API_CONV_COMMON_CONV_COMMON_H) as a legacy convention. New code should prefer theASCENDC_prefix.Note: Some basic API header files use
MODULE/INTERFACEinstead ofKERNEL/INTFin the Layer 2 guard (e.g.,kernel_operator_vec_binary_intf.hhas guardASCENDC_MODULE_OPERATOR_VEC_BINARY_INTERFACE_H), while the Layer 1 undef usesKERNEL/INTF. This is a legacy naming convention; new code should use macro names derived from the filename.
Implementation Header Files (Additional #pragma message Warning)
When the implementation contained in impl/ is included at the bottom of a public header file, the implementation header file itself should add:
#if !defined(__ASCENDC_INCLUDE_INTERNAL_HEADERS__)
#pragma message("impl/basic_api/kernel_operator_vec_binary_intf_impl.h "
"is an internal header file and must not be used directly. "
"Functions or variables defined in this file may be removed in the future. "
"Please use \"#include \\\"basic_api/kernel_operator_vec_binary_intf.h\\\"\" "
"and use public functions or variables defined in interface headers files.")
#define __ASCENDC_INCLUDE_INTERNAL_HEADERS__
#define __UNDEF_ASCENDC_INCLUDE_INTERNAL_HEADERS_KERNEL_OPERATOR_VEC_BINARY_INTF_IMPL_H__
#endif
C API Header Files
C API uses a separate sentinel namespace:
#if !defined(ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS)
#define ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
#define UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC_C_API_H
#endif
#pragma once Prohibited
This project does not use #pragma once in principle; public header files for basic API, high-level API, and C API use the #ifndef / #define / #endif style.
Include Standards
Quotes vs Angle Brackets
| Symbol | Purpose | Example |
|---|---|---|
"" |
Internal project header files | #include "kernel_tensor.h" |
<> |
Standard library header files (recommended inside the ASCENDC_CPU_DEBUG guard) |
#include <cstdint> |
Four Include Path Modes
| Mode | Example | Applicable Scenario |
|---|---|---|
| Bare filename | #include "kernel_tensor.h" |
Headers in the same directory or dependencies |
| Subdirectory path | #include "reg_compute/kernel_reg_compute_utils.h" |
Different subdirectory within the same module |
include/ prefix absolute path |
#include "include/adv_api/kernel_api.h" |
Cross-module references |
../../impl/ relative backtrack |
#include "../../impl/basic_api/kernel_operator_vec_binary_intf_impl.h" |
Interface header referencing implementation header |
Include Order
Organize includes in the following order, with a blank line separating each group:
-
Core Project Dependencies
#include "kernel_macros.h" #include "kernel_tensor.h" -
Same-Module Struct/Type Headers
#include "kernel_struct_binary.h" #include "kernel_struct_unary.h" -
Architecture-Conditional Includes
#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510 || __NPU_ARCH__ == 5102) #include "reg_compute/kernel_reg_compute_utils.h" #endif -
CPU Debug Conditional Includes (Standard Library)
#if defined(ASCENDC_CPU_DEBUG) && ASCENDC_CPU_DEBUG == 1 #include <cstdint> #include "stub_def.h" #endif -
Impl Header References (placed at the bottom, before the
#endifof the Layer 2 guard)#include "../../impl/basic_api/kernel_operator_vec_binary_intf_impl.h" #endif // ASCENDC_<MODULE>_H
Public Entry Header Files
Unified entry files for high-level APIs (e.g., kernel_api.h) include sub-header files directly; __NPU_ARCH__ architecture guards are managed internally by each sub-header file:
#include "math/axpy.h"
Namespace Standards
Main Namespace
All public C++ APIs reside under namespace AscendC { }; C API asc_* interfaces are in the global namespace.
namespace AscendC {
__aicore__ inline void Add(...);
} // namespace AscendC
Sub-Namespaces
| Sub-Namespace | Purpose |
|---|---|
AscendC::Std |
Standard library compatibility layer |
AscendC::Simt |
SIMT programming model |
AscendC::Te |
Tensor Engine |
AscendC::Reg |
Register Compute |
Namespace Closing Comments
A comment is recommended after the closing brace:
} // namespace AscendC::Std
} // namespace AscendC
using namespace Prohibited
using namespace is not allowed in header files.
#pragma begin_pipe / #pragma end_pipe
Pipeline function blocks are wrapped with the following pragmas:
#pragma begin_pipe(V)
namespace AscendC {
// vector pipeline functions...
} // namespace AscendC
#pragma end_pipe
Macro Standards
Function-like Macros
Wrap multi-statement macros with do { ... } while (0):
#define ASCENDC_ASSERT(cond, behavior) \
do { \
if (!(cond)) { \
behavior; \
AscendC::KernelRaise::GetInstance().Raise(SIGABRT); \
} \
} while (0)
Logging Macros
#define KERNEL_LOG(level, format, ...) KERNEL_LOG_##level(format, ##__VA_ARGS__)
Log levels: KERNEL_DEBUG, KERNEL_INFO, KERNEL_WARN, KERNEL_ERROR
Assertion and Validation Macros
| Macro | Purpose |
|---|---|
ASCENDC_ASSERT(cond, behavior) |
Executes behavior and aborts on assertion failure (only effective in CPU Debug / Host builds; expands to empty on device) |
ASCENDC_ASSERT_WARNING(cond, behavior) |
Executes behavior only on assertion failure, without abort |
ASCENDC_HOST_ASSERT(cond, ret, format, ...) |
Tiling-side (host-side) assertion, executes ret and outputs diagnostic message on failure |
ASCENDC_CHECK_VALUE_RANGE(v, lo, hi, name, msg) |
Parameter value range validation |
ASCENDC_CHECK_TENSOR_PTR_ALIGN(ptr, pos, align, name, msg) |
Address alignment validation |
ASCENDC_REPORT_NOT_SUPPORT(cond, msg) |
Unsupported condition report |
ASCENDC_REPORT_OVERFLOW_MEM(cond) |
Memory overflow report |
Architecture Conditional Macros
#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510 || __NPU_ARCH__ == 5102)
// architecture-specific code
#endif
#if defined(ASCENDC_CPU_DEBUG) && ASCENDC_CPU_DEBUG == 1
// CPU debug code
#endif
#if (defined(UT_TEST) || defined(ST_TEST))
// test code
#endif
Macro Naming Prefix Conventions
ASCENDC_: unified prefix for all functional macrosKERNEL_LOG_: prefix for logging macros__ASCENDC_INCLUDE_INTERNAL_HEADERS__and the companion__UNDEF_*cleanup macros: guard system uses the__prefix
constexpr and Compile-Time Programming
Global Configuration Constants
constexpr FixpipeConfig CFG_NZ_FIX = {CO2Layout::NZ, false, true};
constexpr FixpipeConfig CFG_NZ = {CO2Layout::NZ, false};
constexpr DivConfig DEFAULT_DIV_CONFIG = {DivAlgo::INTRINSIC};
constexpr BinaryConfig DEFAULT_BINARY_CONFIG = {1};
constexpr + __aicore__ on Member Functions
constexpr appears before __aicore__ (the recommended unified style):
constexpr __aicore__ static inline T Max()
constexpr __aicore__ static inline T Min()
constexpr __aicore__ inline int16_t GetDataBlockSizeInBytes()
Note: The
__aicore__ constexprstyle still predominates in the current codebase. New code should consistently placeconstexprfirst, as the migration target for new code.
if constexpr Compile-Time Branching
if constexpr (sizeof(U) == sizeof(float)) {
Axpy<T, U>(dstTensor, srcTensor, scalarValue, calCount);
} else {
AxpySub<T, U, isReuseSource>(dstTensor, srcTensor, scalarValue, sharedTmpBuffer, calCount);
}
if constexpr (AscendC::Std::is_same<T, uint8_t>::value) {
// ...
} else if constexpr (AscendC::Std::is_same<T, float>::value) {
// ...
}
static_assert Type Constraints
static_assert(SupportType<T, uint8_t, int8_t, uint16_t, int16_t, half, float>(),
"current data type is not supported on current device!");
static constexpr Class Members
static constexpr TQueConfig config = GetTQueConfig(mask);
static constexpr TPosition srcPosition = src;
static constexpr Hardware srcHardType = GetPhyType(src);
Error Handling Standards
ASCENDC_ASSERT
Perform parameter validation at the beginning of functions:
__aicore__ inline void Add(const LocalTensor<T>& dst, const LocalTensor<T>& src0,
const LocalTensor<T>& src1, ...)
{
ASCENDC_ASSERT((dst.GetSize() == src0.GetSize()), {
KERNEL_LOG(KERNEL_ERROR, "Tensor size mismatch: dst=%u, src0=%u",
dst.GetSize(), src0.GetSize());
});
// ...
}
CHECK_FUNC_HIGHLEVEL_API
In high-level API implementation functions or interface functions, call it on the first line of the function body:
template <typename T, typename U, bool isReuseSource>
__aicore__ inline void AxpyImpl(...)
{
CHECK_FUNC_HIGHLEVEL_API(
Axpy, (T, U, isReuseSource), (dstTensor, srcTensor, scalarValue, sharedTmpBuffer, calCount));
// ...
}
KERNEL_LOG Log Level Selection
| Level | Usage Scenario |
|---|---|
KERNEL_DEBUG |
Development debug information |
KERNEL_INFO |
General runtime information |
KERNEL_WARN |
Potential issue warning |
KERNEL_ERROR |
Error condition |
#pragma message Deprecation Warnings
Warning prohibiting direct inclusion of impl headers:
#pragma message("impl/xxx.h is an internal header file and must not be used directly. Please use include/xxx.h.")
Formatting
clang-format Configuration
The .clang-format file in the project root directory configures a unified code style. Key configuration items:
| Configuration Item | Value | Description |
|---|---|---|
| BasedOnStyle | Based on Google C++ Style | |
| ColumnLimit | 120 | Maximum 120 characters per line |
| IndentWidth | 4 | 4-space indentation |
| UseTab | Never | Do not use Tab |
| PointerAlignment | Left | Pointer symbol left-aligned |
| BreakBeforeBraces | Custom | Custom brace wrapping (see BraceWrapping below) |
| BraceWrapping.AfterFunction | true | Function braces wrapped |
| BraceWrapping.AfterControlStatement | false | Control-flow braces not wrapped |
| SortIncludes | false | Do not auto-sort includes |
| AccessModifierOffset | -4 | Access modifier indentation |
| AlwaysBreakTemplateDeclarations | true | Break between template declaration and subsequent declaration |
Automatic Formatting
The project automatically formats C/C++/.asc source files at commit time via a pre-commit hook (the clang-format hook in .pre-commit-config.yaml). Refer to the actual repository file for the specific configuration; developers do not need to maintain it manually.
Enabling steps:
- Install pre-commit:
pip install pre-commit - Run
pre-commit installin the repository root to install the git hook - Afterwards, each
git commitwill automatically trigger clang-format; files that do not conform to the style will be fixed in place and the commit blocked. Re-rungit addand commit again.
You can also skip the hook and manually format a single file:
clang-format -i --style=file <file>
Code Comment Standards
Comment Style Overview
The project uses three comment styles for different API types:
| Style | Prefix Symbol | Applicable Scenario | Example Location |
|---|---|---|---|
\brief / \param / \note |
Backslash \ |
High-level API public header files | include/adv_api/math/sin.h |
@ingroup / @brief |
@ symbol |
Basic API public header files | include/basic_api/kernel_operator_vec_binary_intf.h |
ingroup / brief |
No prefix | impl internal header files | impl/basic_api/kernel_operator_common_intf_impl.h |
File Header Comments
Every public header file must begin with a \file block:
/*!
* \file kernel_common.h
* \brief
*/
- Fill in the filename after
\file \briefmay be left empty (basic API) or contain a one-line functional description (high-level API)
High-level APIs may include formula descriptions:
/*!
* \file sin.h
* \brief Defines a series of interface used to do elementwise math sin calculation.
* Formula: sin(x) = (-1)^k*sin(x0), sin(x) = xP(x)
*/
Function/Class Comments
High-level API style (\brief / \param / \note)
/*!
* \ingroup Sin
* \brief compute Sin elementwisely
*
* \tparam T: half/float
* \tparam isReuseSource: whether allows API to modify source data during calculation
*
* \param [out] dstTensor: output LocalTensor
* \param [in] srcTensor: input LocalTensor
* \param [in] sharedTmpBuffer: extra temporary shared space for intermediate
* \param [in] calCount: number of elements to be calculated
*
* \note src/dst Tensor must be 32B aligned
* \note The calculation may allocate temporary space through sharedTmpBuffer
*/
Elements:
\ingroup+ functional group name (first line)\brief+ brief functional description\tparam+ template parameter description (one line per parameter)\param [out]/\param [in]+ parameter description\note+ constraints and notes
Basic API style (@ingroup / @brief + separator line)
/* **************************************************************************************************
* Add *
* ************************************************************************************************* */
/*
* @ingroup Add Level 0
* @brief dst = src0 + src1
*
* @param [out] dst output LocalTensor
* @param [in] src0 input LocalTensor
* @param [in] src1 input LocalTensor
* @param [in] mask[]/mask mask array/count
* @param [in] repeatTime repeat times
* @param [in] repeatParams.dstBlkStride dst block stride
* @param [in] repeatParams.src0BlkStride src0 block stride
* @param [in] repeatParams.src1BlkStride src1 block stride
* @param [in] repeatParams.dstRepStride dst repeat stride
* @param [in] repeatParams.src0RepStride src0 repeat stride
* @param [in] repeatParams.src1RepStride src1 repeat stride
*/
Elements:
*separator line, with the function name in the middle@ingroup+ group + Level (first line)@brief+ formula@param [out]/@param [in]+ parameter description- Nested parameters separated by
.(e.g.,repeatParams.dstBlkStride)
C API style
// ==========asc_add(half/float)==========
// Continuous mode
__aicore__ inline void asc_add(__ubuf__ half* dst, __ubuf__ half* src0, __ubuf__ half* src1, uint32_t count);
// Configuration mode
__aicore__ inline void asc_add(__ubuf__ half* dst, ...);
Parameter Annotation Conventions
Direction Annotations
| Annotation | Meaning |
|---|---|
\param [out] |
Output parameter |
\param [in] |
Input parameter |
\param [in/out] |
Input/output parameter |
Template Parameters
\tparam T: target operand data type, supports half/float
\tparam U: source operand data type, supports half/float
\tparam isReuseSource: whether allows API to modify source data during calculation
Parameter Description Format
- Parameter names match the actual formal parameter names
- Descriptions should be concise, explaining type constraints and value ranges
- Use English or Chinese consistently within a single file
Special Annotations
\note Constraint Notes
/*!
* \note src/dst Tensor must be 32B aligned.
* \note CalCount must be less than or equal to the element count of src/dst Tensor.
* \note support data type: half and float
*/
Common uses include alignment requirements, data range limits, supported data types, and performance notes.
Deprecation Annotations
Method one [[deprecated]] attribute:
[[deprecated("NOTICE: SetDumpWorkSpacePtr has been deprecated and will be removed "
"in the next version. Please do not use it!")]]
__aicore__ inline __gm__ uint8_t* SetDumpWorkSpacePtr(__gm__ uint8_t* workspace)
Method two line comment:
// NOTICE: InitOutput has been deprecated and will be removed in the next version.
// Please use Fill instead!
Function Group Separator (Basic API)
/* **************************************************************************************************
* Add *
* ************************************************************************************************* */
- 100 columns wide, with the function name in the middle
- Used to delineate functional blocks in large interface files
Chinese-English Language Conventions
| Content Type | Language | Example |
|---|---|---|
Public API comments (\brief, \param) |
English | \brief compute Sin elementwisely |
| impl internal comments | Chinese | // 计算循环次数 |
| Log messages | English | "Tensor size mismatch" |
| Assertion messages | English | "current data type is not supported" |
| File/function/variable names | English | kernel_operator_vec_binary_intf.h |
| Documentation descriptions (.md) | Match the document locale | docs/zh: Chinese; docs/en and *_en.md: English |