LDMX Software
ap_int_base.h
1/*
2 * Copyright 2011-2019 Xilinx, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef __AP_INT_BASE_H__
18#define __AP_INT_BASE_H__
19
20#ifndef __AP_INT_H__
21#error "Only ap_fixed.h and ap_int.h can be included directly in user code."
22#endif
23
24#ifndef __cplusplus
25#error "C++ is required to include this header file"
26#else
27
28#include "ap_common.h"
29#ifndef __SYNTHESIS__
30#if _AP_ENABLE_HALF_ == 1
31#include <hls_half.h>
32#endif
33#include <string.h>
34
35#include <iostream>
36#endif
37
38/* ----------------------------------------------------------------
39 * ap_int_base: AutoPilot integer/Arbitrary precision integer.
40 * ----------------------------------------------------------------
41 */
42
43/* helper trait. Selecting the smallest C type that can hold the value,
44 * return 64 bit C type if not possible.
45 */
46template <int _AP_N, bool _AP_S>
47struct retval;
48
49// at least 64 bit
50template <int _AP_N>
51struct retval<_AP_N, true> {
52 typedef ap_slong Type;
53};
54
55template <int _AP_N>
56struct retval<_AP_N, false> {
57 typedef ap_ulong Type;
58};
59
60// at least 8 bit
61template <>
62struct retval<1, true> {
63 typedef signed char Type;
64};
65
66template <>
67struct retval<1, false> {
68 typedef unsigned char Type;
69};
70
71// at least 16 bit
72template <>
73struct retval<2, true> {
74 typedef short Type;
75};
76
77template <>
78struct retval<2, false> {
79 typedef unsigned short Type;
80};
81
82// at least 32 bit
83template <>
84struct retval<3, true> {
85 typedef long Type;
86};
87
88template <>
89struct retval<3, false> {
90 typedef unsigned long Type;
91};
92
93template <>
94struct retval<4, true> {
95 typedef long Type;
96};
97
98template <>
99struct retval<4, false> {
100 typedef unsigned long Type;
101};
102
103// trait for letting base class to return derived class.
104// Notice that derived class template is incomplete, and we cannot use
105// the member of the derived class.
106template <int _AP_W2, bool _AP_S2>
107struct _ap_int_factory;
108template <int _AP_W2>
109struct _ap_int_factory<_AP_W2, true> {
110 typedef ap_int<_AP_W2> type;
111};
112template <int _AP_W2>
113struct _ap_int_factory<_AP_W2, false> {
114 typedef ap_uint<_AP_W2> type;
115};
116
117template <int _AP_W, bool _AP_S>
118struct ap_int_base : public _AP_ROOT_TYPE<_AP_W, _AP_S> {
119 public:
120 typedef _AP_ROOT_TYPE<_AP_W, _AP_S> Base;
121
122 /* ap_int_base<_AP_W, _AP_S, true>
123 * typedef typename retval<(_AP_W + 7) / 8, _AP_S>::Type RetType;
124 *
125 * ap_int_base<_AP_W, _AP_S, false>
126 * typedef typename retval<8, _AP_S>::Type RetType;
127 */
128 typedef typename retval<AP_MAX((_AP_W + 7) / 8, 8), _AP_S>::Type RetType;
129
130 static const int width = _AP_W;
131
132 template <int _AP_W2, bool _AP_S2>
133 struct RType {
134 enum {
135 mult_w = _AP_W + _AP_W2,
136 mult_s = _AP_S || _AP_S2,
137 plus_w =
138 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
139 plus_s = _AP_S || _AP_S2,
140 minus_w =
141 AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1,
142 minus_s = true,
143 div_w = _AP_W + _AP_S2,
144 div_s = _AP_S || _AP_S2,
145 mod_w = AP_MIN(_AP_W, _AP_W2 + (!_AP_S2 && _AP_S)),
146 mod_s = _AP_S,
147 logic_w = AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)),
148 logic_s = _AP_S || _AP_S2
149 };
150
151 typedef ap_int_base<mult_w, mult_s> mult_base;
152 typedef ap_int_base<plus_w, plus_s> plus_base;
153 typedef ap_int_base<minus_w, minus_s> minus_base;
154 typedef ap_int_base<logic_w, logic_s> logic_base;
155 typedef ap_int_base<div_w, div_s> div_base;
156 typedef ap_int_base<mod_w, mod_s> mod_base;
157 typedef ap_int_base<_AP_W, _AP_S> arg1_base;
158
159 typedef typename _ap_int_factory<mult_w, mult_s>::type mult;
160 typedef typename _ap_int_factory<plus_w, plus_s>::type plus;
161 typedef typename _ap_int_factory<minus_w, minus_s>::type minus;
162 typedef typename _ap_int_factory<logic_w, logic_s>::type logic;
163 typedef typename _ap_int_factory<div_w, div_s>::type div;
164 typedef typename _ap_int_factory<mod_w, mod_s>::type mod;
165 typedef typename _ap_int_factory<_AP_W, _AP_S>::type arg1;
166 typedef bool reduce;
167 };
168
169 /* Constructors.
170 * ----------------------------------------------------------------
171 */
173 INLINE ap_int_base() {
174 /*
175 #ifdef __SC_COMPATIBLE__
176 Base::V = 0;
177 #endif
178 */
179 }
180
182 template <int _AP_W2, bool _AP_S2>
183 INLINE ap_int_base(const ap_int_base<_AP_W2, _AP_S2>& op) {
184 Base::V = op.V;
185 }
186
188 template <int _AP_W2, bool _AP_S2>
189 INLINE ap_int_base(const volatile ap_int_base<_AP_W2, _AP_S2>& op) {
190 Base::V = op.V;
191 }
192
193// XXX C++11 feature.
194// The explicit specifier specifies that a constructor or conversion function
195// (since C++11) doesn't allow implicit conversions or copy-initialization.
196// ap_int_base<W,S> x = 1;
197// ap_int_base<W,S> foo() { return 1; }
198// but allows
199// ap_int_base<W,S> x(1);
200// ap_int_base<W,S> y {1};
201
203#define CTOR_FROM_INT(Type, Size, Signed) \
204 INLINE ap_int_base(const Type op) { Base::V = op; }
205
206 CTOR_FROM_INT(bool, 1, false)
207 CTOR_FROM_INT(char, 8, CHAR_IS_SIGNED)
208 CTOR_FROM_INT(signed char, 8, true)
209 CTOR_FROM_INT(unsigned char, 8, false)
210 CTOR_FROM_INT(short, _AP_SIZE_short, true)
211 CTOR_FROM_INT(unsigned short, _AP_SIZE_short, false)
212 CTOR_FROM_INT(int, _AP_SIZE_int, true)
213 CTOR_FROM_INT(unsigned int, _AP_SIZE_int, false)
214 CTOR_FROM_INT(long, _AP_SIZE_long, true)
215 CTOR_FROM_INT(unsigned long, _AP_SIZE_long, false)
216 CTOR_FROM_INT(ap_slong, _AP_SIZE_ap_slong, true)
217 CTOR_FROM_INT(ap_ulong, _AP_SIZE_ap_slong, false)
218#undef CTOR_FROM_INT
219
220#if _AP_ENABLE_HALF_ == 1
222 // TODO optimize
223 INLINE ap_int_base(half op) {
224 ap_int_base<_AP_W, _AP_S> t((float)op);
225 Base::V = t.V;
226 }
227#endif
228
230 INLINE ap_int_base(float op) {
231 const int BITS = FLOAT_MAN + FLOAT_EXP + 1;
233 reg.V = floatToRawBits(op);
234 bool is_neg = _AP_ROOT_op_get_bit(reg.V, BITS - 1);
235
237 exp.V = _AP_ROOT_op_get_range(reg.V, FLOAT_MAN, BITS - 2);
238 exp = exp - FLOAT_BIAS;
239
241 man.V = _AP_ROOT_op_get_range(reg.V, 0, FLOAT_MAN - 1);
242 // check for NaN
243 _AP_WARNING(exp == ((unsigned char)(FLOAT_BIAS + 1)) && man.V != 0,
244 "assign NaN to ap integer value");
245 // set leading 1.
246 man.V = _AP_ROOT_op_set_bit(man.V, FLOAT_MAN, 1);
247 // if (is_neg) man = -man;
248
249 if ((reg.V & 0x7ffffffful) == 0) {
250 Base::V = 0;
251 } else {
252 int sh_amt = FLOAT_MAN - exp.V;
253 if (sh_amt == 0) {
254 Base::V = man.V;
255 } else if (sh_amt > 0) {
256 if (sh_amt < FLOAT_MAN + 2) {
257 Base::V = man.V >> sh_amt;
258 } else {
259 if (is_neg)
260 Base::V = -1;
261 else
262 Base::V = 0;
263 }
264 } else {
265 sh_amt = -sh_amt;
266 if (sh_amt < _AP_W) {
267 Base::V = man.V;
268 Base::V <<= sh_amt;
269 } else {
270 Base::V = 0;
271 }
272 }
273 }
274 if (is_neg) *this = -(*this);
275 }
276
278 INLINE ap_int_base(double op) {
279 const int BITS = DOUBLE_MAN + DOUBLE_EXP + 1;
281 reg.V = doubleToRawBits(op);
282 bool is_neg = _AP_ROOT_op_get_bit(reg.V, BITS - 1);
283
285 exp.V = _AP_ROOT_op_get_range(reg.V, DOUBLE_MAN, BITS - 2);
286 exp = exp - DOUBLE_BIAS;
287
289 man.V = _AP_ROOT_op_get_range(reg.V, 0, DOUBLE_MAN - 1);
290 // check for NaN
291 _AP_WARNING(exp == ((unsigned char)(DOUBLE_BIAS + 1)) && man.V != 0,
292 "assign NaN to ap integer value");
293 // set leading 1.
294 man.V = _AP_ROOT_op_set_bit(man.V, DOUBLE_MAN, 1);
295 // if (is_neg) man = -man;
296
297 if ((reg.V & 0x7fffffffffffffffull) == 0) {
298 Base::V = 0;
299 } else {
300 int sh_amt = DOUBLE_MAN - exp.V;
301 if (sh_amt == 0) {
302 Base::V = man.V;
303 } else if (sh_amt > 0) {
304 if (sh_amt < DOUBLE_MAN + 2) {
305 Base::V = man.V >> sh_amt;
306 } else {
307 if (is_neg)
308 Base::V = -1;
309 else
310 Base::V = 0;
311 }
312 } else {
313 sh_amt = -sh_amt;
314 if (sh_amt < _AP_W) {
315 Base::V = man.V;
316 Base::V <<= sh_amt;
317 } else {
318 Base::V = 0;
319 }
320 }
321 }
322 if (is_neg) *this = -(*this);
323 }
324
326 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
327 ap_o_mode _AP_O2, int _AP_N2>
328 INLINE ap_int_base(
330 Base::V = op.to_ap_int_base().V;
331 }
332
333 template <int _AP_W2, bool _AP_S2>
334 INLINE ap_int_base(const ap_range_ref<_AP_W2, _AP_S2>& ref) {
335 Base::V = (ref.get()).V;
336 }
337
338 template <int _AP_W2, bool _AP_S2>
339 INLINE ap_int_base(const ap_bit_ref<_AP_W2, _AP_S2>& ref) {
340 Base::V = ref.operator bool();
341 }
342
343 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
346 false>
347 tmp = ref.get();
348 Base::V = tmp.V;
349 }
350
351 /* radix has default value in set */
352
353#ifndef __SYNTHESIS__
354 INLINE ap_int_base(const char* s, signed char rd = 0) {
355 if (rd == 0) rd = guess_radix(s);
356 unsigned int length = strlen(s);
357 Base::V.fromString(s, length, rd);
358 }
359#else
360 // XXX __builtin_bit_from_string(...) requires const C string and radix.
361 INLINE ap_int_base(const char* s) {
362 typeof(Base::V) t;
363 _ssdm_string2bits((void*)(&t), (const char*)(s), 10, _AP_W, _AP_S, AP_TRN,
364 AP_WRAP, 0, _AP_C99);
365 Base::V = t;
366 }
367 INLINE ap_int_base(const char* s, signed char rd) {
368 typeof(Base::V) t;
369 _ssdm_string2bits((void*)(&t), (const char*)(s), rd, _AP_W, _AP_S, AP_TRN,
370 AP_WRAP, 0, _AP_C99);
371 Base::V = t;
372 }
373#endif
374
375 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
376 ap_o_mode _AP_O2, int _AP_N2>
377 INLINE ap_int_base(
379 Base::V = (val.get()).V;
380 }
381
382 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
383 ap_o_mode _AP_O2, int _AP_N2>
384 INLINE ap_int_base(
386 Base::V = val.operator bool();
387 }
388
389 INLINE ap_int_base read() volatile {
390 /*AP_DEBUG(printf("call read %d\n", Base::V););*/
391 ap_int_base ret;
392 ret.V = Base::V;
393 return ret;
394 }
395
396 INLINE void write(const ap_int_base<_AP_W, _AP_S>& op2) volatile {
397 /*AP_DEBUG(printf("call write %d\n", op2.V););*/
398 Base::V = op2.V;
399 }
400
401 /* Another form of "write".*/
402 template <int _AP_W2, bool _AP_S2>
403 INLINE void operator=(
404 const volatile ap_int_base<_AP_W2, _AP_S2>& op2) volatile {
405 Base::V = op2.V;
406 }
407
408 INLINE void operator=(
409 const volatile ap_int_base<_AP_W, _AP_S>& op2) volatile {
410 Base::V = op2.V;
411 }
412
413 template <int _AP_W2, bool _AP_S2>
414 INLINE void operator=(const ap_int_base<_AP_W2, _AP_S2>& op2) volatile {
415 Base::V = op2.V;
416 }
417
418 INLINE void operator=(const ap_int_base<_AP_W, _AP_S>& op2) volatile {
419 Base::V = op2.V;
420 }
421
422 template <int _AP_W2, bool _AP_S2>
423 INLINE ap_int_base& operator=(
424 const volatile ap_int_base<_AP_W2, _AP_S2>& op2) {
425 Base::V = op2.V;
426 return *this;
427 }
428
429 template <int _AP_W2, bool _AP_S2>
430 INLINE ap_int_base& operator=(const ap_int_base<_AP_W2, _AP_S2>& op2) {
431 Base::V = op2.V;
432 return *this;
433 }
434
435 INLINE ap_int_base& operator=(const volatile ap_int_base<_AP_W, _AP_S>& op2) {
436 Base::V = op2.V;
437 return *this;
438 }
439
440 INLINE ap_int_base& operator=(const ap_int_base<_AP_W, _AP_S>& op2) {
441 Base::V = op2.V;
442 return *this;
443 }
444
445#define ASSIGN_OP_FROM_INT(Type, Size, Signed) \
446 INLINE ap_int_base& operator=(Type op) { \
447 Base::V = op; \
448 return *this; \
449 }
450
451 ASSIGN_OP_FROM_INT(bool, 1, false)
452 ASSIGN_OP_FROM_INT(char, 8, CHAR_IS_SIGNED)
453 ASSIGN_OP_FROM_INT(signed char, 8, true)
454 ASSIGN_OP_FROM_INT(unsigned char, 8, false)
455 ASSIGN_OP_FROM_INT(short, _AP_SIZE_short, true)
456 ASSIGN_OP_FROM_INT(unsigned short, _AP_SIZE_short, false)
457 ASSIGN_OP_FROM_INT(int, _AP_SIZE_int, true)
458 ASSIGN_OP_FROM_INT(unsigned int, _AP_SIZE_int, false)
459 ASSIGN_OP_FROM_INT(long, _AP_SIZE_long, true)
460 ASSIGN_OP_FROM_INT(unsigned long, _AP_SIZE_long, false)
461 ASSIGN_OP_FROM_INT(ap_slong, _AP_SIZE_ap_slong, true)
462 ASSIGN_OP_FROM_INT(ap_ulong, _AP_SIZE_ap_slong, false)
463
464#undef ASSIGN_OP_FROM_INT
465
466 template <int _AP_W2, bool _AP_S2>
467 INLINE ap_int_base& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& op2) {
468 Base::V = (bool)op2;
469 return *this;
470 }
471
472 template <int _AP_W2, bool _AP_S2>
473 INLINE ap_int_base& operator=(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
474 Base::V = (ap_int_base<_AP_W2, false>(op2)).V;
475 return *this;
476 }
477
478 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
479 INLINE ap_int_base& operator=(
481 Base::V = op2.get().V;
482 return *this;
483 }
484
485 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
486 ap_o_mode _AP_O2, int _AP_N2>
487 INLINE ap_int_base& operator=(
489 Base::V = op.to_ap_int_base().V;
490 return *this;
491 }
492
493 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
494 ap_o_mode _AP_O2, int _AP_N2>
495 INLINE ap_int_base& operator=(
497 Base::V = (bool)op;
498 return *this;
499 }
500
501 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
502 ap_o_mode _AP_O2, int _AP_N2>
503 INLINE ap_int_base& operator=(
505 Base::V = ((const ap_int_base<_AP_W2, false>)(op)).V;
506 return *this;
507 }
508
509 // FIXME: UG902 has clearly required user to use to_int() to convert to
510 // built-in types, but this implicit conversion is relied on in hls_cordic.h
511 // and hls_rsr.h. For example:
512 // int d_exp = fps_x.exp - fps_y.exp;
513 INLINE operator RetType() const { return (RetType)(Base::V); }
514
515 /* Explicit conversions to C types.
516 * ----------------------------------------------------------------
517 */
518 INLINE bool to_bool() const { return (bool)(Base::V); }
519 INLINE char to_char() const { return (char)(Base::V); }
520 INLINE signed char to_schar() const { return (signed char)(Base::V); }
521 INLINE unsigned char to_uchar() const { return (unsigned char)(Base::V); }
522 INLINE short to_short() const { return (short)(Base::V); }
523 INLINE unsigned short to_ushort() const { return (unsigned short)(Base::V); }
524 INLINE int to_int() const { return (int)(Base::V); }
525 INLINE unsigned to_uint() const { return (unsigned)(Base::V); }
526 INLINE long to_long() const { return (long)(Base::V); }
527 INLINE unsigned long to_ulong() const { return (unsigned long)(Base::V); }
528 INLINE ap_slong to_int64() const { return (ap_slong)(Base::V); }
529 INLINE ap_ulong to_uint64() const { return (ap_ulong)(Base::V); }
530 INLINE float to_float() const { return (float)(Base::V); }
531 INLINE double to_double() const { return (double)(Base::V); }
532
533 // TODO decide if user-defined conversion should be provided.
534#if 0
535 INLINE operator char() const { return (char)(Base::V); }
536 INLINE operator signed char() const { return (signed char)(Base::V); }
537 INLINE operator unsigned char() const { return (unsigned char)(Base::V); }
538 INLINE operator short() const { return (short)(Base::V); }
539 INLINE operator unsigned short() const { return (unsigned short)(Base::V); }
540 INLINE operator int() const { return (int)(Base::V); }
541 INLINE operator unsigned int () const { return (unsigned)(Base::V); }
542 INLINE operator long () const { return (long)(Base::V); }
543 INLINE operator unsigned long () const { return (unsigned long)(Base::V); }
544 INLINE operator ap_slong () { return (ap_slong)(Base::V); }
545 INLINE operator ap_ulong () { return (ap_ulong)(Base::V); }
546#endif
547
548 /* Helper methods.
549 ----------------------------------------------------------------
550 */
551 /* we cannot call a non-volatile function on a volatile instance.
552 * but calling a volatile function is ok.
553 * XXX deleted non-volatile version.
554 */
555 INLINE int length() const volatile { return _AP_W; }
556
557 /*Return true if the value of ap_int_base instance is zero*/
558 INLINE bool iszero() const { return Base::V == 0; }
559
560 /*Return true if the value of ap_int_base instance is zero*/
561 INLINE bool is_zero() const { return Base::V == 0; }
562
563 /* x < 0 */
564 INLINE bool sign() const {
565 if (_AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1))
566 return true;
567 else
568 return false;
569 }
570
571 /* x[i] = 0 */
572 INLINE void clear(int i) {
573 AP_ASSERT(i >= 0 && i < _AP_W, "position out of range");
574 Base::V = _AP_ROOT_op_set_bit(Base::V, i, 0);
575 }
576
577 /* x[i] = !x[i]*/
578 INLINE void invert(int i) {
579 AP_ASSERT(i >= 0 && i < _AP_W, "position out of range");
580 bool val = _AP_ROOT_op_get_bit(Base::V, i);
581 if (val)
582 Base::V = _AP_ROOT_op_set_bit(Base::V, i, 0);
583 else
584 Base::V = _AP_ROOT_op_set_bit(Base::V, i, 1);
585 }
586
587 INLINE bool test(int i) const {
588 AP_ASSERT(i >= 0 && i < _AP_W, "position out of range");
589 return _AP_ROOT_op_get_bit(Base::V, i);
590 }
591
592 // Get self. For ap_concat_ref expansion.
593 INLINE ap_int_base& get() { return *this; }
594
595 // Set the ith bit into 1
596 INLINE void set(int i) {
597 AP_ASSERT(i >= 0 && i < _AP_W, "position out of range");
598 Base::V = _AP_ROOT_op_set_bit(Base::V, i, 1);
599 }
600
601 // Set the ith bit into v
602 INLINE void set(int i, bool v) {
603 AP_ASSERT(i >= 0 && i < _AP_W, "position out of range");
604 Base::V = _AP_ROOT_op_set_bit(Base::V, i, v);
605 }
606
607 // This is used for sc_lv and sc_bv, which is implemented by sc_uint
608 // Rotate an ap_int_base object n places to the left
609 INLINE ap_int_base& lrotate(int n) {
610 AP_ASSERT(n >= 0 && n < _AP_W, "shift value out of range");
611 // TODO unify this.
612#ifdef __SYNTHESIS__
613 typeof(Base::V) l_p = Base::V << n;
614 typeof(Base::V) r_p = Base::V >> (_AP_W - n);
615 Base::V = l_p | r_p;
616#else
617 Base::V.lrotate(n);
618#endif
619 return *this;
620 }
621
622 // This is used for sc_lv and sc_bv, which is implemented by sc_uint
623 // Rotate an ap_int_base object n places to the right
624 INLINE ap_int_base& rrotate(int n) {
625 AP_ASSERT(n >= 0 && n < _AP_W, "shift value out of range");
626 // TODO unify this.
627#ifdef __SYNTHESIS__
628 typeof(Base::V) l_p = Base::V << (_AP_W - n);
629 typeof(Base::V) r_p = Base::V >> n;
630 Base::V = l_p | r_p;
631#else
632 Base::V.rrotate(n);
633#endif
634 return *this;
635 }
636
637 // Reverse the contents of ap_int_base instance.
638 // I.e. LSB becomes MSB and vise versa.
639 INLINE ap_int_base& reverse() {
640 Base::V = _AP_ROOT_op_get_range(Base::V, _AP_W - 1, 0);
641 return *this;
642 }
643
644 // Set the ith bit into v
645 INLINE void set_bit(int i, bool v) {
646 Base::V = _AP_ROOT_op_set_bit(Base::V, i, v);
647 }
648
649 // Get the value of ith bit
650 INLINE bool get_bit(int i) const {
651 return (bool)_AP_ROOT_op_get_bit(Base::V, i);
652 }
653
654 // complements every bit
655 INLINE void b_not() { Base::V = ~Base::V; }
656
657#define OP_ASSIGN_AP(Sym) \
658 template <int _AP_W2, bool _AP_S2> \
659 INLINE ap_int_base& operator Sym(const ap_int_base<_AP_W2, _AP_S2>& op2) { \
660 Base::V Sym op2.V; \
661 return *this; \
662 }
663
664 /* Arithmetic assign.
665 * ----------------------------------------------------------------
666 */
667 OP_ASSIGN_AP(*=)
668 OP_ASSIGN_AP(+=)
669 OP_ASSIGN_AP(-=)
670 OP_ASSIGN_AP(/=)
671 OP_ASSIGN_AP(%=)
672#undef OP_ASSIGN_AP
673
674 /* Bitwise assign: and, or, xor.
675 * ----------------------------------------------------------------
676 */
677#define OP_ASSIGN_AP_CHK(Sym) \
678 template <int _AP_W2, bool _AP_S2> \
679 INLINE ap_int_base& operator Sym(const ap_int_base<_AP_W2, _AP_S2>& op2) { \
680 _AP_WARNING((_AP_W != _AP_W2), \
681 "Bitsize mismatch for ap_[u]int" #Sym "ap_[u]int."); \
682 Base::V Sym op2.V; \
683 return *this; \
684 }
685 OP_ASSIGN_AP_CHK(&=)
686 OP_ASSIGN_AP_CHK(|=)
687 OP_ASSIGN_AP_CHK(^=)
688#undef OP_ASSIGN_AP_CHK
689
690 /* Prefix increment, decrement.
691 * ----------------------------------------------------------------
692 */
693 INLINE ap_int_base& operator++() {
694 operator+=((ap_int_base<1, false>)1);
695 return *this;
696 }
697 INLINE ap_int_base& operator--() {
698 operator-=((ap_int_base<1, false>)1);
699 return *this;
700 }
701
702 /* Postfix increment, decrement
703 * ----------------------------------------------------------------
704 */
705 INLINE const typename RType<_AP_W, _AP_S>::arg1 operator++(int) {
706 ap_int_base t = *this;
707 operator+=((ap_int_base<1, false>)1);
708 return t;
709 }
710 INLINE const typename RType<_AP_W, _AP_S>::arg1 operator--(int) {
711 ap_int_base t = *this;
712 operator-=((ap_int_base<1, false>)1);
713 return t;
714 }
715
716 /* Unary arithmetic.
717 * ----------------------------------------------------------------
718 */
719 INLINE typename RType<_AP_W, _AP_S>::arg1 operator+() const { return *this; }
720
721 // TODO used to be W>64 only... need check.
722 INLINE typename RType<1, false>::minus operator-() const {
723 return ap_int_base<1, false>(0) - *this;
724 }
725
726 /* Not (!)
727 * ----------------------------------------------------------------
728 */
729 INLINE bool operator!() const { return Base::V == 0; }
730
731 /* Bitwise (arithmetic) unary: complement
732 ----------------------------------------------------------------
733 */
734 // XXX different from Mentor's ac_int!
735 INLINE typename RType<_AP_W, _AP_S>::arg1 operator~() const {
737 r.V = ~Base::V;
738 return r;
739 }
740
741 /* Shift (result constrained by left operand).
742 * ----------------------------------------------------------------
743 */
744 template <int _AP_W2>
745 INLINE typename RType<_AP_W, _AP_S>::arg1 operator<<(
746 const ap_int_base<_AP_W2, true>& op2) const {
747 bool isNeg = _AP_ROOT_op_get_bit(op2.V, _AP_W2 - 1);
749 if (isNeg) {
750 sh = -op2;
751 return operator>>(sh);
752 } else
753 return operator<<(sh);
754 }
755
756 template <int _AP_W2>
757 INLINE typename RType<_AP_W, _AP_S>::arg1 operator<<(
758 const ap_int_base<_AP_W2, false>& op2) const {
759 ap_int_base r;
760 r.V = Base::V << op2.to_uint();
761 return r;
762 }
763
764 template <int _AP_W2>
765 INLINE typename RType<_AP_W, _AP_S>::arg1 operator>>(
766 const ap_int_base<_AP_W2, true>& op2) const {
767 bool isNeg = _AP_ROOT_op_get_bit(op2.V, _AP_W2 - 1);
769 if (isNeg) {
770 sh = -op2;
771 return operator<<(sh);
772 }
773 return operator>>(sh);
774 }
775
776 template <int _AP_W2>
777 INLINE typename RType<_AP_W, _AP_S>::arg1 operator>>(
778 const ap_int_base<_AP_W2, false>& op2) const {
779 ap_int_base r;
780 r.V = Base::V >> op2.to_uint();
781 return r;
782 }
783
784 // FIXME we standalone operator>> for ap_int_base and ap_range_ref.
785#if 0
786 template <int _AP_W2, bool _AP_S2>
787 INLINE ap_int_base operator<<(const ap_range_ref<_AP_W2, _AP_S2>& op2) const {
788 return *this << (op2.operator ap_int_base<_AP_W2, false>());
789 }
790
791 template <int _AP_W2, bool _AP_S2>
792 INLINE ap_int_base operator>>(const ap_range_ref<_AP_W2, _AP_S2>& op2) const {
793 return *this >> (op2.operator ap_int_base<_AP_W2, false>());
794 }
795#endif
796
797 /* Shift assign
798 * ----------------------------------------------------------------
799 */
800 template <int _AP_W2>
801 INLINE ap_int_base& operator<<=(const ap_int_base<_AP_W2, true>& op2) {
802 bool isNeg = _AP_ROOT_op_get_bit(op2.V, _AP_W2 - 1);
804 if (isNeg) {
805 sh = -op2;
806 return operator>>=(sh);
807 } else
808 return operator<<=(sh);
809 }
810
811 template <int _AP_W2>
812 INLINE ap_int_base& operator<<=(const ap_int_base<_AP_W2, false>& op2) {
813 Base::V <<= op2.to_uint();
814 return *this;
815 }
816
817 template <int _AP_W2>
818 INLINE ap_int_base& operator>>=(const ap_int_base<_AP_W2, true>& op2) {
819 bool isNeg = _AP_ROOT_op_get_bit(op2.V, _AP_W2 - 1);
821 if (isNeg) {
822 sh = -op2;
823 return operator<<=(sh);
824 }
825 return operator>>=(sh);
826 }
827
828 template <int _AP_W2>
829 INLINE ap_int_base& operator>>=(const ap_int_base<_AP_W2, false>& op2) {
830 Base::V >>= op2.to_uint();
831 return *this;
832 }
833
834 // FIXME we standalone operator>> for ap_int_base and ap_range_ref.
835#if 0
836 template <int _AP_W2, bool _AP_S2>
837 INLINE ap_int_base& operator<<=(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
838 return *this <<= (op2.operator ap_int_base<_AP_W2, false>());
839 }
840 template <int _AP_W2, bool _AP_S2>
841 INLINE ap_int_base& operator>>=(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
842 return *this >>= (op2.operator ap_int_base<_AP_W2, false>());
843 }
844#endif
845
846 /* Equality and Relational.
847 * ----------------------------------------------------------------
848 */
849 template <int _AP_W2, bool _AP_S2>
850 INLINE bool operator==(const ap_int_base<_AP_W2, _AP_S2>& op2) const {
851 return Base::V == op2.V;
852 }
853 template <int _AP_W2, bool _AP_S2>
854 INLINE bool operator!=(const ap_int_base<_AP_W2, _AP_S2>& op2) const {
855 return !(Base::V == op2.V);
856 }
857 template <int _AP_W2, bool _AP_S2>
858 INLINE bool operator<(const ap_int_base<_AP_W2, _AP_S2>& op2) const {
859 return Base::V < op2.V;
860 }
861 template <int _AP_W2, bool _AP_S2>
862 INLINE bool operator>=(const ap_int_base<_AP_W2, _AP_S2>& op2) const {
863 return Base::V >= op2.V;
864 }
865 template <int _AP_W2, bool _AP_S2>
866 INLINE bool operator>(const ap_int_base<_AP_W2, _AP_S2>& op2) const {
867 return Base::V > op2.V;
868 }
869 template <int _AP_W2, bool _AP_S2>
870 INLINE bool operator<=(const ap_int_base<_AP_W2, _AP_S2>& op2) const {
871 return Base::V <= op2.V;
872 }
873
874 /* Bit and Part Select
875 * ----------------------------------------------------------------
876 */
877 INLINE ap_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) {
878 _AP_ERROR(Hi >= _AP_W, "Hi(%d)out of bound(%d) in range()", Hi, _AP_W);
879 _AP_ERROR(Lo >= _AP_W, "Lo(%d)out of bound(%d) in range()", Lo, _AP_W);
880 return ap_range_ref<_AP_W, _AP_S>(this, Hi, Lo);
881 }
882
883 // This is a must to strip constness to produce reference type.
884 INLINE ap_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) const {
885 _AP_ERROR(Hi >= _AP_W, "Hi(%d)out of bound(%d) in range()", Hi, _AP_W);
886 _AP_ERROR(Lo >= _AP_W, "Lo(%d)out of bound(%d) in range()", Lo, _AP_W);
887 return ap_range_ref<_AP_W, _AP_S>(const_cast<ap_int_base*>(this), Hi, Lo);
888 }
889
890 template <int _AP_W2, bool _AP_S2, int _AP_W3, bool _AP_S3>
891 INLINE ap_range_ref<_AP_W, _AP_S> range(
892 const ap_int_base<_AP_W2, _AP_S2>& HiIdx,
893 const ap_int_base<_AP_W3, _AP_S3>& LoIdx) {
894 int Hi = HiIdx.to_int();
895 int Lo = LoIdx.to_int();
896 return this->range(Hi, Lo);
897 }
898
899 template <int _AP_W2, bool _AP_S2, int _AP_W3, bool _AP_S3>
900 INLINE ap_range_ref<_AP_W, _AP_S> range(
901 const ap_int_base<_AP_W2, _AP_S2>& HiIdx,
902 const ap_int_base<_AP_W3, _AP_S3>& LoIdx) const {
903 int Hi = HiIdx.to_int();
904 int Lo = LoIdx.to_int();
905 return this->range(Hi, Lo);
906 }
907
908 INLINE ap_range_ref<_AP_W, _AP_S> range() {
909 return this->range(_AP_W - 1, 0);
910 }
911
912 INLINE ap_range_ref<_AP_W, _AP_S> range() const {
913 return this->range(_AP_W - 1, 0);
914 }
915
916 INLINE ap_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) {
917 return this->range(Hi, Lo);
918 }
919
920 INLINE ap_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) const {
921 return this->range(Hi, Lo);
922 }
923
924 template <int _AP_W2, bool _AP_S2, int _AP_W3, bool _AP_S3>
925 INLINE ap_range_ref<_AP_W, _AP_S> operator()(
926 const ap_int_base<_AP_W2, _AP_S2>& HiIdx,
927 const ap_int_base<_AP_W3, _AP_S3>& LoIdx) {
928 int Hi = HiIdx.to_int();
929 int Lo = LoIdx.to_int();
930 return this->range(Hi, Lo);
931 }
932
933 template <int _AP_W2, bool _AP_S2, int _AP_W3, bool _AP_S3>
934 INLINE ap_range_ref<_AP_W, _AP_S> operator()(
935 const ap_int_base<_AP_W2, _AP_S2>& HiIdx,
936 const ap_int_base<_AP_W3, _AP_S3>& LoIdx) const {
937 int Hi = HiIdx.to_int();
938 int Lo = LoIdx.to_int();
939 return this->range(Hi, Lo);
940 }
941
942#if 0
943 template<int Hi, int Lo>
944 INLINE ap_int_base<Hi-Lo+1, false> slice() const {
945 AP_ASSERT(Hi >= Lo && Hi < _AP_W && Lo < _AP_W, "Out of bounds in slice()");
946 ap_int_base<Hi-Lo+1, false> tmp ;
947 tmp.V = _AP_ROOT_op_get_range(Base::V, Lo, Hi);
948 return tmp;
949 }
950
951 INLINE ap_bit_ref<_AP_W,_AP_S> operator [] ( unsigned int uindex) {
952 AP_ASSERT(uindex < _AP_W, "Attempting to read bit beyond MSB");
953 ap_bit_ref<_AP_W,_AP_S> bvh( this, uindex );
954 return bvh;
955 }
956#endif
957
958 INLINE ap_bit_ref<_AP_W, _AP_S> operator[](int index) {
959 AP_ASSERT(index >= 0, "Attempting to read bit with negative index");
960 AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB");
961 ap_bit_ref<_AP_W, _AP_S> bvh(this, index);
962 return bvh;
963 }
964
965 template <int _AP_W2, bool _AP_S2>
966 INLINE ap_bit_ref<_AP_W, _AP_S> operator[](
967 const ap_int_base<_AP_W2, _AP_S2>& index) {
968 AP_ASSERT(index >= 0, "Attempting to read bit with negative index");
969 AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB");
970 ap_bit_ref<_AP_W, _AP_S> bvh(this, index.to_int());
971 return bvh;
972 }
973
974 INLINE bool operator[](int index) const {
975 AP_ASSERT(index >= 0, "Attempting to read bit with negative index");
976 AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB");
977 ap_bit_ref<_AP_W, _AP_S> br(this, index);
978 return br.to_bool();
979 }
980 template <int _AP_W2, bool _AP_S2>
981 INLINE bool operator[](const ap_int_base<_AP_W2, _AP_S2>& index) const {
982 AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB");
983 ap_bit_ref<_AP_W, _AP_S> br(this, index.to_int());
984 return br.to_bool();
985 }
986
987 INLINE ap_bit_ref<_AP_W, _AP_S> bit(int index) {
988 AP_ASSERT(index >= 0, "Attempting to read bit with negative index");
989 AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB");
990 ap_bit_ref<_AP_W, _AP_S> bvh(this, index);
991 return bvh;
992 }
993 template <int _AP_W2, bool _AP_S2>
994 INLINE ap_bit_ref<_AP_W, _AP_S> bit(
995 const ap_int_base<_AP_W2, _AP_S2>& index) {
996 AP_ASSERT(index >= 0, "Attempting to read bit with negative index");
997 AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB");
998 ap_bit_ref<_AP_W, _AP_S> bvh(this, index.to_int());
999 return bvh;
1000 }
1001
1002 INLINE bool bit(int index) const {
1003 AP_ASSERT(index >= 0, "Attempting to read bit with negative index");
1004 AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB");
1005 ap_bit_ref<_AP_W, _AP_S> br(this, index);
1006 return br.to_bool();
1007 }
1008
1009 template <int _AP_W2, bool _AP_S2>
1010 INLINE bool bit(const ap_int_base<_AP_W2, _AP_S2>& index) const {
1011 return bit(index.to_int());
1012 }
1013
1014#if 0
1015 template<typename _AP_T>
1016 INLINE bool operator[](_AP_T index) const {
1017 AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB");
1018 ap_bit_ref<_AP_W,_AP_S> br = operator[](index);
1019 return br.to_bool();
1020 }
1021#endif
1022
1023 // Count the number of zeros from the most significant bit
1024 // to the first one bit.
1025 INLINE int countLeadingZeros() {
1026#ifdef __SYNTHESIS__
1027 if (_AP_W <= 32) {
1028 ap_int_base<32, false> t(-1UL), x;
1029 x.V = _AP_ROOT_op_get_range(this->V, _AP_W - 1, 0); // reverse
1030 t.V = _AP_ROOT_op_set_range(t.V, 0, _AP_W - 1, x.V);
1031 return __builtin_ctz(t.V); // count trailing zeros.
1032 } else if (_AP_W <= 64) {
1033 ap_int_base<64, false> t(-1ULL);
1035 x.V = _AP_ROOT_op_get_range(this->V, _AP_W - 1, 0); // reverse
1036 t.V = _AP_ROOT_op_set_range(t.V, 0, _AP_W - 1, x.V);
1037 return __builtin_ctzll(t.V); // count trailing zeros.
1038 } else {
1039 enum {__N = (_AP_W + 63) / 64};
1040 int NZeros = 0;
1041 int i = 0;
1042 bool hitNonZero = false;
1043 for (i = 0; i < __N - 1; ++i) {
1045 t.V = _AP_ROOT_op_get_range(this->V, _AP_W - i * 64 - 64,
1046 _AP_W - i * 64 - 1);
1047 NZeros +=
1048 hitNonZero ? 0 : __builtin_clzll(t.V); // count leading zeros.
1049 hitNonZero |= (t.V != 0);
1050 }
1051 if (!hitNonZero) {
1052 ap_int_base<64, false> t(-1ULL);
1053 enum {REST = (_AP_W - 1) % 64};
1055 x.V = _AP_ROOT_op_get_range(this->V, 0, REST);
1056 t.V = _AP_ROOT_op_set_range(t.V, 63 - REST, 63, x.V);
1057 NZeros += __builtin_clzll(t.V);
1058 }
1059 return NZeros;
1060 }
1061#else
1062 return (Base::V).countLeadingZeros();
1063#endif
1064 } // countLeadingZeros
1065
1066 template <int _AP_W2, bool _AP_S2>
1068 concat(const ap_int_base<_AP_W2, _AP_S2>& a2) const {
1069 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2,
1071 const_cast<ap_int_base<_AP_W, _AP_S>&>(*this),
1072 const_cast<ap_int_base<_AP_W2, _AP_S2>&>(a2));
1073 }
1074
1075 template <int _AP_W2, bool _AP_S2>
1077 concat(ap_int_base<_AP_W2, _AP_S2>& a2) {
1078 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2,
1079 ap_int_base<_AP_W2, _AP_S2> >(*this, a2);
1080 }
1081
1082 template <int _AP_W2, bool _AP_S2>
1083 INLINE
1085 operator,(const ap_range_ref<_AP_W2, _AP_S2>&a2) const {
1086 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2,
1088 const_cast<ap_int_base<_AP_W, _AP_S>&>(*this),
1089 const_cast<ap_range_ref<_AP_W2, _AP_S2>&>(a2));
1090 }
1091
1092 template <int _AP_W2, bool _AP_S2>
1093 INLINE
1095 operator,(ap_range_ref<_AP_W2, _AP_S2>&a2) {
1096 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2,
1097 ap_range_ref<_AP_W2, _AP_S2> >(*this, a2);
1098 }
1099
1100 template <int _AP_W2, bool _AP_S2>
1102 operator,(const ap_int_base<_AP_W2, _AP_S2>&a2) {
1103 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2,
1105 *this, const_cast<ap_int_base<_AP_W2, _AP_S2>&>(a2));
1106 }
1107
1108 template <int _AP_W2, bool _AP_S2>
1110 operator,(ap_int_base<_AP_W2, _AP_S2>&a2) const {
1111 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2,
1113 const_cast<ap_int_base<_AP_W, _AP_S>&>(*this), a2);
1114 }
1115
1116 template <int _AP_W2, bool _AP_S2>
1118 operator,(const ap_int_base<_AP_W2, _AP_S2>&a2) const {
1119 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2,
1121 const_cast<ap_int_base<_AP_W, _AP_S>&>(*this),
1122 const_cast<ap_int_base<_AP_W2, _AP_S2>&>(a2));
1123 }
1124
1125 template <int _AP_W2, bool _AP_S2>
1127 operator,(ap_int_base<_AP_W2, _AP_S2>&a2) {
1128 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2,
1129 ap_int_base<_AP_W2, _AP_S2> >(*this, a2);
1130 }
1131
1132 template <int _AP_W2, bool _AP_S2>
1134 operator,(const ap_bit_ref<_AP_W2, _AP_S2>&a2) const {
1136 const_cast<ap_int_base<_AP_W, _AP_S>&>(*this),
1137 const_cast<ap_bit_ref<_AP_W2, _AP_S2>&>(a2));
1138 }
1139
1140 template <int _AP_W2, bool _AP_S2>
1142 operator,(ap_bit_ref<_AP_W2, _AP_S2>&a2) {
1144 *this, a2);
1145 }
1146
1147 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
1148 INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2 + _AP_W3,
1151 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2 + _AP_W3,
1153 const_cast<ap_int_base<_AP_W, _AP_S>&>(*this),
1155 }
1156
1157 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
1158 INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2 + _AP_W3,
1161 return ap_concat_ref<_AP_W, ap_int_base, _AP_W2 + _AP_W3,
1163 a2);
1164 }
1165
1166 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
1167 ap_o_mode _AP_O2, int _AP_N2>
1168 INLINE ap_concat_ref<
1169 _AP_W, ap_int_base, _AP_W2,
1172 &a2) const {
1173 return ap_concat_ref<
1174 _AP_W, ap_int_base, _AP_W2,
1176 const_cast<ap_int_base<_AP_W, _AP_S>&>(*this),
1177 const_cast<
1179 }
1180
1181 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
1182 ap_o_mode _AP_O2, int _AP_N2>
1183 INLINE ap_concat_ref<
1184 _AP_W, ap_int_base, _AP_W2,
1187 return ap_concat_ref<
1188 _AP_W, ap_int_base, _AP_W2,
1190 a2);
1191 }
1192
1193 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
1194 ap_o_mode _AP_O2, int _AP_N2>
1195 INLINE
1196 ap_concat_ref<_AP_W, ap_int_base, 1,
1199 &a2) const {
1200 return ap_concat_ref<
1201 _AP_W, ap_int_base, 1,
1203 const_cast<ap_int_base<_AP_W, _AP_S>&>(*this),
1205 a2));
1206 }
1207
1208 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
1209 ap_o_mode _AP_O2, int _AP_N2>
1210 INLINE
1211 ap_concat_ref<_AP_W, ap_int_base, 1,
1214 return ap_concat_ref<
1215 _AP_W, ap_int_base, 1,
1217 }
1218
1219 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
1220 INLINE ap_int_base<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator&(
1222 return *this & a2.get();
1223 }
1224
1225 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
1226 INLINE ap_int_base<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator|(
1228 return *this | a2.get();
1229 }
1230
1231 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
1232 INLINE ap_int_base<AP_MAX(_AP_W2 + _AP_W3, _AP_W), _AP_S> operator^(
1234 return *this ^ a2.get();
1235 }
1236
1237 template <int _AP_W3>
1238 INLINE void set(const ap_int_base<_AP_W3, false>& val) {
1239 Base::V = val.V;
1240 }
1241
1242 /* Reduce operations.
1243 * ----------------------------------------------------------------
1244 */
1245 // XXX non-const version deleted.
1246 INLINE bool and_reduce() const { return _AP_ROOT_op_reduce(and, Base::V); }
1247 INLINE bool nand_reduce() const { return _AP_ROOT_op_reduce(nand, Base::V); }
1248 INLINE bool or_reduce() const { return _AP_ROOT_op_reduce(or, Base::V); }
1249 INLINE bool nor_reduce() const { return !(_AP_ROOT_op_reduce(or, Base::V)); }
1250 INLINE bool xor_reduce() const { return _AP_ROOT_op_reduce(xor, Base::V); }
1251 INLINE bool xnor_reduce() const {
1252 return !(_AP_ROOT_op_reduce(xor, Base::V));
1253 }
1254
1255 /* Output as a string.
1256 * ----------------------------------------------------------------
1257 */
1258#ifndef __SYNTHESIS__
1259 std::string to_string(signed char rd = 2, bool sign = _AP_S) const {
1260 // XXX in autosim/autowrap.tcl "(${name}).to_string(2).c_str()" is used to
1261 // initialize sc_lv, which seems incapable of handling format "-0b".
1262 if (rd == 2) sign = false;
1263 return (Base::V).to_string(rd, sign);
1264 }
1265#else
1266 INLINE char* to_string(signed char rd = 2, bool sign = _AP_S) const {
1267 return 0;
1268 }
1269#endif
1270}; // struct ap_int_base
1271
1272// XXX apcc cannot handle global std::ios_base::Init() brought in by <iostream>
1273#ifndef AP_AUTOCC
1274#ifndef __SYNTHESIS__
1275template <int _AP_W, bool _AP_S>
1276INLINE std::ostream& operator<<(std::ostream& os,
1277 const ap_int_base<_AP_W, _AP_S>& x) {
1278 std::ios_base::fmtflags ff = std::cout.flags();
1279 if (ff & std::cout.hex) {
1280 os << x.to_string(16); // don't print sign
1281 } else if (ff & std::cout.oct) {
1282 os << x.to_string(8); // don't print sign
1283 } else {
1284 os << x.to_string(10);
1285 }
1286 return os;
1287}
1288#endif // ifndef __SYNTHESIS__
1289
1290#ifndef __SYNTHESIS__
1291template <int _AP_W, bool _AP_S>
1292INLINE std::istream& operator>>(std::istream& in,
1294 std::string str;
1295 in >> str;
1296 const std::ios_base::fmtflags basefield =
1297 in.flags() & std::ios_base::basefield;
1298 unsigned radix = (basefield == std::ios_base::dec)
1299 ? 0
1300 : ((basefield == std::ios_base::oct)
1301 ? 8
1302 : ((basefield == std::ios_base::hex) ? 16 : 0));
1303 op = ap_int_base<_AP_W, _AP_S>(str.c_str(), radix);
1304 return in;
1305}
1306#endif // ifndef __SYNTHESIS__
1307#endif // ifndef AP_AUTOCC
1308
1309/* Operators with another ap_int_base.
1310 * ----------------------------------------------------------------
1311 */
1312#define OP_BIN_AP(Sym, Rty) \
1313 template <int _AP_W, bool _AP_S, int _AP_W2, bool _AP_S2> \
1314 INLINE \
1315 typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W2, _AP_S2>::Rty \
1316 operator Sym(const ap_int_base<_AP_W, _AP_S>& op, \
1317 const ap_int_base<_AP_W2, _AP_S2>& op2) { \
1318 typename ap_int_base<_AP_W, _AP_S>::template RType< \
1319 _AP_W2, _AP_S2>::Rty##_base lhs(op); \
1320 typename ap_int_base<_AP_W, _AP_S>::template RType< \
1321 _AP_W2, _AP_S2>::Rty##_base rhs(op2); \
1322 typename ap_int_base<_AP_W, _AP_S>::template RType< \
1323 _AP_W2, _AP_S2>::Rty##_base ret; \
1324 ret.V = lhs.V Sym rhs.V; \
1325 return ret; \
1326 }
1327
1328OP_BIN_AP(*, mult)
1329OP_BIN_AP(+, plus)
1330OP_BIN_AP(-, minus)
1331OP_BIN_AP(&, logic)
1332OP_BIN_AP(|, logic)
1333OP_BIN_AP(^, logic)
1334
1335#define OP_BIN_AP2(Sym, Rty) \
1336 template <int _AP_W, bool _AP_S, int _AP_W2, bool _AP_S2> \
1337 INLINE \
1338 typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W2, _AP_S2>::Rty \
1339 operator Sym(const ap_int_base<_AP_W, _AP_S>& op, \
1340 const ap_int_base<_AP_W2, _AP_S2>& op2) { \
1341 typename ap_int_base<_AP_W, _AP_S>::template RType< \
1342 _AP_W2, _AP_S2>::Rty##_base ret; \
1343 ret.V = op.V Sym op2.V; \
1344 return ret; \
1345 }
1346
1347OP_BIN_AP2(/, div)
1348OP_BIN_AP2(%, mod)
1349
1350// shift operators are defined inside class.
1351// compound assignment operators are defined inside class.
1352
1353/* Operators with a pointer type.
1354 * ----------------------------------------------------------------
1355 * char a[100];
1356 * char* ptr = a;
1357 * ap_int<2> n = 3;
1358 * char* ptr2 = ptr + n*2;
1359 * avoid ambiguous errors.
1360 */
1361#define OP_BIN_WITH_PTR(BIN_OP) \
1362 template <typename PTR_TYPE, int _AP_W, bool _AP_S> \
1363 INLINE PTR_TYPE* operator BIN_OP(PTR_TYPE* i_op, \
1364 const ap_int_base<_AP_W, _AP_S>& op) { \
1365 ap_slong op2 = op.to_int64(); /* Not all implementation */ \
1366 return i_op BIN_OP op2; \
1367 } \
1368 template <typename PTR_TYPE, int _AP_W, bool _AP_S> \
1369 INLINE PTR_TYPE* operator BIN_OP(const ap_int_base<_AP_W, _AP_S>& op, \
1370 PTR_TYPE* i_op) { \
1371 ap_slong op2 = op.to_int64(); /* Not all implementation */ \
1372 return op2 BIN_OP i_op; \
1373 }
1374
1375OP_BIN_WITH_PTR(+)
1376OP_BIN_WITH_PTR(-)
1377
1378/* Operators with a native floating point types.
1379 * ----------------------------------------------------------------
1380 */
1381// float OP ap_int
1382// when ap_int<wa>'s width > 64, then trunc ap_int<w> to ap_int<64>
1383#define OP_BIN_WITH_FLOAT(BIN_OP, C_TYPE) \
1384 template <int _AP_W, bool _AP_S> \
1385 INLINE C_TYPE operator BIN_OP(C_TYPE i_op, \
1386 const ap_int_base<_AP_W, _AP_S>& op) { \
1387 typename ap_int_base<_AP_W, _AP_S>::RetType op2 = op; \
1388 return i_op BIN_OP op2; \
1389 } \
1390 template <int _AP_W, bool _AP_S> \
1391 INLINE C_TYPE operator BIN_OP(const ap_int_base<_AP_W, _AP_S>& op, \
1392 C_TYPE i_op) { \
1393 typename ap_int_base<_AP_W, _AP_S>::RetType op2 = op; \
1394 return op2 BIN_OP i_op; \
1395 }
1396
1397#define ALL_OP_WITH_FLOAT(C_TYPE) \
1398 OP_BIN_WITH_FLOAT(*, C_TYPE) \
1399 OP_BIN_WITH_FLOAT(/, C_TYPE) \
1400 OP_BIN_WITH_FLOAT(+, C_TYPE) \
1401 OP_BIN_WITH_FLOAT(-, C_TYPE)
1402
1403#if _AP_ENABLE_HALF_ == 1
1404ALL_OP_WITH_FLOAT(half)
1405#endif
1406ALL_OP_WITH_FLOAT(float)
1407ALL_OP_WITH_FLOAT(double)
1408
1409// TODO no shift?
1410
1411/* Operators with a native integral types.
1412 * ----------------------------------------------------------------
1413 */
1414// arithmetic and bitwise operators.
1415#define OP_BIN_WITH_INT(BIN_OP, C_TYPE, _AP_W2, _AP_S2, RTYPE) \
1416 template <int _AP_W, bool _AP_S> \
1417 INLINE typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W2, \
1418 _AP_S2>::RTYPE \
1419 operator BIN_OP(C_TYPE i_op, const ap_int_base<_AP_W, _AP_S>& op) { \
1420 return ap_int_base<_AP_W2, _AP_S2>(i_op) BIN_OP(op); \
1421 } \
1422 template <int _AP_W, bool _AP_S> \
1423 INLINE typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W2, \
1424 _AP_S2>::RTYPE \
1425 operator BIN_OP(const ap_int_base<_AP_W, _AP_S>& op, C_TYPE i_op) { \
1426 return op BIN_OP ap_int_base<_AP_W2, _AP_S2>(i_op); \
1427 }
1428
1429#define ALL_OP_BIN_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \
1430 OP_BIN_WITH_INT(*, C_TYPE, _AP_W2, _AP_S2, mult) \
1431 OP_BIN_WITH_INT(+, C_TYPE, _AP_W2, _AP_S2, plus) \
1432 OP_BIN_WITH_INT(-, C_TYPE, _AP_W2, _AP_S2, minus) \
1433 OP_BIN_WITH_INT(/, C_TYPE, _AP_W2, _AP_S2, div) \
1434 OP_BIN_WITH_INT(%, C_TYPE, _AP_W2, _AP_S2, mod) \
1435 OP_BIN_WITH_INT(&, C_TYPE, _AP_W2, _AP_S2, logic) \
1436 OP_BIN_WITH_INT(|, C_TYPE, _AP_W2, _AP_S2, logic) \
1437 OP_BIN_WITH_INT(^, C_TYPE, _AP_W2, _AP_S2, logic)
1438
1439ALL_OP_BIN_WITH_INT(bool, 1, false)
1440ALL_OP_BIN_WITH_INT(char, 8, CHAR_IS_SIGNED)
1441ALL_OP_BIN_WITH_INT(signed char, 8, true)
1442ALL_OP_BIN_WITH_INT(unsigned char, 8, false)
1443ALL_OP_BIN_WITH_INT(short, _AP_SIZE_short, true)
1444ALL_OP_BIN_WITH_INT(unsigned short, _AP_SIZE_short, false)
1445ALL_OP_BIN_WITH_INT(int, _AP_SIZE_int, true)
1446ALL_OP_BIN_WITH_INT(unsigned int, _AP_SIZE_int, false)
1447ALL_OP_BIN_WITH_INT(long, _AP_SIZE_long, true)
1448ALL_OP_BIN_WITH_INT(unsigned long, _AP_SIZE_long, false)
1449ALL_OP_BIN_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true)
1450ALL_OP_BIN_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false)
1451
1452#undef OP_BIN_WITH_INT
1453#undef ALL_OP_BIN_WITH_INT
1454
1455// shift operators.
1456#define ALL_OP_SHIFT_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \
1457 template <int _AP_W, bool _AP_S> \
1458 INLINE \
1459 typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W, _AP_S>::arg1 \
1460 operator<<(const ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \
1461 ap_int_base<_AP_W, _AP_S> r; \
1462 if (_AP_S2) \
1463 r.V = op2 >= 0 ? (op.V << op2) : (op.V >> (-op2)); \
1464 else \
1465 r.V = op.V << op2; \
1466 return r; \
1467 } \
1468 template <int _AP_W, bool _AP_S> \
1469 INLINE \
1470 typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W, _AP_S>::arg1 \
1471 operator>>(const ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \
1472 ap_int_base<_AP_W, _AP_S> r; \
1473 if (_AP_S2) \
1474 r.V = op2 >= 0 ? (op.V >> op2) : (op.V << (-op2)); \
1475 else \
1476 r.V = op.V >> op2; \
1477 return r; \
1478 }
1479
1480ALL_OP_SHIFT_WITH_INT(char, 8, CHAR_IS_SIGNED)
1481ALL_OP_SHIFT_WITH_INT(signed char, 8, true)
1482ALL_OP_SHIFT_WITH_INT(short, _AP_SIZE_short, true)
1483ALL_OP_SHIFT_WITH_INT(int, _AP_SIZE_int, true)
1484ALL_OP_SHIFT_WITH_INT(long, _AP_SIZE_long, true)
1485ALL_OP_SHIFT_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true)
1486
1487#undef ALL_OP_SHIFT_WITH_INT
1488
1489#define ALL_OP_SHIFT_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \
1490 template <int _AP_W, bool _AP_S> \
1491 INLINE \
1492 typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W, _AP_S>::arg1 \
1493 operator<<(const ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \
1494 ap_int_base<_AP_W, _AP_S> r; \
1495 r.V = op.V << op2; \
1496 return r; \
1497 } \
1498 template <int _AP_W, bool _AP_S> \
1499 INLINE \
1500 typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W, _AP_S>::arg1 \
1501 operator>>(const ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \
1502 ap_int_base<_AP_W, _AP_S> r; \
1503 r.V = op.V >> op2; \
1504 return r; \
1505 }
1506ALL_OP_SHIFT_WITH_INT(bool, 1, false)
1507ALL_OP_SHIFT_WITH_INT(unsigned char, 8, false)
1508ALL_OP_SHIFT_WITH_INT(unsigned short, _AP_SIZE_short, false)
1509ALL_OP_SHIFT_WITH_INT(unsigned int, _AP_SIZE_int, false)
1510ALL_OP_SHIFT_WITH_INT(unsigned long, _AP_SIZE_long, false)
1511ALL_OP_SHIFT_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false)
1512
1513#undef ALL_OP_SHIFT_WITH_INT
1514
1515// compound assign operators.
1516#define OP_ASSIGN_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \
1517 template <int _AP_W, bool _AP_S> \
1518 INLINE ap_int_base<_AP_W, _AP_S>& operator ASSIGN_OP( \
1519 ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \
1520 return op ASSIGN_OP ap_int_base<_AP_W2, _AP_S2>(op2); \
1521 }
1522
1523// TODO int a; ap_int<16> b; a += b;
1524
1525#define ALL_OP_ASSIGN_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \
1526 OP_ASSIGN_WITH_INT(+=, C_TYPE, _AP_W2, _AP_S2) \
1527 OP_ASSIGN_WITH_INT(-=, C_TYPE, _AP_W2, _AP_S2) \
1528 OP_ASSIGN_WITH_INT(*=, C_TYPE, _AP_W2, _AP_S2) \
1529 OP_ASSIGN_WITH_INT(/=, C_TYPE, _AP_W2, _AP_S2) \
1530 OP_ASSIGN_WITH_INT(%=, C_TYPE, _AP_W2, _AP_S2) \
1531 OP_ASSIGN_WITH_INT(&=, C_TYPE, _AP_W2, _AP_S2) \
1532 OP_ASSIGN_WITH_INT(|=, C_TYPE, _AP_W2, _AP_S2) \
1533 OP_ASSIGN_WITH_INT(^=, C_TYPE, _AP_W2, _AP_S2) \
1534 OP_ASSIGN_WITH_INT(>>=, C_TYPE, _AP_W2, _AP_S2) \
1535 OP_ASSIGN_WITH_INT(<<=, C_TYPE, _AP_W2, _AP_S2)
1536
1537ALL_OP_ASSIGN_WITH_INT(bool, 1, false)
1538ALL_OP_ASSIGN_WITH_INT(char, 8, CHAR_IS_SIGNED)
1539ALL_OP_ASSIGN_WITH_INT(signed char, 8, true)
1540ALL_OP_ASSIGN_WITH_INT(unsigned char, 8, false)
1541ALL_OP_ASSIGN_WITH_INT(short, _AP_SIZE_short, true)
1542ALL_OP_ASSIGN_WITH_INT(unsigned short, _AP_SIZE_short, false)
1543ALL_OP_ASSIGN_WITH_INT(int, _AP_SIZE_int, true)
1544ALL_OP_ASSIGN_WITH_INT(unsigned int, _AP_SIZE_int, false)
1545ALL_OP_ASSIGN_WITH_INT(long, _AP_SIZE_long, true)
1546ALL_OP_ASSIGN_WITH_INT(unsigned long, _AP_SIZE_long, false)
1547ALL_OP_ASSIGN_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true)
1548ALL_OP_ASSIGN_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false)
1549
1550#undef OP_ASSIGN_WITH_INT
1551#undef ALL_OP_ASSIGN_WITH_INT
1552
1553// equality and relational operators.
1554#define OP_REL_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \
1555 template <int _AP_W, bool _AP_S> \
1556 INLINE bool operator REL_OP(C_TYPE i_op, \
1557 const ap_int_base<_AP_W, _AP_S>& op) { \
1558 return ap_int_base<_AP_W2, _AP_S2>(i_op) REL_OP op; \
1559 } \
1560 template <int _AP_W, bool _AP_S> \
1561 INLINE bool operator REL_OP(const ap_int_base<_AP_W, _AP_S>& op, \
1562 C_TYPE op2) { \
1563 return op REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \
1564 }
1565
1566#define ALL_OP_REL_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \
1567 OP_REL_WITH_INT(>, C_TYPE, _AP_W2, _AP_S2) \
1568 OP_REL_WITH_INT(<, C_TYPE, _AP_W2, _AP_S2) \
1569 OP_REL_WITH_INT(>=, C_TYPE, _AP_W2, _AP_S2) \
1570 OP_REL_WITH_INT(<=, C_TYPE, _AP_W2, _AP_S2) \
1571 OP_REL_WITH_INT(==, C_TYPE, _AP_W2, _AP_S2) \
1572 OP_REL_WITH_INT(!=, C_TYPE, _AP_W2, _AP_S2)
1573
1574ALL_OP_REL_WITH_INT(bool, 1, false)
1575ALL_OP_REL_WITH_INT(char, 8, CHAR_IS_SIGNED)
1576ALL_OP_REL_WITH_INT(signed char, 8, true)
1577ALL_OP_REL_WITH_INT(unsigned char, 8, false)
1578ALL_OP_REL_WITH_INT(short, _AP_SIZE_short, true)
1579ALL_OP_REL_WITH_INT(unsigned short, _AP_SIZE_short, false)
1580ALL_OP_REL_WITH_INT(int, _AP_SIZE_int, true)
1581ALL_OP_REL_WITH_INT(unsigned int, _AP_SIZE_int, false)
1582ALL_OP_REL_WITH_INT(long, _AP_SIZE_long, true)
1583ALL_OP_REL_WITH_INT(unsigned long, _AP_SIZE_long, false)
1584ALL_OP_REL_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true)
1585ALL_OP_REL_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false)
1586
1587#undef OP_REL_WITH_INT
1588#undef ALL_OP_BIN_WITH_INT
1589
1590#define OP_REL_WITH_DOUBLE_OR_FLOAT(Sym) \
1591 template <int _AP_W, bool _AP_S> \
1592 INLINE bool operator Sym(const ap_int_base<_AP_W, _AP_S>& op1, double op2) { \
1593 return op1.to_double() Sym op2; \
1594 } \
1595 template <int _AP_W, bool _AP_S> \
1596 INLINE bool operator Sym(double op1, const ap_int_base<_AP_W, _AP_S>& op2) { \
1597 return op1 Sym op2.to_double(); \
1598 } \
1599 template <int _AP_W, bool _AP_S> \
1600 INLINE bool operator Sym(const ap_int_base<_AP_W, _AP_S>& op1, float op2) { \
1601 return op1.to_double() Sym op2; \
1602 } \
1603 template <int _AP_W, bool _AP_S> \
1604 INLINE bool operator Sym(float op1, const ap_int_base<_AP_W, _AP_S>& op2) { \
1605 return op1 Sym op2.to_double(); \
1606 }
1607OP_REL_WITH_DOUBLE_OR_FLOAT(>)
1608OP_REL_WITH_DOUBLE_OR_FLOAT(<)
1609OP_REL_WITH_DOUBLE_OR_FLOAT(>=)
1610OP_REL_WITH_DOUBLE_OR_FLOAT(<=)
1611OP_REL_WITH_DOUBLE_OR_FLOAT(==)
1612OP_REL_WITH_DOUBLE_OR_FLOAT(!=)
1613
1614#undef OP_REL_WITH_DOUBLE_OR_FLOAT
1615
1616/* Operators with ap_bit_ref.
1617 * ------------------------------------------------------------
1618 */
1619// arithmetic, bitwise and shift operators.
1620#define OP_BIN_WITH_RANGE(BIN_OP, RTYPE) \
1621 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1622 INLINE typename ap_int_base<_AP_W1, _AP_S1>::template RType<_AP_W2, \
1623 _AP_S2>::RTYPE \
1624 operator BIN_OP(const ap_range_ref<_AP_W1, _AP_S1>& op1, \
1625 const ap_int_base<_AP_W2, _AP_S2>& op2) { \
1626 return ap_int_base<_AP_W1, false>(op1) BIN_OP op2; \
1627 } \
1628 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1629 INLINE typename ap_int_base<_AP_W1, _AP_S1>::template RType<_AP_W2, \
1630 _AP_S2>::RTYPE \
1631 operator BIN_OP(const ap_int_base<_AP_W1, _AP_S1>& op1, \
1632 const ap_range_ref<_AP_W2, _AP_S2>& op2) { \
1633 return op1 BIN_OP ap_int_base<_AP_W2, false>(op2); \
1634 }
1635
1636OP_BIN_WITH_RANGE(+, plus)
1637OP_BIN_WITH_RANGE(-, minus)
1638OP_BIN_WITH_RANGE(*, mult)
1639OP_BIN_WITH_RANGE(/, div)
1640OP_BIN_WITH_RANGE(%, mod)
1641OP_BIN_WITH_RANGE(&, logic)
1642OP_BIN_WITH_RANGE(|, logic)
1643OP_BIN_WITH_RANGE(^, logic)
1644OP_BIN_WITH_RANGE(>>, arg1)
1645OP_BIN_WITH_RANGE(<<, arg1)
1646
1647#undef OP_BIN_WITH_RANGE
1648
1649// compound assignment operators.
1650#define OP_ASSIGN_WITH_RANGE(ASSIGN_OP) \
1651 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1652 INLINE ap_int_base<_AP_W1, _AP_S1>& operator ASSIGN_OP( \
1653 ap_int_base<_AP_W1, _AP_S1>& op1, ap_range_ref<_AP_W2, _AP_S2>& op2) { \
1654 return op1 ASSIGN_OP ap_int_base<_AP_W2, false>(op2); \
1655 } \
1656 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1657 INLINE ap_range_ref<_AP_W1, _AP_S1>& operator ASSIGN_OP( \
1658 ap_range_ref<_AP_W1, _AP_S1>& op1, ap_int_base<_AP_W2, _AP_S2>& op2) { \
1659 ap_int_base<_AP_W1, false> tmp(op1); \
1660 tmp ASSIGN_OP op2; \
1661 op1 = tmp; \
1662 return op1; \
1663 }
1664
1665OP_ASSIGN_WITH_RANGE(+=)
1666OP_ASSIGN_WITH_RANGE(-=)
1667OP_ASSIGN_WITH_RANGE(*=)
1668OP_ASSIGN_WITH_RANGE(/=)
1669OP_ASSIGN_WITH_RANGE(%=)
1670OP_ASSIGN_WITH_RANGE(&=)
1671OP_ASSIGN_WITH_RANGE(|=)
1672OP_ASSIGN_WITH_RANGE(^=)
1673OP_ASSIGN_WITH_RANGE(>>=)
1674OP_ASSIGN_WITH_RANGE(<<=)
1675
1676#undef OP_ASSIGN_WITH_RANGE
1677
1678// equality and relational operators
1679#define OP_REL_WITH_RANGE(REL_OP) \
1680 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1681 INLINE bool operator REL_OP(const ap_range_ref<_AP_W1, _AP_S1>& op1, \
1682 const ap_int_base<_AP_W2, _AP_S2>& op2) { \
1683 return ap_int_base<_AP_W1, false>(op1).operator REL_OP(op2); \
1684 } \
1685 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1686 INLINE bool operator REL_OP(const ap_int_base<_AP_W1, _AP_S1>& op1, \
1687 const ap_range_ref<_AP_W2, _AP_S2>& op2) { \
1688 return op1.operator REL_OP(op2.operator ap_int_base<_AP_W2, false>()); \
1689 }
1690
1691OP_REL_WITH_RANGE(==)
1692OP_REL_WITH_RANGE(!=)
1693OP_REL_WITH_RANGE(>)
1694OP_REL_WITH_RANGE(>=)
1695OP_REL_WITH_RANGE(<)
1696OP_REL_WITH_RANGE(<=)
1697
1698#undef OP_REL_WITH_RANGE
1699
1700/* Operators with ap_bit_ref.
1701 * ------------------------------------------------------------
1702 */
1703// arithmetic, bitwise and shift operators.
1704#define OP_BIN_WITH_BIT(BIN_OP, RTYPE) \
1705 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1706 INLINE typename ap_int_base<_AP_W1, _AP_S1>::template RType<1, false>::RTYPE \
1707 operator BIN_OP(const ap_int_base<_AP_W1, _AP_S1>& op1, \
1708 const ap_bit_ref<_AP_W2, _AP_S2>& op2) { \
1709 return op1 BIN_OP ap_int_base<1, false>(op2); \
1710 } \
1711 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1712 INLINE typename ap_int_base<1, false>::template RType<_AP_W2, _AP_S2>::RTYPE \
1713 operator BIN_OP(const ap_bit_ref<_AP_W1, _AP_S1>& op1, \
1714 const ap_int_base<_AP_W2, _AP_S2>& op2) { \
1715 return ap_int_base<1, false>(op1) BIN_OP op2; \
1716 }
1717
1718OP_BIN_WITH_BIT(+, plus)
1719OP_BIN_WITH_BIT(-, minus)
1720OP_BIN_WITH_BIT(*, mult)
1721OP_BIN_WITH_BIT(/, div)
1722OP_BIN_WITH_BIT(%, mod)
1723OP_BIN_WITH_BIT(&, logic)
1724OP_BIN_WITH_BIT(|, logic)
1725OP_BIN_WITH_BIT(^, logic)
1726OP_BIN_WITH_BIT(>>, arg1)
1727OP_BIN_WITH_BIT(<<, arg1)
1728
1729#undef OP_BIN_WITH_BIT
1730
1731// compound assignment operators.
1732#define OP_ASSIGN_WITH_BIT(ASSIGN_OP) \
1733 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1734 INLINE ap_int_base<_AP_W1, _AP_S1>& operator ASSIGN_OP( \
1735 ap_int_base<_AP_W1, _AP_S1>& op1, ap_bit_ref<_AP_W2, _AP_S2>& op2) { \
1736 return op1 ASSIGN_OP ap_int_base<1, false>(op2); \
1737 } \
1738 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1739 INLINE ap_bit_ref<_AP_W1, _AP_S1>& operator ASSIGN_OP( \
1740 ap_bit_ref<_AP_W1, _AP_S1>& op1, ap_int_base<_AP_W2, _AP_S2>& op2) { \
1741 ap_int_base<1, false> tmp(op1); \
1742 tmp ASSIGN_OP op2; \
1743 op1 = tmp; \
1744 return op1; \
1745 }
1746
1747OP_ASSIGN_WITH_BIT(+=)
1748OP_ASSIGN_WITH_BIT(-=)
1749OP_ASSIGN_WITH_BIT(*=)
1750OP_ASSIGN_WITH_BIT(/=)
1751OP_ASSIGN_WITH_BIT(%=)
1752OP_ASSIGN_WITH_BIT(&=)
1753OP_ASSIGN_WITH_BIT(|=)
1754OP_ASSIGN_WITH_BIT(^=)
1755OP_ASSIGN_WITH_BIT(>>=)
1756OP_ASSIGN_WITH_BIT(<<=)
1757
1758#undef OP_ASSIGN_WITH_BIT
1759
1760// equality and relational operators.
1761#define OP_REL_WITH_BIT(REL_OP) \
1762 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1763 INLINE bool operator REL_OP(const ap_int_base<_AP_W1, _AP_S1>& op1, \
1764 const ap_bit_ref<_AP_W2, _AP_S2>& op2) { \
1765 return op1 REL_OP ap_int_base<1, false>(op2); \
1766 } \
1767 template <int _AP_W1, bool _AP_S1, int _AP_W2, bool _AP_S2> \
1768 INLINE bool operator REL_OP(const ap_bit_ref<_AP_W1, _AP_S1>& op1, \
1769 const ap_int_base<_AP_W2, _AP_S2>& op2) { \
1770 return ap_int_base<1, false>(op1) REL_OP op2; \
1771 }
1772
1773OP_REL_WITH_BIT(==)
1774OP_REL_WITH_BIT(!=)
1775OP_REL_WITH_BIT(>)
1776OP_REL_WITH_BIT(>=)
1777OP_REL_WITH_BIT(<)
1778OP_REL_WITH_BIT(<=)
1779
1780#undef OP_REL_WITH_BIT
1781
1782/* Operators with ap_concat_ref.
1783 * ------------------------------------------------------------
1784 */
1785// arithmetic, bitwise and shift operators.
1786// bitwise operators are defined in struct.
1787// TODO specify whether to define arithmetic and bitwise operators.
1788#if 0
1789#define OP_BIN_WITH_CONCAT(BIN_OP, RTYPE) \
1790 template <int _AP_W1, typename _AP_T1, int _AP_W2, typename _AP_T2, \
1791 int _AP_W3, bool _AP_S3> \
1792 INLINE typename ap_int_base<_AP_W3, _AP_S3>::template RType<_AP_W1 + _AP_W2, \
1793 false>::RTYPE \
1794 operator BIN_OP(const ap_int_base<_AP_W3, _AP_S3>& op1, \
1795 const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op2) { \
1796 /* convert ap_concat_ref to ap_int_base */ \
1797 return op1 BIN_OP op2.get(); \
1798 } \
1799 template <int _AP_W1, typename _AP_T1, int _AP_W2, typename _AP_T2, \
1800 int _AP_W3, bool _AP_S3> \
1801 INLINE typename ap_int_base<_AP_W1 + _AP_W2, \
1802 false>::template RType<_AP_W3, _AP_S3>::RTYPE \
1803 operator BIN_OP(const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op1, \
1804 const ap_int_base<_AP_W3, _AP_S3>& op2) { \
1805 /* convert ap_concat_ref to ap_int_base */ \
1806 return op1.get() BIN_OP op2; \
1807 }
1808
1809OP_BIN_WITH_CONCAT(+, plus)
1810OP_BIN_WITH_CONCAT(-, minus)
1811OP_BIN_WITH_CONCAT(*, mult)
1812OP_BIN_WITH_CONCAT(/, div)
1813OP_BIN_WITH_CONCAT(%, mod)
1814OP_BIN_WITH_CONCAT(&, logic)
1815OP_BIN_WITH_CONCAT(|, logic)
1816OP_BIN_WITH_CONCAT(^, logic)
1817OP_BIN_WITH_CONCAT(>>, arg1)
1818OP_BIN_WITH_CONCAT(<<, arg1)
1819
1820#undef OP_BIN_WITH_CONCAT
1821
1822// compound assignment operators.
1823#define OP_ASSIGN_WITH_CONCAT(ASSIGN_OP) \
1824 template <int _AP_W1, typename _AP_T1, int _AP_W2, typename _AP_T2, \
1825 int _AP_W3, bool _AP_S3> \
1826 INLINE typename ap_int_base<_AP_W3, _AP_S3>::template RType<_AP_W1 + _AP_W2, \
1827 false>::RTYPE \
1828 operator ASSIGN_OP( \
1829 const ap_int_base<_AP_W3, _AP_S3>& op1, \
1830 const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op2) { \
1831 /* convert ap_concat_ref to ap_int_base */ \
1832 return op1 ASSIGN_OP op2.get(); \
1833 } \
1834 template <int _AP_W1, typename _AP_T1, int _AP_W2, typename _AP_T2, \
1835 int _AP_W3, bool _AP_S3> \
1836 INLINE typename ap_int_base<_AP_W1 + _AP_W2, \
1837 false>::template RType<_AP_W3, _AP_S3>::RTYPE \
1838 operator ASSIGN_OP(const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op1, \
1839 const ap_int_base<_AP_W3, _AP_S3>& op2) { \
1840 /* convert ap_concat_ref to ap_int_base */ \
1841 ap_int_base<_AP_W1 + _AP_W2, false> tmp = op1.get(); \
1842 tmp ASSIGN_OP op2; \
1843 op1 = tmp; \
1844 return op1; \
1845 }
1846
1847OP_ASSIGN_WITH_CONCAT(+=)
1848OP_ASSIGN_WITH_CONCAT(-=)
1849OP_ASSIGN_WITH_CONCAT(*=)
1850OP_ASSIGN_WITH_CONCAT(/=)
1851OP_ASSIGN_WITH_CONCAT(%=)
1852OP_ASSIGN_WITH_CONCAT(&=)
1853OP_ASSIGN_WITH_CONCAT(|=)
1854OP_ASSIGN_WITH_CONCAT(^=)
1855OP_ASSIGN_WITH_CONCAT(>>=)
1856OP_ASSIGN_WITH_CONCAT(<<=)
1857
1858#undef OP_ASSIGN_WITH_CONCAT
1859#endif
1860
1861// equality and relational operators.
1862#define OP_REL_WITH_CONCAT(REL_OP) \
1863 template <int _AP_W1, typename _AP_T1, int _AP_W2, typename _AP_T2, \
1864 int _AP_W3, bool _AP_S3> \
1865 INLINE bool operator REL_OP( \
1866 const ap_int_base<_AP_W3, _AP_S3>& op1, \
1867 const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op2) { \
1868 /* convert ap_concat_ref to ap_int_base */ \
1869 return op1 REL_OP op2.get(); \
1870 } \
1871 template <int _AP_W1, typename _AP_T1, int _AP_W2, typename _AP_T2, \
1872 int _AP_W3, bool _AP_S3> \
1873 INLINE bool operator REL_OP( \
1874 const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op1, \
1875 const ap_int_base<_AP_W3, _AP_S3>& op2) { \
1876 /* convert ap_concat_ref to ap_int_base */ \
1877 return op1.get() REL_OP op2; \
1878 }
1879
1880OP_REL_WITH_CONCAT(==)
1881OP_REL_WITH_CONCAT(!=)
1882OP_REL_WITH_CONCAT(>)
1883OP_REL_WITH_CONCAT(>=)
1884OP_REL_WITH_CONCAT(<)
1885OP_REL_WITH_CONCAT(<=)
1886
1887#undef OP_REL_WITH_CONCAT
1888
1889#endif // ifndef __cplusplus
1890#endif // ifndef __AP_INT_BASE_H__
1891
1892// -*- cpp -*-
conditions objects which are tables indexed by raw detector id values
Sign Arbitrary Precision Type.
Definition ap_int.h:28
Unsigned Arbitrary Precision Type.
Definition ap_int.h:166