This section describes the hardware architecture and functions of the __NPU_ARCH__ version 220x. 220 indicates the IP core ID, and x indicates the configuration version of the same IP core. The corresponding product models are as follows:
As shown in the following figure, the AI Core in this architecture consists of two independent cores: AIC and AIV, which are used for cube computation and vector computation, respectively. Each core has its own Scalar Unit and can independently load its own code segments. Data is transferred between the AIV and AIC through the global memory.

Separated deployment of the Cube Unit and Vector Unit
In this architecture, the Cube Unit and Vector Unit are deployed on the AIC and AIV cores, respectively. Each core has its own Scalar Unit and can independently load its own code segments.
Vector Unit
Cube Unit
Obtaining the memory size of a storage unit
You can query the memory size of each storage unit by calling the platform information acquisition API.
Minimum access granularities (alignment requirements) of each storage unit
|
Core |
Storage Unit |
Alignment Requirement |
|---|---|---|
|
AIV |
Unified Buffer |
32-byte aligned. |
|
AIC |
L1 Buffer |
32-byte aligned. |
|
L0A Buffer |
512-byte aligned. |
|
|
L0B Buffer |
512-byte aligned. |
|
|
L0C Buffer |
64-byte aligned. |
|
|
BiasTable Buffer |
64-byte aligned. |
|
|
Fixpipe Buffer |
64-byte aligned. |
Recommended data layout formats for each storage unit
These formats are optimized for compute-intensive tasks such as cube multiplication, significantly improving the compute efficiency.
Resolving access conflicts of storage units to improve read/write performance
When multiple operations attempt to access the same bank or bank group of the Unified Buffer at the same time, bank conflicts may occur, including the read-write conflict, write-write conflict, and read-read conflict. As a result, the accesses queue and the performance deteriorates. The read/write performance can be improved by optimizing bank allocation. For details, see Avoiding Bank Conflicts in the Unified Buffer.
Alignment requirements during movement
The size of the data to be moved is subject to certain requirements because the moved data is used for computation. The size of the data moved to the Unified Buffer must be aligned based on the data block size. The data moved to other storage units must be aligned based on the fractal requirements. For example, when data is moved from the L1 Buffer to the L0A Buffer, the data format needs to be converted from NZ to ZZ. The size of the data to be moved must be aligned based on the fractal size. If the remaining size of the L1 Buffer is less than one fractal, an exception will occur during hardware execution.
Inter-device data movement (HCCS physical link)
In the development of inter-device communication operators, the DataCopy APIs support inter-device data movement. On the
FixPipe hardware acceleration
FixPipe is an acceleration module that hardens typical operations on the NPU. It is located inside the AIC and works with the Cube Unit to complete on-the-fly computation. Its main functions are as follows:

In the preceding figure, Channel Merge supports the S8, U8, S4, and U4 data types, while Channel Split supports the FP32 data type.
For the target data type converted to S8 or U8, the fractal cube is converted from 16×16 to 16×32 through hardware. If the number of output channels (N) is an even multiple of 16, every two adjacent 16×16 fractal cubes in the N direction are merged into one 16×32 fractal cube. If the value of N is an odd multiple of 16, channels [1, N–16] are merged; the final 16 channels are not merged.
As shown below, the target data type is S8, M is 32, and N is 48. First, the 16×16 fractal cubes in the first two columns are merged into one 16×32 cube, and then the remaining 16×16 fractal cubes are directly moved to the L1 Buffer.

For the target data type converted to S4 or U4, the fractal cube is converted from 16×16 to 16×32 through hardware. If the number of output channels (N) is a multiple of 64, every four adjacent 16×16 fractal cubes in the N direction are merged into a single 16×64 fractal cube.
For example, the target data type is S4, M is 32, and N is 64. First, the 16×16 fractal cubes in the first row are merged into a 16×64 cube, and then the 16×16 fractal cubes in the second row are also merged.
In this case, N must be a multiple of 64.

For the target type FP32, the fractal cube can be converted from 16×16 to 16×8 through hardware. If Channel Split is enabled, each 16×16 fractal cube is split into two 16×8 fractal cubes.
As shown in the following figure, the target data type is FP32, M is 64, and N is 32. The cube is split into sixteen 16×8 fractals.

The execution units (such as the MTE2 and Vector Unit) within the AI Core operate asynchronously and in parallel. As a result, data dependencies may arise when reading data from or writing data to the local memory (such as the Unified Buffer). To ensure data consistency and computational accuracy, synchronization control is required to coordinate the timing of operations.
For example, in the process where the MTE2 moves data from the GM to the UB for Abs computation by the Vector Unit and then moves the data back to the GM, the following synchronization conditions must be met:
The synchronization control process is shown in the following figure.

In the preceding figure, ID1, ID2, ID3, ID4, ID5, and ID6 represent event IDs. Each event ID corresponds to the movement status of a piece of stored data, ensuring the correctness and consistency of data operations.
For example, SetFlag<HardEvent::S_MTE3>(1) and SetFlag<HardEvent::MTE3_MTE1>(1) set different event IDs because their template parameters are different. They set the same event ID only when their template parameters and event IDs are the same.
When different cores operate the same global memory, data dependency issues such as read-after-write, write-after-read, and write-after-write may occur. To avoid such issues, inter-core synchronization control is required.
The inter-core synchronization control has the following modes, as shown in the following figure.

For example, after the AIC core moves the L0C computation result to the GM, the AIV core needs to move the GM data to the UB. In this case, you can use the CrossCoreSetFlag and CrossCoreWaitFlag commands to ensure that the data is successfully moved from the L0C to the GM and then from the GM to the UB. The following figure shows the process.

The CrossCoreSetFlag and CrossCoreWaitFlag APIs are used together. The flag ID (flagId, that is, ID1 in the above figure) for inter-core synchronization needs to be passed in. Each ID corresponds to a counter whose initial value is 0. After CrossCoreSetFlag is executed, the value of the counter corresponding to the ID is incremented by 1. If the counter value is 0, CrossCoreWaitFlag is not executed. If the counter value is greater than 0, the counter decreases by 1 and subsequent instructions start to be executed. The value of flagId ranges from 0 to 10.
Note the following:
CrossCoreSetFlag and CrossCoreWaitFlag must be used in pairs. Otherwise, the operator may time out.
The template parameters and flagId of CrossCoreSetFlag must be the same as those of CrossCoreWaitFlag. Otherwise, they are considered as different flag IDs. For example, CrossCoreSetFlag<0x0, PIPE_MTE3>(0x8) and CrossCoreSetFlag<0x2, PIPE_FIX>(0x8) set different flag IDs.
Setting the same flag ID consecutively is not allowed, preventing the counter status from being disordered.
This API is used to control inter-core synchronization in the internal implementation of the Matmul high-level APIs. Therefore, you are advised not to use this API and the Matmul high-level APIs at the same time. Otherwise, flag IDs may conflict.
The counter of the same flag ID can be set for a maximum of 15 times.
The instruction pipeline type does not need to be explicitly set for CrossCoreWaitFlag. PIPE_S is used by default.