Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2024 Accenture
3 : *
4 : * This program and the accompanying materials are made available under the
5 : * terms of the Apache License Version 2.0 which is available at
6 : * https://www.apache.org/licenses/LICENSE-2.0
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : ********************************************************************************/
10 :
11 : #pragma once
12 :
13 : #include "platform/estdint.h"
14 :
15 : /**
16 : * This data type provides an abstract runtime mapping between a common shared I/O and
17 : * higher-level instances that can use this I/O.
18 : *
19 : * Usage: create an instance of dynamic client inside the class responsible for distribution of the
20 : * I/O channels that have to be dynamic, and provide public methods for adding and removing the
21 : * dynamic client.
22 : *
23 : * @tparam T - type that contains client's index + index of a channel inside a client.
24 : * @tparam IDynamicClient - type of an object that should be registered as a dynamic client
25 : * @tparam Size - bit width for count of clients, number of clients then is 2^Size
26 : * @tparam dynamicChannelsCount - number of dynamic channels that can be stored in this structure
27 : * @tparam dynamicClientsCount - number of dynamic clients that use this proxy.
28 : */
29 : template<
30 : typename T,
31 : typename IDynamicClient,
32 : int32_t Size,
33 : int32_t dynamicChannelsCount,
34 : int32_t dynamicClientsCount = 0>
35 : struct dynamicClient
36 : {
37 : //[Enum_start]
38 :
39 : enum
40 : {
41 : bitWidthDynamicClientCount = Size,
42 : bitWidthDynamicClientsChannelCount = ((sizeof(T) * 8) - bitWidthDynamicClientCount),
43 : maxDynamicClientCount = (0x01U << bitWidthDynamicClientCount),
44 : channelInvalid = (0x01U << bitWidthDynamicClientsChannelCount) - 1U,
45 : dynamicClientInvalid = (0x01U << bitWidthDynamicClientCount) - 1U,
46 : dynamicChannels = dynamicChannelsCount
47 : };
48 :
49 : //[Enum_end]
50 :
51 : /**
52 : * If dynamicClientsCount is not explicitly specified, maximum possible dynamicClientsCount is
53 : * selected.
54 : */
55 : static T const dynamicClientCountCfg
56 : = (dynamicClientsCount == 0 ? static_cast<int32_t>(maxDynamicClientCount)
57 : : dynamicClientsCount);
58 :
59 : /**
60 : * This structure is responsible for distributing number of clients and number of
61 : * instances per client.
62 : * If T is 8 bit, then dynamicClient can devote N bits to instances' indexing and (8-N) bits to
63 : * indexing inside a single client.
64 : * Example:
65 : * T = uint8_t, Size = 2 --> instanceNumber is in [0..3], numberInsideClient is in [0..31]
66 : */
67 : using tDynamicClientCfg = struct
68 : {
69 : T numberInsideClient : bitWidthDynamicClientsChannelCount;
70 : T instanceNumber : bitWidthDynamicClientCount;
71 : };
72 :
73 : // METHOD_START
74 : /**
75 : * Clean all Clients
76 : */
77 : static void cleanDynamicClients();
78 :
79 : /**
80 : * Check Valid Channel
81 : * @param : number of channel
82 : * @ret : true is valid ,false - not valid
83 : */
84 : static bool getClientValid(T channel);
85 :
86 : /**
87 : * setDynamicClient
88 : * @param : channel number ,
89 : * @param : numberInsideClient , channel number inside the Client
90 : * @param : IDynamicClient* client
91 : * @ret : true , false
92 : */
93 : bool setDynamicClient(T channel, T numberInsideClient, IDynamicClient* client);
94 :
95 : /**
96 : * clearDynamicClient
97 : * @param : channel number ,
98 : * @ret : true , false
99 : */
100 : bool clearDynamicClient(T channel);
101 :
102 : /**
103 : * getClientInstance, channel has to be first checked using `getClientValid()` method
104 : * @param : number of channel
105 : * @ret : IDynamicClient*
106 : */
107 3 : static inline IDynamicClient* getClientInstance(T channel)
108 : {
109 3 : return (fpDynamicClient[fDynamicChannelCfg[channel].instanceNumber]);
110 : }
111 :
112 3 : static inline T getChannelInsideClient(T channel)
113 : {
114 3 : return (fDynamicChannelCfg[channel].numberInsideClient);
115 : }
116 :
117 : static tDynamicClientCfg fDynamicChannelCfg[dynamicChannels];
118 : static IDynamicClient* fpDynamicClient[dynamicClientCountCfg];
119 :
120 : // METHOD_END
121 : };
122 :
123 : template<
124 : typename T,
125 : typename IDynamicClient,
126 : int32_t Size,
127 : int32_t dynamicChannelsCount,
128 : int32_t dynamicClientCount>
129 : typename dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
130 : tDynamicClientCfg
131 : dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
132 : fDynamicChannelCfg[dynamicChannels];
133 :
134 : template<
135 : typename T,
136 : typename IDynamicClient,
137 : int32_t Size,
138 : int32_t dynamicChannels,
139 : int32_t dynamicClientCount>
140 : IDynamicClient* dynamicClient<T, IDynamicClient, Size, dynamicChannels, dynamicClientCount>::
141 : fpDynamicClient[dynamicClientCountCfg];
142 :
143 : template<
144 : typename T,
145 : typename IDynamicClient,
146 : int32_t Size,
147 : int32_t dynamicChannelsCount,
148 : int32_t dynamicClientCount>
149 : void dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
150 : cleanDynamicClients()
151 : {
152 : for (int32_t i = 0; i < (dynamicClientCountCfg); i++)
153 : {
154 : fpDynamicClient[i] = nullptr;
155 : }
156 : for (int32_t i = 0; i < (dynamicChannels); i++)
157 : {
158 : fDynamicChannelCfg[i].numberInsideClient = channelInvalid;
159 : fDynamicChannelCfg[i].instanceNumber = dynamicClientInvalid;
160 : }
161 : }
162 :
163 : template<
164 : typename T,
165 : typename IDynamicClient,
166 : int32_t Size,
167 : int32_t dynamicChannelsCount,
168 : int32_t dynamicClientCount>
169 : bool dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
170 : getClientValid(T channel)
171 : {
172 : bool ret = false;
173 : if (channel < dynamicChannels)
174 : {
175 : T instanceNumber = fDynamicChannelCfg[channel].instanceNumber;
176 : if (instanceNumber < dynamicClientCountCfg)
177 : {
178 : if ((instanceNumber < dynamicClientInvalid)
179 : && (fDynamicChannelCfg[channel].numberInsideClient < channelInvalid)
180 : && (fpDynamicClient[instanceNumber] != nullptr))
181 : {
182 : ret = true;
183 : }
184 : }
185 : }
186 :
187 : return ret;
188 : }
189 :
190 : template<
191 : typename T,
192 : typename IDynamicClient,
193 : int32_t Size,
194 : int32_t dynamicChannelsCount,
195 : int32_t dynamicClientCount>
196 3 : bool dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
197 : setDynamicClient(T channel, T numberInsideClient, IDynamicClient* client)
198 : {
199 : // range of outputNumber check
200 3 : if (numberInsideClient >= channelInvalid)
201 : {
202 0 : return false;
203 : }
204 :
205 3 : if (channel < dynamicChannels) // number is out of range
206 : {
207 3 : uint8_t mySlot = 0xFFU;
208 3 : uint8_t availableClient = 0xFFU;
209 20 : for (T i = 0; (i < dynamicClientCountCfg) && (availableClient == 0xFFU); i++)
210 : {
211 17 : if (client == fpDynamicClient[i])
212 : {
213 1 : availableClient = static_cast<uint8_t>(i);
214 : }
215 17 : if (fpDynamicClient[i] == nullptr)
216 : {
217 15 : if (mySlot == 0xFFU)
218 : {
219 2 : mySlot = static_cast<uint8_t>(i);
220 : }
221 : }
222 : }
223 : // Occupy slot for client
224 3 : if (availableClient == 0xFFU) // not in Map yet
225 : {
226 2 : if (mySlot != 0xFFU) // placed
227 : {
228 2 : fpDynamicClient[mySlot] = client;
229 : }
230 : else // no free place
231 : {
232 0 : return false;
233 : }
234 : }
235 : else
236 : {
237 1 : mySlot = availableClient;
238 : }
239 :
240 3 : fDynamicChannelCfg[channel].numberInsideClient = numberInsideClient;
241 3 : fDynamicChannelCfg[channel].instanceNumber = mySlot;
242 3 : return true;
243 : }
244 : else
245 : {
246 0 : return false;
247 : }
248 : }
249 :
250 : template<
251 : typename T,
252 : typename IDynamicClient,
253 : int32_t Size,
254 : int32_t dynamicChannelsCount,
255 : int32_t dynamicClientCount>
256 : bool dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
257 : clearDynamicClient(T channel)
258 : {
259 : if (channel < dynamicChannels) // number is out of range
260 : {
261 : T instanceNumber = fDynamicChannelCfg[channel].instanceNumber;
262 : IDynamicClient* client = fpDynamicClient[instanceNumber];
263 :
264 : fDynamicChannelCfg[channel].numberInsideClient = channelInvalid;
265 : fDynamicChannelCfg[channel].instanceNumber = dynamicClientInvalid;
266 : // look for other outputs
267 :
268 : if ((client == nullptr) || (instanceNumber >= dynamicClientCountCfg))
269 : {
270 : return true;
271 : }
272 :
273 : uint8_t availableClient = 0xFFU;
274 : for (T i = 0; i < dynamicClientCountCfg; i++)
275 : {
276 : if (client == fpDynamicClient[i])
277 : {
278 : availableClient = i; // Found a client
279 : break;
280 : }
281 : }
282 : if (availableClient != 0xFFU)
283 : {
284 : bool found = false;
285 : for (T i = 0; i < dynamicChannels; i++)
286 : {
287 : if (fDynamicChannelCfg[i].instanceNumber == availableClient)
288 : {
289 : found = true;
290 : break;
291 : }
292 : }
293 : if (!found)
294 : {
295 : // No client was found, the link can be deleted.
296 : fpDynamicClient[availableClient] = nullptr;
297 : }
298 : }
299 :
300 : return true;
301 : }
302 : else
303 : {
304 : return false;
305 : }
306 : }
|