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