17#ifndef __AP_PRIVATE_H__
18#define __AP_PRIVATE_H__
22#ifndef __AP_COMMON_H__
23#error "ap_impl/ap_private.h cannot be included directly."
29template <
int _AP_W,
bool _AP_S>
31template <
int _AP_W,
bool _AP_S>
35#ifndef LLVM_SUPPORT_MATHEXTRAS_H
36#define LLVM_SUPPORT_MATHEXTRAS_H
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;
65template <
class DataType>
66DataType INLINE min(DataType a, DataType b) {
67 return (a >= b) ? b : a;
70template <
class DataType>
71DataType INLINE max(DataType a, DataType b) {
72 return (a >= b) ? a : b;
88namespace ap_private_ops {
90static INLINE uint32_t Hi_32(uint64_t Value) {
91 return static_cast<uint32_t
>(Value >> 32);
95static INLINE uint32_t Lo_32(uint64_t Value) {
96 return static_cast<uint32_t
>(Value);
100INLINE
bool isNegative(
const ap_private<_AP_W, false>& a) {
105INLINE
bool isNegative(
const ap_private<_AP_W, true>& a) {
107 APINT_BITS_PER_WORD = 64,
108 _AP_N = (_AP_W + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD
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;
118static INLINE
unsigned CountLeadingZeros_32(uint32_t Value) {
122#if !defined(__ppc__) && !defined(__ppc64__)
123 if (Value == 0)
return 32;
125 Count = __builtin_clz(Value);
127 if (Value == 0)
return 32;
130 for (
unsigned Shift = 32 >> 1; Shift; Shift >>= 1) {
131 uint32_t Tmp = (Value) >> (Shift);
146static INLINE
unsigned CountLeadingZeros_64(uint64_t Value) {
150#if !defined(__ppc__) && !defined(__ppc64__)
151 if (!Value)
return 64;
153 Count = __builtin_clzll(Value);
155 if (
sizeof(
long) ==
sizeof(int64_t)) {
156 if (!Value)
return 64;
159 for (
unsigned Shift = 64 >> 1; Shift; Shift >>= 1) {
160 uint64_t Tmp = (Value) >> (Shift);
169 uint32_t Hi = Hi_32(Value);
174 Count = CountLeadingZeros_32(Hi);
177 uint32_t Lo = Lo_32(Value);
179 Count = CountLeadingZeros_32(Lo) + 32;
190static INLINE
unsigned CountTrailingZeros_64(uint64_t Value) {
192 return (Value != 0) ? __builtin_ctzll(Value) : 64;
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];
205static INLINE
unsigned CountPopulation_64(uint64_t Value) {
207 return __builtin_popcountll(Value);
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);
216static INLINE uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) {
218 if (skip) (__V) <<= (skip);
219 while (__V && (__V & (1ULL << 63))) {
226static INLINE std::string oct2Bin(
char oct) {
259 assert(0 &&
"Invalid character in digit string");
263static INLINE std::string hex2Bin(
char hex) {
326 assert(0 &&
"Invalid character in digit string");
330static INLINE uint32_t decode_digit(
char cdigit,
int radix) {
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");
339 digit = cdigit -
'0';
340 else if (cdigit >=
'a')
341 digit = cdigit -
'a' + 10;
342 else if (cdigit >=
'A')
343 digit = cdigit -
'A' + 10;
345 assert(0 &&
"huh? we shouldn't get here");
346 }
else if (isdigit(cdigit)) {
347 digit = cdigit -
'0';
349 assert(0 &&
"Invalid character in digit string");
357static INLINE std::string parseString(
const std::string& input,
358 unsigned char& radix) {
359 size_t len = input.length();
361 if (radix == 0) radix = 10;
367 while (input[startPos] ==
' ' && startPos < len) startPos++;
368 while (input[len - 1] ==
' ' && startPos < len) len--;
370 std::string val = input.substr(startPos, len - startPos);
378 if (radix == 0) radix = 10;
382 bool isNegative =
false;
390 }
else if (val[0] ==
'+')
393 if (len - startPos < 2) {
394 if (radix == 0) radix = 10;
398 if (val.substr(startPos, 2) ==
"0x" || val.substr(startPos, 2) ==
"0X") {
402 }
else if (val.substr(startPos, 2) ==
"0b" ||
403 val.substr(startPos, 2) ==
"0B") {
407 }
else if (val.substr(startPos, 2) ==
"0o" ||
408 val.substr(startPos, 2) ==
"0O") {
412 }
else if (radix == 0) {
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) {
426 has_exponent =
false;
430 ans += val.substr(startPos, expPos - startPos);
433 std::istringstream iss(val.substr(expPos + 1, len - expPos - 1));
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) {
444 has_exponent =
false;
449 assert(startPos <= expPos);
451 for (
size_t i = startPos; i < expPos; ++i) {
453 ans += hex2Bin(val[i]);
454 }
else if (radix == 8) {
455 ans += oct2Bin(val[i]);
464 std::istringstream iss(val.substr(expPos + 1, len - expPos - 1));
468 if (exp == 0)
return ans;
470 size_t decPos = ans.find(
'.');
471 if (decPos == std::string::npos) decPos = ans.length();
472 if ((
int)decPos + exp >= (
int)ans.length()) {
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';
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];
488 for (
size_t i = decPos; i < decPos + exp; ++i) ans[i] = ans[i + 1];
490 if (decPos == ans.length()) ans +=
' ';
491 for (
int i = decPos; i > (int)decPos + exp; --i) ans[i] = ans[i - 1];
493 ans[decPos + exp] =
'.';
503static INLINE
bool sub_1(uint64_t x[], uint32_t len, uint64_t y) {
504 for (uint32_t i = 0; i < len; ++i) {
521static INLINE
bool add_1(uint64_t dest[], uint64_t x[], uint32_t len,
523 for (uint32_t i = 0; i < len; ++i) {
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) {
543 uint32_t len = AESL_std::min(xlen, ylen);
545 for (i = 0; i < len && i < destlen; ++i) {
547 AESL_std::min(x[i], y[i]);
548 dest[i] = x[i] + y[i] + carry;
549 carry = dest[i] < limit || (carry && dest[i] == limit);
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);
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);
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) {
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];
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;
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];
608static INLINE uint64_t mul_1(uint64_t dest[],
const uint64_t x[], uint32_t len,
611 uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32;
613 static const uint64_t two_power_32 = 1ULL << 32;
615 for (uint32_t i = 0; i < len; ++i) {
617 uint64_t lx = x[i] & 0xffffffffULL;
618 uint64_t hx = (x[i]) >> 32;
623 uint8_t hasCarry = 0;
624 dest[i] = carry + lx * ly;
626 hasCarry = (dest[i] < carry) ? 1 : 0;
627 carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0);
630 hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0);
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;
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) {
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;
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;
671 (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) +
672 ((carry) >> 32) + (dest[i + j] < resul ? 1 : 0) + ((lx * hy) >> 32) +
675 if (i + xlen < destlen) dest[i + xlen] = carry;
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");
693 uint64_t b = uint64_t(1) << 32;
711 uint32_t shift = CountLeadingZeros_32(v[n - 1]);
712 uint32_t v_carry = 0;
713 uint32_t u_carry = 0;
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;
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;
747 uint64_t dividend = ((uint64_t(u[j + n]) << 32) + u[j + n - 1]);
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]) {
754 if (rp < b && (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2])) qp--;
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;
771 uint64_t result = u_tmp - subtrahend;
773 u[k++] = (uint32_t)(result & (b - 1));
774 u[k++] = (uint32_t)((result) >> 32);
775 while (borrow && k <= m + n) {
794 for (uint32_t i = 0; i <= m + n; ++i) {
795 u[i] = ~u[i] + carry;
796 carry = carry && u[i] == 0;
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);
843 for (
int i = n - 1; i >= 0; i--) {
844 r[i] = ((u[i]) >> (shift)) | carry;
845 carry = (u[i]) << (32 - shift);
849 for (
int i = n - 1; i >= 0; i--) {
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 };
873 uint64_t
mask = ~0ull >> (
sizeof(uint32_t) * 8);
874 uint32_t n = rhsWords * 2;
875 uint32_t m = (lhsWords * 2) - n;
884 if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) {
886 __V = &SPACE[m + n + 1];
887 __Q = &SPACE[(m + n + 1) + n];
888 if (Remainder) __R = &SPACE[(m + n + 1) + n + (m + n)];
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];
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);
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);
914 memset(__Q, 0, (m + n) *
sizeof(uint32_t));
915 if (Remainder) memset(__R, 0, n *
sizeof(uint32_t));
921 for (
unsigned i = n; i > 0 && __V[i - 1] == 0; i--) {
925 for (
unsigned i = m + n; i > 0 && __U[i - 1] == 0; i--) m--;
933 assert(n != 0 &&
"Divide by zero?");
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) {
942 }
else if (partial_dividend < divisor) {
944 remainder = (uint32_t)partial_dividend;
945 }
else if (partial_dividend == divisor) {
949 __Q[i] = (uint32_t)(partial_dividend / divisor);
950 remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor));
953 if (__R) __R[0] = remainder;
957 KnuthDiv(__U, __V, __Q, __R, m, n);
963 if (Quotient->BitWidth != LHS.BitWidth) {
964 if (Quotient->isSingleWord()) Quotient->set_VAL(0);
972 uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2));
973 Quotient->set_VAL(tmp);
975 assert(!Quotient->isSingleWord() &&
976 "Quotient ap_private not large enough");
977 for (
unsigned i = 0; i < lhsWords; ++i)
979 i, uint64_t(__Q[i * 2]) |
980 ((uint64_t(__Q[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2)));
982 Quotient->clearUnusedBits();
988 if (Remainder->BitWidth != RHS.BitWidth) {
989 if (Remainder->isSingleWord()) Remainder->set_VAL(0);
997 uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2));
998 Remainder->set_VAL(tmp);
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)));
1007 Remainder->clearUnusedBits();
1011 if (__U != &SPACE[0]) {
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 };
1033 uint64_t
mask = ~0ull >> (
sizeof(uint32_t) * 8);
1035 uint32_t m = (lhsWords * 2) - n;
1039 uint32_t SPACE[128];
1044 if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) {
1046 __V = &SPACE[m + n + 1];
1047 __Q = &SPACE[(m + n + 1) + n];
1048 if (Remainder) __R = &SPACE[(m + n + 1) + n + (m + n)];
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];
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);
1066 memset(__V, 0, (n) *
sizeof(uint32_t));
1067 __V[0] = RHS &
mask;
1068 __V[1] = (RHS) >> (
sizeof(uint32_t) * 8);
1071 memset(__Q, 0, (m + n) *
sizeof(uint32_t));
1072 if (Remainder) memset(__R, 0, n *
sizeof(uint32_t));
1078 for (
unsigned i = n; i > 0 && __V[i - 1] == 0; i--) {
1082 for (
unsigned i = m + n; i > 0 && __U[i - 1] == 0; i--) m--;
1090 assert(n != 0 &&
"Divide by zero?");
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) {
1099 }
else if (partial_dividend < divisor) {
1101 remainder = partial_dividend;
1102 }
else if (partial_dividend == divisor) {
1106 __Q[i] = partial_dividend / divisor;
1107 remainder = partial_dividend - (__Q[i] * divisor);
1110 if (__R) __R[0] = remainder;
1114 KnuthDiv(__U, __V, __Q, __R, m, n);
1120 if (Quotient->BitWidth != LHS.BitWidth) {
1121 if (Quotient->isSingleWord()) Quotient->set_VAL(0);
1127 if (lhsWords == 1) {
1129 uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2));
1130 Quotient->set_VAL(tmp);
1132 assert(!Quotient->isSingleWord() &&
1133 "Quotient ap_private not large enough");
1134 for (
unsigned i = 0; i < lhsWords; ++i)
1136 i, uint64_t(__Q[i * 2]) |
1137 ((uint64_t(__Q[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2)));
1139 Quotient->clearUnusedBits();
1145 if (Remainder->BitWidth != 64 ) {
1146 if (Remainder->isSingleWord()) Remainder->set_VAL(0);
1152 if (rhsWords == 1) {
1154 uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2));
1155 Remainder->set_VAL(tmp);
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)));
1164 Remainder->clearUnusedBits();
1168 if (__U != &SPACE[0]) {
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);
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);
1239#if defined(_MSC_VER)
1240#if _MSC_VER < 1400 && !defined(for)
1246typedef unsigned __int64 ap_ulong;
1247typedef signed __int64 ap_slong;
1249typedef unsigned long long ap_ulong;
1250typedef signed long long ap_slong;
1252template <
int _AP_N8,
bool _AP_S>
1255template <
int _AP_N8>
1257 typedef uint64_t Type;
1260template <
int _AP_N8>
1262 typedef int64_t Type;
1267 typedef unsigned char Type;
1271 typedef unsigned short Type;
1275 typedef unsigned int Type;
1279 typedef unsigned int Type;
1283 typedef signed char Type;
1298template <
bool enable>
1302 static const bool isValid =
true;
1306template <
int _AP_W,
bool _AP_S>
1307class ap_private<_AP_W, _AP_S, true> {
1312#pragma warning(disable : 4521 4522)
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>
1320 mult_w = _AP_W + _AP_W2,
1321 mult_s = _AP_S || _AP_S2,
1323 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
1324 plus_s = _AP_S || _AP_S2,
1326 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
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)),
1332 logic_w = AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)),
1333 logic_s = _AP_S || _AP_S2
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;
1344 enum { APINT_BITS_PER_WORD =
sizeof(uint64_t) * 8 };
1346 excess_bits = (_AP_W % APINT_BITS_PER_WORD)
1347 ? APINT_BITS_PER_WORD - (_AP_W % APINT_BITS_PER_WORD)
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;
1357 static const int width = _AP_W;
1366 void check_canary() { assert(CANARY == (ValType)0xDEADBEEFDEADBEEF); }
1367 void set_canary() { CANARY = (ValType)0xDEADBEEFDEADBEEF; }
1369 void check_canary() {}
1370 void set_canary() {}
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");
1383 INLINE ValType get_pVal(
int i)
const volatile {
return VAL; }
1384 INLINE uint64_t* get_pVal()
const volatile {
1385 assert(0 &&
"invalid usage");
1388 INLINE
void set_pVal(
int i, uint64_t value) { VAL = (ValType)value; }
1390 INLINE uint32_t getBitWidth()
const {
return BitWidth; }
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());
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());
1408 void operator=(
const ap_private& RHS)
volatile {
1410 VAL = RHS.get_VAL();
1414 ap_private& operator=(
const ap_private& RHS) {
1416 VAL = RHS.get_VAL();
1421 void operator=(
const volatile ap_private& RHS)
volatile {
1423 VAL = RHS.get_VAL();
1427 ap_private& operator=(
const volatile ap_private& RHS) {
1429 VAL = RHS.get_VAL();
1434 template <
int _AP_W2,
bool _AP_S2>
1436 *
this = ap_private<_AP_W2, false>(op2);
1440#define ASSIGN_OP_FROM_INT(C_TYPE) \
1441 INLINE ap_private& operator=(const C_TYPE v) { \
1443 this->VAL = (ValType)v; \
1444 clearUnusedBits(); \
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)
1462ASSIGN_OP_FROM_INT(half)
1463ASSIGN_OP_FROM_INT(
float)
1464ASSIGN_OP_FROM_INT(
double)
1466#undef ASSIGN_OP_FROM_INT
1469 INLINE ap_private& operator=(
const char* s) {
1476 explicit INLINE ap_private(uint64_t* val) : VAL(val[0]) {
1482 INLINE
bool isSingleWord()
const {
return true; }
1485 INLINE
void fromString(
const char* strStart, uint32_t slen, uint8_t radix) {
1486 bool isNeg = strStart[0] ==
'-';
1492 if (strStart[0] ==
'0' && (strStart[1] ==
'b' || strStart[1] ==
'B')) {
1494 _AP_WARNING(radix != 2,
"%s seems to have base %d, but %d given.",
1495 strStart, 2, radix);
1498 }
else if (strStart[0] ==
'0' &&
1499 (strStart[1] ==
'o' || strStart[1] ==
'O')) {
1501 _AP_WARNING(radix != 8,
"%s seems to have base %d, but %d given.",
1502 strStart, 8, radix);
1505 }
else if (strStart[0] ==
'0' &&
1506 (strStart[1] ==
'x' || strStart[1] ==
'X')) {
1508 _AP_WARNING(radix != 16,
"%s seems to have base %d, but %d given.",
1509 strStart, 16, radix);
1512 }
else if (strStart[0] ==
'0' &&
1513 (strStart[1] ==
'd' || strStart[1] ==
'D')) {
1515 _AP_WARNING(radix != 10,
"%s seems to have base %d, but %d given.",
1516 strStart, 10, radix);
1519 }
else if (radix == 0) {
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?");
1529 uint64_t tmpVAL = VAL = 0;
1535 for (; *strStart; ++strStart) {
1536 assert((*strStart ==
'0' || *strStart ==
'1') &&
1537 (
"Wrong binary number"));
1539 tmpVAL |= (*strStart -
'0');
1544 sscanf_s(strStart,
"%llo", &tmpVAL, slen + 1);
1546#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__)
1547 sscanf(strStart,
"%lo", &tmpVAL);
1549 sscanf(strStart,
"%llo", &tmpVAL);
1555 sscanf_s(strStart,
"%llu", &tmpVAL, slen + 1);
1557#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__)
1558 sscanf(strStart,
"%lu", &tmpVAL);
1560 sscanf(strStart,
"%llu", &tmpVAL);
1566 sscanf_s(strStart,
"%llx", &tmpVAL, slen + 1);
1568#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__)
1569 sscanf(strStart,
"%lx", &tmpVAL);
1571 sscanf(strStart,
"%llx", &tmpVAL);
1576 assert(
true &&
"Unknown radix");
1579 VAL = isNeg ? (ValType)(-tmpVAL) : (ValType)(tmpVAL);
1585 INLINE ap_private(
const std::string& val, uint8_t radix = 2) : VAL(0) {
1586 assert(!val.empty() &&
"String empty?");
1588 fromString(val.c_str(), val.size(), radix);
1592 INLINE ap_private(
const char strStart[], uint32_t slen, uint8_t radix)
1595 fromString(strStart, slen, radix);
1599 INLINE ap_private(uint32_t numWords,
const uint64_t bigVal[])
1607 INLINE ap_private() : VAL(0) {
1614 INLINE ap_private(TYPE v) : VAL((ValType)v) { \
1616 clearUnusedBits(); \
1624 CTOR(
unsigned short)
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()) {
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()) {
1654 explicit INLINE ap_private(
const char* val) {
1656 unsigned char radix = 10;
1658 ap_private_ops::parseString(val, radix);
1659 std::string::size_type pos = str.find(
'.');
1661 if (pos != std::string::npos) str = str.substr(pos);
1663 ap_private<_AP_W, _AP_S> ap_private_val(str, radix);
1664 operator=(ap_private_val);
1668 INLINE ap_private(
const char* val,
signed char rd) {
1670 unsigned char radix = rd;
1672 ap_private_ops::parseString(val, radix);
1673 std::string::size_type pos = str.find(
'.');
1675 if (pos != std::string::npos) str = str.substr(pos);
1677 ap_private<_AP_W, _AP_S> ap_private_val(str, radix);
1678 operator=(ap_private_val);
1682 INLINE ~ap_private() { check_canary(); }
1684 INLINE
bool isNegative()
const {
1685 static const uint64_t sign_mask = 1ULL << (_AP_W - 1);
1686 return _AP_S && (sign_mask & VAL);
1689 INLINE
bool isPositive()
const {
return !isNegative(); }
1691 INLINE
bool isStrictlyPositive()
const {
return !isNegative() && VAL != 0; }
1693 INLINE
bool isAllOnesValue()
const {
return (
mask & VAL) ==
mask; }
1695 INLINE
bool operator==(
const ap_private<_AP_W, _AP_S>& RHS)
const {
1696 return VAL == RHS.get_VAL();
1698 INLINE
bool operator==(
const ap_private<_AP_W, !_AP_S>& RHS)
const {
1699 return (uint64_t)VAL == (uint64_t)RHS.get_VAL();
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();
1707 INLINE
bool operator!=(
const ap_private<_AP_W, !_AP_S>& RHS)
const {
1708 return (uint64_t)VAL != (uint64_t)RHS.get_VAL();
1713 ap_private orig(*
this);
1728 ap_private orig(*
this);
1743 ap_private<_AP_W + !_AP_S, true> Result(*
this);
1750 return ap_private<1, false>(0) - (*this);
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);
1760 INLINE std::string toStringSigned(uint8_t radix = 10)
const {
1761 return toString(radix,
true);
1763 INLINE
void clear() { VAL = 0; }
1764 INLINE ap_private& clear(uint32_t bitPosition) {
1765 VAL &= ~(1ULL << (bitPosition));
1770 INLINE ap_private ashr(uint32_t shiftAmt)
const {
1772 return ap_private((shiftAmt == BitWidth) ? 0
1773 : ((int64_t)VAL) >> (shiftAmt));
1775 return ap_private((shiftAmt == BitWidth) ? 0
1776 : ((uint64_t)VAL) >> (shiftAmt));
1779 INLINE ap_private lshr(uint32_t shiftAmt)
const {
1780 return ap_private((shiftAmt == BitWidth)
1782 : ap_private((VAL &
mask) >> (shiftAmt)));
1785 INLINE ap_private shl(uint32_t shiftAmt)
const
1787#if defined(__clang__) && !defined(__CLANG_3_1__)
1788 __attribute__((no_sanitize(
"undefined")))
1791 if (shiftAmt > BitWidth) {
1793 return ap_private(0);
1795 return ap_private(-1);
1797 if (shiftAmt == BitWidth)
1798 return ap_private(0);
1800 return ap_private((VAL) << (shiftAmt));
1805 INLINE int64_t getSExtValue()
const {
return VAL; }
1808 INLINE uint64_t getZExtValue()
const {
return VAL &
mask; }
1810 template <
int _AP_W2,
bool _AP_S2>
1817 template <
int _AP_W2,
bool _AP_S2>
1820 *
this = ((uint64_t)(
bool)ref);
1852 INLINE
void write(
const ap_private<_AP_W, _AP_S>& op2)
volatile {
1858 INLINE
operator ValType()
const {
return get_VAL(); }
1860 INLINE
int to_uchar()
const {
return (
unsigned char)get_VAL(); }
1862 INLINE
int to_char()
const {
return (
signed char)get_VAL(); }
1864 INLINE
int to_ushort()
const {
return (
unsigned short)get_VAL(); }
1866 INLINE
int to_short()
const {
return (
short)get_VAL(); }
1868 INLINE
int to_int()
const {
1870 return (
int)get_VAL();
1873 INLINE
unsigned to_uint()
const {
return (
unsigned)get_VAL(); }
1875 INLINE
long to_long()
const {
return (
long)get_VAL(); }
1877 INLINE
unsigned long to_ulong()
const {
return (
unsigned long)get_VAL(); }
1879 INLINE ap_slong to_int64()
const {
return (ap_slong)get_VAL(); }
1881 INLINE ap_ulong to_uint64()
const {
return (ap_ulong)get_VAL(); }
1883 INLINE
double to_double()
const {
1885 return roundToDouble(
true);
1887 return roundToDouble(
false);
1890 INLINE
unsigned length()
const {
return _AP_W; }
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());
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());
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());
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());
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());
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());
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) &
1943 typename RType<_AP_W1, _AP_S1>::logic Ret = *
this;
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) ^
1956 typename RType<_AP_W1, _AP_S1>::logic Ret = *
this;
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) |
1969 typename RType<_AP_W1, _AP_S1>::logic Ret = *
this;
1974 INLINE ap_private And(
const ap_private& RHS)
const {
1975 return ap_private(VAL & RHS.get_VAL());
1978 INLINE ap_private Or(
const ap_private& RHS)
const {
1979 return ap_private(VAL | RHS.get_VAL());
1982 INLINE ap_private Xor(
const ap_private& RHS)
const {
1983 return ap_private(VAL ^ RHS.get_VAL());
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) *
1994 typename RType<_AP_W1, _AP_S1>::mult Result(*
this);
2000 INLINE ap_private Mul(
const ap_private& RHS)
const {
2001 return ap_private(VAL * RHS.get_VAL());
2004 INLINE ap_private Add(
const ap_private& RHS)
const {
2005 return ap_private(VAL + RHS.get_VAL());
2008 INLINE ap_private Sub(
const ap_private& RHS)
const {
2009 return ap_private(VAL - RHS.get_VAL());
2012 INLINE ap_private& operator&=(uint64_t RHS) {
2013 VAL &= (ValType)RHS;
2017 INLINE ap_private& operator|=(uint64_t RHS) {
2018 VAL |= (ValType)RHS;
2022 INLINE ap_private& operator^=(uint64_t RHS) {
2023 VAL ^= (ValType)RHS;
2027 INLINE ap_private& operator*=(uint64_t RHS) {
2028 VAL *= (ValType)RHS;
2032 INLINE ap_private& operator+=(uint64_t RHS) {
2033 VAL += (ValType)RHS;
2037 INLINE ap_private& operator-=(uint64_t RHS) {
2038 VAL -= (ValType)RHS;
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));
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;
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;
2074 INLINE uint32_t countPopulation()
const {
2075 return ap_private_ops::CountPopulation_64(VAL);
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);
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);
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);
2101 INLINE ap_private<_AP_W, _AP_S>& set(uint32_t bitPosition) {
2102 VAL |= (1ULL << (bitPosition));
2108 VAL = (ValType)~0ULL;
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));
2117 INLINE
void set(
const ap_private& val) { operator=(val); }
2119 INLINE
void clearUnusedBits(
void)
volatile
2121#if defined(__clang__) && !defined(__CLANG_3_1__)
2122 __attribute__((no_sanitize(
"undefined")))
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)) >>
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);
2138 INLINE ap_private udiv(
const ap_private& RHS)
const {
2139 return ap_private((uint64_t)VAL / RHS.get_VAL());
2144 INLINE ap_private
sdiv(
const ap_private& RHS)
const {
2146 if (RHS.isNegative())
2147 return ((uint64_t)(0 - (*
this))) / (uint64_t)(0 - RHS);
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);
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()));
2163 template <
bool _AP_S2>
2164 INLINE ap_private
srem(
const ap_private<_AP_W, _AP_S2>& RHS)
const {
2166 ap_private lhs = 0 - (*this);
2167 if (RHS.isNegative()) {
2168 ap_private rhs = 0 - RHS;
2169 return 0 - (lhs.urem(rhs));
2171 return 0 - (lhs.urem(RHS));
2172 }
else if (RHS.isNegative()) {
2173 ap_private rhs = 0 - RHS;
2174 return this->urem(rhs);
2176 return this->urem(RHS);
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;
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);
2193 template <
int _AP_W1,
bool _AP_S1>
2194 INLINE
bool ult(
const ap_private<_AP_W1, _AP_S1>& RHS)
const {
2196 uint64_t lhsZext = ((uint64_t(VAL)) << (64 - _AP_W)) >> (64 - _AP_W);
2198 ((uint64_t(RHS.get_VAL())) << (64 - _AP_W1)) >> (64 - _AP_W1);
2199 return lhsZext < rhsZext;
2201 return RHS.uge(*
this);
2208 template <
int _AP_W1,
bool _AP_S1>
2209 INLINE
bool slt(
const ap_private<_AP_W1, _AP_S1>& RHS)
const
2211#if defined(__clang__) && !defined(__CLANG_3_1__)
2212 __attribute__((no_sanitize(
"undefined")))
2216 int64_t lhsSext = ((int64_t(VAL)) << (64 - _AP_W)) >> (64 - _AP_W);
2218 ((int64_t(RHS.get_VAL())) << (64 - _AP_W1)) >> (64 - _AP_W1);
2219 return lhsSext < rhsSext;
2221 return RHS.sge(*
this);
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);
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);
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);
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);
2264 template <
int _AP_W1,
bool _AP_S1>
2265 INLINE
bool uge(
const ap_private<_AP_W1, _AP_S1>& RHS)
const {
2273 template <
int _AP_W1,
bool _AP_S1>
2274 INLINE
bool sge(
const ap_private<_AP_W1, _AP_S1>& RHS)
const {
2278 INLINE ap_private abs()
const {
2279 if (isNegative())
return -(*this);
2283 INLINE ap_private<_AP_W, false> get()
const {
2284 ap_private<_AP_W, false> ret(*
this);
2288 INLINE
static uint32_t getBitsNeeded(
const char* str, uint32_t slen,
2293 INLINE uint32_t getActiveBits()
const {
2294 uint32_t bits = _AP_W - countLeadingZeros();
2295 return bits ? bits : 1;
2298 INLINE
double roundToDouble(
bool isSigned =
false)
const {
2299 return isSigned ? double((int64_t)VAL) : double((uint64_t)VAL);
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))
2314 clear(_AP_W - 1 - i);
2321 INLINE
bool iszero()
const {
return isMinValue(); }
2323 INLINE
bool to_bool()
const {
return !iszero(); }
2326 INLINE
bool sign()
const {
2327 if (isNegative())
return true;
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");
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);
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));
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));
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);
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);
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);
2384 VAL = (ValType)((~0ULL ^ VAL) &
mask);
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));
2397 INLINE
void b_not() { flip(); }
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); \
2416 template <
int _AP_W2,
bool _AP_S2>
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))>
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))>
2427 return typename RType<_AP_W2, _AP_S2>::div(
2428 (_AP_S || _AP_S2) ? lhs.sdiv(rhs) : lhs.udiv(rhs));
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))>
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))>
2442 typename RType<_AP_W2, _AP_S2>::mod res =
2443 typename RType<_AP_W2, _AP_S2>::mod(_AP_S ? lhs.srem(rhs)
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); \
2458#undef OP_ASSIGN_AP_2
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); \
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)
2486 OP_LEFT_SHIFT_CTYPE(half,
false)
2487 OP_LEFT_SHIFT_CTYPE(
float, false)
2488 OP_LEFT_SHIFT_CTYPE(
double, false)
2491#undef OP_LEFT_SHIFT_CTYPE
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();
2499 int sh = op2.to_int();
2504#define OP_RIGHT_SHIFT_CTYPE(TYPE, SIGNED) \
2505 INLINE ap_private operator>>(const TYPE op) const { \
2506 if (op >= _AP_W) { \
2508 return ap_private(-1); \
2510 return ap_private(0); \
2512 if ((SIGNED) && op < 0) return *this << (0 - op); \
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)
2532 OP_RIGHT_SHIFT_CTYPE(half,
false)
2533 OP_RIGHT_SHIFT_CTYPE(
float, false)
2534 OP_RIGHT_SHIFT_CTYPE(
double, false)
2537#undef OP_RIGHT_SHIFT_CTYPE
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();
2545 int sh = op2.to_int();
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(); \
2566 INLINE ap_private& operator Sym##=(unsigned int op) { \
2567 *this = operator Sym(op); \
2568 clearUnusedBits(); \
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(); \
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();
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);
2600 template <
int _AP_W2,
bool _AP_S2>
2601 INLINE
bool operator>(
const ap_private<_AP_W2, _AP_S2>& op)
const {
2603 _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2))
2605 ap_private<_AP_MAX_W, _AP_S> lhs(*
this);
2606 ap_private<_AP_MAX_W, _AP_S2> rhs(op);
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)
2613 return lhs.sgt(rhs);
2618 if (_AP_W2 >= _AP_W)
2619 return lhs.ugt(rhs);
2621 return lhs.sgt(rhs);
2622 else if (_AP_W >= _AP_W2)
2623 return lhs.ugt(rhs);
2625 return lhs.sgt(rhs);
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);
2633 template <
int _AP_W2,
bool _AP_S2>
2634 INLINE
bool operator<(
const ap_private<_AP_W2, _AP_S2>& op)
const {
2636 _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2))
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);
2645 if (_AP_W2 >= _AP_W)
2646 return lhs.ult(rhs);
2648 return lhs.slt(rhs);
2649 else if (_AP_W >= _AP_W2)
2650 return lhs.ult(rhs);
2652 return lhs.slt(rhs);
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);
2669 const_cast<ap_private<_AP_W, _AP_S>*
>(
this), Hi, Lo);
2674 (
const_cast<ap_private<_AP_W, _AP_S>*
>(
this)), Hi, Lo);
2685 template <
int _AP_W2,
bool _AP_S2>
2687 const ap_private<_AP_W2, _AP_S2>& index) {
2693 const_cast<ap_private<_AP_W, _AP_S>&
>(*
this), index);
2696 template <
int _AP_W2,
bool _AP_S2>
2698 const ap_private<_AP_W2, _AP_S2>& index)
const {
2700 const_cast<ap_private<_AP_W, _AP_S>&
>(*
this), index.to_int());
2707 template <
int _AP_W2,
bool _AP_S2>
2709 const ap_private<_AP_W2, _AP_S2>& index) {
2715 const_cast<ap_private<_AP_W, _AP_S>&
>(*
this), index);
2718 template <
int _AP_W2,
bool _AP_S2>
2720 const ap_private<_AP_W2, _AP_S2>& index)
const {
2722 const_cast<ap_private<_AP_W, _AP_S>&
>(*
this), index.to_int());
2914 INLINE
bool and_reduce()
const {
return (VAL &
mask) ==
mask; }
2916 INLINE
bool nand_reduce()
const {
return (VAL &
mask) !=
mask; }
2918 INLINE
bool or_reduce()
const {
return (
bool)VAL; }
2920 INLINE
bool nor_reduce()
const {
return VAL == 0; }
2922 INLINE
bool xor_reduce()
const {
2923 unsigned int i = countPopulation();
2924 return (i % 2) ? true :
false;
2927 INLINE
bool xnor_reduce()
const {
2928 unsigned int i = countPopulation();
2929 return (i % 2) ? false :
true;
2932 INLINE std::string to_string(uint8_t radix = 2,
bool sign =
false)
const {
2933 return toString(radix, radix == 10 ? _AP_S : sign);
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"};
2951 if (*
this == (uint64_t)(0)) {
2965 assert(
"invalid radix" && 0);
2968 ap_private<_AP_W, false, true> tmp(*
this);
2969 size_t insert_at = 0;
2970 bool leading_zero =
true;
2971 if (wantSigned && isNegative()) {
2979 leading_zero =
false;
2992 assert(
"invalid radix" && 0);
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);
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);
3007 msb = (digit >> (shift - 1)) == 1;
3010 if (bits < _AP_W && leading_zero && msb)
3011 result.insert(insert_at, digits[0]);
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()) {
3029 if (tmp == ap_private<_AP_W, false, true>(0ULL))
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]);
3045template <
int _AP_W,
bool _AP_S>
3046class ap_private<_AP_W, _AP_S, false> {
3051#pragma warning(disable : 4521 4522)
3054 enum { BitWidth = _AP_W, _AP_N = (_AP_W + 63) / 64 };
3055 static const int width = _AP_W;
3070 assert(bigVal &&
"Null pointer detected!");
3073 memset(pVal, 0, _AP_N *
sizeof(uint64_t));
3076 uint32_t words = AESL_std::min<uint32_t>(numWords, _AP_N);
3078 memcpy(pVal, bigVal, words * APINT_WORD_SIZE);
3079 if (words >= _AP_W) clearUnusedBits();
3095 assert(!val.empty() &&
"The input string is empty.");
3096 const char* c_str = val.c_str();
3097 fromString(c_str, val.size(), radix);
3111 INLINE
ap_private(
const char strStart[], uint32_t slen, uint8_t radix) {
3113 fromString(strStart, slen, radix);
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);
3129 uint64_t pVal[_AP_N];
3132 INLINE
void check_canary() { assert(CANARY == (uint64_t)0xDEADBEEFDEADBEEF); }
3133 INLINE
void set_canary() { CANARY = (uint64_t)0xDEADBEEFDEADBEEF; }
3135 INLINE
void check_canary() {}
3136 INLINE
void set_canary() {}
3141 typedef ap_private<_AP_W, _AP_S> 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>
3148 template <
int _AP_W2,
bool _AP_S2>
3151 mult_w = _AP_W + _AP_W2,
3152 mult_s = _AP_S || _AP_S2,
3154 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
3155 plus_s = _AP_S || _AP_S2,
3157 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
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)),
3163 logic_w = AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)),
3164 logic_s = _AP_S || _AP_S2
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;
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; }
3190 APINT_BITS_PER_WORD =
sizeof(uint64_t) * 8,
3191 APINT_WORD_SIZE =
sizeof(uint64_t)
3195 excess_bits = (_AP_W % APINT_BITS_PER_WORD)
3196 ? APINT_BITS_PER_WORD - (_AP_W % APINT_BITS_PER_WORD)
3199 static const uint64_t
mask = ((uint64_t)~0ULL >> (excess_bits));
3203 explicit INLINE ap_private(
const char* val) {
3205 unsigned char radix = 10;
3207 ap_private_ops::parseString(val, 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);
3216 INLINE ap_private(
const char* val,
unsigned char rd) {
3218 unsigned char radix = rd;
3220 ap_private_ops::parseString(val, 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);
3231 template <
int _AP_W2,
bool _AP_S2>
3239 template <
int _AP_W2,
bool _AP_S2>
3242 *
this = ((uint64_t)(
bool)ref);
3282 memcpy(pVal, that.get_pVal(), _AP_N * APINT_WORD_SIZE);
3287 template <
int _AP_W1,
bool _AP_S1>
3288 INLINE ap_private(
const ap_private<_AP_W1, _AP_S1, false>& that) {
3294 template <
int _AP_W1,
bool _AP_S1>
3295 INLINE ap_private(
const volatile ap_private<_AP_W1, _AP_S1, false>& that) {
3297 operator=(
const_cast<const ap_private<_AP_W1, _AP_S1, false>&
>(that));
3301 template <
int _AP_W1,
bool _AP_S1>
3302 INLINE ap_private(
const ap_private<_AP_W1, _AP_S1, true>& that) {
3304 static const uint64_t that_sign_ext_mask =
3305 (_AP_W1 == APINT_BITS_PER_WORD)
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));
3313 pVal[0] = that.get_VAL();
3314 memset(pVal + 1, 0,
sizeof(uint64_t) * (_AP_N - 1));
3320 template <
int _AP_W1,
bool _AP_S1>
3321 INLINE ap_private(
const volatile ap_private<_AP_W1, _AP_S1, true>& that) {
3323 operator=(
const_cast<const ap_private<_AP_W1, _AP_S1, true>&
>(that));
3339 memset(pVal, 0, _AP_N *
sizeof(uint64_t));
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); }
3355#define CTOR(TYPE, SIGNED) \
3356 INLINE ap_private(TYPE val, bool isSigned = SIGNED) { \
3358 pVal[0] = (ValType)val; \
3359 if (isSigned && int64_t(pVal[0]) < 0) { \
3360 memset(pVal + 1, ~0, sizeof(uint64_t) * (_AP_N - 1)); \
3362 memset(pVal + 1, 0, sizeof(uint64_t) * (_AP_N - 1)); \
3364 clearUnusedBits(); \
3369 CTOR(
char, CHAR_IS_SIGNED)
3370 CTOR(
signed char, true)
3371 CTOR(
unsigned char, false)
3373 CTOR(
unsigned short, false)
3375 CTOR(
unsigned int, false)
3377 CTOR(
unsigned long, false)
3378 CTOR(ap_slong, true)
3379 CTOR(ap_ulong, false)
3395 return (bitPosition) >> 6;
3401 static INLINE uint32_t
whichBit(uint32_t bitPosition) {
3403 return bitPosition & 0x3f;
3410 static INLINE uint64_t
maskBit(uint32_t bitPosition) {
3411 return 1ULL << (whichBit(bitPosition));
3416 INLINE uint64_t
getWord(uint32_t bitPosition)
const {
3417 return pVal[whichWord(bitPosition)];
3427#if defined(__clang__) && !defined(__CLANG_3_1__)
3428 __attribute__((no_sanitize(
"undefined")))
3432 _AP_S ? ((((int64_t)pVal[_AP_N - 1]) << (excess_bits)) >> excess_bits)
3434 ? ((pVal[_AP_N - 1]) << (excess_bits)) >> (excess_bits)
3438 INLINE
void clearUnusedBitsToZero(
void) { pVal[_AP_N - 1] &=
mask; }
3440 INLINE
void clearUnusedBitsToOne(
void) { pVal[_AP_N - 1] |=
mask; }
3444 INLINE
void fromString(
const char* str, uint32_t slen, uint8_t radix) {
3445 enum { numbits = _AP_W };
3446 bool isNeg = str[0] ==
'-';
3452 if (str[0] ==
'0' && (str[1] ==
'b' || str[1] ==
'B')) {
3454 _AP_WARNING(radix != 2,
"%s seems to have base %d, but %d given.", str, 2,
3458 }
else if (str[0] ==
'0' && (str[1] ==
'o' || str[1] ==
'O')) {
3460 _AP_WARNING(radix != 8,
"%s seems to have base %d, but %d given.", str, 8,
3464 }
else if (str[0] ==
'0' && (str[1] ==
'x' || str[1] ==
'X')) {
3466 _AP_WARNING(radix != 16,
"%s seems to have base %d, but %d given.", str,
3470 }
else if (str[0] ==
'0' && (str[1] ==
'd' || str[1] ==
'D')) {
3472 _AP_WARNING(radix != 10,
"%s seems to have base %d, but %d given.", str,
3476 }
else if (radix == 0) {
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?");
3486 while (*str ==
'0' && *(str + 1) !=
'\0') {
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");
3499 memset(pVal, 0, _AP_N *
sizeof(uint64_t));
3502 uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0);
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);
3512 for (
unsigned i = 0; i < slen; i++) {
3515 char cdigit = str[i];
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;
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");
3544 apdigit.set_VAL(digit);
3555 INLINE ap_private read()
volatile {
return *
this; }
3557 INLINE
void write(
const ap_private& op2)
volatile { *
this = (op2); }
3559 INLINE
operator ValType()
const {
return get_VAL(); }
3561 INLINE
int to_uchar()
const {
return (
unsigned char)get_VAL(); }
3563 INLINE
int to_char()
const {
return (
signed char)get_VAL(); }
3565 INLINE
int to_ushort()
const {
return (
unsigned short)get_VAL(); }
3567 INLINE
int to_short()
const {
return (
short)get_VAL(); }
3569 INLINE
int to_int()
const {
return (
int)get_VAL(); }
3571 INLINE
unsigned to_uint()
const {
return (
unsigned)get_VAL(); }
3573 INLINE
long to_long()
const {
return (
long)get_VAL(); }
3575 INLINE
unsigned long to_ulong()
const {
return (
unsigned long)get_VAL(); }
3577 INLINE ap_slong to_int64()
const {
return (ap_slong)get_VAL(); }
3579 INLINE ap_ulong to_uint64()
const {
return (ap_ulong)get_VAL(); }
3581 INLINE
double to_double()
const {
3583 return roundToDouble(
true);
3585 return roundToDouble(
false);
3588 INLINE
unsigned length()
const {
return _AP_W; }
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))
3602 clear(_AP_W - 1 - i);
3609 INLINE
bool iszero()
const {
return isMinValue(); }
3611 INLINE
bool to_bool()
const {
return !iszero(); }
3614 INLINE
bool sign()
const {
3615 if (isNegative())
return true;
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");
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);
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);
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);
3648 INLINE ap_private& set(uint32_t bitPosition) {
3649 pVal[whichWord(bitPosition)] |= maskBit(bitPosition);
3655 for (
int i = 0; i < _AP_N; ++i) pVal[i] = ~0ULL;
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);
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);
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));
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));
3691 INLINE ap_private&
clear(uint32_t bitPosition) {
3692 pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition);
3698 INLINE
void clear() { memset(pVal, 0, _AP_N * APINT_WORD_SIZE); }
3702 for (
int i = 0; i < _AP_N; ++i) pVal[i] ^= ~0ULL;
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));
3715 INLINE
void b_not() { flip(); }
3717 INLINE ap_private getLoBits(uint32_t numBits)
const {
3718 return ap_private_ops::lshr(ap_private_ops::shl(*
this, _AP_W - numBits),
3722 INLINE ap_private getHiBits(uint32_t numBits)
const {
3723 return ap_private_ops::lshr(*
this, _AP_W - numBits);
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); \
3756 if (_AP_W != _AP_W1) \
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; \
3764 clearUnusedBits(); \
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
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,
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,
3798 template <
int _AP_W1,
bool _AP_S1>
3799 INLINE ap_private& operator*=(
const ap_private<_AP_W1, _AP_S1>& RHS) {
3801 uint32_t lhsBits = getActiveBits();
3802 uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1;
3808 ap_private dupRHS = RHS;
3810 uint32_t rhsBits = dupRHS.getActiveBits();
3811 uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1;
3819 uint32_t destWords = rhsWords + lhsWords;
3820 uint64_t* dest = (uint64_t*)malloc(destWords *
sizeof(uint64_t));
3823 ap_private_ops::mul(dest, pVal, lhsWords, dupRHS.get_pVal(), rhsWords,
3828 uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords;
3830 memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE);
3832 uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL;
3833 for (
int i = wordsToCopy; i < _AP_N; i++) pVal[i] = ext;
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); \
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 { \
3856 numWords = (RType<_AP_W1, _AP_S1>::logic_w + APINT_BITS_PER_WORD - 1) / \
3857 APINT_BITS_PER_WORD \
3859 typename RType<_AP_W1, _AP_S1>::logic Result; \
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())) \
3871 if (_AP_N > _AP_N1) \
3872 for (; i < max_N; i++) Result.set_pVal(i, pVal[i] Sym ext); \
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())) \
3880 Result.set_pVal(i, ext Sym ext2); \
3883 Result.clearUnusedBits(); \
3891#undef OP_BIN_LOGIC_AP
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();
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();
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;
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))>
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))>
3934 return typename RType<_AP_W2, _AP_S2>::div(
3935 (_AP_S || _AP_S2) ? lhs.sdiv(rhs) : lhs.udiv(rhs));
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))>
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))>
3949 typename RType<_AP_W2, _AP_S2>::mod res =
3950 typename RType<_AP_W2, _AP_S2>::mod(_AP_S ? lhs.srem(rhs)
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); \
3962 OP_LEFT_SHIFT_CTYPE(
int,
true)
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)
3974 OP_LEFT_SHIFT_CTYPE(half,
false)
3975 OP_LEFT_SHIFT_CTYPE(
float, false)
3976 OP_LEFT_SHIFT_CTYPE(
double, false)
3978#undef OP_LEFT_SHIFT_CTYPE
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();
3986 int sh = op2.to_int();
3991#define OP_RIGHT_SHIFT_CTYPE(TYPE, SIGNED) \
3992 INLINE ap_private operator>>(const TYPE op) const { \
3993 if (op >= _AP_W) { \
3995 return ap_private(-1); \
3997 return ap_private(0); \
3999 if ((SIGNED) && op < 0) return *this << (0 - op); \
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)
4019 OP_RIGHT_SHIFT_CTYPE(half,
false)
4020 OP_RIGHT_SHIFT_CTYPE(
float, false)
4021 OP_RIGHT_SHIFT_CTYPE(
double, false)
4023#undef OP_RIGHT_SHIFT_CTYPE
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();
4031 int sh = op2.to_int();
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); \
4045 INLINE ap_private& operator Sym##=(unsigned int op) { \
4046 *this = operator Sym(op); \
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); \
4062 uint32_t n1 = getActiveBits();
4063 uint32_t n2 = RHS.getActiveBits();
4066 if (n1 != n2)
return false;
4070 if (n1 <= APINT_BITS_PER_WORD)
return pVal[0] == RHS.get_pVal(0);
4073 for (
int i = whichWord(n1 - 1); i >= 0; --i)
4074 if (pVal[i] != RHS.get_pVal(i))
return false;
4078 template <
int _AP_W2,
bool _AP_S2>
4079 INLINE
bool operator==(
const ap_private<_AP_W2, _AP_S2>& op)
const {
4081 _AP_MAX_W = AP_MAX(_AP_W, _AP_W2),
4083 ap_private<_AP_MAX_W, false> lhs(*
this);
4084 ap_private<_AP_MAX_W, false> rhs(op);
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;
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);
4101 template <
bool _AP_S1>
4102 INLINE
bool operator!=(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
4103 return !((*this) == RHS);
4106 INLINE
bool operator!=(uint64_t Val)
const {
return !((*this) == Val); }
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);
4113 INLINE
bool operator<(
const ap_private& op)
const {
4114 return _AP_S ? slt(op) : ult(op);
4117 template <
int _AP_W2,
bool _AP_S2>
4118 INLINE
bool operator<(
const ap_private<_AP_W2, _AP_S2>& op)
const {
4120 _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2))
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);
4127 if (_AP_W2 >= _AP_W)
4128 return lhs.ult(rhs);
4130 return lhs.slt(rhs);
4131 else if (_AP_W >= _AP_W2)
4132 return lhs.ult(rhs);
4134 return lhs.slt(rhs);
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);
4142 INLINE
bool operator>(
const ap_private& op)
const {
4143 return _AP_S ? sgt(op) : ugt(op);
4146 template <
int _AP_W2,
bool _AP_S2>
4147 INLINE
bool operator>(
const ap_private<_AP_W2, _AP_S2>& op)
const {
4149 _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2))
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);
4156 if (_AP_W2 >= _AP_W)
4157 return lhs.ugt(rhs);
4159 return lhs.sgt(rhs);
4160 else if (_AP_W >= _AP_W2)
4161 return lhs.ugt(rhs);
4163 return lhs.sgt(rhs);
4174 const_cast<ap_private<_AP_W, _AP_S>*
>(
this), Hi, Lo);
4179 (
const_cast<ap_private<_AP_W, _AP_S>*
>(
this)), Hi, Lo);
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();
4195 template <
int _AP_W2,
bool _AP_S2,
int _AP_W3,
bool _AP_S3>
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();
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();
4214 template <
int _AP_W2,
bool _AP_S2,
int _AP_W3,
bool _AP_S3>
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);
4227 template <
int _AP_W2,
bool _AP_S2>
4229 const ap_private<_AP_W2, _AP_S2>& index) {
4233 template <
int _AP_W2,
bool _AP_S2>
4235 const ap_private<_AP_W2, _AP_S2>& index)
const {
4237 const_cast<ap_private<_AP_W, _AP_S>&
>(*
this), index.to_int());
4242 const_cast<ap_private<_AP_W, _AP_S>&
>(*
this), index);
4249 template <
int _AP_W2,
bool _AP_S2>
4251 const ap_private<_AP_W2, _AP_S2>& index) {
4257 const_cast<ap_private<_AP_W, _AP_S>&
>(*
this), index);
4260 template <
int _AP_W2,
bool _AP_S2>
4262 const ap_private<_AP_W2, _AP_S2>& index)
const {
4264 const_cast<ap_private<_AP_W, _AP_S>&
>(*
this), index.to_int());
4436 INLINE ap_private<_AP_W, false> get()
const {
4437 ap_private<_AP_W, false> ret(*
this);
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));
4452 INLINE
bool isNegative()
const {
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);
4467 return isPositive() && (*this) != 0;
4478 INLINE
bool isMaxValue()
const {
return countPopulation() == _AP_W; }
4484 return !isNegative() && countPopulation() == _AP_W - 1;
4490 INLINE
bool isMinValue()
const {
return countPopulation() == 0; }
4496 return isNegative() && countPopulation() == 1;
4511 INLINE ap_private sqrt()
const {
4513 uint32_t magnitude = getActiveBits();
4517 if (magnitude <= 5) {
4518 static const uint8_t results[32] = {
4523 4, 4, 4, 4, 4, 4, 4, 4,
4524 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4526 return ap_private<_AP_W, _AP_S>( results[get_VAL()]);
4533 if (magnitude < 52) {
4536 return ap_private<_AP_W, _AP_S>(
4537 uint64_t(::sqrt(
double(get_VAL()))) +
4540 return ap_private<_AP_W, _AP_S>(
4542 ::round(::sqrt(
double(get_VAL())))));
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( 1);
4554 ap_private<_AP_W, _AP_S> x_new(0);
4555 ap_private<_AP_W, _AP_S> two( 2);
4558 for (;; i += 2, testy = testy.shl(2))
4559 if (i >= nbits || this->ule(testy)) {
4560 x_old = x_old.shl(i / 2);
4566 x_new = (this->udiv(x_old) + x_old).udiv(two);
4567 if (x_old.ule(x_new))
break;
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))
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))
4590 assert(0 &&
"Error in ap_private<_AP_W, _AP_S>::sqrt computation");
4600 if (
this != &RHS) memcpy(pVal, RHS.get_pVal(), _AP_N * APINT_WORD_SIZE);
4604 INLINE ap_private& operator=(
const volatile ap_private& RHS) {
4606 for (
int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i);
4610 INLINE
void operator=(
const ap_private& RHS)
volatile {
4612 for (
int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i);
4615 INLINE
void operator=(
const volatile ap_private& RHS)
volatile {
4617 for (
int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i);
4621 template <
int _AP_W1,
bool _AP_S1>
4622 INLINE ap_private& operator=(
const ap_private<_AP_W1, _AP_S1>& RHS) {
4631 template <
int _AP_W1,
bool _AP_S1>
4632 INLINE ap_private& operator=(
const volatile ap_private<_AP_W1, _AP_S1>& RHS) {
4641 template <
int _AP_W2,
bool _AP_S2>
4643 *
this = ap_private<_AP_W2, false>(op2);
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));
4655 pVal[0] = RHS.get_VAL();
4656 memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1));
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));
4669 pVal[0] = RHS.get_VAL();
4670 memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1));
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; \
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
4712 INLINE
const ap_private operator++(
int) {
4713 ap_private API(*
this);
4721 ap_private_ops::add_1(pVal, pVal, _AP_N, 1);
4729 ap_private API(*
this);
4737 ap_private_ops::sub_1(pVal, _AP_N, 1);
4746 ap_private<_AP_W + !_AP_S, true> Result(*
this);
4755 return ap_private<1, false>(0) - (*this);
4762 for (
int i = 0; i < _AP_N; ++i)
4763 if (pVal[i])
return false;
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);
4772 template <
bool _AP_S1>
4773 INLINE ap_private Or(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
4774 return this->operator|(RHS);
4776 template <
bool _AP_S1>
4777 INLINE ap_private Xor(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
4778 return this->operator^(RHS);
4781 INLINE ap_private Mul(
const ap_private& RHS)
const {
4782 ap_private Result(*
this);
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();
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();
4805 INLINE ap_private
ashr(uint32_t shiftAmt)
const {
4806 assert(shiftAmt <= BitWidth &&
"Invalid shift amount, too big");
4808 if (shiftAmt == 0)
return ap_private(*
this);
4814 if (shiftAmt == BitWidth) {
4816 return ap_private(-1);
4818 return ap_private(0);
4822 ap_private Retval(0);
4823 uint64_t* val = Retval.get_pVal();
4826 uint32_t wordShift =
4827 shiftAmt % APINT_BITS_PER_WORD;
4828 uint32_t offset = shiftAmt / APINT_BITS_PER_WORD;
4829 uint32_t breakWord = _AP_N - 1 - offset;
4830 uint32_t bitsInWord = whichBit(BitWidth);
4831 if (bitsInWord == 0) bitsInWord = APINT_BITS_PER_WORD;
4834 if (wordShift == 0) {
4836 for (uint32_t i = 0; i <= breakWord; ++i)
4837 val[i] = pVal[i + offset];
4841 if (bitsInWord < APINT_BITS_PER_WORD)
4842 val[breakWord] |= ~0ULL << (bitsInWord);
4845 for (uint32_t i = 0; i < breakWord; ++i) {
4848 val[i] = ((pVal[i + offset]) >> (wordShift));
4849 val[i] |= ((pVal[i + offset + 1]) << (APINT_BITS_PER_WORD - wordShift));
4854 val[breakWord] = (pVal[breakWord + offset]) >> (wordShift);
4860 if (wordShift > bitsInWord) {
4862 val[breakWord - 1] |=
4863 ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord));
4864 val[breakWord] |= ~0ULL;
4866 val[breakWord] |= (~0ULL << (bitsInWord - wordShift));
4871 uint64_t fillValue = (isNegative() ? ~0ULL : 0);
4872 for (
int i = breakWord + 1; i < _AP_N; ++i) val[i] = fillValue;
4873 Retval.clearUnusedBits();
4879 INLINE ap_private
lshr(uint32_t shiftAmt)
const {
4883 if (shiftAmt == BitWidth)
return ap_private(0);
4888 if (shiftAmt == 0)
return ap_private(*
this);
4891 ap_private Retval(0);
4892 uint64_t* val = Retval.get_pVal();
4896 if (shiftAmt < APINT_BITS_PER_WORD) {
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);
4902 Retval.clearUnusedBits();
4907 uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD;
4908 uint32_t offset = shiftAmt / APINT_BITS_PER_WORD;
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();
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));
4924 val[breakWord] = (pVal[breakWord + offset]) >> (wordShift);
4927 for (
int i = breakWord + 1; i < _AP_N; ++i) val[i] = 0;
4928 Retval.clearUnusedBits();
4934 INLINE ap_private
shl(uint32_t shiftAmt)
const {
4935 assert(shiftAmt <= BitWidth &&
"Invalid shift amount, too big");
4939 if (shiftAmt == BitWidth)
return ap_private(0);
4945 if (shiftAmt == 0)
return ap_private(*
this);
4948 ap_private Retval(0);
4949 uint64_t* val = Retval.get_pVal();
4951 if (shiftAmt < APINT_BITS_PER_WORD) {
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);
4957 Retval.clearUnusedBits();
4962 uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD;
4963 uint32_t offset = shiftAmt / APINT_BITS_PER_WORD;
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();
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();
4984 INLINE ap_private rotl(uint32_t rotateAmt)
const {
4985 if (rotateAmt == 0)
return ap_private(*
this);
4987 ap_private hi(*
this);
4988 ap_private lo(*
this);
4990 lo.lshr(BitWidth - rotateAmt);
4994 INLINE ap_private rotr(uint32_t rotateAmt)
const {
4995 if (rotateAmt == 0)
return ap_private(*
this);
4997 ap_private hi(*
this);
4998 ap_private lo(*
this);
5000 hi.shl(BitWidth - rotateAmt);
5009 INLINE ap_private
udiv(
const ap_private& RHS)
const {
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);
5020 return ap_private(0);
5021 else if (lhsWords < rhsWords || this->ult(RHS)) {
5023 return ap_private(0);
5024 }
else if (*
this == RHS) {
5026 return ap_private(1);
5027 }
else if (lhsWords == 1 && rhsWords == 1) {
5029 return ap_private(this->pVal[0] / RHS.get_pVal(0));
5033 ap_private Quotient(0);
5034 ap_private_ops::divide(*
this, lhsWords, RHS, rhsWords, &Quotient,
5041 INLINE ap_private
sdiv(
const ap_private& RHS)
const {
5043 if (RHS.isNegative())
5044 return (-(*
this)).udiv(-RHS);
5046 return -((-(*this)).udiv(RHS));
5047 else if (RHS.isNegative())
5048 return -(this->udiv((ap_private)(-RHS)));
5049 return this->udiv(RHS);
5060 INLINE ap_private
urem(
const ap_private& RHS)
const {
5062 uint32_t lhsBits = getActiveBits();
5063 uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1);
5066 uint32_t rhsBits = RHS.getActiveBits();
5067 uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1);
5068 assert(rhsWords &&
"Performing remainder operation by zero ???");
5071 if (lhsWords == 0) {
5073 return ap_private(0);
5074 }
else if (lhsWords < rhsWords || this->ult(RHS)) {
5077 }
else if (*
this == RHS) {
5079 return ap_private(0);
5080 }
else if (lhsWords == 1) {
5082 return ap_private(pVal[0] % RHS.get_pVal(0));
5086 ap_private Remainder(0);
5087 ap_private_ops::divide(*
this, lhsWords, RHS, rhsWords, (ap_private*)(0),
5092 INLINE ap_private
urem(uint64_t RHS)
const {
5094 uint32_t lhsBits = getActiveBits();
5095 uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1);
5097 uint32_t rhsWords = 1;
5099 assert(rhsWords &&
"Performing remainder operation by zero ???");
5101 if (lhsWords == 0) {
5103 return ap_private(0);
5104 }
else if (lhsWords < rhsWords || this->ult(RHS)) {
5107 }
else if (*
this == RHS) {
5109 return ap_private(0);
5110 }
else if (lhsWords == 1) {
5112 return ap_private(pVal[0] % RHS);
5116 ap_private Remainder(0);
5117 divide(*
this, lhsWords, RHS, (ap_private*)(0), &Remainder);
5123 INLINE ap_private
srem(
const ap_private& RHS)
const {
5125 ap_private lhs = -(*this);
5126 if (RHS.isNegative()) {
5127 ap_private rhs = -RHS;
5128 return -(lhs.urem(rhs));
5130 return -(lhs.urem(RHS));
5131 }
else if (RHS.isNegative()) {
5132 ap_private rhs = -RHS;
5133 return this->urem(rhs);
5135 return this->urem(RHS);
5140 INLINE ap_private
srem(int64_t RHS)
const {
5143 return -((-(*this)).urem(-RHS));
5145 return -((-(*this)).urem(RHS));
5147 return this->urem(-RHS);
5148 return this->urem(RHS);
5155 template <
bool _AP_S1>
5156 INLINE
bool eq(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
5157 return (*
this) == RHS;
5164 template <
bool _AP_S1>
5165 INLINE
bool ne(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
5166 return !((*this) == RHS);
5173 template <
bool _AP_S1>
5174 INLINE
bool ult(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
5176 uint32_t n1 = getActiveBits();
5177 uint32_t n2 = RHS.getActiveBits();
5180 if (n1 < n2)
return true;
5183 if (n2 < n1)
return false;
5186 if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD)
5187 return pVal[0] < RHS.get_pVal(0);
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;
5198 INLINE
bool ult(uint64_t RHS)
const {
5200 uint32_t n1 = getActiveBits();
5202 64 - ap_private_ops::CountLeadingZeros_64(RHS);
5205 if (n1 < n2)
return true;
5208 if (n2 < n1)
return false;
5211 if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD)
5212 return pVal[0] < RHS;
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();
5237 return lhs.ugt(rhs);
5243 return lhs.ult(rhs);
5250 template <
bool _AP_S1>
5251 INLINE
bool ule(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
5252 return ult(RHS) || eq(RHS);
5259 template <
bool _AP_S1>
5260 INLINE
bool sle(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
5261 return slt(RHS) || eq(RHS);
5268 template <
bool _AP_S1>
5269 INLINE
bool ugt(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
5270 return !ult(RHS) && !eq(RHS);
5277 template <
bool _AP_S1>
5278 INLINE
bool sgt(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
5279 return !slt(RHS) && !eq(RHS);
5286 template <
bool _AP_S1>
5287 INLINE
bool uge(
const ap_private<_AP_W, _AP_S>& RHS)
const {
5295 template <
bool _AP_S1>
5296 INLINE
bool sge(
const ap_private<_AP_W, _AP_S1>& RHS)
const {
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");
5306 if (!that.isNegative()) {
5312 enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD };
5313 const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N;
5315 if (_AP_N1 == _AP_N) {
5316 enum { newWordBits = _AP_W % APINT_BITS_PER_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;
5324 enum { newWordBits = _AP_W % APINT_BITS_PER_WORD };
5326 static const uint64_t
mask = wordBits ? (~0ULL << (wordBits)) : 0ULL;
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;
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;
5343 for (; i < _AP_N1; ++i) pVal[i] = that.get_pVal(i);
5344 for (; i < _AP_N; ++i) pVal[i] = 0;
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)
5353 for (
int i = 0; i < _AP_N; ++i) pVal[i] = that.get_pVal(i);
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)
5363 for (
int i = 0; i < _AP_N; ++i) pVal[i] = that.get_pVal(i);
5379 return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
5387 uint32_t bits = BitWidth - countLeadingZeros();
5388 return bits ? bits : 1;
5397 assert(getActiveBits() <= 64 &&
"Too many bits for uint64_t");
5407 assert(getActiveBits() <= 64 &&
"Too many bits for int64_t");
5408 return int64_t(pVal[0]);
5416 assert(str != 0 &&
"Invalid value string");
5417 assert(slen > 0 &&
"Invalid string length");
5420 uint32_t isNegative = str[0] ==
'-';
5427 if (radix == 2)
return slen + isNegative;
5428 if (radix == 8)
return slen * 3 + isNegative;
5429 if (radix == 16)
return slen * 4 + isNegative;
5432 assert(radix == 10 &&
"Invalid radix");
5439 return isNegative + slen * 4;
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
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) {
5460 Count += APINT_BITS_PER_WORD;
5462 Count += ap_private_ops::CountLeadingZeros_64(pVal[i - 1]);
5477 return countLeadingOnes_64(get_VAL(), APINT_BITS_PER_WORD - BitWidth);
5479 uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD;
5481 (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits);
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;
5489 Count += countLeadingOnes_64(get_pVal(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);
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);
5531 INLINE std::string toString(uint8_t radix,
bool wantSigned)
const;
5539 return toString(radix,
false);
5548 return toString(radix,
true);
5554 if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) {
5555 uint64_t val = pVal[0];
5557 int64_t sext = ((int64_t(val)) << (64 - BitWidth)) >> (64 - BitWidth);
5558 return double(sext);
5564 bool isNeg = isSigned ? (*this)[BitWidth - 1] :
false;
5567 ap_private<_AP_W, _AP_S> Tmp(isNeg ? -(*
this) : (*this));
5570 uint32_t n = Tmp.getActiveBits();
5579 if (!isSigned || !isNeg)
5580 return std::numeric_limits<double>::infinity();
5582 return -std::numeric_limits<double>::infinity();
5589 unsigned hiWord = whichWord(n - 1);
5591 mantissa = Tmp.get_pVal(0);
5593 (mantissa) >>= (n - 52);
5595 assert(hiWord > 0 &&
"High word is negative?");
5596 uint64_t hibits = (Tmp.get_pVal(hiWord))
5597 << (52 - n % APINT_BITS_PER_WORD);
5599 (Tmp.get_pVal(hiWord - 1)) >> (11 + n % APINT_BITS_PER_WORD);
5600 mantissa = hibits | lobits;
5604 uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0;
5609 __T.__I = sign | ((exp) << 52) | mantissa;
5641 __T.__I = uint32_t(pVal[0]);
5674 INLINE
bool and_reduce()
const {
return isMaxValue(); }
5676 INLINE
bool nand_reduce()
const {
return isMinValue(); }
5678 INLINE
bool or_reduce()
const {
return (
bool)countPopulation(); }
5680 INLINE
bool nor_reduce()
const {
return countPopulation() == 0; }
5682 INLINE
bool xor_reduce()
const {
5683 unsigned int i = countPopulation();
5684 return (i % 2) ? true :
false;
5687 INLINE
bool xnor_reduce()
const {
5688 unsigned int i = countPopulation();
5689 return (i % 2) ? false :
true;
5691 INLINE std::string to_string(uint8_t radix = 16,
bool sign =
false)
const {
5692 return toString(radix, radix == 10 ? _AP_S : sign);
5696namespace ap_private_ops {
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) {
5704template <
int _AP_W,
bool _AP_S>
5705INLINE
bool operator!=(uint64_t V1,
const ap_private<_AP_W, _AP_S>& V2) {
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);
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) {
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
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);
5731 a.get_pVal(msb_word) |=
mask;
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);
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);
5744 a.get_pVal(msb_word) |= msb_mask;
5746 a.clearUnusedBits();
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) {
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
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));
5765 a.get_pVal(msb_word) &=
mask;
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));
5771 a.get_pVal(lsb_word) &= lsb_mask;
5772 for (
int i = lsb_word + 1; i < msb_word; i++) {
5777 a.get_pVal(msb_word) &= msb_mask;
5779 a.clearUnusedBits();
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);
5788 a.get_pVal(word) |=
mask;
5789 a.clearUnusedBits();
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));
5798 a.get_pVal(word) &=
mask;
5799 a.clearUnusedBits();
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"};
5819 if (*
this == (uint64_t)(0))
5822 ap_private<_AP_W, false> tmp(*
this);
5823 size_t insert_at = 0;
5824 bool leading_zero =
true;
5825 if (wantSigned && isNegative()) {
5831 tmp.clearUnusedBitsToZero();
5834 leading_zero =
false;
5847 assert(
"invalid radix" && 0);
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);
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);
5862 if (bits < _AP_W && leading_zero) result.insert(insert_at, digits[0]);
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()) {
5877 tmp.clearUnusedBitsToZero();
5881 if (tmp == ap_private<_AP_W, false>(0))
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]);
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);
5903 }
else if (ff & std::cout.oct) {
5904 os << x.toString(8,
false);
5906 os << x.toString(10, _AP_S);
6155template <
int _AP_W,
bool _AP_S>
6158#pragma warning(disable : 4521 4522)
6160 ap_private<_AP_W, _AP_S>& d_bv;
6167 : d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {}
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 "
6176 _AP_WARNING(h >= _AP_W || l >= _AP_W,
6177 "Higher bound (%d) or lower bound (%d) out of range (%d).", h,
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;
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;
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;
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;
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;
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;
6246 INLINE
operator ap_private<_AP_W, false>()
const {
6247 ap_private<_AP_W, false> val(0);
6248 if (h_index >= l_index) {
6251 ap_private<_AP_W, false>
mask(-1);
6252 mask >>= _AP_W - (h_index - l_index + 1);
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)));
6260 for (
int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++)
6261 if ((d_bv)[j]) val.set(i);
6266 INLINE
operator unsigned long long()
const {
return to_uint64(); }
6269 template <
int _AP_W2,
bool _AP_S2>
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);
6277 ap_private<_AP_W, false>
mask(-1);
6282 if (h_index < _AP_W - 1) {
6283 ap_private<_AP_W, false> mask2(-1);
6284 mask2 >>= _AP_W - h_index - 1;
6292 unsigned shift = 64 - _AP_W;
6293 uint64_t
mask = ~0ULL >> (shift);
6295 vval =
mask & vval << l_index;
6298 if (h_index < _AP_W - 1) {
6299 uint64_t mask2 =
mask;
6300 mask2 >>= (_AP_W - h_index - 1);
6313 const ap_private<_AP_W, _AP_S> vval = val;
6314 return operator=(vval);
6317 template <
int _AP_W2,
bool _AP_S2>
6320 return operator=((
unsigned long long)(
bool)val);
6323 template <
int _AP_W2,
bool _AP_S2>
6326 const ap_private<_AP_W, false> tmpVal(val);
6327 return operator=(tmpVal);
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>
6344 return operator=(val.to_ap_int_base().V);
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>
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>
6358 return operator=((
unsigned long long)(
bool)val);
6439 template <
int _AP_W2,
bool _AP_S2>
6441 ap_private<_AP_W, false> lhs = get();
6442 ap_private<_AP_W2, false> rhs = op2.get();
6446 template <
int _AP_W2,
bool _AP_S2>
6448 ap_private<_AP_W, false> lhs = get();
6449 ap_private<_AP_W2, false> rhs = op2.get();
6453 template <
int _AP_W2,
bool _AP_S2>
6455 ap_private<_AP_W, false> lhs = get();
6456 ap_private<_AP_W2, false> rhs = op2.get();
6460 template <
int _AP_W2,
bool _AP_S2>
6462 ap_private<_AP_W, false> lhs = get();
6463 ap_private<_AP_W2, false> rhs = op2.get();
6467 template <
int _AP_W2,
bool _AP_S2>
6469 ap_private<_AP_W, false> lhs = get();
6470 ap_private<_AP_W2, false> rhs = op2.get();
6474 template <
int _AP_W2,
bool _AP_S2>
6476 ap_private<_AP_W, false> lhs = get();
6477 ap_private<_AP_W2, false> rhs = op2.get();
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);
6489 ap_private<_AP_W, _AP_S>
mask(-1);
6491 ap_private<_AP_W, false> mask1(-1);
6492 mask1 >>= _AP_W - l_index;
6498 if (h_index < _AP_W - 1) {
6499 ap_private<_AP_W, false> mask2(-1);
6500 mask2 <<= h_index + 1;
6509 uint64_t
mask = ~0ULL >> (64 - _AP_W);
6511 uint64_t mask1 =
mask;
6512 mask1 =
mask & (mask1 >> (_AP_W - l_index));
6513 vval =
mask & (vval << l_index);
6517 if (h_index < _AP_W - 1) {
6518 uint64_t mask2 = ~0ULL >> (64 - _AP_W);
6519 mask2 =
mask & (mask2 << (h_index + 1));
6523 d_bv &= (
~mask & (~0ULL >> (64 - _AP_W)));
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);
6537 if (h_index < _AP_W - 1) {
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)));
6543 ap_private<_AP_W, false>
mask(-1);
6544 mask >>= _AP_W - (h_index - l_index + 1);
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);
6560 if (h_index < _AP_W - 1) {
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)));
6565 ap_private<_AP_W, false>
mask(-1);
6566 mask >>= _AP_W - (h_index - l_index + 1);
6574 INLINE
int length()
const {
6575 return h_index >= l_index ? h_index - l_index + 1 : l_index - h_index + 1;
6578 INLINE
int to_int()
const {
6579 ap_private<_AP_W, false> val = get();
6580 return val.to_int();
6583 INLINE
unsigned int to_uint()
const {
6584 ap_private<_AP_W, false> val = get();
6585 return val.to_uint();
6588 INLINE
long to_long()
const {
6589 ap_private<_AP_W, false> val = get();
6590 return val.to_long();
6593 INLINE
unsigned long to_ulong()
const {
6594 ap_private<_AP_W, false> val = get();
6595 return val.to_ulong();
6598 INLINE ap_slong to_int64()
const {
6599 ap_private<_AP_W, false> val = get();
6600 return val.to_int64();
6603 INLINE ap_ulong to_uint64()
const {
6604 ap_private<_AP_W, false> val = get();
6605 return val.to_uint64();
6608 INLINE std::string to_string(uint8_t radix = 2)
const {
6609 return get().to_string(radix);
6612 INLINE
bool and_reduce() {
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];
6621 INLINE
bool or_reduce() {
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];
6630 INLINE
bool xor_reduce() {
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];
6644template <
int _AP_W,
bool _AP_S>
6647#pragma warning(disable : 4521 4522)
6649 ap_private<_AP_W, _AP_S>& d_bv;
6655 : d_bv(ref.d_bv), d_index(ref.d_index) {}
6659 : d_bv(bv), d_index(index) {
6660 _AP_WARNING(d_index < 0,
"Index of bit vector (%d) cannot be negative.\n",
6662 _AP_WARNING(d_index >= _AP_W,
6663 "Index of bit vector (%d) out of range (%d).\n", d_index,
6667 INLINE
operator bool()
const {
return d_bv.get_bit(d_index); }
6669 INLINE
bool to_bool()
const {
return operator bool(); }
6671 template <
typename T>
6676 d_bv.clear(d_index);
6765 template <
int _AP_W2,
bool _AP_S2>
6767 return get() == op.get();
6770 template <
int _AP_W2,
bool _AP_S2>
6772 return get() != op.get();
6775 INLINE
bool get()
const {
return operator bool(); }
6787 INLINE
int length()
const {
return 1; }
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; \
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, \
6811 typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \
6812 return op2 BIN_OP i_op; \
6817#undef OP_BIN_MIX_PTR
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; \
6828 template <int _AP_W, bool _AP_S> \
6829 INLINE C_TYPE operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, \
6831 typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \
6832 return op2 BIN_OP i_op; \
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)
6842OPS_MIX_FLOAT(
double)
6843#undef OP_BIN_MIX_FLOAT
6854#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \
6855 template <int _AP_W, bool _AP_S> \
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); \
6861 template <int _AP_W, bool _AP_S> \
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)); \
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, \
6872 return op.operator REL_OP(ap_private<_AP_W2, _AP_S2>(op2)); \
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); \
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)); \
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()); \
6893 template <int _AP_W, bool _AP_S> \
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); \
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); \
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); \
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) \
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)) \
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))
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)
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
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, \
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); \
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, \
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)); \
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)); \
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); \
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); \
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>()); \
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
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
7042#undef OP_REL_MIX_RANGE
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); \
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)); \
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)); \
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); \
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); \
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)); \
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
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
7117#undef OP_REL_MIX_BIT
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, \
7123 return (ap_private<_AP_W, false>(op)) \
7125 operator REL_OP(ap_private<_AP_W2, _AP_S2>(op2)); \
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)); \
7133 template <int _AP_W, bool _AP_S> \
7134 INLINE bool operator REL_OP(const _private_bit_ref<_AP_W, _AP_S>& op, \
7136 return (bool(op))REL_OP op2; \
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)); \
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))
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
7167#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \
7168 template <int _AP_W, bool _AP_S> \
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, \
7173 return (ap_private<_AP_W, false>(op)) \
7175 operator BIN_OP(ap_private<_AP_W2, _AP_S2>(op2)); \
7177 template <int _AP_W, bool _AP_S> \
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)); \
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))
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
7213#define REF_BIN_OP(BIN_OP, RTYPE) \
7214 template <int _AP_W, bool _AP_S, int _AP_W2, bool _AP_S2> \
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)); \
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...
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.