MatchLib
All Classes Namespaces Files Functions Modules Pages
nvhls_int.h
1/*
2 * Copyright (c) 2016-2020, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * When indicated below in comments, some compute functions in this file have
19 * been derived from code in the Algorithmic C Datatypes v3.7.1 distributed
20 * with the following license:
21 */
22/**************************************************************************
23 * *
24 * Algorithmic C (tm) Datatypes *
25 * *
26 * Software Version: 3.7 *
27 * *
28 * Release Date : Sat Jun 25 13:27:03 PDT 2016 *
29 * Release Type : Production Release *
30 * Release Build : 3.7.1 *
31 * *
32 * Copyright 2004-2016, Mentor Graphics Corporation, *
33 * *
34 * All Rights Reserved. *
35 *
36 **************************************************************************
37 * Licensed under the Apache License, Version 2.0 (the "License"); *
38 * you may not use this file except in compliance with the License. *
39 * You may obtain a copy of the License at *
40 * *
41 * http://www.apache.org/licenses/LICENSE-2.0 *
42 * *
43 * Unless required by applicable law or agreed to in writing, software *
44 * distributed under the License is distributed on an "AS IS" BASIS, *
45 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
46 * implied. *
47 * See the License for the specific language governing permissions and *
48 * limitations under the License. *
49 **************************************************************************
50 * *
51 * The most recent version of this package is available at github. *
52 * *
53 *************************************************************************/
54
55#ifndef NVHLS_INT_H
56#define NVHLS_INT_H
57
58#include <systemc.h>
59#include <nvhls_marshaller.h>
60#ifdef HLS_CATAPULT
61#include <ac_sc.h>
62#include <ac_int.h>
63#endif
64
65namespace nvhls {
66
67/**************************************************************************
68 * Begin *
69 * Algorithmic C (tm) Datatypes *
70 *************************************************************************/
71
72// Helper structs for statically computing log2 like functions (nbits,
73// log2_floor, log2_ceil) using recursive templates
74
75template <unsigned char N>
76struct s_N {
77 template <unsigned X>
78 struct s_X {
79 enum {
80 X2 = X >> N,
81 N_div_2 = N >> 1,
84 : 0
85 };
86 };
87};
88template <>
89struct s_N<0> {
90 template <unsigned X>
91 struct s_X {
92 enum { nbits = !!X };
93 };
94};
95
96// compiler time constant for log2 like functions
117template <unsigned X>
118struct nbits {
119 enum { val = s_N<16>::s_X<X>::nbits };
120};
141template <unsigned X>
143 enum { val = nbits<X>::val - 1 };
144};
145
151template <>
152struct log2_floor<0> {};
173template <unsigned X>
174struct log2_ceil {
175 enum { lf = log2_floor<X>::val, val = (X == (1 << lf) ? lf : lf + 1) };
176};
177
183template <>
184struct log2_ceil<0> {};
185
186
207template <int n_val>
208struct next_pow2 {
209 enum {
210 val =
211 n_val <= 1
212 ? 1
213 : n_val <= 2
214 ? 2
215 : n_val <= 4
216 ? 4
217 : n_val <= 8
218 ? 8
219 : n_val <= 16
220 ? 16
221 : n_val <= 32
222 ? 32
223 : n_val <= 64
224 ? 64
225 : n_val <= 128
226 ? 128
227 : n_val <= 256
228 ? 256
229 : n_val <= 512
230 ? 512
231 : n_val <=
232 1024
233 ? 1024
234 : n_val <=
235 2048
236 ? 2048
237 : n_val <=
238 4096
239 ? 4096
240 : n_val <=
241 8192
242 ? 8192
243 : n_val <=
244 16384
245 ? 16384
246 : n_val <=
247 32768
248 ? 32768
249 : n_val <=
250 65536
251 ? 65536
252 : 1048576
253 };
254};
255
256/**************************************************************************
257 * End *
258 * Algorithmic C (tm) Datatypes *
259 *************************************************************************/
260
284template <unsigned X>
286 enum { val = (X==1)? 1 : log2_ceil<X>::val };
287};
288
289// Definition of vendor agnostic data types. We can add more data types to
290// nvhls_t struct and move it to a separate file if needed
328#ifdef HLS_CATAPULT
329template <unsigned int N>
330struct nvhls_t {
331 typedef ac_int<N, true> nvint_t;
332 typedef ac_int<N, false> nvuint_t;
333};
334#else
335template <unsigned int N, bool B = (N <= 64)>
336struct nvhls_t;
337
338template <unsigned int N>
340 typedef sc_int<N> nvint_t;
341 typedef sc_uint<N> nvuint_t;
342};
343
344template <unsigned int N>
346 typedef sc_bigint<N> nvint_t;
347 typedef sc_biguint<N> nvuint_t;
348};
349#endif
350
386template <typename type1, typename type2>
387type1 set_slc(type1 X, type2 Y, const unsigned int i) {
388 type1 X_temp = X;
389#ifdef HLS_CATAPULT
390 X_temp.set_slc(i, Y);
391 return X_temp;
392#else
393 const unsigned int W2 = Wrapped<type2>::width;
394 X_temp.range(i + W2 - 1, i) = Y;
395 return X_temp;
396#endif
397}
398
433template <unsigned int W, typename type>
434#ifdef HLS_STRATUS
435sc_biguint<W> get_slc(type X, const unsigned int i){
436#else
437typename nvhls_t<W>::nvuint_t get_slc(type X, const unsigned int i) {
438#endif
439 // Assuming i>=0,
440 type X_temp = X;
441typename nvhls_t<W>::nvuint_t Z;
442#ifdef HLS_CATAPULT
443Z = X_temp.template slc<W>(i);
444return Z;
445#else
446 Z = X_temp.range(i + W - 1, i);
447 return Z;
448#endif
449}
450
486template <typename type>
487type get_slc(type X, const unsigned int i, const unsigned int j) {
488 // Assuming i>=0,j>=0, i>=j
489 type X_temp = X;
490 type Z;
491#ifdef HLS_CATAPULT
492 const unsigned int W = type::width;
493 Z = (X_temp >> j) & ((((ac_int<W + 1>)1) << (i - j + 1)) - 1);
494#else
495 Z = X_temp.range(i, j);
496#endif
497 return Z;
498}
499
500// Leading zero detector function
501// template <typename type1, typename type2>
502// type2 lzd_impl(type1 X) {
503// type1 X_temp = X;
504// type2 Z;
505// const unsigned int W1 = Wrapped<type1>::width;
506// const bool is_signed = Wrapped<type1>::is_signed;
507// int i;
508// if (is_signed) {
509// for (i = W1 - 2; i >= 0; i--) {
510// if (X_temp[i] != 0) break;
511// }
512// Z = W1 - 2 - i;
513// } else {
514// for (i = W1 - 1; i >= 0; i--) {
515// if (X_temp[i] != 0) break;
516// }
517// Z = W1 - 1 - i;
518// }
519// return Z;
520//}
521
522/**************************************************************************
523 * Begin *
524 * Algorithmic C (tm) Datatypes *
525 *************************************************************************/
526// Based on MG implementation
560template <unsigned int W1, typename type1, typename type2>
562 const unsigned int W2 = log2_ceil<W1>::val;
563 enum { P2 = next_pow2<(W1 + 1) / 2>::val };
564
565 typename nvhls_t<W1>::nvuint_t X_temp = X;
566 enum { Wu = (W1 > P2) ? (W1 - P2) : 1 };
569 typename nvhls_t<W2>::nvuint_t idx = 0;
570
571 enum { logWu = (log2_ceil<Wu>::val > 0) ? log2_ceil<Wu>::val : 1 };
572 enum { logP2 = (log2_ceil<P2>::val > 0) ? log2_ceil<P2>::val : 1 };
573 typename nvhls_t<logWu>::nvuint_t idxu = 0;
574 typename nvhls_t<P2>::nvuint_t idxl = 0;
575 if (upper != 0) {
578 idx = idxu | P2;
579 } else {
582 idx = idxl;
583 }
584 return idx;
585}
586/**************************************************************************
587 * End *
588 * Algorithmic C (tm) Datatypes *
589 *************************************************************************/
590
591template <>
594 return 0;
595}
596
626template <typename type1>
627unsigned int lzd(type1 X) {
628 unsigned int l;
629#ifdef HLS_CATAPULT
630 if (X!=0) {
631 l = X.leading_sign();
632 } else {
633 l = Wrapped<type1>::width -1;
634 }
635 return l;
636#else
637#if defined(DPOPT)
638 HLS_DPOPT_REGION(DPOPT_DEFAULT, "leading_ones", "leading_ones");
640#endif
641 const unsigned int W1 = Wrapped<type1>::width;
642 const unsigned int W2 = log2_ceil<W1>::val;
643 typedef typename nvhls_t<W2>::nvuint_t type2;
644 const bool is_signed = Wrapped<type1>::is_signed;
646 if (is_signed)
647 l = W1 - 2 - l;
648 else
649 l = W1 - 1 - l;
650 return l;
651#endif
652}
653
681template <typename type>
683 const unsigned int W = Wrapped<type>::width;
684 const bool is_signed = Wrapped<type>::is_signed;
685 type out;
686 if (is_signed)
687 out = (-((((type)(1)) << (W - 1)) - 1));
688 else
689 out = 0;
690 return out;
691}
692
721template <typename type>
722type left_shift(type X, int shift) {
723#ifdef HLS_CATAPULT
724 return (X << shift);
725#else
726 const unsigned int W = Wrapped<type>::width;
727 const bool is_signed = Wrapped<type>::is_signed;
728 type mag, out;
729 if (is_signed) {
730 mag = X.range(W - 2, 0);
731 // Catapult reports an error for the following line
732 // mag = (shift > 0) ? static_cast<type>(mag << shift) :
733 // static_cast<type>(mag >> (-shift));
734 if (shift > 0)
735 mag <<= shift;
736 else
737 mag >>= (-shift);
738 out = mag;
739 out[W - 1] = X[W - 1];
740 } else {
741 mag = X;
742 // mag = (shift > 0) ? (mag << shift) : (mag >> (-shift));
743 if (shift > 0)
744 mag <<= shift;
745 else
746 mag >>= (-shift);
747 out = mag;
748 }
749 return out;
750#endif
751}
781template <typename type>
782type right_shift(type X, int shift) {
783#ifdef HLS_CATAPULT
784 return (X >> shift);
785#else
786 const unsigned int W = Wrapped<type>::width;
787 const bool is_signed = Wrapped<type>::is_signed;
788 type mag, out;
789 if (is_signed) {
790 mag = X.range(W - 2, 0);
791 // mag = (shift > 0) ? static_cast<type>(mag >> shift) :
792 // static_cast<type>(mag << (-shift));
793 if (shift > 0)
794 mag >>= shift;
795 else
796 mag <<= (-shift);
797 out = mag;
798 out[W - 1] = X[W - 1];
799 } else {
800 mag = X;
801 // mag = (shift > 0) ? static_cast<type>(mag << shift) :
802 // static_cast<type>(mag >> (-shift));
803 if (shift > 0)
804 mag >>= shift;
805 else
806 mag <<= (-shift);
807 out = mag;
808 }
809 return out;
810#endif
811}
812
845// Normalize function for unsigned exponent
846// X is treated as mantissa and Y is treated as exp
847template <typename type1, typename type2>
849 bool b;
850#ifdef HLS_CATAPULT
851 b = X.normalize(Y);
852 return b;
853#else
854 const unsigned int W1 = Wrapped<type1>::width;
855 const unsigned int W2 = Wrapped<type2>::width;
856 const bool type2_signed = Wrapped<type2>::is_signed;
857 const unsigned int logW1 = log2_ceil<W1>::val;
858 typedef typename nvhls_t<logW1>::nvuint_t lzd_type;
860 lzd_type l = lzd(X);
863 // If W>logW1, then (Y-l) can be stored in type2 if it is signed or
864 // signed_type2 if type2 is unsigned
865 if (W2 > logW1) {
866 if (type2_signed) {
867 type2 Y_l = Y - l;
868 if (Y_l < min_Y) {
869 shift = Y - min_Y;
870 Y = min_Y;
871 b = false;
872 } else {
873 shift = l;
874 Y = Y_l;
875 b = true;
876 }
877 } else {
878 typedef typename nvhls_t<W2 + 1>::nvint_t signed_type2;
879 signed_type2 Y_l = Y - l;
880 if (Y_l < ((signed_type2)min_Y)) {
881 shift = Y - min_Y;
882 Y = min_Y;
883 b = false;
884 } else {
885 shift = l;
886 Y = Y_l;
887 b = true;
888 }
889 }
890 } else {
892 if (Y_l < ((signed_lzd_type)min_Y)) {
893 shift = Y - min_Y;
894 Y = min_Y;
895 b = false;
896 } else {
897 shift = l;
898 Y = Y_l;
899 b = true;
900 }
901 }
902 if (X == (type1)0) {
903 Y = min_Y;
904 b = true;
905 }
906 X = left_shift(X, shift);
907 return b;
908#endif
909}
910}
911;
912
913#endif
type get_min_val()
Minimum Value of a type.
Definition nvhls_int.h:682
unsigned int lzd(type1 X)
Leading zero detector.
Definition nvhls_int.h:627
nvhls_t< W >::nvuint_t get_slc(type X, const unsigned int i)
Function that returns slice of bits.
Definition nvhls_int.h:437
bool normalize(type1 &X, type2 &Y)
Normalize function.
Definition nvhls_int.h:848
type right_shift(type X, int shift)
Function that performs right shift while preserving sign.
Definition nvhls_int.h:782
type left_shift(type X, int shift)
Function that performs left shift while preserving sign.
Definition nvhls_int.h:722
type1 set_slc(type1 X, type2 Y, const unsigned int i)
Function that replaces slice of bits.
Definition nvhls_int.h:387
type2 leading_ones(type1 X)
LeadingOne Detector.
Definition nvhls_int.h:561
Compute index width of a constant.
Definition nvhls_int.h:285
Compute Celing of log2 of a constant.
Definition nvhls_int.h:174
Compute Floor of log2 of a constant.
Definition nvhls_int.h:142
Compute number of bits to represent a constant.
Definition nvhls_int.h:118
Compute power of 2 value greater than a given value.
Definition nvhls_int.h:208
Definition of vendor agnostic integer data types.
Definition nvhls_int.h:336