├── .gitignore ├── LICENSE.TXT ├── README.MD ├── examples ├── ap_fixed │ ├── Makefile │ └── test.cpp └── ap_int │ ├── Makefile │ └── test.cpp └── include ├── ap_common.h ├── ap_decl.h ├── ap_fixed.h ├── ap_fixed_base.h ├── ap_fixed_ref.h ├── ap_fixed_special.h ├── ap_int.h ├── ap_int_base.h ├── ap_int_ref.h ├── ap_int_special.h └── etc └── ap_private.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Vim temp 35 | *.swp 36 | *.swo 37 | 38 | # test folder 39 | test 40 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # HLS Arbitrary Precision Types Library 2 | 3 | This repo provides simulation code of HLS Arbitrary Precision Types. 4 | 5 | The code is based from headers shipped with Vivado, 6 | but due to absence of synthesis support **it should not be used in an HLS project targeting FPGA**. 7 | 8 | ## Compatibility 9 | 10 | Tested with g++ (GCC) 6.2.0 on x86_64 GNU/Linux. 11 | 12 | ## Usage 13 | 14 | Include the `ap_int.h` or `ap_fixed.h` in C++ code, 15 | and set compiler option to add the path of `include` directory in this repo 16 | into header search directory list. 17 | 18 | ``` 19 | $ cd examples/ap_int 20 | $ g++ -I ../../include/ test.cpp 21 | $ ./a.out 22 | a = 11.3137 (0x0b.504ea4p0) 23 | b = 11.3137 (0x0b.504f33p0) 24 | c = a + b = 22.6274 (0x16.a09dd7p0) 25 | $ 26 | ``` 27 | 28 | ## License Info 29 | 30 | Copyright 2011-2019 Xilinx, Inc. 31 | 32 | Licensed under the Apache License, Version 2.0 (the "License"); 33 | you may not use this file except in compliance with the License. 34 | You may obtain a copy of the License at 35 | 36 | http://www.apache.org/licenses/LICENSE-2.0 37 | 38 | Unless required by applicable law or agreed to in writing, software 39 | distributed under the License is distributed on an "AS IS" BASIS, 40 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 41 | See the License for the specific language governing permissions and 42 | limitations under the License. 43 | -------------------------------------------------------------------------------- /examples/ap_fixed/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 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 | a.out: test.cpp 17 | g++ -I../../include test.cpp 18 | ./a.out 19 | 20 | .PHONY: clean 21 | clean: 22 | rm -rf a.out 23 | -------------------------------------------------------------------------------- /examples/ap_fixed/test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 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 | #include "ap_fixed.h" 17 | #include 18 | 19 | int main(int argc, const char* argv[]) { 20 | 21 | ap_ufixed<28, 4> a = 11.3137; 22 | std::cout << "a = " << a << " (" << a.to_string(AP_HEX) << ")\n"; 23 | 24 | #if __cplusplus >= 201103L 25 | ap_ufixed<28, 4> b = 0xB.504F33p0; // hex-float 26 | #else 27 | ap_ufixed<28, 4> b = "0xB.504F33p0"; 28 | #endif 29 | std::cout << "b = " << b << " (" << b.to_string(AP_HEX) << ")\n"; 30 | 31 | ap_ufixed<29, 5> c = a + b; 32 | std::cout << "c = a + b = " << c.to_double() << " (" << c.to_string(AP_HEX) << ")" << std::endl; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /examples/ap_int/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 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 | a.out: test.cpp 17 | g++ -I../../include test.cpp -std=c++11 18 | ./a.out 19 | 20 | .PHONY: clean 21 | clean: 22 | rm -rf a.out 23 | -------------------------------------------------------------------------------- /examples/ap_int/test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 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 | #include "ap_int.h" 17 | #include 18 | 19 | int main(int argc, const char* argv[]) { 20 | 21 | ap_int<5> a = 11; 22 | std::cout << "a = " << a << " (" << a.to_string(AP_HEX) << ")\n"; 23 | 24 | ap_uint<65> b = "0x1ffffffff"; 25 | std::cout << "b = " << b << " (" << b.to_string(AP_HEX) << ")\n"; 26 | 27 | auto c = a + b; 28 | std::cout << "c = a + b = " << c.to_double() << " (" << c.to_string(AP_HEX) << ")" << std::endl; 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /include/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 24 | 25 | 26 | #ifdef __SYNTHESIS__ 27 | #error "The open-source version of AP types does not support synthesis." 28 | #endif // ifdef __SYNTHESIS__ 29 | #define _AP_ENABLE_HALF_ 0 30 | 31 | 32 | #if _AP_ENABLE_HALF_ == 1 33 | // Before ap_private definition. 34 | #ifdef __SYNTHESIS__ 35 | #define _HLS_HALF_DEFINED_ 36 | typedef __fp16 half; 37 | #else 38 | class half; 39 | #endif // __SYNTHESIS__ 40 | #endif // _AP_ENABLE_HALF_ 41 | 42 | // ---------------------------------------------------------------------- 43 | 44 | // Macro functions 45 | #define AP_MAX(a, b) ((a) > (b) ? (a) : (b)) 46 | #define AP_MIN(a, b) ((a) < (b) ? (a) : (b)) 47 | #define AP_ABS(a) ((a) >= 0 ? (a) : -(a)) 48 | 49 | #ifndef AP_ASSERT 50 | #ifndef __SYNTHESIS__ 51 | #include 52 | #define AP_ASSERT(cond, msg) assert((cond) && (msg)) 53 | #else 54 | #define AP_ASSERT(cond, msg) 55 | #endif // ifndef __SYNTHESIS__ 56 | #endif // ifndef AP_ASSERT 57 | 58 | #ifndef __SYNTHESIS__ 59 | // for fprintf messages. 60 | #include 61 | // for exit on error. 62 | #include 63 | #endif 64 | 65 | // same disable condition as assert. 66 | #if !defined(__SYNTHESIS__) && !defined(NDEBUG) 67 | 68 | #define _AP_DEBUG(cond, ...) \ 69 | do { \ 70 | if ((cond)) { \ 71 | fprintf(stderr, "DEBUG: " __VA_ARGS__); \ 72 | fprintf(stderr, "\n"); \ 73 | } \ 74 | } while (0) 75 | #define _AP_WARNING(cond, ...) \ 76 | do { \ 77 | if ((cond)) { \ 78 | fprintf(stderr, "WARNING: " __VA_ARGS__); \ 79 | fprintf(stderr, "\n"); \ 80 | } \ 81 | } while (0) 82 | #define _AP_ERROR(cond, ...) \ 83 | do { \ 84 | if ((cond)) { \ 85 | fprintf(stderr, "ERROR: " __VA_ARGS__); \ 86 | fprintf(stderr, "\n"); \ 87 | abort(); \ 88 | } \ 89 | } while (0) 90 | 91 | #else // if !defined(__SYNTHESIS__) && !defined(NDEBUG) 92 | 93 | #define __AP_VOID_CAST static_cast 94 | #define _AP_DEBUG(cond, ...) (__AP_VOID_CAST(0)) 95 | #define _AP_WARNING(cond, ...) (__AP_VOID_CAST(0)) 96 | #define _AP_ERROR(cond, ...) (__AP_VOID_CAST(0)) 97 | 98 | #endif // if !defined(__SYNTHESIS__) && !defined(NDEBUG) else 99 | 100 | // ---------------------------------------------------------------------- 101 | 102 | // Attribute only for synthesis 103 | #ifdef __SYNTHESIS__ 104 | #define INLINE inline __attribute__((always_inline)) 105 | //#define INLINE inline __attribute__((noinline)) 106 | #else 107 | #define INLINE inline 108 | #endif 109 | 110 | #define AP_WEAK 111 | // __attribute__((weak)) 112 | 113 | #ifndef AP_INT_MAX_W 114 | #define AP_INT_MAX_W 1024 115 | #endif 116 | 117 | #define BIT_WIDTH_UPPER_LIMIT (1 << 15) 118 | #if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT 119 | #error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" 120 | #endif 121 | 122 | #define MAX_MODE(BITS) ((BITS + 1023) / 1024) 123 | 124 | // ---------------------------------------------------------------------- 125 | 126 | // XXX apcc cannot handle global std::ios_base::Init() brought in by 127 | #ifndef AP_AUTOCC 128 | #ifndef __SYNTHESIS__ 129 | // for overload operator<< 130 | #include 131 | #endif 132 | #endif // ifndef AP_AUTOCC 133 | 134 | #ifndef __SYNTHESIS__ 135 | // for string format. 136 | #include 137 | // for string. 138 | #include 139 | #endif 140 | 141 | // for detecting if char is signed. 142 | enum { CHAR_IS_SIGNED = (char)-1 < 0 }; 143 | 144 | // TODO we have similar traits in x_hls_utils.h, should consider unify. 145 | namespace _ap_type { 146 | template 147 | struct is_signed { 148 | static const bool value = _Tp(-1) < _Tp(1); 149 | }; 150 | 151 | template 152 | struct is_integral { 153 | static const bool value = false; 154 | }; 155 | #define DEF_IS_INTEGRAL(CTYPE) \ 156 | template <> \ 157 | struct is_integral { \ 158 | static const bool value = true; \ 159 | }; 160 | DEF_IS_INTEGRAL(bool) 161 | DEF_IS_INTEGRAL(char) 162 | DEF_IS_INTEGRAL(signed char) 163 | DEF_IS_INTEGRAL(unsigned char) 164 | DEF_IS_INTEGRAL(short) 165 | DEF_IS_INTEGRAL(unsigned short) 166 | DEF_IS_INTEGRAL(int) 167 | DEF_IS_INTEGRAL(unsigned int) 168 | DEF_IS_INTEGRAL(long) 169 | DEF_IS_INTEGRAL(unsigned long) 170 | DEF_IS_INTEGRAL(ap_slong) 171 | DEF_IS_INTEGRAL(ap_ulong) 172 | #undef DEF_IS_INTEGRAL 173 | 174 | template 175 | struct enable_if {}; 176 | // partial specialization for true 177 | template 178 | struct enable_if { 179 | typedef _Tp type; 180 | }; 181 | 182 | template 183 | struct remove_const { 184 | typedef _Tp type; 185 | }; 186 | 187 | template 188 | struct remove_const<_Tp const> { 189 | typedef _Tp type; 190 | }; 191 | } // namespace _ap_type 192 | 193 | // ---------------------------------------------------------------------- 194 | 195 | // Define ssdm_int and _ssdm_op. 196 | // XXX deleted in open-source version 197 | 198 | #ifndef NON_C99STRING 199 | #define _AP_C99 true 200 | #else 201 | #define _AP_C99 false 202 | #endif 203 | 204 | static inline unsigned char guess_radix(const char* s) { 205 | unsigned char rd = 10; ///< default radix 206 | const char* p = s; 207 | // skip neg sign if it exists 208 | if (p[0] == '-' || p[0] == '+') ++p; 209 | // guess based on following two bits. 210 | if (p[0] == '0') { 211 | if (p[1] == 'b' || p[1] == 'B') { 212 | rd = 2; 213 | } else if (p[1] == 'o' || p[1] == 'O') { 214 | rd = 8; 215 | } else if (p[1] == 'x' || p[1] == 'X') { 216 | rd = 16; 217 | } else if (p[1] == 'd' || p[1] == 'D') { 218 | rd = 10; 219 | } 220 | } 221 | return rd; 222 | } 223 | 224 | // ---------------------------------------------------------------------- 225 | 226 | // Basic integral struct upon which ap_int and ap_fixed are defined. 227 | #ifdef __SYNTHESIS__ 228 | // Use ssdm_int, a compiler dependent, attribute constrained integeral type as 229 | // basic data type. 230 | #define _AP_ROOT_TYPE ssdm_int 231 | // Basic ops. 232 | #define _AP_ROOT_op_concat(Ret, X, Y) _ssdm_op_concat(Ret, X, Y) 233 | #define _AP_ROOT_op_get_bit(Val, Bit) _ssdm_op_get_bit(Val, Bit) 234 | #define _AP_ROOT_op_set_bit(Val, Bit, Repl) _ssdm_op_set_bit(Val, Bit, Repl) 235 | #define _AP_ROOT_op_get_range(Val, Lo, Hi) _ssdm_op_get_range(Val, Lo, Hi) 236 | #define _AP_ROOT_op_set_range(Val, Lo, Hi, Repl) \ 237 | _ssdm_op_set_range(Val, Lo, Hi, Repl) 238 | #define _AP_ROOT_op_reduce(Op, Val) _ssdm_op_reduce(Op, Val) 239 | #else // ifdef __SYNTHESIS__ 240 | // Use ap_private for compiler-independent basic data type 241 | template 242 | class ap_private; 243 | /// model ssdm_int in standard C++ for simulation. 244 | template 245 | struct ssdm_int_sim { 246 | /// integral type with template-specified width and signedness. 247 | ap_private<_AP_W, _AP_S> V; 248 | ssdm_int_sim() {} 249 | }; 250 | #define _AP_ROOT_TYPE ssdm_int_sim 251 | // private's ref uses _AP_ROOT_TYPE. 252 | #include 253 | // XXX The C-sim model cannot use GCC-extension 254 | // Basic ops. Ret and Val are ap_private. 255 | template 256 | inline _Tp1 _AP_ROOT_op_concat(const _Tp1& Ret, const _Tp2& X, const _Tp3& Y) { 257 | _Tp1 r = (X).operator,(Y); 258 | return r; 259 | } 260 | #define _AP_ROOT_op_get_bit(Val, Bit) (Val).get_bit((Bit)) 261 | template 262 | inline _Tp1& _AP_ROOT_op_set_bit(_Tp1& Val, const _Tp2& Bit, const _Tp3& Repl) { 263 | (Val).set_bit((Bit), (Repl)); 264 | return Val; 265 | } 266 | // notice the order of high and low index is different in ssdm call and 267 | // ap_private.range()... 268 | #define _AP_ROOT_op_get_range(Val, Lo, Hi) (Val).range((Hi), (Lo)) 269 | template 270 | inline _Tp1& _AP_ROOT_op_set_range(_Tp1& Val, const _Tp2& Lo, const _Tp3& Hi, 271 | const _Tp4& Repl) { 272 | (Val).range((Hi), (Lo)) = Repl; 273 | return (Val); 274 | } 275 | #define _AP_ROOT_op_and_reduce(Val) (Val).and_reduce() 276 | #define _AP_ROOT_op_nand_reduce(Val) (Val).nand_reduce() 277 | #define _AP_ROOT_op_or_reduce(Val) (Val).or_reduce() 278 | #define _AP_ROOT_op_xor_reduce(Val) (Val).xor_reduce() 279 | // ## is the concatenation in preprocessor: 280 | #define _AP_ROOT_op_reduce(Op, Val) _AP_ROOT_op_##Op##_reduce(Val) 281 | #endif // ifdef __SYNTHESIS__ else 282 | 283 | // ---------------------------------------------------------------------- 284 | 285 | // Constants for half, single, double pricision floating points 286 | #define HALF_MAN 10 287 | #define FLOAT_MAN 23 288 | #define DOUBLE_MAN 52 289 | 290 | #define HALF_EXP 5 291 | #define FLOAT_EXP 8 292 | #define DOUBLE_EXP 11 293 | 294 | #define BIAS(e) ((1L << (e - 1L)) - 1L) 295 | #define HALF_BIAS BIAS(HALF_EXP) 296 | #define FLOAT_BIAS BIAS(FLOAT_EXP) 297 | #define DOUBLE_BIAS BIAS(DOUBLE_EXP) 298 | 299 | #define APFX_IEEE_DOUBLE_E_MAX DOUBLE_BIAS 300 | #define APFX_IEEE_DOUBLE_E_MIN (-DOUBLE_BIAS + 1) 301 | 302 | INLINE ap_ulong doubleToRawBits(double pf) { 303 | union { 304 | ap_ulong __L; 305 | double __D; 306 | } LD; 307 | LD.__D = pf; 308 | return LD.__L; 309 | } 310 | 311 | INLINE unsigned int floatToRawBits(float pf) { 312 | union { 313 | unsigned int __L; 314 | float __D; 315 | } LD; 316 | LD.__D = pf; 317 | return LD.__L; 318 | } 319 | 320 | #if _AP_ENABLE_HALF_ == 1 321 | INLINE unsigned short halfToRawBits(half pf) { 322 | #ifdef __SYNTHESIS__ 323 | union { 324 | unsigned short __L; 325 | half __D; 326 | } LD; 327 | LD.__D = pf; 328 | return LD.__L; 329 | #else 330 | return pf.get_bits(); 331 | #endif 332 | } 333 | #endif 334 | 335 | // usigned long long is at least 64-bit 336 | INLINE double rawBitsToDouble(ap_ulong pi) { 337 | union { 338 | ap_ulong __L; 339 | double __D; 340 | } LD; 341 | LD.__L = pi; 342 | return LD.__D; 343 | } 344 | 345 | // long is at least 32-bit 346 | INLINE float rawBitsToFloat(unsigned long pi) { 347 | union { 348 | unsigned int __L; 349 | float __D; 350 | } LD; 351 | LD.__L = pi; 352 | return LD.__D; 353 | } 354 | 355 | #if _AP_ENABLE_HALF_ == 1 356 | // short is at least 16-bit 357 | INLINE half rawBitsToHalf(unsigned short pi) { 358 | #ifdef __SYNTHESIS__ 359 | union { 360 | unsigned short __L; 361 | half __D; 362 | } LD; 363 | LD.__L = pi; 364 | return LD.__D; 365 | #else 366 | // sim model of half has a non-trivial constructor 367 | half __D; 368 | __D.set_bits(pi); 369 | return __D; 370 | #endif 371 | } 372 | #endif 373 | 374 | #endif // ifndef __AP_COMMON_H__ 375 | 376 | // -*- cpp -*- 377 | -------------------------------------------------------------------------------- /include/ap_decl.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_DECL_H__ 18 | #define __AP_DECL_H__ 19 | 20 | // ---------------------------------------------------------------------- 21 | 22 | #if !defined(__AP_FIXED_H__) && !defined(__AP_INT_H__) && !defined(__AUTOPILOT_CBE_H__) && !defined(__HLS_HALF_H__) 23 | #error "Only ap_fixed.h and ap_int.h can be included directly in user code." 24 | #endif 25 | 26 | // Test __SYNTHESIS__ only for mode 27 | #if !defined(__SYNTHESIS__) && (defined(AESL_SYN) || defined(__HLS_SYN__)) 28 | //#pragma message "AESL_SYN and __HLS_SYN__ should be replaced by __SYNTHESIS__" 29 | #define __SYNTHESIS__ 30 | #endif 31 | 32 | /* for safety*/ 33 | #if (defined(_AP_N) || defined(_AP_C)) 34 | #error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. 35 | #endif 36 | 37 | /* for safety*/ 38 | #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || \ 39 | defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || \ 40 | defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2) || \ 41 | defined(_AP_N) || defined(_AP_N2)) 42 | #error \ 43 | "One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2. Definition conflicts with their usage as template parameters." 44 | #endif 45 | 46 | /*for safety*/ 47 | #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) 48 | #error \ 49 | "One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters." 50 | #endif 51 | 52 | #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_T) || \ 53 | defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) 54 | #error \ 55 | "One or more of the following is defined: _AP_W1, _AP_S1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters." 56 | #endif 57 | 58 | #ifndef __cplusplus 59 | #error "AP data type can only be used in C++" 60 | #endif 61 | 62 | // ---------------------------------------------------------------------- 63 | 64 | #ifndef __SC_COMPATIBLE__ 65 | /// ap_fixed quantification mode 66 | enum ap_q_mode { 67 | AP_RND, //< rounding to plus infinity 68 | AP_RND_ZERO, //< rounding to zero 69 | AP_RND_MIN_INF, //< rounding to minus infinity 70 | AP_RND_INF, //< rounding to infinity 71 | AP_RND_CONV, //< convergent rounding 72 | AP_TRN, //< truncation 73 | AP_TRN_ZERO, //< truncation to zero 74 | }; 75 | 76 | // FIXME for legacy code 77 | #ifndef SYSTEMC_INCLUDED 78 | #define SC_RND AP_RND 79 | #define SC_RND_ZERO AP_RND_ZERO 80 | #define SC_RND_MIN_INF AP_RND_MIN_INF 81 | #define SC_RND_INF AP_RND_INF 82 | #define SC_RND_CONV AP_RND_CONV 83 | #define SC_TRN AP_TRN 84 | #define SC_TRN_ZERO AP_TRN_ZERO 85 | #endif // !defined(SYSTEMC_INCLUDED) 86 | 87 | /// ap_fixed saturation mode 88 | enum ap_o_mode { 89 | AP_SAT, //< saturation 90 | AP_SAT_ZERO, //< saturation to zero 91 | AP_SAT_SYM, //< symmetrical saturation 92 | AP_WRAP, //< wrap-around (*) 93 | AP_WRAP_SM, //< sign magnitude wrap-around (*) 94 | }; 95 | 96 | // FIXME for legacy code 97 | #ifndef SYSTEMC_INCLUDED 98 | #define SC_SAT AP_SAT 99 | #define SC_SAT_ZERO AP_SAT_ZERO 100 | #define SC_SAT_SYM AP_SAT_SYM 101 | #define SC_WRAP AP_WRAP 102 | #define SC_WRAP_SM AP_WRAP_SM 103 | #endif // !defined(SYSTEMC_INCLUDED) 104 | 105 | #else // defined(__SC_COMPATIBLE__) 106 | 107 | // There will not be sc_fxdefs.h, and the emu should be defined by ap_fixed. 108 | 109 | /// ap_fixed quantification mode 110 | enum ap_q_mode { 111 | SC_RND, //< rounding to plus infinity 112 | SC_RND_ZERO, //< rounding to zero 113 | SC_RND_MIN_INF, //< rounding to minus infinity 114 | SC_RND_INF, //< rounding to infinity 115 | SC_RND_CONV, //< convergent rounding 116 | SC_TRN, //< truncation 117 | SC_TRN_ZERO, //< truncation to zero 118 | }; 119 | 120 | #define AP_RND SC_RND 121 | #define AP_RND_ZERO SC_RND_ZERO 122 | #define AP_RND_MIN_INF SC_RND_MIN_INF 123 | #define AP_RND_INF SC_RND_INF 124 | #define AP_RND_CONV SC_RND_CONV 125 | #define AP_TRN SC_TRN 126 | #define AP_TRN_ZERO SC_TRN_ZERO 127 | 128 | /// ap_fixed saturation mode 129 | enum ap_o_mode { 130 | SC_SAT, //< saturation 131 | SC_SAT_ZERO, //< saturation to zero 132 | SC_SAT_SYM, //< symmetrical saturation 133 | SC_WRAP, //< wrap-around (*) 134 | SC_WRAP_SM, //< sign magnitude wrap-around (*) 135 | }; 136 | 137 | #define AP_SAT SC_SAT 138 | #define AP_SAT_ZERO SC_SAT_ZERO 139 | #define AP_SAT_SYM SC_SAT_SYM 140 | #define AP_WRAP SC_WRAP 141 | #define AP_WRAP_SM SC_WRAP_SM 142 | 143 | #endif // defined(__SC_COMPATIBLE__) 144 | 145 | template 146 | struct ap_int_base; 147 | 148 | template 149 | struct ap_int; 150 | 151 | template 152 | struct ap_uint; 153 | 154 | template 155 | struct ap_range_ref; 156 | 157 | template 158 | struct ap_bit_ref; 159 | 160 | template 161 | struct ap_concat_ref; 162 | 163 | template 165 | struct ap_fixed_base; 166 | 167 | template 169 | struct ap_fixed; 170 | 171 | template 173 | struct ap_ufixed; 174 | 175 | template 177 | struct af_range_ref; 178 | 179 | template 181 | struct af_bit_ref; 182 | 183 | /// string base mode 184 | enum BaseMode { AP_BIN = 2, AP_OCT = 8, AP_DEC = 10, AP_HEX = 16 }; 185 | 186 | #ifndef SYSTEMC_INCLUDED 187 | #define SC_BIN 2 188 | #define SC_OCT 8 189 | #define SC_DEC 10 190 | #define SC_HEX 16 191 | #endif // !defined(SYSTEMC_INCLUDED) 192 | 193 | // Alias C data types 194 | #ifdef _MSC_VER 195 | typedef signed __int64 ap_slong; 196 | typedef unsigned __int64 ap_ulong; 197 | #else // !defined(_MSC_VER) 198 | typedef signed long long ap_slong; 199 | typedef unsigned long long ap_ulong; 200 | #endif // !defined(_MSC_VER) 201 | 202 | enum { 203 | _AP_SIZE_char = 8, 204 | _AP_SIZE_short = sizeof(short) * 8, 205 | _AP_SIZE_int = sizeof(int) * 8, 206 | _AP_SIZE_long = sizeof(long) * 8, 207 | _AP_SIZE_ap_slong = sizeof(ap_slong) * 8 208 | }; 209 | 210 | #endif // !defined(__AP_DECL_H__) 211 | 212 | // -*- cpp -*- 213 | -------------------------------------------------------------------------------- /include/ap_fixed.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_FIXED_H__ 18 | #define __AP_FIXED_H__ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | //--------------------------------------------------------------- 25 | 26 | /// Signed Arbitrary Precision Fixed-Point Type. 27 | // default for _AP_Q, _AP_O and _AP_N set in ap_decl.h 28 | template 29 | struct ap_fixed : ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { 30 | typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; 31 | // Constructor 32 | /// default ctor 33 | INLINE ap_fixed() : Base() {} 34 | 35 | /// default copy ctor 36 | INLINE ap_fixed(const ap_fixed& op) { Base::V = op.V; } 37 | 38 | /// copy ctor from ap_fixed_base. 39 | template 41 | INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, 42 | _AP_O2, _AP_N2>& op) 43 | : Base(op) {} 44 | 45 | template 47 | INLINE ap_fixed(const volatile ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, 48 | _AP_O2, _AP_N2>& op) 49 | : Base(op) {} 50 | 51 | //// from ap_fixed 52 | //template 54 | //INLINE ap_fixed( 55 | // const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 56 | // : Base(ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} 57 | 58 | //template 60 | //INLINE ap_fixed( 61 | // const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 62 | // : Base(ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} 63 | 64 | //// from ap_ufixed. 65 | //template 67 | //INLINE ap_fixed( 68 | // const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 69 | // : Base(ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>(op)) { 70 | //} 71 | 72 | //template 74 | //INLINE ap_fixed( 75 | // const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 76 | // : Base(ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>(op)) { 77 | //} 78 | 79 | /// copy ctor from ap_int_base. 80 | template 81 | INLINE ap_fixed(const ap_int_base<_AP_W2, _AP_S2>& op) : Base(op) {} 82 | 83 | template 84 | INLINE ap_fixed(const volatile ap_int_base<_AP_W2, _AP_S2>& op) : Base(op) {} 85 | 86 | //// from ap_int. 87 | //template 88 | //INLINE ap_fixed(const ap_int<_AP_W2>& op) 89 | // : Base(ap_int_base<_AP_W2, true>(op)) {} 90 | 91 | //template 92 | //INLINE ap_fixed(const volatile ap_int<_AP_W2>& op) 93 | // : Base(ap_int_base<_AP_W2, true>(op)) {} 94 | 95 | //// from ap_uint. 96 | //template 97 | //INLINE ap_fixed(const ap_uint<_AP_W2>& op) 98 | // : Base(ap_int_base<_AP_W2, false>(op)) {} 99 | 100 | //template 101 | //INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op) 102 | // : Base(ap_int_base<_AP_W2, false>(op)) {} 103 | 104 | // from ap_bit_ref. 105 | template 106 | INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op) : Base(op) {} 107 | 108 | // from ap_range_ref. 109 | template 110 | INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op) : Base(op) {} 111 | 112 | // from ap_concat_ref. 113 | template 114 | INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) 115 | : Base(op) {} 116 | 117 | // from af_bit_ref. 118 | template 120 | INLINE ap_fixed( 121 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 122 | : Base(op) {} 123 | 124 | // from af_range_ref. 125 | template 127 | INLINE ap_fixed( 128 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 129 | : Base(op) {} 130 | 131 | // from c types. 132 | #define CTOR(TYPE) \ 133 | INLINE ap_fixed(TYPE v) : Base(v) {} 134 | 135 | CTOR(bool) 136 | CTOR(char) 137 | CTOR(signed char) 138 | CTOR(unsigned char) 139 | CTOR(short) 140 | CTOR(unsigned short) 141 | CTOR(int) 142 | CTOR(unsigned int) 143 | CTOR(long) 144 | CTOR(unsigned long) 145 | CTOR(ap_slong) 146 | CTOR(ap_ulong) 147 | #if _AP_ENABLE_HALF_ == 1 148 | CTOR(half) 149 | #endif 150 | CTOR(float) 151 | CTOR(double) 152 | #undef CTOR 153 | 154 | INLINE ap_fixed(const char* s) : Base(s) {} 155 | 156 | INLINE ap_fixed(const char* s, signed char rd) : Base(s, rd) {} 157 | 158 | // Assignment 159 | // The assignment operator is technically inherited; however, it is always 160 | // hidden by an explicitly or implicitly defined assignment operator for the 161 | // derived class. 162 | /* XXX ctor will be used when right is not of proper type. */ 163 | INLINE ap_fixed& operator=( 164 | const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) { 165 | Base::V = op.V; 166 | return *this; 167 | } 168 | 169 | INLINE void operator=( 170 | const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) volatile { 171 | Base::V = op.V; 172 | } 173 | 174 | INLINE ap_fixed& operator=( 175 | const volatile ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) { 176 | Base::V = op.V; 177 | return *this; 178 | } 179 | 180 | INLINE void operator=( 181 | const volatile ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) volatile { 182 | Base::V = op.V; 183 | } 184 | }; // struct ap_fixed. 185 | 186 | //------------------------------------------------------------------- 187 | 188 | // Unsigned Arbitrary Precision Fixed-Point Type. 189 | // default for _AP_Q, _AP_O and _AP_N set in ap_decl.h 190 | template 191 | struct ap_ufixed : ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { 192 | typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; 193 | // Constructor 194 | /// default ctor 195 | INLINE ap_ufixed() : Base() {} 196 | 197 | /// default copy ctor 198 | INLINE ap_ufixed(const ap_ufixed& op) { Base::V = op.V; } 199 | 200 | /// copy ctor from ap_fixed_base 201 | template 203 | INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, 204 | _AP_O2, _AP_N2>& op) 205 | : Base(op) {} 206 | 207 | /// copy ctor from ap_fixed_base 208 | template 210 | INLINE ap_ufixed(const volatile ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, 211 | _AP_O2, _AP_N2>& op) 212 | : Base(op) {} 213 | 214 | //template 216 | //INLINE ap_ufixed( 217 | // const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 218 | // : Base(ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} 219 | 220 | //template 222 | //INLINE ap_ufixed( 223 | // const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 224 | // : Base(ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} 225 | 226 | //template 228 | //INLINE ap_ufixed( 229 | // const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 230 | // : Base(ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>(op)) { 231 | //} 232 | 233 | //template 235 | //INLINE ap_ufixed( 236 | // const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 237 | // : Base(ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>(op)) { 238 | //} 239 | 240 | /// copy ctor from ap_int_base. 241 | template 242 | INLINE ap_ufixed(const ap_int_base<_AP_W2, _AP_S2>& op) : Base(op) {} 243 | 244 | template 245 | INLINE ap_ufixed(const volatile ap_int_base<_AP_W2, _AP_S2>& op) : Base(op) {} 246 | 247 | //template 248 | //INLINE ap_ufixed(const ap_int<_AP_W2>& op) 249 | // : Base(ap_int_base<_AP_W2, true>(op)) {} 250 | 251 | //template 252 | //INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op) 253 | // : Base(ap_int_base<_AP_W2, true>(op)) {} 254 | 255 | //template 256 | //INLINE ap_ufixed(const ap_uint<_AP_W2>& op) 257 | // : Base(ap_int_base<_AP_W2, false>(op)) {} 258 | 259 | //template 260 | //INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op) 261 | // : Base(ap_int_base<_AP_W2, false>(op)) {} 262 | 263 | template 264 | INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op) : Base(op) {} 265 | 266 | template 267 | INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op) : Base(op) {} 268 | 269 | template 270 | INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) 271 | : Base(op) {} 272 | 273 | template 275 | INLINE ap_ufixed( 276 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 277 | : Base(op) {} 278 | 279 | template 281 | INLINE ap_ufixed( 282 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 283 | : Base(op) {} 284 | 285 | #define CTOR(TYPE) \ 286 | INLINE ap_ufixed(TYPE v) : Base(v) {} 287 | 288 | CTOR(bool) 289 | CTOR(char) 290 | CTOR(signed char) 291 | CTOR(unsigned char) 292 | CTOR(short) 293 | CTOR(unsigned short) 294 | CTOR(int) 295 | CTOR(unsigned int) 296 | CTOR(long) 297 | CTOR(unsigned long) 298 | CTOR(ap_slong) 299 | CTOR(ap_ulong) 300 | #if _AP_ENABLE_HALF_ == 1 301 | CTOR(half) 302 | #endif 303 | CTOR(float) 304 | CTOR(double) 305 | #undef CTOR 306 | 307 | INLINE ap_ufixed(const char* s) : Base(s) {} 308 | 309 | INLINE ap_ufixed(const char* s, signed char rd) : Base(s, rd) {} 310 | 311 | // Assignment 312 | INLINE ap_ufixed& operator=( 313 | const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) { 314 | Base::V = op.V; 315 | return *this; 316 | } 317 | 318 | INLINE void operator=( 319 | const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) volatile { 320 | Base::V = op.V; 321 | } 322 | 323 | INLINE ap_ufixed& operator=( 324 | const volatile ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) { 325 | Base::V = op.V; 326 | return *this; 327 | } 328 | 329 | INLINE void operator=(const volatile ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, 330 | _AP_N>& op) volatile { 331 | Base::V = op.V; 332 | } 333 | }; // struct ap_ufixed 334 | 335 | 336 | #if !defined(__SYNTHESIS__) && (defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED)) 337 | // XXX sc_trace overload for ap_fixed is already included in 338 | // "ap_sysc/ap_sc_extras.h", so do not define in synthesis. 339 | template 340 | INLINE void sc_trace(sc_core::sc_trace_file* tf, 341 | const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op, 342 | const std::string& name) { 343 | tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); 344 | } 345 | 346 | template 347 | INLINE void sc_trace(sc_core::sc_trace_file* tf, 348 | const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op, 349 | const std::string& name) { 350 | tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); 351 | } 352 | #endif // System C sim 353 | 354 | // Specialization of std containers, so that std::complex can have its 355 | // image part automatically zero-initialized when only real part is provided. 356 | #include 357 | 358 | #endif // ifndef __AP_FIXED_H__ 359 | 360 | // -*- cpp -*- 361 | -------------------------------------------------------------------------------- /include/ap_fixed_ref.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2019 Xilinx, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __AP_FIXED_REF_H__ 18 | #define __AP_FIXED_REF_H__ 19 | 20 | #ifndef __AP_FIXED_H__ 21 | #error "Only ap_fixed.h and ap_int.h can be included directly in user code." 22 | #endif 23 | 24 | #ifndef __cplusplus 25 | #error "C++ is required to include this header file" 26 | 27 | #else 28 | #ifndef __SYNTHESIS__ 29 | #include 30 | #endif 31 | /// Proxy class, which allows bit selection to be used as both rvalue (for 32 | /// reading) and lvalue (for writing) 33 | template 35 | struct af_bit_ref { 36 | #ifdef _MSC_VER 37 | #pragma warning(disable : 4521 4522) 38 | #endif 39 | typedef ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> ref_type; 40 | ref_type& d_bv; 41 | int d_index; 42 | 43 | public: 44 | INLINE af_bit_ref( 45 | const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ref) 46 | : d_bv(ref.d_bv), d_index(ref.d_index) { 47 | #ifndef __SYNTHESIS__ 48 | _AP_WARNING(d_index < 0, "Index of bit vector (%d) cannot be negative.", 49 | d_index); 50 | _AP_WARNING(d_index >= _AP_W, "Index of bit vector (%d) out of range (%d).", 51 | d_index, _AP_W); 52 | #endif 53 | } 54 | 55 | INLINE af_bit_ref(ref_type* bv, int index = 0) : d_bv(*bv), d_index(index) {} 56 | 57 | INLINE af_bit_ref(const ref_type* bv, int index = 0) 58 | : d_bv(*const_cast(bv)), d_index(index) {} 59 | 60 | /// convert operators. 61 | INLINE operator bool() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } 62 | 63 | /// @name assign operators 64 | // @{ 65 | INLINE af_bit_ref& operator=(bool val) { 66 | d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, val); 67 | return *this; 68 | } 69 | 70 | // Be explicit to prevent it from being deleted, as field d_bv 71 | // is of reference type. 72 | INLINE af_bit_ref& operator=(const af_bit_ref& val) { 73 | return operator=(bool(val)); 74 | } 75 | 76 | template 78 | INLINE af_bit_ref& operator=( 79 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { 80 | return operator=(bool(val)); 81 | } 82 | 83 | template 84 | INLINE af_bit_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) { 85 | return operator=(bool(val)); 86 | } 87 | 88 | template 89 | INLINE af_bit_ref& operator=(const ap_int_base<_AP_W2, _AP_S2>& val) { 90 | return operator=(val != 0); 91 | } 92 | 93 | template 94 | INLINE af_bit_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) { 95 | return operator=(ap_int_base<_AP_W2, false>(val)); 96 | } 97 | 98 | template 100 | INLINE af_bit_ref& operator=( 101 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { 102 | return operator=(ap_int_base<_AP_W2, false>(val)); 103 | } 104 | 105 | template 106 | INLINE af_bit_ref& operator=( 107 | const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { 108 | return operator=(ap_int_base<_AP_W2 + _AP_W3, false>(val)); 109 | } 110 | // @} 111 | 112 | /// @name concatenate operators 113 | // @{ 114 | template 115 | INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 116 | operator,(ap_int_base<_AP_W2, _AP_S2> &op) { 117 | return ap_concat_ref<1, af_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( 118 | *this, op); 119 | } 120 | 121 | template 122 | INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > operator,( 123 | const ap_bit_ref<_AP_W2, _AP_S2> &op) { 124 | return ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> >(*this, 125 | op); 126 | } 127 | 128 | template 129 | INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > 130 | operator,(const ap_range_ref<_AP_W2, _AP_S2> &op) { 131 | return ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> >( 132 | *this, op); 133 | } 134 | 135 | template 136 | INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, 137 | ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > 138 | operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { 139 | return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, 140 | ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, 141 | op); 142 | } 143 | 144 | template 146 | INLINE ap_concat_ref< 147 | 1, af_bit_ref, _AP_W2, 148 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > 149 | operator,( 150 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &op) { 151 | return ap_concat_ref< 152 | 1, af_bit_ref, _AP_W2, 153 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, 154 | op); 155 | } 156 | 157 | template 159 | INLINE ap_concat_ref<1, af_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, 160 | _AP_Q2, _AP_O2, _AP_N2> > 161 | operator,( 162 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &op) { 163 | return ap_concat_ref<1, af_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, 164 | _AP_Q2, _AP_O2, _AP_N2> >( 165 | *this, 166 | const_cast&>( 167 | op)); 168 | } 169 | // @} 170 | 171 | /// @name comparison 172 | // @{ 173 | template 175 | INLINE bool operator==( 176 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { 177 | return get() == op.get(); 178 | } 179 | 180 | template 182 | INLINE bool operator!=( 183 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { 184 | return get() != op.get(); 185 | } 186 | // @} 187 | 188 | INLINE bool operator~() const { 189 | bool bit = _AP_ROOT_op_get_bit(d_bv.V, d_index); 190 | return bit ? false : true; 191 | } 192 | 193 | INLINE bool get() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } 194 | 195 | INLINE int length() const { return 1; } 196 | 197 | #ifndef __SYNTHESIS__ 198 | std::string to_string() const { return get() ? "1" : "0"; } 199 | #else 200 | // XXX HLS will delete this in synthesis 201 | INLINE char* to_string() const { return 0; } 202 | #endif 203 | }; // struct af_bit_ref 204 | 205 | // XXX apcc cannot handle global std::ios_base::Init() brought in by 206 | #ifndef AP_AUTOCC 207 | #ifndef __SYNTHESIS__ 208 | template 210 | INLINE std::ostream& operator<<( 211 | std::ostream& os, 212 | const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& x) { 213 | os << x.to_string(); 214 | return os; 215 | } 216 | #endif // ifndef __SYNTHESIS__ 217 | #endif // ifndef AP_AUTOCC 218 | 219 | /// Range (slice) reference. 220 | template 222 | struct af_range_ref { 223 | #ifdef _MSC_VER 224 | #pragma warning(disable : 4521 4522) 225 | #endif 226 | typedef ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> ref_type; 227 | ref_type& d_bv; 228 | int l_index; 229 | int h_index; 230 | 231 | public: 232 | /// copy ctor 233 | INLINE af_range_ref( 234 | const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ref) 235 | : d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} 236 | 237 | /// ctor from ap_fixed_base, higher and lower bound. 238 | /** if h is less than l, the bits selected will be returned in reverse order. 239 | */ 240 | INLINE af_range_ref(ref_type* bv, int h, int l) 241 | : d_bv(*bv), l_index(l), h_index(h) { 242 | #ifndef __SYNTHESIS__ 243 | _AP_WARNING(h < 0 || l < 0, 244 | "Higher bound(%d) and lower(%d) bound cannot be negative.", h, 245 | l); 246 | _AP_WARNING(h >= _AP_W || l >= _AP_W, 247 | "Higher bound(%d) or lower(%d) bound out of range.", h, l); 248 | _AP_WARNING(h < l, "The bits selected will be returned in reverse order."); 249 | #endif 250 | } 251 | 252 | INLINE af_range_ref(const ref_type* bv, int h, int l) 253 | : d_bv(*const_cast(bv)), l_index(l), h_index(h) { 254 | #ifndef __SYNTHESIS__ 255 | _AP_WARNING(h < 0 || l < 0, 256 | "Higher bound(%d) and lower(%d) bound cannot be negative.", h, 257 | l); 258 | _AP_WARNING(h >= _AP_W || l >= _AP_W, 259 | "Higher bound(%d) or lower(%d) bound out of range.", h, l); 260 | _AP_WARNING(h < l, "The bits selected will be returned in reverse order."); 261 | #endif 262 | } 263 | 264 | /// @name assign operators 265 | // @{ 266 | 267 | #define ASSIGN_CTYPE_TO_AF_RANGE(DATA_TYPE) \ 268 | INLINE af_range_ref& operator=(const DATA_TYPE val) { \ 269 | ap_int_base<_AP_W, false> loc(val); \ 270 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, loc.V); \ 271 | return *this; \ 272 | } 273 | 274 | ASSIGN_CTYPE_TO_AF_RANGE(bool) 275 | ASSIGN_CTYPE_TO_AF_RANGE(char) 276 | ASSIGN_CTYPE_TO_AF_RANGE(signed char) 277 | ASSIGN_CTYPE_TO_AF_RANGE(unsigned char) 278 | ASSIGN_CTYPE_TO_AF_RANGE(short) 279 | ASSIGN_CTYPE_TO_AF_RANGE(unsigned short) 280 | ASSIGN_CTYPE_TO_AF_RANGE(int) 281 | ASSIGN_CTYPE_TO_AF_RANGE(unsigned int) 282 | ASSIGN_CTYPE_TO_AF_RANGE(long) 283 | ASSIGN_CTYPE_TO_AF_RANGE(unsigned long) 284 | ASSIGN_CTYPE_TO_AF_RANGE(ap_slong) 285 | ASSIGN_CTYPE_TO_AF_RANGE(ap_ulong) 286 | #if _AP_ENABLE_HALF_ == 1 287 | ASSIGN_CTYPE_TO_AF_RANGE(half) 288 | #endif 289 | ASSIGN_CTYPE_TO_AF_RANGE(float) 290 | ASSIGN_CTYPE_TO_AF_RANGE(double) 291 | #undef ASSIGN_CTYPE_TO_AF_RANGE 292 | 293 | /// assgin using a string. XXX crucial for cosim. 294 | INLINE af_range_ref& operator=(const char* val) { 295 | const ap_int_base<_AP_W, false> tmp(val); // XXX figure out radix 296 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); 297 | return *this; 298 | } 299 | 300 | /// assign from ap_int_base. 301 | // NOTE Base of other assgin operators. 302 | template 303 | INLINE af_range_ref& operator=(const ap_int_base<_AP_W3, _AP_S3>& val) { 304 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V); 305 | return *this; 306 | } 307 | 308 | /// assign from range reference to ap_int_base. 309 | template 310 | INLINE af_range_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) { 311 | const ap_int_base<_AP_W2, false> tmp(val); 312 | return operator=(tmp); 313 | } 314 | 315 | /// assign from bit reference to ap_int_base.. 316 | template 317 | INLINE af_range_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) { 318 | const ap_int_base<1, false> tmp((bool)val); 319 | return operator=(tmp); 320 | } 321 | 322 | /// assgin from ap_fixed_base. 323 | template 325 | INLINE af_range_ref& operator=( 326 | const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& 327 | val) { 328 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V); 329 | return *this; 330 | } 331 | 332 | /// copy assgin. 333 | // XXX This has to be explicit, otherwise it will be deleted, as d_bv is 334 | // of reference type. 335 | INLINE af_range_ref& operator=(const af_range_ref& val) { 336 | ap_int_base<_AP_W, false> tmp(val); 337 | return operator=(tmp); 338 | } 339 | 340 | /// assign from range reference to ap_fixed_base. 341 | template 343 | INLINE af_range_ref& operator=( 344 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { 345 | ap_int_base<_AP_W2, false> tmp(val); 346 | return operator=(tmp); 347 | } 348 | 349 | /// assign from bit reference to ap_fixed_base. 350 | template 352 | INLINE af_range_ref& operator=( 353 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { 354 | ap_int_base<1, false> tmp((bool)val); 355 | return operator=(tmp); 356 | } 357 | 358 | /// assign from compound reference. 359 | template 360 | INLINE af_range_ref& operator=( 361 | const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { 362 | const ap_int_base<_AP_W2 + _AP_W3, false> tmp(val); 363 | return operator=(tmp); 364 | } 365 | // @} 366 | 367 | /// @name comparison operators with ap_range_ref. 368 | // @{ 369 | template 370 | INLINE bool operator==(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 371 | ap_int_base<_AP_W, false> lop(*this); 372 | ap_int_base<_AP_W2, false> rop(op2); 373 | return lop == rop; 374 | } 375 | 376 | template 377 | INLINE bool operator!=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 378 | return !(operator==(op2)); 379 | } 380 | 381 | template 382 | INLINE bool operator<(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 383 | ap_int_base<_AP_W, false> lop(*this); 384 | ap_int_base<_AP_W2, false> rop(op2); 385 | return lop < rop; 386 | } 387 | 388 | template 389 | INLINE bool operator>(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 390 | ap_int_base<_AP_W, false> lop(*this); 391 | ap_int_base<_AP_W2, false> rop(op2); 392 | return lop > rop; 393 | } 394 | 395 | template 396 | INLINE bool operator<=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 397 | return !(operator>(op2)); 398 | } 399 | 400 | template 401 | INLINE bool operator>=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 402 | return !(operator<(op2)); 403 | } 404 | // @} 405 | 406 | /// @name comparison operators with af_range_ref. 407 | // @{ 408 | template 410 | INLINE bool operator==( 411 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { 412 | ap_int_base<_AP_W, false> lop(*this); 413 | ap_int_base<_AP_W2, false> rop(op2); 414 | return lop == rop; 415 | } 416 | 417 | template 419 | INLINE bool operator!=( 420 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { 421 | return !(operator==(op2)); 422 | } 423 | 424 | template 426 | INLINE bool operator<( 427 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { 428 | ap_int_base<_AP_W, false> lop(*this); 429 | ap_int_base<_AP_W2, false> rop(op2); 430 | return lop < rop; 431 | } 432 | 433 | template 435 | INLINE bool operator>( 436 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { 437 | ap_int_base<_AP_W, false> lop(*this); 438 | ap_int_base<_AP_W2, false> rop(op2); 439 | return lop > rop; 440 | } 441 | 442 | template 444 | INLINE bool operator<=( 445 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { 446 | return !(operator>(op2)); 447 | } 448 | 449 | template 451 | INLINE bool operator>=( 452 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { 453 | return !(operator<(op2)); 454 | } 455 | // @} 456 | 457 | /// @name concatenate operators. 458 | /// @{ 459 | /// concatenate with ap_int_base. 460 | template 461 | INLINE 462 | ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 463 | operator,(ap_int_base<_AP_W2, _AP_S2> &op) { 464 | return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, 465 | ap_int_base<_AP_W2, _AP_S2> >(*this, op); 466 | } 467 | 468 | /// concatenate with ap_bit_ref. 469 | template 470 | INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > 471 | operator,(const ap_bit_ref<_AP_W2, _AP_S2> &op) { 472 | return ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> >( 473 | *this, const_cast&>(op)); 474 | } 475 | 476 | /// concatenate with ap_bit_ref. 477 | template 478 | INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > 479 | operator,(const ap_range_ref<_AP_W2, _AP_S2> &op) { 480 | return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, 481 | ap_range_ref<_AP_W2, _AP_S2> >( 482 | *this, const_cast&>(op)); 483 | } 484 | 485 | /// concatenate with ap_concat_ref. 486 | template 487 | INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, 488 | ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > 489 | operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { 490 | return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, 491 | ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( 492 | *this, const_cast&>(op)); 493 | } 494 | 495 | /// concatenate with another af_range_ref. 496 | template 498 | INLINE 499 | ap_concat_ref<_AP_W, af_range_ref, _AP_W2, 500 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > 501 | operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> 502 | &op) { 503 | return ap_concat_ref< 504 | _AP_W, af_range_ref, _AP_W2, 505 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( 506 | *this, 507 | const_cast&>( 508 | op)); 509 | } 510 | 511 | /// concatenate with another af_bit_ref. 512 | template 514 | INLINE 515 | ap_concat_ref<_AP_W, af_range_ref, 1, 516 | af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > 517 | operator,( 518 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &op) { 519 | return ap_concat_ref< 520 | _AP_W, af_range_ref, 1, 521 | af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( 522 | *this, 523 | const_cast&>( 524 | op)); 525 | } 526 | // @} 527 | 528 | INLINE operator ap_ulong() const { 529 | ap_int_base<_AP_W, false> ret; 530 | ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); 531 | return ret.to_uint64(); 532 | } 533 | 534 | INLINE operator ap_int_base<_AP_W, false>() const { 535 | ap_int_base<_AP_W, false> ret; 536 | ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); 537 | return ret; 538 | } 539 | 540 | INLINE ap_int_base<_AP_W, false> to_ap_int_base() const { 541 | ap_int_base<_AP_W, false> ret; 542 | ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); 543 | return ret; 544 | } 545 | 546 | // used in ap_fixed_base::to_string() 547 | INLINE char to_char() const { 548 | return (char)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 549 | } 550 | 551 | INLINE int to_int() const { 552 | return (int)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 553 | } 554 | 555 | INLINE unsigned to_uint() const { 556 | return (unsigned)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 557 | } 558 | 559 | INLINE long to_long() const { 560 | return (long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 561 | } 562 | 563 | INLINE unsigned long to_ulong() const { 564 | return (unsigned long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 565 | } 566 | 567 | INLINE ap_slong to_int64() const { 568 | return (ap_slong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 569 | } 570 | 571 | INLINE ap_ulong to_uint64() const { 572 | return (ap_ulong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 573 | } 574 | 575 | INLINE ap_int_base<_AP_W, false> get() const { 576 | ap_int_base<_AP_W, false> ret; 577 | ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); 578 | return ret; 579 | } 580 | 581 | template 582 | INLINE void set(const ap_int_base<_AP_W2, false>& val) { 583 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V); 584 | } 585 | 586 | INLINE int length() const { 587 | return h_index >= l_index ? h_index - l_index + 1 : l_index - h_index + 1; 588 | } 589 | 590 | #ifndef __SYNTHESIS__ 591 | std::string to_string(signed char rd = 2) const { 592 | ap_int_base<_AP_W, false> ret; 593 | ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); 594 | return ret.to_string(rd); 595 | } 596 | #else 597 | // XXX HLS will delete this in synthesis 598 | INLINE char* to_string(signed char rd = 2) const { 599 | return 0; 600 | } 601 | #endif 602 | }; // struct af_range_ref 603 | 604 | // XXX apcc cannot handle global std::ios_base::Init() brought in by 605 | #ifndef AP_AUTOCC 606 | #ifndef __SYNTHESIS__ 607 | template 609 | INLINE std::ostream& operator<<( 610 | std::ostream& os, 611 | const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& x) { 612 | os << x.to_string(); 613 | return os; 614 | } 615 | #endif 616 | #endif // ifndef AP_AUTOCC 617 | 618 | #define AF_REF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ 619 | template \ 621 | INLINE bool operator REL_OP( \ 622 | const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ 623 | C_TYPE op2) { \ 624 | return ap_int_base<_AP_W, false>(op) \ 625 | REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ 626 | } \ 627 | \ 628 | template \ 630 | INLINE bool operator REL_OP( \ 631 | C_TYPE op2, \ 632 | const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ 633 | return ap_int_base<_AP_W2, _AP_S2>(op2) \ 634 | REL_OP ap_int_base<_AP_W, false>(op); \ 635 | } \ 636 | \ 637 | template \ 639 | INLINE bool operator REL_OP( \ 640 | const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ 641 | C_TYPE op2) { \ 642 | return bool(op) REL_OP op2; \ 643 | } \ 644 | \ 645 | template \ 647 | INLINE bool operator REL_OP( \ 648 | C_TYPE op2, \ 649 | const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ 650 | return op2 REL_OP bool(op); \ 651 | } 652 | 653 | #define AF_REF_REL_OPS_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \ 654 | AF_REF_REL_OP_WITH_INT(>, C_TYPE, (_AP_W2), (_AP_S2)) \ 655 | AF_REF_REL_OP_WITH_INT(<, C_TYPE, (_AP_W2), (_AP_S2)) \ 656 | AF_REF_REL_OP_WITH_INT(>=, C_TYPE, (_AP_W2), (_AP_S2)) \ 657 | AF_REF_REL_OP_WITH_INT(<=, C_TYPE, (_AP_W2), (_AP_S2)) \ 658 | AF_REF_REL_OP_WITH_INT(==, C_TYPE, (_AP_W2), (_AP_S2)) \ 659 | AF_REF_REL_OP_WITH_INT(!=, C_TYPE, (_AP_W2), (_AP_S2)) 660 | 661 | AF_REF_REL_OPS_WITH_INT(bool, 1, false) 662 | AF_REF_REL_OPS_WITH_INT(char, 8, CHAR_IS_SIGNED) 663 | AF_REF_REL_OPS_WITH_INT(signed char, 8, true) 664 | AF_REF_REL_OPS_WITH_INT(unsigned char, 8, false) 665 | AF_REF_REL_OPS_WITH_INT(short, _AP_SIZE_short, true) 666 | AF_REF_REL_OPS_WITH_INT(unsigned short, _AP_SIZE_short, false) 667 | AF_REF_REL_OPS_WITH_INT(int, _AP_SIZE_int, true) 668 | AF_REF_REL_OPS_WITH_INT(unsigned int, _AP_SIZE_int, false) 669 | AF_REF_REL_OPS_WITH_INT(long, _AP_SIZE_long, true) 670 | AF_REF_REL_OPS_WITH_INT(unsigned long, _AP_SIZE_long, false) 671 | AF_REF_REL_OPS_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) 672 | AF_REF_REL_OPS_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) 673 | 674 | #undef AF_REF_REL_OP_INT 675 | #undef AF_REF_REL_OPS_WITH_INT 676 | 677 | #define AF_REF_REL_OP_WITH_AP_INT(REL_OP) \ 678 | template \ 680 | INLINE bool operator REL_OP( \ 681 | const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ 682 | const ap_int_base<_AP_W2, _AP_S>& op2) { \ 683 | return ap_int_base<_AP_W, false>(op) REL_OP op2; \ 684 | } \ 685 | template \ 687 | INLINE bool operator REL_OP( \ 688 | const ap_int_base<_AP_W2, _AP_S2>& op2, \ 689 | const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ 690 | return op2 REL_OP ap_int_base<_AP_W, false>(op); \ 691 | } \ 692 | template \ 694 | INLINE bool operator REL_OP( \ 695 | const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ 696 | const ap_int_base<_AP_W2, _AP_S2>& op2) { \ 697 | return ap_int_base<1, false>(op) REL_OP op2; \ 698 | } \ 699 | template \ 701 | INLINE bool operator REL_OP( \ 702 | const ap_int_base<_AP_W2, _AP_S2>& op2, \ 703 | const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ 704 | return op2 REL_OP ap_int_base<1, false>(op); \ 705 | } 706 | 707 | AF_REF_REL_OP_WITH_AP_INT(>) 708 | AF_REF_REL_OP_WITH_AP_INT(<) 709 | AF_REF_REL_OP_WITH_AP_INT(>=) 710 | AF_REF_REL_OP_WITH_AP_INT(<=) 711 | AF_REF_REL_OP_WITH_AP_INT(==) 712 | AF_REF_REL_OP_WITH_AP_INT(!=) 713 | 714 | #endif // ifndef __cplusplus 715 | 716 | #endif // ifndef __AP_FIXED_REF_H__ 717 | 718 | // -*- cpp -*- 719 | -------------------------------------------------------------------------------- /include/ap_fixed_special.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_FIXED_SPECIAL_H__ 18 | #define __AP_FIXED_SPECIAL_H__ 19 | 20 | #ifndef __AP_FIXED_H__ 21 | #error "Only ap_fixed.h and ap_int.h can be included directly in user code." 22 | #endif 23 | 24 | #ifndef __SYNTHESIS__ 25 | #include 26 | #include 27 | #endif 28 | // FIXME AP_AUTOCC cannot handle many standard headers, so declare instead of 29 | // include. 30 | // #include 31 | namespace std { 32 | template class complex; 33 | } 34 | 35 | /* 36 | TODO: Modernize the code using C++11/C++14 37 | 1. constexpr http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0415r0.html 38 | 2. move constructor 39 | */ 40 | 41 | namespace std { 42 | /* 43 | Specialize std::complex to zero initialization ap_fixed. 44 | 45 | To reduce the area cost, ap_fixed is not zero initialized, just like basic 46 | types float or double. However, libstdc++ provides specialization for float, 47 | double and long double, initializing image part to 0 when not specified. 48 | 49 | This has become a difficulty in switching legacy code from these C types to 50 | ap_fixed. To ease the tranform of legacy code, we have to implement 51 | specialization of std::complex<> for our type. 52 | 53 | As ap_fixed is a template, it is impossible to specialize only the methods 54 | that causes default initialization of value type in std::complex<>. An 55 | explicit full specialization of the template class has to be done, covering 56 | all the member functions and operators of std::complex<> as specified 57 | in standard 26.2.4 and 26.2.5. 58 | */ 59 | template 60 | class complex > { 61 | public: 62 | typedef ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> _Tp; 63 | typedef _Tp value_type; 64 | 65 | // 26.2.4/1 66 | // Constructor without argument 67 | // Default initialize, so that in dataflow, the variable is only written once. 68 | complex() : _M_real(_Tp()), _M_imag(_Tp()) {} 69 | // Constructor with ap_fixed. 70 | // Zero initialize image part when not specified, so that `C(1) == C(1,0)` 71 | complex(const _Tp &__r, const _Tp &__i = _Tp(0)) 72 | : _M_real(__r), _M_imag(__i) {} 73 | 74 | // Constructor with another complex number 75 | template 76 | complex(const complex<_Up> &__z) : _M_real(__z.real()), _M_imag(__z.imag()) {} 77 | 78 | #if __cplusplus >= 201103L 79 | const _Tp& real() const { return _M_real; } 80 | const _Tp& imag() const { return _M_imag; } 81 | #else 82 | _Tp& real() { return _M_real; } 83 | const _Tp& real() const { return _M_real; } 84 | _Tp& imag() { return _M_imag; } 85 | const _Tp& imag() const { return _M_imag; } 86 | #endif 87 | 88 | void real(_Tp __val) { _M_real = __val; } 89 | 90 | void imag(_Tp __val) { _M_imag = __val; } 91 | 92 | // Assign this complex number with ap_fixed. 93 | // Zero initialize image poarrt, so that `C c; c = 1; c == C(1,0);` 94 | complex<_Tp> &operator=(const _Tp __t) { 95 | _M_real = __t; 96 | _M_imag = _Tp(0); 97 | return *this; 98 | } 99 | 100 | // 26.2.5/1 101 | // Add ap_fixed to this complex number. 102 | complex<_Tp> &operator+=(const _Tp &__t) { 103 | _M_real += __t; 104 | return *this; 105 | } 106 | 107 | // 26.2.5/3 108 | // Subtract ap_fixed from this complex number. 109 | complex<_Tp> &operator-=(const _Tp &__t) { 110 | _M_real -= __t; 111 | return *this; 112 | } 113 | 114 | // 26.2.5/5 115 | // Multiply this complex number by ap_fixed. 116 | complex<_Tp> &operator*=(const _Tp &__t) { 117 | _M_real *= __t; 118 | _M_imag *= __t; 119 | return *this; 120 | } 121 | 122 | // 26.2.5/7 123 | // Divide this complex number by ap_fixed. 124 | complex<_Tp> &operator/=(const _Tp &__t) { 125 | _M_real /= __t; 126 | _M_imag /= __t; 127 | return *this; 128 | } 129 | 130 | // Assign complex number to this complex number. 131 | template 132 | complex<_Tp> &operator=(const complex<_Up> &__z) { 133 | _M_real = __z.real(); 134 | _M_imag = __z.imag(); 135 | return *this; 136 | } 137 | 138 | // 26.2.5/9 139 | // Add complex number to this. 140 | template 141 | complex<_Tp> &operator+=(const complex<_Up> &__z) { 142 | _M_real += __z.real(); 143 | _M_imag += __z.imag(); 144 | return *this; 145 | } 146 | 147 | // 26.2.5/11 148 | // Subtract complex number from this. 149 | template 150 | complex<_Tp> &operator-=(const complex<_Up> &__z) { 151 | _M_real -= __z.real(); 152 | _M_imag -= __z.imag(); 153 | return *this; 154 | } 155 | 156 | // 26.2.5/13 157 | // Multiply this by complex number. 158 | template 159 | complex<_Tp> &operator*=(const complex<_Up> &__z) { 160 | const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag(); 161 | _M_imag = _M_real * __z.imag() + _M_imag * __z.real(); 162 | _M_real = __r; 163 | return *this; 164 | } 165 | 166 | // 26.2.5/15 167 | // Divide this by complex number. 168 | template 169 | complex<_Tp> &operator/=(const complex<_Up> &__z) { 170 | complex<_Tp> cj (__z.real(), -__z.imag()); 171 | complex<_Tp> a = (*this) * cj; 172 | complex<_Tp> b = cj * __z; 173 | _M_real = a.real() / b.real(); 174 | _M_imag = a.imag() / b.real(); 175 | return *this; 176 | } 177 | 178 | private: 179 | _Tp _M_real; 180 | _Tp _M_imag; 181 | 182 | }; // class complex > 183 | 184 | /* 185 | Non-member operations 186 | These operations are not required by standard in 26.2.6, but libstdc++ 187 | defines them for 188 | float, double or long double's specialization. 189 | */ 190 | // Compare complex number with ap_fixed. 191 | template 192 | inline bool operator==( 193 | const complex > &__x, 194 | const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> &__y) { 195 | return __x.real() == __y && 196 | __x.imag() == 0; 197 | } 198 | 199 | // Compare ap_fixed with complex number. 200 | template 201 | inline bool operator==( 202 | const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> &__x, 203 | const complex > &__y) { 204 | return __x == __y.real() && 205 | 0 == __y.imag(); 206 | } 207 | 208 | // Compare complex number with ap_fixed. 209 | template 210 | inline bool operator!=( 211 | const complex > &__x, 212 | const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> &__y) { 213 | return __x.real() != __y || 214 | __x.imag() != 0; 215 | } 216 | 217 | // Compare ap_fixed with complex number. 218 | template 219 | inline bool operator!=( 220 | const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> &__x, 221 | const complex > &__y) { 222 | return __x != __y.real() || 223 | 0 != __y.imag(); 224 | } 225 | 226 | } // namespace std 227 | 228 | #endif // ifndef __AP_FIXED_SPECIAL_H__ 229 | 230 | // -*- cpp -*- 231 | -------------------------------------------------------------------------------- /include/ap_int.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2019 Xilinx, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __AP_INT_H__ 18 | #define __AP_INT_H__ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | //--------------------------------------------------------------- 25 | 26 | /// Sign Arbitrary Precision Type. 27 | template 28 | struct ap_int : ap_int_base<_AP_W, true> { 29 | typedef ap_int_base<_AP_W, true> Base; 30 | // Constructor 31 | INLINE ap_int() : Base() {} 32 | 33 | // Copy ctor 34 | INLINE ap_int(const ap_int& op) { Base::V = op.V; } 35 | 36 | template 37 | INLINE ap_int(const ap_int<_AP_W2>& op) { 38 | Base::V = op.V; 39 | } 40 | 41 | template 42 | INLINE ap_int(const volatile ap_int<_AP_W2>& op) { 43 | Base::V = op.V; 44 | } 45 | 46 | template 47 | INLINE ap_int(const ap_uint<_AP_W2>& op) { 48 | Base::V = op.V; 49 | } 50 | 51 | template 52 | INLINE ap_int(const volatile ap_uint<_AP_W2>& op) { 53 | Base::V = op.V; 54 | } 55 | 56 | template 57 | INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref) : Base(ref) {} 58 | 59 | template 60 | INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref) : Base(ref) {} 61 | 62 | template 63 | INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref) 64 | : Base(ref) {} 65 | 66 | template 68 | INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 69 | : Base((ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>)op) {} 70 | 71 | template 73 | INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 74 | : Base((ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>)op) { 75 | } 76 | 77 | template 79 | INLINE ap_int( 80 | const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 81 | : Base((ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>)op) {} 82 | 83 | template 85 | INLINE ap_int( 86 | const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 87 | : Base((ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>)op) { 88 | } 89 | 90 | template 91 | INLINE ap_int(const ap_int_base<_AP_W2, _AP_S2>& op) { 92 | Base::V = op.V; 93 | } 94 | 95 | template 97 | INLINE ap_int( 98 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 99 | : Base(op) {} 100 | 101 | template 103 | INLINE ap_int( 104 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 105 | : Base(op) {} 106 | 107 | template 109 | INLINE ap_int( 110 | const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 111 | : Base(op) {} 112 | 113 | #define CTOR(TYPE) \ 114 | INLINE ap_int(TYPE val) { Base::V = val; } 115 | CTOR(bool) 116 | CTOR(char) 117 | CTOR(signed char) 118 | CTOR(unsigned char) 119 | CTOR(short) 120 | CTOR(unsigned short) 121 | CTOR(int) 122 | CTOR(unsigned int) 123 | CTOR(long) 124 | CTOR(unsigned long) 125 | CTOR(ap_slong) 126 | CTOR(ap_ulong) 127 | #undef CTOR 128 | ap_int(double val) : Base(val) {} 129 | ap_int(float val) : Base(val) {} 130 | #if _AP_ENABLE_HALF_ == 1 131 | ap_int(half val) : Base(val) {} 132 | #endif 133 | 134 | // ap_int_base will guess radix if radix is not provided. 135 | INLINE ap_int(const char* s) : Base(s) {} 136 | 137 | INLINE ap_int(const char* s, signed char rd) : Base(s, rd) {} 138 | 139 | // Assignment 140 | /* ctor will be used when right is not of proper type. */ 141 | 142 | INLINE ap_int& operator=(const ap_int<_AP_W>& op2) { 143 | Base::V = op2.V; 144 | return *this; 145 | } 146 | 147 | /* cannot bind volatile reference to non-volatile type. */ 148 | INLINE ap_int& operator=(const volatile ap_int<_AP_W>& op2) { 149 | Base::V = op2.V; 150 | return *this; 151 | } 152 | 153 | /* cannot return volatile *this. */ 154 | INLINE void operator=(const ap_int<_AP_W>& op2) volatile { Base::V = op2.V; } 155 | 156 | INLINE void operator=(const volatile ap_int<_AP_W>& op2) volatile { 157 | Base::V = op2.V; 158 | } 159 | 160 | }; // struct ap_int. 161 | 162 | //--------------------------------------------------------------- 163 | 164 | /// Unsigned Arbitrary Precision Type. 165 | template 166 | struct ap_uint : ap_int_base<_AP_W, false> { 167 | typedef ap_int_base<_AP_W, false> Base; 168 | // Constructor 169 | INLINE ap_uint() : Base() {} 170 | 171 | // Copy ctor 172 | INLINE ap_uint(const ap_uint& op) { Base::V = op.V; } 173 | 174 | template 175 | INLINE ap_uint(const ap_uint<_AP_W2>& op) { 176 | Base::V = op.V; 177 | } 178 | 179 | template 180 | INLINE ap_uint(const ap_int<_AP_W2>& op) { 181 | Base::V = op.V; 182 | } 183 | 184 | template 185 | INLINE ap_uint(const volatile ap_uint<_AP_W2>& op) { 186 | Base::V = op.V; 187 | } 188 | 189 | template 190 | INLINE ap_uint(const volatile ap_int<_AP_W2>& op) { 191 | Base::V = op.V; 192 | } 193 | 194 | template 195 | INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref) : Base(ref) {} 196 | 197 | template 198 | INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref) : Base(ref) {} 199 | 200 | template 201 | INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref) 202 | : Base(ref) {} 203 | 204 | template 206 | INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 207 | : Base((ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>)op) {} 208 | 209 | template 211 | INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 212 | : Base((ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>)op) { 213 | } 214 | 215 | template 217 | INLINE ap_uint( 218 | const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 219 | : Base((ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>)op) {} 220 | 221 | template 223 | INLINE ap_uint( 224 | const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) 225 | : Base((ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>)op) { 226 | } 227 | 228 | template 229 | INLINE ap_uint(const ap_int_base<_AP_W2, _AP_S2>& op) { 230 | Base::V = op.V; 231 | } 232 | 233 | template 235 | INLINE ap_uint( 236 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 237 | : Base(op) {} 238 | 239 | template 241 | INLINE ap_uint( 242 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 243 | : Base(op) {} 244 | 245 | template 247 | INLINE ap_uint( 248 | const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) 249 | : Base(op) {} 250 | 251 | #define CTOR(TYPE) \ 252 | INLINE ap_uint(TYPE val) { Base::V = val; } 253 | CTOR(bool) 254 | CTOR(char) 255 | CTOR(signed char) 256 | CTOR(unsigned char) 257 | CTOR(short) 258 | CTOR(unsigned short) 259 | CTOR(int) 260 | CTOR(unsigned int) 261 | CTOR(long) 262 | CTOR(unsigned long) 263 | CTOR(ap_slong) 264 | CTOR(ap_ulong) 265 | #undef CTOR 266 | ap_uint(double val) : Base(val) {} 267 | ap_uint(float val) : Base(val) {} 268 | #if _AP_ENABLE_HALF_ == 1 269 | ap_uint(half val) : Base(val) {} 270 | #endif 271 | 272 | // ap_int_base will guess radix if radix is not provided. 273 | INLINE ap_uint(const char* s) : Base(s) {} 274 | 275 | INLINE ap_uint(const char* s, signed char rd) : Base(s, rd) {} 276 | 277 | // Assignment 278 | /* XXX ctor will be used when right is not of proper type. */ 279 | 280 | INLINE ap_uint& operator=(const ap_uint<_AP_W>& op2) { 281 | Base::V = op2.V; 282 | return *this; 283 | } 284 | 285 | /* cannot bind volatile reference to non-volatile type. */ 286 | INLINE ap_uint& operator=(const volatile ap_uint<_AP_W>& op2) { 287 | Base::V = op2.V; 288 | return *this; 289 | } 290 | 291 | /* cannot return volatile *this. */ 292 | INLINE void operator=(const ap_uint<_AP_W>& op2) volatile { Base::V = op2.V; } 293 | 294 | INLINE void operator=(const volatile ap_uint<_AP_W>& op2) volatile { 295 | Base::V = op2.V; 296 | } 297 | 298 | }; // struct ap_uint. 299 | 300 | #define ap_bigint ap_int 301 | #define ap_biguint ap_uint 302 | 303 | #if !defined(__SYNTHESIS__) && (defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED)) 304 | // XXX sc_trace overload for ap_fixed is already included in 305 | // "ap_sysc/ap_sc_extras.h", so do not define in synthesis. 306 | template 307 | INLINE void sc_trace(sc_core::sc_trace_file* tf, const ap_int<_AP_W>& op, 308 | const std::string& name) { 309 | if (tf) tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); 310 | } 311 | 312 | template 313 | INLINE void sc_trace(sc_core::sc_trace_file* tf, const ap_uint<_AP_W>& op, 314 | const std::string& name) { 315 | if (tf) tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); 316 | } 317 | #endif // System C sim 318 | 319 | #include 320 | 321 | #endif // ifndef __AP_INT_H__ else 322 | 323 | // FIXME user should include ap_fixed.h when using ap_fixed. 324 | // to avoid circular inclusion, must check whether this is required by 325 | // ap_fixed.h 326 | #ifndef __AP_FIXED_H__ 327 | #include 328 | #endif 329 | 330 | // -*- cpp -*- 331 | -------------------------------------------------------------------------------- /include/ap_int_ref.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2019 Xilinx, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __AP_INT_REF_H__ 18 | #define __AP_INT_REF_H__ 19 | 20 | #ifndef __AP_INT_H__ 21 | #error "Only ap_fixed.h and ap_int.h can be included directly in user code." 22 | #endif 23 | 24 | #ifndef __cplusplus 25 | #error "C++ is required to include this header file" 26 | 27 | #else 28 | 29 | #ifndef __SYNTHESIS__ 30 | #include 31 | #endif 32 | 33 | /* Concatination reference. 34 | ---------------------------------------------------------------- 35 | */ 36 | template 37 | struct ap_concat_ref { 38 | enum { 39 | _AP_WR = _AP_W1 + _AP_W2, 40 | }; 41 | 42 | _AP_T1& mbv1; 43 | _AP_T2& mbv2; 44 | 45 | INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& ref) 46 | : mbv1(ref.mbv1), mbv2(ref.mbv2) {} 47 | 48 | INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2) : mbv1(bv1), mbv2(bv2) {} 49 | 50 | template 51 | INLINE ap_concat_ref& operator=(const ap_int_base<_AP_W3, _AP_S3>& val) { 52 | ap_int_base<_AP_W1 + _AP_W2, false> vval(val); 53 | int W_ref1 = mbv1.length(); 54 | int W_ref2 = mbv2.length(); 55 | ap_int_base<_AP_W1, false> Part1; 56 | Part1.V = _AP_ROOT_op_get_range(vval.V, W_ref2, W_ref1 + W_ref2 - 1); 57 | mbv1.set(Part1); 58 | ap_int_base<_AP_W2, false> Part2; 59 | Part2.V = _AP_ROOT_op_get_range(vval.V, 0, W_ref2 - 1); 60 | mbv2.set(Part2); 61 | return *this; 62 | } 63 | 64 | // assign op from hls supported C integral types. 65 | // FIXME disabled to support legacy code directly assign from sc_signal 66 | //template 67 | //INLINE typename _ap_type::enable_if<_ap_type::is_integral::value, 68 | // ap_concat_ref&>::type 69 | //operator=(T val) { 70 | // ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); 71 | // return operator=(tmpVal); 72 | //} 73 | #define ASSIGN_WITH_CTYPE(_Tp) \ 74 | INLINE ap_concat_ref& operator=(_Tp val) { \ 75 | ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); \ 76 | return operator=(tmpVal); \ 77 | } 78 | 79 | ASSIGN_WITH_CTYPE(bool) 80 | ASSIGN_WITH_CTYPE(char) 81 | ASSIGN_WITH_CTYPE(signed char) 82 | ASSIGN_WITH_CTYPE(unsigned char) 83 | ASSIGN_WITH_CTYPE(short) 84 | ASSIGN_WITH_CTYPE(unsigned short) 85 | ASSIGN_WITH_CTYPE(int) 86 | ASSIGN_WITH_CTYPE(unsigned int) 87 | ASSIGN_WITH_CTYPE(long) 88 | ASSIGN_WITH_CTYPE(unsigned long) 89 | ASSIGN_WITH_CTYPE(ap_slong) 90 | ASSIGN_WITH_CTYPE(ap_ulong) 91 | #if _AP_ENABLE_HALF_ == 1 92 | ASSIGN_WITH_CTYPE(half) 93 | #endif 94 | ASSIGN_WITH_CTYPE(float) 95 | ASSIGN_WITH_CTYPE(double) 96 | 97 | #undef ASSIGN_WITH_CTYPE 98 | 99 | // Be explicit to prevent it from being deleted, as field d_bv 100 | // is of reference type. 101 | INLINE ap_concat_ref& operator=( 102 | const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { 103 | ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); 104 | return operator=(tmpVal); 105 | } 106 | 107 | template 108 | INLINE ap_concat_ref& operator=( 109 | const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { 110 | ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); 111 | return operator=(tmpVal); 112 | } 113 | 114 | template 115 | INLINE ap_concat_ref& operator=(const ap_bit_ref<_AP_W3, _AP_S3>& val) { 116 | ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); 117 | return operator=(tmpVal); 118 | } 119 | template 120 | INLINE ap_concat_ref& operator=(const ap_range_ref<_AP_W3, _AP_S3>& val) { 121 | ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); 122 | return operator=(tmpVal); 123 | } 124 | 125 | template 127 | INLINE ap_concat_ref& operator=( 128 | const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& val) { 129 | return operator=((const ap_int_base<_AP_W3, false>)(val)); 130 | } 131 | 132 | template 134 | INLINE ap_concat_ref& operator=( 135 | const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& 136 | val) { 137 | return operator=(val.to_ap_int_base()); 138 | } 139 | 140 | template 142 | INLINE ap_concat_ref& operator=( 143 | const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& val) { 144 | return operator=((ap_ulong)(bool)(val)); 145 | } 146 | 147 | INLINE operator ap_int_base<_AP_WR, false>() const { return get(); } 148 | 149 | INLINE operator ap_ulong() const { return get().to_uint64(); } 150 | 151 | template 152 | INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, 153 | ap_range_ref<_AP_W3, _AP_S3> > 154 | operator,(const ap_range_ref<_AP_W3, _AP_S3> &a2) { 155 | return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, 156 | ap_range_ref<_AP_W3, _AP_S3> >( 157 | *this, const_cast&>(a2)); 158 | } 159 | 160 | template 161 | INLINE 162 | ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_int_base<_AP_W3, _AP_S3> > 163 | operator,(ap_int_base<_AP_W3, _AP_S3> &a2) { 164 | return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, 165 | ap_int_base<_AP_W3, _AP_S3> >(*this, a2); 166 | } 167 | 168 | template 169 | INLINE 170 | ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_int_base<_AP_W3, _AP_S3> > 171 | operator,(volatile ap_int_base<_AP_W3, _AP_S3> &a2) { 172 | return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, 173 | ap_int_base<_AP_W3, _AP_S3> >( 174 | *this, const_cast&>(a2)); 175 | } 176 | 177 | template 178 | INLINE 179 | ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_int_base<_AP_W3, _AP_S3> > 180 | operator,(const ap_int_base<_AP_W3, _AP_S3> &a2) { 181 | return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, 182 | ap_int_base<_AP_W3, _AP_S3> >( 183 | *this, const_cast&>(a2)); 184 | } 185 | 186 | template 187 | INLINE 188 | ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_int_base<_AP_W3, _AP_S3> > 189 | operator,(const volatile ap_int_base<_AP_W3, _AP_S3> &a2) { 190 | // FIXME op's life does not seem long enough 191 | ap_int_base<_AP_W3, _AP_S3> op(a2); 192 | return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, 193 | ap_int_base<_AP_W3, _AP_S3> >( 194 | *this, const_cast&>(op)); 195 | } 196 | 197 | template 198 | INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > 199 | operator,(const ap_bit_ref<_AP_W3, _AP_S3> &a2) { 200 | return ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> >( 201 | *this, const_cast&>(a2)); 202 | } 203 | 204 | template 205 | INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4, 206 | ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> > 207 | operator,(const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> &a2) { 208 | return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4, 209 | ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> >( 210 | *this, const_cast&>(a2)); 211 | } 212 | 213 | template 215 | INLINE ap_concat_ref< 216 | _AP_WR, ap_concat_ref, _AP_W3, 217 | af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > 218 | operator,( 219 | const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> &a2) { 220 | return ap_concat_ref< 221 | _AP_WR, ap_concat_ref, _AP_W3, 222 | af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >( 223 | *this, 224 | const_cast< 225 | af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>&>(a2)); 226 | } 227 | 228 | template 230 | INLINE 231 | ap_concat_ref<_AP_WR, ap_concat_ref, 1, 232 | af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > 233 | operator,(const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> 234 | &a2) { 235 | return ap_concat_ref< 236 | _AP_WR, ap_concat_ref, 1, 237 | af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >( 238 | *this, 239 | const_cast&>( 240 | a2)); 241 | } 242 | 243 | template 244 | INLINE ap_int_base operator&( 245 | const ap_int_base<_AP_W3, _AP_S3>& a2) { 246 | return get() & a2; 247 | } 248 | 249 | template 250 | INLINE ap_int_base operator|( 251 | const ap_int_base<_AP_W3, _AP_S3>& a2) { 252 | return get() | a2; 253 | } 254 | 255 | template 256 | INLINE ap_int_base operator^( 257 | const ap_int_base<_AP_W3, _AP_S3>& a2) { 258 | return get() ^ a2; 259 | } 260 | 261 | #if 0 262 | template 263 | INLINE ap_int_base slice() { 264 | ap_int_base<_AP_WR, false> bv = get(); 265 | return bv.slice(); 266 | } 267 | #endif 268 | 269 | INLINE ap_int_base<_AP_WR, false> get() const { 270 | ap_int_base<_AP_WR, false> tmpVal(0); 271 | int W_ref1 = mbv1.length(); 272 | int W_ref2 = mbv2.length(); 273 | ap_int_base<_AP_W2, false> v2(mbv2); 274 | ap_int_base<_AP_W1, false> v1(mbv1); 275 | tmpVal.V = _AP_ROOT_op_set_range(tmpVal.V, 0, W_ref2 - 1, v2.V); 276 | tmpVal.V = 277 | _AP_ROOT_op_set_range(tmpVal.V, W_ref2, W_ref1 + W_ref2 - 1, v1.V); 278 | return tmpVal; 279 | } 280 | 281 | template 282 | INLINE void set(const ap_int_base<_AP_W3, false>& val) { 283 | ap_int_base<_AP_W1 + _AP_W2, false> vval(val); 284 | int W_ref1 = mbv1.length(); 285 | int W_ref2 = mbv2.length(); 286 | ap_int_base<_AP_W1, false> tmpVal1; 287 | tmpVal1.V = _AP_ROOT_op_get_range(vval.V, W_ref2, W_ref1 + W_ref2 - 1); 288 | mbv1.set(tmpVal1); 289 | ap_int_base<_AP_W2, false> tmpVal2; 290 | tmpVal2.V = _AP_ROOT_op_get_range(vval.V, 0, W_ref2 - 1); 291 | mbv2.set(tmpVal2); 292 | } 293 | 294 | INLINE int length() const { return mbv1.length() + mbv2.length(); } 295 | }; // struct ap_concat_ref 296 | 297 | /* Range (slice) reference. 298 | ---------------------------------------------------------------- 299 | */ 300 | template 301 | struct ap_range_ref { 302 | // struct ssdm_int or its sim model. 303 | // TODO make it possible to reference to ap_fixed_base/ap_fixed/ap_ufixed 304 | // and then we can retire af_range_ref. 305 | typedef ap_int_base<_AP_W, _AP_S> ref_type; 306 | ref_type& d_bv; 307 | int l_index; 308 | int h_index; 309 | 310 | public: 311 | INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref) 312 | : d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} 313 | 314 | INLINE ap_range_ref(ref_type* bv, int h, int l) 315 | : d_bv(*bv), l_index(l), h_index(h) {} 316 | 317 | INLINE ap_range_ref(const ref_type* bv, int h, int l) 318 | : d_bv(*const_cast(bv)), l_index(l), h_index(h) {} 319 | 320 | INLINE operator ap_int_base<_AP_W, false>() const { 321 | ap_int_base<_AP_W, false> ret; 322 | ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); 323 | return ret; 324 | } 325 | 326 | INLINE operator ap_ulong() const { return to_uint64(); } 327 | 328 | /// @name assign operators 329 | // @{ 330 | 331 | // FIXME disabled to work-around lagacy code assigning from sc_signal, 332 | // which dependes on implicit type conversion. 333 | // 334 | // /// assign from hls supported C integral types. 335 | // template 336 | // INLINE typename _ap_type::enable_if<_ap_type::is_integral::value, 337 | // ap_range_ref&>::type 338 | // operator=(T val) { 339 | // ap_int_base<_AP_W, false> tmp(val); 340 | // d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); 341 | // return *this; 342 | // } 343 | #define ASSIGN_WITH_CTYPE(_Tp) \ 344 | INLINE ap_range_ref& operator=(_Tp val) { \ 345 | ap_int_base<_AP_W, false> tmp(val); \ 346 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); \ 347 | return *this; \ 348 | } 349 | 350 | ASSIGN_WITH_CTYPE(bool) 351 | ASSIGN_WITH_CTYPE(char) 352 | ASSIGN_WITH_CTYPE(signed char) 353 | ASSIGN_WITH_CTYPE(unsigned char) 354 | ASSIGN_WITH_CTYPE(short) 355 | ASSIGN_WITH_CTYPE(unsigned short) 356 | ASSIGN_WITH_CTYPE(int) 357 | ASSIGN_WITH_CTYPE(unsigned int) 358 | ASSIGN_WITH_CTYPE(long) 359 | ASSIGN_WITH_CTYPE(unsigned long) 360 | ASSIGN_WITH_CTYPE(ap_slong) 361 | ASSIGN_WITH_CTYPE(ap_ulong) 362 | #if _AP_ENABLE_HALF_ == 1 363 | ASSIGN_WITH_CTYPE(half) 364 | #endif 365 | ASSIGN_WITH_CTYPE(float) 366 | ASSIGN_WITH_CTYPE(double) 367 | 368 | #undef ASSIGN_WITH_CTYPE 369 | 370 | /// assign using string. XXX crucial for cosim. 371 | INLINE ap_range_ref& operator=(const char* val) { 372 | const ap_int_base<_AP_W, false> tmp(val); // XXX figure out radix 373 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); 374 | return *this; 375 | } 376 | 377 | /// assign from ap_int_base. 378 | template 379 | INLINE ap_range_ref& operator=(const ap_int_base<_AP_W2, _AP_S2>& val) { 380 | ap_int_base<_AP_W, false> tmp(val); 381 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); 382 | return *this; 383 | } 384 | 385 | /// copy assign operator 386 | // XXX Be explicit to prevent it from being deleted, as field d_bv 387 | // is of reference type. 388 | INLINE ap_range_ref& operator=(const ap_range_ref& val) { 389 | return operator=((const ap_int_base<_AP_W, false>)val); 390 | } 391 | 392 | /// assign from range reference to ap_int_base. 393 | template 394 | INLINE ap_range_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) { 395 | return operator=((const ap_int_base<_AP_W2, false>)val); 396 | } 397 | 398 | /// assign from bit reference to ap_int_base. 399 | template 400 | INLINE ap_range_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) { 401 | return operator=((ap_ulong)(bool)(val)); 402 | } 403 | 404 | /// assign from ap_fixed_base. 405 | template 407 | INLINE ap_range_ref& operator=( 408 | const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& 409 | val) { 410 | return operator=(val.to_ap_int_base()); 411 | } 412 | 413 | /// assign from range reference to ap_fixed_base. 414 | template 416 | INLINE ap_range_ref& operator=( 417 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { 418 | return operator=((const ap_int_base<_AP_W2, false>)val); 419 | } 420 | 421 | /// assign from bit reference to ap_fixed_base. 422 | template 424 | INLINE ap_range_ref& operator=( 425 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { 426 | return operator=((ap_ulong)(bool)(val)); 427 | } 428 | 429 | /// assign from compound reference. 430 | template 431 | INLINE ap_range_ref& operator=( 432 | const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { 433 | return operator=((const ap_int_base<_AP_W2 + _AP_W3, false>)(val)); 434 | } 435 | // @} 436 | 437 | template 438 | INLINE 439 | ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > 440 | operator,(const ap_range_ref<_AP_W2, _AP_S2> &a2) { 441 | return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, 442 | ap_range_ref<_AP_W2, _AP_S2> >( 443 | *this, const_cast&>(a2)); 444 | } 445 | 446 | template 447 | INLINE 448 | ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 449 | operator,(ap_int_base<_AP_W2, _AP_S2> &a2) { 450 | return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, 451 | ap_int_base<_AP_W2, _AP_S2> >(*this, a2); 452 | } 453 | 454 | INLINE 455 | ap_concat_ref<_AP_W, ap_range_ref, _AP_W, ap_int_base<_AP_W, _AP_S> > 456 | operator,(ap_int_base<_AP_W, _AP_S>& a2) { 457 | return ap_concat_ref<_AP_W, ap_range_ref, _AP_W, 458 | ap_int_base<_AP_W, _AP_S> >(*this, a2); 459 | } 460 | 461 | template 462 | INLINE 463 | ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 464 | operator,(volatile ap_int_base<_AP_W2, _AP_S2> &a2) { 465 | return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, 466 | ap_int_base<_AP_W2, _AP_S2> >( 467 | *this, const_cast&>(a2)); 468 | } 469 | 470 | template 471 | INLINE 472 | ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 473 | operator,(const ap_int_base<_AP_W2, _AP_S2> &a2) { 474 | return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, 475 | ap_int_base<_AP_W2, _AP_S2> >( 476 | *this, const_cast&>(a2)); 477 | } 478 | 479 | template 480 | INLINE 481 | ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 482 | operator,(const volatile ap_int_base<_AP_W2, _AP_S2> &a2) { 483 | return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, 484 | ap_int_base<_AP_W2, _AP_S2> >( 485 | *this, const_cast&>(a2)); 486 | } 487 | 488 | template 489 | INLINE ap_concat_ref<_AP_W, ap_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > 490 | operator,(const ap_bit_ref<_AP_W2, _AP_S2> &a2) { 491 | return ap_concat_ref<_AP_W, ap_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> >( 492 | *this, const_cast&>(a2)); 493 | } 494 | 495 | template 496 | INLINE ap_concat_ref<_AP_W, ap_range_ref, _AP_W2 + _AP_W3, 497 | ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > 498 | operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { 499 | return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2 + _AP_W3, 500 | ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( 501 | *this, const_cast&>(a2)); 502 | } 503 | 504 | template 506 | INLINE ap_concat_ref< 507 | _AP_W, ap_range_ref, _AP_W2, 508 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > 509 | operator,( 510 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> a2) { 511 | return ap_concat_ref< 512 | _AP_W, ap_range_ref, _AP_W2, 513 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( 514 | *this, 515 | const_cast< 516 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&>(a2)); 517 | } 518 | 519 | template 521 | INLINE 522 | ap_concat_ref<_AP_W, ap_range_ref, 1, 523 | af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > 524 | operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> 525 | &a2) { 526 | return ap_concat_ref< 527 | _AP_W, ap_range_ref, 1, 528 | af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( 529 | *this, 530 | const_cast&>( 531 | a2)); 532 | } 533 | 534 | template 535 | INLINE bool operator==(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 536 | ap_int_base<_AP_W, false> lop(*this); 537 | ap_int_base<_AP_W2, false> hop(op2); 538 | return lop == hop; 539 | } 540 | 541 | template 542 | INLINE bool operator!=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 543 | return !(operator==(op2)); 544 | } 545 | 546 | template 547 | INLINE bool operator<(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 548 | ap_int_base<_AP_W, false> lop(*this); 549 | ap_int_base<_AP_W2, false> hop(op2); 550 | return lop < hop; 551 | } 552 | 553 | template 554 | INLINE bool operator<=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 555 | ap_int_base<_AP_W, false> lop(*this); 556 | ap_int_base<_AP_W2, false> hop(op2); 557 | return lop <= hop; 558 | } 559 | 560 | template 561 | INLINE bool operator>(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 562 | return !(operator<=(op2)); 563 | } 564 | 565 | template 566 | INLINE bool operator>=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { 567 | return !(operator<(op2)); 568 | } 569 | 570 | template 571 | INLINE ap_range_ref<_AP_W, _AP_S>& operator|=( 572 | const ap_range_ref<_AP_W2, _AP_S2>& op2) { 573 | (this->d_bv).V |= (op2.d_bv).V; 574 | return *this; 575 | }; 576 | 577 | template 578 | INLINE ap_range_ref<_AP_W, _AP_S>& operator|=( 579 | const ap_int_base<_AP_W2, _AP_S2>& op2) { 580 | (this->d_bv).V |= op2.V; 581 | return *this; 582 | }; 583 | 584 | template 585 | INLINE ap_range_ref<_AP_W, _AP_S>& operator&=( 586 | const ap_range_ref<_AP_W2, _AP_S2>& op2) { 587 | (this->d_bv).V &= (op2.d_bv).V; 588 | return *this; 589 | }; 590 | 591 | template 592 | INLINE ap_range_ref<_AP_W, _AP_S>& operator&=( 593 | const ap_int_base<_AP_W2, _AP_S2>& op2) { 594 | (this->d_bv).V &= op2.V; 595 | return *this; 596 | }; 597 | 598 | template 599 | INLINE ap_range_ref<_AP_W, _AP_S>& operator^=( 600 | const ap_range_ref<_AP_W2, _AP_S2>& op2) { 601 | (this->d_bv).V ^= (op2.d_bv).V; 602 | return *this; 603 | }; 604 | 605 | template 606 | INLINE ap_range_ref<_AP_W, _AP_S>& operator^=( 607 | const ap_int_base<_AP_W2, _AP_S2>& op2) { 608 | (this->d_bv).V ^= op2.V; 609 | return *this; 610 | }; 611 | 612 | INLINE ap_int_base<_AP_W, false> get() const { 613 | ap_int_base<_AP_W, false> ret; 614 | ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); 615 | return ret; 616 | } 617 | 618 | template 619 | INLINE void set(const ap_int_base<_AP_W2, false>& val) { 620 | d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V); 621 | } 622 | 623 | INLINE int length() const { 624 | return h_index >= l_index ? h_index - l_index + 1 : l_index - h_index + 1; 625 | } 626 | 627 | INLINE int to_int() const { 628 | return (int)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 629 | } 630 | 631 | INLINE unsigned to_uint() const { 632 | return (unsigned)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 633 | } 634 | 635 | INLINE long to_long() const { 636 | return (long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 637 | } 638 | 639 | INLINE unsigned long to_ulong() const { 640 | return (unsigned long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 641 | } 642 | 643 | INLINE ap_slong to_int64() const { 644 | return (ap_slong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 645 | } 646 | 647 | INLINE ap_ulong to_uint64() const { 648 | return (ap_ulong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); 649 | } 650 | 651 | INLINE bool and_reduce() const { 652 | bool ret = true; 653 | bool reverse = l_index > h_index; 654 | unsigned low = reverse ? h_index : l_index; 655 | unsigned high = reverse ? l_index : h_index; 656 | for (unsigned i = low; i != high; ++i) { 657 | #ifdef __SYNTHESIS__ 658 | #pragma HLS unroll 659 | #endif 660 | ret &= _AP_ROOT_op_get_bit(d_bv.V, i); 661 | } 662 | return ret; 663 | } 664 | 665 | INLINE bool or_reduce() const { 666 | bool ret = false; 667 | bool reverse = l_index > h_index; 668 | unsigned low = reverse ? h_index : l_index; 669 | unsigned high = reverse ? l_index : h_index; 670 | for (unsigned i = low; i != high; ++i) { 671 | #ifdef __SYNTHESIS__ 672 | #pragma HLS unroll 673 | #endif 674 | ret |= _AP_ROOT_op_get_bit(d_bv.V, i); 675 | } 676 | return ret; 677 | } 678 | 679 | INLINE bool xor_reduce() const { 680 | bool ret = false; 681 | bool reverse = l_index > h_index; 682 | unsigned low = reverse ? h_index : l_index; 683 | unsigned high = reverse ? l_index : h_index; 684 | for (unsigned i = low; i != high; ++i) { 685 | #ifdef __SYNTHESIS__ 686 | #pragma HLS unroll 687 | #endif 688 | ret ^= _AP_ROOT_op_get_bit(d_bv.V, i); 689 | } 690 | return ret; 691 | } 692 | #ifndef __SYNTHESIS__ 693 | std::string to_string(signed char radix = 2) const { 694 | ap_int_base<_AP_W, false> ret; 695 | ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); 696 | return ret.to_string(radix); 697 | } 698 | #else 699 | // XXX HLS will delete this in synthesis 700 | INLINE char* to_string(signed char radix = 2) const { 701 | return 0; 702 | } 703 | #endif 704 | }; // struct ap_range_ref 705 | 706 | // XXX apcc cannot handle global std::ios_base::Init() brought in by 707 | #ifndef AP_AUTOCC 708 | #ifndef __SYNTHESIS__ 709 | template 710 | INLINE std::ostream& operator<<(std::ostream& os, 711 | const ap_range_ref<_AP_W, _AP_S>& x) { 712 | std::ios_base::fmtflags ff = std::cout.flags(); 713 | if (ff & std::cout.hex) { 714 | os << x.to_string(16); // don't print sign 715 | } else if (ff & std::cout.oct) { 716 | os << x.to_string(8); // don't print sign 717 | } else { 718 | os << x.to_string(10); 719 | } 720 | return os; 721 | } 722 | #endif // ifndef __SYNTHESIS__ 723 | 724 | #ifndef __SYNTHESIS__ 725 | template 726 | INLINE std::istream& operator>>(std::istream& in, 727 | ap_range_ref<_AP_W, _AP_S>& op) { 728 | std::string str; 729 | in >> str; 730 | op = ap_int_base<_AP_W, _AP_S>(str.c_str()); 731 | return in; 732 | } 733 | #endif // ifndef __SYNTHESIS__ 734 | #endif // ifndef AP_AUTOCC 735 | 736 | /* Bit reference. 737 | ---------------------------------------------------------------- 738 | */ 739 | template 740 | struct ap_bit_ref { 741 | // struct ssdm_int or its sim model. 742 | // TODO make it possible to reference to ap_fixed_base/ap_fixed/ap_ufixed 743 | // and then we can retire af_bit_ref. 744 | typedef ap_int_base<_AP_W, _AP_S> ref_type; 745 | ref_type& d_bv; 746 | int d_index; 747 | 748 | public: 749 | // copy ctor 750 | INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref) 751 | : d_bv(ref.d_bv), d_index(ref.d_index) {} 752 | 753 | INLINE ap_bit_ref(ref_type* bv, int index = 0) : d_bv(*bv), d_index(index) {} 754 | 755 | INLINE ap_bit_ref(const ref_type* bv, int index = 0) 756 | : d_bv(*const_cast(bv)), d_index(index) {} 757 | 758 | INLINE operator bool() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } 759 | INLINE bool to_bool() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } 760 | 761 | // assign op from hls supported C integral types. 762 | // FIXME disabled to support sc_signal. 763 | // NOTE this used to be unsigned long long. 764 | //template 765 | //INLINE typename _ap_type::enable_if<_ap_type::is_integral::value, 766 | // ap_bit_ref&>::type 767 | //operator=(T val) { 768 | // d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, val); 769 | // return *this; 770 | //} 771 | #define ASSIGN_WITH_CTYPE(_Tp) \ 772 | INLINE ap_bit_ref& operator=(_Tp val) { \ 773 | d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, val); \ 774 | return *this; \ 775 | } 776 | 777 | ASSIGN_WITH_CTYPE(bool) 778 | ASSIGN_WITH_CTYPE(char) 779 | ASSIGN_WITH_CTYPE(signed char) 780 | ASSIGN_WITH_CTYPE(unsigned char) 781 | ASSIGN_WITH_CTYPE(short) 782 | ASSIGN_WITH_CTYPE(unsigned short) 783 | ASSIGN_WITH_CTYPE(int) 784 | ASSIGN_WITH_CTYPE(unsigned int) 785 | ASSIGN_WITH_CTYPE(long) 786 | ASSIGN_WITH_CTYPE(unsigned long) 787 | ASSIGN_WITH_CTYPE(ap_slong) 788 | ASSIGN_WITH_CTYPE(ap_ulong) 789 | 790 | #undef ASSIGN_WITH_CTYPE 791 | 792 | #define ASSIGN_WITH_CTYPE_FP(_Tp) \ 793 | INLINE ap_bit_ref& operator=(_Tp val) { \ 794 | bool tmp_val = val; \ 795 | d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index,tmp_val); \ 796 | return *this; \ 797 | } 798 | 799 | #if _AP_ENABLE_HALF_ == 1 800 | ASSIGN_WITH_CTYPE_FP(half) 801 | #endif 802 | ASSIGN_WITH_CTYPE_FP(float) 803 | ASSIGN_WITH_CTYPE_FP(double) 804 | 805 | #undef ASSIGN_WITH_CTYPE_FP 806 | 807 | 808 | template 809 | INLINE ap_bit_ref& operator=(const ap_int_base<_AP_W2, _AP_S2>& val) { 810 | return operator=((ap_ulong)(val.V != 0)); 811 | } 812 | 813 | template 814 | INLINE ap_bit_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) { 815 | return operator=((ap_int_base<_AP_W2, false>)val); 816 | } 817 | 818 | // Be explicit to prevent it from being deleted, as field d_bv 819 | // is of reference type. 820 | INLINE ap_bit_ref& operator=(const ap_bit_ref& val) { 821 | return operator=((ap_ulong)(bool)val); 822 | } 823 | 824 | template 825 | INLINE ap_bit_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) { 826 | return operator=((ap_ulong)(bool)val); 827 | } 828 | 829 | template 831 | INLINE ap_bit_ref& operator=( 832 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { 833 | return operator=((const ap_int_base<_AP_W2, false>)val); 834 | } 835 | 836 | template 838 | INLINE ap_bit_ref& operator=( 839 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { 840 | return operator=((ap_ulong)(bool)val); 841 | } 842 | 843 | template 844 | INLINE ap_bit_ref& operator=( 845 | const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { 846 | return operator=((const ap_int_base<_AP_W2 + _AP_W3, false>)val); 847 | } 848 | 849 | template 850 | INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 851 | operator,(ap_int_base<_AP_W2, _AP_S2> &a2) { 852 | return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( 853 | *this, a2); 854 | } 855 | 856 | template 857 | INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 858 | operator,(volatile ap_int_base<_AP_W2, _AP_S2> &a2) { 859 | return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( 860 | *this, const_cast&>(a2)); 861 | } 862 | 863 | template 864 | INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 865 | operator,(const ap_int_base<_AP_W2, _AP_S2> &a2) { 866 | ap_int_base<_AP_W2, _AP_S2> op(a2); 867 | return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( 868 | *this, const_cast&>(op)); 869 | } 870 | 871 | template 872 | INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > 873 | operator,(const volatile ap_int_base<_AP_W2, _AP_S2> &a2) { 874 | ap_int_base<_AP_W2, _AP_S2> op(a2); 875 | return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( 876 | *this, const_cast&>(op)); 877 | } 878 | 879 | template 880 | INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > 881 | operator,(const ap_range_ref<_AP_W2, _AP_S2> &a2) { 882 | return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> >( 883 | *this, const_cast&>(a2)); 884 | } 885 | 886 | template 887 | INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > operator,( 888 | const ap_bit_ref<_AP_W2, _AP_S2> &a2) { 889 | return ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> >( 890 | *this, const_cast&>(a2)); 891 | } 892 | 893 | template 894 | INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2 + _AP_W3, 895 | ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > 896 | operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { 897 | return ap_concat_ref<1, ap_bit_ref, _AP_W2 + _AP_W3, 898 | ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( 899 | *this, const_cast&>(a2)); 900 | } 901 | 902 | template 904 | INLINE ap_concat_ref< 905 | 1, ap_bit_ref, _AP_W2, 906 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > 907 | operator,( 908 | const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { 909 | return ap_concat_ref< 910 | 1, ap_bit_ref, _AP_W2, 911 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( 912 | *this, 913 | const_cast< 914 | af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&>(a2)); 915 | } 916 | 917 | template 919 | INLINE ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, 920 | _AP_Q2, _AP_O2, _AP_N2> > 921 | operator,( 922 | const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { 923 | return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, 924 | _AP_Q2, _AP_O2, _AP_N2> >( 925 | *this, 926 | const_cast&>( 927 | a2)); 928 | } 929 | 930 | template 931 | INLINE bool operator==(const ap_bit_ref<_AP_W2, _AP_S2>& op) { 932 | return get() == op.get(); 933 | } 934 | 935 | template 936 | INLINE bool operator!=(const ap_bit_ref<_AP_W2, _AP_S2>& op) { 937 | return get() != op.get(); 938 | } 939 | 940 | INLINE bool get() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } 941 | 942 | INLINE bool get() { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } 943 | 944 | template 945 | INLINE void set(const ap_int_base<_AP_W3, false>& val) { 946 | operator=(val); 947 | } 948 | 949 | INLINE bool operator~() const { 950 | bool bit = _AP_ROOT_op_get_bit(d_bv.V, d_index); 951 | return bit ? false : true; 952 | } 953 | 954 | INLINE int length() const { return 1; } 955 | 956 | #ifndef __SYNTHESIS__ 957 | std::string to_string() const { return get() ? "1" : "0"; } 958 | #else 959 | // XXX HLS will delete this in synthesis 960 | INLINE char* to_string() const { return 0; } 961 | #endif 962 | }; // struct ap_bit_ref 963 | 964 | /* ap_range_ref with int. 965 | * ------------------------------------------------------------ 966 | */ 967 | // equality and relational operators. 968 | #define REF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ 969 | template \ 970 | INLINE bool operator REL_OP(const ap_range_ref<_AP_W, _AP_S>& op, \ 971 | C_TYPE op2) { \ 972 | return ap_int_base<_AP_W, false>(op) \ 973 | REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ 974 | } \ 975 | template \ 976 | INLINE bool operator REL_OP(const ap_bit_ref<_AP_W, _AP_S>& op, \ 977 | C_TYPE op2) { \ 978 | return bool(op) REL_OP op2; \ 979 | } \ 980 | template \ 981 | INLINE bool operator REL_OP(C_TYPE op2, \ 982 | const ap_bit_ref<_AP_W, _AP_S>& op) { \ 983 | return op2 REL_OP bool(op); \ 984 | } \ 985 | template \ 986 | INLINE bool operator REL_OP( \ 987 | const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1>& op, C_TYPE op2) { \ 988 | return ap_int_base<_AP_W + _AP_W1, false>(op) \ 989 | REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ 990 | } 991 | 992 | // Make the line shorter than 5000 chars 993 | #define REF_REL_WITH_INT_1(C_TYPE, _AP_WI, _AP_SI) \ 994 | REF_REL_OP_WITH_INT(>, C_TYPE, _AP_WI, _AP_SI) \ 995 | REF_REL_OP_WITH_INT(<, C_TYPE, _AP_WI, _AP_SI) \ 996 | REF_REL_OP_WITH_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ 997 | REF_REL_OP_WITH_INT(<=, C_TYPE, _AP_WI, _AP_SI) 998 | 999 | REF_REL_WITH_INT_1(bool, 1, false) 1000 | REF_REL_WITH_INT_1(char, 8, CHAR_IS_SIGNED) 1001 | REF_REL_WITH_INT_1(signed char, 8, true) 1002 | REF_REL_WITH_INT_1(unsigned char, 8, false) 1003 | REF_REL_WITH_INT_1(short, _AP_SIZE_short, true) 1004 | REF_REL_WITH_INT_1(unsigned short, _AP_SIZE_short, false) 1005 | REF_REL_WITH_INT_1(int, _AP_SIZE_int, true) 1006 | REF_REL_WITH_INT_1(unsigned int, _AP_SIZE_int, false) 1007 | REF_REL_WITH_INT_1(long, _AP_SIZE_long, true) 1008 | REF_REL_WITH_INT_1(unsigned long, _AP_SIZE_long, false) 1009 | REF_REL_WITH_INT_1(ap_slong, _AP_SIZE_ap_slong, true) 1010 | REF_REL_WITH_INT_1(ap_ulong, _AP_SIZE_ap_slong, false) 1011 | 1012 | // Make the line shorter than 5000 chars 1013 | #define REF_REL_WITH_INT_2(C_TYPE, _AP_WI, _AP_SI) \ 1014 | REF_REL_OP_WITH_INT(==, C_TYPE, _AP_WI, _AP_SI) \ 1015 | REF_REL_OP_WITH_INT(!=, C_TYPE, _AP_WI, _AP_SI) 1016 | 1017 | REF_REL_WITH_INT_2(bool, 1, false) 1018 | REF_REL_WITH_INT_2(char, 8, CHAR_IS_SIGNED) 1019 | REF_REL_WITH_INT_2(signed char, 8, true) 1020 | REF_REL_WITH_INT_2(unsigned char, 8, false) 1021 | REF_REL_WITH_INT_2(short, _AP_SIZE_short, true) 1022 | REF_REL_WITH_INT_2(unsigned short, _AP_SIZE_short, false) 1023 | REF_REL_WITH_INT_2(int, _AP_SIZE_int, true) 1024 | REF_REL_WITH_INT_2(unsigned int, _AP_SIZE_int, false) 1025 | REF_REL_WITH_INT_2(long, _AP_SIZE_long, true) 1026 | REF_REL_WITH_INT_2(unsigned long, _AP_SIZE_long, false) 1027 | REF_REL_WITH_INT_2(ap_slong, _AP_SIZE_ap_slong, true) 1028 | REF_REL_WITH_INT_2(ap_ulong, _AP_SIZE_ap_slong, false) 1029 | 1030 | #undef REF_REL_OP_WITH_INT 1031 | #undef REF_REL_WITH_INT_1 1032 | #undef REF_REL_WITH_INT_2 1033 | 1034 | #define REF_BIN_OP_WITH_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ 1035 | template \ 1036 | INLINE typename ap_int_base<_AP_W, false>::template RType<_AP_W2, \ 1037 | _AP_S2>::RTYPE \ 1038 | operator BIN_OP(const ap_range_ref<_AP_W, _AP_S>& op, C_TYPE op2) { \ 1039 | return ap_int_base<_AP_W, false>(op) \ 1040 | BIN_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ 1041 | } \ 1042 | template \ 1043 | INLINE typename ap_int_base<_AP_W2, _AP_S2>::template RType<_AP_W, \ 1044 | false>::RTYPE \ 1045 | operator BIN_OP(C_TYPE op2, const ap_range_ref<_AP_W, _AP_S>& op) { \ 1046 | return ap_int_base<_AP_W2, _AP_S2>(op2) \ 1047 | BIN_OP ap_int_base<_AP_W, false>(op); \ 1048 | } 1049 | 1050 | // arithmetic operators. 1051 | #define REF_BIN_OP_WITH_INT_ARITH(C_TYPE, _AP_W2, _AP_S2) \ 1052 | REF_BIN_OP_WITH_INT(+, plus, C_TYPE, (_AP_W2), (_AP_S2)) \ 1053 | REF_BIN_OP_WITH_INT(-, minus, C_TYPE, (_AP_W2), (_AP_S2)) \ 1054 | REF_BIN_OP_WITH_INT(*, mult, C_TYPE, (_AP_W2), (_AP_S2)) \ 1055 | REF_BIN_OP_WITH_INT(/, div, C_TYPE, (_AP_W2), (_AP_S2)) \ 1056 | REF_BIN_OP_WITH_INT(%, mod, C_TYPE, (_AP_W2), (_AP_S2)) 1057 | 1058 | REF_BIN_OP_WITH_INT_ARITH(bool, 1, false) 1059 | REF_BIN_OP_WITH_INT_ARITH(char, 8, CHAR_IS_SIGNED) 1060 | REF_BIN_OP_WITH_INT_ARITH(signed char, 8, true) 1061 | REF_BIN_OP_WITH_INT_ARITH(unsigned char, 8, false) 1062 | REF_BIN_OP_WITH_INT_ARITH(short, _AP_SIZE_short, true) 1063 | REF_BIN_OP_WITH_INT_ARITH(unsigned short, _AP_SIZE_short, false) 1064 | REF_BIN_OP_WITH_INT_ARITH(int, _AP_SIZE_int, true) 1065 | REF_BIN_OP_WITH_INT_ARITH(unsigned int, _AP_SIZE_int, false) 1066 | REF_BIN_OP_WITH_INT_ARITH(long, _AP_SIZE_long, true) 1067 | REF_BIN_OP_WITH_INT_ARITH(unsigned long, _AP_SIZE_long, false) 1068 | REF_BIN_OP_WITH_INT_ARITH(ap_slong, _AP_SIZE_ap_slong, true) 1069 | REF_BIN_OP_WITH_INT_ARITH(ap_ulong, _AP_SIZE_ap_slong, false) 1070 | 1071 | #undef REF_BIN_OP_WITH_INT_ARITH 1072 | 1073 | // bitwise and shift operators 1074 | #define REF_BIN_OP_WITH_INT_BITS(C_TYPE, _AP_W2, _AP_S2) \ 1075 | REF_BIN_OP_WITH_INT(&, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ 1076 | REF_BIN_OP_WITH_INT(|, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ 1077 | REF_BIN_OP_WITH_INT(^, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ 1078 | REF_BIN_OP_WITH_INT(>>, arg1, C_TYPE, (_AP_W2), (_AP_S2)) \ 1079 | REF_BIN_OP_WITH_INT(<<, arg1, C_TYPE, (_AP_W2), (_AP_S2)) 1080 | 1081 | REF_BIN_OP_WITH_INT_BITS(bool, 1, false) 1082 | REF_BIN_OP_WITH_INT_BITS(char, 8, CHAR_IS_SIGNED) 1083 | REF_BIN_OP_WITH_INT_BITS(signed char, 8, true) 1084 | REF_BIN_OP_WITH_INT_BITS(unsigned char, 8, false) 1085 | REF_BIN_OP_WITH_INT_BITS(short, _AP_SIZE_short, true) 1086 | REF_BIN_OP_WITH_INT_BITS(unsigned short, _AP_SIZE_short, false) 1087 | REF_BIN_OP_WITH_INT_BITS(int, _AP_SIZE_int, true) 1088 | REF_BIN_OP_WITH_INT_BITS(unsigned int, _AP_SIZE_int, false) 1089 | REF_BIN_OP_WITH_INT_BITS(long, _AP_SIZE_long, true) 1090 | REF_BIN_OP_WITH_INT_BITS(unsigned long, _AP_SIZE_long, false) 1091 | REF_BIN_OP_WITH_INT_BITS(ap_slong, _AP_SIZE_ap_slong, true) 1092 | REF_BIN_OP_WITH_INT_BITS(ap_ulong, _AP_SIZE_ap_slong, false) 1093 | 1094 | #undef REF_BIN_OP_WITH_INT_BITS 1095 | 1096 | /* ap_range_ref with ap_range_ref 1097 | * ------------------------------------------------------------ 1098 | */ 1099 | #define REF_BIN_OP(BIN_OP, RTYPE) \ 1100 | template \ 1101 | INLINE \ 1102 | typename ap_int_base<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ 1103 | operator BIN_OP(const ap_range_ref<_AP_W, _AP_S>& lhs, \ 1104 | const ap_range_ref<_AP_W2, _AP_S2>& rhs) { \ 1105 | return (lhs.operator ap_int_base<_AP_W, false>())BIN_OP( \ 1106 | rhs.operator ap_int_base<_AP_W2, false>()); \ 1107 | } 1108 | 1109 | REF_BIN_OP(+, plus) 1110 | REF_BIN_OP(-, minus) 1111 | REF_BIN_OP(*, mult) 1112 | REF_BIN_OP(/, div) 1113 | REF_BIN_OP(%, mod) 1114 | REF_BIN_OP(&, logic) 1115 | REF_BIN_OP(|, logic) 1116 | REF_BIN_OP(^, logic) 1117 | REF_BIN_OP(>>, arg1) 1118 | REF_BIN_OP(<<, arg1) 1119 | 1120 | /* ap_concat_ref with ap_concat_ref. 1121 | * ------------------------------------------------------------ 1122 | */ 1123 | 1124 | //************************************************************************ 1125 | // Implement 1126 | // ap_int_base = ap_concat_ref OP ap_concat_ref 1127 | // for operators +, -, *, /, %, >>, <<, &, |, ^ 1128 | // Without these operators the operands are converted to int64 and 1129 | // larger results lose informations (higher order bits). 1130 | // 1131 | // operand OP 1132 | // / | 1133 | // left-concat right-concat 1134 | // / | / | 1135 | // 1136 | // 1137 | // _AP_LW1, _AP_LT1 (width and type of left-concat's left side) 1138 | // _AP_LW2, _AP_LT2 (width and type of left-concat's right side) 1139 | // Similarly for RHS of operand OP: _AP_RW1, AP_RW2, _AP_RT1, _AP_RT2 1140 | // 1141 | // In Verilog 2001 result of concatenation is always unsigned even 1142 | // when both sides are signed. 1143 | //************************************************************************ 1144 | 1145 | #undef SYN_CONCAT_REF_BIN_OP 1146 | 1147 | #define SYN_CONCAT_REF_BIN_OP(BIN_OP, RTYPE) \ 1148 | template \ 1150 | INLINE typename ap_int_base<_AP_LW1 + _AP_LW2, false>::template RType< \ 1151 | _AP_RW1 + _AP_RW2, false>::RTYPE \ 1152 | operator BIN_OP( \ 1153 | const ap_concat_ref<_AP_LW1, _AP_LT1, _AP_LW2, _AP_LT2>& lhs, \ 1154 | const ap_concat_ref<_AP_RW1, _AP_RT1, _AP_RW2, _AP_RT2>& rhs) { \ 1155 | return lhs.get() BIN_OP rhs.get(); \ 1156 | } 1157 | 1158 | SYN_CONCAT_REF_BIN_OP(+, plus) 1159 | SYN_CONCAT_REF_BIN_OP(-, minus) 1160 | SYN_CONCAT_REF_BIN_OP(*, mult) 1161 | SYN_CONCAT_REF_BIN_OP(/, div) 1162 | SYN_CONCAT_REF_BIN_OP(%, mod) 1163 | SYN_CONCAT_REF_BIN_OP(&, logic) 1164 | SYN_CONCAT_REF_BIN_OP(|, logic) 1165 | SYN_CONCAT_REF_BIN_OP(^, logic) 1166 | SYN_CONCAT_REF_BIN_OP(>>, arg1) 1167 | SYN_CONCAT_REF_BIN_OP(<<, arg1) 1168 | 1169 | #undef SYN_CONCAT_REF_BIN_OP 1170 | 1171 | #define CONCAT_OP_WITH_INT(C_TYPE, _AP_WI, _AP_SI) \ 1172 | template \ 1173 | INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ 1174 | const ap_int_base<_AP_W, _AP_S> &op1, C_TYPE op2) { \ 1175 | ap_int_base<_AP_WI + _AP_W, false> val(op2); \ 1176 | ap_int_base<_AP_WI + _AP_W, false> ret(op1); \ 1177 | ret <<= _AP_WI; \ 1178 | if (_AP_SI) { \ 1179 | val <<= _AP_W; \ 1180 | val >>= _AP_W; \ 1181 | } \ 1182 | ret |= val; \ 1183 | return ret; \ 1184 | } \ 1185 | template \ 1186 | INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ 1187 | C_TYPE op1, const ap_int_base<_AP_W, _AP_S> &op2) { \ 1188 | ap_int_base<_AP_WI + _AP_W, false> val(op1); \ 1189 | ap_int_base<_AP_WI + _AP_W, false> ret(op2); \ 1190 | if (_AP_S) { \ 1191 | ret <<= _AP_WI; \ 1192 | ret >>= _AP_WI; \ 1193 | } \ 1194 | ret |= val << _AP_W; \ 1195 | return ret; \ 1196 | } \ 1197 | template \ 1198 | INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ 1199 | const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ 1200 | ap_int_base<_AP_WI + _AP_W, false> val(op2); \ 1201 | ap_int_base<_AP_WI + _AP_W, false> ret(op1); \ 1202 | ret <<= _AP_WI; \ 1203 | if (_AP_SI) { \ 1204 | val <<= _AP_W; \ 1205 | val >>= _AP_W; \ 1206 | } \ 1207 | ret |= val; \ 1208 | return ret; \ 1209 | } \ 1210 | template \ 1211 | INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ 1212 | C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ 1213 | ap_int_base<_AP_WI + _AP_W, false> val(op1); \ 1214 | ap_int_base<_AP_WI + _AP_W, false> ret(op2); \ 1215 | int len = op2.length(); \ 1216 | val <<= len; \ 1217 | ret |= val; \ 1218 | return ret; \ 1219 | } \ 1220 | template \ 1221 | INLINE ap_int_base<_AP_WI + 1, false> operator,( \ 1222 | const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ 1223 | ap_int_base<_AP_WI + 1, false> val(op2); \ 1224 | val[_AP_WI] = op1; \ 1225 | return val; \ 1226 | } \ 1227 | template \ 1228 | INLINE ap_int_base<_AP_WI + 1, false> operator,( \ 1229 | C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ 1230 | ap_int_base<_AP_WI + 1, false> val(op1); \ 1231 | val <<= 1; \ 1232 | val[0] = op2; \ 1233 | return val; \ 1234 | } \ 1235 | template \ 1236 | INLINE ap_int_base<_AP_W + _AP_W2 + _AP_WI, false> operator,( \ 1237 | const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) { \ 1238 | ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2); \ 1239 | ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1); \ 1240 | if (_AP_SI) { \ 1241 | val <<= _AP_W + _AP_W2; \ 1242 | val >>= _AP_W + _AP_W2; \ 1243 | } \ 1244 | ret <<= _AP_WI; \ 1245 | ret |= val; \ 1246 | return ret; \ 1247 | } \ 1248 | template \ 1249 | INLINE ap_int_base<_AP_W + _AP_W2 + _AP_WI, false> operator,( \ 1250 | C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) { \ 1251 | ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1); \ 1252 | ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2); \ 1253 | int len = op2.length(); \ 1254 | val <<= len; \ 1255 | ret |= val; \ 1256 | return ret; \ 1257 | } \ 1258 | template \ 1260 | INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ 1261 | const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, \ 1262 | C_TYPE op2) { \ 1263 | ap_int_base<_AP_WI + _AP_W, false> val(op2); \ 1264 | ap_int_base<_AP_WI + _AP_W, false> ret(op1); \ 1265 | if (_AP_SI) { \ 1266 | val <<= _AP_W; \ 1267 | val >>= _AP_W; \ 1268 | } \ 1269 | ret <<= _AP_WI; \ 1270 | ret |= val; \ 1271 | return ret; \ 1272 | } \ 1273 | template \ 1275 | INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ 1276 | C_TYPE op1, \ 1277 | const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op2) { \ 1278 | ap_int_base<_AP_WI + _AP_W, false> val(op1); \ 1279 | ap_int_base<_AP_WI + _AP_W, false> ret(op2); \ 1280 | int len = op2.length(); \ 1281 | val <<= len; \ 1282 | ret |= val; \ 1283 | return ret; \ 1284 | } \ 1285 | template \ 1287 | INLINE ap_int_base<1 + _AP_WI, false> operator,( \ 1288 | const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, \ 1289 | C_TYPE op2) { \ 1290 | ap_int_base<_AP_WI + 1, _AP_SI> val(op2); \ 1291 | val[_AP_WI] = op1; \ 1292 | return val; \ 1293 | } \ 1294 | template \ 1296 | INLINE ap_int_base<1 + _AP_WI, false> operator,( \ 1297 | C_TYPE op1, \ 1298 | const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op2) { \ 1299 | ap_int_base<_AP_WI + 1, _AP_SI> val(op1); \ 1300 | val <<= 1; \ 1301 | val[0] = op2; \ 1302 | return val; \ 1303 | } 1304 | 1305 | CONCAT_OP_WITH_INT(bool, 1, false) 1306 | CONCAT_OP_WITH_INT(char, 8, CHAR_IS_SIGNED) 1307 | CONCAT_OP_WITH_INT(signed char, 8, true) 1308 | CONCAT_OP_WITH_INT(unsigned char, 8, false) 1309 | CONCAT_OP_WITH_INT(short, _AP_SIZE_short, true) 1310 | CONCAT_OP_WITH_INT(unsigned short, _AP_SIZE_short, false) 1311 | CONCAT_OP_WITH_INT(int, _AP_SIZE_int, true) 1312 | CONCAT_OP_WITH_INT(unsigned int, _AP_SIZE_int, false) 1313 | CONCAT_OP_WITH_INT(long, _AP_SIZE_long, true) 1314 | CONCAT_OP_WITH_INT(unsigned long, _AP_SIZE_long, false) 1315 | CONCAT_OP_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) 1316 | CONCAT_OP_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) 1317 | 1318 | #undef CONCAT_OP_WITH_INT 1319 | 1320 | #define CONCAT_SHIFT_WITH_INT(C_TYPE, OP) \ 1321 | template \ 1322 | INLINE ap_uint<_AP_W + _AP_W1> operator OP( \ 1323 | const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ 1324 | return ap_uint<_AP_W + _AP_W1>(lhs).get() OP int(rhs); \ 1325 | } 1326 | 1327 | // FIXME int(rhs) may loose precision. 1328 | 1329 | CONCAT_SHIFT_WITH_INT(int, <<) 1330 | CONCAT_SHIFT_WITH_INT(unsigned int, <<) 1331 | CONCAT_SHIFT_WITH_INT(long, <<) 1332 | CONCAT_SHIFT_WITH_INT(unsigned long, <<) 1333 | CONCAT_SHIFT_WITH_INT(ap_slong, <<) 1334 | CONCAT_SHIFT_WITH_INT(ap_ulong, <<) 1335 | 1336 | CONCAT_SHIFT_WITH_INT(int, >>) 1337 | CONCAT_SHIFT_WITH_INT(unsigned int, >>) 1338 | CONCAT_SHIFT_WITH_INT(long, >>) 1339 | CONCAT_SHIFT_WITH_INT(unsigned long, >>) 1340 | CONCAT_SHIFT_WITH_INT(ap_slong, >>) 1341 | CONCAT_SHIFT_WITH_INT(ap_ulong, >>) 1342 | 1343 | #endif // ifndef __cplusplus 1344 | #endif // ifndef __AP_INT_REF_H__ 1345 | 1346 | // -*- cpp -*- 1347 | -------------------------------------------------------------------------------- /include/ap_int_special.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2019 Xilinx, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __AP_INT_SPECIAL_H__ 18 | #define __AP_INT_SPECIAL_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 __SYNTHESIS__ 25 | #include 26 | #include 27 | #endif 28 | // FIXME AP_AUTOCC cannot handle many standard headers, so declare instead of 29 | // include. 30 | // #include 31 | namespace std { 32 | template class complex; 33 | } 34 | 35 | /* 36 | TODO: Modernize the code using C++11/C++14 37 | 1. constexpr http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0415r0.html 38 | 2. move constructor 39 | */ 40 | 41 | namespace std { 42 | /* 43 | Specialize std::complex to zero initialization ap_int. 44 | 45 | To reduce the area cost, ap_int is not zero initialized, just like basic 46 | types float or double. However, libstdc++ provides specialization for float, 47 | double and long double, initializing image part to 0 when not specified. 48 | 49 | This has become a difficulty in switching legacy code from these C types to 50 | ap_int. To ease the tranform of legacy code, we have to implement 51 | specialization of std::complex<> for our type. 52 | 53 | As ap_int is a template, it is impossible to specialize only the methods 54 | that causes default initialization of value type in std::complex<>. An 55 | explicit full specialization of the template class has to be done, covering 56 | all the member functions and operators of std::complex<> as specified 57 | in standard 26.2.4 and 26.2.5. 58 | */ 59 | template 60 | class complex > { 61 | public: 62 | typedef ap_int<_AP_W> _Tp; 63 | typedef _Tp value_type; 64 | 65 | // 26.2.4/1 66 | // Constructor without argument 67 | // Default initialize, so that in dataflow, the variable is only written once. 68 | complex() : _M_real(_Tp()), _M_imag(_Tp()) {} 69 | // Constructor with ap_int. 70 | // Zero initialize image part when not specified, so that `C(1) == C(1,0)` 71 | complex(const _Tp &__r, const _Tp &__i = _Tp(0)) 72 | : _M_real(__r), _M_imag(__i) {} 73 | 74 | // Constructor with another complex number 75 | template 76 | complex(const complex<_Up> &__z) : _M_real(__z.real()), _M_imag(__z.imag()) {} 77 | 78 | #if __cplusplus >= 201103L 79 | const _Tp& real() const { return _M_real; } 80 | const _Tp& imag() const { return _M_imag; } 81 | #else 82 | _Tp& real() { return _M_real; } 83 | const _Tp& real() const { return _M_real; } 84 | _Tp& imag() { return _M_imag; } 85 | const _Tp& imag() const { return _M_imag; } 86 | #endif 87 | 88 | void real(_Tp __val) { _M_real = __val; } 89 | 90 | void imag(_Tp __val) { _M_imag = __val; } 91 | 92 | // Assign this complex number with ap_int. 93 | // Zero initialize image poarrt, so that `C c; c = 1; c == C(1,0);` 94 | complex<_Tp> &operator=(const _Tp __t) { 95 | _M_real = __t; 96 | _M_imag = _Tp(0); 97 | return *this; 98 | } 99 | 100 | // 26.2.5/1 101 | // Add ap_int to this complex number. 102 | complex<_Tp> &operator+=(const _Tp &__t) { 103 | _M_real += __t; 104 | return *this; 105 | } 106 | 107 | // 26.2.5/3 108 | // Subtract ap_int from this complex number. 109 | complex<_Tp> &operator-=(const _Tp &__t) { 110 | _M_real -= __t; 111 | return *this; 112 | } 113 | 114 | // 26.2.5/5 115 | // Multiply this complex number by ap_int. 116 | complex<_Tp> &operator*=(const _Tp &__t) { 117 | _M_real *= __t; 118 | _M_imag *= __t; 119 | return *this; 120 | } 121 | 122 | // 26.2.5/7 123 | // Divide this complex number by ap_int. 124 | complex<_Tp> &operator/=(const _Tp &__t) { 125 | _M_real /= __t; 126 | _M_imag /= __t; 127 | return *this; 128 | } 129 | 130 | // Assign complex number to this complex number. 131 | template 132 | complex<_Tp> &operator=(const complex<_Up> &__z) { 133 | _M_real = __z.real(); 134 | _M_imag = __z.imag(); 135 | return *this; 136 | } 137 | 138 | // 26.2.5/9 139 | // Add complex number to this. 140 | template 141 | complex<_Tp> &operator+=(const complex<_Up> &__z) { 142 | _M_real += __z.real(); 143 | _M_imag += __z.imag(); 144 | return *this; 145 | } 146 | 147 | // 26.2.5/11 148 | // Subtract complex number from this. 149 | template 150 | complex<_Tp> &operator-=(const complex<_Up> &__z) { 151 | _M_real -= __z.real(); 152 | _M_imag -= __z.imag(); 153 | return *this; 154 | } 155 | 156 | // 26.2.5/13 157 | // Multiply this by complex number. 158 | template 159 | complex<_Tp> &operator*=(const complex<_Up> &__z) { 160 | const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag(); 161 | _M_imag = _M_real * __z.imag() + _M_imag * __z.real(); 162 | _M_real = __r; 163 | return *this; 164 | } 165 | 166 | // 26.2.5/15 167 | // Divide this by complex number. 168 | template 169 | complex<_Tp> &operator/=(const complex<_Up> &__z) { 170 | complex<_Tp> cj (__z.real(), -__z.imag()); 171 | complex<_Tp> a = (*this) * cj; 172 | complex<_Tp> b = cj * __z; 173 | _M_real = a.real() / b.real(); 174 | _M_imag = a.imag() / b.real(); 175 | return *this; 176 | } 177 | 178 | private: 179 | _Tp _M_real; 180 | _Tp _M_imag; 181 | 182 | }; // class complex > 183 | 184 | 185 | /* 186 | Non-member operations 187 | These operations are not required by standard in 26.2.6, but libstdc++ 188 | defines them for 189 | float, double or long double's specialization. 190 | */ 191 | // Compare complex number with ap_int. 192 | template 193 | inline bool operator==(const complex > &__x, const ap_int<_AP_W> &__y) { 194 | return __x.real() == __y && 195 | __x.imag() == 0; 196 | } 197 | 198 | // Compare ap_int with complex number. 199 | template 200 | inline bool operator==(const ap_int<_AP_W> &__x, const complex > &__y) { 201 | return __x == __y.real() && 202 | 0 == __y.imag(); 203 | } 204 | 205 | // Compare complex number with ap_int. 206 | template 207 | inline bool operator!=(const complex > &__x, const ap_int<_AP_W> &__y) { 208 | return __x.real() != __y || 209 | __x.imag() != 0; 210 | } 211 | 212 | // Compare ap_int with complex number. 213 | template 214 | inline bool operator!=(const ap_int<_AP_W> &__x, const complex > &__y) { 215 | return __x != __y.real() || 216 | 0 != __y.imag(); 217 | } 218 | 219 | } // namespace std 220 | 221 | #endif // ifndef __AP_INT_SPECIAL_H__ 222 | 223 | // -*- cpp -*- 224 | --------------------------------------------------------------------------------