LDMX Software
ap_common.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_COMMON_H__
18#define __AP_COMMON_H__
19
20// ----------------------------------------------------------------------
21
22// Forward declaration of all AP types.
23#include "ap_decl.h"
24
25#ifdef __SYNTHESIS__
26#error "The open-source version of AP types does not support synthesis."
27#endif // ifdef __SYNTHESIS__
28#define _AP_ENABLE_HALF_ 0
29
30#if _AP_ENABLE_HALF_ == 1
31// Before ap_private definition.
32#ifdef __SYNTHESIS__
33#define _HLS_HALF_DEFINED_
34typedef __fp16 half;
35#else
36class half;
37#endif // __SYNTHESIS__
38#endif // _AP_ENABLE_HALF_
39
40// ----------------------------------------------------------------------
41
42// Macro functions
43#define AP_MAX(a, b) ((a) > (b) ? (a) : (b))
44#define AP_MIN(a, b) ((a) < (b) ? (a) : (b))
45#define AP_ABS(a) ((a) >= 0 ? (a) : -(a))
46
47#ifndef AP_ASSERT
48#ifndef __SYNTHESIS__
49#include <assert.h>
50#define AP_ASSERT(cond, msg) assert((cond) && (msg))
51#else
52#define AP_ASSERT(cond, msg)
53#endif // ifndef __SYNTHESIS__
54#endif // ifndef AP_ASSERT
55
56#ifndef __SYNTHESIS__
57// for fprintf messages.
58#include <stdio.h>
59// for exit on error.
60#include <stdlib.h>
61#endif
62
63// same disable condition as assert.
64#if !defined(__SYNTHESIS__) && !defined(NDEBUG)
65
66#define _AP_DEBUG(cond, ...) \
67 do { \
68 if ((cond)) { \
69 fprintf(stderr, "DEBUG: " __VA_ARGS__); \
70 fprintf(stderr, "\n"); \
71 } \
72 } while (0)
73#define _AP_WARNING(cond, ...) \
74 do { \
75 if ((cond)) { \
76 fprintf(stderr, "WARNING: " __VA_ARGS__); \
77 fprintf(stderr, "\n"); \
78 } \
79 } while (0)
80#define _AP_ERROR(cond, ...) \
81 do { \
82 if ((cond)) { \
83 fprintf(stderr, "ERROR: " __VA_ARGS__); \
84 fprintf(stderr, "\n"); \
85 abort(); \
86 } \
87 } while (0)
88
89#else // if !defined(__SYNTHESIS__) && !defined(NDEBUG)
90
91#define __AP_VOID_CAST static_cast<void>
92#define _AP_DEBUG(cond, ...) (__AP_VOID_CAST(0))
93#define _AP_WARNING(cond, ...) (__AP_VOID_CAST(0))
94#define _AP_ERROR(cond, ...) (__AP_VOID_CAST(0))
95
96#endif // if !defined(__SYNTHESIS__) && !defined(NDEBUG) else
97
98// ----------------------------------------------------------------------
99
100// Attribute only for synthesis
101#ifdef __SYNTHESIS__
102#define INLINE inline __attribute__((always_inline))
103//#define INLINE inline __attribute__((noinline))
104#else
105#define INLINE inline
106#endif
107
108#define AP_WEAK
109// __attribute__((weak))
110
111#ifndef AP_INT_MAX_W
112#define AP_INT_MAX_W 1024
113#endif
114
115#define BIT_WIDTH_UPPER_LIMIT (1 << 15)
116#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT
117#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value"
118#endif
119
120#define MAX_MODE(BITS) ((BITS + 1023) / 1024)
121
122// ----------------------------------------------------------------------
123
124// XXX apcc cannot handle global std::ios_base::Init() brought in by <iostream>
125#ifndef AP_AUTOCC
126#ifndef __SYNTHESIS__
127// for overload operator<<
128#include <iostream>
129#endif
130#endif // ifndef AP_AUTOCC
131
132#ifndef __SYNTHESIS__
133// for string format.
134#include <sstream>
135// for string.
136#include <string>
137#endif
138
139// for detecting if char is signed.
140enum { CHAR_IS_SIGNED = (char)-1 < 0 };
141
142// TODO we have similar traits in x_hls_utils.h, should consider unify.
143namespace _ap_type {
144template <typename _Tp>
145struct is_signed {
146 static const bool value = _Tp(-1) < _Tp(1);
147};
148
149template <typename _Tp>
151 static const bool value = false;
152};
153#define DEF_IS_INTEGRAL(CTYPE) \
154 template <> \
155 struct is_integral<CTYPE> { \
156 static const bool value = true; \
157 };
158DEF_IS_INTEGRAL(bool)
159DEF_IS_INTEGRAL(char)
160DEF_IS_INTEGRAL(signed char)
161DEF_IS_INTEGRAL(unsigned char)
162DEF_IS_INTEGRAL(short)
163DEF_IS_INTEGRAL(unsigned short)
164DEF_IS_INTEGRAL(int)
165DEF_IS_INTEGRAL(unsigned int)
166DEF_IS_INTEGRAL(long)
167DEF_IS_INTEGRAL(unsigned long)
168DEF_IS_INTEGRAL(ap_slong)
169DEF_IS_INTEGRAL(ap_ulong)
170#undef DEF_IS_INTEGRAL
171
172template <bool, typename _Tp = void>
173struct enable_if {};
174// partial specialization for true
175template <typename _Tp>
176struct enable_if<true, _Tp> {
177 typedef _Tp type;
178};
179
180template <typename _Tp>
182 typedef _Tp type;
183};
184
185template <typename _Tp>
186struct remove_const<_Tp const> {
187 typedef _Tp type;
188};
189} // namespace _ap_type
190
191// ----------------------------------------------------------------------
192
193// Define ssdm_int and _ssdm_op.
194// XXX deleted in open-source version
195
196#ifndef NON_C99STRING
197#define _AP_C99 true
198#else
199#define _AP_C99 false
200#endif
201
202static inline unsigned char guess_radix(const char* s) {
203 unsigned char rd = 10;
204 const char* p = s;
205 // skip neg sign if it exists
206 if (p[0] == '-' || p[0] == '+') ++p;
207 // guess based on following two bits.
208 if (p[0] == '0') {
209 if (p[1] == 'b' || p[1] == 'B') {
210 rd = 2;
211 } else if (p[1] == 'o' || p[1] == 'O') {
212 rd = 8;
213 } else if (p[1] == 'x' || p[1] == 'X') {
214 rd = 16;
215 } else if (p[1] == 'd' || p[1] == 'D') {
216 rd = 10;
217 }
218 }
219 return rd;
220}
221
222// ----------------------------------------------------------------------
223
224// Basic integral struct upon which ap_int and ap_fixed are defined.
225#ifdef __SYNTHESIS__
226// Use ssdm_int, a compiler dependent, attribute constrained integeral type as
227// basic data type.
228#define _AP_ROOT_TYPE ssdm_int
229// Basic ops.
230#define _AP_ROOT_op_concat(Ret, X, Y) _ssdm_op_concat(Ret, X, Y)
231#define _AP_ROOT_op_get_bit(Val, Bit) _ssdm_op_get_bit(Val, Bit)
232#define _AP_ROOT_op_set_bit(Val, Bit, Repl) _ssdm_op_set_bit(Val, Bit, Repl)
233#define _AP_ROOT_op_get_range(Val, Lo, Hi) _ssdm_op_get_range(Val, Lo, Hi)
234#define _AP_ROOT_op_set_range(Val, Lo, Hi, Repl) \
235 _ssdm_op_set_range(Val, Lo, Hi, Repl)
236#define _AP_ROOT_op_reduce(Op, Val) _ssdm_op_reduce(Op, Val)
237#else // ifdef __SYNTHESIS__
238// Use ap_private for compiler-independent basic data type
239template <int _AP_W, bool _AP_S, bool _AP_C = _AP_W <= 64>
240class ap_private;
242template <int _AP_W, bool _AP_S>
243struct ssdm_int_sim {
245 ap_private<_AP_W, _AP_S> V;
246 ssdm_int_sim() {}
247};
248#define _AP_ROOT_TYPE ssdm_int_sim
249// private's ref uses _AP_ROOT_TYPE.
250#include "ap_private.h"
251// XXX The C-sim model cannot use GCC-extension
252// Basic ops. Ret and Val are ap_private.
253template <typename _Tp1, typename _Tp2, typename _Tp3>
254inline _Tp1 _AP_ROOT_op_concat(const _Tp1& Ret, const _Tp2& X, const _Tp3& Y) {
255 _Tp1 r = (X).operator,(Y);
256 return r;
257}
258#define _AP_ROOT_op_get_bit(Val, Bit) (Val).get_bit((Bit))
259template <typename _Tp1, typename _Tp2, typename _Tp3>
260inline _Tp1& _AP_ROOT_op_set_bit(_Tp1& Val, const _Tp2& Bit, const _Tp3& Repl) {
261 (Val).set_bit((Bit), (Repl));
262 return Val;
263}
264// notice the order of high and low index is different in ssdm call and
265// ap_private.range()...
266#define _AP_ROOT_op_get_range(Val, Lo, Hi) (Val).range((Hi), (Lo))
267template <typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
268inline _Tp1& _AP_ROOT_op_set_range(_Tp1& Val, const _Tp2& Lo, const _Tp3& Hi,
269 const _Tp4& Repl) {
270 (Val).range((Hi), (Lo)) = Repl;
271 return (Val);
272}
273#define _AP_ROOT_op_and_reduce(Val) (Val).and_reduce()
274#define _AP_ROOT_op_nand_reduce(Val) (Val).nand_reduce()
275#define _AP_ROOT_op_or_reduce(Val) (Val).or_reduce()
276#define _AP_ROOT_op_xor_reduce(Val) (Val).xor_reduce()
277// ## is the concatenation in preprocessor:
278#define _AP_ROOT_op_reduce(Op, Val) _AP_ROOT_op_##Op##_reduce(Val)
279#endif // ifdef __SYNTHESIS__ else
280
281// ----------------------------------------------------------------------
282
283// Constants for half, single, double pricision floating points
284#define HALF_MAN 10
285#define FLOAT_MAN 23
286#define DOUBLE_MAN 52
287
288#define HALF_EXP 5
289#define FLOAT_EXP 8
290#define DOUBLE_EXP 11
291
292#define BIAS(e) ((1L << (e - 1L)) - 1L)
293#define HALF_BIAS BIAS(HALF_EXP)
294#define FLOAT_BIAS BIAS(FLOAT_EXP)
295#define DOUBLE_BIAS BIAS(DOUBLE_EXP)
296
297#define APFX_IEEE_DOUBLE_E_MAX DOUBLE_BIAS
298#define APFX_IEEE_DOUBLE_E_MIN (-DOUBLE_BIAS + 1)
299
300INLINE ap_ulong doubleToRawBits(double pf) {
301 union {
302 ap_ulong __L;
303 double __D;
304 } LD;
305 LD.__D = pf;
306 return LD.__L;
307}
308
309INLINE unsigned int floatToRawBits(float pf) {
310 union {
311 unsigned int __L;
312 float __D;
313 } LD;
314 LD.__D = pf;
315 return LD.__L;
316}
317
318#if _AP_ENABLE_HALF_ == 1
319INLINE unsigned short halfToRawBits(half pf) {
320#ifdef __SYNTHESIS__
321 union {
322 unsigned short __L;
323 half __D;
324 } LD;
325 LD.__D = pf;
326 return LD.__L;
327#else
328 return pf.get_bits();
329#endif
330}
331#endif
332
333// usigned long long is at least 64-bit
334INLINE double rawBitsToDouble(ap_ulong pi) {
335 union {
336 ap_ulong __L;
337 double __D;
338 } LD;
339 LD.__L = pi;
340 return LD.__D;
341}
342
343// long is at least 32-bit
344INLINE float rawBitsToFloat(unsigned long pi) {
345 union {
346 unsigned int __L;
347 float __D;
348 } LD;
349 LD.__L = pi;
350 return LD.__D;
351}
352
353#if _AP_ENABLE_HALF_ == 1
354// short is at least 16-bit
355INLINE half rawBitsToHalf(unsigned short pi) {
356#ifdef __SYNTHESIS__
357 union {
358 unsigned short __L;
359 half __D;
360 } LD;
361 LD.__L = pi;
362 return LD.__D;
363#else
364 // sim model of half has a non-trivial constructor
365 half __D;
366 __D.set_bits(pi);
367 return __D;
368#endif
369}
370#endif
371
372#endif // ifndef __AP_COMMON_H__
373
374// -*- cpp -*-