LDMX Software
ap_private.h
1/*
2 * Copyright 2011-2019 Xilinx, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef __AP_PRIVATE_H__
18#define __AP_PRIVATE_H__
19
20// common macros and type declarations are now defined in ap_common.h, and
21// ap_private becomes part of it.
22#ifndef __AP_COMMON_H__
23#error "ap_impl/ap_private.h cannot be included directly."
24#endif
25
26// forward declarations
27// template <int _AP_W, bool _AP_S, bool _AP_C = _AP_W <= 64>
28// class ap_private; // moved to ap_common.h
29template <int _AP_W, bool _AP_S>
31template <int _AP_W, bool _AP_S>
32struct _private_bit_ref;
33
34// TODO clean up this part.
35#ifndef LLVM_SUPPORT_MATHEXTRAS_H
36#define LLVM_SUPPORT_MATHEXTRAS_H
37
38#ifdef _MSC_VER
39#if _MSC_VER <= 1500
40typedef __int8 int8_t;
41typedef unsigned __int8 uint8_t;
42typedef __int16 int16_t;
43typedef unsigned __int16 uint16_t;
44typedef __int32 int32_t;
45typedef unsigned __int32 uint32_t;
46typedef __int64 int64_t;
47typedef unsigned __int64 uint64_t;
48#else
49#include <stdint.h>
50#endif
51#else
52#include <stdint.h>
53#endif
54
55#ifndef INLINE
56#define INLINE inline
57// Enable to debug ap_int/ap_fixed
58// #define INLINE __attribute__((weak))
59#endif
60
61// NOTE: The following support functions use the _32/_64 extensions instead of
62// type overloading so that signed and unsigned integers can be used without
63// ambiguity.
64namespace AESL_std {
65template <class DataType>
66DataType INLINE min(DataType a, DataType b) {
67 return (a >= b) ? b : a;
68}
69
70template <class DataType>
71DataType INLINE max(DataType a, DataType b) {
72 return (a >= b) ? a : b;
73}
74} // namespace AESL_std
75
76// TODO clean up included headers.
77#include <math.h>
78#include <stdio.h>
79
80#include <cassert>
81#include <cstdlib>
82#include <cstring>
83#include <iomanip>
84#include <limits>
85#include <sstream>
86#include <string>
87
88namespace ap_private_ops {
90static INLINE uint32_t Hi_32(uint64_t Value) {
91 return static_cast<uint32_t>(Value >> 32);
92}
93
95static INLINE uint32_t Lo_32(uint64_t Value) {
96 return static_cast<uint32_t>(Value);
97}
98
99template <int _AP_W>
100INLINE bool isNegative(const ap_private<_AP_W, false>& a) {
101 return false;
102}
103
104template <int _AP_W>
105INLINE bool isNegative(const ap_private<_AP_W, true>& a) {
106 enum {
107 APINT_BITS_PER_WORD = 64,
108 _AP_N = (_AP_W + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD
109 };
110 static const uint64_t sign_mask = 1ULL << ((_AP_W - 1) % APINT_BITS_PER_WORD);
111 return (sign_mask & a.get_pVal(_AP_N - 1)) != 0;
112}
113
118static INLINE unsigned CountLeadingZeros_32(uint32_t Value) {
119 unsigned Count; // result
120#if __GNUC__ >= 4
121// PowerPC is defined for __builtin_clz(0)
122#if !defined(__ppc__) && !defined(__ppc64__)
123 if (Value == 0) return 32;
124#endif
125 Count = __builtin_clz(Value);
126#else
127 if (Value == 0) return 32;
128 Count = 0;
129 // bisecton method for count leading zeros
130 for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) {
131 uint32_t Tmp = (Value) >> (Shift);
132 if (Tmp) {
133 Value = Tmp;
134 } else {
135 Count |= Shift;
136 }
137 }
138#endif
139 return Count;
140}
141
146static INLINE unsigned CountLeadingZeros_64(uint64_t Value) {
147 unsigned Count; // result
148#if __GNUC__ >= 4
149// PowerPC is defined for __builtin_clzll(0)
150#if !defined(__ppc__) && !defined(__ppc64__)
151 if (!Value) return 64;
152#endif
153 Count = __builtin_clzll(Value);
154#else
155 if (sizeof(long) == sizeof(int64_t)) {
156 if (!Value) return 64;
157 Count = 0;
158 // bisecton method for count leading zeros
159 for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) {
160 uint64_t Tmp = (Value) >> (Shift);
161 if (Tmp) {
162 Value = Tmp;
163 } else {
164 Count |= Shift;
165 }
166 }
167 } else {
168 // get hi portion
169 uint32_t Hi = Hi_32(Value);
170
171 // if some bits in hi portion
172 if (Hi) {
173 // leading zeros in hi portion plus all bits in lo portion
174 Count = CountLeadingZeros_32(Hi);
175 } else {
176 // get lo portion
177 uint32_t Lo = Lo_32(Value);
178 // same as 32 bit value
179 Count = CountLeadingZeros_32(Lo) + 32;
180 }
181 }
182#endif
183 return Count;
184}
185
190static INLINE unsigned CountTrailingZeros_64(uint64_t Value) {
191#if __GNUC__ >= 4
192 return (Value != 0) ? __builtin_ctzll(Value) : 64;
193#else
194 static const unsigned Mod67Position[] = {
195 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, 4,
196 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, 47, 5, 32,
197 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, 29, 50, 43, 46, 31,
198 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, 7, 48, 35, 6, 34, 33, 0};
199 return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67];
200#endif
201}
202
205static INLINE unsigned CountPopulation_64(uint64_t Value) {
206#if __GNUC__ >= 4
207 return __builtin_popcountll(Value);
208#else
209 uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL);
210 v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL);
211 v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
212 return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
213#endif
214}
215
216static INLINE uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) {
217 uint32_t Count = 0;
218 if (skip) (__V) <<= (skip);
219 while (__V && (__V & (1ULL << 63))) {
220 Count++;
221 (__V) <<= 1;
222 }
223 return Count;
224}
225
226static INLINE std::string oct2Bin(char oct) {
227 switch (oct) {
228 case '\0': {
229 return "";
230 }
231 case '.': {
232 return ".";
233 }
234 case '0': {
235 return "000";
236 }
237 case '1': {
238 return "001";
239 }
240 case '2': {
241 return "010";
242 }
243 case '3': {
244 return "011";
245 }
246 case '4': {
247 return "100";
248 }
249 case '5': {
250 return "101";
251 }
252 case '6': {
253 return "110";
254 }
255 case '7': {
256 return "111";
257 }
258 }
259 assert(0 && "Invalid character in digit string");
260 return "";
261}
262
263static INLINE std::string hex2Bin(char hex) {
264 switch (hex) {
265 case '\0': {
266 return "";
267 }
268 case '.': {
269 return ".";
270 }
271 case '0': {
272 return "0000";
273 }
274 case '1': {
275 return "0001";
276 }
277 case '2': {
278 return "0010";
279 }
280 case '3': {
281 return "0011";
282 }
283 case '4': {
284 return "0100";
285 }
286 case '5': {
287 return "0101";
288 }
289 case '6': {
290 return "0110";
291 }
292 case '7': {
293 return "0111";
294 }
295 case '8': {
296 return "1000";
297 }
298 case '9': {
299 return "1001";
300 }
301 case 'A':
302 case 'a': {
303 return "1010";
304 }
305 case 'B':
306 case 'b': {
307 return "1011";
308 }
309 case 'C':
310 case 'c': {
311 return "1100";
312 }
313 case 'D':
314 case 'd': {
315 return "1101";
316 }
317 case 'E':
318 case 'e': {
319 return "1110";
320 }
321 case 'F':
322 case 'f': {
323 return "1111";
324 }
325 }
326 assert(0 && "Invalid character in digit string");
327 return "";
328}
329
330static INLINE uint32_t decode_digit(char cdigit, int radix) {
331 uint32_t digit = 0;
332 if (radix == 16) {
333#define isxdigit(c) \
334 (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || \
335 ((c) >= 'A' && (c) <= 'F'))
336#define isdigit(c) ((c) >= '0' && (c) <= '9')
337 if (!isxdigit(cdigit)) assert(0 && "Invalid hex digit in string");
338 if (isdigit(cdigit))
339 digit = cdigit - '0';
340 else if (cdigit >= 'a')
341 digit = cdigit - 'a' + 10;
342 else if (cdigit >= 'A')
343 digit = cdigit - 'A' + 10;
344 else
345 assert(0 && "huh? we shouldn't get here");
346 } else if (isdigit(cdigit)) {
347 digit = cdigit - '0';
348 } else {
349 assert(0 && "Invalid character in digit string");
350 }
351#undef isxdigit
352#undef isdigit
353 return digit;
354}
355
356// Determine the radix of "val".
357static INLINE std::string parseString(const std::string& input,
358 unsigned char& radix) {
359 size_t len = input.length();
360 if (len == 0) {
361 if (radix == 0) radix = 10;
362 return input;
363 }
364
365 size_t startPos = 0;
366 // Trim whitespace
367 while (input[startPos] == ' ' && startPos < len) startPos++;
368 while (input[len - 1] == ' ' && startPos < len) len--;
369
370 std::string val = input.substr(startPos, len - startPos);
371 // std::cout << "val = " << val << "\n";
372 len = val.length();
373 startPos = 0;
374
375 // If the length of the string is less than 2, then radix
376 // is decimal and there is no exponent.
377 if (len < 2) {
378 if (radix == 0) radix = 10;
379 return val;
380 }
381
382 bool isNegative = false;
383 std::string ans;
384
385 // First check to see if we start with a sign indicator
386 if (val[0] == '-') {
387 ans = "-";
388 ++startPos;
389 isNegative = true;
390 } else if (val[0] == '+')
391 ++startPos;
392
393 if (len - startPos < 2) {
394 if (radix == 0) radix = 10;
395 return val;
396 }
397
398 if (val.substr(startPos, 2) == "0x" || val.substr(startPos, 2) == "0X") {
399 // If we start with "0x", then the radix is hex.
400 radix = 16;
401 startPos += 2;
402 } else if (val.substr(startPos, 2) == "0b" ||
403 val.substr(startPos, 2) == "0B") {
404 // If we start with "0b", then the radix is binary.
405 radix = 2;
406 startPos += 2;
407 } else if (val.substr(startPos, 2) == "0o" ||
408 val.substr(startPos, 2) == "0O") {
409 // If we start with "0o", then the radix is octal.
410 radix = 8;
411 startPos += 2;
412 } else if (radix == 0) {
413 radix = 10;
414 }
415
416 int exp = 0;
417 if (radix == 10) {
418 // If radix is decimal, then see if there is an
419 // exponent indicator.
420 size_t expPos = val.find('e');
421 bool has_exponent = true;
422 if (expPos == std::string::npos) expPos = val.find('E');
423 if (expPos == std::string::npos) {
424 // No exponent indicator, so the mantissa goes to the end.
425 expPos = len;
426 has_exponent = false;
427 }
428 // std::cout << "startPos = " << startPos << " " << expPos << "\n";
429
430 ans += val.substr(startPos, expPos - startPos);
431 if (has_exponent) {
432 // Parse the exponent.
433 std::istringstream iss(val.substr(expPos + 1, len - expPos - 1));
434 iss >> exp;
435 }
436 } else {
437 // Check for a binary exponent indicator.
438 size_t expPos = val.find('p');
439 bool has_exponent = true;
440 if (expPos == std::string::npos) expPos = val.find('P');
441 if (expPos == std::string::npos) {
442 // No exponent indicator, so the mantissa goes to the end.
443 expPos = len;
444 has_exponent = false;
445 }
446
447 // std::cout << "startPos = " << startPos << " " << expPos << "\n";
448
449 assert(startPos <= expPos);
450 // Convert to binary as we go.
451 for (size_t i = startPos; i < expPos; ++i) {
452 if (radix == 16) {
453 ans += hex2Bin(val[i]);
454 } else if (radix == 8) {
455 ans += oct2Bin(val[i]);
456 } else { // radix == 2
457 ans += val[i];
458 }
459 }
460 // End in binary
461 radix = 2;
462 if (has_exponent) {
463 // Parse the exponent.
464 std::istringstream iss(val.substr(expPos + 1, len - expPos - 1));
465 iss >> exp;
466 }
467 }
468 if (exp == 0) return ans;
469
470 size_t decPos = ans.find('.');
471 if (decPos == std::string::npos) decPos = ans.length();
472 if ((int)decPos + exp >= (int)ans.length()) {
473 int i = decPos;
474 for (; i < (int)ans.length() - 1; ++i) ans[i] = ans[i + 1];
475 for (; i < (int)ans.length(); ++i) ans[i] = '0';
476 for (; i < (int)decPos + exp; ++i) ans += '0';
477 return ans;
478 } else if ((int)decPos + exp < (int)isNegative) {
479 std::string dupAns = "0.";
480 if (ans[0] == '-') dupAns = "-0.";
481 for (int i = 0; i < isNegative - (int)decPos - exp; ++i) dupAns += '0';
482 for (size_t i = isNegative; i < ans.length(); ++i)
483 if (ans[i] != '.') dupAns += ans[i];
484 return dupAns;
485 }
486
487 if (exp > 0)
488 for (size_t i = decPos; i < decPos + exp; ++i) ans[i] = ans[i + 1];
489 else {
490 if (decPos == ans.length()) ans += ' ';
491 for (int i = decPos; i > (int)decPos + exp; --i) ans[i] = ans[i - 1];
492 }
493 ans[decPos + exp] = '.';
494 return ans;
495}
496
503static INLINE bool sub_1(uint64_t x[], uint32_t len, uint64_t y) {
504 for (uint32_t i = 0; i < len; ++i) {
505 uint64_t __X = x[i];
506 x[i] -= y;
507 if (y > __X)
508 y = 1; // We have to "borrow 1" from next "digit"
509 else {
510 y = 0; // No need to borrow
511 break; // Remaining digits are unchanged so exit early
512 }
513 }
514 return (y != 0);
515}
516
521static INLINE bool add_1(uint64_t dest[], uint64_t x[], uint32_t len,
522 uint64_t y) {
523 for (uint32_t i = 0; i < len; ++i) {
524 dest[i] = y + x[i];
525 if (dest[i] < y)
526 y = 1; // Carry one to next digit.
527 else {
528 y = 0; // No need to carry so exit early
529 break;
530 }
531 }
532 return (y != 0);
533}
534
539static INLINE bool add(uint64_t* dest, const uint64_t* x, const uint64_t* y,
540 uint32_t destlen, uint32_t xlen, uint32_t ylen,
541 bool xsigned, bool ysigned) {
542 bool carry = false;
543 uint32_t len = AESL_std::min(xlen, ylen);
544 uint32_t i;
545 for (i = 0; i < len && i < destlen; ++i) {
546 uint64_t limit =
547 AESL_std::min(x[i], y[i]); // must come first in case dest == x
548 dest[i] = x[i] + y[i] + carry;
549 carry = dest[i] < limit || (carry && dest[i] == limit);
550 }
551 if (xlen > ylen) {
552 const uint64_t yext = ysigned && int64_t(y[ylen - 1]) < 0 ? -1 : 0;
553 for (i = ylen; i < xlen && i < destlen; i++) {
554 uint64_t limit = AESL_std::min(x[i], yext);
555 dest[i] = x[i] + yext + carry;
556 carry = (dest[i] < limit) || (carry && dest[i] == limit);
557 }
558 } else if (ylen > xlen) {
559 const uint64_t xext = xsigned && int64_t(x[xlen - 1]) < 0 ? -1 : 0;
560 for (i = xlen; i < ylen && i < destlen; i++) {
561 uint64_t limit = AESL_std::min(xext, y[i]);
562 dest[i] = xext + y[i] + carry;
563 carry = (dest[i] < limit) || (carry && dest[i] == limit);
564 }
565 }
566 return carry;
567}
568
571static INLINE bool sub(uint64_t* dest, const uint64_t* x, const uint64_t* y,
572 uint32_t destlen, uint32_t xlen, uint32_t ylen,
573 bool xsigned, bool ysigned) {
574 bool borrow = false;
575 uint32_t i;
576 uint32_t len = AESL_std::min(xlen, ylen);
577 for (i = 0; i < len && i < destlen; ++i) {
578 uint64_t x_tmp = borrow ? x[i] - 1 : x[i];
579 borrow = y[i] > x_tmp || (borrow && x[i] == 0);
580 dest[i] = x_tmp - y[i];
581 }
582 if (xlen > ylen) {
583 const uint64_t yext = ysigned && int64_t(y[ylen - 1]) < 0 ? -1 : 0;
584 for (i = ylen; i < xlen && i < destlen; i++) {
585 uint64_t x_tmp = borrow ? x[i] - 1 : x[i];
586 borrow = yext > x_tmp || (borrow && x[i] == 0);
587 dest[i] = x_tmp - yext;
588 }
589 } else if (ylen > xlen) {
590 const uint64_t xext = xsigned && int64_t(x[xlen - 1]) < 0 ? -1 : 0;
591 for (i = xlen; i < ylen && i < destlen; i++) {
592 uint64_t x_tmp = borrow ? xext - 1 : xext;
593 borrow = y[i] > x_tmp || (borrow && xext == 0);
594 dest[i] = x_tmp - y[i];
595 }
596 }
597 return borrow;
598}
599
603
608static INLINE uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len,
609 uint64_t y) {
610 // Split y into high 32-bit part (hy) and low 32-bit part (ly)
611 uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32;
612 uint64_t carry = 0;
613 static const uint64_t two_power_32 = 1ULL << 32;
614 // For each digit of x.
615 for (uint32_t i = 0; i < len; ++i) {
616 // Split x into high and low words
617 uint64_t lx = x[i] & 0xffffffffULL;
618 uint64_t hx = (x[i]) >> 32;
619 // hasCarry - A flag to indicate if there is a carry to the next digit.
620 // hasCarry == 0, no carry
621 // hasCarry == 1, has carry
622 // hasCarry == 2, no carry and the calculation result == 0.
623 uint8_t hasCarry = 0;
624 dest[i] = carry + lx * ly;
625 // Determine if the add above introduces carry.
626 hasCarry = (dest[i] < carry) ? 1 : 0;
627 carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0);
628 // The upper limit of carry can be (2^32 - 1)(2^32 - 1) +
629 // (2^32 - 1) + 2^32 = 2^64.
630 hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0);
631
632 carry += (lx * hy) & 0xffffffffULL;
633 dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL);
634 carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) +
635 ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy;
636 }
637 return carry;
638}
639
646static INLINE void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen,
647 const uint64_t y[], uint32_t ylen, uint32_t destlen) {
648 assert(xlen > 0);
649 assert(ylen > 0);
650 assert(destlen >= xlen + ylen);
651 if (xlen < destlen) dest[xlen] = mul_1(dest, x, xlen, y[0]);
652 for (uint32_t i = 1; i < ylen; ++i) {
653 uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32;
654 uint64_t carry = 0, lx = 0, hx = 0;
655 for (uint32_t j = 0; j < xlen; ++j) {
656 lx = x[j] & 0xffffffffULL;
657 hx = (x[j]) >> 32;
658 // hasCarry - A flag to indicate if has carry.
659 // hasCarry == 0, no carry
660 // hasCarry == 1, has carry
661 // hasCarry == 2, no carry and the calculation result == 0.
662 uint8_t hasCarry = 0;
663 uint64_t resul = carry + lx * ly;
664 hasCarry = (resul < carry) ? 1 : 0;
665 carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32);
666 hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0);
667 carry += (lx * hy) & 0xffffffffULL;
668 resul = ((carry) << 32) | (resul & 0xffffffffULL);
669 if (i + j < destlen) dest[i + j] += resul;
670 carry =
671 (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) +
672 ((carry) >> 32) + (dest[i + j] < resul ? 1 : 0) + ((lx * hy) >> 32) +
673 hx * hy;
674 }
675 if (i + xlen < destlen) dest[i + xlen] = carry;
676 }
677}
678
683static INLINE void KnuthDiv(uint32_t* u, uint32_t* v, uint32_t* q, uint32_t* r,
684 uint32_t m, uint32_t n) {
685 assert(u && "Must provide dividend");
686 assert(v && "Must provide divisor");
687 assert(q && "Must provide quotient");
688 assert(u != v && u != q && v != q && "Must us different memory");
689 assert(n > 1 && "n must be > 1");
690
691 // Knuth uses the value b as the base of the number system. In our case b
692 // is 2^31 so we just set it to -1u.
693 uint64_t b = uint64_t(1) << 32;
694
695 // DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n');
696 // DEBUG(cerr << "KnuthDiv: original:");
697 // DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) <<
698 // u[i]);
699 // DEBUG(cerr << " by");
700 // DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) <<
701 // v[i-1]);
702 // DEBUG(cerr << '\n');
703 // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of
704 // u and v by d. Note that we have taken Knuth's advice here to use a power
705 // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of
706 // 2 allows us to shift instead of multiply and it is easy to determine the
707 // shift amount from the leading zeros. We are basically normalizing the u
708 // and v so that its high bits are shifted to the top of v's range without
709 // overflow. Note that this can require an extra word in u so that u must
710 // be of length m+n+1.
711 uint32_t shift = CountLeadingZeros_32(v[n - 1]);
712 uint32_t v_carry = 0;
713 uint32_t u_carry = 0;
714 if (shift) {
715 for (uint32_t i = 0; i < m + n; ++i) {
716 uint32_t u_tmp = (u[i]) >> (32 - shift);
717 u[i] = ((u[i]) << (shift)) | u_carry;
718 u_carry = u_tmp;
719 }
720 for (uint32_t i = 0; i < n; ++i) {
721 uint32_t v_tmp = (v[i]) >> (32 - shift);
722 v[i] = ((v[i]) << (shift)) | v_carry;
723 v_carry = v_tmp;
724 }
725 }
726 u[m + n] = u_carry;
727 // DEBUG(cerr << "KnuthDiv: normal:");
728 // DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) <<
729 // u[i]);
730 // DEBUG(cerr << " by");
731 // DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) <<
732 // v[i-1]);
733 // DEBUG(cerr << '\n');
734
735 // D2. [Initialize j.] Set j to m. This is the loop counter over the places.
736 int j = m;
737 do {
738 // DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n');
739 // D3. [Calculate q'.].
740 // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q')
741 // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r')
742 // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease
743 // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test
744 // on v[n-2] determines at high speed most of the cases in which the trial
745 // value qp is one too large, and it eliminates all cases where qp is two
746 // too large.
747 uint64_t dividend = ((uint64_t(u[j + n]) << 32) + u[j + n - 1]);
748 // DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n');
749 uint64_t qp = dividend / v[n - 1];
750 uint64_t rp = dividend % v[n - 1];
751 if (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2]) {
752 qp--;
753 rp += v[n - 1];
754 if (rp < b && (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2])) qp--;
755 }
756 // DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n');
757
758 // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with
759 // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation
760 // consists of a simple multiplication by a one-place number, combined with
761 // a subtraction.
762 bool isNeg = false;
763 for (uint32_t i = 0; i < n; ++i) {
764 uint64_t u_tmp = uint64_t(u[j + i]) | ((uint64_t(u[j + i + 1])) << 32);
765 uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]);
766 bool borrow = subtrahend > u_tmp;
767 /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp
768 << ", subtrahend == " << subtrahend
769 << ", borrow = " << borrow << '\n');*/
770
771 uint64_t result = u_tmp - subtrahend;
772 uint32_t k = j + i;
773 u[k++] = (uint32_t)(result & (b - 1)); // subtract low word
774 u[k++] = (uint32_t)((result) >> 32); // subtract high word
775 while (borrow && k <= m + n) { // deal with borrow to the left
776 borrow = u[k] == 0;
777 u[k]--;
778 k++;
779 }
780 isNeg |= borrow;
781 /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " <<
782 u[j+i+1] << '\n');*/
783 }
784 /*DEBUG(cerr << "KnuthDiv: after subtraction:");
785 DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]);
786 DEBUG(cerr << '\n');*/
787 // The digits (u[j+n]...u[j]) should be kept positive; if the result of
788 // this step is actually negative, (u[j+n]...u[j]) should be left as the
789 // true value plus b**(n+1), namely as the b's complement of
790 // the true value, and a "borrow" to the left should be remembered.
791 //
792 if (isNeg) {
793 bool carry = true; // true because b's complement is "complement + 1"
794 for (uint32_t i = 0; i <= m + n; ++i) {
795 u[i] = ~u[i] + carry; // b's complement
796 carry = carry && u[i] == 0;
797 }
798 }
799 /*DEBUG(cerr << "KnuthDiv: after complement:");
800 DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]);
801 DEBUG(cerr << '\n');*/
802
803 // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was
804 // negative, go to step D6; otherwise go on to step D7.
805 q[j] = (uint32_t)qp;
806 if (isNeg) {
807 // D6. [Add back]. The probability that this step is necessary is very
808 // small, on the order of only 2/b. Make sure that test data accounts for
809 // this possibility. Decrease q[j] by 1
810 q[j]--;
811 // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]).
812 // A carry will occur to the left of u[j+n], and it should be ignored
813 // since it cancels with the borrow that occurred in D4.
814 bool carry = false;
815 for (uint32_t i = 0; i < n; i++) {
816 uint32_t limit = AESL_std::min(u[j + i], v[i]);
817 u[j + i] += v[i] + carry;
818 carry = u[j + i] < limit || (carry && u[j + i] == limit);
819 }
820 u[j + n] += carry;
821 }
822 /*DEBUG(cerr << "KnuthDiv: after correction:");
823 DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]);
824 DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/
825
826 // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3.
827 } while (--j >= 0);
828
829 /*DEBUG(cerr << "KnuthDiv: quotient:");
830 DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]);
831 DEBUG(cerr << '\n');*/
832
833 // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired
834 // remainder may be obtained by dividing u[...] by d. If r is non-null we
835 // compute the remainder (urem uses this).
836 if (r) {
837 // The value d is expressed by the "shift" value above since we avoided
838 // multiplication by d by using a shift left. So, all we have to do is
839 // shift right here. In order to mak
840 if (shift) {
841 uint32_t carry = 0;
842 // DEBUG(cerr << "KnuthDiv: remainder:");
843 for (int i = n - 1; i >= 0; i--) {
844 r[i] = ((u[i]) >> (shift)) | carry;
845 carry = (u[i]) << (32 - shift);
846 // DEBUG(cerr << " " << r[i]);
847 }
848 } else {
849 for (int i = n - 1; i >= 0; i--) {
850 r[i] = u[i];
851 // DEBUG(cerr << " " << r[i]);
852 }
853 }
854 // DEBUG(cerr << '\n');
855 }
856 // DEBUG(cerr << std::setbase(10) << '\n');
857}
858
859template <int _AP_W, bool _AP_S>
860void divide(const ap_private<_AP_W, _AP_S>& LHS, uint32_t lhsWords,
861 const ap_private<_AP_W, _AP_S>& RHS, uint32_t rhsWords,
862 ap_private<_AP_W, _AP_S>* Quotient,
863 ap_private<_AP_W, _AP_S>* Remainder) {
864 assert(lhsWords >= rhsWords && "Fractional result");
865 enum { APINT_BITS_PER_WORD = 64 };
866 // First, compose the values into an array of 32-bit words instead of
867 // 64-bit words. This is a necessity of both the "short division" algorithm
868 // and the the Knuth "classical algorithm" which requires there to be native
869 // operations for +, -, and * on an m bit value with an m*2 bit result. We
870 // can't use 64-bit operands here because we don't have native results of
871 // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't
872 // work on large-endian machines.
873 uint64_t mask = ~0ull >> (sizeof(uint32_t) * 8);
874 uint32_t n = rhsWords * 2;
875 uint32_t m = (lhsWords * 2) - n;
876
877 // Allocate space for the temporary values we need either on the stack, if
878 // it will fit, or on the heap if it won't.
879 uint32_t SPACE[128];
880 uint32_t* __U = 0;
881 uint32_t* __V = 0;
882 uint32_t* __Q = 0;
883 uint32_t* __R = 0;
884 if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) {
885 __U = &SPACE[0];
886 __V = &SPACE[m + n + 1];
887 __Q = &SPACE[(m + n + 1) + n];
888 if (Remainder) __R = &SPACE[(m + n + 1) + n + (m + n)];
889 } else {
890 __U = new uint32_t[m + n + 1];
891 __V = new uint32_t[n];
892 __Q = new uint32_t[m + n];
893 if (Remainder) __R = new uint32_t[n];
894 }
895
896 // Initialize the dividend
897 memset(__U, 0, (m + n + 1) * sizeof(uint32_t));
898 for (unsigned i = 0; i < lhsWords; ++i) {
899 uint64_t tmp = LHS.get_pVal(i);
900 __U[i * 2] = (uint32_t)(tmp & mask);
901 __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t) * 8);
902 }
903 __U[m + n] = 0; // this extra word is for "spill" in the Knuth algorithm.
904
905 // Initialize the divisor
906 memset(__V, 0, (n) * sizeof(uint32_t));
907 for (unsigned i = 0; i < rhsWords; ++i) {
908 uint64_t tmp = RHS.get_pVal(i);
909 __V[i * 2] = (uint32_t)(tmp & mask);
910 __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t) * 8);
911 }
912
913 // initialize the quotient and remainder
914 memset(__Q, 0, (m + n) * sizeof(uint32_t));
915 if (Remainder) memset(__R, 0, n * sizeof(uint32_t));
916
917 // Now, adjust m and n for the Knuth division. n is the number of words in
918 // the divisor. m is the number of words by which the dividend exceeds the
919 // divisor (i.e. m+n is the length of the dividend). These sizes must not
920 // contain any zero words or the Knuth algorithm fails.
921 for (unsigned i = n; i > 0 && __V[i - 1] == 0; i--) {
922 n--;
923 m++;
924 }
925 for (unsigned i = m + n; i > 0 && __U[i - 1] == 0; i--) m--;
926
927 // If we're left with only a single word for the divisor, Knuth doesn't work
928 // so we implement the short division algorithm here. This is much simpler
929 // and faster because we are certain that we can divide a 64-bit quantity
930 // by a 32-bit quantity at hardware speed and short division is simply a
931 // series of such operations. This is just like doing short division but we
932 // are using base 2^32 instead of base 10.
933 assert(n != 0 && "Divide by zero?");
934 if (n == 1) {
935 uint32_t divisor = __V[0];
936 uint32_t remainder = 0;
937 for (int i = m + n - 1; i >= 0; i--) {
938 uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i];
939 if (partial_dividend == 0) {
940 __Q[i] = 0;
941 remainder = 0;
942 } else if (partial_dividend < divisor) {
943 __Q[i] = 0;
944 remainder = (uint32_t)partial_dividend;
945 } else if (partial_dividend == divisor) {
946 __Q[i] = 1;
947 remainder = 0;
948 } else {
949 __Q[i] = (uint32_t)(partial_dividend / divisor);
950 remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor));
951 }
952 }
953 if (__R) __R[0] = remainder;
954 } else {
955 // Now we're ready to invoke the Knuth classical divide algorithm. In this
956 // case n > 1.
957 KnuthDiv(__U, __V, __Q, __R, m, n);
958 }
959
960 // If the caller wants the quotient
961 if (Quotient) {
962 // Set up the Quotient value's memory.
963 if (Quotient->BitWidth != LHS.BitWidth) {
964 if (Quotient->isSingleWord()) Quotient->set_VAL(0);
965 } else
966 Quotient->clear();
967
968 // The quotient is in Q. Reconstitute the quotient into Quotient's low
969 // order words.
970 if (lhsWords == 1) {
971 uint64_t tmp =
972 uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2));
973 Quotient->set_VAL(tmp);
974 } else {
975 assert(!Quotient->isSingleWord() &&
976 "Quotient ap_private not large enough");
977 for (unsigned i = 0; i < lhsWords; ++i)
978 Quotient->set_pVal(
979 i, uint64_t(__Q[i * 2]) |
980 ((uint64_t(__Q[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2)));
981 }
982 Quotient->clearUnusedBits();
983 }
984
985 // If the caller wants the remainder
986 if (Remainder) {
987 // Set up the Remainder value's memory.
988 if (Remainder->BitWidth != RHS.BitWidth) {
989 if (Remainder->isSingleWord()) Remainder->set_VAL(0);
990 } else
991 Remainder->clear();
992
993 // The remainder is in R. Reconstitute the remainder into Remainder's low
994 // order words.
995 if (rhsWords == 1) {
996 uint64_t tmp =
997 uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2));
998 Remainder->set_VAL(tmp);
999 } else {
1000 assert(!Remainder->isSingleWord() &&
1001 "Remainder ap_private not large enough");
1002 for (unsigned i = 0; i < rhsWords; ++i)
1003 Remainder->set_pVal(
1004 i, uint64_t(__R[i * 2]) |
1005 ((uint64_t(__R[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2)));
1006 }
1007 Remainder->clearUnusedBits();
1008 }
1009
1010 // Clean up the memory we allocated.
1011 if (__U != &SPACE[0]) {
1012 delete[] __U;
1013 delete[] __V;
1014 delete[] __Q;
1015 delete[] __R;
1016 }
1017}
1018
1019template <int _AP_W, bool _AP_S>
1020void divide(const ap_private<_AP_W, _AP_S>& LHS, uint32_t lhsWords,
1021 uint64_t RHS, ap_private<_AP_W, _AP_S>* Quotient,
1022 ap_private<_AP_W, _AP_S>* Remainder) {
1023 uint32_t rhsWords = 1;
1024 assert(lhsWords >= rhsWords && "Fractional result");
1025 enum { APINT_BITS_PER_WORD = 64 };
1026 // First, compose the values into an array of 32-bit words instead of
1027 // 64-bit words. This is a necessity of both the "short division" algorithm
1028 // and the the Knuth "classical algorithm" which requires there to be native
1029 // operations for +, -, and * on an m bit value with an m*2 bit result. We
1030 // can't use 64-bit operands here because we don't have native results of
1031 // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't
1032 // work on large-endian machines.
1033 uint64_t mask = ~0ull >> (sizeof(uint32_t) * 8);
1034 uint32_t n = 2;
1035 uint32_t m = (lhsWords * 2) - n;
1036
1037 // Allocate space for the temporary values we need either on the stack, if
1038 // it will fit, or on the heap if it won't.
1039 uint32_t SPACE[128];
1040 uint32_t* __U = 0;
1041 uint32_t* __V = 0;
1042 uint32_t* __Q = 0;
1043 uint32_t* __R = 0;
1044 if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) {
1045 __U = &SPACE[0];
1046 __V = &SPACE[m + n + 1];
1047 __Q = &SPACE[(m + n + 1) + n];
1048 if (Remainder) __R = &SPACE[(m + n + 1) + n + (m + n)];
1049 } else {
1050 __U = new uint32_t[m + n + 1];
1051 __V = new uint32_t[n];
1052 __Q = new uint32_t[m + n];
1053 if (Remainder) __R = new uint32_t[n];
1054 }
1055
1056 // Initialize the dividend
1057 memset(__U, 0, (m + n + 1) * sizeof(uint32_t));
1058 for (unsigned i = 0; i < lhsWords; ++i) {
1059 uint64_t tmp = LHS.get_pVal(i);
1060 __U[i * 2] = tmp & mask;
1061 __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t) * 8);
1062 }
1063 __U[m + n] = 0; // this extra word is for "spill" in the Knuth algorithm.
1064
1065 // Initialize the divisor
1066 memset(__V, 0, (n) * sizeof(uint32_t));
1067 __V[0] = RHS & mask;
1068 __V[1] = (RHS) >> (sizeof(uint32_t) * 8);
1069
1070 // initialize the quotient and remainder
1071 memset(__Q, 0, (m + n) * sizeof(uint32_t));
1072 if (Remainder) memset(__R, 0, n * sizeof(uint32_t));
1073
1074 // Now, adjust m and n for the Knuth division. n is the number of words in
1075 // the divisor. m is the number of words by which the dividend exceeds the
1076 // divisor (i.e. m+n is the length of the dividend). These sizes must not
1077 // contain any zero words or the Knuth algorithm fails.
1078 for (unsigned i = n; i > 0 && __V[i - 1] == 0; i--) {
1079 n--;
1080 m++;
1081 }
1082 for (unsigned i = m + n; i > 0 && __U[i - 1] == 0; i--) m--;
1083
1084 // If we're left with only a single word for the divisor, Knuth doesn't work
1085 // so we implement the short division algorithm here. This is much simpler
1086 // and faster because we are certain that we can divide a 64-bit quantity
1087 // by a 32-bit quantity at hardware speed and short division is simply a
1088 // series of such operations. This is just like doing short division but we
1089 // are using base 2^32 instead of base 10.
1090 assert(n != 0 && "Divide by zero?");
1091 if (n == 1) {
1092 uint32_t divisor = __V[0];
1093 uint32_t remainder = 0;
1094 for (int i = m + n - 1; i >= 0; i--) {
1095 uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i];
1096 if (partial_dividend == 0) {
1097 __Q[i] = 0;
1098 remainder = 0;
1099 } else if (partial_dividend < divisor) {
1100 __Q[i] = 0;
1101 remainder = partial_dividend;
1102 } else if (partial_dividend == divisor) {
1103 __Q[i] = 1;
1104 remainder = 0;
1105 } else {
1106 __Q[i] = partial_dividend / divisor;
1107 remainder = partial_dividend - (__Q[i] * divisor);
1108 }
1109 }
1110 if (__R) __R[0] = remainder;
1111 } else {
1112 // Now we're ready to invoke the Knuth classical divide algorithm. In this
1113 // case n > 1.
1114 KnuthDiv(__U, __V, __Q, __R, m, n);
1115 }
1116
1117 // If the caller wants the quotient
1118 if (Quotient) {
1119 // Set up the Quotient value's memory.
1120 if (Quotient->BitWidth != LHS.BitWidth) {
1121 if (Quotient->isSingleWord()) Quotient->set_VAL(0);
1122 } else
1123 Quotient->clear();
1124
1125 // The quotient is in Q. Reconstitute the quotient into Quotient's low
1126 // order words.
1127 if (lhsWords == 1) {
1128 uint64_t tmp =
1129 uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2));
1130 Quotient->set_VAL(tmp);
1131 } else {
1132 assert(!Quotient->isSingleWord() &&
1133 "Quotient ap_private not large enough");
1134 for (unsigned i = 0; i < lhsWords; ++i)
1135 Quotient->set_pVal(
1136 i, uint64_t(__Q[i * 2]) |
1137 ((uint64_t(__Q[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2)));
1138 }
1139 Quotient->clearUnusedBits();
1140 }
1141
1142 // If the caller wants the remainder
1143 if (Remainder) {
1144 // Set up the Remainder value's memory.
1145 if (Remainder->BitWidth != 64 /* RHS.BitWidth */) {
1146 if (Remainder->isSingleWord()) Remainder->set_VAL(0);
1147 } else
1148 Remainder->clear();
1149
1150 // The remainder is in __R. Reconstitute the remainder into Remainder's low
1151 // order words.
1152 if (rhsWords == 1) {
1153 uint64_t tmp =
1154 uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2));
1155 Remainder->set_VAL(tmp);
1156 } else {
1157 assert(!Remainder->isSingleWord() &&
1158 "Remainder ap_private not large enough");
1159 for (unsigned i = 0; i < rhsWords; ++i)
1160 Remainder->set_pVal(
1161 i, uint64_t(__R[i * 2]) |
1162 ((uint64_t(__R[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2)));
1163 }
1164 Remainder->clearUnusedBits();
1165 }
1166
1167 // Clean up the memory we allocated.
1168 if (__U != &SPACE[0]) {
1169 delete[] __U;
1170 delete[] __V;
1171 delete[] __Q;
1172 delete[] __R;
1173 }
1174}
1175
1177template <int _AP_W, bool _AP_S, bool _AP_C>
1178INLINE ap_private<_AP_W, _AP_S, _AP_C> lshr(
1179 const ap_private<_AP_W, _AP_S, _AP_C>& LHS, uint32_t shiftAmt) {
1180 return LHS.lshr(shiftAmt);
1181}
1182
1185template <int _AP_W, bool _AP_S, bool _AP_C>
1186INLINE ap_private<_AP_W, _AP_S, _AP_C> shl(
1187 const ap_private<_AP_W, _AP_S, _AP_C>& LHS, uint32_t shiftAmt) {
1188 return LHS.shl(shiftAmt);
1189}
1190
1191} // namespace ap_private_ops
1192
1193#endif // LLVM_SUPPORT_MATHEXTRAS_H
1194
1197enum {
1198 MIN_INT_BITS = 1,
1200 MAX_INT_BITS =
1201 (1 << 23) - 1
1203};
1204
1205//===----------------------------------------------------------------------===//
1206// ap_private Class
1207//===----------------------------------------------------------------------===//
1208
1238
1239#if defined(_MSC_VER)
1240#if _MSC_VER < 1400 && !defined(for)
1241#define for \
1242 if (0) \
1243 ; \
1244 else for
1245#endif
1246typedef unsigned __int64 ap_ulong;
1247typedef signed __int64 ap_slong;
1248#else
1249typedef unsigned long long ap_ulong;
1250typedef signed long long ap_slong;
1251#endif
1252template <int _AP_N8, bool _AP_S>
1253struct valtype;
1254
1255template <int _AP_N8>
1256struct valtype<_AP_N8, false> {
1257 typedef uint64_t Type;
1258};
1259
1260template <int _AP_N8>
1261struct valtype<_AP_N8, true> {
1262 typedef int64_t Type;
1263};
1264
1265template <>
1266struct valtype<1, false> {
1267 typedef unsigned char Type;
1268};
1269template <>
1270struct valtype<2, false> {
1271 typedef unsigned short Type;
1272};
1273template <>
1274struct valtype<3, false> {
1275 typedef unsigned int Type;
1276};
1277template <>
1278struct valtype<4, false> {
1279 typedef unsigned int Type;
1280};
1281template <>
1282struct valtype<1, true> {
1283 typedef signed char Type;
1284};
1285template <>
1286struct valtype<2, true> {
1287 typedef short Type;
1288};
1289template <>
1290struct valtype<3, true> {
1291 typedef int Type;
1292};
1293template <>
1294struct valtype<4, true> {
1295 typedef int Type;
1296};
1297
1298template <bool enable>
1300template <>
1302 static const bool isValid = true;
1303};
1304
1305// When bitwidth < 64
1306template <int _AP_W, bool _AP_S>
1307class ap_private<_AP_W, _AP_S, true> {
1308 // SFINAE pattern. Only consider this class when _AP_W <= 64
1309 const static bool valid = ap_private_enable_if<_AP_W <= 64>::isValid;
1310
1311#ifdef _MSC_VER
1312#pragma warning(disable : 4521 4522)
1313#endif
1314 public:
1315 typedef typename valtype<(_AP_W + 7) / 8, _AP_S>::Type ValType;
1316 typedef ap_private<_AP_W, _AP_S> Type;
1317 template <int _AP_W2, bool _AP_S2>
1318 struct RType {
1319 enum {
1320 mult_w = _AP_W + _AP_W2,
1321 mult_s = _AP_S || _AP_S2,
1322 plus_w =
1323 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
1324 plus_s = _AP_S || _AP_S2,
1325 minus_w =
1326 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
1327 minus_s = true,
1328 div_w = _AP_W + _AP_S2,
1329 div_s = _AP_S || _AP_S2,
1330 mod_w = AP_MIN(_AP_W, _AP_W2 + (!_AP_S2 && _AP_S)),
1331 mod_s = _AP_S,
1332 logic_w = AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)),
1333 logic_s = _AP_S || _AP_S2
1334 };
1335 typedef ap_private<mult_w, mult_s> mult;
1336 typedef ap_private<plus_w, plus_s> plus;
1337 typedef ap_private<minus_w, minus_s> minus;
1338 typedef ap_private<logic_w, logic_s> logic;
1339 typedef ap_private<div_w, div_s> div;
1340 typedef ap_private<mod_w, mod_s> mod;
1341 typedef ap_private<_AP_W, _AP_S> arg1;
1342 typedef bool reduce;
1343 };
1344 enum { APINT_BITS_PER_WORD = sizeof(uint64_t) * 8 };
1345 enum {
1346 excess_bits = (_AP_W % APINT_BITS_PER_WORD)
1347 ? APINT_BITS_PER_WORD - (_AP_W % APINT_BITS_PER_WORD)
1348 : 0
1349 };
1350 static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits));
1351 static const uint64_t not_mask = ~mask;
1352 static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD - 1);
1353 template <int _AP_W1>
1354 struct sign_ext_mask {
1355 static const uint64_t mask = ~0ULL << _AP_W1;
1356 };
1357 static const int width = _AP_W;
1358
1359 enum {
1360 BitWidth = _AP_W,
1361 _AP_N = 1,
1362 };
1363 ValType VAL;
1364#ifdef AP_CANARY
1365 ValType CANARY;
1366 void check_canary() { assert(CANARY == (ValType)0xDEADBEEFDEADBEEF); }
1367 void set_canary() { CANARY = (ValType)0xDEADBEEFDEADBEEF; }
1368#else
1369 void check_canary() {}
1370 void set_canary() {}
1371#endif
1372
1373 INLINE ValType& get_VAL(void) { return VAL; }
1374 INLINE ValType get_VAL(void) const { return VAL; }
1375 INLINE ValType get_VAL(void) const volatile { return VAL; }
1376 INLINE void set_VAL(uint64_t value) { VAL = (ValType)value; }
1377 INLINE ValType& get_pVal(int i) { return VAL; }
1378 INLINE ValType get_pVal(int i) const { return VAL; }
1379 INLINE const uint64_t* get_pVal() const {
1380 assert(0 && "invalid usage");
1381 return 0;
1382 }
1383 INLINE ValType get_pVal(int i) const volatile { return VAL; }
1384 INLINE uint64_t* get_pVal() const volatile {
1385 assert(0 && "invalid usage");
1386 return 0;
1387 }
1388 INLINE void set_pVal(int i, uint64_t value) { VAL = (ValType)value; }
1389
1390 INLINE uint32_t getBitWidth() const { return BitWidth; }
1391
1392 template <int _AP_W1, bool _AP_S1>
1393 ap_private<_AP_W, _AP_S>& operator=(const ap_private<_AP_W1, _AP_S1>& RHS) {
1394 VAL = (ValType)(RHS.get_VAL());
1395 clearUnusedBits();
1396 return *this;
1397 }
1398
1399 template <int _AP_W1, bool _AP_S1>
1400 ap_private<_AP_W, _AP_S>& operator=(
1401 const volatile ap_private<_AP_W1, _AP_S1>& RHS) {
1402 VAL = (ValType)(RHS.get_VAL()); // TODO check here about
1403 // ap_private<W,S,false>
1404 clearUnusedBits();
1405 return *this;
1406 }
1407
1408 void operator=(const ap_private& RHS) volatile {
1409 // Don't do anything for X = X
1410 VAL = RHS.get_VAL(); // No need to check because no harm done by copying.
1411 clearUnusedBits();
1412 }
1413
1414 ap_private& operator=(const ap_private& RHS) {
1415 // Don't do anything for X = X
1416 VAL = RHS.get_VAL(); // No need to check because no harm done by copying.
1417 clearUnusedBits();
1418 return *this;
1419 }
1420
1421 void operator=(const volatile ap_private& RHS) volatile {
1422 // Don't do anything for X = X
1423 VAL = RHS.get_VAL(); // No need to check because no harm done by copying.
1424 clearUnusedBits();
1425 }
1426
1427 ap_private& operator=(const volatile ap_private& RHS) {
1428 // Don't do anything for X = X
1429 VAL = RHS.get_VAL(); // No need to check because no harm done by copying.
1430 clearUnusedBits();
1431 return *this;
1432 }
1433
1434 template <int _AP_W2, bool _AP_S2>
1435 INLINE ap_private& operator=(const _private_range_ref<_AP_W2, _AP_S2>& op2) {
1436 *this = ap_private<_AP_W2, false>(op2);
1437 return *this;
1438 }
1439
1440#define ASSIGN_OP_FROM_INT(C_TYPE) \
1441 INLINE ap_private& operator=(const C_TYPE v) { \
1442 set_canary(); \
1443 this->VAL = (ValType)v; \
1444 clearUnusedBits(); \
1445 check_canary(); \
1446 return *this; \
1447 }
1448
1449 ASSIGN_OP_FROM_INT(bool)
1450 ASSIGN_OP_FROM_INT(char)
1451 ASSIGN_OP_FROM_INT(signed char)
1452 ASSIGN_OP_FROM_INT(unsigned char)
1453 ASSIGN_OP_FROM_INT(short)
1454 ASSIGN_OP_FROM_INT(unsigned short)
1455 ASSIGN_OP_FROM_INT(int)
1456 ASSIGN_OP_FROM_INT(unsigned int)
1457 ASSIGN_OP_FROM_INT(long)
1458 ASSIGN_OP_FROM_INT(unsigned long)
1459 ASSIGN_OP_FROM_INT(ap_slong)
1460 ASSIGN_OP_FROM_INT(ap_ulong)
1461#if 0
1462ASSIGN_OP_FROM_INT(half)
1463ASSIGN_OP_FROM_INT(float)
1464ASSIGN_OP_FROM_INT(double)
1465#endif
1466#undef ASSIGN_OP_FROM_INT
1467
1468 // XXX This is a must to prevent pointer being converted to bool.
1469 INLINE ap_private& operator=(const char* s) {
1470 ap_private tmp(s); // XXX direct-initialization, as ctor is explicit.
1471 operator=(tmp);
1472 return *this;
1473 }
1474
1475 private:
1476 explicit INLINE ap_private(uint64_t* val) : VAL(val[0]) {
1477 set_canary();
1478 clearUnusedBits();
1479 check_canary();
1480 }
1481
1482 INLINE bool isSingleWord() const { return true; }
1483
1484 public:
1485 INLINE void fromString(const char* strStart, uint32_t slen, uint8_t radix) {
1486 bool isNeg = strStart[0] == '-';
1487 if (isNeg) {
1488 strStart++;
1489 slen--;
1490 }
1491
1492 if (strStart[0] == '0' && (strStart[1] == 'b' || strStart[1] == 'B')) {
1493 // if(radix == 0) radix = 2;
1494 _AP_WARNING(radix != 2, "%s seems to have base %d, but %d given.",
1495 strStart, 2, radix);
1496 strStart += 2;
1497 slen -= 2;
1498 } else if (strStart[0] == '0' &&
1499 (strStart[1] == 'o' || strStart[1] == 'O')) {
1500 // if (radix == 0) radix = 8;
1501 _AP_WARNING(radix != 8, "%s seems to have base %d, but %d given.",
1502 strStart, 8, radix);
1503 strStart += 2;
1504 slen -= 2;
1505 } else if (strStart[0] == '0' &&
1506 (strStart[1] == 'x' || strStart[1] == 'X')) {
1507 // if (radix == 0) radix = 16;
1508 _AP_WARNING(radix != 16, "%s seems to have base %d, but %d given.",
1509 strStart, 16, radix);
1510 strStart += 2;
1511 slen -= 2;
1512 } else if (strStart[0] == '0' &&
1513 (strStart[1] == 'd' || strStart[1] == 'D')) {
1514 // if (radix == 0) radix = 10;
1515 _AP_WARNING(radix != 10, "%s seems to have base %d, but %d given.",
1516 strStart, 10, radix);
1517 strStart += 2;
1518 slen -= 2;
1519 } else if (radix == 0) {
1520 // radix = 2; // XXX default value
1521 }
1522
1523 // Check our assumptions here
1524 assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
1525 "Radix should be 2, 8, 10, or 16!");
1526 assert(strStart && "String is null?");
1527
1528 // Clear bits.
1529 uint64_t tmpVAL = VAL = 0;
1530
1531 switch (radix) {
1532 case 2:
1533 // sscanf(strStart,"%b",&VAL);
1534 // tmpVAL = *strStart =='1' ? ~0ULL : 0;
1535 for (; *strStart; ++strStart) {
1536 assert((*strStart == '0' || *strStart == '1') &&
1537 ("Wrong binary number"));
1538 tmpVAL <<= 1;
1539 tmpVAL |= (*strStart - '0');
1540 }
1541 break;
1542 case 8:
1543#ifdef _MSC_VER
1544 sscanf_s(strStart, "%llo", &tmpVAL, slen + 1);
1545#else
1546#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__)
1547 sscanf(strStart, "%lo", &tmpVAL);
1548#else
1549 sscanf(strStart, "%llo", &tmpVAL);
1550#endif //__x86_64__
1551#endif //_MSC_VER
1552 break;
1553 case 10:
1554#ifdef _MSC_VER
1555 sscanf_s(strStart, "%llu", &tmpVAL, slen + 1);
1556#else
1557#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__)
1558 sscanf(strStart, "%lu", &tmpVAL);
1559#else
1560 sscanf(strStart, "%llu", &tmpVAL);
1561#endif //__x86_64__
1562#endif //_MSC_VER
1563 break;
1564 case 16:
1565#ifdef _MSC_VER
1566 sscanf_s(strStart, "%llx", &tmpVAL, slen + 1);
1567#else
1568#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__)
1569 sscanf(strStart, "%lx", &tmpVAL);
1570#else
1571 sscanf(strStart, "%llx", &tmpVAL);
1572#endif //__x86_64__
1573#endif //_MSC_VER
1574 break;
1575 default:
1576 assert(true && "Unknown radix");
1577 // error
1578 }
1579 VAL = isNeg ? (ValType)(-tmpVAL) : (ValType)(tmpVAL);
1580
1581 clearUnusedBits();
1582 }
1583
1584 private:
1585 INLINE ap_private(const std::string& val, uint8_t radix = 2) : VAL(0) {
1586 assert(!val.empty() && "String empty?");
1587 set_canary();
1588 fromString(val.c_str(), val.size(), radix);
1589 check_canary();
1590 }
1591
1592 INLINE ap_private(const char strStart[], uint32_t slen, uint8_t radix)
1593 : VAL(0) {
1594 set_canary();
1595 fromString(strStart, slen, radix);
1596 check_canary();
1597 }
1598
1599 INLINE ap_private(uint32_t numWords, const uint64_t bigVal[])
1600 : VAL(bigVal[0]) {
1601 set_canary();
1602 clearUnusedBits();
1603 check_canary();
1604 }
1605
1606 public:
1607 INLINE ap_private() : VAL(0) {
1608 set_canary();
1609 clearUnusedBits();
1610 check_canary();
1611 }
1612
1613#define CTOR(TYPE) \
1614 INLINE ap_private(TYPE v) : VAL((ValType)v) { \
1615 set_canary(); \
1616 clearUnusedBits(); \
1617 check_canary(); \
1618 }
1619 CTOR(bool)
1620 CTOR(char)
1621 CTOR(signed char)
1622 CTOR(unsigned char)
1623 CTOR(short)
1624 CTOR(unsigned short)
1625 CTOR(int)
1626 CTOR(unsigned int)
1627 CTOR(long)
1628 CTOR(unsigned long)
1629 CTOR(ap_slong)
1630 CTOR(ap_ulong)
1631#if 0
1632 CTOR(half)
1633 CTOR(float)
1634 CTOR(double)
1635#endif
1636#undef CTOR
1637
1638 template <int _AP_W1, bool _AP_S1, bool _AP_OPT>
1639 INLINE ap_private(const ap_private<_AP_W1, _AP_S1, _AP_OPT>& that)
1640 : VAL((ValType)that.get_VAL()) {
1641 set_canary();
1642 clearUnusedBits();
1643 check_canary();
1644 }
1645
1646 template <int _AP_W1, bool _AP_S1, bool _AP_OPT>
1647 INLINE ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_OPT>& that)
1648 : VAL((ValType)that.get_VAL()) {
1649 set_canary();
1650 clearUnusedBits();
1651 check_canary();
1652 }
1653
1654 explicit INLINE ap_private(const char* val) {
1655 set_canary();
1656 unsigned char radix = 10;
1657 std::string str =
1658 ap_private_ops::parseString(val, radix); // will set radix.
1659 std::string::size_type pos = str.find('.');
1660 // trunc all fraction part
1661 if (pos != std::string::npos) str = str.substr(pos);
1662
1663 ap_private<_AP_W, _AP_S> ap_private_val(str, radix);
1664 operator=(ap_private_val);
1665 check_canary();
1666 }
1667
1668 INLINE ap_private(const char* val, signed char rd) {
1669 set_canary();
1670 unsigned char radix = rd;
1671 std::string str =
1672 ap_private_ops::parseString(val, radix); // will set radix.
1673 std::string::size_type pos = str.find('.');
1674 // trunc all fraction part
1675 if (pos != std::string::npos) str = str.substr(pos);
1676
1677 ap_private<_AP_W, _AP_S> ap_private_val(str, radix);
1678 operator=(ap_private_val);
1679 check_canary();
1680 }
1681
1682 INLINE ~ap_private() { check_canary(); }
1683
1684 INLINE bool isNegative() const {
1685 static const uint64_t sign_mask = 1ULL << (_AP_W - 1);
1686 return _AP_S && (sign_mask & VAL);
1687 }
1688
1689 INLINE bool isPositive() const { return !isNegative(); }
1690
1691 INLINE bool isStrictlyPositive() const { return !isNegative() && VAL != 0; }
1692
1693 INLINE bool isAllOnesValue() const { return (mask & VAL) == mask; }
1694
1695 INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const {
1696 return VAL == RHS.get_VAL();
1697 }
1698 INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const {
1699 return (uint64_t)VAL == (uint64_t)RHS.get_VAL();
1700 }
1701
1702 INLINE bool operator==(uint64_t Val) const { return ((uint64_t)VAL == Val); }
1703 INLINE bool operator!=(uint64_t Val) const { return ((uint64_t)VAL != Val); }
1704 INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const {
1705 return VAL != RHS.get_VAL();
1706 }
1707 INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const {
1708 return (uint64_t)VAL != (uint64_t)RHS.get_VAL();
1709 }
1710
1712 const ap_private operator++(int) {
1713 ap_private orig(*this);
1714 VAL++;
1715 clearUnusedBits();
1716 return orig;
1717 }
1718
1720 const ap_private operator++() {
1721 ++VAL;
1722 clearUnusedBits();
1723 return *this;
1724 }
1725
1727 const ap_private operator--(int) {
1728 ap_private orig(*this);
1729 --VAL;
1730 clearUnusedBits();
1731 return orig;
1732 }
1733
1735 const ap_private operator--() {
1736 --VAL;
1737 clearUnusedBits();
1738 return *this;
1739 }
1740
1742 INLINE ap_private<_AP_W + !_AP_S, true> operator~() const {
1743 ap_private<_AP_W + !_AP_S, true> Result(*this);
1744 Result.flip();
1745 return Result;
1746 }
1747
1749 INLINE typename RType<1, false>::minus operator-() const {
1750 return ap_private<1, false>(0) - (*this);
1751 }
1752
1754 INLINE bool operator!() const { return !VAL; }
1755
1756 INLINE std::string toString(uint8_t radix, bool wantSigned) const;
1757 INLINE std::string toStringUnsigned(uint8_t radix = 10) const {
1758 return toString(radix, false);
1759 }
1760 INLINE std::string toStringSigned(uint8_t radix = 10) const {
1761 return toString(radix, true);
1762 }
1763 INLINE void clear() { VAL = 0; }
1764 INLINE ap_private& clear(uint32_t bitPosition) {
1765 VAL &= ~(1ULL << (bitPosition));
1766 clearUnusedBits();
1767 return *this;
1768 }
1769
1770 INLINE ap_private ashr(uint32_t shiftAmt) const {
1771 if (_AP_S)
1772 return ap_private((shiftAmt == BitWidth) ? 0
1773 : ((int64_t)VAL) >> (shiftAmt));
1774 else
1775 return ap_private((shiftAmt == BitWidth) ? 0
1776 : ((uint64_t)VAL) >> (shiftAmt));
1777 }
1778
1779 INLINE ap_private lshr(uint32_t shiftAmt) const {
1780 return ap_private((shiftAmt == BitWidth)
1781 ? ap_private(0)
1782 : ap_private((VAL & mask) >> (shiftAmt)));
1783 }
1784
1785 INLINE ap_private shl(uint32_t shiftAmt) const
1786// just for clang compiler
1787#if defined(__clang__) && !defined(__CLANG_3_1__)
1788 __attribute__((no_sanitize("undefined")))
1789#endif
1790 {
1791 if (shiftAmt > BitWidth) {
1792 if (!isNegative())
1793 return ap_private(0);
1794 else
1795 return ap_private(-1);
1796 }
1797 if (shiftAmt == BitWidth)
1798 return ap_private(0);
1799 else
1800 return ap_private((VAL) << (shiftAmt));
1801 // return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) :
1802 // ap_private(VAL << shiftAmt));
1803 }
1804
1805 INLINE int64_t getSExtValue() const { return VAL; }
1806
1807 // XXX XXX this function is used in CBE
1808 INLINE uint64_t getZExtValue() const { return VAL & mask; }
1809
1810 template <int _AP_W2, bool _AP_S2>
1811 INLINE ap_private(const _private_range_ref<_AP_W2, _AP_S2>& ref) {
1812 set_canary();
1813 *this = ref.get();
1814 check_canary();
1815 }
1816
1817 template <int _AP_W2, bool _AP_S2>
1818 INLINE ap_private(const _private_bit_ref<_AP_W2, _AP_S2>& ref) {
1819 set_canary();
1820 *this = ((uint64_t)(bool)ref);
1821 check_canary();
1822 }
1823
1824 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
1825 // INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>&
1826 // ref) {
1827 // set_canary();
1828 // *this = ref.get();
1829 // check_canary();
1830 // }
1831 //
1832 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
1833 // ap_o_mode _AP_O2, int _AP_N2>
1834 // INLINE ap_private(
1835 // const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&
1836 // val) {
1837 // set_canary();
1838 // *this = ((val.operator ap_private<_AP_W2, false>()));
1839 // check_canary();
1840 // }
1841 //
1842 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
1843 // ap_o_mode _AP_O2, int _AP_N2>
1844 // INLINE ap_private(
1845 // const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val)
1846 // {
1847 // set_canary();
1848 // *this = (uint64_t)(bool)val;
1849 // check_canary();
1850 // }
1851
1852 INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile {
1853 *this = (op2);
1854 }
1855
1856 // Explicit conversions to C interger types
1857 //-----------------------------------------------------------
1858 INLINE operator ValType() const { return get_VAL(); }
1859
1860 INLINE int to_uchar() const { return (unsigned char)get_VAL(); }
1861
1862 INLINE int to_char() const { return (signed char)get_VAL(); }
1863
1864 INLINE int to_ushort() const { return (unsigned short)get_VAL(); }
1865
1866 INLINE int to_short() const { return (short)get_VAL(); }
1867
1868 INLINE int to_int() const {
1869 // ap_private<64 /* _AP_W */, _AP_S> res(V);
1870 return (int)get_VAL();
1871 }
1872
1873 INLINE unsigned to_uint() const { return (unsigned)get_VAL(); }
1874
1875 INLINE long to_long() const { return (long)get_VAL(); }
1876
1877 INLINE unsigned long to_ulong() const { return (unsigned long)get_VAL(); }
1878
1879 INLINE ap_slong to_int64() const { return (ap_slong)get_VAL(); }
1880
1881 INLINE ap_ulong to_uint64() const { return (ap_ulong)get_VAL(); }
1882
1883 INLINE double to_double() const {
1884 if (isNegative())
1885 return roundToDouble(true);
1886 else
1887 return roundToDouble(false);
1888 }
1889
1890 INLINE unsigned length() const { return _AP_W; }
1891
1892 INLINE bool isMinValue() const { return VAL == 0; }
1893 template <int _AP_W1, bool _AP_S1>
1894 INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) {
1895 VAL = (ValType)(((uint64_t)VAL) & RHS.get_VAL());
1896 clearUnusedBits();
1897 return *this;
1898 }
1899
1900 template <int _AP_W1, bool _AP_S1>
1901 INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) {
1902 VAL = (ValType)(((uint64_t)VAL) | RHS.get_VAL());
1903 clearUnusedBits();
1904 return *this;
1905 }
1906
1907 template <int _AP_W1, bool _AP_S1>
1908 INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS) {
1909 VAL = (ValType)(((uint64_t)VAL) ^ RHS.get_VAL());
1910 clearUnusedBits();
1911 return *this;
1912 }
1913
1914 template <int _AP_W1, bool _AP_S1>
1915 INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS) {
1916 VAL = (ValType)(((uint64_t)VAL) * RHS.get_VAL());
1917 clearUnusedBits();
1918 return *this;
1919 }
1920
1921 template <int _AP_W1, bool _AP_S1>
1922 INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS) {
1923 VAL = (ValType)(((uint64_t)VAL) + RHS.get_VAL());
1924 clearUnusedBits();
1925 return *this;
1926 }
1927
1928 template <int _AP_W1, bool _AP_S1>
1929 INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS) {
1930 VAL = (ValType)(((uint64_t)VAL) - RHS.get_VAL());
1931 clearUnusedBits();
1932 return *this;
1933 }
1934
1935 template <int _AP_W1, bool _AP_S1>
1936 INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(
1937 const ap_private<_AP_W1, _AP_S1>& RHS) const {
1938 if (RType<_AP_W1, _AP_S1>::logic_w <= 64) {
1939 typename RType<_AP_W1, _AP_S1>::logic Ret(((uint64_t)VAL) &
1940 RHS.get_VAL());
1941 return Ret;
1942 } else {
1943 typename RType<_AP_W1, _AP_S1>::logic Ret = *this;
1944 return Ret & RHS;
1945 }
1946 }
1947
1948 template <int _AP_W1, bool _AP_S1>
1949 INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(
1950 const ap_private<_AP_W1, _AP_S1>& RHS) const {
1951 if (RType<_AP_W1, _AP_S1>::logic_w <= 64) {
1952 typename RType<_AP_W1, _AP_S1>::logic Ret(((uint64_t)VAL) ^
1953 RHS.get_VAL());
1954 return Ret;
1955 } else {
1956 typename RType<_AP_W1, _AP_S1>::logic Ret = *this;
1957 return Ret ^ RHS;
1958 }
1959 }
1960
1961 template <int _AP_W1, bool _AP_S1>
1962 INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(
1963 const ap_private<_AP_W1, _AP_S1>& RHS) const {
1964 if (RType<_AP_W1, _AP_S1>::logic_w <= 64) {
1965 typename RType<_AP_W1, _AP_S1>::logic Ret(((uint64_t)VAL) |
1966 RHS.get_VAL());
1967 return Ret;
1968 } else {
1969 typename RType<_AP_W1, _AP_S1>::logic Ret = *this;
1970 return Ret | RHS;
1971 }
1972 }
1973
1974 INLINE ap_private And(const ap_private& RHS) const {
1975 return ap_private(VAL & RHS.get_VAL());
1976 }
1977
1978 INLINE ap_private Or(const ap_private& RHS) const {
1979 return ap_private(VAL | RHS.get_VAL());
1980 }
1981
1982 INLINE ap_private Xor(const ap_private& RHS) const {
1983 return ap_private(VAL ^ RHS.get_VAL());
1984 }
1985#if 1
1986 template <int _AP_W1, bool _AP_S1>
1987 INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(
1988 const ap_private<_AP_W1, _AP_S1>& RHS) const {
1989 if (RType<_AP_W1, _AP_S1>::mult_w <= 64) {
1990 typename RType<_AP_W1, _AP_S1>::mult Result(((uint64_t)VAL) *
1991 RHS.get_VAL());
1992 return Result;
1993 } else {
1994 typename RType<_AP_W1, _AP_S1>::mult Result(*this);
1995 Result *= RHS;
1996 return Result;
1997 }
1998 }
1999#endif
2000 INLINE ap_private Mul(const ap_private& RHS) const {
2001 return ap_private(VAL * RHS.get_VAL());
2002 }
2003
2004 INLINE ap_private Add(const ap_private& RHS) const {
2005 return ap_private(VAL + RHS.get_VAL());
2006 }
2007
2008 INLINE ap_private Sub(const ap_private& RHS) const {
2009 return ap_private(VAL - RHS.get_VAL());
2010 }
2011
2012 INLINE ap_private& operator&=(uint64_t RHS) {
2013 VAL &= (ValType)RHS;
2014 clearUnusedBits();
2015 return *this;
2016 }
2017 INLINE ap_private& operator|=(uint64_t RHS) {
2018 VAL |= (ValType)RHS;
2019 clearUnusedBits();
2020 return *this;
2021 }
2022 INLINE ap_private& operator^=(uint64_t RHS) {
2023 VAL ^= (ValType)RHS;
2024 clearUnusedBits();
2025 return *this;
2026 }
2027 INLINE ap_private& operator*=(uint64_t RHS) {
2028 VAL *= (ValType)RHS;
2029 clearUnusedBits();
2030 return *this;
2031 }
2032 INLINE ap_private& operator+=(uint64_t RHS) {
2033 VAL += (ValType)RHS;
2034 clearUnusedBits();
2035 return *this;
2036 }
2037 INLINE ap_private& operator-=(uint64_t RHS) {
2038 VAL -= (ValType)RHS;
2039 clearUnusedBits();
2040 return *this;
2041 }
2042
2043 INLINE bool isMinSignedValue() const {
2044 static const uint64_t min_mask = ~(~0ULL << (_AP_W - 1));
2045 return BitWidth == 1 ? VAL == 1
2046 : (ap_private_ops::isNegative<_AP_W>(*this) &&
2047 ((min_mask & VAL) == 0));
2048 }
2049
2050 template <int _AP_W1, bool _AP_S1>
2051 INLINE typename RType<_AP_W1, _AP_S1>::plus operator+(
2052 const ap_private<_AP_W1, _AP_S1>& RHS) const {
2053 if (RType<_AP_W1, _AP_S1>::plus_w <= 64)
2054 return typename RType<_AP_W1, _AP_S1>::plus(
2055 RType<_AP_W1, _AP_S1>::plus_s
2056 ? int64_t(((uint64_t)VAL) + RHS.get_VAL())
2057 : uint64_t(((uint64_t)VAL) + RHS.get_VAL()));
2058 typename RType<_AP_W1, _AP_S1>::plus Result = RHS;
2059 Result += VAL;
2060 return Result;
2061 }
2062
2063 template <int _AP_W1, bool _AP_S1>
2064 INLINE typename RType<_AP_W1, _AP_S1>::minus operator-(
2065 const ap_private<_AP_W1, _AP_S1>& RHS) const {
2066 if (RType<_AP_W1, _AP_S1>::minus_w <= 64)
2067 return typename RType<_AP_W1, _AP_S1>::minus(
2068 int64_t(((uint64_t)VAL) - RHS.get_VAL()));
2069 typename RType<_AP_W1, _AP_S1>::minus Result = *this;
2070 Result -= RHS;
2071 return Result;
2072 }
2073
2074 INLINE uint32_t countPopulation() const {
2075 return ap_private_ops::CountPopulation_64(VAL);
2076 }
2077 INLINE uint32_t countLeadingZeros() const {
2078 int remainder = BitWidth % 64;
2079 int excessBits = (64 - remainder) % 64;
2080 uint32_t Count = ap_private_ops::CountLeadingZeros_64(VAL);
2081 if (Count) Count -= excessBits;
2082 return AESL_std::min(Count, (uint32_t)_AP_W);
2083 }
2084
2086 INLINE ap_private<_AP_W, _AP_S> getHiBits(uint32_t numBits) const {
2087 ap_private<_AP_W, _AP_S> ret(*this);
2088 ret = (ret) >> (BitWidth - numBits);
2089 return ret;
2090 }
2091
2093 INLINE ap_private<_AP_W, _AP_S> getLoBits(uint32_t numBits) const {
2094 ap_private<_AP_W, _AP_S> ret(((uint64_t)VAL) << (BitWidth - numBits));
2095 ret = (ret) >> (BitWidth - numBits);
2096 return ret;
2097 // return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth -
2098 // numBits));
2099 }
2100
2101 INLINE ap_private<_AP_W, _AP_S>& set(uint32_t bitPosition) {
2102 VAL |= (1ULL << (bitPosition));
2103 clearUnusedBits();
2104 return *this; // clearUnusedBits();
2105 }
2106
2107 INLINE void set() {
2108 VAL = (ValType)~0ULL;
2109 clearUnusedBits();
2110 }
2111
2112 template <int _AP_W3>
2113 INLINE void set(const ap_private<_AP_W3, false>& val) {
2114 operator=(ap_private<_AP_W3, _AP_S>(val));
2115 }
2116
2117 INLINE void set(const ap_private& val) { operator=(val); }
2118
2119 INLINE void clearUnusedBits(void) volatile
2120// just for clang compiler
2121#if defined(__clang__) && !defined(__CLANG_3_1__)
2122 __attribute__((no_sanitize("undefined")))
2123#endif
2124 {
2125 enum { excess_bits = (_AP_W % 64) ? 64 - _AP_W % 64 : 0 };
2126 VAL = (ValType)(_AP_S ? ((((int64_t)VAL) << (excess_bits)) >> (excess_bits))
2127 : (excess_bits ? (((uint64_t)VAL) << (excess_bits)) >>
2128 (excess_bits)
2129 : (uint64_t)VAL));
2130 }
2131
2132 INLINE void clearUnusedBitsToZero(void) {
2133 enum { excess_bits = (_AP_W % 64) ? 64 - _AP_W % 64 : 0 };
2134 static uint64_t mask = ~0ULL >> (excess_bits);
2135 VAL &= mask;
2136 }
2137
2138 INLINE ap_private udiv(const ap_private& RHS) const {
2139 return ap_private((uint64_t)VAL / RHS.get_VAL());
2140 }
2141
2144 INLINE ap_private sdiv(const ap_private& RHS) const {
2145 if (isNegative())
2146 if (RHS.isNegative())
2147 return ((uint64_t)(0 - (*this))) / (uint64_t)(0 - RHS);
2148 else
2149 return 0 - ((uint64_t)(0 - (*this)) / (uint64_t)(RHS));
2150 else if (RHS.isNegative())
2151 return 0 - (this->udiv((ap_private)(0 - RHS)));
2152 return this->udiv(RHS);
2153 }
2154
2155 template <bool _AP_S2>
2156 INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const {
2157 assert(RHS.get_VAL() != 0 && "Divide by 0");
2158 return ap_private(((uint64_t)VAL) % ((uint64_t)RHS.get_VAL()));
2159 }
2160
2163 template <bool _AP_S2>
2164 INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const {
2165 if (isNegative()) {
2166 ap_private lhs = 0 - (*this);
2167 if (RHS.isNegative()) {
2168 ap_private rhs = 0 - RHS;
2169 return 0 - (lhs.urem(rhs));
2170 } else
2171 return 0 - (lhs.urem(RHS));
2172 } else if (RHS.isNegative()) {
2173 ap_private rhs = 0 - RHS;
2174 return this->urem(rhs);
2175 }
2176 return this->urem(RHS);
2177 }
2178
2179 template <int _AP_W1, bool _AP_S1>
2180 INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2181 return (*this) == RHS;
2182 }
2183
2184 template <int _AP_W1, bool _AP_S1>
2185 INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2186 return !((*this) == RHS);
2187 }
2188
2193 template <int _AP_W1, bool _AP_S1>
2194 INLINE bool ult(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2195 if (_AP_W1 <= 64) {
2196 uint64_t lhsZext = ((uint64_t(VAL)) << (64 - _AP_W)) >> (64 - _AP_W);
2197 uint64_t rhsZext =
2198 ((uint64_t(RHS.get_VAL())) << (64 - _AP_W1)) >> (64 - _AP_W1);
2199 return lhsZext < rhsZext;
2200 } else
2201 return RHS.uge(*this);
2202 }
2203
2208 template <int _AP_W1, bool _AP_S1>
2209 INLINE bool slt(const ap_private<_AP_W1, _AP_S1>& RHS) const
2210// just for clang compiler
2211#if defined(__clang__) && !defined(__CLANG_3_1__)
2212 __attribute__((no_sanitize("undefined")))
2213#endif
2214 {
2215 if (_AP_W1 <= 64) {
2216 int64_t lhsSext = ((int64_t(VAL)) << (64 - _AP_W)) >> (64 - _AP_W);
2217 int64_t rhsSext =
2218 ((int64_t(RHS.get_VAL())) << (64 - _AP_W1)) >> (64 - _AP_W1);
2219 return lhsSext < rhsSext;
2220 } else
2221 return RHS.sge(*this);
2222 }
2223
2228 template <int _AP_W1, bool _AP_S1>
2229 INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2230 return ult(RHS) || eq(RHS);
2231 }
2232
2237 template <int _AP_W1, bool _AP_S1>
2238 INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2239 return slt(RHS) || eq(RHS);
2240 }
2241
2246 template <int _AP_W1, bool _AP_S1>
2247 INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2248 return !ult(RHS) && !eq(RHS);
2249 }
2250
2255 template <int _AP_W1, bool _AP_S1>
2256 INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2257 return !slt(RHS) && !eq(RHS);
2258 }
2259
2264 template <int _AP_W1, bool _AP_S1>
2265 INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2266 return !ult(RHS);
2267 }
2268
2273 template <int _AP_W1, bool _AP_S1>
2274 INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const {
2275 return !slt(RHS);
2276 }
2277
2278 INLINE ap_private abs() const {
2279 if (isNegative()) return -(*this);
2280 return *this;
2281 }
2282
2283 INLINE ap_private<_AP_W, false> get() const {
2284 ap_private<_AP_W, false> ret(*this);
2285 return ret;
2286 }
2287
2288 INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen,
2289 uint8_t radix) {
2290 return _AP_W;
2291 }
2292
2293 INLINE uint32_t getActiveBits() const {
2294 uint32_t bits = _AP_W - countLeadingZeros();
2295 return bits ? bits : 1;
2296 }
2297
2298 INLINE double roundToDouble(bool isSigned = false) const {
2299 return isSigned ? double((int64_t)VAL) : double((uint64_t)VAL);
2300 }
2301
2302 /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise
2303 * versa*/
2304 INLINE ap_private& reverse() {
2305 for (int i = 0; i < _AP_W / 2; ++i) {
2306 bool tmp = operator[](i);
2307 if (operator[](_AP_W - 1 - i))
2308 set(i);
2309 else
2310 clear(i);
2311 if (tmp)
2312 set(_AP_W - 1 - i);
2313 else
2314 clear(_AP_W - 1 - i);
2315 }
2316 clearUnusedBits();
2317 return *this;
2318 }
2319
2320 /*Return true if the value of ap_private instance is zero*/
2321 INLINE bool iszero() const { return isMinValue(); }
2322
2323 INLINE bool to_bool() const { return !iszero(); }
2324
2325 /* x < 0 */
2326 INLINE bool sign() const {
2327 if (isNegative()) return true;
2328 return false;
2329 }
2330
2331 /* x[i] = !x[i] */
2332 INLINE void invert(int i) {
2333 assert(i >= 0 && "Attempting to read bit with negative index");
2334 assert(i < _AP_W && "Attempting to read bit beyond MSB");
2335 flip(i);
2336 }
2337
2338 /* x[i] */
2339 INLINE bool test(int i) const {
2340 assert(i >= 0 && "Attempting to read bit with negative index");
2341 assert(i < _AP_W && "Attempting to read bit beyond MSB");
2342 return operator[](i);
2343 }
2344
2345 // This is used for sc_lv and sc_bv, which is implemented by sc_uint
2346 // Rotate an ap_private object n places to the left
2347 INLINE void lrotate(int n) {
2348 assert(n >= 0 && "Attempting to shift negative index");
2349 assert(n < _AP_W && "Shift value larger than bit width");
2350 operator=(shl(n) | lshr(_AP_W - n));
2351 }
2352
2353 // This is used for sc_lv and sc_bv, which is implemented by sc_uint
2354 // Rotate an ap_private object n places to the right
2355 INLINE void rrotate(int n) {
2356 assert(n >= 0 && "Attempting to shift negative index");
2357 assert(n < _AP_W && "Shift value larger than bit width");
2358 operator=(lshr(n) | shl(_AP_W - n));
2359 }
2360
2361 // Set the ith bit into v
2362 INLINE void set(int i, bool v) {
2363 assert(i >= 0 && "Attempting to write bit with negative index");
2364 assert(i < _AP_W && "Attempting to write bit beyond MSB");
2365 v ? set(i) : clear(i);
2366 }
2367
2368 // Set the ith bit into v
2369 INLINE void set_bit(int i, bool v) {
2370 assert(i >= 0 && "Attempting to write bit with negative index");
2371 assert(i < _AP_W && "Attempting to write bit beyond MSB");
2372 v ? set(i) : clear(i);
2373 }
2374
2375 // Get the value of ith bit
2376 INLINE bool get_bit(int i) const {
2377 assert(i >= 0 && "Attempting to read bit with negative index");
2378 assert(i < _AP_W && "Attempting to read bit beyond MSB");
2379 return (((1ULL << i) & VAL) != 0);
2380 }
2381
2383 INLINE ap_private& flip() {
2384 VAL = (ValType)((~0ULL ^ VAL) & mask);
2385 clearUnusedBits();
2386 return *this;
2387 }
2388
2390 INLINE ap_private& flip(uint32_t bitPosition) {
2391 assert(bitPosition < BitWidth && "Out of the bit-width range!");
2392 set_bit(bitPosition, !get_bit(bitPosition));
2393 return *this;
2394 }
2395
2396 // complements every bit
2397 INLINE void b_not() { flip(); }
2398
2399// Binary Arithmetic
2400//-----------------------------------------------------------
2401#define OP_BIN_AP(Sym, Rty, Fun) \
2402 template <int _AP_W2, bool _AP_S2> \
2403 INLINE typename RType<_AP_W2, _AP_S2>::Rty operator Sym( \
2404 const ap_private<_AP_W2, _AP_S2>& op) const { \
2405 typename RType<_AP_W2, _AP_S2>::Rty lhs(*this); \
2406 typename RType<_AP_W2, _AP_S2>::Rty rhs(op); \
2407 return lhs.Fun(rhs); \
2408 }
2409
2411// OP_BIN_AP(&,logic, And)
2412// OP_BIN_AP(|,logic, Or)
2413// OP_BIN_AP(^,logic, Xor)
2414#undef OP_BIN_AP
2415
2416 template <int _AP_W2, bool _AP_S2>
2417 INLINE typename RType<_AP_W2, _AP_S2>::div operator/(
2418 const ap_private<_AP_W2, _AP_S2>& op) const {
2419 ap_private<AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)),
2420 (_AP_W > _AP_W2 ? _AP_S
2421 : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))>
2422 lhs = *this;
2423 ap_private<AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)),
2424 (_AP_W > _AP_W2 ? _AP_S
2425 : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))>
2426 rhs = op;
2427 return typename RType<_AP_W2, _AP_S2>::div(
2428 (_AP_S || _AP_S2) ? lhs.sdiv(rhs) : lhs.udiv(rhs));
2429 }
2430
2431 template <int _AP_W2, bool _AP_S2>
2432 INLINE typename RType<_AP_W2, _AP_S2>::mod operator%(
2433 const ap_private<_AP_W2, _AP_S2>& op) const {
2434 ap_private<AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)),
2435 (_AP_W > _AP_W2 ? _AP_S
2436 : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))>
2437 lhs = *this;
2438 ap_private<AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)),
2439 (_AP_W > _AP_W2 ? _AP_S
2440 : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))>
2441 rhs = op;
2442 typename RType<_AP_W2, _AP_S2>::mod res =
2443 typename RType<_AP_W2, _AP_S2>::mod(_AP_S ? lhs.srem(rhs)
2444 : lhs.urem(rhs));
2445 return res;
2446 }
2447
2448#define OP_ASSIGN_AP_2(Sym) \
2449 template <int _AP_W2, bool _AP_S2> \
2450 INLINE ap_private<_AP_W, _AP_S>& operator Sym##=( \
2451 const ap_private<_AP_W2, _AP_S2>& op) { \
2452 *this = operator Sym(op); \
2453 return *this; \
2454 }
2455
2456 OP_ASSIGN_AP_2(/)
2457 OP_ASSIGN_AP_2(%)
2458#undef OP_ASSIGN_AP_2
2459
2461 //-------------------------------------------------------------
2462 // OP_ASSIGN_AP(&)
2463 // OP_ASSIGN_AP(^)
2464 // OP_ASSIGN_AP(|)
2465
2466#define OP_LEFT_SHIFT_CTYPE(TYPE, SIGNED) \
2467 INLINE ap_private operator<<(const TYPE op) const { \
2468 if (op >= _AP_W) return ap_private(0); \
2469 if (SIGNED && op < 0) return *this >> (0 - op); \
2470 return shl(op); \
2471 }
2472
2473 // OP_LEFT_SHIFT_CTYPE(bool, false)
2474 OP_LEFT_SHIFT_CTYPE(char, CHAR_IS_SIGNED)
2475 OP_LEFT_SHIFT_CTYPE(signed char, true)
2476 OP_LEFT_SHIFT_CTYPE(unsigned char, false)
2477 OP_LEFT_SHIFT_CTYPE(short, true)
2478 OP_LEFT_SHIFT_CTYPE(unsigned short, false)
2479 OP_LEFT_SHIFT_CTYPE(int, true)
2480 OP_LEFT_SHIFT_CTYPE(unsigned int, false)
2481 OP_LEFT_SHIFT_CTYPE(long, true)
2482 OP_LEFT_SHIFT_CTYPE(unsigned long, false)
2483 OP_LEFT_SHIFT_CTYPE(long long, true)
2484 OP_LEFT_SHIFT_CTYPE(unsigned long long, false)
2485#if 0
2486 OP_LEFT_SHIFT_CTYPE(half, false)
2487 OP_LEFT_SHIFT_CTYPE(float, false)
2488 OP_LEFT_SHIFT_CTYPE(double, false)
2489#endif
2490
2491#undef OP_LEFT_SHIFT_CTYPE
2492
2493 template <int _AP_W2, bool _AP_S2>
2494 INLINE ap_private operator<<(const ap_private<_AP_W2, _AP_S2>& op2) const {
2495 if (_AP_S2 == false) {
2496 uint32_t sh = op2.to_uint();
2497 return *this << sh;
2498 } else {
2499 int sh = op2.to_int();
2500 return *this << sh;
2501 }
2502 }
2503
2504#define OP_RIGHT_SHIFT_CTYPE(TYPE, SIGNED) \
2505 INLINE ap_private operator>>(const TYPE op) const { \
2506 if (op >= _AP_W) { \
2507 if (isNegative()) \
2508 return ap_private(-1); \
2509 else \
2510 return ap_private(0); \
2511 } \
2512 if ((SIGNED) && op < 0) return *this << (0 - op); \
2513 if (_AP_S) \
2514 return ashr(op); \
2515 else \
2516 return lshr(op); \
2517 }
2518
2519 // OP_RIGHT_SHIFT_CTYPE(bool, false)
2520 OP_RIGHT_SHIFT_CTYPE(char, CHAR_IS_SIGNED)
2521 OP_RIGHT_SHIFT_CTYPE(signed char, true)
2522 OP_RIGHT_SHIFT_CTYPE(unsigned char, false)
2523 OP_RIGHT_SHIFT_CTYPE(short, true)
2524 OP_RIGHT_SHIFT_CTYPE(unsigned short, false)
2525 OP_RIGHT_SHIFT_CTYPE(int, true)
2526 OP_RIGHT_SHIFT_CTYPE(unsigned int, false)
2527 OP_RIGHT_SHIFT_CTYPE(long, true)
2528 OP_RIGHT_SHIFT_CTYPE(unsigned long, false)
2529 OP_RIGHT_SHIFT_CTYPE(unsigned long long, false)
2530 OP_RIGHT_SHIFT_CTYPE(long long, true)
2531#if 0
2532 OP_RIGHT_SHIFT_CTYPE(half, false)
2533 OP_RIGHT_SHIFT_CTYPE(float, false)
2534 OP_RIGHT_SHIFT_CTYPE(double, false)
2535#endif
2536
2537#undef OP_RIGHT_SHIFT_CTYPE
2538
2539 template <int _AP_W2, bool _AP_S2>
2540 INLINE ap_private operator>>(const ap_private<_AP_W2, _AP_S2>& op2) const {
2541 if (_AP_S2 == false) {
2542 uint32_t sh = op2.to_uint();
2543 return *this >> sh;
2544 } else {
2545 int sh = op2.to_int();
2546 return *this >> sh;
2547 }
2548 }
2549
2551 //-----------------------------------------------------------------
2552
2553 // INLINE const ap_private& operator<<=(uint32_t shiftAmt) {
2554 // VAL <<= shiftAmt;
2555 // clearUnusedBits();
2556 // return *this;
2557 // }
2558
2559#define OP_ASSIGN_AP(Sym) \
2560 template <int _AP_W2, bool _AP_S2> \
2561 INLINE ap_private& operator Sym##=(int op) { \
2562 *this = operator Sym(op); \
2563 clearUnusedBits(); \
2564 return *this; \
2565 } \
2566 INLINE ap_private& operator Sym##=(unsigned int op) { \
2567 *this = operator Sym(op); \
2568 clearUnusedBits(); \
2569 return *this; \
2570 } \
2571 template <int _AP_W2, bool _AP_S2> \
2572 INLINE ap_private& operator Sym##=(const ap_private<_AP_W2, _AP_S2>& op) { \
2573 *this = operator Sym(op); \
2574 clearUnusedBits(); \
2575 return *this; \
2576 }
2577
2578 OP_ASSIGN_AP(>>)
2579 OP_ASSIGN_AP(<<)
2580#undef OP_ASSIGN_AP
2581
2583 //-----------------------------------------------------------------
2584 template <int _AP_W1, bool _AP_S1>
2585 INLINE bool operator==(const ap_private<_AP_W1, _AP_S1>& op) const {
2586 enum { _AP_MAX_W = AP_MAX(AP_MAX(_AP_W, _AP_W1), 32) };
2587 ap_private<_AP_MAX_W, false> lhs(*this);
2588 ap_private<_AP_MAX_W, false> rhs(op);
2589 if (_AP_MAX_W <= 64) {
2590 return (uint64_t)lhs.get_VAL() == (uint64_t)rhs.get_VAL();
2591 } else
2592 return lhs == rhs;
2593 }
2594
2595 template <int _AP_W2, bool _AP_S2>
2596 INLINE bool operator!=(const ap_private<_AP_W2, _AP_S2>& op) const {
2597 return !(*this == op);
2598 }
2599
2600 template <int _AP_W2, bool _AP_S2>
2601 INLINE bool operator>(const ap_private<_AP_W2, _AP_S2>& op) const {
2602 enum {
2603 _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2))
2604 };
2605 ap_private<_AP_MAX_W, _AP_S> lhs(*this);
2606 ap_private<_AP_MAX_W, _AP_S2> rhs(op);
2607 // this will follow gcc rule for comparison
2608 // between different bitwidth and signness
2609 if (_AP_S == _AP_S2)
2610 return _AP_S ? lhs.sgt(rhs) : lhs.ugt(rhs);
2611 else if (_AP_W < 32 && _AP_W2 < 32)
2612 // different signness but both bitwidth is less than 32
2613 return lhs.sgt(rhs);
2614 else
2615 // different signness but bigger bitwidth
2616 // is greater or equal to 32
2617 if (_AP_S)
2618 if (_AP_W2 >= _AP_W)
2619 return lhs.ugt(rhs);
2620 else
2621 return lhs.sgt(rhs);
2622 else if (_AP_W >= _AP_W2)
2623 return lhs.ugt(rhs);
2624 else
2625 return lhs.sgt(rhs);
2626 }
2627
2628 template <int _AP_W2, bool _AP_S2>
2629 INLINE bool operator<=(const ap_private<_AP_W2, _AP_S2>& op) const {
2630 return !(*this > op);
2631 }
2632
2633 template <int _AP_W2, bool _AP_S2>
2634 INLINE bool operator<(const ap_private<_AP_W2, _AP_S2>& op) const {
2635 enum {
2636 _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2))
2637 };
2638 ap_private<_AP_MAX_W, _AP_S> lhs(*this);
2639 ap_private<_AP_MAX_W, _AP_S2> rhs(op);
2640 if (_AP_S == _AP_S2)
2641 return _AP_S ? lhs.slt(rhs) : lhs.ult(rhs);
2642 else if (_AP_W < 32 && _AP_W2 < 32)
2643 return lhs.slt(rhs);
2644 else if (_AP_S)
2645 if (_AP_W2 >= _AP_W)
2646 return lhs.ult(rhs);
2647 else
2648 return lhs.slt(rhs);
2649 else if (_AP_W >= _AP_W2)
2650 return lhs.ult(rhs);
2651 else
2652 return lhs.slt(rhs);
2653 }
2654
2655 template <int _AP_W2, bool _AP_S2>
2656 INLINE bool operator>=(const ap_private<_AP_W2, _AP_S2>& op) const {
2657 return !(*this < op);
2658 }
2659
2661 //--------------------------------------------------------------
2662 // FIXME now _private_range_ref refs to _AP_ROOT_TYPE(struct ssdm_int).
2664 return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo);
2665 }
2666
2667 INLINE _private_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) const {
2669 const_cast<ap_private<_AP_W, _AP_S>*>(this), Hi, Lo);
2670 }
2671
2672 INLINE _private_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) const {
2674 (const_cast<ap_private<_AP_W, _AP_S>*>(this)), Hi, Lo);
2675 }
2676
2677 INLINE _private_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) {
2678 return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo);
2679 }
2680
2681 INLINE _private_bit_ref<_AP_W, _AP_S> operator[](int index) {
2682 return _private_bit_ref<_AP_W, _AP_S>(*this, index);
2683 }
2684
2685 template <int _AP_W2, bool _AP_S2>
2686 INLINE _private_bit_ref<_AP_W, _AP_S> operator[](
2687 const ap_private<_AP_W2, _AP_S2>& index) {
2688 return _private_bit_ref<_AP_W, _AP_S>(*this, index.to_int());
2689 }
2690
2691 INLINE const _private_bit_ref<_AP_W, _AP_S> operator[](int index) const {
2693 const_cast<ap_private<_AP_W, _AP_S>&>(*this), index);
2694 }
2695
2696 template <int _AP_W2, bool _AP_S2>
2697 INLINE const _private_bit_ref<_AP_W, _AP_S> operator[](
2698 const ap_private<_AP_W2, _AP_S2>& index) const {
2700 const_cast<ap_private<_AP_W, _AP_S>&>(*this), index.to_int());
2701 }
2702
2703 INLINE _private_bit_ref<_AP_W, _AP_S> bit(int index) {
2704 return _private_bit_ref<_AP_W, _AP_S>(*this, index);
2705 }
2706
2707 template <int _AP_W2, bool _AP_S2>
2709 const ap_private<_AP_W2, _AP_S2>& index) {
2710 return _private_bit_ref<_AP_W, _AP_S>(*this, index.to_int());
2711 }
2712
2713 INLINE const _private_bit_ref<_AP_W, _AP_S> bit(int index) const {
2715 const_cast<ap_private<_AP_W, _AP_S>&>(*this), index);
2716 }
2717
2718 template <int _AP_W2, bool _AP_S2>
2719 INLINE const _private_bit_ref<_AP_W, _AP_S> bit(
2720 const ap_private<_AP_W2, _AP_S2>& index) const {
2722 const_cast<ap_private<_AP_W, _AP_S>&>(*this), index.to_int());
2723 }
2724
2725 // template <int _AP_W2, bool _AP_S2>
2726 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
2727 // ap_private<_AP_W2, _AP_S2> >
2728 // concat(const ap_private<_AP_W2, _AP_S2>& a2) const {
2729 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
2730 // ap_private<_AP_W2, _AP_S2> >(
2731 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
2732 // const_cast<ap_private<_AP_W2, _AP_S2>&>(a2));
2733 // }
2734 //
2735 // template <int _AP_W2, bool _AP_S2>
2736 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
2737 // ap_private<_AP_W2, _AP_S2> >
2738 // concat(ap_private<_AP_W2, _AP_S2>& a2) {
2739 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
2740 // ap_private<_AP_W2, _AP_S2> >(*this, a2);
2741 // }
2742 //
2743 // template <int _AP_W2, bool _AP_S2>
2744 // INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2>
2745 // > operator,(const ap_private<_AP_W2, _AP_S2> &a2) const {
2746 // return ap_concat_ref<_AP_W, ap_private, _AP_W2,
2747 // ap_private<_AP_W2, _AP_S2> >(
2748 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
2749 // const_cast<ap_private<_AP_W2, _AP_S2>&>(a2));
2750 // }
2751 //
2752 // template <int _AP_W2, bool _AP_S2>
2753 // INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2>
2754 // > operator,(const ap_private<_AP_W2, _AP_S2> &a2) {
2755 // return ap_concat_ref<_AP_W, ap_private, _AP_W2,
2756 // ap_private<_AP_W2, _AP_S2> >(
2757 // *this, const_cast<ap_private<_AP_W2, _AP_S2>&>(a2));
2758 // }
2759 //
2760 // template <int _AP_W2, bool _AP_S2>
2761 // INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2>
2762 // > operator,(ap_private<_AP_W2, _AP_S2> &a2) const {
2763 // return ap_concat_ref<_AP_W, ap_private, _AP_W2,
2764 // ap_private<_AP_W2, _AP_S2> >(
2765 // const_cast<ap_private<_AP_W, _AP_S>&>(*this), a2);
2766 // }
2767 //
2768 // template <int _AP_W2, bool _AP_S2>
2769 // INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2>
2770 // > operator,(ap_private<_AP_W2, _AP_S2> &a2) {
2771 // return ap_concat_ref<_AP_W, ap_private, _AP_W2,
2772 // ap_private<_AP_W2, _AP_S2> >(*this, a2);
2773 // }
2774 //
2775 // template <int _AP_W2, bool _AP_S2>
2776 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
2777 // _private_range_ref<_AP_W2, _AP_S2> >
2778 // operator,(const _private_range_ref<_AP_W2, _AP_S2> &a2) const {
2779 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
2780 // _private_range_ref<_AP_W2, _AP_S2> >(
2781 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
2782 // const_cast<_private_range_ref<_AP_W2, _AP_S2>&>(a2));
2783 // }
2784 //
2785 // template <int _AP_W2, bool _AP_S2>
2786 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
2787 // _private_range_ref<_AP_W2, _AP_S2> >
2788 // operator,(_private_range_ref<_AP_W2, _AP_S2> &a2) {
2789 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
2790 // _private_range_ref<_AP_W2, _AP_S2> >(*this, a2);
2791 // }
2792 //
2793 // template <int _AP_W2, bool _AP_S2>
2794 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1,
2795 // _private_bit_ref<_AP_W2, _AP_S2> >
2796 // operator,(const _private_bit_ref<_AP_W2, _AP_S2> &a2) const {
2797 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1,
2798 // _private_bit_ref<_AP_W2, _AP_S2> >(
2799 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
2800 // const_cast<_private_bit_ref<_AP_W2, _AP_S2>&>(a2));
2801 // }
2802 //
2803 // template <int _AP_W2, bool _AP_S2>
2804 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1,
2805 // _private_bit_ref<_AP_W2, _AP_S2> >
2806 // operator,(_private_bit_ref<_AP_W2, _AP_S2> &a2) {
2807 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1,
2808 // _private_bit_ref<_AP_W2, _AP_S2> >(*this, a2);
2809 // }
2810 //
2811 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
2812 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3,
2813 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >
2814 // operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const {
2815 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3,
2816 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(
2817 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
2818 // const_cast<ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>&>(a2));
2819 // }
2820 //
2821 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
2822 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3,
2823 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >
2824 // operator,(ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) {
2825 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3,
2826 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>
2827 // >(*this,
2828 // a2);
2829 // }
2830 //
2831 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
2832 // ap_o_mode _AP_O2, int _AP_N2>
2833 // INLINE ap_concat_ref<
2834 // _AP_W, ap_private, _AP_W2,
2835 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >
2836 // operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
2837 // _AP_N2>
2838 // &a2) const {
2839 // return ap_concat_ref<
2840 // _AP_W, ap_private, _AP_W2,
2841 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(
2842 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
2843 // const_cast<
2844 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
2845 // _AP_N2>&>(a2));
2846 // }
2847 //
2848 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
2849 // ap_o_mode _AP_O2, int _AP_N2>
2850 // INLINE ap_concat_ref<
2851 // _AP_W, ap_private, _AP_W2,
2852 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >
2853 // operator,(af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>
2854 // &a2) {
2855 // return ap_concat_ref<
2856 // _AP_W, ap_private, _AP_W2,
2857 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>
2858 // >(*this,
2859 // a2);
2860 // }
2861 //
2862 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
2863 // ap_o_mode _AP_O2, int _AP_N2>
2864 // INLINE
2865 // ap_concat_ref<_AP_W, ap_private, 1,
2866 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
2867 // _AP_N2> >
2868 // operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
2869 // _AP_N2>
2870 // &a2) const {
2871 // return ap_concat_ref<
2872 // _AP_W, ap_private, 1,
2873 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(
2874 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
2875 // const_cast<af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
2876 // _AP_N2>&>(
2877 // a2));
2878 // }
2879 //
2880 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
2881 // ap_o_mode _AP_O2, int _AP_N2>
2882 // INLINE
2883 // ap_concat_ref<_AP_W, ap_private, 1,
2884 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
2885 // _AP_N2> >
2886 // operator,(
2887 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) {
2888 // return ap_concat_ref<
2889 // _AP_W, ap_private, 1,
2890 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this,
2891 // a2);
2892 // }
2893 //
2894 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
2895 // INLINE ap_private<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator&(
2896 // const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) {
2897 // return *this & a2.get();
2898 // }
2899 //
2900 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
2901 // INLINE ap_private<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator|(
2902 // const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) {
2903 // return *this | a2.get();
2904 // }
2905 //
2906 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
2907 // INLINE ap_private<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator^(
2908 // const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) {
2909 // return *this ^ a2.get();
2910 // }
2911
2912 // Reduce operation
2913 //-----------------------------------------------------------
2914 INLINE bool and_reduce() const { return (VAL & mask) == mask; }
2915
2916 INLINE bool nand_reduce() const { return (VAL & mask) != mask; }
2917
2918 INLINE bool or_reduce() const { return (bool)VAL; }
2919
2920 INLINE bool nor_reduce() const { return VAL == 0; }
2921
2922 INLINE bool xor_reduce() const {
2923 unsigned int i = countPopulation();
2924 return (i % 2) ? true : false;
2925 }
2926
2927 INLINE bool xnor_reduce() const {
2928 unsigned int i = countPopulation();
2929 return (i % 2) ? false : true;
2930 }
2931
2932 INLINE std::string to_string(uint8_t radix = 2, bool sign = false) const {
2933 return toString(radix, radix == 10 ? _AP_S : sign);
2934 }
2935}; // End of class ap_private <_AP_W, _AP_S, true>
2936
2937template <int _AP_W, bool _AP_S>
2938std::string ap_private<_AP_W, _AP_S, true>::toString(uint8_t radix,
2939 bool wantSigned) const {
2940 assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
2941 "Radix should be 2, 8, 10, or 16!");
2942 static const char* digits[] = {"0", "1", "2", "3", "4", "5", "6", "7",
2943 "8", "9", "a", "b", "c", "d", "e", "f"};
2944 std::string result;
2945 if (radix != 10) {
2946 // For the 2, 8 and 16 bit cases, we can just shift instead of divide
2947 // because the number of bits per digit (1,3 and 4 respectively) divides
2948 // equaly. We just shift until there value is zero.
2949
2950 // First, check for a zero value and just short circuit the logic below.
2951 if (*this == (uint64_t)(0)) {
2952 // Always generate a radix indicator because fixed-point
2953 // formats require it.
2954 switch (radix) {
2955 case 2:
2956 result = "0b0";
2957 break;
2958 case 8:
2959 result = "0o0";
2960 break;
2961 case 16:
2962 result = "0x0";
2963 break;
2964 default:
2965 assert("invalid radix" && 0);
2966 }
2967 } else {
2968 ap_private<_AP_W, false, true> tmp(*this);
2969 size_t insert_at = 0;
2970 bool leading_zero = true;
2971 if (wantSigned && isNegative()) {
2972 // They want to print the signed version and it is a negative value
2973 // Flip the bits and add one to turn it into the equivalent positive
2974 // value and put a '-' in the result.
2975 tmp.flip();
2976 tmp++;
2977 result = "-";
2978 insert_at = 1;
2979 leading_zero = false;
2980 }
2981 switch (radix) {
2982 case 2:
2983 result += "0b";
2984 break;
2985 case 8:
2986 result += "0o";
2987 break;
2988 case 16:
2989 result += "0x";
2990 break;
2991 default:
2992 assert("invalid radix" && 0);
2993 }
2994 insert_at += 2;
2995
2996 // Just shift tmp right for each digit width until it becomes zero
2997 uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1));
2998 uint64_t mask = radix - 1;
2999 ap_private<_AP_W, false, true> zero(0);
3000 unsigned bits = 0;
3001 bool msb = false;
3002 while (tmp.ne(zero)) {
3003 unsigned digit = (unsigned)(tmp.get_VAL() & mask);
3004 result.insert(insert_at, digits[digit]);
3005 tmp = tmp.lshr(shift);
3006 bits++;
3007 msb = (digit >> (shift - 1)) == 1;
3008 }
3009 bits *= shift;
3010 if (bits < _AP_W && leading_zero && msb)
3011 result.insert(insert_at, digits[0]);
3012 }
3013 return result;
3014 }
3015
3016 ap_private<_AP_W, false, true> tmp(*this);
3017 ap_private<6, false, true> divisor(radix);
3018 ap_private<_AP_W, _AP_S, true> zero(0);
3019 size_t insert_at = 0;
3020 if (wantSigned && isNegative()) {
3021 // They want to print the signed version and it is a negative value
3022 // Flip the bits and add one to turn it into the equivalent positive
3023 // value and put a '-' in the result.
3024 tmp.flip();
3025 tmp++;
3026 result = "-";
3027 insert_at = 1;
3028 }
3029 if (tmp == ap_private<_AP_W, false, true>(0ULL))
3030 result = "0";
3031 else
3032 while (tmp.ne(zero)) {
3033 ap_private<_AP_W, false, true> APdigit = tmp % divisor;
3034 ap_private<_AP_W, false, true> tmp2 = tmp / divisor;
3035 uint32_t digit = (uint32_t)(APdigit.getZExtValue());
3036 assert(digit < radix && "divide failed");
3037 result.insert(insert_at, digits[digit]);
3038 tmp = tmp2;
3039 }
3040 return result;
3041
3042} // End of ap_private<_AP_W, _AP_S, true>::toString()
3043
3044// bitwidth > 64
3045template <int _AP_W, bool _AP_S>
3046class ap_private<_AP_W, _AP_S, false> {
3047 // SFINAE pattern. Only consider this class when _AP_W > 64
3048 const static bool valid = ap_private_enable_if<(_AP_W > 64)>::isValid;
3049
3050#ifdef _MSC_VER
3051#pragma warning(disable : 4521 4522)
3052#endif
3053 public:
3054 enum { BitWidth = _AP_W, _AP_N = (_AP_W + 63) / 64 };
3055 static const int width = _AP_W;
3056
3057 private:
3060
3061 /* Constructors */
3068 INLINE ap_private(uint32_t numWords, const uint64_t bigVal[]) {
3069 set_canary();
3070 assert(bigVal && "Null pointer detected!");
3071 {
3072 // Get memory, cleared to 0
3073 memset(pVal, 0, _AP_N * sizeof(uint64_t));
3074
3075 // Calculate the number of words to copy
3076 uint32_t words = AESL_std::min<uint32_t>(numWords, _AP_N);
3077 // Copy the words from bigVal to pVal
3078 memcpy(pVal, bigVal, words * APINT_WORD_SIZE);
3079 if (words >= _AP_W) clearUnusedBits();
3080 // Make sure unused high bits are cleared
3081 }
3082 check_canary();
3083 }
3084
3093 INLINE ap_private(const std::string& val, uint8_t radix = 2) {
3094 set_canary();
3095 assert(!val.empty() && "The input string is empty.");
3096 const char* c_str = val.c_str();
3097 fromString(c_str, val.size(), radix);
3098 check_canary();
3099 }
3100
3111 INLINE ap_private(const char strStart[], uint32_t slen, uint8_t radix) {
3112 set_canary();
3113 fromString(strStart, slen, radix);
3114 check_canary();
3115 }
3116
3117 INLINE void report() {
3118 _AP_ERROR(_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024,
3119 "ap_%sint<%d>: Bitwidth exceeds the "
3120 "default max value %d. Please use macro "
3121 "AP_INT_MAX_W to set a larger max value.",
3122 _AP_S ? "" : "u", _AP_W, MAX_MODE(AP_INT_MAX_W) * 1024);
3123 }
3126
3128 // uint64_t VAL; ///< Used to store the <= 64 bits integer value.
3129 uint64_t pVal[_AP_N];
3130#ifdef AP_CANARY
3131 uint64_t CANARY;
3132 INLINE void check_canary() { assert(CANARY == (uint64_t)0xDEADBEEFDEADBEEF); }
3133 INLINE void set_canary() { CANARY = (uint64_t)0xDEADBEEFDEADBEEF; }
3134#else
3135 INLINE void check_canary() {}
3136 INLINE void set_canary() {}
3137#endif
3138
3139 public:
3140 typedef typename valtype<8, _AP_S>::Type ValType;
3141 typedef ap_private<_AP_W, _AP_S> Type;
3142 // FIXME remove friend type?
3143 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
3144 ap_o_mode _AP_O2, int _AP_N2>
3145 friend struct ap_fixed_base;
3147 //----------------------------------------------------------
3148 template <int _AP_W2, bool _AP_S2>
3149 struct RType {
3150 enum {
3151 mult_w = _AP_W + _AP_W2,
3152 mult_s = _AP_S || _AP_S2,
3153 plus_w =
3154 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
3155 plus_s = _AP_S || _AP_S2,
3156 minus_w =
3157 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
3158 minus_s = true,
3159 div_w = _AP_W + _AP_S2,
3160 div_s = _AP_S || _AP_S2,
3161 mod_w = AP_MIN(_AP_W, _AP_W2 + (!_AP_S2 && _AP_S)),
3162 mod_s = _AP_S,
3163 logic_w = AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)),
3164 logic_s = _AP_S || _AP_S2
3165 };
3166 typedef ap_private<mult_w, mult_s> mult;
3167 typedef ap_private<plus_w, plus_s> plus;
3168 typedef ap_private<minus_w, minus_s> minus;
3169 typedef ap_private<logic_w, logic_s> logic;
3170 typedef ap_private<div_w, div_s> div;
3171 typedef ap_private<mod_w, mod_s> mod;
3172 typedef ap_private<_AP_W, _AP_S> arg1;
3173 typedef bool reduce;
3174 };
3175
3176 INLINE uint64_t& get_VAL(void) { return pVal[0]; }
3177 INLINE uint64_t get_VAL(void) const { return pVal[0]; }
3178 INLINE uint64_t get_VAL(void) const volatile { return pVal[0]; }
3179 INLINE void set_VAL(uint64_t value) { pVal[0] = value; }
3180 INLINE uint64_t& get_pVal(int index) { return pVal[index]; }
3181 INLINE uint64_t* get_pVal() { return pVal; }
3182 INLINE const uint64_t* get_pVal() const { return pVal; }
3183 INLINE uint64_t get_pVal(int index) const { return pVal[index]; }
3184 INLINE uint64_t* get_pVal() const volatile { return pVal; }
3185 INLINE uint64_t get_pVal(int index) const volatile { return pVal[index]; }
3186 INLINE void set_pVal(int i, uint64_t value) { pVal[i] = value; }
3187
3189 enum {
3190 APINT_BITS_PER_WORD = sizeof(uint64_t) * 8,
3191 APINT_WORD_SIZE = sizeof(uint64_t)
3193
3194 enum {
3195 excess_bits = (_AP_W % APINT_BITS_PER_WORD)
3196 ? APINT_BITS_PER_WORD - (_AP_W % APINT_BITS_PER_WORD)
3197 : 0
3198 };
3199 static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits));
3200
3201 public:
3202 // NOTE changed to explicit to be consistent with ap_private<W,S,true>
3203 explicit INLINE ap_private(const char* val) {
3204 set_canary();
3205 unsigned char radix = 10;
3206 std::string str =
3207 ap_private_ops::parseString(val, radix); // determine radix.
3208 std::string::size_type pos = str.find('.');
3209 if (pos != std::string::npos) str = str.substr(pos);
3210 ap_private ap_private_val(str, radix);
3211 operator=(ap_private_val);
3212 report();
3213 check_canary();
3214 }
3215
3216 INLINE ap_private(const char* val, unsigned char rd) {
3217 set_canary();
3218 unsigned char radix = rd;
3219 std::string str =
3220 ap_private_ops::parseString(val, radix); // determine radix.
3221 std::string::size_type pos = str.find('.');
3222 if (pos != std::string::npos) str = str.substr(pos);
3223 ap_private ap_private_val(str, radix);
3224 operator=(ap_private_val);
3225 report();
3226
3227 report();
3228 check_canary();
3229 }
3230
3231 template <int _AP_W2, bool _AP_S2>
3232 INLINE ap_private(const _private_range_ref<_AP_W2, _AP_S2>& ref) {
3233 set_canary();
3234 *this = ref.get();
3235 report();
3236 check_canary();
3237 }
3238
3239 template <int _AP_W2, bool _AP_S2>
3240 INLINE ap_private(const _private_bit_ref<_AP_W2, _AP_S2>& ref) {
3241 set_canary();
3242 *this = ((uint64_t)(bool)ref);
3243 report();
3244 check_canary();
3245 }
3246
3247 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
3248 // INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>&
3249 // ref) {
3250 // set_canary();
3251 // *this = ref.get();
3252 // report();
3253 // check_canary();
3254 // }
3255 //
3256 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
3257 // ap_o_mode _AP_O2, int _AP_N2>
3258 // INLINE ap_private(
3259 // const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&
3260 // val) {
3261 // set_canary();
3262 // *this = ((val.operator ap_private<_AP_W2, false>()));
3263 // report();
3264 // check_canary();
3265 // }
3266 //
3267 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
3268 // ap_o_mode _AP_O2, int _AP_N2>
3269 // INLINE ap_private(
3270 // const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val)
3271 // {
3272 // set_canary();
3273 // *this = (uint64_t)(bool)val;
3274 // report();
3275 // check_canary();
3276 // }
3277
3280 INLINE ap_private(const ap_private& that) {
3281 set_canary();
3282 memcpy(pVal, that.get_pVal(), _AP_N * APINT_WORD_SIZE);
3283 clearUnusedBits();
3284 check_canary();
3285 }
3286
3287 template <int _AP_W1, bool _AP_S1>
3288 INLINE ap_private(const ap_private<_AP_W1, _AP_S1, false>& that) {
3289 set_canary();
3290 operator=(that);
3291 check_canary();
3292 }
3293
3294 template <int _AP_W1, bool _AP_S1>
3295 INLINE ap_private(const volatile ap_private<_AP_W1, _AP_S1, false>& that) {
3296 set_canary();
3297 operator=(const_cast<const ap_private<_AP_W1, _AP_S1, false>&>(that));
3298 check_canary();
3299 }
3300
3301 template <int _AP_W1, bool _AP_S1>
3302 INLINE ap_private(const ap_private<_AP_W1, _AP_S1, true>& that) {
3303 set_canary();
3304 static const uint64_t that_sign_ext_mask =
3305 (_AP_W1 == APINT_BITS_PER_WORD)
3306 ? 0
3307 : ~0ULL >> (_AP_W1 % APINT_BITS_PER_WORD)
3308 << (_AP_W1 % APINT_BITS_PER_WORD);
3309 if (that.isNegative()) {
3310 pVal[0] = that.get_VAL() | that_sign_ext_mask;
3311 memset(pVal + 1, ~0, sizeof(uint64_t) * (_AP_N - 1));
3312 } else {
3313 pVal[0] = that.get_VAL();
3314 memset(pVal + 1, 0, sizeof(uint64_t) * (_AP_N - 1));
3315 }
3316 clearUnusedBits();
3317 check_canary();
3318 }
3319
3320 template <int _AP_W1, bool _AP_S1>
3321 INLINE ap_private(const volatile ap_private<_AP_W1, _AP_S1, true>& that) {
3322 set_canary();
3323 operator=(const_cast<const ap_private<_AP_W1, _AP_S1, true>&>(that));
3324 check_canary();
3325 }
3326
3328 // virtual ~ap_private() {}
3329 INLINE ~ap_private() { check_canary(); }
3330
3333
3337 INLINE ap_private() {
3338 set_canary();
3339 memset(pVal, 0, _AP_N * sizeof(uint64_t));
3340 clearUnusedBits();
3341 check_canary();
3342 }
3343
3344 INLINE ap_private(uint64_t* val, uint32_t bits = _AP_W) { assert(0); }
3345 INLINE ap_private(const uint64_t* const val, uint32_t bits) { assert(0); }
3346
3355#define CTOR(TYPE, SIGNED) \
3356 INLINE ap_private(TYPE val, bool isSigned = SIGNED) { \
3357 set_canary(); \
3358 pVal[0] = (ValType)val; \
3359 if (isSigned && int64_t(pVal[0]) < 0) { \
3360 memset(pVal + 1, ~0, sizeof(uint64_t) * (_AP_N - 1)); \
3361 } else { \
3362 memset(pVal + 1, 0, sizeof(uint64_t) * (_AP_N - 1)); \
3363 } \
3364 clearUnusedBits(); \
3365 check_canary(); \
3366 }
3367
3368 CTOR(bool, false)
3369 CTOR(char, CHAR_IS_SIGNED)
3370 CTOR(signed char, true)
3371 CTOR(unsigned char, false)
3372 CTOR(short, true)
3373 CTOR(unsigned short, false)
3374 CTOR(int, true)
3375 CTOR(unsigned int, false)
3376 CTOR(long, true)
3377 CTOR(unsigned long, false)
3378 CTOR(ap_slong, true)
3379 CTOR(ap_ulong, false)
3380#if 0
3381 CTOR(half, false)
3382 CTOR(float, false)
3383 CTOR(double, false)
3384#endif
3385#undef CTOR
3386
3389 INLINE bool isSingleWord() const { return false; }
3390
3393 static INLINE uint32_t whichWord(uint32_t bitPosition) {
3394 // return bitPosition / APINT_BITS_PER_WORD;
3395 return (bitPosition) >> 6;
3396 }
3397
3401 static INLINE uint32_t whichBit(uint32_t bitPosition) {
3402 // return bitPosition % APINT_BITS_PER_WORD;
3403 return bitPosition & 0x3f;
3404 }
3405
3410 static INLINE uint64_t maskBit(uint32_t bitPosition) {
3411 return 1ULL << (whichBit(bitPosition));
3412 }
3413
3416 INLINE uint64_t getWord(uint32_t bitPosition) const {
3417 return pVal[whichWord(bitPosition)];
3418 }
3419
3425 INLINE void clearUnusedBits(void) volatile
3426// just for clang compiler
3427#if defined(__clang__) && !defined(__CLANG_3_1__)
3428 __attribute__((no_sanitize("undefined")))
3429#endif
3430 {
3431 pVal[_AP_N - 1] =
3432 _AP_S ? ((((int64_t)pVal[_AP_N - 1]) << (excess_bits)) >> excess_bits)
3433 : (excess_bits
3434 ? ((pVal[_AP_N - 1]) << (excess_bits)) >> (excess_bits)
3435 : pVal[_AP_N - 1]);
3436 }
3437
3438 INLINE void clearUnusedBitsToZero(void) { pVal[_AP_N - 1] &= mask; }
3439
3440 INLINE void clearUnusedBitsToOne(void) { pVal[_AP_N - 1] |= mask; }
3441
3444 INLINE void fromString(const char* str, uint32_t slen, uint8_t radix) {
3445 enum { numbits = _AP_W };
3446 bool isNeg = str[0] == '-';
3447 if (isNeg) {
3448 str++;
3449 slen--;
3450 }
3451
3452 if (str[0] == '0' && (str[1] == 'b' || str[1] == 'B')) {
3453 // if(radix == 0) radix = 2;
3454 _AP_WARNING(radix != 2, "%s seems to have base %d, but %d given.", str, 2,
3455 radix);
3456 str += 2;
3457 slen -= 2;
3458 } else if (str[0] == '0' && (str[1] == 'o' || str[1] == 'O')) {
3459 // if (radix == 0) radix = 8;
3460 _AP_WARNING(radix != 8, "%s seems to have base %d, but %d given.", str, 8,
3461 radix);
3462 str += 2;
3463 slen -= 2;
3464 } else if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
3465 // if (radix == 0) radix = 16;
3466 _AP_WARNING(radix != 16, "%s seems to have base %d, but %d given.", str,
3467 16, radix);
3468 str += 2;
3469 slen -= 2;
3470 } else if (str[0] == '0' && (str[1] == 'd' || str[1] == 'D')) {
3471 // if (radix == 0) radix = 10;
3472 _AP_WARNING(radix != 10, "%s seems to have base %d, but %d given.", str,
3473 10, radix);
3474 str += 2;
3475 slen -= 2;
3476 } else if (radix == 0) {
3477 // radix = 2; // XXX default value
3478 }
3479
3480 // Check our assumptions here
3481 assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
3482 "Radix should be 2, 8, 10, or 16!");
3483 assert(str && "String is null?");
3484
3485 // skip any leading zero
3486 while (*str == '0' && *(str + 1) != '\0') {
3487 str++;
3488 slen--;
3489 }
3490 assert((slen <= numbits || radix != 2) && "Insufficient bit width");
3491 assert(((slen - 1) * 3 <= numbits || radix != 8) &&
3492 "Insufficient bit width");
3493 assert(((slen - 1) * 4 <= numbits || radix != 16) &&
3494 "Insufficient bit width");
3495 assert((((slen - 1) * 64) / 22 <= numbits || radix != 10) &&
3496 "Insufficient bit width");
3497
3498 // clear bits
3499 memset(pVal, 0, _AP_N * sizeof(uint64_t));
3500
3501 // Figure out if we can shift instead of multiply
3502 uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0);
3503
3504 // Set up an ap_private for the digit to add outside the loop so we don't
3505 // constantly construct/destruct it.
3506 uint64_t bigVal[_AP_N];
3507 memset(bigVal, 0, _AP_N * sizeof(uint64_t));
3508 ap_private<_AP_W, _AP_S> apdigit(getBitWidth(), bigVal);
3509 ap_private<_AP_W, _AP_S> apradix(radix);
3510
3511 // Enter digit traversal loop
3512 for (unsigned i = 0; i < slen; i++) {
3513 // Get a digit
3514 uint32_t digit = 0;
3515 char cdigit = str[i];
3516 if (radix == 16) {
3517#define isxdigit(c) \
3518 (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || \
3519 ((c) >= 'A' && (c) <= 'F'))
3520#define isdigit(c) ((c) >= '0' && (c) <= '9')
3521 if (!isxdigit(cdigit)) assert(0 && "Invalid hex digit in string");
3522 if (isdigit(cdigit))
3523 digit = cdigit - '0';
3524 else if (cdigit >= 'a')
3525 digit = cdigit - 'a' + 10;
3526 else if (cdigit >= 'A')
3527 digit = cdigit - 'A' + 10;
3528 else
3529 assert(0 && "huh? we shouldn't get here");
3530 } else if (isdigit(cdigit)) {
3531 digit = cdigit - '0';
3532 } else if (cdigit != '\0') {
3533 assert(0 && "Invalid character in digit string");
3534 }
3535#undef isxdigit
3536#undef isdigit
3537 // Shift or multiply the value by the radix
3538 if (shift)
3539 *this <<= shift;
3540 else
3541 *this *= apradix;
3542
3543 // Add in the digit we just interpreted
3544 apdigit.set_VAL(digit);
3545 *this += apdigit;
3546 }
3547 // If its negative, put it in two's complement form
3548 if (isNeg) {
3549 (*this)--;
3550 this->flip();
3551 }
3552 clearUnusedBits();
3553 }
3554
3555 INLINE ap_private read() volatile { return *this; }
3556
3557 INLINE void write(const ap_private& op2) volatile { *this = (op2); }
3558
3559 INLINE operator ValType() const { return get_VAL(); }
3560
3561 INLINE int to_uchar() const { return (unsigned char)get_VAL(); }
3562
3563 INLINE int to_char() const { return (signed char)get_VAL(); }
3564
3565 INLINE int to_ushort() const { return (unsigned short)get_VAL(); }
3566
3567 INLINE int to_short() const { return (short)get_VAL(); }
3568
3569 INLINE int to_int() const { return (int)get_VAL(); }
3570
3571 INLINE unsigned to_uint() const { return (unsigned)get_VAL(); }
3572
3573 INLINE long to_long() const { return (long)get_VAL(); }
3574
3575 INLINE unsigned long to_ulong() const { return (unsigned long)get_VAL(); }
3576
3577 INLINE ap_slong to_int64() const { return (ap_slong)get_VAL(); }
3578
3579 INLINE ap_ulong to_uint64() const { return (ap_ulong)get_VAL(); }
3580
3581 INLINE double to_double() const {
3582 if (isNegative())
3583 return roundToDouble(true);
3584 else
3585 return roundToDouble(false);
3586 }
3587
3588 INLINE unsigned length() const { return _AP_W; }
3589
3590 /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise
3591 * versa*/
3592 INLINE ap_private& reverse() {
3593 for (int i = 0; i < _AP_W / 2; ++i) {
3594 bool tmp = operator[](i);
3595 if (operator[](_AP_W - 1 - i))
3596 set(i);
3597 else
3598 clear(i);
3599 if (tmp)
3600 set(_AP_W - 1 - i);
3601 else
3602 clear(_AP_W - 1 - i);
3603 }
3604 clearUnusedBits();
3605 return *this;
3606 }
3607
3608 /*Return true if the value of ap_private instance is zero*/
3609 INLINE bool iszero() const { return isMinValue(); }
3610
3611 INLINE bool to_bool() const { return !iszero(); }
3612
3613 /* x < 0 */
3614 INLINE bool sign() const {
3615 if (isNegative()) return true;
3616 return false;
3617 }
3618
3619 /* x[i] = !x[i] */
3620 INLINE void invert(int i) {
3621 assert(i >= 0 && "Attempting to read bit with negative index");
3622 assert(i < _AP_W && "Attempting to read bit beyond MSB");
3623 flip(i);
3624 }
3625
3626 /* x[i] */
3627 INLINE bool test(int i) const {
3628 assert(i >= 0 && "Attempting to read bit with negative index");
3629 assert(i < _AP_W && "Attempting to read bit beyond MSB");
3630 return operator[](i);
3631 }
3632
3633 // Set the ith bit into v
3634 INLINE void set(int i, bool v) {
3635 assert(i >= 0 && "Attempting to write bit with negative index");
3636 assert(i < _AP_W && "Attempting to write bit beyond MSB");
3637 v ? set(i) : clear(i);
3638 }
3639
3640 // Set the ith bit into v
3641 INLINE void set_bit(int i, bool v) {
3642 assert(i >= 0 && "Attempting to write bit with negative index");
3643 assert(i < _AP_W && "Attempting to write bit beyond MSB");
3644 v ? set(i) : clear(i);
3645 }
3646
3647 // FIXME different argument for different action?
3648 INLINE ap_private& set(uint32_t bitPosition) {
3649 pVal[whichWord(bitPosition)] |= maskBit(bitPosition);
3650 clearUnusedBits();
3651 return *this;
3652 }
3653
3654 INLINE void set() {
3655 for (int i = 0; i < _AP_N; ++i) pVal[i] = ~0ULL;
3656 clearUnusedBits();
3657 }
3658
3659 // Get the value of ith bit
3660 INLINE bool get(int i) const {
3661 assert(i >= 0 && "Attempting to read bit with negative index");
3662 assert(i < _AP_W && "Attempting to read bit beyond MSB");
3663 return ((maskBit(i) & (pVal[whichWord(i)])) != 0);
3664 }
3665
3666 // Get the value of ith bit
3667 INLINE bool get_bit(int i) const {
3668 assert(i >= 0 && "Attempting to read bit with negative index");
3669 assert(i < _AP_W && "Attempting to read bit beyond MSB");
3670 return ((maskBit(i) & (pVal[whichWord(i)])) != 0);
3671 }
3672
3673 // This is used for sc_lv and sc_bv, which is implemented by sc_uint
3674 // Rotate an ap_private object n places to the left
3675 INLINE void lrotate(int n) {
3676 assert(n >= 0 && "Attempting to shift negative index");
3677 assert(n < _AP_W && "Shift value larger than bit width");
3678 operator=(shl(n) | lshr(_AP_W - n));
3679 }
3680
3681 // This is used for sc_lv and sc_bv, which is implemented by sc_uint
3682 // Rotate an ap_private object n places to the right
3683 INLINE void rrotate(int n) {
3684 assert(n >= 0 && "Attempting to shift negative index");
3685 assert(n < _AP_W && "Shift value larger than bit width");
3686 operator=(lshr(n) | shl(_AP_W - n));
3687 }
3688
3691 INLINE ap_private& clear(uint32_t bitPosition) {
3692 pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition);
3693 clearUnusedBits();
3694 return *this;
3695 }
3696
3698 INLINE void clear() { memset(pVal, 0, _AP_N * APINT_WORD_SIZE); }
3699
3701 ap_private& flip() {
3702 for (int i = 0; i < _AP_N; ++i) pVal[i] ^= ~0ULL;
3703 clearUnusedBits();
3704 return *this;
3705 }
3706
3708 INLINE ap_private& flip(uint32_t bitPosition) {
3709 assert(bitPosition < BitWidth && "Out of the bit-width range!");
3710 set_bit(bitPosition, !get_bit(bitPosition));
3711 return *this;
3712 }
3713
3714 // complements every bit
3715 INLINE void b_not() { flip(); }
3716
3717 INLINE ap_private getLoBits(uint32_t numBits) const {
3718 return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits),
3719 _AP_W - numBits);
3720 }
3721
3722 INLINE ap_private getHiBits(uint32_t numBits) const {
3723 return ap_private_ops::lshr(*this, _AP_W - numBits);
3724 }
3725
3726 // Binary Arithmetic
3727 //-----------------------------------------------------------
3728
3729 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
3730 // INLINE ap_private<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator&(
3731 // const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) {
3732 // return *this & a2.get();
3733 // }
3734 //
3735 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
3736 // INLINE ap_private<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator|(
3737 // const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) {
3738 // return *this | a2.get();
3739 // }
3740 //
3741 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
3742 // INLINE ap_private<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator^(
3743 // const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) {
3744 // return *this ^ a2.get();
3745 // }
3746
3748 //-------------------------------------------------------------
3749
3750#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \
3751 template <int _AP_W1, bool _AP_S1> \
3752 INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1>& RHS) { \
3753 const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N; \
3754 uint32_t numWords = AESL_std::min((int)_AP_N, _AP_N1); \
3755 uint32_t i; \
3756 if (_AP_W != _AP_W1) \
3757 fprintf(stderr, \
3758 "Warning! Bitsize mismach for ap_[u]int " #Sym " ap_[u]int.\n"); \
3759 for (i = 0; i < numWords; ++i) pVal[i] Sym RHS.get_pVal(i); \
3760 if (_AP_N1 < _AP_N) { \
3761 uint64_t ext = RHS.isNegative() ? ~0ULL : 0; \
3762 for (; i < _AP_N; i++) pVal[i] Sym ext; \
3763 } \
3764 clearUnusedBits(); \
3765 return *this; \
3766 }
3767
3768 OP_BIN_LOGIC_ASSIGN_AP(&=);
3769 OP_BIN_LOGIC_ASSIGN_AP(|=);
3770 OP_BIN_LOGIC_ASSIGN_AP(^=);
3771#undef OP_BIN_LOGIC_ASSIGN_AP
3772
3776 template <int _AP_W1, bool _AP_S1>
3777 INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS) {
3778 const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N;
3779 uint64_t RHSpVal[_AP_N1];
3780 for (int i = 0; i < _AP_N1; ++i) RHSpVal[i] = RHS.get_pVal(i);
3781 ap_private_ops::add(pVal, pVal, RHSpVal, _AP_N, _AP_N, _AP_N1, _AP_S,
3782 _AP_S1);
3783 clearUnusedBits();
3784 return *this;
3785 }
3786
3787 template <int _AP_W1, bool _AP_S1>
3788 INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS) {
3789 const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N;
3790 uint64_t RHSpVal[_AP_N1];
3791 for (int i = 0; i < _AP_N1; ++i) RHSpVal[i] = RHS.get_pVal(i);
3792 ap_private_ops::sub(pVal, pVal, RHSpVal, _AP_N, _AP_N, _AP_N1, _AP_S,
3793 _AP_S1);
3794 clearUnusedBits();
3795 return *this;
3796 }
3797
3798 template <int _AP_W1, bool _AP_S1>
3799 INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS) {
3800 // Get some bit facts about LHS and check for zero
3801 uint32_t lhsBits = getActiveBits();
3802 uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1;
3803 if (!lhsWords) {
3804 // 0 * X ===> 0
3805 return *this;
3806 }
3807
3808 ap_private dupRHS = RHS;
3809 // Get some bit facts about RHS and check for zero
3810 uint32_t rhsBits = dupRHS.getActiveBits();
3811 uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1;
3812 if (!rhsWords) {
3813 // X * 0 ===> 0
3814 clear();
3815 return *this;
3816 }
3817
3818 // Allocate space for the result
3819 uint32_t destWords = rhsWords + lhsWords;
3820 uint64_t* dest = (uint64_t*)malloc(destWords * sizeof(uint64_t));
3821
3822 // Perform the long multiply
3823 ap_private_ops::mul(dest, pVal, lhsWords, dupRHS.get_pVal(), rhsWords,
3824 destWords);
3825
3826 // Copy result back into *this
3827 clear();
3828 uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords;
3829
3830 memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE);
3831
3832 uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL;
3833 for (int i = wordsToCopy; i < _AP_N; i++) pVal[i] = ext;
3834 clearUnusedBits();
3835 // delete dest array and return
3836 free(dest);
3837 return *this;
3838 }
3839
3840#define OP_ASSIGN_AP(Sym) \
3841 template <int _AP_W2, bool _AP_S2> \
3842 INLINE ap_private& operator Sym##=(const ap_private<_AP_W2, _AP_S2>& op) { \
3843 *this = operator Sym(op); \
3844 return *this; \
3845 }
3846
3847 OP_ASSIGN_AP(/)
3848 OP_ASSIGN_AP(%)
3849#undef OP_ASSIGN_AP
3850
3851#define OP_BIN_LOGIC_AP(Sym) \
3852 template <int _AP_W1, bool _AP_S1> \
3853 INLINE typename RType<_AP_W1, _AP_S1>::logic operator Sym( \
3854 const ap_private<_AP_W1, _AP_S1>& RHS) const { \
3855 enum { \
3856 numWords = (RType<_AP_W1, _AP_S1>::logic_w + APINT_BITS_PER_WORD - 1) / \
3857 APINT_BITS_PER_WORD \
3858 }; \
3859 typename RType<_AP_W1, _AP_S1>::logic Result; \
3860 uint32_t i; \
3861 const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N; \
3862 uint32_t min_N = std::min((int)_AP_N, _AP_N1); \
3863 uint32_t max_N = std::max((int)_AP_N, _AP_N1); \
3864 for (i = 0; i < min_N; ++i) \
3865 Result.set_pVal(i, pVal[i] Sym RHS.get_pVal(i)); \
3866 if (numWords > i) { \
3867 uint64_t ext = ((_AP_N < _AP_N1 && isNegative()) || \
3868 (_AP_N1 < _AP_N && RHS.isNegative())) \
3869 ? ~0ULL \
3870 : 0; \
3871 if (_AP_N > _AP_N1) \
3872 for (; i < max_N; i++) Result.set_pVal(i, pVal[i] Sym ext); \
3873 else \
3874 for (; i < max_N; i++) Result.set_pVal(i, RHS.get_pVal(i) Sym ext); \
3875 if (numWords > i) { \
3876 uint64_t ext2 = ((_AP_N > _AP_N1 && isNegative()) || \
3877 (_AP_N1 > _AP_N && RHS.isNegative())) \
3878 ? ~0ULL \
3879 : 0; \
3880 Result.set_pVal(i, ext Sym ext2); \
3881 } \
3882 } \
3883 Result.clearUnusedBits(); \
3884 return Result; \
3885 }
3886
3887 OP_BIN_LOGIC_AP(|);
3888 OP_BIN_LOGIC_AP(&);
3889 OP_BIN_LOGIC_AP(^);
3890
3891#undef OP_BIN_LOGIC_AP
3892
3893 template <int _AP_W1, bool _AP_S1>
3894 INLINE typename RType<_AP_W1, _AP_S1>::plus operator+(
3895 const ap_private<_AP_W1, _AP_S1>& RHS) const {
3896 typename RType<_AP_W1, _AP_S1>::plus Result, lhs(*this), rhs(RHS);
3897 const int Result_AP_N = (RType<_AP_W1, _AP_S1>::plus_w + 63) / 64;
3898 ap_private_ops::add(Result.get_pVal(), lhs.get_pVal(), rhs.get_pVal(),
3899 Result_AP_N, Result_AP_N, Result_AP_N, _AP_S, _AP_S1);
3900 Result.clearUnusedBits();
3901 return Result;
3902 }
3903
3904 template <int _AP_W1, bool _AP_S1>
3905 INLINE typename RType<_AP_W1, _AP_S1>::minus operator-(
3906 const ap_private<_AP_W1, _AP_S1>& RHS) const {
3907 typename RType<_AP_W1, _AP_S1>::minus Result, lhs(*this), rhs(RHS);
3908 const int Result_AP_N = (RType<_AP_W1, _AP_S1>::minus_w + 63) / 64;
3909 ap_private_ops::sub(Result.get_pVal(), lhs.get_pVal(), rhs.get_pVal(),
3910 Result_AP_N, Result_AP_N, Result_AP_N, _AP_S, _AP_S1);
3911 Result.clearUnusedBits();
3912 return Result;
3913 }
3914
3915 template <int _AP_W1, bool _AP_S1>
3916 INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(
3917 const ap_private<_AP_W1, _AP_S1>& RHS) const {
3918 typename RType<_AP_W1, _AP_S1>::mult temp = *this;
3919 temp *= RHS;
3920 return temp;
3921 }
3922
3923 template <int _AP_W2, bool _AP_S2>
3924 INLINE typename RType<_AP_W2, _AP_S2>::div operator/(
3925 const ap_private<_AP_W2, _AP_S2>& op) const {
3926 ap_private<AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)),
3927 (_AP_W > _AP_W2 ? _AP_S
3928 : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))>
3929 lhs = *this;
3930 ap_private<AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)),
3931 (_AP_W > _AP_W2 ? _AP_S
3932 : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))>
3933 rhs = op;
3934 return typename RType<_AP_W2, _AP_S2>::div(
3935 (_AP_S || _AP_S2) ? lhs.sdiv(rhs) : lhs.udiv(rhs));
3936 }
3937
3938 template <int _AP_W2, bool _AP_S2>
3939 INLINE typename RType<_AP_W2, _AP_S2>::mod operator%(
3940 const ap_private<_AP_W2, _AP_S2>& op) const {
3941 ap_private<AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)),
3942 (_AP_W > _AP_W2 ? _AP_S
3943 : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))>
3944 lhs = *this;
3945 ap_private<AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)),
3946 (_AP_W > _AP_W2 ? _AP_S
3947 : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))>
3948 rhs = op;
3949 typename RType<_AP_W2, _AP_S2>::mod res =
3950 typename RType<_AP_W2, _AP_S2>::mod(_AP_S ? lhs.srem(rhs)
3951 : lhs.urem(rhs));
3952 return res;
3953 }
3954
3955#define OP_LEFT_SHIFT_CTYPE(TYPE, SIGNED) \
3956 INLINE ap_private operator<<(const TYPE op) const { \
3957 if (op >= _AP_W) return ap_private(0); \
3958 if (SIGNED && op < 0) return *this >> (0 - op); \
3959 return shl(op); \
3960 }
3961
3962 OP_LEFT_SHIFT_CTYPE(int, true)
3963 // OP_LEFT_SHIFT_CTYPE(bool, false)
3964 OP_LEFT_SHIFT_CTYPE(signed char, true)
3965 OP_LEFT_SHIFT_CTYPE(unsigned char, false)
3966 OP_LEFT_SHIFT_CTYPE(short, true)
3967 OP_LEFT_SHIFT_CTYPE(unsigned short, false)
3968 OP_LEFT_SHIFT_CTYPE(unsigned int, false)
3969 OP_LEFT_SHIFT_CTYPE(long, true)
3970 OP_LEFT_SHIFT_CTYPE(unsigned long, false)
3971 OP_LEFT_SHIFT_CTYPE(unsigned long long, false)
3972 OP_LEFT_SHIFT_CTYPE(long long, true)
3973#if 0
3974 OP_LEFT_SHIFT_CTYPE(half, false)
3975 OP_LEFT_SHIFT_CTYPE(float, false)
3976 OP_LEFT_SHIFT_CTYPE(double, false)
3977#endif
3978#undef OP_LEFT_SHIFT_CTYPE
3979
3980 template <int _AP_W2, bool _AP_S2>
3981 INLINE ap_private operator<<(const ap_private<_AP_W2, _AP_S2>& op2) const {
3982 if (_AP_S2 == false) {
3983 uint32_t sh = op2.to_uint();
3984 return *this << sh;
3985 } else {
3986 int sh = op2.to_int();
3987 return *this << sh;
3988 }
3989 }
3990
3991#define OP_RIGHT_SHIFT_CTYPE(TYPE, SIGNED) \
3992 INLINE ap_private operator>>(const TYPE op) const { \
3993 if (op >= _AP_W) { \
3994 if (isNegative()) \
3995 return ap_private(-1); \
3996 else \
3997 return ap_private(0); \
3998 } \
3999 if ((SIGNED) && op < 0) return *this << (0 - op); \
4000 if (_AP_S) \
4001 return ashr(op); \
4002 else \
4003 return lshr(op); \
4004 }
4005
4006 // OP_RIGHT_SHIFT_CTYPE(bool, false)
4007 OP_RIGHT_SHIFT_CTYPE(char, CHAR_IS_SIGNED)
4008 OP_RIGHT_SHIFT_CTYPE(signed char, true)
4009 OP_RIGHT_SHIFT_CTYPE(unsigned char, false)
4010 OP_RIGHT_SHIFT_CTYPE(short, true)
4011 OP_RIGHT_SHIFT_CTYPE(unsigned short, false)
4012 OP_RIGHT_SHIFT_CTYPE(int, true)
4013 OP_RIGHT_SHIFT_CTYPE(unsigned int, false)
4014 OP_RIGHT_SHIFT_CTYPE(long, true)
4015 OP_RIGHT_SHIFT_CTYPE(unsigned long, false)
4016 OP_RIGHT_SHIFT_CTYPE(unsigned long long, false)
4017 OP_RIGHT_SHIFT_CTYPE(long long, true)
4018#if 0
4019 OP_RIGHT_SHIFT_CTYPE(half, false)
4020 OP_RIGHT_SHIFT_CTYPE(float, false)
4021 OP_RIGHT_SHIFT_CTYPE(double, false)
4022#endif
4023#undef OP_RIGHT_SHIFT_CTYPE
4024
4025 template <int _AP_W2, bool _AP_S2>
4026 INLINE ap_private operator>>(const ap_private<_AP_W2, _AP_S2>& op2) const {
4027 if (_AP_S2 == false) {
4028 uint32_t sh = op2.to_uint();
4029 return *this >> sh;
4030 } else {
4031 int sh = op2.to_int();
4032 return *this >> sh;
4033 }
4034 }
4035
4037 //------------------------------------------------------------------
4038 // TODO call clearUnusedBits ?
4039#define OP_ASSIGN_AP(Sym) \
4040 template <int _AP_W2, bool _AP_S2> \
4041 INLINE ap_private& operator Sym##=(int op) { \
4042 *this = operator Sym(op); \
4043 return *this; \
4044 } \
4045 INLINE ap_private& operator Sym##=(unsigned int op) { \
4046 *this = operator Sym(op); \
4047 return *this; \
4048 } \
4049 template <int _AP_W2, bool _AP_S2> \
4050 INLINE ap_private& operator Sym##=(const ap_private<_AP_W2, _AP_S2>& op) { \
4051 *this = operator Sym(op); \
4052 return *this; \
4053 }
4054 OP_ASSIGN_AP(>>)
4055 OP_ASSIGN_AP(<<)
4056#undef OP_ASSIGN_AP
4057
4059 //-----------------------------------------------------------------
4060 INLINE bool operator==(const ap_private& RHS) const {
4061 // Get some facts about the number of bits used in the two operands.
4062 uint32_t n1 = getActiveBits();
4063 uint32_t n2 = RHS.getActiveBits();
4064
4065 // If the number of bits isn't the same, they aren't equal
4066 if (n1 != n2) return false;
4067
4068 // If the number of bits fits in a word, we only need to compare the low
4069 // word.
4070 if (n1 <= APINT_BITS_PER_WORD) return pVal[0] == RHS.get_pVal(0);
4071
4072 // Otherwise, compare everything
4073 for (int i = whichWord(n1 - 1); i >= 0; --i)
4074 if (pVal[i] != RHS.get_pVal(i)) return false;
4075 return true;
4076 }
4077
4078 template <int _AP_W2, bool _AP_S2>
4079 INLINE bool operator==(const ap_private<_AP_W2, _AP_S2>& op) const {
4080 enum {
4081 _AP_MAX_W = AP_MAX(_AP_W, _AP_W2),
4082 };
4083 ap_private<_AP_MAX_W, false> lhs(*this);
4084 ap_private<_AP_MAX_W, false> rhs(op);
4085 return lhs == rhs;
4086 }
4087
4088 INLINE bool operator==(uint64_t Val) const {
4089 uint32_t n = getActiveBits();
4090 if (n <= APINT_BITS_PER_WORD)
4091 return pVal[0] == Val;
4092 else
4093 return false;
4094 }
4095
4096 template <int _AP_W2, bool _AP_S2>
4097 INLINE bool operator!=(const ap_private<_AP_W2, _AP_S2>& op) const {
4098 return !(*this == op);
4099 }
4100
4101 template <bool _AP_S1>
4102 INLINE bool operator!=(const ap_private<_AP_W, _AP_S1>& RHS) const {
4103 return !((*this) == RHS);
4104 }
4105
4106 INLINE bool operator!=(uint64_t Val) const { return !((*this) == Val); }
4107
4108 template <int _AP_W2, bool _AP_S2>
4109 INLINE bool operator<=(const ap_private<_AP_W2, _AP_S2>& op) const {
4110 return !(*this > op);
4111 }
4112
4113 INLINE bool operator<(const ap_private& op) const {
4114 return _AP_S ? slt(op) : ult(op);
4115 }
4116
4117 template <int _AP_W2, bool _AP_S2>
4118 INLINE bool operator<(const ap_private<_AP_W2, _AP_S2>& op) const {
4119 enum {
4120 _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2))
4121 };
4122 ap_private<_AP_MAX_W, _AP_S> lhs(*this);
4123 ap_private<_AP_MAX_W, _AP_S2> rhs(op);
4124 if (_AP_S == _AP_S2)
4125 return _AP_S ? lhs.slt(rhs) : lhs.ult(rhs);
4126 else if (_AP_S)
4127 if (_AP_W2 >= _AP_W)
4128 return lhs.ult(rhs);
4129 else
4130 return lhs.slt(rhs);
4131 else if (_AP_W >= _AP_W2)
4132 return lhs.ult(rhs);
4133 else
4134 return lhs.slt(rhs);
4135 }
4136
4137 template <int _AP_W2, bool _AP_S2>
4138 INLINE bool operator>=(const ap_private<_AP_W2, _AP_S2>& op) const {
4139 return !(*this < op);
4140 }
4141
4142 INLINE bool operator>(const ap_private& op) const {
4143 return _AP_S ? sgt(op) : ugt(op);
4144 }
4145
4146 template <int _AP_W2, bool _AP_S2>
4147 INLINE bool operator>(const ap_private<_AP_W2, _AP_S2>& op) const {
4148 enum {
4149 _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2))
4150 };
4151 ap_private<_AP_MAX_W, _AP_S> lhs(*this);
4152 ap_private<_AP_MAX_W, _AP_S2> rhs(op);
4153 if (_AP_S == _AP_S2)
4154 return _AP_S ? lhs.sgt(rhs) : lhs.ugt(rhs);
4155 else if (_AP_S)
4156 if (_AP_W2 >= _AP_W)
4157 return lhs.ugt(rhs);
4158 else
4159 return lhs.sgt(rhs);
4160 else if (_AP_W >= _AP_W2)
4161 return lhs.ugt(rhs);
4162 else
4163 return lhs.sgt(rhs);
4164 }
4165
4167 //--------------------------------------------------------------
4169 return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo);
4170 }
4171
4172 INLINE _private_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) const {
4174 const_cast<ap_private<_AP_W, _AP_S>*>(this), Hi, Lo);
4175 }
4176
4177 INLINE _private_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) const {
4179 (const_cast<ap_private<_AP_W, _AP_S>*>(this)), Hi, Lo);
4180 }
4181
4182 INLINE _private_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) {
4183 return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo);
4184 }
4185
4186 template <int _AP_W2, bool _AP_S2, int _AP_W3, bool _AP_S3>
4188 const ap_private<_AP_W2, _AP_S2>& HiIdx,
4189 const ap_private<_AP_W3, _AP_S3>& LoIdx) {
4190 int Hi = HiIdx.to_int();
4191 int Lo = LoIdx.to_int();
4192 return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo);
4193 }
4194
4195 template <int _AP_W2, bool _AP_S2, int _AP_W3, bool _AP_S3>
4196 INLINE _private_range_ref<_AP_W, _AP_S> operator()(
4197 const ap_private<_AP_W2, _AP_S2>& HiIdx,
4198 const ap_private<_AP_W3, _AP_S3>& LoIdx) {
4199 int Hi = HiIdx.to_int();
4200 int Lo = LoIdx.to_int();
4201 return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo);
4202 }
4203
4204 template <int _AP_W2, bool _AP_S2, int _AP_W3, bool _AP_S3>
4206 const ap_private<_AP_W2, _AP_S2>& HiIdx,
4207 const ap_private<_AP_W3, _AP_S3>& LoIdx) const {
4208 int Hi = HiIdx.to_int();
4209 int Lo = LoIdx.to_int();
4210 return _private_range_ref<_AP_W, _AP_S>(const_cast<ap_private*>(this), Hi,
4211 Lo);
4212 }
4213
4214 template <int _AP_W2, bool _AP_S2, int _AP_W3, bool _AP_S3>
4215 INLINE _private_range_ref<_AP_W, _AP_S> operator()(
4216 const ap_private<_AP_W2, _AP_S2>& HiIdx,
4217 const ap_private<_AP_W3, _AP_S3>& LoIdx) const {
4218 int Hi = HiIdx.to_int();
4219 int Lo = LoIdx.to_int();
4220 return this->range(Hi, Lo);
4221 }
4222
4223 INLINE _private_bit_ref<_AP_W, _AP_S> operator[](int index) {
4224 return _private_bit_ref<_AP_W, _AP_S>(*this, index);
4225 }
4226
4227 template <int _AP_W2, bool _AP_S2>
4228 INLINE _private_bit_ref<_AP_W, _AP_S> operator[](
4229 const ap_private<_AP_W2, _AP_S2>& index) {
4230 return _private_bit_ref<_AP_W, _AP_S>(*this, index.to_int());
4231 }
4232
4233 template <int _AP_W2, bool _AP_S2>
4234 INLINE const _private_bit_ref<_AP_W, _AP_S> operator[](
4235 const ap_private<_AP_W2, _AP_S2>& index) const {
4237 const_cast<ap_private<_AP_W, _AP_S>&>(*this), index.to_int());
4238 }
4239
4240 INLINE const _private_bit_ref<_AP_W, _AP_S> operator[](int index) const {
4242 const_cast<ap_private<_AP_W, _AP_S>&>(*this), index);
4243 }
4244
4245 INLINE _private_bit_ref<_AP_W, _AP_S> bit(int index) {
4246 return _private_bit_ref<_AP_W, _AP_S>(*this, index);
4247 }
4248
4249 template <int _AP_W2, bool _AP_S2>
4251 const ap_private<_AP_W2, _AP_S2>& index) {
4252 return _private_bit_ref<_AP_W, _AP_S>(*this, index.to_int());
4253 }
4254
4255 INLINE const _private_bit_ref<_AP_W, _AP_S> bit(int index) const {
4257 const_cast<ap_private<_AP_W, _AP_S>&>(*this), index);
4258 }
4259
4260 template <int _AP_W2, bool _AP_S2>
4261 INLINE const _private_bit_ref<_AP_W, _AP_S> bit(
4262 const ap_private<_AP_W2, _AP_S2>& index) const {
4264 const_cast<ap_private<_AP_W, _AP_S>&>(*this), index.to_int());
4265 }
4266
4267 // template <int _AP_W2, bool _AP_S2>
4268 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
4269 // ap_private<_AP_W2, _AP_S2> >
4270 // concat(ap_private<_AP_W2, _AP_S2>& a2) {
4271 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
4272 // ap_private<_AP_W2, _AP_S2> >(*this, a2);
4273 // }
4274 //
4275 // template <int _AP_W2, bool _AP_S2>
4276 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
4277 // ap_private<_AP_W2, _AP_S2> >
4278 // concat(const ap_private<_AP_W2, _AP_S2>& a2) const {
4279 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
4280 // ap_private<_AP_W2, _AP_S2> >(
4281 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
4282 // const_cast<ap_private<_AP_W2, _AP_S2>&>(a2));
4283 // }
4284 //
4285 // template <int _AP_W2, bool _AP_S2>
4286 // INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2>
4287 // > operator,(ap_private<_AP_W2, _AP_S2> &a2) {
4288 // return ap_concat_ref<_AP_W, ap_private, _AP_W2,
4289 // ap_private<_AP_W2, _AP_S2> >(*this, a2);
4290 // }
4291 //
4292 // template <int _AP_W2, bool _AP_S2>
4293 // INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2>
4294 // > operator,(ap_private<_AP_W2, _AP_S2> &a2) const {
4295 // return ap_concat_ref<_AP_W, ap_private, _AP_W2,
4296 // ap_private<_AP_W2, _AP_S2> >(
4297 // const_cast<ap_private<_AP_W, _AP_S>&>(*this), a2);
4298 // }
4299 //
4300 // template <int _AP_W2, bool _AP_S2>
4301 // INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2>
4302 // > operator,(const ap_private<_AP_W2, _AP_S2> &a2) {
4303 // return ap_concat_ref<_AP_W, ap_private, _AP_W2,
4304 // ap_private<_AP_W2, _AP_S2> >(
4305 // *this, const_cast<ap_private<_AP_W2, _AP_S2>&>(a2));
4306 // }
4307 //
4308 // template <int _AP_W2, bool _AP_S2>
4309 // INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2>
4310 // > operator,(const ap_private<_AP_W2, _AP_S2> &a2) const {
4311 // return ap_concat_ref<_AP_W, ap_private, _AP_W2,
4312 // ap_private<_AP_W2, _AP_S2> >(
4313 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
4314 // const_cast<ap_private<_AP_W2, _AP_S2>&>(a2));
4315 // }
4316 //
4317 // template <int _AP_W2, bool _AP_S2>
4318 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
4319 // _private_range_ref<_AP_W2, _AP_S2> >
4320 // operator,(const _private_range_ref<_AP_W2, _AP_S2> &a2) const {
4321 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
4322 // _private_range_ref<_AP_W2, _AP_S2> >(
4323 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
4324 // const_cast<_private_range_ref<_AP_W2, _AP_S2>&>(a2));
4325 // }
4326 //
4327 // template <int _AP_W2, bool _AP_S2>
4328 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
4329 // _private_range_ref<_AP_W2, _AP_S2> >
4330 // operator,(_private_range_ref<_AP_W2, _AP_S2> &a2) {
4331 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2,
4332 // _private_range_ref<_AP_W2, _AP_S2> >(*this, a2);
4333 // }
4334 //
4335 // template <int _AP_W2, bool _AP_S2>
4336 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1,
4337 // _private_bit_ref<_AP_W2, _AP_S2> >
4338 // operator,(const _private_bit_ref<_AP_W2, _AP_S2> &a2) const {
4339 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1,
4340 // _private_bit_ref<_AP_W2, _AP_S2> >(
4341 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
4342 // const_cast<_private_bit_ref<_AP_W2, _AP_S2>&>(a2));
4343 // }
4344 //
4345 // template <int _AP_W2, bool _AP_S2>
4346 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1,
4347 // _private_bit_ref<_AP_W2, _AP_S2> >
4348 // operator,(_private_bit_ref<_AP_W2, _AP_S2> &a2) {
4349 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1,
4350 // _private_bit_ref<_AP_W2, _AP_S2> >(*this, a2);
4351 // }
4352 //
4353 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
4354 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3,
4355 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >
4356 // operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const {
4357 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3,
4358 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(
4359 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
4360 // const_cast<ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>&>(a2));
4361 // }
4362 //
4363 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
4364 // INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3,
4365 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >
4366 // operator,(ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) {
4367 // return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3,
4368 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>
4369 // >(*this,
4370 // a2);
4371 // }
4372 //
4373 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
4374 // ap_o_mode _AP_O2, int _AP_N2>
4375 // INLINE ap_concat_ref<
4376 // _AP_W, ap_private, _AP_W2,
4377 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >
4378 // operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
4379 // _AP_N2>
4380 // &a2) const {
4381 // return ap_concat_ref<
4382 // _AP_W, ap_private, _AP_W2,
4383 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(
4384 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
4385 // const_cast<
4386 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
4387 // _AP_N2>&>(a2));
4388 // }
4389 //
4390 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
4391 // ap_o_mode _AP_O2, int _AP_N2>
4392 // INLINE ap_concat_ref<
4393 // _AP_W, ap_private, _AP_W2,
4394 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >
4395 // operator,(af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>
4396 // &a2) {
4397 // return ap_concat_ref<
4398 // _AP_W, ap_private, _AP_W2,
4399 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>
4400 // >(*this,
4401 // a2);
4402 // }
4403 //
4404 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
4405 // ap_o_mode _AP_O2, int _AP_N2>
4406 // INLINE
4407 // ap_concat_ref<_AP_W, ap_private, 1,
4408 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
4409 // _AP_N2> >
4410 // operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
4411 // _AP_N2>
4412 // &a2) const {
4413 // return ap_concat_ref<
4414 // _AP_W, ap_private, 1,
4415 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(
4416 // const_cast<ap_private<_AP_W, _AP_S>&>(*this),
4417 // const_cast<af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
4418 // _AP_N2>&>(
4419 // a2));
4420 // }
4421 //
4422 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
4423 // ap_o_mode _AP_O2, int _AP_N2>
4424 // INLINE
4425 // ap_concat_ref<_AP_W, ap_private, 1,
4426 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
4427 // _AP_N2> >
4428 // operator,(
4429 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) {
4430 // return ap_concat_ref<
4431 // _AP_W, ap_private, 1,
4432 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this,
4433 // a2);
4434 // }
4435
4436 INLINE ap_private<_AP_W, false> get() const {
4437 ap_private<_AP_W, false> ret(*this);
4438 return ret;
4439 }
4440
4441 template <int _AP_W3>
4442 INLINE void set(const ap_private<_AP_W3, false>& val) {
4443 operator=(ap_private<_AP_W3, _AP_S>(val));
4444 }
4445
4452 INLINE bool isNegative() const {
4453 // just for get rid of warnings
4454 enum { shift = (_AP_W - APINT_BITS_PER_WORD * (_AP_N - 1) - 1) };
4455 static const uint64_t mask = 1ULL << (shift);
4456 return _AP_S && (pVal[_AP_N - 1] & mask);
4457 }
4458
4461 INLINE bool isPositive() const { return !isNegative(); }
4462
4466 INLINE bool isStrictlyPositive() const {
4467 return isPositive() && (*this) != 0;
4468 }
4469
4473 INLINE bool isAllOnesValue() const { return countPopulation() == _AP_W; }
4474
4478 INLINE bool isMaxValue() const { return countPopulation() == _AP_W; }
4479
4483 INLINE bool isMaxSignedValue() const {
4484 return !isNegative() && countPopulation() == _AP_W - 1;
4485 }
4486
4490 INLINE bool isMinValue() const { return countPopulation() == 0; }
4491
4495 INLINE bool isMinSignedValue() const {
4496 return isNegative() && countPopulation() == 1;
4497 }
4498
4502 INLINE const uint64_t* getRawData() const { return &pVal[0]; }
4503
4504 // Square Root - this method computes and returns the square root of "this".
4505 // Three mechanisms are used for computation. For small values (<= 5 bits),
4506 // a table lookup is done. This gets some performance for common cases. For
4507 // values using less than 52 bits, the value is converted to double and then
4508 // the libc sqrt function is called. The result is rounded and then converted
4509 // back to a uint64_t which is then used to construct the result. Finally,
4510 // the Babylonian method for computing square roots is used.
4511 INLINE ap_private sqrt() const {
4512 // Determine the magnitude of the value.
4513 uint32_t magnitude = getActiveBits();
4514
4515 // Use a fast table for some small values. This also gets rid of some
4516 // rounding errors in libc sqrt for small values.
4517 if (magnitude <= 5) {
4518 static const uint8_t results[32] = {
4519 /* 0 */ 0,
4520 /* 1- 2 */ 1, 1,
4521 /* 3- 6 */ 2, 2, 2, 2,
4522 /* 7-12 */ 3, 3, 3, 3, 3, 3,
4523 /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4,
4524 /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4525 /* 31 */ 6};
4526 return ap_private<_AP_W, _AP_S>(/*BitWidth,*/ results[get_VAL()]);
4527 }
4528
4529 // If the magnitude of the value fits in less than 52 bits (the precision of
4530 // an IEEE double precision floating point value), then we can use the
4531 // libc sqrt function which will probably use a hardware sqrt computation.
4532 // This should be faster than the algorithm below.
4533 if (magnitude < 52) {
4534#ifdef _MSC_VER
4535 // Amazingly, VC++ doesn't have round().
4536 return ap_private<_AP_W, _AP_S>(/*BitWidth,*/
4537 uint64_t(::sqrt(double(get_VAL()))) +
4538 0.5);
4539#else
4540 return ap_private<_AP_W, _AP_S>(/*BitWidth,*/
4541 uint64_t(
4542 ::round(::sqrt(double(get_VAL())))));
4543#endif
4544 }
4545
4546 // Okay, all the short cuts are exhausted. We must compute it. The following
4547 // is a classical Babylonian method for computing the square root. This code
4548 // was adapted to APINt from a wikipedia article on such computations.
4549 // See http://www.wikipedia.org/ and go to the page named
4550 // Calculate_an_integer_square_root.
4551 uint32_t nbits = BitWidth, i = 4;
4552 ap_private<_AP_W, _AP_S> testy(16);
4553 ap_private<_AP_W, _AP_S> x_old(/*BitWidth,*/ 1);
4554 ap_private<_AP_W, _AP_S> x_new(0);
4555 ap_private<_AP_W, _AP_S> two(/*BitWidth,*/ 2);
4556
4557 // Select a good starting value using binary logarithms.
4558 for (;; i += 2, testy = testy.shl(2))
4559 if (i >= nbits || this->ule(testy)) {
4560 x_old = x_old.shl(i / 2);
4561 break;
4562 }
4563
4564 // Use the Babylonian method to arrive at the integer square root:
4565 for (;;) {
4566 x_new = (this->udiv(x_old) + x_old).udiv(two);
4567 if (x_old.ule(x_new)) break;
4568 x_old = x_new;
4569 }
4570
4571 // Make sure we return the closest approximation
4572 // NOTE: The rounding calculation below is correct. It will produce an
4573 // off-by-one discrepancy with results from pari/gp. That discrepancy has
4574 // been
4575 // determined to be a rounding issue with pari/gp as it begins to use a
4576 // floating point representation after 192 bits. There are no discrepancies
4577 // between this algorithm and pari/gp for bit widths < 192 bits.
4578 ap_private<_AP_W, _AP_S> square(x_old * x_old);
4579 ap_private<_AP_W, _AP_S> nextSquare((x_old + 1) * (x_old + 1));
4580 if (this->ult(square))
4581 return x_old;
4582 else if (this->ule(nextSquare)) {
4583 ap_private<_AP_W, _AP_S> midpoint((nextSquare - square).udiv(two));
4584 ap_private<_AP_W, _AP_S> offset(*this - square);
4585 if (offset.ult(midpoint))
4586 return x_old;
4587 else
4588 return x_old + 1;
4589 } else
4590 assert(0 && "Error in ap_private<_AP_W, _AP_S>::sqrt computation");
4591 return x_old + 1;
4592 }
4593
4599 INLINE ap_private& operator=(const ap_private& RHS) {
4600 if (this != &RHS) memcpy(pVal, RHS.get_pVal(), _AP_N * APINT_WORD_SIZE);
4601 clearUnusedBits();
4602 return *this;
4603 }
4604 INLINE ap_private& operator=(const volatile ap_private& RHS) {
4605 if (this != &RHS)
4606 for (int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i);
4607 clearUnusedBits();
4608 return *this;
4609 }
4610 INLINE void operator=(const ap_private& RHS) volatile {
4611 if (this != &RHS)
4612 for (int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i);
4613 clearUnusedBits();
4614 }
4615 INLINE void operator=(const volatile ap_private& RHS) volatile {
4616 if (this != &RHS)
4617 for (int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i);
4618 clearUnusedBits();
4619 }
4620
4621 template <int _AP_W1, bool _AP_S1>
4622 INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1>& RHS) {
4623 if (_AP_S1)
4624 cpSextOrTrunc(RHS);
4625 else
4626 cpZextOrTrunc(RHS);
4627 clearUnusedBits();
4628 return *this;
4629 }
4630
4631 template <int _AP_W1, bool _AP_S1>
4632 INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1>& RHS) {
4633 if (_AP_S1)
4634 cpSextOrTrunc(RHS);
4635 else
4636 cpZextOrTrunc(RHS);
4637 clearUnusedBits();
4638 return *this;
4639 }
4640
4641 template <int _AP_W2, bool _AP_S2>
4642 INLINE ap_private& operator=(const _private_range_ref<_AP_W2, _AP_S2>& op2) {
4643 *this = ap_private<_AP_W2, false>(op2);
4644 return *this;
4645 }
4646
4647#if 0
4648 template<int _AP_W1, bool _AP_S1>
4649 INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, true>& RHS) {
4650 static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD);
4651 if (RHS.isNegative()) {
4652 pVal[0] = RHS.get_VAL() | that_sign_ext_mask;
4653 memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1));
4654 } else {
4655 pVal[0] = RHS.get_VAL();
4656 memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1));
4657 }
4658 clearUnusedBits();
4659 return *this;
4660 }
4661
4662 template<int _AP_W1, bool _AP_S1>
4663 INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, true>& RHS) {
4664 static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD);
4665 if (RHS.isNegative()) {
4666 pVal[0] = RHS.get_VAL() | that_sign_ext_mask;
4667 memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1));
4668 } else {
4669 pVal[0] = RHS.get_VAL();
4670 memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1));
4671 }
4672 clearUnusedBits();
4673 return *this;
4674 }
4675#endif
4676
4678#define ASSIGN_OP_FROM_INT(C_TYPE, _AP_W2, _AP_S2) \
4679 INLINE ap_private& operator=(const C_TYPE rhs) { \
4680 ap_private<(_AP_W2), (_AP_S2)> tmp = rhs; \
4681 operator=(tmp); \
4682 return *this; \
4683 }
4684
4685 ASSIGN_OP_FROM_INT(bool, 1, false)
4686 ASSIGN_OP_FROM_INT(char, 8, CHAR_IS_SIGNED)
4687 ASSIGN_OP_FROM_INT(signed char, 8, true)
4688 ASSIGN_OP_FROM_INT(unsigned char, 8, false)
4689 ASSIGN_OP_FROM_INT(short, sizeof(short) * 8, true)
4690 ASSIGN_OP_FROM_INT(unsigned short, sizeof(unsigned short) * 8, false)
4691 ASSIGN_OP_FROM_INT(int, sizeof(int) * 8, true)
4692 ASSIGN_OP_FROM_INT(unsigned int, sizeof(unsigned int) * 8, false)
4693 ASSIGN_OP_FROM_INT(long, sizeof(long) * 8, true)
4694 ASSIGN_OP_FROM_INT(unsigned long, sizeof(unsigned long) * 8, false)
4695 ASSIGN_OP_FROM_INT(ap_slong, sizeof(ap_slong) * 8, true)
4696 ASSIGN_OP_FROM_INT(ap_ulong, sizeof(ap_ulong) * 8, false)
4697#undef ASSIGN_OP_FROM_INT
4698
4700 // XXX this is a must, to prevent pointer being converted to bool.
4701 INLINE ap_private& operator=(const char* s) {
4702 ap_private tmp(s); // XXX direct initialization, as ctor is explicit.
4703 operator=(tmp);
4704 return *this;
4705 }
4706
4712 INLINE const ap_private operator++(int) {
4713 ap_private API(*this);
4714 ++(*this);
4715 return API;
4716 }
4717
4720 INLINE ap_private& operator++() {
4721 ap_private_ops::add_1(pVal, pVal, _AP_N, 1);
4722 clearUnusedBits();
4723 return *this;
4724 }
4725
4728 INLINE const ap_private operator--(int) {
4729 ap_private API(*this);
4730 --(*this);
4731 return API;
4732 }
4733
4736 INLINE ap_private& operator--() {
4737 ap_private_ops::sub_1(pVal, _AP_N, 1);
4738 clearUnusedBits();
4739 return *this;
4740 }
4741
4745 INLINE ap_private<_AP_W + !_AP_S, true> operator~() const {
4746 ap_private<_AP_W + !_AP_S, true> Result(*this);
4747 Result.flip();
4748 return Result;
4749 }
4750
4754 INLINE typename RType<1, false>::minus operator-() const {
4755 return ap_private<1, false>(0) - (*this);
4756 }
4757
4761 INLINE bool operator!() const {
4762 for (int i = 0; i < _AP_N; ++i)
4763 if (pVal[i]) return false;
4764 return true;
4765 }
4766
4767 template <bool _AP_S1>
4768 INLINE ap_private<_AP_W, _AP_S || _AP_S1> And(
4769 const ap_private<_AP_W, _AP_S1>& RHS) const {
4770 return this->operator&(RHS);
4771 }
4772 template <bool _AP_S1>
4773 INLINE ap_private Or(const ap_private<_AP_W, _AP_S1>& RHS) const {
4774 return this->operator|(RHS);
4775 }
4776 template <bool _AP_S1>
4777 INLINE ap_private Xor(const ap_private<_AP_W, _AP_S1>& RHS) const {
4778 return this->operator^(RHS);
4779 }
4780
4781 INLINE ap_private Mul(const ap_private& RHS) const {
4782 ap_private Result(*this);
4783 Result *= RHS;
4784 return Result;
4785 }
4786
4787 INLINE ap_private Add(const ap_private& RHS) const {
4788 ap_private Result(0);
4789 ap_private_ops::add(Result.get_pVal(), pVal, RHS.get_pVal(), _AP_N, _AP_N,
4790 _AP_N, _AP_S, _AP_S);
4791 Result.clearUnusedBits();
4792 return Result;
4793 }
4794
4795 INLINE ap_private Sub(const ap_private& RHS) const {
4796 ap_private Result(0);
4797 ap_private_ops::sub(Result.get_pVal(), pVal, RHS.get_pVal(), _AP_N, _AP_N,
4798 _AP_N, _AP_S, _AP_S);
4799 Result.clearUnusedBits();
4800 return Result;
4801 }
4802
4805 INLINE ap_private ashr(uint32_t shiftAmt) const {
4806 assert(shiftAmt <= BitWidth && "Invalid shift amount, too big");
4807 // Handle a degenerate case
4808 if (shiftAmt == 0) return ap_private(*this);
4809
4810 // If all the bits were shifted out, the result is, technically, undefined.
4811 // We return -1 if it was negative, 0 otherwise. We check this early to
4812 // avoid
4813 // issues in the algorithm below.
4814 if (shiftAmt == BitWidth) {
4815 if (isNegative())
4816 return ap_private(-1);
4817 else
4818 return ap_private(0);
4819 }
4820
4821 // Create some space for the result.
4822 ap_private Retval(0);
4823 uint64_t* val = Retval.get_pVal();
4824
4825 // Compute some values needed by the following shift algorithms
4826 uint32_t wordShift =
4827 shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word
4828 uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift
4829 uint32_t breakWord = _AP_N - 1 - offset; // last word affected
4830 uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word?
4831 if (bitsInWord == 0) bitsInWord = APINT_BITS_PER_WORD;
4832
4833 // If we are shifting whole words, just move whole words
4834 if (wordShift == 0) {
4835 // Move the words containing significant bits
4836 for (uint32_t i = 0; i <= breakWord; ++i)
4837 val[i] = pVal[i + offset]; // move whole word
4838
4839 // Adjust the top significant word for sign bit fill, if negative
4840 if (isNegative())
4841 if (bitsInWord < APINT_BITS_PER_WORD)
4842 val[breakWord] |= ~0ULL << (bitsInWord); // set high bits
4843 } else {
4844 // Shift the low order words
4845 for (uint32_t i = 0; i < breakWord; ++i) {
4846 // This combines the shifted corresponding word with the low bits from
4847 // the next word (shifted into this word's high bits).
4848 val[i] = ((pVal[i + offset]) >> (wordShift));
4849 val[i] |= ((pVal[i + offset + 1]) << (APINT_BITS_PER_WORD - wordShift));
4850 }
4851
4852 // Shift the break word. In this case there are no bits from the next word
4853 // to include in this word.
4854 val[breakWord] = (pVal[breakWord + offset]) >> (wordShift);
4855
4856 // Deal with sign extenstion in the break word, and possibly the word
4857 // before
4858 // it.
4859 if (isNegative()) {
4860 if (wordShift > bitsInWord) {
4861 if (breakWord > 0)
4862 val[breakWord - 1] |=
4863 ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord));
4864 val[breakWord] |= ~0ULL;
4865 } else
4866 val[breakWord] |= (~0ULL << (bitsInWord - wordShift));
4867 }
4868 }
4869
4870 // Remaining words are 0 or -1, just assign them.
4871 uint64_t fillValue = (isNegative() ? ~0ULL : 0);
4872 for (int i = breakWord + 1; i < _AP_N; ++i) val[i] = fillValue;
4873 Retval.clearUnusedBits();
4874 return Retval;
4875 }
4876
4879 INLINE ap_private lshr(uint32_t shiftAmt) const {
4880 // If all the bits were shifted out, the result is 0. This avoids issues
4881 // with shifting by the size of the integer type, which produces undefined
4882 // results. We define these "undefined results" to always be 0.
4883 if (shiftAmt == BitWidth) return ap_private(0);
4884
4885 // If none of the bits are shifted out, the result is *this. This avoids
4886 // issues with shifting byt he size of the integer type, which produces
4887 // undefined results in the code below. This is also an optimization.
4888 if (shiftAmt == 0) return ap_private(*this);
4889
4890 // Create some space for the result.
4891 ap_private Retval(0);
4892 uint64_t* val = Retval.get_pVal();
4893
4894 // If we are shifting less than a word, compute the shift with a simple
4895 // carry
4896 if (shiftAmt < APINT_BITS_PER_WORD) {
4897 uint64_t carry = 0;
4898 for (int i = _AP_N - 1; i >= 0; --i) {
4899 val[i] = ((pVal[i]) >> (shiftAmt)) | carry;
4900 carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt);
4901 }
4902 Retval.clearUnusedBits();
4903 return Retval;
4904 }
4905
4906 // Compute some values needed by the remaining shift algorithms
4907 uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD;
4908 uint32_t offset = shiftAmt / APINT_BITS_PER_WORD;
4909
4910 // If we are shifting whole words, just move whole words
4911 if (wordShift == 0) {
4912 for (uint32_t i = 0; i < _AP_N - offset; ++i) val[i] = pVal[i + offset];
4913 for (uint32_t i = _AP_N - offset; i < _AP_N; i++) val[i] = 0;
4914 Retval.clearUnusedBits();
4915 return Retval;
4916 }
4917
4918 // Shift the low order words
4919 uint32_t breakWord = _AP_N - offset - 1;
4920 for (uint32_t i = 0; i < breakWord; ++i)
4921 val[i] = ((pVal[i + offset]) >> (wordShift)) |
4922 ((pVal[i + offset + 1]) << (APINT_BITS_PER_WORD - wordShift));
4923 // Shift the break word.
4924 val[breakWord] = (pVal[breakWord + offset]) >> (wordShift);
4925
4926 // Remaining words are 0
4927 for (int i = breakWord + 1; i < _AP_N; ++i) val[i] = 0;
4928 Retval.clearUnusedBits();
4929 return Retval;
4930 }
4931
4934 INLINE ap_private shl(uint32_t shiftAmt) const {
4935 assert(shiftAmt <= BitWidth && "Invalid shift amount, too big");
4936 // If all the bits were shifted out, the result is 0. This avoids issues
4937 // with shifting by the size of the integer type, which produces undefined
4938 // results. We define these "undefined results" to always be 0.
4939 if (shiftAmt == BitWidth) return ap_private(0);
4940
4941 // If none of the bits are shifted out, the result is *this. This avoids a
4942 // lshr by the words size in the loop below which can produce incorrect
4943 // results. It also avoids the expensive computation below for a common
4944 // case.
4945 if (shiftAmt == 0) return ap_private(*this);
4946
4947 // Create some space for the result.
4948 ap_private Retval(0);
4949 uint64_t* val = Retval.get_pVal();
4950 // If we are shifting less than a word, do it the easy way
4951 if (shiftAmt < APINT_BITS_PER_WORD) {
4952 uint64_t carry = 0;
4953 for (int i = 0; i < _AP_N; i++) {
4954 val[i] = ((pVal[i]) << (shiftAmt)) | carry;
4955 carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt);
4956 }
4957 Retval.clearUnusedBits();
4958 return Retval;
4959 }
4960
4961 // Compute some values needed by the remaining shift algorithms
4962 uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD;
4963 uint32_t offset = shiftAmt / APINT_BITS_PER_WORD;
4964
4965 // If we are shifting whole words, just move whole words
4966 if (wordShift == 0) {
4967 for (uint32_t i = 0; i < offset; i++) val[i] = 0;
4968 for (int i = offset; i < _AP_N; i++) val[i] = pVal[i - offset];
4969 Retval.clearUnusedBits();
4970 return Retval;
4971 }
4972
4973 // Copy whole words from this to Result.
4974 uint32_t i = _AP_N - 1;
4975 for (; i > offset; --i)
4976 val[i] = (pVal[i - offset]) << (wordShift) |
4977 (pVal[i - offset - 1]) >> (APINT_BITS_PER_WORD - wordShift);
4978 val[offset] = (pVal[0]) << (wordShift);
4979 for (i = 0; i < offset; ++i) val[i] = 0;
4980 Retval.clearUnusedBits();
4981 return Retval;
4982 }
4983
4984 INLINE ap_private rotl(uint32_t rotateAmt) const {
4985 if (rotateAmt == 0) return ap_private(*this);
4986 // Don't get too fancy, just use existing shift/or facilities
4987 ap_private hi(*this);
4988 ap_private lo(*this);
4989 hi.shl(rotateAmt);
4990 lo.lshr(BitWidth - rotateAmt);
4991 return hi | lo;
4992 }
4993
4994 INLINE ap_private rotr(uint32_t rotateAmt) const {
4995 if (rotateAmt == 0) return ap_private(*this);
4996 // Don't get too fancy, just use existing shift/or facilities
4997 ap_private hi(*this);
4998 ap_private lo(*this);
4999 lo.lshr(rotateAmt);
5000 hi.shl(BitWidth - rotateAmt);
5001 return hi | lo;
5002 }
5003
5009 INLINE ap_private udiv(const ap_private& RHS) const {
5010 // Get some facts about the LHS and RHS number of bits and words
5011 uint32_t rhsBits = RHS.getActiveBits();
5012 uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1);
5013 assert(rhsWords && "Divided by zero???");
5014 uint32_t lhsBits = this->getActiveBits();
5015 uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1);
5016
5017 // Deal with some degenerate cases
5018 if (!lhsWords)
5019 // 0 / X ===> 0
5020 return ap_private(0);
5021 else if (lhsWords < rhsWords || this->ult(RHS)) {
5022 // X / Y ===> 0, iff X < Y
5023 return ap_private(0);
5024 } else if (*this == RHS) {
5025 // X / X ===> 1
5026 return ap_private(1);
5027 } else if (lhsWords == 1 && rhsWords == 1) {
5028 // All high words are zero, just use native divide
5029 return ap_private(this->pVal[0] / RHS.get_pVal(0));
5030 }
5031
5032 // We have to compute it the hard way. Invoke the Knuth divide algorithm.
5033 ap_private Quotient(0); // to hold result.
5034 ap_private_ops::divide(*this, lhsWords, RHS, rhsWords, &Quotient,
5035 (ap_private*)0);
5036 return Quotient;
5037 }
5038
5041 INLINE ap_private sdiv(const ap_private& RHS) const {
5042 if (isNegative())
5043 if (RHS.isNegative())
5044 return (-(*this)).udiv(-RHS);
5045 else
5046 return -((-(*this)).udiv(RHS));
5047 else if (RHS.isNegative())
5048 return -(this->udiv((ap_private)(-RHS)));
5049 return this->udiv(RHS);
5050 }
5051
5060 INLINE ap_private urem(const ap_private& RHS) const {
5061 // Get some facts about the LHS
5062 uint32_t lhsBits = getActiveBits();
5063 uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1);
5064
5065 // Get some facts about the RHS
5066 uint32_t rhsBits = RHS.getActiveBits();
5067 uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1);
5068 assert(rhsWords && "Performing remainder operation by zero ???");
5069
5070 // Check the degenerate cases
5071 if (lhsWords == 0) {
5072 // 0 % Y ===> 0
5073 return ap_private(0);
5074 } else if (lhsWords < rhsWords || this->ult(RHS)) {
5075 // X % Y ===> X, iff X < Y
5076 return *this;
5077 } else if (*this == RHS) {
5078 // X % X == 0;
5079 return ap_private(0);
5080 } else if (lhsWords == 1) {
5081 // All high words are zero, just use native remainder
5082 return ap_private(pVal[0] % RHS.get_pVal(0));
5083 }
5084
5085 // We have to compute it the hard way. Invoke the Knuth divide algorithm.
5086 ap_private Remainder(0);
5087 ap_private_ops::divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0),
5088 &Remainder);
5089 return Remainder;
5090 }
5091
5092 INLINE ap_private urem(uint64_t RHS) const {
5093 // Get some facts about the LHS
5094 uint32_t lhsBits = getActiveBits();
5095 uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1);
5096 // Get some facts about the RHS
5097 uint32_t rhsWords = 1;
5099 assert(rhsWords && "Performing remainder operation by zero ???");
5100 // Check the degenerate cases
5101 if (lhsWords == 0) {
5102 // 0 % Y ===> 0
5103 return ap_private(0);
5104 } else if (lhsWords < rhsWords || this->ult(RHS)) {
5105 // X % Y ===> X, iff X < Y
5106 return *this;
5107 } else if (*this == RHS) {
5108 // X % X == 0;
5109 return ap_private(0);
5110 } else if (lhsWords == 1) {
5111 // All high words are zero, just use native remainder
5112 return ap_private(pVal[0] % RHS);
5113 }
5114
5115 // We have to compute it the hard way. Invoke the Knuth divide algorithm.
5116 ap_private Remainder(0);
5117 divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder);
5118 return Remainder;
5119 }
5120
5123 INLINE ap_private srem(const ap_private& RHS) const {
5124 if (isNegative()) {
5125 ap_private lhs = -(*this);
5126 if (RHS.isNegative()) {
5127 ap_private rhs = -RHS;
5128 return -(lhs.urem(rhs));
5129 } else
5130 return -(lhs.urem(RHS));
5131 } else if (RHS.isNegative()) {
5132 ap_private rhs = -RHS;
5133 return this->urem(rhs);
5134 }
5135 return this->urem(RHS);
5136 }
5137
5140 INLINE ap_private srem(int64_t RHS) const {
5141 if (isNegative())
5142 if (RHS < 0)
5143 return -((-(*this)).urem(-RHS));
5144 else
5145 return -((-(*this)).urem(RHS));
5146 else if (RHS < 0)
5147 return this->urem(-RHS);
5148 return this->urem(RHS);
5149 }
5150
5155 template <bool _AP_S1>
5156 INLINE bool eq(const ap_private<_AP_W, _AP_S1>& RHS) const {
5157 return (*this) == RHS;
5158 }
5159
5164 template <bool _AP_S1>
5165 INLINE bool ne(const ap_private<_AP_W, _AP_S1>& RHS) const {
5166 return !((*this) == RHS);
5167 }
5168
5173 template <bool _AP_S1>
5174 INLINE bool ult(const ap_private<_AP_W, _AP_S1>& RHS) const {
5175 // Get active bit length of both operands
5176 uint32_t n1 = getActiveBits();
5177 uint32_t n2 = RHS.getActiveBits();
5178
5179 // If magnitude of LHS is less than RHS, return true.
5180 if (n1 < n2) return true;
5181
5182 // If magnitude of RHS is greather than LHS, return false.
5183 if (n2 < n1) return false;
5184
5185 // If they bot fit in a word, just compare the low order word
5186 if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD)
5187 return pVal[0] < RHS.get_pVal(0);
5188
5189 // Otherwise, compare all words
5190 uint32_t topWord = whichWord(AESL_std::max(n1, n2) - 1);
5191 for (int i = topWord; i >= 0; --i) {
5192 if (pVal[i] > RHS.get_pVal(i)) return false;
5193 if (pVal[i] < RHS.get_pVal(i)) return true;
5194 }
5195 return false;
5196 }
5197
5198 INLINE bool ult(uint64_t RHS) const {
5199 // Get active bit length of both operands
5200 uint32_t n1 = getActiveBits();
5201 uint32_t n2 =
5202 64 - ap_private_ops::CountLeadingZeros_64(RHS); // RHS.getActiveBits();
5203
5204 // If magnitude of LHS is less than RHS, return true.
5205 if (n1 < n2) return true;
5206
5207 // If magnitude of RHS is greather than LHS, return false.
5208 if (n2 < n1) return false;
5209
5210 // If they bot fit in a word, just compare the low order word
5211 if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD)
5212 return pVal[0] < RHS;
5213 assert(0);
5214 }
5215
5216 template <bool _AP_S1>
5217 INLINE bool slt(const ap_private<_AP_W, _AP_S1>& RHS) const {
5218 ap_private lhs(*this);
5219 ap_private<_AP_W, _AP_S1> rhs(RHS);
5220 bool lhsNeg = isNegative();
5221 bool rhsNeg = rhs.isNegative();
5222 if (lhsNeg) {
5223 // Sign bit is set so perform two's complement to make it positive
5224 lhs.flip();
5225 lhs++;
5226 }
5227 if (rhsNeg) {
5228 // Sign bit is set so perform two's complement to make it positive
5229 rhs.flip();
5230 rhs++;
5231 }
5232
5233 // Now we have unsigned values to compare so do the comparison if necessary
5234 // based on the negativeness of the values.
5235 if (lhsNeg)
5236 if (rhsNeg)
5237 return lhs.ugt(rhs);
5238 else
5239 return true;
5240 else if (rhsNeg)
5241 return false;
5242 else
5243 return lhs.ult(rhs);
5244 }
5245
5250 template <bool _AP_S1>
5251 INLINE bool ule(const ap_private<_AP_W, _AP_S1>& RHS) const {
5252 return ult(RHS) || eq(RHS);
5253 }
5254
5259 template <bool _AP_S1>
5260 INLINE bool sle(const ap_private<_AP_W, _AP_S1>& RHS) const {
5261 return slt(RHS) || eq(RHS);
5262 }
5263
5268 template <bool _AP_S1>
5269 INLINE bool ugt(const ap_private<_AP_W, _AP_S1>& RHS) const {
5270 return !ult(RHS) && !eq(RHS);
5271 }
5272
5277 template <bool _AP_S1>
5278 INLINE bool sgt(const ap_private<_AP_W, _AP_S1>& RHS) const {
5279 return !slt(RHS) && !eq(RHS);
5280 }
5281
5286 template <bool _AP_S1>
5287 INLINE bool uge(const ap_private<_AP_W, _AP_S>& RHS) const {
5288 return !ult(RHS);
5289 }
5290
5295 template <bool _AP_S1>
5296 INLINE bool sge(const ap_private<_AP_W, _AP_S1>& RHS) const {
5297 return !slt(RHS);
5298 }
5299
5300 // Sign extend to a new width.
5301 template <int _AP_W1, bool _AP_S1>
5302 INLINE void cpSext(const ap_private<_AP_W1, _AP_S1>& that) {
5303 assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request");
5304 assert(_AP_W1 <= MAX_INT_BITS && "Too many bits");
5305 // If the sign bit isn't set, this is the same as zext.
5306 if (!that.isNegative()) {
5307 cpZext(that);
5308 return;
5309 }
5310
5311 // The sign bit is set. First, get some facts
5312 enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD };
5313 const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N;
5314 // Mask the high order word appropriately
5315 if (_AP_N1 == _AP_N) {
5316 enum { newWordBits = _AP_W % APINT_BITS_PER_WORD };
5317 // The extension is contained to the wordsBefore-1th word.
5318 static const uint64_t mask = wordBits ? (~0ULL << (wordBits)) : 0ULL;
5319 for (int i = 0; i < _AP_N; ++i) pVal[i] = that.get_pVal(i);
5320 pVal[_AP_N - 1] |= mask;
5321 return;
5322 }
5323
5324 enum { newWordBits = _AP_W % APINT_BITS_PER_WORD };
5325 // The extension is contained to the wordsBefore-1th word.
5326 static const uint64_t mask = wordBits ? (~0ULL << (wordBits)) : 0ULL;
5327 int i;
5328 for (i = 0; i < _AP_N1; ++i) pVal[i] = that.get_pVal(i);
5329 pVal[i - 1] |= mask;
5330 for (; i < _AP_N - 1; i++) pVal[i] = ~0ULL;
5331 pVal[i] = ~0ULL;
5332 clearUnusedBits();
5333 return;
5334 }
5335
5336 // Zero extend to a new width.
5337 template <int _AP_W1, bool _AP_S1>
5338 INLINE void cpZext(const ap_private<_AP_W1, _AP_S1>& that) {
5339 assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request");
5340 assert(_AP_W1 <= MAX_INT_BITS && "Too many bits");
5341 const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N;
5342 int i = 0;
5343 for (; i < _AP_N1; ++i) pVal[i] = that.get_pVal(i);
5344 for (; i < _AP_N; ++i) pVal[i] = 0;
5345 clearUnusedBits();
5346 }
5347
5348 template <int _AP_W1, bool _AP_S1>
5349 INLINE void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1>& that) {
5350 if (BitWidth > _AP_W1)
5351 cpZext(that);
5352 else {
5353 for (int i = 0; i < _AP_N; ++i) pVal[i] = that.get_pVal(i);
5354 clearUnusedBits();
5355 }
5356 }
5357
5358 template <int _AP_W1, bool _AP_S1>
5359 INLINE void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1>& that) {
5360 if (BitWidth > _AP_W1)
5361 cpSext(that);
5362 else {
5363 for (int i = 0; i < _AP_N; ++i) pVal[i] = that.get_pVal(i);
5364 clearUnusedBits();
5365 }
5366 }
5367
5371
5373 INLINE uint32_t getBitWidth() const { return BitWidth; }
5374
5378 INLINE uint32_t getNumWords() const {
5379 return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
5380 }
5381
5386 INLINE uint32_t getActiveBits() const {
5387 uint32_t bits = BitWidth - countLeadingZeros();
5388 return bits ? bits : 1;
5389 }
5390
5396 INLINE uint64_t getZExtValue() const {
5397 assert(getActiveBits() <= 64 && "Too many bits for uint64_t");
5398 return *pVal;
5399 }
5400
5406 INLINE int64_t getSExtValue() const {
5407 assert(getActiveBits() <= 64 && "Too many bits for int64_t");
5408 return int64_t(pVal[0]);
5409 }
5410
5414 INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen,
5415 uint8_t radix) {
5416 assert(str != 0 && "Invalid value string");
5417 assert(slen > 0 && "Invalid string length");
5418
5419 // Each computation below needs to know if its negative
5420 uint32_t isNegative = str[0] == '-';
5421 if (isNegative) {
5422 slen--;
5423 str++;
5424 }
5425 // For radixes of power-of-two values, the bits required is accurately and
5426 // easily computed
5427 if (radix == 2) return slen + isNegative;
5428 if (radix == 8) return slen * 3 + isNegative;
5429 if (radix == 16) return slen * 4 + isNegative;
5430
5431 // Otherwise it must be radix == 10, the hard case
5432 assert(radix == 10 && "Invalid radix");
5433
5434 // Convert to the actual binary value.
5435 // ap_private<_AP_W, _AP_S> tmp(sufficient, str, slen, radix);
5436
5437 // Compute how many bits are required.
5438 // return isNegative + tmp.logBase2() + 1;
5439 return isNegative + slen * 4;
5440 }
5441
5448 INLINE uint32_t countLeadingZeros() const {
5449 enum {
5450 msw_bits = (BitWidth % APINT_BITS_PER_WORD)
5451 ? (BitWidth % APINT_BITS_PER_WORD)
5452 : APINT_BITS_PER_WORD,
5453 excessBits = APINT_BITS_PER_WORD - msw_bits
5454 };
5455 uint32_t Count = ap_private_ops::CountLeadingZeros_64(pVal[_AP_N - 1]);
5456 if (Count >= excessBits) Count -= excessBits;
5457 if (!pVal[_AP_N - 1]) {
5458 for (int i = _AP_N - 1; i; --i) {
5459 if (!pVal[i - 1])
5460 Count += APINT_BITS_PER_WORD;
5461 else {
5462 Count += ap_private_ops::CountLeadingZeros_64(pVal[i - 1]);
5463 break;
5464 }
5465 }
5466 }
5467 return Count;
5468 }
5469
5475 INLINE uint32_t countLeadingOnes() const {
5476 if (isSingleWord())
5477 return countLeadingOnes_64(get_VAL(), APINT_BITS_PER_WORD - BitWidth);
5478
5479 uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD;
5480 uint32_t shift =
5481 (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits);
5482 int i = _AP_N - 1;
5483 uint32_t Count = countLeadingOnes_64(get_pVal(i), shift);
5484 if (Count == highWordBits) {
5485 for (i--; i >= 0; --i) {
5486 if (get_pVal(i) == ~0ULL)
5487 Count += APINT_BITS_PER_WORD;
5488 else {
5489 Count += countLeadingOnes_64(get_pVal(i), 0);
5490 break;
5491 }
5492 }
5493 }
5494 return Count;
5495 }
5496
5504 INLINE uint32_t countTrailingZeros() const {
5505 uint32_t Count = 0;
5506 uint32_t i = 0;
5507 for (; i < _AP_N && get_pVal(i) == 0; ++i) Count += APINT_BITS_PER_WORD;
5508 if (i < _AP_N) Count += ap_private_ops::CountTrailingZeros_64(get_pVal(i));
5509 return AESL_std::min(Count, BitWidth);
5510 }
5517 INLINE uint32_t countPopulation() const {
5518 uint32_t Count = 0;
5519 for (int i = 0; i < _AP_N - 1; ++i)
5520 Count += ap_private_ops::CountPopulation_64(pVal[i]);
5521 Count += ap_private_ops::CountPopulation_64(pVal[_AP_N - 1] & mask);
5522 return Count;
5523 }
5524
5528
5531 INLINE std::string toString(uint8_t radix, bool wantSigned) const;
5532
5538 INLINE std::string toStringUnsigned(uint8_t radix = 10) const {
5539 return toString(radix, false);
5540 }
5541
5547 INLINE std::string toStringSigned(uint8_t radix = 10) const {
5548 return toString(radix, true);
5549 }
5550
5552 INLINE double roundToDouble(bool isSigned) const {
5553 // Handle the simple case where the value is contained in one uint64_t.
5554 if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) {
5555 uint64_t val = pVal[0];
5556 if (isSigned) {
5557 int64_t sext = ((int64_t(val)) << (64 - BitWidth)) >> (64 - BitWidth);
5558 return double(sext);
5559 } else
5560 return double(val);
5561 }
5562
5563 // Determine if the value is negative.
5564 bool isNeg = isSigned ? (*this)[BitWidth - 1] : false;
5565
5566 // Construct the absolute value if we're negative.
5567 ap_private<_AP_W, _AP_S> Tmp(isNeg ? -(*this) : (*this));
5568
5569 // Figure out how many bits we're using.
5570 uint32_t n = Tmp.getActiveBits();
5571
5572 // The exponent (without bias normalization) is just the number of bits
5573 // we are using. Note that the sign bit is gone since we constructed the
5574 // absolute value.
5575 uint64_t exp = n;
5576
5577 // Return infinity for exponent overflow
5578 if (exp > 1023) {
5579 if (!isSigned || !isNeg)
5580 return std::numeric_limits<double>::infinity();
5581 else
5582 return -std::numeric_limits<double>::infinity();
5583 }
5584 exp += 1023; // Increment for 1023 bias
5585
5586 // Number of bits in mantissa is 52. To obtain the mantissa value, we must
5587 // extract the high 52 bits from the correct words in pVal.
5588 uint64_t mantissa;
5589 unsigned hiWord = whichWord(n - 1);
5590 if (hiWord == 0) {
5591 mantissa = Tmp.get_pVal(0);
5592 if (n > 52)
5593 (mantissa) >>= (n - 52); // shift down, we want the top 52 bits.
5594 } else {
5595 assert(hiWord > 0 && "High word is negative?");
5596 uint64_t hibits = (Tmp.get_pVal(hiWord))
5597 << (52 - n % APINT_BITS_PER_WORD);
5598 uint64_t lobits =
5599 (Tmp.get_pVal(hiWord - 1)) >> (11 + n % APINT_BITS_PER_WORD);
5600 mantissa = hibits | lobits;
5601 }
5602
5603 // The leading bit of mantissa is implicit, so get rid of it.
5604 uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0;
5605 union {
5606 double __D;
5607 uint64_t __I;
5608 } __T;
5609 __T.__I = sign | ((exp) << 52) | mantissa;
5610 return __T.__D;
5611 }
5612
5614 INLINE double roundToDouble() const { return roundToDouble(false); }
5615
5617 INLINE double signedRoundToDouble() const { return roundToDouble(true); }
5618
5623 INLINE double bitsToDouble() const {
5624 union {
5625 uint64_t __I;
5626 double __D;
5627 } __T;
5628 __T.__I = pVal[0];
5629 return __T.__D;
5630 }
5631
5636 INLINE float bitsToFloat() const {
5637 union {
5638 uint32_t __I;
5639 float __F;
5640 } __T;
5641 __T.__I = uint32_t(pVal[0]);
5642 return __T.__F;
5643 }
5644
5649 INLINE ap_private& doubleToBits(double __V) {
5650 union {
5651 uint64_t __I;
5652 double __D;
5653 } __T;
5654 __T.__D = __V;
5655 pVal[0] = __T.__I;
5656 return *this;
5657 }
5658
5663 INLINE ap_private& floatToBits(float __V) {
5664 union {
5665 uint32_t __I;
5666 float __F;
5667 } __T;
5668 __T.__F = __V;
5669 pVal[0] = __T.__I;
5670 }
5671
5672 // Reduce operation
5673 //-----------------------------------------------------------
5674 INLINE bool and_reduce() const { return isMaxValue(); }
5675
5676 INLINE bool nand_reduce() const { return isMinValue(); }
5677
5678 INLINE bool or_reduce() const { return (bool)countPopulation(); }
5679
5680 INLINE bool nor_reduce() const { return countPopulation() == 0; }
5681
5682 INLINE bool xor_reduce() const {
5683 unsigned int i = countPopulation();
5684 return (i % 2) ? true : false;
5685 }
5686
5687 INLINE bool xnor_reduce() const {
5688 unsigned int i = countPopulation();
5689 return (i % 2) ? false : true;
5690 }
5691 INLINE std::string to_string(uint8_t radix = 16, bool sign = false) const {
5692 return toString(radix, radix == 10 ? _AP_S : sign);
5693 }
5694}; // End of class ap_private <_AP_W, _AP_S, false>
5695
5696namespace ap_private_ops {
5697
5698enum { APINT_BITS_PER_WORD = 64 };
5699template <int _AP_W, bool _AP_S>
5700INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S>& V2) {
5701 return V2 == V1;
5702}
5703
5704template <int _AP_W, bool _AP_S>
5705INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S>& V2) {
5706 return V2 != V1;
5707}
5708
5709template <int _AP_W, bool _AP_S, int index>
5710INLINE bool get(const ap_private<_AP_W, _AP_S>& a) {
5711 static const uint64_t mask = 1ULL << (index & 0x3f);
5712 return ((mask & a.get_pVal((index) >> 6)) != 0);
5713}
5714
5715template <int _AP_W, bool _AP_S, int msb_index, int lsb_index>
5716INLINE void set(ap_private<_AP_W, _AP_S>& a,
5717 const ap_private<AP_MAX(msb_index, 1), true>& mark1 = 0,
5718 const ap_private<AP_MAX(lsb_index, 1), true>& mark2 = 0) {
5719 enum {
5720 APINT_BITS_PER_WORD = 64,
5721 lsb_word = lsb_index / APINT_BITS_PER_WORD,
5722 msb_word = msb_index / APINT_BITS_PER_WORD,
5723 msb = msb_index % APINT_BITS_PER_WORD,
5724 lsb = lsb_index % APINT_BITS_PER_WORD
5725 };
5726 if (msb_word == lsb_word) {
5727 const uint64_t mask = ~0ULL >>
5728 (lsb) << (APINT_BITS_PER_WORD - msb + lsb - 1) >>
5729 (APINT_BITS_PER_WORD - msb - 1);
5730 // a.set_pVal(msb_word, a.get_pVal(msb_word) | mask);
5731 a.get_pVal(msb_word) |= mask;
5732 } else {
5733 const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb);
5734 const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD - msb - 1) >>
5735 (APINT_BITS_PER_WORD - msb - 1);
5736 // a.set_pVal(lsb_word, a.get_pVal(lsb_word) | lsb_mask);
5737 a.get_pVal(lsb_word) |= lsb_mask;
5738 for (int i = lsb_word + 1; i < msb_word; i++) {
5739 a.set_pVal(i, ~0ULL);
5740 // a.get_pVal(i)=0;
5741 }
5742 // a.set_pVal(msb_word, a.get_pVal(msb_word) | msb_mask);
5743
5744 a.get_pVal(msb_word) |= msb_mask;
5745 }
5746 a.clearUnusedBits();
5747}
5748
5749template <int _AP_W, bool _AP_S, int msb_index, int lsb_index>
5750INLINE void clear(ap_private<_AP_W, _AP_S>& a,
5751 const ap_private<AP_MAX(msb_index, 1), true>& mark1 = 0,
5752 const ap_private<AP_MAX(lsb_index, 1), true>& mark2 = 0) {
5753 enum {
5754 APINT_BITS_PER_WORD = 64,
5755 lsb_word = lsb_index / APINT_BITS_PER_WORD,
5756 msb_word = msb_index / APINT_BITS_PER_WORD,
5757 msb = msb_index % APINT_BITS_PER_WORD,
5758 lsb = lsb_index % APINT_BITS_PER_WORD
5759 };
5760 if (msb_word == lsb_word) {
5761 const uint64_t mask =
5762 ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD - msb + lsb - 1) >>
5763 (APINT_BITS_PER_WORD - msb - 1));
5764 // a.set_pVal(msb_word, a.get_pVal(msb_word) & mask);
5765 a.get_pVal(msb_word) &= mask;
5766 } else {
5767 const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb));
5768 const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD - msb - 1) >>
5769 (APINT_BITS_PER_WORD - msb - 1));
5770 // a.set_pVal(lsb_word, a.get_pVal(lsb_word) & lsb_mask);
5771 a.get_pVal(lsb_word) &= lsb_mask;
5772 for (int i = lsb_word + 1; i < msb_word; i++) {
5773 // a.set_pVal(i, 0);
5774 a.get_pVal(i) = 0;
5775 }
5776 // a.set_pVal(msb_word, a.get_pVal(msb_word) & msb_mask);
5777 a.get_pVal(msb_word) &= msb_mask;
5778 }
5779 a.clearUnusedBits();
5780}
5781
5782template <int _AP_W, bool _AP_S, int index>
5783INLINE void set(ap_private<_AP_W, _AP_S>& a,
5784 const ap_private<AP_MAX(index, 1), true>& mark = 0) {
5785 enum { APINT_BITS_PER_WORD = 64, word = index / APINT_BITS_PER_WORD };
5786 static const uint64_t mask = 1ULL << (index % APINT_BITS_PER_WORD);
5787 // a.set_pVal(word, a.get_pVal(word) | mask);
5788 a.get_pVal(word) |= mask;
5789 a.clearUnusedBits();
5790}
5791
5792template <int _AP_W, bool _AP_S, int index>
5793INLINE void clear(ap_private<_AP_W, _AP_S>& a,
5794 const ap_private<AP_MAX(index, 1), true>& mark = 0) {
5795 enum { APINT_BITS_PER_WORD = 64, word = index / APINT_BITS_PER_WORD };
5796 static const uint64_t mask = ~(1ULL << (index % APINT_BITS_PER_WORD));
5797 // a.set_pVal(word, a.get_pVal(word) & mask);
5798 a.get_pVal(word) &= mask;
5799 a.clearUnusedBits();
5800}
5801
5802} // namespace ap_private_ops
5803
5804template <int _AP_W, bool _AP_S>
5805INLINE std::string ap_private<_AP_W, _AP_S, false>::toString(
5806 uint8_t radix, bool wantSigned) const {
5807 assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
5808 "Radix should be 2, 8, 10, or 16!");
5809 static const char* digits[] = {"0", "1", "2", "3", "4", "5", "6", "7",
5810 "8", "9", "A", "B", "C", "D", "E", "F"};
5811 std::string result;
5812
5813 if (radix != 10) {
5814 // For the 2, 8 and 16 bit cases, we can just shift instead of divide
5815 // because the number of bits per digit (1,3 and 4 respectively) divides
5816 // equaly. We just shift until there value is zero.
5817
5818 // First, check for a zero value and just short circuit the logic below.
5819 if (*this == (uint64_t)(0))
5820 result = "0";
5821 else {
5822 ap_private<_AP_W, false> tmp(*this);
5823 size_t insert_at = 0;
5824 bool leading_zero = true;
5825 if (wantSigned && isNegative()) {
5826 // They want to print the signed version and it is a negative value
5827 // Flip the bits and add one to turn it into the equivalent positive
5828 // value and put a '-' in the result.
5829 tmp.flip();
5830 tmp++;
5831 tmp.clearUnusedBitsToZero();
5832 result = "-";
5833 insert_at = 1;
5834 leading_zero = false;
5835 }
5836 switch (radix) {
5837 case 2:
5838 result += "0b";
5839 break;
5840 case 8:
5841 result += "0o";
5842 break;
5843 case 16:
5844 result += "0x";
5845 break;
5846 default:
5847 assert("invalid radix" && 0);
5848 }
5849 insert_at += 2;
5850 // Just shift tmp right for each digit width until it becomes zero
5851 uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1));
5852 uint64_t mask = radix - 1;
5853 ap_private<_AP_W, false> zero(0);
5854 unsigned bits = 0;
5855 while (tmp.ne(zero)) {
5856 uint64_t digit = tmp.get_VAL() & mask;
5857 result.insert(insert_at, digits[digit]);
5858 tmp = tmp.lshr(shift);
5859 ++bits;
5860 }
5861 bits *= shift;
5862 if (bits < _AP_W && leading_zero) result.insert(insert_at, digits[0]);
5863 }
5864 return result;
5865 }
5866
5867 ap_private<_AP_W, false> tmp(*this);
5868 ap_private<_AP_W, false> divisor(radix);
5869 ap_private<_AP_W, false> zero(0);
5870 size_t insert_at = 0;
5871 if (wantSigned && isNegative()) {
5872 // They want to print the signed version and it is a negative value
5873 // Flip the bits and add one to turn it into the equivalent positive
5874 // value and put a '-' in the result.
5875 tmp.flip();
5876 tmp++;
5877 tmp.clearUnusedBitsToZero();
5878 result = "-";
5879 insert_at = 1;
5880 }
5881 if (tmp == ap_private<_AP_W, false>(0))
5882 result = "0";
5883 else
5884 while (tmp.ne(zero)) {
5885 ap_private<_AP_W, false> APdigit(0);
5886 ap_private<_AP_W, false> tmp2(0);
5887 ap_private_ops::divide(tmp, tmp.getNumWords(), divisor,
5888 divisor.getNumWords(), &tmp2, &APdigit);
5889 uint64_t digit = APdigit.getZExtValue();
5890 assert(digit < radix && "divide failed");
5891 result.insert(insert_at, digits[digit]);
5892 tmp = tmp2;
5893 }
5894
5895 return result;
5896} // End of ap_private<_AP_W, _AP_S, false>::toString()
5897
5898template <int _AP_W, bool _AP_S>
5899std::ostream& operator<<(std::ostream& os, const ap_private<_AP_W, _AP_S>& x) {
5900 std::ios_base::fmtflags ff = std::cout.flags();
5901 if (ff & std::cout.hex) {
5902 os << x.toString(16, false); // don't print sign
5903 } else if (ff & std::cout.oct) {
5904 os << x.toString(8, false); // don't print sign
5905 } else {
5906 os << x.toString(10, _AP_S);
5907 }
5908 return os;
5909}
5910
5911// ------------------------------------------------------------ //
5912// XXX moved here from ap_int_sim.h XXX //
5913// ------------------------------------------------------------ //
5914
5918// ----------------------------------------------------------------
5919// template <int _AP_W1, typename _AP_T1, int _AP_W2, typename _AP_T2>
5920// struct ap_concat_ref {
5921//#ifdef _MSC_VER
5922//#pragma warning(disable : 4521 4522)
5923//#endif
5924// enum {
5925// _AP_WR = _AP_W1 + _AP_W2,
5926// };
5927// _AP_T1& mbv1;
5928// _AP_T2& mbv2;
5929//
5930// INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>&
5931// ref)
5932// : mbv1(ref.mbv1), mbv2(ref.mbv2) {}
5933//
5934// INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2) : mbv1(bv1), mbv2(bv2) {}
5935//
5936// template <int _AP_W3, bool _AP_S3>
5937// INLINE ap_concat_ref& operator=(const ap_private<_AP_W3, _AP_S3>& val) {
5938// ap_private<_AP_W1 + _AP_W2, false> vval(val);
5939// int W_ref1 = mbv1.length();
5940// int W_ref2 = mbv2.length();
5941// ap_private<_AP_W1, false> mask1(-1);
5942// mask1 >>= _AP_W1 - W_ref1;
5943// ap_private<_AP_W2, false> mask2(-1);
5944// mask2 >>= _AP_W2 - W_ref2;
5945// mbv1.set(ap_private<_AP_W1, false>((vval >> W_ref2) & mask1));
5946// mbv2.set(ap_private<_AP_W2, false>(vval & mask2));
5947// return *this;
5948// }
5949//
5950// INLINE ap_concat_ref& operator=(unsigned long long val) {
5951// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val);
5952// return operator=(tmpVal);
5953// }
5954//
5955// template <int _AP_W3, typename _AP_T3, int _AP_W4, typename _AP_T4>
5956// INLINE ap_concat_ref& operator=(
5957// const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) {
5958// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val);
5959// return operator=(tmpVal);
5960// }
5961//
5962// INLINE ap_concat_ref& operator=(
5963// const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) {
5964// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val);
5965// return operator=(tmpVal);
5966// }
5967//
5968// template <int _AP_W3, bool _AP_S3>
5969// INLINE ap_concat_ref& operator=(const _private_bit_ref<_AP_W3, _AP_S3>&
5970// val) {
5971// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val);
5972// return operator=(tmpVal);
5973// }
5974//
5975// template <int _AP_W3, bool _AP_S3>
5976// INLINE ap_concat_ref& operator=(const _private_range_ref<_AP_W3, _AP_S3>&
5977// val) {
5978// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val);
5979// return operator=(tmpVal);
5980// }
5981//
5982// template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
5983// ap_o_mode _AP_O3, int _AP_N3>
5984// INLINE ap_concat_ref& operator=(
5985// const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& val)
5986// {
5987// return operator=((const ap_private<_AP_W3, false>)(val));
5988// }
5989//
5990// template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
5991// ap_o_mode _AP_O3, int _AP_N3>
5992// INLINE ap_concat_ref& operator=(
5993// const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>&
5994// val) {
5995// return operator=(val.to_ap_private());
5996// }
5997//
5998// template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
5999// ap_o_mode _AP_O3, int _AP_N3>
6000// INLINE ap_concat_ref& operator=(
6001// const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& val) {
6002// return operator=((unsigned long long)(bool)(val));
6003// }
6004//
6005// INLINE operator ap_private<_AP_WR, false>() const { return get(); }
6006//
6007// INLINE operator unsigned long long() const { return get().to_uint64(); }
6008//
6009// template <int _AP_W3, bool _AP_S3>
6010// INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
6011// _private_range_ref<_AP_W3, _AP_S3> >
6012// operator,(const _private_range_ref<_AP_W3, _AP_S3> &a2) {
6013// return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
6014// _private_range_ref<_AP_W3, _AP_S3> >(
6015// *this, const_cast<_private_range_ref<_AP_W3, _AP_S3>&>(a2));
6016// }
6017//
6018// template <int _AP_W3, bool _AP_S3>
6019// INLINE
6020// ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3>
6021// >
6022// operator,(ap_private<_AP_W3, _AP_S3> &a2) {
6023// return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
6024// ap_private<_AP_W3, _AP_S3> >(*this, a2);
6025// }
6026//
6027// template <int _AP_W3, bool _AP_S3>
6028// INLINE
6029// ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3>
6030// >
6031// operator,(const ap_private<_AP_W3, _AP_S3> &a2) {
6032// return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
6033// ap_private<_AP_W3, _AP_S3> >(
6034// *this, const_cast<ap_private<_AP_W3, _AP_S3>&>(a2));
6035// }
6036//
6037// template <int _AP_W3, bool _AP_S3>
6038// INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, _private_bit_ref<_AP_W3,
6039// _AP_S3> >
6040// operator,(const _private_bit_ref<_AP_W3, _AP_S3> &a2) {
6041// return ap_concat_ref<_AP_WR, ap_concat_ref, 1, _private_bit_ref<_AP_W3,
6042// _AP_S3> >(
6043// *this, const_cast<_private_bit_ref<_AP_W3, _AP_S3>&>(a2));
6044// }
6045//
6046// template <int _AP_W3, typename _AP_T3, int _AP_W4, typename _AP_T4>
6047// INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4,
6048// ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> >
6049// operator,(const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> &a2) {
6050// return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4,
6051// ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> >(
6052// *this, const_cast<ap_concat_ref<_AP_W3, _AP_T3, _AP_W4,
6053// _AP_T4>&>(a2));
6054// }
6055//
6056// template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
6057// ap_o_mode _AP_O3, int _AP_N3>
6058// INLINE ap_concat_ref<
6059// _AP_WR, ap_concat_ref, _AP_W3,
6060// af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >
6061// operator,(
6062// const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> &a2)
6063// {
6064// return ap_concat_ref<
6065// _AP_WR, ap_concat_ref, _AP_W3,
6066// af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(
6067// *this,
6068// const_cast<
6069// af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3,
6070// _AP_N3>&>(a2));
6071// }
6072//
6073// template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
6074// ap_o_mode _AP_O3, int _AP_N3>
6075// INLINE
6076// ap_concat_ref<_AP_WR, ap_concat_ref, 1,
6077// af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>
6078// >
6079// operator,(const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3,
6080// _AP_N3>
6081// &a2) {
6082// return ap_concat_ref<
6083// _AP_WR, ap_concat_ref, 1,
6084// af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(
6085// *this,
6086// const_cast<af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3,
6087// _AP_N3>&>(
6088// a2));
6089// }
6090//
6091// template <int _AP_W3, bool _AP_S3>
6092// INLINE ap_private<AP_MAX(_AP_WR, _AP_W3), _AP_S3> operator&(
6093// const ap_private<_AP_W3, _AP_S3>& a2) {
6094// return get() & a2;
6095// }
6096//
6097// template <int _AP_W3, bool _AP_S3>
6098// INLINE ap_private<AP_MAX(_AP_WR, _AP_W3), _AP_S3> operator|(
6099// const ap_private<_AP_W3, _AP_S3>& a2) {
6100// return get() | a2;
6101// }
6102//
6103// template <int _AP_W3, bool _AP_S3>
6104// INLINE ap_private<AP_MAX(_AP_WR, _AP_W3), _AP_S3> operator^(
6105// const ap_private<_AP_W3, _AP_S3>& a2) {
6106// return ap_private<AP_MAX(_AP_WR, _AP_W3), _AP_S3>(get() ^ a2);
6107// }
6108//
6109// INLINE const ap_private<_AP_WR, false> get() const {
6110// ap_private<_AP_W1 + _AP_W2, false> tmpVal =
6111// ap_private<_AP_W1 + _AP_W2, false>(mbv1.get());
6112// ap_private<_AP_W1 + _AP_W2, false> tmpVal2 =
6113// ap_private<_AP_W1 + _AP_W2, false>(mbv2.get());
6114// int W_ref2 = mbv2.length();
6115// tmpVal <<= W_ref2;
6116// tmpVal |= tmpVal2;
6117// return tmpVal;
6118// }
6119//
6120// INLINE const ap_private<_AP_WR, false> get() {
6121// ap_private<_AP_W1 + _AP_W2, false> tmpVal =
6122// ap_private<_AP_W1 + _AP_W2, false>(mbv1.get());
6123// ap_private<_AP_W1 + _AP_W2, false> tmpVal2 =
6124// ap_private<_AP_W1 + _AP_W2, false>(mbv2.get());
6125// int W_ref2 = mbv2.length();
6126// tmpVal <<= W_ref2;
6127// tmpVal |= tmpVal2;
6128// return tmpVal;
6129// }
6130//
6131// template <int _AP_W3>
6132// INLINE void set(const ap_private<_AP_W3, false>& val) {
6133// ap_private<_AP_W1 + _AP_W2, false> vval(val);
6134// int W_ref1 = mbv1.length();
6135// int W_ref2 = mbv2.length();
6136// ap_private<_AP_W1, false> mask1(-1);
6137// mask1 >>= _AP_W1 - W_ref1;
6138// ap_private<_AP_W2, false> mask2(-1);
6139// mask2 >>= _AP_W2 - W_ref2;
6140// mbv1.set(ap_private<_AP_W1, false>((vval >> W_ref2) & mask1));
6141// mbv2.set(ap_private<_AP_W2, false>(vval & mask2));
6142// }
6143//
6144// INLINE int length() const { return mbv1.length() + mbv2.length(); }
6145//
6146// INLINE std::string to_string(uint8_t radix = 2) const {
6147// return get().to_string(radix);
6148// }
6149//}; // struct ap_concat_ref.
6150
6154//------------------------------------------------------------
6155template <int _AP_W, bool _AP_S>
6157#ifdef _MSC_VER
6158#pragma warning(disable : 4521 4522)
6159#endif
6160 ap_private<_AP_W, _AP_S>& d_bv;
6161 int l_index;
6162 int h_index;
6163
6164 public:
6167 : d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {}
6168
6170 INLINE _private_range_ref(ap_private<_AP_W, _AP_S>* bv, int h, int l)
6171 : d_bv(*bv), l_index(l), h_index(h) {
6172 _AP_WARNING(h < 0 || l < 0,
6173 "Higher bound (%d) and lower bound (%d) cannot be "
6174 "negative.",
6175 h, l);
6176 _AP_WARNING(h >= _AP_W || l >= _AP_W,
6177 "Higher bound (%d) or lower bound (%d) out of range (%d).", h,
6178 l, _AP_W);
6179 }
6180
6182 template <int _AP_W2, bool _AP_S2>
6185 _AP_WARNING((h_index - l_index) != (ref.h_index - ref.l_index),
6186 "Bitsize mismach for ap_private<>.range() &= "
6187 "ap_private<>.range().");
6188 this->d_bv |= ref.d_bv;
6189 return *this;
6190 }
6191
6193 template <int _AP_W2, bool _AP_S2>
6195 const _AP_ROOT_TYPE<_AP_W2, _AP_S2>& ref) {
6196 _AP_WARNING((h_index - l_index + 1) != _AP_W2,
6197 "Bitsize mismach for ap_private<>.range() |= _AP_ROOT_TYPE<>.");
6198 this->d_bv |= ref.V;
6199 return *this;
6200 }
6201
6203 template <int _AP_W2, bool _AP_S2>
6206 _AP_WARNING((h_index - l_index) != (ref.h_index - ref.l_index),
6207 "Bitsize mismach for ap_private<>.range() &= "
6208 "ap_private<>.range().");
6209 this->d_bv &= ref.d_bv;
6210 return *this;
6211 };
6212
6214 template <int _AP_W2, bool _AP_S2>
6216 const _AP_ROOT_TYPE<_AP_W2, _AP_S2>& ref) {
6217 _AP_WARNING((h_index - l_index + 1) != _AP_W2,
6218 "Bitsize mismach for ap_private<>.range() &= _AP_ROOT_TYPE<>.");
6219 this->d_bv &= ref.V;
6220 return *this;
6221 }
6222
6224 template <int _AP_W2, bool _AP_S2>
6227 _AP_WARNING((h_index - l_index) != (ref.h_index - ref.l_index),
6228 "Bitsize mismach for ap_private<>.range() ^= "
6229 "ap_private<>.range().");
6230 this->d_bv ^= ref.d_bv;
6231 return *this;
6232 };
6233
6235 template <int _AP_W2, bool _AP_S2>
6237 const _AP_ROOT_TYPE<_AP_W2, _AP_S2>& ref) {
6238 _AP_WARNING((h_index - l_index + 1) != _AP_W2,
6239 "Bitsize mismach for ap_private<>.range() ^= _AP_ROOT_TYPE<>.");
6240 this->d_bv ^= ref.V;
6241 return *this;
6242 }
6243
6245 // @{
6246 INLINE operator ap_private<_AP_W, false>() const {
6247 ap_private<_AP_W, false> val(0);
6248 if (h_index >= l_index) {
6249 if (_AP_W > 64) {
6250 val = d_bv;
6251 ap_private<_AP_W, false> mask(-1);
6252 mask >>= _AP_W - (h_index - l_index + 1);
6253 val >>= l_index;
6254 val &= mask;
6255 } else {
6256 const static uint64_t mask = (~0ULL >> (64 > _AP_W ? (64 - _AP_W) : 0));
6257 val = (d_bv >> l_index) & (mask >> (_AP_W - (h_index - l_index + 1)));
6258 }
6259 } else {
6260 for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++)
6261 if ((d_bv)[j]) val.set(i);
6262 }
6263 return val;
6264 }
6265
6266 INLINE operator unsigned long long() const { return to_uint64(); }
6267 // @}
6268
6269 template <int _AP_W2, bool _AP_S2>
6270 INLINE _private_range_ref& operator=(const ap_private<_AP_W2, _AP_S2>& val) {
6271 ap_private<_AP_W, false> vval = ap_private<_AP_W, false>(val);
6272 if (l_index > h_index) {
6273 for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++)
6274 (vval)[i] ? d_bv.set(j) : d_bv.clear(j);
6275 } else {
6276 if (_AP_W > 64) {
6277 ap_private<_AP_W, false> mask(-1);
6278 if (l_index > 0) {
6279 mask <<= l_index;
6280 vval <<= l_index;
6281 }
6282 if (h_index < _AP_W - 1) {
6283 ap_private<_AP_W, false> mask2(-1);
6284 mask2 >>= _AP_W - h_index - 1;
6285 mask &= mask2;
6286 vval &= mask2;
6287 }
6288 mask.flip();
6289 d_bv &= mask;
6290 d_bv |= vval;
6291 } else {
6292 unsigned shift = 64 - _AP_W;
6293 uint64_t mask = ~0ULL >> (shift);
6294 if (l_index > 0) {
6295 vval = mask & vval << l_index;
6296 mask = mask & mask << l_index;
6297 }
6298 if (h_index < _AP_W - 1) {
6299 uint64_t mask2 = mask;
6300 mask2 >>= (_AP_W - h_index - 1);
6301 mask &= mask2;
6302 vval &= mask2;
6303 }
6304 mask = ~mask;
6305 d_bv &= mask;
6306 d_bv |= vval;
6307 }
6308 }
6309 return *this;
6310 } // operator=(const ap_private<>&)
6311
6312 INLINE _private_range_ref& operator=(unsigned long long val) {
6313 const ap_private<_AP_W, _AP_S> vval = val;
6314 return operator=(vval);
6315 }
6316
6317 template <int _AP_W2, bool _AP_S2>
6318 INLINE _private_range_ref& operator=(
6320 return operator=((unsigned long long)(bool)val);
6321 }
6322
6323 template <int _AP_W2, bool _AP_S2>
6324 INLINE _private_range_ref& operator=(
6326 const ap_private<_AP_W, false> tmpVal(val);
6327 return operator=(tmpVal);
6328 }
6329
6330 // template <int _AP_W3, typename _AP_T3, int _AP_W4, typename _AP_T4>
6331 // INLINE _private_range_ref& operator=(
6332 // const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) {
6333 // const ap_private<_AP_W, false> tmpVal(val);
6334 // return operator=(tmpVal);
6335 // }
6336
6337 // TODO from ap_int_base, ap_bit_ref and ap_range_ref.
6338
6339 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
6340 ap_o_mode _AP_O2, int _AP_N2>
6341 INLINE _private_range_ref& operator=(
6343 val) {
6344 return operator=(val.to_ap_int_base().V);
6345 }
6346
6347 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
6348 ap_o_mode _AP_O2, int _AP_N2>
6349 INLINE _private_range_ref& operator=(
6351 return operator=(val.operator ap_int_base<_AP_W2, false>().V);
6352 }
6353
6354 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
6355 ap_o_mode _AP_O2, int _AP_N2>
6356 INLINE _private_range_ref& operator=(
6358 return operator=((unsigned long long)(bool)val);
6359 }
6360
6361 // template <int _AP_W2, bool _AP_S2>
6362 // INLINE ap_concat_ref<_AP_W, _private_range_ref, _AP_W2,
6363 // _private_range_ref<_AP_W2, _AP_S2> >
6364 // operator,(const _private_range_ref<_AP_W2, _AP_S2> &a2) {
6365 // return ap_concat_ref<_AP_W, _private_range_ref, _AP_W2,
6366 // _private_range_ref<_AP_W2, _AP_S2> >(
6367 // *this, const_cast<_private_range_ref<_AP_W2, _AP_S2>&>(a2));
6368 // }
6369 //
6370 // template <int _AP_W2, bool _AP_S2>
6371 // INLINE ap_concat_ref<_AP_W, _private_range_ref, _AP_W2,
6372 // ap_private<_AP_W2, _AP_S2> >
6373 // operator,(ap_private<_AP_W2, _AP_S2> &a2) {
6374 // return ap_concat_ref<_AP_W, _private_range_ref, _AP_W2,
6375 // ap_private<_AP_W2, _AP_S2> >(*this, a2);
6376 // }
6377 //
6378 // INLINE
6379 // ap_concat_ref<_AP_W, _private_range_ref, _AP_W, ap_private<_AP_W, _AP_S> >
6380 // operator,(ap_private<_AP_W, _AP_S>& a2) {
6381 // return ap_concat_ref<_AP_W, _private_range_ref, _AP_W,
6382 // ap_private<_AP_W, _AP_S> >(*this, a2);
6383 // }
6384 //
6385 // template <int _AP_W2, bool _AP_S2>
6386 // INLINE ap_concat_ref<_AP_W, _private_range_ref, 1,
6387 // _private_bit_ref<_AP_W2, _AP_S2> >
6388 // operator,(const _private_bit_ref<_AP_W2, _AP_S2> &a2) {
6389 // return ap_concat_ref<_AP_W, _private_range_ref, 1,
6390 // _private_bit_ref<_AP_W2, _AP_S2> >(
6391 // *this, const_cast<_private_bit_ref<_AP_W2, _AP_S2>&>(a2));
6392 // }
6393 //
6394 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
6395 // INLINE ap_concat_ref<_AP_W, _private_range_ref, _AP_W2 + _AP_W3,
6396 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >
6397 // operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) {
6398 // return ap_concat_ref<_AP_W, _private_range_ref, _AP_W2 + _AP_W3,
6399 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(
6400 // *this, const_cast<ap_concat_ref<_AP_W2, _AP_T2, _AP_W3,
6401 // _AP_T3>&>(a2));
6402 // }
6403 //
6404 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
6405 // ap_o_mode _AP_O2, int _AP_N2>
6406 // INLINE ap_concat_ref<
6407 // _AP_W, _private_range_ref, _AP_W2,
6408 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >
6409 // operator,(
6410 // const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>
6411 // &a2) {
6412 // return ap_concat_ref<
6413 // _AP_W, _private_range_ref, _AP_W2,
6414 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(
6415 // *this,
6416 // const_cast<
6417 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6418 // _AP_N2>&>(a2));
6419 // }
6420 //
6421 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
6422 // ap_o_mode _AP_O2, int _AP_N2>
6423 // INLINE
6424 // ap_concat_ref<_AP_W, _private_range_ref, 1,
6425 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6426 // _AP_N2> >
6427 // operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6428 // _AP_N2>
6429 // &a2) {
6430 // return ap_concat_ref<
6431 // _AP_W, _private_range_ref, 1,
6432 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(
6433 // *this,
6434 // const_cast<af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6435 // _AP_N2>&>(
6436 // a2));
6437 // }
6438
6439 template <int _AP_W2, bool _AP_S2>
6440 INLINE bool operator==(const _private_range_ref<_AP_W2, _AP_S2>& op2) {
6441 ap_private<_AP_W, false> lhs = get();
6442 ap_private<_AP_W2, false> rhs = op2.get();
6443 return lhs == rhs;
6444 }
6445
6446 template <int _AP_W2, bool _AP_S2>
6447 INLINE bool operator!=(const _private_range_ref<_AP_W2, _AP_S2>& op2) {
6448 ap_private<_AP_W, false> lhs = get();
6449 ap_private<_AP_W2, false> rhs = op2.get();
6450 return lhs != rhs;
6451 }
6452
6453 template <int _AP_W2, bool _AP_S2>
6454 INLINE bool operator>(const _private_range_ref<_AP_W2, _AP_S2>& op2) {
6455 ap_private<_AP_W, false> lhs = get();
6456 ap_private<_AP_W2, false> rhs = op2.get();
6457 return lhs > rhs;
6458 }
6459
6460 template <int _AP_W2, bool _AP_S2>
6461 INLINE bool operator>=(const _private_range_ref<_AP_W2, _AP_S2>& op2) {
6462 ap_private<_AP_W, false> lhs = get();
6463 ap_private<_AP_W2, false> rhs = op2.get();
6464 return lhs >= rhs;
6465 }
6466
6467 template <int _AP_W2, bool _AP_S2>
6468 INLINE bool operator<(const _private_range_ref<_AP_W2, _AP_S2>& op2) {
6469 ap_private<_AP_W, false> lhs = get();
6470 ap_private<_AP_W2, false> rhs = op2.get();
6471 return lhs < rhs;
6472 }
6473
6474 template <int _AP_W2, bool _AP_S2>
6475 INLINE bool operator<=(const _private_range_ref<_AP_W2, _AP_S2>& op2) {
6476 ap_private<_AP_W, false> lhs = get();
6477 ap_private<_AP_W2, false> rhs = op2.get();
6478 return lhs <= rhs;
6479 }
6480
6481 template <int _AP_W2>
6482 INLINE void set(const ap_private<_AP_W2, false>& val) {
6483 ap_private<_AP_W, _AP_S> vval = val;
6484 if (l_index > h_index) {
6485 for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++)
6486 (vval)[i] ? d_bv.set(j) : d_bv.clear(j);
6487 } else {
6488 if (_AP_W > 64) {
6489 ap_private<_AP_W, _AP_S> mask(-1);
6490 if (l_index > 0) {
6491 ap_private<_AP_W, false> mask1(-1);
6492 mask1 >>= _AP_W - l_index;
6493 mask1.flip();
6494 mask = mask1;
6495 // vval&=mask1;
6496 vval <<= l_index;
6497 }
6498 if (h_index < _AP_W - 1) {
6499 ap_private<_AP_W, false> mask2(-1);
6500 mask2 <<= h_index + 1;
6501 mask2.flip();
6502 mask &= mask2;
6503 vval &= mask2;
6504 }
6505 mask.flip();
6506 d_bv &= mask;
6507 d_bv |= vval;
6508 } else {
6509 uint64_t mask = ~0ULL >> (64 - _AP_W);
6510 if (l_index > 0) {
6511 uint64_t mask1 = mask;
6512 mask1 = mask & (mask1 >> (_AP_W - l_index));
6513 vval = mask & (vval << l_index);
6514 mask = ~mask1 & mask;
6515 // vval&=mask1;
6516 }
6517 if (h_index < _AP_W - 1) {
6518 uint64_t mask2 = ~0ULL >> (64 - _AP_W);
6519 mask2 = mask & (mask2 << (h_index + 1));
6520 mask &= ~mask2;
6521 vval &= ~mask2;
6522 }
6523 d_bv &= (~mask & (~0ULL >> (64 - _AP_W)));
6524 d_bv |= vval;
6525 }
6526 }
6527 }
6528
6529 INLINE ap_private<_AP_W, false> get() const {
6530 ap_private<_AP_W, false> val(0);
6531 if (h_index < l_index) {
6532 for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++)
6533 if ((d_bv)[j]) val.set(i);
6534 } else {
6535 val = d_bv;
6536 val >>= l_index;
6537 if (h_index < _AP_W - 1) {
6538 if (_AP_W <= 64) {
6539 const static uint64_t mask =
6540 (~0ULL >> (64 > _AP_W ? (64 - _AP_W) : 0));
6541 val &= (mask >> (_AP_W - (h_index - l_index + 1)));
6542 } else {
6543 ap_private<_AP_W, false> mask(-1);
6544 mask >>= _AP_W - (h_index - l_index + 1);
6545 val &= mask;
6546 }
6547 }
6548 }
6549 return val;
6550 }
6551
6552 INLINE ap_private<_AP_W, false> get() {
6553 ap_private<_AP_W, false> val(0);
6554 if (h_index < l_index) {
6555 for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++)
6556 if ((d_bv)[j]) val.set(i);
6557 } else {
6558 val = d_bv;
6559 val >>= l_index;
6560 if (h_index < _AP_W - 1) {
6561 if (_AP_W <= 64) {
6562 static const uint64_t mask = ~0ULL >> (64 > _AP_W ? (64 - _AP_W) : 0);
6563 return val &= ((mask) >> (_AP_W - (h_index - l_index + 1)));
6564 } else {
6565 ap_private<_AP_W, false> mask(-1);
6566 mask >>= _AP_W - (h_index - l_index + 1);
6567 val &= mask;
6568 }
6569 }
6570 }
6571 return val;
6572 }
6573
6574 INLINE int length() const {
6575 return h_index >= l_index ? h_index - l_index + 1 : l_index - h_index + 1;
6576 }
6577
6578 INLINE int to_int() const {
6579 ap_private<_AP_W, false> val = get();
6580 return val.to_int();
6581 }
6582
6583 INLINE unsigned int to_uint() const {
6584 ap_private<_AP_W, false> val = get();
6585 return val.to_uint();
6586 }
6587
6588 INLINE long to_long() const {
6589 ap_private<_AP_W, false> val = get();
6590 return val.to_long();
6591 }
6592
6593 INLINE unsigned long to_ulong() const {
6594 ap_private<_AP_W, false> val = get();
6595 return val.to_ulong();
6596 }
6597
6598 INLINE ap_slong to_int64() const {
6599 ap_private<_AP_W, false> val = get();
6600 return val.to_int64();
6601 }
6602
6603 INLINE ap_ulong to_uint64() const {
6604 ap_private<_AP_W, false> val = get();
6605 return val.to_uint64();
6606 }
6607
6608 INLINE std::string to_string(uint8_t radix = 2) const {
6609 return get().to_string(radix);
6610 }
6611
6612 INLINE bool and_reduce() {
6613 bool ret = true;
6614 bool reverse = l_index > h_index;
6615 unsigned low = reverse ? h_index : l_index;
6616 unsigned high = reverse ? l_index : h_index;
6617 for (unsigned i = low; i != high; ++i) ret &= d_bv[i];
6618 return ret;
6619 }
6620
6621 INLINE bool or_reduce() {
6622 bool ret = false;
6623 bool reverse = l_index > h_index;
6624 unsigned low = reverse ? h_index : l_index;
6625 unsigned high = reverse ? l_index : h_index;
6626 for (unsigned i = low; i != high; ++i) ret |= d_bv[i];
6627 return ret;
6628 }
6629
6630 INLINE bool xor_reduce() {
6631 bool ret = false;
6632 bool reverse = l_index > h_index;
6633 unsigned low = reverse ? h_index : l_index;
6634 unsigned high = reverse ? l_index : h_index;
6635 for (unsigned i = low; i != high; ++i) ret ^= d_bv[i];
6636 return ret;
6637 }
6638}; // struct _private_range_ref.
6639
6643//--------------------------------------------------------------
6644template <int _AP_W, bool _AP_S>
6646#ifdef _MSC_VER
6647#pragma warning(disable : 4521 4522)
6648#endif
6649 ap_private<_AP_W, _AP_S>& d_bv;
6650 int d_index;
6651
6652 public:
6653 // copy ctor.
6655 : d_bv(ref.d_bv), d_index(ref.d_index) {}
6656
6657 // director ctor.
6658 INLINE _private_bit_ref(ap_private<_AP_W, _AP_S>& bv, int index = 0)
6659 : d_bv(bv), d_index(index) {
6660 _AP_WARNING(d_index < 0, "Index of bit vector (%d) cannot be negative.\n",
6661 d_index);
6662 _AP_WARNING(d_index >= _AP_W,
6663 "Index of bit vector (%d) out of range (%d).\n", d_index,
6664 _AP_W);
6665 }
6666
6667 INLINE operator bool() const { return d_bv.get_bit(d_index); }
6668
6669 INLINE bool to_bool() const { return operator bool(); }
6670
6671 template <typename T>
6672 INLINE _private_bit_ref& operator=(const T& val) {
6673 if (!!val)
6674 d_bv.set(d_index);
6675 else
6676 d_bv.clear(d_index);
6677 return *this;
6678 }
6679
6680 // template <int _AP_W2, bool _AP_S2>
6681 // INLINE ap_concat_ref<1, _private_bit_ref, _AP_W2, ap_private<_AP_W2,
6682 // _AP_S2> >
6683 // operator,(ap_private<_AP_W2, _AP_S2> &a2) const {
6684 // return ap_concat_ref<1, _private_bit_ref, _AP_W2, ap_private<_AP_W2,
6685 // _AP_S2> >(
6686 // const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this), a2);
6687 // }
6688 //
6689 // template <int _AP_W2, bool _AP_S2>
6690 // INLINE ap_concat_ref<1, _private_bit_ref, _AP_W2,
6691 // _private_range_ref<_AP_W2,
6692 // _AP_S2> >
6693 // operator,(const _private_range_ref<_AP_W2, _AP_S2> &a2) const {
6694 // return ap_concat_ref<1, _private_bit_ref, _AP_W2,
6695 // _private_range_ref<_AP_W2,
6696 // _AP_S2> >(
6697 // const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this),
6698 // const_cast<_private_range_ref<_AP_W2, _AP_S2>&>(a2));
6699 // }
6700 //
6701 // template <int _AP_W2, bool _AP_S2>
6702 // INLINE ap_concat_ref<1, _private_bit_ref, 1, _private_bit_ref<_AP_W2,
6703 // _AP_S2> > operator,(
6704 // const _private_bit_ref<_AP_W2, _AP_S2> &a2) const {
6705 // return ap_concat_ref<1, _private_bit_ref, 1,
6706 // _private_bit_ref<_AP_W2, _AP_S2> >(
6707 // const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this),
6708 // const_cast<_private_bit_ref<_AP_W2, _AP_S2>&>(a2));
6709 // }
6710 //
6711 // INLINE ap_concat_ref<1, _private_bit_ref, 1, _private_bit_ref>
6712 // operator,(
6713 // const _private_bit_ref &a2) const {
6714 // return ap_concat_ref<1, _private_bit_ref, 1, _private_bit_ref>(
6715 // const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this),
6716 // const_cast<_private_bit_ref&>(a2));
6717 // }
6718 //
6719 // template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
6720 // INLINE ap_concat_ref<1, _private_bit_ref, _AP_W2 + _AP_W3,
6721 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >
6722 // operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const {
6723 // return ap_concat_ref<1, _private_bit_ref, _AP_W2 + _AP_W3,
6724 // ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(
6725 // const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this),
6726 // const_cast<ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>&>(a2));
6727 // }
6728 //
6729 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
6730 // ap_o_mode _AP_O2, int _AP_N2>
6731 // INLINE ap_concat_ref<
6732 // 1, _private_bit_ref, _AP_W2,
6733 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >
6734 // operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6735 // _AP_N2>
6736 // &a2) const {
6737 // return ap_concat_ref<
6738 // 1, _private_bit_ref, _AP_W2,
6739 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(
6740 // const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this),
6741 // const_cast<
6742 // af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6743 // _AP_N2>&>(a2));
6744 // }
6745 //
6746 // template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
6747 // ap_o_mode _AP_O2, int _AP_N2>
6748 // INLINE
6749 // ap_concat_ref<1, _private_bit_ref, 1,
6750 // af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6751 // _AP_N2> >
6752 // operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6753 // _AP_N2>
6754 // &a2) const {
6755 // return ap_concat_ref<1, _private_bit_ref, 1, af_bit_ref<_AP_W2,
6756 // _AP_I2, _AP_S2,
6757 // _AP_Q2, _AP_O2,
6758 // _AP_N2> >(
6759 // const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this),
6760 // const_cast<af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2,
6761 // _AP_N2>&>(
6762 // a2));
6763 // }
6764
6765 template <int _AP_W2, bool _AP_S2>
6766 INLINE bool operator==(const _private_bit_ref<_AP_W2, _AP_S2>& op) const {
6767 return get() == op.get();
6768 }
6769
6770 template <int _AP_W2, bool _AP_S2>
6771 INLINE bool operator!=(const _private_bit_ref<_AP_W2, _AP_S2>& op) const {
6772 return get() != op.get();
6773 }
6774
6775 INLINE bool get() const { return operator bool(); }
6776
6777 // template <int _AP_W3>
6778 // INLINE void set(const ap_private<_AP_W3, false>& val) {
6779 // operator=(val);
6780 // }
6781
6782 // INLINE bool operator~() const {
6783 // bool bit = (d_bv)[d_index];
6784 // return bit ? false : true;
6785 // }
6786
6787 INLINE int length() const { return 1; }
6788
6789 // INLINE std::string to_string() const {
6790 // bool val = get();
6791 // return val ? "1" : "0";
6792 // }
6793
6794}; // struct _private_bit_ref.
6795
6796// char a[100];
6797// char* ptr = a;
6798// ap_int<2> n = 3;
6799// char* ptr2 = ptr + n*2;
6800// avoid ambiguous errors
6801#define OP_BIN_MIX_PTR(BIN_OP) \
6802 template <typename PTR_TYPE, int _AP_W, bool _AP_S> \
6803 INLINE PTR_TYPE* operator BIN_OP(PTR_TYPE* i_op, \
6804 const ap_private<_AP_W, _AP_S>& op) { \
6805 typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \
6806 return i_op BIN_OP op2; \
6807 } \
6808 template <typename PTR_TYPE, int _AP_W, bool _AP_S> \
6809 INLINE PTR_TYPE* operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, \
6810 PTR_TYPE* i_op) { \
6811 typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \
6812 return op2 BIN_OP i_op; \
6813 }
6814
6815OP_BIN_MIX_PTR(+)
6816OP_BIN_MIX_PTR(-)
6817#undef OP_BIN_MIX_PTR
6818
6819// float OP ap_int
6820// when ap_int<wa>'s width > 64, then trunc ap_int<w> to ap_int<64>
6821#define OP_BIN_MIX_FLOAT(BIN_OP, C_TYPE) \
6822 template <int _AP_W, bool _AP_S> \
6823 INLINE C_TYPE operator BIN_OP(C_TYPE i_op, \
6824 const ap_private<_AP_W, _AP_S>& op) { \
6825 typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \
6826 return i_op BIN_OP op2; \
6827 } \
6828 template <int _AP_W, bool _AP_S> \
6829 INLINE C_TYPE operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, \
6830 C_TYPE i_op) { \
6831 typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \
6832 return op2 BIN_OP i_op; \
6833 }
6834
6835#define OPS_MIX_FLOAT(C_TYPE) \
6836 OP_BIN_MIX_FLOAT(*, C_TYPE) \
6837 OP_BIN_MIX_FLOAT(/, C_TYPE) \
6838 OP_BIN_MIX_FLOAT(+, C_TYPE) \
6839 OP_BIN_MIX_FLOAT(-, C_TYPE)
6840
6841OPS_MIX_FLOAT(float)
6842OPS_MIX_FLOAT(double)
6843#undef OP_BIN_MIX_FLOAT
6844#undef OPS_MIX_FLOAT
6845
6847// ----------------------------------------------------------------
6848
6849// partially specialize template argument _AP_C in order that:
6850// for _AP_W > 64, we will explicitly convert operand with native data type
6851// into corresponding ap_private
6852// for _AP_W <= 64, we will implicitly convert operand with ap_private into
6853// (unsigned) long long
6854#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \
6855 template <int _AP_W, bool _AP_S> \
6856 INLINE \
6857 typename ap_private<_AP_WI, _AP_SI>::template RType<_AP_W, _AP_S>::RTYPE \
6858 operator BIN_OP(C_TYPE i_op, const ap_private<_AP_W, _AP_S>& op) { \
6859 return ap_private<_AP_WI, _AP_SI>(i_op).operator BIN_OP(op); \
6860 } \
6861 template <int _AP_W, bool _AP_S> \
6862 INLINE \
6863 typename ap_private<_AP_W, _AP_S>::template RType<_AP_WI, _AP_SI>::RTYPE \
6864 operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, C_TYPE i_op) { \
6865 return op.operator BIN_OP(ap_private<_AP_WI, _AP_SI>(i_op)); \
6866 }
6867
6868#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \
6869 template <int _AP_W, bool _AP_S> \
6870 INLINE bool operator REL_OP(const ap_private<_AP_W, _AP_S>& op, \
6871 C_TYPE op2) { \
6872 return op.operator REL_OP(ap_private<_AP_W2, _AP_S2>(op2)); \
6873 } \
6874 template <int _AP_W, bool _AP_S> \
6875 INLINE bool operator REL_OP(C_TYPE op2, \
6876 const ap_private<_AP_W, _AP_S, false>& op) { \
6877 return ap_private<_AP_W2, _AP_S2>(op2).operator REL_OP(op); \
6878 }
6879
6880#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \
6881 template <int _AP_W, bool _AP_S> \
6882 INLINE ap_private<_AP_W, _AP_S>& operator ASSIGN_OP( \
6883 ap_private<_AP_W, _AP_S>& op, C_TYPE op2) { \
6884 return op.operator ASSIGN_OP(ap_private<_AP_W2, _AP_S2>(op2)); \
6885 }
6886
6887#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \
6888 template <int _AP_W, bool _AP_S> \
6889 C_TYPE operator BIN_OP(C_TYPE i_op, \
6890 const ap_private<_AP_W, _AP_S, false>& op) { \
6891 return i_op BIN_OP(op.get_VAL()); \
6892 } \
6893 template <int _AP_W, bool _AP_S> \
6894 INLINE \
6895 typename ap_private<_AP_W, _AP_S>::template RType<_AP_WI, _AP_SI>::RTYPE \
6896 operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, C_TYPE i_op) { \
6897 return op.operator BIN_OP(i_op); \
6898 }
6899
6900#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \
6901 template <int _AP_W, bool _AP_S> \
6902 INLINE ap_private<_AP_W, _AP_S>& operator ASSIGN_OP( \
6903 ap_private<_AP_W, _AP_S>& op, C_TYPE op2) { \
6904 op = op.operator>>(op2); \
6905 return op; \
6906 }
6907
6908#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \
6909 template <int _AP_W, bool _AP_S> \
6910 INLINE ap_private<_AP_W, _AP_S>& operator ASSIGN_OP( \
6911 ap_private<_AP_W, _AP_S>& op, C_TYPE op2) { \
6912 op = op.operator<<(op2); \
6913 return op; \
6914 }
6915
6916#define OPS_MIX_INT(C_TYPE, _AP_W2, _AP_S2) \
6917 OP_BIN_MIX_INT(*, C_TYPE, (_AP_W2), (_AP_S2), mult) \
6918 OP_BIN_MIX_INT(+, C_TYPE, (_AP_W2), (_AP_S2), plus) \
6919 OP_BIN_MIX_INT(-, C_TYPE, (_AP_W2), (_AP_S2), minus) \
6920 OP_BIN_MIX_INT(/, C_TYPE, (_AP_W2), (_AP_S2), div) \
6921 OP_BIN_MIX_INT(%, C_TYPE, (_AP_W2), (_AP_S2), mod) \
6922 OP_BIN_MIX_INT(&, C_TYPE, (_AP_W2), (_AP_S2), logic) \
6923 OP_BIN_MIX_INT(|, C_TYPE, (_AP_W2), (_AP_S2), logic) \
6924 OP_BIN_MIX_INT(^, C_TYPE, (_AP_W2), (_AP_S2), logic) \
6925 OP_BIN_SHIFT_INT(>>, C_TYPE, (_AP_W2), (_AP_S2), arg1) \
6926 OP_BIN_SHIFT_INT(<<, C_TYPE, (_AP_W2), (_AP_S2), arg1) \
6927 \
6928 OP_ASSIGN_MIX_INT(+=, C_TYPE, (_AP_W2), (_AP_S2)) \
6929 OP_ASSIGN_MIX_INT(-=, C_TYPE, (_AP_W2), (_AP_S2)) \
6930 OP_ASSIGN_MIX_INT(*=, C_TYPE, (_AP_W2), (_AP_S2)) \
6931 OP_ASSIGN_MIX_INT(/=, C_TYPE, (_AP_W2), (_AP_S2)) \
6932 OP_ASSIGN_MIX_INT(%=, C_TYPE, (_AP_W2), (_AP_S2)) \
6933 OP_ASSIGN_MIX_INT(&=, C_TYPE, (_AP_W2), (_AP_S2)) \
6934 OP_ASSIGN_MIX_INT(|=, C_TYPE, (_AP_W2), (_AP_S2)) \
6935 OP_ASSIGN_MIX_INT(^=, C_TYPE, (_AP_W2), (_AP_S2)) \
6936 OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, (_AP_W2), (_AP_S2)) \
6937 OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, (_AP_W2), (_AP_S2)) \
6938 \
6939 OP_REL_MIX_INT(>, C_TYPE, (_AP_W2), (_AP_S2)) \
6940 OP_REL_MIX_INT(<, C_TYPE, (_AP_W2), (_AP_S2)) \
6941 OP_REL_MIX_INT(>=, C_TYPE, (_AP_W2), (_AP_S2)) \
6942 OP_REL_MIX_INT(<=, C_TYPE, (_AP_W2), (_AP_S2)) \
6943 OP_REL_MIX_INT(==, C_TYPE, (_AP_W2), (_AP_S2)) \
6944 OP_REL_MIX_INT(!=, C_TYPE, (_AP_W2), (_AP_S2))
6945
6946OPS_MIX_INT(bool, 1, false)
6947OPS_MIX_INT(char, 8, CHAR_IS_SIGNED)
6948OPS_MIX_INT(signed char, 8, true)
6949OPS_MIX_INT(unsigned char, 8, false)
6950OPS_MIX_INT(short, sizeof(short) * 8, true)
6951OPS_MIX_INT(unsigned short, sizeof(unsigned short) * 8, false)
6952OPS_MIX_INT(int, sizeof(int) * 8, true)
6953OPS_MIX_INT(unsigned int, sizeof(unsigned int) * 8, false)
6954OPS_MIX_INT(long, sizeof(long) * 8, true)
6955OPS_MIX_INT(unsigned long, sizeof(unsigned long) * 8, false)
6956OPS_MIX_INT(ap_slong, sizeof(ap_slong) * 8, true)
6957OPS_MIX_INT(ap_ulong, sizeof(ap_ulong) * 8, false)
6958
6959#undef OP_BIN_MIX_INT
6960#undef OP_BIN_SHIFT_INT
6961#undef OP_ASSIGN_MIX_INT
6962#undef OP_ASSIGN_RSHIFT_INT
6963#undef OP_ASSIGN_LSHIFT_INT
6964#undef OP_REL_MIX_INT
6965#undef OPS_MIX_INT
6966
6967#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \
6968 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
6969 INLINE typename ap_private<_AP_W1, _AP_S1>::template RType<_AP_W2, \
6970 _AP_S2>::RTYPE \
6971 operator BIN_OP(const _private_range_ref<_AP_W1, _AP_S1>& op1, \
6972 const ap_private<_AP_W2, _AP_S2>& op2) { \
6973 return ap_private<_AP_W1, false>(op1).operator BIN_OP(op2); \
6974 } \
6975 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
6976 INLINE typename ap_private<_AP_W1, _AP_S1>::template RType<_AP_W2, \
6977 _AP_S2>::RTYPE \
6978 operator BIN_OP(const ap_private<_AP_W1, _AP_S1>& op1, \
6979 const _private_range_ref<_AP_W2, _AP_S2>& op2) { \
6980 return op1.operator BIN_OP(ap_private<_AP_W2, false>(op2)); \
6981 }
6982
6983#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \
6984 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
6985 INLINE ap_private<_AP_W1, _AP_S1>& operator ASSIGN_OP( \
6986 ap_private<_AP_W1, _AP_S1>& op1, \
6987 const _private_range_ref<_AP_W2, _AP_S2>& op2) { \
6988 return op1.operator ASSIGN_OP(ap_private<_AP_W2, false>(op2)); \
6989 } \
6990 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
6991 INLINE _private_range_ref<_AP_W1, _AP_S1>& operator ASSIGN_OP( \
6992 _private_range_ref<_AP_W1, _AP_S1>& op1, \
6993 ap_private<_AP_W2, _AP_S2>& op2) { \
6994 ap_private<_AP_W1, false> tmp(op1); \
6995 tmp.operator ASSIGN_OP(op2); \
6996 op1 = tmp; \
6997 return op1; \
6998 }
6999
7000#define OP_REL_MIX_RANGE(REL_OP) \
7001 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
7002 INLINE bool operator REL_OP(const _private_range_ref<_AP_W1, _AP_S1>& op1, \
7003 const ap_private<_AP_W2, _AP_S2>& op2) { \
7004 return ap_private<_AP_W1, false>(op1).operator REL_OP(op2); \
7005 } \
7006 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
7007 INLINE bool operator REL_OP(const ap_private<_AP_W1, _AP_S1>& op1, \
7008 const _private_range_ref<_AP_W2, _AP_S2>& op2) { \
7009 return op1.operator REL_OP(op2.operator ap_private<_AP_W2, false>()); \
7010 }
7011
7012OP_BIN_MIX_RANGE(+, plus)
7013OP_BIN_MIX_RANGE(-, minus)
7014OP_BIN_MIX_RANGE(*, mult)
7015OP_BIN_MIX_RANGE(/, div)
7016OP_BIN_MIX_RANGE(%, mod)
7017OP_BIN_MIX_RANGE(&, logic)
7018OP_BIN_MIX_RANGE(|, logic)
7019OP_BIN_MIX_RANGE(^, logic)
7020OP_BIN_MIX_RANGE(>>, arg1)
7021OP_BIN_MIX_RANGE(<<, arg1)
7022#undef OP_BIN_MIX_RANGE
7023
7024OP_ASSIGN_MIX_RANGE(+=)
7025OP_ASSIGN_MIX_RANGE(-=)
7026OP_ASSIGN_MIX_RANGE(*=)
7027OP_ASSIGN_MIX_RANGE(/=)
7028OP_ASSIGN_MIX_RANGE(%=)
7029OP_ASSIGN_MIX_RANGE(&=)
7030OP_ASSIGN_MIX_RANGE(|=)
7031OP_ASSIGN_MIX_RANGE(^=)
7032OP_ASSIGN_MIX_RANGE(>>=)
7033OP_ASSIGN_MIX_RANGE(<<=)
7034#undef OP_ASSIGN_MIX_RANGE
7035
7036OP_REL_MIX_RANGE(>)
7037OP_REL_MIX_RANGE(<)
7038OP_REL_MIX_RANGE(>=)
7039OP_REL_MIX_RANGE(<=)
7040OP_REL_MIX_RANGE(==)
7041OP_REL_MIX_RANGE(!=)
7042#undef OP_REL_MIX_RANGE
7043
7044#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \
7045 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
7046 INLINE typename ap_private<1, false>::template RType<_AP_W2, _AP_S2>::RTYPE \
7047 operator BIN_OP(const _private_bit_ref<_AP_W1, _AP_S1>& op1, \
7048 const ap_private<_AP_W2, _AP_S2>& op2) { \
7049 return ap_private<1, false>(op1).operator BIN_OP(op2); \
7050 } \
7051 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
7052 INLINE typename ap_private<_AP_W1, _AP_S1>::template RType<1, false>::RTYPE \
7053 operator BIN_OP(const ap_private<_AP_W1, _AP_S1>& op1, \
7054 const _private_bit_ref<_AP_W2, _AP_S2>& op2) { \
7055 return op1.operator BIN_OP(ap_private<1, false>(op2)); \
7056 }
7057
7058#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \
7059 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
7060 INLINE ap_private<_AP_W1, _AP_S1>& operator ASSIGN_OP( \
7061 ap_private<_AP_W1, _AP_S1>& op1, \
7062 _private_bit_ref<_AP_W2, _AP_S2>& op2) { \
7063 return op1.operator ASSIGN_OP(ap_private<1, false>(op2)); \
7064 } \
7065 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
7066 INLINE _private_bit_ref<_AP_W1, _AP_S1>& operator ASSIGN_OP( \
7067 _private_bit_ref<_AP_W1, _AP_S1>& op1, \
7068 ap_private<_AP_W2, _AP_S2>& op2) { \
7069 ap_private<1, false> tmp(op1); \
7070 tmp.operator ASSIGN_OP(op2); \
7071 op1 = tmp; \
7072 return op1; \
7073 }
7074
7075#define OP_REL_MIX_BIT(REL_OP) \
7076 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
7077 INLINE bool operator REL_OP(const _private_bit_ref<_AP_W1, _AP_S1>& op1, \
7078 const ap_private<_AP_W2, _AP_S2>& op2) { \
7079 return ap_private<_AP_W1, false>(op1).operator REL_OP(op2); \
7080 } \
7081 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
7082 INLINE bool operator REL_OP(const ap_private<_AP_W1, _AP_S1>& op1, \
7083 const _private_bit_ref<_AP_W2, _AP_S2>& op2) { \
7084 return op1.operator REL_OP(ap_private<1, false>(op2)); \
7085 }
7086
7087OP_ASSIGN_MIX_BIT(+=)
7088OP_ASSIGN_MIX_BIT(-=)
7089OP_ASSIGN_MIX_BIT(*=)
7090OP_ASSIGN_MIX_BIT(/=)
7091OP_ASSIGN_MIX_BIT(%=)
7092OP_ASSIGN_MIX_BIT(&=)
7093OP_ASSIGN_MIX_BIT(|=)
7094OP_ASSIGN_MIX_BIT(^=)
7095OP_ASSIGN_MIX_BIT(>>=)
7096OP_ASSIGN_MIX_BIT(<<=)
7097#undef OP_ASSIGN_MIX_BIT
7098
7099OP_BIN_MIX_BIT(+, plus)
7100OP_BIN_MIX_BIT(-, minus)
7101OP_BIN_MIX_BIT(*, mult)
7102OP_BIN_MIX_BIT(/, div)
7103OP_BIN_MIX_BIT(%, mod)
7104OP_BIN_MIX_BIT(&, logic)
7105OP_BIN_MIX_BIT(|, logic)
7106OP_BIN_MIX_BIT(^, logic)
7107OP_BIN_MIX_BIT(>>, arg1)
7108OP_BIN_MIX_BIT(<<, arg1)
7109#undef OP_BIN_MIX_BIT
7110
7111OP_REL_MIX_BIT(>)
7112OP_REL_MIX_BIT(<)
7113OP_REL_MIX_BIT(<=)
7114OP_REL_MIX_BIT(>=)
7115OP_REL_MIX_BIT(==)
7116OP_REL_MIX_BIT(!=)
7117#undef OP_REL_MIX_BIT
7118
7119#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \
7120 template <int _AP_W, bool _AP_S> \
7121 INLINE bool operator REL_OP(const _private_range_ref<_AP_W, _AP_S>& op, \
7122 C_TYPE op2) { \
7123 return (ap_private<_AP_W, false>(op)) \
7124 . \
7125 operator REL_OP(ap_private<_AP_W2, _AP_S2>(op2)); \
7126 } \
7127 template <int _AP_W, bool _AP_S> \
7128 INLINE bool operator REL_OP(C_TYPE op2, \
7129 const _private_range_ref<_AP_W, _AP_S>& op) { \
7130 return ap_private<_AP_W2, _AP_S2>(op2).operator REL_OP( \
7131 ap_private<_AP_W, false>(op)); \
7132 } \
7133 template <int _AP_W, bool _AP_S> \
7134 INLINE bool operator REL_OP(const _private_bit_ref<_AP_W, _AP_S>& op, \
7135 C_TYPE op2) { \
7136 return (bool(op))REL_OP op2; \
7137 } \
7138 template <int _AP_W, bool _AP_S> \
7139 INLINE bool operator REL_OP(C_TYPE op2, \
7140 const _private_bit_ref<_AP_W, _AP_S>& op) { \
7141 return op2 REL_OP(bool(op)); \
7142 }
7143
7144#define REF_REL_MIX_INT(C_TYPE, _AP_W2, _AP_S2) \
7145 REF_REL_OP_MIX_INT(>, C_TYPE, (_AP_W2), (_AP_S2)) \
7146 REF_REL_OP_MIX_INT(<, C_TYPE, (_AP_W2), (_AP_S2)) \
7147 REF_REL_OP_MIX_INT(>=, C_TYPE, (_AP_W2), (_AP_S2)) \
7148 REF_REL_OP_MIX_INT(<=, C_TYPE, (_AP_W2), (_AP_S2)) \
7149 REF_REL_OP_MIX_INT(==, C_TYPE, (_AP_W2), (_AP_S2)) \
7150 REF_REL_OP_MIX_INT(!=, C_TYPE, (_AP_W2), (_AP_S2))
7151
7152REF_REL_MIX_INT(bool, 1, false)
7153REF_REL_MIX_INT(char, 8, CHAR_IS_SIGNED)
7154REF_REL_MIX_INT(signed char, 8, true)
7155REF_REL_MIX_INT(unsigned char, 8, false)
7156REF_REL_MIX_INT(short, sizeof(short) * 8, true)
7157REF_REL_MIX_INT(unsigned short, sizeof(unsigned short) * 8, false)
7158REF_REL_MIX_INT(int, sizeof(int) * 8, true)
7159REF_REL_MIX_INT(unsigned int, sizeof(unsigned int) * 8, false)
7160REF_REL_MIX_INT(long, sizeof(long) * 8, true)
7161REF_REL_MIX_INT(unsigned long, sizeof(unsigned long) * 8, false)
7162REF_REL_MIX_INT(ap_slong, sizeof(ap_slong) * 8, true)
7163REF_REL_MIX_INT(ap_ulong, sizeof(ap_ulong) * 8, false)
7164#undef REF_REL_OP_MIX_INT
7165#undef REF_REL_MIX_INT
7166
7167#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \
7168 template <int _AP_W, bool _AP_S> \
7169 INLINE \
7170 typename ap_private<_AP_W, false>::template RType<_AP_W2, _AP_S2>::RTYPE \
7171 operator BIN_OP(const _private_range_ref<_AP_W, _AP_S>& op, \
7172 C_TYPE op2) { \
7173 return (ap_private<_AP_W, false>(op)) \
7174 . \
7175 operator BIN_OP(ap_private<_AP_W2, _AP_S2>(op2)); \
7176 } \
7177 template <int _AP_W, bool _AP_S> \
7178 INLINE \
7179 typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W, false>::RTYPE \
7180 operator BIN_OP(C_TYPE op2, \
7181 const _private_range_ref<_AP_W, _AP_S>& op) { \
7182 return ap_private<_AP_W2, _AP_S2>(op2).operator BIN_OP( \
7183 ap_private<_AP_W, false>(op)); \
7184 }
7185
7186#define REF_BIN_MIX_INT(C_TYPE, _AP_W2, _AP_S2) \
7187 REF_BIN_OP_MIX_INT(+, plus, C_TYPE, (_AP_W2), (_AP_S2)) \
7188 REF_BIN_OP_MIX_INT(-, minus, C_TYPE, (_AP_W2), (_AP_S2)) \
7189 REF_BIN_OP_MIX_INT(*, mult, C_TYPE, (_AP_W2), (_AP_S2)) \
7190 REF_BIN_OP_MIX_INT(/, div, C_TYPE, (_AP_W2), (_AP_S2)) \
7191 REF_BIN_OP_MIX_INT(%, mod, C_TYPE, (_AP_W2), (_AP_S2)) \
7192 REF_BIN_OP_MIX_INT(&, logic, C_TYPE, (_AP_W2), (_AP_S2)) \
7193 REF_BIN_OP_MIX_INT(|, logic, C_TYPE, (_AP_W2), (_AP_S2)) \
7194 REF_BIN_OP_MIX_INT(^, logic, C_TYPE, (_AP_W2), (_AP_S2)) \
7195 REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, (_AP_W2), (_AP_S2)) \
7196 REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, (_AP_W2), (_AP_S2))
7197
7198REF_BIN_MIX_INT(bool, 1, false)
7199REF_BIN_MIX_INT(char, 8, CHAR_IS_SIGNED)
7200REF_BIN_MIX_INT(signed char, 8, true)
7201REF_BIN_MIX_INT(unsigned char, 8, false)
7202REF_BIN_MIX_INT(short, sizeof(short) * 8, true)
7203REF_BIN_MIX_INT(unsigned short, sizeof(unsigned short) * 8, false)
7204REF_BIN_MIX_INT(int, sizeof(int) * 8, true)
7205REF_BIN_MIX_INT(unsigned int, sizeof(unsigned int) * 8, false)
7206REF_BIN_MIX_INT(long, sizeof(long) * 8, true)
7207REF_BIN_MIX_INT(unsigned long, sizeof(unsigned long) * 8, false)
7208REF_BIN_MIX_INT(ap_slong, sizeof(ap_slong) * 8, true)
7209REF_BIN_MIX_INT(ap_ulong, sizeof(ap_ulong) * 8, false)
7210#undef REF_BIN_OP_MIX_INT
7211#undef REF_BIN_MIX_INT
7212
7213#define REF_BIN_OP(BIN_OP, RTYPE) \
7214 template <int _AP_W, bool _AP_S, int _AP_W2, bool _AP_S2> \
7215 INLINE \
7216 typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \
7217 operator BIN_OP(const _private_range_ref<_AP_W, _AP_S>& lhs, \
7218 const _private_range_ref<_AP_W2, _AP_S2>& rhs) { \
7219 return ap_private<_AP_W, false>(lhs).operator BIN_OP( \
7220 ap_private<_AP_W2, false>(rhs)); \
7221 }
7222
7223REF_BIN_OP(+, plus)
7224REF_BIN_OP(-, minus)
7225REF_BIN_OP(*, mult)
7226REF_BIN_OP(/, div)
7227REF_BIN_OP(%, mod)
7228REF_BIN_OP(&, logic)
7229REF_BIN_OP(|, logic)
7230REF_BIN_OP(^, logic)
7231REF_BIN_OP(>>, arg1)
7232REF_BIN_OP(<<, arg1)
7233#undef REF_BIN_OP
7234
7235//************************************************************************
7236// Implement
7237// ap_private<M+N> = ap_concat_ref<M> OP ap_concat_ref<N>
7238// for operators +, -, *, /, %, >>, <<, &, |, ^
7239// Without these operators the operands are converted to int64 and
7240// larger results lose informations (higher order bits).
7241//
7242// operand OP
7243// / |
7244// left-concat right-concat
7245// / | / |
7246// <LW1,LT1> <LW2,LT2> <RW1,RT1> <RW2,RT2>
7247//
7248// _AP_LW1, _AP_LT1 (width and type of left-concat's left side)
7249// _AP_LW2, _AP_LT2 (width and type of left-concat's right side)
7250// Similarly for RHS of operand OP: _AP_RW1, AP_RW2, _AP_RT1, _AP_RT2
7251//
7252// In Verilog 2001 result of concatenation is always unsigned even
7253// when both sides are signed.
7254//************************************************************************
7255
7256#endif // ifndef __AP_PRIVATE_H__
7257
7258// -*- cpp -*-
INLINE bool sgt(const ap_private< _AP_W, _AP_S1 > &RHS) const
Regards both *this and RHS as signed quantities and compares them for the validity of the greater-tha...
INLINE int64_t getSExtValue() const
This method attempts to return the value of this ap_private as a sign extended int64_t.
INLINE bool ugt(const ap_private< _AP_W, _AP_S1 > &RHS) const
Regards both *this and RHS as unsigned quantities and compares them for the validity of the greater-t...
INLINE ap_private(const ap_private &that)
Simply makes *this a copy of that.
INLINE ap_private & operator=(const ap_private &RHS)
@Assignment Operators
static INLINE uint32_t getBitsNeeded(const char *str, uint32_t slen, uint8_t radix)
This method determines how many bits are required to hold the ap_private equivalent of the string giv...
INLINE _private_range_ref< _AP_W, _AP_S > operator()(int Hi, int Lo)
Bit and Part Select.
INLINE ap_private & operator--()
Prefix decrement operator.
INLINE ap_private srem(const ap_private &RHS) const
Signed remainder operation on ap_private.
INLINE bool isMinSignedValue() const
This checks to see if the value of this ap_private is the minimum signed value for the ap_private's b...
INLINE std::string toStringSigned(uint8_t radix=10) const
Considers the ap_private to be unsigned and converts it into a string in the radix given.
INLINE double bitsToDouble() const
The conversion does not do a translation from integer to double, it just re-interprets the bits as a ...
INLINE bool ule(const ap_private< _AP_W, _AP_S1 > &RHS) const
Regards both *this and RHS as unsigned quantities and compares them for validity of the less-or-equal...
INLINE ap_private< _AP_W+!_AP_S, true > operator~() const
Performs a bitwise complement operation on this ap_private.
INLINE bool sge(const ap_private< _AP_W, _AP_S1 > &RHS) const
Regards both *this and RHS as signed quantities and compares them for validity of the greater-or-equa...
INLINE bool eq(const ap_private< _AP_W, _AP_S1 > &RHS) const
Compares this ap_private with RHS for the validity of the equality relationship.
static INLINE uint32_t whichWord(uint32_t bitPosition)
Determine which word a bit is in.
INLINE float bitsToFloat() const
The conversion does not do a translation from integer to float, it just re-interprets the bits as a f...
INLINE ap_private & operator++()
Prefix increment operator.
INLINE uint64_t getWord(uint32_t bitPosition) const
Get the word corresponding to a bit position.
INLINE ap_private(const char strStart[], uint32_t slen, uint8_t radix)
This constructor interprets the slen characters starting at StrStart as a string in the given radix.
INLINE ap_private(const std::string &val, uint8_t radix=2)
This constructor interprets Val as a string in the given radix.
INLINE ap_private sdiv(const ap_private &RHS) const
Signed divide this ap_private by ap_private RHS.
INLINE bool isAllOnesValue() const
This checks to see if the value has all bits of the ap_private are set or not.
INLINE ap_private srem(int64_t RHS) const
Signed remainder operation on ap_private.
INLINE void clear()
Set every bit to 0.
INLINE uint32_t getBitWidth() const
INLINE uint32_t countTrailingZeros() const
countTrailingZeros - This function is an ap_private version of the countTrailingZoers_{32,...
INLINE ap_private & clear(uint32_t bitPosition)
Set the given bit to 0 whose position is given as "bitPosition".
INLINE bool isMaxSignedValue() const
This checks to see if the value of this ap_private is the maximum signed value for the ap_private's b...
INLINE ap_private(uint32_t numWords, const uint64_t bigVal[])
This constructor is used only internally for speed of construction of temporaries.
INLINE double roundToDouble(bool isSigned) const
Converts this ap_private to a double value.
INLINE const uint64_t * getRawData() const
This function returns a pointer to the internal storage of the ap_private.
INLINE ap_private ashr(uint32_t shiftAmt) const
Arithmetic right-shift this ap_private by shiftAmt.
INLINE uint64_t getZExtValue() const
This method attempts to return the value of this ap_private as a zero extended uint64_t.
INLINE ap_private shl(uint32_t shiftAmt) const
Left-shift this ap_private by shiftAmt.
INLINE uint32_t getActiveBits() const
This function returns the number of active bits which is defined as the bit width minus the number of...
INLINE void clearUnusedBits(void) volatile
This method is used internally to clear the to "N" bits in the high order word that are not used by t...
INLINE bool isMinValue() const
This checks to see if the value of this ap_private is the minimum unsigned value for the ap_private's...
INLINE bool isStrictlyPositive() const
This tests if the value of this ap_private is strictly positive (> 0).
INLINE uint32_t countPopulation() const
countPopulation - This function is an ap_private version of the countPopulation_{32,...
INLINE uint32_t countLeadingZeros() const
countLeadingZeros - This function is an ap_private version of the countLeadingZeros_{32,...
INLINE bool ult(const ap_private< _AP_W, _AP_S1 > &RHS) const
Regards both *this and RHS as unsigned quantities and compares them for the validity of the less-than...
INLINE bool operator==(const ap_private &RHS) const
Comparisons.
INLINE const ap_private operator--(int)
Postfix decrement operator.
INLINE ap_private()
Default constructor that creates an uninitialized ap_private.
INLINE uint32_t getNumWords() const
Here one word's bitwidth equals to that of uint64_t.
INLINE bool uge(const ap_private< _AP_W, _AP_S > &RHS) const
Regards both *this and RHS as unsigned quantities and compares them for validity of the greater-or-eq...
INLINE ap_private & flip(uint32_t bitPosition)
Toggles a given bit to its opposite value.
INLINE bool ne(const ap_private< _AP_W, _AP_S1 > &RHS) const
Compares this ap_private with RHS for the validity of the inequality relationship.
INLINE RType< 1, false >::minus operator-() const
Negates *this using two's complement logic.
INLINE double signedRoundToDouble() const
Converts this signed ap_private to a double value.
INLINE ap_private lshr(uint32_t shiftAmt) const
Logical right-shift this ap_private by shiftAmt.
static INLINE uint64_t maskBit(uint32_t bitPosition)
bit at a specific bit position.
INLINE bool operator!() const
Performs logical negation operation on this ap_private.
static INLINE uint32_t whichBit(uint32_t bitPosition)
Determine which bit in a word a bit is in.
INLINE ap_private udiv(const ap_private &RHS) const
Perform an unsigned divide operation on this ap_private by RHS.
INLINE ap_private urem(uint64_t RHS) const
INLINE bool sle(const ap_private< _AP_W, _AP_S1 > &RHS) const
Regards both *this and RHS as signed quantities and compares them for validity of the less-or-equal r...
INLINE ap_private urem(const ap_private &RHS) const
Perform an unsigned remainder operation on this ap_private with RHS being the divisor.
INLINE ap_private & operator+=(const ap_private< _AP_W1, _AP_S1 > &RHS)
Adds the RHS APint to this ap_private.
INLINE std::string toStringUnsigned(uint8_t radix=10) const
Considers the ap_private to be unsigned and converts it into a string in the radix given.
INLINE ap_private & floatToBits(float __V)
The conversion does not do a translation from float to integer, it just re-interprets the bits of the...
INLINE void fromString(const char *str, uint32_t slen, uint8_t radix)
This is used by the constructors that take string arguments.
INLINE double roundToDouble() const
Converts this unsigned ap_private to a double value.
INLINE bool isMaxValue() const
This checks to see if the value of this ap_private is the maximum unsigned value for the ap_private's...
INLINE ~ap_private()
Destructor.
INLINE ap_private & doubleToBits(double __V)
The conversion does not do a translation from double to integer, it just re-interprets the bits of th...
INLINE ap_private & operator=(const char *s)
from c string.
INLINE uint32_t countLeadingOnes() const
countLeadingOnes - This function counts the number of contiguous 1 bits in the high order bits.
ap_private & flip()
Toggle every bit to its opposite value.
INLINE bool isPositive() const
This tests the high bit of the ap_private to determine if it is unset.
INLINE bool isSingleWord() const
Determine if this ap_private just has one word to store value.
INLINE bool ule(const ap_private< _AP_W1, _AP_S1 > &RHS) const
Regards both *this and RHS as unsigned quantities and compares them for validity of the less-or-equal...
INLINE bool sle(const ap_private< _AP_W1, _AP_S1 > &RHS) const
Regards both *this and RHS as signed quantities and compares them for validity of the less-or-equal r...
INLINE bool ult(const ap_private< _AP_W1, _AP_S1 > &RHS) const
Regards both *this and RHS as unsigned quantities and compares them for the validity of the less-than...
INLINE _private_range_ref< _AP_W, _AP_S > operator()(int Hi, int Lo)
Bit and Part Select.
ValType VAL
Used to store the <= 64 bits integer value.
const ap_private operator++(int)
postfix increment.
INLINE bool ugt(const ap_private< _AP_W1, _AP_S1 > &RHS) const
Regards both *this and RHS as unsigned quantities and compares them for the validity of the greater-t...
const ap_private operator--(int)
postfix decrement.
INLINE ap_private srem(const ap_private< _AP_W, _AP_S2 > &RHS) const
Signed remainder operation on ap_private.
INLINE bool sge(const ap_private< _AP_W1, _AP_S1 > &RHS) const
Regards both *this and RHS as signed quantities and compares them for validity of the greater-or-equa...
INLINE ap_private & flip()
Toggle all bits.
INLINE ap_private< _AP_W, _AP_S > getHiBits(uint32_t numBits) const
HiBits - This function returns the high "numBits" bits of this ap_private.
INLINE ap_private & flip(uint32_t bitPosition)
Toggles a given bit to its opposite value.
INLINE ap_private sdiv(const ap_private &RHS) const
Signed divide this ap_private by ap_private RHS.
INLINE ap_private< _AP_W, _AP_S > getLoBits(uint32_t numBits) const
LoBits - This function returns the low "numBits" bits of this ap_private.
INLINE bool operator!() const
logic negation.
INLINE ap_private< _AP_W+!_AP_S, true > operator~() const
one's complement.
const ap_private operator--()
prefix decrement.
INLINE bool sgt(const ap_private< _AP_W1, _AP_S1 > &RHS) const
Regards both *this and RHS as signed quantities and compares them for the validity of the greater-tha...
INLINE bool uge(const ap_private< _AP_W1, _AP_S1 > &RHS) const
Regards both *this and RHS as unsigned quantities and compares them for validity of the greater-or-eq...
INLINE RType< _AP_W2, _AP_S2 >::div operator/(const ap_private< _AP_W2, _AP_S2 > &op) const
Bitwise and, or, xor.
INLINE bool slt(const ap_private< _AP_W1, _AP_S1 > &RHS) const
Regards both *this and RHS as signed quantities and compares them for validity of the less-than relat...
INLINE bool operator==(const ap_private< _AP_W1, _AP_S1 > &op) const
Comparisons.
const ap_private operator++()
prefix increment.
INLINE RType< 1, false >::minus operator-() const
two's complement.
Bit reference Proxy class, which allows bit selection to be used as rvalue(for reading) and lvalue(fo...
Concatination reference.
INLINE _private_range_ref< _AP_W, _AP_S > & operator^=(const _private_range_ref< _AP_W2, _AP_S2 > &ref)
compound xor assignment.
INLINE _private_range_ref< _AP_W, _AP_S > & operator|=(const _AP_ROOT_TYPE< _AP_W2, _AP_S2 > &ref)
compound or assignment with root type.
INLINE _private_range_ref< _AP_W, _AP_S > & operator&=(const _AP_ROOT_TYPE< _AP_W2, _AP_S2 > &ref)
compound and assignment with root type.
INLINE _private_range_ref(ap_private< _AP_W, _AP_S > *bv, int h, int l)
direct ctor.
INLINE _private_range_ref< _AP_W, _AP_S > & operator&=(const _private_range_ref< _AP_W2, _AP_S2 > &ref)
compound and assignment.
INLINE _private_range_ref< _AP_W, _AP_S > & operator^=(const _AP_ROOT_TYPE< _AP_W2, _AP_S2 > &ref)
compound xor assignment with root type.
INLINE _private_range_ref< _AP_W, _AP_S > & operator|=(const _private_range_ref< _AP_W2, _AP_S2 > &ref)
compound or assignment.
INLINE _private_range_ref(const _private_range_ref< _AP_W, _AP_S > &ref)
copy ctor.