已合并
FEAT: A5 CTRL寄存器接口补充 #5135
yiming创建于 16 天前
FEAT: A5 CTRL寄存器接口补充 #5135
已合并
yiming创建于 16 天前
16 个文件变更+885-0
@@ -23,6 +23,10 @@
23#include "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_dcci_impl.h"23#include "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_dcci_impl.h"
24#include "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_get_icache_preload_status_impl.h"24#include "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_get_icache_preload_status_impl.h"
25#include "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_dci_impl.h"25#include "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_dci_impl.h"
26+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
27+#include "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_set_scalar_cache_mode_impl.h"
28+#include "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_get_scalar_cache_mode_impl.h"
29+#endif
26 30 
27// ==========asc_icache_preload==========31// ==========asc_icache_preload==========
28__aicore__ inline void asc_icache_preload(const void* addr, int64_t prefetch_len)32__aicore__ inline void asc_icache_preload(const void* addr, int64_t prefetch_len)
@@ -53,6 +57,30 @@ __aicore__ inline int64_t asc_get_icache_preload_status() { return asc_get_icach
53//==============asc_dci===============57//==============asc_dci===============
54__aicore__ inline void asc_dci() { asc_dci_impl(); }58__aicore__ inline void asc_dci() { asc_dci_impl(); }
55 59 
60+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
61+//==============asc_set_scalar_cache_mode===============
62+__aicore__ inline void asc_set_scalar_cache_mode(asc_load_l2_cache_mode l2_cache_mode)
63+{
毛浩地16 天前

这里调用impl函数的部分用版本宏进行隔离

likedislike
64+ asc_set_scalar_cache_mode_impl(l2_cache_mode);
65+}
66+ 
67+__aicore__ inline void asc_set_scalar_cache_mode(asc_store_l2_cache_mode l2_cache_mode)
68+{
69+ asc_set_scalar_cache_mode_impl(l2_cache_mode);
70+}
71+ 
72+//==============asc_get_scalar_load/store_cache_mode===============
73+__aicore__ inline asc_load_l2_cache_mode asc_get_scalar_load_cache_mode()
74+{
75+ return asc_get_scalar_load_cache_mode_impl();
76+}
77+ 
78+__aicore__ inline asc_store_l2_cache_mode asc_get_scalar_store_cache_mode()
79+{
80+ return asc_get_scalar_store_cache_mode_impl();
81+}
82+#endif
83+ 
56#endif84#endif
57 85 
58#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)86#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)
@@ -0,0 +1,48 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software; you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/* !
12+ * \file asc_get_scalar_cache_mode_impl.h
13+ * \brief
14+ */
15+ 
16+#if !defined(ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS)
17+#warning \
18+ "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_get_scalar_cache_mode_impl.h is an internal header file and must not be used directly. Functions or variables defined in this file maybe removed in the future. Please use "#include "c_api/asc_simd.h"" and use public functions or variables defined in interface headers files."
19+#define ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
20+#define UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
21+#endif
22+ 
23+#ifndef IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_CACHE_CTRL_IMPL_ASC_GET_SCALAR_CACHE_MODE_IMPL_H
24+#define IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_CACHE_CTRL_IMPL_ASC_GET_SCALAR_CACHE_MODE_IMPL_H
25+ 
26+#include "impl/c_api/instr_impl/npu_arch_3510/utils_impl.h"
27+ 
28+// Enum underlying values match HW encodings; cast is used as-is (illegal codes are not normalized).
29+__aicore__ inline asc_load_l2_cache_mode asc_get_scalar_load_cache_mode_impl()
30+{
31+ constexpr uint8_t start_bit = 16; // READ mode: CTRL[19:16]
32+ uint8_t cache_bits = static_cast<uint8_t>((get_ctrl() >> start_bit) & 0xF);
33+ return static_cast<asc_load_l2_cache_mode>(cache_bits);
34+}
35+ 
36+__aicore__ inline asc_store_l2_cache_mode asc_get_scalar_store_cache_mode_impl()
37+{
38+ constexpr uint8_t start_bit = 20; // WRITE mode: CTRL[23:20]
39+ uint8_t cache_bits = static_cast<uint8_t>((get_ctrl() >> start_bit) & 0xF);
40+ return static_cast<asc_store_l2_cache_mode>(cache_bits);
41+}
42+ 
43+#endif
44+ 
45+#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)
46+#undef ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
47+#undef UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
48+#endif
@@ -0,0 +1,59 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software; you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/* !
12+ * \file asc_set_scalar_cache_mode_impl.h
13+ * \brief
14+ */
15+ 
16+#if !defined(ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS)
17+#warning \
18+ "impl/c_api/instr_impl/npu_arch_3510/cache_ctrl_impl/asc_set_scalar_cache_mode_impl.h is an internal header file and must not be used directly. Functions or variables defined in this file maybe removed in the future. Please use "#include "c_api/asc_simd.h"" and use public functions or variables defined in interface headers files."
19+#define ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
20+#define UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
21+#endif
22+ 
23+#ifndef IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_CACHE_CTRL_IMPL_ASC_SET_SCALAR_CACHE_MODE_IMPL_H
24+#define IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_CACHE_CTRL_IMPL_ASC_SET_SCALAR_CACHE_MODE_IMPL_H
25+ 
26+#include "impl/c_api/instr_impl/npu_arch_3510/utils_impl.h"
27+ 
28+union ctrl_scalar_cache_bits {
29+ uint64_t value;
30+ struct {
31+ uint64_t reserved0 : 16;
32+ uint64_t scalar_load_cache_mode : 4;
33+ uint64_t scalar_store_cache_mode : 4;
34+ uint64_t reserved1 : 40;
35+ };
36+};
37+ 
38+__aicore__ inline void asc_set_scalar_cache_mode_impl(asc_load_l2_cache_mode l2_cache_mode)
39+{
40+ ctrl_scalar_cache_bits ctrl;
41+ ctrl.value = static_cast<uint64_t>(get_ctrl());
42+ ctrl.scalar_load_cache_mode = static_cast<uint8_t>(l2_cache_mode);
43+ set_ctrl(static_cast<int64_t>(ctrl.value));
44+}
45+ 
46+__aicore__ inline void asc_set_scalar_cache_mode_impl(asc_store_l2_cache_mode l2_cache_mode)
47+{
48+ ctrl_scalar_cache_bits ctrl;
49+ ctrl.value = static_cast<uint64_t>(get_ctrl());
50+ ctrl.scalar_store_cache_mode = static_cast<uint8_t>(l2_cache_mode);
51+ set_ctrl(static_cast<int64_t>(ctrl.value));
52+}
53+ 
54+#endif
55+ 
56+#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)
57+#undef ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
58+#undef UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
59+#endif
@@ -42,6 +42,12 @@
42#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_sub_block_id_impl.h"42#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_sub_block_id_impl.h"
43#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_sub_block_num_impl.h"43#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_sub_block_num_impl.h"
44#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_sys_virtual_base_impl.h"44#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_sys_virtual_base_impl.h"
45+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
46+#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_set_saturation_flag_impl.h"
47+#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_saturation_flag_impl.h"
48+#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_set_saturation_strategy_impl.h"
49+#include "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_saturation_strategy_impl.h"
50+#endif
45 51 
46[[deprecated("NOTICE: asc_get_ar_spr is deprecated. "52[[deprecated("NOTICE: asc_get_ar_spr is deprecated. "
47 "Please use asc_get_squeeze_status instead.")]] __aicore__ inline int64_t53 "Please use asc_get_squeeze_status instead.")]] __aicore__ inline int64_t
@@ -130,6 +136,25 @@ __aicore__ inline int64_t asc_get_status() { return asc_get_status_impl(); }
130 136 
131__aicore__ inline int64_t asc_get_sys_virtual_base() { return asc_get_sys_virtual_base_impl(); }137__aicore__ inline int64_t asc_get_sys_virtual_base() { return asc_get_sys_virtual_base_impl(); }
132 138 
139+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
140+__aicore__ inline void asc_set_saturation_flag(asc_saturation_mode saturation_mode, bool enable_sat)
141+{
142+ asc_set_saturation_flag_impl(saturation_mode, enable_sat);
143+}
144+ 
145+__aicore__ inline bool asc_get_saturation_flag(asc_saturation_mode saturation_mode)
146+{
147+ return asc_get_saturation_flag_impl(saturation_mode);
148+}
149+ 
150+__aicore__ inline void asc_set_saturation_strategy(asc_override_strategy strategy)
151+{
152+ asc_set_saturation_strategy_impl(strategy);
153+}
154+ 
155+__aicore__ inline asc_override_strategy asc_get_saturation_strategy() { return asc_get_saturation_strategy_impl(); }
156+#endif
157+ 
133#endif158#endif
134 159 
135#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)160#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)
@@ -0,0 +1,41 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file asc_get_saturation_flag_impl.h
13+ * \brief
14+ */
15+ 
16+#if !defined(ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS)
17+#warning \
18+ "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_saturation_flag_impl.h is an internal header file and must not be used directly. Functions or variables defined in this file maybe removed in the future. Please use "#include "c_api/asc_simd.h"" and use public functions or variables defined in interface headers files."
19+#define ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
20+#define UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
21+#endif
22+ 
23+#ifndef IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_SYS_VAR_IMPL_ASC_GET_SATURATION_FLAG_IMPL_H
24+#define IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_SYS_VAR_IMPL_ASC_GET_SATURATION_FLAG_IMPL_H
25+ 
26+#include "impl/c_api/instr_impl/npu_arch_3510/utils_impl.h"
27+ 
28+__aicore__ inline bool asc_get_saturation_flag_impl(asc_saturation_mode saturation_mode)
29+{
30+ // Enum underlying values are CTRL bit indices. INT: 1=sat; FLOAT/FLOAT8/CAST: 0=sat.
31+ const uint8_t bit = static_cast<uint8_t>(saturation_mode);
32+ const bool is_bit_set = ((get_ctrl() >> bit) & 1) != 0;
33+ return (saturation_mode == asc_saturation_mode::INT) ? is_bit_set : !is_bit_set;
34+}
35+ 
36+#endif
37+ 
38+#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)
39+#undef ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
40+#undef UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
41+#endif
@@ -0,0 +1,40 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file asc_get_saturation_strategy_impl.h
13+ * \brief
14+ */
15+ 
16+#if !defined(ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS)
17+#warning \
18+ "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_get_saturation_strategy_impl.h is an internal header file and must not be used directly. Functions or variables defined in this file maybe removed in the future. Please use "#include "c_api/asc_simd.h"" and use public functions or variables defined in interface headers files."
19+#define ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
20+#define UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
21+#endif
22+ 
23+#ifndef IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_SYS_VAR_IMPL_ASC_GET_SATURATION_STRATEGY_IMPL_H
24+#define IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_SYS_VAR_IMPL_ASC_GET_SATURATION_STRATEGY_IMPL_H
25+ 
26+#include "impl/c_api/instr_impl/npu_arch_3510/utils_impl.h"
27+ 
28+__aicore__ inline asc_override_strategy asc_get_saturation_strategy_impl()
29+{
30+ // CTRL[60]: 0 => USE_API, 1 => USE_GLOBAL. Aligns with AscendC::GetSaturationStrategy.
31+ int64_t value = (get_ctrl() >> 60) & 1;
32+ return value == 0 ? asc_override_strategy::USE_API : asc_override_strategy::USE_GLOBAL;
33+}
34+ 
35+#endif
36+ 
37+#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)
38+#undef ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
39+#undef UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
40+#endif
@@ -0,0 +1,41 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file asc_set_saturation_flag_impl.h
13+ * \brief
14+ */
15+ 
16+#if !defined(ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS)
17+#warning \
18+ "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_set_saturation_flag_impl.h is an internal header file and must not be used directly. Functions or variables defined in this file maybe removed in the future. Please use "#include "c_api/asc_simd.h"" and use public functions or variables defined in interface headers files."
19+#define ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
20+#define UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
21+#endif
22+ 
23+#ifndef IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_SYS_VAR_IMPL_ASC_SET_SATURATION_FLAG_IMPL_H
24+#define IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_SYS_VAR_IMPL_ASC_SET_SATURATION_FLAG_IMPL_H
25+ 
26+#include "impl/c_api/instr_impl/npu_arch_3510/utils_impl.h"
27+ 
28+__aicore__ inline void asc_set_saturation_flag_impl(asc_saturation_mode saturation_mode, bool enable_sat)
29+{
30+ // Enum underlying values are CTRL bit indices. INT: 1=sat; FLOAT/FLOAT8/CAST: 0=sat.
31+ const int64_t bit = static_cast<int64_t>(saturation_mode);
32+ const bool is_bit_set = (saturation_mode == asc_saturation_mode::INT) ? enable_sat : !enable_sat;
33+ set_ctrl(is_bit_set ? sbitset1(get_ctrl(), bit) : sbitset0(get_ctrl(), bit));
34+}
35+ 
36+#endif
37+ 
38+#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)
39+#undef ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
40+#undef UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
41+#endif
@@ -0,0 +1,40 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file asc_set_saturation_strategy_impl.h
13+ * \brief
14+ */
15+ 
16+#if !defined(ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS)
17+#warning \
18+ "impl/c_api/instr_impl/npu_arch_3510/sys_var_impl/asc_set_saturation_strategy_impl.h is an internal header file and must not be used directly. Functions or variables defined in this file maybe removed in the future. Please use "#include "c_api/asc_simd.h"" and use public functions or variables defined in interface headers files."
19+#define ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
20+#define UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
21+#endif
22+ 
23+#ifndef IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_SYS_VAR_IMPL_ASC_SET_SATURATION_STRATEGY_IMPL_H
24+#define IMPL_C_API_INSTR_IMPL_NPU_ARCH_3510_SYS_VAR_IMPL_ASC_SET_SATURATION_STRATEGY_IMPL_H
25+ 
26+#include "impl/c_api/instr_impl/npu_arch_3510/utils_impl.h"
27+ 
28+__aicore__ inline void asc_set_saturation_strategy_impl(asc_override_strategy strategy)
29+{
30+ // CTRL[60]: 0 => USE_API, 1 => USE_GLOBAL. Aligns with AscendC::SetSaturationStrategy.
31+ int64_t ctrl_value = get_ctrl();
32+ set_ctrl(strategy == asc_override_strategy::USE_API ? sbitset0(ctrl_value, 60) : sbitset1(ctrl_value, 60));
33+}
34+ 
35+#endif
36+ 
37+#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC)
38+#undef ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS
39+#undef UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC
40+#endif
@@ -53,6 +53,14 @@ __aicore__ inline void asc_datacache_preload(__gm__ uint64_t* address, int64_t o
53 53 
54__aicore__ inline void asc_dci();54__aicore__ inline void asc_dci();
55 55 
56+__aicore__ inline void asc_set_scalar_cache_mode(asc_load_l2_cache_mode l2_cache_mode);
57+ 
58+__aicore__ inline void asc_set_scalar_cache_mode(asc_store_l2_cache_mode l2_cache_mode);
59+ 
60+__aicore__ inline asc_load_l2_cache_mode asc_get_scalar_load_cache_mode();
61+ 
62+__aicore__ inline asc_store_l2_cache_mode asc_get_scalar_store_cache_mode();
63+ 
56#endif64#endif
57 65 
58#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC_C_API_H)66#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC_C_API_H)
@@ -36,6 +36,18 @@ enum class asc_hf32_round_mode : uint8_t {
36 NEAREST_ZERO = NEAREST_AWAY // Compatible with the old name; the actual behavior is equivalent to NEAREST_AWAY.36 NEAREST_ZERO = NEAREST_AWAY // Compatible with the old name; the actual behavior is equivalent to NEAREST_AWAY.
37};37};
38 38 
39+enum class asc_saturation_mode : uint8_t {
40+ FLOAT = 48, // 浮点数计算和浮点数精度转换饱和模式
41+ FLOAT8 = 50, // 浮点数精度转换时NaN饱和模式
42+ INT = 53, // 整数计算指令饱和模式
43+ CAST = 59 // 浮点数转整数或整数转整数精度转换饱和模式
44+};
45+ 
46+enum class asc_override_strategy : uint8_t {
47+ USE_API = 0, // 饱和模式为单指令设置饱和
48+ USE_GLOBAL = 1 // 饱和模式为全局设置饱和
49+};
50+ 
39enum class asc_position_mode { EVEN = 0, ODD };51enum class asc_position_mode { EVEN = 0, ODD };
40 52 
41constexpr std::integral_constant<asc_position_mode, asc_position_mode::EVEN> ASC_POSITION_EVEN;53constexpr std::integral_constant<asc_position_mode, asc_position_mode::EVEN> ASC_POSITION_EVEN;
@@ -37,6 +37,11 @@ __aicore__ inline int64_t asc_get_squeeze_status();
37 "Please use asc_get_squeeze_status instead.")]]37 "Please use asc_get_squeeze_status instead.")]]
38__aicore__ inline int64_t asc_get_ar_spr();38__aicore__ inline int64_t asc_get_ar_spr();
39 39 
40+__aicore__ inline void asc_set_saturation_flag(asc_saturation_mode saturation_mode, bool enable_sat);
41+__aicore__ inline bool asc_get_saturation_flag(asc_saturation_mode saturation_mode);
42+__aicore__ inline void asc_set_saturation_strategy(asc_override_strategy strategy);
43+__aicore__ inline asc_override_strategy asc_get_saturation_strategy();
44+ 
40#endif45#endif
41 46 
42#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC_C_API_H)47#if defined(UNDEF_ASCENDC_C_API_INCLUDE_COMPILER_INTERNAL_HEADERS_ASCENDC_C_API_H)
@@ -19,7 +19,10 @@ static void test_host_c_api_cache_ctrl_0()
19 using ::asc_dcci_entire_ub;19 using ::asc_dcci_entire_ub;
20 using ::asc_dci;20 using ::asc_dci;
21 using ::asc_get_icache_preload_status;21 using ::asc_get_icache_preload_status;
22+ using ::asc_get_scalar_load_cache_mode;
23+ using ::asc_get_scalar_store_cache_mode;
22 using ::asc_icache_preload;24 using ::asc_icache_preload;
25+ using ::asc_set_scalar_cache_mode;
23 using ::asc_ub_dcci_single;26 using ::asc_ub_dcci_single;
24 using __asc_aicore::asc_dcci_single;27 using __asc_aicore::asc_dcci_single;
25}28}
@@ -23,6 +23,8 @@ static void test_host_c_api_sys_var_0()
23 using ::asc_get_phy_buf_addr;23 using ::asc_get_phy_buf_addr;
24 using ::asc_get_phy_stack_base;24 using ::asc_get_phy_stack_base;
25 using ::asc_get_program_counter;25 using ::asc_get_program_counter;
26+ using ::asc_get_saturation_flag;
27+ using ::asc_get_saturation_strategy;
26 using ::asc_get_smmu_tag_version;28 using ::asc_get_smmu_tag_version;
27 using ::asc_get_squeeze_status;29 using ::asc_get_squeeze_status;
28 using ::asc_get_status;30 using ::asc_get_status;
@@ -33,4 +35,6 @@ static void test_host_c_api_sys_var_0()
33 using ::asc_get_vf_len;35 using ::asc_get_vf_len;
34 using ::asc_set_ctrl;36 using ::asc_set_ctrl;
35 using ::asc_set_ffts_base_addr;37 using ::asc_set_ffts_base_addr;
38+ using ::asc_set_saturation_flag;
39+ using ::asc_set_saturation_strategy;
36}40}
@@ -0,0 +1,348 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software; you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#include <gtest/gtest.h>
12+#include <mockcpp/mockcpp.hpp>
13+#include "tests/api/c_api/stub/cce_stub.h"
14+#include "include/c_api/asc_simd.h"
15+ 
16+class TestScalarCacheModeCAPI : public testing::Test {
17+protected:
18+ void SetUp() {}
19+ void TearDown() {}
20+};
21+ 
22+namespace {
23+int64_t g_ctrlValue = 0;
24+ 
25+int64_t get_ctrl_stub() { return g_ctrlValue; }
26+ 
27+void set_ctrl_stub(uint64_t config) { g_ctrlValue = static_cast<int64_t>(config); }
28+} // namespace
29+ 
30+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_load_cache_mode_normal_first_victim)
31+{
32+ g_ctrlValue = 0;
33+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
34+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
35+ 
36+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NORMAL_FIRST_VICTIM);
37+ 
38+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 16) & 0xF);
39+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_load_l2_cache_mode::NORMAL_FIRST_VICTIM));
40+ GlobalMockObject::verify();
41+}
42+ 
43+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_load_cache_mode_normal_last_victim)
44+{
45+ g_ctrlValue = 0;
46+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
47+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
48+ 
49+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NORMAL_LAST_VICTIM);
50+ 
51+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 16) & 0xF);
52+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_load_l2_cache_mode::NORMAL_LAST_VICTIM));
53+ GlobalMockObject::verify();
54+}
55+ 
56+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_load_cache_mode_normal_persistent)
57+{
58+ g_ctrlValue = 0;
59+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
60+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
61+ 
62+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NORMAL_PERSISTENT);
63+ 
64+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 16) & 0xF);
65+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_load_l2_cache_mode::NORMAL_PERSISTENT));
66+ GlobalMockObject::verify();
67+}
68+ 
69+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_load_cache_mode_notalloc_keep)
70+{
71+ g_ctrlValue = 0;
72+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
73+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
74+ 
75+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NOTALLOC_KEEP);
76+ 
77+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 16) & 0xF);
78+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_load_l2_cache_mode::NOTALLOC_KEEP));
79+ GlobalMockObject::verify();
80+}
81+ 
82+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_load_cache_mode_notalloc_clean)
83+{
84+ g_ctrlValue = 0;
85+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
86+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
87+ 
88+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NOTALLOC_CLEAN);
89+ 
90+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 16) & 0xF);
91+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_load_l2_cache_mode::NOTALLOC_CLEAN));
92+ GlobalMockObject::verify();
93+}
94+ 
95+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_load_cache_mode_notalloc_drop)
96+{
97+ g_ctrlValue = 0;
98+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
99+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
100+ 
101+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NOTALLOC_DROP);
102+ 
103+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 16) & 0xF);
104+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_load_l2_cache_mode::NOTALLOC_DROP));
105+ GlobalMockObject::verify();
106+}
107+ 
108+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_load_cache_mode_preserve_other_bits)
109+{
110+ g_ctrlValue = static_cast<int64_t>(0xDEAD) << 32;
111+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
112+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
113+ 
114+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NORMAL_PERSISTENT);
115+ 
116+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 16) & 0xF);
117+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_load_l2_cache_mode::NORMAL_PERSISTENT));
118+ int64_t preservedBits = g_ctrlValue & (~(0xFLL << 16));
119+ EXPECT_EQ(preservedBits, static_cast<int64_t>(0xDEAD) << 32);
120+ GlobalMockObject::verify();
121+}
122+ 
123+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_store_cache_mode_normal_first_victim)
124+{
125+ g_ctrlValue = 0;
126+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
127+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
128+ 
129+ asc_set_scalar_cache_mode(asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM);
130+ 
131+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 20) & 0xF);
132+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM));
133+ GlobalMockObject::verify();
134+}
135+ 
136+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_store_cache_mode_normal_last_victim)
137+{
138+ g_ctrlValue = 0;
139+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
140+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
141+ 
142+ asc_set_scalar_cache_mode(asc_store_l2_cache_mode::NORMAL_LAST_VICTIM);
143+ 
144+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 20) & 0xF);
145+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_store_l2_cache_mode::NORMAL_LAST_VICTIM));
146+ GlobalMockObject::verify();
147+}
148+ 
149+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_store_cache_mode_normal_persistent)
150+{
151+ g_ctrlValue = 0;
152+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
153+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
154+ 
155+ asc_set_scalar_cache_mode(asc_store_l2_cache_mode::NORMAL_PERSISTENT);
156+ 
157+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 20) & 0xF);
158+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_store_l2_cache_mode::NORMAL_PERSISTENT));
159+ GlobalMockObject::verify();
160+}
161+ 
162+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_store_cache_mode_notalloc_clean)
163+{
164+ g_ctrlValue = 0;
165+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
166+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
167+ 
168+ asc_set_scalar_cache_mode(asc_store_l2_cache_mode::NOTALLOC_CLEAN);
169+ 
170+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 20) & 0xF);
171+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_store_l2_cache_mode::NOTALLOC_CLEAN));
172+ GlobalMockObject::verify();
173+}
174+ 
175+TEST_F(TestScalarCacheModeCAPI, c_api_set_scalar_store_cache_mode_preserve_other_bits)
176+{
177+ g_ctrlValue = static_cast<int64_t>(0xDEAD) << 32;
178+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
179+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
180+ 
181+ asc_set_scalar_cache_mode(asc_store_l2_cache_mode::NORMAL_PERSISTENT);
182+ 
183+ uint8_t cacheBits = static_cast<uint8_t>((g_ctrlValue >> 20) & 0xF);
184+ EXPECT_EQ(cacheBits, static_cast<uint8_t>(asc_store_l2_cache_mode::NORMAL_PERSISTENT));
185+ int64_t preservedBits = g_ctrlValue & (~(0xFLL << 20));
186+ EXPECT_EQ(preservedBits, static_cast<int64_t>(0xDEAD) << 32);
187+ GlobalMockObject::verify();
188+}
189+ 
190+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_load_cache_mode_normal_first_victim)
191+{
192+ g_ctrlValue = 0;
193+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
194+ 
195+ auto mode = asc_get_scalar_load_cache_mode();
196+ EXPECT_EQ(mode, asc_load_l2_cache_mode::NORMAL_FIRST_VICTIM);
197+ GlobalMockObject::verify();
198+}
199+ 
200+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_load_cache_mode_normal_last_victim)
201+{
202+ g_ctrlValue = static_cast<int64_t>(1) << 16;
203+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
204+ 
205+ auto mode = asc_get_scalar_load_cache_mode();
206+ EXPECT_EQ(mode, asc_load_l2_cache_mode::NORMAL_LAST_VICTIM);
207+ GlobalMockObject::verify();
208+}
209+ 
210+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_load_cache_mode_normal_persistent)
211+{
212+ g_ctrlValue = static_cast<int64_t>(2) << 16;
213+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
214+ 
215+ auto mode = asc_get_scalar_load_cache_mode();
216+ EXPECT_EQ(mode, asc_load_l2_cache_mode::NORMAL_PERSISTENT);
217+ GlobalMockObject::verify();
218+}
219+ 
220+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_load_cache_mode_notalloc_keep)
221+{
222+ g_ctrlValue = static_cast<int64_t>(4) << 16;
223+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
224+ 
225+ auto mode = asc_get_scalar_load_cache_mode();
226+ EXPECT_EQ(mode, asc_load_l2_cache_mode::NOTALLOC_KEEP);
227+ GlobalMockObject::verify();
228+}
229+ 
230+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_load_cache_mode_notalloc_clean)
231+{
232+ g_ctrlValue = static_cast<int64_t>(5) << 16;
233+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
234+ 
235+ auto mode = asc_get_scalar_load_cache_mode();
236+ EXPECT_EQ(mode, asc_load_l2_cache_mode::NOTALLOC_CLEAN);
237+ GlobalMockObject::verify();
238+}
239+ 
240+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_load_cache_mode_notalloc_drop)
241+{
242+ g_ctrlValue = static_cast<int64_t>(6) << 16;
243+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
244+ 
245+ auto mode = asc_get_scalar_load_cache_mode();
246+ EXPECT_EQ(mode, asc_load_l2_cache_mode::NOTALLOC_DROP);
247+ GlobalMockObject::verify();
248+}
249+ 
250+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_load_cache_mode_passthrough_illegal_encoding)
251+{
252+ g_ctrlValue = static_cast<int64_t>(3) << 16;
253+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
254+ 
255+ auto mode = asc_get_scalar_load_cache_mode();
256+ EXPECT_EQ(mode, static_cast<asc_load_l2_cache_mode>(3));
257+ GlobalMockObject::verify();
258+}
259+ 
260+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_store_cache_mode_normal_first_victim)
261+{
262+ g_ctrlValue = 0;
263+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
264+ 
265+ auto mode = asc_get_scalar_store_cache_mode();
266+ EXPECT_EQ(mode, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM);
267+ GlobalMockObject::verify();
268+}
269+ 
270+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_store_cache_mode_normal_last_victim)
271+{
272+ g_ctrlValue = static_cast<int64_t>(1) << 20;
273+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
274+ 
275+ auto mode = asc_get_scalar_store_cache_mode();
276+ EXPECT_EQ(mode, asc_store_l2_cache_mode::NORMAL_LAST_VICTIM);
277+ GlobalMockObject::verify();
278+}
279+ 
280+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_store_cache_mode_normal_persistent)
281+{
282+ g_ctrlValue = static_cast<int64_t>(2) << 20;
283+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
284+ 
285+ auto mode = asc_get_scalar_store_cache_mode();
286+ EXPECT_EQ(mode, asc_store_l2_cache_mode::NORMAL_PERSISTENT);
287+ GlobalMockObject::verify();
288+}
289+ 
290+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_store_cache_mode_notalloc_clean)
291+{
292+ g_ctrlValue = static_cast<int64_t>(4) << 20;
293+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
294+ 
295+ auto mode = asc_get_scalar_store_cache_mode();
296+ EXPECT_EQ(mode, asc_store_l2_cache_mode::NOTALLOC_CLEAN);
297+ GlobalMockObject::verify();
298+}
299+ 
300+TEST_F(TestScalarCacheModeCAPI, c_api_get_scalar_store_cache_mode_passthrough_illegal_encoding)
301+{
302+ g_ctrlValue = static_cast<int64_t>(3) << 20;
303+ MOCKER_CPP(get_ctrl, int64_t(void)).times(1).will(invoke(get_ctrl_stub));
304+ 
305+ auto mode = asc_get_scalar_store_cache_mode();
306+ EXPECT_EQ(mode, static_cast<asc_store_l2_cache_mode>(3));
307+ GlobalMockObject::verify();
308+}
309+ 
310+TEST_F(TestScalarCacheModeCAPI, c_api_set_and_get_scalar_load_cache_mode_roundtrip)
311+{
312+ g_ctrlValue = 0;
313+ MOCKER_CPP(get_ctrl, int64_t(void)).times(2).will(invoke(get_ctrl_stub));
314+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
315+ 
316+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NOTALLOC_DROP);
317+ auto mode = asc_get_scalar_load_cache_mode();
318+ EXPECT_EQ(mode, asc_load_l2_cache_mode::NOTALLOC_DROP);
319+ GlobalMockObject::verify();
320+}
321+ 
322+TEST_F(TestScalarCacheModeCAPI, c_api_set_and_get_scalar_store_cache_mode_roundtrip)
323+{
324+ g_ctrlValue = 0;
325+ MOCKER_CPP(get_ctrl, int64_t(void)).times(2).will(invoke(get_ctrl_stub));
326+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(1).will(invoke(set_ctrl_stub));
327+ 
328+ asc_set_scalar_cache_mode(asc_store_l2_cache_mode::NOTALLOC_CLEAN);
329+ auto mode = asc_get_scalar_store_cache_mode();
330+ EXPECT_EQ(mode, asc_store_l2_cache_mode::NOTALLOC_CLEAN);
331+ GlobalMockObject::verify();
332+}
333+ 
334+TEST_F(TestScalarCacheModeCAPI, c_api_set_load_and_store_cache_mode_independent)
335+{
336+ g_ctrlValue = 0;
337+ MOCKER_CPP(get_ctrl, int64_t(void)).times(4).will(invoke(get_ctrl_stub));
338+ MOCKER_CPP(set_ctrl, void(uint64_t)).times(2).will(invoke(set_ctrl_stub));
339+ 
340+ asc_set_scalar_cache_mode(asc_load_l2_cache_mode::NORMAL_LAST_VICTIM);
341+ asc_set_scalar_cache_mode(asc_store_l2_cache_mode::NORMAL_PERSISTENT);
342+ 
343+ auto loadMode = asc_get_scalar_load_cache_mode();
344+ auto storeMode = asc_get_scalar_store_cache_mode();
345+ EXPECT_EQ(loadMode, asc_load_l2_cache_mode::NORMAL_LAST_VICTIM);
346+ EXPECT_EQ(storeMode, asc_store_l2_cache_mode::NORMAL_PERSISTENT);
347+ GlobalMockObject::verify();
348+}
@@ -0,0 +1,84 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#include <gtest/gtest.h>
12+#include <mockcpp/mockcpp.hpp>
13+#include "tests/api/c_api/stub/cce_stub.h"
14+#include "include/c_api/asc_simd.h"
15+ 
16+class TestSaturationFlagCAPI : public testing::Test {
17+protected:
18+ void SetUp() {}
19+ void TearDown() { GlobalMockObject::verify(); }
20+};
21+ 
22+namespace {
23+int64_t g_ctrlValue = 0;
24+ 
25+int64_t get_ctrl_stub() { return g_ctrlValue; }
26+ 
27+void set_ctrl_stub(uint64_t config) { g_ctrlValue = static_cast<int64_t>(config); }
28+ 
29+uint64_t sbitset0_stub(uint64_t bits, int64_t idx) { return bits & ~(static_cast<uint64_t>(1) << idx); }
30+ 
31+uint64_t sbitset1_stub(uint64_t bits, int64_t idx) { return bits | (static_cast<uint64_t>(1) << idx); }
32+ 
33+void MockCtrlRw()
34+{
35+ MOCKER_CPP(get_ctrl, int64_t(void)).stubs().will(invoke(get_ctrl_stub));
36+ MOCKER_CPP(set_ctrl, void(uint64_t)).stubs().will(invoke(set_ctrl_stub));
37+ MOCKER_CPP(sbitset0, uint64_t(uint64_t, int64_t)).stubs().will(invoke(sbitset0_stub));
38+ MOCKER_CPP(sbitset1, uint64_t(uint64_t, int64_t)).stubs().will(invoke(sbitset1_stub));
39+}
40+ 
41+int64_t GetCtrlBit(int8_t bit) { return (g_ctrlValue >> bit) & 1; }
42+ 
43+void CheckSaturationFlag(asc_saturation_mode mode, int8_t ctrlBit, int64_t enabledValue, int64_t disabledValue)
44+{
45+ g_ctrlValue = 0;
46+ MockCtrlRw();
47+ 
48+ asc_set_saturation_flag(mode, true);
49+ EXPECT_EQ(asc_get_saturation_flag(mode), true);
50+ EXPECT_EQ(GetCtrlBit(ctrlBit), enabledValue);
51+ 
52+ asc_set_saturation_flag(mode, false);
53+ EXPECT_EQ(asc_get_saturation_flag(mode), false);
54+ EXPECT_EQ(GetCtrlBit(ctrlBit), disabledValue);
55+ 
56+ asc_set_saturation_flag(mode, true);
57+ EXPECT_EQ(asc_get_saturation_flag(mode), true);
58+ EXPECT_EQ(GetCtrlBit(ctrlBit), enabledValue);
59+}
60+} // namespace
61+ 
62+TEST_F(TestSaturationFlagCAPI, FloatMode)
63+{
64+ // FLOAT: CTRL[48], 0=sat, 1=no sat
65+ CheckSaturationFlag(asc_saturation_mode::FLOAT, 48, 0, 1);
66+}
67+ 
68+TEST_F(TestSaturationFlagCAPI, Float8Mode)
69+{
70+ // FLOAT8: CTRL[50], 0=sat, 1=no sat
71+ CheckSaturationFlag(asc_saturation_mode::FLOAT8, 50, 0, 1);
72+}
73+ 
74+TEST_F(TestSaturationFlagCAPI, IntMode)
75+{
76+ // INT: CTRL[53], 1=sat, 0=truncation
77+ CheckSaturationFlag(asc_saturation_mode::INT, 53, 1, 0);
78+}
79+ 
80+TEST_F(TestSaturationFlagCAPI, CastMode)
81+{
82+ // CAST: CTRL[59], 0=sat, 1=truncation
83+ CheckSaturationFlag(asc_saturation_mode::CAST, 59, 0, 1);
84+}
@@ -0,0 +1,99 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#include <gtest/gtest.h>
12+#include <mockcpp/mockcpp.hpp>
13+#include "tests/api/c_api/stub/cce_stub.h"
14+#include "include/c_api/asc_simd.h"
15+ 
16+class TestSaturationStrategyCAPI : public testing::Test {
17+protected:
18+ void SetUp() {}
19+ void TearDown() { GlobalMockObject::verify(); }
20+};
21+ 
22+namespace {
23+int64_t g_ctrlValue = 0;
24+ 
25+int64_t get_ctrl_stub() { return g_ctrlValue; }
26+ 
27+void set_ctrl_stub(uint64_t config) { g_ctrlValue = static_cast<int64_t>(config); }
28+ 
29+uint64_t sbitset0_stub(uint64_t bits, int64_t idx) { return bits & ~(static_cast<uint64_t>(1) << idx); }
30+ 
31+uint64_t sbitset1_stub(uint64_t bits, int64_t idx) { return bits | (static_cast<uint64_t>(1) << idx); }
32+ 
33+void MockCtrlRw()
34+{
35+ MOCKER_CPP(get_ctrl, int64_t(void)).stubs().will(invoke(get_ctrl_stub));
36+ MOCKER_CPP(set_ctrl, void(uint64_t)).stubs().will(invoke(set_ctrl_stub));
37+ MOCKER_CPP(sbitset0, uint64_t(uint64_t, int64_t)).stubs().will(invoke(sbitset0_stub));
38+ MOCKER_CPP(sbitset1, uint64_t(uint64_t, int64_t)).stubs().will(invoke(sbitset1_stub));
39+}
40+ 
41+int64_t GetCtrlBit(int8_t bit) { return (g_ctrlValue >> bit) & 1; }
42+} // namespace
43+ 
44+TEST_F(TestSaturationStrategyCAPI, UseApi)
45+{
46+ // USE_API: CTRL[60]=0
47+ g_ctrlValue = 0;
48+ MockCtrlRw();
49+ 
50+ asc_set_saturation_strategy(asc_override_strategy::USE_API);
51+ EXPECT_EQ(asc_get_saturation_strategy(), asc_override_strategy::USE_API);
52+ EXPECT_EQ(GetCtrlBit(60), 0);
53+}
54+ 
55+TEST_F(TestSaturationStrategyCAPI, UseGlobal)
56+{
57+ // USE_GLOBAL: CTRL[60]=1
58+ g_ctrlValue = 0;
59+ MockCtrlRw();
60+ 
61+ asc_set_saturation_strategy(asc_override_strategy::USE_GLOBAL);
62+ EXPECT_EQ(asc_get_saturation_strategy(), asc_override_strategy::USE_GLOBAL);
63+ EXPECT_EQ(GetCtrlBit(60), 1);
64+}
65+ 
66+TEST_F(TestSaturationStrategyCAPI, RoundTrip)
67+{
68+ g_ctrlValue = 0;
69+ MockCtrlRw();
70+ 
71+ asc_set_saturation_strategy(asc_override_strategy::USE_API);
72+ EXPECT_EQ(asc_get_saturation_strategy(), asc_override_strategy::USE_API);
73+ EXPECT_EQ(GetCtrlBit(60), 0);
74+ 
75+ asc_set_saturation_strategy(asc_override_strategy::USE_GLOBAL);
76+ EXPECT_EQ(asc_get_saturation_strategy(), asc_override_strategy::USE_GLOBAL);
77+ EXPECT_EQ(GetCtrlBit(60), 1);
78+ 
79+ asc_set_saturation_strategy(asc_override_strategy::USE_API);
80+ EXPECT_EQ(asc_get_saturation_strategy(), asc_override_strategy::USE_API);
81+ EXPECT_EQ(GetCtrlBit(60), 0);
82+}
83+ 
84+TEST_F(TestSaturationStrategyCAPI, PreserveOtherBits)
85+{
86+ // Pre-set CTRL[48], ensure strategy only touches bit60.
87+ g_ctrlValue = static_cast<int64_t>(1) << 48;
88+ MockCtrlRw();
89+ 
90+ asc_set_saturation_strategy(asc_override_strategy::USE_GLOBAL);
91+ EXPECT_EQ(asc_get_saturation_strategy(), asc_override_strategy::USE_GLOBAL);
92+ EXPECT_EQ(GetCtrlBit(60), 1);
93+ EXPECT_EQ(GetCtrlBit(48), 1);
94+ 
95+ asc_set_saturation_strategy(asc_override_strategy::USE_API);
96+ EXPECT_EQ(asc_get_saturation_strategy(), asc_override_strategy::USE_API);
97+ EXPECT_EQ(GetCtrlBit(60), 0);
98+ EXPECT_EQ(GetCtrlBit(48), 1);
99+}