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