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 19971 : HcclResult HDCommunicateLite::Get(u32 offset, u32 length, u8* value)
67 : {
68 19971 : if (length == 0) {
69 0 : return HCCL_SUCCESS;
70 : }
71 19971 : CHK_PTR_NULL(value);
72 19971 : CHK_PRT_RET(
73 : (static_cast<u64>(offset) + length > buffLen),
74 : HCCL_ERROR(
75 : "[HDCommunicateLite][Get]Invalid length, offset=%u, length=%u, befferLen=%u", offset, length, buffLen),
76 : HCCL_E_PARA);
77 19971 : std::unique_lock<std::mutex> lock(shmLock);
78 19971 : return Read(offset, length, value);
79 19971 : }
80 :
81 : #pragma GCC push_options
82 : #pragma GCC optimize("O0")
83 13 : HcclResult HDCommunicateLite::Write(u32 offset, u32 length, u8* value)
84 : {
85 13 : if (length == 0) {
86 0 : return HCCL_SUCCESS;
87 : }
88 13 : CHK_PTR_NULL(value);
89 13 : u32 head = *headCntAddr;
90 13 : head++;
91 13 : *headCntAddr = head;
92 :
93 52 : auto ret = memcpy_s(
94 13 : reinterpret_cast<u8*>(devMem->GetAddr()) + offset,
95 13 : devMem->GetSize() - HCCL_HDC_CONTROL_WORDS * sizeof(u32) - offset, value, length);
96 13 : CHK_PRT_RET(ret != EOK, HCCL_ERROR("[HDCommunicateLite][Write]memcpy_s failed, return[%d].", ret), HCCL_E_INTERNAL);
97 :
98 13 : u32 tail = *tailCntAddr;
99 13 : tail++;
100 13 : *tailCntAddr = tail;
101 :
102 13 : return HCCL_SUCCESS;
103 : }
104 :
105 19971 : HcclResult HDCommunicateLite::Read(u32 offset, u32 length, u8* value)
106 : {
107 19971 : if (length == 0) {
108 0 : return HCCL_SUCCESS;
109 : }
110 19971 : CHK_PTR_NULL(value);
111 19971 : u32* cachedTailCntAddr = HcclHdcGetControlWordAddr(readCacheAddr, devMem->GetSize(), HCCL_HDC_TAIL_POS);
112 19971 : volatile u32 cachedTailCnt = *cachedTailCntAddr;
113 19971 : volatile u32 tailCnt = 0;
114 19971 : tailCnt = *tailCntAddr;
115 :
116 19971 : if (cachedTailCnt != tailCnt) {
117 : // 默认HDC超时时间为10s
118 11 : CHK_RET(UpdateCache(10));
119 : }
120 19971 : auto ret = memcpy_s(value, length, static_cast<u8*>(readCacheAddr) + offset, length);
121 19971 : CHK_PRT_RET(ret != EOK, HCCL_ERROR("[HDCommunicateLite][Read]memcpy_s failed, return[%d].", ret), HCCL_E_INTERNAL);
122 19971 : return HCCL_SUCCESS;
123 : }
124 :
125 11 : HcclResult HDCommunicateLite::UpdateCache(u32 timeoutSec)
126 : {
127 11 : void* srcBaseAddr = reinterpret_cast<void*>(devMem->GetAddr());
128 11 : u32* srcHeadCntAddr = HcclHdcGetControlWordAddr(srcBaseAddr, devMem->GetSize(), HCCL_HDC_HEAD_POS);
129 11 : u32* srcTailCntAddr = HcclHdcGetControlWordAddr(srcBaseAddr, devMem->GetSize(), HCCL_HDC_TAIL_POS);
130 11 : u32* cachedHeadCntAddr = HcclHdcGetControlWordAddr(readCacheAddr, devMem->GetSize(), HCCL_HDC_HEAD_POS);
131 11 : u32* cachedTailCntAddr = HcclHdcGetControlWordAddr(readCacheAddr, devMem->GetSize(), HCCL_HDC_TAIL_POS);
132 :
133 11 : s32 ret = 0;
134 11 : auto startTime = std::chrono::steady_clock::now();
135 11 : auto timeout = std::chrono::seconds(timeoutSec);
136 : while (1) {
137 : // step1: cache尾计数
138 11 : ret = memcpy_s(cachedTailCntAddr, sizeof(u32), srcTailCntAddr, sizeof(u32));
139 11 : CHK_PRT_RET(
140 : ret != EOK, HCCL_ERROR("[HDCommunicateLite][UpdateCache]memcpy_s failed, return[%d].", ret),
141 : HCCL_E_INTERNAL);
142 :
143 : // step2: cache数据
144 33 : ret = memcpy_s(
145 11 : readCacheAddr, devMem->GetSize() - HCCL_HDC_CONTROL_WORDS * sizeof(u32), srcBaseAddr,
146 11 : devMem->GetSize() - HCCL_HDC_CONTROL_WORDS * sizeof(u32));
147 11 : CHK_PRT_RET(
148 : ret != EOK, HCCL_ERROR("[HDCommunicateLite][UpdateCache]memcpy_s failed, return[%d].", ret),
149 : HCCL_E_INTERNAL);
150 :
151 : // step3:cache头计数
152 11 : ret = memcpy_s(cachedHeadCntAddr, sizeof(u32), srcHeadCntAddr, sizeof(u32));
153 11 : CHK_PRT_RET(
154 : ret != EOK, HCCL_ERROR("[HDCommunicateLite][UpdateCache]memcpy_s failed, return[%d].", ret),
155 : HCCL_E_INTERNAL);
156 :
157 11 : volatile u32 cachedHeadCnt = *cachedHeadCntAddr;
158 11 : volatile u32 cachedTailCnt = *cachedTailCntAddr;
159 :
160 11 : if (cachedHeadCnt == cachedTailCnt) {
161 11 : break;
162 : }
163 0 : CHK_PRT_RET(
164 : ((std::chrono::steady_clock::now() - startTime) >= timeout),
165 : HCCL_WARNING("[HDCommunicateLite][UpdateCache]get remote data timeout[%u s].", timeoutSec), HCCL_E_AGAIN);
166 0 : }
167 11 : return HCCL_SUCCESS;
168 : }
169 : #pragma GCC pop_options
170 :
171 : } // namespace Hccl
|