Line data Source code
1 : /**
2 : * Copyright (c) 2025 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 "hdc_lite.h"
12 : #include <chrono>
13 : #include "log.h"
14 :
15 : namespace Hccl {
16 : constexpr u32 HCCL_HDC_CONTROL_WORDS = 2;
17 : constexpr u32 HCCL_HDC_HEAD_POS = 2;
18 : constexpr u32 HCCL_HDC_TAIL_POS = 1;
19 :
20 0 : inline u32* HcclHdcGetControlWordAddr(void* base, u64 size, u32 pos)
21 : {
22 0 : return reinterpret_cast<u32*>(reinterpret_cast<u8*>((base)) + size - pos * sizeof(pos));
23 : }
24 :
25 19 : HcclResult HDCommunicateLite::Init(const struct HDCommunicateParams& params)
26 : {
27 19 : CHK_PRT_RET(
28 : (params.devMemSize == 0), HCCL_ERROR("[HDCommunicateLite][InitDevice]Invalid devMemSize=%u", params.devMemSize),
29 : HCCL_E_PARA);
30 19 : void* deviceAddr = reinterpret_cast<void*>(params.deviceAddr);
31 19 : CHK_PTR_NULL(deviceAddr);
32 19 : readCacheAddr = reinterpret_cast<void*>(params.readCacheAddr);
33 19 : CHK_PTR_NULL(readCacheAddr);
34 19 : devMem = std::make_unique<Buffer>(reinterpret_cast<uintptr_t>(deviceAddr), params.devMemSize);
35 19 : buffLen = params.buffLen;
36 19 : flag = params.flag;
37 :
38 : headCntAddr
39 19 : = HcclHdcGetControlWordAddr(reinterpret_cast<void*>(devMem->GetAddr()), devMem->GetSize(), HCCL_HDC_HEAD_POS);
40 : tailCntAddr
41 19 : = HcclHdcGetControlWordAddr(reinterpret_cast<void*>(devMem->GetAddr()), devMem->GetSize(), HCCL_HDC_TAIL_POS);
42 :
43 57 : HCCL_INFO(
44 : "[HDCommunicateLite][Init] buffLen=%u, flag=%u, readCacheAddr=%p, headCntAddr=%p, tailCntAddr=%p", buffLen,
45 : flag, readCacheAddr, headCntAddr, tailCntAddr);
46 19 : return HCCL_SUCCESS;
47 : }
48 :
49 13 : HcclResult HDCommunicateLite::Put(u32 offset, u32 length, u8* value)
50 : {
51 13 : if (length == 0) {
52 0 : return HCCL_SUCCESS;
53 : }
54 13 : CHK_PTR_NULL(value);
55 13 : if ((flag == HCCLV2_HDC_TYPE_H2D)) {
56 0 : HCCL_ERROR("[HDCommunicateLite][Put]Invalid usage, flag=%u", flag);
57 0 : return HCCL_E_PARA;
58 : }
59 13 : CHK_PRT_RET(
60 : (static_cast<u64>(offset) + length > buffLen),
61 : HCCL_ERROR("[HDCommunicateLite][Put]Invalid length, offset=%u, length=%u", offset, length), HCCL_E_PARA);
62 13 : std::unique_lock<std::mutex> lock(shmLock);
63 13 : return Write(offset, length, value);
64 13 : }
65 :
66 15931 : HcclResult HDCommunicateLite::Get(u32 offset, u32 length, u8* value)
67 : {
68 15931 : if (length == 0) {
69 0 : return HCCL_SUCCESS;
70 : }
71 15931 : CHK_PTR_NULL(value);
72 15931 : CHK_PRT_RET(
73 : (static_cast<u64>(offset) + length > buffLen),
74 : HCCL_ERROR("[HDCommunicateLite][Get]Invalid length, offset=%u, length=%u, buffLen=%u", offset, length, buffLen),
75 : HCCL_E_PARA);
76 15931 : std::unique_lock<std::mutex> lock(shmLock);
77 15931 : return Read(offset, length, value);
78 15931 : }
79 :
80 : #pragma GCC push_options
81 : #pragma GCC optimize("O0")
82 13 : HcclResult HDCommunicateLite::Write(u32 offset, u32 length, u8* value)
83 : {
84 13 : if (length == 0) {
85 0 : return HCCL_SUCCESS;
86 : }
87 13 : CHK_PTR_NULL(value);
88 13 : u32 head = *headCntAddr;
89 13 : head++;
90 13 : *headCntAddr = head;
91 :
92 52 : auto ret = memcpy_s(
93 13 : reinterpret_cast<u8*>(devMem->GetAddr()) + offset,
94 13 : devMem->GetSize() - HCCL_HDC_CONTROL_WORDS * sizeof(u32) - offset, value, length);
95 13 : CHK_PRT_RET(ret != EOK, HCCL_ERROR("[HDCommunicateLite][Write]memcpy_s failed, return[%d].", ret), HCCL_E_INTERNAL);
96 :
97 13 : u32 tail = *tailCntAddr;
98 13 : tail++;
99 13 : *tailCntAddr = tail;
100 :
101 13 : return HCCL_SUCCESS;
102 : }
103 :
104 15931 : HcclResult HDCommunicateLite::Read(u32 offset, u32 length, u8* value)
105 : {
106 15931 : if (length == 0) {
107 0 : return HCCL_SUCCESS;
108 : }
109 15931 : CHK_PTR_NULL(value);
110 15931 : u32* cachedTailCntAddr = HcclHdcGetControlWordAddr(readCacheAddr, devMem->GetSize(), HCCL_HDC_TAIL_POS);
111 15931 : volatile u32 cachedTailCnt = *cachedTailCntAddr;
112 15931 : volatile u32 tailCnt = 0;
113 15931 : tailCnt = *tailCntAddr;
114 :
115 15931 : if (cachedTailCnt != tailCnt) {
116 : // 默认HDC超时时间为10s
117 11 : CHK_RET(UpdateCache(10));
118 : }
119 15931 : auto ret = memcpy_s(value, length, static_cast<u8*>(readCacheAddr) + offset, length);
120 15931 : CHK_PRT_RET(ret != EOK, HCCL_ERROR("[HDCommunicateLite][Read]memcpy_s failed, return[%d].", ret), HCCL_E_INTERNAL);
121 15931 : return HCCL_SUCCESS;
122 : }
123 :
124 11 : HcclResult HDCommunicateLite::UpdateCache(u32 timeoutSec)
125 : {
126 11 : void* srcBaseAddr = reinterpret_cast<void*>(devMem->GetAddr());
127 11 : u32* srcHeadCntAddr = HcclHdcGetControlWordAddr(srcBaseAddr, devMem->GetSize(), HCCL_HDC_HEAD_POS);
128 11 : u32* srcTailCntAddr = HcclHdcGetControlWordAddr(srcBaseAddr, devMem->GetSize(), HCCL_HDC_TAIL_POS);
129 11 : u32* cachedHeadCntAddr = HcclHdcGetControlWordAddr(readCacheAddr, devMem->GetSize(), HCCL_HDC_HEAD_POS);
130 11 : u32* cachedTailCntAddr = HcclHdcGetControlWordAddr(readCacheAddr, devMem->GetSize(), HCCL_HDC_TAIL_POS);
131 :
132 11 : s32 ret = 0;
133 11 : auto startTime = std::chrono::steady_clock::now();
134 11 : auto timeout = std::chrono::seconds(timeoutSec);
135 : while (1) {
136 : // step1: cache尾计数
137 11 : ret = memcpy_s(cachedTailCntAddr, sizeof(u32), srcTailCntAddr, sizeof(u32));
138 11 : CHK_PRT_RET(
139 : ret != EOK, HCCL_ERROR("[HDCommunicateLite][UpdateCache]memcpy_s failed, return[%d].", ret),
140 : HCCL_E_INTERNAL);
141 :
142 : // step2: cache数据
143 33 : ret = memcpy_s(
144 11 : readCacheAddr, devMem->GetSize() - HCCL_HDC_CONTROL_WORDS * sizeof(u32), srcBaseAddr,
145 11 : devMem->GetSize() - HCCL_HDC_CONTROL_WORDS * sizeof(u32));
146 11 : CHK_PRT_RET(
147 : ret != EOK, HCCL_ERROR("[HDCommunicateLite][UpdateCache]memcpy_s failed, return[%d].", ret),
148 : HCCL_E_INTERNAL);
149 :
150 : // step3:cache头计数
151 11 : ret = memcpy_s(cachedHeadCntAddr, sizeof(u32), srcHeadCntAddr, sizeof(u32));
152 11 : CHK_PRT_RET(
153 : ret != EOK, HCCL_ERROR("[HDCommunicateLite][UpdateCache]memcpy_s failed, return[%d].", ret),
154 : HCCL_E_INTERNAL);
155 :
156 11 : volatile u32 cachedHeadCnt = *cachedHeadCntAddr;
157 11 : volatile u32 cachedTailCnt = *cachedTailCntAddr;
158 :
159 11 : if (cachedHeadCnt == cachedTailCnt) {
160 11 : break;
161 : }
162 0 : CHK_PRT_RET(
163 : ((std::chrono::steady_clock::now() - startTime) >= timeout),
164 : HCCL_WARNING("[HDCommunicateLite][UpdateCache]get remote data timeout[%u s].", timeoutSec), HCCL_E_AGAIN);
165 0 : }
166 11 : return HCCL_SUCCESS;
167 : }
168 : #pragma GCC pop_options
169 :
170 : } // namespace Hccl
|