LDMX Software
ap_int_ref.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_REF_H__
18#define __AP_INT_REF_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
27#else
28
29#ifndef __SYNTHESIS__
30#include <iostream>
31#endif
32
33/* Concatination reference.
34 ----------------------------------------------------------------
35*/
36template <int _AP_W1, typename _AP_T1, int _AP_W2, typename _AP_T2>
37struct ap_concat_ref {
38 enum {
39 _AP_WR = _AP_W1 + _AP_W2,
40 };
41
42 _AP_T1& mbv1;
43 _AP_T2& mbv2;
44
46 : mbv1(ref.mbv1), mbv2(ref.mbv2) {}
47
48 INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2) : mbv1(bv1), mbv2(bv2) {}
49
50 template <int _AP_W3, bool _AP_S3>
51 INLINE ap_concat_ref& operator=(const ap_int_base<_AP_W3, _AP_S3>& val) {
53 int W_ref1 = mbv1.length();
54 int W_ref2 = mbv2.length();
56 Part1.V = _AP_ROOT_op_get_range(vval.V, W_ref2, W_ref1 + W_ref2 - 1);
57 mbv1.set(Part1);
59 Part2.V = _AP_ROOT_op_get_range(vval.V, 0, W_ref2 - 1);
60 mbv2.set(Part2);
61 return *this;
62 }
63
64 // assign op from hls supported C integral types.
65 // FIXME disabled to support legacy code directly assign from sc_signal<T>
66 // template <typename T>
67 // INLINE typename _ap_type::enable_if<_ap_type::is_integral<T>::value,
68 // ap_concat_ref&>::type
69 // operator=(T val) {
70 // ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val);
71 // return operator=(tmpVal);
72 //}
73#define ASSIGN_WITH_CTYPE(_Tp) \
74 INLINE ap_concat_ref& operator=(_Tp val) { \
75 ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); \
76 return operator=(tmpVal); \
77 }
78
79 ASSIGN_WITH_CTYPE(bool)
80 ASSIGN_WITH_CTYPE(char)
81 ASSIGN_WITH_CTYPE(signed char)
82 ASSIGN_WITH_CTYPE(unsigned char)
83 ASSIGN_WITH_CTYPE(short)
84 ASSIGN_WITH_CTYPE(unsigned short)
85 ASSIGN_WITH_CTYPE(int)
86 ASSIGN_WITH_CTYPE(unsigned int)
87 ASSIGN_WITH_CTYPE(long)
88 ASSIGN_WITH_CTYPE(unsigned long)
89 ASSIGN_WITH_CTYPE(ap_slong)
90 ASSIGN_WITH_CTYPE(ap_ulong)
91#if _AP_ENABLE_HALF_ == 1
92 ASSIGN_WITH_CTYPE(half)
93#endif
94 ASSIGN_WITH_CTYPE(float)
95 ASSIGN_WITH_CTYPE(double)
96
97#undef ASSIGN_WITH_CTYPE
98
99 // Be explicit to prevent it from being deleted, as field d_bv
100 // is of reference type.
101 INLINE ap_concat_ref& operator=(
104 return operator=(tmpVal);
105 }
106
107 template <int _AP_W3, typename _AP_T3, int _AP_W4, typename _AP_T4>
108 INLINE ap_concat_ref& operator=(
111 return operator=(tmpVal);
112 }
113
114 template <int _AP_W3, bool _AP_S3>
115 INLINE ap_concat_ref& operator=(const ap_bit_ref<_AP_W3, _AP_S3>& val) {
117 return operator=(tmpVal);
118 }
119 template <int _AP_W3, bool _AP_S3>
120 INLINE ap_concat_ref& operator=(const ap_range_ref<_AP_W3, _AP_S3>& val) {
122 return operator=(tmpVal);
123 }
124
125 template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
126 ap_o_mode _AP_O3, int _AP_N3>
127 INLINE ap_concat_ref& operator=(
129 return operator=((const ap_int_base<_AP_W3, false>)(val));
130 }
131
132 template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
133 ap_o_mode _AP_O3, int _AP_N3>
134 INLINE ap_concat_ref& operator=(
136 val) {
137 return operator=(val.to_ap_int_base());
138 }
139
140 template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
141 ap_o_mode _AP_O3, int _AP_N3>
142 INLINE ap_concat_ref& operator=(
144 return operator=((ap_ulong)(bool)(val));
145 }
146
147 INLINE operator ap_int_base<_AP_WR, false>() const { return get(); }
148
149 INLINE operator ap_ulong() const { return get().to_uint64(); }
150
151 template <int _AP_W3, bool _AP_S3>
152 INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
154 operator,(const ap_range_ref<_AP_W3, _AP_S3>&a2) {
155 return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
157 *this, const_cast<ap_range_ref<_AP_W3, _AP_S3>&>(a2));
158 }
159
160 template <int _AP_W3, bool _AP_S3>
161 INLINE
163 operator,(ap_int_base<_AP_W3, _AP_S3>&a2) {
164 return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
165 ap_int_base<_AP_W3, _AP_S3> >(*this, a2);
166 }
167
168 template <int _AP_W3, bool _AP_S3>
169 INLINE
171 operator,(volatile ap_int_base<_AP_W3, _AP_S3>&a2) {
172 return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
174 *this, const_cast<ap_int_base<_AP_W3, _AP_S3>&>(a2));
175 }
176
177 template <int _AP_W3, bool _AP_S3>
178 INLINE
180 operator,(const ap_int_base<_AP_W3, _AP_S3>&a2) {
181 return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
183 *this, const_cast<ap_int_base<_AP_W3, _AP_S3>&>(a2));
184 }
185
186 template <int _AP_W3, bool _AP_S3>
187 INLINE
189 operator,(const volatile ap_int_base<_AP_W3, _AP_S3>&a2) {
190 // FIXME op's life does not seem long enough
192 return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3,
194 *this, const_cast<ap_int_base<_AP_W3, _AP_S3>&>(op));
195 }
196
197 template <int _AP_W3, bool _AP_S3>
199 operator,(const ap_bit_ref<_AP_W3, _AP_S3>&a2) {
201 *this, const_cast<ap_bit_ref<_AP_W3, _AP_S3>&>(a2));
202 }
203
204 template <int _AP_W3, typename _AP_T3, int _AP_W4, typename _AP_T4>
205 INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4,
208 return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4,
210 *this, const_cast<ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4>&>(a2));
211 }
212
213 template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
214 ap_o_mode _AP_O3, int _AP_N3>
215 INLINE ap_concat_ref<
216 _AP_WR, ap_concat_ref, _AP_W3,
218 operator,(
220 return ap_concat_ref<
221 _AP_WR, ap_concat_ref, _AP_W3,
223 *this,
224 const_cast<
226 }
227
228 template <int _AP_W3, int _AP_I3, bool _AP_S3, ap_q_mode _AP_Q3,
229 ap_o_mode _AP_O3, int _AP_N3>
230 INLINE
231 ap_concat_ref<_AP_WR, ap_concat_ref, 1,
233 operator,(
235 return ap_concat_ref<
236 _AP_WR, ap_concat_ref, 1,
238 *this,
240 a2));
241 }
242
243 template <int _AP_W3, bool _AP_S3>
244 INLINE ap_int_base<AP_MAX(_AP_WR, _AP_W3), _AP_S3> operator&(
245 const ap_int_base<_AP_W3, _AP_S3>& a2) {
246 return get() & a2;
247 }
248
249 template <int _AP_W3, bool _AP_S3>
250 INLINE ap_int_base<AP_MAX(_AP_WR, _AP_W3), _AP_S3> operator|(
251 const ap_int_base<_AP_W3, _AP_S3>& a2) {
252 return get() | a2;
253 }
254
255 template <int _AP_W3, bool _AP_S3>
256 INLINE ap_int_base<AP_MAX(_AP_WR, _AP_W3), _AP_S3> operator^(
257 const ap_int_base<_AP_W3, _AP_S3>& a2) {
258 return get() ^ a2;
259 }
260
261#if 0
262 template<int Hi, int Lo>
263 INLINE ap_int_base<Hi-Lo+1, false> slice() {
265 return bv.slice<Hi,Lo>();
266 }
267#endif
268
269 INLINE ap_int_base<_AP_WR, false> get() const {
271 int W_ref1 = mbv1.length();
272 int W_ref2 = mbv2.length();
275 tmpVal.V = _AP_ROOT_op_set_range(tmpVal.V, 0, W_ref2 - 1, v2.V);
276 tmpVal.V =
277 _AP_ROOT_op_set_range(tmpVal.V, W_ref2, W_ref1 + W_ref2 - 1, v1.V);
278 return tmpVal;
279 }
280
281 template <int _AP_W3>
282 INLINE void set(const ap_int_base<_AP_W3, false>& val) {
284 int W_ref1 = mbv1.length();
285 int W_ref2 = mbv2.length();
287 tmpVal1.V = _AP_ROOT_op_get_range(vval.V, W_ref2, W_ref1 + W_ref2 - 1);
288 mbv1.set(tmpVal1);
290 tmpVal2.V = _AP_ROOT_op_get_range(vval.V, 0, W_ref2 - 1);
291 mbv2.set(tmpVal2);
292 }
293
294 INLINE int length() const { return mbv1.length() + mbv2.length(); }
295}; // struct ap_concat_ref
296
297/* Range (slice) reference.
298 ----------------------------------------------------------------
299*/
300template <int _AP_W, bool _AP_S>
301struct ap_range_ref {
302 // struct ssdm_int or its sim model.
303 // TODO make it possible to reference to ap_fixed_base/ap_fixed/ap_ufixed
304 // and then we can retire af_range_ref.
305 typedef ap_int_base<_AP_W, _AP_S> ref_type;
306 ref_type& d_bv;
307 int l_index;
308 int h_index;
309
310 public:
312 : d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {}
313
314 INLINE ap_range_ref(ref_type* bv, int h, int l)
315 : d_bv(*bv), l_index(l), h_index(h) {}
316
317 INLINE ap_range_ref(const ref_type* bv, int h, int l)
318 : d_bv(*const_cast<ref_type*>(bv)), l_index(l), h_index(h) {}
319
320 INLINE operator ap_int_base<_AP_W, false>() const {
322 ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index);
323 return ret;
324 }
325
326 INLINE operator ap_ulong() const { return to_uint64(); }
327
329 // @{
330
331 // FIXME disabled to work-around lagacy code assigning from sc_signal<T>,
332 // which dependes on implicit type conversion.
333 //
334 // /// assign from hls supported C integral types.
335 // template <typename T>
336 // INLINE typename _ap_type::enable_if<_ap_type::is_integral<T>::value,
337 // ap_range_ref&>::type
338 // operator=(T val) {
339 // ap_int_base<_AP_W, false> tmp(val);
340 // d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V);
341 // return *this;
342 // }
343#define ASSIGN_WITH_CTYPE(_Tp) \
344 INLINE ap_range_ref& operator=(_Tp val) { \
345 ap_int_base<_AP_W, false> tmp(val); \
346 d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); \
347 return *this; \
348 }
349
350 ASSIGN_WITH_CTYPE(bool)
351 ASSIGN_WITH_CTYPE(char)
352 ASSIGN_WITH_CTYPE(signed char)
353 ASSIGN_WITH_CTYPE(unsigned char)
354 ASSIGN_WITH_CTYPE(short)
355 ASSIGN_WITH_CTYPE(unsigned short)
356 ASSIGN_WITH_CTYPE(int)
357 ASSIGN_WITH_CTYPE(unsigned int)
358 ASSIGN_WITH_CTYPE(long)
359 ASSIGN_WITH_CTYPE(unsigned long)
360 ASSIGN_WITH_CTYPE(ap_slong)
361 ASSIGN_WITH_CTYPE(ap_ulong)
362#if _AP_ENABLE_HALF_ == 1
363 ASSIGN_WITH_CTYPE(half)
364#endif
365 ASSIGN_WITH_CTYPE(float)
366 ASSIGN_WITH_CTYPE(double)
367
368#undef ASSIGN_WITH_CTYPE
369
371 INLINE ap_range_ref& operator=(const char* val) {
372 const ap_int_base<_AP_W, false> tmp(val); // XXX figure out radix
373 d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V);
374 return *this;
375 }
376
378 template <int _AP_W2, bool _AP_S2>
379 INLINE ap_range_ref& operator=(const ap_int_base<_AP_W2, _AP_S2>& val) {
381 d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V);
382 return *this;
383 }
384
386 // XXX Be explicit to prevent it from being deleted, as field d_bv
387 // is of reference type.
388 INLINE ap_range_ref& operator=(const ap_range_ref& val) {
389 return operator=((const ap_int_base<_AP_W, false>)val);
390 }
391
393 template <int _AP_W2, bool _AP_S2>
394 INLINE ap_range_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) {
395 return operator=((const ap_int_base<_AP_W2, false>)val);
396 }
397
399 template <int _AP_W2, bool _AP_S2>
400 INLINE ap_range_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) {
401 return operator=((ap_ulong)(bool)(val));
402 }
403
405 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
406 ap_o_mode _AP_O2, int _AP_N2>
407 INLINE ap_range_ref& operator=(
409 val) {
410 return operator=(val.to_ap_int_base());
411 }
412
414 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
415 ap_o_mode _AP_O2, int _AP_N2>
416 INLINE ap_range_ref& operator=(
418 return operator=((const ap_int_base<_AP_W2, false>)val);
419 }
420
422 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
423 ap_o_mode _AP_O2, int _AP_N2>
424 INLINE ap_range_ref& operator=(
426 return operator=((ap_ulong)(bool)(val));
427 }
428
430 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
431 INLINE ap_range_ref& operator=(
433 return operator=((const ap_int_base<_AP_W2 + _AP_W3, false>)(val));
434 }
435 // @}
436
437 template <int _AP_W2, bool _AP_S2>
438 INLINE
440 operator,(const ap_range_ref<_AP_W2, _AP_S2>&a2) {
441 return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2,
443 *this, const_cast<ap_range_ref<_AP_W2, _AP_S2>&>(a2));
444 }
445
446 template <int _AP_W2, bool _AP_S2>
447 INLINE
449 operator,(ap_int_base<_AP_W2, _AP_S2>&a2) {
450 return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2,
451 ap_int_base<_AP_W2, _AP_S2> >(*this, a2);
452 }
453
454 INLINE
456 operator,(ap_int_base<_AP_W, _AP_S>& a2) {
457 return ap_concat_ref<_AP_W, ap_range_ref, _AP_W,
458 ap_int_base<_AP_W, _AP_S> >(*this, a2);
459 }
460
461 template <int _AP_W2, bool _AP_S2>
462 INLINE
464 operator,(volatile ap_int_base<_AP_W2, _AP_S2>&a2) {
465 return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2,
467 *this, const_cast<ap_int_base<_AP_W2, _AP_S2>&>(a2));
468 }
469
470 template <int _AP_W2, bool _AP_S2>
471 INLINE
473 operator,(const ap_int_base<_AP_W2, _AP_S2>&a2) {
474 return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2,
476 *this, const_cast<ap_int_base<_AP_W2, _AP_S2>&>(a2));
477 }
478
479 template <int _AP_W2, bool _AP_S2>
480 INLINE
482 operator,(const volatile ap_int_base<_AP_W2, _AP_S2>&a2) {
483 return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2,
485 *this, const_cast<ap_int_base<_AP_W2, _AP_S2>&>(a2));
486 }
487
488 template <int _AP_W2, bool _AP_S2>
490 operator,(const ap_bit_ref<_AP_W2, _AP_S2>&a2) {
492 *this, const_cast<ap_bit_ref<_AP_W2, _AP_S2>&>(a2));
493 }
494
495 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
496 INLINE ap_concat_ref<_AP_W, ap_range_ref, _AP_W2 + _AP_W3,
499 return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2 + _AP_W3,
501 *this, const_cast<ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>&>(a2));
502 }
503
504 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
505 ap_o_mode _AP_O2, int _AP_N2>
506 INLINE ap_concat_ref<
507 _AP_W, ap_range_ref, _AP_W2,
509 operator,(
511 return ap_concat_ref<
512 _AP_W, ap_range_ref, _AP_W2,
514 *this,
515 const_cast<
517 }
518
519 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
520 ap_o_mode _AP_O2, int _AP_N2>
521 INLINE
522 ap_concat_ref<_AP_W, ap_range_ref, 1,
524 operator,(
526 return ap_concat_ref<
527 _AP_W, ap_range_ref, 1,
529 *this,
531 a2));
532 }
533
534 template <int _AP_W2, bool _AP_S2>
535 INLINE bool operator==(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
536 ap_int_base<_AP_W, false> lop(*this);
538 return lop == hop;
539 }
540
541 template <int _AP_W2, bool _AP_S2>
542 INLINE bool operator!=(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
543 return !(operator==(op2));
544 }
545
546 template <int _AP_W2, bool _AP_S2>
547 INLINE bool operator<(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
548 ap_int_base<_AP_W, false> lop(*this);
550 return lop < hop;
551 }
552
553 template <int _AP_W2, bool _AP_S2>
554 INLINE bool operator<=(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
555 ap_int_base<_AP_W, false> lop(*this);
557 return lop <= hop;
558 }
559
560 template <int _AP_W2, bool _AP_S2>
561 INLINE bool operator>(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
562 return !(operator<=(op2));
563 }
564
565 template <int _AP_W2, bool _AP_S2>
566 INLINE bool operator>=(const ap_range_ref<_AP_W2, _AP_S2>& op2) {
567 return !(operator<(op2));
568 }
569
570 template <int _AP_W2, bool _AP_S2>
571 INLINE ap_range_ref<_AP_W, _AP_S>& operator|=(
572 const ap_range_ref<_AP_W2, _AP_S2>& op2) {
573 (this->d_bv).V |= (op2.d_bv).V;
574 return *this;
575 };
576
577 template <int _AP_W2, bool _AP_S2>
578 INLINE ap_range_ref<_AP_W, _AP_S>& operator|=(
579 const ap_int_base<_AP_W2, _AP_S2>& op2) {
580 (this->d_bv).V |= op2.V;
581 return *this;
582 };
583
584 template <int _AP_W2, bool _AP_S2>
585 INLINE ap_range_ref<_AP_W, _AP_S>& operator&=(
586 const ap_range_ref<_AP_W2, _AP_S2>& op2) {
587 (this->d_bv).V &= (op2.d_bv).V;
588 return *this;
589 };
590
591 template <int _AP_W2, bool _AP_S2>
592 INLINE ap_range_ref<_AP_W, _AP_S>& operator&=(
593 const ap_int_base<_AP_W2, _AP_S2>& op2) {
594 (this->d_bv).V &= op2.V;
595 return *this;
596 };
597
598 template <int _AP_W2, bool _AP_S2>
599 INLINE ap_range_ref<_AP_W, _AP_S>& operator^=(
600 const ap_range_ref<_AP_W2, _AP_S2>& op2) {
601 (this->d_bv).V ^= (op2.d_bv).V;
602 return *this;
603 };
604
605 template <int _AP_W2, bool _AP_S2>
606 INLINE ap_range_ref<_AP_W, _AP_S>& operator^=(
607 const ap_int_base<_AP_W2, _AP_S2>& op2) {
608 (this->d_bv).V ^= op2.V;
609 return *this;
610 };
611
612 INLINE ap_int_base<_AP_W, false> get() const {
614 ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index);
615 return ret;
616 }
617
618 template <int _AP_W2>
619 INLINE void set(const ap_int_base<_AP_W2, false>& val) {
620 d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V);
621 }
622
623 INLINE int length() const {
624 return h_index >= l_index ? h_index - l_index + 1 : l_index - h_index + 1;
625 }
626
627 INLINE int to_int() const {
628 return (int)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index));
629 }
630
631 INLINE unsigned to_uint() const {
632 return (unsigned)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index));
633 }
634
635 INLINE long to_long() const {
636 return (long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index));
637 }
638
639 INLINE unsigned long to_ulong() const {
640 return (unsigned long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index));
641 }
642
643 INLINE ap_slong to_int64() const {
644 return (ap_slong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index));
645 }
646
647 INLINE ap_ulong to_uint64() const {
648 return (ap_ulong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index));
649 }
650
651 INLINE bool and_reduce() const {
652 bool ret = true;
653 bool reverse = l_index > h_index;
654 unsigned low = reverse ? h_index : l_index;
655 unsigned high = reverse ? l_index : h_index;
656 for (unsigned i = low; i != high; ++i) {
657#ifdef __SYNTHESIS__
658#pragma HLS unroll
659#endif
660 ret &= _AP_ROOT_op_get_bit(d_bv.V, i);
661 }
662 return ret;
663 }
664
665 INLINE bool or_reduce() const {
666 bool ret = false;
667 bool reverse = l_index > h_index;
668 unsigned low = reverse ? h_index : l_index;
669 unsigned high = reverse ? l_index : h_index;
670 for (unsigned i = low; i != high; ++i) {
671#ifdef __SYNTHESIS__
672#pragma HLS unroll
673#endif
674 ret |= _AP_ROOT_op_get_bit(d_bv.V, i);
675 }
676 return ret;
677 }
678
679 INLINE bool xor_reduce() const {
680 bool ret = false;
681 bool reverse = l_index > h_index;
682 unsigned low = reverse ? h_index : l_index;
683 unsigned high = reverse ? l_index : h_index;
684 for (unsigned i = low; i != high; ++i) {
685#ifdef __SYNTHESIS__
686#pragma HLS unroll
687#endif
688 ret ^= _AP_ROOT_op_get_bit(d_bv.V, i);
689 }
690 return ret;
691 }
692#ifndef __SYNTHESIS__
693 std::string to_string(signed char radix = 2) const {
695 ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index);
696 return ret.to_string(radix);
697 }
698#else
699 // XXX HLS will delete this in synthesis
700 INLINE char* to_string(signed char radix = 2) const { return 0; }
701#endif
702}; // struct ap_range_ref
703
704// XXX apcc cannot handle global std::ios_base::Init() brought in by <iostream>
705#ifndef AP_AUTOCC
706#ifndef __SYNTHESIS__
707template <int _AP_W, bool _AP_S>
708INLINE std::ostream& operator<<(std::ostream& os,
710 std::ios_base::fmtflags ff = std::cout.flags();
711 if (ff & std::cout.hex) {
712 os << x.to_string(16); // don't print sign
713 } else if (ff & std::cout.oct) {
714 os << x.to_string(8); // don't print sign
715 } else {
716 os << x.to_string(10);
717 }
718 return os;
719}
720#endif // ifndef __SYNTHESIS__
721
722#ifndef __SYNTHESIS__
723template <int _AP_W, bool _AP_S>
724INLINE std::istream& operator>>(std::istream& in,
726 std::string str;
727 in >> str;
728 op = ap_int_base<_AP_W, _AP_S>(str.c_str());
729 return in;
730}
731#endif // ifndef __SYNTHESIS__
732#endif // ifndef AP_AUTOCC
733
734/* Bit reference.
735 ----------------------------------------------------------------
736*/
737template <int _AP_W, bool _AP_S>
738struct ap_bit_ref {
739 // struct ssdm_int or its sim model.
740 // TODO make it possible to reference to ap_fixed_base/ap_fixed/ap_ufixed
741 // and then we can retire af_bit_ref.
742 typedef ap_int_base<_AP_W, _AP_S> ref_type;
743 ref_type& d_bv;
744 int d_index;
745
746 public:
747 // copy ctor
748 INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref)
749 : d_bv(ref.d_bv), d_index(ref.d_index) {}
750
751 INLINE ap_bit_ref(ref_type* bv, int index = 0) : d_bv(*bv), d_index(index) {}
752
753 INLINE ap_bit_ref(const ref_type* bv, int index = 0)
754 : d_bv(*const_cast<ref_type*>(bv)), d_index(index) {}
755
756 INLINE operator bool() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); }
757 INLINE bool to_bool() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); }
758
759 // assign op from hls supported C integral types.
760 // FIXME disabled to support sc_signal<bool>.
761 // NOTE this used to be unsigned long long.
762 // template <typename T>
763 // INLINE typename _ap_type::enable_if<_ap_type::is_integral<T>::value,
764 // ap_bit_ref&>::type
765 // operator=(T val) {
766 // d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, val);
767 // return *this;
768 //}
769#define ASSIGN_WITH_CTYPE(_Tp) \
770 INLINE ap_bit_ref& operator=(_Tp val) { \
771 d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, val); \
772 return *this; \
773 }
774
775 ASSIGN_WITH_CTYPE(bool)
776 ASSIGN_WITH_CTYPE(char)
777 ASSIGN_WITH_CTYPE(signed char)
778 ASSIGN_WITH_CTYPE(unsigned char)
779 ASSIGN_WITH_CTYPE(short)
780 ASSIGN_WITH_CTYPE(unsigned short)
781 ASSIGN_WITH_CTYPE(int)
782 ASSIGN_WITH_CTYPE(unsigned int)
783 ASSIGN_WITH_CTYPE(long)
784 ASSIGN_WITH_CTYPE(unsigned long)
785 ASSIGN_WITH_CTYPE(ap_slong)
786 ASSIGN_WITH_CTYPE(ap_ulong)
787
788#undef ASSIGN_WITH_CTYPE
789
790#define ASSIGN_WITH_CTYPE_FP(_Tp) \
791 INLINE ap_bit_ref& operator=(_Tp val) { \
792 bool tmp_val = val; \
793 d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, tmp_val); \
794 return *this; \
795 }
796
797#if _AP_ENABLE_HALF_ == 1
798 ASSIGN_WITH_CTYPE_FP(half)
799#endif
800 ASSIGN_WITH_CTYPE_FP(float)
801 ASSIGN_WITH_CTYPE_FP(double)
802
803#undef ASSIGN_WITH_CTYPE_FP
804
805 template <int _AP_W2, bool _AP_S2>
806 INLINE ap_bit_ref& operator=(const ap_int_base<_AP_W2, _AP_S2>& val) {
807 return operator=((ap_ulong)(val.V != 0));
808 }
809
810 template <int _AP_W2, bool _AP_S2>
811 INLINE ap_bit_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) {
812 return operator=((ap_int_base<_AP_W2, false>)val);
813 }
814
815 // Be explicit to prevent it from being deleted, as field d_bv
816 // is of reference type.
817 INLINE ap_bit_ref& operator=(const ap_bit_ref& val) {
818 return operator=((ap_ulong)(bool)val);
819 }
820
821 template <int _AP_W2, bool _AP_S2>
822 INLINE ap_bit_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) {
823 return operator=((ap_ulong)(bool)val);
824 }
825
826 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
827 ap_o_mode _AP_O2, int _AP_N2>
828 INLINE ap_bit_ref& operator=(
830 return operator=((const ap_int_base<_AP_W2, false>)val);
831 }
832
833 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
834 ap_o_mode _AP_O2, int _AP_N2>
835 INLINE ap_bit_ref& operator=(
837 return operator=((ap_ulong)(bool)val);
838 }
839
840 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
841 INLINE ap_bit_ref& operator=(
843 return operator=((const ap_int_base<_AP_W2 + _AP_W3, false>)val);
844 }
845
846 template <int _AP_W2, bool _AP_S2>
848 operator,(ap_int_base<_AP_W2, _AP_S2>&a2) {
850 *this, a2);
851 }
852
853 template <int _AP_W2, bool _AP_S2>
855 operator,(volatile ap_int_base<_AP_W2, _AP_S2>&a2) {
857 *this, const_cast<ap_int_base<_AP_W2, _AP_S2>&>(a2));
858 }
859
860 template <int _AP_W2, bool _AP_S2>
862 operator,(const ap_int_base<_AP_W2, _AP_S2>&a2) {
865 *this, const_cast<ap_int_base<_AP_W2, _AP_S2>&>(op));
866 }
867
868 template <int _AP_W2, bool _AP_S2>
870 operator,(const volatile ap_int_base<_AP_W2, _AP_S2>&a2) {
873 *this, const_cast<ap_int_base<_AP_W2, _AP_S2>&>(op));
874 }
875
876 template <int _AP_W2, bool _AP_S2>
878 operator,(const ap_range_ref<_AP_W2, _AP_S2>&a2) {
880 *this, const_cast<ap_range_ref<_AP_W2, _AP_S2>&>(a2));
881 }
882
883 template <int _AP_W2, bool _AP_S2>
887 *this, const_cast<ap_bit_ref<_AP_W2, _AP_S2>&>(a2));
888 }
889
890 template <int _AP_W2, typename _AP_T2, int _AP_W3, typename _AP_T3>
891 INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2 + _AP_W3,
894 return ap_concat_ref<1, ap_bit_ref, _AP_W2 + _AP_W3,
896 *this, const_cast<ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>&>(a2));
897 }
898
899 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
900 ap_o_mode _AP_O2, int _AP_N2>
901 INLINE ap_concat_ref<
902 1, ap_bit_ref, _AP_W2,
904 operator,(
906 return ap_concat_ref<
907 1, ap_bit_ref, _AP_W2,
909 *this,
910 const_cast<
912 }
913
914 template <int _AP_W2, int _AP_I2, bool _AP_S2, ap_q_mode _AP_Q2,
915 ap_o_mode _AP_O2, int _AP_N2>
916 INLINE
919 operator,(
921 return ap_concat_ref<
922 1, ap_bit_ref, 1,
924 *this,
926 a2));
927 }
928
929 template <int _AP_W2, bool _AP_S2>
930 INLINE bool operator==(const ap_bit_ref<_AP_W2, _AP_S2>& op) {
931 return get() == op.get();
932 }
933
934 template <int _AP_W2, bool _AP_S2>
935 INLINE bool operator!=(const ap_bit_ref<_AP_W2, _AP_S2>& op) {
936 return get() != op.get();
937 }
938
939 INLINE bool get() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); }
940
941 INLINE bool get() { return _AP_ROOT_op_get_bit(d_bv.V, d_index); }
942
943 template <int _AP_W3>
944 INLINE void set(const ap_int_base<_AP_W3, false>& val) {
945 operator=(val);
946 }
947
948 INLINE bool operator~() const {
949 bool bit = _AP_ROOT_op_get_bit(d_bv.V, d_index);
950 return bit ? false : true;
951 }
952
953 INLINE int length() const { return 1; }
954
955#ifndef __SYNTHESIS__
956 std::string to_string() const { return get() ? "1" : "0"; }
957#else
958 // XXX HLS will delete this in synthesis
959 INLINE char* to_string() const { return 0; }
960#endif
961}; // struct ap_bit_ref
962
963/* ap_range_ref with int.
964 * ------------------------------------------------------------
965 */
966// equality and relational operators.
967#define REF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \
968 template <int _AP_W, bool _AP_S> \
969 INLINE bool operator REL_OP(const ap_range_ref<_AP_W, _AP_S>& op, \
970 C_TYPE op2) { \
971 return ap_int_base<_AP_W, false>(op) \
972 REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \
973 } \
974 template <int _AP_W, bool _AP_S> \
975 INLINE bool operator REL_OP(const ap_bit_ref<_AP_W, _AP_S>& op, \
976 C_TYPE op2) { \
977 return bool(op) REL_OP op2; \
978 } \
979 template <int _AP_W, bool _AP_S> \
980 INLINE bool operator REL_OP(C_TYPE op2, \
981 const ap_bit_ref<_AP_W, _AP_S>& op) { \
982 return op2 REL_OP bool(op); \
983 } \
984 template <int _AP_W, typename _AP_T, int _AP_W1, typename _AP_T1> \
985 INLINE bool operator REL_OP( \
986 const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1>& op, C_TYPE op2) { \
987 return ap_int_base<_AP_W + _AP_W1, false>(op) \
988 REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \
989 }
990
991// Make the line shorter than 5000 chars
992#define REF_REL_WITH_INT_1(C_TYPE, _AP_WI, _AP_SI) \
993 REF_REL_OP_WITH_INT(>, C_TYPE, _AP_WI, _AP_SI) \
994 REF_REL_OP_WITH_INT(<, C_TYPE, _AP_WI, _AP_SI) \
995 REF_REL_OP_WITH_INT(>=, C_TYPE, _AP_WI, _AP_SI) \
996 REF_REL_OP_WITH_INT(<=, C_TYPE, _AP_WI, _AP_SI)
997
998REF_REL_WITH_INT_1(bool, 1, false)
999REF_REL_WITH_INT_1(char, 8, CHAR_IS_SIGNED)
1000REF_REL_WITH_INT_1(signed char, 8, true)
1001REF_REL_WITH_INT_1(unsigned char, 8, false)
1002REF_REL_WITH_INT_1(short, _AP_SIZE_short, true)
1003REF_REL_WITH_INT_1(unsigned short, _AP_SIZE_short, false)
1004REF_REL_WITH_INT_1(int, _AP_SIZE_int, true)
1005REF_REL_WITH_INT_1(unsigned int, _AP_SIZE_int, false)
1006REF_REL_WITH_INT_1(long, _AP_SIZE_long, true)
1007REF_REL_WITH_INT_1(unsigned long, _AP_SIZE_long, false)
1008REF_REL_WITH_INT_1(ap_slong, _AP_SIZE_ap_slong, true)
1009REF_REL_WITH_INT_1(ap_ulong, _AP_SIZE_ap_slong, false)
1010
1011// Make the line shorter than 5000 chars
1012#define REF_REL_WITH_INT_2(C_TYPE, _AP_WI, _AP_SI) \
1013 REF_REL_OP_WITH_INT(==, C_TYPE, _AP_WI, _AP_SI) \
1014 REF_REL_OP_WITH_INT(!=, C_TYPE, _AP_WI, _AP_SI)
1015
1016REF_REL_WITH_INT_2(bool, 1, false)
1017REF_REL_WITH_INT_2(char, 8, CHAR_IS_SIGNED)
1018REF_REL_WITH_INT_2(signed char, 8, true)
1019REF_REL_WITH_INT_2(unsigned char, 8, false)
1020REF_REL_WITH_INT_2(short, _AP_SIZE_short, true)
1021REF_REL_WITH_INT_2(unsigned short, _AP_SIZE_short, false)
1022REF_REL_WITH_INT_2(int, _AP_SIZE_int, true)
1023REF_REL_WITH_INT_2(unsigned int, _AP_SIZE_int, false)
1024REF_REL_WITH_INT_2(long, _AP_SIZE_long, true)
1025REF_REL_WITH_INT_2(unsigned long, _AP_SIZE_long, false)
1026REF_REL_WITH_INT_2(ap_slong, _AP_SIZE_ap_slong, true)
1027REF_REL_WITH_INT_2(ap_ulong, _AP_SIZE_ap_slong, false)
1028
1029#undef REF_REL_OP_WITH_INT
1030#undef REF_REL_WITH_INT_1
1031#undef REF_REL_WITH_INT_2
1032
1033#define REF_BIN_OP_WITH_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \
1034 template <int _AP_W, bool _AP_S> \
1035 INLINE typename ap_int_base<_AP_W, false>::template RType<_AP_W2, \
1036 _AP_S2>::RTYPE \
1037 operator BIN_OP(const ap_range_ref<_AP_W, _AP_S>& op, C_TYPE op2) { \
1038 return ap_int_base<_AP_W, false>(op) \
1039 BIN_OP ap_int_base<_AP_W2, _AP_S2>(op2); \
1040 } \
1041 template <int _AP_W, bool _AP_S> \
1042 INLINE typename ap_int_base<_AP_W2, _AP_S2>::template RType<_AP_W, \
1043 false>::RTYPE \
1044 operator BIN_OP(C_TYPE op2, const ap_range_ref<_AP_W, _AP_S>& op) { \
1045 return ap_int_base<_AP_W2, _AP_S2>(op2) \
1046 BIN_OP ap_int_base<_AP_W, false>(op); \
1047 }
1048
1049// arithmetic operators.
1050#define REF_BIN_OP_WITH_INT_ARITH(C_TYPE, _AP_W2, _AP_S2) \
1051 REF_BIN_OP_WITH_INT(+, plus, C_TYPE, (_AP_W2), (_AP_S2)) \
1052 REF_BIN_OP_WITH_INT(-, minus, C_TYPE, (_AP_W2), (_AP_S2)) \
1053 REF_BIN_OP_WITH_INT(*, mult, C_TYPE, (_AP_W2), (_AP_S2)) \
1054 REF_BIN_OP_WITH_INT(/, div, C_TYPE, (_AP_W2), (_AP_S2)) \
1055 REF_BIN_OP_WITH_INT(%, mod, C_TYPE, (_AP_W2), (_AP_S2))
1056
1057REF_BIN_OP_WITH_INT_ARITH(bool, 1, false)
1058REF_BIN_OP_WITH_INT_ARITH(char, 8, CHAR_IS_SIGNED)
1059REF_BIN_OP_WITH_INT_ARITH(signed char, 8, true)
1060REF_BIN_OP_WITH_INT_ARITH(unsigned char, 8, false)
1061REF_BIN_OP_WITH_INT_ARITH(short, _AP_SIZE_short, true)
1062REF_BIN_OP_WITH_INT_ARITH(unsigned short, _AP_SIZE_short, false)
1063REF_BIN_OP_WITH_INT_ARITH(int, _AP_SIZE_int, true)
1064REF_BIN_OP_WITH_INT_ARITH(unsigned int, _AP_SIZE_int, false)
1065REF_BIN_OP_WITH_INT_ARITH(long, _AP_SIZE_long, true)
1066REF_BIN_OP_WITH_INT_ARITH(unsigned long, _AP_SIZE_long, false)
1067REF_BIN_OP_WITH_INT_ARITH(ap_slong, _AP_SIZE_ap_slong, true)
1068REF_BIN_OP_WITH_INT_ARITH(ap_ulong, _AP_SIZE_ap_slong, false)
1069
1070#undef REF_BIN_OP_WITH_INT_ARITH
1071
1072// bitwise and shift operators
1073#define REF_BIN_OP_WITH_INT_BITS(C_TYPE, _AP_W2, _AP_S2) \
1074 REF_BIN_OP_WITH_INT(&, logic, C_TYPE, (_AP_W2), (_AP_S2)) \
1075 REF_BIN_OP_WITH_INT(|, logic, C_TYPE, (_AP_W2), (_AP_S2)) \
1076 REF_BIN_OP_WITH_INT(^, logic, C_TYPE, (_AP_W2), (_AP_S2)) \
1077 REF_BIN_OP_WITH_INT(>>, arg1, C_TYPE, (_AP_W2), (_AP_S2)) \
1078 REF_BIN_OP_WITH_INT(<<, arg1, C_TYPE, (_AP_W2), (_AP_S2))
1079
1080REF_BIN_OP_WITH_INT_BITS(bool, 1, false)
1081REF_BIN_OP_WITH_INT_BITS(char, 8, CHAR_IS_SIGNED)
1082REF_BIN_OP_WITH_INT_BITS(signed char, 8, true)
1083REF_BIN_OP_WITH_INT_BITS(unsigned char, 8, false)
1084REF_BIN_OP_WITH_INT_BITS(short, _AP_SIZE_short, true)
1085REF_BIN_OP_WITH_INT_BITS(unsigned short, _AP_SIZE_short, false)
1086REF_BIN_OP_WITH_INT_BITS(int, _AP_SIZE_int, true)
1087REF_BIN_OP_WITH_INT_BITS(unsigned int, _AP_SIZE_int, false)
1088REF_BIN_OP_WITH_INT_BITS(long, _AP_SIZE_long, true)
1089REF_BIN_OP_WITH_INT_BITS(unsigned long, _AP_SIZE_long, false)
1090REF_BIN_OP_WITH_INT_BITS(ap_slong, _AP_SIZE_ap_slong, true)
1091REF_BIN_OP_WITH_INT_BITS(ap_ulong, _AP_SIZE_ap_slong, false)
1092
1093#undef REF_BIN_OP_WITH_INT_BITS
1094
1095/* ap_range_ref with ap_range_ref
1096 * ------------------------------------------------------------
1097 */
1098#define REF_BIN_OP(BIN_OP, RTYPE) \
1099 template <int _AP_W, bool _AP_S, int _AP_W2, bool _AP_S2> \
1100 INLINE \
1101 typename ap_int_base<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \
1102 operator BIN_OP(const ap_range_ref<_AP_W, _AP_S>& lhs, \
1103 const ap_range_ref<_AP_W2, _AP_S2>& rhs) { \
1104 return (lhs.operator ap_int_base<_AP_W, false>())BIN_OP( \
1105 rhs.operator ap_int_base<_AP_W2, false>()); \
1106 }
1107
1108REF_BIN_OP(+, plus)
1109REF_BIN_OP(-, minus)
1110REF_BIN_OP(*, mult)
1111REF_BIN_OP(/, div)
1112REF_BIN_OP(%, mod)
1113REF_BIN_OP(&, logic)
1114REF_BIN_OP(|, logic)
1115REF_BIN_OP(^, logic)
1116REF_BIN_OP(>>, arg1)
1117REF_BIN_OP(<<, arg1)
1118
1119/* ap_concat_ref with ap_concat_ref.
1120 * ------------------------------------------------------------
1121 */
1122
1123//************************************************************************
1124// Implement
1125// ap_int_base<M+N> = ap_concat_ref<M> OP ap_concat_ref<N>
1126// for operators +, -, *, /, %, >>, <<, &, |, ^
1127// Without these operators the operands are converted to int64 and
1128// larger results lose informations (higher order bits).
1129//
1130// operand OP
1131// / |
1132// left-concat right-concat
1133// / | / |
1134// <LW1,LT1> <LW2,LT2> <RW1,RT1> <RW2,RT2>
1135//
1136// _AP_LW1, _AP_LT1 (width and type of left-concat's left side)
1137// _AP_LW2, _AP_LT2 (width and type of left-concat's right side)
1138// Similarly for RHS of operand OP: _AP_RW1, AP_RW2, _AP_RT1, _AP_RT2
1139//
1140// In Verilog 2001 result of concatenation is always unsigned even
1141// when both sides are signed.
1142//************************************************************************
1143
1144#undef SYN_CONCAT_REF_BIN_OP
1145
1146#define SYN_CONCAT_REF_BIN_OP(BIN_OP, RTYPE) \
1147 template <int _AP_LW1, typename _AP_LT1, int _AP_LW2, typename _AP_LT2, \
1148 int _AP_RW1, typename _AP_RT1, int _AP_RW2, typename _AP_RT2> \
1149 INLINE typename ap_int_base<_AP_LW1 + _AP_LW2, false>::template RType< \
1150 _AP_RW1 + _AP_RW2, false>::RTYPE \
1151 operator BIN_OP( \
1152 const ap_concat_ref<_AP_LW1, _AP_LT1, _AP_LW2, _AP_LT2>& lhs, \
1153 const ap_concat_ref<_AP_RW1, _AP_RT1, _AP_RW2, _AP_RT2>& rhs) { \
1154 return lhs.get() BIN_OP rhs.get(); \
1155 }
1156
1157SYN_CONCAT_REF_BIN_OP(+, plus)
1158SYN_CONCAT_REF_BIN_OP(-, minus)
1159SYN_CONCAT_REF_BIN_OP(*, mult)
1160SYN_CONCAT_REF_BIN_OP(/, div)
1161SYN_CONCAT_REF_BIN_OP(%, mod)
1162SYN_CONCAT_REF_BIN_OP(&, logic)
1163SYN_CONCAT_REF_BIN_OP(|, logic)
1164SYN_CONCAT_REF_BIN_OP(^, logic)
1165SYN_CONCAT_REF_BIN_OP(>>, arg1)
1166SYN_CONCAT_REF_BIN_OP(<<, arg1)
1167
1168#undef SYN_CONCAT_REF_BIN_OP
1169
1170#define CONCAT_OP_WITH_INT(C_TYPE, _AP_WI, _AP_SI) \
1171 template <int _AP_W, bool _AP_S> \
1172 INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \
1173 const ap_int_base<_AP_W, _AP_S>&op1, C_TYPE op2) { \
1174 ap_int_base<_AP_WI + _AP_W, false> val(op2); \
1175 ap_int_base<_AP_WI + _AP_W, false> ret(op1); \
1176 ret <<= _AP_WI; \
1177 if (_AP_SI) { \
1178 val <<= _AP_W; \
1179 val >>= _AP_W; \
1180 } \
1181 ret |= val; \
1182 return ret; \
1183 } \
1184 template <int _AP_W, bool _AP_S> \
1185 INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \
1186 C_TYPE op1, const ap_int_base<_AP_W, _AP_S>&op2) { \
1187 ap_int_base<_AP_WI + _AP_W, false> val(op1); \
1188 ap_int_base<_AP_WI + _AP_W, false> ret(op2); \
1189 if (_AP_S) { \
1190 ret <<= _AP_WI; \
1191 ret >>= _AP_WI; \
1192 } \
1193 ret |= val << _AP_W; \
1194 return ret; \
1195 } \
1196 template <int _AP_W, bool _AP_S> \
1197 INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \
1198 const ap_range_ref<_AP_W, _AP_S>&op1, C_TYPE op2) { \
1199 ap_int_base<_AP_WI + _AP_W, false> val(op2); \
1200 ap_int_base<_AP_WI + _AP_W, false> ret(op1); \
1201 ret <<= _AP_WI; \
1202 if (_AP_SI) { \
1203 val <<= _AP_W; \
1204 val >>= _AP_W; \
1205 } \
1206 ret |= val; \
1207 return ret; \
1208 } \
1209 template <int _AP_W, bool _AP_S> \
1210 INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \
1211 C_TYPE op1, const ap_range_ref<_AP_W, _AP_S>&op2) { \
1212 ap_int_base<_AP_WI + _AP_W, false> val(op1); \
1213 ap_int_base<_AP_WI + _AP_W, false> ret(op2); \
1214 int len = op2.length(); \
1215 val <<= len; \
1216 ret |= val; \
1217 return ret; \
1218 } \
1219 template <int _AP_W, bool _AP_S> \
1220 INLINE ap_int_base<_AP_WI + 1, false> operator,( \
1221 const ap_bit_ref<_AP_W, _AP_S>&op1, C_TYPE op2) { \
1222 ap_int_base<_AP_WI + 1, false> val(op2); \
1223 val[_AP_WI] = op1; \
1224 return val; \
1225 } \
1226 template <int _AP_W, bool _AP_S> \
1227 INLINE ap_int_base<_AP_WI + 1, false> operator,( \
1228 C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S>&op2) { \
1229 ap_int_base<_AP_WI + 1, false> val(op1); \
1230 val <<= 1; \
1231 val[0] = op2; \
1232 return val; \
1233 } \
1234 template <int _AP_W, typename _AP_T, int _AP_W2, typename _AP_T2> \
1235 INLINE ap_int_base<_AP_W + _AP_W2 + _AP_WI, false> operator,( \
1236 const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2>&op1, C_TYPE op2) { \
1237 ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2); \
1238 ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1); \
1239 if (_AP_SI) { \
1240 val <<= _AP_W + _AP_W2; \
1241 val >>= _AP_W + _AP_W2; \
1242 } \
1243 ret <<= _AP_WI; \
1244 ret |= val; \
1245 return ret; \
1246 } \
1247 template <int _AP_W, typename _AP_T, int _AP_W2, typename _AP_T2> \
1248 INLINE ap_int_base<_AP_W + _AP_W2 + _AP_WI, false> operator,( \
1249 C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2>&op2) { \
1250 ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1); \
1251 ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2); \
1252 int len = op2.length(); \
1253 val <<= len; \
1254 ret |= val; \
1255 return ret; \
1256 } \
1257 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
1258 ap_o_mode _AP_O, int _AP_N> \
1259 INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \
1260 const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>&op1, \
1261 C_TYPE op2) { \
1262 ap_int_base<_AP_WI + _AP_W, false> val(op2); \
1263 ap_int_base<_AP_WI + _AP_W, false> ret(op1); \
1264 if (_AP_SI) { \
1265 val <<= _AP_W; \
1266 val >>= _AP_W; \
1267 } \
1268 ret <<= _AP_WI; \
1269 ret |= val; \
1270 return ret; \
1271 } \
1272 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
1273 ap_o_mode _AP_O, int _AP_N> \
1274 INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \
1275 C_TYPE op1, \
1276 const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>&op2) { \
1277 ap_int_base<_AP_WI + _AP_W, false> val(op1); \
1278 ap_int_base<_AP_WI + _AP_W, false> ret(op2); \
1279 int len = op2.length(); \
1280 val <<= len; \
1281 ret |= val; \
1282 return ret; \
1283 } \
1284 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
1285 ap_o_mode _AP_O, int _AP_N> \
1286 INLINE ap_int_base<1 + _AP_WI, false> operator,( \
1287 const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>&op1, \
1288 C_TYPE op2) { \
1289 ap_int_base<_AP_WI + 1, _AP_SI> val(op2); \
1290 val[_AP_WI] = op1; \
1291 return val; \
1292 } \
1293 template <int _AP_W, int _AP_I, bool _AP_S, ap_q_mode _AP_Q, \
1294 ap_o_mode _AP_O, int _AP_N> \
1295 INLINE ap_int_base<1 + _AP_WI, false> operator,( \
1296 C_TYPE op1, \
1297 const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>&op2) { \
1298 ap_int_base<_AP_WI + 1, _AP_SI> val(op1); \
1299 val <<= 1; \
1300 val[0] = op2; \
1301 return val; \
1302 }
1303
1304CONCAT_OP_WITH_INT(bool, 1, false)
1305CONCAT_OP_WITH_INT(char, 8, CHAR_IS_SIGNED)
1306CONCAT_OP_WITH_INT(signed char, 8, true)
1307CONCAT_OP_WITH_INT(unsigned char, 8, false)
1308CONCAT_OP_WITH_INT(short, _AP_SIZE_short, true)
1309CONCAT_OP_WITH_INT(unsigned short, _AP_SIZE_short, false)
1310CONCAT_OP_WITH_INT(int, _AP_SIZE_int, true)
1311CONCAT_OP_WITH_INT(unsigned int, _AP_SIZE_int, false)
1312CONCAT_OP_WITH_INT(long, _AP_SIZE_long, true)
1313CONCAT_OP_WITH_INT(unsigned long, _AP_SIZE_long, false)
1314CONCAT_OP_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true)
1315CONCAT_OP_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false)
1316
1317#undef CONCAT_OP_WITH_INT
1318
1319#define CONCAT_SHIFT_WITH_INT(C_TYPE, OP) \
1320 template <int _AP_W, typename _AP_T, int _AP_W1, typename _AP_T1> \
1321 INLINE ap_uint<_AP_W + _AP_W1> operator OP( \
1322 const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \
1323 return ap_uint<_AP_W + _AP_W1>(lhs).get() OP int(rhs); \
1324 }
1325
1326// FIXME int(rhs) may loose precision.
1327
1328CONCAT_SHIFT_WITH_INT(int, <<)
1329CONCAT_SHIFT_WITH_INT(unsigned int, <<)
1330CONCAT_SHIFT_WITH_INT(long, <<)
1331CONCAT_SHIFT_WITH_INT(unsigned long, <<)
1332CONCAT_SHIFT_WITH_INT(ap_slong, <<)
1333CONCAT_SHIFT_WITH_INT(ap_ulong, <<)
1334
1335CONCAT_SHIFT_WITH_INT(int, >>)
1336CONCAT_SHIFT_WITH_INT(unsigned int, >>)
1337CONCAT_SHIFT_WITH_INT(long, >>)
1338CONCAT_SHIFT_WITH_INT(unsigned long, >>)
1339CONCAT_SHIFT_WITH_INT(ap_slong, >>)
1340CONCAT_SHIFT_WITH_INT(ap_ulong, >>)
1341
1342#endif // ifndef __cplusplus
1343#endif // ifndef __AP_INT_REF_H__
1344
1345// -*- cpp -*-