├── LICENSE ├── include ├── ac_array.h ├── ac_float_add_tree.h ├── ac_math.h ├── ac_math │ ├── ac_abs.h │ ├── ac_arccos_cordic.h │ ├── ac_arcsin_cordic.h │ ├── ac_atan2_cordic.h │ ├── ac_atan_pwl.h │ ├── ac_atan_pwl_ha.h │ ├── ac_atan_pwl_vha.h │ ├── ac_barrel_shift.h │ ├── ac_chol_d.h │ ├── ac_cholinv.h │ ├── ac_determinant.h │ ├── ac_div.h │ ├── ac_div_v2.h │ ├── ac_elu_pwl.h │ ├── ac_flfx_mul.h │ ├── ac_gelu_pwl.h │ ├── ac_hcordic.h │ ├── ac_inverse_sqrt_pwl.h │ ├── ac_inverse_sqrt_pwl_vha.h │ ├── ac_leading.h │ ├── ac_leading_ones_tmpl.h │ ├── ac_leakyrelu.h │ ├── ac_log_pwl.h │ ├── ac_matrixmul.h │ ├── ac_normalize.h │ ├── ac_pow_pwl.h │ ├── ac_prelu.h │ ├── ac_qrd.h │ ├── ac_random.h │ ├── ac_reciprocal_pwl.h │ ├── ac_reciprocal_pwl_ha.h │ ├── ac_reciprocal_pwl_vha.h │ ├── ac_relu.h │ ├── ac_selu_pwl.h │ ├── ac_shift.h │ ├── ac_sigmoid_pwl.h │ ├── ac_sincos_cordic.h │ ├── ac_sincos_lut.h │ ├── ac_softmax_pwl.h │ ├── ac_softmax_pwl_new.h │ ├── ac_softplus_pwl.h │ ├── ac_softsign_pwl.h │ ├── ac_sqrt.h │ ├── ac_sqrt_pwl.h │ ├── ac_tan_pwl.h │ └── ac_tanh_pwl.h ├── ac_matrix.h └── ac_std_float_add_tree.h ├── lutgen ├── ac_atan_pwl_ha_lutgen.cpp ├── ac_atan_pwl_lutgen.cpp ├── ac_atan_pwl_vha_lutgen.cpp ├── ac_inverse_sqrt_pwl_lutgen.cpp ├── ac_inverse_sqrt_pwl_vha_lutgen.cpp ├── ac_log_pwl_lutgen.cpp ├── ac_pow_pwl_lutgen.cpp ├── ac_reciprocal_pwl_ha_lutgen.cpp ├── ac_reciprocal_pwl_lutgen.cpp ├── ac_reciprocal_pwl_vha_lutgen.cpp ├── ac_sigmoid_pwl_lutgen.cpp ├── ac_sincos_lut_lutgen.cpp ├── ac_sqrt_pwl_lutgen.cpp ├── ac_tan_pwl_lutgen.cpp ├── ac_tanh_pwl_lutgen.cpp └── helper_functions.h ├── pdfdocs ├── ac_math_ref.pdf └── ac_math_relnotes.pdf └── tests ├── Makefile ├── Visual_studio.bat ├── mc_scverify.h ├── rtest_ac_abs.cpp ├── rtest_ac_arccos_cordic.cpp ├── rtest_ac_arcsin_cordic.cpp ├── rtest_ac_array.cpp ├── rtest_ac_atan2_cordic.cpp ├── rtest_ac_atan_pwl.cpp ├── rtest_ac_atan_pwl_ha.cpp ├── rtest_ac_atan_pwl_vha.cpp ├── rtest_ac_barrel_shift.cpp ├── rtest_ac_chol_d.cpp ├── rtest_ac_cholinv.cpp ├── rtest_ac_determinant.cpp ├── rtest_ac_div.cpp ├── rtest_ac_elu_pwl.cpp ├── rtest_ac_exp2_cordic.cpp ├── rtest_ac_exp_cordic.cpp ├── rtest_ac_exp_pwl.cpp ├── rtest_ac_flfx_mul.cpp ├── rtest_ac_float_add_tree.cpp ├── rtest_ac_gelu_pwl.cpp ├── rtest_ac_inverse_sqrt_pwl.cpp ├── rtest_ac_inverse_sqrt_pwl_vha.cpp ├── rtest_ac_leading.cpp ├── rtest_ac_leakyrelu.cpp ├── rtest_ac_log2_cordic.cpp ├── rtest_ac_log2_pwl.cpp ├── rtest_ac_log_cordic.cpp ├── rtest_ac_log_pwl.cpp ├── rtest_ac_matrix.cpp ├── rtest_ac_matrixmul.cpp ├── rtest_ac_normalize.cpp ├── rtest_ac_pow2_pwl.cpp ├── rtest_ac_pow_cordic.cpp ├── rtest_ac_pow_pwl.cpp ├── rtest_ac_prelu.cpp ├── rtest_ac_qrd.cpp ├── rtest_ac_reciprocal_pwl.cpp ├── rtest_ac_reciprocal_pwl_ha.cpp ├── rtest_ac_reciprocal_pwl_vha.cpp ├── rtest_ac_relu.cpp ├── rtest_ac_selu_pwl.cpp ├── rtest_ac_shift.cpp ├── rtest_ac_sigmoid_pwl.cpp ├── rtest_ac_sincos_cordic.cpp ├── rtest_ac_sincos_lut.cpp ├── rtest_ac_softmax_pwl.cpp ├── rtest_ac_softmax_pwl_new.cpp ├── rtest_ac_softplus_pwl.cpp ├── rtest_ac_softsign_pwl.cpp ├── rtest_ac_sqrt.cpp ├── rtest_ac_sqrt_pwl.cpp ├── rtest_ac_tan_pwl.cpp ├── rtest_ac_tanh_pwl.cpp ├── rtest_signed_ac_div_v2.cpp └── rtest_unsigned_ac_div_v2.cpp /include/ac_array.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // ************************************************************************* 32 | // File : ac_array.h 33 | // 34 | // Created on: Jun 14, 2017 35 | // 36 | // Description: Container class for multi-dimensional (up to 3-D) arrays. 37 | // Using this container class simplifies copy while still providing 38 | // the common C-style array index operator []. 39 | // The number of dimension sizes specified in the template parameterization 40 | // determines the number of dimensions of the ac_array object: 41 | // ac_array x; // a 1-D array of integers with 4 elements 42 | // ac_array y; // a 2-D array of bools of size [5][6] 43 | // ac_array z; // a 3-D array of size [3][4][5] 44 | // 45 | // The C++ ostream left-shift operator provides pretty-print output: 46 | // cout << z << endl; 47 | // Comparison operators ==, != compare two arrays of the same size. 48 | // Array indexing uses []: 49 | // cout << "element z(2,1,1)=" << z[2][1][1] << endl; 50 | // 51 | // Note: The base class 'ac_array_b' is not intended to be used 52 | // directly - only use ac_array. 53 | // 54 | // Usage: 55 | // Below is a sample design and C++ testbench 56 | // 57 | // #include 58 | // #include 59 | // 60 | // typedef ac_int<8,false> dtype_t; 61 | // 62 | // void design(ac_array a_2Din, dtype_t scale, 63 | // ac_array &a_2Dout) 64 | // { 65 | // for (int i=0; i<3; i++) { 66 | // for (int j=0; j<4; j++) { 67 | // a_2Dout[i][j] = a_2Din[i][j] * scale; 68 | // } 69 | // } 70 | // } 71 | // 72 | // #ifndef __SYNTHESIS__ 73 | // #include 74 | // CCS_MAIN(int argc, char *argv[]) 75 | // { 76 | // ac_array tb_in; 77 | // ac_array tb_out; 78 | // dtype_t scale; 79 | // for (int iteration=1; iteration<10; iteration++) { 80 | // // fill input 2-D array 81 | // for (int i=0; i<3; i++) for (int j=0; j<4; j++) { tb_in[i][j] = iteration*(i*4+j); } 82 | // scale = iteration; 83 | // // debug dump of contents 84 | // std::cout << "Array input: " << tb_in << std::endl; 85 | // CCS_DESIGN(design)(tb_in, scale, tb_out); 86 | // // debug dump of output 87 | // std::cout << "Array output: " << tb_out << std::endl; 88 | // } 89 | // CCS_RETURN(0); 90 | // } 91 | // #endif 92 | // 93 | // ************************************************************************* 94 | 95 | #ifndef _INCLUDED_AC_ARRAY_H_ 96 | #define _INCLUDED_AC_ARRAY_H_ 97 | 98 | #include 99 | #ifdef AC_ARRAY_ASSERT 100 | #include 101 | #define AC_A_ASSERT(cond) ac::ac_assert(__FILE__, __LINE__, #cond, cond) 102 | #else // !AC_ARRAY_ASSERT 103 | #define AC_A_ASSERT(cond) 104 | #endif // AC_ARRAY_ASSERT 105 | 106 | #ifndef __SYNTHESIS__ 107 | #include 108 | #endif 109 | 110 | // Forward declaration 111 | template class ac_array; 112 | 113 | //========================================================================= 114 | // Class: ac_array_b 115 | // 116 | // Description: Base class for n-d array 117 | // This class is not directly used in designs - use ac_array<>. 118 | // 119 | //------------------------------------------------------------------------- 120 | 121 | 122 | template 123 | class ac_array_b 124 | { 125 | public: 126 | typedef T ElemType; 127 | 128 | ac_array_b() {} 129 | virtual ~ac_array_b() {} 130 | 131 | T &operator[] (unsigned i) { 132 | AC_A_ASSERT(i < D); 133 | return d[i]; 134 | } 135 | 136 | const T &operator[] (unsigned i) const { 137 | AC_A_ASSERT(i < D); 138 | return d[i]; 139 | } 140 | 141 | unsigned size() const { return D; } 142 | 143 | void set(const Td &ival) { 144 | for ( unsigned i = 0; i < D; ++i ) { 145 | set(i, ival); 146 | } 147 | } 148 | 149 | void set(unsigned i, const Td &ival) { 150 | AC_A_ASSERT(i < D); 151 | d[i] = ival; 152 | } 153 | 154 | void clearAll(bool dc=false) { 155 | for ( unsigned i = 0; i < D; ++i ) { 156 | clear(i, dc); 157 | } 158 | } 159 | 160 | void clear(unsigned i, bool dc=false) { 161 | AC_A_ASSERT(i < D); 162 | if ( !dc ) { 163 | d[i] = 0; 164 | } else { 165 | Td v; 166 | d[i] = v; 167 | } 168 | } 169 | 170 | // Relational operators - can only compare against 171 | // same sized arrays 172 | bool operator==(const ac_array_b &other) const { 173 | bool equal = true; 174 | for (unsigned i=0; id[i] != other[i]) { 176 | equal = false; 177 | break; 178 | } 179 | } 180 | return equal; 181 | } 182 | 183 | bool operator!=(const ac_array_b &other) const { 184 | return !operator==(other); 185 | } 186 | 187 | public: // data 188 | T d[D]; 189 | }; 190 | 191 | //========================================================================= 192 | // Class: ac_array 193 | // 194 | //------------------------------------------------------------------------- 195 | 196 | template 197 | class ac_array : public ac_array_b< ac_array, T, D1> 198 | { 199 | typedef ac_array_b< ac_array, T, D1> Base; 200 | public: 201 | 202 | ac_array() {} 203 | ac_array(const T &ival) { Base::set(ival); } 204 | virtual ~ac_array() {} 205 | 206 | ac_array &operator= (const T &v) { Base::set(v); return *this; } 207 | }; 208 | 209 | //========================================================================= 210 | // Specialization Class: ac_array for 1 dimension (row) 211 | // 212 | //------------------------------------------------------------------------- 213 | 214 | template 215 | class ac_array : public ac_array_b 216 | { 217 | typedef ac_array_b Base; 218 | public: 219 | ac_array() {} 220 | ac_array(const T &ival) { Base::set(ival); } 221 | virtual ~ac_array() {} 222 | 223 | ac_array &operator= (const T &v) { Base::set(v); return *this; } 224 | }; 225 | 226 | template 227 | class ac_array : public ac_array_b 228 | { 229 | typedef ac_array_b Base; 230 | public: 231 | ac_array() {} 232 | ac_array(const T &ival) { Base::set(ival); } 233 | virtual ~ac_array() {} 234 | 235 | ac_array &operator= (const T &v) { Base::set(v); return *this; } 236 | }; 237 | 238 | //========================================================================= 239 | // Non-synthesis helper functions 240 | // 241 | //------------------------------------------------------------------------- 242 | #ifndef __SYNTHESIS__ 243 | 244 | //======================================================================= 245 | // Pretty-print with ostream operator << 246 | //----------------------------------------------------------------------- 247 | template 248 | std::ostream &operator<<(std::ostream &os, const ac_array_b &a) 249 | { 250 | os << '{'; 251 | for (unsigned i=0; i 258 | inline void sc_trace(sc_trace_file *tf, const ac_array_b &v, const std::string &nm) 259 | { 260 | for (unsigned i=0; i 40 | // ac_abs() 41 | 42 | #include 43 | // ac_arccos_cordic() 44 | 45 | #include 46 | // ac_arcsin_cordic() 47 | 48 | #include 49 | // ac_atan_pwl() 50 | 51 | #include 52 | // ac_atan_pwl_ha() 53 | 54 | #include 55 | // ac_atan2_cordic() 56 | 57 | #include 58 | //ac_barrel_shift() 59 | 60 | #include 61 | // ac_div() 62 | 63 | #include 64 | // ac_log_cordic() 65 | // ac_log2_cordic() 66 | // ac_exp_cordic() 67 | // ac_exp2_cordic() 68 | // ac_pow_cordic() 69 | 70 | #include 71 | // ac_inverse_sqrt_pwl() 72 | 73 | #include 74 | // ac_log_pwl() 75 | // ac_log2_pwl() 76 | 77 | #include 78 | // ac_normalize() 79 | 80 | #include 81 | // ac_pow2_pwl() 82 | // ac_exp_pwl() 83 | 84 | #include 85 | // ac_reciprocal_pwl() 86 | 87 | #include 88 | // ac_reciprocal_pwl_ha() 89 | 90 | #include 91 | // ac_shift_left() 92 | // ac_shift_right() 93 | 94 | #include 95 | // ac_sigmoid_pwl() 96 | 97 | #include 98 | // ac_sincos_cordic() 99 | 100 | #include 101 | // ac_sincos_lut() 102 | 103 | #include 104 | // ac_sqrt() 105 | 106 | #include 107 | // ac_sqrt_pwl() 108 | 109 | #include 110 | // ac_tan_pwl() 111 | 112 | #include 113 | // ac_tanh_pwl() 114 | 115 | #include 116 | // ac_softmax_pwl() 117 | 118 | #include 119 | // add_tree() 120 | // add_tree_ptr() 121 | // block_add_tree() 122 | // block_add_tree_ptr() 123 | 124 | #endif 125 | 126 | -------------------------------------------------------------------------------- /include/ac_math/ac_barrel_shift.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // File: ac_tanh_pwl.h 33 | // 34 | // Description: 35 | // Provides Barrel Shift Right implimentation for ac_int datatype, Barrel Left Shift can 36 | // be conversly implemented with same hardware. 37 | // Usage: 38 | // A sample testbench and its implementation looks like this: 39 | // 40 | // void design( ac_int &data_out, 41 | // ac_int data_inp, 42 | // ac_int< ac::nbits< NB - 1 >::val,false> s_in ){ 43 | // Calling of ac_barrel_shift templetized funtion 44 | // data_out = ac_barrel_shift(data_inp, s_in); 45 | // } 46 | // 47 | // Notes: 48 | // Attempting to call this file with a datatype that is not implemented will 49 | // result in a compile-time error. 50 | // 51 | // Revision History: 52 | // 3.2.4 - Barrel Shift Added 53 | //************************************************************************************************* 54 | 55 | #ifndef __INCLUDED_AC_BARREL_SHIFT__ 56 | #define __INCLUDED_AC_BARREL_SHIFT__ 57 | 58 | #include 59 | //template< int NUM_BITS > ac_int barrel_shift( ac_int , ac_int< ac::nbits< NUM_BITS >::val,false> ); 60 | 61 | // Barrel Shift block is high throughput block to provide optimum latency for Dynamic rotate right shift 62 | // ac_barrel_shift class can be instantiated as a block or Combo-CCore based on requirements 63 | // snippet of funtion instantiation is below 64 | // Shifted_Output = ac_barrel_shift< Number_of_Bits >(Input, Control_Bits); 65 | // IO-port of barrel shifter will be as follows 66 | // Port: 67 | // Data_Input : Number_of_Bits" wide port for input data 68 | // Shift_IN : log2("Number_of_Bits") Bits wide port for right shift number 69 | // Data_Output: Number_of_Bits" wide port for output data 70 | namespace ac_math 71 | { 72 | //CCORE is uniquified and constant propagates the index "i" 73 | //RTL characterization is enabled along with delay contraint to crunch the CCORE 74 | #pragma hls_design ccore 75 | #pragma hls_ccore_type combinational 76 | template< int N_BITS > 77 | void shift_layer(ac_int din_in, ac_int &din_tmp_out, ac_int< ac::nbits< N_BITS >::val,false> s, ac_int< ac::nbits< N_BITS >::val,false> i) 78 | { 79 | ac_int din_tmp; 80 | din_tmp.set_slc(0,din_in); 81 | din_tmp.set_slc(N_BITS,din_in); 82 | if (s[i] == 1) 83 | { din_tmp = (din_tmp >> (1<(0); 85 | } 86 | 87 | //All layers are CCOREd and clocke overhead is set to 0 88 | #pragma hls_design ccore 89 | template< int NUM_BITS > 90 | ac_int ac_barrel_shift(ac_int din, 91 | ac_int< ac::nbits< NUM_BITS - 1 >::val,false> s_in) 92 | { 93 | ac_int< ac::nbits< NUM_BITS -1 >::val,false> s = s_in; 94 | ac_int din_tmp = 0; 95 | din_tmp = din; 96 | #pragma hls_unroll yes 97 | for (int i=0; i< ac::nbits< NUM_BITS -1 >::val; i++) { 98 | shift_layer(din_tmp,din_tmp,s, i); 99 | } 100 | return din_tmp; 101 | } 102 | } //namespace ac_math 103 | #endif 104 | 105 | 106 | -------------------------------------------------------------------------------- /include/ac_math/ac_div_v2.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | /****************************************************************************************** 32 | File: ac_div_v2.h for Unsigned and Signed integers 33 | ******************************************************************************************/ 34 | 35 | /****************************************************************************************** 36 | 37 | Port Description: 38 | + inputs: dividend, divisor 39 | + outputs: quotient and remainder 40 | 41 | 42 | Design Parameters 43 | + NW: Numerator Width 44 | + DW: Denominator Width 45 | + QW: Quotient Width 46 | + RW: Remainder Width 47 | + PW: Pad Width (value to be withing 1-> DW), this determines range of the divisor values the minimum value of the divisor supported. 48 | 49 | Only divisor values above 2^(DW-PW) are supported 50 | if PW=1 , area shall be least, if PW = DW, area shall be maximum. 51 | 52 | * Integer Unsigned 53 | void ac_div(ac_int dividend, ac_int divisor, ac_int "ient, ac_int &remainder) 54 | 55 | Usage: 56 | A sample testbench for unsigned inputs and output look like this: 57 | 58 | #include 59 | using namespace ac_math; 60 | 61 | enum { 62 | MAX_NW = 5, 63 | MAX_DW = 3, 64 | QUO_W = 5, 65 | REM_W = 5, 66 | PAD_W = 1, // Value to be padded to the numerator width, that varies the range of value divisor can accept. 67 | }; 68 | 69 | typedef ac_int num_type; 70 | typedef ac_int den_type; 71 | typedef ac_int quo_type; 72 | typedef ac_int rem_type 73 | 74 | #pragma hls_design top 75 | void project( 76 | const num_type &num, 77 | const den_type &den, 78 | quo_type &quo, 79 | rem_type &rem 80 | ) 81 | { 82 | 83 | //to replicate: quo = num / den and rem= num%den 84 | ac_div(num, den, quo, rem); 85 | } 86 | 87 | #ifndef __SYNTHESIS__ 88 | #include 89 | 90 | CCS_MAIN(int arg, char **argc) 91 | { 92 | num_type num = 32; 93 | den_type den = 6; 94 | quo_type quo; 95 | rem_type rem; 96 | CCS_DESIGN(project)(num, den, quo,rem); 97 | CCS_RETURN (0); 98 | } 99 | #endif 100 | 101 | ********************************************************************************************/ 102 | 103 | #ifndef _INCLUDED_AC_DIV_V2_H_ 104 | #define _INCLUDED_AC_DIV_V2_H_ 105 | 106 | #ifndef __cplusplus 107 | #error C++ is required to include this header file 108 | #endif 109 | 110 | // Include headers for data types supported by these implementations 111 | #include 112 | 113 | // Include header file for ac_shift functions 114 | #include 115 | 116 | template< int NW, int DW, int QW, int RW, int PW> 117 | void ac_div_v2( 118 | ac_int dividend, 119 | ac_int divisor, 120 | ac_int "ient, 121 | ac_int &remainder 122 | ) 123 | { 124 | const unsigned int int_nw=NW+PW; 125 | const unsigned int int_qw=int_nw-DW; 126 | 127 | ac_int min_div_value=0; 128 | min_div_value[DW-PW]=1; 129 | ac_int temp_numer; 130 | ac_int rem; 131 | ac_int quot; 132 | ac_int const_mask; 133 | 134 | const_mask.template set_val(); 135 | 136 | AC_ASSERT(!!divisor, "Division by zero."); 137 | AC_ASSERT(!!(divisor>= min_div_value), "Divisor is Below the range supported by the synthesized design, check for Padding width"); 138 | 139 | temp_numer = (ac_int) dividend; 140 | quot = 0; 141 | #pragma hls_unroll yes 142 | /*UNROLL it to save on latency, Roll it save on Area*/ 143 | AC_DIV_CORE_LOOP :for (ac_int cnt=0; cnt) ((temp_numer<<1)>>int_qw) - (ac_int) divisor; 145 | quot = (rem < 0) ? ((quot<<1)|0) : ((quot<<1)|1); 146 | temp_numer = (rem < 0) ? (temp_numer<<1) : (((ac_int) rem)<>(DW+1))); 147 | } 148 | remainder= (ac_int)(rem>0)? (ac_int)rem : (ac_int)(temp_numer>>int_qw); 149 | quotient = (ac_int)quot; 150 | } 151 | 152 | /****************************************************************************************** 153 | 154 | Port Description: 155 | + inputs: dividend, divisor 156 | + outputs: quotient and remainder 157 | 158 | 159 | Design Parameters 160 | + NW: Numerator Width 161 | + DW: Denominator Width 162 | + QW: Quotient Width 163 | + RW: Remainder Width 164 | + PW: Pad Width (value to be withing 2 to DW), this determines range of the divisor values the minimum value of the divisor supported. 165 | 166 | Range of Divisor Values supported for signed input/output is (-2^(DW-1)/(2^(PW-1) to (2^(DW-1) - 1)/(2^(PW-1) 167 | if PW=2 , area shall be least, if PW = DW, area shall be maximum. 168 | 169 | * Integer Signed 170 | void ac_div(ac_int dividend, ac_int divisor, ac_int "ient, ac_int &remainder) 171 | 172 | 173 | Usage: 174 | A sample testbench for unsigned inputs and output look like this: 175 | 176 | #include 177 | using namespace ac_math; 178 | 179 | enum { 180 | MAX_NW = 5, 181 | MAX_DW = 3, 182 | QUO_W = 5, 183 | REM_W = 5, 184 | PAD_W = 1, // Value to be padded to the numerator width, that varies the range of value divisor can accept. 185 | }; 186 | 187 | typedef ac_int num_type; 188 | typedef ac_int den_type; 189 | typedef ac_int quo_type; 190 | typedef ac_int rem_type 191 | 192 | #pragma hls_design top 193 | void project( 194 | const num_type &num, 195 | const den_type &den, 196 | quo_type &quo, 197 | rem_type &rem 198 | ) 199 | { 200 | //to replicate: quo = num / den and rem= num%den 201 | ac_div(num, den, quo, rem); 202 | } 203 | 204 | #ifndef __SYNTHESIS__ 205 | #include 206 | 207 | CCS_MAIN(int arg, char **argc) 208 | { 209 | num_type num = 32; 210 | den_type den = 6; 211 | quo_type quo; 212 | rem_type rem; 213 | CCS_DESIGN(project)(num, den, quo,rem); 214 | CCS_RETURN (0); 215 | } 216 | #endif 217 | 218 | ********************************************************************************************/ 219 | 220 | template< int NW, int DW, int QW, int RW, int PW > 221 | void ac_div_v2( 222 | ac_int dividend, 223 | ac_int divisor, 224 | ac_int "ient, 225 | ac_int &remainder 226 | ) 227 | { 228 | AC_ASSERT(!!divisor, "Division by zero."); 229 | bool neg_dividend = dividend < 0; 230 | ac_int uN = neg_dividend ? (ac_int) -dividend : (ac_int) dividend; 231 | bool neg_divisor = divisor < 0; 232 | ac_int uD = neg_divisor ? (ac_int) -divisor : (ac_int) divisor; 233 | ac_int uQ; 234 | ac_int uR; 235 | ac_div_v2(uN, uD, uQ, uR); 236 | // std::cout << "Resulting Quotient is: " <(uQ) << " ] "<< std::endl; 237 | 238 | ac_int quotient_temp = neg_dividend == neg_divisor ? (ac_int) uQ : (ac_int) -uQ; 239 | 240 | quotient = quotient_temp; 241 | 242 | // std::cout << divisor << std::endl; 243 | 244 | ac_int rem = neg_dividend ? (ac_int) -uR : (ac_int) uR; 245 | remainder = rem; 246 | } 247 | 248 | #endif 249 | 250 | -------------------------------------------------------------------------------- /include/ac_math/ac_elu_pwl.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // Function: ac_elu_pwl (for ac_fixed) 33 | // 34 | // Description: 35 | // Provides piece-wise linear approximation of the elu function 36 | // for the ac_fixed datatype 37 | // 38 | // Usage: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // typedef ac_fixed<10, 4, false, AC_RND, AC_SAT> input_type; 45 | // typedef ac_fixed<20, 2, false, AC_RND, AC_SAT> output_type; 46 | // 47 | // #pragma hls_design top 48 | // void project( 49 | // const input_type &input, 50 | // output_type &output 51 | // ) 52 | // { 53 | // ac_elu_pwl(input,output); 54 | // } 55 | // 56 | // #ifndef __SYNTHESIS__ 57 | // #include 58 | // 59 | // CCS_MAIN(int arg, char **argc) 60 | // { 61 | // input_type input = 3.5; 62 | // output_type output; 63 | // CCS_DESIGN(project)(input, output); 64 | // CCS_RETURN (0); 65 | // } 66 | // #endif 67 | // 68 | // Notes: 69 | //************************************************************************************************* 70 | 71 | #ifndef _INCLUDED_AC_ELU_PWL_H_ 72 | #define _INCLUDED_AC_ELU_PWL_H_ 73 | 74 | // The below functions use default template parameters, which are only supported by C++11 or later 75 | // compiler standards. Hence, the user should be informed if they are not using those standards. 76 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 77 | #error Please use C++11 or a later standard for compilation. 78 | #endif 79 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 80 | #error Please use Microsoft VS 2019 or a later standard for compilation. 81 | #endif 82 | 83 | #include 84 | // Include headers for data types supported by these implementations 85 | #include 86 | #include 87 | 88 | #if !defined(__SYNTHESIS__) 89 | #include 90 | #include 91 | #include 92 | #include 93 | using namespace std; 94 | #endif 95 | 96 | //========================================================================= 97 | // Function: ac_elu_pwl (for ac_fixed) 98 | // 99 | // Description: 100 | // Elu function for real inputs, passed as ac_fixed 101 | // variables. 102 | // 103 | // Usage: 104 | // See above example for usage. 105 | // 106 | //------------------------------------------------------------------------- 107 | 108 | namespace ac_math 109 | { 110 | template 114 | void ac_elu_pwl( 115 | const ac_fixed &input, 116 | ac_fixed &output, 117 | const ac_fixed &alpha 118 | ) 119 | { 120 | // n_segments_lut and n_frac_bits should be the same as the corresponding values in the ac_fixed 121 | // implementation for ac_exp_pwl. 122 | // The bitwidth calculations which use these constants are designed with a PWL domain of [0, 1) in 123 | // mind. They will still work for other PWL domains, but at a possibly lower-than-optimal accuracy. 124 | // 125 | // NOTE: Change these constants if you change the either of the corresponding values in the 126 | // ac_fixed implementation for the ac_exp_pwl function. 127 | const unsigned n_segments_lut = 4; 128 | const int n_frac_bits = 10; 129 | 130 | const bool is_n_seg_po2 = !bool(n_segments_lut & (n_segments_lut - 1)); 131 | const int extra_f_bits = is_n_seg_po2 ? ac::nbits::val : 0; 132 | 133 | const int I_width = (I<0) ? -I:I; 134 | 135 | // Find type of intermediate variable used to store output of x*log2(e) 136 | typedef class comp_pii_exp::pit_t input_inter_type; 137 | 138 | const int out_pow_width = input_inter_type::width; 139 | const int out_pow_iwidth = input_inter_type::i_width; 140 | 141 | // Since scaling constant is a positive power-of-two, multiplication with it is the same as left-shifting by 2. 142 | // Accordingly, the scaled normalized input will have 2 less fractional bits than the normalized input, provided that this 143 | // number of fractional bits is lesser than n_frac_bits. If not, the number of fractional bits in the scaled input is set to n_frac_bits. 144 | const int sc_input_frac_bits = AC_MAX(1, AC_MIN(n_frac_bits, out_pow_width - out_pow_iwidth - 2)); 145 | 146 | typedef ac_fixed<((out_pow_iwidth + 1)*out_pow_iwidth) + sc_input_frac_bits + n_frac_bits, ((out_pow_iwidth + 1)*out_pow_iwidth), false, AC_TRN, AC_WRAP> out_pow_type; 147 | 148 | out_pow_type out_pow; 149 | 150 | ac_exp_pwl(input, out_pow); 151 | 152 | if (input>=0) { 153 | output = input; 154 | } 155 | else { 156 | output = alpha * (out_pow - ac_fixed<1, 1, false>(1.0)); 157 | } 158 | } 159 | 160 | // The following version enables a return-by-value. 161 | template 165 | T_out ac_elu_pwl(const T_in &input, const T_alpha &alpha) 166 | { 167 | T_out output; 168 | ac_elu_pwl(input, output, alpha); 169 | return output; 170 | } 171 | } 172 | #endif 173 | -------------------------------------------------------------------------------- /include/ac_math/ac_gelu_pwl.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // Function: ac_gelu_pwl (for ac_fixed) 33 | // 34 | // Description: 35 | // Provides piece-wise linear approximation of the gelu function 36 | // for the ac_fixed datatype 37 | // 38 | // Usage: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // typedef ac_fixed<10, 4, false, AC_RND, AC_SAT> input_type; 45 | // typedef ac_fixed<20, 2, false, AC_RND, AC_SAT> output_type; 46 | // 47 | // #pragma hls_design top 48 | // void project( 49 | // const input_type &input, 50 | // output_type &output 51 | // ) 52 | // { 53 | // ac_gelu_pwl(input,output); 54 | // } 55 | // 56 | // #ifndef __SYNTHESIS__ 57 | // #include 58 | // 59 | // CCS_MAIN(int arg, char **argc) 60 | // { 61 | // input_type input = 3.5; 62 | // output_type output; 63 | // CCS_DESIGN(project)(input, output); 64 | // CCS_RETURN (0); 65 | // } 66 | // #endif 67 | // 68 | // Notes: 69 | //************************************************************************************************* 70 | 71 | #ifndef _INCLUDED_AC_GELU_PWL_H_ 72 | #define _INCLUDED_AC_GELU_PWL_H_ 73 | 74 | // The below functions use default template parameters, which are only supported by C++11 or later 75 | // compiler standards. Hence, the user should be informed if they are not using those standards. 76 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 77 | #error Please use C++11 or a later standard for compilation. 78 | #endif 79 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 80 | #error Please use Microsoft VS 2019 or a later standard for compilation. 81 | #endif 82 | 83 | #include 84 | // Include headers for data types supported by these implementations 85 | #include 86 | #include 87 | 88 | #if !defined(__SYNTHESIS__) 89 | #include 90 | #include 91 | #include 92 | #include 93 | using namespace std; 94 | #endif 95 | 96 | //========================================================================= 97 | // Function: ac_gelu_pwl (for ac_fixed) 98 | // 99 | // Description: 100 | // Gelu function for real inputs, passed as ac_fixed 101 | // variables. 102 | // 103 | // Usage: 104 | // See above example for usage. 105 | // 106 | //------------------------------------------------------------------------- 107 | 108 | namespace ac_math 109 | { 110 | template 113 | void ac_gelu_pwl( 114 | const ac_fixed &input, 115 | ac_fixed &output 116 | ) 117 | { 118 | const int n_frac_bits = 10; 119 | 120 | typedef ac_fixed T_out; 121 | 122 | const int tanh_intwidth = ((I input_tanh_type; 125 | 126 | typedef ac_fixed output_tanh_type; 127 | 128 | typedef ac_fixed output_gelu_type; 129 | 130 | ac_fixed<20, 1, false> aconst = 0.7978845608; 131 | 132 | ac_fixed<20, 1, false> bconst = 0.044715; 133 | 134 | ac_fixed<3, 1, false> cconst = 0.5; 135 | 136 | input_tanh_type tanh_input; 137 | 138 | output_tanh_type tanh_output; 139 | 140 | output_gelu_type gelu_output; 141 | 142 | tanh_input = aconst * (input + (bconst * input * input * input)); 143 | 144 | tanh_output = ac_tanh_pwl(tanh_input); 145 | 146 | output = cconst * input * (1 + tanh_output); 147 | 148 | } 149 | 150 | // The following version enables a return-by-value. 151 | template 154 | T_out ac_gelu_pwl(const T_in &input) 155 | { 156 | T_out output; 157 | ac_gelu_pwl(input, output); 158 | return output; 159 | } 160 | } 161 | #endif 162 | -------------------------------------------------------------------------------- /include/ac_math/ac_leading_ones_tmpl.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.6 * 6 | * * 7 | * Release Date : Tue Nov 12 23:14:00 PST 2024 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.6.0 * 10 | * * 11 | * Copyright Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | /************************************************************************** 32 | * * 33 | * Algorithmic C (tm) Math Library * 34 | * * 35 | * Software Version: 3.5 * 36 | * * 37 | * Release Date : Mon Apr 17 23:58:27 PDT 2023 * 38 | * Release Type : Production Release * 39 | * Release Build : 3.5.0 * 40 | * * 41 | * Copyright 2018 Siemens * 42 | * * 43 | ************************************************************************** 44 | * Licensed under the Apache License, Version 2.0 (the "License"); * 45 | * you may not use this file except in compliance with the License. * 46 | * You may obtain a copy of the License at * 47 | * * 48 | * http://www.apache.org/licenses/LICENSE-2.0 * 49 | * * 50 | * Unless required by applicable law or agreed to in writing, software * 51 | * distributed under the License is distributed on an "AS IS" BASIS, * 52 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 53 | * implied. * 54 | * See the License for the specific language governing permissions and * 55 | * limitations under the License. * 56 | ************************************************************************** 57 | * * 58 | * The most recent version of this package is available at github. * 59 | * * 60 | *************************************************************************/ 61 | //***************************************************************************************** 62 | // File: ac_leading_ones_tmpl.h 63 | // 64 | // Description: An example of using C++ template recursion to implement a leading ones 65 | // detection block. Note that this results in single-bit logic, so as it get bigger 66 | // timing will get worse. Placing this in a C-CORE will help as long as it can fit 67 | // in one clock cycle. 68 | // 69 | // Usage: 70 | // 71 | // Notes: 72 | // 73 | // Revision History: 74 | // 3.4.0 - Copied from HLS Bluebook examples 75 | // 76 | //***************************************************************************************** 77 | 78 | #ifndef _INCLUDED_AC_LEADING_ONES_TMPL_H_ 79 | #define _INCLUDED_AC_LEADING_ONES_TMPL_H_ 80 | 81 | #include 82 | 83 | template 84 | bool ac_leading_ones(ac_int &din, 85 | ac_int::val,false> &dout) 86 | { 87 | enum { 88 | P2 = ac::nbits<(N_BITS+1)/2>::val 89 | }; 90 | ac_int upper; 91 | ac_int lower; 92 | ac_int::val,0> idx=0; 93 | ac_int::val,0> idxu=0; 94 | ac_int::val,0> idxl=0; 95 | static bool flag = false; 96 | 97 | upper.set_slc(0, din.template slc(P2)); 98 | lower.set_slc(0, din.template slc(0)); 99 | flag = (din!=0) ? 1 : 0; 100 | if (upper) { 101 | ac_leading_ones(upper,idxu); 102 | idx = idxu | P2; 103 | } else { 104 | ac_leading_ones(lower,idxl); 105 | idx = idxl; 106 | } 107 | dout = idx; 108 | return flag; 109 | } 110 | 111 | template<> 112 | bool ac_leading_ones<1>(ac_int<1,false> &din, 113 | ac_int::val,false> &dout) 114 | { 115 | dout = 0; 116 | return din[0]; 117 | } 118 | 119 | #endif 120 | 121 | -------------------------------------------------------------------------------- /include/ac_math/ac_leakyrelu.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // Function: ac_leakyrelu (for ac_fixed) 33 | // 34 | // Description: 35 | // Provides an implementation for the leakyrelu function 36 | // for the ac_fixed datatype 37 | // 38 | // Usage: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // typedef ac_fixed<10, 4, false, AC_RND, AC_SAT> input_type; 45 | // typedef ac_fixed<11, 4, false, AC_RND, AC_SAT> output_type; 46 | // 47 | // #pragma hls_design top 48 | // void project( 49 | // const input_type &input, 50 | // output_type &output, 51 | // alpha_type &alpha 52 | // ) 53 | // { 54 | // ac_leakyrelu(input,output,alpha); 55 | // } 56 | // 57 | // #ifndef __SYNTHESIS__ 58 | // #include 59 | // 60 | // CCS_MAIN(int arg, char **argc) 61 | // { 62 | // input_type input = 3.5; 63 | // output_type output; 64 | // CCS_DESIGN(project)(input, output, alpha); 65 | // CCS_RETURN (0); 66 | // } 67 | // #endif 68 | // 69 | // Notes: 70 | //************************************************************************************************* 71 | 72 | #ifndef _INCLUDED_AC_LEAKYRELU_H_ 73 | #define _INCLUDED_AC_LEAKYRELU_H_ 74 | 75 | // The below functions use default template parameters, which are only supported by C++11 or later 76 | // compiler standards. Hence, the user should be informed if they are not using those standards. 77 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 78 | #error Please use C++11 or a later standard for compilation. 79 | #endif 80 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 81 | #error Please use Microsoft VS 2019 or a later standard for compilation. 82 | #endif 83 | 84 | #include 85 | // Include headers for data types supported by these implementations 86 | #include 87 | 88 | #if !defined(__SYNTHESIS__) 89 | #include 90 | #include 91 | #include 92 | #include 93 | using namespace std; 94 | #endif 95 | 96 | //========================================================================= 97 | // Function: ac_leakyrelu (for ac_fixed) 98 | // 99 | // Description: 100 | // Selu function for real inputs, passed as ac_fixed 101 | // variables. 102 | // 103 | // Usage: 104 | // See above example for usage. 105 | // 106 | //------------------------------------------------------------------------- 107 | 108 | namespace ac_math 109 | { 110 | template 113 | void ac_leakyrelu(const ac_fixed &input, 114 | ac_fixed &output, 115 | const ac_fixed &alpha 116 | ) 117 | { 118 | if (input>0) 119 | output = input; 120 | else 121 | output = alpha*input; 122 | } 123 | 124 | // The following version enables a return-by-value. 125 | template 128 | T_out ac_leakyrelu(const T_in &input, const T_alpha &alpha) 129 | { 130 | T_out output; 131 | ac_leakyrelu(input, output, alpha); 132 | return output; 133 | } 134 | } 135 | #endif 136 | -------------------------------------------------------------------------------- /include/ac_math/ac_matrixmul.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //******************************************************************************* 32 | // File: ac_matrixmul.h 33 | // 34 | // Description: 35 | // Matrix multiplication for ac_fixed and ac_complex types with full precision 36 | // 37 | // Usage: 38 | // A sample testbench and its implementation look like 39 | // this: 40 | // #include 41 | // #include 42 | // #include 43 | // #include 44 | // 45 | // typedef ac_matrix, M, N> input_type1; 46 | // typedef ac_matrix, N, P> input_type2; 47 | // typedef ac_matrix, M, P> output_type; 48 | // 49 | // #pragma hls_design top 50 | // void CCS_BLOCK(project)( 51 | // const input_type1 &A, 52 | // const input_type2 &B, 53 | // output_type &C 54 | // ) 55 | // { 56 | // ac_matrixmul(A,B,C); 57 | // } 58 | // #ifndef __SYNTHESIS__ 59 | // CCS_MAIN(int argc, char *argv[]) 60 | // { 61 | // input_type1 A; 62 | // input_type2 B; 63 | // output_type C; 64 | // gen_matrix(A, B); 65 | // CCS_DESIGN(project)(A, B, C); 66 | // CCS_RETURN (0); 67 | // } 68 | // #endif 69 | // 70 | // For a more detailed example, please refer to the "ac_matrixmul_tb.cpp" and 71 | // "ac_matrixmul_tb.h" files 72 | // 73 | // Revision History: 74 | // 2.0.10 - Official open-source release as part of the ac_math library. 75 | // 76 | //*************************************************************************** 77 | 78 | #ifndef _INCLUDED_AC_MATRIXMUL_H_ 79 | #define _INCLUDED_AC_MATRIXMUL_H_ 80 | 81 | // Include headers for data types supported by these implementations 82 | #include 83 | #include 84 | #include 85 | 86 | namespace ac_math 87 | { 88 | template 89 | void arraymultiply(const TA A[M][N], const TB B[N][P], TC C[M][P]) 90 | { 91 | MLOOP: 92 | for (unsigned i=0; i::mult T; 96 | typename T::rt_unary::template set::sum add = 0.0; 97 | NLOOP: 98 | for (unsigned k=0; k 116 | void ac_matrixmul(const ac_fixed A[M][N], 117 | const ac_fixed B[N][P], 118 | ac_fixed C[M][P] 119 | ) 120 | { 121 | arraymultiply(A, B, C); 122 | } 123 | 124 | //============================================================================ 125 | // Function: matrix multiplication (for ac_complex) 126 | // 127 | // Usage: 128 | // See above example code for usage. 129 | //------------------------------------------------------------------------- 130 | template 133 | void ac_matrixmul(const ac_complex > A[M][N], 134 | const ac_complex > B[N][P], 135 | ac_complex > C[M][P] 136 | ) 137 | { 138 | arraymultiply(A, B, C); 139 | } 140 | } //namespace ac_math 141 | 142 | //========================================================================= 143 | // Function: ac_matrix_matrixmul 144 | // Helper function for using ac_chol_d on ac_matrix objects 145 | //------------------------------------------------------------------------- 146 | 147 | template 148 | void ac_matrix_matrixmul(const TA &A, const TB &B, TC &C) 149 | { 150 | // Extract 2D array member data, and pass it over to the 2D array implementation. 151 | ac_math::ac_matrixmul(A.m_data, B.m_data, C.m_data); 152 | } 153 | 154 | namespace ac_math 155 | { 156 | //============================================================================ 157 | // Function: matrix multiplication (for ac_matrix) 158 | // 159 | // Usage: 160 | // See above example code for usage. 161 | //------------------------------------------------------------------------- 162 | template 165 | void ac_matrixmul(const ac_matrix , M, N> &A, 166 | const ac_matrix , N, P> &B, 167 | ac_matrix , M, P> &C 168 | ) 169 | 170 | { 171 | ac_matrix_matrixmul(A, B, C); 172 | } 173 | 174 | //============================================================================ 175 | // Function: matrix multiplication (for ac_matrix >) 176 | // 177 | // Usage: 178 | // See above example code for usage. 179 | //------------------------------------------------------------------------- 180 | template 183 | void ac_matrixmul(const ac_matrix >, M, N> &A, 184 | const ac_matrix >, N, P> &B, 185 | ac_matrix >, M, P> &C 186 | ) 187 | { 188 | ac_matrix_matrixmul(A, B, C); 189 | } 190 | }//namespace ac_math 191 | #endif 192 | 193 | -------------------------------------------------------------------------------- /include/ac_math/ac_prelu.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // Function: ac_prelu (for ac_fixed) 33 | // 34 | // Description: 35 | // Provides an implementation for the prelu function 36 | // for the ac_fixed datatype 37 | // 38 | // Usage: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // typedef ac_fixed<10, 4, false, AC_RND, AC_SAT> input_type; 45 | // typedef ac_fixed<11, 4, false, AC_RND, AC_SAT> output_type; 46 | // 47 | // #pragma hls_design top 48 | // void project( 49 | // const input_type &input, 50 | // output_type &output 51 | // ) 52 | // { 53 | // ac_prelu(input,output); 54 | // } 55 | // 56 | // #ifndef __SYNTHESIS__ 57 | // #include 58 | // 59 | // CCS_MAIN(int arg, char **argc) 60 | // { 61 | // input_type input = 3.5; 62 | // output_type output; 63 | // CCS_DESIGN(project)(input, output); 64 | // CCS_RETURN (0); 65 | // } 66 | // #endif 67 | // 68 | // Notes: 69 | //************************************************************************************************* 70 | 71 | #ifndef _INCLUDED_AC_PRELU_H_ 72 | #define _INCLUDED_AC_PRELU_H_ 73 | 74 | // The below functions use default template parameters, which are only supported by C++11 or later 75 | // compiler standards. Hence, the user should be informed if they are not using those standards. 76 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 77 | #error Please use C++11 or a later standard for compilation. 78 | #endif 79 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 80 | #error Please use Microsoft VS 2019 or a later standard for compilation. 81 | #endif 82 | 83 | #include 84 | // Include headers for data types supported by these implementations 85 | #include 86 | 87 | #if !defined(__SYNTHESIS__) 88 | #include 89 | #include 90 | #include 91 | #include 92 | using namespace std; 93 | #endif 94 | 95 | //========================================================================= 96 | // Function: ac_prelu (for ac_fixed) 97 | // 98 | // Description: 99 | // Prelu function for real inputs, passed as ac_fixed 100 | // variables. 101 | // 102 | // Usage: 103 | // See above example for usage. 104 | // 105 | //------------------------------------------------------------------------- 106 | 107 | namespace ac_math 108 | { 109 | template 112 | void ac_prelu( 113 | const ac_fixed &input, 114 | ac_fixed &output, 115 | const ac_fixed &alpha 116 | ) 117 | { 118 | if (input>0) 119 | output = input; 120 | else 121 | output = alpha*input; 122 | } 123 | 124 | // The following version enables a return-by-value. 125 | template 128 | T_out ac_prelu(const T_in &input, const T_alpha &alpha) 129 | { 130 | T_out output; 131 | ac_prelu(input, output, alpha); 132 | return output; 133 | } 134 | } 135 | #endif 136 | -------------------------------------------------------------------------------- /include/ac_math/ac_relu.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // Function: ac_relu (for ac_fixed) 33 | // 34 | // Description: 35 | // Provides an implementation for the relu function 36 | // for the ac_fixed datatype 37 | // 38 | // Usage: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // typedef ac_fixed<10, 4, false, AC_RND, AC_SAT> input_type; 45 | // typedef ac_fixed<11, 4, false, AC_RND, AC_SAT> output_type; 46 | // 47 | // #pragma hls_design top 48 | // void project( 49 | // const input_type &input, 50 | // output_type &output 51 | // ) 52 | // { 53 | // ac_relu(input,output); 54 | // } 55 | // 56 | // #ifndef __SYNTHESIS__ 57 | // #include 58 | // 59 | // CCS_MAIN(int arg, char **argc) 60 | // { 61 | // input_type input = 3.5; 62 | // output_type output; 63 | // CCS_DESIGN(project)(input, output); 64 | // CCS_RETURN (0); 65 | // } 66 | // #endif 67 | // 68 | // Notes: 69 | //************************************************************************************************* 70 | 71 | #ifndef _INCLUDED_AC_RELU_H_ 72 | #define _INCLUDED_AC_RELU_H_ 73 | 74 | // The below functions use default template parameters, which are only supported by C++11 or later 75 | // compiler standards. Hence, the user should be informed if they are not using those standards. 76 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 77 | #error Please use C++11 or a later standard for compilation. 78 | #endif 79 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 80 | #error Please use Microsoft VS 2019 or a later standard for compilation. 81 | #endif 82 | 83 | #include 84 | // Include headers for data types supported by these implementations 85 | #include 86 | 87 | #if !defined(__SYNTHESIS__) 88 | #include 89 | #include 90 | #include 91 | #include 92 | using namespace std; 93 | #endif 94 | 95 | //========================================================================= 96 | // Function: ac_relu (for ac_fixed) 97 | // 98 | // Description: 99 | // Relu function for real inputs, passed as ac_fixed 100 | // variables. 101 | // 102 | // Usage: 103 | // See above example for usage. 104 | // 105 | //------------------------------------------------------------------------- 106 | 107 | namespace ac_math 108 | { 109 | template 111 | void ac_relu( 112 | const ac_fixed &input, 113 | ac_fixed &output 114 | ) 115 | { 116 | output = (input>0)?input:0; 117 | } 118 | 119 | // The following version enables a return-by-value. 120 | template 122 | T_out ac_relu(const T_in &input) 123 | { 124 | T_out output; 125 | ac_relu(input, output); 126 | return output; 127 | } 128 | } 129 | #endif 130 | -------------------------------------------------------------------------------- /include/ac_math/ac_selu_pwl.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // Function: ac_selu_pwl (for ac_fixed) 33 | // 34 | // Description: 35 | // Provides piece-wise linear approximation of the selu function 36 | // for the ac_fixed datatype 37 | // 38 | // Usage: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // typedef ac_fixed<10, 4, false, AC_RND, AC_SAT> input_type; 45 | // typedef ac_fixed<20, 2, false, AC_RND, AC_SAT> output_type; 46 | // 47 | // #pragma hls_design top 48 | // void project( 49 | // const input_type &input, 50 | // output_type &output 51 | // ) 52 | // { 53 | // ac_selu_pwl(input,output); 54 | // } 55 | // 56 | // #ifndef __SYNTHESIS__ 57 | // #include 58 | // 59 | // CCS_MAIN(int arg, char **argc) 60 | // { 61 | // input_type input = 3.5; 62 | // output_type output; 63 | // CCS_DESIGN(project)(input, output); 64 | // CCS_RETURN (0); 65 | // } 66 | // #endif 67 | // 68 | // Notes: 69 | //************************************************************************************************* 70 | 71 | #ifndef _INCLUDED_AC_SELU_PWL_H_ 72 | #define _INCLUDED_AC_SELU_PWL_H_ 73 | 74 | // The below functions use default template parameters, which are only supported by C++11 or later 75 | // compiler standards. Hence, the user should be informed if they are not using those standards. 76 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 77 | #error Please use C++11 or a later standard for compilation. 78 | #endif 79 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 80 | #error Please use Microsoft VS 2019 or a later standard for compilation. 81 | #endif 82 | 83 | #include 84 | // Include headers for data types supported by these implementations 85 | #include 86 | #include 87 | 88 | #if !defined(__SYNTHESIS__) 89 | #include 90 | #include 91 | #include 92 | #include 93 | using namespace std; 94 | #endif 95 | 96 | //========================================================================= 97 | // Function: ac_selu_pwl (for ac_fixed) 98 | // 99 | // Description: 100 | // Selu function for real inputs, passed as ac_fixed 101 | // variables. 102 | // 103 | // Usage: 104 | // See above example for usage. 105 | // 106 | //------------------------------------------------------------------------- 107 | 108 | namespace ac_math 109 | { 110 | template 113 | void ac_selu_pwl( 114 | const ac_fixed &input, 115 | ac_fixed &output 116 | ) 117 | { 118 | typedef ac_fixed T_out; 119 | T_out out_elu; 120 | const int n_frac_bits = 20; // Number of fractional bits 121 | //lambda constant 122 | ac_fixed lambda = 1.0507009873554804934193349852946; 123 | 124 | //alpha constant 125 | ac_fixed alpha = 1.6732632423543772848170429916717; 126 | 127 | if (input>=0) { 128 | output = lambda * input; 129 | } 130 | else { 131 | out_elu = ac_elu_pwl(input, alpha); 132 | output = lambda * out_elu; 133 | } 134 | 135 | 136 | } 137 | 138 | // The following version enables a return-by-value. 139 | template 142 | T_out ac_selu_pwl(const T_in &input) 143 | { 144 | T_out output; 145 | ac_selu_pwl(input, output); 146 | return output; 147 | } 148 | } 149 | #endif 150 | -------------------------------------------------------------------------------- /include/ac_math/ac_softmax_pwl.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //***************************************************************************************** 32 | // File: ac_softmax_pwl.h (for ac_fixed) 33 | // 34 | // Description: Synthesizable softmax function for AC fixed point datatypes. 35 | // Usage: 36 | // Calculation of softmax of an array of real inputs, passed as ac_fixed variables. 37 | // 38 | // Notes: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // const int num_logits_tb = 20; 45 | // 46 | // typedef ac_fixed<16, 8, true, AC_TRN, AC_SAT> input_type; 47 | // typedef ac_fixed<16, 8, false, AC_TRN, AC_SAT> output_type; 48 | // 49 | // #pragma hls_design top 50 | // void project( 51 | // const input_type (&input)[num_logits_tb], 52 | // output_type (&output)[num_logits_tb] 53 | // ) 54 | // { 55 | // ac_softmax_pwl(input,output); 56 | // } 57 | // 58 | // #ifndef __SYNTHESIS__ 59 | // #include 60 | // 61 | // CCS_MAIN(int arg, char **argc) 62 | // { 63 | // input_type input[num_logits_tb]; 64 | // for (int i = 0; i < num_logits_tb; i++) { input[i] = 9 - i; } 65 | // output_type output; 66 | // CCS_DESIGN(project)(input, output); 67 | // CCS_RETURN (0); 68 | // } 69 | // #endif 70 | // 71 | // Notes: 72 | // Attempting to call this function with a type that is not implemented will 73 | // result in a compile-time error. 74 | // 75 | // This file uses the ac_exp_pwl() function from the file ac_pow_pwl.h and the 76 | // ac_reciprocal_pwl() function from the file ac_reciprocal_pwl.h. 77 | // 78 | // Revision History: 79 | // 3.4.3 - dgb - Updated compiler checks to work with MS VS 2019 80 | // 3.3.0 - [CAT-25798] Added CDesignChecker fixes/waivers for code check and Synthesis-simulation mismatch/violations in ac_math PWL and Linear Algebra IPs. 81 | // 3.2.0 - Initial version 82 | // 83 | //***************************************************************************************** 84 | 85 | #ifndef _INCLUDED_AC_SOFTMAX_PWL_H_ 86 | #define _INCLUDED_AC_SOFTMAX_PWL_H_ 87 | 88 | // The function uses default template parameters, which are only supported by C++11 or later 89 | // compiler standards. Hence, the user should be informed if they are not using those standards. 90 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 91 | #error Please use C++11 or a later standard for compilation. 92 | #endif 93 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 94 | #error Please use Microsoft VS 2019 or a later standard for compilation. 95 | #endif 96 | 97 | // Include header for supported datatype. 98 | #include 99 | 100 | // Include headers for required functions 101 | #include 102 | #include 103 | 104 | // Encapsulate within ac_math namespace. 105 | namespace ac_math 106 | { 107 | // or_e: Override the default type assigned to the exponent variable. Use user-supplied type information instead. 108 | // or_r: Same as above, but for the reciprocal variable. 109 | // K: number of input elements. 110 | template 116 | // By declaring the function parameters as references to arrays (i.e. "(&input)[K]" and "(&output)[K]"), we ensure 117 | // that template parameter deduction infers the value of K. 118 | void ac_softmax_pwl( 119 | const ac_fixed (&input)[K], 120 | ac_fixed (&output)[K] 121 | ) 122 | { 123 | // The default number of fractional bits assigned to the exponent variables assumes that the PWL implementation 124 | // has four segments and uses 10 fractional bits to store the slope and intercept values. For any other implementation 125 | // the default number may have to be changed to ensure no loss of precision. 126 | const int exp_frac_bits = or_e ? iW_e - iI_e : AC_MAX(1, AC_MIN(10, W - I - 2)) + 10; 127 | const int exp_int_bits = or_e ? iI_e : int(1.443*double(1 << (I - S))) + 1; 128 | // The default rounding and saturation modes are AC_TRN and AC_WRAP, respectively. 129 | const ac_q_mode exp_Q = or_e ? ac_q_mode(iQ_e) : ac_q_mode(AC_TRN); 130 | const ac_o_mode exp_O = or_e ? ac_o_mode(iO_e) : ac_o_mode(AC_WRAP); 131 | // The below static_assert limits the size the integer width of the exponent variable can reach. 132 | static_assert(exp_int_bits <= 64, "Intermediate bitwidth calculation gives a very large value for integer bits. Consider reducing the number of input integer bits."); 133 | typedef ac_fixed T_exp; 134 | typedef ac_fixed::val, T_exp::i_width + ac::log2_ceil::val, false> T_sum; 135 | 136 | #pragma hls_waive APT 137 | T_exp exp_arr[K]; 138 | // The reciprocal variable is also assigned a default bitwidth based on the default PWL bitwidths and segments (10 fractional bits and 8 segments). 139 | // For any PWL implementation other than the default, these bitwidths may change. 140 | const int recip_W = or_r ? iW_r : T_sum::width + 20; 141 | const int recip_I = or_r ? iI_r : T_sum::width - T_sum::i_width + 1; 142 | const ac_q_mode recip_Q = or_r ? ac_q_mode(iQ_r) : ac_q_mode(AC_TRN); 143 | const ac_o_mode recip_O = or_r ? ac_o_mode(iO_r) : ac_o_mode(AC_WRAP); 144 | typedef ac_fixed T_recip; 145 | T_recip sum_exp_recip; 146 | 147 | // All the loops used in this function can be pipelined/unrolled to give the desired area/throughput score. 148 | // 1. Pipelining all the loops and the main function call with an II of 1 gives (2K) number of throughput cycles. 149 | // 2. Unrolling all the loops and pipelining the main function call with an II of 1 ensures a throughput of 1. 150 | // The second option can also result in a very large area score. 151 | 152 | // Calculate exponential of all inputs. 153 | CALC_EXP_LOOP: for (unsigned i = 0; i < K; i++) { ac_exp_pwl(input[i], exp_arr[i]); } 154 | 155 | // Perform a MAC operation to add all the exponential values. 156 | T_sum sum_exp = 0.0; 157 | SUM_EXP_LOOP: for (unsigned i = 0; i < K; i++) { sum_exp += exp_arr[i]; } 158 | 159 | // Find the reciprocal of the sum of exponentials. 160 | ac_reciprocal_pwl(sum_exp, sum_exp_recip); 161 | 162 | // The types for the exponent and reciprocal variable are configurable primarily to ensure that the size of the multiplier used for the multiplication below 163 | // does not become too large. A large multiplier can become an issue if the loop below is being unrolled and the number of iterations (K) is large, 164 | // hence resulting in many large multipliers and a very large area. 165 | CALC_SOFTMAX_LOOP: for (unsigned i = 0; i < K; i++) { output[i] = sum_exp_recip*exp_arr[i]; } 166 | } 167 | 168 | }; 169 | 170 | 171 | #endif // #ifndef _INCLUDED_AC_SOFTMAX_PWL_H_ 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /include/ac_math/ac_softmax_pwl_new.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //***************************************************************************************** 32 | // File: ac_softmax_pwl_new.h (for ac_fixed) 33 | // 34 | // Description: 35 | // Synthesizable softmax function for AC fixed point datatypes. 36 | // New design normalizes the numerator and denominator terms in the softmax equation 37 | // to minimize bit growth and improve QofR. 38 | // 39 | // Usage: 40 | // Calculation of softmax of an array of real inputs, passed as ac_fixed variables. 41 | // 42 | // Notes: 43 | // A sample testbench and its implementation looks like this: 44 | // 45 | // #include 46 | // 47 | // const int num_logits_tb = 20; 48 | // 49 | // typedef ac_fixed<16, 8, true, AC_TRN, AC_SAT> input_type; 50 | // typedef ac_fixed<16, 8, false, AC_TRN, AC_SAT> output_type; 51 | // 52 | // #pragma hls_design top 53 | // void project( 54 | // const input_type (&input)[num_logits_tb], 55 | // output_type (&output)[num_logits_tb] 56 | // ) 57 | // { 58 | // ac_math::ac_softmax_pwl_new(input,output); 59 | // } 60 | // 61 | // #ifndef __SYNTHESIS__ 62 | // #include 63 | // 64 | // CCS_MAIN(int arg, char **argc) 65 | // { 66 | // input_type input[num_logits_tb]; 67 | // for (int i = 0; i < num_logits_tb; i++) { input[i] = 9 - i; } 68 | // output_type output; 69 | // CCS_DESIGN(project)(input, output); 70 | // CCS_RETURN (0); 71 | // } 72 | // #endif 73 | // 74 | // Notes: 75 | // Attempting to call this function with a type that is not implemented will 76 | // result in a compile-time error. 77 | // 78 | // This file uses the ac_exp_pwl() function from the file ac_pow_pwl.h and the 79 | // ac_reciprocal_pwl() function from the file ac_reciprocal_pwl.h. 80 | // 81 | // Revision History: 82 | // 3.4.3 - dgb - Updated compiler checks to work with MS VS 2019 83 | // 3.3.0 - [CAT-25798] Added CDesignChecker fixes/waivers for code check and Synthesis-simulation mismatch/violations in ac_math PWL and Linear Algebra IPs. 84 | // 3.2.0 - Initial version 85 | // 86 | //***************************************************************************************** 87 | 88 | #ifndef _INCLUDED_AC_SOFTMAX_PWL_NEW_H_ 89 | #define _INCLUDED_AC_SOFTMAX_PWL_NEW_H_ 90 | 91 | // The function uses default template parameters, which are only supported by C++11 or later 92 | // compiler standards. Hence, the user should be informed if they are not using those standards. 93 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 94 | #error Please use C++11 or a later standard for compilation. 95 | #endif 96 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 97 | #error Please use Microsoft VS 2019 or a later standard for compilation. 98 | #endif 99 | 100 | // Include header for supported datatype. 101 | #include 102 | 103 | // Include headers for required functions 104 | #include 105 | #include 106 | 107 | // Encapsulate within ac_math namespace. 108 | namespace ac_math 109 | { 110 | template 116 | void ac_softmax_pwl_new_ptr( 117 | const ac_fixed input[K], 118 | ac_fixed output[K] 119 | ) 120 | { 121 | typedef ac_fixed in_type; 122 | 123 | const ac_fixed<33, 1, false> full_prec_log2e = 1.4426950407214462757110595703125; 124 | static_assert(l2e_fw_ <= full_prec_log2e.width - full_prec_log2e.i_width, "l2e_fw_ must not exceed the number of fractional bits in full_prec_log2e."); 125 | constexpr int l2e_fw = l2e_fw_ > 0 ? l2e_fw_ : 16; 126 | typedef ac_fixed log2e_type; 127 | const log2e_type log2e = full_prec_log2e; 128 | typedef typename ac::rt_2T::mult b2_pow_type; 129 | typedef ac_int b2p_I_type; 130 | b2p_I_type b2p_I[K]; 131 | b2p_I_type b2p_Im; 132 | constexpr int exp2f_fw = exp2f_fw_ > 0 ? exp2f_fw_ : AC_MAX(1, AC_MIN(10, W - I - 2)) + 10; 133 | ac_fixed exp2_frac[K]; 134 | 135 | SEPARATE_INTO_INT_AND_FRAC: for (unsigned i = 0; i < K; i++) { 136 | b2_pow_type b2_pow = input[i]*log2e; 137 | b2p_I[i] = b2_pow.to_ac_int(); 138 | if (b2_pow_type::width > b2_pow_type::i_width) { 139 | // fwidth must always be positive to prevent compiler errors. 140 | constexpr int fwidth = AC_MAX(b2_pow_type::width - b2_pow_type::i_width, 1); 141 | ac_fixed frac_part; 142 | frac_part.set_slc(0, b2_pow.template slc(0)); 143 | ac_math::ac_pow2_pwl(frac_part, exp2_frac[i]); 144 | } else { 145 | exp2_frac[i] = 1.0; // No fractional part => exp2(frac_part) = exp2(0) = 1 146 | } 147 | if (i == 0) { b2p_Im = b2p_I[i]; } 148 | else { b2p_Im = AC_MAX(b2p_I[i], b2p_Im); } 149 | } 150 | 151 | ac_fixed prod[K]; 152 | constexpr int sprod_Iw = ac::nbits<2*K - 1>::val; 153 | ac_fixed prod_sum = 0.0; 154 | 155 | CALCULATE_NORM_NUM_AND_DEN: for (unsigned i = 0; i < K; i++) { 156 | ac_int del_b2p_I = b2p_Im - b2p_I[i]; 157 | prod[i] = exp2_frac[i] >> del_b2p_I; 158 | prod_sum += prod[i]; 159 | } 160 | 161 | constexpr int recip_W = prod_sum.width + 20; 162 | constexpr int recip_iW = prod_sum.width - prod_sum.i_width + 1; 163 | 164 | ac_fixed recip_sum; 165 | ac_reciprocal_pwl(prod_sum, recip_sum); 166 | 167 | CALCULATE_SOFTMAX_OUT: for (unsigned i = 0; i < K; i++) { output[i] = prod[i]*recip_sum; } 168 | } 169 | 170 | template 176 | // By declaring the function parameters as references to arrays (i.e. "(&input)[K]" and "(&output)[K]"), we ensure 177 | // that template parameter deduction infers the value of K. 178 | void ac_softmax_pwl_new( 179 | const ac_fixed (&input)[K], 180 | ac_fixed (&output)[K] 181 | ) 182 | { 183 | ac_softmax_pwl_new_ptr(input, output); 184 | } 185 | }; 186 | 187 | 188 | #endif // #ifndef _INCLUDED_AC_SOFTMAX_PWL_NEW_H_ 189 | -------------------------------------------------------------------------------- /include/ac_math/ac_softplus_pwl.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // Function: ac_softplus_pwl (for ac_fixed) 33 | // 34 | // Description: 35 | // Provides piece-wise linear approximation of the softplus function 36 | // for the ac_fixed datatype 37 | // 38 | // Usage: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // typedef ac_fixed<10, 4, false, AC_RND, AC_SAT> input_type; 45 | // typedef ac_fixed<20, 2, false, AC_RND, AC_SAT> output_type; 46 | // 47 | // #pragma hls_design top 48 | // void project( 49 | // const input_type &input, 50 | // output_type &output 51 | // ) 52 | // { 53 | // ac_softplus_pwl(input,output); 54 | // } 55 | // 56 | // #ifndef __SYNTHESIS__ 57 | // #include 58 | // 59 | // CCS_MAIN(int arg, char **argc) 60 | // { 61 | // input_type input = 3.5; 62 | // output_type output; 63 | // CCS_DESIGN(project)(input, output); 64 | // CCS_RETURN (0); 65 | // } 66 | // #endif 67 | // 68 | // Notes: 69 | // The softplus activation function is equal to log(1+e^x). This function relies on 70 | // the pow_pwl and log_pwl functions for its computation. e^x is computed using 71 | // e^x = 2^(x*log2(e)). So here the input is multiplied with log2(e) and the passed to 72 | // the ac_pow2_pwl function. And then finally 1 + e^x is passed to the ac_log_pwl function. 73 | // As the below function relies on the ac_pow_pwl function, make sure to use the same value 74 | // of constants n_segments_lut and n_frac_bits used below as defined in the ac_fixed 75 | // implementation for ac_pow_pwl.h. 76 | //************************************************************************************************* 77 | 78 | #ifndef _INCLUDED_AC_SOFTPLUS_PWL_H_ 79 | #define _INCLUDED_AC_SOFTPLUS_PWL_H_ 80 | 81 | // The below functions use default template parameters, which are only supported by C++11 or later 82 | // compiler standards. Hence, the user should be informed if they are not using those standards. 83 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 84 | #error Please use C++11 or a later standard for compilation. 85 | #endif 86 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 87 | #error Please use Microsoft VS 2019 or a later standard for compilation. 88 | #endif 89 | 90 | #include 91 | // Include headers for data types supported by these implementations 92 | #include 93 | #include 94 | #include 95 | 96 | #if !defined(__SYNTHESIS__) 97 | #include 98 | #include 99 | #include 100 | #include 101 | using namespace std; 102 | #endif 103 | 104 | //========================================================================= 105 | // Function: ac_softplus_pwl (for ac_fixed) 106 | // 107 | // Description: 108 | // Softplus function for real inputs, passed as ac_fixed 109 | // variables. 110 | // 111 | // Usage: 112 | // See above example for usage. 113 | // 114 | //------------------------------------------------------------------------- 115 | 116 | namespace ac_math 117 | { 118 | template 121 | void ac_softplus_pwl( 122 | const ac_fixed &input, 123 | ac_fixed &output 124 | ) 125 | { 126 | // n_segments_lut and n_frac_bits should be the same as the corresponding values in the ac_fixed 127 | // implementation for ac_exp_pwl. 128 | // The bitwidth calculations which use these constants are designed with a PWL domain of [0, 1) in 129 | // mind. They will still work for other PWL domains, but at a possibly lower-than-optimal accuracy. 130 | // 131 | // NOTE: Change these constants if you change the either of the corresponding values in the 132 | // ac_fixed implementation for the ac_exp_pwl function. 133 | const unsigned n_segments_lut = 4; 134 | const int n_frac_bits = 10; 135 | 136 | const bool is_n_seg_po2 = !bool(n_segments_lut & (n_segments_lut - 1)); 137 | const int extra_f_bits = is_n_seg_po2 ? ac::nbits::val : 0; 138 | 139 | const int I_width = (I<0) ? -I:I; 140 | 141 | // Find type of intermediate variable used to store output of x*log2(e) 142 | typedef class comp_pii_exp::pit_t input_inter_type; 143 | 144 | const int out_pow_width = input_inter_type::width; 145 | const int out_pow_iwidth = input_inter_type::i_width; 146 | 147 | // Since scaling constant is a positive power-of-two, multiplication with it is the same as left-shifting by 2. 148 | // Accordingly, the scaled normalized input will have 2 less fractional bits than the normalized input, provided that this 149 | // number of fractional bits is lesser than n_frac_bits. If not, the number of fractional bits in the scaled input is set to n_frac_bits. 150 | const int sc_input_frac_bits = AC_MAX(1, AC_MIN(n_frac_bits, out_pow_width - out_pow_iwidth - 2)); 151 | 152 | typedef ac_fixed<((out_pow_iwidth + 1)*out_pow_iwidth) + sc_input_frac_bits + n_frac_bits, ((out_pow_iwidth + 1)*out_pow_iwidth), false, AC_TRN, AC_WRAP> out_pow_type; 153 | 154 | out_pow_type out_pow; 155 | 156 | ac_exp_pwl(input, out_pow); 157 | 158 | typedef ac_fixed inp_log_type; 159 | 160 | inp_log_type inp_log = out_pow + 1; 161 | 162 | ac_log_pwl(inp_log, output); 163 | } 164 | 165 | // The following version enables a return-by-value. 166 | template 169 | T_out ac_softplus_pwl(const T_in &input) 170 | { 171 | T_out output; 172 | ac_softplus_pwl(input, output); 173 | return output; 174 | } 175 | } 176 | #endif 177 | -------------------------------------------------------------------------------- /include/ac_math/ac_softsign_pwl.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | //****************************************************************************************** 32 | // Function: ac_softsign_pwl (for ac_fixed) 33 | // 34 | // Description: 35 | // Provides piece-wise linear approximation of the softsign function 36 | // for the ac_fixed datatype 37 | // 38 | // Usage: 39 | // A sample testbench and its implementation looks like this: 40 | // 41 | // #include 42 | // using namespace ac_math; 43 | // 44 | // typedef ac_fixed<10, 4, false, AC_RND, AC_SAT> input_type; 45 | // typedef ac_fixed<20, 2, false, AC_RND, AC_SAT> output_type; 46 | // 47 | // #pragma hls_design top 48 | // void project( 49 | // const input_type &input, 50 | // output_type &output 51 | // ) 52 | // { 53 | // ac_softsign_pwl(input,output); 54 | // } 55 | // 56 | // #ifndef __SYNTHESIS__ 57 | // #include 58 | // 59 | // CCS_MAIN(int arg, char **argc) 60 | // { 61 | // input_type input = 3.5; 62 | // output_type output; 63 | // CCS_DESIGN(project)(input, output); 64 | // CCS_RETURN (0); 65 | // } 66 | // #endif 67 | // 68 | // Notes: 69 | //************************************************************************************************* 70 | 71 | #ifndef _INCLUDED_AC_SOFTSIGN_PWL_H_ 72 | #define _INCLUDED_AC_SOFTSIGN_PWL_H_ 73 | 74 | // The below functions use default template parameters, which are only supported by C++11 or later 75 | // compiler standards. Hence, the user should be informed if they are not using those standards. 76 | #if (defined(__GNUC__) && (__cplusplus < 201103L)) 77 | #error Please use C++11 or a later standard for compilation. 78 | #endif 79 | #if (defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__EDG__)) 80 | #error Please use Microsoft VS 2019 or a later standard for compilation. 81 | #endif 82 | 83 | #include 84 | // Include headers for data types supported by these implementations 85 | #include 86 | #include 87 | 88 | #if !defined(__SYNTHESIS__) 89 | #include 90 | #include 91 | #include 92 | #include 93 | using namespace std; 94 | #endif 95 | 96 | //========================================================================= 97 | // Function: ac_softsign_pwl (for ac_fixed) 98 | // 99 | // Description: 100 | // Softsign function for real inputs, passed as ac_fixed 101 | // variables. 102 | // 103 | // Usage: 104 | // See above example for usage. 105 | // 106 | //------------------------------------------------------------------------- 107 | 108 | namespace ac_math 109 | { 110 | template 113 | void ac_softsign_pwl( 114 | const ac_fixed &input, 115 | ac_fixed &output 116 | ) 117 | { 118 | // n_frac_bits should be the same as the corresponding values in the ac_fixed implementation for ac_reciprocal_pwl. 119 | // The bitwidth calculations which use these constants are designed with a PWL domain of [0.5, 1) in 120 | // mind. They will still work for other PWL domains, but at a possibly lower-than-optimal accuracy. 121 | // 122 | // NOTE: Change these constants if you change the either of the corresponding values in the 123 | // ac_fixed implementation for the ac_reciprocal_pwl function. 124 | const int n_frac_bits = 10; 125 | 126 | // Since scaling constant is a positive power-of-two, multiplication with it is the same as left-shifting by 4. 127 | // Accordingly, the scaled normalized input will have 4 less fractional bits than the normalized input, provided that this 128 | // number of fractional bits is lesser than n_frac_bits. If not, the number of fractional bits in the scaled input is set to n_frac_bits. 129 | const int sc_input_frac_bits = AC_MAX(1, AC_MIN(n_frac_bits, W - 4)); 130 | 131 | ac_fixed input_abs_value; 132 | 133 | ac_fixed normalized_fixed; 134 | 135 | #pragma hls_waive CNS 136 | if (S) { 137 | input_abs_value = ((input >= 0) ? (ac_fixed )input : (ac_fixed )(-input)); 138 | } 139 | // If input is unsigned, assign value of input to intermediate variable. 140 | else { 141 | input_abs_value = input; 142 | } 143 | 144 | const int I_width = (I<0) ? -I:I; 145 | 146 | const int W_width = (W rec_inp_type; 149 | 150 | rec_inp_type rec_inp = input_abs_value + 1; 151 | 152 | typedef ac_fixed rec_out_type; 153 | 154 | rec_out_type out_rec; 155 | 156 | ac_reciprocal_pwl(rec_inp, out_rec); 157 | 158 | output = input * out_rec; 159 | } 160 | 161 | // The following version enables a return-by-value. 162 | template 165 | T_out ac_softsign_pwl(const T_in &input) 166 | { 167 | T_out output; 168 | ac_softsign_pwl(input, output); 169 | return output; 170 | } 171 | } 172 | #endif 173 | -------------------------------------------------------------------------------- /lutgen/ac_atan_pwl_lutgen.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // Usage: 32 | // g++ -I$MGC_HOME/shared/include ac_atan_pwl_lutgen.cpp -o ac_atan_pwl_lutgen 33 | // ./ac_atan_pwl_lutgen 34 | // results in a text file ac_atan_pwl_lut_values.txt which can be pasted into 35 | // a locally modified version of ac_atan_pwl.h. 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | using namespace std; 46 | 47 | #include "helper_functions.h" 48 | 49 | int main() 50 | { 51 | //Define the number of points in your LUT. 52 | const unsigned npoints = 5; 53 | const unsigned nsegments = npoints - 1; 54 | const double x_min = 0; 55 | const double x_max = 1; 56 | const double prop_constant = nsegments/(x_max - x_min); 57 | double m[nsegments]; 58 | double c[nsegments]; 59 | 60 | FILE *fp; 61 | 62 | //The output ROM values will be printed to a file in c++ syntax. 63 | //Define the filename below. The new file will be in the same folder 64 | //as this .cpp file 65 | const char filename[] = "ac_atan_pwl_lut_values.txt"; 66 | 67 | //Define your domain for calculation. 68 | double x[npoints]; 69 | double x_sc[npoints]; 70 | double y[npoints]; 71 | double x_val_inc = x_min; 72 | ostringstream mstrstream; 73 | ostringstream cstrstream; 74 | string mstr=""; 75 | string cstr=""; 76 | 77 | //Find slope and intercept for each segment. 78 | for (int i = 0; i < npoints; i++) { 79 | y[i] = atan(x_val_inc); 80 | x[i] = x_val_inc; 81 | x_sc[i] = (x_val_inc - x_min)*prop_constant; 82 | x_val_inc += (1/prop_constant); 83 | } 84 | 85 | //Shift segments downward 86 | for (int i = 0; i < nsegments; i++) { 87 | m[i] = y[i + 1] - y[i]; 88 | c[i] = y[i]; 89 | double x_mid = 0.5*(x[i + 1] + x[i]); 90 | double max_diff = (pwl_new(x_mid, m, c, prop_constant, x_min, nsegments) - atan(x_mid)); 91 | c[i] = c[i] - 0.5*(max_diff); 92 | //cout << "max_diff = " << max_diff << endl; 93 | } 94 | 95 | double y1_new, y2_new; 96 | 97 | //Correct slopes and intercepts in order for monotonicity to 98 | //be maintained. 99 | for (int i = 1; i < nsegments; i++) { 100 | y1_new = m[i - 1] + c[i - 1]; 101 | y2_new = m[i] + c[i]; 102 | m[i] = y2_new - y1_new; 103 | c[i] = y1_new; 104 | } 105 | 106 | //Use a negative power of two as an increment. 107 | double increment = 1.0 / 65536.0; 108 | double abs_error, abs_error_max = 0, rel_error_max = 0, input_error_max; 109 | 110 | for (double input_tb = x_min; input_tb < x_max; input_tb += increment) { 111 | double expected = atan(input_tb); 112 | double actual = pwl_new(input_tb, m, c, prop_constant, x_min, nsegments); 113 | double rel_error = abs( (expected - actual) / expected) * 100; 114 | if (rel_error > rel_error_max) { rel_error_max = rel_error; } 115 | abs_error = abs(expected - actual); 116 | if (abs_error > abs_error_max) { 117 | abs_error_max = abs_error; 118 | input_error_max = input_tb; 119 | } 120 | } 121 | 122 | int nfrac_bits = abs(floor(log2(abs_error_max))) + 1; 123 | 124 | //Add elements to Objects that contain declaration of LUT arrays 125 | //in C++ syntax. 126 | for (int i = 0; i < nsegments; i++) { 127 | if (i == 0) { 128 | mstrstream << "{" << o_ac_f(m[i], nfrac_bits) << ", "; 129 | cstrstream << "{" << o_ac_f(c[i], nfrac_bits) << ", "; 130 | } else if (i == nsegments - 1) { 131 | mstrstream << o_ac_f(m[i], nfrac_bits) << "}"; 132 | cstrstream << o_ac_f(c[i], nfrac_bits) << "}"; 133 | } else { 134 | mstrstream << o_ac_f(m[i], nfrac_bits) << ", "; 135 | cstrstream << o_ac_f(c[i], nfrac_bits) << ", "; 136 | } 137 | } 138 | mstr = mstrstream.str(); 139 | cstr = cstrstream.str(); 140 | 141 | // Find max value in array, and see if it has any negative values. This helps figure out 142 | // the number of integer bits to use to store array values. 143 | double m_max_val, c_max_val; 144 | bool is_neg_m, is_neg_c; 145 | 146 | is_neg_m = is_neg_max_array(m, nsegments, m_max_val); 147 | is_neg_c = is_neg_max_array(c, nsegments, c_max_val); 148 | 149 | string is_neg_m_s = is_neg_m ? "true" : "false"; 150 | string is_neg_c_s = is_neg_c ? "true" : "false"; 151 | 152 | int m_int_bits = int_bits_calc(m_max_val, is_neg_m); 153 | int c_int_bits = int_bits_calc(c_max_val, is_neg_c); 154 | int x_min_int_bits = int_bits_calc(x_min, x_min < 0); 155 | int x_max_int_bits = int_bits_calc(x_max, x_max < 0); 156 | int p_c_int_bits = int_bits_calc(prop_constant, false); 157 | 158 | string is_neg_x_min_s = (x_min < 0) ? "true" : "false"; 159 | string is_neg_x_max_s = (x_max < 0) ? "true" : "false"; 160 | 161 | std::ofstream outfile(filename); 162 | outfile << "const unsigned n_segments_lut = " << nsegments << ";" < m_lut[n_segments_lut] = " << mstr << ";" << endl; 165 | outfile << "const ac_fixed<" << c_int_bits << " + n_frac_bits, " << c_int_bits << ", " << is_neg_c_s << "> c_lut[n_segments_lut] = " << cstr << ";" << endl; 166 | outfile << "const ac_fixed<" << x_min_int_bits << " + n_frac_bits, " << x_min_int_bits << ", " << is_neg_x_min_s << "> x_min_lut = " << o_ac_f(x_min, nfrac_bits) << ";" << endl; 167 | outfile << "const ac_fixed<" << x_max_int_bits << " + n_frac_bits, " << x_max_int_bits << ", " << is_neg_x_max_s << "> x_max_lut = " << o_ac_f(x_max, nfrac_bits) << ";" << endl; 168 | outfile << "const ac_fixed<" << p_c_int_bits << " + n_frac_bits, " << p_c_int_bits << ", false> sc_constant_lut = " << o_ac_f(prop_constant, nfrac_bits) << ";" << endl; 169 | outfile.close(); 170 | 171 | cout << endl; 172 | cout << __FILE__ << ", " << __LINE__ << ": Values are written, check \"" 173 | << filename << "\" for " << "the required ROM values" << endl ; 174 | cout << "abs_error_max = " << abs_error_max << endl; 175 | cout << "input_error_max = " << input_error_max << endl; 176 | cout << "nfrac_bits = " << nfrac_bits << endl; 177 | cout << "rel_error_max = " << rel_error_max << endl; 178 | 179 | return 0; 180 | } 181 | 182 | -------------------------------------------------------------------------------- /lutgen/ac_log_pwl_lutgen.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // Usage: 32 | // g++ -I$MGC_HOME/shared/include ac_log_pwl_lutgen.cpp -o ac_log_pwl_lutgen 33 | // ./ac_log_pwl_lutgen 34 | // results in a text file ac_log_pwl_lut_values.txt which can be pasted into 35 | // a locally modified version of ac_log_pwl.h. 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | using namespace std; 46 | 47 | #include "helper_functions.h" 48 | 49 | int main() 50 | { 51 | //Define the number of points in your LUT. 52 | const unsigned npoints = 9; 53 | const unsigned nsegments = npoints - 1; 54 | const double x_min = 0.5; 55 | const double x_max = 1; 56 | const double prop_constant = nsegments/(x_max - x_min); 57 | double m[nsegments]; 58 | double c[nsegments]; 59 | 60 | FILE *fp; 61 | 62 | //The output ROM values will be printed to a file in c++ syntax. 63 | //Define the filename below. The new file will be in the same folder 64 | //as this .cpp file 65 | const char filename[] = "ac_log_pwl_lut_values.txt"; 66 | 67 | //Define your domain for calculation. In case you want to use the 68 | //value of pi, use M_PI, a math.h macro that has the value of pi. 69 | //(e.g. "x_max = M_PI/4") 70 | double x[npoints]; 71 | double x_sc[npoints]; 72 | double y[npoints]; 73 | double x_val_inc = x_min; 74 | ostringstream mstrstream; 75 | ostringstream cstrstream; 76 | string mstr=""; 77 | string cstr=""; 78 | 79 | //Find slope and intercept for each segment. 80 | for (int i = 0; i < npoints; i++) { 81 | y[i] = log2(x_val_inc); 82 | x[i] = x_val_inc; 83 | x_sc[i] = (x_val_inc - x_min)*prop_constant; 84 | x_val_inc += (1/prop_constant); 85 | } 86 | 87 | //Shift segments downward 88 | for (int i = 0; i < nsegments; i++) { 89 | m[i] = y[i + 1] - y[i]; 90 | c[i] = y[i]; 91 | double x_mid = 0.5*(x[i + 1] + x[i]); 92 | double max_diff = (pwl_new(x_mid, m, c, prop_constant, x_min, nsegments) - log2(x_mid)); 93 | c[i] = c[i] - 0.5*(max_diff); 94 | //cout << "max_diff = " << max_diff << endl; 95 | } 96 | 97 | double y1_new, y2_new; 98 | 99 | //Correct slopes and intercepts in order for monotonicity to 100 | //be maintained. 101 | for (int i = 1; i < nsegments; i++) { 102 | y1_new = m[i - 1] + c[i - 1]; 103 | y2_new = m[i] + c[i]; 104 | m[i] = y2_new - y1_new; 105 | c[i] = y1_new; 106 | } 107 | 108 | //Use a negative power of two as an increment. 109 | double increment = 1.0 / 65536.0; 110 | double abs_error, abs_error_max = 0, rel_error_max = 0, input_error_max; 111 | 112 | for (double input_tb = x_min; input_tb < x_max; input_tb += increment) { 113 | double expected = log2(input_tb); 114 | double actual = pwl_new(input_tb, m, c, prop_constant, x_min, nsegments); 115 | double rel_error = abs( (expected - actual) / expected) * 100; 116 | if (rel_error > rel_error_max) { rel_error_max = rel_error; } 117 | abs_error = abs(expected - actual); 118 | if (abs_error > abs_error_max) { 119 | abs_error_max = abs_error; 120 | input_error_max = input_tb; 121 | } 122 | } 123 | 124 | int nfrac_bits = abs(floor(log2(abs_error_max))) + 1; 125 | 126 | ac_fixed<128, 64, true> m_fixed[nsegments], c_fixed[nsegments]; 127 | 128 | // Quantize double values according to fixed point precision. 129 | for (int i = 0; i < nsegments; i++) { 130 | m_fixed[i] = o_ac_f(m[i], nfrac_bits); 131 | c_fixed[i] = o_ac_f(c[i], nfrac_bits); 132 | } 133 | 134 | // Find the quantum value of an fixed point variable with nfrac_bits number of fractional bits. 135 | const ac_fixed<128, 64, true> quant_val = pow(2, double(-nfrac_bits)); 136 | 137 | // Check left- and right-hand limits of the PWL function for each segment boundary. 138 | for (int i = 0; i < nsegments - 1; i++) { 139 | double lhl = (m_fixed[i] + c_fixed[i]).to_double(); 140 | double rhl = (c_fixed[i + 1]).to_double(); 141 | if (rhl < lhl) { 142 | // If the PWL output is not increasing at the segment boundary, decrease the slope of the 143 | // preceding segment so as to lower the left hand limit and make the PWL output increase 144 | // across the boundary. 145 | m_fixed[i] = m_fixed[i] - quant_val; 146 | } 147 | } 148 | 149 | //Add elements to Objects that contain declaration of LUT arrays 150 | //in C++ syntax. 151 | for (int i = 0; i < nsegments; i++) { 152 | if (i == 0) { 153 | mstrstream << "{" << m_fixed[i] << ", "; 154 | cstrstream << "{" << c_fixed[i] << ", "; 155 | } else if (i == nsegments - 1) { 156 | mstrstream << m_fixed[i] << "}"; 157 | cstrstream << c_fixed[i] << "}"; 158 | } else { 159 | mstrstream << m_fixed[i] << ", "; 160 | cstrstream << c_fixed[i] << ", "; 161 | } 162 | } 163 | mstr = mstrstream.str(); 164 | cstr = cstrstream.str(); 165 | 166 | // Find max value in array, and see if it has any negative values. This helps figure out 167 | // the number of integer bits to use to store array values. 168 | double m_max_val, c_max_val; 169 | bool is_neg_m, is_neg_c; 170 | 171 | is_neg_m = is_neg_max_array(m, nsegments, m_max_val); 172 | is_neg_c = is_neg_max_array(c, nsegments, c_max_val); 173 | 174 | string is_neg_m_s = is_neg_m ? "true" : "false"; 175 | string is_neg_c_s = is_neg_c ? "true" : "false"; 176 | 177 | int m_int_bits = int_bits_calc(m_max_val, is_neg_m); 178 | int c_int_bits = int_bits_calc(c_max_val, is_neg_c); 179 | int x_min_int_bits = int_bits_calc(x_min, x_min < 0); 180 | int x_max_int_bits = int_bits_calc(x_max, x_max < 0); 181 | int p_c_int_bits = int_bits_calc(prop_constant, false); 182 | 183 | string is_neg_x_min_s = (x_min < 0) ? "true" : "false"; 184 | string is_neg_x_max_s = (x_max < 0) ? "true" : "false"; 185 | 186 | std::ofstream outfile(filename); 187 | outfile << "const unsigned n_segments_lut = " << nsegments << ";" < m_lut[n_segments_lut] = " << mstr << ";" << endl; 190 | outfile << "const ac_fixed<" << c_int_bits << " + n_frac_bits, " << c_int_bits << ", " << is_neg_c_s << "> c_lut[n_segments_lut] = " << cstr << ";" << endl; 191 | outfile << "const ac_fixed<" << x_min_int_bits << " + n_frac_bits, " << x_min_int_bits << ", " << is_neg_x_min_s << "> x_min_lut = " << o_ac_f(x_min, nfrac_bits) << ";" << endl; 192 | outfile << "const ac_fixed<" << x_max_int_bits << " + n_frac_bits, " << x_max_int_bits << ", " << is_neg_x_max_s << "> x_max_lut = " << o_ac_f(x_max, nfrac_bits) << ";" << endl; 193 | outfile << "const ac_fixed<" << p_c_int_bits << " + n_frac_bits, " << p_c_int_bits << ", false> sc_constant_lut = " << o_ac_f(prop_constant, nfrac_bits) << ";" << endl; 194 | outfile.close(); 195 | 196 | cout << endl; 197 | cout << __FILE__ << ", " << __LINE__ << ": Values are written, check \"" 198 | << filename << "\" for " << "the required ROM values" << endl ; 199 | cout << "abs_error_max = " << abs_error_max << endl; 200 | cout << "input_error_max = " << input_error_max << endl; 201 | cout << "nfrac_bits = " << nfrac_bits << endl; 202 | cout << "rel_error_max = " << rel_error_max << endl; 203 | 204 | return 0; 205 | } 206 | 207 | -------------------------------------------------------------------------------- /lutgen/ac_sigmoid_pwl_lutgen.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // Usage: 32 | // g++ -I$MGC_HOME/shared/include ac_sigmoid_pwl_lutgen.cpp -o ac_sigmoid_pwl_lutgen 33 | // ./ac_sigmoid_pwl_lutgen 34 | // results in a text file ac_sigmoid_pwl_lut_values.txt which can be pasted into 35 | // a locally modified version of ac_sigmoid_pwl.h. 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | using namespace std; 46 | 47 | 48 | //Define the number of points in your LUT. 49 | const unsigned npoints = 9; 50 | const unsigned nsegments = npoints - 1; 51 | const double x_min = 0; 52 | const double x_max = 5; 53 | const double prop_constant = nsegments/(x_max - x_min); 54 | double m[nsegments]; 55 | double c[nsegments]; 56 | 57 | #include "helper_functions.h" 58 | 59 | int main() 60 | { 61 | FILE *fp; 62 | 63 | //The output ROM values will be printed to a file in c++ syntax. 64 | //Define the filename below. The new file will be in the same folder 65 | //as this .cpp file 66 | const char filename[] = "ac_sigmoid_pwl_lut_values.txt"; 67 | 68 | //Define your domain for calculation. In case you want to use the 69 | //value of pi, use M_PI, a math.h macro that has the value of pi. 70 | //(e.g. "x_max = M_PI/4") 71 | double x[npoints]; 72 | double x_sc[npoints]; 73 | double y[npoints]; 74 | double x_val_inc = x_min; 75 | ostringstream mstrstream; 76 | ostringstream cstrstream; 77 | string mstr=""; 78 | string cstr=""; 79 | 80 | //Find slope and intercept for each segment. 81 | for (int i = 0; i < npoints; i++) { 82 | y[i] = 1/(1 + exp(-x_val_inc)); 83 | x[i] = x_val_inc; 84 | x_sc[i] = (x_val_inc - x_min)*prop_constant; 85 | x_val_inc += (1/prop_constant); 86 | } 87 | 88 | //Shift segments upward 89 | for (int i = 0; i < nsegments; i++) { 90 | m[i] = y[i + 1] - y[i]; 91 | c[i] = y[i]; 92 | double x_mid = 0.5*(x[i + 1] + x[i]); 93 | double max_diff = (pwl_new(x_mid, m, c, prop_constant, x_min, nsegments) - (1/(1 + exp(-x_mid)))); 94 | c[i] = c[i] - 0.5*(max_diff); 95 | //cout << "max_diff = " << max_diff << endl; 96 | } 97 | 98 | double y1_new, y2_new; 99 | 100 | //Correct slopes and intercepts in order for monotonicity to 101 | //be maintained. 102 | for (int i = 1; i < nsegments; i++) { 103 | y1_new = m[i - 1] + c[i - 1]; 104 | y2_new = m[i] + c[i]; 105 | m[i] = y2_new - y1_new; 106 | c[i] = y1_new; 107 | } 108 | 109 | // Make the increment a negative power of two. 110 | double increment = 1.0 / 65536.0; 111 | double abs_error, abs_error_max = 0, rel_error_max = 0, input_error_max; 112 | 113 | for (double input_tb = x_min; input_tb < x_max; input_tb += increment) { 114 | double expected = 1/(1 + exp(-input_tb)); 115 | double actual = pwl_new(input_tb, m, c, prop_constant, x_min, nsegments); 116 | double rel_error = abs( (expected - actual) / expected) * 100; 117 | if (rel_error > rel_error_max) { rel_error_max = rel_error; } 118 | abs_error = abs(expected - actual); 119 | if (abs_error > abs_error_max) { 120 | abs_error_max = abs_error; 121 | input_error_max = input_tb; 122 | } 123 | } 124 | 125 | int nfrac_bits = abs(floor(log2(abs_error_max))) + 1; 126 | 127 | ac_fixed<128, 64, true> m_fixed[nsegments], c_fixed[nsegments]; 128 | 129 | // Quantize double values according to fixed point precision. 130 | for (int i = 0; i < nsegments; i++) { 131 | m_fixed[i] = o_ac_f(m[i], nfrac_bits); 132 | c_fixed[i] = o_ac_f(c[i], nfrac_bits); 133 | } 134 | 135 | // Find the quantum value of an fixed point variable with nfrac_bits number of fractional bits. 136 | const ac_fixed<128, 64, true> quant_val = pow(2, double(-nfrac_bits)); 137 | 138 | // Check left- and right-hand limits of the PWL function for each segment boundary. 139 | for (int i = 0; i < nsegments - 1; i++) { 140 | double lhl = (m_fixed[i] + c_fixed[i]).to_double(); 141 | double rhl = (c_fixed[i + 1]).to_double(); 142 | if (rhl < lhl) { 143 | // If the PWL output is not increasing at the segment boundary, decrease the slope of the 144 | // preceding segment so as to lower the left hand limit and make the PWL output increase 145 | // across the boundary. 146 | m_fixed[i] = m_fixed[i] - quant_val; 147 | } 148 | } 149 | 150 | //Add elements to Objects that contain declaration of LUT arrays 151 | //in C++ syntax. 152 | for (int i = 0; i < nsegments; i++) { 153 | if (i == 0) { 154 | mstrstream << "{" << m_fixed[i] << ", "; 155 | cstrstream << "{" << c_fixed[i] << ", "; 156 | } else if (i == nsegments - 1) { 157 | mstrstream << m_fixed[i] << "}"; 158 | cstrstream << c_fixed[i] << "}"; 159 | } else { 160 | mstrstream << m_fixed[i] << ", "; 161 | cstrstream << c_fixed[i] << ", "; 162 | } 163 | } 164 | mstr = mstrstream.str(); 165 | cstr = cstrstream.str(); 166 | 167 | // Find max value in array, and see if it has any negative values. This helps figure out 168 | // the number of integer bits to use to store array values. 169 | double m_max_val, c_max_val; 170 | bool is_neg_m, is_neg_c; 171 | 172 | is_neg_m = is_neg_max_array(m, nsegments, m_max_val); 173 | is_neg_c = is_neg_max_array(c, nsegments, c_max_val); 174 | 175 | string is_neg_m_s = is_neg_m ? "true" : "false"; 176 | string is_neg_c_s = is_neg_c ? "true" : "false"; 177 | 178 | int m_int_bits = int_bits_calc(m_max_val, is_neg_m); 179 | int c_int_bits = int_bits_calc(c_max_val, is_neg_c); 180 | int x_min_int_bits = int_bits_calc(x_min, x_min < 0); 181 | int x_max_int_bits = int_bits_calc(x_max, x_max < 0); 182 | int p_c_int_bits = int_bits_calc(prop_constant, false); 183 | 184 | string is_neg_x_min_s = (x_min < 0) ? "true" : "false"; 185 | string is_neg_x_max_s = (x_max < 0) ? "true" : "false"; 186 | 187 | std::ofstream outfile(filename); 188 | outfile << "const unsigned n_segments_lut = " << nsegments << ";" < m_lut[n_segments_lut] = " << mstr << ";" << endl; 191 | outfile << "const ac_fixed<" << c_int_bits << " + n_frac_bits, " << c_int_bits << ", " << is_neg_c_s << "> c_lut[n_segments_lut] = " << cstr << ";" << endl; 192 | outfile << "const ac_fixed<" << x_min_int_bits << " + n_frac_bits, " << x_min_int_bits << ", " << is_neg_x_min_s << "> x_min_lut = " << o_ac_f(x_min, nfrac_bits) << ";" << endl; 193 | outfile << "const ac_fixed<" << x_max_int_bits << " + n_frac_bits, " << x_max_int_bits << ", " << is_neg_x_max_s << "> x_max_lut = " << o_ac_f(x_max, nfrac_bits) << ";" << endl; 194 | outfile << "const ac_fixed<" << p_c_int_bits << " + n_frac_bits, " << p_c_int_bits << ", false> sc_constant_lut = " << o_ac_f(prop_constant, nfrac_bits) << ";" << endl; 195 | outfile.close(); 196 | 197 | cout << endl; 198 | cout << __FILE__ << ", " << __LINE__ << ": Values are written, check \"" 199 | << filename << "\" for " << "the required ROM values" << endl ; 200 | cout << "abs_error_max = " << abs_error_max << endl; 201 | cout << "input_error_max = " << input_error_max << endl; 202 | cout << "nfrac_bits = " << nfrac_bits << endl; 203 | cout << "rel_error_max = " << rel_error_max << endl; 204 | 205 | return 0; 206 | } 207 | 208 | -------------------------------------------------------------------------------- /lutgen/ac_sincos_lut_lutgen.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // Usage: 32 | // g++ -I$MGC_HOME/shared/include ac_sincos_lut_lutgen.cpp -o ac_sincos_lut_lutgen 33 | // ./ac_sincos_lut_lutgen 34 | // results in a text file ac_sincos_lut_values.txt which can be pasted into 35 | // a locally modified version of ac_sincos_lut.h. 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | //========================================================================================== 44 | // Note: 45 | // This file is used to generate a lookup table for the ac_sincos_lut.h library header. 46 | // In this file, a lookup table has been generated for an input width of 12 bits and 47 | // input integer width of 0 bits. So for example, if a lookup table has to be generated 48 | // for an input width of 14 bits and input integer width of 2 bits, then the variables 49 | // input_width and input_int have to be replaced accordingly. 50 | //------------------------------------------------------------------------------------------ 51 | 52 | int main() 53 | { 54 | 55 | FILE *f = fopen("ac_sincos_lut.txt", "w"); 56 | if (f == NULL) { 57 | printf("Error opening file!\n"); 58 | exit(1); 59 | } 60 | 61 | const int input_width = 12; 62 | const int input_int = 0; 63 | 64 | unsigned int NTE = 1<<(input_width - input_int -3); //No of table entries 65 | double step = M_PI/(4*NTE); //Interval between angles 66 | double y = 0; 67 | double scaled_angle = 0; 68 | 69 | fprintf(f, "static const luttype sincos[%d] = { \n", NTE); 70 | 71 | for (unsigned int i=0; i < NTE; i++) { 72 | fprintf(f, " {%23.22f, %23.22f}, //index = %d, scaled angle = %13.12f \n", cos(y), sin(y), i, scaled_angle); 73 | y += step; 74 | scaled_angle = y/(2*M_PI); 75 | } 76 | 77 | fclose(f); 78 | 79 | return 0; 80 | 81 | } 82 | -------------------------------------------------------------------------------- /lutgen/ac_tan_pwl_lutgen.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // Usage: 32 | // g++ -I$MGC_HOME/shared/include ac_tan_pwl_lutgen.cpp -o ac_tan_pwl_lutgen 33 | // ./ac_tan_pwl_lutgen 34 | // results in a text file ac_tan_pwl_lut_values.txt which can be pasted into 35 | // a locally modified version of ac_tan_pwl.h. 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | using namespace std; 46 | 47 | #include "helper_functions.h" 48 | 49 | int main() 50 | { 51 | //Define the number of points in your LUT. 52 | const unsigned npoints = 9; 53 | const unsigned nsegments = npoints - 1; 54 | const double x_min = 0; 55 | const double x_max = M_PI / 4; 56 | const double prop_constant = nsegments/(x_max - x_min); 57 | double m[nsegments]; 58 | double c[nsegments]; 59 | 60 | FILE *fp; 61 | 62 | //The output ROM values will be printed to a file in c++ syntax. 63 | //Define the filename below. The new file will be in the same folder 64 | //as this .cpp file 65 | const char filename[] = "ac_tan_pwl_lut_values.txt"; 66 | 67 | //Define your domain for calculation. In case you want to use the 68 | //value of pi, use M_PI, a math.h macro that has the value of pi. 69 | //(e.g. "x_max = M_PI/4") 70 | double x[npoints]; 71 | double x_sc[npoints]; 72 | double y[npoints]; 73 | double x_val_inc = x_min; 74 | ostringstream mstrstream; 75 | ostringstream cstrstream; 76 | string mstr=""; 77 | string cstr=""; 78 | 79 | //Find slope and intercept for each segment. 80 | for (int i = 0; i < npoints; i++) { 81 | y[i] = tan(x_val_inc); 82 | x[i] = x_val_inc; 83 | x_sc[i] = (x_val_inc - x_min)*prop_constant; 84 | x_val_inc += (1/prop_constant); 85 | } 86 | 87 | //Shift segments downward 88 | for (int i = 0; i < nsegments; i++) { 89 | m[i] = y[i + 1] - y[i]; 90 | c[i] = y[i]; 91 | double x_mid = 0.5*(x[i + 1] + x[i]); 92 | double max_diff = (pwl_new(x_mid, m, c, prop_constant, x_min, nsegments) - tan(x_mid)); 93 | c[i] = c[i] - 0.5*(max_diff); 94 | //cout << "max_diff = " << max_diff << endl; 95 | } 96 | 97 | double y1_new, y2_new; 98 | 99 | //Correct slopes and intercepts in order for monotonicity to 100 | //be maintained. 101 | for (int i = 1; i < nsegments; i++) { 102 | y1_new = m[i - 1] + c[i - 1]; 103 | y2_new = m[i] + c[i]; 104 | m[i] = y2_new - y1_new; 105 | c[i] = y1_new; 106 | } 107 | 108 | //Use a negative power of two as an increment. 109 | double increment = 1.0 / 65536.0; 110 | double abs_error, abs_error_max = 0, rel_error_max = 0, input_error_max; 111 | 112 | for (double input_tb = x_min; input_tb < x_max; input_tb += increment) { 113 | double expected = tan(input_tb); 114 | double actual = pwl_new(input_tb, m, c, prop_constant, x_min, nsegments); 115 | double rel_error = abs( (expected - actual) / expected) * 100; 116 | if (rel_error > rel_error_max) { rel_error_max = rel_error; } 117 | abs_error = abs(expected - actual); 118 | if (abs_error > abs_error_max) { 119 | abs_error_max = abs_error; 120 | input_error_max = input_tb; 121 | } 122 | } 123 | 124 | int nfrac_bits = abs(floor(log2(abs_error_max))) + 1; 125 | 126 | //Add elements to Objects that contain declaration of LUT arrays 127 | //in C++ syntax. 128 | for (int i = 0; i < nsegments; i++) { 129 | if (i == 0) { 130 | mstrstream << "{" << o_ac_f(m[i], nfrac_bits) << ", "; 131 | cstrstream << "{" << o_ac_f(c[i], nfrac_bits) << ", "; 132 | } else if (i == nsegments - 1) { 133 | mstrstream << o_ac_f(m[i], nfrac_bits) << "}"; 134 | cstrstream << o_ac_f(c[i], nfrac_bits) << "}"; 135 | } else { 136 | mstrstream << o_ac_f(m[i], nfrac_bits) << ", "; 137 | cstrstream << o_ac_f(c[i], nfrac_bits) << ", "; 138 | } 139 | } 140 | mstr = mstrstream.str(); 141 | cstr = cstrstream.str(); 142 | 143 | // Find max value in array, and see if it has any negative values. This helps figure out 144 | // the number of integer bits to use to store array values. 145 | double m_max_val, c_max_val; 146 | bool is_neg_m, is_neg_c; 147 | 148 | is_neg_m = is_neg_max_array(m, nsegments, m_max_val); 149 | is_neg_c = is_neg_max_array(c, nsegments, c_max_val); 150 | 151 | string is_neg_m_s = is_neg_m ? "true" : "false"; 152 | string is_neg_c_s = is_neg_c ? "true" : "false"; 153 | 154 | int m_int_bits = int_bits_calc(m_max_val, is_neg_m); 155 | int c_int_bits = int_bits_calc(c_max_val, is_neg_c); 156 | int x_min_int_bits = int_bits_calc(x_min, x_min < 0); 157 | int x_max_int_bits = int_bits_calc(x_max, x_max < 0); 158 | int p_c_int_bits = int_bits_calc(prop_constant, false); 159 | 160 | string is_neg_x_min_s = (x_min < 0) ? "true" : "false"; 161 | string is_neg_x_max_s = (x_max < 0) ? "true" : "false"; 162 | 163 | std::ofstream outfile(filename); 164 | outfile << "const unsigned n_segments_lut = " << nsegments << ";" < m_lut[n_segments_lut] = " << mstr << ";" << endl; 167 | outfile << "const ac_fixed<" << c_int_bits << " + n_frac_bits, " << c_int_bits << ", " << is_neg_c_s << "> c_lut[n_segments_lut] = " << cstr << ";" << endl; 168 | outfile << "const ac_fixed<" << x_min_int_bits << " + n_frac_bits, " << x_min_int_bits << ", " << is_neg_x_min_s << "> x_min_lut = " << o_ac_f(x_min, nfrac_bits) << ";" << endl; 169 | outfile << "const ac_fixed<" << x_max_int_bits << " + n_frac_bits, " << x_max_int_bits << ", " << is_neg_x_max_s << "> x_max_lut = " << o_ac_f(x_max, nfrac_bits) << ";" << endl; 170 | outfile << "const ac_fixed<" << p_c_int_bits << " + n_frac_bits, " << p_c_int_bits << ", false> sc_constant_lut = " << o_ac_f(prop_constant, nfrac_bits) << ";" << endl; 171 | outfile.close(); 172 | 173 | cout << endl; 174 | cout << __FILE__ << ", " << __LINE__ << ": Values are written, check \"" 175 | << filename << "\" for " << "the required ROM values" << endl ; 176 | cout << "abs_error_max = " << abs_error_max << endl; 177 | cout << "input_error_max = " << input_error_max << endl; 178 | cout << "nfrac_bits = " << nfrac_bits << endl; 179 | cout << "rel_error_max = " << rel_error_max << endl; 180 | 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /lutgen/ac_tanh_pwl_lutgen.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // Usage: 32 | // g++ -I$MGC_HOME/shared/include ac_tanh_pwl_lutgen.cpp -o ac_tanh_pwl_lutgen 33 | // ./ac_tanh_pwl_lutgen 34 | // results in a text file ac_tanh_pwl_lut_values.txt which can be pasted into 35 | // a locally modified version of ac_tanh_pwl.h. 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | using namespace std; 46 | 47 | #include "helper_functions.h" 48 | 49 | int main() 50 | { 51 | // Define the number of points in your LUT. 52 | const unsigned npoints = 13; 53 | const unsigned nsegments = npoints - 1; 54 | const double x_min = 0; 55 | const double x_max = 3; 56 | const double prop_constant = nsegments/(x_max - x_min); 57 | double m[nsegments]; 58 | double c[nsegments]; 59 | 60 | FILE *fp; 61 | 62 | //The output ROM values will be printed to a file in c++ syntax. 63 | //Define the filename below. The new file will be in the same folder 64 | //as this .cpp file 65 | const char filename[] = "ac_tanh_pwl_lut_values.txt"; 66 | 67 | //Define your domain for calculation. In case you want to use the 68 | //value of pi, use M_PI, a math.h macro that has the value of pi. 69 | //(e.g. "x_max = M_PI/4") 70 | double x[npoints]; 71 | double x_sc[npoints]; 72 | double y[npoints]; 73 | double x_val_inc = x_min; 74 | ostringstream mstrstream; 75 | ostringstream cstrstream; 76 | string mstr=""; 77 | string cstr=""; 78 | 79 | //Find slope and intercept for each segment. 80 | for (int i = 0; i < npoints; i++) { 81 | y[i] = tanh(x_val_inc); 82 | x[i] = x_val_inc; 83 | x_sc[i] = (x_val_inc - x_min)*prop_constant; 84 | x_val_inc += (1/prop_constant); 85 | } 86 | 87 | //Shift segments upward 88 | for (int i = 0; i < nsegments; i++) { 89 | m[i] = y[i + 1] - y[i]; 90 | c[i] = y[i]; 91 | double x_mid = 0.5*(x[i + 1] + x[i]); 92 | double max_diff = pwl_new(x_mid, m, c, prop_constant, x_min, nsegments) - tanh(x_mid); 93 | c[i] = c[i] - 0.5*(max_diff); 94 | } 95 | 96 | double y1_new, y2_new; 97 | 98 | //Correct slopes and intercepts in order for monotonicity to 99 | //be maintained. 100 | for (int i = 1; i < nsegments; i++) { 101 | y1_new = m[i - 1] + c[i - 1]; 102 | y2_new = m[i] + c[i]; 103 | m[i] = y2_new - y1_new; 104 | c[i] = y1_new; 105 | } 106 | 107 | double increment = 3.0 / 65536.0; 108 | double abs_error, abs_error_max = 0, rel_error_max = 0, input_error_max; 109 | 110 | for (double input_tb = x_min; input_tb < x_max; input_tb += increment) { 111 | double expected = tanh(input_tb); 112 | double actual = pwl_new(input_tb, m, c, prop_constant, x_min, nsegments); 113 | double rel_error = abs( (expected - actual) / expected) * 100; 114 | if (rel_error > rel_error_max) { rel_error_max = rel_error; } 115 | abs_error = abs(expected - actual); 116 | if (abs_error > abs_error_max) { 117 | abs_error_max = abs_error; 118 | input_error_max = input_tb; 119 | } 120 | } 121 | 122 | int nfrac_bits = abs(floor(log2(abs_error_max))) + 1; 123 | 124 | ac_fixed<128, 64, true> m_fixed[nsegments], c_fixed[nsegments]; 125 | 126 | // Quantize double values according to fixed point precision. 127 | for (int i = 0; i < nsegments; i++) { 128 | m_fixed[i] = o_ac_f(m[i], nfrac_bits); 129 | c_fixed[i] = o_ac_f(c[i], nfrac_bits); 130 | } 131 | 132 | // Find the quantum value of an fixed point variable with nfrac_bits number of fractional bits. 133 | const ac_fixed<128, 64, true> quant_val = pow(2, double(-nfrac_bits)); 134 | 135 | // Check left- and right-hand limits of the PWL function for each segment boundary. 136 | for (int i = 0; i < nsegments - 1; i++) { 137 | double lhl = (m_fixed[i] + c_fixed[i]).to_double(); 138 | double rhl = (c_fixed[i + 1]).to_double(); 139 | if (rhl < lhl) { 140 | // If the PWL output is not increasing at the segment boundary, decrease the slope of the 141 | // preceding segment so as to lower the left hand limit and make the PWL output increase 142 | // across the boundary. 143 | //m_fixed[i] = m_fixed[i] - quant_val; 144 | } 145 | } 146 | 147 | //Add elements to Objects that contain declaration of LUT arrays 148 | //in C++ syntax. 149 | for (int i = 0; i < nsegments; i++) { 150 | if (i == 0) { 151 | mstrstream << "{" << m_fixed[i] << ", "; 152 | cstrstream << "{" << c_fixed[i] << ", "; 153 | } else if (i == nsegments - 1) { 154 | mstrstream << m_fixed[i] << "}"; 155 | cstrstream << c_fixed[i] << "}"; 156 | } else { 157 | mstrstream << m_fixed[i] << ", "; 158 | cstrstream << c_fixed[i] << ", "; 159 | } 160 | } 161 | mstr = mstrstream.str(); 162 | cstr = cstrstream.str(); 163 | 164 | // Find max value in array, and see if it has any negative values. This helps figure out 165 | // the number of integer bits to use to store array values. 166 | double m_max_val, c_max_val; 167 | bool is_neg_m, is_neg_c; 168 | 169 | is_neg_m = is_neg_max_array(m, nsegments, m_max_val); 170 | is_neg_c = is_neg_max_array(c, nsegments, c_max_val); 171 | 172 | string is_neg_m_s = is_neg_m ? "true" : "false"; 173 | string is_neg_c_s = is_neg_c ? "true" : "false"; 174 | 175 | int m_int_bits = int_bits_calc(m_max_val, is_neg_m); 176 | int c_int_bits = int_bits_calc(c_max_val, is_neg_c); 177 | int x_min_int_bits = int_bits_calc(x_min, x_min < 0); 178 | int x_max_int_bits = int_bits_calc(x_max, x_max < 0); 179 | int p_c_int_bits = int_bits_calc(prop_constant, false); 180 | 181 | string is_neg_x_min_s = (x_min < 0) ? "true" : "false"; 182 | string is_neg_x_max_s = (x_max < 0) ? "true" : "false"; 183 | 184 | std::ofstream outfile(filename); 185 | outfile << "const unsigned n_segments_lut = " << nsegments << ";" < m_lut[n_segments_lut] = " << mstr << ";" << endl; 188 | outfile << "const ac_fixed<" << c_int_bits << " + n_frac_bits, " << c_int_bits << ", " << is_neg_c_s << "> c_lut[n_segments_lut] = " << cstr << ";" << endl; 189 | outfile << "const ac_fixed<" << x_min_int_bits << " + n_frac_bits, " << x_min_int_bits << ", " << is_neg_x_min_s << "> x_min_lut = " << o_ac_f(x_min, nfrac_bits) << ";" << endl; 190 | outfile << "const ac_fixed<" << x_max_int_bits << " + n_frac_bits, " << x_max_int_bits << ", " << is_neg_x_max_s << "> x_max_lut = " << o_ac_f(x_max, nfrac_bits) << ";" << endl; 191 | outfile << "const ac_fixed<" << p_c_int_bits << " + n_frac_bits, " << p_c_int_bits << ", false> sc_constant_lut = " << o_ac_f(prop_constant, nfrac_bits) << ";" << endl; 192 | outfile.close(); 193 | 194 | cout << endl; 195 | cout << __FILE__ << ", " << __LINE__ << ": Values are written, check \"" 196 | << filename << "\" for " << "the required ROM values" << endl ; 197 | cout << "abs_error_max = " << abs_error_max << endl; 198 | cout << "input_error_max = " << input_error_max << endl; 199 | cout << "nfrac_bits = " << nfrac_bits << endl; 200 | cout << "rel_error_max = " << rel_error_max << endl; 201 | 202 | return 0; 203 | } 204 | 205 | -------------------------------------------------------------------------------- /lutgen/helper_functions.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | #ifndef HELPER_FUNCTIONS_H 32 | #define HELPER_FUNCTIONS_H 33 | 34 | template 35 | double pwl_new(const double x_in, const double (&m)[size], const double (&c)[size], const double prop_constant, const double x_min, const unsigned nsegments) 36 | { 37 | unsigned index; 38 | double x_in_sc = (x_in - x_min) * prop_constant; 39 | if (x_in_sc < nsegments) {index = floor(x_in_sc);} 40 | else {index = nsegments - 1;} 41 | double y_out = m[index] * (x_in_sc - index) + c[index]; 42 | return y_out; 43 | } 44 | 45 | // Function that returns max value and presence of negative elements in an array. 46 | template 47 | bool is_neg_max_array(const double (&input_array)[size], const unsigned nsegments, double &max_val) 48 | { 49 | // This variable is set to true if even a single element is negative. 50 | bool is_neg = (input_array[0] < 0); 51 | max_val = abs(input_array[0]); 52 | for(unsigned i = 1; i < nsegments; i++) { 53 | if(input_array[i] < 0) { is_neg = true; } 54 | if(abs(input_array[i]) > max_val) { max_val = abs(input_array[i]); } 55 | } 56 | return is_neg; 57 | } 58 | 59 | // Make a number non-zero, useful for log calculations. 60 | double make_non_zero(double input) 61 | { 62 | if(input == 0) {input = 1;} 63 | return input; 64 | } 65 | 66 | int int_bits_calc(double val, bool S) 67 | { 68 | return ceil(log2(make_non_zero(abs(val)))) + int(S) + 1; 69 | } 70 | 71 | // This function takes a double variable and performs an operation that mimics the quantization of the same double variable into an ac_fixed variable with "nfrac_bits" number of fractional 72 | // bits and rounding turned on (AC_RND). 73 | ac_fixed<128, 64, true> o_ac_f(double input, int nfrac_bits) 74 | { 75 | return (ac_fixed<128, 64, true>)((double)rint(input * (1 << nfrac_bits)) * pow(2, (double)(-nfrac_bits))); 76 | } 77 | 78 | // This function takes a double variable and performs an operation that mimics the quantization of the same double variable into an ac_fixed variable with "nfrac_bits" number of fractional 79 | // bits and rounding turned off (AC_TRN). 80 | ac_fixed<128, 64, true> o_ac_f_trn(double input, int nfrac_bits) 81 | { 82 | return (ac_fixed<128, 64, true>)((double)floor(input * (1 << nfrac_bits)) * pow(2, (double)(-nfrac_bits))); 83 | } 84 | 85 | // Find out whether a double number is an integer or not. 86 | bool is_int(double &input) { 87 | return trunc(input) == input; 88 | } 89 | 90 | #endif // HELPER_FUNCTIONS_H 91 | -------------------------------------------------------------------------------- /pdfdocs/ac_math_ref.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hlslibs/ac_math/d4a37599a533b463a093a0d8c01751882dbce733/pdfdocs/ac_math_ref.pdf -------------------------------------------------------------------------------- /pdfdocs/ac_math_relnotes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hlslibs/ac_math/d4a37599a533b463a093a0d8c01751882dbce733/pdfdocs/ac_math_relnotes.pdf -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | ifeq "$(AC_TYPES_INC)" "" 2 | $(error Error: The AC_TYPES_INC variable was not set. Cannot locate AC Datatypes installation) 3 | endif 4 | 5 | AC_MATH_INC = ../include 6 | 7 | ifeq "$(GCC_EXEC)" "" 8 | GCC_EXEC = g++ 9 | endif 10 | 11 | CXXFLAGS = -g -std=c++11 -I. -O3 12 | LDFLAGS = -s -static-libstdc++ 13 | WD = $(shell pwd) 14 | GCOV_ENABLED = false 15 | 16 | ifneq "x$(GCOV_HOME)" "x" 17 | GCOV_ENABLED = true 18 | GCOV = $(GCOV_HOME)/gcov 19 | LCOV = $(GCOV_HOME)/lcov 20 | GENHTML = $(GCOV_HOME)/genhtml 21 | CXXFLAGS += -coverage 22 | LDFLAGS += -lgcov 23 | GCOV_OPTS := --gcov-tool $(GCOV) --quiet --rc geninfo_auto_base=1 --rc lcov_branch_coverage=1 --external 24 | GCCVER = $(shell $(GCC_EXEC) -dumpversion) 25 | GCOV_FILT_PAT := '/usr/include/*' '/usr/lib/*' '$(GCCVER)/*' 26 | endif 27 | 28 | DIE = || exit 1 ; 29 | RM := rm -f 30 | ECHO := echo 31 | 32 | SOURCES_CPP = \ 33 | rtest_ac_div.cpp \ 34 | rtest_ac_atan_pwl.cpp \ 35 | rtest_ac_atan_pwl_ha.cpp \ 36 | rtest_ac_atan_pwl_vha.cpp \ 37 | rtest_ac_barrel_shift.cpp \ 38 | rtest_ac_tan_pwl.cpp \ 39 | rtest_ac_sigmoid_pwl.cpp \ 40 | rtest_ac_tanh_pwl.cpp \ 41 | rtest_ac_cholinv.cpp \ 42 | rtest_ac_exp_cordic.cpp \ 43 | rtest_ac_exp2_cordic.cpp \ 44 | rtest_ac_pow2_pwl.cpp \ 45 | rtest_ac_exp_pwl.cpp \ 46 | rtest_ac_determinant.cpp \ 47 | rtest_ac_chol_d.cpp \ 48 | rtest_ac_qrd.cpp \ 49 | rtest_ac_abs.cpp \ 50 | rtest_ac_arccos_cordic.cpp \ 51 | rtest_ac_arcsin_cordic.cpp \ 52 | rtest_ac_atan2_cordic.cpp \ 53 | rtest_ac_exp_pwl.cpp \ 54 | rtest_ac_inverse_sqrt_pwl.cpp \ 55 | rtest_ac_inverse_sqrt_pwl_vha.cpp \ 56 | rtest_ac_log_cordic.cpp \ 57 | rtest_ac_log2_cordic.cpp \ 58 | rtest_ac_log2_pwl.cpp \ 59 | rtest_ac_log_pwl.cpp \ 60 | rtest_ac_matrix.cpp \ 61 | rtest_ac_array.cpp \ 62 | rtest_ac_matrixmul.cpp \ 63 | rtest_ac_normalize.cpp \ 64 | rtest_ac_pow2_pwl.cpp \ 65 | rtest_ac_pow_cordic.cpp \ 66 | rtest_ac_pow_pwl.cpp \ 67 | rtest_ac_reciprocal_pwl.cpp \ 68 | rtest_ac_reciprocal_pwl_ha.cpp \ 69 | rtest_ac_reciprocal_pwl_vha.cpp \ 70 | rtest_ac_shift.cpp \ 71 | rtest_ac_sincos_cordic.cpp \ 72 | rtest_ac_sincos_lut.cpp \ 73 | rtest_ac_softmax_pwl.cpp \ 74 | rtest_ac_softmax_pwl_new.cpp \ 75 | rtest_ac_sqrt.cpp \ 76 | rtest_ac_sqrt_pwl.cpp \ 77 | rtest_ac_leading.cpp\ 78 | rtest_signed_ac_div_v2.cpp\ 79 | rtest_unsigned_ac_div_v2.cpp \ 80 | rtest_ac_softplus_pwl.cpp \ 81 | rtest_ac_softsign_pwl.cpp \ 82 | rtest_ac_elu_pwl.cpp \ 83 | rtest_ac_selu_pwl.cpp \ 84 | rtest_ac_gelu_pwl.cpp \ 85 | rtest_ac_leakyrelu.cpp \ 86 | rtest_ac_relu.cpp \ 87 | rtest_ac_prelu.cpp \ 88 | rtest_ac_float_add_tree.cpp \ 89 | rtest_ac_flfx_mul.cpp 90 | 91 | OBJS = $(SOURCES_CPP:.cpp=.o) 92 | 93 | GCOVDAT = $(SOURCES_CPP:.cpp=.gcda) $(SOURCES_CPP:.cpp=.gcno) $(SOURCES_CPP:.cpp=.o.base.info) $(SOURCES_CPP:.cpp=.o.test.info) $(SOURCES_CPP:.cpp=.o.total.info) $(SOURCES_CPP:.cpp=.o.filt.info) 94 | 95 | # Compilation rule 96 | %.o: %.cpp 97 | ifeq "$(GCOV_ENABLED)" "true" 98 | -@$(RM) *.gcda *.gcno 99 | endif 100 | -@$(ECHO) "------------------------------ Compile $< ----------------------------------" 101 | @$(GCC_EXEC) $(CXXFLAGS) -I$(AC_TYPES_INC) -I$(AC_MATH_INC) $< $(LDFLAGS) $(LINK_LIBNAMES) -o $@ $(DIE) 102 | ifeq "$(GCOV_ENABLED)" "true" 103 | -@$(ECHO) "------------------------------ Prep $< ----------------------------------" 104 | -@$(RM) *.info 105 | @-$(LCOV) $(GCOV_OPTS) --capture --initial --directory . --output-file $@.base.info 106 | endif 107 | -@$(ECHO) "------------------------------ Running $< ----------------------------------" 108 | @./$@ $(DIE) 109 | ifeq "$(GCOV_ENABLED)" "true" 110 | -@$(ECHO) "------------------------------ Coverage $< ----------------------------------" 111 | @-$(LCOV) $(GCOV_OPTS) --capture --directory . --output-file $@.test.info 112 | @-$(LCOV) $(GCOV_OPTS) --add-tracefile $@.base.info --add-tracefile $@.test.info --output-file $@.total.info 113 | @-$(LCOV) $(GCOV_OPTS) --remove $@.total.info $(GCOV_FILT_PAT) -o $@.filt.info 114 | @-$(GENHTML) --rc geninfo_auto_base=1 --rc lcov_branch_coverage=1 --ignore-errors source $@.filt.info --legend --output-directory=$@-test-lcov 115 | @-$(ECHO) "HTML coverage report written to: file://$(WD)/$@-test-lcov/index.html" 116 | endif 117 | 118 | all: $(OBJS) 119 | 120 | .PHONY: clean 121 | clean: 122 | @-$(RM) -r $(OBJS) $(GCOVDAT) 123 | 124 | -------------------------------------------------------------------------------- /tests/Visual_studio.bat: -------------------------------------------------------------------------------- 1 | ::This is a windows .bat file which runs the ac_ipl unit tests using the visual studio developer command prompt 2 | 3 | ::Invoke the visual studio developer command prompt 4 | call "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\Tools\VsDevCmd.bat" 5 | 6 | ::Set the path for Mgc_home 7 | set MGC_HOME=C:\MGCNoScan\abeemana\sb\sif\ixn\Mgc_home 8 | 9 | ::All the unit tests 10 | set SOURCES_CPP=rtest_ac_div;^ 11 | rtest_ac_atan_pwl;^ 12 | rtest_ac_atan_pwl_ha;^ 13 | rtest_ac_atan_pwl_vha;^ 14 | rtest_ac_barrel_shift;^ 15 | rtest_ac_tan_pwl;^ 16 | rtest_ac_sigmoid_pwl;^ 17 | rtest_ac_tanh_pwl;^ 18 | rtest_ac_cholinv;^ 19 | rtest_ac_exp_cordic;^ 20 | rtest_ac_exp2_cordic;^ 21 | rtest_ac_pow2_pwl;^ 22 | rtest_ac_exp_pwl;^ 23 | rtest_ac_determinant;^ 24 | rtest_ac_chol_d;^ 25 | rtest_ac_qrd;^ 26 | rtest_ac_abs;^ 27 | rtest_ac_arccos_cordic;^ 28 | rtest_ac_arcsin_cordic;^ 29 | rtest_ac_atan2_cordic;^ 30 | rtest_ac_exp_pwl;^ 31 | rtest_ac_inverse_sqrt_pwl;^ 32 | rtest_ac_inverse_sqrt_pwl_vha;^ 33 | rtest_ac_log_cordic;^ 34 | rtest_ac_log2_cordic;^ 35 | rtest_ac_log2_pwl;^ 36 | rtest_ac_log_pwl;^ 37 | rtest_ac_array;^ 38 | rtest_ac_matrix;^ 39 | rtest_ac_matrixmul;^ 40 | rtest_ac_normalize;^ 41 | rtest_ac_pow2_pwl;^ 42 | rtest_ac_pow_cordic;^ 43 | rtest_ac_pow_pwl;^ 44 | rtest_ac_reciprocal_pwl;^ 45 | rtest_ac_reciprocal_pwl_ha;^ 46 | rtest_ac_reciprocal_pwl_vha;^ 47 | rtest_ac_shift;^ 48 | rtest_ac_sincos_cordic;^ 49 | rtest_ac_sincos_lut;^ 50 | rtest_ac_softmax_pwl;^ 51 | rtest_ac_sqrt;^ 52 | rtest_ac_sqrt_pwl;^ 53 | rtest_ac_leading;^ 54 | rtest_signed_ac_div_v2;^ 55 | rtest_unsigned_ac_div_v2 56 | 57 | ::Compile and execute the unit tests 58 | (for %%a in (%SOURCES_CPP%) do ( 59 | cl /EHsc /I%MGC_HOME%\shared\include %%a.cpp 60 | %%a.exe 61 | )) 62 | -------------------------------------------------------------------------------- /tests/mc_scverify.h: -------------------------------------------------------------------------------- 1 | // This header is a stub replacement for the full verification 2 | // header from Catapult placed here for standalone compilation of 3 | // the blocks. 4 | #if defined(CCS_SCVERIFY) || defined(CCS_SYSC) 5 | #error Incorrect mc_scverify.h header encountered during compilation 6 | #else 7 | #define CCS_BLOCK(a) a 8 | #endif 9 | -------------------------------------------------------------------------------- /tests/rtest_ac_atan2_cordic.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // =========================TESTBENCH======================================= 32 | // This testbench file contains a stand-alone testbench that exercises the 33 | // ac_atan2_cordic() function using a variety of bit-widths. 34 | 35 | // To compile standalone and run: 36 | // $MGC_HOME/bin/c++ -std=c++11 -I$MGC_HOME/shared/include rtest_ac_atan2_cordic.cpp -o design 37 | // ./design 38 | 39 | // Include the AC Math function that is exercised with this testbench 40 | #include 41 | using namespace ac_math; 42 | 43 | //============================================================================== 44 | // Test Design 45 | // This simple function allows executing the ac_atan2_cordic() function. 46 | // Template parameters are used to configure the bit-widths of the types. 47 | 48 | template 49 | void test_ac_atan2_cordic( 50 | const ac_fixed &y, 51 | const ac_fixed &x, 52 | ac_fixed &out_atan2 53 | ) 54 | { 55 | ac_atan2_cordic(y, x, out_atan2); 56 | } 57 | 58 | //============================================================================== 59 | 60 | #include 61 | #include 62 | #include 63 | #include 64 | using namespace std; 65 | 66 | //============================================================================== 67 | // Function: test_driver() 68 | // Description: A templatized function that can be configured for certain bit- 69 | // widths of the fixed point AC datatype. It uses the type information to 70 | // iterate through a range of valid values on that type in order to compare 71 | // the precision of the cordic based atan2 model with atan2 using 72 | // the standard C math library. The maximum error for each type is accumulated 73 | // in variables defined in the calling function. 74 | 75 | template 76 | int test_driver( 77 | double &cummulative_max_error_atan2, 78 | const double allowed_error, 79 | bool details = false 80 | ) 81 | { 82 | bool passed = true; 83 | double max_error_atan2 = 0.0; // reset for this run 84 | 85 | ac_fixed y; 86 | ac_fixed x; 87 | ac_fixed out_atan2; 88 | 89 | typedef ac_fixed T_out; 90 | 91 | double lower_limit, upper_limit, step; 92 | 93 | // set ranges and step size for the testbench 94 | lower_limit = y.template set_val().to_double(); 95 | upper_limit = y.template set_val().to_double(); 96 | step = y.template set_val().to_double(); 97 | 98 | cout << "TEST: ac_atan2_cordic() INPUT: "; 99 | cout.width(38); 100 | cout << left << y.type_name(); 101 | cout << " OUTPUTS: "; 102 | cout.width(38); 103 | cout << left << out_atan2.type_name(); 104 | cout << "RESULT: "; 105 | 106 | // Dump the test details 107 | if (details) { 108 | cout << endl; // LCOV_EXCL_LINE 109 | cout << " Ranges for input types:" << endl; // LCOV_EXCL_LINE 110 | cout << " lower_limit = " << lower_limit << endl; // LCOV_EXCL_LINE 111 | cout << " upper_limit = " << upper_limit << endl; // LCOV_EXCL_LINE 112 | cout << " step = " << step << endl; // LCOV_EXCL_LINE 113 | } 114 | 115 | for (double i = lower_limit; i < upper_limit; i += step) 116 | for (double j = lower_limit; j < upper_limit; j += step) { 117 | // Set values for input. 118 | x = i; 119 | y = j; 120 | test_ac_atan2_cordic(y, x, out_atan2); 121 | 122 | double expected_atan2_value = ((T_out)(atan2(y.to_double(), x.to_double()))).to_double(); 123 | double actual_atan2_value = out_atan2.to_double(); 124 | double this_error_atan2; 125 | 126 | this_error_atan2 = fabs(expected_atan2_value - actual_atan2_value) * 100.0; 127 | 128 | if (this_error_atan2 > max_error_atan2) {max_error_atan2 = this_error_atan2;} 129 | 130 | } 131 | 132 | if (passed) { printf("PASSED , max err (%f atan2) \n", max_error_atan2); } 133 | else { printf("FAILED , max err (%f atan2) \n", max_error_atan2); } // LCOV_EXCL_LINE 134 | 135 | if (max_error_atan2>cummulative_max_error_atan2) { cummulative_max_error_atan2 = max_error_atan2; } 136 | 137 | return 0; 138 | } 139 | 140 | 141 | int main(int argc, char *argv[]) 142 | { 143 | double max_error_atan2 = 0; 144 | double allowed_error = 0.1; 145 | cout << "=============================================================================" << endl; 146 | cout << "Testing function: ac_atan2_cordic() - Allowed error " << allowed_error << endl; 147 | 148 | // template 149 | test_driver< 12, 1, true, 24, 5, true>(max_error_atan2, allowed_error); 150 | test_driver< 2, 0, true, 27, 2, true>(max_error_atan2, allowed_error); 151 | test_driver< 11, 6, true, 24, 3, true>(max_error_atan2, allowed_error); 152 | test_driver< 4, 1, true, 25, 3, true>(max_error_atan2, allowed_error); 153 | test_driver< 10, -2, true, 30, 4, true>(max_error_atan2, allowed_error); 154 | test_driver< 9, -2, true, 28, 2, true>(max_error_atan2, allowed_error); 155 | test_driver< 2, -2, true, 32, 2, true>(max_error_atan2, allowed_error); 156 | test_driver< 11, 1, true, 34, 2, true>(max_error_atan2, allowed_error); 157 | test_driver< 8, -3, true, 25, 2, true>(max_error_atan2, allowed_error); 158 | test_driver< 7, -3, true, 26, 2, true>(max_error_atan2, allowed_error); 159 | test_driver< 5, 2, true, 24, 2, true>(max_error_atan2, allowed_error); 160 | test_driver< 6, 2, true, 24, 2, true>(max_error_atan2, allowed_error); 161 | 162 | cout << "=============================================================================" << endl; 163 | cout << " Testbench finished. Maximum errors observed across all bit-width variations:" << endl; 164 | cout << " max_error_atan2 = " << max_error_atan2 << endl; 165 | 166 | // If error limits on any tested datatype have been crossed, the test has failed 167 | bool test_fail = max_error_atan2 > allowed_error; 168 | 169 | // Notify the user that the test was a failure. 170 | if (test_fail) { 171 | cout << " ac_atan2_cordic - FAILED - Error tolerance(s) exceeded" << endl; // LCOV_EXCL_LINE 172 | cout << "=============================================================================" << endl; // LCOV_EXCL_LINE 173 | return -1; // LCOV_EXCL_LINE 174 | } else { 175 | cout << " ac_atan2_cordic - PASSED" << endl; 176 | cout << "=============================================================================" << endl; 177 | } 178 | return 0; 179 | } 180 | 181 | 182 | -------------------------------------------------------------------------------- /tests/rtest_ac_barrel_shift.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // =========================TESTBENCH======================================= 32 | // This testbench file contains a stand-alone testbench that exercises the 33 | // ac_barrel_shift() function using a variety of data types and bit- 34 | // widths. 35 | 36 | // To compile standalone and run: 37 | // $MGC_HOME/bin/c++ -std=c++11 -I$MGC_HOME/shared/include rtest_ac_barrel_shift.cpp -o design 38 | // ./design 39 | 40 | // Include the AC Math function that is exercised with this testbench 41 | 42 | #include 43 | using namespace ac_math; 44 | 45 | // ============================================================================== 46 | // Test Designs 47 | // These simple functions allow executing the ac_barrel_shift function 48 | // using multiple data types at the same time. Template parameters are used to 49 | // configure the bit-widths of the types. 50 | 51 | // Test for barrel shifts on unsigned ac_int inputs and outputs. 52 | template 53 | void test_ac_barrel_shift_us( 54 | const ac_int &us_int_input, 55 | ac_int &us_int_output, 56 | const ac_int< ac::nbits< W - 1 >::val,false> &us_shift 57 | ) 58 | { 59 | us_int_output =ac_barrel_shift(us_int_input, (ac_int< ac::nbits< W - 1 >::val,false>)us_shift); 60 | } 61 | 62 | // ============================================================================== 63 | 64 | #include 65 | #include 66 | #include 67 | #include 68 | using namespace std; 69 | 70 | // ------------------------------------------------------------ 71 | // Helper functions for error detection and output checking. 72 | 73 | #ifdef DEBUG 74 | 75 | // Helper functions to pin-point error. 76 | 77 | template 78 | void print_origin_error( 79 | const ac_int input, 80 | const int n 81 | ) 82 | { 83 | cout << "error coming from barrel shift function" << endl; 84 | } 85 | #endif 86 | 87 | // Check output and make sure it is correct for real values and shifts 88 | 89 | template 90 | bool output_check_barrel_shift( 91 | const ac_int input, 92 | const ac_int< ac::nbits< W - 1 >::val,false> n, 93 | const ac_int output 94 | ) 95 | { 96 | // Since the output of ac_barrel_shift operations have an arithmetic 97 | // basis and take into account rounding and saturation, test 98 | // the output against the input multiplied by 2^(shift_count) 99 | 100 | ac_int expected_output = (input >> (n%W)) | (input << (W-(n%W))); 101 | bool correct = (output == expected_output); 102 | 103 | #ifdef DEBUG 104 | if (!correct) { 105 | cout << endl; 106 | cout << "barrel shift" << endl; 107 | print_origin_error(input, n); 108 | cout << "The output is not as expected." << endl; 109 | cout << "input = " << input << endl; 110 | cout << "expected_output = " << expected_output << endl; 111 | cout << "output = " << output << endl; 112 | cout << "n = " << n << endl; 113 | assert(false); 114 | } 115 | #endif 116 | 117 | return correct; 118 | } 119 | 120 | // ============================================================================== 121 | // Functions: test_driver functions 122 | // Description: Templatized functions that can be configured for certain bit- 123 | // widths of AC datatypes. They use the type information to iterate through a 124 | // range of valid values on that type and make sure that the output of the 125 | // ac_barrel_shift function is correct 126 | 127 | // ============================================================================== 128 | // Function: test_driver_us() 129 | // Description: test_driver function for unsigned ac_int and ac_int inputs 130 | // and outputs. 131 | 132 | template 133 | int test_driver_us( 134 | bool &all_tests_pass, 135 | bool details = false 136 | ) 137 | { 138 | ac_int us_int_input; 139 | ac_int us_int_output; 140 | 141 | double lower_limit, upper_limit, step; 142 | 143 | // set ranges and step size for int point testbench 144 | lower_limit = us_int_input.template set_val().to_double(); 145 | upper_limit = us_int_input.template set_val().to_double(); 146 | step = us_int_input.template set_val().to_double()*upper_limit/50; 147 | step = step==0?1:step; 148 | 149 | cout << "TEST: ac_barrel_shift() INPUT: "; 150 | cout.width(38); 151 | cout << left << us_int_input.type_name(); 152 | cout << "OUTPUT: "; 153 | cout.width(50); 154 | cout << left << us_int_output.type_name(); 155 | cout << "RESULT: "; 156 | 157 | // Dump the test details 158 | if (details) { 159 | cout << endl; // LCOV_EXCL_LINE 160 | cout << " Ranges for input types:" << endl; // LCOV_EXCL_LINE 161 | cout << " lower_limit = " << lower_limit << endl; // LCOV_EXCL_LINE 162 | cout << " upper_limit = " << upper_limit << endl; // LCOV_EXCL_LINE 163 | cout << " step = " << step << endl; // LCOV_EXCL_LINE 164 | } 165 | 166 | bool correct = true; 167 | 168 | for (int n = 0; n <= W; n++) { 169 | for (double i = lower_limit; i <= upper_limit; i += step) { 170 | us_int_input = i; 171 | test_ac_barrel_shift_us(us_int_input, us_int_output, n); 172 | bool correct_iteration_barrel_shift = output_check_barrel_shift( us_int_input, n, us_int_output ); 173 | 174 | correct = correct && correct_iteration_barrel_shift; 175 | } 176 | } 177 | 178 | if (correct) { printf("PASSED\n"); } 179 | else { printf("FAILED\n"); } // LCOV_EXCL_LINE 180 | 181 | all_tests_pass = all_tests_pass && correct; 182 | 183 | return 0; 184 | } 185 | 186 | int main(int argc, char *argv[]) 187 | { 188 | cout << "=============================================================================" << endl; 189 | cout << "Testing function: ac_barrel_shift(), unsigned ac_int types." << endl; 190 | 191 | bool all_tests_pass = true; 192 | 193 | // If any of the tests fail, the all_tests_pass variable will be set to false 194 | 195 | test_driver_us<10>(all_tests_pass); 196 | test_driver_us<15>(all_tests_pass); 197 | test_driver_us<13>(all_tests_pass); 198 | test_driver_us<18>(all_tests_pass); 199 | test_driver_us<20>(all_tests_pass); 200 | 201 | cout << "=============================================================================" << endl; 202 | cout << " Testbench finished." << endl; 203 | 204 | // Notify the user if the test was a failure. 205 | if (!all_tests_pass) { 206 | cout << " ac_barrel_shift - FAILED - output not correct for all test values" << endl; // LCOV_EXCL_LINE 207 | cout << "=============================================================================" << endl; // LCOV_EXCL_LINE 208 | return -1; // LCOV_EXCL_LINE 209 | } else { 210 | cout << " ac_barrel_shift - PASSED" << endl; 211 | cout << "=============================================================================" << endl; 212 | } 213 | 214 | return 0; 215 | } 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | -------------------------------------------------------------------------------- /tests/rtest_ac_softsign_pwl.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright 2018 Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // =========================TESTBENCH======================================= 32 | // This testbench file contains a stand-alone testbench that exercises the 33 | // ac_softsign_pwl() function using a variety of bit-widths. 34 | 35 | // To compile standalone and run: 36 | // $MGC_HOME/bin/c++ -std=c++11 -I$MGC_HOME/shared/include rtest_ac_softsign_pwl.cpp -o design 37 | // ./design 38 | 39 | // Include the AC Math function that is exercised with this testbench 40 | #include 41 | using namespace ac_math; 42 | 43 | // ============================================================================== 44 | // Test Designs 45 | // These simple function allow executing the ac_softsign_pwl() function. 46 | // Template parameters are used to configure the bit-widths of the 47 | // inputs and outputs. 48 | 49 | // Test design for real fixed point values. 50 | 51 | template 52 | void test_ac_softsign_pwl_fixed( 53 | const ac_fixed &in, 54 | ac_fixed &out 55 | ) 56 | { 57 | ac_softsign_pwl(in, out); 58 | } 59 | 60 | // ============================================================================== 61 | 62 | #include 63 | #include 64 | #include 65 | #include 66 | using namespace std; 67 | 68 | // ============================================================================== 69 | // Function: test_driver_fixed() 70 | // Description: A templatized function that can be configured for certain bit- 71 | // widths of ac_fixed inputs. It uses the type information to iterate through a 72 | // range of valid values on that type in order to compare the precision of the 73 | // piece-wise linear softsign model with the computed softsign using a 74 | // standard C double type. The maximum error for each type is accumulated 75 | // in variables defined in the calling function. 76 | 77 | template 78 | int test_driver_fixed( 79 | double &cumulative_max_error_fixed, 80 | const double allowed_error, 81 | const double threshold_fixed, 82 | bool details = false 83 | ) 84 | { 85 | double max_error_fixed = 0.0; // reset for this run 86 | 87 | ac_fixed input_fixed; 88 | typedef ac_fixed T_out; 89 | T_out output; 90 | 91 | double lower_limit, upper_limit, step; 92 | 93 | // set ranges and step size for fixed point testbench 94 | lower_limit = input_fixed.template set_val().to_double(); 95 | upper_limit = input_fixed.template set_val().to_double(); 96 | step = input_fixed.template set_val().to_double(); 97 | 98 | cout << "TEST: ac_softsign_pwl() INPUT: "; 99 | cout.width(38); 100 | cout << left << input_fixed.type_name(); 101 | cout << "OUTPUT: "; 102 | cout.width(38); 103 | cout << left << output.type_name(); 104 | cout << "RESULT: "; 105 | 106 | // Dump the test details 107 | if (details) { 108 | cout << endl; // LCOV_EXCL_LINE 109 | cout << " Ranges for input types:" << endl; // LCOV_EXCL_LINE 110 | cout << " lower_limit = " << lower_limit << endl; // LCOV_EXCL_LINE 111 | cout << " upper_limit = " << upper_limit << endl; // LCOV_EXCL_LINE 112 | cout << " step = " << step << endl; // LCOV_EXCL_LINE 113 | } 114 | 115 | double old_output; 116 | bool compare = false; 117 | 118 | for (double i = lower_limit; i <= upper_limit; i += step) { 119 | // Set values for input. 120 | input_fixed = i; 121 | test_ac_softsign_pwl_fixed(input_fixed, output); 122 | 123 | double expected_value = ((T_out)(input_fixed.to_double()/(1 + abs(input_fixed.to_double())))).to_double(); 124 | double actual_value = output.to_double(); 125 | 126 | double this_error; 127 | 128 | // If expected value of output falls below the threshold, calculate absolute error instead of relative 129 | if (expected_value > threshold_fixed) { 130 | this_error = abs( (expected_value - actual_value) / expected_value ) * 100.0; 131 | } else { 132 | this_error = abs(expected_value - actual_value) * 100.0; 133 | } 134 | 135 | #ifdef DEBUG 136 | if (this_error > allowed_error) { 137 | cout << endl; 138 | cout << "Error exceeds tolerance" << endl; 139 | cout << "input_fixed = " << input_fixed << endl; 140 | cout << "expected_value = " << expected_value << endl; 141 | cout << "actual_value = " << actual_value << endl; 142 | cout << "this_error = " << this_error << endl; 143 | cout << "threshold_fixed = " << threshold_fixed << endl; 144 | assert(false); 145 | } 146 | #endif 147 | 148 | if (this_error > max_error_fixed) {max_error_fixed = this_error;} 149 | } 150 | 151 | bool passed = (max_error_fixed < allowed_error); 152 | 153 | if (passed) { printf("PASSED , max err (%f)\n", max_error_fixed); } 154 | else { printf("FAILED , max err (%f)\n", max_error_fixed); } 155 | 156 | if (max_error_fixed>cumulative_max_error_fixed) { cumulative_max_error_fixed = max_error_fixed; } 157 | 158 | return 0; 159 | } 160 | 161 | int main(int argc, char *argv[]) 162 | { 163 | double max_error_fixed = 0.0; 164 | double allowed_error = 2.0; 165 | double threshold = 0.005; 166 | 167 | cout << "=============================================================================" << endl; 168 | cout << "Testing function: ac_softsign_pwl() - Allowed error " << allowed_error << endl; 169 | 170 | // template 171 | 172 | test_driver_fixed< 10, 3, false, 64, 32, false>(max_error_fixed, allowed_error, threshold); 173 | test_driver_fixed< 9, 4, false, 64, 32, false>(max_error_fixed, allowed_error, threshold); 174 | test_driver_fixed< 4, 2, false, 64, 32, false>(max_error_fixed, allowed_error, threshold); 175 | test_driver_fixed< 3, 4, false, 64, 32, false>(max_error_fixed, allowed_error, threshold); 176 | test_driver_fixed< 1, 3, false, 61, 33, false>(max_error_fixed, allowed_error, threshold); 177 | test_driver_fixed< 2, 3, false, 64, 32, false>(max_error_fixed, allowed_error, threshold); 178 | test_driver_fixed< 18, 4, false, 64, 32, false>(max_error_fixed, allowed_error, threshold); 179 | test_driver_fixed< 20, 0, false, 64, 32, false>(max_error_fixed, allowed_error, threshold); 180 | test_driver_fixed< 18, 3, true, 64, 32, true>(max_error_fixed, allowed_error, threshold); 181 | test_driver_fixed< 19, 2, true, 64, 32, true>(max_error_fixed, allowed_error, threshold); 182 | test_driver_fixed< 21, -4, true, 64, 32, true>(max_error_fixed, allowed_error, threshold); 183 | test_driver_fixed< 20, 3, true, 64, 32, true>(max_error_fixed, allowed_error, threshold); 184 | 185 | 186 | // If error limits on any tested datatype have been crossed, the test has failed 187 | bool test_fail = (max_error_fixed > allowed_error); 188 | 189 | // Notify the user that the test was a failure. 190 | if (test_fail) { 191 | cout << " ac_softsign_pwl - FAILED - Error tolerance(s) exceeded" << endl; 192 | cout << "=============================================================================" << endl; 193 | return -1; 194 | } else { 195 | cout << " ac_softsign_pwl - PASSED" << endl; 196 | cout << "=============================================================================" << endl; 197 | } 198 | return (0); 199 | } 200 | -------------------------------------------------------------------------------- /tests/rtest_signed_ac_div_v2.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // =========================TESTBENCH======================================= 32 | // This testbench file contains a stand-alone testbench that exercises the 33 | // ac_div() function using a variety of data types and bit- 34 | // widths. 35 | 36 | // To compile standalone and run: 37 | // $MGC_HOME/bin/c++ -std=c++11 -I$MGC_HOME/shared/include rtest_signed_ac_div_v2.cpp -o design 38 | // ./design 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | // Include the AC Math function that is exercised with this testbench 49 | #include 50 | 51 | using namespace std; 52 | 53 | const int numWint = 10; 54 | const int denWint = 5; 55 | const int padWint= 2; 56 | 57 | // Pad width minimum is 2 for Signed values and maximum is divisor width. 58 | // For Unsigned minium is 1 and max is divisor width. 59 | 60 | const int quoWint = numWint-denWint+1+padWint; 61 | const int remWint = numWint; 62 | 63 | // Define types for ac_int<> signed usage 64 | typedef ac_int s_real_num_int_type; 65 | typedef ac_int s_real_den_int_type; 66 | typedef ac_int s_real_quo_int_type; 67 | typedef ac_int s_real_rem_int_type; 68 | 69 | #pragma hls_design top 70 | void rtest_ac_div( 71 | const s_real_num_int_type &in1, 72 | const s_real_den_int_type &in2, 73 | s_real_quo_int_type &out1, 74 | s_real_rem_int_type &out2 75 | ) 76 | { 77 | ac_div_v2(in1,in2,out1,out2); 78 | } 79 | 80 | int main(int argc, char *argv[]) 81 | { 82 | 83 | //================== Variable Declared ================================= 84 | bool ERROR=false; 85 | s_real_num_int_type Dividend,max_num,min_num; 86 | s_real_den_int_type Divisor,max_den,min_den,mask=0; 87 | s_real_quo_int_type DUT_Quotient; 88 | s_real_rem_int_type DUT_Remainder; 89 | int32 REF_Quotient, REF_Remainder; 90 | mask[padWint-1]=1; 91 | //================================================ 92 | max_den.template set_val(); 93 | max_num.template set_val(); 94 | min_num.template set_val(); 95 | min_den.template set_val(); 96 | 97 | #ifdef DEBUG 98 | 99 | cout << "Max value of the numerator : " << max_num << " [ " << bitset(max_num) << " ] "<< endl; 100 | cout << "Max value of the denominator : " << max_den << " [ " << bitset(max_den) << " ] "<< endl; 101 | cout << "Min value of the numerator : " << min_num << " [ " << bitset(min_num) << " ] "<< endl; 102 | cout << "Min value of the denominator : " << min_den << " [ " << bitset(min_den) << " ] "<< endl;; 103 | cout << "Range of Divisor values not supported by synthesized design are from : " << (min_den/mask)-1 << " to " << (max_den/mask)+1 << endl; 104 | 105 | #endif 106 | 107 | for (double i=min_den; i<=(double)max_den; i++) { 108 | for (double j =min_num; j<=(double)max_num; j++) { 109 | // cout << "----------------------------------------" << endl; 110 | 111 | Dividend=j; 112 | Divisor=i; 113 | 114 | if (Divisor==0) { 115 | // cout << "Skipping the Zero Value input " << endl; 116 | continue; 117 | } 118 | 119 | else if (Divisor>(min_den/mask)-1 && Divisor < (max_den/mask)+1) { 120 | // cout << "Skipping the Divisor values out of range " << endl; 121 | continue; 122 | } 123 | 124 | /* Feed the random values into the design */ 125 | rtest_ac_div(Dividend,Divisor,DUT_Quotient,DUT_Remainder); 126 | 127 | /* Golden Reference of the division model */ 128 | REF_Quotient=Dividend/Divisor; // Reference Version 129 | REF_Remainder=Dividend%Divisor; 130 | 131 | #ifdef DEBUG 132 | /* Debug System Outs */ 133 | cout << "Dividend : " << Dividend << " [ " << bitset(Dividend) << " ] "<< endl; 134 | cout << "Divisor : " << Divisor << " [ " << bitset(Divisor) << " ] "<< endl; 135 | cout << "Quotient : " << "New Design: " << DUT_Quotient << " || ReF Value: " << REF_Quotient << endl; 136 | cout << "Remainder : " << "New Design: " << DUT_Remainder << " || ReF Value: " << REF_Remainder << endl; 137 | #endif 138 | 139 | /* Compare the DUT values against Reference value */ 140 | if (DUT_Quotient.to_int() != REF_Quotient) { 141 | cout << "ERROR !!!!!!!!!!! in Quotient " << endl; 142 | ERROR= true; 143 | return 0; 144 | } 145 | if (DUT_Remainder.to_int() != REF_Remainder) { 146 | cout << "ERROR !!!!!!!!!!! in Remainder " << endl; 147 | ERROR = true; 148 | return 0; 149 | } 150 | } 151 | } 152 | if (!ERROR) { 153 | cout << " No Error , All Clear " << endl; 154 | } 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /tests/rtest_unsigned_ac_div_v2.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Algorithmic C (tm) Math Library * 4 | * * 5 | * Software Version: 3.8 * 6 | * * 7 | * Release Date : Tue May 13 15:34:32 PDT 2025 * 8 | * Release Type : Production Release * 9 | * Release Build : 3.8.1 * 10 | * * 11 | * Copyright Siemens * 12 | * * 13 | ************************************************************************** 14 | * Licensed under the Apache License, Version 2.0 (the "License"); * 15 | * you may not use this file except in compliance with the License. * 16 | * You may obtain a copy of the License at * 17 | * * 18 | * http://www.apache.org/licenses/LICENSE-2.0 * 19 | * * 20 | * Unless required by applicable law or agreed to in writing, software * 21 | * distributed under the License is distributed on an "AS IS" BASIS, * 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 23 | * implied. * 24 | * See the License for the specific language governing permissions and * 25 | * limitations under the License. * 26 | ************************************************************************** 27 | * * 28 | * The most recent version of this package is available at github. * 29 | * * 30 | *************************************************************************/ 31 | // =========================TESTBENCH======================================= 32 | // This testbench file contains a stand-alone testbench that exercises the 33 | // ac_div() function using a variety of data types and bit- 34 | // widths. 35 | 36 | // To compile standalone and run: 37 | // $MGC_HOME/bin/c++ -std=c++11 -I$MGC_HOME/shared/include rtest_unsigned_ac_div_v2.cpp -o design 38 | // ./design 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | // Include the AC Math function that is exercised with this testbench 49 | #include 50 | 51 | using namespace std; 52 | 53 | // #if defined(RUNNING_OUTSIDE_OF_HLSTEST) 54 | const int numWint = 10; 55 | const int denWint = 5; 56 | const int padWint = 1; 57 | // Pad width minimum is 2 for Signed values and maximum is divisor width. 58 | // For Unsigned minium is 1 and max is divisor width. 59 | const int quoWint = numWint; 60 | const int remWint = numWint; 61 | 62 | 63 | // Define types for ac_int<> unsigned usage 64 | typedef ac_int us_real_num_int_type; 65 | typedef ac_int us_real_den_int_type; 66 | typedef ac_int us_real_quo_int_type; 67 | typedef ac_int us_real_rem_int_type; 68 | 69 | 70 | #pragma hls_design top 71 | void rtest_ac_div( 72 | const us_real_num_int_type &in1, 73 | const us_real_den_int_type &in2, 74 | us_real_quo_int_type &out1, 75 | us_real_rem_int_type &out2 76 | ) 77 | { 78 | ac_div_v2(in1,in2,out1,out2); 79 | } 80 | 81 | int main(int argc, char *argv[]) 82 | { 83 | 84 | //================== Variable Declared ================================= 85 | 86 | bool ERROR=false; 87 | us_real_num_int_type Dividend,max_num,min_num; 88 | us_real_den_int_type Divisor,max_den,min_den,mask; 89 | us_real_quo_int_type DUT_Quotient; 90 | us_real_rem_int_type DUT_Remainder; 91 | uint32 REF_Quotient, REF_Remainder; 92 | 93 | mask[denWint-padWint]=1; // Signed values. 94 | 95 | //================================================ 96 | max_den.template set_val(); 97 | max_num.template set_val(); 98 | min_num.template set_val(); 99 | min_den.template set_val(); 100 | 101 | #ifdef DEBUG 102 | cout << "Max value of the numerator : " << max_num << " [ " << bitset(max_num) << " ] "<< endl; 103 | cout << "Min value of the numerator : " << min_num << " [ " << bitset(min_num) << " ] "<< endl; 104 | cout << "Max value of the denominator : " << max_den << " [ " << bitset(max_den) << " ] "<< endl; 105 | cout << "Min value of the denominator : " << min_den << " [ " << bitset(min_den) << " ] "<< endl; 106 | cout << "Range of divisor values not supported by the synthesized design are from 0 to " << mask << endl; 107 | #endif 108 | 109 | for (double i=mask; i<=(double)max_den; i++) { 110 | for (double j =min_num; j<=(double)max_num; j++) { 111 | 112 | /* Debug System Outs */ 113 | // cout << "----------------------------------------" << endl; 114 | Dividend=j; 115 | Divisor=i; 116 | 117 | if (Divisor==0) { 118 | continue; 119 | } 120 | 121 | /* Feed the random values into the design */ 122 | rtest_ac_div(Dividend,Divisor,DUT_Quotient,DUT_Remainder); 123 | 124 | /* Golden Reference of the division model */ 125 | REF_Quotient=Dividend/Divisor; // Reference Version 126 | REF_Remainder=Dividend%Divisor; 127 | 128 | #ifdef DEBUG 129 | /* Debug System Outs */ 130 | cout << "Dividend : " << Dividend << " [ " << bitset(Dividend) << " ] "<< endl; 131 | cout << "Divisor : " << Divisor << " [ " << bitset(Divisor) << " ] "<< endl; 132 | cout << "Quotient : " << "New Design: " << DUT_Quotient << " || ReF Value: " << REF_Quotient << endl; 133 | cout << "Remainder : " << "New Design: " << DUT_Remainder << " || ReF Value: " << REF_Remainder << endl; 134 | #endif 135 | /* Compare the DUT values against Reference value */ 136 | if (DUT_Quotient.to_int() != REF_Quotient) { 137 | cout << "ERROR !!!!!!!!!!! in Quotient " << endl; 138 | ERROR= true; 139 | return 0; 140 | } 141 | if (DUT_Remainder.to_int() != REF_Remainder) { 142 | cout << "ERROR !!!!!!!!!!! in Remainder " << endl; 143 | ERROR = true; 144 | return 0; 145 | } 146 | } 147 | } 148 | if (!ERROR) { 149 | cout << " No Error , All Clear " << endl; 150 | } 151 | 152 | return 0; 153 | } 154 | --------------------------------------------------------------------------------