1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2018-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #include "utils/nvbitvector.h"
24
25 /**
26 * @brief Returns the size, in bytes, of this bitvector.
27 * @note due to the compiler trick of storing the last index within a
28 * structure pointer in the data, the minimum size of an NV_BITEVECTOR
29 * will be the size of one pointer on a given architecture. If the
30 * storage size of the underlying data is changed to something less
31 * than the size of a pointer on a given architecture, then two
32 * libraries running on different architectures transferring bitvectors
33 * between them may disagree on the value of the direct sizeof operator
34 * on a struct of an NV_BITVECTOR derivative. This version of SizeOf
35 * should be agreeable to all architectures, and should be used instead
36 * of sizeof to marshall data between libraries running on different
37 * architectures.
38 */
39 NvU32
bitVectorSizeOf_IMPL(const NV_BITVECTOR * pBitVector,NvU16 bitVectorLast)40 bitVectorSizeOf_IMPL
41 (
42 const NV_BITVECTOR *pBitVector,
43 NvU16 bitVectorLast
44 )
45 {
46 NV_ASSERT_OR_RETURN(NULL != pBitVector, 0);
47
48 return NV_BITVECTOR_BYTE_SIZE(bitVectorLast);
49 }
50
51 /**
52 * @brief Clears all flags in pBitVector.
53 */
54 NV_STATUS
bitVectorClrAll_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast)55 bitVectorClrAll_IMPL
56 (
57 NV_BITVECTOR *pBitVector,
58 NvU16 bitVectorLast
59 )
60 {
61 NvLength byteSize = NV_BITVECTOR_BYTE_SIZE(bitVectorLast);
62 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
63
64 portMemSet(&pBitVector->qword, 0x0, byteSize);
65 return NV_OK;
66 }
67
68 /**
69 * @brief Clears the flag in pBitVector according to bit index idx
70 */
71 NV_STATUS
bitVectorClr_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,NvU16 idx)72 bitVectorClr_IMPL
73 (
74 NV_BITVECTOR *pBitVector,
75 NvU16 bitVectorLast,
76 NvU16 idx
77 )
78 {
79 NvU64 *qword;
80 NvU32 qwordIdx = NV_BITVECTOR_IDX(idx);
81 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(idx);
82
83 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
84 NV_ASSERT_OR_RETURN(idx < bitVectorLast, NV_ERR_INVALID_ARGUMENT);
85
86 qword = (NvU64 *)&pBitVector->qword;
87 qword[qwordIdx] &= ~NVBIT64(qwordOffset);
88 return NV_OK;
89 }
90
91 /**
92 * @brief Clears all flags within a range in pBitVector
93 */
94 NV_STATUS
bitVectorClrRange_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,NV_RANGE range)95 bitVectorClrRange_IMPL
96 (
97 NV_BITVECTOR *pBitVector,
98 NvU16 bitVectorLast,
99 NV_RANGE range
100 )
101 {
102 NvU64 *qword;
103 NvU16 idx;
104 NV_STATUS status = NV_OK;
105
106 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
107 NV_ASSERT_OR_RETURN(rangeContains(rangeMake(0, bitVectorLast - 1), range),
108 NV_ERR_INVALID_ARGUMENT);
109
110 qword = (NvU64 *)&pBitVector->qword;
111 for (idx = (NvU16)range.lo; idx <= (NvU16)range.hi; ++idx)
112 {
113 if ((0 == NV_BITVECTOR_OFFSET(idx)) &&
114 (rangeContains(range, rangeMake(idx + 63, idx + 63))))
115 {
116 qword[NV_BITVECTOR_IDX(idx)] = 0x0;
117 idx += 63;
118 continue;
119 }
120
121 status = bitVectorClr_IMPL(pBitVector, bitVectorLast, idx);
122 if (NV_OK != status)
123 {
124 return status;
125 }
126 }
127
128 return status;
129 }
130
131 /**
132 * @brief Sets all flags in pBitVector
133 */
134 NV_STATUS
bitVectorSetAll_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast)135 bitVectorSetAll_IMPL
136 (
137 NV_BITVECTOR *pBitVector,
138 NvU16 bitVectorLast
139 )
140 {
141 NvU64 *qword;
142 NvLength byteSize = NV_BITVECTOR_BYTE_SIZE(bitVectorLast);
143 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorLast);
144 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorLast - 1);
145
146 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
147
148 qword = (NvU64 *)&pBitVector->qword;
149 portMemSet(qword, NV_U8_MAX, byteSize);
150 qword[arraySize - 1] &= (NV_U64_MAX >> (63 - qwordOffset));
151
152 return NV_OK;
153 }
154
155 /**
156 * @brief Sets the flag in pBitVector according to bit index idx
157 */
158 NV_STATUS
bitVectorSet_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,NvU16 idx)159 bitVectorSet_IMPL
160 (
161 NV_BITVECTOR *pBitVector,
162 NvU16 bitVectorLast,
163 NvU16 idx
164 )
165 {
166 NvU64 *qword;
167 NvU32 qwordIdx = NV_BITVECTOR_IDX(idx);
168 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(idx);
169
170 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
171
172 qword = (NvU64 *)&pBitVector->qword;
173 qword[qwordIdx] |= NVBIT64(qwordOffset);
174
175 return NV_OK;
176 }
177
178 /**
179 * @brief Sets all flags within a range in pBitVector
180 */
181 NV_STATUS
bitVectorSetRange_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,NV_RANGE range)182 bitVectorSetRange_IMPL
183 (
184 NV_BITVECTOR *pBitVector,
185 NvU16 bitVectorLast,
186 NV_RANGE range
187 )
188 {
189 NvU64 *qword;
190 NvU16 idx;
191 NV_STATUS status = NV_OK;
192
193 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
194 NV_ASSERT_OR_RETURN(rangeContains(rangeMake(0, bitVectorLast - 1), range),
195 NV_ERR_INVALID_ARGUMENT);
196
197 qword = (NvU64 *)&pBitVector->qword;
198 for (idx = (NvU16)range.lo; idx <= (NvU16)range.hi; ++idx)
199 {
200 if ((0 == NV_BITVECTOR_OFFSET(idx)) &&
201 (rangeContains(range, rangeMake(idx + 63, idx + 63))))
202 {
203 qword[NV_BITVECTOR_IDX(idx)] = (NV_U64_MAX);
204 idx += 63;
205 continue;
206 }
207
208 status = bitVectorSet_IMPL(pBitVector, bitVectorLast, idx);
209 if (NV_OK != status)
210 {
211 return status;
212 }
213 }
214
215 return status;
216 }
217
218 /**
219 * @brief Toggles the flag in pBitVector according to bit index idx
220 */
221 NV_STATUS
bitVectorInv_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,NvU16 idx)222 bitVectorInv_IMPL
223 (
224 NV_BITVECTOR *pBitVector,
225 NvU16 bitVectorLast,
226 NvU16 idx
227 )
228 {
229 NvU64 *qword;
230 NvU32 qwordIdx = NV_BITVECTOR_IDX(idx);
231 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(idx);
232
233 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
234
235 qword = (NvU64 *)&pBitVector->qword;
236 qword[qwordIdx] ^= NVBIT64(qwordOffset);
237
238 return NV_OK;
239 }
240
241 /**
242 * @brief Toggles all flags within a range in pBitVector
243 */
244 NV_STATUS
bitVectorInvRange_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,NV_RANGE range)245 bitVectorInvRange_IMPL
246 (
247 NV_BITVECTOR *pBitVector,
248 NvU16 bitVectorLast,
249 NV_RANGE range
250 )
251 {
252 NvU64 *qword;
253 NvU16 idx;
254 NV_STATUS status = NV_OK;
255
256 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
257 NV_ASSERT_OR_RETURN(rangeContains(rangeMake(0, bitVectorLast - 1), range),
258 NV_ERR_INVALID_ARGUMENT);
259
260 qword = (NvU64 *)&pBitVector->qword;
261 for (idx = (NvU16)range.lo; idx <= (NvU16)range.hi; ++idx)
262 {
263 if ((0 == NV_BITVECTOR_OFFSET(idx)) &&
264 (rangeContains(range, rangeMake(idx + 63, idx + 63))))
265 {
266 qword[NV_BITVECTOR_IDX(idx)] = ~qword[NV_BITVECTOR_IDX(idx)];
267 idx += 63;
268 continue;
269 }
270
271 status = bitVectorInv_IMPL(pBitVector, bitVectorLast, idx);
272 if (NV_OK != status)
273 {
274 return status;
275 }
276 }
277
278 return status;
279 }
280
281 /**
282 * @brief Initializes a NV_BITVECTOR with the bit indices contained within
283 * pIndices set.
284 */
285 NV_STATUS
bitVectorFromArrayU16_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,NvU16 * pIndices,NvU32 indicesSize)286 bitVectorFromArrayU16_IMPL
287 (
288 NV_BITVECTOR *pBitVector,
289 NvU16 bitVectorLast,
290 NvU16 *pIndices,
291 NvU32 indicesSize
292 )
293 {
294 NV_STATUS status = NV_OK;
295 NvU32 i;
296
297 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
298 NV_ASSERT_OR_RETURN(NULL != pIndices, NV_ERR_INVALID_ARGUMENT);
299 NV_ASSERT_OR_RETURN(0 != indicesSize, NV_ERR_INVALID_ARGUMENT);
300
301 status = bitVectorClrAll_IMPL(pBitVector, bitVectorLast);
302 if (NV_OK != status)
303 {
304 return status;
305 }
306
307 for (i = 0; i < indicesSize; ++i)
308 {
309 status = bitVectorSet_IMPL(pBitVector, bitVectorLast, pIndices[i]);
310 if (NV_OK != status)
311 {
312 return status;
313 }
314 }
315
316 return status;
317 }
318
319 /**
320 * @brief Checks if all flags in pBitVector are set
321 */
322 NvBool
bitVectorTestAllSet_IMPL(const NV_BITVECTOR * pBitVector,NvU16 bitVectorLast)323 bitVectorTestAllSet_IMPL
324 (
325 const NV_BITVECTOR *pBitVector,
326 NvU16 bitVectorLast
327 )
328 {
329 const NvU64 *qword;
330 NvU32 idx;
331 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorLast);
332 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorLast - 1);
333 NvU64 mask;
334
335 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_FALSE);
336
337 qword = (const NvU64 *)&pBitVector->qword;
338 for (idx = 0; idx < arraySize; idx++)
339 {
340 mask = (idx < arraySize - 1) ? NV_U64_MAX :
341 (NV_U64_MAX >> (63 - qwordOffset));
342
343 if (mask != (qword[idx] & mask))
344 {
345 return NV_FALSE;
346 }
347 }
348
349 return NV_TRUE;
350 }
351
352 /**
353 * @brief Checks if all flags in pBitVector are cleared
354 */
355 NvBool
bitVectorTestAllCleared_IMPL(const NV_BITVECTOR * pBitVector,NvU16 bitVectorLast)356 bitVectorTestAllCleared_IMPL
357 (
358 const NV_BITVECTOR *pBitVector,
359 NvU16 bitVectorLast
360 )
361 {
362 const NvU64 *qword;
363 NvU32 idx;
364 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorLast);
365 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorLast - 1);
366 NvU64 mask;
367
368 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_FALSE);
369
370 qword = (const NvU64 *)&pBitVector->qword;
371 for (idx = 0; idx < arraySize; idx++)
372 {
373 mask = (idx < arraySize - 1) ? NV_U64_MAX :
374 (NV_U64_MAX >> (63 - qwordOffset));
375
376 if (0x0 != (qword[idx] & mask))
377 {
378 return NV_FALSE;
379 }
380 }
381
382 return NV_TRUE;
383 }
384
385 /**
386 * @brief Checks if two bitVectors are equivalent
387 */
388 NvBool
bitVectorTestEqual_IMPL(const NV_BITVECTOR * pBitVectorA,NvU16 bitVectorALast,const NV_BITVECTOR * pBitVectorB,NvU16 bitVectorBLast)389 bitVectorTestEqual_IMPL
390 (
391 const NV_BITVECTOR *pBitVectorA,
392 NvU16 bitVectorALast,
393 const NV_BITVECTOR *pBitVectorB,
394 NvU16 bitVectorBLast
395 )
396 {
397 const NvU64 *qwordA;
398 const NvU64 *qwordB;
399 NvU32 idx;
400 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorALast);
401 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorALast - 1);
402 NvU64 mask;
403
404 NV_ASSERT_OR_RETURN(NULL != pBitVectorA, NV_ERR_INVALID_ARGUMENT);
405 NV_ASSERT_OR_RETURN(NULL != pBitVectorB, NV_ERR_INVALID_ARGUMENT);
406 NV_ASSERT_OR_RETURN((bitVectorALast == bitVectorBLast), NV_ERR_INVALID_ARGUMENT);
407
408 qwordA = (const NvU64 *)&pBitVectorA->qword;
409 qwordB = (const NvU64 *)&pBitVectorB->qword;
410 for (idx = 0; idx < arraySize; idx++)
411 {
412 mask = (idx < arraySize - 1) ? NV_U64_MAX :
413 (NV_U64_MAX >> (63 - qwordOffset));
414
415 if ((qwordA[idx] & mask) != (qwordB[idx] & mask))
416 {
417 return NV_FALSE;
418 }
419 }
420
421 return NV_TRUE;
422 }
423
424 /**
425 * @brief Checks if the set of set flags in bitVectorA is a subset of the set of
426 * set flags in bitVectorB.
427 */
428 NvBool
bitVectorTestIsSubset_IMPL(const NV_BITVECTOR * pBitVectorA,NvU16 bitVectorALast,const NV_BITVECTOR * pBitVectorB,NvU16 bitVectorBLast)429 bitVectorTestIsSubset_IMPL
430 (
431 const NV_BITVECTOR *pBitVectorA,
432 NvU16 bitVectorALast,
433 const NV_BITVECTOR *pBitVectorB,
434 NvU16 bitVectorBLast
435 )
436 {
437 const NvU64 *qwordA;
438 const NvU64 *qwordB;
439 NvU32 idx;
440 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorALast);
441 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorALast - 1);
442 NvU64 mask;
443
444 NV_ASSERT_OR_RETURN(NULL != pBitVectorA, NV_ERR_INVALID_ARGUMENT);
445 NV_ASSERT_OR_RETURN(NULL != pBitVectorB, NV_ERR_INVALID_ARGUMENT);
446 NV_ASSERT_OR_RETURN((bitVectorALast == bitVectorBLast), NV_ERR_INVALID_ARGUMENT);
447
448 qwordA = (const NvU64 *)&pBitVectorA->qword;
449 qwordB = (const NvU64 *)&pBitVectorB->qword;
450 for (idx = 0; idx < arraySize; idx++)
451 {
452 mask = (idx < arraySize - 1) ? NV_U64_MAX :
453 (NV_U64_MAX >> (63 - qwordOffset));
454
455 if (((qwordA[idx] & mask) & (qwordB[idx] & mask)) != (qwordA[idx] & mask))
456 {
457 return NV_FALSE;
458 }
459 }
460
461 return NV_TRUE;
462 }
463
464 /**
465 * @brief Checks if the flag according to bit index idx in pBitVector is set
466 */
467 NvBool
bitVectorTest_IMPL(const NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,NvU16 idx)468 bitVectorTest_IMPL
469 (
470 const NV_BITVECTOR *pBitVector,
471 NvU16 bitVectorLast,
472 NvU16 idx
473 )
474 {
475 const NvU64 *qword;
476 NvU32 qwordIdx = NV_BITVECTOR_IDX(idx);
477 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(idx);
478
479 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_FALSE);
480 NV_ASSERT_OR_RETURN(idx < bitVectorLast, NV_FALSE);
481
482 qword = (const NvU64 *)&pBitVector->qword;
483 return !!(qword[qwordIdx] & NVBIT64(qwordOffset));
484 }
485
486 /**
487 * @brief Computes the intersection of flags in pBitVectorA and pBitVectorB, and
488 * stores the result in pBitVectorDst
489 *
490 * @param[out] pBitVectorDst Destination
491 * @param[in] pBitVectorA First operand
492 * @param[in] pBitVectorB Second operand
493 *
494 * @note it is valid for the same bitVector to be both destination and operand
495 * for this operation
496 */
497 NV_STATUS
bitVectorAnd_IMPL(NV_BITVECTOR * pBitVectorDst,NvU16 bitVectorDstLast,const NV_BITVECTOR * pBitVectorA,NvU16 bitVectorALast,const NV_BITVECTOR * pBitVectorB,NvU16 bitVectorBLast)498 bitVectorAnd_IMPL
499 (
500 NV_BITVECTOR *pBitVectorDst,
501 NvU16 bitVectorDstLast,
502 const NV_BITVECTOR *pBitVectorA,
503 NvU16 bitVectorALast,
504 const NV_BITVECTOR *pBitVectorB,
505 NvU16 bitVectorBLast
506 )
507 {
508 NvU64 *qwordDst;
509 const NvU64 *qwordA;
510 const NvU64 *qwordB;
511 NvU32 idx;
512 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorDstLast);
513 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorDstLast - 1);
514 NvU64 mask;
515
516 NV_ASSERT_OR_RETURN(NULL != pBitVectorDst, NV_ERR_INVALID_ARGUMENT);
517 NV_ASSERT_OR_RETURN(NULL != pBitVectorA, NV_ERR_INVALID_ARGUMENT);
518 NV_ASSERT_OR_RETURN(NULL != pBitVectorB, NV_ERR_INVALID_ARGUMENT);
519 NV_ASSERT_OR_RETURN(((bitVectorDstLast == bitVectorALast) && (bitVectorALast ==
520 bitVectorBLast)), NV_ERR_INVALID_ARGUMENT);
521
522 qwordDst = (NvU64 *)&pBitVectorDst->qword;
523 qwordA = (const NvU64 *)&pBitVectorA->qword;
524 qwordB = (const NvU64 *)&pBitVectorB->qword;
525 for (idx = 0; idx < arraySize; idx++)
526 {
527 mask = (idx < arraySize - 1) ? NV_U64_MAX :
528 (NV_U64_MAX >> (63 - qwordOffset));
529
530 qwordDst[idx] = (qwordA[idx] & qwordB[idx]) & mask;
531 }
532
533 return NV_OK;
534 }
535
536 /**
537 * @brief Computes the union of flags in pBitVectorA and pBitVectorB, and stores
538 * the result in pBitVectorDst
539 *
540 * @param[out] pBitVectorDst Destination
541 * @param[in] pBitVectorA First operand
542 * @param[in] pBitVectorB Second operand
543 *
544 * @note it is valid for the same bitVector to be both destination and operand
545 * for this operation
546 */
547 NV_STATUS
bitVectorOr_IMPL(NV_BITVECTOR * pBitVectorDst,NvU16 bitVectorDstLast,const NV_BITVECTOR * pBitVectorA,NvU16 bitVectorALast,const NV_BITVECTOR * pBitVectorB,NvU16 bitVectorBLast)548 bitVectorOr_IMPL
549 (
550 NV_BITVECTOR *pBitVectorDst,
551 NvU16 bitVectorDstLast,
552 const NV_BITVECTOR *pBitVectorA,
553 NvU16 bitVectorALast,
554 const NV_BITVECTOR *pBitVectorB,
555 NvU16 bitVectorBLast
556 )
557 {
558 NvU64 *qwordDst;
559 const NvU64 *qwordA;
560 const NvU64 *qwordB;
561 NvU32 idx;
562 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorDstLast);
563 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorDstLast - 1);
564 NvU64 mask;
565
566 NV_ASSERT_OR_RETURN(NULL != pBitVectorDst, NV_ERR_INVALID_ARGUMENT);
567 NV_ASSERT_OR_RETURN(NULL != pBitVectorA, NV_ERR_INVALID_ARGUMENT);
568 NV_ASSERT_OR_RETURN(NULL != pBitVectorB, NV_ERR_INVALID_ARGUMENT);
569 NV_ASSERT_OR_RETURN(((bitVectorDstLast == bitVectorALast) && (bitVectorALast ==
570 bitVectorBLast)), NV_ERR_INVALID_ARGUMENT);
571
572 qwordDst = (NvU64 *)&pBitVectorDst->qword;
573 qwordA = (const NvU64 *)&pBitVectorA->qword;
574 qwordB = (const NvU64 *)&pBitVectorB->qword;
575 for (idx = 0; idx < arraySize; idx++)
576 {
577 mask = (idx < arraySize - 1) ? NV_U64_MAX :
578 (NV_U64_MAX >> (63 - qwordOffset));
579
580 qwordDst[idx] = (qwordA[idx] | qwordB[idx]) & mask;
581 }
582
583 return NV_OK;
584 }
585
586 /**
587 * @brief Computes the exclusive OR of flags in pBitVectorA and pBitVectorB, and stores
588 * the result in pBitVectorDst
589 *
590 * @param[out] pBitVectorDst Destination
591 * @param[in] pBitVectorA First operand
592 * @param[in] pBitVectorB Second operand
593 *
594 * @note it is valid for the same bitVector to be both destination and operand
595 * for this operation
596 */
597 NV_STATUS
bitVectorXor_IMPL(NV_BITVECTOR * pBitVectorDst,NvU16 bitVectorDstLast,const NV_BITVECTOR * pBitVectorA,NvU16 bitVectorALast,const NV_BITVECTOR * pBitVectorB,NvU16 bitVectorBLast)598 bitVectorXor_IMPL
599 (
600 NV_BITVECTOR *pBitVectorDst,
601 NvU16 bitVectorDstLast,
602 const NV_BITVECTOR *pBitVectorA,
603 NvU16 bitVectorALast,
604 const NV_BITVECTOR *pBitVectorB,
605 NvU16 bitVectorBLast
606 )
607 {
608 NvU64 *qwordDst;
609 const NvU64 *qwordA;
610 const NvU64 *qwordB;
611 NvU32 idx;
612 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorDstLast);
613 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorDstLast - 1);
614 NvU64 mask;
615
616 NV_ASSERT_OR_RETURN(NULL != pBitVectorDst, NV_ERR_INVALID_ARGUMENT);
617 NV_ASSERT_OR_RETURN(NULL != pBitVectorA, NV_ERR_INVALID_ARGUMENT);
618 NV_ASSERT_OR_RETURN(NULL != pBitVectorB, NV_ERR_INVALID_ARGUMENT);
619 NV_ASSERT_OR_RETURN(((bitVectorDstLast == bitVectorALast) && (bitVectorALast ==
620 bitVectorBLast)), NV_ERR_INVALID_ARGUMENT);
621
622 qwordDst = (NvU64 *)&pBitVectorDst->qword;
623 qwordA = (const NvU64 *)&pBitVectorA->qword;
624 qwordB = (const NvU64 *)&pBitVectorB->qword;
625 for (idx = 0; idx < arraySize; idx++)
626 {
627 mask = (idx < arraySize - 1) ? NV_U64_MAX :
628 (NV_U64_MAX >> (63 - qwordOffset));
629
630 qwordDst[idx] = (qwordA[idx] ^ qwordB[idx]) & mask;
631 }
632
633 return NV_OK;
634 }
635
636 /**
637 * @brief Causes the set of raised flags in pBitVectorDst to be equal to the
638 * complement of the set of raised flags in pBitVectorSrc.
639 *
640 * @param[out] pBitVectorDst Destination
641 * @param[in] pBitVectorSrc Source
642 *
643 * @note it is valid for the same bitVector to be both destination and
644 * source for this operation
645 */
646 NV_STATUS
bitVectorComplement_IMPL(NV_BITVECTOR * pBitVectorDst,NvU16 bitVectorDstLast,const NV_BITVECTOR * pBitVectorSrc,NvU16 bitVectorSrcLast)647 bitVectorComplement_IMPL
648 (
649 NV_BITVECTOR *pBitVectorDst,
650 NvU16 bitVectorDstLast,
651 const NV_BITVECTOR *pBitVectorSrc,
652 NvU16 bitVectorSrcLast
653 )
654 {
655 NvU64 *qwordDst;
656 const NvU64 *qwordSrc;
657 NvU32 idx;
658 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorDstLast);
659 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorDstLast - 1);
660 NvU64 mask;
661
662 NV_ASSERT_OR_RETURN(NULL != pBitVectorDst, NV_ERR_INVALID_ARGUMENT);
663 NV_ASSERT_OR_RETURN(NULL != pBitVectorSrc, NV_ERR_INVALID_ARGUMENT);
664 NV_ASSERT_OR_RETURN(((bitVectorDstLast == bitVectorSrcLast)), NV_ERR_INVALID_ARGUMENT);
665
666 qwordDst = (NvU64 *)&pBitVectorDst->qword;
667 qwordSrc = (const NvU64 *)&pBitVectorSrc->qword;
668 for (idx = 0; idx < arraySize; idx++)
669 {
670 mask = (idx < arraySize - 1) ? NV_U64_MAX :
671 (NV_U64_MAX >> (63 - qwordOffset));
672
673 qwordDst[idx] = (~qwordSrc[idx]) & mask;
674 }
675
676 return NV_OK;
677 }
678
679 /**
680 * @brief Causes the set of raised flags in pBitVectorDst to be equal to the set
681 * of raised flags in pBitVectorSrc.
682 *
683 * @param[out] pBitVectorDst Destination
684 * @param[in] pBitVectorSrc Source
685 *
686 * @note it is \b invalid for the same bitVector to be both destination and
687 * source for this operation
688 */
689 NV_STATUS
bitVectorCopy_IMPL(NV_BITVECTOR * pBitVectorDst,NvU16 bitVectorDstLast,const NV_BITVECTOR * pBitVectorSrc,NvU16 bitVectorSrcLast)690 bitVectorCopy_IMPL
691 (
692 NV_BITVECTOR *pBitVectorDst,
693 NvU16 bitVectorDstLast,
694 const NV_BITVECTOR *pBitVectorSrc,
695 NvU16 bitVectorSrcLast
696 )
697 {
698 NvLength byteSizeDst = NV_BITVECTOR_BYTE_SIZE(bitVectorDstLast);
699 NvLength byteSizeSrc = NV_BITVECTOR_BYTE_SIZE(bitVectorSrcLast);
700
701 NV_ASSERT_OR_RETURN(NULL != pBitVectorDst, NV_ERR_INVALID_ARGUMENT);
702 NV_ASSERT_OR_RETURN(NULL != pBitVectorSrc, NV_ERR_INVALID_ARGUMENT);
703 NV_ASSERT_OR_RETURN(bitVectorDstLast == bitVectorSrcLast, NV_ERR_INVALID_ARGUMENT);
704 NV_ASSERT_OR_RETURN(pBitVectorDst != pBitVectorSrc, NV_WARN_NOTHING_TO_DO);
705
706 portMemCopy(&pBitVectorDst->qword, byteSizeDst, &pBitVectorSrc->qword, byteSizeSrc);
707 return NV_OK;
708 }
709
710 /**
711 * @brief Returns the bit index of the first set flag in pBitVector.
712 *
713 * @note in the absence of set flags in pBitVector, the index of the first
714 * invalid flag is returned.
715 */
716 NvU32
bitVectorCountTrailingZeros_IMPL(const NV_BITVECTOR * pBitVector,NvU16 bitVectorLast)717 bitVectorCountTrailingZeros_IMPL
718 (
719 const NV_BITVECTOR *pBitVector,
720 NvU16 bitVectorLast
721 )
722 {
723 const NvU64 *qword;
724 NvU32 idx;
725 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorLast);
726 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorLast - 1);
727 NvU64 mask;
728
729 NV_ASSERT_OR_RETURN(NULL != pBitVector, 0);
730
731 qword = (const NvU64 *)&pBitVector->qword;
732 for (idx = 0; idx < arraySize; idx++)
733 {
734 mask = (idx < arraySize - 1) ? NV_U64_MAX :
735 (NV_U64_MAX >> (63 - qwordOffset));
736
737 if (0x0 != (qword[idx] & mask))
738 {
739 return ((idx * (sizeof(NvU64) * 8)) +
740 portUtilCountTrailingZeros64(qword[idx] & mask));
741 }
742 }
743
744 return bitVectorLast;
745 }
746
747 /**
748 * @brief Returns the bit index of the last set flag in pBitVector.
749 *
750 * @note in the absence of set flags in pBitVector, the index of the first
751 * invalid flag is returned.
752 */
753 NvU32
bitVectorCountLeadingZeros_IMPL(const NV_BITVECTOR * pBitVector,NvU16 bitVectorLast)754 bitVectorCountLeadingZeros_IMPL
755 (
756 const NV_BITVECTOR *pBitVector,
757 NvU16 bitVectorLast
758 )
759 {
760 const NvU64 *qword;
761 NvU32 idx;
762 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorLast);
763 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorLast - 1);
764 NvU32 qwordUnused = 63 - qwordOffset;
765 NvU64 mask;
766
767 NV_ASSERT_OR_RETURN(NULL != pBitVector, 0);
768
769 qword = (const NvU64 *)&pBitVector->qword;
770 for (idx = (arraySize - 1); idx != (NvU32)-1; idx--)
771 {
772 mask = (idx < arraySize - 1) ? NV_U64_MAX :
773 (NV_U64_MAX >> (63 - qwordOffset));
774
775 if (0x0 != qword[idx])
776 {
777 //
778 // We're counting from the MSB, and we have to subtract the unused
779 // portion of the bitvector from the output
780 //
781 return (((arraySize - idx - 1) * (sizeof(NvU64) * 8)) +
782 portUtilCountLeadingZeros64(qword[idx] & mask)) -
783 qwordUnused;
784 }
785 }
786
787 return bitVectorLast;
788 }
789
790 /**
791 * @brief Returns the number of set bits in the bitvector.
792 */
793 NvU32
bitVectorCountSetBits_IMPL(const NV_BITVECTOR * pBitVector,NvU16 bitVectorLast)794 bitVectorCountSetBits_IMPL
795 (
796 const NV_BITVECTOR *pBitVector,
797 NvU16 bitVectorLast
798 )
799 {
800 const NvU64 *qword;
801 NvU32 idx;
802 NvU32 arraySize = NV_BITVECTOR_ARRAY_SIZE(bitVectorLast);
803 NvU32 qwordOffset = NV_BITVECTOR_OFFSET(bitVectorLast - 1);
804 NvU64 mask;
805 NvU32 count;
806
807 NV_ASSERT_OR_RETURN(NULL != pBitVector, 0);
808
809 count = 0;
810 qword = (const NvU64 *)&pBitVector->qword;
811 for (idx = 0; idx < arraySize; idx++)
812 {
813 mask = (idx < arraySize - 1) ? NV_U64_MAX :
814 (NV_U64_MAX >> (63 - qwordOffset));
815 count += nvPopCount64(qword[idx] & mask);
816 }
817
818 return count;
819 }
820
821 /**
822 * @brief Exports the bitVector data to an NvU64 raw bitmask array.
823 */
824 NV_STATUS
bitVectorToRaw_IMPL(const NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,void * pRawMask,NvU32 rawMaskSize)825 bitVectorToRaw_IMPL
826 (
827 const NV_BITVECTOR *pBitVector,
828 NvU16 bitVectorLast,
829 void *pRawMask,
830 NvU32 rawMaskSize
831 )
832 {
833 const NvLength byteSize = NV_BITVECTOR_BYTE_SIZE(bitVectorLast);
834
835 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
836 NV_ASSERT_OR_RETURN(NULL != pRawMask, NV_ERR_INVALID_ARGUMENT);
837 NV_ASSERT_OR_RETURN(rawMaskSize >= byteSize, NV_ERR_BUFFER_TOO_SMALL);
838
839 portMemCopy(pRawMask, byteSize, &pBitVector->qword, byteSize);
840 return NV_OK;
841 }
842
843 /**
844 * @brief Imports the bitVector data from an Nvu64 raw bitmask array.
845 */
846 NV_STATUS
bitVectorFromRaw_IMPL(NV_BITVECTOR * pBitVector,NvU16 bitVectorLast,const void * pRawMask,NvU32 rawMaskSize)847 bitVectorFromRaw_IMPL
848 (
849 NV_BITVECTOR *pBitVector,
850 NvU16 bitVectorLast,
851 const void *pRawMask,
852 NvU32 rawMaskSize
853 )
854 {
855 const NvLength byteSize = NV_BITVECTOR_BYTE_SIZE(bitVectorLast);
856
857 NV_ASSERT_OR_RETURN(NULL != pBitVector, NV_ERR_INVALID_ARGUMENT);
858 NV_ASSERT_OR_RETURN(NULL != pRawMask, NV_ERR_INVALID_ARGUMENT);
859 NV_ASSERT_OR_RETURN(rawMaskSize >= byteSize, NV_ERR_BUFFER_TOO_SMALL);
860
861 portMemCopy(&pBitVector->qword, byteSize, pRawMask, byteSize);
862 return NV_OK;
863 }
864
865